Search
lxdream.org :: lxdream/src/display.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/display.c
changeset 615:38b69ec2f4c8
prev614:a2d239d4438a
next627:c218b062a843
author nkeynes
date Mon Jan 28 11:17:15 2008 +0000 (12 years ago)
permissions -rw-r--r--
last change Split axes into positive and negative sides. Works better now
file annotate diff log raw
nkeynes@144
     1
/**
nkeynes@561
     2
 * $Id$
nkeynes@144
     3
 *
nkeynes@144
     4
 * Generic support for keyboard and other input sources. The active display
nkeynes@144
     5
 * driver is expected to deliver events here, where they're translated and
nkeynes@144
     6
 * passed to the appropriate dreamcast controllers (if any).
nkeynes@144
     7
 *
nkeynes@144
     8
 * Copyright (c) 2005 Nathan Keynes.
nkeynes@144
     9
 *
nkeynes@144
    10
 * This program is free software; you can redistribute it and/or modify
nkeynes@144
    11
 * it under the terms of the GNU General Public License as published by
nkeynes@144
    12
 * the Free Software Foundation; either version 2 of the License, or
nkeynes@144
    13
 * (at your option) any later version.
nkeynes@144
    14
 *
nkeynes@144
    15
 * This program is distributed in the hope that it will be useful,
nkeynes@144
    16
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
nkeynes@144
    17
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
nkeynes@144
    18
 * GNU General Public License for more details.
nkeynes@144
    19
 */
nkeynes@144
    20
nkeynes@144
    21
#include <stdint.h>
nkeynes@144
    22
#include <assert.h>
nkeynes@144
    23
#include "dream.h"
nkeynes@144
    24
#include "display.h"
nkeynes@431
    25
#include "pvr2/pvr2.h"
nkeynes@144
    26
nkeynes@531
    27
display_driver_t display_driver_list[] = { 
nkeynes@541
    28
#ifdef HAVE_GTK
nkeynes@531
    29
					   &display_gtk_driver,
nkeynes@541
    30
#endif
nkeynes@531
    31
					   &display_null_driver,
nkeynes@531
    32
					   NULL };
nkeynes@531
    33
nkeynes@614
    34
/* Some explanation:
nkeynes@614
    35
 *   The system has at least one "root" device representing the main display 
nkeynes@614
    36
 * (which may be the null display). This device is part of the display_driver
nkeynes@614
    37
 * and generates events with no input_driver. The root device has no id
nkeynes@614
    38
 * as such (for the purposes of event names)
nkeynes@614
    39
 *
nkeynes@614
    40
 *   The system may also have one or more auxilliary devices which each have
nkeynes@614
    41
 * an input_driver and an id (eg "JS0"). So the keysym "Return" is (de)coded by
nkeynes@614
    42
 * the root device, and the keysym "JS0: Button0" is (de)coded by the JS0 input
nkeynes@614
    43
 * device as "Button0".
nkeynes@614
    44
 *
nkeynes@614
    45
 *   For the moment, mice are handled specially, as they behave a little
nkeynes@614
    46
 * differently from other devices (although this will probably change in the 
nkeynes@614
    47
 * future.
nkeynes@614
    48
 */
nkeynes@614
    49
nkeynes@614
    50
nkeynes@144
    51
typedef struct keymap_entry {
nkeynes@144
    52
    input_key_callback_t callback;
nkeynes@144
    53
    void *data;
nkeynes@144
    54
    uint32_t value;
nkeynes@608
    55
    struct keymap_entry *next; // allow chaining
nkeynes@144
    56
} *keymap_entry_t;
nkeynes@144
    57
nkeynes@608
    58
typedef struct mouse_entry {
nkeynes@608
    59
    gboolean relative;
nkeynes@608
    60
    input_mouse_callback_t callback;
nkeynes@608
    61
    void *data;
nkeynes@608
    62
    struct mouse_entry *next;
nkeynes@608
    63
} *mouse_entry_t;
nkeynes@608
    64
