diff options
| author | trustable-code <krauter.simon@arcor.de> | 2018-05-07 21:12:54 +0200 |
|---|---|---|
| committer | trustable-code <krauter.simon@arcor.de> | 2018-05-07 21:12:54 +0200 |
| commit | f8825fa1d708c644997ad01c1a8dfaedc787727b (patch) | |
| tree | 2bd2c4cf8e5d73c3e55737869c0e7906d796e6e3 | |
| parent | 684cfa5e63123d4bb4b84d3e52e3e4418e66890a (diff) | |
| download | NiGui-f8825fa1d708c644997ad01c1a8dfaedc787727b.tar.gz NiGui-f8825fa1d708c644997ad01c1a8dfaedc787727b.zip | |
Add possibility to check, which keys are pressed togehter
New procs:
- isDown(key: Key): bool
- downKeys(): seq[Key]
| -rwxr-xr-x | examples/example_06_keyboard_events.nim | 6 | ||||
| -rwxr-xr-x | src/nigui.nim | 40 | ||||
| -rwxr-xr-x | src/nigui/private/gtk3/platform_impl.nim | 5 | ||||
| -rwxr-xr-x | src/nigui/private/windows/platform_impl.nim | 50 |
4 files changed, 81 insertions, 20 deletions
diff --git a/examples/example_06_keyboard_events.nim b/examples/example_06_keyboard_events.nim index fad1eb7..ea19404 100755 --- a/examples/example_06_keyboard_events.nim +++ b/examples/example_06_keyboard_events.nim @@ -10,7 +10,11 @@ var label = newLabel() window.add(label)
window.onKeyDown = proc(event: KeyboardEvent) =
- label.text = label.text & "KeyDown event: key: " & $event.key & ", unicode: " & $event.unicode & ", character: " & event.character & "\n"
+ label.text = label.text & "KeyDown event: key: " & $event.key & ", unicode: " & $event.unicode & ", character: " & event.character & ", down keys: " & $downKeys() & "\n"
+
+ # Ctrl + Q -> Quit application
+ if Key_Q.isDown() and Key_ControlL.isDown():
+ app.quit()
window.show()
diff --git a/src/nigui.nim b/src/nigui.nim index f7b0f36..6667719 100755 --- a/src/nigui.nim +++ b/src/nigui.nim @@ -335,8 +335,9 @@ when useGtk(): include "nigui/private/gtk3/platform_types3" # Global Variables # ---------------------------------------------------------------------------------------- -var quitOnLastWindowClose* = true -var clickMaxXYMove* = 20 +var + quitOnLastWindowClose* = true + clickMaxXYMove* = 20 # dummy type and object, needed to use get/set properties type App = object @@ -377,6 +378,10 @@ proc `clipboardText=`*(app: App, text: string) proc rgb*(red, green, blue: byte, alpha: byte = 255): Color +proc isDown*(key: Key): bool + +proc downKeys*(): seq[Key] + # ---------------------------------------------------------------------------------------- # Dialogs @@ -907,15 +912,17 @@ import unicode # Global Variables # ---------------------------------------------------------------------------------------- -var fErrorHandler: ErrorHandlerProc = nil -var windowList: seq[Window] = @[] -var fScrollbarSize = -1 +var + fErrorHandler: ErrorHandlerProc = nil + windowList: seq[Window] = @[] + fScrollbarSize = -1 + fDownKeys: seq[Key] = @[] -# Default style: -var fDefaultBackgroundColor: Color # initialized by platform-specific init() -var fDefaultTextColor: Color # initialized by platform-specific init() -var fDefaultFontFamily = "" -var fDefaultFontSize = 15.float + # Default style: + fDefaultBackgroundColor: Color # initialized by platform-specific init() + fDefaultTextColor: Color # initialized by platform-specific init() + fDefaultFontFamily = "" + fDefaultFontSize = 15.float # ---------------------------------------------------------------------------------------- @@ -1042,6 +1049,19 @@ proc newSaveFileDialog(): SaveFileDialog = result.defaultName = "" result.file = "" +proc isDown(key: Key): bool = fDownKeys.contains(key) + +proc downKeys(): seq[Key] = fDownKeys + +proc internalKeyDown(key: Key) = + if not fDownKeys.contains(key): + fDownKeys.add(key) + +proc internalKeyUp(key: Key) = + let i = fDownKeys.find(key) + if i != -1: + fDownKeys.delete(i) + # ---------------------------------------------------------------------------------------- # Canvas diff --git a/src/nigui/private/gtk3/platform_impl.nim b/src/nigui/private/gtk3/platform_impl.nim index ba4f51a..52315f1 100755 --- a/src/nigui/private/gtk3/platform_impl.nim +++ b/src/nigui/private/gtk3/platform_impl.nim @@ -88,6 +88,7 @@ proc pKeyvalToKey(keyval: cint): Key = proc pWindowKeyPressSignal(widget: pointer, event: var GdkEventKey, data: pointer): bool {.cdecl.} = let window = cast[WindowImpl](data) window.fKeyPressed = pKeyvalToKey(event.keyval) + internalKeyDown(window.fKeyPressed) if gtk_im_context_filter_keypress(window.fIMContext, event) and window.fKeyPressed == Key_None: return var evt = new KeyboardEvent @@ -104,6 +105,9 @@ proc pWindowKeyPressSignal(widget: pointer, event: var GdkEventKey, data: pointe handleException() result = evt.handled +proc pWindowKeyReleaseSignal(widget: pointer, event: var GdkEventKey): bool {.cdecl.} = + internalKeyUp(pKeyvalToKey(event.keyval)) + proc pControlKeyPressSignal(widget: pointer, event: var GdkEventKey, data: pointer): bool {.cdecl.} = let control = cast[ControlImpl](data) control.fKeyPressed = pKeyvalToKey(event.keyval) @@ -624,6 +628,7 @@ proc init(window: WindowImpl) = discard g_signal_connect_data(window.fHandle, "delete-event", pWindowDeleteSignal, cast[pointer](window)) discard g_signal_connect_data(window.fHandle, "configure-event", pWindowConfigureSignal, cast[pointer](window)) discard g_signal_connect_data(window.fHandle, "key-press-event", pWindowKeyPressSignal, cast[pointer](window)) + discard g_signal_connect_data(window.fHandle, "key-release-event", pWindowKeyReleaseSignal, cast[pointer](window)) discard g_signal_connect_data(window.fHandle, "window-state-event", pWindowStateEventSignal, cast[pointer](window)) # Enable drag and drop of files: diff --git a/src/nigui/private/windows/platform_impl.nim b/src/nigui/private/windows/platform_impl.nim index 3251b61..24d5c8c 100755 --- a/src/nigui/private/windows/platform_impl.nim +++ b/src/nigui/private/windows/platform_impl.nim @@ -231,7 +231,34 @@ proc pVirtualKeyToKey(keyval, scancode: int32): Key = of VK_DELETE: result = Key_Delete else: result = cast[Key](keyval.unicodeToUpper) +proc pWMParamsToKey(wParam, lParam: pointer): Key = + case cast[int32](wParam) + of VK_CONTROL, VK_SHIFT, VK_MENU: + let scancode = (cast[int32](lParam) and 0x00FF0000) shr 16 + case MapVirtualKeyW(scancode, MAPVK_VSC_TO_VK_EX) + of VK_LCONTROL: result = Key_ControlL + of VK_RCONTROL: result = Key_ControlR + of VK_LSHIFT: result = Key_ShiftL + of VK_RSHIFT: result = Key_ShiftR + of VK_LMENU: result = Key_AltL + of VK_RMENU: result = Key_AltR + else: discard + of VK_PRIOR: result = Key_PageUp + of VK_NEXT: result = Key_PageDown + of VK_END: result = Key_End + of VK_HOME: result = Key_Home + of VK_LEFT: result = Key_Left + of VK_UP: result = Key_Up + of VK_RIGHT: result = Key_Right + of VK_DOWN: result = Key_Down + of VK_INSERT: result = Key_Insert + of VK_DELETE: result = Key_Delete + of VK_OEM_5: result = Key_Circumflex + else: result = cast[Key](cast[int32](wParam).unicodeToUpper) + proc pHandleWMKEYDOWNOrWMCHAR(window: Window, control: Control, unicode: int): bool = + internalKeyDown(pKeyDownKey) + var windowEvent = new KeyboardEvent windowEvent.window = window windowEvent.key = pKeyDownKey @@ -262,17 +289,17 @@ proc pHandleWMKEYDOWNOrWMCHAR(window: Window, control: Control, unicode: int): b proc pHandleWMKEYDOWN(window: Window, control: Control, wParam, lParam: pointer): bool = if not GetKeyboardState(pKeyState): pRaiseLastOSError() + + pKeyDownKey = pWMParamsToKey(wParam, lParam) # Save the key for WM_CHAR, because WM_CHAR only gets the key combined with the dead key state - var widestring = newString(2) - let scancode = (cast[int32](lParam) and 0x00FF0000) shr 16 - pKeyDownKey = pVirtualKeyToKey(cast[int32](wParam), scancode) - if cast[int](wParam) == VK_OEM_5: + + if pKeyDownKey != Key_Circumflex: # When the dead key "^" on German keyboard is pressed, don't call ToUnicode(), because this would destroy the dead key state - pKeyDownKey = Key_Circumflex - return pHandleWMKEYDOWNOrWMCHAR(window, control, 0) - let ret = ToUnicode(cast[int](wParam).int32, scancode, pKeyState, widestring, 1, 0) - if ret == 1: - return # Unicode characters are handled by WM_CHAR + let scancode = (cast[int32](lParam) and 0x00FF0000) shr 16 + var widestring = newString(2) + let ret = ToUnicode(cast[int](wParam).int32, scancode, pKeyState, widestring, 1, 0) + if ret == 1: + return # Unicode characters are handled by WM_CHAR result = pHandleWMKEYDOWNOrWMCHAR(window, control, 0) proc pHandleWMCHAR(window: Window, control: Control, wParam, lParam: pointer): bool = @@ -324,6 +351,8 @@ proc pWindowWndProc(hWnd: pointer, uMsg: int32, wParam, lParam: pointer): pointe let window = cast[Window](pGetWindowLongPtr(hWnd, GWLP_USERDATA)) if window != nil and pHandleWMKEYDOWN(window, nil, wParam, lParam): return + of WM_KEYUP: + internalKeyUp(pWMParamsToKey(wParam, lParam)) of WM_CHAR: let window = cast[Window](pGetWindowLongPtr(hWnd, GWLP_USERDATA)) if window != nil and pHandleWMCHAR(window, nil, wParam, lParam): @@ -1044,6 +1073,9 @@ proc pCommonControlWndProc(hWnd: pointer, uMsg: int32, wParam, lParam: pointer): if control != nil and pHandleWMKEYDOWN(control.parentWindow, control, wParam, lParam): return PWndProcResult_False + of WM_KEYUP: + internalKeyUp(pWMParamsToKey(wParam, lParam)) + of WM_CHAR: let control = cast[Control](pGetWindowLongPtr(hWnd, GWLP_USERDATA)) if control != nil and pHandleWMCHAR(control.parentWindow, control, wParam, lParam): |
