diff options
Diffstat (limited to 'contrib/SDL-3.2.8/src/core/openbsd')
| -rw-r--r-- | contrib/SDL-3.2.8/src/core/openbsd/SDL_wscons.h | 25 | ||||
| -rw-r--r-- | contrib/SDL-3.2.8/src/core/openbsd/SDL_wscons_kbd.c | 948 | ||||
| -rw-r--r-- | contrib/SDL-3.2.8/src/core/openbsd/SDL_wscons_mouse.c | 127 |
3 files changed, 1100 insertions, 0 deletions
diff --git a/contrib/SDL-3.2.8/src/core/openbsd/SDL_wscons.h b/contrib/SDL-3.2.8/src/core/openbsd/SDL_wscons.h new file mode 100644 index 0000000..f9b7bf8 --- /dev/null +++ b/contrib/SDL-3.2.8/src/core/openbsd/SDL_wscons.h | |||
| @@ -0,0 +1,25 @@ | |||
| 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 | void SDL_WSCONS_Init(void); | ||
| 23 | void SDL_WSCONS_Quit(void); | ||
| 24 | |||
| 25 | void SDL_WSCONS_PumpEvents(void); | ||
diff --git a/contrib/SDL-3.2.8/src/core/openbsd/SDL_wscons_kbd.c b/contrib/SDL-3.2.8/src/core/openbsd/SDL_wscons_kbd.c new file mode 100644 index 0000000..5a71044 --- /dev/null +++ b/contrib/SDL-3.2.8/src/core/openbsd/SDL_wscons_kbd.c | |||
| @@ -0,0 +1,948 @@ | |||
| 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 | #include <dev/wscons/wsksymvar.h> | ||
| 24 | #include <dev/wscons/wsksymdef.h> | ||
| 25 | #include "SDL_wscons.h" | ||
| 26 | #include <sys/time.h> | ||
| 27 | #include <dev/wscons/wsconsio.h> | ||
| 28 | #include <dev/wscons/wsdisplay_usl_io.h> | ||
| 29 | #include <termios.h> | ||
| 30 | #include <fcntl.h> | ||
| 31 | #include <sys/ioctl.h> | ||
| 32 | #include <sys/param.h> | ||
| 33 | #include <unistd.h> | ||
| 34 | |||
| 35 | #include "../../events/SDL_events_c.h" | ||
| 36 | #include "../../events/SDL_keyboard_c.h" | ||
| 37 | |||
| 38 | #ifdef SDL_PLATFORM_NETBSD | ||
| 39 | #define KS_GROUP_Ascii KS_GROUP_Plain | ||
| 40 | #define KS_Cmd_ScrollBack KS_Cmd_ScrollFastUp | ||
| 41 | #define KS_Cmd_ScrollFwd KS_Cmd_ScrollFastDown | ||
| 42 | #endif | ||
| 43 | |||
| 44 | #define RETIFIOCTLERR(x) \ | ||
| 45 | if ((x) == -1) { \ | ||
| 46 | SDL_free(input); \ | ||
| 47 | input = NULL; \ | ||
| 48 | return NULL; \ | ||
| 49 | } | ||
| 50 | |||
| 51 | typedef struct SDL_WSCONS_mouse_input_data SDL_WSCONS_mouse_input_data; | ||
| 52 | extern SDL_WSCONS_mouse_input_data *SDL_WSCONS_Init_Mouse(void); | ||
| 53 | extern void updateMouse(SDL_WSCONS_mouse_input_data *input); | ||
| 54 | extern void SDL_WSCONS_Quit_Mouse(SDL_WSCONS_mouse_input_data *input); | ||
| 55 | |||
| 56 | // Conversion table courtesy of /usr/src/sys/dev/wscons/wskbdutil.c | ||
| 57 | static const unsigned char latin1_to_upper[256] = { | ||
| 58 | // 0 8 1 9 2 a 3 b 4 c 5 d 6 e 7 f | ||
| 59 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0 | ||
| 60 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0 | ||
| 61 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 1 | ||
| 62 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 1 | ||
| 63 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 2 | ||
| 64 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 2 | ||
| 65 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 3 | ||
| 66 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 3 | ||
| 67 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 4 | ||
| 68 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 4 | ||
| 69 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 5 | ||
| 70 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 5 | ||
| 71 | 0x00, 'A', 'B', 'C', 'D', 'E', 'F', 'G', // 6 | ||
| 72 | 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', // 6 | ||
| 73 | 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', // 7 | ||
| 74 | 'X', 'Y', 'Z', 0x00, 0x00, 0x00, 0x00, 0x00, // 7 | ||
| 75 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 8 | ||
| 76 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 8 | ||
| 77 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 9 | ||
| 78 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 9 | ||
| 79 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // a | ||
| 80 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // a | ||
| 81 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // b | ||
| 82 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // b | ||
| 83 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // c | ||
| 84 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // c | ||
| 85 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // d | ||
| 86 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // d | ||
| 87 | 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, // e | ||
| 88 | 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, // e | ||
| 89 | 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0x00, // f | ||
| 90 | 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0x00, // f | ||
| 91 | }; | ||
| 92 | |||
| 93 | // Compose table courtesy of /usr/src/sys/dev/wscons/wskbdutil.c | ||
| 94 | static struct SDL_wscons_compose_tab_s | ||
| 95 | { | ||
| 96 | keysym_t elem[2]; | ||
| 97 | keysym_t result; | ||
| 98 | } compose_tab[] = { | ||
| 99 | { { KS_plus, KS_plus }, KS_numbersign }, | ||
| 100 | { { KS_a, KS_a }, KS_at }, | ||
| 101 | { { KS_parenleft, KS_parenleft }, KS_bracketleft }, | ||
| 102 | { { KS_slash, KS_slash }, KS_backslash }, | ||
| 103 | { { KS_parenright, KS_parenright }, KS_bracketright }, | ||
| 104 | { { KS_parenleft, KS_minus }, KS_braceleft }, | ||
| 105 | { { KS_slash, KS_minus }, KS_bar }, | ||
| 106 | { { KS_parenright, KS_minus }, KS_braceright }, | ||
| 107 | { { KS_exclam, KS_exclam }, KS_exclamdown }, | ||
| 108 | { { KS_c, KS_slash }, KS_cent }, | ||
| 109 | { { KS_l, KS_minus }, KS_sterling }, | ||
| 110 | { { KS_y, KS_minus }, KS_yen }, | ||
| 111 | { { KS_s, KS_o }, KS_section }, | ||
| 112 | { { KS_x, KS_o }, KS_currency }, | ||
| 113 | { { KS_c, KS_o }, KS_copyright }, | ||
| 114 | { { KS_less, KS_less }, KS_guillemotleft }, | ||
| 115 | { { KS_greater, KS_greater }, KS_guillemotright }, | ||
| 116 | { { KS_question, KS_question }, KS_questiondown }, | ||
| 117 | { { KS_dead_acute, KS_space }, KS_apostrophe }, | ||
| 118 | { { KS_dead_grave, KS_space }, KS_grave }, | ||
| 119 | { { KS_dead_tilde, KS_space }, KS_asciitilde }, | ||
| 120 | { { KS_dead_circumflex, KS_space }, KS_asciicircum }, | ||
| 121 | { { KS_dead_diaeresis, KS_space }, KS_quotedbl }, | ||
| 122 | { { KS_dead_cedilla, KS_space }, KS_comma }, | ||
| 123 | { { KS_dead_circumflex, KS_A }, KS_Acircumflex }, | ||
| 124 | { { KS_dead_diaeresis, KS_A }, KS_Adiaeresis }, | ||
| 125 | { { KS_dead_grave, KS_A }, KS_Agrave }, | ||
| 126 | { { KS_dead_abovering, KS_A }, KS_Aring }, | ||
| 127 | { { KS_dead_tilde, KS_A }, KS_Atilde }, | ||
| 128 | { { KS_dead_cedilla, KS_C }, KS_Ccedilla }, | ||
| 129 | { { KS_dead_acute, KS_E }, KS_Eacute }, | ||
| 130 | { { KS_dead_circumflex, KS_E }, KS_Ecircumflex }, | ||
| 131 | { { KS_dead_diaeresis, KS_E }, KS_Ediaeresis }, | ||
| 132 | { { KS_dead_grave, KS_E }, KS_Egrave }, | ||
| 133 | { { KS_dead_acute, KS_I }, KS_Iacute }, | ||
| 134 | { { KS_dead_circumflex, KS_I }, KS_Icircumflex }, | ||
| 135 | { { KS_dead_diaeresis, KS_I }, KS_Idiaeresis }, | ||
| 136 | { { KS_dead_grave, KS_I }, KS_Igrave }, | ||
| 137 | { { KS_dead_tilde, KS_N }, KS_Ntilde }, | ||
| 138 | { { KS_dead_acute, KS_O }, KS_Oacute }, | ||
| 139 | { { KS_dead_circumflex, KS_O }, KS_Ocircumflex }, | ||
| 140 | { { KS_dead_diaeresis, KS_O }, KS_Odiaeresis }, | ||
| 141 | { { KS_dead_grave, KS_O }, KS_Ograve }, | ||
| 142 | { { KS_dead_tilde, KS_O }, KS_Otilde }, | ||
| 143 | { { KS_dead_acute, KS_U }, KS_Uacute }, | ||
| 144 | { { KS_dead_circumflex, KS_U }, KS_Ucircumflex }, | ||
| 145 | { { KS_dead_diaeresis, KS_U }, KS_Udiaeresis }, | ||
| 146 | { { KS_dead_grave, KS_U }, KS_Ugrave }, | ||
| 147 | { { KS_dead_acute, KS_Y }, KS_Yacute }, | ||
| 148 | { { KS_dead_acute, KS_a }, KS_aacute }, | ||
| 149 | { { KS_dead_circumflex, KS_a }, KS_acircumflex }, | ||
| 150 | { { KS_dead_diaeresis, KS_a }, KS_adiaeresis }, | ||
| 151 | { { KS_dead_grave, KS_a }, KS_agrave }, | ||
| 152 | { { KS_dead_abovering, KS_a }, KS_aring }, | ||
| 153 | { { KS_dead_tilde, KS_a }, KS_atilde }, | ||
| 154 | { { KS_dead_cedilla, KS_c }, KS_ccedilla }, | ||
| 155 | { { KS_dead_acute, KS_e }, KS_eacute }, | ||
| 156 | { { KS_dead_circumflex, KS_e }, KS_ecircumflex }, | ||
| 157 | { { KS_dead_diaeresis, KS_e }, KS_ediaeresis }, | ||
| 158 | { { KS_dead_grave, KS_e }, KS_egrave }, | ||
| 159 | { { KS_dead_acute, KS_i }, KS_iacute }, | ||
| 160 | { { KS_dead_circumflex, KS_i }, KS_icircumflex }, | ||
| 161 | { { KS_dead_diaeresis, KS_i }, KS_idiaeresis }, | ||
| 162 | { { KS_dead_grave, KS_i }, KS_igrave }, | ||
| 163 | { { KS_dead_tilde, KS_n }, KS_ntilde }, | ||
| 164 | { { KS_dead_acute, KS_o }, KS_oacute }, | ||
| 165 | { { KS_dead_circumflex, KS_o }, KS_ocircumflex }, | ||
| 166 | { { KS_dead_diaeresis, KS_o }, KS_odiaeresis }, | ||
| 167 | { { KS_dead_grave, KS_o }, KS_ograve }, | ||
| 168 | { { KS_dead_tilde, KS_o }, KS_otilde }, | ||
| 169 | { { KS_dead_acute, KS_u }, KS_uacute }, | ||
| 170 | { { KS_dead_circumflex, KS_u }, KS_ucircumflex }, | ||
| 171 | { { KS_dead_diaeresis, KS_u }, KS_udiaeresis }, | ||
| 172 | { { KS_dead_grave, KS_u }, KS_ugrave }, | ||
| 173 | { { KS_dead_acute, KS_y }, KS_yacute }, | ||
| 174 | { { KS_dead_diaeresis, KS_y }, KS_ydiaeresis }, | ||
| 175 | { { KS_quotedbl, KS_A }, KS_Adiaeresis }, | ||
| 176 | { { KS_quotedbl, KS_E }, KS_Ediaeresis }, | ||
| 177 | { { KS_quotedbl, KS_I }, KS_Idiaeresis }, | ||
| 178 | { { KS_quotedbl, KS_O }, KS_Odiaeresis }, | ||
| 179 | { { KS_quotedbl, KS_U }, KS_Udiaeresis }, | ||
| 180 | { { KS_quotedbl, KS_a }, KS_adiaeresis }, | ||
| 181 | { { KS_quotedbl, KS_e }, KS_ediaeresis }, | ||
| 182 | { { KS_quotedbl, KS_i }, KS_idiaeresis }, | ||
| 183 | { { KS_quotedbl, KS_o }, KS_odiaeresis }, | ||
| 184 | { { KS_quotedbl, KS_u }, KS_udiaeresis }, | ||
| 185 | { { KS_quotedbl, KS_y }, KS_ydiaeresis }, | ||
| 186 | { { KS_acute, KS_A }, KS_Aacute }, | ||
| 187 | { { KS_asciicircum, KS_A }, KS_Acircumflex }, | ||
| 188 | { { KS_grave, KS_A }, KS_Agrave }, | ||
| 189 | { { KS_asterisk, KS_A }, KS_Aring }, | ||
| 190 | { { KS_asciitilde, KS_A }, KS_Atilde }, | ||
| 191 | { { KS_cedilla, KS_C }, KS_Ccedilla }, | ||
| 192 | { { KS_acute, KS_E }, KS_Eacute }, | ||
| 193 | { { KS_asciicircum, KS_E }, KS_Ecircumflex }, | ||
| 194 | { { KS_grave, KS_E }, KS_Egrave }, | ||
| 195 | { { KS_acute, KS_I }, KS_Iacute }, | ||
| 196 | { { KS_asciicircum, KS_I }, KS_Icircumflex }, | ||
| 197 | { { KS_grave, KS_I }, KS_Igrave }, | ||
| 198 | { { KS_asciitilde, KS_N }, KS_Ntilde }, | ||
| 199 | { { KS_acute, KS_O }, KS_Oacute }, | ||
| 200 | { { KS_asciicircum, KS_O }, KS_Ocircumflex }, | ||
| 201 | { { KS_grave, KS_O }, KS_Ograve }, | ||
| 202 | { { KS_asciitilde, KS_O }, KS_Otilde }, | ||
| 203 | { { KS_acute, KS_U }, KS_Uacute }, | ||
| 204 | { { KS_asciicircum, KS_U }, KS_Ucircumflex }, | ||
| 205 | { { KS_grave, KS_U }, KS_Ugrave }, | ||
| 206 | { { KS_acute, KS_Y }, KS_Yacute }, | ||
| 207 | { { KS_acute, KS_a }, KS_aacute }, | ||
| 208 | { { KS_asciicircum, KS_a }, KS_acircumflex }, | ||
| 209 | { { KS_grave, KS_a }, KS_agrave }, | ||
| 210 | { { KS_asterisk, KS_a }, KS_aring }, | ||
| 211 | { { KS_asciitilde, KS_a }, KS_atilde }, | ||
| 212 | { { KS_cedilla, KS_c }, KS_ccedilla }, | ||
| 213 | { { KS_acute, KS_e }, KS_eacute }, | ||
| 214 | { { KS_asciicircum, KS_e }, KS_ecircumflex }, | ||
| 215 | { { KS_grave, KS_e }, KS_egrave }, | ||
| 216 | { { KS_acute, KS_i }, KS_iacute }, | ||
| 217 | { { KS_asciicircum, KS_i }, KS_icircumflex }, | ||
| 218 | { { KS_grave, KS_i }, KS_igrave }, | ||
| 219 | { { KS_asciitilde, KS_n }, KS_ntilde }, | ||
| 220 | { { KS_acute, KS_o }, KS_oacute }, | ||
| 221 | { { KS_asciicircum, KS_o }, KS_ocircumflex }, | ||
| 222 | { { KS_grave, KS_o }, KS_ograve }, | ||
| 223 | { { KS_asciitilde, KS_o }, KS_otilde }, | ||
| 224 | { { KS_acute, KS_u }, KS_uacute }, | ||
| 225 | { { KS_asciicircum, KS_u }, KS_ucircumflex }, | ||
| 226 | { { KS_grave, KS_u }, KS_ugrave }, | ||
| 227 | { { KS_acute, KS_y }, KS_yacute }, | ||
| 228 | #ifndef SDL_PLATFORM_NETBSD | ||
| 229 | { { KS_dead_caron, KS_space }, KS_L2_caron }, | ||
| 230 | { { KS_dead_caron, KS_S }, KS_L2_Scaron }, | ||
| 231 | { { KS_dead_caron, KS_Z }, KS_L2_Zcaron }, | ||
| 232 | { { KS_dead_caron, KS_s }, KS_L2_scaron }, | ||
| 233 | { { KS_dead_caron, KS_z }, KS_L2_zcaron } | ||
| 234 | #endif | ||
| 235 | }; | ||
| 236 | |||
| 237 | static keysym_t ksym_upcase(keysym_t ksym) | ||
| 238 | { | ||
| 239 | if (ksym >= KS_f1 && ksym <= KS_f20) { | ||
| 240 | return KS_F1 - KS_f1 + ksym; | ||
| 241 | } | ||
| 242 | |||
| 243 | if (KS_GROUP(ksym) == KS_GROUP_Ascii && ksym <= 0xff && latin1_to_upper[ksym] != 0x00) { | ||
| 244 | return latin1_to_upper[ksym]; | ||
| 245 | } | ||
| 246 | |||
| 247 | return ksym; | ||
| 248 | } | ||
| 249 | static struct wscons_keycode_to_SDL | ||
| 250 | { | ||
| 251 | keysym_t sourcekey; | ||
| 252 | SDL_Scancode targetKey; | ||
| 253 | } conversion_table[] = { | ||
| 254 | { KS_Menu, SDL_SCANCODE_APPLICATION }, | ||
| 255 | { KS_Up, SDL_SCANCODE_UP }, | ||
| 256 | { KS_Down, SDL_SCANCODE_DOWN }, | ||
| 257 | { KS_Left, SDL_SCANCODE_LEFT }, | ||
| 258 | { KS_Right, SDL_SCANCODE_RIGHT }, | ||
| 259 | { KS_Hold_Screen, SDL_SCANCODE_SCROLLLOCK }, | ||
| 260 | { KS_Num_Lock, SDL_SCANCODE_NUMLOCKCLEAR }, | ||
| 261 | { KS_Caps_Lock, SDL_SCANCODE_CAPSLOCK }, | ||
| 262 | { KS_BackSpace, SDL_SCANCODE_BACKSPACE }, | ||
| 263 | { KS_space, SDL_SCANCODE_SPACE }, | ||
| 264 | { KS_Delete, SDL_SCANCODE_BACKSPACE }, | ||
| 265 | { KS_Home, SDL_SCANCODE_HOME }, | ||
| 266 | { KS_End, SDL_SCANCODE_END }, | ||
| 267 | { KS_Pause, SDL_SCANCODE_PAUSE }, | ||
| 268 | { KS_Print_Screen, SDL_SCANCODE_PRINTSCREEN }, | ||
| 269 | { KS_Insert, SDL_SCANCODE_INSERT }, | ||
| 270 | { KS_Escape, SDL_SCANCODE_ESCAPE }, | ||
| 271 | { KS_Return, SDL_SCANCODE_RETURN }, | ||
| 272 | { KS_Linefeed, SDL_SCANCODE_RETURN }, | ||
| 273 | { KS_KP_Delete, SDL_SCANCODE_DELETE }, | ||
| 274 | { KS_KP_Insert, SDL_SCANCODE_INSERT }, | ||
| 275 | { KS_Control_L, SDL_SCANCODE_LCTRL }, | ||
| 276 | { KS_Control_R, SDL_SCANCODE_RCTRL }, | ||
| 277 | { KS_Shift_L, SDL_SCANCODE_LSHIFT }, | ||
| 278 | { KS_Shift_R, SDL_SCANCODE_RSHIFT }, | ||
| 279 | { KS_Alt_L, SDL_SCANCODE_LALT }, | ||
| 280 | { KS_Alt_R, SDL_SCANCODE_RALT }, | ||
| 281 | { KS_grave, SDL_SCANCODE_GRAVE }, | ||
| 282 | |||
| 283 | { KS_KP_0, SDL_SCANCODE_KP_0 }, | ||
| 284 | { KS_KP_1, SDL_SCANCODE_KP_1 }, | ||
| 285 | { KS_KP_2, SDL_SCANCODE_KP_2 }, | ||
| 286 | { KS_KP_3, SDL_SCANCODE_KP_3 }, | ||
| 287 | { KS_KP_4, SDL_SCANCODE_KP_4 }, | ||
| 288 | { KS_KP_5, SDL_SCANCODE_KP_5 }, | ||
| 289 | { KS_KP_6, SDL_SCANCODE_KP_6 }, | ||
| 290 | { KS_KP_7, SDL_SCANCODE_KP_7 }, | ||
| 291 | { KS_KP_8, SDL_SCANCODE_KP_8 }, | ||
| 292 | { KS_KP_9, SDL_SCANCODE_KP_9 }, | ||
| 293 | { KS_KP_Enter, SDL_SCANCODE_KP_ENTER }, | ||
| 294 | { KS_KP_Multiply, SDL_SCANCODE_KP_MULTIPLY }, | ||
| 295 | { KS_KP_Add, SDL_SCANCODE_KP_PLUS }, | ||
| 296 | { KS_KP_Subtract, SDL_SCANCODE_KP_MINUS }, | ||
| 297 | { KS_KP_Divide, SDL_SCANCODE_KP_DIVIDE }, | ||
| 298 | { KS_KP_Up, SDL_SCANCODE_UP }, | ||
| 299 | { KS_KP_Down, SDL_SCANCODE_DOWN }, | ||
| 300 | { KS_KP_Left, SDL_SCANCODE_LEFT }, | ||
| 301 | { KS_KP_Right, SDL_SCANCODE_RIGHT }, | ||
| 302 | { KS_KP_Equal, SDL_SCANCODE_KP_EQUALS }, | ||
| 303 | { KS_f1, SDL_SCANCODE_F1 }, | ||
| 304 | { KS_f2, SDL_SCANCODE_F2 }, | ||
| 305 | { KS_f3, SDL_SCANCODE_F3 }, | ||
| 306 | { KS_f4, SDL_SCANCODE_F4 }, | ||
| 307 | { KS_f5, SDL_SCANCODE_F5 }, | ||
| 308 | { KS_f6, SDL_SCANCODE_F6 }, | ||
| 309 | { KS_f7, SDL_SCANCODE_F7 }, | ||
| 310 | { KS_f8, SDL_SCANCODE_F8 }, | ||
| 311 | { KS_f9, SDL_SCANCODE_F9 }, | ||
| 312 | { KS_f10, SDL_SCANCODE_F10 }, | ||
| 313 | { KS_f11, SDL_SCANCODE_F11 }, | ||
| 314 | { KS_f12, SDL_SCANCODE_F12 }, | ||
| 315 | { KS_f13, SDL_SCANCODE_F13 }, | ||
| 316 | { KS_f14, SDL_SCANCODE_F14 }, | ||
| 317 | { KS_f15, SDL_SCANCODE_F15 }, | ||
| 318 | { KS_f16, SDL_SCANCODE_F16 }, | ||
| 319 | { KS_f17, SDL_SCANCODE_F17 }, | ||
| 320 | { KS_f18, SDL_SCANCODE_F18 }, | ||
| 321 | { KS_f19, SDL_SCANCODE_F19 }, | ||
| 322 | { KS_f20, SDL_SCANCODE_F20 }, | ||
| 323 | #ifndef SDL_PLATFORM_NETBSD | ||
| 324 | { KS_f21, SDL_SCANCODE_F21 }, | ||
| 325 | { KS_f22, SDL_SCANCODE_F22 }, | ||
| 326 | { KS_f23, SDL_SCANCODE_F23 }, | ||
| 327 | { KS_f24, SDL_SCANCODE_F24 }, | ||
| 328 | #endif | ||
| 329 | { KS_Meta_L, SDL_SCANCODE_LGUI }, | ||
| 330 | { KS_Meta_R, SDL_SCANCODE_RGUI }, | ||
| 331 | { KS_Zenkaku_Hankaku, SDL_SCANCODE_LANG5 }, | ||
| 332 | { KS_Hiragana_Katakana, SDL_SCANCODE_INTERNATIONAL2 }, | ||
| 333 | { KS_yen, SDL_SCANCODE_INTERNATIONAL3 }, | ||
| 334 | { KS_Henkan, SDL_SCANCODE_INTERNATIONAL4 }, | ||
| 335 | { KS_Muhenkan, SDL_SCANCODE_INTERNATIONAL5 }, | ||
| 336 | { KS_KP_Prior, SDL_SCANCODE_PRIOR }, | ||
| 337 | |||
| 338 | { KS_a, SDL_SCANCODE_A }, | ||
| 339 | { KS_b, SDL_SCANCODE_B }, | ||
| 340 | { KS_c, SDL_SCANCODE_C }, | ||
| 341 | { KS_d, SDL_SCANCODE_D }, | ||
| 342 | { KS_e, SDL_SCANCODE_E }, | ||
| 343 | { KS_f, SDL_SCANCODE_F }, | ||
| 344 | { KS_g, SDL_SCANCODE_G }, | ||
| 345 | { KS_h, SDL_SCANCODE_H }, | ||
| 346 | { KS_i, SDL_SCANCODE_I }, | ||
| 347 | { KS_j, SDL_SCANCODE_J }, | ||
| 348 | { KS_k, SDL_SCANCODE_K }, | ||
| 349 | { KS_l, SDL_SCANCODE_L }, | ||
| 350 | { KS_m, SDL_SCANCODE_M }, | ||
| 351 | { KS_n, SDL_SCANCODE_N }, | ||
| 352 | { KS_o, SDL_SCANCODE_O }, | ||
| 353 | { KS_p, SDL_SCANCODE_P }, | ||
| 354 | { KS_q, SDL_SCANCODE_Q }, | ||
| 355 | { KS_r, SDL_SCANCODE_R }, | ||
| 356 | { KS_s, SDL_SCANCODE_S }, | ||
| 357 | { KS_t, SDL_SCANCODE_T }, | ||
| 358 | { KS_u, SDL_SCANCODE_U }, | ||
| 359 | { KS_v, SDL_SCANCODE_V }, | ||
| 360 | { KS_w, SDL_SCANCODE_W }, | ||
| 361 | { KS_x, SDL_SCANCODE_X }, | ||
| 362 | { KS_y, SDL_SCANCODE_Y }, | ||
| 363 | { KS_z, SDL_SCANCODE_Z }, | ||
| 364 | |||
| 365 | { KS_0, SDL_SCANCODE_0 }, | ||
| 366 | { KS_1, SDL_SCANCODE_1 }, | ||
| 367 | { KS_2, SDL_SCANCODE_2 }, | ||
| 368 | { KS_3, SDL_SCANCODE_3 }, | ||
| 369 | { KS_4, SDL_SCANCODE_4 }, | ||
| 370 | { KS_5, SDL_SCANCODE_5 }, | ||
| 371 | { KS_6, SDL_SCANCODE_6 }, | ||
| 372 | { KS_7, SDL_SCANCODE_7 }, | ||
| 373 | { KS_8, SDL_SCANCODE_8 }, | ||
| 374 | { KS_9, SDL_SCANCODE_9 }, | ||
| 375 | { KS_minus, SDL_SCANCODE_MINUS }, | ||
| 376 | { KS_equal, SDL_SCANCODE_EQUALS }, | ||
| 377 | { KS_Tab, SDL_SCANCODE_TAB }, | ||
| 378 | { KS_KP_Tab, SDL_SCANCODE_KP_TAB }, | ||
| 379 | { KS_apostrophe, SDL_SCANCODE_APOSTROPHE }, | ||
| 380 | { KS_bracketleft, SDL_SCANCODE_LEFTBRACKET }, | ||
| 381 | { KS_bracketright, SDL_SCANCODE_RIGHTBRACKET }, | ||
| 382 | { KS_semicolon, SDL_SCANCODE_SEMICOLON }, | ||
| 383 | { KS_comma, SDL_SCANCODE_COMMA }, | ||
| 384 | { KS_period, SDL_SCANCODE_PERIOD }, | ||
| 385 | { KS_slash, SDL_SCANCODE_SLASH }, | ||
| 386 | { KS_backslash, SDL_SCANCODE_BACKSLASH } | ||
| 387 | }; | ||
| 388 | |||
| 389 | typedef struct | ||
| 390 | { | ||
| 391 | int fd; | ||
| 392 | SDL_KeyboardID keyboardID; | ||
| 393 | struct wskbd_map_data keymap; | ||
| 394 | int ledstate; | ||
| 395 | int origledstate; | ||
| 396 | int shiftstate[4]; | ||
| 397 | int shiftheldstate[8]; | ||
| 398 | int lockheldstate[5]; | ||
| 399 | kbd_t encoding; | ||
| 400 | char text[128]; | ||
| 401 | unsigned int text_len; | ||
| 402 | keysym_t composebuffer[2]; | ||
| 403 | unsigned char composelen; | ||
| 404 | int type; | ||
| 405 | } SDL_WSCONS_input_data; | ||
| 406 | |||
| 407 | static SDL_WSCONS_input_data *inputs[4] = { NULL, NULL, NULL, NULL }; | ||
| 408 | static SDL_WSCONS_mouse_input_data *mouseInputData = NULL; | ||
| 409 | #define IS_CONTROL_HELD (input->shiftstate[2] > 0) | ||
| 410 | #define IS_ALT_HELD (input->shiftstate[1] > 0) | ||
| 411 | #define IS_SHIFT_HELD ((input->shiftstate[0] > 0) || (input->ledstate & (1 << 5))) | ||
| 412 | |||
| 413 | #define IS_ALTGR_MODE ((input->ledstate & (1 << 4)) || (input->shiftstate[3] > 0)) | ||
| 414 | #define IS_NUMLOCK_ON (input->ledstate & LED_NUM) | ||
| 415 | #define IS_SCROLLLOCK_ON (input->ledstate & LED_SCR) | ||
| 416 | #define IS_CAPSLOCK_ON (input->ledstate & LED_CAP) | ||
| 417 | static SDL_WSCONS_input_data *SDL_WSCONS_Init_Keyboard(const char *dev) | ||
| 418 | { | ||
| 419 | #ifdef WSKBDIO_SETVERSION | ||
| 420 | int version = WSKBDIO_EVENT_VERSION; | ||
| 421 | #endif | ||
| 422 | SDL_WSCONS_input_data *input = (SDL_WSCONS_input_data *)SDL_calloc(1, sizeof(SDL_WSCONS_input_data)); | ||
| 423 | |||
| 424 | if (!input) { | ||
| 425 | return NULL; | ||
| 426 | } | ||
| 427 | |||
| 428 | input->fd = open(dev, O_RDWR | O_NONBLOCK | O_CLOEXEC); | ||
| 429 | if (input->fd == -1) { | ||
| 430 | SDL_free(input); | ||
| 431 | input = NULL; | ||
| 432 | return NULL; | ||
| 433 | } | ||
| 434 | |||
| 435 | input->keyboardID = SDL_GetNextObjectID(); | ||
| 436 | SDL_AddKeyboard(input->keyboardID, NULL, false); | ||
| 437 | |||
| 438 | input->keymap.map = SDL_calloc(KS_NUMKEYCODES, sizeof(struct wscons_keymap)); | ||
| 439 | if (!input->keymap.map) { | ||
| 440 | SDL_free(input); | ||
| 441 | return NULL; | ||
| 442 | } | ||
| 443 | input->keymap.maplen = KS_NUMKEYCODES; | ||
| 444 | RETIFIOCTLERR(ioctl(input->fd, WSKBDIO_GETMAP, &input->keymap)); | ||
| 445 | RETIFIOCTLERR(ioctl(input->fd, WSKBDIO_GETLEDS, &input->ledstate)); | ||
| 446 | input->origledstate = input->ledstate; | ||
| 447 | RETIFIOCTLERR(ioctl(input->fd, WSKBDIO_GETENCODING, &input->encoding)); | ||
| 448 | RETIFIOCTLERR(ioctl(input->fd, WSKBDIO_GTYPE, &input->type)); | ||
| 449 | #ifdef WSKBDIO_SETVERSION | ||
| 450 | RETIFIOCTLERR(ioctl(input->fd, WSKBDIO_SETVERSION, &version)); | ||
| 451 | #endif | ||
| 452 | return input; | ||
| 453 | } | ||
| 454 | |||
| 455 | void SDL_WSCONS_Init(void) | ||
| 456 | { | ||
| 457 | inputs[0] = SDL_WSCONS_Init_Keyboard("/dev/wskbd0"); | ||
| 458 | inputs[1] = SDL_WSCONS_Init_Keyboard("/dev/wskbd1"); | ||
| 459 | inputs[2] = SDL_WSCONS_Init_Keyboard("/dev/wskbd2"); | ||
| 460 | inputs[3] = SDL_WSCONS_Init_Keyboard("/dev/wskbd3"); | ||
| 461 | |||
| 462 | mouseInputData = SDL_WSCONS_Init_Mouse(); | ||
| 463 | return; | ||
| 464 | } | ||
| 465 | |||
| 466 | void SDL_WSCONS_Quit(void) | ||
| 467 | { | ||
| 468 | int i = 0; | ||
| 469 | SDL_WSCONS_input_data *input = NULL; | ||
| 470 | |||
| 471 | SDL_WSCONS_Quit_Mouse(mouseInputData); | ||
| 472 | mouseInputData = NULL; | ||
| 473 | for (i = 0; i < 4; i++) { | ||
| 474 | input = inputs[i]; | ||
| 475 | if (input) { | ||
| 476 | if (input->fd != -1 && input->fd != 0) { | ||
| 477 | ioctl(input->fd, WSKBDIO_SETLEDS, &input->origledstate); | ||
| 478 | close(input->fd); | ||
| 479 | input->fd = -1; | ||
| 480 | } | ||
| 481 | SDL_free(input); | ||
| 482 | input = NULL; | ||
| 483 | } | ||
| 484 | inputs[i] = NULL; | ||
| 485 | } | ||
| 486 | } | ||
| 487 | |||
| 488 | static void put_queue(SDL_WSCONS_input_data *kbd, uint c) | ||
| 489 | { | ||
| 490 | // c is already part of a UTF-8 sequence and safe to add as a character | ||
| 491 | if (kbd->text_len < (sizeof(kbd->text) - 1)) { | ||
| 492 | kbd->text[kbd->text_len++] = (char)(c); | ||
| 493 | } | ||
| 494 | } | ||
| 495 | |||
| 496 | static void put_utf8(SDL_WSCONS_input_data *input, uint c) | ||
| 497 | { | ||
| 498 | if (c < 0x80) | ||
| 499 | /* 0******* */ | ||
| 500 | put_queue(input, c); | ||
| 501 | else if (c < 0x800) { | ||
| 502 | /* 110***** 10****** */ | ||
| 503 | put_queue(input, 0xc0 | (c >> 6)); | ||
| 504 | put_queue(input, 0x80 | (c & 0x3f)); | ||
| 505 | } else if (c < 0x10000) { | ||
| 506 | if (c >= 0xD800 && c <= 0xF500) { | ||
| 507 | return; | ||
| 508 | } | ||
| 509 | if (c == 0xFFFF) { | ||
| 510 | return; | ||
| 511 | } | ||
| 512 | /* 1110**** 10****** 10****** */ | ||
| 513 | put_queue(input, 0xe0 | (c >> 12)); | ||
| 514 | put_queue(input, 0x80 | ((c >> 6) & 0x3f)); | ||
| 515 | put_queue(input, 0x80 | (c & 0x3f)); | ||
| 516 | } else if (c < 0x110000) { | ||
| 517 | /* 11110*** 10****** 10****** 10****** */ | ||
| 518 | put_queue(input, 0xf0 | (c >> 18)); | ||
| 519 | put_queue(input, 0x80 | ((c >> 12) & 0x3f)); | ||
| 520 | put_queue(input, 0x80 | ((c >> 6) & 0x3f)); | ||
| 521 | put_queue(input, 0x80 | (c & 0x3f)); | ||
| 522 | } | ||
| 523 | } | ||
| 524 | |||
| 525 | static void Translate_to_text(SDL_WSCONS_input_data *input, keysym_t ksym) | ||
| 526 | { | ||
| 527 | if (KS_GROUP(ksym) == KS_GROUP_Keypad) { | ||
| 528 | if (SDL_isprint(ksym & 0xFF)) { | ||
| 529 | ksym &= 0xFF; | ||
| 530 | } | ||
| 531 | } | ||
| 532 | switch (ksym) { | ||
| 533 | case KS_Escape: | ||
| 534 | case KS_Delete: | ||
| 535 | case KS_BackSpace: | ||
| 536 | case KS_Return: | ||
| 537 | case KS_Linefeed: | ||
| 538 | // All of these are unprintable characters. Ignore them | ||
| 539 | break; | ||
| 540 | default: | ||
| 541 | put_utf8(input, ksym); | ||
| 542 | break; | ||
| 543 | } | ||
| 544 | if (input->text_len > 0) { | ||
| 545 | input->text[input->text_len] = '\0'; | ||
| 546 | SDL_SendKeyboardText(input->text); | ||
| 547 | // SDL_memset(input->text, 0, sizeof(input->text)); | ||
| 548 | input->text_len = 0; | ||
| 549 | input->text[0] = 0; | ||
| 550 | } | ||
| 551 | } | ||
| 552 | |||
| 553 | static void Translate_to_keycode(SDL_WSCONS_input_data *input, int type, keysym_t ksym, Uint64 timestamp) | ||
| 554 | { | ||
| 555 | struct wscons_keymap keyDesc = input->keymap.map[ksym]; | ||
| 556 | keysym_t *group = &keyDesc.group1[KS_GROUP(keyDesc.group1[0]) == KS_GROUP_Keypad && IS_NUMLOCK_ON ? !IS_SHIFT_HELD : 0]; | ||
| 557 | int i = 0; | ||
| 558 | |||
| 559 | // Check command first, then group[0] | ||
| 560 | switch (keyDesc.command) { | ||
| 561 | case KS_Cmd_ScrollBack: | ||
| 562 | { | ||
| 563 | SDL_SendKeyboardKey(timestamp, input->keyboardID, 0, SDL_SCANCODE_PAGEUP, (type == WSCONS_EVENT_KEY_DOWN)); | ||
| 564 | return; | ||
| 565 | } | ||
| 566 | case KS_Cmd_ScrollFwd: | ||
| 567 | { | ||
| 568 | SDL_SendKeyboardKey(timestamp, input->keyboardID, 0, SDL_SCANCODE_PAGEDOWN, (type == WSCONS_EVENT_KEY_DOWN)); | ||
| 569 | return; | ||
| 570 | } | ||
| 571 | default: | ||
| 572 | break; | ||
| 573 | } | ||
| 574 | for (i = 0; i < SDL_arraysize(conversion_table); i++) { | ||
| 575 | if (conversion_table[i].sourcekey == group[0]) { | ||
| 576 | SDL_SendKeyboardKey(timestamp, input->keyboardID, group[0], conversion_table[i].targetKey, (type == WSCONS_EVENT_KEY_DOWN)); | ||
| 577 | return; | ||
| 578 | } | ||
| 579 | } | ||
| 580 | SDL_SendKeyboardKey(timestamp, input->keyboardID, group[0], SDL_SCANCODE_UNKNOWN, (type == WSCONS_EVENT_KEY_DOWN)); | ||
| 581 | } | ||
| 582 | |||
| 583 | static Uint64 GetEventTimestamp(struct timespec *time) | ||
| 584 | { | ||
| 585 | // FIXME: Get the event time in the SDL tick time base | ||
| 586 | return SDL_GetTicksNS(); | ||
| 587 | } | ||
| 588 | |||
| 589 | static void updateKeyboard(SDL_WSCONS_input_data *input) | ||
| 590 | { | ||
| 591 | struct wscons_event events[64]; | ||
| 592 | int type; | ||
| 593 | int n, i, gindex, acc_i; | ||
| 594 | keysym_t *group; | ||
| 595 | keysym_t ksym, result; | ||
| 596 | |||
| 597 | if (!input) { | ||
| 598 | return; | ||
| 599 | } | ||
| 600 | if ((n = read(input->fd, events, sizeof(events))) > 0) { | ||
| 601 | n /= sizeof(struct wscons_event); | ||
| 602 | for (i = 0; i < n; i++) { | ||
| 603 | Uint64 timestamp = GetEventTimestamp(&events[i].time); | ||
| 604 | type = events[i].type; | ||
| 605 | switch (type) { | ||
| 606 | case WSCONS_EVENT_KEY_DOWN: | ||
| 607 | { | ||
| 608 | switch (input->keymap.map[events[i].value].group1[0]) { | ||
| 609 | case KS_Hold_Screen: | ||
| 610 | { | ||
| 611 | if (input->lockheldstate[0] >= 1) { | ||
| 612 | break; | ||
| 613 | } | ||
| 614 | input->ledstate ^= LED_SCR; | ||
| 615 | ioctl(input->fd, WSKBDIO_SETLEDS, &input->ledstate); | ||
| 616 | input->lockheldstate[0] = 1; | ||
| 617 | break; | ||
| 618 | } | ||
| 619 | case KS_Num_Lock: | ||
| 620 | { | ||
| 621 | if (input->lockheldstate[1] >= 1) { | ||
| 622 | break; | ||
| 623 | } | ||
| 624 | input->ledstate ^= LED_NUM; | ||
| 625 | ioctl(input->fd, WSKBDIO_SETLEDS, &input->ledstate); | ||
| 626 | input->lockheldstate[1] = 1; | ||
| 627 | break; | ||
| 628 | } | ||
| 629 | case KS_Caps_Lock: | ||
| 630 | { | ||
| 631 | if (input->lockheldstate[2] >= 1) { | ||
| 632 | break; | ||
| 633 | } | ||
| 634 | input->ledstate ^= LED_CAP; | ||
| 635 | ioctl(input->fd, WSKBDIO_SETLEDS, &input->ledstate); | ||
| 636 | input->lockheldstate[2] = 1; | ||
| 637 | break; | ||
| 638 | } | ||
| 639 | #ifndef SDL_PLATFORM_NETBSD | ||
| 640 | case KS_Mode_Lock: | ||
| 641 | { | ||
| 642 | if (input->lockheldstate[3] >= 1) { | ||
| 643 | break; | ||
| 644 | } | ||
| 645 | input->ledstate ^= 1 << 4; | ||
| 646 | ioctl(input->fd, WSKBDIO_SETLEDS, &input->ledstate); | ||
| 647 | input->lockheldstate[3] = 1; | ||
| 648 | break; | ||
| 649 | } | ||
| 650 | #endif | ||
| 651 | case KS_Shift_Lock: | ||
| 652 | { | ||
| 653 | if (input->lockheldstate[4] >= 1) { | ||
| 654 | break; | ||
| 655 | } | ||
| 656 | input->ledstate ^= 1 << 5; | ||
| 657 | ioctl(input->fd, WSKBDIO_SETLEDS, &input->ledstate); | ||
| 658 | input->lockheldstate[4] = 1; | ||
| 659 | break; | ||
| 660 | } | ||
| 661 | case KS_Shift_L: | ||
| 662 | { | ||
| 663 | if (input->shiftheldstate[0]) { | ||
| 664 | break; | ||
| 665 | } | ||
| 666 | input->shiftstate[0]++; | ||
| 667 | input->shiftheldstate[0] = 1; | ||
| 668 | break; | ||
| 669 | } | ||
| 670 | case KS_Shift_R: | ||
| 671 | { | ||
| 672 | if (input->shiftheldstate[1]) { | ||
| 673 | break; | ||
| 674 | } | ||
| 675 | input->shiftstate[0]++; | ||
| 676 | input->shiftheldstate[1] = 1; | ||
| 677 | break; | ||
| 678 | } | ||
| 679 | case KS_Alt_L: | ||
| 680 | { | ||
| 681 | if (input->shiftheldstate[2]) { | ||
| 682 | break; | ||
| 683 | } | ||
| 684 | input->shiftstate[1]++; | ||
| 685 | input->shiftheldstate[2] = 1; | ||
| 686 | break; | ||
| 687 | } | ||
| 688 | case KS_Alt_R: | ||
| 689 | { | ||
| 690 | if (input->shiftheldstate[3]) { | ||
| 691 | break; | ||
| 692 | } | ||
| 693 | input->shiftstate[1]++; | ||
| 694 | input->shiftheldstate[3] = 1; | ||
| 695 | break; | ||
| 696 | } | ||
| 697 | case KS_Control_L: | ||
| 698 | { | ||
| 699 | if (input->shiftheldstate[4]) { | ||
| 700 | break; | ||
| 701 | } | ||
| 702 | input->shiftstate[2]++; | ||
| 703 | input->shiftheldstate[4] = 1; | ||
| 704 | break; | ||
| 705 | } | ||
| 706 | case KS_Control_R: | ||
| 707 | { | ||
| 708 | if (input->shiftheldstate[5]) { | ||
| 709 | break; | ||
| 710 | } | ||
| 711 | input->shiftstate[2]++; | ||
| 712 | input->shiftheldstate[5] = 1; | ||
| 713 | break; | ||
| 714 | } | ||
| 715 | case KS_Mode_switch: | ||
| 716 | { | ||
| 717 | if (input->shiftheldstate[6]) { | ||
| 718 | break; | ||
| 719 | } | ||
| 720 | input->shiftstate[3]++; | ||
| 721 | input->shiftheldstate[6] = 1; | ||
| 722 | break; | ||
| 723 | } | ||
| 724 | } | ||
| 725 | } break; | ||
| 726 | case WSCONS_EVENT_KEY_UP: | ||
| 727 | { | ||
| 728 | switch (input->keymap.map[events[i].value].group1[0]) { | ||
| 729 | case KS_Hold_Screen: | ||
| 730 | { | ||
| 731 | if (input->lockheldstate[0]) { | ||
| 732 | input->lockheldstate[0] = 0; | ||
| 733 | } | ||
| 734 | } break; | ||
| 735 | case KS_Num_Lock: | ||
| 736 | { | ||
| 737 | if (input->lockheldstate[1]) { | ||
| 738 | input->lockheldstate[1] = 0; | ||
| 739 | } | ||
| 740 | } break; | ||
| 741 | case KS_Caps_Lock: | ||
| 742 | { | ||
| 743 | if (input->lockheldstate[2]) { | ||
| 744 | input->lockheldstate[2] = 0; | ||
| 745 | } | ||
| 746 | } break; | ||
| 747 | #ifndef SDL_PLATFORM_NETBSD | ||
| 748 | case KS_Mode_Lock: | ||
| 749 | { | ||
| 750 | if (input->lockheldstate[3]) { | ||
| 751 | input->lockheldstate[3] = 0; | ||
| 752 | } | ||
| 753 | } break; | ||
| 754 | #endif | ||
| 755 | case KS_Shift_Lock: | ||
| 756 | { | ||
| 757 | if (input->lockheldstate[4]) { | ||
| 758 | input->lockheldstate[4] = 0; | ||
| 759 | } | ||
| 760 | } break; | ||
| 761 | case KS_Shift_L: | ||
| 762 | { | ||
| 763 | input->shiftheldstate[0] = 0; | ||
| 764 | if (input->shiftstate[0]) { | ||
| 765 | input->shiftstate[0]--; | ||
| 766 | } | ||
| 767 | break; | ||
| 768 | } | ||
| 769 | case KS_Shift_R: | ||
| 770 | { | ||
| 771 | input->shiftheldstate[1] = 0; | ||
| 772 | if (input->shiftstate[0]) { | ||
| 773 | input->shiftstate[0]--; | ||
| 774 | } | ||
| 775 | break; | ||
| 776 | } | ||
| 777 | case KS_Alt_L: | ||
| 778 | { | ||
| 779 | input->shiftheldstate[2] = 0; | ||
| 780 | if (input->shiftstate[1]) { | ||
| 781 | input->shiftstate[1]--; | ||
| 782 | } | ||
| 783 | break; | ||
| 784 | } | ||
| 785 | case KS_Alt_R: | ||
| 786 | { | ||
| 787 | input->shiftheldstate[3] = 0; | ||
| 788 | if (input->shiftstate[1]) { | ||
| 789 | input->shiftstate[1]--; | ||
| 790 | } | ||
| 791 | break; | ||
| 792 | } | ||
| 793 | case KS_Control_L: | ||
| 794 | { | ||
| 795 | input->shiftheldstate[4] = 0; | ||
| 796 | if (input->shiftstate[2]) { | ||
| 797 | input->shiftstate[2]--; | ||
| 798 | } | ||
| 799 | break; | ||
| 800 | } | ||
| 801 | case KS_Control_R: | ||
| 802 | { | ||
| 803 | input->shiftheldstate[5] = 0; | ||
| 804 | if (input->shiftstate[2]) { | ||
| 805 | input->shiftstate[2]--; | ||
| 806 | } | ||
| 807 | break; | ||
| 808 | } | ||
| 809 | case KS_Mode_switch: | ||
| 810 | { | ||
| 811 | input->shiftheldstate[6] = 0; | ||
| 812 | if (input->shiftstate[3]) { | ||
| 813 | input->shiftstate[3]--; | ||
| 814 | } | ||
| 815 | break; | ||
| 816 | } | ||
| 817 | } | ||
| 818 | } break; | ||
| 819 | case WSCONS_EVENT_ALL_KEYS_UP: | ||
| 820 | for (i = 0; i < SDL_SCANCODE_COUNT; i++) { | ||
| 821 | SDL_SendKeyboardKey(timestamp, input->keyboardID, 0, (SDL_Scancode)i, false); | ||
| 822 | } | ||
| 823 | break; | ||
| 824 | default: | ||
| 825 | break; | ||
| 826 | } | ||
| 827 | |||
| 828 | if (input->type == WSKBD_TYPE_USB && events[i].value <= 0xE7) { | ||
| 829 | SDL_SendKeyboardKey(timestamp, input->keyboardID, 0, (SDL_Scancode)events[i].value, (type == WSCONS_EVENT_KEY_DOWN)); | ||
| 830 | } else { | ||
| 831 | Translate_to_keycode(input, type, events[i].value, timestamp); | ||
| 832 | } | ||
| 833 | |||
| 834 | if (type == WSCONS_EVENT_KEY_UP) { | ||
| 835 | continue; | ||
| 836 | } | ||
| 837 | |||
| 838 | if (IS_ALTGR_MODE && !IS_CONTROL_HELD) | ||
| 839 | group = &input->keymap.map[events[i].value].group2[0]; | ||
| 840 | else | ||
| 841 | group = &input->keymap.map[events[i].value].group1[0]; | ||
| 842 | |||
| 843 | if (IS_NUMLOCK_ON && KS_GROUP(group[1]) == KS_GROUP_Keypad) { | ||
| 844 | gindex = !IS_SHIFT_HELD; | ||
| 845 | ksym = group[gindex]; | ||
| 846 | } else { | ||
| 847 | if (IS_CAPSLOCK_ON && !IS_SHIFT_HELD) { | ||
| 848 | gindex = 0; | ||
| 849 | ksym = ksym_upcase(group[0]); | ||
| 850 | } else { | ||
| 851 | gindex = IS_SHIFT_HELD; | ||
| 852 | ksym = group[gindex]; | ||
| 853 | } | ||
| 854 | } | ||
| 855 | result = KS_voidSymbol; | ||
| 856 | |||
| 857 | switch (KS_GROUP(ksym)) { | ||
| 858 | case KS_GROUP_Ascii: | ||
| 859 | case KS_GROUP_Keypad: | ||
| 860 | case KS_GROUP_Function: | ||
| 861 | result = ksym; | ||
| 862 | break; | ||
| 863 | case KS_GROUP_Mod: | ||
| 864 | if (ksym == KS_Multi_key) { | ||
| 865 | input->ledstate |= WSKBD_LED_COMPOSE; | ||
| 866 | ioctl(input->fd, WSKBDIO_SETLEDS, &input->ledstate); | ||
| 867 | input->composelen = 2; | ||
| 868 | input->composebuffer[0] = input->composebuffer[1] = 0; | ||
| 869 | } | ||
| 870 | break; | ||
| 871 | case KS_GROUP_Dead: | ||
| 872 | if (input->composelen == 0) { | ||
| 873 | input->ledstate |= WSKBD_LED_COMPOSE; | ||
| 874 | ioctl(input->fd, WSKBDIO_SETLEDS, &input->ledstate); | ||
| 875 | input->composelen = 1; | ||
| 876 | input->composebuffer[0] = ksym; | ||
| 877 | input->composebuffer[1] = 0; | ||
| 878 | } else | ||
| 879 | result = ksym; | ||
| 880 | break; | ||
| 881 | } | ||
| 882 | if (result == KS_voidSymbol) { | ||
| 883 | continue; | ||
| 884 | } | ||
| 885 | |||
| 886 | if (input->composelen > 0) { | ||
| 887 | if (input->composelen == 2 && group == &input->keymap.map[events[i].value].group2[0]) { | ||
| 888 | if (input->keymap.map[events[i].value].group2[gindex] == input->keymap.map[events[i].value].group1[gindex]) { | ||
| 889 | input->composelen = 0; | ||
| 890 | input->composebuffer[0] = input->composebuffer[1] = 0; | ||
| 891 | } | ||
| 892 | } | ||
| 893 | |||
| 894 | if (input->composelen != 0) { | ||
| 895 | input->composebuffer[2 - input->composelen] = result; | ||
| 896 | if (--input->composelen == 0) { | ||
| 897 | result = KS_voidSymbol; | ||
| 898 | input->ledstate &= ~WSKBD_LED_COMPOSE; | ||
| 899 | ioctl(input->fd, WSKBDIO_SETLEDS, &input->ledstate); | ||
| 900 | for (acc_i = 0; acc_i < SDL_arraysize(compose_tab); acc_i++) { | ||
| 901 | if ((compose_tab[acc_i].elem[0] == input->composebuffer[0] && compose_tab[acc_i].elem[1] == input->composebuffer[1]) || (compose_tab[acc_i].elem[0] == input->composebuffer[1] && compose_tab[acc_i].elem[1] == input->composebuffer[0])) { | ||
| 902 | result = compose_tab[acc_i].result; | ||
| 903 | break; | ||
| 904 | } | ||
| 905 | } | ||
| 906 | } else | ||
| 907 | continue; | ||
| 908 | } | ||
| 909 | } | ||
| 910 | |||
| 911 | if (KS_GROUP(result) == KS_GROUP_Ascii) { | ||
| 912 | if (IS_CONTROL_HELD) { | ||
| 913 | if ((result >= KS_at && result <= KS_z) || result == KS_space) { | ||
| 914 | result = result & 0x1f; | ||
| 915 | } else if (result == KS_2) { | ||
| 916 | result = 0x00; | ||
| 917 | } else if (result >= KS_3 && result <= KS_7) { | ||
| 918 | result = KS_Escape + (result - KS_3); | ||
| 919 | } else if (result == KS_8) { | ||
| 920 | result = KS_Delete; | ||
| 921 | } | ||
| 922 | } | ||
| 923 | if (IS_ALT_HELD) { | ||
| 924 | if (input->encoding & KB_METAESC) { | ||
| 925 | Translate_to_keycode(input, WSCONS_EVENT_KEY_DOWN, KS_Escape, 0); | ||
| 926 | Translate_to_text(input, result); | ||
| 927 | continue; | ||
| 928 | } else { | ||
| 929 | result |= 0x80; | ||
| 930 | } | ||
| 931 | } | ||
| 932 | } | ||
| 933 | Translate_to_text(input, result); | ||
| 934 | continue; | ||
| 935 | } | ||
| 936 | } | ||
| 937 | } | ||
| 938 | |||
| 939 | void SDL_WSCONS_PumpEvents(void) | ||
| 940 | { | ||
| 941 | int i = 0; | ||
| 942 | for (i = 0; i < 4; i++) { | ||
| 943 | updateKeyboard(inputs[i]); | ||
| 944 | } | ||
| 945 | if (mouseInputData) { | ||
| 946 | updateMouse(mouseInputData); | ||
| 947 | } | ||
| 948 | } | ||
diff --git a/contrib/SDL-3.2.8/src/core/openbsd/SDL_wscons_mouse.c b/contrib/SDL-3.2.8/src/core/openbsd/SDL_wscons_mouse.c new file mode 100644 index 0000000..51195f3 --- /dev/null +++ b/contrib/SDL-3.2.8/src/core/openbsd/SDL_wscons_mouse.c | |||
| @@ -0,0 +1,127 @@ | |||
| 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 | #include <sys/time.h> | ||
| 24 | #include <dev/wscons/wsconsio.h> | ||
| 25 | #include <unistd.h> | ||
| 26 | #include <sys/ioctl.h> | ||
| 27 | #include <stdlib.h> | ||
| 28 | #include <fcntl.h> | ||
| 29 | |||
| 30 | #include "../../events/SDL_mouse_c.h" | ||
| 31 | |||
| 32 | typedef struct SDL_WSCONS_mouse_input_data | ||
| 33 | { | ||
| 34 | int fd; | ||
| 35 | SDL_MouseID mouseID; | ||
| 36 | } SDL_WSCONS_mouse_input_data; | ||
| 37 | |||
| 38 | SDL_WSCONS_mouse_input_data *SDL_WSCONS_Init_Mouse(void) | ||
| 39 | { | ||
| 40 | #ifdef WSMOUSEIO_SETVERSION | ||
| 41 | int version = WSMOUSE_EVENT_VERSION; | ||
| 42 | #endif | ||
| 43 | SDL_WSCONS_mouse_input_data *input = SDL_calloc(1, sizeof(SDL_WSCONS_mouse_input_data)); | ||
| 44 | |||
| 45 | if (!input) { | ||
| 46 | return NULL; | ||
| 47 | } | ||
| 48 | input->fd = open("/dev/wsmouse", O_RDWR | O_NONBLOCK | O_CLOEXEC); | ||
| 49 | if (input->fd == -1) { | ||
| 50 | SDL_free(input); | ||
| 51 | return NULL; | ||
| 52 | } | ||
| 53 | |||
| 54 | input->mouseID = SDL_GetNextObjectID(); | ||
| 55 | SDL_AddMouse(input->mouseID, NULL, false); | ||
| 56 | |||
| 57 | #ifdef WSMOUSEIO_SETMODE | ||
| 58 | ioctl(input->fd, WSMOUSEIO_SETMODE, WSMOUSE_COMPAT); | ||
| 59 | #endif | ||
| 60 | #ifdef WSMOUSEIO_SETVERSION | ||
| 61 | ioctl(input->fd, WSMOUSEIO_SETVERSION, &version); | ||
| 62 | #endif | ||
| 63 | return input; | ||
| 64 | } | ||
| 65 | |||
| 66 | static Uint64 GetEventTimestamp(struct timespec *time) | ||
| 67 | { | ||
| 68 | // FIXME: Get the event time in the SDL tick time base | ||
| 69 | return SDL_GetTicksNS(); | ||
| 70 | } | ||
| 71 | |||
| 72 | void updateMouse(SDL_WSCONS_mouse_input_data *input) | ||
| 73 | { | ||
| 74 | struct wscons_event events[64]; | ||
| 75 | int n; | ||
| 76 | SDL_Mouse *mouse = SDL_GetMouse(); | ||
| 77 | |||
| 78 | if ((n = read(input->fd, events, sizeof(events))) > 0) { | ||
| 79 | int i; | ||
| 80 | n /= sizeof(struct wscons_event); | ||
| 81 | for (i = 0; i < n; i++) { | ||
| 82 | Uint64 timestamp = GetEventTimestamp(&events[i].time); | ||
| 83 | int type = events[i].type; | ||
| 84 | switch (type) { | ||
| 85 | case WSCONS_EVENT_MOUSE_DOWN: | ||
| 86 | case WSCONS_EVENT_MOUSE_UP: | ||
| 87 | { | ||
| 88 | Uint8 button = SDL_BUTTON_LEFT + events[i].value; | ||
| 89 | bool down = (type == WSCONS_EVENT_MOUSE_DOWN); | ||
| 90 | SDL_SendMouseButton(timestamp, mouse->focus, input->mouseID, button, down); | ||
| 91 | break; | ||
| 92 | } | ||
| 93 | case WSCONS_EVENT_MOUSE_DELTA_X: | ||
| 94 | { | ||
| 95 | SDL_SendMouseMotion(timestamp, mouse->focus, input->mouseID, true, (float)events[i].value, 0.0f); | ||
| 96 | break; | ||
| 97 | } | ||
| 98 | case WSCONS_EVENT_MOUSE_DELTA_Y: | ||
| 99 | { | ||
| 100 | SDL_SendMouseMotion(timestamp, mouse->focus, input->mouseID, true, 0.0f, -(float)events[i].value); | ||
| 101 | break; | ||
| 102 | } | ||
| 103 | case WSCONS_EVENT_MOUSE_DELTA_W: | ||
| 104 | { | ||
| 105 | SDL_SendMouseWheel(timestamp, mouse->focus, input->mouseID, events[i].value, 0, SDL_MOUSEWHEEL_NORMAL); | ||
| 106 | break; | ||
| 107 | } | ||
| 108 | case WSCONS_EVENT_MOUSE_DELTA_Z: | ||
| 109 | { | ||
| 110 | SDL_SendMouseWheel(timestamp, mouse->focus, input->mouseID, 0, -events[i].value, SDL_MOUSEWHEEL_NORMAL); | ||
| 111 | break; | ||
| 112 | } | ||
| 113 | default: | ||
| 114 | break; | ||
| 115 | } | ||
| 116 | } | ||
| 117 | } | ||
| 118 | } | ||
| 119 | |||
| 120 | void SDL_WSCONS_Quit_Mouse(SDL_WSCONS_mouse_input_data *input) | ||
| 121 | { | ||
| 122 | if (!input) { | ||
| 123 | return; | ||
| 124 | } | ||
| 125 | close(input->fd); | ||
| 126 | SDL_free(input); | ||
| 127 | } | ||
