changeset 52981:54482f5ea7be

Remove tear off capability for GTK popup menus. Since the context in Lisp is not present anymore, we don't know how to invoke the action for a menu item.
author Jan Djärv <jan.h.d@swipnet.se>
date Sun, 02 Nov 2003 16:47:32 +0000
parents 46bcce3b9533
children 2087fd567663
files src/ChangeLog src/gtkutil.c src/gtkutil.h src/xmenu.c
diffstat 4 files changed, 80 insertions(+), 66 deletions(-) [+]
line wrap: on
line diff
--- a/src/ChangeLog	Sun Nov 02 07:02:32 2003 +0000
+++ b/src/ChangeLog	Sun Nov 02 16:47:32 2003 +0000
@@ -1,3 +1,30 @@
+2003-11-02  Jan Dj,Ad(Brv  <jan.h.d@swipnet.se>
+
+	* gtkutil.h: Declare xg_have_tear_offs, remove xg_keep_popup
+	and xg_did_tearoff.
+
+	* gtkutil.c: Remove variable xg_did_tearoff.
+	(xg_have_tear_offs): New function.
+	(tearoff_remove): Just decrease xg_detached_menus.
+	(tearoff_activate): Increase xg_detached_menus and call
+	tearoff_remove when tearoff is removed.
+	(xg_keep_popup): Removed function.
+	(create_menus): Give add_tearoff_p as argument to recursive
+	call to create_menus.
+	(xg_create_widget): Use variables instead of multiple
+	strcmp.  Tell create_menus to create tear off only for
+	menu bar menus.
+	(xg_update_menubar): Change title for a detached menu also.
+	(xg_modify_menubar_widgets): Always call xg_update_menubar, regardless
+	of deep_p.
+	(xg_initialize): Initialize xg_detached_menus, remove
+	initialization of xg_did_tearoff.
+
+	* xmenu.c (set_frame_menubar): For GTK, set deep_p if
+	xg_have_tear_offs returns non-zero.
+	(create_and_show_popup_menu): Remove setting of xg_did_tearoff and
+	call to xg_keep_popup.
+
 2003-11-01  Andrew Choi  <akochoi@shaw.ca>
 
 	* macterm.c (XTread_socket): Handle menubar selection and grow
--- a/src/gtkutil.c	Sun Nov 02 07:02:32 2003 +0000
+++ b/src/gtkutil.c	Sun Nov 02 16:47:32 2003 +0000
@@ -1333,27 +1333,29 @@
   return 0;
 }
 
-GtkWidget *xg_did_tearoff;
+static int xg_detached_menus;
+
+/* Returns non-zero if there are detached menus.  */
+int
+xg_have_tear_offs ()
+{
+  return xg_detached_menus > 0;
+}
 
 /* Callback invoked when a detached menu window is removed.  Here we
-   delete the popup menu.
+   decrease the xg_detached_menus count.
    WIDGET is the top level window that is removed (the parent of the menu).
-   EVENT is the event that triggers the window removal.
-   CLIENT_DATA points to the menu that is detached.
-
-   Returns TRUE to tell GTK to stop processing this event.  */
-static gboolean
-tearoff_remove (widget, event, client_data)
+   CLIENT_DATA is not used.  */
+static void
+tearoff_remove (widget, client_data)
      GtkWidget *widget;
-     GdkEvent *event;
      gpointer client_data;
 {
-  gtk_widget_destroy (GTK_WIDGET (client_data));
-  return TRUE;
+  if (xg_detached_menus > 0) --xg_detached_menus;
 }
 
-/* Callback invoked when a menu is detached.  It sets the xg_did_tearoff
-   variable.
+/* Callback invoked when a menu is detached.  It increases the
+   xg_detached_menus count.
    WIDGET is the GtkTearoffMenuItem.
    CLIENT_DATA is not used.  */
 static void
