mirror of https://gitlab.com/nakst/essence
fix single key press detection
This commit is contained in:
parent
6c7ac5e749
commit
622073ffb2
|
@ -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))
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
Loading…
Reference in New Issue