filename | src/display.c |
changeset | 627:c218b062a843 |
prev | 615:38b69ec2f4c8 |
next | 681:1755a126b109 |
author | nkeynes |
date | Mon May 12 10:00:13 2008 +0000 (15 years ago) |
permissions | -rw-r--r-- |
last change | Cleanup most of the -Wall warnings (getting a bit sloppy...) Convert FP code to use fixed banks rather than indirect pointer (3-4% faster this way now) |
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 #endif
31 &display_null_driver,
32 NULL };
34 /* Some explanation:
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)
39 *
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".
44 *
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
47 * future.
48 */
51 typedef struct keymap_entry {
52 input_key_callback_t callback;
53 void *data;
54 uint32_t value;
55 struct keymap_entry *next; // allow chaining
56 } *keymap_entry_t;
58 typedef struct mouse_entry {
59 gboolean relative;
60 input_mouse_callback_t callback;
61 void *data;
62 struct mouse_entry *next;
63 } *mouse_entry_t;
65 typedef struct input_driver_entry {
66 input_driver_t driver;
67 uint16_t entry_count;
68 struct keymap_entry *keymap[0];
69 } *input_driver_entry_t;
71 /**
72 * Colour format information
73 */
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 },
86 };
88 /**
89 * FIXME: make this more memory efficient
90 */
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 )
100 {
101 GList *ptr;
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 ) {
105 return FALSE;
106 }
107 }
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 );
113 return TRUE;
114 }
116 gboolean input_has_device( const gchar *id )
117 {
118 GList *ptr;
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( strcasecmp(entry->driver->id, id) == 0 ) {
122 return TRUE;
123 }
124 }
125 return FALSE;
126 }
129 void input_unregister_device( input_driver_t driver )
130 {
131 GList *ptr;
132 for( ptr = input_drivers; ptr != NULL; ptr = g_list_next(ptr) ) {
133 input_driver_entry_t entry = (input_driver_entry_t)ptr->data;
134 if( entry->driver == driver ) {
135 if( driver->destroy != NULL ) {
136 driver->destroy(driver);
137 }
138 input_drivers = g_list_remove(input_drivers, (gpointer)entry);
139 g_free( entry );
140 return;
141 }
142 }
143 }
145 /**
146 * Resolve the keysym and return a pointer to the keymap entry pointer
147 * @return keymap pointer or NULL if the key was unresolved
148 */
149 static struct keymap_entry **input_entry_from_keysym( const gchar *keysym )
150 {
151 if( keysym == NULL || keysym[0] == 0 ) {
152 return NULL;
153 }
154 char **strv = g_strsplit(keysym,":",2);
155 if( strv[1] == NULL ) {
156 /* root device */
157 if( display_driver == NULL || display_driver->resolve_keysym == NULL) {
158 // Root device has no input handling
159 g_strfreev(strv);
160 return NULL;
161 }
162 uint16_t keycode = display_driver->resolve_keysym(g_strstrip(strv[0]));
163 g_strfreev(strv);
164 if( keycode == 0 ) {
165 return NULL;
166 }
167 return &root_keymap[keycode-1];
168 } else {
169 char *id = g_strstrip(strv[0]);
170 GList *ptr;
171 for( ptr = input_drivers; ptr != NULL; ptr = g_list_next(ptr) ) {
172 input_driver_entry_t entry = (input_driver_entry_t)ptr->data;
173 if( strcasecmp( entry->driver->id, id ) == 0 ) {
174 /* we have ze device */
175 if( entry->driver->resolve_keysym == NULL ) {
176 g_strfreev(strv);
177 return NULL;
178 }
179 uint16_t keycode = entry->driver->resolve_keysym(entry->driver, g_strstrip(strv[1]));
180 g_strfreev(strv);
181 if( keycode == 0 || keycode > entry->entry_count ) {
182 return NULL;
183 }
184 return &entry->keymap[keycode-1];
185 }
186 }
187 g_strfreev(strv);
188 return NULL; // device not found
189 }
190 }
192 static struct keymap_entry **input_entry_from_keycode( input_driver_t driver, uint16_t keycode )
193 {
194 GList *ptr;
196 if( keycode == 0 ) {
197 return NULL;
198 }
200 if( driver == NULL ) {
201 return &root_keymap[keycode-1];
202 }
204 for( ptr = input_drivers; ptr != NULL; ptr = g_list_next(ptr) ) {
205 input_driver_entry_t entry = (input_driver_entry_t)ptr->data;
206 if( entry->driver == driver ) {
207 if( keycode > entry->entry_count ) {
208 return NULL;
209 } else {
210 return &entry->keymap[keycode-1];
211 }
212 }
213 }
214 return NULL;
215 }
217 static gchar *input_keysym_for_keycode( input_driver_t driver, uint16_t keycode )
218 {
219 if( keycode == 0 ) {
220 return NULL;
221 }
222 if( driver == NULL ) {
223 if( display_driver != NULL && display_driver->get_keysym_for_keycode != NULL ) {
224 return display_driver->get_keysym_for_keycode(keycode);
225 }
226 } else if( driver->get_keysym_for_keycode ) {
227 gchar *sym = driver->get_keysym_for_keycode(driver,keycode);
228 if( sym != NULL ) {
229 gchar *result = g_strdup_printf( "%s: %s", driver->id, sym );
230 g_free(sym);
231 return result;
232 }
233 }
234 return NULL;
235 }
238 gboolean input_register_key( const gchar *keysym, input_key_callback_t callback,
239 void *data, uint32_t value )
240 {
241 if( keysym == NULL ) {
242 return FALSE;
243 }
244 int keys = 0;
245 gchar **strv = g_strsplit(keysym, ",", 16);
246 gchar **s = strv;
247 while( *s != NULL ) {
248 keymap_entry_t *entryp = input_entry_from_keysym(*s);
249 if( entryp != NULL ) {
250 *entryp = g_malloc0(sizeof(struct keymap_entry));
251 (*entryp)->callback = callback;
252 (*entryp)->data = data;
253 (*entryp)->value = value;
254 keys++;
255 }
256 s++;
257 }
258 g_strfreev(strv);
259 return keys != 0;
260 }
262 void input_unregister_key( const gchar *keysym, input_key_callback_t callback,
263 void *data, uint32_t value )
264 {
265 if( keysym == NULL ) {
266 return;
267 }
269 gchar **strv = g_strsplit(keysym, ",", 16);
270 gchar **s = strv;
271 while( *s != NULL ) {
272 keymap_entry_t *entryp = input_entry_from_keysym(*s);
273 if( entryp != NULL && *entryp != NULL && (*entryp)->callback == callback &&
274 (*entryp)->data == data && (*entryp)->value == value ) {
275 g_free( *entryp );
276 *entryp = NULL;
277 }
278 s++;
279 }
280 g_strfreev(strv);
281 }
283 gboolean input_register_hook( input_key_callback_t callback,
284 void *data )
285 {
286 keymap_entry_t key = malloc( sizeof( struct keymap_entry ) );
287 assert( key != NULL );
288 key->callback = callback;
289 key->data = data;
290 key->next = keyhooks;
291 keyhooks = key;
292 return TRUE;
293 }
295 void input_unregister_hook( input_key_callback_t callback,
296 void *data )
297 {
298 keymap_entry_t key = keyhooks;
299 if( key != NULL ) {
300 if( key->callback == callback && key->data == data ) {
301 keyhooks = keyhooks->next;
302 free(key);
303 return;
304 }
305 while( key->next != NULL ) {
306 if( key->next->callback == callback && key->next->data == data ) {
307 keymap_entry_t next = key->next;
308 key->next = next->next;
309 free(next);
310 return;
311 }
312 key = key->next;
313 }
314 }
315 }
317 gboolean input_register_mouse_hook( gboolean relative, input_mouse_callback_t callback,
318 void *data )
319 {
320 mouse_entry_t ent = malloc( sizeof( struct mouse_entry ) );
321 assert( ent != NULL );
322 ent->callback = callback;
323 ent->data = data;
324 ent->next = mousehooks;
325 mousehooks = ent;
326 return TRUE;
327 }
329 void input_unregister_mouse_hook( input_mouse_callback_t callback, void *data )
330 {
331 mouse_entry_t ent = mousehooks;
332 if( ent != NULL ) {
333 if( ent->callback == callback && ent->data == data ) {
334 mousehooks = mousehooks->next;
335 free(ent);
336 return;
337 }
338 while( ent->next != NULL ) {
339 if( ent->next->callback == callback && ent->next->data == data ) {
340 mouse_entry_t next = ent->next;
341 ent->next = next->next;
342 free(next);
343 return;
344 }
345 ent = ent->next;
346 }
347 }
348 }
350 void input_event_mouse( uint32_t buttons, int32_t x, int32_t y )
351 {
352 mouse_entry_t ent = mousehooks;
353 while( ent != NULL ) {
354 ent->callback(ent->data, buttons, x, y);
355 ent = ent->next;
356 }
357 }
359 gboolean input_is_key_valid( const gchar *keysym )
360 {
361 keymap_entry_t *ptr = input_entry_from_keysym(keysym);
362 return ptr != NULL;
363 }
365 gboolean input_is_key_registered( const gchar *keysym )
366 {
367 keymap_entry_t *ptr = input_entry_from_keysym(keysym);
368 return ptr != NULL && *ptr != NULL;
369 }
371 void input_event_keydown( input_driver_t driver, uint16_t keycode, uint32_t pressure )
372 {
373 if( display_focused ) {
374 keymap_entry_t *entryp = input_entry_from_keycode(driver,keycode);
375 if( entryp != NULL && *entryp != NULL ) {
376 (*entryp)->callback( (*entryp)->data, (*entryp)->value, pressure, TRUE );
377 }
378 keymap_entry_t key = keyhooks;
379 while( key != NULL ) {
380 key->callback( key->data, keycode, pressure, TRUE );
381 key = key->next;
382 }
383 }
384 if( display_keysym_hook != NULL ) {
385 gchar *sym = input_keysym_for_keycode( driver, keycode );
386 if( sym != NULL ) {
387 display_keysym_hook(display_keysym_hook_data, sym);
388 g_free(sym);
389 }
390 }
391 }
393 void input_event_keyup( 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 && *entryp != NULL ) {
398 (*entryp)->callback( (*entryp)->data, (*entryp)->value, pressure, FALSE );
399 }
401 keymap_entry_t key = keyhooks;
402 while( key != NULL ) {
403 key->callback( key->data, keycode, pressure, FALSE );
404 key = key->next;
405 }
406 }
407 }
409 uint16_t input_keycode_to_dckeysym( uint16_t keycode )
410 {
411 return display_driver->convert_to_dckeysym(keycode);
412 }
414 display_driver_t get_display_driver_by_name( const char *name )
415 {
416 int i;
417 if( name == NULL ) {
418 return display_driver_list[0];
419 }
420 for( i=0; display_driver_list[i] != NULL; i++ ) {
421 if( strcasecmp( display_driver_list[i]->name, name ) == 0 ) {
422 return display_driver_list[i];
423 }
424 }
426 return NULL;
427 }
430 gboolean display_set_driver( display_driver_t driver )
431 {
432 gboolean rv = TRUE;
433 if( display_driver != NULL && display_driver->shutdown_driver != NULL )
434 display_driver->shutdown_driver();
436 display_driver = driver;
437 if( driver->init_driver != NULL )
438 rv = driver->init_driver();
439 if( !rv ) {
440 display_driver = NULL;
441 }
442 return rv;
443 }
445 void display_set_focused( gboolean has_focus )
446 {
447 display_focused = has_focus;
448 }
450 void input_set_keysym_hook( display_keysym_callback_t hook, void *data )
451 {
452 display_keysym_hook = hook;
453 display_keysym_hook_data = data;
454 }
.