From 125cdfde4b6c4742a2a0c0305cbb614df67eb788 Mon Sep 17 00:00:00 2001 From: nakst <> Date: Sat, 25 Sep 2021 21:26:45 +0100 Subject: [PATCH] scroll wheel support --- desktop/api.cpp | 1 - desktop/desktop.cpp | 7 ------- desktop/gui.cpp | 13 ++++++++++--- desktop/os.header | 10 ++++++++-- drivers/ps2.cpp | 2 +- drivers/usb_hid.cpp | 23 +++++++++++++++++++---- kernel/module.h | 6 +++--- kernel/syscall.cpp | 13 ------------- kernel/windows.cpp | 41 +++++++++++++++++++++++++++++++---------- 9 files changed, 72 insertions(+), 44 deletions(-) diff --git a/desktop/api.cpp b/desktop/api.cpp index 73de673..a4411ab 100644 --- a/desktop/api.cpp +++ b/desktop/api.cpp @@ -55,7 +55,6 @@ struct EnumString { const char *cName; int value; }; #define DESKTOP_MSG_CLIPBOARD_GET (12) #define DESKTOP_MSG_SYSTEM_CONFIGURATION_GET (13) #define DESKTOP_MSG_FILE_TYPES_GET (14) -#define DESKTOP_MSG_UNHANDLED_KEY_EVENT (15) #define DESKTOP_MSG_START_USER_TASK (16) #define DESKTOP_MSG_SET_PROGRESS (17) #define DESKTOP_MSG_RENAME (18) diff --git a/desktop/desktop.cpp b/desktop/desktop.cpp index 5a6ca03..d055165 100644 --- a/desktop/desktop.cpp +++ b/desktop/desktop.cpp @@ -2754,13 +2754,6 @@ void DesktopSyscall(EsMessage *message, uint8_t *buffer, EsBuffer *pipe) { desktop.installedApplications.Add(application); ApplicationInstanceCreate(application->id, nullptr, nullptr); } - } else if (buffer[0] == DESKTOP_MSG_UNHANDLED_KEY_EVENT && instance->tab) { - _EsMessageWithObject message; - EsSyscall(ES_SYSCALL_WINDOW_GET_EMBED_KEYBOARD, instance->tab->window->handle, (uintptr_t) &message, 0, 0); - - if (message.message.type != ES_MSG_INVALID) { - UIProcessWindowManagerMessage((EsWindow *) message.object, &message.message, nullptr); - } } else { EsPrint("DesktopSyscall - Received unhandled message %d.\n", buffer[0]); } diff --git a/desktop/gui.cpp b/desktop/gui.cpp index b94c7e2..331f898 100644 --- a/desktop/gui.cpp +++ b/desktop/gui.cpp @@ -2858,6 +2858,9 @@ void ScrollPane::ReceivedMessage(EsMessage *message) { EsMessageSend(parent, &m); parent->internalOffsetRight = (m.measure.height + fixedViewport[1] > message->measure.height) ? bar[1]->currentStyle->preferredWidth : 0; } + } else if (message->type == ES_MSG_SCROLL_WHEEL) { + SetPosition(0, position[0] + message->scrollWheel.dx, true); + SetPosition(1, position[1] + message->scrollWheel.dy, true); } } @@ -7212,10 +7215,14 @@ void UIProcessWindowManagerMessage(EsWindow *window, EsMessage *message, Process goto doneInputMessage; } } + } else if (message->type == ES_MSG_SCROLL_WHEEL) { + EsElement *element = window->dragged ?: window->pressed ?: window->hovered; - if (window->windowStyle == ES_WINDOW_NORMAL) { - uint8_t m = DESKTOP_MSG_UNHANDLED_KEY_EVENT; - MessageDesktop(&m, 1, window->handle); + message->scrollWheel.dx /= 5; + message->scrollWheel.dy /= -5; + + if (element && (~element->flags & ES_ELEMENT_DISABLED) && (~element->state & UI_STATE_BLOCK_INTERACTION)) { + UIMessageSendPropagateToAncestors(element, message); } } else if (message->type == ES_MSG_WINDOW_RESIZED) { AccessKeyModeExit(); diff --git a/desktop/os.header b/desktop/os.header index edcae7b..38b5587 100644 --- a/desktop/os.header +++ b/desktop/os.header @@ -735,6 +735,8 @@ define ES_PATH_MOVE_ALLOW_COPY_AND_DELETE (1 << 0) // Copy and delete the file i define ES_CLIPBOARD_ADD_LAZY_CUT (1 << 0) // Only perform the deletion after pasting; often implemented as a move. +define ES_SCROLL_WHEEL_SCALE (0x100) + include desktop/icons.header enum EsFatalError { @@ -814,7 +816,6 @@ enum EsSyscallType { ES_SYSCALL_WINDOW_FIND_BY_POINT ES_SYSCALL_WINDOW_GET_ID ES_SYSCALL_WINDOW_GET_BOUNDS - ES_SYSCALL_WINDOW_GET_EMBED_KEYBOARD ES_SYSCALL_WINDOW_SET_BITS ES_SYSCALL_WINDOW_SET_CURSOR ES_SYSCALL_WINDOW_SET_PROPERTY @@ -888,7 +889,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_SCROLL_WHEEL = 0x1011 ES_MSG_WM_END = 0x13FF // Internal GUI messages: // None of these should be sent directly. @@ -1546,6 +1547,10 @@ struct EsMessageKeyboard { bool repeat, numpad, numlock, single; }; +struct EsMessageScrollWheel { + int32_t dx, dy; +}; + struct EsMessageAnimate { int64_t deltaMs, waitMs; bool complete; @@ -1795,6 +1800,7 @@ struct EsMessage { EsMessageBeforeZOrder beforeZOrder; EsMessageItemToString itemToString; EsMessageFocus focus; + EsMessageScrollWheel scrollWheel; const EsStyle *childStyleVariant; EsRectangle *accessKeyHintBounds; EsPainter *painter; diff --git a/drivers/ps2.cpp b/drivers/ps2.cpp index 774a701..0a4b24b 100644 --- a/drivers/ps2.cpp +++ b/drivers/ps2.cpp @@ -198,7 +198,7 @@ uint16_t scancodeConversionTable2[] = { void PS2MouseUpdated(EsGeneric _update) { PS2Update *update = (PS2Update *) _update.p; - KCursorUpdate(update->xMovement * K_CURSOR_MOVEMENT_SCALE, update->yMovement * K_CURSOR_MOVEMENT_SCALE, update->buttons); + KMouseUpdate(update->xMovement * K_CURSOR_MOVEMENT_SCALE, update->yMovement * K_CURSOR_MOVEMENT_SCALE, update->buttons); } void PS2KeyboardUpdated(EsGeneric _update) { diff --git a/drivers/usb_hid.cpp b/drivers/usb_hid.cpp index 162c868..bdb3753 100644 --- a/drivers/usb_hid.cpp +++ b/drivers/usb_hid.cpp @@ -1,5 +1,7 @@ #include +// #define TRACE_REPORTS + // TODO Key repeat not working on Qemu. struct ReportItem { @@ -101,6 +103,7 @@ struct UsageString { #define HID_USAGE_X_ROTATION (0x010033) #define HID_USAGE_Y_ROTATION (0x010034) #define HID_USAGE_Z_ROTATION (0x010035) +#define HID_USAGE_WHEEL (0x010038) #define HID_USAGE_HAT_SWITCH (0x010039) #define HID_USAGE_KEYCODES (0x070000) #define HID_USAGE_BUTTON_1 (0x090001) @@ -418,7 +421,8 @@ void HIDDevice::ReportReceived(BitBuffer *buffer) { #endif bool mouseEvent = false; - int mouseXMovement = 0, mouseYMovement = 0, mouseButtons = 0; + int mouseXMovement = 0, mouseYMovement = 0; + int mouseScrollWheel = 0, mouseButtons = 0; bool keyboardEvent = false; uint16_t keysDown[32]; size_t keysDownCount = 0; @@ -502,6 +506,8 @@ void HIDDevice::ReportReceived(BitBuffer *buffer) { if (buffer->ReadUnsigned(item->bits)) mouseButtons |= 1 << 2; } else if (item->usage == HID_USAGE_BUTTON_3) { if (buffer->ReadUnsigned(item->bits)) mouseButtons |= 1 << 1; + } else if (item->usage == HID_USAGE_WHEEL) { + mouseScrollWheel = buffer->ReadSigned(item->bits); } else { handled = false; } @@ -559,9 +565,18 @@ void HIDDevice::ReportReceived(BitBuffer *buffer) { } } - if (mouseEvent) KCursorUpdate(mouseXMovement * K_CURSOR_MOVEMENT_SCALE, mouseYMovement * K_CURSOR_MOVEMENT_SCALE, mouseButtons); - if (keyboardEvent) KKeyboardUpdate(keysDown, keysDownCount); - if (gameControllerEvent) KGameControllerUpdateState(&controllerState); + if (mouseEvent) { + KMouseUpdate(mouseXMovement * K_CURSOR_MOVEMENT_SCALE, mouseYMovement * K_CURSOR_MOVEMENT_SCALE, + mouseButtons, 0, mouseScrollWheel * ES_SCROLL_WHEEL_SCALE); + } + + if (keyboardEvent) { + KKeyboardUpdate(keysDown, keysDownCount); + } + + if (gameControllerEvent) { + KGameControllerUpdate(&controllerState); + } if (device->flags & K_DEVICE_REMOVED) { KDeviceCloseHandle(this); diff --git a/kernel/module.h b/kernel/module.h index 88c0f44..2276704 100644 --- a/kernel/module.h +++ b/kernel/module.h @@ -364,14 +364,14 @@ void KTimerRemove(KTimer *timer); // Timers with callbacks cannot be removed (it // Window manager. // --------------------------------------------------------------------------------------------------------------- -#define K_CURSOR_MOVEMENT_SCALE (0x100) -void KCursorUpdate(int32_t xMovement, int32_t yMovement, uint32_t buttons); +#define K_CURSOR_MOVEMENT_SCALE ES_SCROLL_WHEEL_SCALE +void KMouseUpdate(int32_t xMovement, int32_t yMovement, uint32_t buttons, int32_t scrollX = 0, int32_t scrollY = 0); void KKeyboardUpdate(uint16_t *keysDown, size_t keysDownCount); void KKeyPress(uint32_t scancode); uint64_t KGameControllerConnect(); void KGameControllerDisconnect(uint64_t id); -void KGameControllerUpdateState(EsGameControllerState *state); +void KGameControllerUpdate(EsGameControllerState *state); #define K_SCANCODE_KEY_RELEASED (1 << 15) #define K_SCANCODE_KEY_PRESSED (0 << 15) diff --git a/kernel/syscall.cpp b/kernel/syscall.cpp index 768b49f..2d80dab 100644 --- a/kernel/syscall.cpp +++ b/kernel/syscall.cpp @@ -1211,19 +1211,6 @@ SYSCALL_IMPLEMENT(ES_SYSCALL_WINDOW_GET_BOUNDS) { SYSCALL_RETURN(ES_SUCCESS, false); } -SYSCALL_IMPLEMENT(ES_SYSCALL_WINDOW_GET_EMBED_KEYBOARD) { - SYSCALL_HANDLE(argument0, KERNEL_OBJECT_WINDOW, window, Window); - _EsMessageWithObject m; - EsMemoryZero(&m, sizeof(_EsMessageWithObject)); - KMutexAcquire(&windowManager.mutex); - m.object = window->apiWindow; - EsMemoryCopy(&m.message, &window->lastEmbedKeyboardMessage, sizeof(EsMessage)); - window->lastEmbedKeyboardMessage.type = ES_MSG_INVALID; - KMutexRelease(&windowManager.mutex); - SYSCALL_WRITE(argument1, &m, sizeof(_EsMessageWithObject)); - SYSCALL_RETURN(ES_SUCCESS, false); -} - SYSCALL_IMPLEMENT(ES_SYSCALL_PROCESS_PAUSE) { SYSCALL_HANDLE(argument0, KERNEL_OBJECT_PROCESS, process, Process); scheduler.PauseProcess(process, (bool) argument1); diff --git a/kernel/windows.cpp b/kernel/windows.cpp index 5466349..4bd47f1 100644 --- a/kernel/windows.cpp +++ b/kernel/windows.cpp @@ -38,7 +38,6 @@ struct Window { EsRectangle solidInsets, embedInsets; bool solid, noClickActivate, hidden, isMaximised, alwaysOnTop, hoveringOverEmbed, queuedScrollUpdate, activationClick, noBringToFront; volatile bool closed; - EsMessage lastEmbedKeyboardMessage; // The most recent keyboard message sent to the embedded window. // Appearance: Surface surface; @@ -66,8 +65,9 @@ struct WindowManager { void Initialise(); void MoveCursor(int64_t xMovement, int64_t yMovement); - void ClickCursor(unsigned buttons); - void PressKey(unsigned scancode); + void ClickCursor(uint32_t buttons); + void ScrollWheel(int32_t dx, int32_t dy); + void PressKey(uint32_t scancode); void Redraw(EsPoint position, int width, int height, Window *except = nullptr, int startingAt = 0, bool addToModifiedRegion = true); @@ -225,13 +225,16 @@ void SendMessageToWindow(Window *window, EsMessage *message) { } else { window->owner->messageQueue.SendMessage(window->apiWindow, message); } + } else if (message->type == ES_MSG_SCROLL_WHEEL) { + if (window->hoveringOverEmbed) { + window->embed->owner->messageQueue.SendMessage(window->embed->apiWindow, message); + } else { + window->owner->messageQueue.SendMessage(window->apiWindow, message); + } } else if (message->type == ES_MSG_KEY_DOWN || message->type == ES_MSG_KEY_UP) { - // If the embedded window doesn't handle the key event, - // then the container window can get it from here. - // See DESKTOP_MSG_UNHANDLED_KEY_EVENT and ES_SYSCALL_WINDOW_GET_EMBED_KEYBOARD. - EsMemoryCopy(&window->lastEmbedKeyboardMessage, message, sizeof(EsMessage)); - + // TODO Only send certain key messages to the container, like modifiers keys and global shortcuts. window->embed->owner->messageQueue.SendMessage(window->embed->apiWindow, message); + window->owner->messageQueue.SendMessage(window->apiWindow, message); } else if (message->type == ES_MSG_MOUSE_EXIT) { window->embed->owner->messageQueue.SendMessage(window->embed->apiWindow, message); window->owner->messageQueue.SendMessage(window->apiWindow, message); @@ -640,6 +643,18 @@ void WindowManager::MoveCursor(int64_t xMovement, int64_t yMovement) { GraphicsUpdateScreen(); } +void WindowManager::ScrollWheel(int32_t dx, int32_t dy) { + KMutexAssertLocked(&mutex); + Window *window = pressedWindow ?: FindWindowAtPosition(cursorX, cursorY); + if (!window) return; + EsMessage message; + EsMemoryZero(&message, sizeof(EsMessage)); + message.type = ES_MSG_SCROLL_WHEEL; + message.scrollWheel.dx = dx; + message.scrollWheel.dy = dy; + SendMessageToWindow(window, &message); +} + void _CloseWindows(uintptr_t) { while (true) { KEventWait(&windowManager.windowsToCloseEvent); @@ -1208,7 +1223,7 @@ void WindowManager::StartEyedrop(uintptr_t object, Window *avoid, uint32_t cance KMutexRelease(&mutex); } -void KCursorUpdate(int xMovement, int yMovement, unsigned buttons) { +void KMouseUpdate(int32_t xMovement, int32_t yMovement, uint32_t buttons, int32_t scrollX, int32_t scrollY) { if (!windowManager.initialised) { return; } @@ -1223,6 +1238,12 @@ void KCursorUpdate(int xMovement, int yMovement, unsigned buttons) { } } + if (scrollX || scrollY) { + KMutexAcquire(&windowManager.mutex); + windowManager.ScrollWheel(scrollX, scrollY); + KMutexRelease(&windowManager.mutex); + } + windowManager.ClickCursor(buttons); } @@ -1314,7 +1335,7 @@ void KGameControllerDisconnect(uint64_t id) { KMutexRelease(&windowManager.gameControllersMutex); } -void KGameControllerUpdateState(EsGameControllerState *state) { +void KGameControllerUpdate(EsGameControllerState *state) { KMutexAcquire(&windowManager.gameControllersMutex); for (uintptr_t i = 0; i < windowManager.gameControllerCount; i++) {