This repository has been archived by the owner on Feb 11, 2021. It is now read-only.
/
SDL_keyboard.c
492 lines (432 loc) · 12.4 KB
1
2
/*
SDL - Simple DirectMedia Layer
3
Copyright (C) 1997-2006 Sam Lantinga
4
5
This library is free software; you can redistribute it and/or
6
modify it under the terms of the GNU Lesser General Public
7
License as published by the Free Software Foundation; either
8
version 2.1 of the License, or (at your option) any later version.
9
10
11
12
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
13
Lesser General Public License for more details.
14
15
16
17
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
18
19
Sam Lantinga
20
slouken@libsdl.org
21
*/
22
#include "SDL_config.h"
23
24
25
26
/* General keyboard handling code for SDL */
#include "SDL_timer.h"
27
#include "SDL_events.h"
28
29
#include "SDL_events_c.h"
#include "SDL_sysevents.h"
30
#include "SDL_keynames.h"
31
32
33
/* Global keyboard information */
34
int SDL_TranslateUNICODE = 0;
35
36
37
static int SDL_num_keyboards;
static int SDL_current_keyboard;
static SDL_Keyboard **SDL_keyboards;
38
39
40
41
42
43
44
45
46
47
/* Public functions */
int
SDL_KeyboardInit(void)
{
/* Set default mode of UNICODE translation */
SDL_EnableUNICODE(DEFAULT_UNICODE_TRANSLATION);
return (0);
}
48
49
50
51
52
53
54
55
56
SDL_Keyboard *
SDL_GetKeyboard(int index)
{
if (index < 0 || index >= SDL_num_keyboards) {
return NULL;
}
return SDL_keyboards[index];
}
57
58
59
int
SDL_AddKeyboard(const SDL_Keyboard * keyboard, int index)
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
SDL_Keyboard **keyboards;
/* Add the keyboard to the list of keyboards */
if (index < 0 || index >= SDL_num_keyboards || SDL_keyboards[index]) {
keyboards =
(SDL_Keyboard **) SDL_realloc(SDL_keyboards,
(SDL_num_keyboards +
1) * sizeof(*keyboards));
if (!keyboards) {
SDL_OutOfMemory();
return -1;
}
SDL_keyboards = keyboards;
index = SDL_num_keyboards++;
}
SDL_keyboards[index] =
(SDL_Keyboard *) SDL_malloc(sizeof(*SDL_keyboards[index]));
if (!SDL_keyboards[index]) {
SDL_OutOfMemory();
return -1;
}
*SDL_keyboards[index] = *keyboard;
return index;
86
}
87
88
89
void
SDL_DelKeyboard(int index)
90
{
91
92
93
94
95
96
97
98
99
100
101
102
SDL_Keyboard *keyboard = SDL_GetKeyboard(index);
if (!keyboard) {
return;
}
if (keyboard->FreeKeyboard) {
keyboard->FreeKeyboard(keyboard);
}
SDL_free(keyboard);
SDL_keyboards[index] = NULL;
103
}
104
105
106
void
SDL_ResetKeyboard(int index)
107
{
108
SDL_Keyboard *keyboard = SDL_GetKeyboard(index);
109
int key;
110
111
112
113
114
115
116
if (!keyboard) {
return;
}
for (key = SDLK_FIRST; key < SDLK_LAST; ++key) {
if (keyboard->keystate[key] == SDL_PRESSED) {
117
118
SDL_SendKeyboardKey(index, SDL_RELEASED, 0,
key | SDL_KEY_CAN_BE_PHYSICAL_BIT);
119
120
}
}
121
122
}
123
124
void
SDL_KeyboardQuit(void)
125
{
126
127
128
129
130
131
132
133
134
135
136
137
138
int i;
for (i = 0; i < SDL_num_keyboards; ++i) {
SDL_DelKeyboard(i);
}
SDL_num_keyboards = 0;
SDL_current_keyboard = 0;
if (SDL_keyboards) {
SDL_free(SDL_keyboards);
SDL_keyboards = NULL;
}
}
139
140
141
142
143
int
SDL_GetNumKeyboards(void)
{
return SDL_num_keyboards;
144
145
}
146
147
int
SDL_SelectKeyboard(int index)
148
{
149
150
151
152
if (index >= 0 && index < SDL_num_keyboards) {
SDL_current_keyboard = index;
}
return SDL_current_keyboard;
153
}
154
155
156
int
SDL_EnableUNICODE(int enable)
157
{
158
159
160
161
162
163
164
int old_mode;
old_mode = SDL_TranslateUNICODE;
if (enable >= 0) {
SDL_TranslateUNICODE = enable;
}
return (old_mode);
165
}
166
167
168
Uint8 *
SDL_GetKeyState(int *numkeys)
169
{
170
171
172
173
174
175
176
177
178
179
SDL_Keyboard *keyboard = SDL_GetKeyboard(SDL_current_keyboard);
if (numkeys != (int *) 0) {
*numkeys = SDLK_LAST;
}
if (!keyboard) {
return NULL;
}
return keyboard->keystate;
180
181
}
182
183
SDLMod
SDL_GetModState(void)
184
{
185
186
187
188
189
190
SDL_Keyboard *keyboard = SDL_GetKeyboard(SDL_current_keyboard);
if (!keyboard) {
return KMOD_NONE;
}
return keyboard->modstate;
191
192
}
193
194
void
SDL_SetModState(SDLMod modstate)
195
{
196
SDL_Keyboard *keyboard = SDL_GetKeyboard(SDL_current_keyboard);
197
198
199
200
201
202
203
if (!keyboard) {
return;
}
keyboard->modstate = modstate;
}
204
205
206
207
208
209
210
211
212
213
214
215
SDLKey
SDL_GetLayoutKey(SDLKey physicalKey)
{
SDL_VideoDevice *_this = SDL_GetVideoDevice();
if (_this && _this->GetLayoutKey) {
return _this->GetLayoutKey(_this, physicalKey)
| (physicalKey & SDL_KEY_KEYPAD_BIT);
} else {
return physicalKey;
}
}
216
const char *
217
SDL_GetKeyName(SDLKey layoutKey)
218
{
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
const char *keyname = NULL;
if ((layoutKey & SDL_KEY_LAYOUT_SPECIAL_BIT) != 0) {
SDL_VideoDevice *_this = SDL_GetVideoDevice();
if (_this && _this->GetSpecialKeyName) {
keyname = _this->GetSpecialKeyName(_this, layoutKey);
}
} else if ((layoutKey & SDL_KEY_CAN_BE_PHYSICAL_BIT) == 0) {
/* SDLK_INDEX(layoutKey) is the unicode code point of the character generated by the key */
static char buffer[9]; /* 6 (maximal UTF-8 char length) + 2 ([] for keypad) + 1 (null teminator) */
char *bufferPtr = &buffer[1];
SDL_iconv_t cd;
size_t inbytesleft = 4, outbytesleft = 8;
Uint32 codepoint = SDLK_INDEX(layoutKey);
const char *codepointPtr = (const char *) &codepoint;
/* 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 (codepoint >= 'a' && codepoint <= 'z') {
codepoint -= 32;
}
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
cd = SDL_iconv_open("UTF-8", "UCS-4");
if (cd == (SDL_iconv_t) (-1))
return "";
SDL_iconv(cd, &codepointPtr, &inbytesleft, &bufferPtr, &outbytesleft);
SDL_iconv_close(cd);
*bufferPtr = '\0';
if ((layoutKey & SDL_KEY_KEYPAD_BIT) != 0) {
buffer[0] = '[';
*bufferPtr++ = ']';
*bufferPtr = '\0';
keyname = buffer;
} else {
keyname = &buffer[1];
}
255
} else {
256
257
258
259
/* SDLK_INDEX(layoutKey) is a physical key number */
if (SDLK_INDEX(layoutKey) < SDL_arraysize(SDL_keynames)) {
keyname = SDL_keynames[SDLK_INDEX(layoutKey)];
}
260
}
261
262
if (keyname == NULL) {
263
keyname = SDL_keynames[SDLK_INDEX(SDLK_UNKNOWN)];
264
}
265
266
267
268
return keyname;
}
269
270
271
272
273
274
275
276
277
void
SDL_SetKeyName(SDLKey physicalKey, const char *name)
{
physicalKey = SDLK_INDEX(physicalKey);
if (physicalKey < SDL_arraysize(SDL_keynames)) {
SDL_keynames[physicalKey] = name;
}
}
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
void
SDL_SetKeyboardFocus(int index, SDL_WindowID windowID)
{
SDL_Keyboard *keyboard = SDL_GetKeyboard(index);
int i;
SDL_bool focus;
if (!keyboard || (keyboard->focus == windowID)) {
return;
}
/* See if the current window has lost focus */
if (keyboard->focus) {
focus = SDL_FALSE;
for (i = 0; i < SDL_num_keyboards; ++i) {
SDL_Keyboard *check;
if (i != index) {
check = SDL_GetKeyboard(i);
if (check && check->focus == keyboard->focus) {
focus = SDL_TRUE;
break;
}
}
}
if (!focus) {
SDL_SendWindowEvent(keyboard->focus, SDL_WINDOWEVENT_FOCUS_LOST,
0, 0);
}
}
keyboard->focus = windowID;
if (keyboard->focus) {
focus = SDL_FALSE;
for (i = 0; i < SDL_num_keyboards; ++i) {
SDL_Keyboard *check;
if (i != index) {
check = SDL_GetKeyboard(i);
if (check && check->focus == keyboard->focus) {
focus = SDL_TRUE;
break;
}
}
}
if (!focus) {
SDL_SendWindowEvent(keyboard->focus, SDL_WINDOWEVENT_FOCUS_GAINED,
0, 0);
}
}
}
328
329
int
330
331
SDL_SendKeyboardKey(int index, Uint8 state, Uint8 scancode,
SDLKey physicalKey)
332
333
{
SDL_Keyboard *keyboard = SDL_GetKeyboard(index);
334
int posted;
335
336
337
Uint16 modstate;
Uint8 type;
338
if (!keyboard || physicalKey == SDLK_NONE) {
339
340
return 0;
}
341
#if 0
342
printf("The '%s' key has been %s\n", SDL_GetKeyName(physicalKey),
343
state == SDL_PRESSED ? "pressed" : "released");
344
#endif
345
346
if (state == SDL_PRESSED) {
modstate = keyboard->modstate;
347
switch (physicalKey) {
348
349
case SDLK_UNKNOWN:
break;
350
case SDLK_KP_NUMLOCKCLEAR:
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
keyboard->modstate ^= KMOD_NUM;
break;
case SDLK_CAPSLOCK:
keyboard->modstate ^= KMOD_CAPS;
break;
case SDLK_LCTRL:
keyboard->modstate |= KMOD_LCTRL;
break;
case SDLK_RCTRL:
keyboard->modstate |= KMOD_RCTRL;
break;
case SDLK_LSHIFT:
keyboard->modstate |= KMOD_LSHIFT;
break;
case SDLK_RSHIFT:
keyboard->modstate |= KMOD_RSHIFT;
break;
case SDLK_LALT:
keyboard->modstate |= KMOD_LALT;
break;
case SDLK_RALT:
keyboard->modstate |= KMOD_RALT;
break;
case SDLK_LMETA:
keyboard->modstate |= KMOD_LMETA;
break;
case SDLK_RMETA:
keyboard->modstate |= KMOD_RMETA;
break;
case SDLK_MODE:
keyboard->modstate |= KMOD_MODE;
break;
default:
break;
}
} else {
387
switch (physicalKey) {
388
389
case SDLK_UNKNOWN:
break;
390
case SDLK_KP_NUMLOCKCLEAR:
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
case SDLK_CAPSLOCK:
break;
case SDLK_LCTRL:
keyboard->modstate &= ~KMOD_LCTRL;
break;
case SDLK_RCTRL:
keyboard->modstate &= ~KMOD_RCTRL;
break;
case SDLK_LSHIFT:
keyboard->modstate &= ~KMOD_LSHIFT;
break;
case SDLK_RSHIFT:
keyboard->modstate &= ~KMOD_RSHIFT;
break;
case SDLK_LALT:
keyboard->modstate &= ~KMOD_LALT;
break;
case SDLK_RALT:
keyboard->modstate &= ~KMOD_RALT;
break;
case SDLK_LMETA:
keyboard->modstate &= ~KMOD_LMETA;
break;
case SDLK_RMETA:
keyboard->modstate &= ~KMOD_RMETA;
break;
case SDLK_MODE:
keyboard->modstate &= ~KMOD_MODE;
break;
default:
break;
}
modstate = keyboard->modstate;
}
/* 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;
}
439
if (physicalKey != SDLK_UNKNOWN) {
440
/* Drop events that don't change state */
441
if (keyboard->keystate[SDLK_INDEX(physicalKey)] == state) {
442
#if 0
443
printf("Keyboard event didn't change state - dropped!\n");
444
#endif
445
446
447
448
return 0;
}
/* Update internal keyboard state */
449
keyboard->keystate[SDLK_INDEX(physicalKey)] = state;
450
451
452
453
454
455
456
457
458
459
}
/* Post the event, if desired */
posted = 0;
if (SDL_ProcessEvents[type] == SDL_ENABLE) {
SDL_Event event;
event.key.type = type;
event.key.which = (Uint8) index;
event.key.state = state;
event.key.keysym.scancode = scancode;
460
event.key.keysym.sym = physicalKey;
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
event.key.keysym.mod = modstate;
event.key.keysym.unicode = 0;
event.key.windowID = keyboard->focus;
posted = (SDL_PushEvent(&event) > 0);
}
return (posted);
}
int
SDL_SendKeyboardText(int index, const char *text)
{
SDL_Keyboard *keyboard = SDL_GetKeyboard(index);
int posted;
if (!keyboard) {
return 0;
}
/* Post the event, if desired */
posted = 0;
if (SDL_ProcessEvents[SDL_TEXTINPUT] == SDL_ENABLE) {
SDL_Event event;
event.text.type = SDL_TEXTINPUT;
event.text.which = (Uint8) index;
SDL_strlcpy(event.text.text, text, SDL_arraysize(event.text.text));
486
event.text.windowID = keyboard->focus;
487
488
489
posted = (SDL_PushEvent(&event) > 0);
}
return (posted);
490
491
}
492
/* vi: set ts=4 sw=4 expandtab: */