Search
lxdream.org :: lxdream/src/gtkui/gtk_ctrl.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/gtkui/gtk_ctrl.c
changeset 852:2b4a5e3575b9
prev849:bbe26d798fc2
next1034:7044e01148f0
author nkeynes
date Tue Sep 09 00:51:43 2008 +0000 (15 years ago)
permissions -rw-r--r--
last change Add general gl_window_to_system_coords function to convert window system coordinates
back into something in the DC range of 640x480, update mouse events to use it
file annotate diff log raw
nkeynes@447
     1
/**
nkeynes@561
     2
 * $Id$
nkeynes@447
     3
 *
nkeynes@447
     4
 * Define the main (emu) GTK window, along with its menubars,
nkeynes@447
     5
 * toolbars, etc.
nkeynes@447
     6
 *
nkeynes@447
     7
 * Copyright (c) 2005 Nathan Keynes.
nkeynes@447
     8
 *
nkeynes@447
     9
 * This program is free software; you can redistribute it and/or modify
nkeynes@447
    10
 * it under the terms of the GNU General Public License as published by
nkeynes@447
    11
 * the Free Software Foundation; either version 2 of the License, or
nkeynes@447
    12
 * (at your option) any later version.
nkeynes@447
    13
 *
nkeynes@447
    14
 * This program is distributed in the hope that it will be useful,
nkeynes@447
    15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
nkeynes@447
    16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
nkeynes@447
    17
 * GNU General Public License for more details.
nkeynes@447
    18
 */
nkeynes@447
    19
nkeynes@447
    20
#include <assert.h>
nkeynes@669
    21
#include <string.h>
nkeynes@447
    22
#include <gtk/gtk.h>
nkeynes@460
    23
#include <gdk/gdkkeysyms.h>
nkeynes@447
    24
nkeynes@614
    25
#include "lxdream.h"
nkeynes@614
    26
#include "display.h"
nkeynes@537
    27
#include "gtkui/gtkui.h"
nkeynes@447
    28
#include "maple/maple.h"
nkeynes@447
    29
nkeynes@447
    30
#define MAX_DEVICES 4
nkeynes@447
    31
nkeynes@455
    32
static void controller_device_configure(maple_device_t device);
nkeynes@455
    33
nkeynes@455
    34
struct maple_config_class {
nkeynes@455
    35
    const char *name;
nkeynes@455
    36
    void (*config_func)(maple_device_t device);
nkeynes@455
    37
};
nkeynes@455
    38
nkeynes@447
    39
typedef struct maple_slot_data {
nkeynes@447
    40
    maple_device_t old_device;
nkeynes@447
    41
    maple_device_t new_device;
nkeynes@447
    42
    GtkWidget *button;
nkeynes@447
    43
    GtkWidget *combo;
nkeynes@447
    44
} *maple_slot_data_t;
nkeynes@447
    45
nkeynes@455
    46
static struct maple_config_class maple_device_config[] = {
nkeynes@736
    47
        { "Sega Controller", controller_device_configure },
nkeynes@852
    48
        { "Sega Lightgun", controller_device_configure },
nkeynes@736
    49
        { NULL, NULL } };
nkeynes@455
    50
nkeynes@447
    51
static struct maple_slot_data maple_data[MAX_DEVICES];
nkeynes@447
    52
nkeynes@614
    53
static void config_keysym_hook( void *data, const gchar *keysym )
nkeynes@614
    54
{
nkeynes@614
    55
    GtkWidget *widget = (GtkWidget *)data;
nkeynes@614
    56
    gtk_entry_set_text( GTK_ENTRY(widget), keysym );
nkeynes@614
    57
    g_object_set_data( G_OBJECT(widget), "keypress_mode", GINT_TO_POINTER(FALSE) );
nkeynes@614
    58
    input_set_keysym_hook(NULL, NULL);
nkeynes@614
    59
}
nkeynes@614
    60
