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
This commit is contained in:
Martin Fouilleul 2023-09-13 12:22:02 +02:00
parent db36158e7a
commit d53c688810
13 changed files with 682 additions and 459 deletions

View File

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

16
sketches/keyboard/build.sh Executable file
View File

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

67
sketches/keyboard/main.c Normal file
View File

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

View File

@ -179,6 +179,23 @@ oc_event* oc_next_event(oc_arena* arena)
return (event); 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 // window rects helpers
//--------------------------------------------------------------- //---------------------------------------------------------------

View File

@ -12,6 +12,7 @@
#include "util/memory.h" #include "util/memory.h"
#include "util/typedefs.h" #include "util/typedefs.h"
#include "util/utf8.h" #include "util/utf8.h"
#include "util/macros.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
@ -77,132 +78,147 @@ typedef enum
OC_KEY_REPEAT OC_KEY_REPEAT
} oc_key_action; } 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 typedef enum
{ {
OC_KEY_UNKNOWN = 0, OC_KEY_TABLE(OC_SCANCODE_ENUM)
OC_KEY_SPACE = 32, OC_SCANCODE_COUNT
OC_KEY_APOSTROPHE = 39, /* ' */ } oc_scan_code;
OC_KEY_COMMA = 44, /* , */
OC_KEY_MINUS = 45, // - typedef enum
OC_KEY_PERIOD = 46, // . {
OC_KEY_SLASH = 47, // / OC_KEY_TABLE(OC_KEYCODE_ENUM)
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_COUNT
} oc_key_code; } oc_key_code;
#undef OC_SCANCODE_ENUM
#undef OC_KEYCODE_ENUM
typedef enum typedef enum
{ {
OC_KEYMOD_NONE = 0x00, OC_KEYMOD_NONE = 0x00,
@ -226,11 +242,11 @@ typedef enum
typedef struct oc_key_event // keyboard and mouse buttons input typedef struct oc_key_event // keyboard and mouse buttons input
{ {
oc_key_action action; oc_key_action action;
i32 code; oc_scan_code scanCode;
oc_key_code keyCode;
oc_mouse_button button;
oc_keymod_flags mods; oc_keymod_flags mods;
char label[8]; u8 clickCount;
u8 labelLen;
int clickCount;
} oc_key_event; } oc_key_event;
typedef struct oc_char_event // character input 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); 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 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 // window management
//-------------------------------------------------------------------- //--------------------------------------------------------------------
@ -459,6 +477,7 @@ void oc_window_set_title(oc_str8 title);
void oc_window_set_size(oc_vec2 size); void oc_window_set_size(oc_vec2 size);
void ORCA_IMPORT(oc_request_quit)(void); 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) #endif // !defined(OC_PLATFORM_ORCA) || !(OC_PLATFORM_ORCA)

View File

@ -52,12 +52,6 @@ typedef struct oc_window_data
// Global App State // Global App State
//--------------------------------------------------------------- //---------------------------------------------------------------
typedef struct oc_key_utf8
{
u8 labelLen;
char label[8];
} oc_key_utf8;
enum enum
{ {
OC_APP_MAX_WINDOWS = 128 OC_APP_MAX_WINDOWS = 128
@ -82,11 +76,12 @@ typedef struct oc_app
oc_live_resize_callback liveResizeCallback; oc_live_resize_callback liveResizeCallback;
void* liveResizeData; void* liveResizeData;
oc_key_utf8 keyLabels[512]; oc_scan_code scanCodes[OC_SCANCODE_COUNT]; // native virtual key code to oc_scan_code
int keyCodes[512]; oc_key_code keyMap[OC_SCANCODE_COUNT]; // oc_scan_code to oc_key_code, as per current keyboard layout
int nativeKeys[OC_KEY_COUNT];
OC_PLATFORM_APP_DATA OC_PLATFORM_APP_DATA
} oc_app; } oc_app;
extern oc_key_code oc_defaultKeyMap[OC_SCANCODE_COUNT];
#endif // __APP_INTERNAL_H_ #endif // __APP_INTERNAL_H_

View File

@ -43,9 +43,6 @@ typedef struct oc_osx_app_data
{ {
NSTimer* frameTimer; NSTimer* frameTimer;
NSCursor* cursor; NSCursor* cursor;
TISInputSourceRef kbLayoutInputSource;
void* kbLayoutUnicodeData;
id kbLayoutListener; id kbLayoutListener;
} oc_osx_app_data; } oc_osx_app_data;

View File

@ -55,143 +55,133 @@ static u32 oc_osx_get_window_style_mask(oc_window_style style)
static void oc_init_osx_keys() 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.scanCodes[0x1D] = OC_SCANCODE_0;
oc_appData.keyCodes[0x12] = OC_KEY_1; oc_appData.scanCodes[0x12] = OC_SCANCODE_1;
oc_appData.keyCodes[0x13] = OC_KEY_2; oc_appData.scanCodes[0x13] = OC_SCANCODE_2;
oc_appData.keyCodes[0x14] = OC_KEY_3; oc_appData.scanCodes[0x14] = OC_SCANCODE_3;
oc_appData.keyCodes[0x15] = OC_KEY_4; oc_appData.scanCodes[0x15] = OC_SCANCODE_4;
oc_appData.keyCodes[0x17] = OC_KEY_5; oc_appData.scanCodes[0x17] = OC_SCANCODE_5;
oc_appData.keyCodes[0x16] = OC_KEY_6; oc_appData.scanCodes[0x16] = OC_SCANCODE_6;
oc_appData.keyCodes[0x1A] = OC_KEY_7; oc_appData.scanCodes[0x1A] = OC_SCANCODE_7;
oc_appData.keyCodes[0x1C] = OC_KEY_8; oc_appData.scanCodes[0x1C] = OC_SCANCODE_8;
oc_appData.keyCodes[0x19] = OC_KEY_9; oc_appData.scanCodes[0x19] = OC_SCANCODE_9;
oc_appData.keyCodes[0x00] = OC_KEY_A; oc_appData.scanCodes[0x00] = OC_SCANCODE_A;
oc_appData.keyCodes[0x0B] = OC_KEY_B; oc_appData.scanCodes[0x0B] = OC_SCANCODE_B;
oc_appData.keyCodes[0x08] = OC_KEY_C; oc_appData.scanCodes[0x08] = OC_SCANCODE_C;
oc_appData.keyCodes[0x02] = OC_KEY_D; oc_appData.scanCodes[0x02] = OC_SCANCODE_D;
oc_appData.keyCodes[0x0E] = OC_KEY_E; oc_appData.scanCodes[0x0E] = OC_SCANCODE_E;
oc_appData.keyCodes[0x03] = OC_KEY_F; oc_appData.scanCodes[0x03] = OC_SCANCODE_F;
oc_appData.keyCodes[0x05] = OC_KEY_G; oc_appData.scanCodes[0x05] = OC_SCANCODE_G;
oc_appData.keyCodes[0x04] = OC_KEY_H; oc_appData.scanCodes[0x04] = OC_SCANCODE_H;
oc_appData.keyCodes[0x22] = OC_KEY_I; oc_appData.scanCodes[0x22] = OC_SCANCODE_I;
oc_appData.keyCodes[0x26] = OC_KEY_J; oc_appData.scanCodes[0x26] = OC_SCANCODE_J;
oc_appData.keyCodes[0x28] = OC_KEY_K; oc_appData.scanCodes[0x28] = OC_SCANCODE_K;
oc_appData.keyCodes[0x25] = OC_KEY_L; oc_appData.scanCodes[0x25] = OC_SCANCODE_L;
oc_appData.keyCodes[0x2E] = OC_KEY_M; oc_appData.scanCodes[0x2E] = OC_SCANCODE_M;
oc_appData.keyCodes[0x2D] = OC_KEY_N; oc_appData.scanCodes[0x2D] = OC_SCANCODE_N;
oc_appData.keyCodes[0x1F] = OC_KEY_O; oc_appData.scanCodes[0x1F] = OC_SCANCODE_O;
oc_appData.keyCodes[0x23] = OC_KEY_P; oc_appData.scanCodes[0x23] = OC_SCANCODE_P;
oc_appData.keyCodes[0x0C] = OC_KEY_Q; oc_appData.scanCodes[0x0C] = OC_SCANCODE_Q;
oc_appData.keyCodes[0x0F] = OC_KEY_R; oc_appData.scanCodes[0x0F] = OC_SCANCODE_R;
oc_appData.keyCodes[0x01] = OC_KEY_S; oc_appData.scanCodes[0x01] = OC_SCANCODE_S;
oc_appData.keyCodes[0x11] = OC_KEY_T; oc_appData.scanCodes[0x11] = OC_SCANCODE_T;
oc_appData.keyCodes[0x20] = OC_KEY_U; oc_appData.scanCodes[0x20] = OC_SCANCODE_U;
oc_appData.keyCodes[0x09] = OC_KEY_V; oc_appData.scanCodes[0x09] = OC_SCANCODE_V;
oc_appData.keyCodes[0x0D] = OC_KEY_W; oc_appData.scanCodes[0x0D] = OC_SCANCODE_W;
oc_appData.keyCodes[0x07] = OC_KEY_X; oc_appData.scanCodes[0x07] = OC_SCANCODE_X;
oc_appData.keyCodes[0x10] = OC_KEY_Y; oc_appData.scanCodes[0x10] = OC_SCANCODE_Y;
oc_appData.keyCodes[0x06] = OC_KEY_Z; oc_appData.scanCodes[0x06] = OC_SCANCODE_Z;
oc_appData.keyCodes[0x27] = OC_KEY_APOSTROPHE; oc_appData.scanCodes[0x27] = OC_SCANCODE_APOSTROPHE;
oc_appData.keyCodes[0x2A] = OC_KEY_BACKSLASH; oc_appData.scanCodes[0x2A] = OC_SCANCODE_BACKSLASH;
oc_appData.keyCodes[0x2B] = OC_KEY_COMMA; oc_appData.scanCodes[0x2B] = OC_SCANCODE_COMMA;
oc_appData.keyCodes[0x18] = OC_KEY_EQUAL; oc_appData.scanCodes[0x18] = OC_SCANCODE_EQUAL;
oc_appData.keyCodes[0x32] = OC_KEY_GRAVE_ACCENT; oc_appData.scanCodes[0x32] = OC_SCANCODE_GRAVE_ACCENT;
oc_appData.keyCodes[0x21] = OC_KEY_LEFT_BRACKET; oc_appData.scanCodes[0x21] = OC_SCANCODE_LEFT_BRACKET;
oc_appData.keyCodes[0x1B] = OC_KEY_MINUS; oc_appData.scanCodes[0x1B] = OC_SCANCODE_MINUS;
oc_appData.keyCodes[0x2F] = OC_KEY_PERIOD; oc_appData.scanCodes[0x2F] = OC_SCANCODE_PERIOD;
oc_appData.keyCodes[0x1E] = OC_KEY_RIGHT_BRACKET; oc_appData.scanCodes[0x1E] = OC_SCANCODE_RIGHT_BRACKET;
oc_appData.keyCodes[0x29] = OC_KEY_SEMICOLON; oc_appData.scanCodes[0x29] = OC_SCANCODE_SEMICOLON;
oc_appData.keyCodes[0x2C] = OC_KEY_SLASH; oc_appData.scanCodes[0x2C] = OC_SCANCODE_SLASH;
oc_appData.keyCodes[0x0A] = OC_KEY_WORLD_1; oc_appData.scanCodes[0x0A] = OC_SCANCODE_WORLD_1;
oc_appData.keyCodes[0x33] = OC_KEY_BACKSPACE; oc_appData.scanCodes[0x33] = OC_SCANCODE_BACKSPACE;
oc_appData.keyCodes[0x39] = OC_KEY_CAPS_LOCK; oc_appData.scanCodes[0x39] = OC_SCANCODE_CAPS_LOCK;
oc_appData.keyCodes[0x75] = OC_KEY_DELETE; oc_appData.scanCodes[0x75] = OC_SCANCODE_DELETE;
oc_appData.keyCodes[0x7D] = OC_KEY_DOWN; oc_appData.scanCodes[0x7D] = OC_SCANCODE_DOWN;
oc_appData.keyCodes[0x77] = OC_KEY_END; oc_appData.scanCodes[0x77] = OC_SCANCODE_END;
oc_appData.keyCodes[0x24] = OC_KEY_ENTER; oc_appData.scanCodes[0x24] = OC_SCANCODE_ENTER;
oc_appData.keyCodes[0x35] = OC_KEY_ESCAPE; oc_appData.scanCodes[0x35] = OC_SCANCODE_ESCAPE;
oc_appData.keyCodes[0x7A] = OC_KEY_F1; oc_appData.scanCodes[0x7A] = OC_SCANCODE_F1;
oc_appData.keyCodes[0x78] = OC_KEY_F2; oc_appData.scanCodes[0x78] = OC_SCANCODE_F2;
oc_appData.keyCodes[0x63] = OC_KEY_F3; oc_appData.scanCodes[0x63] = OC_SCANCODE_F3;
oc_appData.keyCodes[0x76] = OC_KEY_F4; oc_appData.scanCodes[0x76] = OC_SCANCODE_F4;
oc_appData.keyCodes[0x60] = OC_KEY_F5; oc_appData.scanCodes[0x60] = OC_SCANCODE_F5;
oc_appData.keyCodes[0x61] = OC_KEY_F6; oc_appData.scanCodes[0x61] = OC_SCANCODE_F6;
oc_appData.keyCodes[0x62] = OC_KEY_F7; oc_appData.scanCodes[0x62] = OC_SCANCODE_F7;
oc_appData.keyCodes[0x64] = OC_KEY_F8; oc_appData.scanCodes[0x64] = OC_SCANCODE_F8;
oc_appData.keyCodes[0x65] = OC_KEY_F9; oc_appData.scanCodes[0x65] = OC_SCANCODE_F9;
oc_appData.keyCodes[0x6D] = OC_KEY_F10; oc_appData.scanCodes[0x6D] = OC_SCANCODE_F10;
oc_appData.keyCodes[0x67] = OC_KEY_F11; oc_appData.scanCodes[0x67] = OC_SCANCODE_F11;
oc_appData.keyCodes[0x6F] = OC_KEY_F12; oc_appData.scanCodes[0x6F] = OC_SCANCODE_F12;
oc_appData.keyCodes[0x69] = OC_KEY_F13; oc_appData.scanCodes[0x69] = OC_SCANCODE_F13;
oc_appData.keyCodes[0x6B] = OC_KEY_F14; oc_appData.scanCodes[0x6B] = OC_SCANCODE_F14;
oc_appData.keyCodes[0x71] = OC_KEY_F15; oc_appData.scanCodes[0x71] = OC_SCANCODE_F15;
oc_appData.keyCodes[0x6A] = OC_KEY_F16; oc_appData.scanCodes[0x6A] = OC_SCANCODE_F16;
oc_appData.keyCodes[0x40] = OC_KEY_F17; oc_appData.scanCodes[0x40] = OC_SCANCODE_F17;
oc_appData.keyCodes[0x4F] = OC_KEY_F18; oc_appData.scanCodes[0x4F] = OC_SCANCODE_F18;
oc_appData.keyCodes[0x50] = OC_KEY_F19; oc_appData.scanCodes[0x50] = OC_SCANCODE_F19;
oc_appData.keyCodes[0x5A] = OC_KEY_F20; oc_appData.scanCodes[0x5A] = OC_SCANCODE_F20;
oc_appData.keyCodes[0x73] = OC_KEY_HOME; oc_appData.scanCodes[0x73] = OC_SCANCODE_HOME;
oc_appData.keyCodes[0x72] = OC_KEY_INSERT; oc_appData.scanCodes[0x72] = OC_SCANCODE_INSERT;
oc_appData.keyCodes[0x7B] = OC_KEY_LEFT; oc_appData.scanCodes[0x7B] = OC_SCANCODE_LEFT;
oc_appData.keyCodes[0x3A] = OC_KEY_LEFT_ALT; oc_appData.scanCodes[0x3A] = OC_SCANCODE_LEFT_ALT;
oc_appData.keyCodes[0x3B] = OC_KEY_LEFT_CONTROL; oc_appData.scanCodes[0x3B] = OC_SCANCODE_LEFT_CONTROL;
oc_appData.keyCodes[0x38] = OC_KEY_LEFT_SHIFT; oc_appData.scanCodes[0x38] = OC_SCANCODE_LEFT_SHIFT;
oc_appData.keyCodes[0x37] = OC_KEY_LEFT_SUPER; oc_appData.scanCodes[0x37] = OC_SCANCODE_LEFT_SUPER;
oc_appData.keyCodes[0x6E] = OC_KEY_MENU; oc_appData.scanCodes[0x6E] = OC_SCANCODE_MENU;
oc_appData.keyCodes[0x47] = OC_KEY_NUM_LOCK; oc_appData.scanCodes[0x47] = OC_SCANCODE_NUM_LOCK;
oc_appData.keyCodes[0x79] = OC_KEY_PAGE_DOWN; oc_appData.scanCodes[0x79] = OC_SCANCODE_PAGE_DOWN;
oc_appData.keyCodes[0x74] = OC_KEY_PAGE_UP; oc_appData.scanCodes[0x74] = OC_SCANCODE_PAGE_UP;
oc_appData.keyCodes[0x7C] = OC_KEY_RIGHT; oc_appData.scanCodes[0x7C] = OC_SCANCODE_RIGHT;
oc_appData.keyCodes[0x3D] = OC_KEY_RIGHT_ALT; oc_appData.scanCodes[0x3D] = OC_SCANCODE_RIGHT_ALT;
oc_appData.keyCodes[0x3E] = OC_KEY_RIGHT_CONTROL; oc_appData.scanCodes[0x3E] = OC_SCANCODE_RIGHT_CONTROL;
oc_appData.keyCodes[0x3C] = OC_KEY_RIGHT_SHIFT; oc_appData.scanCodes[0x3C] = OC_SCANCODE_RIGHT_SHIFT;
oc_appData.keyCodes[0x36] = OC_KEY_RIGHT_SUPER; oc_appData.scanCodes[0x36] = OC_SCANCODE_RIGHT_SUPER;
oc_appData.keyCodes[0x31] = OC_KEY_SPACE; oc_appData.scanCodes[0x31] = OC_SCANCODE_SPACE;
oc_appData.keyCodes[0x30] = OC_KEY_TAB; oc_appData.scanCodes[0x30] = OC_SCANCODE_TAB;
oc_appData.keyCodes[0x7E] = OC_KEY_UP; oc_appData.scanCodes[0x7E] = OC_SCANCODE_UP;
oc_appData.keyCodes[0x52] = OC_KEY_KP_0; oc_appData.scanCodes[0x52] = OC_SCANCODE_KP_0;
oc_appData.keyCodes[0x53] = OC_KEY_KP_1; oc_appData.scanCodes[0x53] = OC_SCANCODE_KP_1;
oc_appData.keyCodes[0x54] = OC_KEY_KP_2; oc_appData.scanCodes[0x54] = OC_SCANCODE_KP_2;
oc_appData.keyCodes[0x55] = OC_KEY_KP_3; oc_appData.scanCodes[0x55] = OC_SCANCODE_KP_3;
oc_appData.keyCodes[0x56] = OC_KEY_KP_4; oc_appData.scanCodes[0x56] = OC_SCANCODE_KP_4;
oc_appData.keyCodes[0x57] = OC_KEY_KP_5; oc_appData.scanCodes[0x57] = OC_SCANCODE_KP_5;
oc_appData.keyCodes[0x58] = OC_KEY_KP_6; oc_appData.scanCodes[0x58] = OC_SCANCODE_KP_6;
oc_appData.keyCodes[0x59] = OC_KEY_KP_7; oc_appData.scanCodes[0x59] = OC_SCANCODE_KP_7;
oc_appData.keyCodes[0x5B] = OC_KEY_KP_8; oc_appData.scanCodes[0x5B] = OC_SCANCODE_KP_8;
oc_appData.keyCodes[0x5C] = OC_KEY_KP_9; oc_appData.scanCodes[0x5C] = OC_SCANCODE_KP_9;
oc_appData.keyCodes[0x45] = OC_KEY_KP_ADD; oc_appData.scanCodes[0x45] = OC_SCANCODE_KP_ADD;
oc_appData.keyCodes[0x41] = OC_KEY_KP_DECIMAL; oc_appData.scanCodes[0x41] = OC_SCANCODE_KP_DECIMAL;
oc_appData.keyCodes[0x4B] = OC_KEY_KP_DIVIDE; oc_appData.scanCodes[0x4B] = OC_SCANCODE_KP_DIVIDE;
oc_appData.keyCodes[0x4C] = OC_KEY_KP_ENTER; oc_appData.scanCodes[0x4C] = OC_SCANCODE_KP_ENTER;
oc_appData.keyCodes[0x51] = OC_KEY_KP_EQUAL; oc_appData.scanCodes[0x51] = OC_SCANCODE_KP_EQUAL;
oc_appData.keyCodes[0x43] = OC_KEY_KP_MULTIPLY; oc_appData.scanCodes[0x43] = OC_SCANCODE_KP_MULTIPLY;
oc_appData.keyCodes[0x4E] = OC_KEY_KP_SUBTRACT; oc_appData.scanCodes[0x4E] = OC_SCANCODE_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;
}
}
} }
static int oc_convert_osx_key(unsigned short nsCode) 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 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); return (mods);
} }
/////////////////////// WIP ////////////////////////////////////
static void oc_update_keyboard_layout() static void oc_update_keyboard_layout()
{ {
if(oc_appData.osx.kbLayoutInputSource) @autoreleasepool
{ {
CFRelease(oc_appData.osx.kbLayoutInputSource); TISInputSourceRef kbLayoutInputSource = TISCopyCurrentKeyboardLayoutInputSource();
oc_appData.osx.kbLayoutInputSource = 0; if(!kbLayoutInputSource)
oc_appData.osx.kbLayoutUnicodeData = nil; {
oc_log_error("Failed to load keyboard layout\n");
goto end;
} }
oc_appData.osx.kbLayoutInputSource = TISCopyCurrentKeyboardLayoutInputSource(); CFDataRef kbLayoutUnicodeData = TISGetInputSourceProperty(kbLayoutInputSource,
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); kTISPropertyUnicodeKeyLayoutData);
if(!oc_appData.osx.kbLayoutUnicodeData) if(!kbLayoutUnicodeData)
{ {
oc_log_error("Failed to load keyboard layout unicode data"); oc_log_error("Failed to load keyboard layout\n");
goto end;
} }
memset(oc_appData.keyLabels, 0, sizeof(oc_key_utf8) * OC_KEY_COUNT); UCKeyboardLayout* kbdLayout = (UCKeyboardLayout*)[(NSData*)kbLayoutUnicodeData bytes];
UInt32 kbdType = LMGetKbdType();
for(int key = 0; key < OC_KEY_COUNT; key++) //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++)
{ {
//TODO: check that the key is printable oc_key_code keyCode = OC_KEY_UNKNOWN;
int nativeKey = oc_appData.nativeKeys[key]; 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; UInt32 deadKeyState = 0;
UniChar characters[4]; UniChar characters[8];
UniCharCount characterCount = 0; UniCharCount characterCount = 0;
if(UCKeyTranslate((UCKeyboardLayout*)[(NSData*)oc_appData.osx.kbLayoutUnicodeData bytes], OSStatus status = UCKeyTranslate(kbdLayout,
nativeKey, osxCode,
kUCKeyActionDisplay, kUCKeyActionDown,
0, 0,
LMGetKbdType(), kbdType,
kUCKeyTranslateNoDeadKeysBit, kUCKeyTranslateNoDeadKeysBit,
&deadKeyState, &deadKeyState,
sizeof(characters) / sizeof(UniChar), sizeof(characters) / sizeof(UniChar),
&characterCount, &characterCount,
characters) characters);
!= noErr)
if(status == noErr)
{ {
oc_appData.keyLabels[key].labelLen = 0; oc_appData.keyMap[scanCode] = characters[0];
}
else
{
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);
} }
} }
} }
//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_str8 oc_key_to_label(oc_key_code key)
{ {
oc_key_utf8* keyInfo = &(oc_appData.keyLabels[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); return (res);
} }
*/
@interface OCWindow : NSWindow @interface OCWindow : NSWindow
{ {
oc_window_data* mpWindow; 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.window = oc_window_handle_from_ptr(window);
event.type = OC_EVENT_MOUSE_BUTTON; event.type = OC_EVENT_MOUSE_BUTTON;
event.key.action = action; event.key.action = action;
event.key.code = button; event.key.button = button;
event.key.mods = oc_convert_osx_mods([nsEvent modifierFlags]); event.key.mods = oc_convert_osx_mods([nsEvent modifierFlags]);
event.key.clickCount = [nsEvent clickCount]; 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.window = oc_window_handle_from_ptr(window);
event.type = OC_EVENT_KEYBOARD_KEY; event.type = OC_EVENT_KEYBOARD_KEY;
event.key.action = action; 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]); event.key.mods = oc_convert_osx_mods([nsEvent modifierFlags]);
oc_str8 label = oc_key_to_label(event.key.code); // oc_str8 label = oc_key_to_label(event.key.code);
event.key.labelLen = label.len; // event.key.labelLen = label.len;
memcpy(event.key.label, label.ptr, label.len); // memcpy(event.key.label, label.ptr, label.len);
oc_queue_event(&event); 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.window = oc_window_handle_from_ptr(window);
event.type = OC_EVENT_KEYBOARD_KEY; event.type = OC_EVENT_KEYBOARD_KEY;
event.key.action = OC_KEY_RELEASE; 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]); event.key.mods = oc_convert_osx_mods([nsEvent modifierFlags]);
oc_queue_event(&event); oc_queue_event(&event);

