Author: nick
Date: 2009-01-31 13:59:15 +0000 (Sat, 31 Jan 2009)
New Revision: 29414

Modified:
   xfce4-panel/trunk/NEWS
   xfce4-panel/trunk/plugins/launcher/launcher.c
Log:
Fix dragging to launcher submenu's (bug #4026).


Modified: xfce4-panel/trunk/NEWS
===================================================================
--- xfce4-panel/trunk/NEWS      2009-01-31 12:02:10 UTC (rev 29413)
+++ xfce4-panel/trunk/NEWS      2009-01-31 13:59:15 UTC (rev 29414)
@@ -1,8 +1,8 @@
 4.x.xx
 ======
 - Block panel autohide if the widget is grabbed (bug #4597).
+- Fix dragging to launcher submenu's (bug #4026).
 
-
 4.5.99.1
 ========
 - Fixed extern char** environ is not defined on BSD platforms (bug #4834).

Modified: xfce4-panel/trunk/plugins/launcher/launcher.c
===================================================================
--- xfce4-panel/trunk/plugins/launcher/launcher.c       2009-01-31 12:02:10 UTC 
(rev 29413)
+++ xfce4-panel/trunk/plugins/launcher/launcher.c       2009-01-31 13:59:15 UTC 
(rev 29414)
@@ -522,6 +522,98 @@
 
 
 
+static gboolean 
+launcher_arrow_button_drag_motion (GtkWidget      *widget,
+                                   GdkDragContext *drag_context,
+                                   gint            x,
+                                   gint            y,
+                                   guint           drag_time,
+                                   LauncherPlugin *launcher)
+{
+    /* do not try to popup if the arrow button is used and the signal
+     * is comming from the icon button */
+    if (launcher->arrow_position != LAUNCHER_ARROW_INSIDE_BUTTON
+        && launcher->arrow_button != widget)
+        return TRUE;
+    
+    if (!gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON 
(launcher->arrow_button)))
+    {
+        /* make the toggle button active */
+        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON 
(launcher->arrow_button), TRUE);
+
+        launcher->popup_timeout_id =
+                g_timeout_add_full (G_PRIORITY_DEFAULT, LAUNCHER_POPUP_DELAY, 
launcher_menu_popup,
+                                    launcher, launcher_menu_popup_destroyed);
+    }
+
+    return TRUE;
+}
+
+
+
+static gboolean
+launcher_arrow_button_drag_leave_timeout (gpointer user_data)
+{
+    LauncherPlugin *launcher = user_data;
+    GdkScreen      *screen;
+    GdkDisplay     *display;
+    gint            x, y;
+    gint            menu_x, menu_y, menu_w, menu_h;
+    
+    if (launcher->menu == NULL)
+        return FALSE;
+    
+    g_return_val_if_fail (GDK_IS_WINDOW (launcher->menu->window), FALSE);
+
+    /* get the current pointer position */
+    screen = gtk_widget_get_screen (launcher->arrow_button);
+    display = gdk_screen_get_display (screen);
+    gdk_display_get_pointer (display, NULL, &x, &y, NULL);
+
+    /* get the menu size and postion */
+    gdk_window_get_root_origin (launcher->menu->window, &menu_x, &menu_y);
+    gdk_drawable_get_size (GDK_DRAWABLE (launcher->menu->window), &menu_w, 
&menu_h);
+
+    /* check if we should hide the menu */
+    if (x < menu_x || x > menu_x + menu_w 
+        || y < menu_y || y > menu_y + menu_h)
+    {
+        /* hide the menu */
+        gtk_widget_hide (GTK_MENU (launcher->menu)->toplevel);
+        gtk_widget_hide (launcher->menu);
+
+        /* inactive the toggle button */
+        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON 
(launcher->arrow_button), FALSE);
+    }
+
+    return FALSE;
+}
+
+
+
+static void
+launcher_arrow_button_drag_leave (GtkWidget      *widget,
+                                  GdkDragContext *drag_context,
+                                  guint           drag_time,
+                                  LauncherPlugin *launcher)
+{
+    if (launcher->popup_timeout_id != 0)
+    {
+        /* destroy the timeout */
+        g_source_remove (launcher->popup_timeout_id);
+        
+        /* restore button */
+        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON 
(launcher->arrow_button), FALSE);
+    }
+    else
+    {
+        /* start a timeout to give the user some time to drag to the menu */
+        g_timeout_add (100, launcher_arrow_button_drag_leave_timeout, 
launcher);
+    }
+}
+
+
+
 /**
  * Global Button Functions
  **/
