input: Fix ascii mapping table.
[gfxprim.git] / libs / input / GP_Event.c
blob01afef2271b900a57fd6ec005d71df62394f4df4
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-2011 Cyril Hrubis <metan@ucw.cz> *
20 * *
21 *****************************************************************************/
23 #include <stdio.h>
24 #include <string.h>
25 #include <stdlib.h>
27 #include "GP_Common.h"
28 #include "GP_Event.h"
30 /* Screen size for clipping the cursor possition */
31 static uint32_t screen_w = 0, screen_h = 0;
33 /* Event queue */
34 static uint32_t queue_first = 0, queue_last = 0;
35 static struct GP_Event event_queue[GP_EVENT_QUEUE_SIZE];
37 /* Global input state */
38 static struct GP_Event cur_state = {.cursor_x = 0, .cursor_y = 0};
40 static char *key_names[] = {
41 "Reserved", "Escape", "1", "2", "3",
42 "4", "5", "6", "7", "8",
43 "9", "0", "Minus", "Equal", "BackSpace",
44 "Tab", "Q", "W", "E", "R",
45 "T", "Y", "U", "I", "O",
46 "P", "LeftBrace", "RightBrace", "Enter", "LeftCtrl",
47 "A", "S", "D", "F", "G",
48 "H", "J", "K", "L", "Semicolon",
49 "Apostrophe", "Grave", "LeftShift", "BackSlash", "Z",
50 "X", "C", "V", "B", "N",
51 "M", "Comma", "Dot", "Slash", "RightShift",
52 "KP Asterisk", "LeftAlt", "Space", "CapsLock", "F1",
53 "F2", "F3", "F4", "F5", "F6",
54 "F7", "F8", "F9", "F10", "NumLock",
55 "ScrollLock", "KP 7", "KP 8", "KP 9", "KP Minus",
56 "KP 4", "KP 5", "KP 6", "KP Plus", "KP 1",
57 "KP 2", "KP 3", "KP 0", "KP Dot", "?",
58 "?", "?", "F11", "F12", "?",
59 "?", "?", "?", "?", "?",
60 "?", "KP Enter", "RightCtrl", "KP Slash", "SysRq",
61 "RightAlt", "?", "Home", "Up", "PageUp",
62 "Left", "Right", "End", "Down", "PageDown",
63 "Insert", "Delete", "?", "?", "?",
64 "?", "?", "KP Equal", "KP PlusMinus", "Pause",
65 "?", "KP Comma", "?", "?", "?",
66 "LeftMeta", "RightMeta", "Compose",
69 static uint16_t key_names_size = sizeof(key_names)/sizeof(void*);
71 void GP_EventSetScreenSize(uint32_t w, uint32_t h)
73 screen_w = w;
74 screen_h = h;
76 /* clip cursor */
77 if (cur_state.cursor_x >= w)
78 cur_state.cursor_x = w - 1;
80 if (cur_state.cursor_y >= h)
81 cur_state.cursor_y = h - 1;
84 void GP_EventSetScreenCursor(uint32_t x, uint32_t y)
86 cur_state.cursor_x = x;
87 cur_state.cursor_y = y;
90 uint32_t GP_EventQueued(void)
92 if (queue_first <= queue_last)
93 return queue_last - queue_first;
95 return GP_EVENT_QUEUE_SIZE - (queue_last - queue_first);
98 int GP_EventGet(struct GP_Event *ev)
100 if (queue_first == queue_last)
101 return 0;
103 *ev = event_queue[queue_first];
105 queue_first = (queue_first + 1) % GP_EVENT_QUEUE_SIZE;
107 return 1;
110 const char *GP_EventKeyName(enum GP_EventKeyValue key)
112 if (key < key_names_size)
113 return key_names[key];
115 switch (key) {
116 case GP_BTN_LEFT:
117 return "LeftButton";
118 case GP_BTN_RIGHT:
119 return "RightButton";
120 case GP_BTN_MIDDLE:
121 return "MiddleButton";
122 case GP_BTN_PEN:
123 return "Pen";
124 default:
125 return "Unknown";
130 static void dump_rel(struct GP_Event *ev)
132 printf("REL ");
134 switch (ev->code) {
135 case GP_EV_REL_POS:
136 printf("POSSITION %u %u\n", ev->cursor_x, ev->cursor_y);
137 break;
138 case GP_EV_REL_WHEEL:
139 printf("WHEEL %i\n", ev->val.val);
140 break;
144 static void dump_key(struct GP_Event *ev)
146 const char *name = GP_EventKeyName(ev->val.key.key);
148 if (ev->val.key.key < key_names_size)
149 name = key_names[ev->val.key.key];
151 printf("KEY %i (Key%s) %s\n",
152 ev->val.key.key, name, ev->code ? "down" : "up");
156 static void dump_abs(struct GP_Event *ev)
158 switch (ev->code) {
159 case GP_EV_ABS_POS:
160 printf("POSSITION %u %u %u\n",
161 ev->cursor_x, ev->cursor_y, ev->val.abs.pressure);
162 break;
166 void GP_EventDump(struct GP_Event *ev)
168 printf("EVENT (%u) ", (unsigned int)ev->time.tv_sec % 10000);
170 switch (ev->type) {
171 case GP_EV_KEY:
172 dump_key(ev);
173 break;
174 case GP_EV_REL:
175 dump_rel(ev);
176 break;
177 case GP_EV_ABS:
178 dump_abs(ev);
179 break;
180 default:
181 printf("Unknown %u\n", ev->type);
185 static void event_put(struct GP_Event *ev)
187 uint32_t next = (queue_last + 1) % GP_EVENT_QUEUE_SIZE;
189 if (next == queue_first) {
190 fprintf(stderr, "Event queue full, dropping event\n");
191 return;
194 event_queue[queue_last] = *ev;
195 queue_last = next;
198 static void set_time(struct timeval *time)
200 if (time == NULL)
201 gettimeofday(&cur_state.time, NULL);
202 else
203 cur_state.time = *time;
206 static uint32_t clip_rel(uint32_t val, uint32_t max, int32_t rel)
208 if (rel < 0) {
209 if (val < GP_ABS(rel))
210 return 0;
211 else
212 return val + rel;
215 if (val + rel >= max)
216 return max - 1;
218 return val + rel;
221 void GP_EventPushRel(int32_t rx, int32_t ry, struct timeval *time)
223 /* event header */
224 cur_state.type = GP_EV_REL;
225 cur_state.code = GP_EV_REL_POS;
227 cur_state.val.rel.rx = rx;
228 cur_state.val.rel.ry = ry;
230 set_time(time);
232 /* move the global cursor */
233 cur_state.cursor_x = clip_rel(cur_state.cursor_x, screen_w, rx);
234 cur_state.cursor_y = clip_rel(cur_state.cursor_y, screen_h, ry);
236 /* put it into queue */
237 event_put(&cur_state);
240 void GP_EventPushAbs(uint32_t x, uint32_t y, uint32_t pressure,
241 uint32_t x_max, uint32_t y_max, uint32_t pressure_max,
242 struct timeval *time)
244 /* event header */
245 cur_state.type = GP_EV_ABS;
246 cur_state.code = GP_EV_ABS_POS;
247 cur_state.val.abs.x = x;
248 cur_state.val.abs.y = y;
249 cur_state.val.abs.pressure = pressure;
250 cur_state.val.abs.x_max = x_max;
251 cur_state.val.abs.y_max = y_max;
252 cur_state.val.abs.pressure_max = pressure_max;
254 set_time(time);
256 /* set global cursor, pressure == 0 is penup */
257 if (pressure != 0) {
258 cur_state.cursor_x = x * screen_w / x_max;
259 cur_state.cursor_y = y * screen_h / y_max;
262 /* put it into queue */
263 event_put(&cur_state);
266 static char keys_to_ascii[] = {
267 0x00, 0x1b, '1', '2', '3', '4', '5', '6', '7', '8',
268 '9', '0', '-', '=', 0x08, '\t', 'q', 'w', 'e', 'r',
269 't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n', 0x00,
270 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';',
271 '\'', '`', 0x00, '\\', 'z', 'x', 'c', 'v', 'b', 'n',
272 'm', ',', '.', '/', 0x00, '*', 0x00, ' ', 0x00, 0x00,
273 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
274 0x00, '7', '8', '9', '-', '4', '5', '6', '+', '1',
275 '2', '3', '0', '.'
278 static char keys_to_ascii_s[] = {
279 0x00, 0x1b, '!', '@', '#', '$', '%', '^', '&', '*',
280 '(', ')', '_', '+', 0x08, '\t', 'Q', 'W', 'E', 'R',
281 'T', 'Y', 'U', 'I', 'O', 'P', '{', '}', '\n', 0x00,
282 'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':',
283 '"', '~', 0x00, '|', 'Z', 'X', 'C', 'V', 'B', 'N',
284 'M', '<', '>', '?', 0x00, '*', 0x00, ' ', 0x00, 0x00,
285 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
286 0x00, '7', '8', '9', '-', '4', '5', '6', '+', '1',
287 '2', '3', '0', '.'
291 * Fills key ascii value accordingly to keys pressed.
293 static void key_to_ascii(GP_Event *ev)
295 ev->val.key.ascii = 0;
297 if (GP_EventGetKey(ev, GP_KEY_LEFT_SHIFT) ||
298 GP_EventGetKey(ev, GP_KEY_RIGHT_SHIFT)) {
299 if (ev->val.key.key < sizeof(keys_to_ascii_s))
300 ev->val.key.ascii = keys_to_ascii_s[ev->val.key.key];
301 } else {
302 if (ev->val.key.key < sizeof(keys_to_ascii))
303 ev->val.key.ascii = keys_to_ascii[ev->val.key.key];
307 void GP_EventPushKey(uint32_t key, uint8_t code, struct timeval *time)
309 switch (code) {
310 case GP_EV_KEY_UP:
311 GP_EventResetKey(&cur_state, key);
312 break;
313 case GP_EV_KEY_DOWN:
314 GP_EventSetKey(&cur_state, key);
315 break;
316 case GP_EV_KEY_REPEAT:
317 break;
318 default:
319 fprintf(stderr, "Invalid key event code %u\n", code);
320 return;
323 /* event header */
324 cur_state.type = GP_EV_KEY;
325 cur_state.code = code;
326 cur_state.val.key.key = key;
327 key_to_ascii(&cur_state);
329 set_time(time);
331 /* put it into queue */
332 event_put(&cur_state);
335 void GP_EventPush(uint16_t type, uint32_t code, int32_t value,
336 struct timeval *time)
338 switch (type) {
339 case GP_EV_KEY:
340 GP_EventPushKey(code, value, time);
341 break;
342 default:
343 cur_state.type = type;
344 cur_state.code = code;
345 cur_state.val.val = value;
347 set_time(time);
349 event_put(&cur_state);