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