spiv: PgUp and PgDown to scrolls by 10 images.
[gfxprim.git] / libs / input / GP_Event.c
blobfe118ff8e7d23a0ce454e9574cce3f980dab7e75
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-2012 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("Position %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("Position %u %u %u\n",
161 ev->cursor_x, ev->cursor_y, ev->val.abs.pressure);
162 break;
166 static void dump_sys(struct GP_Event *ev)
168 switch (ev->code) {
169 case GP_EV_SYS_QUIT:
170 printf("Sys Quit\n");
171 break;
172 case GP_EV_SYS_RESIZE:
173 printf("Sys Resize %ux%u\n", ev->val.sys.w, ev->val.sys.h);
174 break;
178 void GP_EventDump(struct GP_Event *ev)
180 printf("Event (%u) ", (unsigned int)ev->time.tv_sec % 10000);
182 switch (ev->type) {
183 case GP_EV_KEY:
184 dump_key(ev);
185 break;
186 case GP_EV_REL:
187 dump_rel(ev);
188 break;
189 case GP_EV_ABS:
190 dump_abs(ev);
191 break;
192 case GP_EV_SYS:
193 dump_sys(ev);
194 break;
195 default:
196 printf("Unknown %u\n", ev->type);
200 static void event_put(struct GP_Event *ev)
202 uint32_t next = (queue_last + 1) % GP_EVENT_QUEUE_SIZE;
204 if (next == queue_first) {
205 fprintf(stderr, "Event queue full, dropping event\n");
206 return;
209 event_queue[queue_last] = *ev;
210 queue_last = next;
213 static void set_time(struct timeval *time)
215 if (time == NULL)
216 gettimeofday(&cur_state.time, NULL);
217 else
218 cur_state.time = *time;
221 static uint32_t clip_rel(uint32_t val, uint32_t max, int32_t rel)
223 if (rel < 0) {
224 if (val < GP_ABS(rel))
225 return 0;
226 else
227 return val + rel;
230 if (val + rel >= max)
231 return max - 1;
233 return val + rel;
236 void GP_EventPushRelTo(uint32_t x, uint32_t y, struct timeval *time)
238 int32_t rx = x - cur_state.cursor_x;
239 int32_t ry = y - cur_state.cursor_y;
241 GP_EventPushRel(rx, ry, time);
244 void GP_EventPushRel(int32_t rx, int32_t ry, struct timeval *time)
246 /* event header */
247 cur_state.type = GP_EV_REL;
248 cur_state.code = GP_EV_REL_POS;
250 cur_state.val.rel.rx = rx;
251 cur_state.val.rel.ry = ry;
253 set_time(time);
255 /* move the global cursor */
256 cur_state.cursor_x = clip_rel(cur_state.cursor_x, screen_w, rx);
257 cur_state.cursor_y = clip_rel(cur_state.cursor_y, screen_h, ry);
259 /* put it into queue */
260 event_put(&cur_state);
263 void GP_EventPushAbs(uint32_t x, uint32_t y, uint32_t pressure,
264 uint32_t x_max, uint32_t y_max, uint32_t pressure_max,
265 struct timeval *time)
267 /* event header */
268 cur_state.type = GP_EV_ABS;
269 cur_state.code = GP_EV_ABS_POS;
270 cur_state.val.abs.x = x;
271 cur_state.val.abs.y = y;
272 cur_state.val.abs.pressure = pressure;
273 cur_state.val.abs.x_max = x_max;
274 cur_state.val.abs.y_max = y_max;
275 cur_state.val.abs.pressure_max = pressure_max;
277 set_time(time);
280 * Set global cursor, the packet could be partial, eg. update only x or
281 * only y. In such case x_max or y_max is zero.
284 if (x_max != 0)
285 cur_state.cursor_x = x * (screen_w - 1) / x_max;
287 if (y_max != 0)
288 cur_state.cursor_y = y * (screen_h - 1) / y_max;
290 /* put it into queue */
291 event_put(&cur_state);
294 void GP_EventPushResize(uint32_t w, uint32_t h, struct timeval *time)
296 /* event header */
297 cur_state.type = GP_EV_SYS;
298 cur_state.code = GP_EV_SYS_RESIZE;
300 cur_state.val.sys.w = w;
301 cur_state.val.sys.h = h;
303 set_time(time);
305 /* put it into queue */
306 event_put(&cur_state);
309 static char keys_to_ascii[] = {
310 0x00, 0x1b, '1', '2', '3', '4', '5', '6', '7', '8',
311 '9', '0', '-', '=', 0x08, '\t', 'q', 'w', 'e', 'r',
312 't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n', 0x00,
313 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';',
314 '\'', '`', 0x00, '\\', 'z', 'x', 'c', 'v', 'b', 'n',
315 'm', ',', '.', '/', 0x00, '*', 0x00, ' ', 0x00, 0x00,
316 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
317 0x00, '7', '8', '9', '-', '4', '5', '6', '+', '1',
318 '2', '3', '0', '.'
321 static char keys_to_ascii_s[] = {
322 0x00, 0x1b, '!', '@', '#', '$', '%', '^', '&', '*',
323 '(', ')', '_', '+', 0x08, '\t', 'Q', 'W', 'E', 'R',
324 'T', 'Y', 'U', 'I', 'O', 'P', '{', '}', '\n', 0x00,
325 'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':',
326 '"', '~', 0x00, '|', 'Z', 'X', 'C', 'V', 'B', 'N',
327 'M', '<', '>', '?', 0x00, '*', 0x00, ' ', 0x00, 0x00,
328 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
329 0x00, '7', '8', '9', '-', '4', '5', '6', '+', '1',
330 '2', '3', '0', '.'
334 * Fills key ascii value accordingly to keys pressed.
336 static void key_to_ascii(GP_Event *ev)
338 ev->val.key.ascii = 0;
340 if (GP_EventGetKey(ev, GP_KEY_LEFT_SHIFT) ||
341 GP_EventGetKey(ev, GP_KEY_RIGHT_SHIFT)) {
342 if (ev->val.key.key < sizeof(keys_to_ascii_s))
343 ev->val.key.ascii = keys_to_ascii_s[ev->val.key.key];
344 } else {
345 if (ev->val.key.key < sizeof(keys_to_ascii))
346 ev->val.key.ascii = keys_to_ascii[ev->val.key.key];
350 void GP_EventPushKey(uint32_t key, uint8_t code, struct timeval *time)
352 switch (code) {
353 case GP_EV_KEY_UP:
354 GP_EventResetKey(&cur_state, key);
355 break;
356 case GP_EV_KEY_DOWN:
357 GP_EventSetKey(&cur_state, key);
358 break;
359 case GP_EV_KEY_REPEAT:
360 break;
361 default:
362 fprintf(stderr, "Invalid key event code %u\n", code);
363 return;
366 /* event header */
367 cur_state.type = GP_EV_KEY;
368 cur_state.code = code;
369 cur_state.val.key.key = key;
370 key_to_ascii(&cur_state);
372 set_time(time);
374 /* put it into queue */
375 event_put(&cur_state);
378 void GP_EventPush(uint16_t type, uint32_t code, int32_t value,
379 struct timeval *time)
381 switch (type) {
382 case GP_EV_KEY:
383 GP_EventPushKey(code, value, time);
384 break;
385 default:
386 cur_state.type = type;
387 cur_state.code = code;
388 cur_state.val.val = value;
390 set_time(time);
392 event_put(&cur_state);