1 /*****************************************************************************
2 * This file is part of gfxprim library. *
4 * Gfxprim is free software; you can redistribute it and/or *
5 * modify it under the terms of the GNU Lesser General Public *
6 * License as published by the Free Software Foundation; either *
7 * version 2.1 of the License, or (at your option) any later version. *
9 * Gfxprim is distributed in the hope that it will be useful, *
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
12 * Lesser General Public License for more details. *
14 * You should have received a copy of the GNU Lesser General Public *
15 * License along with gfxprim; if not, write to the Free Software *
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, *
17 * Boston, MA 02110-1301 USA *
19 * Copyright (C) 2009-2013 Cyril Hrubis <metan@ucw.cz> *
21 *****************************************************************************/
23 #include <X11/keysym.h>
24 #include <X11/XF86keysym.h>
27 static uint16_t keycode_table
[] = {
28 0, GP_KEY_1
, GP_KEY_2
, GP_KEY_3
,
29 GP_KEY_4
, GP_KEY_5
, GP_KEY_6
, GP_KEY_7
,
30 GP_KEY_8
, GP_KEY_9
, GP_KEY_0
, GP_KEY_MINUS
,
31 GP_KEY_EQUAL
, 0, 0, GP_KEY_Q
,
32 GP_KEY_W
, GP_KEY_E
, GP_KEY_R
, GP_KEY_T
,
33 GP_KEY_Y
, GP_KEY_U
, GP_KEY_I
, GP_KEY_O
,
34 GP_KEY_P
, GP_KEY_LEFT_BRACE
, GP_KEY_RIGHT_BRACE
, GP_KEY_ENTER
,
35 0, GP_KEY_A
, GP_KEY_S
, GP_KEY_D
,
36 GP_KEY_F
, GP_KEY_G
, GP_KEY_H
, GP_KEY_J
,
37 GP_KEY_K
, GP_KEY_L
, GP_KEY_SEMICOLON
, GP_KEY_APOSTROPHE
,
38 GP_KEY_GRAVE
, 0, GP_KEY_BACKSLASH
, GP_KEY_Z
,
39 GP_KEY_X
, GP_KEY_C
, GP_KEY_V
, GP_KEY_B
,
40 GP_KEY_N
, GP_KEY_M
, GP_KEY_COMMA
, GP_KEY_DOT
,
41 GP_KEY_SLASH
, 0, 0, 0,
42 GP_KEY_SPACE
, 0, GP_KEY_F1
, GP_KEY_F2
,
43 GP_KEY_F3
, GP_KEY_F4
, GP_KEY_F5
, GP_KEY_F6
,
44 GP_KEY_F7
, GP_KEY_F8
, GP_KEY_F9
, GP_KEY_F10
,
45 GP_KEY_NUM_LOCK
, 0, 0, 0,
49 0, 0, GP_KEY_F11
, GP_KEY_F12
,
76 /* X11 KeySyms to load dynamically */
82 static const struct keytable sym_to_key
[] = {
85 {XK_Down
, GP_KEY_DOWN
},
86 {XK_Left
, GP_KEY_LEFT
},
87 {XK_Right
, GP_KEY_RIGHT
},
88 {XK_Home
, GP_KEY_HOME
},
89 {XK_Page_Up
, GP_KEY_PAGE_UP
},
90 {XK_Page_Down
, GP_KEY_PAGE_DOWN
},
94 {XK_BackSpace
, GP_KEY_BACKSPACE
},
96 {XK_Escape
, GP_KEY_ESC
},
97 {XK_Delete
, GP_KEY_DELETE
},
98 {XK_Insert
, GP_KEY_INSERT
},
99 {XK_Sys_Req
, GP_KEY_SYSRQ
},
100 {XK_Pause
, GP_KEY_PAUSE
},
101 {XK_Scroll_Lock
, GP_KEY_SCROLL_LOCK
},
104 {XK_Shift_L
, GP_KEY_LEFT_SHIFT
},
105 {XK_Shift_R
, GP_KEY_RIGHT_SHIFT
},
106 {XK_Alt_L
, GP_KEY_LEFT_ALT
},
107 {XK_Alt_R
, GP_KEY_RIGHT_ALT
},
108 {XK_Control_L
, GP_KEY_LEFT_CTRL
},
109 {XK_Control_R
, GP_KEY_RIGHT_CTRL
},
110 {XK_Caps_Lock
, GP_KEY_CAPS_LOCK
},
111 {XK_Super_L
, GP_KEY_LEFT_META
},
112 {XK_Super_R
, GP_KEY_RIGHT_META
},
113 {XK_Menu
, GP_KEY_COMPOSE
},
116 {XK_KP_Enter
, GP_KEY_KP_ENTER
},
117 {XK_KP_0
, GP_KEY_KP_0
},
118 {XK_KP_1
, GP_KEY_KP_1
},
119 {XK_KP_2
, GP_KEY_KP_2
},
120 {XK_KP_3
, GP_KEY_KP_3
},
121 {XK_KP_4
, GP_KEY_KP_4
},
122 {XK_KP_5
, GP_KEY_KP_5
},
123 {XK_KP_6
, GP_KEY_KP_6
},
124 {XK_KP_7
, GP_KEY_KP_7
},
125 {XK_KP_8
, GP_KEY_KP_8
},
126 {XK_KP_9
, GP_KEY_KP_9
},
127 {XK_KP_Add
, GP_KEY_KP_PLUS
},
128 {XK_KP_Subtract
, GP_KEY_KP_MINUS
},
129 {XK_KP_Decimal
, GP_KEY_KP_DOT
},
130 {XK_KP_Divide
, GP_KEY_KP_SLASH
},
131 {XK_KP_Multiply
, GP_KEY_KP_ASTERISK
},
134 {XF86XK_AudioLowerVolume
, GP_KEY_VOLUMEDOWN
},
135 {XF86XK_AudioRaiseVolume
, GP_KEY_VOLUMEUP
},
136 {XF86XK_AudioMute
, GP_KEY_MUTE
},
137 {XF86XK_AudioNext
, GP_KEY_NEXTSONG
},
138 {XF86XK_AudioPrev
, GP_KEY_PREVIOUSSONG
},
139 {XF86XK_AudioPlay
, GP_KEY_PLAYPAUSE
},
142 static void x11_input_init(void)
144 GP_DEBUG(1, "Initializing X11 KeyCode table");
148 for (i
= 0; i
< GP_ARRAY_SIZE(sym_to_key
); i
++) {
149 unsigned int keycode
;
151 keycode
= XKeysymToKeycode(x11_conn
.dpy
,
152 sym_to_key
[i
].x_keysym
);
155 GP_DEBUG(1, "KeySym '%s' (%u) not defined",
156 XKeysymToString(sym_to_key
[i
].x_keysym
),
157 sym_to_key
[i
].x_keysym
);
161 GP_DEBUG(3, "Mapping Key '%s' KeySym '%s' (%u) to KeyCode %u",
162 GP_EventKeyName(sym_to_key
[i
].key
),
163 XKeysymToString(sym_to_key
[i
].x_keysym
),
164 sym_to_key
[i
].x_keysym
,
167 if (keycode
- 9 >= GP_ARRAY_SIZE(keycode_table
)) {
168 GP_WARN("Key '%s' keycode %u out of table",
169 GP_EventKeyName(sym_to_key
[i
].key
), keycode
);
173 if (keycode_table
[keycode
- 9]) {
174 GP_WARN("Key '%s' keycode %u collides with key '%s'",
175 GP_EventKeyName(sym_to_key
[i
].key
), keycode
,
176 GP_EventKeyName(keycode_table
[keycode
- 9]));
180 keycode_table
[keycode
- 9] = sym_to_key
[i
].key
;
184 static unsigned int get_key(unsigned int xkey
)
186 unsigned int key
= 0;
188 if (xkey
> 8 && xkey
- 9 <= GP_ARRAY_SIZE(keycode_table
))
189 key
= keycode_table
[xkey
- 9];
192 GP_WARN("Unmapped X11 keycode 0x%02x %u", xkey
, xkey
);
197 static void x11_input_event_put(struct GP_EventQueue
*event_queue
,
198 XEvent
*ev
, int w
, int h
)
200 int key
= 0, press
= 0;
206 switch (ev
->xbutton
.button
) {
219 GP_EventQueuePush(event_queue
, GP_EV_REL
,
220 GP_EV_REL_WHEEL
, 1, NULL
);
224 GP_EventQueuePush(event_queue
, GP_EV_REL
,
225 GP_EV_REL_WHEEL
, -1, NULL
);
230 GP_WARN("Unmapped X11 button %02x",
235 GP_EventQueuePush(event_queue
, GP_EV_KEY
, key
, press
, NULL
);
237 case ConfigureNotify
:
238 GP_EventQueuePushResize(event_queue
, ev
->xconfigure
.width
,
239 ev
->xconfigure
.height
, NULL
);
243 /* Ignore all pointer events that are out of the window */
244 if (ev
->xmotion
.x
< 0 || ev
->xmotion
.y
< 0 ||
245 ev
->xmotion
.x
> w
|| ev
->xmotion
.y
> h
)
248 GP_EventQueuePushRelTo(event_queue
,
249 ev
->xmotion
.x
, ev
->xmotion
.y
, NULL
);
254 key
= get_key(ev
->xkey
.keycode
);
259 GP_EventQueuePushKey(event_queue
, key
, press
, NULL
);
263 if ((Atom
)ev
->xclient
.data
.l
[0] == x11_conn
.A_WM_DELETE_WINDOW
) {
264 GP_EventQueuePush(event_queue
, GP_EV_SYS
,
265 GP_EV_SYS_QUIT
, 0, NULL
);
268 GP_WARN("Unknown X Client Message");
271 GP_DEBUG(1, "MapNotify event received");
274 GP_DEBUG(1, "ReparentNotify event received");
277 GP_DEBUG(1, "GravityNotify event received");
280 GP_DEBUG(1, "UnmapNotify event received");
283 GP_WARN("Unhandled X11 event type %u", ev
->type
);