Search
lxdream.org :: lxdream/src/display.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/display.c
changeset 1245:01e0020adf88
prev1244:6b54ef5ed413
next1298:d0eb2307b847
author nkeynes
date Fri Mar 02 23:49:10 2012 +1000 (8 years ago)
permissions -rw-r--r--
last change Android WIP:
* Rename gui_jni.c to gui_android.c - now quite android specific.
* Implement generic EGL driver with very minimal Java wrapper
* Run emulation in separate thread, and implement simple queue for
inter-thread communication.
* Add menu/action-bar items for start + reset
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@1245
    26
#include "pvr2/glutil.h"
nkeynes@144
    27
nkeynes@681
    28
display_driver_t display_driver_list[] = {
nkeynes@541
    29
#ifdef HAVE_GTK
nkeynes@736
    30
        &display_gtk_driver,
nkeynes@681
    31
#else
nkeynes@681
    32
#ifdef HAVE_COCOA
nkeynes@736
    33
        &display_osx_driver,
nkeynes@541
    34
#endif
nkeynes@1244
    35
#endif
nkeynes@1244
    36
#ifdef __ANDROID__
nkeynes@1245
    37
        &display_egl_driver,
nkeynes@1244
    38
#endif
nkeynes@736
    39
        &display_null_driver,
nkeynes@736
    40
        NULL };
nkeynes@531
    41
nkeynes@614
    42
/* Some explanation:
nkeynes@614
    43
 *   The system has at least one "root" device representing the main display 
nkeynes@614
    44
 * (which may be the null display). This device is part of the display_driver
nkeynes@614
    45
 * and generates events with no input_driver. The root device has no id
nkeynes@614
    46
 * as such (for the purposes of event names)
nkeynes@614
    47
 *
nkeynes@614
    48
 *   The system may also have one or more auxilliary devices which each have
nkeynes@614
    49
 * an input_driver and an id (eg "JS0"). So the keysym "Return" is (de)coded by
nkeynes@614
    50
 * the root device, and the keysym "JS0: Button0" is (de)coded by the JS0 input
nkeynes@614
    51
 * device as "Button0".
nkeynes@614
    52
 *
nkeynes@614
    53
 *   For the moment, mice are handled specially, as they behave a little
nkeynes@614
    54
 * differently from other devices (although this will probably change in the 
nkeynes@614
    55
 * future.
nkeynes@614
    56
 */
nkeynes@614
    57
nkeynes@614
    58
nkeynes@144
    59
typedef struct keymap_entry {
nkeynes@144
    60
    input_key_callback_t callback;
nkeynes@144
    61
    void *data;
nkeynes@144
    62
    uint32_t value;
nkeynes@1072
    63
    lxdream_config_group_t group;
nkeynes@608
    64
    struct keymap_entry *next; // allow chaining
nkeynes@144
    65
} *keymap_entry_t;
nkeynes@144
    66
nkeynes@608
    67
typedef struct mouse_entry {
nkeynes@608
    68
    gboolean relative;
nkeynes@608
    69
    input_mouse_callback_t callback;
nkeynes@608
    70
    void *data;
nkeynes@1072
    71
    const lxdream_config_group_t group;
nkeynes@608
    72
    struct mouse_entry *next;
nkeynes@608
    73
} *mouse_entry_t;
nkeynes@608
    74
nkeynes@614
    75
typedef struct input_driver_entry {
nkeynes@614
    76
    input_driver_t driver;
nkeynes@614
    77
    uint16_t entry_count;
nkeynes@614
    78
    struct keymap_entry *keymap[0];
nkeynes@614
    79
} *input_driver_entry_t;
nkeynes@614
    80
nkeynes@1239
    81
nkeynes@1239
    82
#ifndef GL_RGBA8
nkeynes@1239
    83
#define GL_RGBA8 GL_RGBA8_OES
nkeynes@1239
    84
#endif
nkeynes@1239
    85
nkeynes@1239
    86
#ifndef GL_RGB5
nkeynes@1239
    87
#define GL_RGB5 GL_RGB565
nkeynes@1239
    88
#endif
nkeynes@1239
    89
nkeynes@1239
    90
#ifndef GL_BGR
nkeynes@1239
    91
#define GL_BGR GL_BGRA
nkeynes@1239
    92
#endif
nkeynes@1239
    93
nkeynes@144
    94