nkeynes@614
    65
typedef struct input_driver_entry {
nkeynes@614
    66
    input_driver_t driver;
nkeynes@614
    67
    uint16_t entry_count;
nkeynes@614
    68
    struct keymap_entry *keymap[0];
nkeynes@614
    69
} *input_driver_entry_t;
nkeynes@614
    70
nkeynes@144
    71
/**
nkeynes@327
    72
 * Colour format information
nkeynes@327
    73
 */
nkeynes@327
    74
struct colour_format colour_formats[] = {
nkeynes@329
    75
    { GL_UNSIGNED_SHORT_1_5_5_5_REV, GL_BGRA, GL_RGB5_A1, 2 },
nkeynes@327
    76
    { GL_UNSIGNED_SHORT_5_6_5, GL_RGB, GL_RGB5, 2 },
nkeynes@327
    77
    { GL_UNSIGNED_SHORT_4_4_4_4_REV, GL_BGRA, GL_RGBA4, 2 },
nkeynes@451
    78
    { GL_UNSIGNED_BYTE, GL_BGRA, GL_RGBA8, 4 }, /* YUV decoded to ARGB8888 */
nkeynes@327
    79
    { GL_UNSIGNED_BYTE, GL_BGR, GL_RGB, 3 },
nkeynes@451
    80
    { GL_UNSIGNED_BYTE, GL_BGRA, GL_RGBA8, 4 },
nkeynes@477
    81
    { GL_UNSIGNED_BYTE, GL_BGRA, GL_RGBA8, 4 }, /* Index4 decoded */
nkeynes@477
    82
    { GL_UNSIGNED_BYTE, GL_BGRA, GL_RGBA8, 4 }, /* Index8 decoded */
nkeynes@477
    83
    { GL_UNSIGNED_BYTE, GL_BGRA, GL_RGBA8, 4 },
nkeynes@477
    84
    { GL_UNSIGNED_BYTE, GL_RGB, GL_RGB, 3 },
nkeynes@352
    85
    
nkeynes@327
    86
};
nkeynes@327
    87
nkeynes@327
    88
/**
nkeynes@144
    89
 * FIXME: make this more memory efficient
nkeynes@144
    90
 */
nkeynes@614
    91
static struct keymap_entry *root_keymap[65535];
nkeynes@614
    92
static struct keymap_entry *keyhooks = NULL;
nkeynes@614
    93
static struct mouse_entry *mousehooks = NULL;
nkeynes@614
    94
static gboolean display_focused = TRUE;
nkeynes@614
    95
static GList *input_drivers= NULL;
nkeynes@614
    96
static display_keysym_callback_t display_keysym_hook = NULL;
nkeynes@614
    97
void *display_keysym_hook_data;
nkeynes@144
    98
nkeynes@614
    99
gboolean input_register_device( input_driver_t driver, uint16_t max_keycode )
nkeynes@144
   100
{
nkeynes@614
   101
    GList *ptr;
nkeynes@614
   102
    for( ptr = input_drivers; ptr != NULL; ptr = g_list_next(ptr) ) {
nkeynes@614
   103
	input_driver_entry_t entry = (input_driver_entry_t)ptr->data;
nkeynes@614
   104
	if( strcasecmp( entry->driver->id, driver->id ) == 0 ) {
nkeynes@614
   105
	    return FALSE;
nkeynes@614
   106
	}
nkeynes@144
   107
    }
nkeynes@614
   108
nkeynes@614
   109
    input_driver_entry_t entry = g_malloc0( sizeof(struct input_driver_entry) + (sizeof(keymap_entry_t) * max_keycode) );
nkeynes@614
   110
    entry->driver = driver;
nkeynes@614
   111
    entry->entry_count = max_keycode;
nkeynes@614
   112
    input_drivers = g_list_append( input_drivers, entry );
nkeynes@614
   113
    return TRUE;
nkeynes@144
   114
}
nkeynes@144
   115