nkeynes@460
    61
static gboolean config_key_buttonpress( GtkWidget *widget, GdkEventButton *event, gpointer user_data )
nkeynes@460
    62
{
nkeynes@460
    63
    gboolean keypress_mode = GPOINTER_TO_INT(g_object_get_data( G_OBJECT(widget), "keypress_mode"));
nkeynes@849
    64
    if( keypress_mode ) {
nkeynes@849
    65
        gchar *keysym = input_keycode_to_keysym( &system_mouse_driver, event->button);
nkeynes@849
    66
        if( keysym != NULL ) {
nkeynes@849
    67
            config_keysym_hook( widget, keysym );
nkeynes@849
    68
            g_free(keysym);
nkeynes@849
    69
        }
nkeynes@849
    70
        return TRUE;
nkeynes@849
    71
    } else {
nkeynes@736
    72
        gtk_entry_set_text( GTK_ENTRY(widget), _("<press key>") );
nkeynes@736
    73
        g_object_set_data( G_OBJECT(widget), "keypress_mode", GINT_TO_POINTER(TRUE) );
nkeynes@736
    74
        input_set_keysym_hook(config_keysym_hook, widget);
nkeynes@460
    75
    }
nkeynes@460
    76
    return FALSE;
nkeynes@460
    77
}
nkeynes@460
    78
nkeynes@455
    79
static gboolean config_key_keypress( GtkWidget *widget, GdkEventKey *event, gpointer user_data )
nkeynes@455
    80
{
nkeynes@460
    81
    gboolean keypress_mode = GPOINTER_TO_INT(g_object_get_data( G_OBJECT(widget), "keypress_mode"));
nkeynes@460
    82
    if( keypress_mode ) {
nkeynes@736
    83
        if( event->keyval == GDK_Escape ) {
nkeynes@736
    84
            gtk_entry_set_text( GTK_ENTRY(widget), "" );
nkeynes@736
    85
            g_object_set_data( G_OBJECT(widget), "keypress_mode", GINT_TO_POINTER(FALSE) );
nkeynes@736
    86
            return TRUE;
nkeynes@736
    87
        }
nkeynes@736
    88
        GdkKeymap *keymap = gdk_keymap_get_default();
nkeynes@736
    89
        guint keyval;
nkeynes@736
    90
nkeynes@736
    91
        gdk_keymap_translate_keyboard_state( keymap, event->hardware_keycode, 0, 0, &keyval, 
nkeynes@736
    92
                                             NULL, NULL, NULL );
nkeynes@736
    93
        gtk_entry_set_text( GTK_ENTRY(widget), gdk_keyval_name(keyval) );
nkeynes@736
    94
        g_object_set_data( G_OBJECT(widget), "keypress_mode", GINT_TO_POINTER(FALSE) );
nkeynes@736
    95
        input_set_keysym_hook(NULL, NULL);
nkeynes@736
    96
        return TRUE;
nkeynes@460
    97
    } else {
nkeynes@736
    98
        switch( event->keyval ) {
nkeynes@736
    99
        case GDK_Return:
nkeynes@736
   100
        case GDK_KP_Enter:
nkeynes@736
   101
            gtk_entry_set_text( GTK_ENTRY(widget), _("<press key>") );
nkeynes@736
   102
            g_object_set_data( G_OBJECT(widget), "keypress_mode", GINT_TO_POINTER(TRUE) );
nkeynes@736
   103
            input_set_keysym_hook(config_keysym_hook, widget);
nkeynes@736
   104
            return TRUE;
nkeynes@736
   105
        case GDK_BackSpace:
nkeynes@736
   106
        case GDK_Delete:
nkeynes@736
   107
            gtk_entry_set_text( GTK_ENTRY(widget), "" );
nkeynes@736
   108
            return TRUE;
nkeynes@736
   109
        }
nkeynes@736
   110
        return FALSE;
nkeynes@460
   111
    }
nkeynes@736
   112
nkeynes@455
   113
}
nkeynes@447
   114