/**
nkeynes@327
    95
 * Colour format information
nkeynes@327
    96
 */
nkeynes@327
    97
struct colour_format colour_formats[] = {
nkeynes@736
    98
        { GL_UNSIGNED_SHORT_1_5_5_5_REV, GL_BGRA, GL_RGB5_A1, 2 },
nkeynes@736
    99
        { GL_UNSIGNED_SHORT_5_6_5, GL_RGB, GL_RGB5, 2 },
nkeynes@736
   100
        { GL_UNSIGNED_SHORT_4_4_4_4_REV, GL_BGRA, GL_RGBA4, 2 },
nkeynes@736
   101
        { GL_UNSIGNED_BYTE, GL_BGRA, GL_RGBA8, 4 }, /* YUV decoded to ARGB8888 */
nkeynes@736
   102
        { GL_UNSIGNED_BYTE, GL_BGR, GL_RGB, 3 },
nkeynes@736
   103
        { GL_UNSIGNED_BYTE, GL_BGRA, GL_RGBA8, 4 },
nkeynes@736
   104
        { GL_UNSIGNED_BYTE, GL_BGRA, GL_RGBA8, 4 }, /* Index4 decoded */
nkeynes@736
   105
        { GL_UNSIGNED_BYTE, GL_BGRA, GL_RGBA8, 4 }, /* Index8 decoded */
nkeynes@736
   106
        { GL_UNSIGNED_BYTE, GL_BGRA, GL_RGBA8, 4 },
nkeynes@736
   107
        { GL_UNSIGNED_BYTE, GL_RGB, GL_RGB, 3 },
nkeynes@736
   108
nkeynes@327
   109
};
nkeynes@327
   110
nkeynes@327
   111
/**
nkeynes@144
   112
 * FIXME: make this more memory efficient
nkeynes@144
   113
 */
nkeynes@614
   114
static struct keymap_entry *root_keymap[65535];
nkeynes@614
   115
static struct keymap_entry *keyhooks = NULL;
nkeynes@614
   116
static gboolean display_focused = TRUE;
nkeynes@614
   117
static GList *input_drivers= NULL;
nkeynes@614
   118
static display_keysym_callback_t display_keysym_hook = NULL;
nkeynes@614
   119
void *display_keysym_hook_data;
nkeynes@144
   120
nkeynes@614
   121
gboolean input_register_device( input_driver_t driver, uint16_t max_keycode )
nkeynes@144
   122
{
nkeynes@614
   123
    GList *ptr;
nkeynes@614
   124
    for( ptr = input_drivers; ptr != NULL; ptr = g_list_next(ptr) ) {
nkeynes@736
   125
        input_driver_entry_t entry = (input_driver_entry_t)ptr->data;
nkeynes@736
   126
        if( strcasecmp( entry->driver->id, driver->id ) == 0 ) {
nkeynes@736
   127
            return FALSE;
nkeynes@736
   128
        }
nkeynes@144
   129
    }
nkeynes@614
   130
nkeynes@614
   131
    input_driver_entry_t entry = g_malloc0( sizeof(struct input_driver_entry) + (sizeof(keymap_entry_t) * max_keycode) );
nkeynes@614
   132
    entry->driver = driver;
nkeynes@614
   133
    entry->entry_count = max_keycode;
nkeynes@614
   134
    input_drivers = g_list_append( input_drivers, entry );
nkeynes@614
   135
    return TRUE;
nkeynes@144
   136
}
nkeynes@144
   137
nkeynes@615
   138
gboolean input_has_device( const gchar *id )
nkeynes@615
   139
{
nkeynes@615
   140
    GList *ptr;
nkeynes@615
   141
    for( ptr = input_drivers; ptr != NULL; ptr = g_list_next(ptr) ) {
nkeynes@736
   142
        input_driver_entry_t entry = (input_driver_entry_t)ptr->data;
nkeynes@736
   143
        if( strcasecmp(entry->driver->id, id) == 0 ) {
nkeynes@736
   144
            return TRUE;
nkeynes@736
   145
        }
nkeynes@615
   146
    }
nkeynes@615
   147
    return FALSE;
nkeynes@615
   148
}
nkeynes@615
   149
nkeynes@615
   150
nkeynes@614
   151
