From 599f48391433ec2d0859efa3722b5c398ab56739 Mon Sep 17 00:00:00 2001 From: Rustam Gamidov Date: Wed, 26 Feb 2020 18:45:03 +0200 Subject: [PATCH] entry: add onKeyEvent handler taking uiAreaKeyEvent --- ui.h | 1 + windows/areaevents.cpp | 37 +--------------------------------- windows/entry.cpp | 42 +++++++++++++++++++++++++++++++++++++-- windows/keyboard.hpp | 45 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 87 insertions(+), 38 deletions(-) diff --git a/ui.h b/ui.h index 4d16b4fd..e73e35b6 100644 --- a/ui.h +++ b/ui.h @@ -168,6 +168,7 @@ typedef struct uiEntry uiEntry; _UI_EXTERN char *uiEntryText(uiEntry *e); _UI_EXTERN void uiEntrySetText(uiEntry *e, const char *text); _UI_EXTERN void uiEntryOnChanged(uiEntry *e, void (*f)(uiEntry *e, void *data), void *data); +_UI_EXTERN void uiEntryOnKeyEvent(uiEntry *e, int (*f)(uiEntry *e, uiAreaKeyEvent *event)); _UI_EXTERN int uiEntryReadOnly(uiEntry *e); _UI_EXTERN void uiEntrySetReadOnly(uiEntry *e, int readonly); _UI_EXTERN uiEntry *uiNewEntry(void); diff --git a/windows/areaevents.cpp b/windows/areaevents.cpp index 3dc4a38e..c65a6b8a 100644 --- a/windows/areaevents.cpp +++ b/windows/areaevents.cpp @@ -5,23 +5,6 @@ // TODO https://github.com/Microsoft/Windows-classic-samples/blob/master/Samples/Win7Samples/multimedia/DirectWrite/PadWrite/TextEditor.cpp notes on explicit RTL handling under MirrorXCoordinate(); also in areadraw.cpp too? -static uiModifiers getModifiers(void) -{ - uiModifiers m = 0; - - if ((GetKeyState(VK_CONTROL) & 0x80) != 0) - m |= uiModifierCtrl; - if ((GetKeyState(VK_MENU) & 0x80) != 0) - m |= uiModifierAlt; - if ((GetKeyState(VK_SHIFT) & 0x80) != 0) - m |= uiModifierShift; - if ((GetKeyState(VK_LWIN) & 0x80) != 0) - m |= uiModifierSuper; - if ((GetKeyState(VK_RWIN) & 0x80) != 0) - m |= uiModifierSuper; - return m; -} - /* Windows doesn't natively support mouse crossing events. @@ -206,25 +189,7 @@ static int areaKeyEvent(uiArea *a, int up, WPARAM wParam, LPARAM lParam) goto keyFound; } - // okay, those above cases didn't match anything - // first try the extended keys - for (i = 0; extKeys[i].vk != VK_SNAPSHOT; i++) - if (extKeys[i].vk == wParam) { - ke.ExtKey = extKeys[i].extkey; - goto keyFound; - } - - // then try modifier keys - for (i = 0; modKeys[i].vk != VK_SNAPSHOT; i++) - if (modKeys[i].vk == wParam) { - ke.Modifier = modKeys[i].mod; - // and don't include the key in Modifiers - ke.Modifiers &= ~ke.Modifier; - goto keyFound; - } - - // and finally everything else - if (uiprivFromScancode((lParam >> 16) & 0xFF, &ke)) + if (fillKeyEvent(ke, wParam, lParam)) goto keyFound; // not a supported key, assume unhandled diff --git a/windows/entry.cpp b/windows/entry.cpp index 2d2b9d56..6dadf908 100644 --- a/windows/entry.cpp +++ b/windows/entry.cpp @@ -1,5 +1,6 @@ // 8 april 2015 #include "uipriv_windows.hpp" +#include "keyboard.hpp" struct uiEntry { uiWindowsControl c; @@ -7,26 +8,46 @@ struct uiEntry { void (*onChanged)(uiEntry *, void *); void *onChangedData; BOOL inhibitChanged; + int (*onKeyEvent)(uiEntry *, uiAreaKeyEvent *); + void *self; WNDPROC native_wndproc; }; - static LRESULT CALLBACK entryWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { + BOOL righthand = FALSE; + uiAreaKeyEvent ke; + ke.Key = 0; + ke.ExtKey = 0; + ke.Modifier = 0; + ke.Modifiers = getModifiers(); + ke.Up = 0; + + int (*onKeyEvent)(uiEntry *, uiAreaKeyEvent *) = (int (*)(uiEntry *, uiAreaKeyEvent *))GetProp(hwnd, L"ON_KEY_EVENT"); + uiEntry *self = (uiEntry *)GetProp(hwnd, L"SELF"); + switch (uMsg) { case WM_GETDLGCODE: return DLGC_HASSETSEL | DLGC_WANTALLKEYS; break; case WM_KEYUP: + ke.Up = 1; case WM_KEYDOWN: + if (onKeyEvent) { + fillKeyEvent(ke, wParam, lParam); + if ((*onKeyEvent)(self, &ke)) { + return TRUE; + } + } break; } WNDPROC native_wndproc = (WNDPROC)GetProp(hwnd, L"NATIVE_WNDPROC"); return CallWindowProcW(native_wndproc, hwnd, uMsg, wParam, lParam); } + static BOOL onWM_COMMAND(uiControl *c, HWND hwnd, WORD code, LRESULT *lResult) { uiEntry *e = uiEntry(c); @@ -46,6 +67,8 @@ static void uiEntryDestroy(uiControl *c) (WNDPROC)SetWindowLongPtrW(e->hwnd, GWLP_WNDPROC, (LONG_PTR)e->native_wndproc); RemoveProp(e->hwnd, L"NATIVE_WNDPROC"); + RemoveProp(e->hwnd, L"ON_KEY_EVENT"); + RemoveProp(e->hwnd, L"SELF"); uiWindowsUnregisterWM_COMMANDHandler(e->hwnd); uiWindowsEnsureDestroyWindow(e->hwnd); @@ -77,6 +100,13 @@ static void defaultOnChanged(uiEntry *e, void *data) // do nothing } +static int defaultOnKeyEvent(uiEntry *e, uiAreaKeyEvent *event) +{ + // do nothing + return FALSE; +} + + char *uiEntryText(uiEntry *e) { return uiWindowsWindowText(e->hwnd); @@ -97,6 +127,12 @@ void uiEntryOnChanged(uiEntry *e, void (*f)(uiEntry *, void *), void *data) e->onChangedData = data; } +void uiEntryOnKeyEvent(uiEntry *e, int (*f)(uiEntry *, uiAreaKeyEvent *)) +{ + e->onKeyEvent = f; + SetProp(e->hwnd, L"ON_KEY_EVENT", (HGLOBAL)(f)); +} + int uiEntryReadOnly(uiEntry *e) { return (getStyle(e->hwnd) & ES_READONLY) != 0; @@ -128,9 +164,11 @@ static uiEntry *finishNewEntry(DWORD style) uiWindowsRegisterWM_COMMANDHandler(e->hwnd, onWM_COMMAND, uiControl(e)); e->native_wndproc = (WNDPROC)SetWindowLongPtrW(e->hwnd, GWLP_WNDPROC, (LONG_PTR)entryWndProc); - SetProp(e->hwnd, L"NATIVE_WNDPROC", (HANDLE)e->native_wndproc); + SetProp(e->hwnd, L"NATIVE_WNDPROC", (HGLOBAL)e->native_wndproc); + SetProp(e->hwnd, L"SELF", (HGLOBAL)e); uiEntryOnChanged(e, defaultOnChanged, NULL); + uiEntryOnKeyEvent(e, defaultOnKeyEvent); return e; } diff --git a/windows/keyboard.hpp b/windows/keyboard.hpp index 06815072..3b4ddaa3 100644 --- a/windows/keyboard.hpp +++ b/windows/keyboard.hpp @@ -74,3 +74,48 @@ static const struct { { VK_RWIN, uiModifierSuper }, { VK_SNAPSHOT, 0 }, }; + +static uiModifiers getModifiers(void) +{ + uiModifiers m = 0; + + if ((GetKeyState(VK_CONTROL) & 0x80) != 0) + m |= uiModifierCtrl; + if ((GetKeyState(VK_MENU) & 0x80) != 0) + m |= uiModifierAlt; + if ((GetKeyState(VK_SHIFT) & 0x80) != 0) + m |= uiModifierShift; + if ((GetKeyState(VK_LWIN) & 0x80) != 0) + m |= uiModifierSuper; + if ((GetKeyState(VK_RWIN) & 0x80) != 0) + m |= uiModifierSuper; + return m; +} + + +static BOOL fillKeyEvent(uiAreaKeyEvent &ke, WPARAM wParam, LPARAM lParam) +{ + int i = 0; + + for (i = 0; extKeys[i].vk != VK_SNAPSHOT; i++) { + if (extKeys[i].vk == wParam) { + ke.ExtKey = extKeys[i].extkey; + return TRUE; + } + } + + for (i = 0; modKeys[i].vk != VK_SNAPSHOT; i++) { + if (modKeys[i].vk == wParam) { + ke.Modifier = modKeys[i].mod; + ke.Modifiers &= ~ke.Modifier; + return TRUE; + } + } + + // TODO the original code only did this if ke.Modifiers == 0 - why? + if (uiprivFromScancode((lParam >> 16) & 0xFF, &ke)) { + return TRUE; + } + + return FALSE; +}