scroll wheel support

This commit is contained in:
nakst 2021-09-25 21:26:45 +01:00
parent b096bc23c4
commit 125cdfde4b
9 changed files with 72 additions and 44 deletions

View File

@ -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)

View File

@ -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]);
}

View File

@ -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();

View File

@ -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;

View File

@ -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) {

View File

@ -1,5 +1,7 @@
#include <module.h>
// #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);

View File

@ -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)

View File

@ -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);

View File

@ -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++) {