void input_unregister_device( input_driver_t driver )
nkeynes@144
   152
{
nkeynes@614
   153
    GList *ptr;
nkeynes@614
   154
    for( ptr = input_drivers; ptr != NULL; ptr = g_list_next(ptr) ) {
nkeynes@736
   155
        input_driver_entry_t entry = (input_driver_entry_t)ptr->data;
nkeynes@736
   156
        if( entry->driver == driver ) {
nkeynes@736
   157
            if( driver->destroy != NULL ) {
nkeynes@736
   158
                driver->destroy(driver);
nkeynes@736
   159
            }
nkeynes@736
   160
            input_drivers = g_list_remove(input_drivers, (gpointer)entry);
nkeynes@736
   161
            g_free( entry );
nkeynes@736
   162
            return;
nkeynes@736
   163
        }
nkeynes@144
   164
    }
nkeynes@144
   165
}
nkeynes@144
   166
nkeynes@614
   167
/**
nkeynes@614
   168
 * Resolve the keysym and return a pointer to the keymap entry pointer
nkeynes@614
   169
 * @return keymap pointer or NULL if the key was unresolved
nkeynes@614
   170
 */
nkeynes@614
   171
static struct keymap_entry **input_entry_from_keysym( const gchar *keysym )
nkeynes@144
   172
{
nkeynes@614
   173
    if( keysym == NULL || keysym[0] == 0 ) {
nkeynes@736
   174
        return NULL;
nkeynes@614
   175
    }
nkeynes@614
   176
    char **strv = g_strsplit(keysym,":",2);
nkeynes@614
   177
    if( strv[1] == NULL ) {
nkeynes@736
   178
        /* root device */
nkeynes@736
   179
        if( display_driver == NULL || display_driver->resolve_keysym == NULL) {
nkeynes@736
   180
            // Root device has no input handling
nkeynes@736
   181
            g_strfreev(strv);
nkeynes@736
   182
            return NULL;
nkeynes@736
   183
        }
nkeynes@736
   184
        uint16_t keycode = display_driver->resolve_keysym(g_strstrip(strv[0]));
nkeynes@736
   185
        g_strfreev(strv);
nkeynes@736
   186
        if( keycode == 0 ) {
nkeynes@736
   187
            return NULL;
nkeynes@736
   188
        }
nkeynes@736
   189
        return &root_keymap[keycode-1];
nkeynes@849
   190
nkeynes@614
   191
    } else {
nkeynes@736
   192
        char *id = g_strstrip(strv[0]);
nkeynes@736
   193
        GList *ptr;
nkeynes@736
   194
        for( ptr = input_drivers; ptr != NULL; ptr = g_list_next(ptr) ) {
nkeynes@736
   195
            input_driver_entry_t entry = (input_driver_entry_t)ptr->data;
nkeynes@736
   196
            if( strcasecmp( entry->driver->id, id ) == 0 ) {
nkeynes@736
   197
                /* we have ze device */
nkeynes@736
   198
                if( entry->driver->resolve_keysym == NULL ) {
nkeynes@736
   199
                    g_strfreev(strv);
nkeynes@736
   200
                    return NULL;
nkeynes@736
   201
                } 
nkeynes@736
   202
                uint16_t keycode = entry->driver->resolve_keysym(entry->driver, g_strstrip(strv[1]));
nkeynes@736
   203
                g_strfreev(strv);
nkeynes@736
   204
                if( keycode == 0 || keycode > entry->entry_count ) {
nkeynes@736
   205
                    return NULL;
nkeynes@736
   206
                }
nkeynes@736
   207
                return &entry->keymap[keycode-1];
nkeynes@736
   208
            }
nkeynes@736
   209
        }
nkeynes@736
   210
        g_strfreev(strv);
nkeynes@736
   211
        return NULL; // device not found
nkeynes@614
   212
    }
nkeynes@144
   213
}
nkeynes@144
   214
nkeynes@614
   215
