[Xfce4-commits] <xfce4-taskbar-plugin:master> Finally fixed the context menu crashes for window actions on hover menu items.

Gearoid Murphy noreply at xfce.org
Sun Oct 14 13:58:01 CEST 2012


Updating branch refs/heads/master
         to b8e11daa4411952355c0b555995c58a2cb8507f7 (commit)
       from 1b80346e44c57e9f1d7b36e2604e595c7907f6ff (commit)

commit b8e11daa4411952355c0b555995c58a2cb8507f7
Author: Gearoid Murphy <gearoid at murphy.com>
Date:   Sun Oct 14 12:26:34 2012 +0100

    Finally fixed the context menu crashes for window actions on hover menu items.

 README           |    2 ++
 taskbar-widget.c |   45 ++++++++++++++++++++++++++++-----------------
 2 files changed, 30 insertions(+), 17 deletions(-)

diff --git a/README b/README
index 3bc9c56..e439ac1 100644
--- a/README
+++ b/README
@@ -1,3 +1,5 @@
+Taskbar plugin was created using code from the Window Buttons plugin, written by Nick Schermer
+
 1) Make sure you've got the development packages
     
     # Valid for XUbuntu 12.04
diff --git a/taskbar-widget.c b/taskbar-widget.c
index 7f80f7c..3ed3e17 100644
--- a/taskbar-widget.c
+++ b/taskbar-widget.c
@@ -247,6 +247,7 @@ static void         xfce_taskbar_group_button_remove            (XfceTaskBarGrou
 static void         xfce_taskbar_group_button_add_window        (XfceTaskBarGroup *group, XfceTaskBarWNode *window_child);
 static gboolean     xfce_taskbar_group_button_enter_event       (GtkWidget *button, GdkEvent *event, XfceTaskBarGroup *group);
 static gboolean     xfce_taskbar_group_button_leave_event       (GtkWidget *button, GdkEvent *event, XfceTaskBarGroup *group);
+static void        xfce_taskbar_group_button_menu_destroy      (GtkWidget *menu_widget, XfceTaskBarGroup *group);
 
 static void xfce_taskbar_disable_group_enter_event(XfceTaskBar *taskbar);
 static void xfce_taskbar_enable_group_enter_event(XfceTaskBar *taskbar);
@@ -262,8 +263,8 @@ static void     cache_pinned_configuration                  (XfceTaskBar *taskba
 
 //hover menu functions
 static gboolean trigger_hover_menu_timeout(GtkWidget *widget, GdkEvent  *event, gpointer menu_ptr);
-static gboolean hover_menu_leave(GtkWidget *widget, GdkEvent  *event, gpointer menu_ptr);
-static gboolean hover_menu_enter(GtkWidget *widget, GdkEvent  *event, gpointer menu_ptr);
+static gboolean xfce_taskbar_hover_menu_leave(GtkWidget *widget, GdkEvent  *event, gpointer menu_ptr);
+static gboolean xfce_taskbar_hover_menu_enter(GtkWidget *widget, GdkEvent  *event, gpointer menu_ptr);
 static gboolean xfce_taskbar_hover_menu_timeout(gpointer menu_ptr);
 static gboolean xfce_taskbar_group_button_hover_timeout(gpointer group_ptr);
 static void    xfce_taskbar_activate_hover_menu(GtkWidget *widget, XfceTaskBarGroup *group, size_t mouse_button);
@@ -1571,6 +1572,12 @@ static gboolean xfce_taskbar_button_enter_notify_event (GtkWidget *button, GdkEv
     return FALSE;
 }
 
+static void wnck_action_menu_destroy(GtkWidget *wnck_widget, GtkWidget *menu_widget)
+{
+    gtk_widget_destroy(wnck_widget);
+    xfce_taskbar_group_button_menu_destroy(menu_widget, NULL);
+}
+
 //This function handles mouse release events on the sub-menu of active windows associated with an application group
 //Returning FALSE will close the menu that generated the event, return TRUE will persist it
 static gboolean xfce_taskbar_app_button_release_event (GtkWidget *button, GdkEventButton *event, XfceTaskBarWNode *child)
@@ -1609,8 +1616,15 @@ static gboolean xfce_taskbar_app_button_release_event (GtkWidget *button, GdkEve
     }
     else// if(event->button == RIGHTMOUSE)
     {
-        GtkWidget *menu ;
-        menu = wnck_action_menu_new (child->window); g_signal_connect (G_OBJECT (menu), "selection-done", G_CALLBACK (gtk_widget_destroy), NULL);
+        GtkWidget *menu = wnck_action_menu_new (child->window);
+        
+        GList *attachlist = gtk_menu_get_for_attach_widget(child->group->button);
+        //This submenu is a component of the hover menu
+        panel_assert(g_list_length(attachlist) == 1);
+        GtkWidget *hover_menu = (GtkWidget *)attachlist->data;
+        //Unfortunately, this is quite elaborate :|
+        panel_assert(g_signal_handlers_disconnect_by_func (GTK_WINDOW (GTK_MENU(hover_menu)->toplevel), xfce_taskbar_hover_menu_leave, hover_menu) == 1);
+        g_signal_connect (G_OBJECT (menu), "selection-done", G_CALLBACK (wnck_action_menu_destroy), hover_menu);
         gtk_menu_attach_to_widget (GTK_MENU (menu), button, NULL);
         gtk_menu_popup (GTK_MENU (menu), NULL, NULL, xfce_panel_plugin_position_menu, xfce_taskbar_get_panel_plugin (child->taskbar), event->button, event->time);
         return TRUE ;
@@ -2130,6 +2144,7 @@ static void xfce_taskbar_group_button_toggle_pinned (XfceTaskBarGroup *group)
 }
 
 // Create the pinning functions first, then *append* the group actions to the menu
+// This awkward way of constructing the pinned menu needs to be refactored
 static GtkWidget * xfce_taskbar_group_button_menu_group_actions (XfceTaskBarGroup *group)
 {
     GSList *li;
@@ -2150,10 +2165,12 @@ static GtkWidget * xfce_taskbar_group_button_menu_group_actions (XfceTaskBarGrou
     //Only offer to pin windows with detectable pids
     else if(group->wnodes && wnck_window_get_pid(((XfceTaskBarWNode *)group->wnodes->data)->window) != 0)
     {
-    
         xfce_taskbar_group_button_build_pin_menu(group, menu);
     }
     
+    //FIXME: When these submenus activate, they cause a leave-notify event on the hover menu which
+    //triggers a destroy event after a short timeout, disabling them for the moment.
+    /*
     for (li = group->wnodes; li != NULL; li = li->next)
     {
         wnode = li->data;
@@ -2166,10 +2183,10 @@ static GtkWidget * xfce_taskbar_group_button_menu_group_actions (XfceTaskBarGrou
             gtk_menu_item_set_submenu (GTK_MENU_ITEM (mi), wnck_action_menu_new (wnode->window));
         }
     }
-    
     mi = gtk_separator_menu_item_new ();
     gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi);
     gtk_widget_show (mi);
+    */
 
     mi = gtk_image_menu_item_new_with_mnemonic (_("Mi_nimize All"));
     gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi);
@@ -2215,14 +2232,11 @@ static GtkWidget * xfce_taskbar_group_button_menu_group_actions (XfceTaskBarGrou
 
 static void xfce_taskbar_group_button_menu_destroy(GtkWidget *menu_widget, XfceTaskBarGroup *group)
 {
-    panel_return_if_fail (XFCE_IS_taskbar (group->taskbar));
-    panel_return_if_fail (GTK_IS_TOGGLE_BUTTON (group->button));
-    panel_return_if_fail (GTK_IS_WIDGET (menu_widget));
     xfce_taskbar_disable_hover_menu_timeout(menu_widget);
     gtk_widget_destroy (menu_widget);
     #ifdef GDK_WINDOWING_X11
     // Removes the wireframe associated with the currently selected window
-    xfce_taskbar_wireframe_hide (group->taskbar);
+    if(group) xfce_taskbar_wireframe_hide (group->taskbar);
     #endif
 }
 
@@ -2279,7 +2293,6 @@ static gboolean xfce_taskbar_group_button_release_event
     {
         GtkMenu *menu = attached->data;
         menu_source = (size_t)(g_object_get_data(G_OBJECT(menu), "menu-source"));
-        printf("menu_source: %zu\n", menu_source);
         gtk_widget_destroy (GTK_WIDGET(menu));
     }
     
@@ -2382,7 +2395,7 @@ static void xfce_taskbar_disable_hover_menu_timeout(GtkWidget *menu_widget)
 }
 
 //Triggered when mouse focus enters the hover menu
-static gboolean hover_menu_enter(GtkWidget *widget, GdkEvent  *event, gpointer menu_ptr)
+static gboolean xfce_taskbar_hover_menu_enter(GtkWidget *widget, GdkEvent  *event, gpointer menu_ptr)
 {
     GtkWidget *menu_widget = (GtkWidget *)menu_ptr;
     xfce_taskbar_disable_hover_menu_timeout(menu_widget);
@@ -2390,14 +2403,12 @@ static gboolean hover_menu_enter(GtkWidget *widget, GdkEvent  *event, gpointer m
 }
 
 //Triggered when mouse focus leaves the hover menu
-static gboolean hover_menu_leave(GtkWidget *widget, GdkEvent  *event, gpointer menu_ptr)
+static gboolean xfce_taskbar_hover_menu_leave(GtkWidget *widget, GdkEvent  *event, gpointer menu_ptr)
 {
     GtkWidget *menu_widget = (GtkWidget *)menu_ptr;
-    
     //We don't want to kill the hover menu immediately, so we wait a small time
     size_t timeout_id = (size_t)g_timeout_add(300, xfce_taskbar_hover_menu_timeout, menu_widget);
     g_object_set_data(G_OBJECT(menu_widget), "timeout_id", (void *)timeout_id);
-    
     return FALSE ;
 }
 
@@ -2406,8 +2417,8 @@ static void xfce_taskbar_activate_hover_menu(GtkWidget *menu_widget, XfceTaskBar
     gtk_menu_attach_to_widget (GTK_MENU (menu_widget), group->button, NULL);
     g_object_set_data(G_OBJECT(menu_widget), "menu-source", (void *)mouse_button);
     g_signal_connect (G_OBJECT (menu_widget), "selection-done", G_CALLBACK (xfce_taskbar_group_button_menu_destroy), group);
-    g_signal_connect (GTK_WINDOW (GTK_MENU(menu_widget)->toplevel), "enter-notify-event", G_CALLBACK (hover_menu_enter), menu_widget);
-    g_signal_connect (GTK_WINDOW (GTK_MENU(menu_widget)->toplevel), "leave-notify-event", G_CALLBACK (hover_menu_leave), menu_widget);
+    g_signal_connect (GTK_WINDOW (GTK_MENU(menu_widget)->toplevel), "enter-notify-event", G_CALLBACK (xfce_taskbar_hover_menu_enter), menu_widget);
+    g_signal_connect (GTK_WINDOW (GTK_MENU(menu_widget)->toplevel), "leave-notify-event", G_CALLBACK (xfce_taskbar_hover_menu_leave), menu_widget);
     {
         gint x, y ;
         gboolean push_in=TRUE;


More information about the Xfce4-commits mailing list