View File

@ -13,134 +13,173 @@
void oc_init_keys() 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.scanCodes[0x00B] = OC_SCANCODE_0;
oc_appData.keyCodes[0x002] = OC_KEY_1; oc_appData.scanCodes[0x002] = OC_SCANCODE_1;
oc_appData.keyCodes[0x003] = OC_KEY_2; oc_appData.scanCodes[0x003] = OC_SCANCODE_2;
oc_appData.keyCodes[0x004] = OC_KEY_3; oc_appData.scanCodes[0x004] = OC_SCANCODE_3;
oc_appData.keyCodes[0x005] = OC_KEY_4; oc_appData.scanCodes[0x005] = OC_SCANCODE_4;
oc_appData.keyCodes[0x006] = OC_KEY_5; oc_appData.scanCodes[0x006] = OC_SCANCODE_5;
oc_appData.keyCodes[0x007] = OC_KEY_6; oc_appData.scanCodes[0x007] = OC_SCANCODE_6;
oc_appData.keyCodes[0x008] = OC_KEY_7; oc_appData.scanCodes[0x008] = OC_SCANCODE_7;
oc_appData.keyCodes[0x009] = OC_KEY_8; oc_appData.scanCodes[0x009] = OC_SCANCODE_8;
oc_appData.keyCodes[0x00A] = OC_KEY_9; oc_appData.scanCodes[0x00A] = OC_SCANCODE_9;
oc_appData.keyCodes[0x01E] = OC_KEY_A; oc_appData.scanCodes[0x01E] = OC_SCANCODE_A;
oc_appData.keyCodes[0x030] = OC_KEY_B; oc_appData.scanCodes[0x030] = OC_SCANCODE_B;
oc_appData.keyCodes[0x02E] = OC_KEY_C; oc_appData.scanCodes[0x02E] = OC_SCANCODE_C;
oc_appData.keyCodes[0x020] = OC_KEY_D; oc_appData.scanCodes[0x020] = OC_SCANCODE_D;
oc_appData.keyCodes[0x012] = OC_KEY_E; oc_appData.scanCodes[0x012] = OC_SCANCODE_E;
oc_appData.keyCodes[0x021] = OC_KEY_F; oc_appData.scanCodes[0x021] = OC_SCANCODE_F;
oc_appData.keyCodes[0x022] = OC_KEY_G; oc_appData.scanCodes[0x022] = OC_SCANCODE_G;
oc_appData.keyCodes[0x023] = OC_KEY_H; oc_appData.scanCodes[0x023] = OC_SCANCODE_H;
oc_appData.keyCodes[0x017] = OC_KEY_I; oc_appData.scanCodes[0x017] = OC_SCANCODE_I;
oc_appData.keyCodes[0x024] = OC_KEY_J; oc_appData.scanCodes[0x024] = OC_SCANCODE_J;
oc_appData.keyCodes[0x025] = OC_KEY_K; oc_appData.scanCodes[0x025] = OC_SCANCODE_K;
oc_appData.keyCodes[0x026] = OC_KEY_L; oc_appData.scanCodes[0x026] = OC_SCANCODE_L;
oc_appData.keyCodes[0x032] = OC_KEY_M; oc_appData.scanCodes[0x032] = OC_SCANCODE_M;
oc_appData.keyCodes[0x031] = OC_KEY_N; oc_appData.scanCodes[0x031] = OC_SCANCODE_N;
oc_appData.keyCodes[0x018] = OC_KEY_O; oc_appData.scanCodes[0x018] = OC_SCANCODE_O;
oc_appData.keyCodes[0x019] = OC_KEY_P; oc_appData.scanCodes[0x019] = OC_SCANCODE_P;
oc_appData.keyCodes[0x010] = OC_KEY_Q; oc_appData.scanCodes[0x010] = OC_SCANCODE_Q;
oc_appData.keyCodes[0x013] = OC_KEY_R; oc_appData.scanCodes[0x013] = OC_SCANCODE_R;
oc_appData.keyCodes[0x01F] = OC_KEY_S; oc_appData.scanCodes[0x01F] = OC_SCANCODE_S;
oc_appData.keyCodes[0x014] = OC_KEY_T; oc_appData.scanCodes[0x014] = OC_SCANCODE_T;
oc_appData.keyCodes[0x016] = OC_KEY_U; oc_appData.scanCodes[0x016] = OC_SCANCODE_U;
oc_appData.keyCodes[0x02F] = OC_KEY_V; oc_appData.scanCodes[0x02F] = OC_SCANCODE_V;
oc_appData.keyCodes[0x011] = OC_KEY_W; oc_appData.scanCodes[0x011] = OC_SCANCODE_W;
oc_appData.keyCodes[0x02D] = OC_KEY_X; oc_appData.scanCodes[0x02D] = OC_SCANCODE_X;
oc_appData.keyCodes[0x015] = OC_KEY_Y; oc_appData.scanCodes[0x015] = OC_SCANCODE_Y;
oc_appData.keyCodes[0x02C] = OC_KEY_Z; oc_appData.scanCodes[0x02C] = OC_SCANCODE_Z;
oc_appData.keyCodes[0x028] = OC_KEY_APOSTROPHE; oc_appData.scanCodes[0x028] = OC_SCANCODE_APOSTROPHE;
oc_appData.keyCodes[0x02B] = OC_KEY_BACKSLASH; oc_appData.scanCodes[0x02B] = OC_SCANCODE_BACKSLASH;
oc_appData.keyCodes[0x033] = OC_KEY_COMMA; oc_appData.scanCodes[0x033] = OC_SCANCODE_COMMA;
oc_appData.keyCodes[0x00D] = OC_KEY_EQUAL; oc_appData.scanCodes[0x00D] = OC_SCANCODE_EQUAL;
oc_appData.keyCodes[0x029] = OC_KEY_GRAVE_ACCENT; oc_appData.scanCodes[0x029] = OC_SCANCODE_GRAVE_ACCENT;
oc_appData.keyCodes[0x01A] = OC_KEY_LEFT_BRACKET; oc_appData.scanCodes[0x01A] = OC_SCANCODE_LEFT_BRACKET;
oc_appData.keyCodes[0x00C] = OC_KEY_MINUS; oc_appData.scanCodes[0x00C] = OC_SCANCODE_MINUS;
oc_appData.keyCodes[0x034] = OC_KEY_PERIOD; oc_appData.scanCodes[0x034] = OC_SCANCODE_PERIOD;
oc_appData.keyCodes[0x01B] = OC_KEY_RIGHT_BRACKET; oc_appData.scanCodes[0x01B] = OC_SCANCODE_RIGHT_BRACKET;
oc_appData.keyCodes[0x027] = OC_KEY_SEMICOLON; oc_appData.scanCodes[0x027] = OC_SCANCODE_SEMICOLON;
oc_appData.keyCodes[0x035] = OC_KEY_SLASH; oc_appData.scanCodes[0x035] = OC_SCANCODE_SLASH;
oc_appData.keyCodes[0x056] = OC_KEY_WORLD_2; oc_appData.scanCodes[0x056] = OC_SCANCODE_WORLD_2;
oc_appData.keyCodes[0x00E] = OC_KEY_BACKSPACE; oc_appData.scanCodes[0x00E] = OC_SCANCODE_BACKSPACE;
oc_appData.keyCodes[0x153] = OC_KEY_DELETE; oc_appData.scanCodes[0x153] = OC_SCANCODE_DELETE;
oc_appData.keyCodes[0x14F] = OC_KEY_END; oc_appData.scanCodes[0x14F] = OC_SCANCODE_END;
oc_appData.keyCodes[0x01C] = OC_KEY_ENTER; oc_appData.scanCodes[0x01C] = OC_SCANCODE_ENTER;
oc_appData.keyCodes[0x001] = OC_KEY_ESCAPE; oc_appData.scanCodes[0x001] = OC_SCANCODE_ESCAPE;
oc_appData.keyCodes[0x147] = OC_KEY_HOME; oc_appData.scanCodes[0x147] = OC_SCANCODE_HOME;
oc_appData.keyCodes[0x152] = OC_KEY_INSERT; oc_appData.scanCodes[0x152] = OC_SCANCODE_INSERT;
oc_appData.keyCodes[0x15D] = OC_KEY_MENU; oc_appData.scanCodes[0x15D] = OC_SCANCODE_MENU;
oc_appData.keyCodes[0x151] = OC_KEY_PAGE_DOWN; oc_appData.scanCodes[0x151] = OC_SCANCODE_PAGE_DOWN;
oc_appData.keyCodes[0x149] = OC_KEY_PAGE_UP; oc_appData.scanCodes[0x149] = OC_SCANCODE_PAGE_UP;
oc_appData.keyCodes[0x045] = OC_KEY_PAUSE; oc_appData.scanCodes[0x045] = OC_SCANCODE_PAUSE;
oc_appData.keyCodes[0x146] = OC_KEY_PAUSE; oc_appData.scanCodes[0x146] = OC_SCANCODE_PAUSE;
oc_appData.keyCodes[0x039] = OC_KEY_SPACE; oc_appData.scanCodes[0x039] = OC_SCANCODE_SPACE;
oc_appData.keyCodes[0x00F] = OC_KEY_TAB; oc_appData.scanCodes[0x00F] = OC_SCANCODE_TAB;
oc_appData.keyCodes[0x03A] = OC_KEY_CAPS_LOCK; oc_appData.scanCodes[0x03A] = OC_SCANCODE_CAPS_LOCK;
oc_appData.keyCodes[0x145] = OC_KEY_NUM_LOCK; oc_appData.scanCodes[0x145] = OC_SCANCODE_NUM_LOCK;
oc_appData.keyCodes[0x046] = OC_KEY_SCROLL_LOCK; oc_appData.scanCodes[0x046] = OC_SCANCODE_SCROLL_LOCK;
oc_appData.keyCodes[0x03B] = OC_KEY_F1; oc_appData.scanCodes[0x03B] = OC_SCANCODE_F1;
oc_appData.keyCodes[0x03C] = OC_KEY_F2; oc_appData.scanCodes[0x03C] = OC_SCANCODE_F2;
oc_appData.keyCodes[0x03D] = OC_KEY_F3; oc_appData.scanCodes[0x03D] = OC_SCANCODE_F3;
oc_appData.keyCodes[0x03E] = OC_KEY_F4; oc_appData.scanCodes[0x03E] = OC_SCANCODE_F4;
oc_appData.keyCodes[0x03F] = OC_KEY_F5; oc_appData.scanCodes[0x03F] = OC_SCANCODE_F5;
oc_appData.keyCodes[0x040] = OC_KEY_F6; oc_appData.scanCodes[0x040] = OC_SCANCODE_F6;
oc_appData.keyCodes[0x041] = OC_KEY_F7; oc_appData.scanCodes[0x041] = OC_SCANCODE_F7;
oc_appData.keyCodes[0x042] = OC_KEY_F8; oc_appData.scanCodes[0x042] = OC_SCANCODE_F8;
oc_appData.keyCodes[0x043] = OC_KEY_F9; oc_appData.scanCodes[0x043] = OC_SCANCODE_F9;
oc_appData.keyCodes[0x044] = OC_KEY_F10; oc_appData.scanCodes[0x044] = OC_SCANCODE_F10;
oc_appData.keyCodes[0x057] = OC_KEY_F11; oc_appData.scanCodes[0x057] = OC_SCANCODE_F11;
oc_appData.keyCodes[0x058] = OC_KEY_F12; oc_appData.scanCodes[0x058] = OC_SCANCODE_F12;
oc_appData.keyCodes[0x064] = OC_KEY_F13; oc_appData.scanCodes[0x064] = OC_SCANCODE_F13;
oc_appData.keyCodes[0x065] = OC_KEY_F14; oc_appData.scanCodes[0x065] = OC_SCANCODE_F14;
oc_appData.keyCodes[0x066] = OC_KEY_F15; oc_appData.scanCodes[0x066] = OC_SCANCODE_F15;
oc_appData.keyCodes[0x067] = OC_KEY_F16; oc_appData.scanCodes[0x067] = OC_SCANCODE_F16;
oc_appData.keyCodes[0x068] = OC_KEY_F17; oc_appData.scanCodes[0x068] = OC_SCANCODE_F17;
oc_appData.keyCodes[0x069] = OC_KEY_F18; oc_appData.scanCodes[0x069] = OC_SCANCODE_F18;
oc_appData.keyCodes[0x06A] = OC_KEY_F19; oc_appData.scanCodes[0x06A] = OC_SCANCODE_F19;
oc_appData.keyCodes[0x06B] = OC_KEY_F20; oc_appData.scanCodes[0x06B] = OC_SCANCODE_F20;
oc_appData.keyCodes[0x06C] = OC_KEY_F21; oc_appData.scanCodes[0x06C] = OC_SCANCODE_F21;
oc_appData.keyCodes[0x06D] = OC_KEY_F22; oc_appData.scanCodes[0x06D] = OC_SCANCODE_F22;
oc_appData.keyCodes[0x06E] = OC_KEY_F23; oc_appData.scanCodes[0x06E] = OC_SCANCODE_F23;
oc_appData.keyCodes[0x076] = OC_KEY_F24; oc_appData.scanCodes[0x076] = OC_SCANCODE_F24;
oc_appData.keyCodes[0x038] = OC_KEY_LEFT_ALT; oc_appData.scanCodes[0x038] = OC_SCANCODE_LEFT_ALT;
oc_appData.keyCodes[0x01D] = OC_KEY_LEFT_CONTROL; oc_appData.scanCodes[0x01D] = OC_SCANCODE_LEFT_CONTROL;
oc_appData.keyCodes[0x02A] = OC_KEY_LEFT_SHIFT; oc_appData.scanCodes[0x02A] = OC_SCANCODE_LEFT_SHIFT;
oc_appData.keyCodes[0x15B] = OC_KEY_LEFT_SUPER; oc_appData.scanCodes[0x15B] = OC_SCANCODE_LEFT_SUPER;
oc_appData.keyCodes[0x137] = OC_KEY_PRINT_SCREEN; oc_appData.scanCodes[0x137] = OC_SCANCODE_PRINT_SCREEN;
oc_appData.keyCodes[0x138] = OC_KEY_RIGHT_ALT; oc_appData.scanCodes[0x138] = OC_SCANCODE_RIGHT_ALT;
oc_appData.keyCodes[0x11D] = OC_KEY_RIGHT_CONTROL; oc_appData.scanCodes[0x11D] = OC_SCANCODE_RIGHT_CONTROL;
oc_appData.keyCodes[0x036] = OC_KEY_RIGHT_SHIFT; oc_appData.scanCodes[0x036] = OC_SCANCODE_RIGHT_SHIFT;
oc_appData.keyCodes[0x15C] = OC_KEY_RIGHT_SUPER; oc_appData.scanCodes[0x15C] = OC_SCANCODE_RIGHT_SUPER;
oc_appData.keyCodes[0x150] = OC_KEY_DOWN; oc_appData.scanCodes[0x150] = OC_SCANCODE_DOWN;
oc_appData.keyCodes[0x14B] = OC_KEY_LEFT; oc_appData.scanCodes[0x14B] = OC_SCANCODE_LEFT;
oc_appData.keyCodes[0x14D] = OC_KEY_RIGHT; oc_appData.scanCodes[0x14D] = OC_SCANCODE_RIGHT;
oc_appData.keyCodes[0x148] = OC_KEY_UP; oc_appData.scanCodes[0x148] = OC_SCANCODE_UP;
oc_appData.keyCodes[0x052] = OC_KEY_KP_0; oc_appData.scanCodes[0x052] = OC_SCANCODE_KP_0;
oc_appData.keyCodes[0x04F] = OC_KEY_KP_1; oc_appData.scanCodes[0x04F] = OC_SCANCODE_KP_1;
oc_appData.keyCodes[0x050] = OC_KEY_KP_2; oc_appData.scanCodes[0x050] = OC_SCANCODE_KP_2;
oc_appData.keyCodes[0x051] = OC_KEY_KP_3; oc_appData.scanCodes[0x051] = OC_SCANCODE_KP_3;
oc_appData.keyCodes[0x04B] = OC_KEY_KP_4; oc_appData.scanCodes[0x04B] = OC_SCANCODE_KP_4;
oc_appData.keyCodes[0x04C] = OC_KEY_KP_5; oc_appData.scanCodes[0x04C] = OC_SCANCODE_KP_5;
oc_appData.keyCodes[0x04D] = OC_KEY_KP_6; oc_appData.scanCodes[0x04D] = OC_SCANCODE_KP_6;
oc_appData.keyCodes[0x047] = OC_KEY_KP_7; oc_appData.scanCodes[0x047] = OC_SCANCODE_KP_7;
oc_appData.keyCodes[0x048] = OC_KEY_KP_8; oc_appData.scanCodes[0x048] = OC_SCANCODE_KP_8;
oc_appData.keyCodes[0x049] = OC_KEY_KP_9; oc_appData.scanCodes[0x049] = OC_SCANCODE_KP_9;
oc_appData.keyCodes[0x04E] = OC_KEY_KP_ADD; oc_appData.scanCodes[0x04E] = OC_SCANCODE_KP_ADD;
oc_appData.keyCodes[0x053] = OC_KEY_KP_DECIMAL; oc_appData.scanCodes[0x053] = OC_SCANCODE_KP_DECIMAL;
oc_appData.keyCodes[0x135] = OC_KEY_KP_DIVIDE; oc_appData.scanCodes[0x135] = OC_SCANCODE_KP_DIVIDE;
oc_appData.keyCodes[0x11C] = OC_KEY_KP_ENTER; oc_appData.scanCodes[0x11C] = OC_SCANCODE_KP_ENTER;
oc_appData.keyCodes[0x037] = OC_KEY_KP_MULTIPLY; oc_appData.scanCodes[0x037] = OC_SCANCODE_KP_MULTIPLY;
oc_appData.keyCodes[0x04A] = OC_KEY_KP_SUBTRACT; oc_appData.scanCodes[0x04A] = OC_SCANCODE_KP_SUBTRACT;
}
memset(oc_appData.nativeKeys, 0, sizeof(int) * OC_KEY_COUNT); void oc_win32_update_keyboard_layout()
for(int nativeKey = 0; nativeKey < 256; nativeKey++)
{ {
oc_key_code mpKey = oc_appData.keyCodes[nativeKey]; memcpy(oc_appData.keyMap, oc_defaultKeyMap, sizeof(oc_key_code) * OC_SCANCODE_COUNT);
if(mpKey)
for(int winCode = 0; winCode < OC_SCANCODE_COUNT; winCode++)
{ {
oc_appData.nativeKeys[mpKey] = nativeKey; oc_scan_code scanCode = oc_appData.scanCodes[winCode];
if(scanCode < 256)
{
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_common();
oc_init_keys(); oc_init_keys();
oc_win32_update_keyboard_layout();
oc_appData.win32.savedConsoleCodePage = GetConsoleOutputCP(); oc_appData.win32.savedConsoleCodePage = GetConsoleOutputCP();
SetConsoleOutputCP(CP_UTF8); SetConsoleOutputCP(CP_UTF8);
@ -189,7 +229,7 @@ void oc_terminate()
static oc_key_code oc_convert_win32_key(int code) 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() static oc_keymod_flags oc_get_mod_keys()
@ -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.window = oc_window_handle_from_ptr(window);
event.type = OC_EVENT_MOUSE_BUTTON; event.type = OC_EVENT_MOUSE_BUTTON;
event.key.action = action; event.key.action = action;
event.key.code = button; event.key.button = button;
event.key.mods = oc_get_mod_keys(); event.key.mods = oc_get_mod_keys();
event.key.clickCount = oc_appData.win32.clickCount[button]; 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; break;
case WM_INPUTLANGCHANGE:
{
oc_win32_update_keyboard_layout();
}
break;
case WM_KEYDOWN: case WM_KEYDOWN:
case WM_SYSKEYDOWN: 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.window = oc_window_handle_from_ptr(mpWindow);
event.type = OC_EVENT_KEYBOARD_KEY; event.type = OC_EVENT_KEYBOARD_KEY;
event.key.action = (lParam & 0x40000000) ? OC_KEY_REPEAT : OC_KEY_PRESS; 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(); event.key.mods = oc_get_mod_keys();
oc_queue_event(&event); 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.window = oc_window_handle_from_ptr(mpWindow);
event.type = OC_EVENT_KEYBOARD_KEY; event.type = OC_EVENT_KEYBOARD_KEY;
event.key.action = OC_KEY_RELEASE; 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(); event.key.mods = oc_get_mod_keys();
oc_queue_event(&event); oc_queue_event(&event);
} }

View File

@ -609,8 +609,8 @@ i32 orca_runloop(void* user)
{ {
if(exports[OC_EXPORT_MOUSE_DOWN]) if(exports[OC_EXPORT_MOUSE_DOWN])
{ {
int key = event->key.code; oc_mouse_button button = event->key.button;
const void* args[1] = { &key }; const void* args[1] = { &button };
M3Result res = m3_Call(exports[OC_EXPORT_MOUSE_DOWN], 1, args); M3Result res = m3_Call(exports[OC_EXPORT_MOUSE_DOWN], 1, args);
if(res) if(res)
{ {
@ -622,8 +622,8 @@ i32 orca_runloop(void* user)
{ {
if(exports[OC_EXPORT_MOUSE_UP]) if(exports[OC_EXPORT_MOUSE_UP])
{ {
int key = event->key.code; oc_mouse_button button = event->key.button;
const void* args[1] = { &key }; const void* args[1] = { &button };
M3Result res = m3_Call(exports[OC_EXPORT_MOUSE_UP], 1, args); M3Result res = m3_Call(exports[OC_EXPORT_MOUSE_UP], 1, args);
if(res) if(res)
{ {
@ -652,7 +652,7 @@ i32 orca_runloop(void* user)
{ {
if(event->key.action == OC_KEY_PRESS) 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_SHIFT)
&& (event->key.mods & OC_KEYMOD_MAIN_MODIFIER)) && (event->key.mods & OC_KEYMOD_MAIN_MODIFIER))
{ {
@ -661,7 +661,7 @@ i32 orca_runloop(void* user)
if(exports[OC_EXPORT_KEY_DOWN]) 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); M3Result res = m3_Call(exports[OC_EXPORT_KEY_DOWN], 1, args);
if(res) if(res)
{ {
@ -673,7 +673,7 @@ i32 orca_runloop(void* user)
{ {
if(exports[OC_EXPORT_KEY_UP]) 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); M3Result res = m3_Call(exports[OC_EXPORT_KEY_UP], 1, args);
if(res) if(res)
{ {

View File

@ -140,7 +140,7 @@ void oc_input_process_event(oc_input_state* state, oc_event* event)
{ {
case OC_EVENT_KEYBOARD_KEY: 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_state(state, key, event->key.action);
oc_update_key_mods(state, event->key.mods); 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: 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); oc_update_key_state(state, key, event->key.action);
if(event->key.action == OC_KEY_PRESS) 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); 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) bool oc_mouse_down(oc_input_state* input, oc_mouse_button button)
{ {
oc_key_state state = oc_mouse_button_get_state(input, button); oc_key_state state = oc_mouse_button_get_state(input, button);

View File

@ -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_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 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 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_pressed(oc_input_state* state, oc_mouse_button button);
ORCA_API int oc_mouse_released(oc_input_state* state, oc_mouse_button button); ORCA_API int oc_mouse_released(oc_input_state* state, oc_mouse_button button);

View File

@ -97,5 +97,14 @@
{ "name": "size", { "name": "size",
"type": {"name": "oc_vec2", "tag": "S"}} "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"}}
]
} }
] ]