static struct keymap_entry **input_entry_from_keycode( input_driver_t driver, uint16_t keycode )
nkeynes@614
   216
{
nkeynes@614
   217
    GList *ptr;
nkeynes@614
   218
nkeynes@614
   219
    if( keycode == 0 ) {
nkeynes@736
   220
        return NULL;
nkeynes@614
   221
    }
nkeynes@614
   222
nkeynes@614
   223
    if( driver == NULL ) {
nkeynes@736
   224
        return &root_keymap[keycode-1];
nkeynes@614
   225
    }
nkeynes@614
   226
nkeynes@614
   227
    for( ptr = input_drivers; ptr != NULL; ptr = g_list_next(ptr) ) {
nkeynes@736
   228
        input_driver_entry_t entry = (input_driver_entry_t)ptr->data;
nkeynes@736
   229
        if( entry->driver == driver ) {
nkeynes@736
   230
            if( keycode > entry->entry_count ) {
nkeynes@736
   231
                return NULL;
nkeynes@736
   232
            } else {
nkeynes@736
   233
                return &entry->keymap[keycode-1];
nkeynes@736
   234
            }
nkeynes@736
   235
        }
nkeynes@614
   236
    }
nkeynes@614
   237
    return NULL;
nkeynes@614
   238
}
nkeynes@614
   239
nkeynes@770
   240
gchar *input_keycode_to_keysym( input_driver_t driver, uint16_t keycode )
nkeynes@614
   241
{
nkeynes@614
   242
    if( keycode == 0 ) {
nkeynes@736
   243
        return NULL;
nkeynes@614
   244
    }
nkeynes@614
   245
    if( driver == NULL ) {
nkeynes@736
   246
        if( display_driver != NULL && display_driver->get_keysym_for_keycode != NULL ) {
nkeynes@736
   247
            return display_driver->get_keysym_for_keycode(keycode);
nkeynes@736
   248
        }
nkeynes@614
   249
    } else if( driver->get_keysym_for_keycode ) {
nkeynes@736
   250
        gchar *sym = driver->get_keysym_for_keycode(driver,keycode);
nkeynes@736
   251
        if( sym != NULL ) {
nkeynes@736
   252
            gchar *result = g_strdup_printf( "%s: %s", driver->id, sym );
nkeynes@736
   253
            g_free(sym);
nkeynes@736
   254
            return result;
nkeynes@736
   255
        }
nkeynes@614
   256
    }
nkeynes@614
   257
    return NULL;
nkeynes@614
   258
}
nkeynes@614
   259
nkeynes@614
   260
nkeynes@144
   261
gboolean input_register_key( const gchar *keysym, input_key_callback_t callback,
nkeynes@736
   262
                             void *data, uint32_t value )
nkeynes@144
   263
{
nkeynes@614
   264
    if( keysym == NULL ) {
nkeynes@736
   265
        return FALSE;
nkeynes@614
   266
    }
nkeynes@614
   267
    int keys = 0;
nkeynes@271
   268
    gchar **strv = g_strsplit(keysym, ",", 16);
nkeynes@271
   269
    gchar **s = strv;
nkeynes@271
   270
    while( *s != NULL ) {
nkeynes@736
   271
        keymap_entry_t *entryp = input_entry_from_keysym(*s);
nkeynes@736
   272
        if( entryp != NULL ) {
nkeynes@1019
   273
            keymap_entry_t newentry = g_malloc0(sizeof(struct keymap_entry));
nkeynes@1019
   274
            newentry->next = *entryp;
nkeynes@1019
   275
            newentry->callback = callback;
nkeynes@1019
   276
            newentry->data = data;
nkeynes@1019
   277
            newentry->value = value;
nkeynes@1019
   278
            *entryp = newentry;
nkeynes@736
   279
            keys++;
nkeynes@736
   280
        }
nkeynes@736
   281
        s++;
nkeynes@271
   282
    }
nkeynes@271
   283
    g_strfreev(strv);
nkeynes@614
   284
    return keys != 0;
nkeynes@144
   285
}
nkeynes@144
   286
nkeynes@451
   287
void input_unregister_key( const gchar *keysym, input_key_callback_t callback,
nkeynes@736
   288
                           void *data, uint32_t value )
