This repository has been archived by the owner on Feb 11, 2021. It is now read-only.
/
SDL_x11keyboard.c
294 lines (262 loc) · 8.61 KB
1
2
/*
SDL - Simple DirectMedia Layer
3
Copyright (C) 1997-2011 Sam Lantinga
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Sam Lantinga
slouken@libsdl.org
*/
#include "SDL_config.h"
24
25
#if SDL_VIDEO_DRIVER_X11
26
27
28
#include "SDL_x11video.h"
#include "../../events/SDL_keyboard_c.h"
29
30
#include "../../events/scancodes_darwin.h"
#include "../../events/scancodes_xfree86.h"
31
32
33
34
35
#include <X11/keysym.h>
#include "imKStoUCS.h"
36
/* *INDENT-OFF* */
37
static const struct {
38
KeySym keysym;
39
SDL_Keycode sdlkey;
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
} KeySymToSDLKey[] = {
{ XK_Return, SDLK_RETURN },
{ XK_Escape, SDLK_ESCAPE },
{ XK_BackSpace, SDLK_BACKSPACE },
{ XK_Tab, SDLK_TAB },
{ XK_Caps_Lock, SDLK_CAPSLOCK },
{ XK_F1, SDLK_F1 },
{ XK_F2, SDLK_F2 },
{ XK_F3, SDLK_F3 },
{ XK_F4, SDLK_F4 },
{ XK_F5, SDLK_F5 },
{ XK_F6, SDLK_F6 },
{ XK_F7, SDLK_F7 },
{ XK_F8, SDLK_F8 },
{ XK_F9, SDLK_F9 },
{ XK_F10, SDLK_F10 },
{ XK_F11, SDLK_F11 },
{ XK_F12, SDLK_F12 },
{ XK_Print, SDLK_PRINTSCREEN },
{ XK_Scroll_Lock, SDLK_SCROLLLOCK },
{ XK_Pause, SDLK_PAUSE },
{ XK_Insert, SDLK_INSERT },
{ XK_Home, SDLK_HOME },
{ XK_Prior, SDLK_PAGEUP },
{ XK_Delete, SDLK_DELETE },
{ XK_End, SDLK_END },
{ XK_Next, SDLK_PAGEDOWN },
{ XK_Right, SDLK_RIGHT },
{ XK_Left, SDLK_LEFT },
{ XK_Down, SDLK_DOWN },
{ XK_Up, SDLK_UP },
{ XK_Num_Lock, SDLK_NUMLOCKCLEAR },
{ XK_KP_Divide, SDLK_KP_DIVIDE },
{ XK_KP_Multiply, SDLK_KP_MULTIPLY },
{ XK_KP_Subtract, SDLK_KP_MINUS },
{ XK_KP_Add, SDLK_KP_PLUS },
{ XK_KP_Enter, SDLK_KP_ENTER },
{ XK_KP_Delete, SDLK_KP_PERIOD },
{ XK_KP_End, SDLK_KP_1 },
{ XK_KP_Down, SDLK_KP_2 },
{ XK_KP_Next, SDLK_KP_3 },
{ XK_KP_Left, SDLK_KP_4 },
{ XK_KP_Begin, SDLK_KP_5 },
{ XK_KP_Right, SDLK_KP_6 },
{ XK_KP_Home, SDLK_KP_7 },
{ XK_KP_Up, SDLK_KP_8 },
{ XK_KP_Prior, SDLK_KP_9 },
{ XK_KP_Insert, SDLK_KP_0 },
{ XK_KP_Decimal, SDLK_KP_PERIOD },
{ XK_KP_1, SDLK_KP_1 },
{ XK_KP_2, SDLK_KP_2 },
{ XK_KP_3, SDLK_KP_3 },
{ XK_KP_4, SDLK_KP_4 },
{ XK_KP_5, SDLK_KP_5 },
{ XK_KP_6, SDLK_KP_6 },
{ XK_KP_7, SDLK_KP_7 },
{ XK_KP_8, SDLK_KP_8 },
{ XK_KP_9, SDLK_KP_9 },
{ XK_KP_0, SDLK_KP_0 },
{ XK_KP_Decimal, SDLK_KP_PERIOD },
{ XK_Hyper_R, SDLK_APPLICATION },
{ XK_KP_Equal, SDLK_KP_EQUALS },
{ XK_F13, SDLK_F13 },
{ XK_F14, SDLK_F14 },
{ XK_F15, SDLK_F15 },
{ XK_F16, SDLK_F16 },
{ XK_F17, SDLK_F17 },
{ XK_F18, SDLK_F18 },
{ XK_F19, SDLK_F19 },
{ XK_F20, SDLK_F20 },
{ XK_F21, SDLK_F21 },
{ XK_F22, SDLK_F22 },
{ XK_F23, SDLK_F23 },
{ XK_F24, SDLK_F24 },
{ XK_Execute, SDLK_EXECUTE },
{ XK_Help, SDLK_HELP },
{ XK_Menu, SDLK_MENU },
{ XK_Select, SDLK_SELECT },
{ XK_Cancel, SDLK_STOP },
{ XK_Redo, SDLK_AGAIN },
{ XK_Undo, SDLK_UNDO },
{ XK_Find, SDLK_FIND },
{ XK_KP_Separator, SDLK_KP_COMMA },
{ XK_Sys_Req, SDLK_SYSREQ },
{ XK_Control_L, SDLK_LCTRL },
{ XK_Shift_L, SDLK_LSHIFT },
{ XK_Alt_L, SDLK_LALT },
{ XK_Meta_L, SDLK_LGUI },
{ XK_Super_L, SDLK_LGUI },
{ XK_Control_R, SDLK_RCTRL },
{ XK_Shift_R, SDLK_RSHIFT },
{ XK_Alt_R, SDLK_RALT },
{ XK_Meta_R, SDLK_RGUI },
{ XK_Super_R, SDLK_RGUI },
{ XK_Mode_switch, SDLK_MODE },
135
136
};
137
static const struct
138
{
139
const SDL_Scancode const *table;
140
141
int table_size;
} scancode_set[] = {
142
143
{ darwin_scancode_table, SDL_arraysize(darwin_scancode_table) },
{ xfree86_scancode_table, SDL_arraysize(xfree86_scancode_table) },
144
{ xfree86_scancode_table2, SDL_arraysize(xfree86_scancode_table2) },
145
146
};
/* *INDENT-OFF* */
147
148
static SDL_Keycode
149
150
151
152
153
154
155
156
157
158
159
160
161
X11_KeyCodeToSDLKey(Display *display, KeyCode keycode)
{
KeySym keysym;
unsigned int ucs4;
int i;
keysym = XKeycodeToKeysym(display, keycode, 0);
if (keysym == NoSymbol) {
return SDLK_UNKNOWN;
}
ucs4 = X11_KeySymToUcs4(keysym);
if (ucs4) {
162
return (SDL_Keycode) ucs4;
163
164
165
166
167
168
169
170
171
172
}
for (i = 0; i < SDL_arraysize(KeySymToSDLKey); ++i) {
if (keysym == KeySymToSDLKey[i].keysym) {
return KeySymToSDLKey[i].sdlkey;
}
}
return SDLK_UNKNOWN;
}
173
int
174
175
176
X11_InitKeyboard(_THIS)
{
SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
177
178
int i, j;
int min_keycode, max_keycode;
179
struct {
180
SDL_Scancode scancode;
181
182
183
184
185
186
KeySym keysym;
int value;
} fingerprint[] = {
{ SDL_SCANCODE_HOME, XK_Home, 0 },
{ SDL_SCANCODE_PAGEUP, XK_Prior, 0 },
{ SDL_SCANCODE_PAGEDOWN, XK_Next, 0 },
187
};
188
SDL_bool fingerprint_detected;
189
190
XAutoRepeatOn(data->display);
191
192
193
194
/* Try to determine which scancodes are being used based on fingerprint */
fingerprint_detected = SDL_FALSE;
XDisplayKeycodes(data->display, &min_keycode, &max_keycode);
195
196
197
for (i = 0; i < SDL_arraysize(fingerprint); ++i) {
fingerprint[i].value =
XKeysymToKeycode(data->display, fingerprint[i].keysym) -
198
199
200
201
202
203
204
205
min_keycode;
}
for (i = 0; i < SDL_arraysize(scancode_set); ++i) {
/* Make sure the scancode set isn't too big */
if ((max_keycode - min_keycode + 1) <= scancode_set[i].table_size) {
continue;
}
for (j = 0; j < SDL_arraysize(fingerprint); ++j) {
206
207
if (fingerprint[j].value < 0
|| fingerprint[j].value >= scancode_set[i].table_size) {
208
209
break;
}
210
211
if (scancode_set[i].table[fingerprint[j].value] !=
fingerprint[j].scancode) {
212
213
214
break;
}
}
215
if (j == SDL_arraysize(fingerprint)) {
216
217
218
#ifdef DEBUG_KEYBOARD
printf("Using scancode set %d, min_keycode = %d, max_keycode = %d, table_size = %d\n", i, min_keycode, max_keycode, scancode_set[i].table_size);
#endif
219
SDL_memcpy(&data->key_layout[min_keycode], scancode_set[i].table,
220
sizeof(SDL_Scancode) * scancode_set[i].table_size);
221
222
fingerprint_detected = SDL_TRUE;
break;
223
224
225
}
}
226
if (!fingerprint_detected) {
227
SDL_Keycode keymap[SDL_NUM_SCANCODES];
228
229
230
231
232
printf
("Keyboard layout unknown, please send the following to the SDL mailing list (sdl@libsdl.org):\n");
/* Determine key_layout - only works on US QWERTY layout */
233
SDL_GetDefaultKeymap(keymap);
234
235
236
for (i = min_keycode; i <= max_keycode; ++i) {
KeySym sym;
sym = XKeycodeToKeysym(data->display, i, 0);
237
if (sym != NoSymbol) {
238
SDL_Keycode key;
239
240
printf("code = %d, sym = 0x%X (%s) ", i - min_keycode,
(unsigned int) sym, XKeysymToString(sym));
241
242
243
key = X11_KeyCodeToSDLKey(data->display, i);
for (j = 0; j < SDL_arraysize(keymap); ++j) {
if (keymap[j] == key) {
244
data->key_layout[i] = (SDL_Scancode) j;
245
246
247
break;
}
}
248
if (j == SDL_arraysize(keymap)) {
249
250
251
252
printf("scancode not found\n");
} else {
printf("scancode = %d (%s)\n", j, SDL_GetScancodeName(j));
}
253
254
255
}
}
}
256
257
X11_UpdateKeymap(_this);
258
259
SDL_SetScancodeName(SDL_SCANCODE_APPLICATION, "Menu");
260
261
262
263
return 0;
}
264
265
void
X11_UpdateKeymap(_THIS)
266
267
{
SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
268
int i;
269
SDL_Scancode scancode;
270
SDL_Keycode keymap[SDL_NUM_SCANCODES];
271
272
SDL_zero(keymap);
273
274
for (i = 0; i < SDL_arraysize(data->key_layout); i++) {
275
276
/* Make sure this is a valid scancode */
277
scancode = data->key_layout[i];
278
if (scancode == SDL_SCANCODE_UNKNOWN) {
279
280
continue;
}
281
282
keymap[scancode] = X11_KeyCodeToSDLKey(data->display, (KeyCode)i);
283
}
284
SDL_SetKeymap(0, keymap, SDL_NUM_SCANCODES);
285
286
287
288
289
290
291
}
void
X11_QuitKeyboard(_THIS)
{
}
292
293
#endif /* SDL_VIDEO_DRIVER_X11 */
294
/* vi: set ts=4 sw=4 expandtab: */