]> Pileus Git - ~andy/gtk/blob - gtk/gtkinputdialog.c
Practically everything changed.
[~andy/gtk] / gtk / gtkinputdialog.c
1 /* GTK - The GTK+ Toolkit
2  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 /*
21  * gtkinputdialog.c
22  *
23  * Copyright 1997 Owen Taylor <owt1@cornell.edu>
24  *
25  */
26
27 /*
28  * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
29  * file for a list of people on the GTK+ Team.  See the ChangeLog
30  * files for a list of changes.  These files are distributed with
31  * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
32  */
33
34 #include "config.h"
35
36 #include <stdlib.h>
37
38 #include "gdk/gdkkeysyms.h"
39
40 #undef GTK_DISABLE_DEPRECATED /* GtkOptionMenu */
41
42 #include "gtkinputdialog.h"
43 #include "gtkbutton.h"
44 #include "gtkentry.h"
45 #include "gtkhbox.h"
46 #include "gtklabel.h"
47 #include "gtkmain.h"
48 #include "gtkmarshalers.h"
49 #include "gtkmenu.h"
50 #include "gtkmenuitem.h"
51 #include "gtknotebook.h"
52 #include "gtkoptionmenu.h"
53 #include "gtkscrolledwindow.h"
54 #include "gtkstock.h"
55 #include "gtktable.h"
56 #include "gtkvbox.h"
57
58 #include "gtkintl.h"
59 #include "gtkalias.h"
60
61 typedef struct _GtkInputDialogPrivate GtkInputDialogPrivate;
62 typedef struct _GtkInputKeyInfo       GtkInputKeyInfo;
63
64 struct _GtkInputDialogPrivate
65 {
66   GtkWidget *device_menu;
67   GtkWidget *device_optionmenu;
68   GtkWidget *no_devices_label;
69   GtkWidget *main_vbox;
70 };
71
72 struct _GtkInputKeyInfo
73 {
74   gint       index;
75   GtkWidget *entry;
76   GtkInputDialog *inputd;
77 };
78
79 enum
80 {
81   ENABLE_DEVICE,
82   DISABLE_DEVICE,
83   LAST_SIGNAL
84 };
85
86
87 #define AXIS_LIST_WIDTH 160
88 #define AXIS_LIST_HEIGHT 175
89
90 #define KEYS_LIST_WIDTH 200
91 #define KEYS_LIST_HEIGHT 175
92
93 /* Forward declarations */
94
95 static void gtk_input_dialog_screen_changed   (GtkWidget           *widget,
96                                                GdkScreen           *previous_screen);
97 static void gtk_input_dialog_set_device       (GtkWidget           *widget,
98                                                gpointer             data);
99 static void gtk_input_dialog_set_mapping_mode (GtkWidget           *w,
100                                                gpointer             data);
101 static void gtk_input_dialog_set_axis         (GtkWidget           *widget,
102                                                gpointer             data);
103 static void gtk_input_dialog_fill_axes        (GtkInputDialog      *inputd,
104                                                GdkDevice           *info);
105 static void gtk_input_dialog_set_key          (GtkInputKeyInfo     *key,
106                                                guint                keyval,
107                                                GdkModifierType      modifiers);
108 static gboolean gtk_input_dialog_key_press    (GtkWidget           *widget,
109                                                GdkEventKey         *event,
110                                                GtkInputKeyInfo     *key);
111 static void gtk_input_dialog_clear_key        (GtkWidget           *widget,
112                                                GtkInputKeyInfo     *key);
113 static void gtk_input_dialog_destroy_key      (GtkWidget           *widget,
114                                                GtkInputKeyInfo     *key);
115 static void gtk_input_dialog_fill_keys        (GtkInputDialog      *inputd,
116                                                GdkDevice           *info);
117
118 static guint input_dialog_signals[LAST_SIGNAL] = { 0 };
119
120 G_DEFINE_TYPE (GtkInputDialog, gtk_input_dialog, GTK_TYPE_DIALOG)
121
122 static GtkInputDialogPrivate *
123 gtk_input_dialog_get_private (GtkInputDialog *input_dialog)
124 {
125   return G_TYPE_INSTANCE_GET_PRIVATE (input_dialog, 
126                                       GTK_TYPE_INPUT_DIALOG, 
127                                       GtkInputDialogPrivate);
128 }
129
130 static GtkInputDialog *
131 input_dialog_from_widget (GtkWidget *widget)
132 {
133   GtkWidget *toplevel;
134   
135   if (GTK_IS_MENU_ITEM (widget))
136     {
137       GtkMenu *menu = GTK_MENU (widget->parent);
138       widget = gtk_menu_get_attach_widget (menu);
139     }
140
141   toplevel = gtk_widget_get_toplevel (widget);
142   return GTK_INPUT_DIALOG (toplevel);
143 }
144
145 static void
146 gtk_input_dialog_class_init (GtkInputDialogClass *klass)
147 {
148   GObjectClass *object_class = (GObjectClass *) klass;
149   GtkWidgetClass *widget_class = (GtkWidgetClass *)klass;
150   
151   widget_class->screen_changed = gtk_input_dialog_screen_changed;
152   
153   klass->enable_device = NULL;
154   klass->disable_device = NULL;
155
156   input_dialog_signals[ENABLE_DEVICE] =
157     g_signal_new (I_("enable_device"),
158                   G_OBJECT_CLASS_TYPE (klass),
159                   G_SIGNAL_RUN_LAST,
160                   G_STRUCT_OFFSET (GtkInputDialogClass, enable_device),
161                   NULL, NULL,
162                   _gtk_marshal_VOID__OBJECT,
163                   G_TYPE_NONE, 1,
164                   GDK_TYPE_DEVICE);
165
166   input_dialog_signals[DISABLE_DEVICE] =
167     g_signal_new (I_("disable_device"),
168                   G_OBJECT_CLASS_TYPE (klass),
169                   G_SIGNAL_RUN_LAST,
170                   G_STRUCT_OFFSET (GtkInputDialogClass, disable_device),
171                   NULL, NULL,
172                   _gtk_marshal_VOID__OBJECT,
173                   G_TYPE_NONE, 1,
174                   GDK_TYPE_DEVICE);
175
176   g_type_class_add_private (object_class, sizeof (GtkInputDialogPrivate));
177 }
178
179 static void
180 gtk_input_dialog_init (GtkInputDialog *inputd)
181 {
182   GtkInputDialogPrivate *private = gtk_input_dialog_get_private (inputd);
183   GtkDialog *dialog = GTK_DIALOG (inputd);
184   GtkWidget *util_box;
185   GtkWidget *label;
186   GtkWidget *mapping_menu;
187   GtkWidget *menuitem;
188   GtkWidget *notebook;
189
190   gtk_widget_push_composite_child ();
191
192   gtk_window_set_title (GTK_WINDOW (inputd), _("Input"));
193
194   gtk_dialog_set_has_separator (dialog, FALSE);
195   gtk_container_set_border_width (GTK_CONTAINER (dialog), 5);
196   gtk_box_set_spacing (GTK_BOX (dialog->vbox), 2); /* 2 * 5 + 2 = 12 */
197   gtk_container_set_border_width (GTK_CONTAINER (dialog->action_area), 5);
198   gtk_box_set_spacing (GTK_BOX (dialog->action_area), 6);
199
200   /* main vbox */
201
202   private->main_vbox = gtk_vbox_new (FALSE, 12);
203   gtk_container_set_border_width (GTK_CONTAINER (private->main_vbox), 5);
204   gtk_box_pack_start (GTK_BOX (GTK_DIALOG (inputd)->vbox), private->main_vbox,
205                       TRUE, TRUE, 0);
206
207   private->no_devices_label = gtk_label_new (_("No extended input devices"));
208   gtk_container_set_border_width (GTK_CONTAINER (private->main_vbox), 5);
209   gtk_box_pack_start (GTK_BOX (GTK_DIALOG (inputd)->vbox),
210                       private->no_devices_label,
211                       TRUE, TRUE, 0);
212
213   /* menu for selecting device */
214
215   private->device_menu = gtk_menu_new ();
216
217   util_box = gtk_hbox_new (FALSE, 12);
218   gtk_box_pack_start (GTK_BOX (private->main_vbox), util_box, FALSE, FALSE, 0);
219
220   label = gtk_label_new_with_mnemonic (_("_Device:"));
221   gtk_box_pack_start (GTK_BOX (util_box), label, FALSE, FALSE, 0);
222
223   private->device_optionmenu = gtk_option_menu_new ();
224   gtk_label_set_mnemonic_widget (GTK_LABEL (label), private->device_optionmenu);
225   gtk_box_pack_start (GTK_BOX (util_box), private->device_optionmenu, TRUE, TRUE, 0);
226   gtk_widget_show (private->device_optionmenu);
227   gtk_option_menu_set_menu (GTK_OPTION_MENU (private->device_optionmenu), private->device_menu);
228
229   gtk_widget_show (label);
230
231   /* Device options */
232
233   /* mapping mode option menu */
234
235   mapping_menu = gtk_menu_new ();
236
237   menuitem = gtk_menu_item_new_with_label(_("Disabled"));
238   gtk_menu_shell_append (GTK_MENU_SHELL (mapping_menu), menuitem);
239   gtk_widget_show (menuitem);
240   g_signal_connect (menuitem, "activate",
241                     G_CALLBACK (gtk_input_dialog_set_mapping_mode),
242                     GINT_TO_POINTER (GDK_MODE_DISABLED));
243
244   menuitem = gtk_menu_item_new_with_label(_("Screen"));
245   gtk_menu_shell_append (GTK_MENU_SHELL (mapping_menu), menuitem);
246   gtk_widget_show (menuitem);
247   g_signal_connect (menuitem, "activate",
248                     G_CALLBACK (gtk_input_dialog_set_mapping_mode),
249                     GINT_TO_POINTER (GDK_MODE_SCREEN));
250
251   menuitem = gtk_menu_item_new_with_label(_("Window"));
252   gtk_menu_shell_append (GTK_MENU_SHELL (mapping_menu), menuitem);
253   gtk_widget_show (menuitem);
254   g_signal_connect (menuitem, "activate",
255                     G_CALLBACK (gtk_input_dialog_set_mapping_mode),
256                     GINT_TO_POINTER (GDK_MODE_WINDOW));
257
258   label = gtk_label_new_with_mnemonic (_("_Mode:"));
259   gtk_box_pack_start (GTK_BOX (util_box), label, FALSE, FALSE, 0);
260   
261   inputd->mode_optionmenu = gtk_option_menu_new ();
262   gtk_label_set_mnemonic_widget (GTK_LABEL (label), inputd->mode_optionmenu);
263   gtk_box_pack_start (GTK_BOX (util_box), inputd->mode_optionmenu, FALSE, FALSE, 0);
264   gtk_widget_show (inputd->mode_optionmenu);
265   gtk_option_menu_set_menu (GTK_OPTION_MENU (inputd->mode_optionmenu), mapping_menu);
266
267   gtk_widget_show(label);
268
269   gtk_widget_show (util_box);
270
271   /* Notebook */
272
273   notebook = gtk_notebook_new ();
274   gtk_box_pack_start (GTK_BOX (private->main_vbox), notebook, TRUE, TRUE, 0);
275   gtk_widget_show (notebook);
276       
277   /*  The axis listbox  */
278
279   label = gtk_label_new (_("Axes"));
280
281   inputd->axis_listbox = gtk_scrolled_window_new (NULL, NULL);
282   gtk_container_set_border_width (GTK_CONTAINER (inputd->axis_listbox), 12);
283   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW(inputd->axis_listbox),
284                                   GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
285       
286   gtk_widget_set_size_request (inputd->axis_listbox,
287                                AXIS_LIST_WIDTH, AXIS_LIST_HEIGHT);
288   gtk_notebook_append_page (GTK_NOTEBOOK(notebook), 
289                             inputd->axis_listbox, label);
290
291   gtk_widget_show (inputd->axis_listbox);
292
293   inputd->axis_list = NULL;
294
295   /* Keys listbox */
296
297   label = gtk_label_new (_("Keys"));
298
299   inputd->keys_listbox = gtk_scrolled_window_new (NULL, NULL);
300   gtk_container_set_border_width (GTK_CONTAINER (inputd->keys_listbox), 12);
301   gtk_widget_set_size_request (inputd->keys_listbox,
302                                KEYS_LIST_WIDTH, KEYS_LIST_HEIGHT);
303   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (inputd->keys_listbox),
304                                   GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
305   gtk_notebook_append_page (GTK_NOTEBOOK (notebook), 
306                             inputd->keys_listbox, label);
307
308   gtk_widget_show (inputd->keys_listbox);
309
310   inputd->keys_list = NULL;
311
312   inputd->save_button = gtk_button_new_from_stock (GTK_STOCK_SAVE);
313   GTK_WIDGET_SET_FLAGS (inputd->save_button, GTK_CAN_DEFAULT);
314   gtk_box_pack_start (GTK_BOX (GTK_DIALOG(inputd)->action_area),
315                       inputd->save_button, TRUE, TRUE, 0);
316   gtk_widget_show (inputd->save_button);
317
318   inputd->close_button = gtk_button_new_from_stock (GTK_STOCK_CLOSE);
319   GTK_WIDGET_SET_FLAGS (inputd->close_button, GTK_CAN_DEFAULT);
320   gtk_box_pack_start (GTK_BOX (GTK_DIALOG(inputd)->action_area),
321                       inputd->close_button, TRUE, TRUE, 0);
322
323   gtk_widget_show (inputd->close_button);
324   gtk_widget_grab_default (inputd->close_button);
325
326   gtk_widget_pop_composite_child ();
327
328   gtk_input_dialog_screen_changed (GTK_WIDGET (inputd), NULL);
329
330   _gtk_dialog_set_ignore_separator (dialog, TRUE);
331 }
332
333 static void
334 gtk_input_dialog_screen_changed (GtkWidget *widget,
335                                  GdkScreen *previous_screen)
336 {
337   GtkInputDialog *inputd = GTK_INPUT_DIALOG (widget);
338   GtkInputDialogPrivate *private = gtk_input_dialog_get_private (inputd);
339   
340   GList *device_info = NULL;
341   GdkDevice *core_pointer = NULL;
342   GList *tmp_list;
343
344   if (gtk_widget_has_screen (widget))
345     {
346       GdkDisplay *display;
347       
348       display = gtk_widget_get_display (widget);
349       device_info = gdk_display_list_devices (display);
350       core_pointer = gdk_display_get_core_pointer (display);
351     }
352
353   inputd->current_device = NULL;
354   gtk_container_foreach (GTK_CONTAINER (private->device_menu),
355                          (GtkCallback)gtk_widget_destroy, NULL);
356   
357   if (g_list_length(device_info) <= 1) /* only core device */
358     {
359       gtk_widget_hide (private->main_vbox);
360       gtk_widget_show (private->no_devices_label);
361       gtk_widget_set_sensitive(inputd->save_button, FALSE);
362     }
363   else
364     {
365       gtk_widget_show (private->main_vbox);
366       gtk_widget_hide (private->no_devices_label);
367       gtk_widget_set_sensitive(inputd->save_button, TRUE);
368
369       for (tmp_list = device_info; tmp_list; tmp_list = tmp_list->next)
370         {
371           GdkDevice *info = tmp_list->data;
372           if (info != core_pointer)
373             {
374               GtkWidget *menuitem;
375               
376               menuitem = gtk_menu_item_new_with_label (info->name);
377               
378               gtk_menu_shell_append (GTK_MENU_SHELL (private->device_menu),
379                                      menuitem);
380               gtk_widget_show (menuitem);
381               g_signal_connect (menuitem, "activate",
382                                 G_CALLBACK (gtk_input_dialog_set_device),
383                                 info);
384             }
385         }
386       
387       gtk_input_dialog_set_device (widget, device_info->data);
388       gtk_option_menu_set_history (GTK_OPTION_MENU (private->device_optionmenu), 0);
389     }
390 }
391      
392 GtkWidget*
393 gtk_input_dialog_new (void)
394 {
395   GtkInputDialog *inputd;
396
397   inputd = g_object_new (GTK_TYPE_INPUT_DIALOG, NULL);
398
399   return GTK_WIDGET (inputd);
400 }
401
402 static void
403 gtk_input_dialog_set_device (GtkWidget *w,
404                              gpointer   data)
405 {
406   GdkDevice *device = data;
407   GtkInputDialog *inputd = input_dialog_from_widget (w);
408
409   inputd->current_device = device;
410
411   gtk_input_dialog_fill_axes (inputd, device);
412   gtk_input_dialog_fill_keys (inputd, device);
413
414   gtk_option_menu_set_history (GTK_OPTION_MENU (inputd->mode_optionmenu),
415                                device->mode);
416 }
417
418 static void
419 gtk_input_dialog_set_mapping_mode (GtkWidget *w,
420                                    gpointer   data)
421 {
422   GtkInputDialog *inputd = input_dialog_from_widget (w);
423   GdkDevice *info = inputd->current_device;
424   GdkInputMode old_mode;
425   GdkInputMode mode = GPOINTER_TO_INT (data);
426
427   if (!info)
428     return;
429   
430   old_mode = info->mode;
431
432   if (mode != old_mode)
433     {
434       if (gdk_device_set_mode (info, mode))
435         {
436           if (mode == GDK_MODE_DISABLED)
437             g_signal_emit (inputd,
438                            input_dialog_signals[DISABLE_DEVICE],
439                            0,
440                            info);
441           else
442             g_signal_emit (inputd,
443                            input_dialog_signals[ENABLE_DEVICE],
444                            0,
445                            info);
446         }
447       else
448         gtk_option_menu_set_history (GTK_OPTION_MENU (inputd->mode_optionmenu),
449                                      old_mode);
450
451       /* FIXME: error dialog ? */
452     }
453 }
454
455 static void
456 gtk_input_dialog_set_axis (GtkWidget *w,
457                            gpointer   data)
458 {
459   GdkAxisUse use = GPOINTER_TO_INT(data) & 0xFFFF;
460   GdkAxisUse old_use;
461   GdkAxisUse *new_axes;
462   GtkInputDialog *inputd = input_dialog_from_widget (w);
463   GdkDevice *info = inputd->current_device;
464
465   gint axis = (GPOINTER_TO_INT(data) >> 16) - 1;
466   gint old_axis;
467   int i;
468
469   if (!info)
470     return;
471
472   new_axes = g_new (GdkAxisUse, info->num_axes);
473   old_axis = -1;
474   for (i=0;i<info->num_axes;i++)
475     {
476       new_axes[i] = info->axes[i].use;
477       if (info->axes[i].use == use)
478         old_axis = i;
479     }
480
481   if (axis != -1)
482     old_use = info->axes[axis].use;
483   else
484     old_use = GDK_AXIS_IGNORE;
485
486   if (axis == old_axis) {
487     g_free (new_axes);
488     return;
489   }
490
491   /* we must always have an x and a y axis */
492   if ((axis == -1 && (use == GDK_AXIS_X || use == GDK_AXIS_Y)) ||
493       (old_axis == -1 && (old_use == GDK_AXIS_X || old_use == GDK_AXIS_Y)))
494     {
495       gtk_option_menu_set_history (
496                 GTK_OPTION_MENU (inputd->axis_items[use]),
497                 old_axis + 1);
498     }
499   else
500     {
501       if (axis != -1)
502         gdk_device_set_axis_use (info, axis, use);
503
504       if (old_axis != -1)
505         gdk_device_set_axis_use (info, old_axis, old_use);
506
507       if (old_use != GDK_AXIS_IGNORE)
508         {
509           gtk_option_menu_set_history (
510                 GTK_OPTION_MENU (inputd->axis_items[old_use]),
511                 old_axis + 1);
512         }
513     }
514
515   g_free (new_axes);
516 }
517
518 static void
519 gtk_input_dialog_fill_axes(GtkInputDialog *inputd, GdkDevice *info)
520 {
521   static const char *const axis_use_strings[GDK_AXIS_LAST] =
522   {
523     "",
524     N_("_X:"),
525     N_("_Y:"),
526     N_("_Pressure:"),
527     N_("X _tilt:"),
528     N_("Y t_ilt:"),
529     N_("_Wheel:")
530   };
531
532   int i,j;
533   GtkWidget *menu;
534   GtkWidget *option_menu;
535   GtkWidget *label;
536   GtkWidget *viewport;
537   GtkWidget *old_child;
538
539   /* remove all the old items */
540   if (inputd->axis_list)
541     {
542       gtk_widget_hide (inputd->axis_list);      /* suppress resizes (or get warnings) */
543       gtk_widget_destroy (inputd->axis_list);
544     }
545   inputd->axis_list = gtk_table_new (GDK_AXIS_LAST, 2, 0);
546   gtk_table_set_row_spacings (GTK_TABLE (inputd->axis_list), 6);
547   gtk_table_set_col_spacings (GTK_TABLE (inputd->axis_list), 12);
548   
549   viewport = gtk_viewport_new (NULL, NULL);
550   old_child = gtk_bin_get_child (GTK_BIN (inputd->axis_listbox));
551   if (old_child != NULL)
552     gtk_widget_destroy (old_child);
553   gtk_container_add (GTK_CONTAINER (inputd->axis_listbox), viewport);
554   gtk_viewport_set_shadow_type (GTK_VIEWPORT (viewport), GTK_SHADOW_NONE);
555   gtk_widget_show (viewport);
556   gtk_container_add (GTK_CONTAINER (viewport), inputd->axis_list);
557   gtk_widget_show (inputd->axis_list);
558
559   gtk_widget_realize (inputd->axis_list);
560   gdk_window_set_background (inputd->axis_list->window,
561                              &inputd->axis_list->style->base[GTK_STATE_NORMAL]);
562
563   for (i=GDK_AXIS_X;i<GDK_AXIS_LAST;i++)
564     {
565       /* create the label */
566
567       label = gtk_label_new_with_mnemonic (_(axis_use_strings[i]));
568       gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
569       gtk_table_attach (GTK_TABLE (inputd->axis_list), label, 0, 1, i, i+1, 
570                         GTK_FILL, 0, 2, 2);
571
572       /* and the use option menu */
573       menu = gtk_menu_new();
574
575       for (j = -1; j < info->num_axes; j++)
576         {
577           char buffer[16];
578           GtkWidget *menu_item;
579
580           if (j == -1)
581             menu_item = gtk_menu_item_new_with_label (_("none"));
582           else
583             {
584               g_snprintf (buffer, sizeof (buffer), "%d", j+1);
585               menu_item = gtk_menu_item_new_with_label (buffer);
586             }
587           g_signal_connect (menu_item, "activate",
588                             G_CALLBACK (gtk_input_dialog_set_axis),
589                             GINT_TO_POINTER (0x10000 * (j + 1) + i));
590           gtk_widget_show (menu_item);
591           gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
592         }
593
594       inputd->axis_items[i] = option_menu = gtk_option_menu_new ();
595       gtk_label_set_mnemonic_widget (GTK_LABEL (label), option_menu);
596       gtk_table_attach (GTK_TABLE (inputd->axis_list), option_menu, 
597                         1, 2, i, i+1, GTK_EXPAND | GTK_FILL, 0, 2, 2);
598
599       gtk_widget_show (option_menu);
600       gtk_option_menu_set_menu (GTK_OPTION_MENU (option_menu), menu);
601       for (j = 0; j < info->num_axes; j++)
602         if (info->axes[j].use == (GdkAxisUse) i)
603           {
604             gtk_option_menu_set_history (GTK_OPTION_MENU (option_menu), j+1);
605             break;
606           }
607
608       gtk_widget_show (label);
609     }
610 }
611
612 static void 
613 gtk_input_dialog_clear_key (GtkWidget *widget, GtkInputKeyInfo *key)
614 {
615   if (!key->inputd->current_device)
616     return;
617   
618   gtk_entry_set_text (GTK_ENTRY(key->entry), _("(disabled)"));
619   gdk_device_set_key (key->inputd->current_device, key->index, 0, 0);
620 }
621
622 static void 
623 gtk_input_dialog_set_key (GtkInputKeyInfo *key,
624                           guint keyval, GdkModifierType modifiers)
625 {
626   GString *str;
627   gchar chars[2];
628
629   if (keyval)
630     {
631       str = g_string_new (NULL);
632       
633       if (modifiers & GDK_SHIFT_MASK)
634         g_string_append (str, "Shift+");
635       if (modifiers & GDK_CONTROL_MASK)
636         g_string_append (str, "Ctrl+");
637       if (modifiers & GDK_MOD1_MASK)
638         g_string_append (str, "Alt+");
639       
640       if ((keyval >= 0x20) && (keyval <= 0xFF))
641         {
642           chars[0] = keyval;
643           chars[1] = 0;
644           g_string_append (str, chars);
645         }
646       else
647         g_string_append (str, _("(unknown)"));
648       gtk_entry_set_text (GTK_ENTRY(key->entry), str->str);
649
650       g_string_free (str, TRUE);
651     }
652   else
653     {
654       gtk_entry_set_text (GTK_ENTRY(key->entry), _("(disabled)"));
655     }
656 }
657
658 static gboolean
659 gtk_input_dialog_key_press (GtkWidget *widget, 
660                             GdkEventKey *event,
661                             GtkInputKeyInfo *key)
662 {
663   if (!key->inputd->current_device)
664     return FALSE;
665   
666   gtk_input_dialog_set_key (key, event->keyval, event->state & 0xFF);
667   gdk_device_set_key (key->inputd->current_device, key->index, 
668                       event->keyval, event->state & 0xFF);
669
670   g_signal_stop_emission_by_name (widget, "key_press_event");
671   
672   return TRUE;
673 }
674
675 static void 
676 gtk_input_dialog_destroy_key (GtkWidget *widget, GtkInputKeyInfo *key)
677 {
678   g_free (key);
679 }
680
681 static void
682 gtk_input_dialog_fill_keys(GtkInputDialog *inputd, GdkDevice *info)
683 {
684   int i;
685   GtkWidget *label;
686   GtkWidget *button;
687   GtkWidget *hbox;
688   GtkWidget *viewport;
689   GtkWidget *old_child;
690
691   char buffer[32];
692   
693   /* remove all the old items */
694   if (inputd->keys_list)
695     {
696       gtk_widget_hide (inputd->keys_list);      /* suppress resizes (or get warnings) */
697       gtk_widget_destroy (inputd->keys_list);
698     }
699
700   inputd->keys_list = gtk_table_new (info->num_keys, 2, FALSE);
701   gtk_table_set_row_spacings (GTK_TABLE (inputd->keys_list), 6);
702   gtk_table_set_col_spacings (GTK_TABLE (inputd->keys_list), 12);
703   
704   viewport = gtk_viewport_new (NULL, NULL);
705   old_child = gtk_bin_get_child (GTK_BIN (inputd->keys_listbox));
706   if (old_child != NULL)
707     gtk_widget_destroy (old_child);
708   gtk_container_add (GTK_CONTAINER (inputd->keys_listbox), viewport);
709   gtk_viewport_set_shadow_type (GTK_VIEWPORT (viewport), GTK_SHADOW_NONE);
710   gtk_widget_show (viewport);
711   gtk_container_add (GTK_CONTAINER (viewport), inputd->keys_list);
712   gtk_widget_show (inputd->keys_list);
713
714   gtk_widget_realize (inputd->keys_list);
715   gdk_window_set_background (inputd->keys_list->window,
716                              &inputd->keys_list->style->base[GTK_STATE_NORMAL]);
717
718   for (i=0;i<info->num_keys;i++)
719     {
720       GtkInputKeyInfo *key = g_new (GtkInputKeyInfo, 1);
721       key->index = i;
722       key->inputd = inputd;
723
724       /* create the label */
725
726       g_snprintf (buffer, sizeof (buffer), "_%d:", i+1);
727       label = gtk_label_new_with_mnemonic (buffer);
728       gtk_table_attach (GTK_TABLE (inputd->keys_list), label, 0, 1, i, i+1, 
729                         GTK_FILL, 0, 2, 2);
730       gtk_widget_show (label);
731
732       /* the entry */
733
734       hbox = gtk_hbox_new (FALSE, 6);
735       gtk_table_attach (GTK_TABLE (inputd->keys_list), hbox, 1, 2, i, i+1, 
736                         GTK_EXPAND | GTK_FILL, 0, 2, 2);
737       gtk_widget_show (hbox);
738
739       key->entry = gtk_entry_new ();
740       gtk_label_set_mnemonic_widget (GTK_LABEL (label), key->entry);
741       gtk_box_pack_start (GTK_BOX (hbox), key->entry, TRUE, TRUE, 0);
742       gtk_widget_show (key->entry);
743
744       g_signal_connect (key->entry, "key_press_event",
745                         G_CALLBACK (gtk_input_dialog_key_press), key);
746       g_signal_connect (key->entry, "destroy",
747                         G_CALLBACK (gtk_input_dialog_destroy_key), key);
748       
749       /* and clear button */
750
751       button = gtk_button_new_with_mnemonic (_("Cl_ear"));
752       gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, TRUE, 0);
753       gtk_widget_show (button);
754
755       g_signal_connect (button, "clicked",
756                         G_CALLBACK (gtk_input_dialog_clear_key), key);
757
758       gtk_input_dialog_set_key (key, info->keys[i].keyval,
759                                 info->keys[i].modifiers);
760     }
761 }
762
763 #define __GTK_INPUTDIALOG_C__
764 #include "gtkaliasdef.c"