nkeynes@144
   289
{
nkeynes@614
   290
    if( keysym == NULL ) {
nkeynes@736
   291
        return;
nkeynes@614
   292
    }
nkeynes@614
   293
nkeynes@614
   294
    gchar **strv = g_strsplit(keysym, ",", 16);
nkeynes@614
   295
    gchar **s = strv;
nkeynes@614
   296
    while( *s != NULL ) {
nkeynes@736
   297
        keymap_entry_t *entryp = input_entry_from_keysym(*s);
nkeynes@1019
   298
        if( entryp != NULL ) {
nkeynes@1019
   299
            while( *entryp != NULL ) {
nkeynes@1019
   300
                if( (*entryp)->callback == callback &&
nkeynes@1019
   301
                    (*entryp)->data == data && (*entryp)->value == value ) {
nkeynes@1019
   302
                    keymap_entry_t next = (*entryp)->next;
nkeynes@1019
   303
                    g_free( *entryp );
nkeynes@1019
   304
                    *entryp = next;
nkeynes@1019
   305
                    break;
nkeynes@1019
   306
                }
nkeynes@1019
   307
                entryp = &(*entryp)->next; // Yes, really
nkeynes@1019
   308
            }
nkeynes@736
   309
        }
nkeynes@736
   310
        s++;
nkeynes@614
   311
    }
nkeynes@614
   312
    g_strfreev(strv);
nkeynes@144
   313
}
nkeynes@608
   314
nkeynes@1072
   315
int input_register_keygroup( lxdream_config_group_t group)
nkeynes@1072
   316
{
nkeynes@1072
   317
    int i;
nkeynes@1072
   318
    int result = 0;
nkeynes@1072
   319
    for( i=0; group->params[i].key != NULL; i++ ) {
nkeynes@1072
   320
        if( group->params[i].type == CONFIG_TYPE_KEY ) {
nkeynes@1072
   321
            if( input_register_key( group->params[i].value, group->key_binding, group->data, group->params[i].tag ) ) {
nkeynes@1072
   322
                result++;
nkeynes@1072
   323
            }
nkeynes@1072
   324
        }
nkeynes@1072
   325
    }
nkeynes@1072
   326
    return result;
nkeynes@1072
   327
}
nkeynes@1072
   328
nkeynes@1072
   329
void input_unregister_keygroup( lxdream_config_group_t group )
nkeynes@1072
   330
{
nkeynes@1072
   331
    int i;
nkeynes@1072
   332
    for( i=0; group->params[i].key != NULL; i++ ) {
nkeynes@1072
   333
        if( group->params[i].type == CONFIG_TYPE_KEY ) {
nkeynes@1072
   334
            input_unregister_key( group->params[i].value, group->key_binding, group->data, group->params[i].tag );
nkeynes@1072
   335
        }
nkeynes@1072
   336
    }
nkeynes@1072
   337
}
nkeynes@1072
   338
nkeynes@1072
   339
gboolean input_keygroup_changed( void *data, lxdream_config_group_t group, unsigned key,
nkeynes@1072
   340
                                 const gchar *oldval, const gchar *newval )
nkeynes@1072
   341
{
nkeynes@1072
   342
    input_unregister_key( oldval, group->key_binding, group->data, group->params[key].tag );
nkeynes@1072
   343
    input_register_key( newval, group->key_binding, group->data, group->params[key].tag );
nkeynes@1072
   344
    return TRUE;
nkeynes@1072
   345
}
nkeynes@1072
   346
nkeynes@849
   347
gboolean input_register_keyboard_hook( input_key_callback_t callback,
nkeynes@736
   348
                              void *data )
nkeynes@608
   349
{
nkeynes@608
   350
    keymap_entry_t key = malloc( sizeof( struct keymap_entry ) );
nkeynes@608
   351
    assert( key != NULL );
nkeynes@608
   352
    key->callback = callback;
nkeynes@608
   353
    key->data = data;
nkeynes@608
   354
    key->next = keyhooks;
nkeynes@608
   355
    keyhooks = key;
nkeynes@608
   356
    return TRUE;
nkeynes@608
   357
}
nkeynes@608
   358
nkeynes@849
   359
void input_unregister_keyboard_hook( input_key_callback_t callback,
nkeynes@736
   360
                            void *data )
nkeynes@608
   361
{
nkeynes@608
   362
    keymap_entry_t key = keyhooks;
nkeynes@608
   363
    if( key != NULL ) {
nkeynes@736
   364
        if( key->callback == callback && key->data == data ) {
nkeynes@736
   365
            keyhooks = keyhooks->next;
nkeynes@736
   366
            free(key);
nkeynes@736
   367
            return;
nkeynes@736
   368
        }
nkeynes@736
   369
        while( key->next != NULL ) {
nkeynes@736
   370
            if( key->next->callback == callback && key->next->data == data ) {
nkeynes@627
   371
                keymap_entry_t next = key->next;
nkeynes@736
   372
                key->next = next->next;
nkeynes@736
   373
                free(next);
nkeynes@736
   374
                return;
nkeynes@736
   375
            }
nkeynes@736
   376
            key = key->next;
nkeynes@736
   377
        }
nkeynes@608
   378
    }
nkeynes@608
   379
}
nkeynes@608
   380
