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-2011 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("POSSITION %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("POSSITION %u %u %u\n",
161 ev
->cursor_x
, ev
->cursor_y
, ev
->val
.abs
.pressure
);
166 void GP_EventDump(struct GP_Event
*ev
)
168 printf("EVENT (%u) ", (unsigned int)ev
->time
.tv_sec
% 10000);
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");
194 event_queue
[queue_last
] = *ev
;
198 static void set_time(struct timeval
*time
)
201 gettimeofday(&cur_state
.time
, NULL
);
203 cur_state
.time
= *time
;
206 static uint32_t clip_rel(uint32_t val
, uint32_t max
, int32_t rel
)
209 if (val
< GP_ABS(rel
))
215 if (val
+ rel
>= max
)
221 void GP_EventPushRel(int32_t rx
, int32_t ry
, struct timeval
*time
)
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
;
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
)
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
;
256 /* set global cursor, pressure == 0 is penup */
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',
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',
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
];
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
)
311 GP_EventResetKey(&cur_state
, key
);
314 GP_EventSetKey(&cur_state
, key
);
316 case GP_EV_KEY_REPEAT
:
319 fprintf(stderr
, "Invalid key event code %u\n", code
);
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
);
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
)
340 GP_EventPushKey(code
, value
, time
);
343 cur_state
.type
= type
;
344 cur_state
.code
= code
;
345 cur_state
.val
.val
= value
;
349 event_put(&cur_state
);