filename | src/display.c |
changeset | 1245:01e0020adf88 |
prev | 1244:6b54ef5ed413 |
next | 1298:d0eb2307b847 |
author | nkeynes |
date | Mon Mar 05 11:41:03 2012 +1000 (12 years ago) |
permissions | -rw-r--r-- |
last change | Small cleanups: Refactor the post-windowing setup into gl_init_driver() in video_gl.c Move gl_sl.c into src/drivers and tidy up a bit. Fix OS X compiling plugins with -mdynamic-no-pic |
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"
26 #include "pvr2/glutil.h"
28 display_driver_t display_driver_list[] = {
29 #ifdef HAVE_GTK
30 &display_gtk_driver,
31 #else
32 #ifdef HAVE_COCOA
33 &display_osx_driver,
34 #endif
35 #endif
36 #ifdef __ANDROID__
37 &display_egl_driver,
38 #endif
39 &display_null_driver,
40 NULL };
42 /* Some explanation:
43 * The system has at least one "root" device representing the main display
44 * (which may be the null display). This device is part of the display_driver
45 * and generates events with no input_driver. The root device has no id
46 * as such (for the purposes of event names)
47 *
48 * The system may also have one or more auxilliary devices which each have
49 * an input_driver and an id (eg "JS0"). So the keysym "Return" is (de)coded by
50 * the root device, and the keysym "JS0: Button0" is (de)coded by the JS0 input
51 * device as "Button0".
52 *
53 * For the moment, mice are handled specially, as they behave a little
54 * differently from other devices (although this will probably change in the
55 * future.
56 */
59 typedef struct keymap_entry {
60 input_key_callback_t callback;
61 void *data;
62 uint32_t value;
63 lxdream_config_group_t group;
64 struct keymap_entry *next; // allow chaining
65 } *keymap_entry_t;
67 typedef struct mouse_entry {
68 gboolean relative;
69 input_mouse_callback_t callback;
70 void *data;
71 const lxdream_config_group_t group;
72 struct mouse_entry *next;
73 } *mouse_entry_t;
75 typedef struct input_driver_entry {
76 input_driver_t driver;
77 uint16_t entry_count;
78 struct keymap_entry *keymap[0];
79 } *input_driver_entry_t;
82 #ifndef GL_RGBA8
83 #define GL_RGBA8 GL_RGBA8_OES
84 #endif
86 #ifndef GL_RGB5
87 #define GL_RGB5 GL_RGB565
88 #endif
90 #ifndef GL_BGR
91 #define GL_BGR GL_BGRA
92 #endif
94 /**
95 * Colour format information
96 */
97 struct colour_format colour_formats[] = {
98 { GL_UNSIGNED_SHORT_1_5_5_5_REV, GL_BGRA, GL_RGB5_A1, 2 },
99 { GL_UNSIGNED_SHORT_5_6_5, GL_RGB, GL_RGB5, 2 },
100 { GL_UNSIGNED_SHORT_4_4_4_4_REV, GL_BGRA, GL_RGBA4, 2 },
101 { GL_UNSIGNED_BYTE, GL_BGRA, GL_RGBA8, 4 }, /* YUV decoded to ARGB8888 */
102 { GL_UNSIGNED_BYTE, GL_BGR, GL_RGB, 3 },
103 { GL_UNSIGNED_BYTE, GL_BGRA, GL_RGBA8, 4 },
104 { GL_UNSIGNED_BYTE, GL_BGRA, GL_RGBA8, 4 }, /* Index4 decoded */
105 { GL_UNSIGNED_BYTE, GL_BGRA, GL_RGBA8, 4 }, /* Index8 decoded */
106 { GL_UNSIGNED_BYTE, GL_BGRA, GL_RGBA8, 4 },
107 { GL_UNSIGNED_BYTE, GL_RGB, GL_RGB, 3 },
109 };
111 /**
112 * FIXME: make this more memory efficient
113 */
114 static struct keymap_entry *root_keymap[65535];
115 static struct keymap_entry *keyhooks = NULL;
116 static gboolean display_focused = TRUE;
117 static GList *input_drivers= NULL;
118 static display_keysym_callback_t display_keysym_hook = NULL;
119 void *display_keysym_hook_data;
121 gboolean input_register_device( input_driver_t driver, uint16_t max_keycode )
122 {
123 GList *ptr;
124 for( ptr = input_drivers; ptr != NULL; ptr = g_list_next(ptr) ) {
125 input_driver_entry_t entry = (input_driver_entry_t)ptr->data;
126 if( strcasecmp( entry->driver->id, driver->id ) == 0 ) {
127 return FALSE;
128 }
129 }
131 input_driver_entry_t entry = g_malloc0( sizeof(struct input_driver_entry) + (sizeof(keymap_entry_t) * max_keycode) );
132 entry->driver = driver;
133 entry->entry_count = max_keycode;
134 input_drivers = g_list_append( input_drivers, entry );
135 return TRUE;
136 }
138 gboolean input_has_device( const gchar *id )
139 {
140 GList *ptr;
141 for( ptr = input_drivers; ptr != NULL; ptr = g_list_next(ptr) ) {
142 input_driver_entry_t entry = (input_driver_entry_t)ptr->data;
143 if( strcasecmp(entry->driver->id, id) == 0 ) {
144 return TRUE;
145 }
146 }
147 return FALSE;
148 }
151 void input_unregister_device( input_driver_t driver )
152 {
153 GList *ptr;
154 for( ptr = input_drivers; ptr != NULL; ptr = g_list_next(ptr) ) {
155 input_driver_entry_t entry = (input_driver_entry_t)ptr->data;
156 if( entry->driver == driver ) {
157 if( driver->destroy != NULL ) {
158 driver->destroy(driver);
159 }
160 input_drivers = g_list_remove(input_drivers, (gpointer)entry);
161 g_free( entry );
162 return;
163 }
164 }
165 }
167 /**
168 * Resolve the keysym and return a pointer to the keymap entry pointer
169 * @return keymap pointer or NULL if the key was unresolved
170 */
171 static struct keymap_entry **input_entry_from_keysym( const gchar *keysym )
172 {
173 if( keysym == NULL || keysym[0] == 0 ) {
174 return NULL;
175 }
176 char **strv = g_strsplit(keysym,":",2);
177 if( strv[1] == NULL ) {
178 /* root device */
179 if( display_driver == NULL || display_driver->resolve_keysym == NULL) {
180 // Root device has no input handling
181 g_strfreev(strv);
182 return NULL;
183 }
184 uint16_t keycode = display_driver->resolve_keysym(g_strstrip(strv[0]));
185 g_strfreev(strv);
186 if( keycode == 0 ) {
187 return NULL;
188 }
189 return &root_keymap[keycode-1];
191 } else {
192 char *id = g_strstrip(strv[0]);
193 GList *ptr;
194 for( ptr = input_drivers; ptr != NULL; ptr = g_list_next(ptr) ) {
195 input_driver_entry_t entry = (input_driver_entry_t)ptr->data;
196 if( strcasecmp( entry->driver->id, id ) == 0 ) {
197 /* we have ze device */
198 if( entry->driver->resolve_keysym == NULL ) {
199 g_strfreev(strv);
200 return NULL;
201 }
202 uint16_t keycode = entry->driver->resolve_keysym(entry->driver, g_strstrip(strv[1]));
203 g_strfreev(strv);
204 if( keycode == 0 || keycode > entry->entry_count ) {
205 return NULL;
206 }
207 return &entry->keymap[keycode-1];
208 }
209 }
210 g_strfreev(strv);
211 return NULL; // device not found
212 }
213 }
215 static struct keymap_entry **input_entry_from_keycode( input_driver_t driver, uint16_t keycode )
216 {
217 GList *ptr;
219 if( keycode == 0 ) {
220 return NULL;
221 }
223 if( driver == NULL ) {
224 return &root_keymap[keycode-1];
225 }
227 for( ptr = input_drivers; ptr != NULL; ptr = g_list_next(ptr) ) {
228 input_driver_entry_t entry = (input_driver_entry_t)ptr->data;
229 if( entry->driver == driver ) {
230 if( keycode > entry->entry_count ) {
231 return NULL;
232 } else {
233 return &entry->keymap[keycode-1];
234 }
235 }
236 }
237 return NULL;
238 }
240 gchar *input_keycode_to_keysym( input_driver_t driver, uint16_t keycode )
241 {
242 if( keycode == 0 ) {
243 return NULL;
244 }
245 if( driver == NULL ) {
246 if( display_driver != NULL && display_driver->get_keysym_for_keycode != NULL ) {
247 return display_driver->get_keysym_for_keycode(keycode);
248 }
249 } else if( driver->get_keysym_for_keycode ) {
250 gchar *sym = driver->get_keysym_for_keycode(driver,keycode);
251 if( sym != NULL ) {
252 gchar *result = g_strdup_printf( "%s: %s", driver->id, sym );
253 g_free(sym);
254 return result;
255 }
256 }
257 return NULL;
258 }
261 gboolean input_register_key( const gchar *keysym, input_key_callback_t callback,
262 void *data, uint32_t value )
263 {
264 if( keysym == NULL ) {
265 return FALSE;
266 }
267 int keys = 0;
268 gchar **strv = g_strsplit(keysym, ",", 16);
269 gchar **s = strv;
270 while( *s != NULL ) {
271 keymap_entry_t *entryp = input_entry_from_keysym(*s);
272 if( entryp != NULL ) {
273 keymap_entry_t newentry = g_malloc0(sizeof(struct keymap_entry));
274 newentry->next = *entryp;
275 newentry->callback = callback;
276 newentry->data = data;
277 newentry->value = value;
278 *entryp = newentry;
279 keys++;
280 }
281 s++;
282 }
283 g_strfreev(strv);
284 return keys != 0;
285 }
287 void input_unregister_key( const gchar *keysym, input_key_callback_t callback,
288 void *data, uint32_t value )
289 {
290 if( keysym == NULL ) {
291 return;
292 }
294 gchar **strv = g_strsplit(keysym, ",", 16);
295 gchar **s = strv;
296 while( *s != NULL ) {
297 keymap_entry_t *entryp = input_entry_from_keysym(*s);
298 if( entryp != NULL ) {
299 while( *entryp != NULL ) {
300 if( (*entryp)->callback == callback &&
301 (*entryp)->data == data && (*entryp)->value == value ) {
302 keymap_entry_t next = (*entryp)->next;
303 g_free( *entryp );
304 *entryp = next;
305 break;
306 }
307 entryp = &(*entryp)->next; // Yes, really
308 }
309 }
310 s++;
311 }
312 g_strfreev(strv);
313 }
315 int input_register_keygroup( lxdream_config_group_t group)
316 {
317 int i;
318 int result = 0;
319 for( i=0; group->params[i].key != NULL; i++ ) {
320 if( group->params[i].type == CONFIG_TYPE_KEY ) {
321 if( input_register_key( group->params[i].value, group->key_binding, group->data, group->params[i].tag ) ) {
322 result++;
323 }
324 }
325 }
326 return result;
327 }
329 void input_unregister_keygroup( lxdream_config_group_t group )
330 {
331 int i;
332 for( i=0; group->params[i].key != NULL; i++ ) {
333 if( group->params[i].type == CONFIG_TYPE_KEY ) {
334 input_unregister_key( group->params[i].value, group->key_binding, group->data, group->params[i].tag );
335 }
336 }
337 }
339 gboolean input_keygroup_changed( void *data, lxdream_config_group_t group, unsigned key,
340 const gchar *oldval, const gchar *newval )
341 {
342 input_unregister_key( oldval, group->key_binding, group->data, group->params[key].tag );
343 input_register_key( newval, group->key_binding, group->data, group->params[key].tag );
344 return TRUE;
345 }
347 gboolean input_register_keyboard_hook( input_key_callback_t callback,
348 void *data )
349 {
350 keymap_entry_t key = malloc( sizeof( struct keymap_entry ) );
351 assert( key != NULL );
352 key->callback = callback;
353 key->data = data;
354 key->next = keyhooks;
355 keyhooks = key;
356 return TRUE;
357 }
359 void input_unregister_keyboard_hook( input_key_callback_t callback,
360 void *data )
361 {
362 keymap_entry_t key = keyhooks;
363 if( key != NULL ) {
364 if( key->callback == callback && key->data == data ) {
365 keyhooks = keyhooks->next;
366 free(key);
367 return;
368 }
369 while( key->next != NULL ) {
370 if( key->next->callback == callback && key->next->data == data ) {
371 keymap_entry_t next = key->next;
372 key->next = next->next;
373 free(next);
374 return;
375 }
376 key = key->next;
377 }
378 }
379 }
381 gboolean input_is_key_valid( const gchar *keysym )
382 {
383 keymap_entry_t *ptr = input_entry_from_keysym(keysym);
384 return ptr != NULL;
385 }
387 gboolean input_is_key_registered( const gchar *keysym )
388 {
389 keymap_entry_t *ptr = input_entry_from_keysym(keysym);
390 return ptr != NULL && *ptr != NULL;
391 }
393 void input_event_keydown( input_driver_t driver, uint16_t keycode, uint32_t pressure )
394 {
395 if( display_focused ) {
396 keymap_entry_t *entryp = input_entry_from_keycode(driver,keycode);
397 if( entryp != NULL ) {
398 keymap_entry_t key = *entryp;
399 while( key != NULL ) {
400 key->callback( key->data, key->value, pressure, TRUE );
401 key = key->next;
402 }
403 }
404 if( driver == NULL ) {
405 keymap_entry_t key = keyhooks;
406 while( key != NULL ) {
407 key->callback( key->data, keycode, pressure, TRUE );
408 key = key->next;
409 }
410 }
411 }
412 if( display_keysym_hook != NULL ) {
413 gchar *sym = input_keycode_to_keysym( driver, keycode );
414 if( sym != NULL ) {
415 display_keysym_hook(display_keysym_hook_data, sym);
416 g_free(sym);
417 }
418 }
419 }
421 void input_event_keyup( input_driver_t driver, uint16_t keycode )
422 {
423 if( display_focused ) {
424 keymap_entry_t *entryp = input_entry_from_keycode(driver,keycode);
425 if( entryp != NULL ) {
426 keymap_entry_t key = *entryp;
427 while( key != NULL ) {
428 key->callback( key->data, key->value, 0, FALSE );
429 key = key->next;
430 }
431 }
433 if( driver == NULL ) {
434 keymap_entry_t key = keyhooks;
435 while( key != NULL ) {
436 key->callback( key->data, keycode, 0, FALSE );
437 key = key->next;
438 }
439 }
440 }
441 }
443 uint16_t input_keycode_to_dckeysym( uint16_t keycode )
444 {
445 return display_driver->convert_to_dckeysym(keycode);
446 }
448 void input_set_keysym_hook( display_keysym_callback_t hook, void *data )
449 {
450 display_keysym_hook = hook;
451 display_keysym_hook_data = data;
452 }
454 /***************** System mouse driver ****************/
456 static struct keymap_entry *mouse_keymap[MAX_MOUSE_BUTTONS];
457 static struct mouse_entry *mousehooks = NULL;
458 static uint32_t mouse_x = -1, mouse_y = -1, mouse_buttons = 0;
460 uint16_t mouse_resolve_keysym( struct input_driver *driver, const gchar *keysym )
461 {
462 if( strncasecmp( keysym, "Button", 6 ) == 0 ){
463 unsigned long button = strtoul( keysym+6, NULL, 10 );
464 if( button > MAX_MOUSE_BUTTONS ) {
465 return 0;
466 }
467 return (uint16_t)button;
468 }
469 return 0;
470 }
472 gchar *mouse_get_keysym( struct input_driver *driver, uint16_t keycode )
473 {
474 return g_strdup_printf( "Button%d", (keycode) );
475 }
477 struct input_driver system_mouse_driver = { "Mouse", mouse_resolve_keysym, NULL, mouse_get_keysym, NULL };
480 gboolean input_register_mouse_hook( gboolean relative, input_mouse_callback_t callback,
481 void *data )
482 {
483 mouse_entry_t ent = malloc( sizeof( struct mouse_entry ) );
484 assert( ent != NULL );
485 ent->callback = callback;
486 ent->data = data;
487 ent->next = mousehooks;
488 mousehooks = ent;
489 return TRUE;
490 }
492 void input_unregister_mouse_hook( input_mouse_callback_t callback, void *data )
493 {
494 mouse_entry_t ent = mousehooks;
495 if( ent != NULL ) {
496 if( ent->callback == callback && ent->data == data ) {
497 mousehooks = mousehooks->next;
498 free(ent);
499 return;
500 }
501 while( ent->next != NULL ) {
502 if( ent->next->callback == callback && ent->next->data == data ) {
503 mouse_entry_t next = ent->next;
504 ent->next = next->next;
505 free(next);
506 return;
507 }
508 ent = ent->next;
509 }
510 }
511 }
513 void input_event_run_mouse_hooks( uint32_t buttons, int32_t x, int32_t y, gboolean absolute )
514 {
515 mouse_entry_t ent = mousehooks;
516 while( ent != NULL ) {
517 ent->callback(ent->data, buttons, x, y, absolute);
518 ent = ent->next;
519 }
520 }
522 void input_event_mousedown( uint16_t button, int32_t x, int32_t y, gboolean absolute )
523 {
524 if( absolute ) {
525 mouse_x = x;
526 mouse_y = y;
527 }
528 mouse_buttons |= (1<<button);
529 input_event_keydown( &system_mouse_driver, button+1, MAX_PRESSURE );
530 input_event_run_mouse_hooks( mouse_buttons, x, y, absolute );
531 }
533 void input_event_mouseup( uint16_t button, int32_t x, int32_t y, gboolean absolute )
534 {
535 if( absolute ) {
536 mouse_x = x;
537 mouse_y = y;
538 }
539 mouse_buttons &= ~(1<<button);
540 input_event_keyup( &system_mouse_driver, button+1 );
541 input_event_run_mouse_hooks( mouse_buttons, x, y, absolute );
542 }
544 void input_event_mousemove( int32_t x, int32_t y, gboolean absolute )
545 {
546 if( absolute ) {
547 mouse_x = x;
548 mouse_y = y;
549 }
550 input_event_run_mouse_hooks( mouse_buttons, x, y, absolute );
551 }
553 /************************ Main display driver *************************/
555 void print_display_drivers( FILE *out )
556 {
557 int i;
558 fprintf( out, "Available video drivers:\n" );
559 for( i=0; display_driver_list[i] != NULL; i++ ) {
560 fprintf( out, " %-8s %s\n", display_driver_list[i]->name,
561 gettext(display_driver_list[i]->description) );
562 }
563 }
565 display_driver_t get_display_driver_by_name( const char *name )
566 {
567 int i;
568 if( name == NULL ) {
569 return display_driver_list[0];
570 }
571 for( i=0; display_driver_list[i] != NULL; i++ ) {
572 if( strcasecmp( display_driver_list[i]->name, name ) == 0 ) {
573 return display_driver_list[i];
574 }
575 }
577 return NULL;
578 }
581 gboolean display_set_driver( display_driver_t driver )
582 {
583 gboolean rv = TRUE;
584 if( display_driver != NULL && display_driver->shutdown_driver != NULL )
585 display_driver->shutdown_driver();
587 display_driver = driver;
588 if( driver->init_driver != NULL )
589 rv = driver->init_driver();
590 if( rv ) {
591 input_register_device(&system_mouse_driver, MAX_MOUSE_BUTTONS);
592 } else {
593 display_driver = NULL;
594 }
595 return rv;
596 }
598 void display_set_focused( gboolean has_focus )
599 {
600 display_focused = has_focus;
601 }
.