nkeynes@849
   381
gboolean input_is_key_valid( const gchar *keysym )
nkeynes@849
   382
{
nkeynes@849
   383
    keymap_entry_t *ptr = input_entry_from_keysym(keysym);
nkeynes@849
   384
    return ptr != NULL;
nkeynes@849
   385
}
nkeynes@849
   386
nkeynes@849
   387
gboolean input_is_key_registered( const gchar *keysym )
nkeynes@849
   388
{
nkeynes@849
   389
    keymap_entry_t *ptr = input_entry_from_keysym(keysym);
nkeynes@849
   390
    return ptr != NULL && *ptr != NULL;
nkeynes@849
   391
}
nkeynes@849
   392
nkeynes@849
   393
void input_event_keydown( input_driver_t driver, uint16_t keycode, uint32_t pressure )
nkeynes@849
   394
{
nkeynes@849
   395
    if( display_focused ) {
nkeynes@849
   396
        keymap_entry_t *entryp = input_entry_from_keycode(driver,keycode);
nkeynes@1019
   397
        if( entryp != NULL ) {
nkeynes@1019
   398
            keymap_entry_t key = *entryp;
nkeynes@1019
   399
            while( key != NULL ) {
nkeynes@1019
   400
                key->callback( key->data, key->value, pressure, TRUE );
nkeynes@1019
   401
                key = key->next;
nkeynes@1019
   402
            }
nkeynes@849
   403
        }
nkeynes@849
   404
        if( driver == NULL ) {
nkeynes@849
   405
            keymap_entry_t key = keyhooks;
nkeynes@849
   406
            while( key != NULL ) {
nkeynes@849
   407
                key->callback( key->data, keycode, pressure, TRUE );
nkeynes@849
   408
                key = key->next;
nkeynes@849
   409
            }
nkeynes@849
   410
        }
nkeynes@849
   411
    }
nkeynes@849
   412
    if( display_keysym_hook != NULL ) {
nkeynes@849
   413
        gchar *sym = input_keycode_to_keysym( driver, keycode );
nkeynes@849
   414
        if( sym != NULL ) {
nkeynes@849
   415
            display_keysym_hook(display_keysym_hook_data, sym);
nkeynes@849
   416
            g_free(sym);
nkeynes@849
   417
        }
nkeynes@849
   418
    }
nkeynes@849
   419
}
nkeynes@849
   420
nkeynes@1010
   421
void input_event_keyup( input_driver_t driver, uint16_t keycode )
nkeynes@849
   422
{
nkeynes@849
   423
    if( display_focused ) {
nkeynes@849
   424
        keymap_entry_t *entryp = input_entry_from_keycode(driver,keycode);
nkeynes@1019
   425
        if( entryp != NULL ) {
nkeynes@1019
   426
            keymap_entry_t key = *entryp;
nkeynes@1019
   427
            while( key != NULL ) {
nkeynes@1019
   428
                key->callback( key->data, key->value, 0, FALSE );
nkeynes@1019
   429
                key = key->next;
nkeynes@1019
   430
            }
nkeynes@849
   431
        }
nkeynes@849
   432
nkeynes@849
   433
        if( driver == NULL ) {
nkeynes@849
   434
            keymap_entry_t key = keyhooks;
nkeynes@849
   435
            while( key != NULL ) {
nkeynes@1010
   436
                key->callback( key->data, keycode, 0, FALSE );
nkeynes@849
   437
                key = key->next;
nkeynes@849
   438
            }
nkeynes@849
   439
        }
nkeynes@849
   440
    }
nkeynes@849
   441
}
nkeynes@849
   442
nkeynes@849
   443
uint16_t input_keycode_to_dckeysym( uint16_t keycode )
nkeynes@849
   444
{
nkeynes@849
   445
    return display_driver->convert_to_dckeysym(keycode);
nkeynes@849
   446
}
nkeynes@849
   447
nkeynes@849
   448
void input_set_keysym_hook( display_keysym_callback_t hook, void *data )
nkeynes@849
   449
{
nkeynes@849
   450
    display_keysym_hook = hook;
nkeynes@849
   451
    display_keysym_hook_data = data;
nkeynes@849
   452
}
nkeynes@849
   453
