filename | src/display.c |
changeset | 1019:87f191f92f8f |
prev | 1010:a506a2f66180 |
next | 1072:d82e04e6d497 |
author | nkeynes |
date | Wed Jun 24 06:06:40 2009 +0000 (14 years ago) |
permissions | -rw-r--r-- |
last change | Support shell substitutions in config paths Keep track of last folder in file dialogs Fix out-of-dateness in GTK path dialog |
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 &display_null_driver,
36 NULL };
38 /* Some explanation:
39 * The system has at least one "root" device representing the main display
40 * (which may be the null display). This device is part of the display_driver
41 * and generates events with no input_driver. The root device has no id
42 * as such (for the purposes of event names)
43 *
44 * The system may also have one or more auxilliary devices which each have
45 * an input_driver and an id (eg "JS0"). So the keysym "Return" is (de)coded by
46 * the root device, and the keysym "JS0: Button0" is (de)coded by the JS0 input
47 * device as "Button0".
48 *
49 * For the moment, mice are handled specially, as they behave a little
50 * differently from other devices (although this will probably change in the
51 * future.
52 */
55 typedef struct keymap_entry {
56 input_key_callback_t callback;
57 void *data;
58 uint32_t value;
59 struct keymap_entry *next; // allow chaining
60 } *keymap_entry_t;
62 typedef struct mouse_entry {
63 gboolean relative;
64 input_mouse_callback_t callback;
65 void *data;
66 struct mouse_entry *next;
67 } *mouse_entry_t;
69 typedef struct input_driver_entry {
70 input_driver_t driver;
71 uint16_t entry_count;
72 struct keymap_entry *keymap[0];
73 } *input_driver_entry_t;
75 /**
76 * Colour format information
77 */
78 struct colour_format colour_formats[] = {
79 { GL_UNSIGNED_SHORT_1_5_5_5_REV, GL_BGRA, GL_RGB5_A1, 2 },
80 { GL_UNSIGNED_SHORT_5_6_5, GL_RGB, GL_RGB5, 2 },
81 { GL_UNSIGNED_SHORT_4_4_4_4_REV, GL_BGRA, GL_RGBA4, 2 },
82 { GL_UNSIGNED_BYTE, GL_BGRA, GL_RGBA8, 4 }, /* YUV decoded to ARGB8888 */
83 { GL_UNSIGNED_BYTE, GL_BGR, GL_RGB, 3 },
84 { GL_UNSIGNED_BYTE, GL_BGRA, GL_RGBA8, 4 },
85 { GL_UNSIGNED_BYTE, GL_BGRA, GL_RGBA8, 4 }, /* Index4 decoded */
86 { GL_UNSIGNED_BYTE, GL_BGRA, GL_RGBA8, 4 }, /* Index8 decoded */
87 { GL_UNSIGNED_BYTE, GL_BGRA, GL_RGBA8, 4 },
88 { GL_UNSIGNED_BYTE, GL_RGB, GL_RGB, 3 },
90 };
92 /**
93 * FIXME: make this more memory efficient
94 */
95 static struct keymap_entry *root_keymap[65535];
96 static struct keymap_entry *keyhooks = NULL;
97 static gboolean display_focused = TRUE;
98 static GList *input_drivers= NULL;
99 static display_keysym_callback_t display_keysym_hook = NULL;
100 void *display_keysym_hook_data;
102 gboolean input_register_device( input_driver_t driver, uint16_t max_keycode )
103 {
104 GList *ptr;
105 for( ptr = input_drivers; ptr != NULL; ptr = g_list_next(ptr) ) {
106 input_driver_entry_t entry = (input_driver_entry_t)ptr->data;
107 if( strcasecmp( entry->driver->id, driver->id ) == 0 ) {
108 return FALSE;
109 }
110 }
112 input_driver_entry_t entry = g_malloc0( sizeof(struct input_driver_entry) + (sizeof(keymap_entry_t) * max_keycode) );
113 entry->driver = driver;
114 entry->entry_count = max_keycode;
115 input_drivers = g_list_append( input_drivers, entry );
116 return TRUE;
117 }
119 gboolean input_has_device( const gchar *id )
120 {
121 GList *ptr;
122 for( ptr = input_drivers; ptr != NULL; ptr = g_list_next(ptr) ) {
123 input_driver_entry_t entry = (input_driver_entry_t)ptr->data;
124 if( strcasecmp(entry->driver->id, id) == 0 ) {
125 return TRUE;
126 }
127 }
128 return FALSE;
129 }
132 void input_unregister_device( input_driver_t driver )
133 {
134 GList *ptr;
135 for( ptr = input_drivers; ptr != NULL; ptr = g_list_next(ptr) ) {
136 input_driver_entry_t entry = (input_driver_entry_t)ptr->data;
137 if( entry->driver == driver ) {
138 if( driver->destroy != NULL ) {
139 driver->destroy(driver);
140 }
141 input_drivers = g_list_remove(input_drivers, (gpointer)entry);
142 g_free( entry );
143 return;
144 }
145 }
146 }
148 /**
149 * Resolve the keysym and return a pointer to the keymap entry pointer
150 * @return keymap pointer or NULL if the key was unresolved
151 */
152 static struct keymap_entry **input_entry_from_keysym( const gchar *keysym )
153 {
154 if( keysym == NULL || keysym[0] == 0 ) {
155 return NULL;
156 }
157 char **strv = g_strsplit(keysym,":",2);
158 if( strv[1] == NULL ) {
159 /* root device */
160 if( display_driver == NULL || display_driver->resolve_keysym == NULL) {
161 // Root device has no input handling
162 g_strfreev(strv);
163 return NULL;
164 }
165 uint16_t keycode = display_driver->resolve_keysym(g_strstrip(strv[0]));
166 g_strfreev(strv);
167 if( keycode == 0 ) {
168 return NULL;
169 }
170 return &root_keymap[keycode-1];
172 } else {
173 char *id = g_strstrip(strv[0]);
174 GList *ptr;
175 for( ptr = input_drivers; ptr != NULL; ptr = g_list_next(ptr) ) {
176 input_driver_entry_t entry = (input_driver_entry_t)ptr->data;
177 if( strcasecmp( entry->driver->id, id ) == 0 ) {
178 /* we have ze device */
179 if( entry->driver->resolve_keysym == NULL ) {
180 g_strfreev(strv);
181 return NULL;
182 }
183 uint16_t keycode = entry->driver->resolve_keysym(entry->driver, g_strstrip(strv[1]));
184 g_strfreev(strv);
185 if( keycode == 0 || keycode > entry->entry_count ) {
186 return NULL;
187 }
188 return &entry->keymap[keycode-1];
189 }
190 }
191 g_strfreev(strv);
192 return NULL; // device not found
193 }
194 }
196 static struct keymap_entry **input_entry_from_keycode( input_driver_t driver, uint16_t keycode )
197 {
198 GList *ptr;
200 if( keycode == 0 ) {
201 return NULL;
202 }
204 if( driver == NULL ) {
205 return &root_keymap[keycode-1];
206 }
208 for( ptr = input_drivers; ptr != NULL; ptr = g_list_next(ptr) ) {
209 input_driver_entry_t entry = (input_driver_entry_t)ptr->data;
210 if( entry->driver == driver ) {
211 if( keycode > entry->entry_count ) {
212 return NULL;
213 } else {
214 return &entry->keymap[keycode-1];
215 }
216 }
217 }
218 return NULL;
219 }
221 gchar *input_keycode_to_keysym( input_driver_t driver, uint16_t keycode )
222 {
223 if( keycode == 0 ) {
224 return NULL;
225 }
226 if( driver == NULL ) {
227 if( display_driver != NULL && display_driver->get_keysym_for_keycode != NULL ) {
228 return display_driver->get_keysym_for_keycode(keycode);
229 }
230 } else if( driver->get_keysym_for_keycode ) {
231 gchar *sym = driver->get_keysym_for_keycode(driver,keycode);
232 if( sym != NULL ) {
233 gchar *result = g_strdup_printf( "%s: %s", driver->id, sym );
234 g_free(sym);
235 return result;
236 }
237 }
238 return NULL;
239 }
242 gboolean input_register_key( const gchar *keysym, input_key_callback_t callback,
243 void *data, uint32_t value )
244 {
245 if( keysym == NULL ) {
246 return FALSE;
247 }
248 int keys = 0;
249 gchar **strv = g_strsplit(keysym, ",", 16);
250 gchar **s = strv;
251 while( *s != NULL ) {
252 keymap_entry_t *entryp = input_entry_from_keysym(*s);
253 if( entryp != NULL ) {
254 keymap_entry_t newentry = g_malloc0(sizeof(struct keymap_entry));
255 newentry->next = *entryp;
256 newentry->callback = callback;
257 newentry->data = data;
258 newentry->value = value;
259 *entryp = newentry;
260 keys++;
261 }
262 s++;
263 }
264 g_strfreev(strv);
265 return keys != 0;
266 }
268 void input_unregister_key( const gchar *keysym, input_key_callback_t callback,
269 void *data, uint32_t value )
270 {
271 if( keysym == NULL ) {
272 return;
273 }
275 gchar **strv = g_strsplit(keysym, ",", 16);
276 gchar **s = strv;
277 while( *s != NULL ) {
278 keymap_entry_t *entryp = input_entry_from_keysym(*s);
279 if( entryp != NULL ) {
280 while( *entryp != NULL ) {
281 if( (*entryp)->callback == callback &&
282 (*entryp)->data == data && (*entryp)->value == value ) {
283 keymap_entry_t next = (*entryp)->next;
284 g_free( *entryp );
285 *entryp = next;
286 break;
287 }
288 entryp = &(*entryp)->next; // Yes, really
289 }
290 }
291 s++;
292 }
293 g_strfreev(strv);
294 }
296 gboolean input_register_keyboard_hook( input_key_callback_t callback,
297 void *data )
298 {
299 keymap_entry_t key = malloc( sizeof( struct keymap_entry ) );
300 assert( key != NULL );
301 key->callback = callback;
302 key->data = data;
303 key->next = keyhooks;
304 keyhooks = key;
305 return TRUE;
306 }
308 void input_unregister_keyboard_hook( input_key_callback_t callback,
309 void *data )
310 {
311 keymap_entry_t key = keyhooks;
312 if( key != NULL ) {
313 if( key->callback == callback && key->data == data ) {
314 keyhooks = keyhooks->next;
315 free(key);
316 return;
317 }
318 while( key->next != NULL ) {
319 if( key->next->callback == callback && key->next->data == data ) {
320 keymap_entry_t next = key->next;
321 key->next = next->next;
322 free(next);
323 return;
324 }
325 key = key->next;
326 }
327 }
328 }
330 gboolean input_is_key_valid( const gchar *keysym )
331 {
332 keymap_entry_t *ptr = input_entry_from_keysym(keysym);
333 return ptr != NULL;
334 }
336 gboolean input_is_key_registered( const gchar *keysym )
337 {
338 keymap_entry_t *ptr = input_entry_from_keysym(keysym);
339 return ptr != NULL && *ptr != NULL;
340 }
342 void input_event_keydown( input_driver_t driver, uint16_t keycode, uint32_t pressure )
343 {
344 if( display_focused ) {
345 keymap_entry_t *entryp = input_entry_from_keycode(driver,keycode);
346 if( entryp != NULL ) {
347 keymap_entry_t key = *entryp;
348 while( key != NULL ) {
349 key->callback( key->data, key->value, pressure, TRUE );
350 key = key->next;
351 }
352 }
353 if( driver == NULL ) {
354 keymap_entry_t key = keyhooks;
355 while( key != NULL ) {
356 key->callback( key->data, keycode, pressure, TRUE );
357 key = key->next;
358 }
359 }
360 }
361 if( display_keysym_hook != NULL ) {
362 gchar *sym = input_keycode_to_keysym( driver, keycode );
363 if( sym != NULL ) {
364 display_keysym_hook(display_keysym_hook_data, sym);
365 g_free(sym);
366 }
367 }
368 }
370 void input_event_keyup( input_driver_t driver, uint16_t keycode )
371 {
372 if( display_focused ) {
373 keymap_entry_t *entryp = input_entry_from_keycode(driver,keycode);
374 if( entryp != NULL ) {
375 keymap_entry_t key = *entryp;
376 while( key != NULL ) {
377 key->callback( key->data, key->value, 0, FALSE );
378 key = key->next;
379 }
380 }
382 if( driver == NULL ) {
383 keymap_entry_t key = keyhooks;
384 while( key != NULL ) {
385 key->callback( key->data, keycode, 0, FALSE );
386 key = key->next;
387 }
388 }
389 }
390 }
392 uint16_t input_keycode_to_dckeysym( uint16_t keycode )
393 {
394 return display_driver->convert_to_dckeysym(keycode);
395 }
397 void input_set_keysym_hook( display_keysym_callback_t hook, void *data )
398 {
399 display_keysym_hook = hook;
400 display_keysym_hook_data = data;
401 }
403 /***************** System mouse driver ****************/
405 static struct keymap_entry *mouse_keymap[MAX_MOUSE_BUTTONS];
406 static struct mouse_entry *mousehooks = NULL;
407 static uint32_t mouse_x = -1, mouse_y = -1, mouse_buttons = 0;
409 uint16_t mouse_resolve_keysym( struct input_driver *driver, const gchar *keysym )
410 {
411 if( strncasecmp( keysym, "Button", 6 ) == 0 ){
412 unsigned long button = strtoul( keysym+6, NULL, 10 );
413 if( button > MAX_MOUSE_BUTTONS ) {
414 return 0;
415 }
416 return (uint16_t)button;
417 }
418 return 0;
419 }
421 gchar *mouse_get_keysym( struct input_driver *driver, uint16_t keycode )
422 {
423 return g_strdup_printf( "Button%d", (keycode) );
424 }
426 struct input_driver system_mouse_driver = { "Mouse", mouse_resolve_keysym, NULL, mouse_get_keysym, NULL };
429 gboolean input_register_mouse_hook( gboolean relative, input_mouse_callback_t callback,
430 void *data )
431 {
432 mouse_entry_t ent = malloc( sizeof( struct mouse_entry ) );
433 assert( ent != NULL );
434 ent->callback = callback;
435 ent->data = data;
436 ent->next = mousehooks;
437 mousehooks = ent;
438 return TRUE;
439 }
441 void input_unregister_mouse_hook( input_mouse_callback_t callback, void *data )
442 {
443 mouse_entry_t ent = mousehooks;
444 if( ent != NULL ) {
445 if( ent->callback == callback && ent->data == data ) {
446 mousehooks = mousehooks->next;
447 free(ent);
448 return;
449 }
450 while( ent->next != NULL ) {
451 if( ent->next->callback == callback && ent->next->data == data ) {
452 mouse_entry_t next = ent->next;
453 ent->next = next->next;
454 free(next);
455 return;
456 }
457 ent = ent->next;
458 }
459 }
460 }
462 void input_event_run_mouse_hooks( uint32_t buttons, int32_t x, int32_t y, gboolean absolute )
463 {
464 mouse_entry_t ent = mousehooks;
465 while( ent != NULL ) {
466 ent->callback(ent->data, buttons, x, y, absolute);
467 ent = ent->next;
468 }
469 }
471 void input_event_mousedown( uint16_t button, int32_t x, int32_t y, gboolean absolute )
472 {
473 if( absolute ) {
474 mouse_x = x;
475 mouse_y = y;
476 }
477 mouse_buttons |= (1<<button);
478 input_event_keydown( &system_mouse_driver, button+1, MAX_PRESSURE );
479 input_event_run_mouse_hooks( mouse_buttons, x, y, absolute );
480 }
482 void input_event_mouseup( uint16_t button, int32_t x, int32_t y, gboolean absolute )
483 {
484 if( absolute ) {
485 mouse_x = x;
486 mouse_y = y;
487 }
488 mouse_buttons &= ~(1<<button);
489 input_event_keyup( &system_mouse_driver, button+1 );
490 input_event_run_mouse_hooks( mouse_buttons, x, y, absolute );
491 }
493 void input_event_mousemove( int32_t x, int32_t y, gboolean absolute )
494 {
495 if( absolute ) {
496 mouse_x = x;
497 mouse_y = y;
498 }
499 input_event_run_mouse_hooks( mouse_buttons, x, y, absolute );
500 }
502 /************************ Main display driver *************************/
504 void print_display_drivers( FILE *out )
505 {
506 int i;
507 fprintf( out, "Available video drivers:\n" );
508 for( i=0; display_driver_list[i] != NULL; i++ ) {
509 fprintf( out, " %-8s %s\n", display_driver_list[i]->name,
510 gettext(display_driver_list[i]->description) );
511 }
512 }
514 display_driver_t get_display_driver_by_name( const char *name )
515 {
516 int i;
517 if( name == NULL ) {
518 return display_driver_list[0];
519 }
520 for( i=0; display_driver_list[i] != NULL; i++ ) {
521 if( strcasecmp( display_driver_list[i]->name, name ) == 0 ) {
522 return display_driver_list[i];
523 }
524 }
526 return NULL;
527 }
530 gboolean display_set_driver( display_driver_t driver )
531 {
532 gboolean rv = TRUE;
533 if( display_driver != NULL && display_driver->shutdown_driver != NULL )
534 display_driver->shutdown_driver();
536 display_driver = driver;
537 if( driver->init_driver != NULL )
538 rv = driver->init_driver();
539 if( rv ) {
540 input_register_device(&system_mouse_driver, MAX_MOUSE_BUTTONS);
541 } else {
542 display_driver = NULL;
543 }
544 return rv;
545 }
547 void display_set_focused( gboolean has_focus )
548 {
549 display_focused = has_focus;
550 }
.