1 /*
2   Simple DirectMedia Layer
3   Copyright (C) 1997-2018 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 #include "../../SDL_internal.h"
22 
23 #if SDL_VIDEO_DRIVER_DIRECTFB
24 
25 /* Handle the event stream, converting DirectFB input events into SDL events */
26 
27 #include "SDL_DirectFB_video.h"
28 #include "SDL_DirectFB_window.h"
29 #include "SDL_DirectFB_modes.h"
30 
31 #include "SDL_syswm.h"
32 
33 #include "../../events/SDL_mouse_c.h"
34 #include "../../events/SDL_keyboard_c.h"
35 #include "../../events/SDL_windowevents_c.h"
36 #include "../../events/SDL_events_c.h"
37 #include "../../events/scancodes_linux.h"
38 #include "../../events/scancodes_xfree86.h"
39 
40 #include "SDL_DirectFB_events.h"
41 
42 #if USE_MULTI_API
43 #define SDL_SendMouseMotion_ex(w, id, relative, x, y, p) SDL_SendMouseMotion(w, id, relative, x, y, p)
44 #define SDL_SendMouseButton_ex(w, id, state, button) SDL_SendMouseButton(w, id, state, button)
45 #define SDL_SendKeyboardKey_ex(id, state, scancode) SDL_SendKeyboardKey(id, state, scancode)
46 #define SDL_SendKeyboardText_ex(id, text) SDL_SendKeyboardText(id, text)
47 #else
48 #define SDL_SendMouseMotion_ex(w, id, relative, x, y, p) SDL_SendMouseMotion(w, id, relative, x, y)
49 #define SDL_SendMouseButton_ex(w, id, state, button) SDL_SendMouseButton(w, id, state, button)
50 #define SDL_SendKeyboardKey_ex(id, state, scancode) SDL_SendKeyboardKey(state, scancode)
51 #define SDL_SendKeyboardText_ex(id, text) SDL_SendKeyboardText(text)
52 #endif
53 
54 typedef struct _cb_data cb_data;
55 struct _cb_data
56 {
57     DFB_DeviceData *devdata;
58     int sys_ids;
59     int sys_kbd;
60 };
61 
62 /* The translation tables from a DirectFB keycode to a SDL keysym */
63 static SDL_Scancode oskeymap[256];
64 
65 
66 static SDL_Keysym *DirectFB_TranslateKey(_THIS, DFBWindowEvent * evt,
67                                          SDL_Keysym * keysym, Uint32 *unicode);
68 static SDL_Keysym *DirectFB_TranslateKeyInputEvent(_THIS, DFBInputEvent * evt,
69                                                    SDL_Keysym * keysym, Uint32 *unicode);
70 
71 static void DirectFB_InitOSKeymap(_THIS, SDL_Scancode * keypmap, int numkeys);
72 static int DirectFB_TranslateButton(DFBInputDeviceButtonIdentifier button);
73 
UnicodeToUtf8(Uint16 w,char * utf8buf)74 static void UnicodeToUtf8( Uint16 w , char *utf8buf)
75 {
76         unsigned char *utf8s = (unsigned char *) utf8buf;
77 
78     if ( w < 0x0080 ) {
79         utf8s[0] = ( unsigned char ) w;
80         utf8s[1] = 0;
81     }
82     else if ( w < 0x0800 ) {
83         utf8s[0] = 0xc0 | (( w ) >> 6 );
84         utf8s[1] = 0x80 | (( w ) & 0x3f );
85         utf8s[2] = 0;
86     }
87     else {
88         utf8s[0] = 0xe0 | (( w ) >> 12 );
89         utf8s[1] = 0x80 | (( ( w ) >> 6 ) & 0x3f );
90         utf8s[2] = 0x80 | (( w ) & 0x3f );
91         utf8s[3] = 0;
92     }
93 }
94 
95 static void
FocusAllMice(_THIS,SDL_Window * window)96 FocusAllMice(_THIS, SDL_Window *window)
97 {
98 #if USE_MULTI_API
99     SDL_DFB_DEVICEDATA(_this);
100     int index;
101 
102     for (index = 0; index < devdata->num_mice; index++)
103         SDL_SetMouseFocus(devdata->mouse_id[index], id);
104 #else
105     SDL_SetMouseFocus(window);
106 #endif
107 }
108 
109 
110 static void
FocusAllKeyboards(_THIS,SDL_Window * window)111 FocusAllKeyboards(_THIS, SDL_Window *window)
112 {
113 #if USE_MULTI_API
114     SDL_DFB_DEVICEDATA(_this);
115     int index;
116 
117     for (index = 0; index < devdata->num_keyboard; index++)
118         SDL_SetKeyboardFocus(index, id);
119 #else
120     SDL_SetKeyboardFocus(window);
121 #endif
122 }
123 
124 static void
MotionAllMice(_THIS,int x,int y)125 MotionAllMice(_THIS, int x, int y)
126 {
127 #if USE_MULTI_API
128     SDL_DFB_DEVICEDATA(_this);
129     int index;
130 
131     for (index = 0; index < devdata->num_mice; index++) {
132         SDL_Mouse *mouse = SDL_GetMouse(index);
133         mouse->x = mouse->last_x = x;
134         mouse->y = mouse->last_y = y;
135         /* SDL_SendMouseMotion(devdata->mouse_id[index], 0, x, y, 0); */
136     }
137 #endif
138 }
139 
140 static int
KbdIndex(_THIS,int id)141 KbdIndex(_THIS, int id)
142 {
143     SDL_DFB_DEVICEDATA(_this);
144     int index;
145 
146     for (index = 0; index < devdata->num_keyboard; index++) {
147         if (devdata->keyboard[index].id == id)
148             return index;
149     }
150     return -1;
151 }
152 
153 static int
ClientXY(DFB_WindowData * p,int * x,int * y)154 ClientXY(DFB_WindowData * p, int *x, int *y)
155 {
156     int cx, cy;
157 
158     cx = *x;
159     cy = *y;
160 
161     cx -= p->client.x;
162     cy -= p->client.y;
163 
164     if (cx < 0 || cy < 0)
165         return 0;
166     if (cx >= p->client.w || cy >= p->client.h)
167         return 0;
168     *x = cx;
169     *y = cy;
170     return 1;
171 }
172 
173 static void
ProcessWindowEvent(_THIS,SDL_Window * sdlwin,DFBWindowEvent * evt)174 ProcessWindowEvent(_THIS, SDL_Window *sdlwin, DFBWindowEvent * evt)
175 {
176     SDL_DFB_DEVICEDATA(_this);
177     SDL_DFB_WINDOWDATA(sdlwin);
178     SDL_Keysym keysym;
179     Uint32 unicode;
180     char text[SDL_TEXTINPUTEVENT_TEXT_SIZE];
181 
182     if (evt->clazz == DFEC_WINDOW) {
183         switch (evt->type) {
184         case DWET_BUTTONDOWN:
185             if (ClientXY(windata, &evt->x, &evt->y)) {
186                 if (!devdata->use_linux_input) {
187                     SDL_SendMouseMotion_ex(sdlwin, devdata->mouse_id[0], 0, evt->x,
188                                         evt->y, 0);
189                     SDL_SendMouseButton_ex(sdlwin, devdata->mouse_id[0],
190                                         SDL_PRESSED,
191                                         DirectFB_TranslateButton
192                                         (evt->button));
193                 } else {
194                     MotionAllMice(_this, evt->x, evt->y);
195                 }
196             }
197             break;
198         case DWET_BUTTONUP:
199             if (ClientXY(windata, &evt->x, &evt->y)) {
200                 if (!devdata->use_linux_input) {
201                     SDL_SendMouseMotion_ex(sdlwin, devdata->mouse_id[0], 0, evt->x,
202                                         evt->y, 0);
203                     SDL_SendMouseButton_ex(sdlwin, devdata->mouse_id[0],
204                                         SDL_RELEASED,
205                                         DirectFB_TranslateButton
206                                         (evt->button));
207                 } else {
208                     MotionAllMice(_this, evt->x, evt->y);
209                 }
210             }
211             break;
212         case DWET_MOTION:
213             if (ClientXY(windata, &evt->x, &evt->y)) {
214                 if (!devdata->use_linux_input) {
215                     if (!(sdlwin->flags & SDL_WINDOW_INPUT_GRABBED))
216                         SDL_SendMouseMotion_ex(sdlwin, devdata->mouse_id[0], 0,
217                                             evt->x, evt->y, 0);
218                 } else {
219                     /* relative movements are not exact!
220                      * This code should limit the number of events sent.
221                      * However it kills MAME axis recognition ... */
222                     static int cnt = 0;
223                     if (1 && ++cnt > 20) {
224                         MotionAllMice(_this, evt->x, evt->y);
225                         cnt = 0;
226                     }
227                 }
228                 if (!(sdlwin->flags & SDL_WINDOW_MOUSE_FOCUS))
229                     SDL_SendWindowEvent(sdlwin, SDL_WINDOWEVENT_ENTER, 0,
230                                         0);
231             }
232             break;
233         case DWET_KEYDOWN:
234             if (!devdata->use_linux_input) {
235                 DirectFB_TranslateKey(_this, evt, &keysym, &unicode);
236                 /* printf("Scancode %d  %d %d\n", keysym.scancode, evt->key_code, evt->key_id); */
237                 SDL_SendKeyboardKey_ex(0, SDL_PRESSED, keysym.scancode);
238                 if (SDL_EventState(SDL_TEXTINPUT, SDL_QUERY)) {
239                     SDL_zero(text);
240                     UnicodeToUtf8(unicode, text);
241                     if (*text) {
242                         SDL_SendKeyboardText_ex(0, text);
243                     }
244                 }
245             }
246             break;
247         case DWET_KEYUP:
248             if (!devdata->use_linux_input) {
249                 DirectFB_TranslateKey(_this, evt, &keysym, &unicode);
250                 SDL_SendKeyboardKey_ex(0, SDL_RELEASED, keysym.scancode);
251             }
252             break;
253         case DWET_POSITION:
254             if (ClientXY(windata, &evt->x, &evt->y)) {
255                 SDL_SendWindowEvent(sdlwin, SDL_WINDOWEVENT_MOVED,
256                                     evt->x, evt->y);
257             }
258             break;
259         case DWET_POSITION_SIZE:
260             if (ClientXY(windata, &evt->x, &evt->y)) {
261                 SDL_SendWindowEvent(sdlwin, SDL_WINDOWEVENT_MOVED,
262                                     evt->x, evt->y);
263             }
264             /* fall throught */
265         case DWET_SIZE:
266             /* FIXME: what about < 0 */
267             evt->w -= (windata->theme.right_size + windata->theme.left_size);
268             evt->h -=
269                 (windata->theme.top_size + windata->theme.bottom_size +
270                  windata->theme.caption_size);
271             SDL_SendWindowEvent(sdlwin, SDL_WINDOWEVENT_RESIZED,
272                                 evt->w, evt->h);
273             break;
274         case DWET_CLOSE:
275             SDL_SendWindowEvent(sdlwin, SDL_WINDOWEVENT_CLOSE, 0, 0);
276             break;
277         case DWET_GOTFOCUS:
278             DirectFB_SetContext(_this, sdlwin);
279             FocusAllKeyboards(_this, sdlwin);
280             SDL_SendWindowEvent(sdlwin, SDL_WINDOWEVENT_FOCUS_GAINED,
281                                 0, 0);
282             break;
283         case DWET_LOSTFOCUS:
284             SDL_SendWindowEvent(sdlwin, SDL_WINDOWEVENT_FOCUS_LOST, 0, 0);
285             FocusAllKeyboards(_this, 0);
286             break;
287         case DWET_ENTER:
288             /* SDL_DirectFB_ReshowCursor(_this, 0); */
289             FocusAllMice(_this, sdlwin);
290             /* FIXME: when do we really enter ? */
291             if (ClientXY(windata, &evt->x, &evt->y))
292                 MotionAllMice(_this, evt->x, evt->y);
293             SDL_SendWindowEvent(sdlwin, SDL_WINDOWEVENT_ENTER, 0, 0);
294             break;
295         case DWET_LEAVE:
296             SDL_SendWindowEvent(sdlwin, SDL_WINDOWEVENT_LEAVE, 0, 0);
297             FocusAllMice(_this, 0);
298             /* SDL_DirectFB_ReshowCursor(_this, 1); */
299             break;
300         default:
301             ;
302         }
303     } else
304         printf("Event Clazz %d\n", evt->clazz);
305 }
306 
307 static void
ProcessInputEvent(_THIS,DFBInputEvent * ievt)308 ProcessInputEvent(_THIS, DFBInputEvent * ievt)
309 {
310     SDL_DFB_DEVICEDATA(_this);
311     SDL_Keysym keysym;
312     int kbd_idx;
313     Uint32 unicode;
314     char text[SDL_TEXTINPUTEVENT_TEXT_SIZE];
315 
316     if (!devdata->use_linux_input) {
317         if (ievt->type == DIET_AXISMOTION) {
318             if ((devdata->grabbed_window != NULL) && (ievt->flags & DIEF_AXISREL)) {
319                 if (ievt->axis == DIAI_X)
320                     SDL_SendMouseMotion_ex(devdata->grabbed_window, ievt->device_id, 1,
321                                         ievt->axisrel, 0, 0);
322                 else if (ievt->axis == DIAI_Y)
323                     SDL_SendMouseMotion_ex(devdata->grabbed_window, ievt->device_id, 1, 0,
324                                         ievt->axisrel, 0);
325             }
326         }
327     } else {
328         static int last_x, last_y;
329 
330         switch (ievt->type) {
331         case DIET_AXISMOTION:
332             if (ievt->flags & DIEF_AXISABS) {
333                 if (ievt->axis == DIAI_X)
334                     last_x = ievt->axisabs;
335                 else if (ievt->axis == DIAI_Y)
336                     last_y = ievt->axisabs;
337                 if (!(ievt->flags & DIEF_FOLLOW)) {
338 #if USE_MULTI_API
339                     SDL_Mouse *mouse = SDL_GetMouse(ievt->device_id);
340                     SDL_Window *window = SDL_GetWindowFromID(mouse->focus);
341 #else
342                     SDL_Window *window = devdata->grabbed_window;
343 #endif
344                     if (window) {
345                         DFB_WindowData *windata =
346                             (DFB_WindowData *) window->driverdata;
347                         int x, y;
348 
349                         windata->dfbwin->GetPosition(windata->dfbwin, &x, &y);
350                         SDL_SendMouseMotion_ex(window, ievt->device_id, 0,
351                                             last_x - (x +
352                                                       windata->client.x),
353                                             last_y - (y +
354                                                       windata->client.y), 0);
355                     } else {
356                         SDL_SendMouseMotion_ex(window, ievt->device_id, 0, last_x,
357                                             last_y, 0);
358                     }
359                 }
360             } else if (ievt->flags & DIEF_AXISREL) {
361                 if (ievt->axis == DIAI_X)
362                     SDL_SendMouseMotion_ex(devdata->grabbed_window, ievt->device_id, 1,
363                                         ievt->axisrel, 0, 0);
364                 else if (ievt->axis == DIAI_Y)
365                     SDL_SendMouseMotion_ex(devdata->grabbed_window, ievt->device_id, 1, 0,
366                                         ievt->axisrel, 0);
367             }
368             break;
369         case DIET_KEYPRESS:
370             kbd_idx = KbdIndex(_this, ievt->device_id);
371             DirectFB_TranslateKeyInputEvent(_this, ievt, &keysym, &unicode);
372             /* printf("Scancode %d  %d %d\n", keysym.scancode, evt->key_code, evt->key_id); */
373             SDL_SendKeyboardKey_ex(kbd_idx, SDL_PRESSED, keysym.scancode);
374             if (SDL_EventState(SDL_TEXTINPUT, SDL_QUERY)) {
375                 SDL_zero(text);
376                 UnicodeToUtf8(unicode, text);
377                 if (*text) {
378                     SDL_SendKeyboardText_ex(kbd_idx, text);
379                 }
380             }
381             break;
382         case DIET_KEYRELEASE:
383             kbd_idx = KbdIndex(_this, ievt->device_id);
384             DirectFB_TranslateKeyInputEvent(_this, ievt, &keysym, &unicode);
385             SDL_SendKeyboardKey_ex(kbd_idx, SDL_RELEASED, keysym.scancode);
386             break;
387         case DIET_BUTTONPRESS:
388             if (ievt->buttons & DIBM_LEFT)
389                 SDL_SendMouseButton_ex(devdata->grabbed_window, ievt->device_id, SDL_PRESSED, 1);
390             if (ievt->buttons & DIBM_MIDDLE)
391                 SDL_SendMouseButton_ex(devdata->grabbed_window, ievt->device_id, SDL_PRESSED, 2);
392             if (ievt->buttons & DIBM_RIGHT)
393                 SDL_SendMouseButton_ex(devdata->grabbed_window, ievt->device_id, SDL_PRESSED, 3);
394             break;
395         case DIET_BUTTONRELEASE:
396             if (!(ievt->buttons & DIBM_LEFT))
397                 SDL_SendMouseButton_ex(devdata->grabbed_window, ievt->device_id, SDL_RELEASED, 1);
398             if (!(ievt->buttons & DIBM_MIDDLE))
399                 SDL_SendMouseButton_ex(devdata->grabbed_window, ievt->device_id, SDL_RELEASED, 2);
400             if (!(ievt->buttons & DIBM_RIGHT))
401                 SDL_SendMouseButton_ex(devdata->grabbed_window, ievt->device_id, SDL_RELEASED, 3);
402             break;
403         default:
404             break;              /* please gcc */
405         }
406     }
407 }
408 
409 void
DirectFB_PumpEventsWindow(_THIS)410 DirectFB_PumpEventsWindow(_THIS)
411 {
412     SDL_DFB_DEVICEDATA(_this);
413     DFBInputEvent ievt;
414     SDL_Window *w;
415 
416     for (w = devdata->firstwin; w != NULL; w = w->next) {
417         SDL_DFB_WINDOWDATA(w);
418         DFBWindowEvent evt;
419 
420         while (windata->eventbuffer->GetEvent(windata->eventbuffer,
421                                         DFB_EVENT(&evt)) == DFB_OK) {
422             if (!DirectFB_WM_ProcessEvent(_this, w, &evt)) {
423                 /* Send a SDL_SYSWMEVENT if the application wants them */
424                 if (SDL_GetEventState(SDL_SYSWMEVENT) == SDL_ENABLE) {
425                     SDL_SysWMmsg wmmsg;
426                     SDL_VERSION(&wmmsg.version);
427                     wmmsg.subsystem = SDL_SYSWM_DIRECTFB;
428                     wmmsg.msg.dfb.event.window = evt;
429                     SDL_SendSysWMEvent(&wmmsg);
430                 }
431                 ProcessWindowEvent(_this, w, &evt);
432             }
433         }
434     }
435 
436     /* Now get relative events in case we need them */
437     while (devdata->events->GetEvent(devdata->events,
438                                      DFB_EVENT(&ievt)) == DFB_OK) {
439 
440         if (SDL_GetEventState(SDL_SYSWMEVENT) == SDL_ENABLE) {
441             SDL_SysWMmsg wmmsg;
442             SDL_VERSION(&wmmsg.version);
443             wmmsg.subsystem = SDL_SYSWM_DIRECTFB;
444             wmmsg.msg.dfb.event.input = ievt;
445             SDL_SendSysWMEvent(&wmmsg);
446         }
447         ProcessInputEvent(_this, &ievt);
448     }
449 }
450 
451 void
DirectFB_InitOSKeymap(_THIS,SDL_Scancode * keymap,int numkeys)452 DirectFB_InitOSKeymap(_THIS, SDL_Scancode * keymap, int numkeys)
453 {
454     int i;
455 
456     /* Initialize the DirectFB key translation table */
457     for (i = 0; i < numkeys; ++i)
458         keymap[i] = SDL_SCANCODE_UNKNOWN;
459 
460     keymap[DIKI_A - DIKI_UNKNOWN] = SDL_SCANCODE_A;
461     keymap[DIKI_B - DIKI_UNKNOWN] = SDL_SCANCODE_B;
462     keymap[DIKI_C - DIKI_UNKNOWN] = SDL_SCANCODE_C;
463     keymap[DIKI_D - DIKI_UNKNOWN] = SDL_SCANCODE_D;
464     keymap[DIKI_E - DIKI_UNKNOWN] = SDL_SCANCODE_E;
465     keymap[DIKI_F - DIKI_UNKNOWN] = SDL_SCANCODE_F;
466     keymap[DIKI_G - DIKI_UNKNOWN] = SDL_SCANCODE_G;
467     keymap[DIKI_H - DIKI_UNKNOWN] = SDL_SCANCODE_H;
468     keymap[DIKI_I - DIKI_UNKNOWN] = SDL_SCANCODE_I;
469     keymap[DIKI_J - DIKI_UNKNOWN] = SDL_SCANCODE_J;
470     keymap[DIKI_K - DIKI_UNKNOWN] = SDL_SCANCODE_K;
471     keymap[DIKI_L - DIKI_UNKNOWN] = SDL_SCANCODE_L;
472     keymap[DIKI_M - DIKI_UNKNOWN] = SDL_SCANCODE_M;
473     keymap[DIKI_N - DIKI_UNKNOWN] = SDL_SCANCODE_N;
474     keymap[DIKI_O - DIKI_UNKNOWN] = SDL_SCANCODE_O;
475     keymap[DIKI_P - DIKI_UNKNOWN] = SDL_SCANCODE_P;
476     keymap[DIKI_Q - DIKI_UNKNOWN] = SDL_SCANCODE_Q;
477     keymap[DIKI_R - DIKI_UNKNOWN] = SDL_SCANCODE_R;
478     keymap[DIKI_S - DIKI_UNKNOWN] = SDL_SCANCODE_S;
479     keymap[DIKI_T - DIKI_UNKNOWN] = SDL_SCANCODE_T;
480     keymap[DIKI_U - DIKI_UNKNOWN] = SDL_SCANCODE_U;
481     keymap[DIKI_V - DIKI_UNKNOWN] = SDL_SCANCODE_V;
482     keymap[DIKI_W - DIKI_UNKNOWN] = SDL_SCANCODE_W;
483     keymap[DIKI_X - DIKI_UNKNOWN] = SDL_SCANCODE_X;
484     keymap[DIKI_Y - DIKI_UNKNOWN] = SDL_SCANCODE_Y;
485     keymap[DIKI_Z - DIKI_UNKNOWN] = SDL_SCANCODE_Z;
486 
487     keymap[DIKI_0 - DIKI_UNKNOWN] = SDL_SCANCODE_0;
488     keymap[DIKI_1 - DIKI_UNKNOWN] = SDL_SCANCODE_1;
489     keymap[DIKI_2 - DIKI_UNKNOWN] = SDL_SCANCODE_2;
490     keymap[DIKI_3 - DIKI_UNKNOWN] = SDL_SCANCODE_3;
491     keymap[DIKI_4 - DIKI_UNKNOWN] = SDL_SCANCODE_4;
492     keymap[DIKI_5 - DIKI_UNKNOWN] = SDL_SCANCODE_5;
493     keymap[DIKI_6 - DIKI_UNKNOWN] = SDL_SCANCODE_6;
494     keymap[DIKI_7 - DIKI_UNKNOWN] = SDL_SCANCODE_7;
495     keymap[DIKI_8 - DIKI_UNKNOWN] = SDL_SCANCODE_8;
496     keymap[DIKI_9 - DIKI_UNKNOWN] = SDL_SCANCODE_9;
497 
498     keymap[DIKI_F1 - DIKI_UNKNOWN] = SDL_SCANCODE_F1;
499     keymap[DIKI_F2 - DIKI_UNKNOWN] = SDL_SCANCODE_F2;
500     keymap[DIKI_F3 - DIKI_UNKNOWN] = SDL_SCANCODE_F3;
501     keymap[DIKI_F4 - DIKI_UNKNOWN] = SDL_SCANCODE_F4;
502     keymap[DIKI_F5 - DIKI_UNKNOWN] = SDL_SCANCODE_F5;
503     keymap[DIKI_F6 - DIKI_UNKNOWN] = SDL_SCANCODE_F6;
504     keymap[DIKI_F7 - DIKI_UNKNOWN] = SDL_SCANCODE_F7;
505     keymap[DIKI_F8 - DIKI_UNKNOWN] = SDL_SCANCODE_F8;
506     keymap[DIKI_F9 - DIKI_UNKNOWN] = SDL_SCANCODE_F9;
507     keymap[DIKI_F10 - DIKI_UNKNOWN] = SDL_SCANCODE_F10;
508     keymap[DIKI_F11 - DIKI_UNKNOWN] = SDL_SCANCODE_F11;
509     keymap[DIKI_F12 - DIKI_UNKNOWN] = SDL_SCANCODE_F12;
510 
511     keymap[DIKI_ESCAPE - DIKI_UNKNOWN] = SDL_SCANCODE_ESCAPE;
512     keymap[DIKI_LEFT - DIKI_UNKNOWN] = SDL_SCANCODE_LEFT;
513     keymap[DIKI_RIGHT - DIKI_UNKNOWN] = SDL_SCANCODE_RIGHT;
514     keymap[DIKI_UP - DIKI_UNKNOWN] = SDL_SCANCODE_UP;
515     keymap[DIKI_DOWN - DIKI_UNKNOWN] = SDL_SCANCODE_DOWN;
516     keymap[DIKI_CONTROL_L - DIKI_UNKNOWN] = SDL_SCANCODE_LCTRL;
517     keymap[DIKI_CONTROL_R - DIKI_UNKNOWN] = SDL_SCANCODE_RCTRL;
518     keymap[DIKI_SHIFT_L - DIKI_UNKNOWN] = SDL_SCANCODE_LSHIFT;
519     keymap[DIKI_SHIFT_R - DIKI_UNKNOWN] = SDL_SCANCODE_RSHIFT;
520     keymap[DIKI_ALT_L - DIKI_UNKNOWN] = SDL_SCANCODE_LALT;
521     keymap[DIKI_ALT_R - DIKI_UNKNOWN] = SDL_SCANCODE_RALT;
522     keymap[DIKI_META_L - DIKI_UNKNOWN] = SDL_SCANCODE_LGUI;
523     keymap[DIKI_META_R - DIKI_UNKNOWN] = SDL_SCANCODE_RGUI;
524     keymap[DIKI_SUPER_L - DIKI_UNKNOWN] = SDL_SCANCODE_APPLICATION;
525     keymap[DIKI_SUPER_R - DIKI_UNKNOWN] = SDL_SCANCODE_APPLICATION;
526     /* FIXME:Do we read hyper keys ?
527      * keymap[DIKI_HYPER_L - DIKI_UNKNOWN] = SDL_SCANCODE_APPLICATION;
528      * keymap[DIKI_HYPER_R - DIKI_UNKNOWN] = SDL_SCANCODE_APPLICATION;
529      */
530     keymap[DIKI_TAB - DIKI_UNKNOWN] = SDL_SCANCODE_TAB;
531     keymap[DIKI_ENTER - DIKI_UNKNOWN] = SDL_SCANCODE_RETURN;
532     keymap[DIKI_SPACE - DIKI_UNKNOWN] = SDL_SCANCODE_SPACE;
533     keymap[DIKI_BACKSPACE - DIKI_UNKNOWN] = SDL_SCANCODE_BACKSPACE;
534     keymap[DIKI_INSERT - DIKI_UNKNOWN] = SDL_SCANCODE_INSERT;
535     keymap[DIKI_DELETE - DIKI_UNKNOWN] = SDL_SCANCODE_DELETE;
536     keymap[DIKI_HOME - DIKI_UNKNOWN] = SDL_SCANCODE_HOME;
537     keymap[DIKI_END - DIKI_UNKNOWN] = SDL_SCANCODE_END;
538     keymap[DIKI_PAGE_UP - DIKI_UNKNOWN] = SDL_SCANCODE_PAGEUP;
539     keymap[DIKI_PAGE_DOWN - DIKI_UNKNOWN] = SDL_SCANCODE_PAGEDOWN;
540     keymap[DIKI_CAPS_LOCK - DIKI_UNKNOWN] = SDL_SCANCODE_CAPSLOCK;
541     keymap[DIKI_NUM_LOCK - DIKI_UNKNOWN] = SDL_SCANCODE_NUMLOCKCLEAR;
542     keymap[DIKI_SCROLL_LOCK - DIKI_UNKNOWN] = SDL_SCANCODE_SCROLLLOCK;
543     keymap[DIKI_PRINT - DIKI_UNKNOWN] = SDL_SCANCODE_PRINTSCREEN;
544     keymap[DIKI_PAUSE - DIKI_UNKNOWN] = SDL_SCANCODE_PAUSE;
545 
546     keymap[DIKI_KP_EQUAL - DIKI_UNKNOWN] = SDL_SCANCODE_KP_EQUALS;
547     keymap[DIKI_KP_DECIMAL - DIKI_UNKNOWN] = SDL_SCANCODE_KP_PERIOD;
548     keymap[DIKI_KP_0 - DIKI_UNKNOWN] = SDL_SCANCODE_KP_0;
549     keymap[DIKI_KP_1 - DIKI_UNKNOWN] = SDL_SCANCODE_KP_1;
550     keymap[DIKI_KP_2 - DIKI_UNKNOWN] = SDL_SCANCODE_KP_2;
551     keymap[DIKI_KP_3 - DIKI_UNKNOWN] = SDL_SCANCODE_KP_3;
552     keymap[DIKI_KP_4 - DIKI_UNKNOWN] = SDL_SCANCODE_KP_4;
553     keymap[DIKI_KP_5 - DIKI_UNKNOWN] = SDL_SCANCODE_KP_5;
554     keymap[DIKI_KP_6 - DIKI_UNKNOWN] = SDL_SCANCODE_KP_6;
555     keymap[DIKI_KP_7 - DIKI_UNKNOWN] = SDL_SCANCODE_KP_7;
556     keymap[DIKI_KP_8 - DIKI_UNKNOWN] = SDL_SCANCODE_KP_8;
557     keymap[DIKI_KP_9 - DIKI_UNKNOWN] = SDL_SCANCODE_KP_9;
558     keymap[DIKI_KP_DIV - DIKI_UNKNOWN] = SDL_SCANCODE_KP_DIVIDE;
559     keymap[DIKI_KP_MULT - DIKI_UNKNOWN] = SDL_SCANCODE_KP_MULTIPLY;
560     keymap[DIKI_KP_MINUS - DIKI_UNKNOWN] = SDL_SCANCODE_KP_MINUS;
561     keymap[DIKI_KP_PLUS - DIKI_UNKNOWN] = SDL_SCANCODE_KP_PLUS;
562     keymap[DIKI_KP_ENTER - DIKI_UNKNOWN] = SDL_SCANCODE_KP_ENTER;
563 
564     keymap[DIKI_QUOTE_LEFT - DIKI_UNKNOWN] = SDL_SCANCODE_GRAVE;        /*  TLDE  */
565     keymap[DIKI_MINUS_SIGN - DIKI_UNKNOWN] = SDL_SCANCODE_MINUS;        /*  AE11  */
566     keymap[DIKI_EQUALS_SIGN - DIKI_UNKNOWN] = SDL_SCANCODE_EQUALS;      /*  AE12  */
567     keymap[DIKI_BRACKET_LEFT - DIKI_UNKNOWN] = SDL_SCANCODE_RIGHTBRACKET;       /*  AD11  */
568     keymap[DIKI_BRACKET_RIGHT - DIKI_UNKNOWN] = SDL_SCANCODE_LEFTBRACKET;       /*  AD12  */
569     keymap[DIKI_BACKSLASH - DIKI_UNKNOWN] = SDL_SCANCODE_BACKSLASH;     /*  BKSL  */
570     keymap[DIKI_SEMICOLON - DIKI_UNKNOWN] = SDL_SCANCODE_SEMICOLON;     /*  AC10  */
571     keymap[DIKI_QUOTE_RIGHT - DIKI_UNKNOWN] = SDL_SCANCODE_APOSTROPHE;  /*  AC11  */
572     keymap[DIKI_COMMA - DIKI_UNKNOWN] = SDL_SCANCODE_COMMA;     /*  AB08  */
573     keymap[DIKI_PERIOD - DIKI_UNKNOWN] = SDL_SCANCODE_PERIOD;   /*  AB09  */
574     keymap[DIKI_SLASH - DIKI_UNKNOWN] = SDL_SCANCODE_SLASH;     /*  AB10  */
575     keymap[DIKI_LESS_SIGN - DIKI_UNKNOWN] = SDL_SCANCODE_NONUSBACKSLASH;        /*  103rd  */
576 
577 }
578 
579 static SDL_Keysym *
DirectFB_TranslateKey(_THIS,DFBWindowEvent * evt,SDL_Keysym * keysym,Uint32 * unicode)580 DirectFB_TranslateKey(_THIS, DFBWindowEvent * evt, SDL_Keysym * keysym, Uint32 *unicode)
581 {
582     SDL_DFB_DEVICEDATA(_this);
583     int kbd_idx = 0; /* Window events lag the device source KbdIndex(_this, evt->device_id); */
584     DFB_KeyboardData *kbd = &devdata->keyboard[kbd_idx];
585 
586     keysym->scancode = SDL_SCANCODE_UNKNOWN;
587 
588     if (kbd->map && evt->key_code >= kbd->map_adjust &&
589         evt->key_code < kbd->map_size + kbd->map_adjust)
590         keysym->scancode = kbd->map[evt->key_code - kbd->map_adjust];
591 
592     if (keysym->scancode == SDL_SCANCODE_UNKNOWN ||
593         devdata->keyboard[kbd_idx].is_generic) {
594         if (evt->key_id - DIKI_UNKNOWN < SDL_arraysize(oskeymap))
595             keysym->scancode = oskeymap[evt->key_id - DIKI_UNKNOWN];
596         else
597             keysym->scancode = SDL_SCANCODE_UNKNOWN;
598     }
599 
600     *unicode =
601         (DFB_KEY_TYPE(evt->key_symbol) == DIKT_UNICODE) ? evt->key_symbol : 0;
602     if (*unicode == 0 &&
603         (evt->key_symbol > 0 && evt->key_symbol < 255))
604         *unicode = evt->key_symbol;
605 
606     return keysym;
607 }
608 
609 static SDL_Keysym *
DirectFB_TranslateKeyInputEvent(_THIS,DFBInputEvent * evt,SDL_Keysym * keysym,Uint32 * unicode)610 DirectFB_TranslateKeyInputEvent(_THIS, DFBInputEvent * evt,
611                                 SDL_Keysym * keysym, Uint32 *unicode)
612 {
613     SDL_DFB_DEVICEDATA(_this);
614     int kbd_idx = KbdIndex(_this, evt->device_id);
615     DFB_KeyboardData *kbd = &devdata->keyboard[kbd_idx];
616 
617     keysym->scancode = SDL_SCANCODE_UNKNOWN;
618 
619     if (kbd->map && evt->key_code >= kbd->map_adjust &&
620         evt->key_code < kbd->map_size + kbd->map_adjust)
621         keysym->scancode = kbd->map[evt->key_code - kbd->map_adjust];
622 
623     if (keysym->scancode == SDL_SCANCODE_UNKNOWN || devdata->keyboard[kbd_idx].is_generic) {
624         if (evt->key_id - DIKI_UNKNOWN < SDL_arraysize(oskeymap))
625             keysym->scancode = oskeymap[evt->key_id - DIKI_UNKNOWN];
626         else
627             keysym->scancode = SDL_SCANCODE_UNKNOWN;
628     }
629 
630     *unicode =
631         (DFB_KEY_TYPE(evt->key_symbol) == DIKT_UNICODE) ? evt->key_symbol : 0;
632     if (*unicode == 0 &&
633         (evt->key_symbol > 0 && evt->key_symbol < 255))
634         *unicode = evt->key_symbol;
635 
636     return keysym;
637 }
638 
639 static int
DirectFB_TranslateButton(DFBInputDeviceButtonIdentifier button)640 DirectFB_TranslateButton(DFBInputDeviceButtonIdentifier button)
641 {
642     switch (button) {
643     case DIBI_LEFT:
644         return 1;
645     case DIBI_MIDDLE:
646         return 2;
647     case DIBI_RIGHT:
648         return 3;
649     default:
650         return 0;
651     }
652 }
653 
654 static DFBEnumerationResult
EnumKeyboards(DFBInputDeviceID device_id,DFBInputDeviceDescription desc,void * callbackdata)655 EnumKeyboards(DFBInputDeviceID device_id,
656                 DFBInputDeviceDescription desc, void *callbackdata)
657 {
658     cb_data *cb = callbackdata;
659     DFB_DeviceData *devdata = cb->devdata;
660 #if USE_MULTI_API
661     SDL_Keyboard keyboard;
662 #endif
663     SDL_Keycode keymap[SDL_NUM_SCANCODES];
664 
665     if (!cb->sys_kbd) {
666         if (cb->sys_ids) {
667             if (device_id >= 0x10)
668                 return DFENUM_OK;
669         } else {
670             if (device_id < 0x10)
671                 return DFENUM_OK;
672         }
673     } else {
674         if (device_id != DIDID_KEYBOARD)
675             return DFENUM_OK;
676     }
677 
678     if ((desc.caps & DIDTF_KEYBOARD)) {
679 #if USE_MULTI_API
680         SDL_zero(keyboard);
681         SDL_AddKeyboard(&keyboard, devdata->num_keyboard);
682 #endif
683         devdata->keyboard[devdata->num_keyboard].id = device_id;
684         devdata->keyboard[devdata->num_keyboard].is_generic = 0;
685         if (!strncmp("X11", desc.name, 3))
686         {
687             devdata->keyboard[devdata->num_keyboard].map = xfree86_scancode_table2;
688             devdata->keyboard[devdata->num_keyboard].map_size = SDL_arraysize(xfree86_scancode_table2);
689             devdata->keyboard[devdata->num_keyboard].map_adjust = 8;
690         } else {
691             devdata->keyboard[devdata->num_keyboard].map = linux_scancode_table;
692             devdata->keyboard[devdata->num_keyboard].map_size = SDL_arraysize(linux_scancode_table);
693             devdata->keyboard[devdata->num_keyboard].map_adjust = 0;
694         }
695 
696         SDL_DFB_LOG("Keyboard %d - %s\n", device_id, desc.name);
697 
698         SDL_GetDefaultKeymap(keymap);
699 #if USE_MULTI_API
700         SDL_SetKeymap(devdata->num_keyboard, 0, keymap, SDL_NUM_SCANCODES);
701 #else
702         SDL_SetKeymap(0, keymap, SDL_NUM_SCANCODES);
703 #endif
704         devdata->num_keyboard++;
705 
706         if (cb->sys_kbd)
707             return DFENUM_CANCEL;
708     }
709     return DFENUM_OK;
710 }
711 
712 void
DirectFB_InitKeyboard(_THIS)713 DirectFB_InitKeyboard(_THIS)
714 {
715     SDL_DFB_DEVICEDATA(_this);
716     cb_data cb;
717 
718     DirectFB_InitOSKeymap(_this, &oskeymap[0], SDL_arraysize(oskeymap));
719 
720     devdata->num_keyboard = 0;
721     cb.devdata = devdata;
722 
723     if (devdata->use_linux_input) {
724         cb.sys_kbd = 0;
725         cb.sys_ids = 0;
726         SDL_DFB_CHECK(devdata->dfb->
727                       EnumInputDevices(devdata->dfb, EnumKeyboards, &cb));
728         if (devdata->num_keyboard == 0) {
729             cb.sys_ids = 1;
730             SDL_DFB_CHECK(devdata->dfb->EnumInputDevices(devdata->dfb,
731                                                          EnumKeyboards,
732                                                          &cb));
733         }
734     } else {
735         cb.sys_kbd = 1;
736         SDL_DFB_CHECK(devdata->dfb->EnumInputDevices(devdata->dfb,
737                                                      EnumKeyboards,
738                                                      &cb));
739     }
740 }
741 
742 void
DirectFB_QuitKeyboard(_THIS)743 DirectFB_QuitKeyboard(_THIS)
744 {
745     /* SDL_DFB_DEVICEDATA(_this); */
746 }
747 
748 #endif /* SDL_VIDEO_DRIVER_DIRECTFB */
749