nkeynes@849
   454
/***************** System mouse driver ****************/
nkeynes@849
   455
nkeynes@849
   456
static struct keymap_entry *mouse_keymap[MAX_MOUSE_BUTTONS];
nkeynes@849
   457
static struct mouse_entry *mousehooks = NULL;
nkeynes@849
   458
static uint32_t mouse_x = -1, mouse_y = -1, mouse_buttons = 0;
nkeynes@849
   459
nkeynes@849
   460
uint16_t mouse_resolve_keysym( struct input_driver *driver, const gchar *keysym )
nkeynes@849
   461
{
nkeynes@849
   462
    if( strncasecmp( keysym, "Button", 6 ) == 0 ){
nkeynes@849
   463
        unsigned long button = strtoul( keysym+6, NULL, 10 );
nkeynes@849
   464
        if( button > MAX_MOUSE_BUTTONS ) {
nkeynes@849
   465
            return 0;
nkeynes@849
   466
        }
nkeynes@849
   467
        return (uint16_t)button;
nkeynes@849
   468
    }
nkeynes@849
   469
    return 0;
nkeynes@849
   470
}
nkeynes@849
   471
nkeynes@849
   472
gchar *mouse_get_keysym( struct input_driver *driver, uint16_t keycode )
nkeynes@849
   473
{
nkeynes@849
   474
    return g_strdup_printf( "Button%d", (keycode) );
nkeynes@849
   475
}
nkeynes@849
   476
nkeynes@849
   477
struct input_driver system_mouse_driver = { "Mouse", mouse_resolve_keysym, NULL, mouse_get_keysym, NULL };
nkeynes@849
   478
nkeynes@849
   479
nkeynes@608
   480
gboolean input_register_mouse_hook( gboolean relative, input_mouse_callback_t callback,
nkeynes@736
   481
                                    void *data )
nkeynes@608
   482
{
nkeynes@608
   483
    mouse_entry_t ent = malloc( sizeof( struct mouse_entry ) );
nkeynes@608
   484
    assert( ent != NULL );
nkeynes@608
   485
    ent->callback = callback;
nkeynes@608
   486
    ent->data = data;
nkeynes@608
   487
    ent->next = mousehooks;
nkeynes@608
   488
    mousehooks = ent;
nkeynes@608
   489
    return TRUE;
nkeynes@608
   490
}    
nkeynes@608
   491
nkeynes@608
   492
void input_unregister_mouse_hook( input_mouse_callback_t callback, void *data )
nkeynes@608
   493
{
nkeynes@608
   494
    mouse_entry_t ent = mousehooks;
nkeynes@608
   495
    if( ent != NULL ) {
nkeynes@736
   496
        if( ent->callback == callback && ent->data == data ) {
nkeynes@736
   497
            mousehooks = mousehooks->next;
nkeynes@736
   498
            free(ent);
nkeynes@736
   499
            return;
nkeynes@736
   500
        }
nkeynes@736
   501
        while( ent->next != NULL ) {
nkeynes@736
   502
            if( ent->next->callback == callback && ent->next->data == data ) {
nkeynes@627
   503
                mouse_entry_t next = ent->next;
nkeynes@736
   504
                ent->next = next->next;
nkeynes@736
   505
                free(next);
nkeynes@736
   506
                return;
nkeynes@736
   507
            }
nkeynes@736
   508
            ent = ent->next;
nkeynes@736
   509
        }
nkeynes@608
   510
    }
nkeynes@608
   511
}
nkeynes@608
   512
nkeynes@849
   513
void input_event_run_mouse_hooks( uint32_t buttons, int32_t x, int32_t y, gboolean absolute )
nkeynes@608
   514
{
nkeynes@608
   515
    mouse_entry_t ent = mousehooks;
nkeynes@608
   516
    while( ent != NULL ) {
nkeynes@839
   517
        ent->callback(ent->data, buttons, x, y, absolute);
nkeynes@736
   518
        ent = ent->next;
nkeynes@608
   519
    }
nkeynes@608
   520
}
nkeynes@144
   521
nkeynes@849
   522