nkeynes@455
   115
static void controller_config_done( GtkWidget *panel, gboolean isOK )
nkeynes@455
   116
{
nkeynes@460
   117
    if( isOK ) {
nkeynes@736
   118
        maple_device_t device = (maple_device_t)gtk_object_get_data( GTK_OBJECT(panel), "maple_device" );
nkeynes@736
   119
        lxdream_config_entry_t conf = device->get_config(device);
nkeynes@736
   120
        int i;
nkeynes@736
   121
        for( i=0; conf[i].key != NULL; i++ ) {
nkeynes@736
   122
            char buf[64];
nkeynes@736
   123
            GtkWidget *entry1, *entry2;
nkeynes@736
   124
            const gchar *key1, *key2;
nkeynes@736
   125
            snprintf( buf, sizeof(buf), "%s.1", conf[i].key );
nkeynes@736
   126
            entry1 = GTK_WIDGET(g_object_get_qdata( G_OBJECT(panel), g_quark_from_string(buf)));
nkeynes@736
   127
            key1 = gtk_entry_get_text(GTK_ENTRY(entry1));
nkeynes@736
   128
            snprintf( buf, sizeof(buf), "%s.2", conf[i].key );
nkeynes@736
   129
            entry2 = GTK_WIDGET(g_object_get_qdata( G_OBJECT(panel), g_quark_from_string(buf)));
nkeynes@736
   130
            key2 = gtk_entry_get_text(GTK_ENTRY(entry2));
nkeynes@736
   131
            if( key1 == NULL || key1[0] == '\0') {
nkeynes@736
   132
                lxdream_set_config_value( &conf[i], key2 );
nkeynes@736
   133
            } else if( key2 == NULL || key2[0] == '\0') {
nkeynes@736
   134
                lxdream_set_config_value( &conf[i], key1 );
nkeynes@736
   135
            } else {
nkeynes@736
   136
                char buf[64];
nkeynes@736
   137
                snprintf( buf, sizeof(buf), "%s, %s", key1, key2 );
nkeynes@736
   138
                lxdream_set_config_value( &conf[i], buf );
nkeynes@736
   139
            }
nkeynes@736
   140
        }
nkeynes@460
   141
    }
nkeynes@614
   142
    input_set_keysym_hook(NULL, NULL);
nkeynes@455
   143
}
nkeynes@455
   144
nkeynes@455
   145
