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[] = {
35 * The system has at least one "root" device representing the main display
36 * (which may be the null display). This device is part of the display_driver
37 * and generates events with no input_driver. The root device has no id
38 * as such (for the purposes of event names)
40 * The system may also have one or more auxilliary devices which each have
41 * an input_driver and an id (eg "JS0"). So the keysym "Return" is (de)coded by
42 * the root device, and the keysym "JS0: Button0" is (de)coded by the JS0 input
43 * device as "Button0".
45 * For the moment, mice are handled specially, as they behave a little
46 * differently from other devices (although this will probably change in the
51 typedef struct keymap_entry {
52 input_key_callback_t callback;
55 struct keymap_entry *next; // allow chaining
58 typedef struct mouse_entry {
60 input_mouse_callback_t callback;
62 struct mouse_entry *next;
65 typedef struct input_driver_entry {
66 input_driver_t driver;
68 struct keymap_entry *keymap[0];
69 } *input_driver_entry_t;
72 * Colour format information
74 struct colour_format colour_formats[] = {
75 { GL_UNSIGNED_SHORT_1_5_5_5_REV, GL_BGRA, GL_RGB5_A1, 2 },
76 { GL_UNSIGNED_SHORT_5_6_5, GL_RGB, GL_RGB5, 2 },
77 { GL_UNSIGNED_SHORT_4_4_4_4_REV, GL_BGRA, GL_RGBA4, 2 },
78 { GL_UNSIGNED_BYTE, GL_BGRA, GL_RGBA8, 4 }, /* YUV decoded to ARGB8888 */
79 { GL_UNSIGNED_BYTE, GL_BGR, GL_RGB, 3 },
80 { GL_UNSIGNED_BYTE, GL_BGRA, GL_RGBA8, 4 },
81 { GL_UNSIGNED_BYTE, GL_BGRA, GL_RGBA8, 4 }, /* Index4 decoded */
82 { GL_UNSIGNED_BYTE, GL_BGRA, GL_RGBA8, 4 }, /* Index8 decoded */
83 { GL_UNSIGNED_BYTE, GL_BGRA, GL_RGBA8, 4 },
84 { GL_UNSIGNED_BYTE, GL_RGB, GL_RGB, 3 },
89 * FIXME: make this more memory efficient
91 static struct keymap_entry *root_keymap[65535];
92 static struct keymap_entry *keyhooks = NULL;
93 static struct mouse_entry *mousehooks = NULL;
94 static gboolean display_focused = TRUE;
95 static GList *input_drivers= NULL;
96 static display_keysym_callback_t display_keysym_hook = NULL;
97 void *display_keysym_hook_data;
99 gboolean input_register_device( input_driver_t driver, uint16_t max_keycode )
102 for( ptr = input_drivers; ptr != NULL; ptr = g_list_next(ptr) ) {
103 input_driver_entry_t entry = (input_driver_entry_t)ptr->data;
104 if( strcasecmp( entry->driver->id, driver->id ) == 0 ) {
109 input_driver_entry_t entry = g_malloc0( sizeof(struct input_driver_entry) + (sizeof(keymap_entry_t) * max_keycode) );
110 entry->driver = driver;
111 entry->entry_count = max_keycode;
112 input_drivers = g_list_append( input_drivers, entry );
116 void input_unregister_device( input_driver_t driver )
119 for( ptr = input_drivers; ptr != NULL; ptr = g_list_next(ptr) ) {
120 input_driver_entry_t entry = (input_driver_entry_t)ptr->data;
121 if( entry->driver == driver ) {
122 if( driver->destroy != NULL ) {
123 driver->destroy(driver);
125 input_drivers = g_list_remove(input_drivers, (gpointer)entry);
133 * Resolve the keysym and return a pointer to the keymap entry pointer
134 * @return keymap pointer or NULL if the key was unresolved
136 static struct keymap_entry **input_entry_from_keysym( const gchar *keysym )
138 if( keysym == NULL || keysym[0] == 0 ) {
141 char **strv = g_strsplit(keysym,":",2);
142 if( strv[1] == NULL ) {
144 if( display_driver == NULL || display_driver->resolve_keysym == NULL) {
145 // Root device has no input handling
149 uint16_t keycode = display_driver->resolve_keysym(g_strstrip(strv[0]));
154 return &root_keymap[keycode-1];
156 char *id = g_strstrip(strv[0]);
158 for( ptr = input_drivers; ptr != NULL; ptr = g_list_next(ptr) ) {
159 input_driver_entry_t entry = (input_driver_entry_t)ptr->data;
160 if( strcasecmp( entry->driver->id, id ) == 0 ) {
161 /* we have ze device */
162 if( entry->driver->resolve_keysym == NULL ) {
166 uint16_t keycode = entry->driver->resolve_keysym(entry->driver, g_strstrip(strv[1]));
168 if( keycode == 0 || keycode > entry->entry_count ) {
171 return &entry->keymap[keycode-1];
175 return NULL; // device not found
179 static struct keymap_entry **input_entry_from_keycode( input_driver_t driver, uint16_t keycode )
187 if( driver == NULL ) {
188 return &root_keymap[keycode-1];
191 for( ptr = input_drivers; ptr != NULL; ptr = g_list_next(ptr) ) {
192 input_driver_entry_t entry = (input_driver_entry_t)ptr->data;
193 if( entry->driver == driver ) {
194 if( keycode > entry->entry_count ) {
197 return &entry->keymap[keycode-1];
204 static gchar *input_keysym_for_keycode( input_driver_t driver, uint16_t keycode )
209 if( driver == NULL ) {
210 if( display_driver != NULL && display_driver->get_keysym_for_keycode != NULL ) {
211 return display_driver->get_keysym_for_keycode(keycode);
213 } else if( driver->get_keysym_for_keycode ) {
214 gchar *sym = driver->get_keysym_for_keycode(driver,keycode);
216 gchar *result = g_strdup_printf( "%s: %s", driver->id, sym );
225 gboolean input_register_key( const gchar *keysym, input_key_callback_t callback,
226 void *data, uint32_t value )
228 if( keysym == NULL ) {
232 gchar **strv = g_strsplit(keysym, ",", 16);
234 while( *s != NULL ) {
235 keymap_entry_t *entryp = input_entry_from_keysym(*s);
236 if( entryp != NULL ) {
237 *entryp = g_malloc0(sizeof(struct keymap_entry));
238 (*entryp)->callback = callback;
239 (*entryp)->data = data;
240 (*entryp)->value = value;
249 void input_unregister_key( const gchar *keysym, input_key_callback_t callback,
250 void *data, uint32_t value )
252 if( keysym == NULL ) {
256 gchar **strv = g_strsplit(keysym, ",", 16);
258 while( *s != NULL ) {
259 keymap_entry_t *entryp = input_entry_from_keysym(*s);
260 if( entryp != NULL && *entryp != NULL && (*entryp)->callback == callback &&
261 (*entryp)->data == data && (*entryp)->value == value ) {
270 gboolean input_register_hook( input_key_callback_t callback,
273 keymap_entry_t key = malloc( sizeof( struct keymap_entry ) );
274 assert( key != NULL );
275 key->callback = callback;
277 key->next = keyhooks;
282 void input_unregister_hook( input_key_callback_t callback,
285 keymap_entry_t key = keyhooks;
287 keymap_entry_t next = key->next;
288 if( key->callback == callback && key->data == data ) {
293 while( next != NULL ) {
294 if( next->callback == callback && next->data == data ) {
295 key->next = next->next;
302 gboolean input_register_mouse_hook( gboolean relative, input_mouse_callback_t callback,
305 mouse_entry_t ent = malloc( sizeof( struct mouse_entry ) );
306 assert( ent != NULL );
307 ent->callback = callback;
309 ent->next = mousehooks;
314 void input_unregister_mouse_hook( input_mouse_callback_t callback, void *data )
316 mouse_entry_t ent = mousehooks;
318 mouse_entry_t next = ent->next;
319 if( ent->callback == callback && ent->data == data ) {
324 while( next != NULL ) {
325 if( next->callback == callback && next->data == data ) {
326 ent->next = next->next;
333 void input_event_mouse( uint32_t buttons, int32_t x, int32_t y )
335 mouse_entry_t ent = mousehooks;
336 while( ent != NULL ) {
337 ent->callback(ent->data, buttons, x, y);
342 gboolean input_is_key_valid( const gchar *keysym )
344 keymap_entry_t *ptr = input_entry_from_keysym(keysym);
348 gboolean input_is_key_registered( const gchar *keysym )
350 keymap_entry_t *ptr = input_entry_from_keysym(keysym);
351 return ptr != NULL && *ptr != NULL;
354 void input_event_keydown( input_driver_t driver, uint16_t keycode, uint32_t pressure )
356 if( display_focused ) {
357 keymap_entry_t *entryp = input_entry_from_keycode(driver,keycode);
358 if( entryp != NULL && *entryp != NULL ) {
359 (*entryp)->callback( (*entryp)->data, (*entryp)->value, pressure, TRUE );
361 keymap_entry_t key = keyhooks;
362 while( key != NULL ) {
363 key->callback( key->data, keycode, pressure, TRUE );
367 if( display_keysym_hook != NULL ) {
368 gchar *sym = input_keysym_for_keycode( driver, keycode );
370 display_keysym_hook(display_keysym_hook_data, sym);
376 void input_event_keyup( 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 && *entryp != NULL ) {
381 (*entryp)->callback( (*entryp)->data, (*entryp)->value, pressure, FALSE );
384 keymap_entry_t key = keyhooks;
385 while( key != NULL ) {
386 key->callback( key->data, keycode, pressure, FALSE );
392 uint16_t input_keycode_to_dckeysym( uint16_t keycode )
394 return display_driver->convert_to_dckeysym(keycode);
397 display_driver_t get_display_driver_by_name( const char *name )
401 return display_driver_list[0];
403 for( i=0; display_driver_list[i] != NULL; i++ ) {
404 if( strcasecmp( display_driver_list[i]->name, name ) == 0 ) {
405 return display_driver_list[i];
413 gboolean display_set_driver( display_driver_t driver )
416 if( display_driver != NULL && display_driver->shutdown_driver != NULL )
417 display_driver->shutdown_driver();
419 display_driver = driver;
420 if( driver->init_driver != NULL )
421 rv = driver->init_driver();
423 display_driver = NULL;
428 void display_set_focused( gboolean has_focus )
430 display_focused = has_focus;
433 void input_set_keysym_hook( display_keysym_callback_t hook, void *data )
435 display_keysym_hook = hook;
436 display_keysym_hook_data = data;
.