@@ -549,18 +641,13 @@
                              LauncherPlugin *launcher)
 {
     GdkScreen     *screen;
-    gint           i;
     LauncherEntry *entry;
 
     /* get the widget screen */
     screen = gtk_widget_get_screen (mi);
 
     /* get the item number */
-    i = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (mi), 
I_("entry-number")));
-
-    /* get the entry from the list */
-    entry = g_list_nth_data (launcher->entries, i);
-
+    entry = g_object_get_data (G_OBJECT (mi), I_("entry"));
     if (G_LIKELY (entry))
     {
         if (event->button == 1)
@@ -569,7 +656,8 @@
             launcher_execute_from_clipboard (screen, entry);
 
         /* move the item to the first position in the list */
-        if (G_UNLIKELY (launcher->move_first && i > 0))
+        if (launcher->move_first
+            && launcher->entries->data != entry)
         {
             /* remove from the list */
             launcher->entries = g_list_remove (launcher->entries, entry);
@@ -594,6 +682,48 @@
 
 
 static void
+launcher_menu_item_drag_data_received (GtkWidget        *widget,
+                                       GdkDragContext   *context,
+                                       gint              x,
+                                       gint              y,
+                                       GtkSelectionData *selection_data,
+                                       guint             info,
+                                       guint             time_,
+                                       LauncherPlugin   *launcher)
+{
+    GSList        *filenames;
+    LauncherEntry *entry;
+    
+    entry = g_object_get_data (G_OBJECT (widget), I_("entry"));
+    if (G_LIKELY (entry != NULL))
+    {
+        /* create filenames list from all the uris */
+        filenames = launcher_utility_filenames_from_selection_data 
(selection_data);
+
+        if (G_LIKELY (filenames))
+        {
+            /* execute the entry with the filenames */
+            launcher_execute (gtk_widget_get_screen (widget), entry, 
filenames);
+
+            /* cleanup */
+            launcher_free_filenames (filenames);
+        }
+
+        /* finish drag */
+        gtk_drag_finish (context, TRUE, FALSE, time_);
+    }
+
+    /* hide the menu */
+    gtk_widget_hide (GTK_MENU (launcher->menu)->toplevel);
+    gtk_widget_hide (launcher->menu);
+
+    /* inactive the toggle button */
+    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (launcher->arrow_button), 
FALSE);
+}
+
+
+
+static void
 launcher_menu_popup_destroyed (gpointer user_data)
 {
     LauncherPlugin *launcher = user_data;
@@ -607,6 +737,7 @@
 launcher_menu_popup (gpointer user_data)
 {
     LauncherPlugin *launcher = user_data;
+    gint            x, y;
 
     GDK_THREADS_ENTER ();
 
@@ -623,6 +754,22 @@
                     launcher->panel_plugin,
                     1, gtk_get_current_event_time ());
 
+    if (!GTK_WIDGET_VISIBLE (launcher->menu))
+    {
+        /* make sure the size is allocated */
+        if (!GTK_WIDGET_REALIZED (launcher->menu))
+            gtk_widget_realize (launcher->menu);
+
+        /* use the widget position function to get the coordinates */
+        xfce_panel_plugin_position_widget (launcher->panel_plugin, 
launcher->menu,
+                                           NULL, &x, &y);
+
+        /* ugly, but it works most of the time... */
+        gtk_widget_show (launcher->menu);
+        gtk_window_move (GTK_WINDOW (GTK_MENU (launcher->menu)->toplevel), x, 
y);
+        gtk_widget_show (GTK_MENU (launcher->menu)->toplevel);
+    }
+
     GDK_THREADS_LEAVE ();
 
     return FALSE;
@@ -729,19 +876,21 @@
             }
         }
 
-        /* set entries list number */
-        g_object_set_data (G_OBJECT (mi), I_("entry-number"), GINT_TO_POINTER 
(n));
+        /* set entry */
+        g_object_set_data (G_OBJECT (mi), I_("entry"), entry);
+        
+        /* dnd support */
+        gtk_drag_dest_set (mi, GTK_DEST_DEFAULT_ALL, drop_targets, 
G_N_ELEMENTS (drop_targets), GDK_ACTION_COPY);
 
         /* connect signals */
         g_signal_connect (G_OBJECT (mi), "button-release-event", G_CALLBACK 
(launcher_menu_item_released), launcher);
+        g_signal_connect (G_OBJECT (mi), "drag-data-received", G_CALLBACK 
(launcher_menu_item_drag_data_received), launcher);
+        g_signal_connect (G_OBJECT (mi), "drag-leave", G_CALLBACK 
(launcher_arrow_button_drag_leave), launcher);
 #if LAUNCHER_NEW_TOOLTIP_API
         gtk_widget_set_has_tooltip (mi, TRUE);
         g_signal_connect (G_OBJECT (mi), "query-tooltip", G_CALLBACK 
(launcher_utility_query_tooltip), entry);
 #endif
 
-        /* dnd support */
-        gtk_drag_dest_set (mi, GTK_DEST_DEFAULT_ALL, drop_targets, 
G_N_ELEMENTS (drop_targets), GDK_ACTION_COPY);
-
 #if !LAUNCHER_NEW_TOOLTIP_API
         /* set tooltip */
         if (entry->comment)
@@ -874,6 +1023,10 @@
                       G_CALLBACK (launcher_icon_button_drag_data_received), 
launcher);
     g_signal_connect_after (G_OBJECT (launcher->image), "expose-event",
                             G_CALLBACK (launcher_icon_button_expose_event), 
launcher);
+    g_signal_connect (G_OBJECT (launcher->icon_button), "drag-motion",
+                      G_CALLBACK (launcher_arrow_button_drag_motion), 
launcher);
+    g_signal_connect (G_OBJECT (launcher->icon_button), "drag-leave",
+                      G_CALLBACK (launcher_arrow_button_drag_leave), launcher);
 
 #if LAUNCHER_NEW_TOOLTIP_API
     gtk_widget_set_has_tooltip (launcher->icon_button, TRUE);
@@ -886,6 +1039,10 @@
                       G_CALLBACK (launcher_button_state_changed), 
launcher->icon_button);
     g_signal_connect (G_OBJECT (launcher->arrow_button), "button-press-event",
                       G_CALLBACK (launcher_arrow_button_pressed), launcher);
+    g_signal_connect (G_OBJECT (launcher->arrow_button), "drag-motion",
+                      G_CALLBACK (launcher_arrow_button_drag_motion), 
launcher);
+    g_signal_connect (G_OBJECT (launcher->arrow_button), "drag-leave",
+                      G_CALLBACK (launcher_arrow_button_drag_leave), launcher);
 
     /* set drag destinations */
     gtk_drag_dest_set (launcher->icon_button, GTK_DEST_DEFAULT_ALL,

_______________________________________________
Xfce4-commits mailing list
Xfce4-commits@xfce.org
http://foo-projects.org/mailman/listinfo/xfce4-commits

Reply via email to