@@ -1362,31 +1364,15 @@
      gpointer client_data;
 {
   GtkWidget *menu = gtk_widget_get_parent (widget);
-  if (! gtk_menu_get_tearoff_state (GTK_MENU (menu)))
-    return;
-
-  xg_did_tearoff = menu;
+  if (gtk_menu_get_tearoff_state (GTK_MENU (menu)))
+    {
+      ++xg_detached_menus;
+      g_signal_connect (G_OBJECT (gtk_widget_get_toplevel (widget)),
+                        "destroy",
+                        G_CALLBACK (tearoff_remove), 0);
+    }
 }
 
-/* If a detach of a popup menu is done, this function should be called
-   to keep the menu around until the detached window is removed.
-   MENU is the top level menu for the popup,
-   SUBMENU is the menu that got detached (that is MENU or a
-   submenu of MENU), see the xg_did_tearoff variable.  */
-void
-xg_keep_popup (menu, submenu)
-     GtkWidget *menu;
-     GtkWidget *submenu;
-{
-  GtkWidget *p;
-
-  /* Find the top widget for the detached menu.  */
-  p = gtk_widget_get_toplevel (submenu);
-
-  /* Delay destroying the menu until the detached menu is removed.  */
-  g_signal_connect (G_OBJECT (p), "unmap_event",
-                    G_CALLBACK (tearoff_remove), menu);
-}
 
 /* Create a menu item widget, and connect the callbacks.
    ITEM decribes the menu item.
@@ -1585,7 +1571,7 @@
                                                  highlight_cb,
                                                  0,
                                                  0,
-                                                 1,
+                                                 add_tearoff_p,
                                                  0,
                                                  cl_data,
                                                  0);
@@ -1626,6 +1612,9 @@
      GCallback highlight_cb;
 {
   GtkWidget *w = 0;
+  int menu_bar_p = strcmp (type, "menubar") == 0;
+  int pop_up_p = strcmp (type, "popup") == 0;
+
   if (strcmp (type, "dialog") == 0)
     {
       w = create_dialog (val, select_cb, deactivate_cb);
@@ -1636,23 +1625,23 @@
       if (w)
         gtk_widget_set_name (w, "emacs-dialog");
     }
-  else if (strcmp (type, "menubar") == 0 || strcmp (type, "popup") == 0)
+  else if (menu_bar_p || pop_up_p)
     {
       w = create_menus (val->contents,
                         f,
                         select_cb,
                         deactivate_cb,
                         highlight_cb,
-                        strcmp (type, "popup") == 0,
-                        strcmp (type, "menubar") == 0,
-                        1,
+                        pop_up_p,
+                        menu_bar_p,
+                        menu_bar_p,
                         0,
                         0,
                         name);
 
       /* Set the cursor to an arrow for popup menus when they are mapped.
          This is done by default for menu bar menus.  */
-      if (strcmp (type, "popup") == 0)
+      if (pop_up_p)
         {
           /* Must realize so the GdkWindow inside the widget is created.  */
           gtk_widget_realize (w);
@@ -1834,9 +1823,16 @@
               is up to date when leaving the minibuffer.  */
           GtkLabel *wlabel = GTK_LABEL (gtk_bin_get_child (GTK_BIN (witem)));
           char *utf8_label = get_utf8_string (val->name);
+          GtkWidget *submenu = gtk_menu_item_get_submenu (witem);
 
           gtk_label_set_text (wlabel, utf8_label);
 
+          /* If this item has a submenu that has been detached, change
+             the title in the WM decorations also.  */
+          if (submenu && gtk_menu_get_tearoff_state (GTK_MENU (submenu)))
+            /* Set the title of the detached window.  */
+            gtk_menu_set_title (GTK_MENU (submenu), utf8_label);
+
           iter = g_list_next (iter);
           val = val->next;
           ++pos;
@@ -2222,18 +2218,15 @@
   cl_data = (xg_menu_cb_data*) g_object_get_data (G_OBJECT (menubar),
                                                   XG_FRAME_DATA);
 
-  if (! deep_p)
-    {
-      widget_value *cur = val->contents;
-      xg_update_menubar (menubar, f, &list, list, 0, cur,
-                         select_cb, highlight_cb, cl_data);
-    }
-  else
+  xg_update_menubar (menubar, f, &list, list, 0, val->contents,
+                     select_cb, highlight_cb, cl_data);
+
+  if (deep_p);
     {
       widget_value *cur;
 
       /* Update all sub menus.
-         We must keep the submenu names (GTK menu item widgets) since the
+         We must keep the submenus (GTK menu item widgets) since the
          X Window in the XEvent that activates the menu are those widgets.  */
 
       /* Update cl_data, menu_item things in F may have changed.  */
@@ -2269,7 +2262,6 @@
              newly created sub menu under witem.  */
           if (newsub != sub)
             gtk_menu_item_set_submenu (witem, newsub);
-
         }
     }
 
