filename | src/display.c |
changeset | 1244:6b54ef5ed413 |
prev | 1239:be3121267597 |
next | 1245:01e0020adf88 |
author | nkeynes |
date | Tue Feb 28 18:22:52 2012 +1000 (12 years ago) |
permissions | -rw-r--r-- |
last change | Add a GL-only video driver for android usage (since the Java code is responsible for creating the context) |
view | annotate | diff | log | raw |
1 /**
2 * $Id$
3 *
4 * Generic support for keyboard and other input sources. The active display
5 * driver is expected to deliver events here, where they're translated and
6 * passed to the appropriate dreamcast controllers (if any).
7 *
8 * Copyright (c) 2005 Nathan Keynes.
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 */
21 #include <stdint.h>
22 #include <assert.h>
23 #include "dream.h"
24 #include "display.h"
25 #include "pvr2/pvr2.h"
27 display_driver_t display_driver_list[] = {
28 #ifdef HAVE_GTK
29 &display_gtk_driver,
30 #else
31 #ifdef HAVE_COCOA
32 &display_osx_driver,
33 #endif
34 #endif
35 #ifdef __ANDROID__
36 &display_gl_driver,
37 #endif
38 &display_null_driver,
39 NULL };
41 /* Some explanation:
42 * The system has at least one "root" device representing the main display
43 * (which may be the null display). This device is part of the display_driver
44 * and generates events with no input_driver. The root device has no id
45 * as such (for the purposes of event names)
46 *
47 * The system may also have one or more auxilliary devices which each have
48 * an input_driver and an id (eg "JS0"). So the keysym "Return" is (de)coded by
49 * the root device, and the keysym "JS0: Button0" is (de)coded by the JS0 input
50 * device as "Button0".
51 *
52 * For the moment, mice are handled specially, as they behave a little
53 * differently from other devices (although this will probably change in the
54 * future.
55 */
58 typedef struct keymap_entry {
59 input_key_callback_t callback;
60 void *data;
61 uint32_t value;
62 lxdream_config_group_t group;
63 struct keymap_entry *next; // allow chaining
64 } *keymap_entry_t;
66 typedef struct mouse_entry {
67 gboolean relative;
68 input_mouse_callback_t callback;
69 void *data;
70 const lxdream_config_group_t group;
71 struct mouse_entry *next;
72 } *mouse_entry_t;
74 typedef struct input_driver_entry {
75 input_driver_t driver;
76 uint16_t entry_count;
77 struct keymap_entry *keymap[0];
78 } *input_driver_entry_t;
81 #ifndef GL_RGBA8
82 #define GL_RGBA8 GL_RGBA8_OES
83 #endif
85 #ifndef GL_RGB5
86 #define GL_RGB5 GL_RGB565
87 #endif
89 #ifndef GL_BGR
90 #define GL_BGR GL_BGRA
91 #endif
93 /**
94 * Colour format information
95 */
96 struct colour_format colour_formats[] = {
97 { GL_UNSIGNED_SHORT_1_5_5_5_REV, GL_BGRA, GL_RGB5_A1, 2 },
98 { GL_UNSIGNED_SHORT_5_6_5, GL_RGB, GL_RGB5, 2 },
99 { GL_UNSIGNED_SHORT_4_4_4_4_REV, GL_BGRA, GL_RGBA4, 2 },
100 { GL_UNSIGNED_BYTE, GL_BGRA, GL_RGBA8, 4 }, /* YUV decoded to ARGB8888 */
101 { GL_UNSIGNED_BYTE, GL_BGR, GL_RGB, 3 },
102 { GL_UNSIGNED_BYTE, GL_BGRA, GL_RGBA8, 4 },
103 { GL_UNSIGNED_BYTE, GL_BGRA, GL_RGBA8, 4 }, /* Index4 decoded */
104 { GL_UNSIGNED_BYTE, GL_BGRA, GL_RGBA8, 4 }, /* Index8 decoded */
105 { GL_UNSIGNED_BYTE, GL_BGRA, GL_RGBA8, 4 },
106 { GL_UNSIGNED_BYTE, GL_RGB, GL_RGB, 3 },
108 };
110 /**
111 * FIXME: make this more memory efficient
112 */
113 static struct keymap_entry *root_keymap[65535];
114 static struct keymap_entry *keyhooks = NULL;
115 static gboolean display_focused = TRUE;
116 static GList *input_drivers= NULL;
117 static display_keysym_callback_t display_keysym_hook = NULL;
118 void *display_keysym_hook_data;
120 gboolean input_register_device( input_driver_t driver, uint16_t max_keycode )
121 {
122 GList *ptr;
123 for( ptr = input_drivers; ptr != NULL; ptr = g_list_next(ptr) ) {
124 input_driver_entry_t entry = (input_driver_entry_t)ptr->data;
125 if( strcasecmp( entry->driver->id, driver->id ) == 0 ) {
126 return FALSE;
127 }
128 }
130 input_driver_entry_t entry = g_malloc0( sizeof(struct input_driver_entry) + (sizeof(keymap_entry_t) * max_keycode) );
131 entry->driver = driver;
132 entry->entry_count = max_keycode;
133 input_drivers = g_list_append( input_drivers, entry );
134 return TRUE;
135 }
137 gboolean input_has_device( const gchar *id )
138 {
139 GList *ptr;
140 for( ptr = input_drivers; ptr != NULL; ptr = g_list_next(ptr) ) {
141 input_driver_entry_t entry = (input_driver_entry_t)ptr->data;
142 if( strcasecmp(entry->driver->id, id) == 0 ) {
143 return TRUE;
144 }
145 }
146 return FALSE;
147 }
150 void input_unregister_device( input_driver_t driver )
151 {
152 GList *ptr;
153 for( ptr = input_drivers; ptr != NULL; ptr = g_list_next(ptr) ) {
154 input_driver_entry_t entry = (input_driver_entry_t)ptr->data;
155 if( entry->driver == driver ) {
156 if( driver->destroy != NULL ) {
157 driver->destroy(driver);
158 }
159 input_drivers = g_list_remove(input_drivers, (gpointer)entry);
160 g_free( entry );
161 return;
162 }
163 }
164 }
166 /**
167 * Resolve the keysym and return a pointer to the keymap entry pointer
168 * @return keymap pointer or NULL if the key was unresolved
169 */
170 static struct keymap_entry **input_entry_from_keysym( const gchar *keysym )
171 {
172 if( keysym == NULL || keysym[0] == 0 ) {
173 return NULL;
174 }
175 char **strv = g_strsplit(keysym,":",2);
176 if( strv[1] == NULL ) {
177 /* root device */
178 if( display_driver == NULL || display_driver->resolve_keysym == NULL) {
179 // Root device has no input handling
180 g_strfreev(strv);
181 return NULL;
182 }
183 uint16_t keycode = display_driver->resolve_keysym(g_strstrip(strv[0]));
184 g_strfreev(strv);
185 if( keycode == 0 ) {
186 return NULL;
187 }
188 return &root_keymap[keycode-1];
190 } else {
191 char *id = g_strstrip(strv[0]);
192 GList *ptr;
193 for( ptr = input_drivers; ptr != NULL; ptr = g_list_next(ptr) ) {
194 input_driver_entry_t entry = (input_driver_entry_t)ptr->data;
195 if( strcasecmp( entry->driver->id, id ) == 0 ) {
196 /* we have ze device */
197 if( entry->driver->resolve_keysym == NULL ) {
198 g_strfreev(strv);
199 return NULL;
200 }
201 uint16_t keycode = entry->driver->resolve_keysym(entry->driver, g_strstrip(strv[1]));
202 g_strfreev(strv);
203 if( keycode == 0 || keycode > entry->entry_count ) {
204 return NULL;
205 }
206 return &entry->keymap[keycode-1];
207 }
208 }
209 g_strfreev(strv);
210 return NULL; // device not found
211 }
212 }
214 static struct keymap_entry **input_entry_from_keycode( input_driver_t driver, uint16_t keycode )
215 {
216 GList *ptr;
218 if( keycode == 0 ) {
219 return NULL;
220 }
222 if( driver == NULL ) {
223 return &root_keymap[keycode-1];
224 }
226 for( ptr = input_drivers; ptr != NULL; ptr = g_list_next(ptr) ) {
227 input_driver_entry_t entry = (input_driver_entry_t)ptr->data;
228 if( entry->driver == driver ) {
229 if( keycode > entry->entry_count ) {
230 return NULL;
231 } else {
232 return &entry->keymap[keycode-1];
233 }
234 }
235 }
236 return NULL;
237 }
239 gchar *input_keycode_to_keysym( input_driver_t driver, uint16_t keycode )
240 {
241 if( keycode == 0 ) {
242 return NULL;
243 }
244 if( driver == NULL ) {
245 if( display_driver != NULL && display_driver->get_keysym_for_keycode != NULL ) {
246 return display_driver->get_keysym_for_keycode(keycode);
247 }
248 } else if( driver->get_keysym_for_keycode ) {
249 gchar *sym = driver->get_keysym_for_keycode(driver,keycode);
250 if( sym != NULL ) {
251 gchar *result = g_strdup_printf( "%s: %s", driver->id, sym );
252 g_free(sym);
253 return result;
254 }
255 }
256 return NULL;
257 }
260 gboolean input_register_key( const gchar *keysym, input_key_callback_t callback,
261 void *data, uint32_t value )
262 {
263 if( keysym == NULL ) {
264 return FALSE;
265 }
266 int keys = 0;
267 gchar **strv = g_strsplit(keysym, ",", 16);
268 gchar **s = strv;
269 while( *s != NULL ) {
270 keymap_entry_t *entryp = input_entry_from_keysym(*s);
271 if( entryp != NULL ) {
272 keymap_entry_t newentry = g_malloc0(sizeof(struct keymap_entry));
273 newentry->next = *entryp;
274 newentry->callback = callback;
275 newentry->data = data;
276 newentry->value = value;
277 *entryp = newentry;
278 keys++;
279 }
280 s++;
281 }
282 g_strfreev(strv);
283 return keys != 0;
284 }
286 void input_unregister_key( const gchar *keysym, input_key_callback_t callback,
287 void *data, uint32_t value )
288 {
289 if( keysym == NULL ) {
290 return;
291 }
293 gchar **strv = g_strsplit(keysym, ",", 16);
294 gchar **s = strv;
295 while( *s != NULL ) {
296 keymap_entry_t *entryp = input_entry_from_keysym(*s);
297 if( entryp != NULL ) {
298 while( *entryp != NULL ) {
299 if( (*entryp)->callback == callback &&
300 (*entryp)->data == data && (*entryp)->value == value ) {
301 keymap_entry_t next = (*entryp)->next;
302 g_free( *entryp );
303 *entryp = next;
304 break;
305 }
306 entryp = &(*entryp)->next; // Yes, really
307 }
308 }
309 s++;
310 }
311 g_strfreev(strv);
312 }
314 int input_register_keygroup( lxdream_config_group_t group)
315 {
316 int i;
317 int result = 0;
318 for( i=0; group->params[i].key != NULL; i++ ) {
319 if( group->params[i].type == CONFIG_TYPE_KEY ) {
320 if( input_register_key( group->params[i].value, group->key_binding, group->data, group->params[i].tag ) ) {
321 result++;
322 }
323 }
324 }
325 return result;
326 }
328 void input_unregister_keygroup( lxdream_config_group_t group )
329 {
330 int i;
331 for( i=0; group->params[i].key != NULL; i++ ) {
332 if( group->params[i].type == CONFIG_TYPE_KEY ) {
333 input_unregister_key( group->params[i].value, group->key_binding, group->data, group->params[i].tag );
334 }
335 }
336 }
338 gboolean input_keygroup_changed( void *data, lxdream_config_group_t group, unsigned key,
339 const gchar *oldval, const gchar *newval )
340 {
341 input_unregister_key( oldval, group->key_binding, group->data, group->params[key].tag );
342 input_register_key( newval, group->key_binding, group->data, group->params[key].tag );
343 return TRUE;
344 }
346 gboolean input_register_keyboard_hook( input_key_callback_t callback,
347 void *data )
348 {
349 keymap_entry_t key = malloc( sizeof( struct keymap_entry ) );
350 assert( key != NULL );
351 key->callback = callback;
352 key->data = data;
353 key->next = keyhooks;
354 keyhooks = key;
355 return TRUE;
356 }
358 void input_unregister_keyboard_hook( input_key_callback_t callback,
359 void *data )
360 {
361 keymap_entry_t key = keyhooks;
362 if( key != NULL ) {
363 if( key->callback == callback && key->data == data ) {
364 keyhooks = keyhooks->next;
365 free(key);
366 return;
367 }
368 while( key->next != NULL ) {
369 if( key->next->callback == callback && key->next->data == data ) {
370 keymap_entry_t next = key->next;
371 key->next = next->next;
372 free(next);
373 return;
374 }
375 key = key->next;
376 }
377 }
378 }
380 gboolean input_is_key_valid( const gchar *keysym )
381 {
382 keymap_entry_t *ptr = input_entry_from_keysym(keysym);
383 return ptr != NULL;
384 }
386 gboolean input_is_key_registered( const gchar *keysym )
387 {
388 keymap_entry_t *ptr = input_entry_from_keysym(keysym);
389 return ptr != NULL && *ptr != NULL;
390 }
392 void input_event_keydown( input_driver_t driver, uint16_t keycode, uint32_t pressure )
393 {
394 if( display_focused ) {
395 keymap_entry_t *entryp = input_entry_from_keycode(driver,keycode);
396 if( entryp != NULL ) {
397 keymap_entry_t key = *entryp;
398 while( key != NULL ) {
399 key->callback( key->data, key->value, pressure, TRUE );
400 key = key->next;
401 }
402 }
403 if( driver == NULL ) {
404 keymap_entry_t key = keyhooks;
405 while( key != NULL ) {
406 key->callback( key->data, keycode, pressure, TRUE );
407 key = key->next;
408 }
409 }
410 }
411 if( display_keysym_hook != NULL ) {
412 gchar *sym = input_keycode_to_keysym( driver, keycode );
413 if( sym != NULL ) {
414 display_keysym_hook(display_keysym_hook_data, sym);
415 g_free(sym);
416 }
417 }
418 }
420 void input_event_keyup( input_driver_t driver, uint16_t keycode )
421 {
422 if( display_focused ) {
423 keymap_entry_t *entryp = input_entry_from_keycode(driver,keycode);
424 if( entryp != NULL ) {
425 keymap_entry_t key = *entryp;
426 while( key != NULL ) {
427 key->callback( key->data, key->value, 0, FALSE );
428 key = key->next;
429 }
430 }
432 if( driver == NULL ) {
433 keymap_entry_t key = keyhooks;
434 while( key != NULL ) {
435 key->callback( key->data, keycode, 0, FALSE );
436 key = key->next;
437 }
438 }
439 }
440 }
442 uint16_t input_keycode_to_dckeysym( uint16_t keycode )
443 {
444 return display_driver->convert_to_dckeysym(keycode);
445 }
447 void input_set_keysym_hook( display_keysym_callback_t hook, void *data )
448 {
449 display_keysym_hook = hook;
450 display_keysym_hook_data = data;
451 }
453 /***************** System mouse driver ****************/
455 static struct keymap_entry *mouse_keymap[MAX_MOUSE_BUTTONS];
456 static struct mouse_entry *mousehooks = NULL;
457 static uint32_t mouse_x = -1, mouse_y = -1, mouse_buttons = 0;
459 uint16_t mouse_resolve_keysym( struct input_driver *driver, const gchar *keysym )
460 {
461 if( strncasecmp( keysym, "Button", 6 ) == 0 ){
462 unsigned long button = strtoul( keysym+6, NULL, 10 );
463 if( button > MAX_MOUSE_BUTTONS ) {
464 return 0;
465 }
466 return (uint16_t)button;
467 }
468 return 0;
469 }
471 gchar *mouse_get_keysym( struct input_driver *driver, uint16_t keycode )
472 {
473 return g_strdup_printf( "Button%d", (keycode) );
474 }
476 struct input_driver system_mouse_driver = { "Mouse", mouse_resolve_keysym, NULL, mouse_get_keysym, NULL };
479 gboolean input_register_mouse_hook( gboolean relative, input_mouse_callback_t callback,
480 void *data )
481 {
482 mouse_entry_t ent = malloc( sizeof( struct mouse_entry ) );
483 assert( ent != NULL );
484 ent->callback = callback;
485 ent->data = data;
486 ent->next = mousehooks;
487 mousehooks = ent;
488 return TRUE;
489 }
491 void input_unregister_mouse_hook( input_mouse_callback_t callback, void *data )
492 {
493 mouse_entry_t ent = mousehooks;
494 if( ent != NULL ) {
495 if( ent->callback == callback && ent->data == data ) {
496 mousehooks = mousehooks->next;
497 free(ent);
498 return;
499 }
500 while( ent->next != NULL ) {
501 if( ent->next->callback == callback && ent->next->data == data ) {
502 mouse_entry_t next = ent->next;
503 ent->next = next->next;
504 free(next);
505 return;
506 }
507 ent = ent->next;
508 }
509 }
510 }
512 void input_event_run_mouse_hooks( uint32_t buttons, int32_t x, int32_t y, gboolean absolute )
513 {
514 mouse_entry_t ent = mousehooks;
515 while( ent != NULL ) {
516 ent->callback(ent->data, buttons, x, y, absolute);
517 ent = ent->next;
518 }
519 }
521 void input_event_mousedown( uint16_t button, int32_t x, int32_t y, gboolean absolute )
522 {
523 if( absolute ) {
524 mouse_x = x;
525 mouse_y = y;
526 }
527 mouse_buttons |= (1<<button);
528 input_event_keydown( &system_mouse_driver, button+1, MAX_PRESSURE );
529 input_event_run_mouse_hooks( mouse_buttons, x, y, absolute );
530 }
532 void input_event_mouseup( uint16_t button, int32_t x, int32_t y, gboolean absolute )
533 {
534 if( absolute ) {
535 mouse_x = x;
536 mouse_y = y;
537 }
538 mouse_buttons &= ~(1<<button);
539 input_event_keyup( &system_mouse_driver, button+1 );
540 input_event_run_mouse_hooks( mouse_buttons, x, y, absolute );
541 }
543 void input_event_mousemove( int32_t x, int32_t y, gboolean absolute )
544 {
545 if( absolute ) {
546 mouse_x = x;
547 mouse_y = y;
548 }
549 input_event_run_mouse_hooks( mouse_buttons, x, y, absolute );
550 }
552 /************************ Main display driver *************************/
554 void print_display_drivers( FILE *out )
555 {
556 int i;
557 fprintf( out, "Available video drivers:\n" );
558 for( i=0; display_driver_list[i] != NULL; i++ ) {
559 fprintf( out, " %-8s %s\n", display_driver_list[i]->name,
560 gettext(display_driver_list[i]->description) );
561 }
562 }
564 display_driver_t get_display_driver_by_name( const char *name )
565 {
566 int i;
567 if( name == NULL ) {
568 return display_driver_list[0];
569 }
570 for( i=0; display_driver_list[i] != NULL; i++ ) {
571 if( strcasecmp( display_driver_list[i]->name, name ) == 0 ) {
572 return display_driver_list[i];
573 }
574 }
576 return NULL;
577 }
580 gboolean display_set_driver( display_driver_t driver )
581 {
582 gboolean rv = TRUE;
583 if( display_driver != NULL && display_driver->shutdown_driver != NULL )
584 display_driver->shutdown_driver();
586 display_driver = driver;
587 if( driver->init_driver != NULL )
588 rv = driver->init_driver();
589 if( rv ) {
590 input_register_device(&system_mouse_driver, MAX_MOUSE_BUTTONS);
591 } else {
592 display_driver = NULL;
593 }
594 return rv;
595 }
597 void display_set_focused( gboolean has_focus )
598 {
599 display_focused = has_focus;
600 }
.