From d53c6888100061605a466a0febc59c68c062d270 Mon Sep 17 00:00:00 2001 From: Martin Fouilleul Date: Wed, 13 Sep 2023 12:22:02 +0200 Subject: [PATCH 1/3] Keyboard layout support: - Convey both fixed scancodes and keyboard-layout dependent keycodes in key events. - Update scancode to keycode mapping when keyboard layout changes - Allow querying key input state using either keycodes or scancodes --- sketches/keyboard/build.bat | 7 + sketches/keyboard/build.sh | 16 ++ sketches/keyboard/main.c | 67 +++++++ src/app/app.c | 17 ++ src/app/app.h | 271 ++++++++++++++------------ src/app/app_internal.h | 13 +- src/app/osx_app.h | 3 - src/app/osx_app.m | 379 +++++++++++++++++++----------------- src/app/win32_app.c | 308 ++++++++++++++++------------- src/runtime.c | 14 +- src/ui/input_state.c | 32 ++- src/ui/input_state.h | 5 + src/wasmbind/core_api.json | 9 + 13 files changed, 682 insertions(+), 459 deletions(-) create mode 100644 sketches/keyboard/build.bat create mode 100755 sketches/keyboard/build.sh create mode 100644 sketches/keyboard/main.c diff --git a/sketches/keyboard/build.bat b/sketches/keyboard/build.bat new file mode 100644 index 0000000..d7338a3 --- /dev/null +++ b/sketches/keyboard/build.bat @@ -0,0 +1,7 @@ + +set INCLUDES=/I ..\..\src + +if not exist "bin" mkdir bin + +cl /we4013 /Zi /Zc:preprocessor /std:c11 /experimental:c11atomics %INCLUDES% main.c /link /LIBPATH:../../build/bin orca.dll.lib /out:bin/keyboard.exe +copy ..\..\build\bin\orca.dll bin diff --git a/sketches/keyboard/build.sh b/sketches/keyboard/build.sh new file mode 100755 index 0000000..159d18c --- /dev/null +++ b/sketches/keyboard/build.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +BINDIR=bin +LIBDIR=../../build/bin +SRCDIR=../../src + +INCLUDES="-I$SRCDIR" +LIBS="-L$LIBDIR -lorca -framework Carbon -framework Cocoa -framework Metal -framework QuartzCore" +FLAGS="-mmacos-version-min=10.15.4 -DOC_DEBUG -DLOG_COMPILE_DEBUG" + +mkdir -p $BINDIR +clang -g $FLAGS $LIBS $INCLUDES -o $BINDIR/keyboard main.c + +cp $LIBDIR/liborca.dylib $BINDIR/ + +install_name_tool -add_rpath "@executable_path" $BINDIR/keyboard diff --git a/sketches/keyboard/main.c b/sketches/keyboard/main.c new file mode 100644 index 0000000..c26857d --- /dev/null +++ b/sketches/keyboard/main.c @@ -0,0 +1,67 @@ +/************************************************************************* +* +* Orca +* Copyright 2023 Martin Fouilleul and the Orca project contributors +* See LICENSE.txt for licensing information +* +**************************************************************************/ +#include "orca.h" + +int main() +{ + oc_init(); + + oc_rect rect = { .x = 100, .y = 100, .w = 200, .h = 200 }; + oc_window window = oc_window_create(rect, OC_STR8("test"), 0); + + oc_window_bring_to_front(window); + oc_window_focus(window); + + oc_window_center(window); + + oc_log_info("keycode for enter = %i\n", OC_KEY_ENTER); + + while(!oc_should_quit()) + { + oc_pump_events(0); + oc_event* event = 0; + while((event = oc_next_event(oc_scratch())) != 0) + { + switch(event->type) + { + case OC_EVENT_WINDOW_CLOSE: + { + oc_request_quit(); + } + break; + + case OC_EVENT_KEYBOARD_KEY: + { + if(event->key.action == OC_KEY_PRESS) + { + if(event->key.keyCode < 128) + { + oc_log_info("Key:\n\tscanCode = %i\n\tkeyCode = %i (%c)\n", + event->key.scanCode, + event->key.keyCode, + event->key.keyCode); + } + else + { + oc_log_info("Key:\n\tscanCode = %i\n\tkeyCode = %i\n", + event->key.scanCode, + event->key.keyCode); + } + } + } + break; + + default: + break; + } + } + oc_arena_clear(oc_scratch()); + } + oc_terminate(); + return (0); +} diff --git a/src/app/app.c b/src/app/app.c index 1ba1903..c01a93c 100644 --- a/src/app/app.c +++ b/src/app/app.c @@ -179,6 +179,23 @@ oc_event* oc_next_event(oc_arena* arena) return (event); } +//--------------------------------------------------------------- +// key / scan codes +//--------------------------------------------------------------- + +oc_key_code oc_scancode_to_keycode(oc_scan_code scanCode) +{ + return (oc_appData.keyMap[scanCode]); +} + +#define OC_DEFAULT_KEYMAP_ENTRY(sc, sv, ...) [(int) sc] = (oc_key_code)sc, + +oc_key_code oc_defaultKeyMap[OC_SCANCODE_COUNT] = { + OC_KEY_TABLE(OC_DEFAULT_KEYMAP_ENTRY) +}; + +#undef OC_DEFAULT_KEYMAP_ENTRY + //--------------------------------------------------------------- // window rects helpers //--------------------------------------------------------------- diff --git a/src/app/app.h b/src/app/app.h index 890927e..474fc98 100644 --- a/src/app/app.h +++ b/src/app/app.h @@ -12,6 +12,7 @@ #include "util/memory.h" #include "util/typedefs.h" #include "util/utf8.h" +#include "util/macros.h" #ifdef __cplusplus extern "C" { @@ -77,132 +78,147 @@ typedef enum OC_KEY_REPEAT } oc_key_action; +#define OC_KEY_TABLE(X) \ + X(OC_SCANCODE_UNKNOWN, 0, OC_KEY_UNKNOWN, '\0') \ + X(OC_SCANCODE_SPACE, 32, OC_KEY_SPACE, ' ') \ + X(OC_SCANCODE_APOSTROPHE, 39, OC_KEY_APOSTROPHE, '\'') \ + X(OC_SCANCODE_COMMA, 44, OC_KEY_COMMA, ',') \ + X(OC_SCANCODE_MINUS, 45, OC_KEY_MINUS, '-') \ + X(OC_SCANCODE_PERIOD, 46, OC_KEY_PERIOD, '.') \ + X(OC_SCANCODE_SLASH, 47, OC_KEY_SLASH, '/') \ + X(OC_SCANCODE_0, 48, OC_KEY_0, '0') \ + X(OC_SCANCODE_1, 49, OC_KEY_1, '1') \ + X(OC_SCANCODE_2, 50, OC_KEY_2, '2') \ + X(OC_SCANCODE_3, 51, OC_KEY_3, '3') \ + X(OC_SCANCODE_4, 52, OC_KEY_4, '4') \ + X(OC_SCANCODE_5, 53, OC_KEY_5, '5') \ + X(OC_SCANCODE_6, 54, OC_KEY_6, '6') \ + X(OC_SCANCODE_7, 55, OC_KEY_7, '7') \ + X(OC_SCANCODE_8, 56, OC_KEY_8, '8') \ + X(OC_SCANCODE_9, 57, OC_KEY_9, '9') \ + X(OC_SCANCODE_SEMICOLON, 59, OC_KEY_SEMICOLON, ';') \ + X(OC_SCANCODE_EQUAL, 61, OC_KEY_EQUAL, '=') \ + X(OC_SCANCODE_LEFT_BRACKET, 91, OC_KEY_LEFT_BRACKET, '[') \ + X(OC_SCANCODE_BACKSLASH, 92, OC_KEY_BACKSLASH, '\\') \ + X(OC_SCANCODE_RIGHT_BRACKET, 93, OC_KEY_RIGHT_BRACKET, ']') \ + X(OC_SCANCODE_GRAVE_ACCENT, 96, OC_KEY_GRAVE_ACCENT, '`') \ + X(OC_SCANCODE_A, 97, OC_KEY_A, 'a') \ + X(OC_SCANCODE_B, 98, OC_KEY_B, 'b') \ + X(OC_SCANCODE_C, 99, OC_KEY_C, 'c') \ + X(OC_SCANCODE_D, 100, OC_KEY_D, 'd') \ + X(OC_SCANCODE_E, 101, OC_KEY_E, 'e') \ + X(OC_SCANCODE_F, 102, OC_KEY_F, 'f') \ + X(OC_SCANCODE_G, 103, OC_KEY_G, 'g') \ + X(OC_SCANCODE_H, 104, OC_KEY_H, 'h') \ + X(OC_SCANCODE_I, 105, OC_KEY_I, 'i') \ + X(OC_SCANCODE_J, 106, OC_KEY_J, 'j') \ + X(OC_SCANCODE_K, 107, OC_KEY_K, 'k') \ + X(OC_SCANCODE_L, 108, OC_KEY_L, 'l') \ + X(OC_SCANCODE_M, 109, OC_KEY_M, 'm') \ + X(OC_SCANCODE_N, 110, OC_KEY_N, 'n') \ + X(OC_SCANCODE_O, 111, OC_KEY_O, 'o') \ + X(OC_SCANCODE_P, 112, OC_KEY_P, 'p') \ + X(OC_SCANCODE_Q, 113, OC_KEY_Q, 'q') \ + X(OC_SCANCODE_R, 114, OC_KEY_R, 'r') \ + X(OC_SCANCODE_S, 115, OC_KEY_S, 's') \ + X(OC_SCANCODE_T, 116, OC_KEY_T, 't') \ + X(OC_SCANCODE_U, 117, OC_KEY_U, 'u') \ + X(OC_SCANCODE_V, 118, OC_KEY_V, 'v') \ + X(OC_SCANCODE_W, 119, OC_KEY_W, 'w') \ + X(OC_SCANCODE_X, 120, OC_KEY_X, 'x') \ + X(OC_SCANCODE_Y, 121, OC_KEY_Y, 'y') \ + X(OC_SCANCODE_Z, 122, OC_KEY_Z, 'z') \ + X(OC_SCANCODE_WORLD_1, 161, OC_KEY_WORLD_1) \ + X(OC_SCANCODE_WORLD_2, 162, OC_KEY_WORLD_2) \ + X(OC_SCANCODE_ESCAPE, 256, OC_KEY_ESCAPE) \ + X(OC_SCANCODE_ENTER, 257, OC_KEY_ENTER) \ + X(OC_SCANCODE_TAB, 258, OC_KEY_TAB) \ + X(OC_SCANCODE_BACKSPACE, 259, OC_KEY_BACKSPACE) \ + X(OC_SCANCODE_INSERT, 260, OC_KEY_INSERT) \ + X(OC_SCANCODE_DELETE, 261, OC_KEY_DELETE) \ + X(OC_SCANCODE_RIGHT, 262, OC_KEY_RIGHT) \ + X(OC_SCANCODE_LEFT, 263, OC_KEY_LEFT) \ + X(OC_SCANCODE_DOWN, 264, OC_KEY_DOWN) \ + X(OC_SCANCODE_UP, 265, OC_KEY_UP) \ + X(OC_SCANCODE_PAGE_UP, 266, OC_KEY_PAGE_UP) \ + X(OC_SCANCODE_PAGE_DOWN, 267, OC_KEY_PAGE_DOWN) \ + X(OC_SCANCODE_HOME, 268, OC_KEY_HOME) \ + X(OC_SCANCODE_END, 269, OC_KEY_END) \ + X(OC_SCANCODE_CAPS_LOCK, 280, OC_KEY_CAPS_LOCK) \ + X(OC_SCANCODE_SCROLL_LOCK, 281, OC_KEY_SCROLL_LOCK) \ + X(OC_SCANCODE_NUM_LOCK, 282, OC_KEY_NUM_LOCK) \ + X(OC_SCANCODE_PRINT_SCREEN, 283, OC_KEY_PRINT_SCREEN) \ + X(OC_SCANCODE_PAUSE, 284, OC_KEY_PAUSE) \ + X(OC_SCANCODE_F1, 290, OC_KEY_F1) \ + X(OC_SCANCODE_F2, 291, OC_KEY_F2) \ + X(OC_SCANCODE_F3, 292, OC_KEY_F3) \ + X(OC_SCANCODE_F4, 293, OC_KEY_F4) \ + X(OC_SCANCODE_F5, 294, OC_KEY_F5) \ + X(OC_SCANCODE_F6, 295, OC_KEY_F6) \ + X(OC_SCANCODE_F7, 296, OC_KEY_F7) \ + X(OC_SCANCODE_F8, 297, OC_KEY_F8) \ + X(OC_SCANCODE_F9, 298, OC_KEY_F9) \ + X(OC_SCANCODE_F10, 299, OC_KEY_F10) \ + X(OC_SCANCODE_F11, 300, OC_KEY_F11) \ + X(OC_SCANCODE_F12, 301, OC_KEY_F12) \ + X(OC_SCANCODE_F13, 302, OC_KEY_F13) \ + X(OC_SCANCODE_F14, 303, OC_KEY_F14) \ + X(OC_SCANCODE_F15, 304, OC_KEY_F15) \ + X(OC_SCANCODE_F16, 305, OC_KEY_F16) \ + X(OC_SCANCODE_F17, 306, OC_KEY_F17) \ + X(OC_SCANCODE_F18, 307, OC_KEY_F18) \ + X(OC_SCANCODE_F19, 308, OC_KEY_F19) \ + X(OC_SCANCODE_F20, 309, OC_KEY_F20) \ + X(OC_SCANCODE_F21, 310, OC_KEY_F21) \ + X(OC_SCANCODE_F22, 311, OC_KEY_F22) \ + X(OC_SCANCODE_F23, 312, OC_KEY_F23) \ + X(OC_SCANCODE_F24, 313, OC_KEY_F24) \ + X(OC_SCANCODE_F25, 314, OC_KEY_F25) \ + X(OC_SCANCODE_KP_0, 320, OC_KEY_KP_0) \ + X(OC_SCANCODE_KP_1, 321, OC_KEY_KP_1) \ + X(OC_SCANCODE_KP_2, 322, OC_KEY_KP_2) \ + X(OC_SCANCODE_KP_3, 323, OC_KEY_KP_3) \ + X(OC_SCANCODE_KP_4, 324, OC_KEY_KP_4) \ + X(OC_SCANCODE_KP_5, 325, OC_KEY_KP_5) \ + X(OC_SCANCODE_KP_6, 326, OC_KEY_KP_6) \ + X(OC_SCANCODE_KP_7, 327, OC_KEY_KP_7) \ + X(OC_SCANCODE_KP_8, 328, OC_KEY_KP_8) \ + X(OC_SCANCODE_KP_9, 329, OC_KEY_KP_9) \ + X(OC_SCANCODE_KP_DECIMAL, 330, OC_KEY_KP_DECIMAL) \ + X(OC_SCANCODE_KP_DIVIDE, 331, OC_KEY_KP_DIVIDE) \ + X(OC_SCANCODE_KP_MULTIPLY, 332, OC_KEY_KP_MULTIPLY) \ + X(OC_SCANCODE_KP_SUBTRACT, 333, OC_KEY_KP_SUBTRACT) \ + X(OC_SCANCODE_KP_ADD, 334, OC_KEY_KP_ADD) \ + X(OC_SCANCODE_KP_ENTER, 335, OC_KEY_KP_ENTER) \ + X(OC_SCANCODE_KP_EQUAL, 336, OC_KEY_KP_EQUAL) \ + X(OC_SCANCODE_LEFT_SHIFT, 340, OC_KEY_LEFT_SHIFT) \ + X(OC_SCANCODE_LEFT_CONTROL, 341, OC_KEY_LEFT_CONTROL) \ + X(OC_SCANCODE_LEFT_ALT, 342, OC_KEY_LEFT_ALT) \ + X(OC_SCANCODE_LEFT_SUPER, 343, OC_KEY_LEFT_SUPER) \ + X(OC_SCANCODE_RIGHT_SHIFT, 344, OC_KEY_RIGHT_SHIFT) \ + X(OC_SCANCODE_RIGHT_CONTROL, 345, OC_KEY_RIGHT_CONTROL) \ + X(OC_SCANCODE_RIGHT_ALT, 346, OC_KEY_RIGHT_ALT) \ + X(OC_SCANCODE_RIGHT_SUPER, 347, OC_KEY_RIGHT_SUPER) \ + X(OC_SCANCODE_MENU, 348, OC_KEY_MENU) + +#define OC_SCANCODE_ENUM(sc, sv, ...) sc = sv, +#define OC_KEYCODE_ENUM(sc, sv, kc, ...) kc = OC_VA_NOPT(sv, ##__VA_ARGS__) __VA_ARGS__, + typedef enum { - OC_KEY_UNKNOWN = 0, - OC_KEY_SPACE = 32, - OC_KEY_APOSTROPHE = 39, /* ' */ - OC_KEY_COMMA = 44, /* , */ - OC_KEY_MINUS = 45, // - - OC_KEY_PERIOD = 46, // . - OC_KEY_SLASH = 47, // / - OC_KEY_0 = 48, - OC_KEY_1 = 49, - OC_KEY_2 = 50, - OC_KEY_3 = 51, - OC_KEY_4 = 52, - OC_KEY_5 = 53, - OC_KEY_6 = 54, - OC_KEY_7 = 55, - OC_KEY_8 = 56, - OC_KEY_9 = 57, - OC_KEY_SEMICOLON = 59, // ; - OC_KEY_EQUAL = 61, // = - OC_KEY_A = 65, - OC_KEY_B = 66, - OC_KEY_C = 67, - OC_KEY_D = 68, - OC_KEY_E = 69, - OC_KEY_F = 70, - OC_KEY_G = 71, - OC_KEY_H = 72, - OC_KEY_I = 73, - OC_KEY_J = 74, - OC_KEY_K = 75, - OC_KEY_L = 76, - OC_KEY_M = 77, - OC_KEY_N = 78, - OC_KEY_O = 79, - OC_KEY_P = 80, - OC_KEY_Q = 81, - OC_KEY_R = 82, - OC_KEY_S = 83, - OC_KEY_T = 84, - OC_KEY_U = 85, - OC_KEY_V = 86, - OC_KEY_W = 87, - OC_KEY_X = 88, - OC_KEY_Y = 89, - OC_KEY_Z = 90, - OC_KEY_LEFT_BRACKET = 91, // [ - OC_KEY_BACKSLASH = 92, // \ */ - OC_KEY_RIGHT_BRACKET = 93, // ] - OC_KEY_GRAVE_ACCENT = 96, // ` - OC_KEY_WORLD_1 = 161, // non-US #1 - OC_KEY_WORLD_2 = 162, // non-US #2 - OC_KEY_ESCAPE = 256, - OC_KEY_ENTER = 257, - OC_KEY_TAB = 258, - OC_KEY_BACKSPACE = 259, - OC_KEY_INSERT = 260, - OC_KEY_DELETE = 261, - OC_KEY_RIGHT = 262, - OC_KEY_LEFT = 263, - OC_KEY_DOWN = 264, - OC_KEY_UP = 265, - OC_KEY_PAGE_UP = 266, - OC_KEY_PAGE_DOWN = 267, - OC_KEY_HOME = 268, - OC_KEY_END = 269, - OC_KEY_CAPS_LOCK = 280, - OC_KEY_SCROLL_LOCK = 281, - OC_KEY_NUM_LOCK = 282, - OC_KEY_PRINT_SCREEN = 283, - OC_KEY_PAUSE = 284, - OC_KEY_F1 = 290, - OC_KEY_F2 = 291, - OC_KEY_F3 = 292, - OC_KEY_F4 = 293, - OC_KEY_F5 = 294, - OC_KEY_F6 = 295, - OC_KEY_F7 = 296, - OC_KEY_F8 = 297, - OC_KEY_F9 = 298, - OC_KEY_F10 = 299, - OC_KEY_F11 = 300, - OC_KEY_F12 = 301, - OC_KEY_F13 = 302, - OC_KEY_F14 = 303, - OC_KEY_F15 = 304, - OC_KEY_F16 = 305, - OC_KEY_F17 = 306, - OC_KEY_F18 = 307, - OC_KEY_F19 = 308, - OC_KEY_F20 = 309, - OC_KEY_F21 = 310, - OC_KEY_F22 = 311, - OC_KEY_F23 = 312, - OC_KEY_F24 = 313, - OC_KEY_F25 = 314, - OC_KEY_KP_0 = 320, - OC_KEY_KP_1 = 321, - OC_KEY_KP_2 = 322, - OC_KEY_KP_3 = 323, - OC_KEY_KP_4 = 324, - OC_KEY_KP_5 = 325, - OC_KEY_KP_6 = 326, - OC_KEY_KP_7 = 327, - OC_KEY_KP_8 = 328, - OC_KEY_KP_9 = 329, - OC_KEY_KP_DECIMAL = 330, - OC_KEY_KP_DIVIDE = 331, - OC_KEY_KP_MULTIPLY = 332, - OC_KEY_KP_SUBTRACT = 333, - OC_KEY_KP_ADD = 334, - OC_KEY_KP_ENTER = 335, - OC_KEY_KP_EQUAL = 336, - OC_KEY_LEFT_SHIFT = 340, - OC_KEY_LEFT_CONTROL = 341, - OC_KEY_LEFT_ALT = 342, - OC_KEY_LEFT_SUPER = 343, - OC_KEY_RIGHT_SHIFT = 344, - OC_KEY_RIGHT_CONTROL = 345, - OC_KEY_RIGHT_ALT = 346, - OC_KEY_RIGHT_SUPER = 347, - OC_KEY_MENU = 348, - OC_KEY_COUNT + OC_KEY_TABLE(OC_SCANCODE_ENUM) + OC_SCANCODE_COUNT +} oc_scan_code; + +typedef enum +{ + OC_KEY_TABLE(OC_KEYCODE_ENUM) + OC_KEY_COUNT } oc_key_code; +#undef OC_SCANCODE_ENUM +#undef OC_KEYCODE_ENUM + typedef enum { OC_KEYMOD_NONE = 0x00, @@ -226,11 +242,11 @@ typedef enum typedef struct oc_key_event // keyboard and mouse buttons input { oc_key_action action; - i32 code; + oc_scan_code scanCode; + oc_key_code keyCode; + oc_mouse_button button; oc_keymod_flags mods; - char label[8]; - u8 labelLen; - int clickCount; + u8 clickCount; } oc_key_event; typedef struct oc_char_event // character input @@ -302,6 +318,8 @@ ORCA_API oc_event* oc_next_event(oc_arena* arena); typedef void (*oc_live_resize_callback)(oc_event event, void* data); ORCA_API void oc_set_live_resize_callback(oc_live_resize_callback callback, void* data); +ORCA_API oc_key_code oc_scancode_to_keycode(oc_scan_code scanCode); + //-------------------------------------------------------------------- // window management //-------------------------------------------------------------------- @@ -459,6 +477,7 @@ void oc_window_set_title(oc_str8 title); void oc_window_set_size(oc_vec2 size); void ORCA_IMPORT(oc_request_quit)(void); +oc_key_code ORCA_IMPORT(oc_scancode_to_keycode)(oc_scan_code scanCode); #endif // !defined(OC_PLATFORM_ORCA) || !(OC_PLATFORM_ORCA) diff --git a/src/app/app_internal.h b/src/app/app_internal.h index 0eca88b..b6d0477 100644 --- a/src/app/app_internal.h +++ b/src/app/app_internal.h @@ -52,12 +52,6 @@ typedef struct oc_window_data // Global App State //--------------------------------------------------------------- -typedef struct oc_key_utf8 -{ - u8 labelLen; - char label[8]; -} oc_key_utf8; - enum { OC_APP_MAX_WINDOWS = 128 @@ -82,11 +76,12 @@ typedef struct oc_app oc_live_resize_callback liveResizeCallback; void* liveResizeData; - oc_key_utf8 keyLabels[512]; - int keyCodes[512]; - int nativeKeys[OC_KEY_COUNT]; + oc_scan_code scanCodes[OC_SCANCODE_COUNT]; // native virtual key code to oc_scan_code + oc_key_code keyMap[OC_SCANCODE_COUNT]; // oc_scan_code to oc_key_code, as per current keyboard layout OC_PLATFORM_APP_DATA } oc_app; +extern oc_key_code oc_defaultKeyMap[OC_SCANCODE_COUNT]; + #endif // __APP_INTERNAL_H_ diff --git a/src/app/osx_app.h b/src/app/osx_app.h index ac6c5f8..4a11c0d 100644 --- a/src/app/osx_app.h +++ b/src/app/osx_app.h @@ -43,9 +43,6 @@ typedef struct oc_osx_app_data { NSTimer* frameTimer; NSCursor* cursor; - - TISInputSourceRef kbLayoutInputSource; - void* kbLayoutUnicodeData; id kbLayoutListener; } oc_osx_app_data; diff --git a/src/app/osx_app.m b/src/app/osx_app.m index 6467b29..d53595d 100644 --- a/src/app/osx_app.m +++ b/src/app/osx_app.m @@ -55,143 +55,133 @@ static u32 oc_osx_get_window_style_mask(oc_window_style style) static void oc_init_osx_keys() { - memset(oc_appData.keyCodes, OC_KEY_UNKNOWN, 256 * sizeof(int)); + memset(oc_appData.scanCodes, OC_SCANCODE_UNKNOWN, 256 * sizeof(int)); - oc_appData.keyCodes[0x1D] = OC_KEY_0; - oc_appData.keyCodes[0x12] = OC_KEY_1; - oc_appData.keyCodes[0x13] = OC_KEY_2; - oc_appData.keyCodes[0x14] = OC_KEY_3; - oc_appData.keyCodes[0x15] = OC_KEY_4; - oc_appData.keyCodes[0x17] = OC_KEY_5; - oc_appData.keyCodes[0x16] = OC_KEY_6; - oc_appData.keyCodes[0x1A] = OC_KEY_7; - oc_appData.keyCodes[0x1C] = OC_KEY_8; - oc_appData.keyCodes[0x19] = OC_KEY_9; - oc_appData.keyCodes[0x00] = OC_KEY_A; - oc_appData.keyCodes[0x0B] = OC_KEY_B; - oc_appData.keyCodes[0x08] = OC_KEY_C; - oc_appData.keyCodes[0x02] = OC_KEY_D; - oc_appData.keyCodes[0x0E] = OC_KEY_E; - oc_appData.keyCodes[0x03] = OC_KEY_F; - oc_appData.keyCodes[0x05] = OC_KEY_G; - oc_appData.keyCodes[0x04] = OC_KEY_H; - oc_appData.keyCodes[0x22] = OC_KEY_I; - oc_appData.keyCodes[0x26] = OC_KEY_J; - oc_appData.keyCodes[0x28] = OC_KEY_K; - oc_appData.keyCodes[0x25] = OC_KEY_L; - oc_appData.keyCodes[0x2E] = OC_KEY_M; - oc_appData.keyCodes[0x2D] = OC_KEY_N; - oc_appData.keyCodes[0x1F] = OC_KEY_O; - oc_appData.keyCodes[0x23] = OC_KEY_P; - oc_appData.keyCodes[0x0C] = OC_KEY_Q; - oc_appData.keyCodes[0x0F] = OC_KEY_R; - oc_appData.keyCodes[0x01] = OC_KEY_S; - oc_appData.keyCodes[0x11] = OC_KEY_T; - oc_appData.keyCodes[0x20] = OC_KEY_U; - oc_appData.keyCodes[0x09] = OC_KEY_V; - oc_appData.keyCodes[0x0D] = OC_KEY_W; - oc_appData.keyCodes[0x07] = OC_KEY_X; - oc_appData.keyCodes[0x10] = OC_KEY_Y; - oc_appData.keyCodes[0x06] = OC_KEY_Z; + oc_appData.scanCodes[0x1D] = OC_SCANCODE_0; + oc_appData.scanCodes[0x12] = OC_SCANCODE_1; + oc_appData.scanCodes[0x13] = OC_SCANCODE_2; + oc_appData.scanCodes[0x14] = OC_SCANCODE_3; + oc_appData.scanCodes[0x15] = OC_SCANCODE_4; + oc_appData.scanCodes[0x17] = OC_SCANCODE_5; + oc_appData.scanCodes[0x16] = OC_SCANCODE_6; + oc_appData.scanCodes[0x1A] = OC_SCANCODE_7; + oc_appData.scanCodes[0x1C] = OC_SCANCODE_8; + oc_appData.scanCodes[0x19] = OC_SCANCODE_9; + oc_appData.scanCodes[0x00] = OC_SCANCODE_A; + oc_appData.scanCodes[0x0B] = OC_SCANCODE_B; + oc_appData.scanCodes[0x08] = OC_SCANCODE_C; + oc_appData.scanCodes[0x02] = OC_SCANCODE_D; + oc_appData.scanCodes[0x0E] = OC_SCANCODE_E; + oc_appData.scanCodes[0x03] = OC_SCANCODE_F; + oc_appData.scanCodes[0x05] = OC_SCANCODE_G; + oc_appData.scanCodes[0x04] = OC_SCANCODE_H; + oc_appData.scanCodes[0x22] = OC_SCANCODE_I; + oc_appData.scanCodes[0x26] = OC_SCANCODE_J; + oc_appData.scanCodes[0x28] = OC_SCANCODE_K; + oc_appData.scanCodes[0x25] = OC_SCANCODE_L; + oc_appData.scanCodes[0x2E] = OC_SCANCODE_M; + oc_appData.scanCodes[0x2D] = OC_SCANCODE_N; + oc_appData.scanCodes[0x1F] = OC_SCANCODE_O; + oc_appData.scanCodes[0x23] = OC_SCANCODE_P; + oc_appData.scanCodes[0x0C] = OC_SCANCODE_Q; + oc_appData.scanCodes[0x0F] = OC_SCANCODE_R; + oc_appData.scanCodes[0x01] = OC_SCANCODE_S; + oc_appData.scanCodes[0x11] = OC_SCANCODE_T; + oc_appData.scanCodes[0x20] = OC_SCANCODE_U; + oc_appData.scanCodes[0x09] = OC_SCANCODE_V; + oc_appData.scanCodes[0x0D] = OC_SCANCODE_W; + oc_appData.scanCodes[0x07] = OC_SCANCODE_X; + oc_appData.scanCodes[0x10] = OC_SCANCODE_Y; + oc_appData.scanCodes[0x06] = OC_SCANCODE_Z; - oc_appData.keyCodes[0x27] = OC_KEY_APOSTROPHE; - oc_appData.keyCodes[0x2A] = OC_KEY_BACKSLASH; - oc_appData.keyCodes[0x2B] = OC_KEY_COMMA; - oc_appData.keyCodes[0x18] = OC_KEY_EQUAL; - oc_appData.keyCodes[0x32] = OC_KEY_GRAVE_ACCENT; - oc_appData.keyCodes[0x21] = OC_KEY_LEFT_BRACKET; - oc_appData.keyCodes[0x1B] = OC_KEY_MINUS; - oc_appData.keyCodes[0x2F] = OC_KEY_PERIOD; - oc_appData.keyCodes[0x1E] = OC_KEY_RIGHT_BRACKET; - oc_appData.keyCodes[0x29] = OC_KEY_SEMICOLON; - oc_appData.keyCodes[0x2C] = OC_KEY_SLASH; - oc_appData.keyCodes[0x0A] = OC_KEY_WORLD_1; + oc_appData.scanCodes[0x27] = OC_SCANCODE_APOSTROPHE; + oc_appData.scanCodes[0x2A] = OC_SCANCODE_BACKSLASH; + oc_appData.scanCodes[0x2B] = OC_SCANCODE_COMMA; + oc_appData.scanCodes[0x18] = OC_SCANCODE_EQUAL; + oc_appData.scanCodes[0x32] = OC_SCANCODE_GRAVE_ACCENT; + oc_appData.scanCodes[0x21] = OC_SCANCODE_LEFT_BRACKET; + oc_appData.scanCodes[0x1B] = OC_SCANCODE_MINUS; + oc_appData.scanCodes[0x2F] = OC_SCANCODE_PERIOD; + oc_appData.scanCodes[0x1E] = OC_SCANCODE_RIGHT_BRACKET; + oc_appData.scanCodes[0x29] = OC_SCANCODE_SEMICOLON; + oc_appData.scanCodes[0x2C] = OC_SCANCODE_SLASH; + oc_appData.scanCodes[0x0A] = OC_SCANCODE_WORLD_1; - oc_appData.keyCodes[0x33] = OC_KEY_BACKSPACE; - oc_appData.keyCodes[0x39] = OC_KEY_CAPS_LOCK; - oc_appData.keyCodes[0x75] = OC_KEY_DELETE; - oc_appData.keyCodes[0x7D] = OC_KEY_DOWN; - oc_appData.keyCodes[0x77] = OC_KEY_END; - oc_appData.keyCodes[0x24] = OC_KEY_ENTER; - oc_appData.keyCodes[0x35] = OC_KEY_ESCAPE; - oc_appData.keyCodes[0x7A] = OC_KEY_F1; - oc_appData.keyCodes[0x78] = OC_KEY_F2; - oc_appData.keyCodes[0x63] = OC_KEY_F3; - oc_appData.keyCodes[0x76] = OC_KEY_F4; - oc_appData.keyCodes[0x60] = OC_KEY_F5; - oc_appData.keyCodes[0x61] = OC_KEY_F6; - oc_appData.keyCodes[0x62] = OC_KEY_F7; - oc_appData.keyCodes[0x64] = OC_KEY_F8; - oc_appData.keyCodes[0x65] = OC_KEY_F9; - oc_appData.keyCodes[0x6D] = OC_KEY_F10; - oc_appData.keyCodes[0x67] = OC_KEY_F11; - oc_appData.keyCodes[0x6F] = OC_KEY_F12; - oc_appData.keyCodes[0x69] = OC_KEY_F13; - oc_appData.keyCodes[0x6B] = OC_KEY_F14; - oc_appData.keyCodes[0x71] = OC_KEY_F15; - oc_appData.keyCodes[0x6A] = OC_KEY_F16; - oc_appData.keyCodes[0x40] = OC_KEY_F17; - oc_appData.keyCodes[0x4F] = OC_KEY_F18; - oc_appData.keyCodes[0x50] = OC_KEY_F19; - oc_appData.keyCodes[0x5A] = OC_KEY_F20; - oc_appData.keyCodes[0x73] = OC_KEY_HOME; - oc_appData.keyCodes[0x72] = OC_KEY_INSERT; - oc_appData.keyCodes[0x7B] = OC_KEY_LEFT; - oc_appData.keyCodes[0x3A] = OC_KEY_LEFT_ALT; - oc_appData.keyCodes[0x3B] = OC_KEY_LEFT_CONTROL; - oc_appData.keyCodes[0x38] = OC_KEY_LEFT_SHIFT; - oc_appData.keyCodes[0x37] = OC_KEY_LEFT_SUPER; - oc_appData.keyCodes[0x6E] = OC_KEY_MENU; - oc_appData.keyCodes[0x47] = OC_KEY_NUM_LOCK; - oc_appData.keyCodes[0x79] = OC_KEY_PAGE_DOWN; - oc_appData.keyCodes[0x74] = OC_KEY_PAGE_UP; - oc_appData.keyCodes[0x7C] = OC_KEY_RIGHT; - oc_appData.keyCodes[0x3D] = OC_KEY_RIGHT_ALT; - oc_appData.keyCodes[0x3E] = OC_KEY_RIGHT_CONTROL; - oc_appData.keyCodes[0x3C] = OC_KEY_RIGHT_SHIFT; - oc_appData.keyCodes[0x36] = OC_KEY_RIGHT_SUPER; - oc_appData.keyCodes[0x31] = OC_KEY_SPACE; - oc_appData.keyCodes[0x30] = OC_KEY_TAB; - oc_appData.keyCodes[0x7E] = OC_KEY_UP; + oc_appData.scanCodes[0x33] = OC_SCANCODE_BACKSPACE; + oc_appData.scanCodes[0x39] = OC_SCANCODE_CAPS_LOCK; + oc_appData.scanCodes[0x75] = OC_SCANCODE_DELETE; + oc_appData.scanCodes[0x7D] = OC_SCANCODE_DOWN; + oc_appData.scanCodes[0x77] = OC_SCANCODE_END; + oc_appData.scanCodes[0x24] = OC_SCANCODE_ENTER; + oc_appData.scanCodes[0x35] = OC_SCANCODE_ESCAPE; + oc_appData.scanCodes[0x7A] = OC_SCANCODE_F1; + oc_appData.scanCodes[0x78] = OC_SCANCODE_F2; + oc_appData.scanCodes[0x63] = OC_SCANCODE_F3; + oc_appData.scanCodes[0x76] = OC_SCANCODE_F4; + oc_appData.scanCodes[0x60] = OC_SCANCODE_F5; + oc_appData.scanCodes[0x61] = OC_SCANCODE_F6; + oc_appData.scanCodes[0x62] = OC_SCANCODE_F7; + oc_appData.scanCodes[0x64] = OC_SCANCODE_F8; + oc_appData.scanCodes[0x65] = OC_SCANCODE_F9; + oc_appData.scanCodes[0x6D] = OC_SCANCODE_F10; + oc_appData.scanCodes[0x67] = OC_SCANCODE_F11; + oc_appData.scanCodes[0x6F] = OC_SCANCODE_F12; + oc_appData.scanCodes[0x69] = OC_SCANCODE_F13; + oc_appData.scanCodes[0x6B] = OC_SCANCODE_F14; + oc_appData.scanCodes[0x71] = OC_SCANCODE_F15; + oc_appData.scanCodes[0x6A] = OC_SCANCODE_F16; + oc_appData.scanCodes[0x40] = OC_SCANCODE_F17; + oc_appData.scanCodes[0x4F] = OC_SCANCODE_F18; + oc_appData.scanCodes[0x50] = OC_SCANCODE_F19; + oc_appData.scanCodes[0x5A] = OC_SCANCODE_F20; + oc_appData.scanCodes[0x73] = OC_SCANCODE_HOME; + oc_appData.scanCodes[0x72] = OC_SCANCODE_INSERT; + oc_appData.scanCodes[0x7B] = OC_SCANCODE_LEFT; + oc_appData.scanCodes[0x3A] = OC_SCANCODE_LEFT_ALT; + oc_appData.scanCodes[0x3B] = OC_SCANCODE_LEFT_CONTROL; + oc_appData.scanCodes[0x38] = OC_SCANCODE_LEFT_SHIFT; + oc_appData.scanCodes[0x37] = OC_SCANCODE_LEFT_SUPER; + oc_appData.scanCodes[0x6E] = OC_SCANCODE_MENU; + oc_appData.scanCodes[0x47] = OC_SCANCODE_NUM_LOCK; + oc_appData.scanCodes[0x79] = OC_SCANCODE_PAGE_DOWN; + oc_appData.scanCodes[0x74] = OC_SCANCODE_PAGE_UP; + oc_appData.scanCodes[0x7C] = OC_SCANCODE_RIGHT; + oc_appData.scanCodes[0x3D] = OC_SCANCODE_RIGHT_ALT; + oc_appData.scanCodes[0x3E] = OC_SCANCODE_RIGHT_CONTROL; + oc_appData.scanCodes[0x3C] = OC_SCANCODE_RIGHT_SHIFT; + oc_appData.scanCodes[0x36] = OC_SCANCODE_RIGHT_SUPER; + oc_appData.scanCodes[0x31] = OC_SCANCODE_SPACE; + oc_appData.scanCodes[0x30] = OC_SCANCODE_TAB; + oc_appData.scanCodes[0x7E] = OC_SCANCODE_UP; - oc_appData.keyCodes[0x52] = OC_KEY_KP_0; - oc_appData.keyCodes[0x53] = OC_KEY_KP_1; - oc_appData.keyCodes[0x54] = OC_KEY_KP_2; - oc_appData.keyCodes[0x55] = OC_KEY_KP_3; - oc_appData.keyCodes[0x56] = OC_KEY_KP_4; - oc_appData.keyCodes[0x57] = OC_KEY_KP_5; - oc_appData.keyCodes[0x58] = OC_KEY_KP_6; - oc_appData.keyCodes[0x59] = OC_KEY_KP_7; - oc_appData.keyCodes[0x5B] = OC_KEY_KP_8; - oc_appData.keyCodes[0x5C] = OC_KEY_KP_9; - oc_appData.keyCodes[0x45] = OC_KEY_KP_ADD; - oc_appData.keyCodes[0x41] = OC_KEY_KP_DECIMAL; - oc_appData.keyCodes[0x4B] = OC_KEY_KP_DIVIDE; - oc_appData.keyCodes[0x4C] = OC_KEY_KP_ENTER; - oc_appData.keyCodes[0x51] = OC_KEY_KP_EQUAL; - oc_appData.keyCodes[0x43] = OC_KEY_KP_MULTIPLY; - oc_appData.keyCodes[0x4E] = OC_KEY_KP_SUBTRACT; - - memset(oc_appData.nativeKeys, 0, sizeof(int) * OC_KEY_COUNT); - for(int nativeKey = 0; nativeKey < 256; nativeKey++) - { - oc_key_code mpKey = oc_appData.keyCodes[nativeKey]; - if(mpKey) - { - oc_appData.nativeKeys[mpKey] = nativeKey; - } - } + oc_appData.scanCodes[0x52] = OC_SCANCODE_KP_0; + oc_appData.scanCodes[0x53] = OC_SCANCODE_KP_1; + oc_appData.scanCodes[0x54] = OC_SCANCODE_KP_2; + oc_appData.scanCodes[0x55] = OC_SCANCODE_KP_3; + oc_appData.scanCodes[0x56] = OC_SCANCODE_KP_4; + oc_appData.scanCodes[0x57] = OC_SCANCODE_KP_5; + oc_appData.scanCodes[0x58] = OC_SCANCODE_KP_6; + oc_appData.scanCodes[0x59] = OC_SCANCODE_KP_7; + oc_appData.scanCodes[0x5B] = OC_SCANCODE_KP_8; + oc_appData.scanCodes[0x5C] = OC_SCANCODE_KP_9; + oc_appData.scanCodes[0x45] = OC_SCANCODE_KP_ADD; + oc_appData.scanCodes[0x41] = OC_SCANCODE_KP_DECIMAL; + oc_appData.scanCodes[0x4B] = OC_SCANCODE_KP_DIVIDE; + oc_appData.scanCodes[0x4C] = OC_SCANCODE_KP_ENTER; + oc_appData.scanCodes[0x51] = OC_SCANCODE_KP_EQUAL; + oc_appData.scanCodes[0x43] = OC_SCANCODE_KP_MULTIPLY; + oc_appData.scanCodes[0x4E] = OC_SCANCODE_KP_SUBTRACT; } static int oc_convert_osx_key(unsigned short nsCode) { - if(nsCode >= 265) + if(nsCode >= OC_SCANCODE_COUNT) { - return (OC_KEY_UNKNOWN); + return (OC_SCANCODE_UNKNOWN); } else { - return (oc_appData.keyCodes[nsCode]); + return (oc_appData.scanCodes[nsCode]); } } @@ -218,64 +208,91 @@ static oc_keymod_flags oc_convert_osx_mods(NSUInteger nsFlags) return (mods); } +/////////////////////// WIP //////////////////////////////////// static void oc_update_keyboard_layout() { - if(oc_appData.osx.kbLayoutInputSource) + @autoreleasepool { - CFRelease(oc_appData.osx.kbLayoutInputSource); - oc_appData.osx.kbLayoutInputSource = 0; - oc_appData.osx.kbLayoutUnicodeData = nil; - } - - oc_appData.osx.kbLayoutInputSource = TISCopyCurrentKeyboardLayoutInputSource(); - if(!oc_appData.osx.kbLayoutInputSource) - { - oc_log_error("Failed to load keyboard layout input source"); - } - - oc_appData.osx.kbLayoutUnicodeData = TISGetInputSourceProperty(oc_appData.osx.kbLayoutInputSource, - kTISPropertyUnicodeKeyLayoutData); - if(!oc_appData.osx.kbLayoutUnicodeData) - { - oc_log_error("Failed to load keyboard layout unicode data"); - } - - memset(oc_appData.keyLabels, 0, sizeof(oc_key_utf8) * OC_KEY_COUNT); - - for(int key = 0; key < OC_KEY_COUNT; key++) - { - //TODO: check that the key is printable - int nativeKey = oc_appData.nativeKeys[key]; - - UInt32 deadKeyState = 0; - UniChar characters[4]; - UniCharCount characterCount = 0; - - if(UCKeyTranslate((UCKeyboardLayout*)[(NSData*)oc_appData.osx.kbLayoutUnicodeData bytes], - nativeKey, - kUCKeyActionDisplay, - 0, - LMGetKbdType(), - kUCKeyTranslateNoDeadKeysBit, - &deadKeyState, - sizeof(characters) / sizeof(UniChar), - &characterCount, - characters) - != noErr) + TISInputSourceRef kbLayoutInputSource = TISCopyCurrentKeyboardLayoutInputSource(); + if(!kbLayoutInputSource) { - oc_appData.keyLabels[key].labelLen = 0; + oc_log_error("Failed to load keyboard layout\n"); + goto end; } - else + + CFDataRef kbLayoutUnicodeData = TISGetInputSourceProperty(kbLayoutInputSource, + kTISPropertyUnicodeKeyLayoutData); + if(!kbLayoutUnicodeData) { - NSString* nsString = [[NSString alloc] initWithCharacters:characters length:characterCount]; - const char* cstring = [nsString UTF8String]; - u32 len = strlen(cstring); - oc_appData.keyLabels[key].labelLen = oc_min(len, 8); - memcpy(oc_appData.keyLabels[key].label, cstring, oc_appData.keyLabels[key].labelLen); + oc_log_error("Failed to load keyboard layout\n"); + goto end; } + + UCKeyboardLayout* kbdLayout = (UCKeyboardLayout*)[(NSData*)kbLayoutUnicodeData bytes]; + UInt32 kbdType = LMGetKbdType(); + + //NOTE: default US layout + memcpy(oc_appData.keyMap, oc_defaultKeyMap, sizeof(oc_key_code) * OC_SCANCODE_COUNT); + + for(int osxCode = 0; osxCode < OC_SCANCODE_COUNT; osxCode++) + { + oc_key_code keyCode = OC_KEY_UNKNOWN; + oc_scan_code scanCode = oc_appData.scanCodes[osxCode]; + + if(scanCode == OC_SCANCODE_ENTER) + { + oc_log_info("scan code enter\n"); + } + + if(scanCode != OC_SCANCODE_UNKNOWN && scanCode < 256) + { + UInt32 deadKeyState = 0; + UniChar characters[8]; + UniCharCount characterCount = 0; + + OSStatus status = UCKeyTranslate(kbdLayout, + osxCode, + kUCKeyActionDown, + 0, + kbdType, + kUCKeyTranslateNoDeadKeysBit, + &deadKeyState, + sizeof(characters) / sizeof(UniChar), + &characterCount, + characters); + + if(status == noErr) + { + oc_appData.keyMap[scanCode] = characters[0]; + } + } + } + + //NOTE fix digit row for azerty keyboards + bool azerty = true; + for(int scanCode = OC_SCANCODE_0; scanCode <= OC_SCANCODE_9; scanCode++) + { + if(oc_appData.keyMap[scanCode] >= OC_KEY_0 && oc_appData.keyMap[scanCode] <= OC_KEY_9) + { + azerty = false; + break; + } + } + if(azerty) + { + for(int scanCode = OC_SCANCODE_0; scanCode <= OC_SCANCODE_9; scanCode++) + { + oc_appData.keyMap[scanCode] = OC_KEY_0 + (scanCode - OC_SCANCODE_0); + } + } + + end: + kbLayoutUnicodeData = nil; + CFRelease(kbLayoutInputSource); } } +/* oc_str8 oc_key_to_label(oc_key_code key) { oc_key_utf8* keyInfo = &(oc_appData.keyLabels[key]); @@ -298,7 +315,7 @@ oc_key_code oc_label_to_key(oc_str8 label) } return (res); } - +*/ @interface OCWindow : NSWindow { oc_window_data* mpWindow; @@ -806,7 +823,7 @@ static void oc_process_mouse_button(NSEvent* nsEvent, oc_window_data* window, oc event.window = oc_window_handle_from_ptr(window); event.type = OC_EVENT_MOUSE_BUTTON; event.key.action = action; - event.key.code = button; + event.key.button = button; event.key.mods = oc_convert_osx_mods([nsEvent modifierFlags]); event.key.clickCount = [nsEvent clickCount]; @@ -906,12 +923,13 @@ static void oc_process_mouse_button(NSEvent* nsEvent, oc_window_data* window, oc event.window = oc_window_handle_from_ptr(window); event.type = OC_EVENT_KEYBOARD_KEY; event.key.action = action; - event.key.code = oc_convert_osx_key([nsEvent keyCode]); + event.key.scanCode = oc_convert_osx_key([nsEvent keyCode]); + event.key.keyCode = oc_scancode_to_keycode(event.key.scanCode); event.key.mods = oc_convert_osx_mods([nsEvent modifierFlags]); - oc_str8 label = oc_key_to_label(event.key.code); - event.key.labelLen = label.len; - memcpy(event.key.label, label.ptr, label.len); + // oc_str8 label = oc_key_to_label(event.key.code); + // event.key.labelLen = label.len; + // memcpy(event.key.label, label.ptr, label.len); oc_queue_event(&event); @@ -924,7 +942,8 @@ static void oc_process_mouse_button(NSEvent* nsEvent, oc_window_data* window, oc event.window = oc_window_handle_from_ptr(window); event.type = OC_EVENT_KEYBOARD_KEY; event.key.action = OC_KEY_RELEASE; - event.key.code = oc_convert_osx_key([nsEvent keyCode]); + event.key.scanCode = oc_convert_osx_key([nsEvent keyCode]); + event.key.keyCode = oc_scancode_to_keycode(event.key.scanCode); event.key.mods = oc_convert_osx_mods([nsEvent modifierFlags]); oc_queue_event(&event); diff --git a/src/app/win32_app.c b/src/app/win32_app.c index 9e4248d..2c41149 100644 --- a/src/app/win32_app.c +++ b/src/app/win32_app.c @@ -13,134 +13,173 @@ void oc_init_keys() { - memset(oc_appData.keyCodes, OC_KEY_UNKNOWN, 256 * sizeof(int)); + memset(oc_appData.scanCodes, OC_SCANCODE_UNKNOWN, 256 * sizeof(int)); - oc_appData.keyCodes[0x00B] = OC_KEY_0; - oc_appData.keyCodes[0x002] = OC_KEY_1; - oc_appData.keyCodes[0x003] = OC_KEY_2; - oc_appData.keyCodes[0x004] = OC_KEY_3; - oc_appData.keyCodes[0x005] = OC_KEY_4; - oc_appData.keyCodes[0x006] = OC_KEY_5; - oc_appData.keyCodes[0x007] = OC_KEY_6; - oc_appData.keyCodes[0x008] = OC_KEY_7; - oc_appData.keyCodes[0x009] = OC_KEY_8; - oc_appData.keyCodes[0x00A] = OC_KEY_9; - oc_appData.keyCodes[0x01E] = OC_KEY_A; - oc_appData.keyCodes[0x030] = OC_KEY_B; - oc_appData.keyCodes[0x02E] = OC_KEY_C; - oc_appData.keyCodes[0x020] = OC_KEY_D; - oc_appData.keyCodes[0x012] = OC_KEY_E; - oc_appData.keyCodes[0x021] = OC_KEY_F; - oc_appData.keyCodes[0x022] = OC_KEY_G; - oc_appData.keyCodes[0x023] = OC_KEY_H; - oc_appData.keyCodes[0x017] = OC_KEY_I; - oc_appData.keyCodes[0x024] = OC_KEY_J; - oc_appData.keyCodes[0x025] = OC_KEY_K; - oc_appData.keyCodes[0x026] = OC_KEY_L; - oc_appData.keyCodes[0x032] = OC_KEY_M; - oc_appData.keyCodes[0x031] = OC_KEY_N; - oc_appData.keyCodes[0x018] = OC_KEY_O; - oc_appData.keyCodes[0x019] = OC_KEY_P; - oc_appData.keyCodes[0x010] = OC_KEY_Q; - oc_appData.keyCodes[0x013] = OC_KEY_R; - oc_appData.keyCodes[0x01F] = OC_KEY_S; - oc_appData.keyCodes[0x014] = OC_KEY_T; - oc_appData.keyCodes[0x016] = OC_KEY_U; - oc_appData.keyCodes[0x02F] = OC_KEY_V; - oc_appData.keyCodes[0x011] = OC_KEY_W; - oc_appData.keyCodes[0x02D] = OC_KEY_X; - oc_appData.keyCodes[0x015] = OC_KEY_Y; - oc_appData.keyCodes[0x02C] = OC_KEY_Z; - oc_appData.keyCodes[0x028] = OC_KEY_APOSTROPHE; - oc_appData.keyCodes[0x02B] = OC_KEY_BACKSLASH; - oc_appData.keyCodes[0x033] = OC_KEY_COMMA; - oc_appData.keyCodes[0x00D] = OC_KEY_EQUAL; - oc_appData.keyCodes[0x029] = OC_KEY_GRAVE_ACCENT; - oc_appData.keyCodes[0x01A] = OC_KEY_LEFT_BRACKET; - oc_appData.keyCodes[0x00C] = OC_KEY_MINUS; - oc_appData.keyCodes[0x034] = OC_KEY_PERIOD; - oc_appData.keyCodes[0x01B] = OC_KEY_RIGHT_BRACKET; - oc_appData.keyCodes[0x027] = OC_KEY_SEMICOLON; - oc_appData.keyCodes[0x035] = OC_KEY_SLASH; - oc_appData.keyCodes[0x056] = OC_KEY_WORLD_2; - oc_appData.keyCodes[0x00E] = OC_KEY_BACKSPACE; - oc_appData.keyCodes[0x153] = OC_KEY_DELETE; - oc_appData.keyCodes[0x14F] = OC_KEY_END; - oc_appData.keyCodes[0x01C] = OC_KEY_ENTER; - oc_appData.keyCodes[0x001] = OC_KEY_ESCAPE; - oc_appData.keyCodes[0x147] = OC_KEY_HOME; - oc_appData.keyCodes[0x152] = OC_KEY_INSERT; - oc_appData.keyCodes[0x15D] = OC_KEY_MENU; - oc_appData.keyCodes[0x151] = OC_KEY_PAGE_DOWN; - oc_appData.keyCodes[0x149] = OC_KEY_PAGE_UP; - oc_appData.keyCodes[0x045] = OC_KEY_PAUSE; - oc_appData.keyCodes[0x146] = OC_KEY_PAUSE; - oc_appData.keyCodes[0x039] = OC_KEY_SPACE; - oc_appData.keyCodes[0x00F] = OC_KEY_TAB; - oc_appData.keyCodes[0x03A] = OC_KEY_CAPS_LOCK; - oc_appData.keyCodes[0x145] = OC_KEY_NUM_LOCK; - oc_appData.keyCodes[0x046] = OC_KEY_SCROLL_LOCK; - oc_appData.keyCodes[0x03B] = OC_KEY_F1; - oc_appData.keyCodes[0x03C] = OC_KEY_F2; - oc_appData.keyCodes[0x03D] = OC_KEY_F3; - oc_appData.keyCodes[0x03E] = OC_KEY_F4; - oc_appData.keyCodes[0x03F] = OC_KEY_F5; - oc_appData.keyCodes[0x040] = OC_KEY_F6; - oc_appData.keyCodes[0x041] = OC_KEY_F7; - oc_appData.keyCodes[0x042] = OC_KEY_F8; - oc_appData.keyCodes[0x043] = OC_KEY_F9; - oc_appData.keyCodes[0x044] = OC_KEY_F10; - oc_appData.keyCodes[0x057] = OC_KEY_F11; - oc_appData.keyCodes[0x058] = OC_KEY_F12; - oc_appData.keyCodes[0x064] = OC_KEY_F13; - oc_appData.keyCodes[0x065] = OC_KEY_F14; - oc_appData.keyCodes[0x066] = OC_KEY_F15; - oc_appData.keyCodes[0x067] = OC_KEY_F16; - oc_appData.keyCodes[0x068] = OC_KEY_F17; - oc_appData.keyCodes[0x069] = OC_KEY_F18; - oc_appData.keyCodes[0x06A] = OC_KEY_F19; - oc_appData.keyCodes[0x06B] = OC_KEY_F20; - oc_appData.keyCodes[0x06C] = OC_KEY_F21; - oc_appData.keyCodes[0x06D] = OC_KEY_F22; - oc_appData.keyCodes[0x06E] = OC_KEY_F23; - oc_appData.keyCodes[0x076] = OC_KEY_F24; - oc_appData.keyCodes[0x038] = OC_KEY_LEFT_ALT; - oc_appData.keyCodes[0x01D] = OC_KEY_LEFT_CONTROL; - oc_appData.keyCodes[0x02A] = OC_KEY_LEFT_SHIFT; - oc_appData.keyCodes[0x15B] = OC_KEY_LEFT_SUPER; - oc_appData.keyCodes[0x137] = OC_KEY_PRINT_SCREEN; - oc_appData.keyCodes[0x138] = OC_KEY_RIGHT_ALT; - oc_appData.keyCodes[0x11D] = OC_KEY_RIGHT_CONTROL; - oc_appData.keyCodes[0x036] = OC_KEY_RIGHT_SHIFT; - oc_appData.keyCodes[0x15C] = OC_KEY_RIGHT_SUPER; - oc_appData.keyCodes[0x150] = OC_KEY_DOWN; - oc_appData.keyCodes[0x14B] = OC_KEY_LEFT; - oc_appData.keyCodes[0x14D] = OC_KEY_RIGHT; - oc_appData.keyCodes[0x148] = OC_KEY_UP; - oc_appData.keyCodes[0x052] = OC_KEY_KP_0; - oc_appData.keyCodes[0x04F] = OC_KEY_KP_1; - oc_appData.keyCodes[0x050] = OC_KEY_KP_2; - oc_appData.keyCodes[0x051] = OC_KEY_KP_3; - oc_appData.keyCodes[0x04B] = OC_KEY_KP_4; - oc_appData.keyCodes[0x04C] = OC_KEY_KP_5; - oc_appData.keyCodes[0x04D] = OC_KEY_KP_6; - oc_appData.keyCodes[0x047] = OC_KEY_KP_7; - oc_appData.keyCodes[0x048] = OC_KEY_KP_8; - oc_appData.keyCodes[0x049] = OC_KEY_KP_9; - oc_appData.keyCodes[0x04E] = OC_KEY_KP_ADD; - oc_appData.keyCodes[0x053] = OC_KEY_KP_DECIMAL; - oc_appData.keyCodes[0x135] = OC_KEY_KP_DIVIDE; - oc_appData.keyCodes[0x11C] = OC_KEY_KP_ENTER; - oc_appData.keyCodes[0x037] = OC_KEY_KP_MULTIPLY; - oc_appData.keyCodes[0x04A] = OC_KEY_KP_SUBTRACT; + oc_appData.scanCodes[0x00B] = OC_SCANCODE_0; + oc_appData.scanCodes[0x002] = OC_SCANCODE_1; + oc_appData.scanCodes[0x003] = OC_SCANCODE_2; + oc_appData.scanCodes[0x004] = OC_SCANCODE_3; + oc_appData.scanCodes[0x005] = OC_SCANCODE_4; + oc_appData.scanCodes[0x006] = OC_SCANCODE_5; + oc_appData.scanCodes[0x007] = OC_SCANCODE_6; + oc_appData.scanCodes[0x008] = OC_SCANCODE_7; + oc_appData.scanCodes[0x009] = OC_SCANCODE_8; + oc_appData.scanCodes[0x00A] = OC_SCANCODE_9; + oc_appData.scanCodes[0x01E] = OC_SCANCODE_A; + oc_appData.scanCodes[0x030] = OC_SCANCODE_B; + oc_appData.scanCodes[0x02E] = OC_SCANCODE_C; + oc_appData.scanCodes[0x020] = OC_SCANCODE_D; + oc_appData.scanCodes[0x012] = OC_SCANCODE_E; + oc_appData.scanCodes[0x021] = OC_SCANCODE_F; + oc_appData.scanCodes[0x022] = OC_SCANCODE_G; + oc_appData.scanCodes[0x023] = OC_SCANCODE_H; + oc_appData.scanCodes[0x017] = OC_SCANCODE_I; + oc_appData.scanCodes[0x024] = OC_SCANCODE_J; + oc_appData.scanCodes[0x025] = OC_SCANCODE_K; + oc_appData.scanCodes[0x026] = OC_SCANCODE_L; + oc_appData.scanCodes[0x032] = OC_SCANCODE_M; + oc_appData.scanCodes[0x031] = OC_SCANCODE_N; + oc_appData.scanCodes[0x018] = OC_SCANCODE_O; + oc_appData.scanCodes[0x019] = OC_SCANCODE_P; + oc_appData.scanCodes[0x010] = OC_SCANCODE_Q; + oc_appData.scanCodes[0x013] = OC_SCANCODE_R; + oc_appData.scanCodes[0x01F] = OC_SCANCODE_S; + oc_appData.scanCodes[0x014] = OC_SCANCODE_T; + oc_appData.scanCodes[0x016] = OC_SCANCODE_U; + oc_appData.scanCodes[0x02F] = OC_SCANCODE_V; + oc_appData.scanCodes[0x011] = OC_SCANCODE_W; + oc_appData.scanCodes[0x02D] = OC_SCANCODE_X; + oc_appData.scanCodes[0x015] = OC_SCANCODE_Y; + oc_appData.scanCodes[0x02C] = OC_SCANCODE_Z; + oc_appData.scanCodes[0x028] = OC_SCANCODE_APOSTROPHE; + oc_appData.scanCodes[0x02B] = OC_SCANCODE_BACKSLASH; + oc_appData.scanCodes[0x033] = OC_SCANCODE_COMMA; + oc_appData.scanCodes[0x00D] = OC_SCANCODE_EQUAL; + oc_appData.scanCodes[0x029] = OC_SCANCODE_GRAVE_ACCENT; + oc_appData.scanCodes[0x01A] = OC_SCANCODE_LEFT_BRACKET; + oc_appData.scanCodes[0x00C] = OC_SCANCODE_MINUS; + oc_appData.scanCodes[0x034] = OC_SCANCODE_PERIOD; + oc_appData.scanCodes[0x01B] = OC_SCANCODE_RIGHT_BRACKET; + oc_appData.scanCodes[0x027] = OC_SCANCODE_SEMICOLON; + oc_appData.scanCodes[0x035] = OC_SCANCODE_SLASH; + oc_appData.scanCodes[0x056] = OC_SCANCODE_WORLD_2; + oc_appData.scanCodes[0x00E] = OC_SCANCODE_BACKSPACE; + oc_appData.scanCodes[0x153] = OC_SCANCODE_DELETE; + oc_appData.scanCodes[0x14F] = OC_SCANCODE_END; + oc_appData.scanCodes[0x01C] = OC_SCANCODE_ENTER; + oc_appData.scanCodes[0x001] = OC_SCANCODE_ESCAPE; + oc_appData.scanCodes[0x147] = OC_SCANCODE_HOME; + oc_appData.scanCodes[0x152] = OC_SCANCODE_INSERT; + oc_appData.scanCodes[0x15D] = OC_SCANCODE_MENU; + oc_appData.scanCodes[0x151] = OC_SCANCODE_PAGE_DOWN; + oc_appData.scanCodes[0x149] = OC_SCANCODE_PAGE_UP; + oc_appData.scanCodes[0x045] = OC_SCANCODE_PAUSE; + oc_appData.scanCodes[0x146] = OC_SCANCODE_PAUSE; + oc_appData.scanCodes[0x039] = OC_SCANCODE_SPACE; + oc_appData.scanCodes[0x00F] = OC_SCANCODE_TAB; + oc_appData.scanCodes[0x03A] = OC_SCANCODE_CAPS_LOCK; + oc_appData.scanCodes[0x145] = OC_SCANCODE_NUM_LOCK; + oc_appData.scanCodes[0x046] = OC_SCANCODE_SCROLL_LOCK; + oc_appData.scanCodes[0x03B] = OC_SCANCODE_F1; + oc_appData.scanCodes[0x03C] = OC_SCANCODE_F2; + oc_appData.scanCodes[0x03D] = OC_SCANCODE_F3; + oc_appData.scanCodes[0x03E] = OC_SCANCODE_F4; + oc_appData.scanCodes[0x03F] = OC_SCANCODE_F5; + oc_appData.scanCodes[0x040] = OC_SCANCODE_F6; + oc_appData.scanCodes[0x041] = OC_SCANCODE_F7; + oc_appData.scanCodes[0x042] = OC_SCANCODE_F8; + oc_appData.scanCodes[0x043] = OC_SCANCODE_F9; + oc_appData.scanCodes[0x044] = OC_SCANCODE_F10; + oc_appData.scanCodes[0x057] = OC_SCANCODE_F11; + oc_appData.scanCodes[0x058] = OC_SCANCODE_F12; + oc_appData.scanCodes[0x064] = OC_SCANCODE_F13; + oc_appData.scanCodes[0x065] = OC_SCANCODE_F14; + oc_appData.scanCodes[0x066] = OC_SCANCODE_F15; + oc_appData.scanCodes[0x067] = OC_SCANCODE_F16; + oc_appData.scanCodes[0x068] = OC_SCANCODE_F17; + oc_appData.scanCodes[0x069] = OC_SCANCODE_F18; + oc_appData.scanCodes[0x06A] = OC_SCANCODE_F19; + oc_appData.scanCodes[0x06B] = OC_SCANCODE_F20; + oc_appData.scanCodes[0x06C] = OC_SCANCODE_F21; + oc_appData.scanCodes[0x06D] = OC_SCANCODE_F22; + oc_appData.scanCodes[0x06E] = OC_SCANCODE_F23; + oc_appData.scanCodes[0x076] = OC_SCANCODE_F24; + oc_appData.scanCodes[0x038] = OC_SCANCODE_LEFT_ALT; + oc_appData.scanCodes[0x01D] = OC_SCANCODE_LEFT_CONTROL; + oc_appData.scanCodes[0x02A] = OC_SCANCODE_LEFT_SHIFT; + oc_appData.scanCodes[0x15B] = OC_SCANCODE_LEFT_SUPER; + oc_appData.scanCodes[0x137] = OC_SCANCODE_PRINT_SCREEN; + oc_appData.scanCodes[0x138] = OC_SCANCODE_RIGHT_ALT; + oc_appData.scanCodes[0x11D] = OC_SCANCODE_RIGHT_CONTROL; + oc_appData.scanCodes[0x036] = OC_SCANCODE_RIGHT_SHIFT; + oc_appData.scanCodes[0x15C] = OC_SCANCODE_RIGHT_SUPER; + oc_appData.scanCodes[0x150] = OC_SCANCODE_DOWN; + oc_appData.scanCodes[0x14B] = OC_SCANCODE_LEFT; + oc_appData.scanCodes[0x14D] = OC_SCANCODE_RIGHT; + oc_appData.scanCodes[0x148] = OC_SCANCODE_UP; + oc_appData.scanCodes[0x052] = OC_SCANCODE_KP_0; + oc_appData.scanCodes[0x04F] = OC_SCANCODE_KP_1; + oc_appData.scanCodes[0x050] = OC_SCANCODE_KP_2; + oc_appData.scanCodes[0x051] = OC_SCANCODE_KP_3; + oc_appData.scanCodes[0x04B] = OC_SCANCODE_KP_4; + oc_appData.scanCodes[0x04C] = OC_SCANCODE_KP_5; + oc_appData.scanCodes[0x04D] = OC_SCANCODE_KP_6; + oc_appData.scanCodes[0x047] = OC_SCANCODE_KP_7; + oc_appData.scanCodes[0x048] = OC_SCANCODE_KP_8; + oc_appData.scanCodes[0x049] = OC_SCANCODE_KP_9; + oc_appData.scanCodes[0x04E] = OC_SCANCODE_KP_ADD; + oc_appData.scanCodes[0x053] = OC_SCANCODE_KP_DECIMAL; + oc_appData.scanCodes[0x135] = OC_SCANCODE_KP_DIVIDE; + oc_appData.scanCodes[0x11C] = OC_SCANCODE_KP_ENTER; + oc_appData.scanCodes[0x037] = OC_SCANCODE_KP_MULTIPLY; + oc_appData.scanCodes[0x04A] = OC_SCANCODE_KP_SUBTRACT; +} - memset(oc_appData.nativeKeys, 0, sizeof(int) * OC_KEY_COUNT); - for(int nativeKey = 0; nativeKey < 256; nativeKey++) +void oc_win32_update_keyboard_layout() +{ + memcpy(oc_appData.keyMap, oc_defaultKeyMap, sizeof(oc_key_code) * OC_SCANCODE_COUNT); + + for(int winCode = 0; winCode < OC_SCANCODE_COUNT; winCode++) { - oc_key_code mpKey = oc_appData.keyCodes[nativeKey]; - if(mpKey) + oc_scan_code scanCode = oc_appData.scanCodes[winCode]; + + if(scanCode < 256) { - oc_appData.nativeKeys[mpKey] = nativeKey; + int vk = MapVirtualKey(winCode, MAPVK_VSC_TO_VK); + if(vk) + { + int ch = MapVirtualKey(vk, MAPVK_VK_TO_CHAR); + ch &= 0x7fff; + if(ch) + { + if(ch >= 'A' && ch <= 'Z') + { + oc_appData.keyMap[scanCode] = 'a' + (ch - 'A'); + } + else + { + oc_appData.keyMap[scanCode] = ch; + } + } + } + } + } + + //NOTE fix digit row for azerty keyboards + bool azerty = true; + for(int scanCode = OC_SCANCODE_0; scanCode <= OC_SCANCODE_9; scanCode++) + { + if(oc_appData.keyMap[scanCode] >= OC_KEY_0 && oc_appData.keyMap[scanCode] <= OC_KEY_9) + { + azerty = false; + break; + } + } + if(azerty) + { + for(int scanCode = OC_SCANCODE_0; scanCode <= OC_SCANCODE_9; scanCode++) + { + oc_appData.keyMap[scanCode] = OC_KEY_0 + (scanCode - OC_SCANCODE_0); } } } @@ -155,6 +194,7 @@ void oc_init() oc_init_common(); oc_init_keys(); + oc_win32_update_keyboard_layout(); oc_appData.win32.savedConsoleCodePage = GetConsoleOutputCP(); SetConsoleOutputCP(CP_UTF8); @@ -189,7 +229,7 @@ void oc_terminate() static oc_key_code oc_convert_win32_key(int code) { - return (oc_appData.keyCodes[code]); + return (oc_appData.scanCodes[code]); } static oc_keymod_flags oc_get_mod_keys() @@ -241,7 +281,7 @@ static void oc_win32_process_mouse_event(oc_window_data* window, oc_key_action a { oc_appData.win32.clickCount[button] = 0; } - for (int i = 0; i < OC_MOUSE_BUTTON_COUNT; i++) + for(int i = 0; i < OC_MOUSE_BUTTON_COUNT; i++) { if(i != button) { @@ -264,7 +304,7 @@ static void oc_win32_process_mouse_event(oc_window_data* window, oc_key_action a event.window = oc_window_handle_from_ptr(window); event.type = OC_EVENT_MOUSE_BUTTON; event.key.action = action; - event.key.code = button; + event.key.button = button; event.key.mods = oc_get_mod_keys(); event.key.clickCount = oc_appData.win32.clickCount[button]; @@ -549,6 +589,12 @@ LRESULT oc_win32_win_proc(HWND windowHandle, UINT message, WPARAM wParam, LPARAM } break; + case WM_INPUTLANGCHANGE: + { + oc_win32_update_keyboard_layout(); + } + break; + case WM_KEYDOWN: case WM_SYSKEYDOWN: { @@ -563,7 +609,8 @@ LRESULT oc_win32_win_proc(HWND windowHandle, UINT message, WPARAM wParam, LPARAM event.window = oc_window_handle_from_ptr(mpWindow); event.type = OC_EVENT_KEYBOARD_KEY; event.key.action = (lParam & 0x40000000) ? OC_KEY_REPEAT : OC_KEY_PRESS; - event.key.code = oc_convert_win32_key(HIWORD(lParam) & 0x1ff); + event.key.scanCode = oc_convert_win32_key(HIWORD(lParam) & 0x1ff); + event.key.keyCode = oc_scancode_to_keycode(event.key.scanCode); event.key.mods = oc_get_mod_keys(); oc_queue_event(&event); } @@ -581,7 +628,8 @@ LRESULT oc_win32_win_proc(HWND windowHandle, UINT message, WPARAM wParam, LPARAM event.window = oc_window_handle_from_ptr(mpWindow); event.type = OC_EVENT_KEYBOARD_KEY; event.key.action = OC_KEY_RELEASE; - event.key.code = oc_convert_win32_key(HIWORD(lParam) & 0x1ff); + event.key.scanCode = oc_convert_win32_key(HIWORD(lParam) & 0x1ff); + event.key.keyCode = oc_scancode_to_keycode(event.key.scanCode); event.key.mods = oc_get_mod_keys(); oc_queue_event(&event); } @@ -661,7 +709,7 @@ void oc_cancel_quit() void oc_request_quit() { oc_appData.shouldQuit = true; - PostThreadMessage(oc_appData.win32.mainThreadID, OC_WM_USER_WAKEUP, 0, 0); + PostThreadMessage(oc_appData.win32.mainThreadID, OC_WM_USER_WAKEUP, 0, 0); } void oc_pump_events(f64 timeout) diff --git a/src/runtime.c b/src/runtime.c index ac7f2a0..f084129 100644 --- a/src/runtime.c +++ b/src/runtime.c @@ -609,8 +609,8 @@ i32 orca_runloop(void* user) { if(exports[OC_EXPORT_MOUSE_DOWN]) { - int key = event->key.code; - const void* args[1] = { &key }; + oc_mouse_button button = event->key.button; + const void* args[1] = { &button }; M3Result res = m3_Call(exports[OC_EXPORT_MOUSE_DOWN], 1, args); if(res) { @@ -622,8 +622,8 @@ i32 orca_runloop(void* user) { if(exports[OC_EXPORT_MOUSE_UP]) { - int key = event->key.code; - const void* args[1] = { &key }; + oc_mouse_button button = event->key.button; + const void* args[1] = { &button }; M3Result res = m3_Call(exports[OC_EXPORT_MOUSE_UP], 1, args); if(res) { @@ -652,7 +652,7 @@ i32 orca_runloop(void* user) { if(event->key.action == OC_KEY_PRESS) { - if(event->key.code == OC_KEY_D + if(event->key.keyCode == OC_KEY_D && (event->key.mods & OC_KEYMOD_SHIFT) && (event->key.mods & OC_KEYMOD_MAIN_MODIFIER)) { @@ -661,7 +661,7 @@ i32 orca_runloop(void* user) if(exports[OC_EXPORT_KEY_DOWN]) { - const void* args[1] = { &event->key.code }; + const void* args[1] = { &event->key.scanCode }; M3Result res = m3_Call(exports[OC_EXPORT_KEY_DOWN], 1, args); if(res) { @@ -673,7 +673,7 @@ i32 orca_runloop(void* user) { if(exports[OC_EXPORT_KEY_UP]) { - const void* args[1] = { &event->key.code }; + const void* args[1] = { &event->key.scanCode }; M3Result res = m3_Call(exports[OC_EXPORT_KEY_UP], 1, args); if(res) { diff --git a/src/ui/input_state.c b/src/ui/input_state.c index 1a0e1d7..1d01643 100644 --- a/src/ui/input_state.c +++ b/src/ui/input_state.c @@ -140,7 +140,7 @@ void oc_input_process_event(oc_input_state* state, oc_event* event) { case OC_EVENT_KEYBOARD_KEY: { - oc_key_state* key = &state->keyboard.keys[event->key.code]; + oc_key_state* key = &state->keyboard.keys[event->key.keyCode]; oc_update_key_state(state, key, event->key.action); oc_update_key_mods(state, event->key.mods); } @@ -168,7 +168,7 @@ void oc_input_process_event(oc_input_state* state, oc_event* event) case OC_EVENT_MOUSE_BUTTON: { - oc_key_state* key = &state->mouse.buttons[event->key.code]; + oc_key_state* key = &state->mouse.buttons[event->key.button]; oc_update_key_state(state, key, event->key.action); if(event->key.action == OC_KEY_PRESS) @@ -288,6 +288,30 @@ int oc_key_repeated(oc_input_state* input, oc_key_code key) return (res); } +bool oc_key_down_scancode(oc_input_state* state, oc_scan_code scanCode) +{ + oc_key_code key = oc_scancode_to_keycode(scanCode); + return (oc_key_down(state, key)); +} + +int oc_key_pressed_scancode(oc_input_state* state, oc_scan_code scanCode) +{ + oc_key_code key = oc_scancode_to_keycode(scanCode); + return (oc_key_pressed(state, key)); +} + +int oc_key_released_scancode(oc_input_state* state, oc_scan_code scanCode) +{ + oc_key_code key = oc_scancode_to_keycode(scanCode); + return (oc_key_released(state, key)); +} + +int oc_key_repeated_scancode(oc_input_state* state, oc_scan_code scanCode) +{ + oc_key_code key = oc_scancode_to_keycode(scanCode); + return (oc_key_repeated(state, key)); +} + bool oc_mouse_down(oc_input_state* input, oc_mouse_button button) { oc_key_state state = oc_mouse_button_get_state(input, button); @@ -338,11 +362,11 @@ oc_vec2 oc_mouse_position(oc_input_state* input) { if(input->mouse.posValid) { - return (input->mouse.pos); + return (input->mouse.pos); } else { - return ((oc_vec2){ -1, -1 }); + return ((oc_vec2){ -1, -1 }); } } diff --git a/src/ui/input_state.h b/src/ui/input_state.h index 31c4564..f5de33a 100644 --- a/src/ui/input_state.h +++ b/src/ui/input_state.h @@ -83,6 +83,11 @@ ORCA_API int oc_key_pressed(oc_input_state* state, oc_key_code key); ORCA_API int oc_key_released(oc_input_state* state, oc_key_code key); ORCA_API int oc_key_repeated(oc_input_state* state, oc_key_code key); +ORCA_API bool oc_key_down_scancode(oc_input_state* state, oc_scan_code key); +ORCA_API int oc_key_pressed_scancode(oc_input_state* state, oc_scan_code key); +ORCA_API int oc_key_released_scancode(oc_input_state* state, oc_scan_code key); +ORCA_API int oc_key_repeated_scancode(oc_input_state* state, oc_scan_code key); + ORCA_API bool oc_mouse_down(oc_input_state* state, oc_mouse_button button); ORCA_API int oc_mouse_pressed(oc_input_state* state, oc_mouse_button button); ORCA_API int oc_mouse_released(oc_input_state* state, oc_mouse_button button); diff --git a/src/wasmbind/core_api.json b/src/wasmbind/core_api.json index 17c64ed..e6acbd5 100644 --- a/src/wasmbind/core_api.json +++ b/src/wasmbind/core_api.json @@ -97,5 +97,14 @@ { "name": "size", "type": {"name": "oc_vec2", "tag": "S"}} ] +}, +{ + "name": "oc_scancode_to_keycode", + "cname": "oc_scancode_to_keycode", + "ret": { "name": "oc_key_code", "tag": "i"}, + "args": [ + { "name": "scanCode", + "type": {"name": "oc_scan_code", "tag": "i"}} + ] } ] -- 2.25.1 From a1ffcd3ddc32f913998b657ee71ffaa0f2b0ba30 Mon Sep 17 00:00:00 2001 From: Martin Fouilleul Date: Wed, 13 Sep 2023 16:21:59 +0200 Subject: [PATCH 2/3] [ui] macOS text edit shortcuts --- src/ui/ui.c | 64 +++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 60 insertions(+), 4 deletions(-) diff --git a/src/ui/ui.c b/src/ui/ui.c index 6f68fe3..a0138ca 100644 --- a/src/ui/ui.c +++ b/src/ui/ui.c @@ -2778,15 +2778,29 @@ const oc_ui_edit_command OC_UI_EDIT_COMMANDS_MACOS[] = { .direction = 1 }, //NOTE(martin): move start { - .key = OC_KEY_Q, + .key = OC_KEY_A, .mods = OC_KEYMOD_CTRL, .operation = OC_UI_EDIT_MOVE, .move = OC_UI_EDIT_MOVE_LINE, .direction = -1 }, + { .key = OC_KEY_UP, .operation = OC_UI_EDIT_MOVE, .move = OC_UI_EDIT_MOVE_LINE, .direction = -1 }, + + { .key = OC_KEY_UP, + .mods = OC_KEYMOD_CMD, + .operation = OC_UI_EDIT_MOVE, + .move = OC_UI_EDIT_MOVE_LINE, + .direction = -1 }, + + { .key = OC_KEY_LEFT, + .mods = OC_KEYMOD_CMD, + .operation = OC_UI_EDIT_MOVE, + .move = OC_UI_EDIT_MOVE_LINE, + .direction = -1 }, + //NOTE(martin): move end { .key = OC_KEY_E, @@ -2794,10 +2808,24 @@ const oc_ui_edit_command OC_UI_EDIT_COMMANDS_MACOS[] = { .operation = OC_UI_EDIT_MOVE, .move = OC_UI_EDIT_MOVE_LINE, .direction = 1 }, + { .key = OC_KEY_DOWN, .operation = OC_UI_EDIT_MOVE, .move = OC_UI_EDIT_MOVE_LINE, .direction = 1 }, + + { .key = OC_KEY_DOWN, + .mods = OC_KEYMOD_CMD, + .operation = OC_UI_EDIT_MOVE, + .move = OC_UI_EDIT_MOVE_LINE, + .direction = 1 }, + + { .key = OC_KEY_RIGHT, + .mods = OC_KEYMOD_CMD, + .operation = OC_UI_EDIT_MOVE, + .move = OC_UI_EDIT_MOVE_LINE, + .direction = 1 }, + //NOTE(martin): select one left { .key = OC_KEY_LEFT, @@ -2828,16 +2856,29 @@ const oc_ui_edit_command OC_UI_EDIT_COMMANDS_MACOS[] = { .direction = 1 }, //NOTE(martin): extend select to start { - .key = OC_KEY_Q, + .key = OC_KEY_A, .mods = OC_KEYMOD_CTRL | OC_KEYMOD_SHIFT, .operation = OC_UI_EDIT_SELECT_EXTEND, .move = OC_UI_EDIT_MOVE_LINE, .direction = -1 }, + { .key = OC_KEY_UP, .mods = OC_KEYMOD_SHIFT, .operation = OC_UI_EDIT_SELECT_EXTEND, .move = OC_UI_EDIT_MOVE_LINE, .direction = -1 }, + + { .key = OC_KEY_UP, + .mods = OC_KEYMOD_CMD | OC_KEYMOD_SHIFT, + .operation = OC_UI_EDIT_SELECT_EXTEND, + .move = OC_UI_EDIT_MOVE_LINE, + .direction = -1 }, + + { .key = OC_KEY_LEFT, + .mods = OC_KEYMOD_CMD | OC_KEYMOD_SHIFT, + .operation = OC_UI_EDIT_SELECT_EXTEND, + .move = OC_UI_EDIT_MOVE_LINE, + .direction = -1 }, //NOTE(martin): extend select to end { .key = OC_KEY_E, @@ -2845,14 +2886,28 @@ const oc_ui_edit_command OC_UI_EDIT_COMMANDS_MACOS[] = { .operation = OC_UI_EDIT_SELECT_EXTEND, .move = OC_UI_EDIT_MOVE_LINE, .direction = 1 }, + { .key = OC_KEY_DOWN, .mods = OC_KEYMOD_SHIFT, .operation = OC_UI_EDIT_SELECT_EXTEND, .move = OC_UI_EDIT_MOVE_LINE, .direction = 1 }, + + { .key = OC_KEY_DOWN, + .mods = OC_KEYMOD_CMD | OC_KEYMOD_SHIFT, + .operation = OC_UI_EDIT_SELECT_EXTEND, + .move = OC_UI_EDIT_MOVE_LINE, + .direction = 1 }, + + { .key = OC_KEY_RIGHT, + .mods = OC_KEYMOD_CMD | OC_KEYMOD_SHIFT, + .operation = OC_UI_EDIT_SELECT_EXTEND, + .move = OC_UI_EDIT_MOVE_LINE, + .direction = 1 }, + //NOTE(martin): select all { - .key = OC_KEY_Q, + .key = OC_KEY_A, .mods = OC_KEYMOD_CMD, .operation = OC_UI_EDIT_SELECT_ALL, .move = OC_UI_EDIT_MOVE_NONE }, @@ -2945,6 +3000,7 @@ const oc_ui_edit_command OC_UI_EDIT_COMMANDS_WINDOWS[] = { .operation = OC_UI_EDIT_MOVE, .move = OC_UI_EDIT_MOVE_LINE, .direction = 1 }, + { .key = OC_KEY_DOWN, .operation = OC_UI_EDIT_MOVE, .move = OC_UI_EDIT_MOVE_LINE, @@ -3178,7 +3234,7 @@ oc_str32 oc_ui_edit_perform_operation(oc_ui_context* ui, oc_ui_edit_op operation case OC_UI_EDIT_MOVE: { bool wasSelectionEmpty = ui->editCursor == ui->editMark; - + //NOTE(martin): we place the cursor on the direction-most side of the selection // before performing the move u32 cursor = direction < 0 ? oc_min(ui->editCursor, ui->editMark) : oc_max(ui->editCursor, ui->editMark); -- 2.25.1 From 7026919b3892fa810abb08d4b996eec0e0eb1cee Mon Sep 17 00:00:00 2001 From: Martin Fouilleul Date: Wed, 13 Sep 2023 16:33:28 +0200 Subject: [PATCH 3/3] pass both scancode and keycode to oc_on_key_up()/oc_on_key_down() --- samples/breakout/src/main.c | 4 ++-- src/runtime.c | 8 ++++---- src/runtime.h | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/samples/breakout/src/main.c b/samples/breakout/src/main.c index 4c31de3..86d54b0 100644 --- a/samples/breakout/src/main.c +++ b/samples/breakout/src/main.c @@ -125,7 +125,7 @@ ORCA_EXPORT void oc_on_resize(u32 width, u32 height) frameSize.y = height; } -ORCA_EXPORT void oc_on_key_down(int key) +ORCA_EXPORT void oc_on_key_down(oc_scan_code scan, oc_key_code key) { oc_log_info("key down: %i", key); if(key == OC_KEY_LEFT) @@ -138,7 +138,7 @@ ORCA_EXPORT void oc_on_key_down(int key) } } -ORCA_EXPORT void oc_on_key_up(int key) +ORCA_EXPORT void oc_on_key_up(oc_scan_code scan, oc_key_code key) { oc_log_info("key up: %i", key); if(key == OC_KEY_LEFT) diff --git a/src/runtime.c b/src/runtime.c index f084129..d04e1f4 100644 --- a/src/runtime.c +++ b/src/runtime.c @@ -661,8 +661,8 @@ i32 orca_runloop(void* user) if(exports[OC_EXPORT_KEY_DOWN]) { - const void* args[1] = { &event->key.scanCode }; - M3Result res = m3_Call(exports[OC_EXPORT_KEY_DOWN], 1, args); + const void* args[2] = { &event->key.scanCode, &event->key.keyCode }; + M3Result res = m3_Call(exports[OC_EXPORT_KEY_DOWN], 2, args); if(res) { ORCA_WASM3_ABORT(app->env.m3Runtime, res, "Runtime error"); @@ -673,8 +673,8 @@ i32 orca_runloop(void* user) { if(exports[OC_EXPORT_KEY_UP]) { - const void* args[1] = { &event->key.scanCode }; - M3Result res = m3_Call(exports[OC_EXPORT_KEY_UP], 1, args); + const void* args[2] = { &event->key.scanCode, &event->key.keyCode }; + M3Result res = m3_Call(exports[OC_EXPORT_KEY_UP], 2, args); if(res) { ORCA_WASM3_ABORT(app->env.m3Runtime, res, "Runtime error"); diff --git a/src/runtime.h b/src/runtime.h index 510365a..b5513d0 100644 --- a/src/runtime.h +++ b/src/runtime.h @@ -22,8 +22,8 @@ X(OC_EXPORT_MOUSE_LEAVE, "oc_on_mouse_leave", "", "") \ X(OC_EXPORT_MOUSE_MOVE, "oc_on_mouse_move", "", "ffff") \ X(OC_EXPORT_MOUSE_WHEEL, "oc_on_mouse_wheel", "", "ff") \ - X(OC_EXPORT_KEY_DOWN, "oc_on_key_down", "", "i") \ - X(OC_EXPORT_KEY_UP, "oc_on_key_up", "", "i") \ + X(OC_EXPORT_KEY_DOWN, "oc_on_key_down", "", "ii") \ + X(OC_EXPORT_KEY_UP, "oc_on_key_up", "", "ii") \ X(OC_EXPORT_FRAME_REFRESH, "oc_on_frame_refresh", "", "") \ X(OC_EXPORT_FRAME_RESIZE, "oc_on_resize", "", "ii") \ X(OC_EXPORT_RAW_EVENT, "oc_on_raw_event", "", "i") \ -- 2.25.1