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-2012 Cyril Hrubis <metan@ucw.cz> *
21 *****************************************************************************/
27 #include "GP_Common.h"
30 /* Screen size for clipping the cursor possition */
31 static uint32_t screen_w
= 0, screen_h
= 0;
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
)
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
)
103 *ev
= event_queue
[queue_first
];
105 queue_first
= (queue_first
+ 1) % GP_EVENT_QUEUE_SIZE
;
110 const char *GP_EventKeyName(enum GP_EventKeyValue key
)
112 if (key
< key_names_size
)
113 return key_names
[key
];
119 return "RightButton";
121 return "MiddleButton";
130 static void dump_rel(struct GP_Event
*ev
)
136 printf("Position %u %u\n", ev
->cursor_x
, ev
->cursor_y
);
138 case GP_EV_REL_WHEEL
:
139 printf("Wheel %i\n", ev
->val
.val
);
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
)
160 printf("Position %u %u %u\n",
161 ev
->cursor_x
, ev
->cursor_y
, ev
->val
.abs
.pressure
);
166 static void dump_sys(struct GP_Event
*ev
)
170 printf("Sys Quit\n");
172 case GP_EV_SYS_RESIZE
:
173 printf("Sys Resize %ux%u\n", ev
->val
.sys
.w
, ev
->val
.sys
.h
);
178 void GP_EventDump(struct GP_Event
*ev
)
180 printf("Event (%u) ", (unsigned int)ev
->time
.tv_sec
% 10000);
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");
209 event_queue
[queue_last
] = *ev
;
213 static void set_time(struct timeval
*time
)
216 gettimeofday(&cur_state
.time
, NULL
);
218 cur_state
.time
= *time
;
221 static uint32_t clip_rel(uint32_t val
, uint32_t max
, int32_t rel
)
224 if (val
< GP_ABS(rel
))
230 if (val
+ rel
>= max
)
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
)
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
;
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
)
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
;
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.
285 cur_state
.cursor_x
= x
* (screen_w
- 1) / x_max
;
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
)
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
;
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',
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',
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
];
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
)
354 GP_EventResetKey(&cur_state
, key
);
357 GP_EventSetKey(&cur_state
, key
);
359 case GP_EV_KEY_REPEAT
:
362 fprintf(stderr
, "Invalid key event code %u\n", code
);
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
);
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
)
383 GP_EventPushKey(code
, value
, time
);
386 cur_state
.type
= type
;
387 cur_state
.code
= code
;
388 cur_state
.val
.val
= value
;
392 event_put(&cur_state
);