static void controller_device_configure( maple_device_t device )
nkeynes@455
   146
{
nkeynes@770
   147
    lxdream_config_entry_t conf = maple_get_device_config(device);
nkeynes@455
   148
    int count, i;
nkeynes@455
   149
    for( count=0; conf[count].key != NULL; count++ );
nkeynes@455
   150
nkeynes@455
   151
    GtkWidget *table = gtk_table_new( (count+1)>>1, 6, FALSE );
nkeynes@460
   152
    GList *focus_chain = NULL;
nkeynes@460
   153
    gtk_object_set_data( GTK_OBJECT(table), "maple_device", device );
nkeynes@455
   154
    for( i=0; i<count; i++ ) {
nkeynes@736
   155
        GtkWidget *text, *text2;
nkeynes@736
   156
        char buf[64];
nkeynes@736
   157
        int x=0;
nkeynes@736
   158
        int y=i;
nkeynes@736
   159
        if( i >= (count+1)>>1 ) {
nkeynes@736
   160
            x = 3;
nkeynes@736
   161
            y -= (count+1)>>1;
nkeynes@736
   162
        }
nkeynes@770
   163
        gtk_table_attach( GTK_TABLE(table), gtk_label_new(gettext(conf[i].label)), x, x+1, y, y+1, 
nkeynes@736
   164
                          GTK_SHRINK, GTK_SHRINK, 0, 0 );
nkeynes@736
   165
        text = gtk_entry_new();
nkeynes@736
   166
        gtk_entry_set_width_chars( GTK_ENTRY(text), 11 );
nkeynes@736
   167
        gtk_entry_set_editable( GTK_ENTRY(text), FALSE );
nkeynes@736
   168
        g_signal_connect( text, "key_press_event", 
nkeynes@736
   169
                          G_CALLBACK(config_key_keypress), NULL );
nkeynes@736
   170
        g_signal_connect( text, "button_press_event",
nkeynes@736
   171
                          G_CALLBACK(config_key_buttonpress), NULL );
nkeynes@736
   172
        snprintf( buf, sizeof(buf), "%s.1", conf[i].key );
nkeynes@736
   173
        g_object_set_data( G_OBJECT(text), "keypress_mode", GINT_TO_POINTER(FALSE) );
nkeynes@736
   174
        g_object_set_qdata( G_OBJECT(table), g_quark_from_string(buf), text );
nkeynes@736
   175
        gtk_table_attach_defaults( GTK_TABLE(table), text, x+1, x+2, y, y+1);
nkeynes@736
   176
        focus_chain = g_list_append( focus_chain, text );
nkeynes@736
   177
        text2 = gtk_entry_new();
nkeynes@736
   178
        gtk_entry_set_width_chars( GTK_ENTRY(text2), 11 );
nkeynes@736
   179
        gtk_entry_set_editable( GTK_ENTRY(text2), FALSE );
nkeynes@736
   180
        g_signal_connect( text2, "key_press_event", 
nkeynes@736
   181
                          G_CALLBACK(config_key_keypress), NULL );
nkeynes@736
   182
        g_signal_connect( text2, "button_press_event",
nkeynes@736
   183
                          G_CALLBACK(config_key_buttonpress), NULL );
nkeynes@736
   184
        snprintf( buf, sizeof(buf), "%s.2", conf[i].key );
nkeynes@736
   185
        g_object_set_data( G_OBJECT(text2), "keypress_mode", GINT_TO_POINTER(FALSE) );
nkeynes@736
   186
        g_object_set_qdata( G_OBJECT(table), g_quark_from_string(buf), text2 );
nkeynes@736
   187
        gtk_table_attach_defaults( GTK_TABLE(table), text2, x+2, x+3, y, y+1);
nkeynes@736
   188
        focus_chain = g_list_append( focus_chain, text2 );
nkeynes@736
   189
        if( conf[i].value != NULL ) {
nkeynes@736
   190
            gchar **parts = g_strsplit(conf[i].value,",",3);
nkeynes@736
   191
            if( parts[0] != NULL ) {
nkeynes@736
   192
                gtk_entry_set_text( GTK_ENTRY(text), g_strstrip(parts[0]) );
nkeynes@736
   193
                if( parts[1] != NULL ) {
nkeynes@736
   194
                    gtk_entry_set_text( GTK_ENTRY(text2), g_strstrip(parts[1]) );
nkeynes@736
   195
                }
nkeynes@736
   196
            }
nkeynes@736
   197
            g_strfreev(parts);
nkeynes@736
   198
        }
nkeynes@455
   199
    }
nkeynes@460
   200
    gtk_container_set_focus_chain( GTK_CONTAINER(table), focus_chain );
nkeynes@508
   201
    gtk_gui_run_property_dialog( _("Controller Configuration"), table, controller_config_done );
nkeynes@455
   202
}
nkeynes@455
   203
nkeynes@455
   204