nkeynes@615
   116
gboolean input_has_device( const gchar *id )
nkeynes@615
   117
{
nkeynes@615
   118
    GList *ptr;
nkeynes@615
   119
    for( ptr = input_drivers; ptr != NULL; ptr = g_list_next(ptr) ) {
nkeynes@615
   120
	input_driver_entry_t entry = (input_driver_entry_t)ptr->data;
nkeynes@615
   121
	if( strcasecmp(entry->driver->id, id) == 0 ) {
nkeynes@615
   122
	    return TRUE;
nkeynes@615
   123
	}
nkeynes@615
   124
    }
nkeynes@615
   125
    return FALSE;
nkeynes@615
   126
}
nkeynes@615
   127
nkeynes@615
   128
nkeynes@614
   129
void input_unregister_device( input_driver_t driver )
nkeynes@144
   130
{
nkeynes@614
   131
    GList *ptr;
nkeynes@614
   132
    for( ptr = input_drivers; ptr != NULL; ptr = g_list_next(ptr) ) {
nkeynes@614
   133
	input_driver_entry_t entry = (input_driver_entry_t)ptr->data;
nkeynes@614
   134
	if( entry->driver == driver ) {
nkeynes@614
   135
	    if( driver->destroy != NULL ) {
nkeynes@614
   136
		driver->destroy(driver);
nkeynes@614
   137
	    }
nkeynes@614
   138
	    input_drivers = g_list_remove(input_drivers, (gpointer)entry);
nkeynes@614
   139
	    g_free( entry );
nkeynes@614
   140
	    return;
nkeynes@614
   141
	}
nkeynes@144
   142
    }
nkeynes@144
   143
}
nkeynes@144
   144
nkeynes@614
   145
/**
nkeynes@614
   146
 * Resolve the keysym and return a pointer to the keymap entry pointer
nkeynes@614
   147
 * @return keymap pointer or NULL if the key was unresolved
nkeynes@614
   148
 */
nkeynes@614
   149
static struct keymap_entry **input_entry_from_keysym( const gchar *keysym )
nkeynes@144
   150
{
nkeynes@614
   151
    if( keysym == NULL || keysym[0] == 0 ) {
nkeynes@614
   152
	return NULL;
nkeynes@614
   153
    }
nkeynes@614
   154
    char **strv = g_strsplit(keysym,":",2);
nkeynes@614
   155
    if( strv[1] == NULL ) {
nkeynes@614
   156
	/* root device */
nkeynes@614
   157
	if( display_driver == NULL || display_driver->resolve_keysym == NULL) {
nkeynes@614
   158
	    // Root device has no input handling
nkeynes@614
   159
	    g_strfreev(strv);
nkeynes@614
   160
	    return NULL;
nkeynes@614
   161
	}
nkeynes@614
   162
	uint16_t keycode = display_driver->resolve_keysym(g_strstrip(strv[0]));
nkeynes@614
   163
	g_strfreev(strv);
nkeynes@614
   164
	if( keycode == 0 ) {
nkeynes@614
   165
	    return NULL;
nkeynes@614
   166
	}
nkeynes@614
   167
	return &root_keymap[keycode-1];
nkeynes@614
   168
    } else {
nkeynes@614
   169
	char *id = g_strstrip(strv[0]);
nkeynes@614
   170
	GList *ptr;
nkeynes@614
   171
	for( ptr = input_drivers; ptr != NULL; ptr = g_list_next(ptr) ) {
nkeynes@614
   172
	    input_driver_entry_t entry = (input_driver_entry_t)ptr->data;
nkeynes@614
   173
	    if( strcasecmp( entry->driver->id, id ) == 0 ) {
nkeynes@614
   174
		/* we have ze device */
nkeynes@614
   175
		if( entry->driver->resolve_keysym == NULL ) {
nkeynes@614
   176
		    g_strfreev(strv);
nkeynes@614
   177
		    return NULL;
nkeynes@614
   178
		} 
nkeynes@614
   179
		uint16_t keycode = entry->driver->resolve_keysym(entry->driver, g_strstrip(strv[1]));
nkeynes@614
   180
		g_strfreev(strv);
nkeynes@614
   181
		if( keycode == 0 || keycode > entry->entry_count ) {
nkeynes@614
   182
		    return NULL;
nkeynes@614
   183
		}
nkeynes@614
   184
		return &entry->keymap[keycode-1];
nkeynes@614
   185
	    }
nkeynes@614
   186
	}
nkeynes@614
   187
	g_strfreev(strv);
nkeynes@614
   188
	return NULL; // device not found
nkeynes@614
   189
    }
nkeynes@144
   190
}
nkeynes@144
   191
