Search
lxdream.org :: lxdream/src/display.c :: diff
lxdream 0.9.1
released Jun 29
Download Now
filename src/display.c
changeset 614:a2d239d4438a
prev608:4f588e52bce0
next615:38b69ec2f4c8
author nkeynes
date Mon Jan 28 02:38:09 2008 +0000 (15 years ago)
permissions -rw-r--r--
last change Bug #49: Joystick support work in progress
file annotate diff log raw
1.1 --- a/src/display.c Sat Jan 26 02:45:27 2008 +0000
1.2 +++ b/src/display.c Mon Jan 28 02:38:09 2008 +0000
1.3 @@ -31,8 +31,24 @@
1.4 &display_null_driver,
1.5 NULL };
1.6
1.7 +/* Some explanation:
1.8 + * The system has at least one "root" device representing the main display
1.9 + * (which may be the null display). This device is part of the display_driver
1.10 + * and generates events with no input_driver. The root device has no id
1.11 + * as such (for the purposes of event names)
1.12 + *
1.13 + * The system may also have one or more auxilliary devices which each have
1.14 + * an input_driver and an id (eg "JS0"). So the keysym "Return" is (de)coded by
1.15 + * the root device, and the keysym "JS0: Button0" is (de)coded by the JS0 input
1.16 + * device as "Button0".
1.17 + *
1.18 + * For the moment, mice are handled specially, as they behave a little
1.19 + * differently from other devices (although this will probably change in the
1.20 + * future.
1.21 + */
1.22 +
1.23 +
1.24 typedef struct keymap_entry {
1.25 - uint16_t keycode;
1.26 input_key_callback_t callback;
1.27 void *data;
1.28 uint32_t value;
1.29 @@ -46,6 +62,12 @@
1.30 struct mouse_entry *next;
1.31 } *mouse_entry_t;
1.32
1.33 +typedef struct input_driver_entry {
1.34 + input_driver_t driver;
1.35 + uint16_t entry_count;
1.36 + struct keymap_entry *keymap[0];
1.37 +} *input_driver_entry_t;
1.38 +
1.39 /**
1.40 * Colour format information
1.41 */
1.42 @@ -66,68 +88,183 @@
1.43 /**
1.44 * FIXME: make this more memory efficient
1.45 */
1.46 -struct keymap_entry *keymap[65536];
1.47 -struct keymap_entry *keyhooks = NULL;
1.48 -struct mouse_entry *mousehooks = NULL;
1.49 +static struct keymap_entry *root_keymap[65535];
1.50 +static struct keymap_entry *keyhooks = NULL;
1.51 +static struct mouse_entry *mousehooks = NULL;
1.52 +static gboolean display_focused = TRUE;
1.53 +static GList *input_drivers= NULL;
1.54 +static display_keysym_callback_t display_keysym_hook = NULL;
1.55 +void *display_keysym_hook_data;
1.56
1.57 -static struct keymap_entry *input_create_key( uint16_t keycode )
1.58 +gboolean input_register_device( input_driver_t driver, uint16_t max_keycode )
1.59 {
1.60 - struct keymap_entry *key = keymap[ keycode ];
1.61 - if( key == NULL ) {
1.62 - key = malloc( sizeof( struct keymap_entry ) );
1.63 - assert( key != NULL );
1.64 - keymap[ keycode ] = key;
1.65 - key->keycode = keycode;
1.66 + GList *ptr;
1.67 + for( ptr = input_drivers; ptr != NULL; ptr = g_list_next(ptr) ) {
1.68 + input_driver_entry_t entry = (input_driver_entry_t)ptr->data;
1.69 + if( strcasecmp( entry->driver->id, driver->id ) == 0 ) {
1.70 + return FALSE;
1.71 + }
1.72 }
1.73 - return key;
1.74 +
1.75 + input_driver_entry_t entry = g_malloc0( sizeof(struct input_driver_entry) + (sizeof(keymap_entry_t) * max_keycode) );
1.76 + entry->driver = driver;
1.77 + entry->entry_count = max_keycode;
1.78 + input_drivers = g_list_append( input_drivers, entry );
1.79 + return TRUE;
1.80 }
1.81
1.82 -static void input_delete_key( uint16_t keycode, input_key_callback_t callback, void *data,
1.83 - uint32_t value )
1.84 +void input_unregister_device( input_driver_t driver )
1.85 {
1.86 - struct keymap_entry *key = keymap[keycode];
1.87 - if( key != NULL && key->callback == callback && key->data == data && key->value == value ) {
1.88 - free( key );
1.89 - keymap[keycode] = NULL;
1.90 + GList *ptr;
1.91 + for( ptr = input_drivers; ptr != NULL; ptr = g_list_next(ptr) ) {
1.92 + input_driver_entry_t entry = (input_driver_entry_t)ptr->data;
1.93 + if( entry->driver == driver ) {
1.94 + if( driver->destroy != NULL ) {
1.95 + driver->destroy(driver);
1.96 + }
1.97 + input_drivers = g_list_remove(input_drivers, (gpointer)entry);
1.98 + g_free( entry );
1.99 + return;
1.100 + }
1.101 }
1.102 }
1.103
1.104 -static struct keymap_entry *input_get_key( uint16_t keycode )
1.105 +/**
1.106 + * Resolve the keysym and return a pointer to the keymap entry pointer
1.107 + * @return keymap pointer or NULL if the key was unresolved
1.108 + */
1.109 +static struct keymap_entry **input_entry_from_keysym( const gchar *keysym )
1.110 {
1.111 - return keymap[ keycode ];
1.112 + if( keysym == NULL || keysym[0] == 0 ) {
1.113 + return NULL;
1.114 + }
1.115 + char **strv = g_strsplit(keysym,":",2);
1.116 + if( strv[1] == NULL ) {
1.117 + /* root device */
1.118 + if( display_driver == NULL || display_driver->resolve_keysym == NULL) {
1.119 + // Root device has no input handling
1.120 + g_strfreev(strv);
1.121 + return NULL;
1.122 + }
1.123 + uint16_t keycode = display_driver->resolve_keysym(g_strstrip(strv[0]));
1.124 + g_strfreev(strv);
1.125 + if( keycode == 0 ) {
1.126 + return NULL;
1.127 + }
1.128 + return &root_keymap[keycode-1];
1.129 + } else {
1.130 + char *id = g_strstrip(strv[0]);
1.131 + GList *ptr;
1.132 + for( ptr = input_drivers; ptr != NULL; ptr = g_list_next(ptr) ) {
1.133 + input_driver_entry_t entry = (input_driver_entry_t)ptr->data;
1.134 + if( strcasecmp( entry->driver->id, id ) == 0 ) {
1.135 + /* we have ze device */
1.136 + if( entry->driver->resolve_keysym == NULL ) {
1.137 + g_strfreev(strv);
1.138 + return NULL;
1.139 + }
1.140 + uint16_t keycode = entry->driver->resolve_keysym(entry->driver, g_strstrip(strv[1]));
1.141 + g_strfreev(strv);
1.142 + if( keycode == 0 || keycode > entry->entry_count ) {
1.143 + return NULL;
1.144 + }
1.145 + return &entry->keymap[keycode-1];
1.146 + }
1.147 + }
1.148 + g_strfreev(strv);
1.149 + return NULL; // device not found
1.150 + }
1.151 }
1.152
1.153 +static struct keymap_entry **input_entry_from_keycode( input_driver_t driver, uint16_t keycode )
1.154 +{
1.155 + GList *ptr;
1.156 +
1.157 + if( keycode == 0 ) {
1.158 + return NULL;
1.159 + }
1.160 +
1.161 + if( driver == NULL ) {
1.162 + return &root_keymap[keycode-1];
1.163 + }
1.164 +
1.165 + for( ptr = input_drivers; ptr != NULL; ptr = g_list_next(ptr) ) {
1.166 + input_driver_entry_t entry = (input_driver_entry_t)ptr->data;
1.167 + if( entry->driver == driver ) {
1.168 + if( keycode > entry->entry_count ) {
1.169 + return NULL;
1.170 + } else {
1.171 + return &entry->keymap[keycode-1];
1.172 + }
1.173 + }
1.174 + }
1.175 + return NULL;
1.176 +}
1.177 +
1.178 +static gchar *input_keysym_for_keycode( input_driver_t driver, uint16_t keycode )
1.179 +{
1.180 + if( keycode == 0 ) {
1.181 + return NULL;
1.182 + }
1.183 + if( driver == NULL ) {
1.184 + if( display_driver != NULL && display_driver->get_keysym_for_keycode != NULL ) {
1.185 + return display_driver->get_keysym_for_keycode(keycode);
1.186 + }
1.187 + } else if( driver->get_keysym_for_keycode ) {
1.188 + gchar *sym = driver->get_keysym_for_keycode(driver,keycode);
1.189 + if( sym != NULL ) {
1.190 + gchar *result = g_strdup_printf( "%s: %s", driver->id, sym );
1.191 + g_free(sym);
1.192 + return result;
1.193 + }
1.194 + }
1.195 + return NULL;
1.196 +}
1.197 +
1.198 +
1.199 gboolean input_register_key( const gchar *keysym, input_key_callback_t callback,
1.200 void *data, uint32_t value )
1.201 {
1.202 - if( display_driver == NULL || keysym == NULL || display_driver->resolve_keysym == NULL )
1.203 - return FALSE; /* No display driver */
1.204 + if( keysym == NULL ) {
1.205 + return FALSE;
1.206 + }
1.207 + int keys = 0;
1.208 gchar **strv = g_strsplit(keysym, ",", 16);
1.209 gchar **s = strv;
1.210 while( *s != NULL ) {
1.211 - uint16_t keycode = display_driver->resolve_keysym(g_strstrip(*s));
1.212 - if( keycode == 0 )
1.213 - return FALSE; /* Invalid keysym */
1.214 -
1.215 - struct keymap_entry *key = input_create_key( keycode );
1.216 - key->callback = callback;
1.217 - key->data = data;
1.218 - key->value = value;
1.219 + keymap_entry_t *entryp = input_entry_from_keysym(*s);
1.220 + if( entryp != NULL ) {
1.221 + *entryp = g_malloc0(sizeof(struct keymap_entry));
1.222 + (*entryp)->callback = callback;
1.223 + (*entryp)->data = data;
1.224 + (*entryp)->value = value;
1.225 + keys++;
1.226 + }
1.227 s++;
1.228 }
1.229 g_strfreev(strv);
1.230 - return TRUE;
1.231 + return keys != 0;
1.232 }
1.233
1.234 void input_unregister_key( const gchar *keysym, input_key_callback_t callback,
1.235 void *data, uint32_t value )
1.236 {
1.237 - if( display_driver == NULL || keysym == NULL || display_driver->resolve_keysym == NULL )
1.238 + if( keysym == NULL ) {
1.239 return;
1.240 - uint16_t keycode = display_driver->resolve_keysym(keysym);
1.241 - if( keycode == 0 )
1.242 - return;
1.243 - input_delete_key( keycode, callback, data, value );
1.244 + }
1.245 +
1.246 + gchar **strv = g_strsplit(keysym, ",", 16);
1.247 + gchar **s = strv;
1.248 + while( *s != NULL ) {
1.249 + keymap_entry_t *entryp = input_entry_from_keysym(*s);
1.250 + if( entryp != NULL && *entryp != NULL && (*entryp)->callback == callback &&
1.251 + (*entryp)->data == data && (*entryp)->value == value ) {
1.252 + g_free( *entryp );
1.253 + *entryp = NULL;
1.254 + }
1.255 + s++;
1.256 + }
1.257 + g_strfreev(strv);
1.258 }
1.259
1.260 gboolean input_register_hook( input_key_callback_t callback,
1.261 @@ -204,44 +341,51 @@
1.262
1.263 gboolean input_is_key_valid( const gchar *keysym )
1.264 {
1.265 - if( display_driver == NULL )
1.266 - return FALSE; /* No display driver */
1.267 - return display_driver->resolve_keysym(keysym) != 0;
1.268 + keymap_entry_t *ptr = input_entry_from_keysym(keysym);
1.269 + return ptr != NULL;
1.270 }
1.271
1.272 gboolean input_is_key_registered( const gchar *keysym )
1.273 {
1.274 - if( display_driver == NULL )
1.275 - return FALSE;
1.276 - uint16_t keycode = display_driver->resolve_keysym(keysym);
1.277 - if( keycode == 0 )
1.278 - return FALSE;
1.279 - return input_get_key( keycode ) != NULL;
1.280 + keymap_entry_t *ptr = input_entry_from_keysym(keysym);
1.281 + return ptr != NULL && *ptr != NULL;
1.282 }
1.283
1.284 -void input_event_keydown( uint16_t keycode )
1.285 +void input_event_keydown( input_driver_t driver, uint16_t keycode, uint32_t pressure )
1.286 {
1.287 - struct keymap_entry *key = input_get_key(keycode);
1.288 - if( key != NULL ) {
1.289 - key->callback( key->data, key->value, TRUE );
1.290 + if( display_focused ) {
1.291 + keymap_entry_t *entryp = input_entry_from_keycode(driver,keycode);
1.292 + if( entryp != NULL && *entryp != NULL ) {
1.293 + (*entryp)->callback( (*entryp)->data, (*entryp)->value, pressure, TRUE );
1.294 + }
1.295 + keymap_entry_t key = keyhooks;
1.296 + while( key != NULL ) {
1.297 + key->callback( key->data, keycode, pressure, TRUE );
1.298 + key = key->next;
1.299 + }
1.300 }
1.301 - key = keyhooks;
1.302 - while( key != NULL ) {
1.303 - key->callback( key->data, keycode, TRUE );
1.304 - key = key->next;
1.305 + if( display_keysym_hook != NULL ) {
1.306 + gchar *sym = input_keysym_for_keycode( driver, keycode );
1.307 + if( sym != NULL ) {
1.308 + display_keysym_hook(display_keysym_hook_data, sym);
1.309 + g_free(sym);
1.310 + }
1.311 }
1.312 }
1.313
1.314 -void input_event_keyup( uint16_t keycode )
1.315 +void input_event_keyup( input_driver_t driver, uint16_t keycode, uint32_t pressure )
1.316 {
1.317 - struct keymap_entry *key = input_get_key(keycode);
1.318 - if( key != NULL ) {
1.319 - key->callback( key->data, key->value, FALSE );
1.320 - }
1.321 - key = keyhooks;
1.322 - while( key != NULL ) {
1.323 - key->callback( key->data, keycode, FALSE );
1.324 - key = key->next;
1.325 + if( display_focused ) {
1.326 + keymap_entry_t *entryp = input_entry_from_keycode(driver,keycode);
1.327 + if( entryp != NULL && *entryp != NULL ) {
1.328 + (*entryp)->callback( (*entryp)->data, (*entryp)->value, pressure, FALSE );
1.329 + }
1.330 +
1.331 + keymap_entry_t key = keyhooks;
1.332 + while( key != NULL ) {
1.333 + key->callback( key->data, keycode, pressure, FALSE );
1.334 + key = key->next;
1.335 + }
1.336 }
1.337 }
1.338
1.339 @@ -280,3 +424,14 @@
1.340 }
1.341 return rv;
1.342 }
1.343 +
1.344 +void display_set_focused( gboolean has_focus )
1.345 +{
1.346 + display_focused = has_focus;
1.347 +}
1.348 +
1.349 +void input_set_keysym_hook( display_keysym_callback_t hook, void *data )
1.350 +{
1.351 + display_keysym_hook = hook;
1.352 + display_keysym_hook_data = data;
1.353 +}
.