gboolean maple_properties_activated( GtkButton *button, gpointer user_data )
nkeynes@447
   205
{
nkeynes@447
   206
    maple_slot_data_t data = (maple_slot_data_t)user_data;
nkeynes@455
   207
    if( data->new_device != NULL ) {
nkeynes@736
   208
        int i;
nkeynes@736
   209
        for( i=0; maple_device_config[i].name != NULL; i++ ) {
nkeynes@736
   210
            if( strcmp(data->new_device->device_class->name, maple_device_config[i].name) == 0 ) {
nkeynes@736
   211
                if( data->new_device == data->old_device ) {
nkeynes@736
   212
                    // Make a copy at this point if we haven't already
nkeynes@736
   213
                    data->new_device = data->old_device->clone(data->old_device);
nkeynes@736
   214
                }
nkeynes@736
   215
                maple_device_config[i].config_func(data->new_device);
nkeynes@736
   216
                break;
nkeynes@736
   217
            }
nkeynes@736
   218
        }
nkeynes@736
   219
        if( maple_device_config[i].name == NULL ) {
nkeynes@736
   220
            gui_error_dialog( _("No configuration page available for device type") );
nkeynes@736
   221
        }
nkeynes@455
   222
    }
nkeynes@455
   223
    return TRUE;
nkeynes@447
   224
}
nkeynes@447
   225
nkeynes@455
   226
gboolean maple_device_changed( GtkComboBox *combo, gpointer user_data )
nkeynes@447
   227
{
nkeynes@447
   228
    maple_slot_data_t data = (maple_slot_data_t)user_data;
nkeynes@447
   229
    int active = gtk_combo_box_get_active(combo);
nkeynes@608
   230
    gboolean has_config = FALSE;
nkeynes@447
   231
    if( active != 0 ) {
nkeynes@736
   232
        gchar *devname = gtk_combo_box_get_active_text(combo);
nkeynes@736
   233
        const maple_device_class_t devclz = maple_get_device_class(devname);
nkeynes@736
   234
        assert(devclz != NULL);
nkeynes@736
   235
        if( data->new_device != NULL ) {
nkeynes@736
   236
            if( data->new_device->device_class != devclz ) {
nkeynes@736
   237
                if( data->new_device != data->old_device ) {
nkeynes@736
   238
                    data->new_device->destroy(data->new_device);
nkeynes@736
   239
                }
nkeynes@736
   240
                data->new_device = maple_new_device(devname);
nkeynes@736
   241
            }
nkeynes@736
   242
        } else {
nkeynes@736
   243
            data->new_device = maple_new_device(devname);
nkeynes@736
   244
        }
nkeynes@736
   245
        has_config = data->new_device != NULL && data->new_device->get_config != NULL;
nkeynes@447
   246
    } else {
nkeynes@736
   247
        if( data->new_device != NULL && data->new_device != data->old_device ) {
nkeynes@736
   248
            data->new_device->destroy(data->new_device);
nkeynes@736
   249
        }
nkeynes@736
   250
        data->new_device = NULL;
nkeynes@447
   251
    }
nkeynes@608
   252
    gtk_widget_set_sensitive(data->button, has_config);
nkeynes@455
   253
    return TRUE;
nkeynes@447
   254
}
nkeynes@447
   255
nkeynes@460
   256
void maple_dialog_done( GtkWidget *panel, gboolean isOK )
nkeynes@447
   257
{
nkeynes@460
   258
    if( isOK ) {
nkeynes@736
   259
        int i;
nkeynes@736
   260
        for( i=0; i<MAX_DEVICES; i++ ) {
nkeynes@736
   261
            if( maple_data[i].new_device != maple_data[i].old_device ) {
nkeynes@736
   262
                if( maple_data[i].old_device != NULL ) {
nkeynes@736
   263
                    maple_detach_device(i,0);
nkeynes@736
   264
                }
nkeynes@736
   265
                if( maple_data[i].new_device != NULL ) {
nkeynes@736
   266
                    maple_attach_device(maple_data[i].new_device, i, 0 );
nkeynes@736
   267
                }
nkeynes@736
   268
            }
nkeynes@736
   269
        }
nkeynes@736
   270
        lxdream_save_config();
nkeynes@460
   271
    } else {
nkeynes@736
   272
        int i;
nkeynes@736
   273
        for( i=0; i<MAX_DEVICES; i++ ) {
nkeynes@736
   274
            if( maple_data[i].new_device != NULL && 
nkeynes@736
   275
                    maple_data[i].new_device != maple_data[i].old_device ) {
nkeynes@736
   276
                maple_data[i].new_device->destroy(maple_data[i].new_device);
nkeynes@736
   277
            }
nkeynes@736
   278
        }
nkeynes@447
   279
    }
nkeynes@447
   280
nkeynes@447
   281
}
nkeynes@447
   282
