diff --git a/apps/2048.cpp b/apps/2048.cpp index a330d7a..8534b01 100644 --- a/apps/2048.cpp +++ b/apps/2048.cpp @@ -1,8 +1,6 @@ #include #include -// TODO Application icon. - #define TILE_COUNT (4) #define TILE_SIZE ((int32_t) (75 * scale)) #define TILE_GAP ((int32_t) (10 * scale)) diff --git a/desktop/desktop.cpp b/desktop/desktop.cpp index 5d7f7d2..b4c5aa3 100644 --- a/desktop/desktop.cpp +++ b/desktop/desktop.cpp @@ -561,6 +561,30 @@ WindowTab *WindowTabMoveToNewContainer(WindowTab *tab, ContainerWindow *containe return newTab; } +int CursorLocatorMessage(EsElement *element, EsMessage *message) { + EsWindow *window = element->window; + + if (message->type == ES_MSG_ANIMATE) { + window->announcementTimeMs += message->animate.deltaMs; + double progress = window->announcementTimeMs / GetConstantNumber("cursorLocatorDuration"); + + if (progress > 1) { + EsElementDestroy(window); + } else { + EsElementRelayout(element); + message->animate.complete = false; + return ES_HANDLED; + } + } else if (message->type == ES_MSG_LAYOUT) { + EsElement *child = element->GetChild(0); + double progress = 1.0 - window->announcementTimeMs / GetConstantNumber("cursorLocatorDuration"); + int width = progress * child->GetWidth(0), height = progress * child->GetHeight(0); + child->InternalMove(width, height, (element->width - width) / 2, (element->height - height) / 2); + } + + return 0; +} + int ProcessGlobalKeyboardShortcuts(EsElement *, EsMessage *message) { if (desktop.installationState) { // Do not process global keyboard shortcuts if the installer is running. @@ -580,6 +604,21 @@ int ProcessGlobalKeyboardShortcuts(EsElement *, EsMessage *message) { } return ES_HANDLED; + } else if (message->type == ES_MSG_KEY_UP) { + if (message->keyboard.scancode == ES_SCANCODE_LEFT_CTRL && message->keyboard.single) { + if (EsSystemConfigurationReadInteger(EsLiteral("general"), EsLiteral("locate_cursor_on_ctrl"))) { + EsPoint position = EsMouseGetPosition(); + EsWindow *window = EsWindowCreate(nullptr, ES_WINDOW_TIP); + EsElement *wrapper = EsCustomElementCreate(window, ES_CELL_FILL, ES_STYLE_CLEAR_BACKGROUND); + wrapper->messageUser = CursorLocatorMessage; + window->announcementBase = position; + EsElement *element = EsCustomElementCreate(wrapper, ES_CELL_FILL, ES_STYLE_CURSOR_LOCATOR); + int width = element->GetWidth(0), height = element->GetHeight(0); + EsRectangle bounds = ES_RECT_4PD(position.x - width / 2, position.y - height / 2, width, height); + EsSyscall(ES_SYSCALL_WINDOW_MOVE, window->handle, (uintptr_t) &bounds, 0, ES_WINDOW_MOVE_ALWAYS_ON_TOP); + wrapper->StartAnimating(); + } + } } return 0; @@ -651,6 +690,8 @@ int ContainerWindowMessage(EsElement *element, EsMessage *message) { ProcessGlobalKeyboardShortcuts(element, message); } } + } else if (message->type == ES_MSG_KEY_UP) { + ProcessGlobalKeyboardShortcuts(element, message); } else if (message->type == ES_MSG_WINDOW_RESIZED) { container->tabBand->preventNextTabSizeAnimation = true; } @@ -2720,30 +2761,6 @@ void EmbeddedWindowDestroyed(EsObjectID id) { EsHeapFree(instance); } -int CursorLocatorMessage(EsElement *element, EsMessage *message) { - EsWindow *window = element->window; - - if (message->type == ES_MSG_ANIMATE) { - window->announcementTimeMs += message->animate.deltaMs; - double progress = window->announcementTimeMs / GetConstantNumber("cursorLocatorDuration"); - - if (progress > 1) { - EsElementDestroy(window); - } else { - EsElementRelayout(element); - message->animate.complete = false; - return ES_HANDLED; - } - } else if (message->type == ES_MSG_LAYOUT) { - EsElement *child = element->GetChild(0); - double progress = 1.0 - window->announcementTimeMs / GetConstantNumber("cursorLocatorDuration"); - int width = progress * child->GetWidth(0), height = progress * child->GetHeight(0); - child->InternalMove(width, height, (element->width - width) / 2, (element->height - height) / 2); - } - - return 0; -} - void DesktopMessage(EsMessage *message) { if (message->type == ES_MSG_POWER_BUTTON_PRESSED) { ShutdownModalCreate(); @@ -2815,19 +2832,6 @@ void DesktopMessage(EsMessage *message) { } else { // The screen resolution will be correctly queried in DesktopSetup. } - } else if (message->type == ES_MSG_SINGLE_CTRL_PRESS) { - if (EsSystemConfigurationReadInteger(EsLiteral("general"), EsLiteral("locate_cursor_on_ctrl"))) { - EsPoint position = EsMouseGetPosition(); - EsWindow *window = EsWindowCreate(nullptr, ES_WINDOW_TIP); - EsElement *wrapper = EsCustomElementCreate(window, ES_CELL_FILL, ES_STYLE_CLEAR_BACKGROUND); - wrapper->messageUser = CursorLocatorMessage; - window->announcementBase = position; - EsElement *element = EsCustomElementCreate(wrapper, ES_CELL_FILL, ES_STYLE_CURSOR_LOCATOR); - int width = element->GetWidth(0), height = element->GetHeight(0); - EsRectangle bounds = ES_RECT_4PD(position.x - width / 2, position.y - height / 2, width, height); - EsSyscall(ES_SYSCALL_WINDOW_MOVE, window->handle, (uintptr_t) &bounds, 0, ES_WINDOW_MOVE_ALWAYS_ON_TOP); - wrapper->StartAnimating(); - } } else if (message->type == ES_MSG_INSTANCE_DESTROY) { CommonDesktopInstance *instance = (CommonDesktopInstance *) message->instanceDestroy.instance; diff --git a/desktop/gui.cpp b/desktop/gui.cpp index c2aae2b..a8128af 100644 --- a/desktop/gui.cpp +++ b/desktop/gui.cpp @@ -45,7 +45,7 @@ struct { bool menuMode; // Access keys. - bool accessKeyMode, unhandledAltPress; + bool accessKeyMode, accessKeyModeJustExited; struct { Array entries; @@ -6589,7 +6589,7 @@ void AccessKeyModeExit() { } void AccessKeyModeHandleKeyPress(EsMessage *message) { - if (message->type == ES_MSG_KEY_UP) { + if (message->type == ES_MSG_KEY_UP || message->keyboard.scancode == ES_SCANCODE_LEFT_ALT) { return; } @@ -6665,23 +6665,20 @@ bool UIHandleKeyMessage(EsWindow *window, EsMessage *message) { if (message->keyboard.scancode == ES_SCANCODE_RIGHT_SHIFT) gui.rightModifiers &= ~ES_MODIFIER_SHIFT; if (message->keyboard.scancode == ES_SCANCODE_RIGHT_FLAG ) gui.rightModifiers &= ~ES_MODIFIER_FLAG; - if (message->keyboard.scancode == ES_SCANCODE_LEFT_ALT && gui.unhandledAltPress) { + if (message->keyboard.scancode == ES_SCANCODE_LEFT_ALT && message->keyboard.single) { AccessKeyModeEnter(window); return true; } else if (window->focused) { - EsMessageSend(window->focused, message); - return true; + return ES_HANDLED == EsMessageSend(window->focused, message); + } else { + return ES_HANDLED == EsMessageSend(window, message); } - - return false; } if (window->targetMenu) { window = window->targetMenu; } - gui.unhandledAltPress = false; - if (message->keyboard.scancode == ES_SCANCODE_F2 && message->keyboard.modifiers == ES_MODIFIER_ALT) { EnterDebugger(); EsPrint("[Alt-F2]\n"); @@ -6758,7 +6755,9 @@ bool UIHandleKeyMessage(EsWindow *window, EsMessage *message) { return true; } } else { - EsMessageSend(window, message); + if (ES_HANDLED == EsMessageSend(window, message)) { + return true; + } } // TODO Radio group navigation. @@ -6776,11 +6775,6 @@ bool UIHandleKeyMessage(EsWindow *window, EsMessage *message) { if (!window->hasDialog) { // TODO Sort out what commands can be used from within dialogs and menus. - if (message->keyboard.scancode == ES_SCANCODE_LEFT_ALT) { - gui.unhandledAltPress = true; - return true; - } - if (!gui.keyboardShortcutNames.itemCount) UIInitialiseKeyboardShortcutNamesTable(); const char *shortcutName = (const char *) HashTableGetShort(&gui.keyboardShortcutNames, message->keyboard.scancode); diff --git a/desktop/os.header b/desktop/os.header index 8740abf..0b2d849 100644 --- a/desktop/os.header +++ b/desktop/os.header @@ -892,6 +892,7 @@ enum EsMessageType { ES_MSG_KEY_DOWN = 0x100E // Propagates to ancestors if unhandled. ES_MSG_KEY_UP = 0x100F ES_MSG_UPDATE_WINDOW = 0x1010 + ES_MSG_SINGLE_ALT_PRESS = 0x1011 ES_MSG_WM_END = 0x13FF // Internal GUI messages: // None of these should be sent directly. @@ -968,7 +969,6 @@ enum EsMessageType { ES_MSG_DESKTOP = 0x4806 ES_MSG_DEVICE_CONNECTED = 0x4807 ES_MSG_DEVICE_DISCONNECTED = 0x4808 - ES_MSG_SINGLE_CTRL_PRESS = 0x4809 // Messages sent from Desktop to application instances: ES_MSG_TAB_INSPECT_UI = 0x4A01 @@ -1546,7 +1546,7 @@ struct EsMessageMouseButton { struct EsMessageKeyboard { uint32_t scancode; uint8_t modifiers; - bool repeat, numpad, numlock; + bool repeat, numpad, numlock, single; }; struct EsMessageAnimate { diff --git a/kernel/windows.cpp b/kernel/windows.cpp index c8f838a..5466349 100644 --- a/kernel/windows.cpp +++ b/kernel/windows.cpp @@ -115,6 +115,8 @@ struct WindowManager { bool shift2, alt2, ctrl2, flag2; bool numlock; uint8_t modifiers; + uint16_t keysHeld, maximumKeysHeld /* cleared when all released */; + uint8_t keysHeldBitSet[512 / 8]; // Eyedropper: @@ -127,7 +129,6 @@ struct WindowManager { // Miscellaneous: EsRectangle workArea; - bool inSingleCtrlPress; // Game controllers: @@ -285,16 +286,10 @@ void WindowManager::PressKey(unsigned scancode) { KernelPanic("WindowManager::PressKey - Panic key pressed.\n"); } - if (scancode == ES_SCANCODE_LEFT_CTRL) { - inSingleCtrlPress = true; - } else if (scancode == (ES_SCANCODE_LEFT_CTRL | K_SCANCODE_KEY_RELEASED) && inSingleCtrlPress) { - EsMessage m; - EsMemoryZero(&m, sizeof(EsMessage)); - m.type = ES_MSG_SINGLE_CTRL_PRESS; - desktopProcess->messageQueue.SendMessage(nullptr, &m); - } else { - inSingleCtrlPress = false; - } + bool single = (scancode & K_SCANCODE_KEY_RELEASED) && maximumKeysHeld == 1; + keysHeld += (scancode & K_SCANCODE_KEY_RELEASED) ? -1 : 1; + keysHeld = MaximumInteger(keysHeld, 0); // Prevent negative keys held count. + maximumKeysHeld = (!keysHeld || keysHeld > maximumKeysHeld) ? keysHeld : maximumKeysHeld; if (eyedropping) { if (scancode == (ES_SCANCODE_ESCAPE | K_SCANCODE_KEY_RELEASED)) { @@ -337,21 +332,20 @@ void WindowManager::PressKey(unsigned scancode) { message.keyboard.modifiers = modifiers; message.keyboard.scancode = scancode & ~K_SCANCODE_KEY_RELEASED; message.keyboard.numlock = numlock; - - static uint8_t heldKeys[512 / 8] = {}; + message.keyboard.single = single; if (message.keyboard.scancode >= 512) { KernelPanic("WindowManager::PressKey - Scancode outside valid range.\n"); } - - if (message.type == ES_MSG_KEY_DOWN && (heldKeys[message.keyboard.scancode / 8] & (1 << (message.keyboard.scancode % 8)))) { + + if (message.type == ES_MSG_KEY_DOWN && (keysHeldBitSet[message.keyboard.scancode / 8] & (1 << (message.keyboard.scancode % 8)))) { message.keyboard.repeat = true; } if (message.type == ES_MSG_KEY_DOWN) { - heldKeys[message.keyboard.scancode / 8] |= (1 << (message.keyboard.scancode % 8)); + keysHeldBitSet[message.keyboard.scancode / 8] |= (1 << (message.keyboard.scancode % 8)); } else { - heldKeys[message.keyboard.scancode / 8] &= ~(1 << (message.keyboard.scancode % 8)); + keysHeldBitSet[message.keyboard.scancode / 8] &= ~(1 << (message.keyboard.scancode % 8)); } if (activeWindow) {