void input_event_mousedown( uint16_t button, int32_t x, int32_t y, gboolean absolute )
nkeynes@144
   523
{
nkeynes@849
   524
    if( absolute ) {
nkeynes@849
   525
        mouse_x = x;
nkeynes@849
   526
        mouse_y = y;
nkeynes@849
   527
    }
nkeynes@849
   528
    mouse_buttons |= (1<<button);
nkeynes@1010
   529
    input_event_keydown( &system_mouse_driver, button+1, MAX_PRESSURE );
nkeynes@849
   530
    input_event_run_mouse_hooks( mouse_buttons, x, y, absolute );
nkeynes@849
   531
}    
nkeynes@849
   532
nkeynes@849
   533
void input_event_mouseup( uint16_t button, int32_t x, int32_t y, gboolean absolute )
nkeynes@849
   534
{
nkeynes@849
   535
    if( absolute ) {
nkeynes@849
   536
        mouse_x = x;
nkeynes@849
   537
        mouse_y = y;
nkeynes@849
   538
    }
nkeynes@849
   539
    mouse_buttons &= ~(1<<button);
nkeynes@1010
   540
    input_event_keyup( &system_mouse_driver, button+1 );
nkeynes@849
   541
    input_event_run_mouse_hooks( mouse_buttons, x, y, absolute );
nkeynes@144
   542
}
nkeynes@144
   543
nkeynes@849
   544
void input_event_mousemove( int32_t x, int32_t y, gboolean absolute )
nkeynes@144
   545
{
nkeynes@849
   546
    if( absolute ) {
nkeynes@849
   547
        mouse_x = x;
nkeynes@849
   548
        mouse_y = y;
nkeynes@849
   549
    }
nkeynes@849
   550
    input_event_run_mouse_hooks( mouse_buttons, x, y, absolute );
nkeynes@144
   551
}
nkeynes@144
   552
nkeynes@849
   553
/************************ Main display driver *************************/
nkeynes@144
   554
nkeynes@700
   555
void print_display_drivers( FILE *out )
nkeynes@700
   556
{
nkeynes@700
   557
    int i;
nkeynes@700
   558
    fprintf( out, "Available video drivers:\n" );
nkeynes@700
   559
    for( i=0; display_driver_list[i] != NULL; i++ ) {
nkeynes@700
   560
        fprintf( out, "  %-8s %s\n", display_driver_list[i]->name,
nkeynes@736
   561
                gettext(display_driver_list[i]->description) );
nkeynes@700
   562
    }
nkeynes@700
   563
}
nkeynes@700
   564
nkeynes@531
   565
display_driver_t get_display_driver_by_name( const char *name )
nkeynes@531
   566
{
nkeynes@531
   567
    int i;
nkeynes@531
   568
    if( name == NULL ) {
nkeynes@736
   569
        return display_driver_list[0];
nkeynes@531
   570
    }
nkeynes@531
   571
    for( i=0; display_driver_list[i] != NULL; i++ ) {
nkeynes@736
   572
        if( strcasecmp( display_driver_list[i]->name, name ) == 0 ) {
nkeynes@736
   573
            return display_driver_list[i];
nkeynes@736
   574
        }
nkeynes@531
   575
    }
nkeynes@531
   576
nkeynes@531
   577
    return NULL;
nkeynes@531
   578
}
nkeynes@144
   579
nkeynes@144
   580
nkeynes@370
   581
gboolean display_set_driver( display_driver_t driver )
nkeynes@144
   582
{
nkeynes@370
   583
    gboolean rv = TRUE;
nkeynes@370
   584
    if( display_driver != NULL && display_driver->shutdown_driver != NULL ) 
nkeynes@736
   585
        display_driver->shutdown_driver();
nkeynes@144
   586
nkeynes@144
   587
    display_driver = driver;
nkeynes@144
   588
    if( driver->init_driver != NULL )
nkeynes@736
   589
        rv = driver->init_driver();
nkeynes@849
   590
    if( rv ) {
nkeynes@849
   591
        input_register_device(&system_mouse_driver, MAX_MOUSE_BUTTONS);
nkeynes@849
   592
    } else {
nkeynes@736
   593
        display_driver = NULL;
nkeynes@370
   594
    }
nkeynes@370
   595
    return rv;
nkeynes@144
   596
}
nkeynes@614
   597
nkeynes@614
   598
void display_set_focused( gboolean has_focus )
nkeynes@614
   599
{
nkeynes@614
   600
    display_focused = has_focus;
nkeynes@614
   601
}
.