loaders: PNG: Handle gamma on 16bpp conversion
[gfxprim.git] / libs / backends / GP_X11_Input.h
blob6305874ec240db98bbeb57844a7e4cc1921734eb
1 /*****************************************************************************
2 * This file is part of gfxprim library. *
3 * *
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. *
8 * *
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. *
13 * *
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 *
18 * *
19 * Copyright (C) 2009-2013 Cyril Hrubis <metan@ucw.cz> *
20 * *
21 *****************************************************************************/
23 #include <X11/keysym.h>
24 #include <X11/XF86keysym.h>
26 /* X11 keycodes */
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,
46 0, 0, 0, 0,
47 0, 0, 0, 0,
48 0, 0, 0, 0,
49 0, 0, GP_KEY_F11, GP_KEY_F12,
50 0, 0, 0, 0,
51 0, 0, 0, 0,
52 0, 0, 0, 0,
53 0, 0, 0, 0,
54 0, 0, 0, 0,
55 0, 0, 0, 0,
56 0, 0, 0, 0,
57 0, 0, 0, 0,
58 0, 0, 0, 0,
59 0, 0, 0, 0,
60 0, 0, 0, 0,
61 0, 0, 0, 0,
62 0, 0, 0, 0,
63 0, 0, 0, 0,
64 0, 0, 0, 0,
65 0, 0, 0, 0,
66 0, 0, 0, 0,
67 0, 0, 0, 0,
68 0, 0, 0, 0,
69 0, 0, 0, 0,
70 0, 0, 0, 0,
71 0, 0, 0, 0,
72 0, 0, 0, 0,
73 0, 0, 0, 0,
76 /* X11 KeySyms to load dynamically */
77 struct keytable {
78 uint32_t x_keysym;
79 uint16_t key;
82 static const struct keytable sym_to_key[] = {
83 /* Cursor control */
84 {XK_Up, GP_KEY_UP},
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},
91 {XK_End, GP_KEY_END},
93 /* TTY Keys */
94 {XK_BackSpace, GP_KEY_BACKSPACE},
95 {XK_Tab, GP_KEY_TAB},
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},
103 /* Modifiers */
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},
115 /* keypad */
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},
133 /* Multimedia */
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");
146 unsigned int i;
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);
154 if (keycode == 0) {
155 GP_DEBUG(1, "KeySym '%s' (%u) not defined",
156 XKeysymToString(sym_to_key[i].x_keysym),
157 sym_to_key[i].x_keysym);
158 continue;
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,
165 keycode);
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);
170 continue;
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]));
177 continue;
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];
191 if (key == 0)
192 GP_WARN("Unmapped X11 keycode 0x%02x %u", xkey, xkey);
194 return key;
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;
202 switch (ev->type) {
203 case ButtonPress:
204 press = 1;
205 case ButtonRelease:
206 switch (ev->xbutton.button) {
207 case 1:
208 key = GP_BTN_LEFT;
209 break;
210 case 2:
211 key = GP_BTN_MIDDLE;
212 break;
213 case 3:
214 key = GP_BTN_RIGHT;
215 break;
216 /* Mouse wheel */
217 case 4:
218 if (press)
219 GP_EventQueuePush(event_queue, GP_EV_REL,
220 GP_EV_REL_WHEEL, 1, NULL);
221 return;
222 case 5:
223 if (press)
224 GP_EventQueuePush(event_queue, GP_EV_REL,
225 GP_EV_REL_WHEEL, -1, NULL);
226 return;
229 if (key == 0) {
230 GP_WARN("Unmapped X11 button %02x",
231 ev->xbutton.button);
232 return;
235 GP_EventQueuePush(event_queue, GP_EV_KEY, key, press, NULL);
236 break;
237 case ConfigureNotify:
238 GP_EventQueuePushResize(event_queue, ev->xconfigure.width,
239 ev->xconfigure.height, NULL);
240 break;
241 break;
242 case MotionNotify:
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)
246 return;
248 GP_EventQueuePushRelTo(event_queue,
249 ev->xmotion.x, ev->xmotion.y, NULL);
250 break;
251 case KeyPress:
252 press = 1;
253 case KeyRelease:
254 key = get_key(ev->xkey.keycode);
256 if (key == 0)
257 return;
259 GP_EventQueuePushKey(event_queue, key, press, NULL);
260 break;
261 /* events from WM */
262 case ClientMessage:
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);
266 return;
268 GP_WARN("Unknown X Client Message");
269 break;
270 case MapNotify:
271 GP_DEBUG(1, "MapNotify event received");
272 break;
273 case ReparentNotify:
274 GP_DEBUG(1, "ReparentNotify event received");
275 break;
276 case GravityNotify:
277 GP_DEBUG(1, "GravityNotify event received");
278 break;
279 case UnmapNotify:
280 GP_DEBUG(1, "UnmapNotify event received");
281 break;
282 default:
283 GP_WARN("Unhandled X11 event type %u", ev->type);