chiark / gitweb /
Generate special fake keypresses from menu options.
[sgt-puzzles.git] / gtk.c
diff --git a/gtk.c b/gtk.c
index c5e3d1c9972de48c4f68a8cbaf176b87ce0aea7d..9ce5c8da7284251dec1a6bd8881d6c3ccb888d25 100644 (file)
--- a/gtk.c
+++ b/gtk.c
@@ -140,7 +140,7 @@ struct font {
  */
 struct frontend {
     GtkWidget *window;
-    GtkAccelGroup *accelgroup;
+    GtkAccelGroup *dummy_accelgroup;
     GtkWidget *area;
     GtkWidget *statusbar;
     GtkWidget *menubar;
@@ -1160,16 +1160,6 @@ static gint key_event(GtkWidget *widget, GdkEventKey *event, gpointer data)
     if (!backing_store_ok(fe))
         return TRUE;
 
-#if !GTK_CHECK_VERSION(2,0,0)
-    /* Gtk 1.2 passes a key event to this function even if it's also
-     * defined as an accelerator.
-     * Gtk 2 doesn't do this, and this function appears not to exist there. */
-    if (fe->accelgroup &&
-        gtk_accel_group_get_entry(fe->accelgroup,
-        event->keyval, event->state))
-        return TRUE;
-#endif
-
     /* Handle mnemonics. */
     if (gtk_window_activate_key(GTK_WINDOW(fe->window), event))
         return TRUE;
@@ -2348,32 +2338,34 @@ static void menu_about_event(GtkMenuItem *menuitem, gpointer data)
 #endif
 }
 
-static GtkWidget *add_menu_item_with_key(frontend *fe, GtkContainer *cont,
-                                         char *text, int key)
+static GtkWidget *add_menu_ui_item(
+    frontend *fe, GtkContainer *cont, char *text, int action,
+    int accel_key, int accel_keyqual)
 {
     GtkWidget *menuitem = gtk_menu_item_new_with_label(text);
-    int keyqual;
     gtk_container_add(cont, menuitem);
-    g_object_set_data(G_OBJECT(menuitem), "user-data", GINT_TO_POINTER(key));
+    g_object_set_data(G_OBJECT(menuitem), "user-data",
+                      GINT_TO_POINTER(action));
     g_signal_connect(G_OBJECT(menuitem), "activate",
                      G_CALLBACK(menu_key_event), fe);
-    switch (key & ~0x1F) {
-      case 0x00:
-       key += 0x60;
-       keyqual = GDK_CONTROL_MASK;
-       break;
-      case 0x40:
-       key += 0x20;
-       keyqual = GDK_SHIFT_MASK;
-       break;
-      default:
-       keyqual = 0;
-       break;
+
+    if (accel_key) {
+        /*
+         * Display a keyboard accelerator alongside this menu item.
+         * Actually this won't be processed via the usual GTK
+         * accelerator system, because we add it to a dummy
+         * accelerator group which is never actually activated on the
+         * main window; this permits back ends to override special
+         * keys like 'n' and 'r' and 'u' in some UI states. So
+         * whatever keystroke we display here will still go to
+         * key_event and be handled in the normal way.
+         */
+        gtk_widget_add_accelerator(menuitem,
+                                   "activate", fe->dummy_accelgroup,
+                                   accel_key, accel_keyqual,
+                                   GTK_ACCEL_VISIBLE | GTK_ACCEL_LOCKED);
     }
-    gtk_widget_add_accelerator(menuitem,
-                              "activate", fe->accelgroup,
-                              key, keyqual,
-                              GTK_ACCEL_VISIBLE);
+
     gtk_widget_show(menuitem);
     return menuitem;
 }
@@ -2535,8 +2527,11 @@ static frontend *new_window(char *arg, int argtype, char **error)
     gtk_container_add(GTK_CONTAINER(fe->window), GTK_WIDGET(vbox));
     gtk_widget_show(GTK_WIDGET(vbox));
 
-    fe->accelgroup = gtk_accel_group_new();
-    gtk_window_add_accel_group(GTK_WINDOW(fe->window), fe->accelgroup);
+    fe->dummy_accelgroup = gtk_accel_group_new();
+    /*
+     * Intentionally _not_ added to the window via
+     * gtk_window_add_accel_group; see menu_key_event
+     */
 
     hbox = GTK_BOX(gtk_hbox_new(FALSE, 0));
     gtk_box_pack_start(vbox, GTK_WIDGET(hbox), FALSE, FALSE, 0);
@@ -2553,7 +2548,7 @@ static frontend *new_window(char *arg, int argtype, char **error)
     menu = gtk_menu_new();
     gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), menu);
 
-    add_menu_item_with_key(fe, GTK_CONTAINER(menu), "New", 'n');
+    add_menu_ui_item(fe, GTK_CONTAINER(menu), "New", UI_NEWGAME, 'n', 0);
 
     menuitem = gtk_menu_item_new_with_label("Restart");
     gtk_container_add(GTK_CONTAINER(menu), menuitem);
@@ -2623,8 +2618,8 @@ static frontend *new_window(char *arg, int argtype, char **error)
     gtk_widget_show(menuitem);
 #ifndef STYLUS_BASED
     add_menu_separator(GTK_CONTAINER(menu));
-    add_menu_item_with_key(fe, GTK_CONTAINER(menu), "Undo", 'u');
-    add_menu_item_with_key(fe, GTK_CONTAINER(menu), "Redo", 'r');
+    add_menu_ui_item(fe, GTK_CONTAINER(menu), "Undo", UI_UNDO, 'u', 0);
+    add_menu_ui_item(fe, GTK_CONTAINER(menu), "Redo", UI_REDO, 'r', 0);
 #endif
     if (thegame.can_format_as_text_ever) {
        add_menu_separator(GTK_CONTAINER(menu));
@@ -2646,7 +2641,7 @@ static frontend *new_window(char *arg, int argtype, char **error)
        gtk_widget_show(menuitem);
     }
     add_menu_separator(GTK_CONTAINER(menu));
-    add_menu_item_with_key(fe, GTK_CONTAINER(menu), "Exit", 'q');
+    add_menu_ui_item(fe, GTK_CONTAINER(menu), "Exit", UI_QUIT, 'q', 0);
 
     menuitem = gtk_menu_item_new_with_mnemonic("_Help");
     gtk_container_add(GTK_CONTAINER(fe->menubar), menuitem);
@@ -2664,7 +2659,7 @@ static frontend *new_window(char *arg, int argtype, char **error)
 #ifdef STYLUS_BASED
     menuitem=gtk_button_new_with_mnemonic("_Redo");
     g_object_set_data(G_OBJECT(menuitem), "user-data",
-                      GINT_TO_POINTER((int)('r')));
+                      GINT_TO_POINTER(UI_REDO));
     g_signal_connect(G_OBJECT(menuitem), "clicked",
                      G_CALLBACK(menu_key_event), fe);
     gtk_box_pack_end(hbox, menuitem, FALSE, FALSE, 0);
@@ -2672,7 +2667,7 @@ static frontend *new_window(char *arg, int argtype, char **error)
 
     menuitem=gtk_button_new_with_mnemonic("_Undo");
     g_object_set_data(G_OBJECT(menuitem), "user-data",
-                      GINT_TO_POINTER((int)('u')));
+                      GINT_TO_POINTER(UI_UNDO));
     g_signal_connect(G_OBJECT(menuitem), "clicked",
                      G_CALLBACK(menu_key_event), fe);
     gtk_box_pack_end(hbox, menuitem, FALSE, FALSE, 0);