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).
8 * Copyright (c) 2005 Nathan Keynes.
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.
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.
25 #include "pvr2/pvr2.h"
27 display_driver_t display_driver_list[] = {
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)
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".
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
55 typedef struct keymap_entry {
56 input_key_callback_t callback;
59 lxdream_config_group_t group;
60 struct keymap_entry *next; // allow chaining
63 typedef struct mouse_entry {
65 input_mouse_callback_t callback;
67 const lxdream_config_group_t group;
68 struct mouse_entry *next;
71 typedef struct input_driver_entry {
72 input_driver_t driver;
74 struct keymap_entry *keymap[0];
75 } *input_driver_entry_t;
78 * Colour format information
80 struct colour_format colour_formats[] = {
81 { GL_UNSIGNED_SHORT_1_5_5_5_REV, GL_BGRA, GL_RGB5_A1, 2 },
82 { GL_UNSIGNED_SHORT_5_6_5, GL_RGB, GL_RGB5, 2 },
83 { GL_UNSIGNED_SHORT_4_4_4_4_REV, GL_BGRA, GL_RGBA4, 2 },
84 { GL_UNSIGNED_BYTE, GL_BGRA, GL_RGBA8, 4 }, /* YUV decoded to ARGB8888 */
85 { GL_UNSIGNED_BYTE, GL_BGR, GL_RGB, 3 },
86 { GL_UNSIGNED_BYTE, GL_BGRA, GL_RGBA8, 4 },
87 { GL_UNSIGNED_BYTE, GL_BGRA, GL_RGBA8, 4 }, /* Index4 decoded */
88 { GL_UNSIGNED_BYTE, GL_BGRA, GL_RGBA8, 4 }, /* Index8 decoded */
89 { GL_UNSIGNED_BYTE, GL_BGRA, GL_RGBA8, 4 },
90 { GL_UNSIGNED_BYTE, GL_RGB, GL_RGB, 3 },
95 * FIXME: make this more memory efficient
97 static struct keymap_entry *root_keymap[65535];
98 static struct keymap_entry *keyhooks = NULL;
99 static gboolean display_focused = TRUE;
100 static GList *input_drivers= NULL;
101 static display_keysym_callback_t display_keysym_hook = NULL;
102 void *display_keysym_hook_data;
104 gboolean input_register_device( input_driver_t driver, uint16_t max_keycode )
107 for( ptr = input_drivers; ptr != NULL; ptr = g_list_next(ptr) ) {
108 input_driver_entry_t entry = (input_driver_entry_t)ptr->data;
109 if( strcasecmp( entry->driver->id, driver->id ) == 0 ) {
114 input_driver_entry_t entry = g_malloc0( sizeof(struct input_driver_entry) + (sizeof(keymap_entry_t) * max_keycode) );
115 entry->driver = driver;
116 entry->entry_count = max_keycode;
117 input_drivers = g_list_append( input_drivers, entry );
121 gboolean input_has_device( const gchar *id )
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, id) == 0 ) {
134 void input_unregister_device( input_driver_t driver )
137 for( ptr = input_drivers; ptr != NULL; ptr = g_list_next(ptr) ) {
138 input_driver_entry_t entry = (input_driver_entry_t)ptr->data;
139 if( entry->driver == driver ) {
140 if( driver->destroy != NULL ) {
141 driver->destroy(driver);
143 input_drivers = g_list_remove(input_drivers, (gpointer)entry);
151 * Resolve the keysym and return a pointer to the keymap entry pointer
152 * @return keymap pointer or NULL if the key was unresolved
154 static struct keymap_entry **input_entry_from_keysym( const gchar *keysym )
156 if( keysym == NULL || keysym[0] == 0 ) {
159 char **strv = g_strsplit(keysym,":",2);
160 if( strv[1] == NULL ) {
162 if( display_driver == NULL || display_driver->resolve_keysym == NULL) {
163 // Root device has no input handling
167 uint16_t keycode = display_driver->resolve_keysym(g_strstrip(strv[0]));
172 return &root_keymap[keycode-1];
175 char *id = g_strstrip(strv[0]);
177 for( ptr = input_drivers; ptr != NULL; ptr = g_list_next(ptr) ) {
178 input_driver_entry_t entry = (input_driver_entry_t)ptr->data;
179 if( strcasecmp( entry->driver->id, id ) == 0 ) {
180 /* we have ze device */
181 if( entry->driver->resolve_keysym == NULL ) {
185 uint16_t keycode = entry->driver->resolve_keysym(entry->driver, g_strstrip(strv[1]));
187 if( keycode == 0 || keycode > entry->entry_count ) {
190 return &entry->keymap[keycode-1];
194 return NULL; // device not found
198 static struct keymap_entry **input_entry_from_keycode( input_driver_t driver, uint16_t keycode )
206 if( driver == NULL ) {
207 return &root_keymap[keycode-1];
210 for( ptr = input_drivers; ptr != NULL; ptr = g_list_next(ptr) ) {
211 input_driver_entry_t entry = (input_driver_entry_t)ptr->data;
212 if( entry->driver == driver ) {
213 if( keycode > entry->entry_count ) {
216 return &entry->keymap[keycode-1];
223 gchar *input_keycode_to_keysym( input_driver_t driver, uint16_t keycode )
228 if( driver == NULL ) {
229 if( display_driver != NULL && display_driver->get_keysym_for_keycode != NULL ) {
230 return display_driver->get_keysym_for_keycode(keycode);
232 } else if( driver->get_keysym_for_keycode ) {
233 gchar *sym = driver->get_keysym_for_keycode(driver,keycode);
235 gchar *result = g_strdup_printf( "%s: %s", driver->id, sym );
244 gboolean input_register_key( const gchar *keysym, input_key_callback_t callback,
245 void *data, uint32_t value )
247 if( keysym == NULL ) {
251 gchar **strv = g_strsplit(keysym, ",", 16);
253 while( *s != NULL ) {
254 keymap_entry_t *entryp = input_entry_from_keysym(*s);
255 if( entryp != NULL ) {
256 keymap_entry_t newentry = g_malloc0(sizeof(struct keymap_entry));
257 newentry->next = *entryp;
258 newentry->callback = callback;
259 newentry->data = data;
260 newentry->value = value;
270 void input_unregister_key( const gchar *keysym, input_key_callback_t callback,
271 void *data, uint32_t value )
273 if( keysym == NULL ) {
277 gchar **strv = g_strsplit(keysym, ",", 16);
279 while( *s != NULL ) {
280 keymap_entry_t *entryp = input_entry_from_keysym(*s);
281 if( entryp != NULL ) {
282 while( *entryp != NULL ) {
283 if( (*entryp)->callback == callback &&
284 (*entryp)->data == data && (*entryp)->value == value ) {
285 keymap_entry_t next = (*entryp)->next;
290 entryp = &(*entryp)->next; // Yes, really
298 int input_register_keygroup( lxdream_config_group_t group)
302 for( i=0; group->params[i].key != NULL; i++ ) {
303 if( group->params[i].type == CONFIG_TYPE_KEY ) {
304 if( input_register_key( group->params[i].value, group->key_binding, group->data, group->params[i].tag ) ) {
312 void input_unregister_keygroup( lxdream_config_group_t group )
315 for( i=0; group->params[i].key != NULL; i++ ) {
316 if( group->params[i].type == CONFIG_TYPE_KEY ) {
317 input_unregister_key( group->params[i].value, group->key_binding, group->data, group->params[i].tag );
322 gboolean input_keygroup_changed( void *data, lxdream_config_group_t group, unsigned key,
323 const gchar *oldval, const gchar *newval )
325 input_unregister_key( oldval, group->key_binding, group->data, group->params[key].tag );
326 input_register_key( newval, group->key_binding, group->data, group->params[key].tag );
330 gboolean input_register_keyboard_hook( input_key_callback_t callback,
333 keymap_entry_t key = malloc( sizeof( struct keymap_entry ) );
334 assert( key != NULL );
335 key->callback = callback;
337 key->next = keyhooks;
342 void input_unregister_keyboard_hook( input_key_callback_t callback,
345 keymap_entry_t key = keyhooks;
347 if( key->callback == callback && key->data == data ) {
348 keyhooks = keyhooks->next;
352 while( key->next != NULL ) {
353 if( key->next->callback == callback && key->next->data == data ) {
354 keymap_entry_t next = key->next;
355 key->next = next->next;
364 gboolean input_is_key_valid( const gchar *keysym )
366 keymap_entry_t *ptr = input_entry_from_keysym(keysym);
370 gboolean input_is_key_registered( const gchar *keysym )
372 keymap_entry_t *ptr = input_entry_from_keysym(keysym);
373 return ptr != NULL && *ptr != NULL;
376 void input_event_keydown( input_driver_t driver, uint16_t keycode, uint32_t pressure )
378 if( display_focused ) {
379 keymap_entry_t *entryp = input_entry_from_keycode(driver,keycode);
380 if( entryp != NULL ) {
381 keymap_entry_t key = *entryp;
382 while( key != NULL ) {
383 key->callback( key->data, key->value, pressure, TRUE );
387 if( driver == NULL ) {
388 keymap_entry_t key = keyhooks;
389 while( key != NULL ) {
390 key->callback( key->data, keycode, pressure, TRUE );
395 if( display_keysym_hook != NULL ) {
396 gchar *sym = input_keycode_to_keysym( driver, keycode );
398 display_keysym_hook(display_keysym_hook_data, sym);
404 void input_event_keyup( input_driver_t driver, uint16_t keycode )
406 if( display_focused ) {
407 keymap_entry_t *entryp = input_entry_from_keycode(driver,keycode);
408 if( entryp != NULL ) {
409 keymap_entry_t key = *entryp;
410 while( key != NULL ) {
411 key->callback( key->data, key->value, 0, FALSE );
416 if( driver == NULL ) {
417 keymap_entry_t key = keyhooks;
418 while( key != NULL ) {
419 key->callback( key->data, keycode, 0, FALSE );
426 uint16_t input_keycode_to_dckeysym( uint16_t keycode )
428 return display_driver->convert_to_dckeysym(keycode);
431 void input_set_keysym_hook( display_keysym_callback_t hook, void *data )
433 display_keysym_hook = hook;
434 display_keysym_hook_data = data;
437 /***************** System mouse driver ****************/
439 static struct keymap_entry *mouse_keymap[MAX_MOUSE_BUTTONS];
440 static struct mouse_entry *mousehooks = NULL;
441 static uint32_t mouse_x = -1, mouse_y = -1, mouse_buttons = 0;
443 uint16_t mouse_resolve_keysym( struct input_driver *driver, const gchar *keysym )
445 if( strncasecmp( keysym, "Button", 6 ) == 0 ){
446 unsigned long button = strtoul( keysym+6, NULL, 10 );
447 if( button > MAX_MOUSE_BUTTONS ) {
450 return (uint16_t)button;
455 gchar *mouse_get_keysym( struct input_driver *driver, uint16_t keycode )
457 return g_strdup_printf( "Button%d", (keycode) );
460 struct input_driver system_mouse_driver = { "Mouse", mouse_resolve_keysym, NULL, mouse_get_keysym, NULL };
463 gboolean input_register_mouse_hook( gboolean relative, input_mouse_callback_t callback,
466 mouse_entry_t ent = malloc( sizeof( struct mouse_entry ) );
467 assert( ent != NULL );
468 ent->callback = callback;
470 ent->next = mousehooks;
475 void input_unregister_mouse_hook( input_mouse_callback_t callback, void *data )
477 mouse_entry_t ent = mousehooks;
479 if( ent->callback == callback && ent->data == data ) {
480 mousehooks = mousehooks->next;
484 while( ent->next != NULL ) {
485 if( ent->next->callback == callback && ent->next->data == data ) {
486 mouse_entry_t next = ent->next;
487 ent->next = next->next;
496 void input_event_run_mouse_hooks( uint32_t buttons, int32_t x, int32_t y, gboolean absolute )
498 mouse_entry_t ent = mousehooks;
499 while( ent != NULL ) {
500 ent->callback(ent->data, buttons, x, y, absolute);
505 void input_event_mousedown( uint16_t button, int32_t x, int32_t y, gboolean absolute )
511 mouse_buttons |= (1<<button);
512 input_event_keydown( &system_mouse_driver, button+1, MAX_PRESSURE );
513 input_event_run_mouse_hooks( mouse_buttons, x, y, absolute );
516 void input_event_mouseup( uint16_t button, int32_t x, int32_t y, gboolean absolute )
522 mouse_buttons &= ~(1<<button);
523 input_event_keyup( &system_mouse_driver, button+1 );
524 input_event_run_mouse_hooks( mouse_buttons, x, y, absolute );
527 void input_event_mousemove( int32_t x, int32_t y, gboolean absolute )
533 input_event_run_mouse_hooks( mouse_buttons, x, y, absolute );
536 /************************ Main display driver *************************/
538 void print_display_drivers( FILE *out )
541 fprintf( out, "Available video drivers:\n" );
542 for( i=0; display_driver_list[i] != NULL; i++ ) {
543 fprintf( out, " %-8s %s\n", display_driver_list[i]->name,
544 gettext(display_driver_list[i]->description) );
548 display_driver_t get_display_driver_by_name( const char *name )
552 return display_driver_list[0];
554 for( i=0; display_driver_list[i] != NULL; i++ ) {
555 if( strcasecmp( display_driver_list[i]->name, name ) == 0 ) {
556 return display_driver_list[i];
564 gboolean display_set_driver( display_driver_t driver )
567 if( display_driver != NULL && display_driver->shutdown_driver != NULL )
568 display_driver->shutdown_driver();
570 display_driver = driver;
571 if( driver->init_driver != NULL )
572 rv = driver->init_driver();
574 input_register_device(&system_mouse_driver, MAX_MOUSE_BUTTONS);
576 display_driver = NULL;
581 void display_set_focused( gboolean has_focus )
583 display_focused = has_focus;
.