1 /* GTK - The GIMP 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 
G_DEFINE_TYPE(GtkInputDialog,gtk_input_dialog,GTK_TYPE_DIALOG)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 *
input_dialog_from_widget(GtkWidget * widget)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
gtk_input_dialog_class_init(GtkInputDialogClass * klass)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
gtk_input_dialog_init(GtkInputDialog * inputd)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_can_default (inputd->save_button, TRUE);
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_can_default (inputd->close_button, TRUE);
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
gtk_input_dialog_screen_changed(GtkWidget * widget,GdkScreen * previous_screen)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*
gtk_input_dialog_new(void)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
gtk_input_dialog_set_device(GtkWidget * w,gpointer data)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
gtk_input_dialog_set_mapping_mode(GtkWidget * w,gpointer data)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
gtk_input_dialog_set_axis(GtkWidget * w,gpointer data)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
gtk_input_dialog_fill_axes(GtkInputDialog * inputd,GdkDevice * info)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
gtk_input_dialog_clear_key(GtkWidget * widget,GtkInputKeyInfo * key)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
gtk_input_dialog_set_key(GtkInputKeyInfo * key,guint keyval,GdkModifierType modifiers)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
gtk_input_dialog_key_press(GtkWidget * widget,GdkEventKey * event,GtkInputKeyInfo * key)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
gtk_input_dialog_destroy_key(GtkWidget * widget,GtkInputKeyInfo * key)676 gtk_input_dialog_destroy_key (GtkWidget *widget, GtkInputKeyInfo *key)
677 {
678   g_free (key);
679 }
680 
681 static void
gtk_input_dialog_fill_keys(GtkInputDialog * inputd,GdkDevice * info)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"
765