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