nkeynes@455
   283
GtkWidget *maple_panel_new()
nkeynes@447
   284
{
nkeynes@447
   285
    GtkWidget *table = gtk_table_new(4, 3, TRUE);
nkeynes@447
   286
    int i,j;
nkeynes@447
   287
    const struct maple_device_class **devices = maple_get_device_classes();
nkeynes@447
   288
nkeynes@447
   289
    for( i=0; i< MAX_DEVICES; i++ ) {
nkeynes@764
   290
        char buf[16];
nkeynes@736
   291
        GtkWidget *combo, *button;
nkeynes@736
   292
        int active = 0;
nkeynes@736
   293
        maple_device_t device = maple_get_device(i,0);
nkeynes@764
   294
        snprintf( buf, sizeof(buf), _("Slot %d."), i );
nkeynes@736
   295
        gtk_table_attach_defaults( GTK_TABLE(table), gtk_label_new(buf), 0, 1, i, i+1 );
nkeynes@736
   296
        combo = gtk_combo_box_new_text();
nkeynes@736
   297
        gtk_combo_box_append_text( GTK_COMBO_BOX(combo), _("<empty>") );
nkeynes@736
   298
        for( j=0; devices[j] != NULL; j++ ) {
nkeynes@736
   299
            gtk_combo_box_append_text(GTK_COMBO_BOX(combo), devices[j]->name);
nkeynes@736
   300
            if( device != NULL && device->device_class == devices[j] ) {
nkeynes@736
   301
                active = j+1;
nkeynes@736
   302
            }
nkeynes@736
   303
        }
nkeynes@736
   304
        gtk_combo_box_set_active(GTK_COMBO_BOX(combo), active);
nkeynes@736
   305
        gtk_table_attach_defaults( GTK_TABLE(table), combo, 1, 2, i, i+1 );
nkeynes@736
   306
        button = gtk_button_new_from_stock( GTK_STOCK_PROPERTIES );
nkeynes@736
   307
        gtk_widget_set_sensitive(button, active != 0 && device->get_config != NULL);
nkeynes@736
   308
        gtk_table_attach_defaults( GTK_TABLE(table), button, 2, 3, i, i+1 );
nkeynes@447
   309
nkeynes@736
   310
        maple_data[i].old_device = device;
nkeynes@736
   311
        maple_data[i].new_device = device;
nkeynes@736
   312
        maple_data[i].combo = combo;
nkeynes@736
   313
        maple_data[i].button = button;
nkeynes@736
   314
        g_signal_connect( button, "clicked", 
nkeynes@736
   315
                          G_CALLBACK( maple_properties_activated ), &maple_data[i] );
nkeynes@736
   316
        g_signal_connect( combo, "changed", 
nkeynes@736
   317
                          G_CALLBACK( maple_device_changed ), &maple_data[i] );
nkeynes@447
   318
nkeynes@447
   319
    }
nkeynes@447
   320
    return table;
nkeynes@447
   321
}
nkeynes@447
   322
nkeynes@460
   323
void maple_dialog_run( )
nkeynes@447
   324
{
nkeynes@508
   325
    gtk_gui_run_property_dialog( _("Controller Settings"), maple_panel_new(), maple_dialog_done );
nkeynes@447
   326
}
.