nkeynes@614
   192
static struct keymap_entry **input_entry_from_keycode( input_driver_t driver, uint16_t keycode )
nkeynes@614
   193
{
nkeynes@614
   194
    GList *ptr;
nkeynes@614
   195
nkeynes@614
   196
    if( keycode == 0 ) {
nkeynes@614
   197
	return NULL;
nkeynes@614
   198
    }
nkeynes@614
   199
nkeynes@614
   200
    if( driver == NULL ) {
nkeynes@614
   201
	return &root_keymap[keycode-1];
nkeynes@614
   202
    }
nkeynes@614
   203
nkeynes@614
   204
    for( ptr = input_drivers; ptr != NULL; ptr = g_list_next(ptr) ) {
nkeynes@614
   205
	input_driver_entry_t entry = (input_driver_entry_t)ptr->data;
nkeynes@614
   206
	if( entry->driver == driver ) {
nkeynes@614
   207
	    if( keycode > entry->entry_count ) {
nkeynes@614
   208
		return NULL;
nkeynes@614
   209
	    } else {
nkeynes@614
   210
		return &entry->keymap[keycode-1];
nkeynes@614
   211
	    }
nkeynes@614
   212
	}
nkeynes@614
   213
    }
nkeynes@614
   214
    return NULL;
nkeynes@614
   215
}
nkeynes@614
   216
nkeynes@614
   217
static gchar *input_keysym_for_keycode( input_driver_t driver, uint16_t keycode )
nkeynes@614
   218
{
nkeynes@614
   219
    if( keycode == 0 ) {
nkeynes@614
   220
	return NULL;
nkeynes@614
   221
    }
nkeynes@614
   222
    if( driver == NULL ) {
nkeynes@614
   223
	if( display_driver != NULL && display_driver->get_keysym_for_keycode != NULL ) {
nkeynes@614
   224
	    return display_driver->get_keysym_for_keycode(keycode);
nkeynes@614
   225
	}
nkeynes@614
   226
    } else if( driver->get_keysym_for_keycode ) {
nkeynes@614
   227
	gchar *sym = driver->get_keysym_for_keycode(driver,keycode);
nkeynes@614
   228
	if( sym != NULL ) {
nkeynes@614
   229
	    gchar *result = g_strdup_printf( "%s: %s", driver->id, sym );
nkeynes@614
   230
	    g_free(sym);
nkeynes@614
   231
	    return result;
nkeynes@614
   232
	}
nkeynes@614
   233
    }
nkeynes@614
   234
    return NULL;
nkeynes@614
   235
}
nkeynes@614
   236
nkeynes@614
   237
nkeynes@144
   238
gboolean input_register_key( const gchar *keysym, input_key_callback_t callback,
nkeynes@144
   239
			     void *data, uint32_t value )
