fix single key press detection

This commit is contained in:
nakst 2021-09-20 17:37:38 +01:00
parent 6c7ac5e749
commit 622073ffb2
5 changed files with 63 additions and 73 deletions

View File

@ -1,8 +1,6 @@
#include <essence.h> #include <essence.h>
#include <shared/strings.cpp> #include <shared/strings.cpp>
// TODO Application icon.
#define TILE_COUNT (4) #define TILE_COUNT (4)
#define TILE_SIZE ((int32_t) (75 * scale)) #define TILE_SIZE ((int32_t) (75 * scale))
#define TILE_GAP ((int32_t) (10 * scale)) #define TILE_GAP ((int32_t) (10 * scale))

View File

@ -561,6 +561,30 @@ WindowTab *WindowTabMoveToNewContainer(WindowTab *tab, ContainerWindow *containe
return newTab; 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) { int ProcessGlobalKeyboardShortcuts(EsElement *, EsMessage *message) {
if (desktop.installationState) { if (desktop.installationState) {
// Do not process global keyboard shortcuts if the installer is running. // Do not process global keyboard shortcuts if the installer is running.
@ -580,6 +604,21 @@ int ProcessGlobalKeyboardShortcuts(EsElement *, EsMessage *message) {
} }
return ES_HANDLED; 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; return 0;
@ -651,6 +690,8 @@ int ContainerWindowMessage(EsElement *element, EsMessage *message) {
ProcessGlobalKeyboardShortcuts(element, message); ProcessGlobalKeyboardShortcuts(element, message);
} }
} }
} else if (message->type == ES_MSG_KEY_UP) {
ProcessGlobalKeyboardShortcuts(element, message);
} else if (message->type == ES_MSG_WINDOW_RESIZED) { } else if (message->type == ES_MSG_WINDOW_RESIZED) {
container->tabBand->preventNextTabSizeAnimation = true; container->tabBand->preventNextTabSizeAnimation = true;
} }
@ -2720,30 +2761,6 @@ void EmbeddedWindowDestroyed(EsObjectID id) {
EsHeapFree(instance); 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) { void DesktopMessage(EsMessage *message) {
if (message->type == ES_MSG_POWER_BUTTON_PRESSED) { if (message->type == ES_MSG_POWER_BUTTON_PRESSED) {
ShutdownModalCreate(); ShutdownModalCreate();
@ -2815,19 +2832,6 @@ void DesktopMessage(EsMessage *message) {
} else { } else {
// The screen resolution will be correctly queried in DesktopSetup. // 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) { } else if (message->type == ES_MSG_INSTANCE_DESTROY) {
CommonDesktopInstance *instance = (CommonDesktopInstance *) message->instanceDestroy.instance; CommonDesktopInstance *instance = (CommonDesktopInstance *) message->instanceDestroy.instance;

View File

@ -45,7 +45,7 @@ struct {
bool menuMode; bool menuMode;
// Access keys. // Access keys.
bool accessKeyMode, unhandledAltPress; bool accessKeyMode, accessKeyModeJustExited;
struct { struct {
Array<AccessKeyEntry> entries; Array<AccessKeyEntry> entries;
@ -6589,7 +6589,7 @@ void AccessKeyModeExit() {
} }
void AccessKeyModeHandleKeyPress(EsMessage *message) { 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; 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_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_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); AccessKeyModeEnter(window);
return true; return true;
} else if (window->focused) { } else if (window->focused) {
EsMessageSend(window->focused, message); return ES_HANDLED == EsMessageSend(window->focused, message);
return true; } else {
return ES_HANDLED == EsMessageSend(window, message);
} }
return false;
} }
if (window->targetMenu) { if (window->targetMenu) {
window = window->targetMenu; window = window->targetMenu;
} }
gui.unhandledAltPress = false;
if (message->keyboard.scancode == ES_SCANCODE_F2 && message->keyboard.modifiers == ES_MODIFIER_ALT) { if (message->keyboard.scancode == ES_SCANCODE_F2 && message->keyboard.modifiers == ES_MODIFIER_ALT) {
EnterDebugger(); EnterDebugger();
EsPrint("[Alt-F2]\n"); EsPrint("[Alt-F2]\n");
@ -6758,7 +6755,9 @@ bool UIHandleKeyMessage(EsWindow *window, EsMessage *message) {
return true; return true;
} }
} else { } else {
EsMessageSend(window, message); if (ES_HANDLED == EsMessageSend(window, message)) {
return true;
}
} }
// TODO Radio group navigation. // TODO Radio group navigation.
@ -6776,11 +6775,6 @@ bool UIHandleKeyMessage(EsWindow *window, EsMessage *message) {
if (!window->hasDialog) { if (!window->hasDialog) {
// TODO Sort out what commands can be used from within dialogs and menus. // 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(); if (!gui.keyboardShortcutNames.itemCount) UIInitialiseKeyboardShortcutNamesTable();
const char *shortcutName = (const char *) HashTableGetShort(&gui.keyboardShortcutNames, message->keyboard.scancode); const char *shortcutName = (const char *) HashTableGetShort(&gui.keyboardShortcutNames, message->keyboard.scancode);

View File

@ -892,6 +892,7 @@ enum EsMessageType {
ES_MSG_KEY_DOWN = 0x100E // Propagates to ancestors if unhandled. ES_MSG_KEY_DOWN = 0x100E // Propagates to ancestors if unhandled.
ES_MSG_KEY_UP = 0x100F ES_MSG_KEY_UP = 0x100F
ES_MSG_UPDATE_WINDOW = 0x1010 ES_MSG_UPDATE_WINDOW = 0x1010
ES_MSG_SINGLE_ALT_PRESS = 0x1011
ES_MSG_WM_END = 0x13FF ES_MSG_WM_END = 0x13FF
// Internal GUI messages: // None of these should be sent directly. // Internal GUI messages: // None of these should be sent directly.
@ -968,7 +969,6 @@ enum EsMessageType {
ES_MSG_DESKTOP = 0x4806 ES_MSG_DESKTOP = 0x4806
ES_MSG_DEVICE_CONNECTED = 0x4807 ES_MSG_DEVICE_CONNECTED = 0x4807
ES_MSG_DEVICE_DISCONNECTED = 0x4808 ES_MSG_DEVICE_DISCONNECTED = 0x4808
ES_MSG_SINGLE_CTRL_PRESS = 0x4809
// Messages sent from Desktop to application instances: // Messages sent from Desktop to application instances:
ES_MSG_TAB_INSPECT_UI = 0x4A01 ES_MSG_TAB_INSPECT_UI = 0x4A01
@ -1546,7 +1546,7 @@ struct EsMessageMouseButton {
struct EsMessageKeyboard { struct EsMessageKeyboard {
uint32_t scancode; uint32_t scancode;
uint8_t modifiers; uint8_t modifiers;
bool repeat, numpad, numlock; bool repeat, numpad, numlock, single;
}; };
struct EsMessageAnimate { struct EsMessageAnimate {

View File

@ -115,6 +115,8 @@ struct WindowManager {
bool shift2, alt2, ctrl2, flag2; bool shift2, alt2, ctrl2, flag2;
bool numlock; bool numlock;
uint8_t modifiers; uint8_t modifiers;
uint16_t keysHeld, maximumKeysHeld /* cleared when all released */;
uint8_t keysHeldBitSet[512 / 8];
// Eyedropper: // Eyedropper:
@ -127,7 +129,6 @@ struct WindowManager {
// Miscellaneous: // Miscellaneous:
EsRectangle workArea; EsRectangle workArea;
bool inSingleCtrlPress;
// Game controllers: // Game controllers:
@ -285,16 +286,10 @@ void WindowManager::PressKey(unsigned scancode) {
KernelPanic("WindowManager::PressKey - Panic key pressed.\n"); KernelPanic("WindowManager::PressKey - Panic key pressed.\n");
} }
if (scancode == ES_SCANCODE_LEFT_CTRL) { bool single = (scancode & K_SCANCODE_KEY_RELEASED) && maximumKeysHeld == 1;
inSingleCtrlPress = true; keysHeld += (scancode & K_SCANCODE_KEY_RELEASED) ? -1 : 1;
} else if (scancode == (ES_SCANCODE_LEFT_CTRL | K_SCANCODE_KEY_RELEASED) && inSingleCtrlPress) { keysHeld = MaximumInteger(keysHeld, 0); // Prevent negative keys held count.
EsMessage m; maximumKeysHeld = (!keysHeld || keysHeld > maximumKeysHeld) ? keysHeld : maximumKeysHeld;
EsMemoryZero(&m, sizeof(EsMessage));
m.type = ES_MSG_SINGLE_CTRL_PRESS;
desktopProcess->messageQueue.SendMessage(nullptr, &m);
} else {
inSingleCtrlPress = false;
}
if (eyedropping) { if (eyedropping) {
if (scancode == (ES_SCANCODE_ESCAPE | K_SCANCODE_KEY_RELEASED)) { if (scancode == (ES_SCANCODE_ESCAPE | K_SCANCODE_KEY_RELEASED)) {
@ -337,21 +332,20 @@ void WindowManager::PressKey(unsigned scancode) {
message.keyboard.modifiers = modifiers; message.keyboard.modifiers = modifiers;
message.keyboard.scancode = scancode & ~K_SCANCODE_KEY_RELEASED; message.keyboard.scancode = scancode & ~K_SCANCODE_KEY_RELEASED;
message.keyboard.numlock = numlock; message.keyboard.numlock = numlock;
message.keyboard.single = single;
static uint8_t heldKeys[512 / 8] = {};
if (message.keyboard.scancode >= 512) { if (message.keyboard.scancode >= 512) {
KernelPanic("WindowManager::PressKey - Scancode outside valid range.\n"); 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; message.keyboard.repeat = true;
} }
if (message.type == ES_MSG_KEY_DOWN) { 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 { } else {
heldKeys[message.keyboard.scancode / 8] &= ~(1 << (message.keyboard.scancode % 8)); keysHeldBitSet[message.keyboard.scancode / 8] &= ~(1 << (message.keyboard.scancode % 8));
} }
if (activeWindow) { if (activeWindow) {