diff options
| author | 3gg <3gg@shellblade.net> | 2025-12-27 12:03:39 -0800 |
|---|---|---|
| committer | 3gg <3gg@shellblade.net> | 2025-12-27 12:03:39 -0800 |
| commit | 5a079a2d114f96d4847d1ee305d5b7c16eeec50e (patch) | |
| tree | 8926ab44f168acf787d8e19608857b3af0f82758 /contrib/SDL-3.2.8/src/core/freebsd | |
Initial commit
Diffstat (limited to 'contrib/SDL-3.2.8/src/core/freebsd')
| -rw-r--r-- | contrib/SDL-3.2.8/src/core/freebsd/SDL_evdev_kbd_default_keyaccmap.h | 167 | ||||
| -rw-r--r-- | contrib/SDL-3.2.8/src/core/freebsd/SDL_evdev_kbd_freebsd.c | 613 |
2 files changed, 780 insertions, 0 deletions
diff --git a/contrib/SDL-3.2.8/src/core/freebsd/SDL_evdev_kbd_default_keyaccmap.h b/contrib/SDL-3.2.8/src/core/freebsd/SDL_evdev_kbd_default_keyaccmap.h new file mode 100644 index 0000000..fc6e5e8 --- /dev/null +++ b/contrib/SDL-3.2.8/src/core/freebsd/SDL_evdev_kbd_default_keyaccmap.h | |||
| @@ -0,0 +1,167 @@ | |||
| 1 | #include <sys/kbio.h> | ||
| 2 | |||
| 3 | /* *INDENT-OFF* */ // clang-format off | ||
| 4 | /* | ||
| 5 | * Automatically generated from /usr/share/vt/keymaps/us.acc.kbd. | ||
| 6 | * DO NOT EDIT! | ||
| 7 | */ | ||
| 8 | static keymap_t keymap_default_us_acc = { 0x6d, { | ||
| 9 | /* alt | ||
| 10 | * scan cntrl alt alt cntrl | ||
| 11 | * code base shift cntrl shift alt shift cntrl shift spcl flgs | ||
| 12 | * --------------------------------------------------------------------------- | ||
| 13 | */ | ||
| 14 | /*00*/{{ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, }, 0xFF,0x00 }, | ||
| 15 | /*01*/{{ 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, DBG, DBG, }, 0x03,0x00 }, | ||
| 16 | /*02*/{{ '1', '!', NOP, NOP, '1', '!', NOP, NOP, }, 0x33,0x00 }, | ||
| 17 | /*03*/{{ '2', '@', 0x00, 0x00, '2', '@', 0x00, 0x00, }, 0x00,0x00 }, | ||
| 18 | /*04*/{{ '3', '#', NOP, NOP, '3', '#', NOP, NOP, }, 0x33,0x00 }, | ||
| 19 | /*05*/{{ '4', '$', NOP, NOP, '4', '$', NOP, NOP, }, 0x33,0x00 }, | ||
| 20 | /*06*/{{ '5', '%', NOP, NOP, '5', '%', NOP, NOP, }, 0x33,0x00 }, | ||
| 21 | /*07*/{{ '6', '^', 0x1E, 0x1E, '6', DCIR, 0x1E, 0x1E, }, 0x04,0x00 }, | ||
| 22 | /*08*/{{ '7', '&', NOP, NOP, '7', '&', NOP, NOP, }, 0x33,0x00 }, | ||
| 23 | /*09*/{{ '8', '*', NOP, NOP, '8', DRIN, NOP, NOP, }, 0x37,0x00 }, | ||
| 24 | /*0a*/{{ '9', '(', NOP, NOP, '9', '(', NOP, NOP, }, 0x33,0x00 }, | ||
| 25 | /*0b*/{{ '0', ')', NOP, NOP, '0', ')', NOP, NOP, }, 0x33,0x00 }, | ||
| 26 | /*0c*/{{ '-', '_', 0x1F, 0x1F, '-', '_', 0x1F, 0x1F, }, 0x00,0x00 }, | ||
| 27 | /*0d*/{{ '=', '+', NOP, NOP, '=', '+', NOP, NOP, }, 0x33,0x00 }, | ||
| 28 | /*0e*/{{ 0x08, 0x08, 0x7F, 0x7F, 0x08, 0x08, 0x7F, 0x7F, }, 0x00,0x00 }, | ||
| 29 | /*0f*/{{ 0x09, BTAB, NEXT, NEXT, 0x09, BTAB, NOP, NOP, }, 0x77,0x00 }, | ||
| 30 | /*10*/{{ 'q', 'Q', 0x11, 0x11, 'q', 'Q', 0x11, 0x11, }, 0x00,0x01 }, | ||
| 31 | /*11*/{{ 'w', 'W', 0x17, 0x17, 'w', 'W', 0x17, 0x17, }, 0x00,0x01 }, | ||
| 32 | /*12*/{{ 'e', 'E', 0x05, 0x05, 'e', 'E', 0x05, 0x05, }, 0x00,0x01 }, | ||
| 33 | /*13*/{{ 'r', 'R', 0x12, 0x12, 'r', 'R', 0x12, 0x12, }, 0x00,0x01 }, | ||
| 34 | /*14*/{{ 't', 'T', 0x14, 0x14, 't', 'T', 0x14, 0x14, }, 0x00,0x01 }, | ||
| 35 | /*15*/{{ 'y', 'Y', 0x19, 0x19, 'y', 'Y', 0x19, 0x19, }, 0x00,0x01 }, | ||
| 36 | /*16*/{{ 'u', 'U', 0x15, 0x15, 'u', 'U', 0x15, 0x15, }, 0x00,0x01 }, | ||
| 37 | /*17*/{{ 'i', 'I', 0x09, 0x09, 'i', 'I', 0x09, 0x09, }, 0x00,0x01 }, | ||
| 38 | /*18*/{{ 'o', 'O', 0x0F, 0x0F, 'o', 'O', 0x0F, 0x0F, }, 0x00,0x01 }, | ||
| 39 | /*19*/{{ 'p', 'P', 0x10, 0x10, 'p', 'P', 0x10, 0x10, }, 0x00,0x01 }, | ||
| 40 | /*1a*/{{ '[', '{', 0x1B, 0x1B, '[', '{', 0x1B, 0x1B, }, 0x00,0x00 }, | ||
| 41 | /*1b*/{{ ']', '}', 0x1D, 0x1D, ']', '}', 0x1D, 0x1D, }, 0x00,0x00 }, | ||
| 42 | /*1c*/{{ 0x0D, 0x0D, 0x0A, 0x0A, 0x0D, 0x0D, 0x0A, 0x0A, }, 0x00,0x00 }, | ||
| 43 | /*1d*/{{ LCTR, LCTR, LCTR, LCTR, LCTR, LCTR, LCTR, LCTR, }, 0xFF,0x00 }, | ||
| 44 | /*1e*/{{ 'a', 'A', 0x01, 0x01, 'a', 'A', 0x01, 0x01, }, 0x00,0x01 }, | ||
| 45 | /*1f*/{{ 's', 'S', 0x13, 0x13, 's', 'S', 0x13, 0x13, }, 0x00,0x01 }, | ||
| 46 | /*20*/{{ 'd', 'D', 0x04, 0x04, 'd', 'D', 0x04, 0x04, }, 0x00,0x01 }, | ||
| 47 | /*21*/{{ 'f', 'F', 0x06, 0x06, 'f', 'F', 0x06, 0x06, }, 0x00,0x01 }, | ||
| 48 | /*22*/{{ 'g', 'G', 0x07, 0x07, 'g', 'G', 0x07, 0x07, }, 0x00,0x01 }, | ||
| 49 | /*23*/{{ 'h', 'H', 0x08, 0x08, 'h', 'H', 0x08, 0x08, }, 0x00,0x01 }, | ||
| 50 | /*24*/{{ 'j', 'J', 0x0A, 0x0A, 'j', 'J', 0x0A, 0x0A, }, 0x00,0x01 }, | ||
| 51 | /*25*/{{ 'k', 'K', 0x0B, 0x0B, 'k', 'K', 0x0B, 0x0B, }, 0x00,0x01 }, | ||
| 52 | /*26*/{{ 'l', 'L', 0x0C, 0x0C, 'l', 'L', 0x0C, 0x0C, }, 0x00,0x01 }, | ||
| 53 | /*27*/{{ ';', ':', NOP, NOP, ';', ':', NOP, NOP, }, 0x33,0x00 }, | ||
| 54 | /*28*/{{ '\'', '"', NOP, NOP, DACU, DUML, NOP, NOP, }, 0x3F,0x00 }, | ||
| 55 | /*29*/{{ '`', '~', NOP, NOP, DGRA, DTIL, NOP, NOP, }, 0x3F,0x00 }, | ||
| 56 | /*2a*/{{ LSH, LSH, LSH, LSH, LSH, LSH, LSH, LSH, }, 0xFF,0x00 }, | ||
| 57 | /*2b*/{{ '\\', '|', 0x1C, 0x1C, '\\', '|', 0x1C, 0x1C, }, 0x00,0x00 }, | ||
| 58 | /*2c*/{{ 'z', 'Z', 0x1A, 0x1A, 'z', 'Z', 0x1A, 0x1A, }, 0x00,0x01 }, | ||
| 59 | /*2d*/{{ 'x', 'X', 0x18, 0x18, 'x', 'X', 0x18, 0x18, }, 0x00,0x01 }, | ||
| 60 | /*2e*/{{ 'c', 'C', 0x03, 0x03, 'c', 'C', 0x03, 0x03, }, 0x00,0x01 }, | ||
| 61 | /*2f*/{{ 'v', 'V', 0x16, 0x16, 'v', 'V', 0x16, 0x16, }, 0x00,0x01 }, | ||
| 62 | /*30*/{{ 'b', 'B', 0x02, 0x02, 'b', 'B', 0x02, 0x02, }, 0x00,0x01 }, | ||
| 63 | /*31*/{{ 'n', 'N', 0x0E, 0x0E, 'n', 'N', 0x0E, 0x0E, }, 0x00,0x01 }, | ||
| 64 | /*32*/{{ 'm', 'M', 0x0D, 0x0D, 'm', 'M', 0x0D, 0x0D, }, 0x00,0x01 }, | ||
| 65 | /*33*/{{ ',', '<', NOP, NOP, DCED, '<', NOP, NOP, }, 0x3B,0x00 }, | ||
| 66 | /*34*/{{ '.', '>', NOP, NOP, '.', '>', NOP, NOP, }, 0x33,0x00 }, | ||
| 67 | /*35*/{{ '/', '?', NOP, NOP, '/', '?', NOP, NOP, }, 0x33,0x00 }, | ||
| 68 | /*36*/{{ RSH, RSH, RSH, RSH, RSH, RSH, RSH, RSH, }, 0xFF,0x00 }, | ||
| 69 | /*37*/{{ '*', '*', '*', '*', '*', '*', '*', '*', }, 0x00,0x00 }, | ||
| 70 | /*38*/{{ LALT, LALT, LALT, LALT, LALT, LALT, LALT, LALT, }, 0xFF,0x00 }, | ||
| 71 | /*39*/{{ ' ', ' ', 0x00, 0x00, ' ', ' ', SUSP, SUSP, }, 0x03,0x00 }, | ||
| 72 | /*3a*/{{ CLK, CLK, CLK, CLK, CLK, CLK, CLK, CLK, }, 0xFF,0x00 }, | ||
| 73 | /*3b*/{{ F( 1), F(13), F(25), F(37), S( 1), S(11), S( 1), S(11),}, 0xFF,0x00 }, | ||
| 74 | /*3c*/{{ F( 2), F(14), F(26), F(38), S( 2), S(12), S( 2), S(12),}, 0xFF,0x00 }, | ||
| 75 | /*3d*/{{ F( 3), F(15), F(27), F(39), S( 3), S(13), S( 3), S(13),}, 0xFF,0x00 }, | ||
| 76 | /*3e*/{{ F( 4), F(16), F(28), F(40), S( 4), S(14), S( 4), S(14),}, 0xFF,0x00 }, | ||
| 77 | /*3f*/{{ F( 5), F(17), F(29), F(41), S( 5), S(15), S( 5), S(15),}, 0xFF,0x00 }, | ||
| 78 | /*40*/{{ F( 6), F(18), F(30), F(42), S( 6), S(16), S( 6), S(16),}, 0xFF,0x00 }, | ||
| 79 | /*41*/{{ F( 7), F(19), F(31), F(43), S( 7), S( 7), S( 7), S( 7),}, 0xFF,0x00 }, | ||
| 80 | /*42*/{{ F( 8), F(20), F(32), F(44), S( 8), S( 8), S( 8), S( 8),}, 0xFF,0x00 }, | ||
| 81 | /*43*/{{ F( 9), F(21), F(33), F(45), S( 9), S( 9), S( 9), S( 9),}, 0xFF,0x00 }, | ||
| 82 | /*44*/{{ F(10), F(22), F(34), F(46), S(10), S(10), S(10), S(10),}, 0xFF,0x00 }, | ||
| 83 | /*45*/{{ NLK, NLK, NLK, NLK, NLK, NLK, NLK, NLK, }, 0xFF,0x00 }, | ||
| 84 | /*46*/{{ SLK, SLK, SLK, SLK, SLK, SLK, SLK, SLK, }, 0xFF,0x00 }, | ||
| 85 | /*47*/{{ F(49), '7', '7', '7', '7', '7', '7', '7', }, 0x80,0x02 }, | ||
| 86 | /*48*/{{ F(50), '8', '8', '8', '8', '8', '8', '8', }, 0x80,0x02 }, | ||
| 87 | /*49*/{{ F(51), '9', '9', '9', '9', '9', '9', '9', }, 0x80,0x02 }, | ||
| 88 | /*4a*/{{ F(52), '-', '-', '-', '-', '-', '-', '-', }, 0x80,0x02 }, | ||
| 89 | /*4b*/{{ F(53), '4', '4', '4', '4', '4', '4', '4', }, 0x80,0x02 }, | ||
| 90 | /*4c*/{{ F(54), '5', '5', '5', '5', '5', '5', '5', }, 0x80,0x02 }, | ||
| 91 | /*4d*/{{ F(55), '6', '6', '6', '6', '6', '6', '6', }, 0x80,0x02 }, | ||
| 92 | /*4e*/{{ F(56), '+', '+', '+', '+', '+', '+', '+', }, 0x80,0x02 }, | ||
| 93 | /*4f*/{{ F(57), '1', '1', '1', '1', '1', '1', '1', }, 0x80,0x02 }, | ||
| 94 | /*50*/{{ F(58), '2', '2', '2', '2', '2', '2', '2', }, 0x80,0x02 }, | ||
| 95 | /*51*/{{ F(59), '3', '3', '3', '3', '3', '3', '3', }, 0x80,0x02 }, | ||
| 96 | /*52*/{{ F(60), '0', '0', '0', '0', '0', '0', '0', }, 0x80,0x02 }, | ||
| 97 | /*53*/{{ 0x7F, '.', '.', '.', '.', '.', RBT, RBT, }, 0x03,0x02 }, | ||
| 98 | /*54*/{{ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, }, 0xFF,0x00 }, | ||
| 99 | /*55*/{{ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, }, 0xFF,0x00 }, | ||
| 100 | /*56*/{{ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, }, 0xFF,0x00 }, | ||
| 101 | /*57*/{{ F(11), F(23), F(35), F(47), S(11), S(11), S(11), S(11),}, 0xFF,0x00 }, | ||
| 102 | /*58*/{{ F(12), F(24), F(36), F(48), S(12), S(12), S(12), S(12),}, 0xFF,0x00 }, | ||
| 103 | /*59*/{{ 0x0D, 0x0D, 0x0A, 0x0A, 0x0D, 0x0D, 0x0A, 0x0A, }, 0x00,0x00 }, | ||
| 104 | /*5a*/{{ RCTR, RCTR, RCTR, RCTR, RCTR, RCTR, RCTR, RCTR, }, 0xFF,0x00 }, | ||
| 105 | /*5b*/{{ '/', '/', '/', '/', '/', '/', '/', '/', }, 0x00,0x02 }, | ||
| 106 | /*5c*/{{ NEXT, NEXT, NOP, NOP, DBG, DBG, DBG, DBG, }, 0xFF,0x00 }, | ||
| 107 | /*5d*/{{ RALT, RALT, RALT, RALT, RALT, RALT, RALT, RALT, }, 0xFF,0x00 }, | ||
| 108 | /*5e*/{{ F(49), F(49), F(49), F(49), F(49), F(49), F(49), F(49),}, 0xFF,0x00 }, | ||
| 109 | /*5f*/{{ F(50), F(50), F(50), F(50), F(50), F(50), F(50), F(50),}, 0xFF,0x00 }, | ||
| 110 | /*60*/{{ F(51), F(51), F(51), F(51), F(51), F(51), F(51), F(51),}, 0xFF,0x00 }, | ||
| 111 | /*61*/{{ F(53), F(53), F(53), F(53), F(53), F(53), F(53), F(53),}, 0xFF,0x00 }, | ||
| 112 | /*62*/{{ F(55), F(55), F(55), F(55), F(55), F(55), F(55), F(55),}, 0xFF,0x00 }, | ||
| 113 | /*63*/{{ F(57), F(57), F(57), F(57), F(57), F(57), F(57), F(57),}, 0xFF,0x00 }, | ||
| 114 | /*64*/{{ F(58), F(58), F(58), F(58), F(58), F(58), F(58), F(58),}, 0xFF,0x00 }, | ||
| 115 | /*65*/{{ F(59), F(59), F(59), F(59), F(59), F(59), F(59), F(59),}, 0xFF,0x00 }, | ||
| 116 | /*66*/{{ F(60), F(60), F(60), F(60), F(60), F(60), F(60), F(60),}, 0xFF,0x00 }, | ||
| 117 | /*67*/{{ F(61), F(61), F(61), F(61), F(61), F(61), RBT, F(61),}, 0xFF,0x00 }, | ||
| 118 | /*68*/{{ SPSC, SPSC, SUSP, SUSP, NOP, NOP, SUSP, SUSP, }, 0xFF,0x00 }, | ||
| 119 | /*69*/{{ F(62), F(62), F(62), F(62), F(62), F(62), F(62), F(62),}, 0xFF,0x00 }, | ||
| 120 | /*6a*/{{ F(63), F(63), F(63), F(63), F(63), F(63), F(63), F(63),}, 0xFF,0x00 }, | ||
| 121 | /*6b*/{{ F(64), F(64), F(64), F(64), F(64), F(64), F(64), F(64),}, 0xFF,0x00 }, | ||
| 122 | /*6c*/{{ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, }, 0xFF,0x00 }, | ||
| 123 | } }; | ||
| 124 | |||
| 125 | static accentmap_t accentmap_default_us_acc = { 11, { | ||
| 126 | // dgra=0 | ||
| 127 | { '`', { { 'a',0xe0 }, { 'A',0xc0 }, { 'e',0xe8 }, { 'E',0xc8 }, | ||
| 128 | { 'i',0xec }, { 'I',0xcc }, { 'o',0xf2 }, { 'O',0xd2 }, | ||
| 129 | { 'u',0xf9 }, { 'U',0xd9 }, }, }, | ||
| 130 | // dacu=1 | ||
| 131 | { 0xb4, { { 'a',0xe1 }, { 'A',0xc1 }, { 'e',0xe9 }, { 'E',0xc9 }, | ||
| 132 | { 'i',0xed }, { 'I',0xcd }, { 'o',0xf3 }, { 'O',0xd3 }, | ||
| 133 | { 'u',0xfa }, { 'U',0xda }, { 'y',0xfd }, { 'Y',0xdd }, }, }, | ||
| 134 | // dcir=2 | ||
| 135 | { '^', { { 'a',0xe2 }, { 'A',0xc2 }, { 'e',0xea }, { 'E',0xca }, | ||
| 136 | { 'i',0xee }, { 'I',0xce }, { 'o',0xf4 }, { 'O',0xd4 }, | ||
| 137 | { 'u',0xfb }, { 'U',0xdb }, }, }, | ||
| 138 | // dtil=3 | ||
| 139 | { '~', { { 'a',0xe3 }, { 'A',0xc3 }, { 'n',0xf1 }, { 'N',0xd1 }, | ||
| 140 | { 'o',0xf5 }, { 'O',0xd5 }, }, }, | ||
| 141 | // dmac=4 | ||
| 142 | { 0x00 }, | ||
| 143 | // dbre=5 | ||
| 144 | { 0x00 }, | ||
| 145 | // ddot=6 | ||
| 146 | { 0x00 }, | ||
| 147 | // duml=7 | ||
| 148 | { 0xa8, { { 'a',0xe4 }, { 'A',0xc4 }, { 'e',0xeb }, { 'E',0xcb }, | ||
| 149 | { 'i',0xef }, { 'I',0xcf }, { 'o',0xf6 }, { 'O',0xd6 }, | ||
| 150 | { 'u',0xfc }, { 'U',0xdc }, { 'y',0xff }, }, }, | ||
| 151 | // dsla=8 | ||
| 152 | { 0x00 }, | ||
| 153 | // drin=9 | ||
| 154 | { 0xb0, { { 'a',0xe5 }, { 'A',0xc5 }, }, }, | ||
| 155 | // dced=10 | ||
| 156 | { 0xb8, { { 'c',0xe7 }, { 'C',0xc7 }, }, }, | ||
| 157 | // dapo=11 | ||
| 158 | { 0x00 }, | ||
| 159 | // ddac=12 | ||
| 160 | { 0x00 }, | ||
| 161 | // dogo=13 | ||
| 162 | { 0x00 }, | ||
| 163 | // dcar=14 | ||
| 164 | { 0x00 }, | ||
| 165 | } }; | ||
| 166 | |||
| 167 | /* *INDENT-ON* */ // clang-format on | ||
diff --git a/contrib/SDL-3.2.8/src/core/freebsd/SDL_evdev_kbd_freebsd.c b/contrib/SDL-3.2.8/src/core/freebsd/SDL_evdev_kbd_freebsd.c new file mode 100644 index 0000000..16a2171 --- /dev/null +++ b/contrib/SDL-3.2.8/src/core/freebsd/SDL_evdev_kbd_freebsd.c | |||
| @@ -0,0 +1,613 @@ | |||
| 1 | /* | ||
| 2 | Simple DirectMedia Layer | ||
| 3 | Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org> | ||
| 4 | |||
| 5 | This software is provided 'as-is', without any express or implied | ||
| 6 | warranty. In no event will the authors be held liable for any damages | ||
| 7 | arising from the use of this software. | ||
| 8 | |||
| 9 | Permission is granted to anyone to use this software for any purpose, | ||
| 10 | including commercial applications, and to alter it and redistribute it | ||
| 11 | freely, subject to the following restrictions: | ||
| 12 | |||
| 13 | 1. The origin of this software must not be misrepresented; you must not | ||
| 14 | claim that you wrote the original software. If you use this software | ||
| 15 | in a product, an acknowledgment in the product documentation would be | ||
| 16 | appreciated but is not required. | ||
| 17 | 2. Altered source versions must be plainly marked as such, and must not be | ||
| 18 | misrepresented as being the original software. | ||
| 19 | 3. This notice may not be removed or altered from any source distribution. | ||
| 20 | */ | ||
| 21 | |||
| 22 | #include "SDL_internal.h" | ||
| 23 | |||
| 24 | #include "../linux/SDL_evdev_kbd.h" | ||
| 25 | |||
| 26 | #ifdef SDL_INPUT_FBSDKBIO | ||
| 27 | |||
| 28 | // This logic is adapted from drivers/tty/vt/keyboard.c in the Linux kernel source, slightly modified to work with FreeBSD | ||
| 29 | |||
| 30 | #include <unistd.h> | ||
| 31 | #include <fcntl.h> | ||
| 32 | #include <sys/ioctl.h> | ||
| 33 | #include <sys/kbio.h> | ||
| 34 | #include <sys/consio.h> | ||
| 35 | |||
| 36 | #include <signal.h> | ||
| 37 | |||
| 38 | #include "../../events/SDL_events_c.h" | ||
| 39 | #include "SDL_evdev_kbd_default_keyaccmap.h" | ||
| 40 | |||
| 41 | typedef void(fn_handler_fn)(SDL_EVDEV_keyboard_state *kbd); | ||
| 42 | |||
| 43 | /* | ||
| 44 | * Keyboard State | ||
| 45 | */ | ||
| 46 | |||
| 47 | struct SDL_EVDEV_keyboard_state | ||
| 48 | { | ||
| 49 | int console_fd; | ||
| 50 | int keyboard_fd; | ||
| 51 | unsigned long old_kbd_mode; | ||
| 52 | unsigned short **key_maps; | ||
| 53 | keymap_t *key_map; | ||
| 54 | keyboard_info_t *kbInfo; | ||
| 55 | unsigned char shift_down[4]; // shift state counters.. | ||
| 56 | bool dead_key_next; | ||
| 57 | int npadch; // -1 or number assembled on pad | ||
| 58 | accentmap_t *accents; | ||
| 59 | unsigned int diacr; | ||
| 60 | bool rep; // flag telling character repeat | ||
| 61 | unsigned char lockstate; | ||
| 62 | unsigned char ledflagstate; | ||
| 63 | char shift_state; | ||
| 64 | char text[128]; | ||
| 65 | unsigned int text_len; | ||
| 66 | }; | ||
| 67 | |||
| 68 | static bool SDL_EVDEV_kbd_load_keymaps(SDL_EVDEV_keyboard_state *kbd) | ||
| 69 | { | ||
| 70 | return ioctl(kbd->keyboard_fd, GIO_KEYMAP, kbd->key_map) >= 0; | ||
| 71 | } | ||
| 72 | |||
| 73 | static SDL_EVDEV_keyboard_state *kbd_cleanup_state = NULL; | ||
| 74 | static int kbd_cleanup_sigactions_installed = 0; | ||
| 75 | static int kbd_cleanup_atexit_installed = 0; | ||
| 76 | |||
| 77 | static struct sigaction old_sigaction[NSIG]; | ||
| 78 | |||
| 79 | static int fatal_signals[] = { | ||
| 80 | // Handlers for SIGTERM and SIGINT are installed in SDL_InitQuit. | ||
| 81 | SIGHUP, SIGQUIT, SIGILL, SIGABRT, | ||
| 82 | SIGFPE, SIGSEGV, SIGPIPE, SIGBUS, | ||
| 83 | SIGSYS | ||
| 84 | }; | ||
| 85 | |||
| 86 | static void kbd_cleanup(void) | ||
| 87 | { | ||
| 88 | struct mouse_info mData; | ||
| 89 | SDL_EVDEV_keyboard_state *kbd = kbd_cleanup_state; | ||
| 90 | if (!kbd) { | ||
| 91 | return; | ||
| 92 | } | ||
| 93 | kbd_cleanup_state = NULL; | ||
| 94 | SDL_zero(mData); | ||
| 95 | mData.operation = MOUSE_SHOW; | ||
| 96 | ioctl(kbd->keyboard_fd, KDSKBMODE, kbd->old_kbd_mode); | ||
| 97 | if (kbd->keyboard_fd != kbd->console_fd) { | ||
| 98 | close(kbd->keyboard_fd); | ||
| 99 | } | ||
| 100 | ioctl(kbd->console_fd, CONS_SETKBD, (unsigned long)(kbd->kbInfo->kb_index)); | ||
| 101 | ioctl(kbd->console_fd, CONS_MOUSECTL, &mData); | ||
| 102 | } | ||
| 103 | |||
| 104 | void SDL_EVDEV_kbd_reraise_signal(int sig) | ||
| 105 | { | ||
| 106 | raise(sig); | ||
| 107 | } | ||
| 108 | |||
| 109 | siginfo_t *SDL_EVDEV_kdb_cleanup_siginfo = NULL; | ||
| 110 | void *SDL_EVDEV_kdb_cleanup_ucontext = NULL; | ||
| 111 | |||
| 112 | static void kbd_cleanup_signal_action(int signum, siginfo_t *info, void *ucontext) | ||
| 113 | { | ||
| 114 | struct sigaction *old_action_p = &(old_sigaction[signum]); | ||
| 115 | sigset_t sigset; | ||
| 116 | |||
| 117 | // Restore original signal handler before going any further. | ||
| 118 | sigaction(signum, old_action_p, NULL); | ||
| 119 | |||
| 120 | // Unmask current signal. | ||
| 121 | sigemptyset(&sigset); | ||
| 122 | sigaddset(&sigset, signum); | ||
| 123 | sigprocmask(SIG_UNBLOCK, &sigset, NULL); | ||
| 124 | |||
| 125 | // Save original signal info and context for archeologists. | ||
| 126 | SDL_EVDEV_kdb_cleanup_siginfo = info; | ||
| 127 | SDL_EVDEV_kdb_cleanup_ucontext = ucontext; | ||
| 128 | |||
| 129 | // Restore keyboard. | ||
| 130 | kbd_cleanup(); | ||
| 131 | |||
| 132 | // Reraise signal. | ||
| 133 | SDL_EVDEV_kbd_reraise_signal(signum); | ||
| 134 | } | ||
| 135 | |||
| 136 | static void kbd_unregister_emerg_cleanup(void) | ||
| 137 | { | ||
| 138 | int tabidx; | ||
| 139 | |||
| 140 | kbd_cleanup_state = NULL; | ||
| 141 | |||
| 142 | if (!kbd_cleanup_sigactions_installed) { | ||
| 143 | return; | ||
| 144 | } | ||
| 145 | kbd_cleanup_sigactions_installed = 0; | ||
| 146 | |||
| 147 | for (tabidx = 0; tabidx < sizeof(fatal_signals) / sizeof(fatal_signals[0]); ++tabidx) { | ||
| 148 | struct sigaction *old_action_p; | ||
| 149 | struct sigaction cur_action; | ||
| 150 | int signum = fatal_signals[tabidx]; | ||
| 151 | old_action_p = &(old_sigaction[signum]); | ||
| 152 | |||
| 153 | // Examine current signal action | ||
| 154 | if (sigaction(signum, NULL, &cur_action)) { | ||
| 155 | continue; | ||
| 156 | } | ||
| 157 | |||
| 158 | // Check if action installed and not modified | ||
| 159 | if (!(cur_action.sa_flags & SA_SIGINFO) || cur_action.sa_sigaction != &kbd_cleanup_signal_action) { | ||
| 160 | continue; | ||
| 161 | } | ||
| 162 | |||
| 163 | // Restore original action | ||
| 164 | sigaction(signum, old_action_p, NULL); | ||
| 165 | } | ||
| 166 | } | ||
| 167 | |||
| 168 | static void kbd_cleanup_atexit(void) | ||
| 169 | { | ||
| 170 | // Restore keyboard. | ||
| 171 | kbd_cleanup(); | ||
| 172 | |||
| 173 | // Try to restore signal handlers in case shared library is being unloaded | ||
| 174 | kbd_unregister_emerg_cleanup(); | ||
| 175 | } | ||
| 176 | |||
| 177 | static void kbd_register_emerg_cleanup(SDL_EVDEV_keyboard_state *kbd) | ||
| 178 | { | ||
| 179 | int tabidx; | ||
| 180 | |||
| 181 | if (kbd_cleanup_state) { | ||
| 182 | return; | ||
| 183 | } | ||
| 184 | kbd_cleanup_state = kbd; | ||
| 185 | |||
| 186 | if (!kbd_cleanup_atexit_installed) { | ||
| 187 | /* Since glibc 2.2.3, atexit() (and on_exit(3)) can be used within a shared library to establish | ||
| 188 | * functions that are called when the shared library is unloaded. | ||
| 189 | * -- man atexit(3) | ||
| 190 | */ | ||
| 191 | atexit(kbd_cleanup_atexit); | ||
| 192 | kbd_cleanup_atexit_installed = 1; | ||
| 193 | } | ||
| 194 | |||
| 195 | if (kbd_cleanup_sigactions_installed) { | ||
| 196 | return; | ||
| 197 | } | ||
| 198 | kbd_cleanup_sigactions_installed = 1; | ||
| 199 | |||
| 200 | for (tabidx = 0; tabidx < sizeof(fatal_signals) / sizeof(fatal_signals[0]); ++tabidx) { | ||
| 201 | struct sigaction *old_action_p; | ||
| 202 | struct sigaction new_action; | ||
| 203 | int signum = fatal_signals[tabidx]; | ||
| 204 | old_action_p = &(old_sigaction[signum]); | ||
| 205 | if (sigaction(signum, NULL, old_action_p)) { | ||
| 206 | continue; | ||
| 207 | } | ||
| 208 | |||
| 209 | /* Skip SIGHUP and SIGPIPE if handler is already installed | ||
| 210 | * - assume the handler will do the cleanup | ||
| 211 | */ | ||
| 212 | if ((signum == SIGHUP || signum == SIGPIPE) && (old_action_p->sa_handler != SIG_DFL || (void (*)(int))old_action_p->sa_sigaction != SIG_DFL)) { | ||
| 213 | continue; | ||
| 214 | } | ||
| 215 | |||
| 216 | new_action = *old_action_p; | ||
| 217 | new_action.sa_flags |= SA_SIGINFO; | ||
| 218 | new_action.sa_sigaction = &kbd_cleanup_signal_action; | ||
| 219 | sigaction(signum, &new_action, NULL); | ||
| 220 | } | ||
| 221 | } | ||
| 222 | |||
| 223 | SDL_EVDEV_keyboard_state *SDL_EVDEV_kbd_init(void) | ||
| 224 | { | ||
| 225 | SDL_EVDEV_keyboard_state *kbd; | ||
| 226 | struct mouse_info mData; | ||
| 227 | char flag_state; | ||
| 228 | char *devicePath; | ||
| 229 | |||
| 230 | SDL_zero(mData); | ||
| 231 | mData.operation = MOUSE_HIDE; | ||
| 232 | kbd = (SDL_EVDEV_keyboard_state *)SDL_calloc(1, sizeof(SDL_EVDEV_keyboard_state)); | ||
| 233 | if (!kbd) { | ||
| 234 | return NULL; | ||
| 235 | } | ||
| 236 | |||
| 237 | kbd->npadch = -1; | ||
| 238 | |||
| 239 | // This might fail if we're not connected to a tty (e.g. on the Steam Link) | ||
| 240 | kbd->keyboard_fd = kbd->console_fd = open("/dev/tty", O_RDONLY | O_CLOEXEC); | ||
| 241 | |||
| 242 | kbd->shift_state = 0; | ||
| 243 | |||
| 244 | kbd->accents = SDL_calloc(1, sizeof(accentmap_t)); | ||
| 245 | kbd->key_map = SDL_calloc(1, sizeof(keymap_t)); | ||
| 246 | kbd->kbInfo = SDL_calloc(1, sizeof(keyboard_info_t)); | ||
| 247 | |||
| 248 | ioctl(kbd->console_fd, KDGKBINFO, kbd->kbInfo); | ||
| 249 | ioctl(kbd->console_fd, CONS_MOUSECTL, &mData); | ||
| 250 | |||
| 251 | if (ioctl(kbd->console_fd, KDGKBSTATE, &flag_state) == 0) { | ||
| 252 | kbd->ledflagstate = flag_state; | ||
| 253 | } | ||
| 254 | |||
| 255 | if (ioctl(kbd->console_fd, GIO_DEADKEYMAP, kbd->accents) < 0) { | ||
| 256 | SDL_free(kbd->accents); | ||
| 257 | kbd->accents = &accentmap_default_us_acc; | ||
| 258 | } | ||
| 259 | |||
| 260 | if (ioctl(kbd->console_fd, KDGKBMODE, &kbd->old_kbd_mode) == 0) { | ||
| 261 | // Set the keyboard in XLATE mode and load the keymaps | ||
| 262 | ioctl(kbd->console_fd, KDSKBMODE, (unsigned long)(K_XLATE)); | ||
| 263 | if (!SDL_EVDEV_kbd_load_keymaps(kbd)) { | ||
| 264 | SDL_free(kbd->key_map); | ||
| 265 | kbd->key_map = &keymap_default_us_acc; | ||
| 266 | } | ||
| 267 | |||
| 268 | if (SDL_GetHintBoolean(SDL_HINT_MUTE_CONSOLE_KEYBOARD, true)) { | ||
| 269 | /* Take keyboard from console and open the actual keyboard device. | ||
| 270 | * Ensures that the keystrokes do not leak through to the console. | ||
| 271 | */ | ||
| 272 | ioctl(kbd->console_fd, CONS_RELKBD, 1ul); | ||
| 273 | SDL_asprintf(&devicePath, "/dev/kbd%d", kbd->kbInfo->kb_index); | ||
| 274 | kbd->keyboard_fd = open(devicePath, O_WRONLY | O_CLOEXEC); | ||
| 275 | if (kbd->keyboard_fd == -1) { | ||
| 276 | // Give keyboard back. | ||
| 277 | ioctl(kbd->console_fd, CONS_SETKBD, (unsigned long)(kbd->kbInfo->kb_index)); | ||
| 278 | kbd->keyboard_fd = kbd->console_fd; | ||
| 279 | } | ||
| 280 | |||
| 281 | /* Make sure to restore keyboard if application fails to call | ||
| 282 | * SDL_Quit before exit or fatal signal is raised. | ||
| 283 | */ | ||
| 284 | if (!SDL_GetHintBoolean(SDL_HINT_NO_SIGNAL_HANDLERS, false)) { | ||
| 285 | kbd_register_emerg_cleanup(kbd); | ||
| 286 | } | ||
| 287 | SDL_free(devicePath); | ||
| 288 | } else | ||
| 289 | kbd->keyboard_fd = kbd->console_fd; | ||
| 290 | } | ||
| 291 | |||
| 292 | return kbd; | ||
| 293 | } | ||
| 294 | |||
| 295 | void SDL_EVDEV_kbd_quit(SDL_EVDEV_keyboard_state *kbd) | ||
| 296 | { | ||
| 297 | struct mouse_info mData; | ||
| 298 | |||
| 299 | if (!kbd) { | ||
| 300 | return; | ||
| 301 | } | ||
| 302 | SDL_zero(mData); | ||
| 303 | mData.operation = MOUSE_SHOW; | ||
| 304 | ioctl(kbd->console_fd, CONS_MOUSECTL, &mData); | ||
| 305 | |||
| 306 | kbd_unregister_emerg_cleanup(); | ||
| 307 | |||
| 308 | if (kbd->keyboard_fd >= 0) { | ||
| 309 | // Restore the original keyboard mode | ||
| 310 | ioctl(kbd->keyboard_fd, KDSKBMODE, kbd->old_kbd_mode); | ||
| 311 | |||
| 312 | close(kbd->keyboard_fd); | ||
| 313 | if (kbd->console_fd != kbd->keyboard_fd && kbd->console_fd >= 0) { | ||
| 314 | // Give back keyboard. | ||
| 315 | ioctl(kbd->console_fd, CONS_SETKBD, (unsigned long)(kbd->kbInfo->kb_index)); | ||
| 316 | } | ||
| 317 | kbd->console_fd = kbd->keyboard_fd = -1; | ||
| 318 | } | ||
| 319 | |||
| 320 | SDL_free(kbd); | ||
| 321 | } | ||
| 322 | |||
| 323 | void SDL_EVDEV_kbd_set_muted(SDL_EVDEV_keyboard_state *state, bool muted) | ||
| 324 | { | ||
| 325 | } | ||
| 326 | |||
| 327 | void SDL_EVDEV_kbd_set_vt_switch_callbacks(SDL_EVDEV_keyboard_state *state, void (*release_callback)(void*), void *release_callback_data, void (*acquire_callback)(void*), void *acquire_callback_data) | ||
| 328 | { | ||
| 329 | } | ||
| 330 | |||
| 331 | void SDL_EVDEV_kbd_update(SDL_EVDEV_keyboard_state *state) | ||
| 332 | { | ||
| 333 | } | ||
| 334 | |||
| 335 | /* | ||
| 336 | * Helper Functions. | ||
| 337 | */ | ||
| 338 | static void put_queue(SDL_EVDEV_keyboard_state *kbd, uint c) | ||
| 339 | { | ||
| 340 | // c is already part of a UTF-8 sequence and safe to add as a character | ||
| 341 | if (kbd->text_len < (sizeof(kbd->text) - 1)) { | ||
| 342 | kbd->text[kbd->text_len++] = (char)c; | ||
| 343 | } | ||
| 344 | } | ||
| 345 | |||
| 346 | static void put_utf8(SDL_EVDEV_keyboard_state *kbd, uint c) | ||
| 347 | { | ||
| 348 | if (c < 0x80) | ||
| 349 | /* 0******* */ | ||
| 350 | put_queue(kbd, c); | ||
| 351 | else if (c < 0x800) { | ||
| 352 | /* 110***** 10****** */ | ||
| 353 | put_queue(kbd, 0xc0 | (c >> 6)); | ||
| 354 | put_queue(kbd, 0x80 | (c & 0x3f)); | ||
| 355 | } else if (c < 0x10000) { | ||
| 356 | if (c >= 0xD800 && c < 0xE000) { | ||
| 357 | return; | ||
| 358 | } | ||
| 359 | if (c == 0xFFFF) { | ||
| 360 | return; | ||
| 361 | } | ||
| 362 | /* 1110**** 10****** 10****** */ | ||
| 363 | put_queue(kbd, 0xe0 | (c >> 12)); | ||
| 364 | put_queue(kbd, 0x80 | ((c >> 6) & 0x3f)); | ||
| 365 | put_queue(kbd, 0x80 | (c & 0x3f)); | ||
| 366 | } else if (c < 0x110000) { | ||
| 367 | /* 11110*** 10****** 10****** 10****** */ | ||
| 368 | put_queue(kbd, 0xf0 | (c >> 18)); | ||
| 369 | put_queue(kbd, 0x80 | ((c >> 12) & 0x3f)); | ||
| 370 | put_queue(kbd, 0x80 | ((c >> 6) & 0x3f)); | ||
| 371 | put_queue(kbd, 0x80 | (c & 0x3f)); | ||
| 372 | } | ||
| 373 | } | ||
| 374 | |||
| 375 | /* | ||
| 376 | * We have a combining character DIACR here, followed by the character CH. | ||
| 377 | * If the combination occurs in the table, return the corresponding value. | ||
| 378 | * Otherwise, if CH is a space or equals DIACR, return DIACR. | ||
| 379 | * Otherwise, conclude that DIACR was not combining after all, | ||
| 380 | * queue it and return CH. | ||
| 381 | */ | ||
| 382 | static unsigned int handle_diacr(SDL_EVDEV_keyboard_state *kbd, unsigned int ch) | ||
| 383 | { | ||
| 384 | unsigned int d = kbd->diacr; | ||
| 385 | unsigned int i, j; | ||
| 386 | |||
| 387 | kbd->diacr = 0; | ||
| 388 | |||
| 389 | for (i = 0; i < kbd->accents->n_accs; i++) { | ||
| 390 | if (kbd->accents->acc[i].accchar == d) { | ||
| 391 | for (j = 0; j < NUM_ACCENTCHARS; ++j) { | ||
| 392 | if (kbd->accents->acc[i].map[j][0] == 0) { // end of table | ||
| 393 | break; | ||
| 394 | } | ||
| 395 | if (kbd->accents->acc[i].map[j][0] == ch) { | ||
| 396 | return kbd->accents->acc[i].map[j][1]; | ||
| 397 | } | ||
| 398 | } | ||
| 399 | } | ||
| 400 | } | ||
| 401 | |||
| 402 | if (ch == ' ' || ch == d) { | ||
| 403 | put_utf8(kbd, d); | ||
| 404 | return 0; | ||
| 405 | } | ||
| 406 | put_utf8(kbd, d); | ||
| 407 | |||
| 408 | return ch; | ||
| 409 | } | ||
| 410 | |||
| 411 | static bool vc_kbd_led(SDL_EVDEV_keyboard_state *kbd, int flag) | ||
| 412 | { | ||
| 413 | return (kbd->ledflagstate & flag) != 0; | ||
| 414 | } | ||
| 415 | |||
| 416 | static void chg_vc_kbd_led(SDL_EVDEV_keyboard_state *kbd, int flag) | ||
| 417 | { | ||
| 418 | kbd->ledflagstate ^= flag; | ||
| 419 | ioctl(kbd->keyboard_fd, KDSKBSTATE, (unsigned long)(kbd->ledflagstate)); | ||
| 420 | } | ||
| 421 | |||
| 422 | /* | ||
| 423 | * Special function handlers | ||
| 424 | */ | ||
| 425 | |||
| 426 | static void k_self(SDL_EVDEV_keyboard_state *kbd, unsigned int value, char up_flag) | ||
| 427 | { | ||
| 428 | if (up_flag) { | ||
| 429 | return; // no action, if this is a key release | ||
| 430 | } | ||
| 431 | |||
| 432 | if (kbd->diacr) { | ||
| 433 | value = handle_diacr(kbd, value); | ||
| 434 | } | ||
| 435 | |||
| 436 | if (kbd->dead_key_next) { | ||
| 437 | kbd->dead_key_next = false; | ||
| 438 | kbd->diacr = value; | ||
| 439 | return; | ||
| 440 | } | ||
| 441 | put_utf8(kbd, value); | ||
| 442 | } | ||
| 443 | |||
| 444 | static void k_deadunicode(SDL_EVDEV_keyboard_state *kbd, unsigned int value, char up_flag) | ||
| 445 | { | ||
| 446 | if (up_flag) | ||
| 447 | return; | ||
| 448 | |||
| 449 | kbd->diacr = (kbd->diacr ? handle_diacr(kbd, value) : value); | ||
| 450 | } | ||
| 451 | |||
| 452 | static void k_shift(SDL_EVDEV_keyboard_state *kbd, unsigned char value, char up_flag) | ||
| 453 | { | ||
| 454 | int old_state = kbd->shift_state; | ||
| 455 | |||
| 456 | if (kbd->rep) | ||
| 457 | return; | ||
| 458 | |||
| 459 | if (up_flag) { | ||
| 460 | /* | ||
| 461 | * handle the case that two shift or control | ||
| 462 | * keys are depressed simultaneously | ||
| 463 | */ | ||
| 464 | if (kbd->shift_down[value]) { | ||
| 465 | kbd->shift_down[value]--; | ||
| 466 | } | ||
| 467 | } else | ||
| 468 | kbd->shift_down[value]++; | ||
| 469 | |||
| 470 | if (kbd->shift_down[value]) | ||
| 471 | kbd->shift_state |= (1 << value); | ||
| 472 | else | ||
| 473 | kbd->shift_state &= ~(1 << value); | ||
| 474 | |||
| 475 | // kludge | ||
| 476 | if (up_flag && kbd->shift_state != old_state && kbd->npadch != -1) { | ||
| 477 | put_utf8(kbd, kbd->npadch); | ||
| 478 | kbd->npadch = -1; | ||
| 479 | } | ||
| 480 | } | ||
| 481 | |||
| 482 | void SDL_EVDEV_kbd_keycode(SDL_EVDEV_keyboard_state *kbd, unsigned int keycode, int down) | ||
| 483 | { | ||
| 484 | keymap_t key_map; | ||
| 485 | struct keyent_t keysym; | ||
| 486 | unsigned int final_key_state; | ||
| 487 | unsigned int map_from_key_sym; | ||
| 488 | |||
| 489 | if (!kbd) { | ||
| 490 | return; | ||
| 491 | } | ||
| 492 | |||
| 493 | key_map = *kbd->key_map; | ||
| 494 | |||
| 495 | kbd->rep = (down == 2); | ||
| 496 | |||
| 497 | if (keycode < NUM_KEYS) { | ||
| 498 | if (keycode >= 89 && keycode <= 95) { | ||
| 499 | // These constitute unprintable language-related keys, so ignore them. | ||
| 500 | return; | ||
| 501 | } | ||
| 502 | if (keycode > 95) { | ||
| 503 | keycode -= 7; | ||
| 504 | } | ||
| 505 | if (vc_kbd_led(kbd, ALKED) || (kbd->shift_state & 0x8)) { | ||
| 506 | keycode += ALTGR_OFFSET; | ||
| 507 | } | ||
| 508 | keysym = key_map.key[keycode]; | ||
| 509 | } else { | ||
| 510 | return; | ||
| 511 | } | ||
| 512 | |||
| 513 | final_key_state = kbd->shift_state & 0x7; | ||
| 514 | if ((keysym.flgs & FLAG_LOCK_C) && vc_kbd_led(kbd, LED_CAP)) { | ||
| 515 | final_key_state ^= 0x1; | ||
| 516 | } | ||
| 517 | if ((keysym.flgs & FLAG_LOCK_N) && vc_kbd_led(kbd, LED_NUM)) { | ||
| 518 | final_key_state ^= 0x1; | ||
| 519 | } | ||
| 520 | |||
| 521 | map_from_key_sym = keysym.map[final_key_state]; | ||
| 522 | if ((keysym.spcl & (0x80 >> final_key_state)) || (map_from_key_sym & SPCLKEY)) { | ||
| 523 | // Special function. | ||
| 524 | if (map_from_key_sym == 0) | ||
| 525 | return; // Nothing to do. | ||
| 526 | if (map_from_key_sym & SPCLKEY) { | ||
| 527 | map_from_key_sym &= ~SPCLKEY; | ||
| 528 | } | ||
| 529 | if (map_from_key_sym >= F_ACC && map_from_key_sym <= L_ACC) { | ||
| 530 | // Accent function. | ||
| 531 | unsigned int accent_index = map_from_key_sym - F_ACC; | ||
| 532 | if (kbd->accents->acc[accent_index].accchar != 0) { | ||
| 533 | k_deadunicode(kbd, kbd->accents->acc[accent_index].accchar, !down); | ||
| 534 | } | ||
| 535 | } else { | ||
| 536 | switch (map_from_key_sym) { | ||
| 537 | case ASH: // alt/meta shift | ||
| 538 | k_shift(kbd, 3, down == 0); | ||
| 539 | break; | ||
| 540 | case LSHA: // left shift + alt lock | ||
| 541 | case RSHA: // right shift + alt lock | ||
| 542 | if (down == 0) { | ||
| 543 | chg_vc_kbd_led(kbd, ALKED); | ||
| 544 | } | ||
| 545 | SDL_FALLTHROUGH; | ||
| 546 | case LSH: // left shift | ||
| 547 | case RSH: // right shift | ||
| 548 | k_shift(kbd, 0, down == 0); | ||
| 549 | break; | ||
| 550 | case LCTRA: // left ctrl + alt lock | ||
| 551 | case RCTRA: // right ctrl + alt lock | ||
| 552 | if (down == 0) { | ||
| 553 | chg_vc_kbd_led(kbd, ALKED); | ||
| 554 | } | ||
| 555 | SDL_FALLTHROUGH; | ||
| 556 | case LCTR: // left ctrl | ||
| 557 | case RCTR: // right ctrl | ||
| 558 | k_shift(kbd, 1, down == 0); | ||
| 559 | break; | ||
| 560 | case LALTA: // left alt + alt lock | ||
| 561 | case RALTA: // right alt + alt lock | ||
| 562 | if (down == 0) { | ||
| 563 | chg_vc_kbd_led(kbd, ALKED); | ||
| 564 | } | ||
| 565 | SDL_FALLTHROUGH; | ||
| 566 | case LALT: // left alt | ||
| 567 | case RALT: // right alt | ||
| 568 | k_shift(kbd, 2, down == 0); | ||
| 569 | break; | ||
| 570 | case ALK: // alt lock | ||
| 571 | if (down == 1) { | ||
| 572 | chg_vc_kbd_led(kbd, ALKED); | ||
| 573 | } | ||
| 574 | break; | ||
| 575 | case CLK: // caps lock | ||
| 576 | if (down == 1) { | ||
| 577 | chg_vc_kbd_led(kbd, CLKED); | ||
| 578 | } | ||
| 579 | break; | ||
| 580 | case NLK: // num lock | ||
| 581 | if (down == 1) { | ||
| 582 | chg_vc_kbd_led(kbd, NLKED); | ||
| 583 | } | ||
| 584 | break; | ||
| 585 | case SLK: // scroll lock | ||
| 586 | if (down == 1) { | ||
| 587 | chg_vc_kbd_led(kbd, SLKED); | ||
| 588 | } | ||
| 589 | break; | ||
| 590 | default: | ||
| 591 | return; | ||
| 592 | } | ||
| 593 | } | ||
| 594 | } else { | ||
| 595 | if (map_from_key_sym == '\n' || map_from_key_sym == '\r') { | ||
| 596 | if (kbd->diacr) { | ||
| 597 | kbd->diacr = 0; | ||
| 598 | return; | ||
| 599 | } | ||
| 600 | } | ||
| 601 | if (map_from_key_sym >= ' ' && map_from_key_sym != 127) { | ||
| 602 | k_self(kbd, map_from_key_sym, !down); | ||
| 603 | } | ||
| 604 | } | ||
| 605 | |||
| 606 | if (kbd->text_len > 0) { | ||
| 607 | kbd->text[kbd->text_len] = '\0'; | ||
| 608 | SDL_SendKeyboardText(kbd->text); | ||
| 609 | kbd->text_len = 0; | ||
| 610 | } | ||
| 611 | } | ||
| 612 | |||
| 613 | #endif // SDL_INPUT_FBSDKBIO | ||