nkeynes@144
   240
{
nkeynes@614
   241
    if( keysym == NULL ) {
nkeynes@614
   242
	return FALSE;
nkeynes@614
   243
    }
nkeynes@614
   244
    int keys = 0;
nkeynes@271
   245
    gchar **strv = g_strsplit(keysym, ",", 16);
nkeynes@271
   246
    gchar **s = strv;
nkeynes@271
   247
    while( *s != NULL ) {
nkeynes@614
   248
	keymap_entry_t *entryp = input_entry_from_keysym(*s);
nkeynes@614
   249
	if( entryp != NULL ) {
nkeynes@614
   250
	    *entryp = g_malloc0(sizeof(struct keymap_entry));
nkeynes@614
   251
	    (*entryp)->callback = callback;
nkeynes@614
   252
	    (*entryp)->data = data;
nkeynes@614
   253
	    (*entryp)->value = value;
nkeynes@614
   254
	    keys++;
nkeynes@614
   255
	}
nkeynes@271
   256
	s++;
nkeynes@271
   257
    }
nkeynes@271
   258
    g_strfreev(strv);
nkeynes@614
   259
    return keys != 0;
nkeynes@144
   260
}
nkeynes@144
   261
nkeynes@451
   262
void input_unregister_key( const gchar *keysym, input_key_callback_t callback,
nkeynes@451
   263
			   void *data, uint32_t value )
nkeynes@144
   264
{
nkeynes@614
   265
    if( keysym == NULL ) {
nkeynes@144
   266
	return;
nkeynes@614
   267
    }
nkeynes@614
   268
nkeynes@614
   269
    gchar **strv = g_strsplit(keysym, ",", 16);
nkeynes@614
   270
    gchar **s = strv;
nkeynes@614
   271
    while( *s != NULL ) {
nkeynes@614
   272
	keymap_entry_t *entryp = input_entry_from_keysym(*s);
nkeynes@614
   273
	if( entryp != NULL && *entryp != NULL && (*entryp)->callback == callback &&
nkeynes@614
   274
	    (*entryp)->data == data && (*entryp)->value == value ) {
nkeynes@614
   275
	    g_free( *entryp );
nkeynes@614
   276
	    *entryp = NULL;
nkeynes@614
   277
	}
nkeynes@614
   278
	s++;
nkeynes@614
   279
    }
nkeynes@614
   280
    g_strfreev(strv);
nkeynes@144
   281
}
nkeynes@608
   282
nkeynes@608
   283
gboolean input_register_hook( input_key_callback_t callback,
nkeynes@608
   284
			      void *data )
nkeynes@608
   285
{
nkeynes@608
   286
    keymap_entry_t key = malloc( sizeof( struct keymap_entry ) );
nkeynes@608
   287
    assert( key != NULL );
nkeynes@608
   288
    key->callback = callback;
nkeynes@608
   289
    key->data = data;
nkeynes@608
   290
    key->next = keyhooks;
nkeynes@608
   291
    keyhooks = key;
nkeynes@608
   292
    return TRUE;
nkeynes@608
   293
}
nkeynes@608
   294
nkeynes@608
   295
void input_unregister_hook( input_key_callback_t callback,
nkeynes@608
   296
			    void *data )
nkeynes@608
   297
{
nkeynes@608
   298
    keymap_entry_t key = keyhooks;
nkeynes@608
   299
    if( key != NULL ) {
nkeynes@608
   300
	keymap_entry_t next = key->next;
nkeynes@608
   301
	if( key->callback == callback && key->data == data ) {
nkeynes@608
   302
	    free(key);
nkeynes@608
   303
	    keyhooks = next;
nkeynes@608
   304
	    return;
nkeynes@608
   305
	}
nkeynes@608
   306
	while( next != NULL ) {
nkeynes@608
   307
	    if( next->callback == callback && next->data == data ) {
nkeynes@608
   308
		key->next = next->next;
nkeynes@608
   309
		free(next);
nkeynes@608
   310
	    }
nkeynes@608
   311
	}
nkeynes@608
   312
    }
nkeynes@608
   313
}
nkeynes@608
   314
