2015-06-21 15:33:46 +00:00
|
|
|
/*
|
|
|
|
Simple DirectMedia Layer
|
2022-01-03 17:40:00 +00:00
|
|
|
Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
|
2015-06-21 15:33:46 +00:00
|
|
|
|
|
|
|
This software is provided 'as-is', without any express or implied
|
|
|
|
warranty. In no event will the authors be held liable for any damages
|
|
|
|
arising from the use of this software.
|
|
|
|
|
|
|
|
Permission is granted to anyone to use this software for any purpose,
|
|
|
|
including commercial applications, and to alter it and redistribute it
|
|
|
|
freely, subject to the following restrictions:
|
|
|
|
|
|
|
|
1. The origin of this software must not be misrepresented; you must not
|
|
|
|
claim that you wrote the original software. If you use this software
|
|
|
|
in a product, an acknowledgment in the product documentation would be
|
|
|
|
appreciated but is not required.
|
|
|
|
2. Altered source versions must be plainly marked as such, and must not be
|
|
|
|
misrepresented as being the original software.
|
|
|
|
3. This notice may not be removed or altered from any source distribution.
|
|
|
|
*/
|
|
|
|
#include "../SDL_internal.h"
|
|
|
|
|
|
|
|
/* General keyboard handling code for SDL */
|
|
|
|
|
2021-01-28 02:41:36 +00:00
|
|
|
#include "SDL_hints.h"
|
2015-06-21 15:33:46 +00:00
|
|
|
#include "SDL_timer.h"
|
|
|
|
#include "SDL_events.h"
|
|
|
|
#include "SDL_events_c.h"
|
|
|
|
#include "../video/SDL_sysvideo.h"
|
|
|
|
|
|
|
|
|
|
|
|
/* #define DEBUG_KEYBOARD */
|
|
|
|
|
|
|
|
/* Global keyboard information */
|
|
|
|
|
2020-04-09 02:16:31 +00:00
|
|
|
#define KEYBOARD_HARDWARE 0x01
|
|
|
|
#define KEYBOARD_AUTORELEASE 0x02
|
|
|
|
|
2015-06-21 15:33:46 +00:00
|
|
|
typedef struct SDL_Keyboard SDL_Keyboard;
|
|
|
|
|
|
|
|
struct SDL_Keyboard
|
|
|
|
{
|
|
|
|
/* Data common to all keyboards */
|
|
|
|
SDL_Window *focus;
|
|
|
|
Uint16 modstate;
|
2020-04-09 02:16:31 +00:00
|
|
|
Uint8 keysource[SDL_NUM_SCANCODES];
|
2015-06-21 15:33:46 +00:00
|
|
|
Uint8 keystate[SDL_NUM_SCANCODES];
|
|
|
|
SDL_Keycode keymap[SDL_NUM_SCANCODES];
|
2020-04-09 02:16:31 +00:00
|
|
|
SDL_bool autorelease_pending;
|
2015-06-21 15:33:46 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static SDL_Keyboard SDL_keyboard;
|
|
|
|
|
|
|
|
static const SDL_Keycode SDL_default_keymap[SDL_NUM_SCANCODES] = {
|
|
|
|
0, 0, 0, 0,
|
|
|
|
'a',
|
|
|
|
'b',
|
|
|
|
'c',
|
|
|
|
'd',
|
|
|
|
'e',
|
|
|
|
'f',
|
|
|
|
'g',
|
|
|
|
'h',
|
|
|
|
'i',
|
|
|
|
'j',
|
|
|
|
'k',
|
|
|
|
'l',
|
|
|
|
'm',
|
|
|
|
'n',
|
|
|
|
'o',
|
|
|
|
'p',
|
|
|
|
'q',
|
|
|
|
'r',
|
|
|
|
's',
|
|
|
|
't',
|
|
|
|
'u',
|
|
|
|
'v',
|
|
|
|
'w',
|
|
|
|
'x',
|
|
|
|
'y',
|
|
|
|
'z',
|
|
|
|
'1',
|
|
|
|
'2',
|
|
|
|
'3',
|
|
|
|
'4',
|
|
|
|
'5',
|
|
|
|
'6',
|
|
|
|
'7',
|
|
|
|
'8',
|
|
|
|
'9',
|
|
|
|
'0',
|
|
|
|
SDLK_RETURN,
|
|
|
|
SDLK_ESCAPE,
|
|
|
|
SDLK_BACKSPACE,
|
|
|
|
SDLK_TAB,
|
|
|
|
SDLK_SPACE,
|
|
|
|
'-',
|
|
|
|
'=',
|
|
|
|
'[',
|
|
|
|
']',
|
|
|
|
'\\',
|
|
|
|
'#',
|
|
|
|
';',
|
|
|
|
'\'',
|
|
|
|
'`',
|
|
|
|
',',
|
|
|
|
'.',
|
|
|
|
'/',
|
|
|
|
SDLK_CAPSLOCK,
|
|
|
|
SDLK_F1,
|
|
|
|
SDLK_F2,
|
|
|
|
SDLK_F3,
|
|
|
|
SDLK_F4,
|
|
|
|
SDLK_F5,
|
|
|
|
SDLK_F6,
|
|
|
|
SDLK_F7,
|
|
|
|
SDLK_F8,
|
|
|
|
SDLK_F9,
|
|
|
|
SDLK_F10,
|
|
|
|
SDLK_F11,
|
|
|
|
SDLK_F12,
|
|
|
|
SDLK_PRINTSCREEN,
|
|
|
|
SDLK_SCROLLLOCK,
|
|
|
|
SDLK_PAUSE,
|
|
|
|
SDLK_INSERT,
|
|
|
|
SDLK_HOME,
|
|
|
|
SDLK_PAGEUP,
|
|
|
|
SDLK_DELETE,
|
|
|
|
SDLK_END,
|
|
|
|
SDLK_PAGEDOWN,
|
|
|
|
SDLK_RIGHT,
|
|
|
|
SDLK_LEFT,
|
|
|
|
SDLK_DOWN,
|
|
|
|
SDLK_UP,
|
|
|
|
SDLK_NUMLOCKCLEAR,
|
|
|
|
SDLK_KP_DIVIDE,
|
|
|
|
SDLK_KP_MULTIPLY,
|
|
|
|
SDLK_KP_MINUS,
|
|
|
|
SDLK_KP_PLUS,
|
|
|
|
SDLK_KP_ENTER,
|
|
|
|
SDLK_KP_1,
|
|
|
|
SDLK_KP_2,
|
|
|
|
SDLK_KP_3,
|
|
|
|
SDLK_KP_4,
|
|
|
|
SDLK_KP_5,
|
|
|
|
SDLK_KP_6,
|
|
|
|
SDLK_KP_7,
|
|
|
|
SDLK_KP_8,
|
|
|
|
SDLK_KP_9,
|
|
|
|
SDLK_KP_0,
|
|
|
|
SDLK_KP_PERIOD,
|
|
|
|
0,
|
|
|
|
SDLK_APPLICATION,
|
|
|
|
SDLK_POWER,
|
|
|
|
SDLK_KP_EQUALS,
|
|
|
|
SDLK_F13,
|
|
|
|
SDLK_F14,
|
|
|
|
SDLK_F15,
|
|
|
|
SDLK_F16,
|
|
|
|
SDLK_F17,
|
|
|
|
SDLK_F18,
|
|
|
|
SDLK_F19,
|
|
|
|
SDLK_F20,
|
|
|
|
SDLK_F21,
|
|
|
|
SDLK_F22,
|
|
|
|
SDLK_F23,
|
|
|
|
SDLK_F24,
|
|
|
|
SDLK_EXECUTE,
|
|
|
|
SDLK_HELP,
|
|
|
|
SDLK_MENU,
|
|
|
|
SDLK_SELECT,
|
|
|
|
SDLK_STOP,
|
|
|
|
SDLK_AGAIN,
|
|
|
|
SDLK_UNDO,
|
|
|
|
SDLK_CUT,
|
|
|
|
SDLK_COPY,
|
|
|
|
SDLK_PASTE,
|
|
|
|
SDLK_FIND,
|
|
|
|
SDLK_MUTE,
|
|
|
|
SDLK_VOLUMEUP,
|
|
|
|
SDLK_VOLUMEDOWN,
|
|
|
|
0, 0, 0,
|
|
|
|
SDLK_KP_COMMA,
|
|
|
|
SDLK_KP_EQUALSAS400,
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
SDLK_ALTERASE,
|
|
|
|
SDLK_SYSREQ,
|
|
|
|
SDLK_CANCEL,
|
|
|
|
SDLK_CLEAR,
|
|
|
|
SDLK_PRIOR,
|
|
|
|
SDLK_RETURN2,
|
|
|
|
SDLK_SEPARATOR,
|
|
|
|
SDLK_OUT,
|
|
|
|
SDLK_OPER,
|
|
|
|
SDLK_CLEARAGAIN,
|
|
|
|
SDLK_CRSEL,
|
|
|
|
SDLK_EXSEL,
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
SDLK_KP_00,
|
|
|
|
SDLK_KP_000,
|
|
|
|
SDLK_THOUSANDSSEPARATOR,
|
|
|
|
SDLK_DECIMALSEPARATOR,
|
|
|
|
SDLK_CURRENCYUNIT,
|
|
|
|
SDLK_CURRENCYSUBUNIT,
|
|
|
|
SDLK_KP_LEFTPAREN,
|
|
|
|
SDLK_KP_RIGHTPAREN,
|
|
|
|
SDLK_KP_LEFTBRACE,
|
|
|
|
SDLK_KP_RIGHTBRACE,
|
|
|
|
SDLK_KP_TAB,
|
|
|
|
SDLK_KP_BACKSPACE,
|
|
|
|
SDLK_KP_A,
|
|
|
|
SDLK_KP_B,
|
|
|
|
SDLK_KP_C,
|
|
|
|
SDLK_KP_D,
|
|
|
|
SDLK_KP_E,
|
|
|
|
SDLK_KP_F,
|
|
|
|
SDLK_KP_XOR,
|
|
|
|
SDLK_KP_POWER,
|
|
|
|
SDLK_KP_PERCENT,
|
|
|
|
SDLK_KP_LESS,
|
|
|
|
SDLK_KP_GREATER,
|
|
|
|
SDLK_KP_AMPERSAND,
|
|
|
|
SDLK_KP_DBLAMPERSAND,
|
|
|
|
SDLK_KP_VERTICALBAR,
|
|
|
|
SDLK_KP_DBLVERTICALBAR,
|
|
|
|
SDLK_KP_COLON,
|
|
|
|
SDLK_KP_HASH,
|
|
|
|
SDLK_KP_SPACE,
|
|
|
|
SDLK_KP_AT,
|
|
|
|
SDLK_KP_EXCLAM,
|
|
|
|
SDLK_KP_MEMSTORE,
|
|
|
|
SDLK_KP_MEMRECALL,
|
|
|
|
SDLK_KP_MEMCLEAR,
|
|
|
|
SDLK_KP_MEMADD,
|
|
|
|
SDLK_KP_MEMSUBTRACT,
|
|
|
|
SDLK_KP_MEMMULTIPLY,
|
|
|
|
SDLK_KP_MEMDIVIDE,
|
|
|
|
SDLK_KP_PLUSMINUS,
|
|
|
|
SDLK_KP_CLEAR,
|
|
|
|
SDLK_KP_CLEARENTRY,
|
|
|
|
SDLK_KP_BINARY,
|
|
|
|
SDLK_KP_OCTAL,
|
|
|
|
SDLK_KP_DECIMAL,
|
|
|
|
SDLK_KP_HEXADECIMAL,
|
|
|
|
0, 0,
|
|
|
|
SDLK_LCTRL,
|
|
|
|
SDLK_LSHIFT,
|
|
|
|
SDLK_LALT,
|
|
|
|
SDLK_LGUI,
|
|
|
|
SDLK_RCTRL,
|
|
|
|
SDLK_RSHIFT,
|
|
|
|
SDLK_RALT,
|
|
|
|
SDLK_RGUI,
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
SDLK_MODE,
|
|
|
|
SDLK_AUDIONEXT,
|
|
|
|
SDLK_AUDIOPREV,
|
|
|
|
SDLK_AUDIOSTOP,
|
|
|
|
SDLK_AUDIOPLAY,
|
|
|
|
SDLK_AUDIOMUTE,
|
|
|
|
SDLK_MEDIASELECT,
|
|
|
|
SDLK_WWW,
|
|
|
|
SDLK_MAIL,
|
|
|
|
SDLK_CALCULATOR,
|
|
|
|
SDLK_COMPUTER,
|
|
|
|
SDLK_AC_SEARCH,
|
|
|
|
SDLK_AC_HOME,
|
|
|
|
SDLK_AC_BACK,
|
|
|
|
SDLK_AC_FORWARD,
|
|
|
|
SDLK_AC_STOP,
|
|
|
|
SDLK_AC_REFRESH,
|
|
|
|
SDLK_AC_BOOKMARKS,
|
|
|
|
SDLK_BRIGHTNESSDOWN,
|
|
|
|
SDLK_BRIGHTNESSUP,
|
|
|
|
SDLK_DISPLAYSWITCH,
|
|
|
|
SDLK_KBDILLUMTOGGLE,
|
|
|
|
SDLK_KBDILLUMDOWN,
|
|
|
|
SDLK_KBDILLUMUP,
|
|
|
|
SDLK_EJECT,
|
|
|
|
SDLK_SLEEP,
|
2017-07-20 17:46:38 +00:00
|
|
|
SDLK_APP1,
|
|
|
|
SDLK_APP2,
|
|
|
|
SDLK_AUDIOREWIND,
|
|
|
|
SDLK_AUDIOFASTFORWARD,
|
2015-06-21 15:33:46 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static const char *SDL_scancode_names[SDL_NUM_SCANCODES] = {
|
|
|
|
NULL, NULL, NULL, NULL,
|
|
|
|
"A",
|
|
|
|
"B",
|
|
|
|
"C",
|
|
|
|
"D",
|
|
|
|
"E",
|
|
|
|
"F",
|
|
|
|
"G",
|
|
|
|
"H",
|
|
|
|
"I",
|
|
|
|
"J",
|
|
|
|
"K",
|
|
|
|
"L",
|
|
|
|
"M",
|
|
|
|
"N",
|
|
|
|
"O",
|
|
|
|
"P",
|
|
|
|
"Q",
|
|
|
|
"R",
|
|
|
|
"S",
|
|
|
|
"T",
|
|
|
|
"U",
|
|
|
|
"V",
|
|
|
|
"W",
|
|
|
|
"X",
|
|
|
|
"Y",
|
|
|
|
"Z",
|
|
|
|
"1",
|
|
|
|
"2",
|
|
|
|
"3",
|
|
|
|
"4",
|
|
|
|
"5",
|
|
|
|
"6",
|
|
|
|
"7",
|
|
|
|
"8",
|
|
|
|
"9",
|
|
|
|
"0",
|
|
|
|
"Return",
|
|
|
|
"Escape",
|
|
|
|
"Backspace",
|
|
|
|
"Tab",
|
|
|
|
"Space",
|
|
|
|
"-",
|
|
|
|
"=",
|
|
|
|
"[",
|
|
|
|
"]",
|
|
|
|
"\\",
|
|
|
|
"#",
|
|
|
|
";",
|
|
|
|
"'",
|
|
|
|
"`",
|
|
|
|
",",
|
|
|
|
".",
|
|
|
|
"/",
|
|
|
|
"CapsLock",
|
|
|
|
"F1",
|
|
|
|
"F2",
|
|
|
|
"F3",
|
|
|
|
"F4",
|
|
|
|
"F5",
|
|
|
|
"F6",
|
|
|
|
"F7",
|
|
|
|
"F8",
|
|
|
|
"F9",
|
|
|
|
"F10",
|
|
|
|
"F11",
|
|
|
|
"F12",
|
|
|
|
"PrintScreen",
|
|
|
|
"ScrollLock",
|
|
|
|
"Pause",
|
|
|
|
"Insert",
|
|
|
|
"Home",
|
|
|
|
"PageUp",
|
|
|
|
"Delete",
|
|
|
|
"End",
|
|
|
|
"PageDown",
|
|
|
|
"Right",
|
|
|
|
"Left",
|
|
|
|
"Down",
|
|
|
|
"Up",
|
|
|
|
"Numlock",
|
|
|
|
"Keypad /",
|
|
|
|
"Keypad *",
|
|
|
|
"Keypad -",
|
|
|
|
"Keypad +",
|
|
|
|
"Keypad Enter",
|
|
|
|
"Keypad 1",
|
|
|
|
"Keypad 2",
|
|
|
|
"Keypad 3",
|
|
|
|
"Keypad 4",
|
|
|
|
"Keypad 5",
|
|
|
|
"Keypad 6",
|
|
|
|
"Keypad 7",
|
|
|
|
"Keypad 8",
|
|
|
|
"Keypad 9",
|
|
|
|
"Keypad 0",
|
|
|
|
"Keypad .",
|
|
|
|
NULL,
|
|
|
|
"Application",
|
|
|
|
"Power",
|
|
|
|
"Keypad =",
|
|
|
|
"F13",
|
|
|
|
"F14",
|
|
|
|
"F15",
|
|
|
|
"F16",
|
|
|
|
"F17",
|
|
|
|
"F18",
|
|
|
|
"F19",
|
|
|
|
"F20",
|
|
|
|
"F21",
|
|
|
|
"F22",
|
|
|
|
"F23",
|
|
|
|
"F24",
|
|
|
|
"Execute",
|
|
|
|
"Help",
|
|
|
|
"Menu",
|
|
|
|
"Select",
|
|
|
|
"Stop",
|
|
|
|
"Again",
|
|
|
|
"Undo",
|
|
|
|
"Cut",
|
|
|
|
"Copy",
|
|
|
|
"Paste",
|
|
|
|
"Find",
|
|
|
|
"Mute",
|
|
|
|
"VolumeUp",
|
|
|
|
"VolumeDown",
|
|
|
|
NULL, NULL, NULL,
|
|
|
|
"Keypad ,",
|
|
|
|
"Keypad = (AS400)",
|
|
|
|
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
|
|
NULL, NULL, NULL, NULL, NULL, NULL,
|
|
|
|
"AltErase",
|
|
|
|
"SysReq",
|
|
|
|
"Cancel",
|
|
|
|
"Clear",
|
|
|
|
"Prior",
|
|
|
|
"Return",
|
|
|
|
"Separator",
|
|
|
|
"Out",
|
|
|
|
"Oper",
|
|
|
|
"Clear / Again",
|
|
|
|
"CrSel",
|
|
|
|
"ExSel",
|
|
|
|
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
|
|
"Keypad 00",
|
|
|
|
"Keypad 000",
|
|
|
|
"ThousandsSeparator",
|
|
|
|
"DecimalSeparator",
|
|
|
|
"CurrencyUnit",
|
|
|
|
"CurrencySubUnit",
|
|
|
|
"Keypad (",
|
|
|
|
"Keypad )",
|
|
|
|
"Keypad {",
|
|
|
|
"Keypad }",
|
|
|
|
"Keypad Tab",
|
|
|
|
"Keypad Backspace",
|
|
|
|
"Keypad A",
|
|
|
|
"Keypad B",
|
|
|
|
"Keypad C",
|
|
|
|
"Keypad D",
|
|
|
|
"Keypad E",
|
|
|
|
"Keypad F",
|
|
|
|
"Keypad XOR",
|
|
|
|
"Keypad ^",
|
|
|
|
"Keypad %",
|
|
|
|
"Keypad <",
|
|
|
|
"Keypad >",
|
|
|
|
"Keypad &",
|
|
|
|
"Keypad &&",
|
|
|
|
"Keypad |",
|
|
|
|
"Keypad ||",
|
|
|
|
"Keypad :",
|
|
|
|
"Keypad #",
|
|
|
|
"Keypad Space",
|
|
|
|
"Keypad @",
|
|
|
|
"Keypad !",
|
|
|
|
"Keypad MemStore",
|
|
|
|
"Keypad MemRecall",
|
|
|
|
"Keypad MemClear",
|
|
|
|
"Keypad MemAdd",
|
|
|
|
"Keypad MemSubtract",
|
|
|
|
"Keypad MemMultiply",
|
|
|
|
"Keypad MemDivide",
|
|
|
|
"Keypad +/-",
|
|
|
|
"Keypad Clear",
|
|
|
|
"Keypad ClearEntry",
|
|
|
|
"Keypad Binary",
|
|
|
|
"Keypad Octal",
|
|
|
|
"Keypad Decimal",
|
|
|
|
"Keypad Hexadecimal",
|
|
|
|
NULL, NULL,
|
|
|
|
"Left Ctrl",
|
|
|
|
"Left Shift",
|
|
|
|
"Left Alt",
|
|
|
|
"Left GUI",
|
|
|
|
"Right Ctrl",
|
|
|
|
"Right Shift",
|
|
|
|
"Right Alt",
|
|
|
|
"Right GUI",
|
|
|
|
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
|
|
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
|
|
NULL,
|
|
|
|
"ModeSwitch",
|
|
|
|
"AudioNext",
|
|
|
|
"AudioPrev",
|
|
|
|
"AudioStop",
|
|
|
|
"AudioPlay",
|
|
|
|
"AudioMute",
|
|
|
|
"MediaSelect",
|
|
|
|
"WWW",
|
|
|
|
"Mail",
|
|
|
|
"Calculator",
|
|
|
|
"Computer",
|
|
|
|
"AC Search",
|
|
|
|
"AC Home",
|
|
|
|
"AC Back",
|
|
|
|
"AC Forward",
|
|
|
|
"AC Stop",
|
|
|
|
"AC Refresh",
|
|
|
|
"AC Bookmarks",
|
|
|
|
"BrightnessDown",
|
|
|
|
"BrightnessUp",
|
|
|
|
"DisplaySwitch",
|
|
|
|
"KBDIllumToggle",
|
|
|
|
"KBDIllumDown",
|
|
|
|
"KBDIllumUp",
|
|
|
|
"Eject",
|
|
|
|
"Sleep",
|
2017-07-20 17:46:38 +00:00
|
|
|
"App1",
|
|
|
|
"App2",
|
|
|
|
"AudioRewind",
|
|
|
|
"AudioFastForward",
|
2015-06-21 15:33:46 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/* Taken from SDL_iconv() */
|
|
|
|
char *
|
|
|
|
SDL_UCS4ToUTF8(Uint32 ch, char *dst)
|
|
|
|
{
|
|
|
|
Uint8 *p = (Uint8 *) dst;
|
|
|
|
if (ch <= 0x7F) {
|
|
|
|
*p = (Uint8) ch;
|
|
|
|
++dst;
|
|
|
|
} else if (ch <= 0x7FF) {
|
|
|
|
p[0] = 0xC0 | (Uint8) ((ch >> 6) & 0x1F);
|
|
|
|
p[1] = 0x80 | (Uint8) (ch & 0x3F);
|
|
|
|
dst += 2;
|
|
|
|
} else if (ch <= 0xFFFF) {
|
|
|
|
p[0] = 0xE0 | (Uint8) ((ch >> 12) & 0x0F);
|
|
|
|
p[1] = 0x80 | (Uint8) ((ch >> 6) & 0x3F);
|
|
|
|
p[2] = 0x80 | (Uint8) (ch & 0x3F);
|
|
|
|
dst += 3;
|
2021-03-15 09:40:49 +00:00
|
|
|
} else {
|
2015-06-21 15:33:46 +00:00
|
|
|
p[0] = 0xF0 | (Uint8) ((ch >> 18) & 0x07);
|
|
|
|
p[1] = 0x80 | (Uint8) ((ch >> 12) & 0x3F);
|
|
|
|
p[2] = 0x80 | (Uint8) ((ch >> 6) & 0x3F);
|
|
|
|
p[3] = 0x80 | (Uint8) (ch & 0x3F);
|
|
|
|
dst += 4;
|
|
|
|
}
|
|
|
|
return dst;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Public functions */
|
|
|
|
int
|
|
|
|
SDL_KeyboardInit(void)
|
|
|
|
{
|
|
|
|
SDL_Keyboard *keyboard = &SDL_keyboard;
|
|
|
|
|
|
|
|
/* Set the default keymap */
|
|
|
|
SDL_memcpy(keyboard->keymap, SDL_default_keymap, sizeof(SDL_default_keymap));
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
SDL_ResetKeyboard(void)
|
|
|
|
{
|
|
|
|
SDL_Keyboard *keyboard = &SDL_keyboard;
|
|
|
|
SDL_Scancode scancode;
|
|
|
|
|
|
|
|
#ifdef DEBUG_KEYBOARD
|
|
|
|
printf("Resetting keyboard\n");
|
|
|
|
#endif
|
2017-03-03 21:38:17 +00:00
|
|
|
for (scancode = (SDL_Scancode) 0; scancode < SDL_NUM_SCANCODES; ++scancode) {
|
2015-06-21 15:33:46 +00:00
|
|
|
if (keyboard->keystate[scancode] == SDL_PRESSED) {
|
|
|
|
SDL_SendKeyboardKey(SDL_RELEASED, scancode);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
SDL_GetDefaultKeymap(SDL_Keycode * keymap)
|
|
|
|
{
|
|
|
|
SDL_memcpy(keymap, SDL_default_keymap, sizeof(SDL_default_keymap));
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
SDL_SetKeymap(int start, SDL_Keycode * keys, int length)
|
|
|
|
{
|
|
|
|
SDL_Keyboard *keyboard = &SDL_keyboard;
|
Fixed bug 3188 - AZERTY keyboard support broken and inconsistent
Daniel Gibson
AZERTY keyboard layouts (which are the default layouts in France and Belgium) don't have the number keys (1, 2, ..., 9, 0) in the first row of keys, but ?, &, ?", ', (, -, ?_, ??), = (with small differences between the France and Belgian variants). Numbers are reached via shift.
On Linux and OSX, SDL seems to use the corresponding ISO 8859-1 codes (231 for ?232 for ?tc) as SDL_Keycode (but no SDK_* constants exists for those values!), while on Windows SDL seems to map those keys to SDLK_1, SDLK_2 etc, like you'd get on QWERTY.
I don't know how other platforms behave.
So we have two problems:
1. At least on Linux and OSX invalid/undefined SDL_Keycodes are returned
2. Different platforms behave differently (Windows vs Linux/OSX)
It's unclear what behavior is desired: Should SDL_* constants for those keys be introduced (and Windows behavior changed accordingly)?
Or should all platforms behave like Windows here and use the existing SDLK_1, ..., SDLK_0 keycodes?
This bug on the mailing list:
https://forums.libsdl.org/viewtopic.php?t=11555 (my post about Linux/Windows)
https://forums.libsdl.org/viewtopic.php?t=11573 (Tim Walters discovered the same problem on OSX about 1.5 weeks later).
2017-08-12 22:41:03 +00:00
|
|
|
SDL_Scancode scancode;
|
2015-06-21 15:33:46 +00:00
|
|
|
|
|
|
|
if (start < 0 || start + length > SDL_NUM_SCANCODES) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
SDL_memcpy(&keyboard->keymap[start], keys, sizeof(*keys) * length);
|
Fixed bug 3188 - AZERTY keyboard support broken and inconsistent
Daniel Gibson
AZERTY keyboard layouts (which are the default layouts in France and Belgium) don't have the number keys (1, 2, ..., 9, 0) in the first row of keys, but ?, &, ?", ', (, -, ?_, ??), = (with small differences between the France and Belgian variants). Numbers are reached via shift.
On Linux and OSX, SDL seems to use the corresponding ISO 8859-1 codes (231 for ?232 for ?tc) as SDL_Keycode (but no SDK_* constants exists for those values!), while on Windows SDL seems to map those keys to SDLK_1, SDLK_2 etc, like you'd get on QWERTY.
I don't know how other platforms behave.
So we have two problems:
1. At least on Linux and OSX invalid/undefined SDL_Keycodes are returned
2. Different platforms behave differently (Windows vs Linux/OSX)
It's unclear what behavior is desired: Should SDL_* constants for those keys be introduced (and Windows behavior changed accordingly)?
Or should all platforms behave like Windows here and use the existing SDLK_1, ..., SDLK_0 keycodes?
This bug on the mailing list:
https://forums.libsdl.org/viewtopic.php?t=11555 (my post about Linux/Windows)
https://forums.libsdl.org/viewtopic.php?t=11573 (Tim Walters discovered the same problem on OSX about 1.5 weeks later).
2017-08-12 22:41:03 +00:00
|
|
|
|
|
|
|
/* The number key scancodes always map to the number key keycodes.
|
|
|
|
* On AZERTY layouts these technically are symbols, but users (and games)
|
|
|
|
* always think of them and view them in UI as number keys.
|
|
|
|
*/
|
|
|
|
keyboard->keymap[SDL_SCANCODE_0] = SDLK_0;
|
|
|
|
for (scancode = SDL_SCANCODE_1; scancode <= SDL_SCANCODE_9; ++scancode) {
|
|
|
|
keyboard->keymap[scancode] = SDLK_1 + (scancode - SDL_SCANCODE_1);
|
|
|
|
}
|
2015-06-21 15:33:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
SDL_SetScancodeName(SDL_Scancode scancode, const char *name)
|
|
|
|
{
|
2021-06-12 05:00:50 +00:00
|
|
|
if (scancode >= SDL_NUM_SCANCODES) {
|
|
|
|
return;
|
|
|
|
}
|
2015-06-21 15:33:46 +00:00
|
|
|
SDL_scancode_names[scancode] = name;
|
|
|
|
}
|
|
|
|
|
|
|
|
SDL_Window *
|
|
|
|
SDL_GetKeyboardFocus(void)
|
|
|
|
{
|
|
|
|
SDL_Keyboard *keyboard = &SDL_keyboard;
|
|
|
|
|
|
|
|
return keyboard->focus;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
SDL_SetKeyboardFocus(SDL_Window * window)
|
|
|
|
{
|
|
|
|
SDL_Keyboard *keyboard = &SDL_keyboard;
|
|
|
|
|
|
|
|
if (keyboard->focus && !window) {
|
|
|
|
/* We won't get anymore keyboard messages, so reset keyboard state */
|
|
|
|
SDL_ResetKeyboard();
|
|
|
|
}
|
|
|
|
|
|
|
|
/* See if the current window has lost focus */
|
|
|
|
if (keyboard->focus && keyboard->focus != window) {
|
|
|
|
|
|
|
|
/* new window shouldn't think it has mouse captured. */
|
|
|
|
SDL_assert(!window || !(window->flags & SDL_WINDOW_MOUSE_CAPTURE));
|
|
|
|
|
|
|
|
/* old window must lose an existing mouse capture. */
|
|
|
|
if (keyboard->focus->flags & SDL_WINDOW_MOUSE_CAPTURE) {
|
|
|
|
SDL_CaptureMouse(SDL_FALSE); /* drop the capture. */
|
|
|
|
SDL_assert(!(keyboard->focus->flags & SDL_WINDOW_MOUSE_CAPTURE));
|
|
|
|
}
|
|
|
|
|
|
|
|
SDL_SendWindowEvent(keyboard->focus, SDL_WINDOWEVENT_FOCUS_LOST,
|
|
|
|
0, 0);
|
|
|
|
|
|
|
|
/* Ensures IME compositions are committed */
|
|
|
|
if (SDL_EventState(SDL_TEXTINPUT, SDL_QUERY)) {
|
|
|
|
SDL_VideoDevice *video = SDL_GetVideoDevice();
|
|
|
|
if (video && video->StopTextInput) {
|
|
|
|
video->StopTextInput(video);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
keyboard->focus = window;
|
|
|
|
|
|
|
|
if (keyboard->focus) {
|
|
|
|
SDL_SendWindowEvent(keyboard->focus, SDL_WINDOWEVENT_FOCUS_GAINED,
|
|
|
|
0, 0);
|
|
|
|
|
|
|
|
if (SDL_EventState(SDL_TEXTINPUT, SDL_QUERY)) {
|
|
|
|
SDL_VideoDevice *video = SDL_GetVideoDevice();
|
|
|
|
if (video && video->StartTextInput) {
|
|
|
|
video->StartTextInput(video);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-09 02:16:31 +00:00
|
|
|
static int
|
|
|
|
SDL_SendKeyboardKeyInternal(Uint8 source, Uint8 state, SDL_Scancode scancode)
|
2015-06-21 15:33:46 +00:00
|
|
|
{
|
|
|
|
SDL_Keyboard *keyboard = &SDL_keyboard;
|
|
|
|
int posted;
|
|
|
|
SDL_Keymod modifier;
|
|
|
|
SDL_Keycode keycode;
|
|
|
|
Uint32 type;
|
2020-04-09 02:16:31 +00:00
|
|
|
Uint8 repeat = SDL_FALSE;
|
2015-06-21 15:33:46 +00:00
|
|
|
|
2021-06-12 05:00:50 +00:00
|
|
|
if (scancode == SDL_SCANCODE_UNKNOWN || scancode >= SDL_NUM_SCANCODES) {
|
2015-06-21 15:33:46 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2020-04-09 02:16:31 +00:00
|
|
|
|
2015-06-21 15:33:46 +00:00
|
|
|
#ifdef DEBUG_KEYBOARD
|
|
|
|
printf("The '%s' key has been %s\n", SDL_GetScancodeName(scancode),
|
|
|
|
state == SDL_PRESSED ? "pressed" : "released");
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* Figure out what type of event this is */
|
|
|
|
switch (state) {
|
|
|
|
case SDL_PRESSED:
|
|
|
|
type = SDL_KEYDOWN;
|
|
|
|
break;
|
|
|
|
case SDL_RELEASED:
|
|
|
|
type = SDL_KEYUP;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
/* Invalid state -- bail */
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Drop events that don't change state */
|
2020-04-09 02:16:31 +00:00
|
|
|
if (state) {
|
|
|
|
if (keyboard->keystate[scancode]) {
|
|
|
|
if (!(keyboard->keysource[scancode] & source)) {
|
|
|
|
keyboard->keysource[scancode] |= source;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
repeat = SDL_TRUE;
|
|
|
|
}
|
|
|
|
keyboard->keysource[scancode] |= source;
|
|
|
|
} else {
|
|
|
|
if (!keyboard->keystate[scancode]) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
keyboard->keysource[scancode] = 0;
|
2015-06-21 15:33:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Update internal keyboard state */
|
|
|
|
keyboard->keystate[scancode] = state;
|
|
|
|
|
|
|
|
keycode = keyboard->keymap[scancode];
|
|
|
|
|
2020-04-09 02:16:31 +00:00
|
|
|
if (source == KEYBOARD_AUTORELEASE) {
|
|
|
|
keyboard->autorelease_pending = SDL_TRUE;
|
|
|
|
}
|
|
|
|
|
2015-06-21 15:33:46 +00:00
|
|
|
/* Update modifiers state if applicable */
|
|
|
|
switch (keycode) {
|
|
|
|
case SDLK_LCTRL:
|
|
|
|
modifier = KMOD_LCTRL;
|
|
|
|
break;
|
|
|
|
case SDLK_RCTRL:
|
|
|
|
modifier = KMOD_RCTRL;
|
|
|
|
break;
|
|
|
|
case SDLK_LSHIFT:
|
|
|
|
modifier = KMOD_LSHIFT;
|
|
|
|
break;
|
|
|
|
case SDLK_RSHIFT:
|
|
|
|
modifier = KMOD_RSHIFT;
|
|
|
|
break;
|
|
|
|
case SDLK_LALT:
|
|
|
|
modifier = KMOD_LALT;
|
|
|
|
break;
|
|
|
|
case SDLK_RALT:
|
|
|
|
modifier = KMOD_RALT;
|
|
|
|
break;
|
|
|
|
case SDLK_LGUI:
|
|
|
|
modifier = KMOD_LGUI;
|
|
|
|
break;
|
|
|
|
case SDLK_RGUI:
|
|
|
|
modifier = KMOD_RGUI;
|
|
|
|
break;
|
|
|
|
case SDLK_MODE:
|
|
|
|
modifier = KMOD_MODE;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
modifier = KMOD_NONE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (SDL_KEYDOWN == type) {
|
|
|
|
switch (keycode) {
|
|
|
|
case SDLK_NUMLOCKCLEAR:
|
|
|
|
keyboard->modstate ^= KMOD_NUM;
|
|
|
|
break;
|
|
|
|
case SDLK_CAPSLOCK:
|
|
|
|
keyboard->modstate ^= KMOD_CAPS;
|
|
|
|
break;
|
2021-08-11 00:50:17 +00:00
|
|
|
case SDLK_SCROLLLOCK:
|
|
|
|
keyboard->modstate ^= KMOD_SCROLL;
|
|
|
|
break;
|
2015-06-21 15:33:46 +00:00
|
|
|
default:
|
|
|
|
keyboard->modstate |= modifier;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
keyboard->modstate &= ~modifier;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Post the event, if desired */
|
|
|
|
posted = 0;
|
|
|
|
if (SDL_GetEventState(type) == SDL_ENABLE) {
|
|
|
|
SDL_Event event;
|
|
|
|
event.key.type = type;
|
|
|
|
event.key.state = state;
|
|
|
|
event.key.repeat = repeat;
|
|
|
|
event.key.keysym.scancode = scancode;
|
|
|
|
event.key.keysym.sym = keycode;
|
Fixed bug 3249 - keysym.mod is incorrect when mod keys are pressed for SDL_KEYDOWN events
Adam M.
The keysym.mod field does not reflect the state of the modified keys when processing key down events for the modifier keys themselves. The documentation says that it returns the current key modifiers, but they are not current for key down events involving modifier keys. I interpret "current" to mean "equal to SDL_GetModState() at the instant the event is processed/enqueued".
For example, if you depress the Shift key you get a key down event with .mod == 0. However, .mod should not be 0 because a shift key is down. If you then release the Shift key, you get a key up event with .mod == 0. Neither event reports the modifier key.
If you press Shift and then A, .mod is incorrect (== 0) when Shift is pressed, but is correct later when A is pressed (== KMOD_LSHIFT).
You might say this behavior is deliberate, i.e. keysym.mod is the value /before/ the event, not the current value as documented, but that explanation is incorrect because only key down events behave that way. Key up events correctly give the current value, not the value before the event.
Not only is it inconsistent with itself, I think it makes keyboard processing harder.
The problem is near line 740 in SDL_keyboard.c:
if (SDL_KEYDOWN == type) {
modstate = keyboard->modstate; // SHOULD THIS BE MOVED DOWN?
switch (keycode) {
case SDLK_NUMLOCKCLEAR:
keyboard->modstate ^= KMOD_NUM;
break;
case SDLK_CAPSLOCK:
keyboard->modstate ^= KMOD_CAPS;
break;
default:
keyboard->modstate |= modifier;
break;
}
} else {
keyboard->modstate &= ~modifier;
modstate = keyboard->modstate;
}
In the key down path, modstate (and thus keysym.mod) ends up being the modifier state /before/ the event, but in the key up path modstate ends up being the modifier state /after/ the event. Personally I think the "modstate = keyboard->modstate" line should just be moved after the entire if/else statement, so that keysym.mod always reflects the current state.
2017-08-12 19:34:09 +00:00
|
|
|
event.key.keysym.mod = keyboard->modstate;
|
2015-06-21 15:33:46 +00:00
|
|
|
event.key.windowID = keyboard->focus ? keyboard->focus->id : 0;
|
|
|
|
posted = (SDL_PushEvent(&event) > 0);
|
|
|
|
}
|
2021-01-28 02:41:36 +00:00
|
|
|
|
|
|
|
/* If the keyboard is grabbed and the grabbed window is in full-screen,
|
|
|
|
minimize the window when we receive Alt+Tab, unless the application
|
|
|
|
has explicitly opted out of this behavior. */
|
|
|
|
if (keycode == SDLK_TAB &&
|
|
|
|
state == SDL_PRESSED &&
|
|
|
|
(keyboard->modstate & KMOD_ALT) &&
|
|
|
|
keyboard->focus &&
|
|
|
|
(keyboard->focus->flags & SDL_WINDOW_KEYBOARD_GRABBED) &&
|
|
|
|
(keyboard->focus->flags & SDL_WINDOW_FULLSCREEN) &&
|
|
|
|
SDL_GetHintBoolean(SDL_HINT_ALLOW_ALT_TAB_WHILE_GRABBED, SDL_TRUE)) {
|
|
|
|
/* We will temporarily forfeit our grab by minimizing our window,
|
|
|
|
allowing the user to escape the application */
|
|
|
|
SDL_MinimizeWindow(keyboard->focus);
|
|
|
|
}
|
2021-06-12 05:00:50 +00:00
|
|
|
|
2015-06-21 15:33:46 +00:00
|
|
|
return (posted);
|
|
|
|
}
|
|
|
|
|
2020-04-09 02:16:31 +00:00
|
|
|
int
|
|
|
|
SDL_SendKeyboardKey(Uint8 state, SDL_Scancode scancode)
|
|
|
|
{
|
|
|
|
return SDL_SendKeyboardKeyInternal(KEYBOARD_HARDWARE, state, scancode);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
SDL_SendKeyboardKeyAutoRelease(SDL_Scancode scancode)
|
|
|
|
{
|
|
|
|
return SDL_SendKeyboardKeyInternal(KEYBOARD_AUTORELEASE, SDL_PRESSED, scancode);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
SDL_ReleaseAutoReleaseKeys(void)
|
|
|
|
{
|
|
|
|
SDL_Keyboard *keyboard = &SDL_keyboard;
|
|
|
|
SDL_Scancode scancode;
|
|
|
|
|
|
|
|
if (keyboard->autorelease_pending) {
|
|
|
|
for (scancode = SDL_SCANCODE_UNKNOWN; scancode < SDL_NUM_SCANCODES; ++scancode) {
|
|
|
|
if (keyboard->keysource[scancode] == KEYBOARD_AUTORELEASE) {
|
|
|
|
SDL_SendKeyboardKeyInternal(KEYBOARD_AUTORELEASE, SDL_RELEASED, scancode);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
keyboard->autorelease_pending = SDL_FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
SDL_bool
|
|
|
|
SDL_HardwareKeyboardKeyPressed(void)
|
|
|
|
{
|
|
|
|
SDL_Keyboard *keyboard = &SDL_keyboard;
|
|
|
|
SDL_Scancode scancode;
|
|
|
|
|
|
|
|
for (scancode = SDL_SCANCODE_UNKNOWN; scancode < SDL_NUM_SCANCODES; ++scancode) {
|
|
|
|
if ((keyboard->keysource[scancode] & KEYBOARD_HARDWARE) != 0) {
|
|
|
|
return SDL_TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return SDL_FALSE;
|
|
|
|
}
|
|
|
|
|
2015-06-21 15:33:46 +00:00
|
|
|
int
|
|
|
|
SDL_SendKeyboardText(const char *text)
|
|
|
|
{
|
|
|
|
SDL_Keyboard *keyboard = &SDL_keyboard;
|
|
|
|
int posted;
|
|
|
|
|
|
|
|
/* Don't post text events for unprintable characters */
|
|
|
|
if ((unsigned char)*text < ' ' || *text == 127) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Post the event, if desired */
|
|
|
|
posted = 0;
|
|
|
|
if (SDL_GetEventState(SDL_TEXTINPUT) == SDL_ENABLE) {
|
|
|
|
SDL_Event event;
|
2022-03-04 18:49:12 +00:00
|
|
|
size_t i = 0, length = SDL_strlen(text);
|
|
|
|
|
2015-06-21 15:33:46 +00:00
|
|
|
event.text.type = SDL_TEXTINPUT;
|
|
|
|
event.text.windowID = keyboard->focus ? keyboard->focus->id : 0;
|
2022-03-04 18:49:12 +00:00
|
|
|
while (i < length) {
|
|
|
|
i += SDL_utf8strlcpy(event.text.text, text + i, SDL_arraysize(event.text.text));
|
|
|
|
posted |= (SDL_PushEvent(&event) > 0);
|
|
|
|
}
|
2015-06-21 15:33:46 +00:00
|
|
|
}
|
|
|
|
return (posted);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
SDL_SendEditingText(const char *text, int start, int length)
|
|
|
|
{
|
|
|
|
SDL_Keyboard *keyboard = &SDL_keyboard;
|
|
|
|
int posted;
|
|
|
|
|
|
|
|
/* Post the event, if desired */
|
|
|
|
posted = 0;
|
|
|
|
if (SDL_GetEventState(SDL_TEXTEDITING) == SDL_ENABLE) {
|
|
|
|
SDL_Event event;
|
|
|
|
event.edit.type = SDL_TEXTEDITING;
|
|
|
|
event.edit.windowID = keyboard->focus ? keyboard->focus->id : 0;
|
|
|
|
event.edit.start = start;
|
|
|
|
event.edit.length = length;
|
|
|
|
SDL_utf8strlcpy(event.edit.text, text, SDL_arraysize(event.edit.text));
|
2022-03-11 22:45:17 +00:00
|
|
|
|
|
|
|
if (SDL_GetHintBoolean(SDL_HINT_IME_SUPPORT_EXTENDED_TEXT, SDL_FALSE) &&
|
|
|
|
SDL_strlen(text) > SDL_arraysize(event.text.text)) {
|
|
|
|
event.editExt.type = SDL_TEXTEDITING_EXT;
|
|
|
|
event.editExt.windowID = keyboard->focus ? keyboard->focus->id : 0;
|
|
|
|
event.editExt.text = text ? SDL_strdup(text) : NULL;
|
|
|
|
event.editExt.start = start;
|
|
|
|
event.editExt.length = length;
|
|
|
|
} else {
|
|
|
|
event.edit.type = SDL_TEXTEDITING;
|
|
|
|
event.edit.windowID = keyboard->focus ? keyboard->focus->id : 0;
|
|
|
|
event.edit.start = start;
|
|
|
|
event.edit.length = length;
|
|
|
|
SDL_utf8strlcpy(event.edit.text, text, SDL_arraysize(event.edit.text));
|
|
|
|
}
|
|
|
|
|
2015-06-21 15:33:46 +00:00
|
|
|
posted = (SDL_PushEvent(&event) > 0);
|
|
|
|
}
|
|
|
|
return (posted);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
SDL_KeyboardQuit(void)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
const Uint8 *
|
|
|
|
SDL_GetKeyboardState(int *numkeys)
|
|
|
|
{
|
|
|
|
SDL_Keyboard *keyboard = &SDL_keyboard;
|
|
|
|
|
|
|
|
if (numkeys != (int *) 0) {
|
|
|
|
*numkeys = SDL_NUM_SCANCODES;
|
|
|
|
}
|
|
|
|
return keyboard->keystate;
|
|
|
|
}
|
|
|
|
|
|
|
|
SDL_Keymod
|
|
|
|
SDL_GetModState(void)
|
|
|
|
{
|
|
|
|
SDL_Keyboard *keyboard = &SDL_keyboard;
|
|
|
|
|
2017-03-03 21:38:17 +00:00
|
|
|
return (SDL_Keymod) keyboard->modstate;
|
2015-06-21 15:33:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
SDL_SetModState(SDL_Keymod modstate)
|
|
|
|
{
|
|
|
|
SDL_Keyboard *keyboard = &SDL_keyboard;
|
|
|
|
|
|
|
|
keyboard->modstate = modstate;
|
|
|
|
}
|
|
|
|
|
2015-12-28 18:07:44 +00:00
|
|
|
/* Note that SDL_ToggleModState() is not a public API. SDL_SetModState() is. */
|
|
|
|
void
|
|
|
|
SDL_ToggleModState(const SDL_Keymod modstate, const SDL_bool toggle)
|
|
|
|
{
|
|
|
|
SDL_Keyboard *keyboard = &SDL_keyboard;
|
|
|
|
if (toggle) {
|
|
|
|
keyboard->modstate |= modstate;
|
|
|
|
} else {
|
|
|
|
keyboard->modstate &= ~modstate;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-06-21 15:33:46 +00:00
|
|
|
SDL_Keycode
|
|
|
|
SDL_GetKeyFromScancode(SDL_Scancode scancode)
|
|
|
|
{
|
|
|
|
SDL_Keyboard *keyboard = &SDL_keyboard;
|
|
|
|
|
2019-10-30 14:13:55 +00:00
|
|
|
if (((int)scancode) < SDL_SCANCODE_UNKNOWN || scancode >= SDL_NUM_SCANCODES) {
|
2015-06-21 15:33:46 +00:00
|
|
|
SDL_InvalidParamError("scancode");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return keyboard->keymap[scancode];
|
|
|
|
}
|
|
|
|
|
|
|
|
SDL_Scancode
|
|
|
|
SDL_GetScancodeFromKey(SDL_Keycode key)
|
|
|
|
{
|
|
|
|
SDL_Keyboard *keyboard = &SDL_keyboard;
|
|
|
|
SDL_Scancode scancode;
|
|
|
|
|
|
|
|
for (scancode = SDL_SCANCODE_UNKNOWN; scancode < SDL_NUM_SCANCODES;
|
|
|
|
++scancode) {
|
|
|
|
if (keyboard->keymap[scancode] == key) {
|
|
|
|
return scancode;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return SDL_SCANCODE_UNKNOWN;
|
|
|
|
}
|
|
|
|
|
|
|
|
const char *
|
|
|
|
SDL_GetScancodeName(SDL_Scancode scancode)
|
|
|
|
{
|
|
|
|
const char *name;
|
2019-10-30 14:13:55 +00:00
|
|
|
if (((int)scancode) < SDL_SCANCODE_UNKNOWN || scancode >= SDL_NUM_SCANCODES) {
|
2015-06-21 15:33:46 +00:00
|
|
|
SDL_InvalidParamError("scancode");
|
|
|
|
return "";
|
|
|
|
}
|
|
|
|
|
|
|
|
name = SDL_scancode_names[scancode];
|
|
|
|
if (name)
|
|
|
|
return name;
|
|
|
|
else
|
|
|
|
return "";
|
|
|
|
}
|
|
|
|
|
|
|
|
SDL_Scancode SDL_GetScancodeFromName(const char *name)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (!name || !*name) {
|
|
|
|
SDL_InvalidParamError("name");
|
|
|
|
return SDL_SCANCODE_UNKNOWN;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < SDL_arraysize(SDL_scancode_names); ++i) {
|
|
|
|
if (!SDL_scancode_names[i]) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (SDL_strcasecmp(name, SDL_scancode_names[i]) == 0) {
|
|
|
|
return (SDL_Scancode)i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
SDL_InvalidParamError("name");
|
|
|
|
return SDL_SCANCODE_UNKNOWN;
|
|
|
|
}
|
|
|
|
|
|
|
|
const char *
|
|
|
|
SDL_GetKeyName(SDL_Keycode key)
|
|
|
|
{
|
|
|
|
static char name[8];
|
|
|
|
char *end;
|
|
|
|
|
|
|
|
if (key & SDLK_SCANCODE_MASK) {
|
|
|
|
return
|
|
|
|
SDL_GetScancodeName((SDL_Scancode) (key & ~SDLK_SCANCODE_MASK));
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (key) {
|
|
|
|
case SDLK_RETURN:
|
|
|
|
return SDL_GetScancodeName(SDL_SCANCODE_RETURN);
|
|
|
|
case SDLK_ESCAPE:
|
|
|
|
return SDL_GetScancodeName(SDL_SCANCODE_ESCAPE);
|
|
|
|
case SDLK_BACKSPACE:
|
|
|
|
return SDL_GetScancodeName(SDL_SCANCODE_BACKSPACE);
|
|
|
|
case SDLK_TAB:
|
|
|
|
return SDL_GetScancodeName(SDL_SCANCODE_TAB);
|
|
|
|
case SDLK_SPACE:
|
|
|
|
return SDL_GetScancodeName(SDL_SCANCODE_SPACE);
|
|
|
|
case SDLK_DELETE:
|
|
|
|
return SDL_GetScancodeName(SDL_SCANCODE_DELETE);
|
|
|
|
default:
|
|
|
|
/* Unaccented letter keys on latin keyboards are normally
|
|
|
|
labeled in upper case (and probably on others like Greek or
|
|
|
|
Cyrillic too, so if you happen to know for sure, please
|
|
|
|
adapt this). */
|
|
|
|
if (key >= 'a' && key <= 'z') {
|
|
|
|
key -= 32;
|
|
|
|
}
|
|
|
|
|
|
|
|
end = SDL_UCS4ToUTF8((Uint32) key, name);
|
|
|
|
*end = '\0';
|
|
|
|
return name;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
SDL_Keycode
|
|
|
|
SDL_GetKeyFromName(const char *name)
|
|
|
|
{
|
|
|
|
SDL_Keycode key;
|
|
|
|
|
2017-01-09 19:30:29 +00:00
|
|
|
/* Check input */
|
|
|
|
if (name == NULL) {
|
|
|
|
return SDLK_UNKNOWN;
|
|
|
|
}
|
2015-06-21 15:33:46 +00:00
|
|
|
|
|
|
|
/* If it's a single UTF-8 character, then that's the keycode itself */
|
|
|
|
key = *(const unsigned char *)name;
|
|
|
|
if (key >= 0xF0) {
|
|
|
|
if (SDL_strlen(name) == 4) {
|
|
|
|
int i = 0;
|
|
|
|
key = (Uint16)(name[i]&0x07) << 18;
|
|
|
|
key |= (Uint16)(name[++i]&0x3F) << 12;
|
|
|
|
key |= (Uint16)(name[++i]&0x3F) << 6;
|
|
|
|
key |= (Uint16)(name[++i]&0x3F);
|
|
|
|
return key;
|
|
|
|
}
|
|
|
|
return SDLK_UNKNOWN;
|
|
|
|
} else if (key >= 0xE0) {
|
|
|
|
if (SDL_strlen(name) == 3) {
|
|
|
|
int i = 0;
|
|
|
|
key = (Uint16)(name[i]&0x0F) << 12;
|
|
|
|
key |= (Uint16)(name[++i]&0x3F) << 6;
|
|
|
|
key |= (Uint16)(name[++i]&0x3F);
|
|
|
|
return key;
|
|
|
|
}
|
|
|
|
return SDLK_UNKNOWN;
|
|
|
|
} else if (key >= 0xC0) {
|
|
|
|
if (SDL_strlen(name) == 2) {
|
|
|
|
int i = 0;
|
|
|
|
key = (Uint16)(name[i]&0x1F) << 6;
|
|
|
|
key |= (Uint16)(name[++i]&0x3F);
|
|
|
|
return key;
|
|
|
|
}
|
|
|
|
return SDLK_UNKNOWN;
|
|
|
|
} else {
|
|
|
|
if (SDL_strlen(name) == 1) {
|
|
|
|
if (key >= 'A' && key <= 'Z') {
|
|
|
|
key += 32;
|
|
|
|
}
|
|
|
|
return key;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Get the scancode for this name, and the associated keycode */
|
|
|
|
return SDL_default_keymap[SDL_GetScancodeFromName(name)];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* vi: set ts=4 sw=4 expandtab: */
|