@@ -3250,8 +3242,7 @@
 {
   xg_ignore_gtk_scrollbar = 0;
   xg_left_ptr_cursor = 0;
-  xg_did_tearoff = 0;
-
+  xg_detached_menus = 0;
   xg_menu_cb_list.prev = xg_menu_cb_list.next =
     xg_menu_item_cb_list.prev = xg_menu_item_cb_list.next = 0;
 
--- a/src/gtkutil.h	Sun Nov 02 07:02:32 2003 +0000
+++ b/src/gtkutil.h	Sun Nov 02 16:47:32 2003 +0000
@@ -150,7 +150,7 @@
 
 extern int xg_update_frame_menubar P_ ((FRAME_PTR f));
 
-extern void xg_keep_popup P_ ((GtkWidget *menu, GtkWidget *submenu));
+extern int xg_have_tear_offs P_ ((void));
 
 extern int xg_get_scroll_id_for_window P_ ((Window wid));
 
@@ -201,12 +201,6 @@
    to indicate that the callback should do nothing.  */
 extern int xg_ignore_gtk_scrollbar;
 
-/* If a detach of a menu is done, this is the menu widget that got
-   detached.  Must be set to NULL before popping up popup menus.
-   Used with xg_keep_popup to delay deleting popup menus when they
-   have been detached.  */
-extern GtkWidget *xg_did_tearoff;
-
 #endif /* USE_GTK */
 #endif /* GTKUTIL_H */
 
--- a/src/xmenu.c	Sun Nov 02 07:02:32 2003 +0000
+++ b/src/xmenu.c	Sun Nov 02 16:47:32 2003 +0000
@@ -1866,6 +1866,12 @@
       f->output_data.x->saved_menu_event->type = 0;
     }
 
+#ifdef USE_GTK
+  /* If we have detached menus, we must update deep so detached menus
+     also gets updated.  */
+  deep_p = deep_p || xg_have_tear_offs ();
+#endif
+
   if (deep_p)
     {
       /* Make a widget-value tree representing the entire menu trees.  */
@@ -2066,7 +2072,7 @@
   xg_crazy_callback_abort = 1;
   if (menubar_widget)
     {
-      /* The third arg is DEEP_P, which says to consider the entire
+      /* The fourth arg is DEEP_P, which says to consider the entire
 	 menu trees we supply, rather than just the menu bar item names.  */
       xg_modify_menubar_widgets (menubar_widget,
                                  f,
@@ -2343,17 +2349,13 @@
   gtk_widget_show_all (menu);
   gtk_menu_popup (GTK_MENU (menu), 0, 0, pos_func, &popup_x_y, i, 0);
 
-  xg_did_tearoff = 0;
   /* Set this to one.  popup_widget_loop increases it by one, so it becomes
      two.  show_help_echo uses this to detect popup menus.  */
   popup_activated_flag = 1;
   /* Process events that apply to the menu.  */
   popup_widget_loop ();
 
-  if (xg_did_tearoff)
-    xg_keep_popup (menu, xg_did_tearoff);
-  else
-    gtk_widget_destroy (menu);
+  gtk_widget_destroy (menu);
 
   /* Must reset this manually because the button release event is not passed
      to Emacs event loop. */