nkeynes@608
   315
gboolean input_register_mouse_hook( gboolean relative, input_mouse_callback_t callback,
nkeynes@608
   316
				void *data )
nkeynes@608
   317
{
nkeynes@608
   318
    mouse_entry_t ent = malloc( sizeof( struct mouse_entry ) );
nkeynes@608
   319
    assert( ent != NULL );
nkeynes@608
   320
    ent->callback = callback;
nkeynes@608
   321
    ent->data = data;
nkeynes@608
   322
    ent->next = mousehooks;
nkeynes@608
   323
    mousehooks = ent;
nkeynes@608
   324
    return TRUE;
nkeynes@608
   325
}    
nkeynes@608
   326
nkeynes@608
   327
void input_unregister_mouse_hook( input_mouse_callback_t callback, void *data )
nkeynes@608
   328
{
nkeynes@608
   329
    mouse_entry_t ent = mousehooks;
nkeynes@608
   330
    if( ent != NULL ) {
nkeynes@608
   331
	mouse_entry_t next = ent->next;
nkeynes@608
   332
	if( ent->callback == callback && ent->data == data ) {
nkeynes@608
   333
	    free(ent);
nkeynes@608
   334
	    mousehooks = next;
nkeynes@608
   335
	    return;
nkeynes@608
   336
	}
nkeynes@608
   337
	while( next != NULL ) {
nkeynes@608
   338
	    if( next->callback == callback && next->data == data ) {
nkeynes@608
   339
		ent->next = next->next;
nkeynes@608
   340
		free(next);
nkeynes@608
   341
	    }
nkeynes@608
   342
	}
nkeynes@608
   343
    }
nkeynes@608
   344
}
nkeynes@608
   345
nkeynes@608
   346
void input_event_mouse( uint32_t buttons, int32_t x, int32_t y )
nkeynes@608
   347
{
nkeynes@608
   348
    mouse_entry_t ent = mousehooks;
nkeynes@608
   349
    while( ent != NULL ) {
nkeynes@608
   350
	ent->callback(ent->data, buttons, x, y);
nkeynes@608
   351
	ent = ent->next;
nkeynes@608
   352
    }
nkeynes@608
   353
}
nkeynes@144
   354
nkeynes@144
   355
gboolean input_is_key_valid( const gchar *keysym )
nkeynes@144
   356
{
nkeynes@614
   357
    keymap_entry_t *ptr = input_entry_from_keysym(keysym);
nkeynes@614
   358
    return ptr != NULL;
nkeynes@144
   359
}
nkeynes@144
   360
nkeynes@144
   361
gboolean input_is_key_registered( const gchar *keysym )
nkeynes@144
   362
{
nkeynes@614
   363
    keymap_entry_t *ptr = input_entry_from_keysym(keysym);
nkeynes@614
   364
    return ptr != NULL && *ptr != NULL;
nkeynes@144
   365
}
nkeynes@144
   366
nkeynes@614
   367
void input_event_keydown( input_driver_t driver, uint16_t keycode, uint32_t pressure )
nkeynes@144
   368
{
nkeynes@614
   369
    if( display_focused ) {
nkeynes@614
   370
	keymap_entry_t *entryp = input_entry_from_keycode(driver,keycode);
nkeynes@614
   371
	if( entryp != NULL && *entryp != NULL ) {
nkeynes@614
   372
	    (*entryp)->callback( (*entryp)->data, (*entryp)->value, pressure, TRUE );
nkeynes@614
   373
	}
nkeynes@614
   374
	keymap_entry_t key = keyhooks;
nkeynes@614
   375
	while( key != NULL ) {
nkeynes@614
   376
	    key->callback( key->data, keycode, pressure, TRUE );
nkeynes@614
   377
	    key = key->next;
nkeynes@614
   378
	}
nkeynes@608
   379
    }
nkeynes@614
   380
    if( display_keysym_hook != NULL ) {
nkeynes@614
   381
	gchar *sym = input_keysym_for_keycode( driver, keycode );
nkeynes@614
   382
	if( sym != NULL ) {
nkeynes@614
   383
	    display_keysym_hook(display_keysym_hook_data, sym);
nkeynes@614
   384
	    g_free(sym);
nkeynes@614
   385
	}
nkeynes@608
   386
    }
nkeynes@144
   387
}
nkeynes@144
   388
nkeynes@614
   389
void input_event_keyup( input_driver_t driver, uint16_t keycode, uint32_t pressure )
nkeynes@144
   390
{
nkeynes@614
   391
    if( display_focused ) {
nkeynes@614
   392
	keymap_entry_t *entryp = input_entry_from_keycode(driver,keycode);
nkeynes@614
   393
	if( entryp != NULL && *entryp != NULL ) {
nkeynes@614
   394
	    (*entryp)->callback( (*entryp)->data, (*entryp)->value, pressure, FALSE );
nkeynes@614
   395
	}
nkeynes@614
   396
nkeynes@614
   397
	keymap_entry_t key = keyhooks;
nkeynes@614
   398
	while( key != NULL ) {
nkeynes@614
   399
	    key->callback( key->data, keycode, pressure, FALSE );
nkeynes@614
   400
	    key = key->next;
nkeynes@614
   401
	}
nkeynes@608
   402
    }
nkeynes@608
   403
}
nkeynes@608
   404
nkeynes@608
   405
uint16_t input_keycode_to_dckeysym( uint16_t keycode )
nkeynes@608
   406
{
nkeynes@608
   407
    return display_driver->convert_to_dckeysym(keycode);
nkeynes@144
   408
}
nkeynes@144
   409
nkeynes@531
   410
display_driver_t get_display_driver_by_name( const char *name )
nkeynes@531
   411
{
nkeynes@531
   412
    int i;
nkeynes@531
   413
    if( name == NULL ) {
nkeynes@531
   414
	return display_driver_list[0];
nkeynes@531
   415
    }
nkeynes@531
   416
    for( i=0; display_driver_list[i] != NULL; i++ ) {
nkeynes@531
   417
	if( strcasecmp( display_driver_list[i]->name, name ) == 0 ) {
nkeynes@531
   418
	    return display_driver_list[i];
nkeynes@531
   419
	}
nkeynes@531
   420
    }
nkeynes@531
   421
nkeynes@531
   422
    return NULL;
nkeynes@531
   423
}
nkeynes@144
   424
nkeynes@144
   425
nkeynes@370
   426
gboolean display_set_driver( display_driver_t driver )
nkeynes@144
   427
{
nkeynes@370
   428
    gboolean rv = TRUE;
nkeynes@370
   429
    if( display_driver != NULL && display_driver->shutdown_driver != NULL ) 
nkeynes@144
   430
	display_driver->shutdown_driver();
nkeynes@144
   431
nkeynes@144
   432
    display_driver = driver;
nkeynes@144
   433
    if( driver->init_driver != NULL )
nkeynes@370
   434
	rv = driver->init_driver();
nkeynes@531
   435
    if( !rv ) {
nkeynes@531
   436
	display_driver = NULL;
nkeynes@370
   437
    }
nkeynes@370
   438
    return rv;
nkeynes@144
   439
}
nkeynes@614
   440
nkeynes@614
   441
void display_set_focused( gboolean has_focus )
nkeynes@614
   442
{
nkeynes@614
   443
    display_focused = has_focus;
nkeynes@614
   444
}
nkeynes@614
   445
nkeynes@614
   446
void input_set_keysym_hook( display_keysym_callback_t hook, void *data )
nkeynes@614
   447
{
nkeynes@614
   448
    display_keysym_hook = hook;
nkeynes@614
   449
    display_keysym_hook_data = data;
nkeynes@614
   450
}
.