[Xfce4-commits] <xfce4-taskbar-plugin:master> Merge branch 'master' of git://git.xfce.org/panel-plugins/xfce4-taskbar-plugin
Gearoid Murphy
noreply at xfce.org
Tue Oct 9 15:02:04 CEST 2012
Updating branch refs/heads/master
to 6a95ca9192dab043e60407017ec49103ad6c331f (commit)
from 99a159b107974ec6738b59822b1473d66fdd04ba (commit)
commit 6a95ca9192dab043e60407017ec49103ad6c331f
Merge: 99a159b e682382
Author: Gearoid Murphy <gearoid.murphy at hp.com>
Date: Tue Oct 9 10:34:39 2012 +0100
Merge branch 'master' of git://git.xfce.org/panel-plugins/xfce4-taskbar-plugin
commit e6823823cecfc858af31ac621af242b2b06fc105
Author: Gearoid Murphy <gearoid at murphy.com>
Date: Mon Oct 8 20:19:06 2012 +0100
Hover menu implementation largely complete, still some conflicts between the old focus grabbing menu
and the new mouse-over-focus only menu, will get to those soon :)
Makefile | 19 ++-
README | 39 +++++-
taskbar-widget.c | 414 +++++++++++++++++++++++++++++++++---------------------
3 files changed, 307 insertions(+), 165 deletions(-)
diff --git a/Makefile b/Makefile
index 0c7aee3..82101e5 100644
--- a/Makefile
+++ b/Makefile
@@ -1,4 +1,5 @@
-CFLAGS=-fPIC -I. `pkg-config --cflags-only-I gtk+-2.0 exo-1 libwnck-1.0 libxfce4panel-1.0 libxfce4ui-1 libxfconf-0 gtkhotkey-1.0`
+#CFLAGS=-fPIC -g -I. `pkg-config --cflags-only-I gtk+-2.0 exo-1 libwnck-1.0 libxfce4panel-1.0 libxfce4ui-1 libxfconf-0 gtkhotkey-1.0`
+CFLAGS=-fPIC -O3 -I. `pkg-config --cflags-only-I gtk+-2.0 exo-1 libwnck-1.0 libxfce4panel-1.0 libxfce4ui-1 libxfconf-0 gtkhotkey-1.0`
LINKFLAGS=`pkg-config --libs gtk+-2.0 exo-1 libwnck-1.0 libxfce4panel-1.0 libxfce4ui-1 libxfconf-0 gobject-2.0 gtk+-x11-2.0 glib-2.0 gtkhotkey-1.0`
OBJ=taskbar.o taskbar-widget.o hotkeys.o
@@ -9,12 +10,20 @@ libtaskbar:$(OBJ)
g++ -shared -o libtaskbar.so $(OBJ) $(LINKFLAGS)
install:
- ln -s `pwd`/libtaskbar.so /usr/lib/xfce4/panel-plugins/libtaskbar.so
- ln -s `pwd`/taskbar.desktop /usr/share/xfce4/panel/plugins/taskbar.desktop
+ sudo ln -s `pwd`/libtaskbar.so /usr/lib/xfce4/panel-plugins/libtaskbar.so
+ sudo ln -s `pwd`/taskbar.desktop /usr/share/xfce4/panel/plugins/taskbar.desktop
uninstall:
- rm -f /usr/lib/xfce4/panel-plugins/libtaskbar.so
- rm -f /usr/share/xfce4/panel/plugins/taskbar.desktop
+ sudo rm -f /usr/lib/xfce4/panel-plugins/libtaskbar.so
+ sudo rm -f /usr/share/xfce4/panel/plugins/taskbar.desktop
clean:
rm -f *.o *.so
+
+devenv:
+ sudo apt-get install libgtk2.0-dev libexo-1-dev libxfce4ui-1-dev libxfce4util-dev libxfcegui4-dev libxfconf-0-dev xfce4-panel-dev libwnck-dev libgtkhotkey-dev
+
+restart:
+ xfce4-panel -r
+
+
\ No newline at end of file
diff --git a/README b/README
index 928e51a..0ebfa35 100644
--- a/README
+++ b/README
@@ -1,15 +1,48 @@
-1) To build and install the plugin:
+1) Make sure you've got the development packages
+
+ # Valid for XUbuntu 12.04
+ make devenv
+
+2) Build and install the plugin:
make
sudo make install
xfce4-panel -r # restart the panel
# It should now be in 'Add New Items' option via panel context menu
-2) To remove the plugin
+3) To remove the plugin
sudo make uninstall
-** Known Issues / Notes ***
+4) For development
+
+ #uninstall, install, restart the panel
+ make restart
+
+** Usage Notes **
+
+ <Super> + number will activate the pinned application indexed by the
+ number (Super is the so-called 'Windows' key)
+
+ Right-click on an application icon will give you the option to pin/unpin
+ the app
+
+ Left-click on the application icon has context dependent behaviour:
+
+ 1) If it is a pinned icon and there are no application instances
+ running, the associated application is started
+
+ 2) If there is a single application instance running, it is raised
+ or lowered, depending on it's current state
+
+ 3) If there are multiple application instances running, a list to
+ the application windows is shown
+
+
+** Known Issues ***
+
+ Drag and drop of applications from the applications menu or the desktop
+ does not work (yet)
The windows are grouped by wnck class resource name
This appears to be a somewhat volatile property as some applications
diff --git a/taskbar-widget.c b/taskbar-widget.c
index 1c85389..2dfcac3 100644
--- a/taskbar-widget.c
+++ b/taskbar-widget.c
@@ -71,6 +71,9 @@ enum
PROP_SHOW_HANDLE,
};
+
+enum {LEFTMOUSE=1, MIDMOUSE=2, RIGHTMOUSE=3} ;
+
struct _XfceTaskBarClass
{
GtkContainerClass __parent__;
@@ -184,8 +187,19 @@ struct _XfceTaskBarGroup
gboolean dragactive ;
gboolean pinned ;
gchar *command ;
+ guint popup_timeout ;
+ gulong enter_signal ;
+ gulong leave_signal ;
};
+#define DISABLE_HOVER_TIMEOUT(group) if(group->popup_timeout != 0) {g_source_remove(group->popup_timeout); group->popup_timeout=0;}
+
+#define ENABLE_ENTER_SIGNAL(group) { group->enter_signal = g_signal_connect(G_OBJECT(group->button), "enter-notify-event", G_CALLBACK(xfce_taskbar_group_button_enter_event), group); }
+#define DISABLE_ENTER_SIGNAL(group) if(group->enter_signal != 0) {g_signal_handler_disconnect(G_OBJECT(group->button), group->enter_signal); group->enter_signal=0;}
+
+#define ENABLE_EXIT_SIGNAL(group) { group->leave_signal = g_signal_connect(G_OBJECT(group->button),"leave-notify-event", G_CALLBACK(xfce_taskbar_group_button_leave_event), group); }
+#define DISABLE_EXIT_SIGNAL(group) if(group->leave_signal != 0) {g_signal_handler_disconnect(G_OBJECT(group->button), group->leave_signal); group->leave_signal=0;}
+
static const GtkTargetEntry source_targets[] =
{
{ "application/x-wnck-window-id", 0, 0 }
@@ -230,10 +244,12 @@ static XfceTaskBarWNode* xfce_taskbar_wnode_new (WnckWindow *win
static void xfce_taskbar_wnode_del (XfceTaskBarWNode *wnode);
/* taskbar group buttons */
-static int xfce_taskbar_group_visible_count (XfceTaskBarGroup *group, WnckWorkspace *active_ws);
-static void xfce_taskbar_group_update_visibility (XfceTaskBarGroup *group);
-static void xfce_taskbar_group_button_remove (XfceTaskBarGroup *group);
-static void xfce_taskbar_group_button_add_window (XfceTaskBarGroup *group, XfceTaskBarWNode *window_child);
+static int xfce_taskbar_group_visible_count (XfceTaskBarGroup *group, WnckWorkspace *active_ws);
+static void xfce_taskbar_group_update_visibility (XfceTaskBarGroup *group);
+static void xfce_taskbar_group_button_remove (XfceTaskBarGroup *group);
+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 XfceTaskBarGroup*
xfce_taskbar_group_button_new (const char *, XfceTaskBar *taskbar);
@@ -245,8 +261,6 @@ static void xfce_taskbar_group_button_build_launch_menu (XfceTaskBarGroup *g
static void xfce_taskbar_group_button_build_pin_menu (XfceTaskBarGroup *group, GtkWidget *menu);
static void cache_pinned_configuration (XfceTaskBar *taskbar);
-
-
/* potential public functions */
static void xfce_taskbar_set_include_all_workspaces (XfceTaskBar *taskbar, gboolean all_workspaces);
static void xfce_taskbar_set_include_all_monitors (XfceTaskBar *taskbar, gboolean all_monitors);
@@ -1407,7 +1421,7 @@ static void xfce_taskbar_button_icon_changed (WnckWindow *window, XfceTaskBarWNo
g_object_unref (G_OBJECT (lucent));
}
-static void xfce_taskbar_button_name_changed (WnckWindow *window, XfceTaskBarWNode *child)
+static void xfce_taskbar_button_name_changed(WnckWindow *window, XfceTaskBarWNode *child)
{
const gchar *name;
gchar *label = NULL;
@@ -1562,59 +1576,52 @@ static gboolean xfce_taskbar_button_enter_notify_event (GtkWidget *button, GdkEv
return FALSE;
}
-//app buttons are the buttons associated with a single instance of a specific application group, exposed by clicking on a group button
-static gboolean xfce_taskbar_app_button_press_event (GtkWidget *button, GdkEventButton *event, XfceTaskBarWNode *child)
+//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)
{
- GtkWidget *menu, *panel_plugin;
-
panel_return_val_if_fail (XFCE_IS_taskbar (child->taskbar), FALSE);
- if (event->type != GDK_BUTTON_PRESS || xfce_taskbar_is_locked (child->taskbar))
+ /* only respond to in-button events */
+ if (
+ ((event->type == GDK_BUTTON_RELEASE &&
+ !xfce_taskbar_is_locked (child->taskbar) &&
+ !(event->x == 0 && event->y == 0) && /* 0,0 = outside the widget in Gtk */
+ event->x >= 0 && event->x < button->allocation.width &&
+ event->y >= 0 && event->y < button->allocation.height))
+ == FALSE
+ )
{
- return FALSE;
+ return FALSE ;
}
-
- /* send the event to the panel plugin if control is pressed */
- if (PANEL_HAS_FLAG (event->state, GDK_CONTROL_MASK))
+
+ //Sanity check the buttons, to be sure to be sure :)
+ if(event->button < LEFTMOUSE || event->button > RIGHTMOUSE)
+ return FALSE ;
+
+ if(event->button == LEFTMOUSE)
{
- /* send the event to the panel plugin */
- panel_plugin = xfce_taskbar_get_panel_plugin (child->taskbar);
- if (G_LIKELY (panel_plugin != NULL))
+ xfce_taskbar_button_activate (child, event->time);
+ return FALSE ;
+ }
+ else if(event->button == MIDMOUSE)
+ {
+ if(WNCK_IS_WINDOW (child->window) == TRUE)
{
- gtk_widget_event (panel_plugin, (GdkEvent *) event);
+ wnck_window_close (child->window, gtk_get_current_event_time ());
+ return FALSE ;
}
-
- return TRUE;
}
-
- if (event->button == 3)
+ else// if(event->button == 3)
{
+ GtkWidget *menu ;
menu = wnck_action_menu_new (child->window); g_signal_connect (G_OBJECT (menu), "selection-done", G_CALLBACK (gtk_widget_destroy), NULL);
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;
+ return TRUE ;
}
-
- return FALSE;
-}
-
-//app buttons are the buttons associated with a single instance of a specific application group, exposed by clicking on a group button
-static gboolean xfce_taskbar_app_button_release_event (GtkWidget *button, GdkEventButton *event, XfceTaskBarWNode *child)
-{
- panel_return_val_if_fail (XFCE_IS_taskbar (child->taskbar), FALSE);
-
- /* only respond to in-button events */
- if (event->type == GDK_BUTTON_RELEASE
- && !xfce_taskbar_is_locked (child->taskbar)
- && event->button == 1
- && !(event->x == 0 && event->y == 0) /* 0,0 = outside the widget in Gtk */
- && event->x >= 0 && event->x < button->allocation.width
- && event->y >= 0 && event->y < button->allocation.height)
- {
- xfce_taskbar_button_activate (child, event->time);
- }
-
- return FALSE;
+
+ return FALSE ;
}
static void xfce_taskbar_button_enter_notify_event_disconnected (gpointer data, GClosure *closure)
@@ -1667,25 +1674,22 @@ static GtkWidget *xfce_taskbar_button_proxy_menu_item (XfceTaskBarWNode *child,
G_CALLBACK (xfce_taskbar_button_enter_notify_event), child,
xfce_taskbar_button_enter_notify_event_disconnected, 0);
}
-
- g_signal_connect (G_OBJECT (mi), "button-press-event", G_CALLBACK (xfce_taskbar_app_button_press_event), child);
+
g_signal_connect (G_OBJECT (mi), "button-release-event", G_CALLBACK (xfce_taskbar_app_button_release_event), child);
-
- /* TODO item dnd */
-
+
return mi;
}
void xfce_taskbar_selgrp_cmd(XfceTaskBar *taskbar, char id) {
- XfceTaskBarGroup *group = g_list_nth_data(taskbar->wgroups, id-1);
- if(!group)
- return;
- XfceTaskBarWNode *first = g_slist_nth_data(group->wnodes, 0);
- if(!first) {
- xfce_taskbar_group_button_launch_pinned(group);
- } else if (!wnck_window_is_active(first->window)) {
- xfce_taskbar_button_activate(first, 0);
- }
+ XfceTaskBarGroup *group = g_list_nth_data(taskbar->wgroups, id-1);
+ if(!group)
+ return;
+ XfceTaskBarWNode *first = g_slist_nth_data(group->wnodes, 0);
+ if(!first) {
+ xfce_taskbar_group_button_launch_pinned(group);
+ } else if (!wnck_window_is_active(first->window)) {
+ xfce_taskbar_button_activate(first, 0);
+ }
}
static void xfce_taskbar_button_activate (XfceTaskBarWNode *wnode, guint32 timestamp)
@@ -1707,39 +1711,39 @@ static void xfce_taskbar_button_activate (XfceTaskBarWNode *wnode, guint32 times
}
else
{
- /* we only change worksapces/viewports for non-pinned windows
- * and if all workspaces/viewports are shown */
+ // we only change worksapces/viewports for non-pinned windows
+ // and if all workspaces/viewports are shown
if (wnode->taskbar->all_workspaces && !wnck_window_is_pinned (wnode->window))
{
workspace = wnck_window_get_workspace (wnode->window);
- /* only switch workspaces/viewports if switch_workspace is enabled or
- * we want to restore a minimized window to the current workspace/viewport */
+ // only switch workspaces/viewports if switch_workspace is enabled or
+ // we want to restore a minimized window to the current workspace/viewport
if (workspace != NULL && (wnode->taskbar->switch_workspace || !wnck_window_is_minimized (wnode->window)))
{
if (G_UNLIKELY (wnck_workspace_is_virtual (workspace)))
{
if (!wnck_window_is_in_viewport (wnode->window, workspace))
{
- /* viewport info */
+ // viewport info
workspace_width = wnck_workspace_get_width (workspace);
workspace_height = wnck_workspace_get_height (workspace);
screen_width = wnck_screen_get_width (wnode->taskbar->screen);
screen_height = wnck_screen_get_height (wnode->taskbar->screen);
- /* we only support multiple viewports like compiz has
- * (all equally spread across the screen) */
+ // we only support multiple viewports like compiz has
+ // (all equally spread across the screen)
if ((workspace_width % screen_width) == 0 && (workspace_height % screen_height) == 0)
{
wnck_window_get_geometry (wnode->window, &window_x, &window_y, NULL, NULL);
- /* lookup nearest workspace edge */
+ // lookup nearest workspace edge
viewport_x = window_x - (window_x % screen_width);
viewport_x = CLAMP (viewport_x, 0, workspace_width - screen_width);
viewport_y = window_y - (window_y % screen_height);
viewport_y = CLAMP (viewport_y, 0, workspace_height - screen_height);
- /* move to the other viewport */
+ // move to the other viewport
wnck_screen_move_viewport (wnode->taskbar->screen, viewport_x, viewport_y);
}
else
@@ -1750,35 +1754,35 @@ static void xfce_taskbar_button_activate (XfceTaskBarWNode *wnode, guint32 times
}
else if (wnck_screen_get_active_workspace (wnode->taskbar->screen) != workspace)
{
- /* switch to the other workspace before we activate the window */
+ // switch to the other workspace before we activate the window
wnck_workspace_activate (workspace, timestamp - 1);
}
}
else if (workspace != NULL && wnck_workspace_is_virtual (workspace) && !wnck_window_is_in_viewport (wnode->window, workspace))
{
- /* viewport info */
+ // viewport info
workspace_width = wnck_workspace_get_width (workspace);
workspace_height = wnck_workspace_get_height (workspace);
screen_width = wnck_screen_get_width (wnode->taskbar->screen);
screen_height = wnck_screen_get_height (wnode->taskbar->screen);
- /* we only support multiple viewports like compiz has
- * (all equaly spread across the screen) */
+ // we only support multiple viewports like compiz has
+ // (all equaly spread across the screen)
if ((workspace_width % screen_width) == 0 && (workspace_height % screen_height) == 0)
{
viewport_x = wnck_workspace_get_viewport_x (workspace);
viewport_y = wnck_workspace_get_viewport_y (workspace);
- /* note that the x and y might be negative numbers, since they are relative
- * to the current screen, not to the edge of the screen they are on. this is
- * not a problem since the mod result will always be positive */
+ // note that the x and y might be negative numbers, since they are relative
+ // to the current screen, not to the edge of the screen they are on. this is
+ // not a problem since the mod result will always be positive
wnck_window_get_geometry (wnode->window, &window_x, &window_y, NULL, NULL);
- /* get the new screen position, with the same screen offset */
+ // get the new screen position, with the same screen offset
window_x = viewport_x + (window_x % screen_width);
window_y = viewport_y + (window_y % screen_height);
- /* move the window */
+ // move the window
wnck_window_set_geometry (wnode->window, WNCK_WINDOW_GRAVITY_CURRENT, WNCK_WINDOW_CHANGE_X | WNCK_WINDOW_CHANGE_Y, window_x, window_y, -1, -1);
}
else
@@ -1798,7 +1802,7 @@ static void xfce_taskbar_button_drag_data_get(GtkWidget *button, GdkDragContext
static void xfce_taskbar_button_drag_begin (GtkWidget *button, GdkDragContext *context, XfceTaskBarGroup *group)
{
- // Hacky workaround for DnD crashes
+ // Gruesomely hacky workaround for DnD crashes :(
usleep(20000);
group->dragactive = TRUE ;
gtk_drag_set_icon_pixmap(context, gtk_widget_get_colormap(group->icon), gtk_widget_get_snapshot(group->icon, NULL), NULL, 0, 0);
@@ -1871,14 +1875,14 @@ static XfceTaskBarWNode * xfce_taskbar_wnode_new (WnckWindow *window, XfceTaskBa
wnode->group_name = g_strdup(wnck_application_get_name(wnck_window_get_application (window)));
wnode->visible = xfce_taskbar_button_visible(wnode, active_ws);
- /* monitor window changes */
+ // monitor window changes
g_signal_connect (G_OBJECT (window), "icon-changed", G_CALLBACK (xfce_taskbar_button_icon_changed), wnode);
g_signal_connect (G_OBJECT (window), "name-changed", G_CALLBACK (xfce_taskbar_button_name_changed), wnode);
g_signal_connect (G_OBJECT (window), "state-changed", G_CALLBACK (xfce_taskbar_button_state_changed), wnode);
g_signal_connect (G_OBJECT (window), "workspace-changed", G_CALLBACK (xfce_taskbar_button_workspace_changed), wnode);
g_signal_connect (G_OBJECT (window), "geometry-changed", G_CALLBACK (xfce_taskbar_button_geometry_changed2), wnode);
- /* poke functions */
+ // poke functions
xfce_taskbar_button_icon_changed (window, wnode);
xfce_taskbar_button_name_changed (NULL, wnode);
@@ -2006,14 +2010,12 @@ static GtkWidget * xfce_taskbar_group_button_menu_launcher(XfceTaskBarGroup *gro
{
GtkWidget *menu;
GtkWidget *mi;
-
menu = gtk_menu_new ();
-
xfce_taskbar_group_button_build_launch_menu(group, menu, FALSE);
-
return menu ;
}
+// Helper function for building the list of windows associated with a group icon
static GtkWidget * xfce_taskbar_group_button_menu_show_active(XfceTaskBarGroup *group)
{
GSList *li;
@@ -2038,7 +2040,7 @@ static GtkWidget * xfce_taskbar_group_button_menu_show_active(XfceTaskBarGroup *
return menu ;
}
-/*** Copied most of this code from the verve plugin ***/
+// Copied most of this code from the verve plugin ;]
static void xfce_taskbar_group_button_launch_pinned (XfceTaskBarGroup *group)
{
gint argc;
@@ -2050,10 +2052,10 @@ static void xfce_taskbar_group_button_launch_pinned (XfceTaskBarGroup *group)
panel_return_if_fail((group->pinned == TRUE));
- /* Parse command line arguments */
+ // Parse command line arguments
success = g_shell_parse_argv (group->command, &argc, &argv, &error);
- /* Return false if command line arguments failed to be arsed */
+ // Return false if command line arguments failed to be parsed
if (G_UNLIKELY (error != NULL))
{
xfce_dialog_show_error (NULL, error, _("Failed to parse the command \"%s\""), group->command);
@@ -2061,15 +2063,15 @@ static void xfce_taskbar_group_button_launch_pinned (XfceTaskBarGroup *group)
return ;
}
- /* Get user's home directory */
+ // Get user's home directory
home_dir = xfce_get_homedir ();
- /* Set up spawn flags */
+ // Set up spawn flags
flags = G_SPAWN_STDOUT_TO_DEV_NULL;
flags |= G_SPAWN_STDERR_TO_DEV_NULL;
flags |= G_SPAWN_SEARCH_PATH;
- /* Spawn subprocess */
+ // Spawn subprocess
success = g_spawn_async (home_dir, argv, NULL, flags, NULL, NULL, NULL, &error);
g_strfreev (argv);
if(!success)
@@ -2079,8 +2081,6 @@ static void xfce_taskbar_group_button_launch_pinned (XfceTaskBarGroup *group)
return ;
}
-
-
}
static void xfce_taskbar_group_button_toggle_pinned (XfceTaskBarGroup *group)
@@ -2132,64 +2132,38 @@ static void xfce_taskbar_group_button_toggle_pinned (XfceTaskBarGroup *group)
}
}
- /* Cache the icon and path data for the pinned items */
+ // Cache the icon and path data for the pinned items
xfce_taskbar_save_pinned_config (group->taskbar);
}
-/* Create the wnck_action_menu first, then *prepend* the pinning functions to the menu */
-static GtkWidget * xfce_taskbar_group_button_menu_single_actions (XfceTaskBarGroup *group, XfceTaskBarWNode *wnode)
-{
- GtkWidget *menu ;
- GtkWidget *mi;
-
- menu = wnck_action_menu_new (wnode->window) ;
- //Only offer to pin windows with detectable pids
- if(wnck_window_get_pid(wnode->window) != 0)
- {
- if(group->pinned == TRUE)
- {
- xfce_taskbar_group_button_build_launch_menu(group, menu, TRUE);
- }
- else
- {
- xfce_taskbar_group_button_build_pin_menu(group, menu);
- }
- }
- return menu ;
-}
-
-/* Create the pinning functions first, then *append* the group actions to the menu */
+// Create the pinning functions first, then *append* the group actions to the menu
static GtkWidget * xfce_taskbar_group_button_menu_group_actions (XfceTaskBarGroup *group)
{
GSList *li;
- XfceTaskBarWNode *wnode;
GtkWidget *mi;
GtkWidget *menu;
GtkWidget *image;
+ XfceTaskBarWNode *wnode;
gint visibility_count = 0 ;
-
+
panel_return_val_if_fail (XFCE_IS_taskbar (group->taskbar), NULL);
menu = gtk_menu_new ();
+ if(group->pinned == TRUE)
+ {
+ xfce_taskbar_group_button_build_launch_menu(group, menu, TRUE);
+ }
//Only offer to pin windows with detectable pids
- if(group->wnodes && wnck_window_get_pid(((XfceTaskBarWNode *)group->wnodes->data)->window) != 0)
+ else if(group->wnodes && wnck_window_get_pid(((XfceTaskBarWNode *)group->wnodes->data)->window) != 0)
{
- if(group->pinned == TRUE)
- {
- xfce_taskbar_group_button_build_launch_menu(group, menu, TRUE);
- }
- else
- {
- xfce_taskbar_group_button_build_pin_menu(group, menu);
- }
-
+
+ xfce_taskbar_group_button_build_pin_menu(group, menu);
}
for (li = group->wnodes; li != NULL; li = li->next)
{
wnode = li->data;
-
if(wnode->visible)
{
visibility_count += 1 ;
@@ -2238,7 +2212,7 @@ static GtkWidget * xfce_taskbar_group_button_menu_group_actions (XfceTaskBarGrou
gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi);
g_signal_connect_swapped (G_OBJECT (mi), "activate", G_CALLBACK (xfce_taskbar_group_button_menu_close_all), group);
gtk_widget_show (mi);
-
+
image = gtk_image_new_from_stock ("wnck-stock-delete", GTK_ICON_SIZE_MENU);
gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (mi), image);
gtk_widget_show (image);
@@ -2246,7 +2220,7 @@ static GtkWidget * xfce_taskbar_group_button_menu_group_actions (XfceTaskBarGrou
return menu;
}
-static void xfce_taskbar_group_button_menu_destroy (GtkWidget *menu, XfceTaskBarGroup *group)
+static void xfce_taskbar_group_button_menu_destroy(GtkWidget *menu, XfceTaskBarGroup *group)
{
panel_return_if_fail (XFCE_IS_taskbar (group->taskbar));
panel_return_if_fail (GTK_IS_TOGGLE_BUTTON (group->button));
@@ -2262,17 +2236,22 @@ static void xfce_taskbar_group_button_menu_destroy (GtkWidget *menu, XfceTaskBar
#endif
}
+// This function handles all the logic for mouse button relase on the taskbar icons
static gboolean xfce_taskbar_group_button_release_event
(GtkWidget *button, GdkEventButton *event, XfceTaskBarGroup *group)
{
GtkWidget *panel_plugin;
GtkWidget *menu;
+ //Disable the timeout, if active
+ DISABLE_HOVER_TIMEOUT(group);
+
panel_return_val_if_fail (XFCE_IS_taskbar (group->taskbar), FALSE);
if (event->type != GDK_BUTTON_RELEASE || xfce_taskbar_is_locked (group->taskbar))
return FALSE;
+ //Some hacky stuff for drag and drop
if(group->dragactive == TRUE)
{
group->dragactive = FALSE ;
@@ -2290,10 +2269,17 @@ static gboolean xfce_taskbar_group_button_release_event
}
return TRUE;
}
-
- if (event->button == 1 || event->button == 3)
+
+ //Middle mouse click on the taskbar icon launchs the icon
+ if(event->button == MIDMOUSE)
+ {
+ xfce_taskbar_group_button_launch_pinned(group);
+ return TRUE ;
+ }
+
+ //This is trying to do too much, need to prune it
+ if (event->button == LEFTMOUSE || event->button == RIGHTMOUSE)
{
-
GSList *li;
XfceTaskBarWNode *child, *active_child=0x0 ;
int visible_count=0x0 ;
@@ -2316,7 +2302,7 @@ static gboolean xfce_taskbar_group_button_release_event
activate that instance instead of showing the associated group menus,
when a left mouse click falls on the icon
*/
- if(active_child && event->button == 1)
+ if(active_child && event->button == LEFTMOUSE)
{
xfce_taskbar_button_activate (active_child, event->time);
return TRUE ;
@@ -2326,7 +2312,7 @@ static gboolean xfce_taskbar_group_button_release_event
{
panel_return_val_if_fail ((group->pinned == TRUE), FALSE);
- if(event->button == 1)
+ if(event->button == LEFTMOUSE)
{
xfce_taskbar_group_button_launch_pinned(group);
return TRUE ;
@@ -2339,38 +2325,149 @@ static gboolean xfce_taskbar_group_button_release_event
else
{
/* Split the particular menu use cases into seperate functions*/
- if(event->button == 1)
+ if(event->button == LEFTMOUSE)
{
menu = xfce_taskbar_group_button_menu_show_active (group);
}
else
{
- if(active_child)
- {
- menu = xfce_taskbar_group_button_menu_single_actions (group,active_child);
- }
- else
- {
- menu = xfce_taskbar_group_button_menu_group_actions (group);
- }
+ menu = xfce_taskbar_group_button_menu_group_actions (group);
}
}
g_signal_connect (G_OBJECT (menu), "selection-done", G_CALLBACK (xfce_taskbar_group_button_menu_destroy), group);
-
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 (group->taskbar),
- event->button,
- event->time);
-
+ xfce_panel_plugin_position_menu,
+ xfce_taskbar_get_panel_plugin(group->taskbar),
+ event->button,
+ event->time);
+
return TRUE;
}
return FALSE;
}
+static gboolean trigger_hover_menu_timeout(GtkWidget *widget, GdkEvent *event, gpointer menu_ptr);
+
+//This callback gets triggered if the mouse has left the group icon but has not entered the hover menu
+static gboolean xfce_taskbar_hover_menu_timeout(gpointer menu_ptr)
+{
+ GtkWidget *menu_widget = (GtkWidget *)menu_ptr;
+
+ if((GTK_MENU_SHELL (menu_widget))->active == FALSE)
+ {
+ GtkWidget *button_widget = gtk_menu_get_attach_widget(GTK_MENU(menu_widget));
+ g_signal_handlers_disconnect_by_func(button_widget, trigger_hover_menu_timeout, menu_ptr);
+ gtk_widget_destroy (menu_widget);
+ }
+
+ return FALSE ;
+}
+
+//Triggered when mouse focus enters the hover menu
+static gboolean hover_menu_enter(GtkWidget *widget, GdkEvent *event, gpointer menu_ptr)
+{
+ void *counter;
+ GtkWidget *menu_widget = (GtkWidget *)menu_ptr;
+
+ //We leave the menu shell in an inactive state until the user transfers mouse focus to it
+ //When mouse focus is recv'd, we disanle the pending timeout and activate the hover menu shell
+ if((GTK_MENU_SHELL (menu_widget))->active == FALSE)
+ {
+ GtkWidget *button_widget = gtk_menu_get_attach_widget(GTK_MENU(menu_widget));
+ g_signal_handlers_disconnect_by_func(button_widget, trigger_hover_menu_timeout, menu_ptr);
+ (GTK_MENU_SHELL (menu_widget))->active = TRUE;
+ }
+
+ return FALSE ;
+}
+
+//Triggered when mouse focus leaves the hover menu
+static gboolean hover_menu_leave(GtkWidget *widget, GdkEvent *event, gpointer menu_ptr)
+{
+ void *counter;
+ GtkWidget *menu_widget = (GtkWidget *)menu_ptr;
+ gtk_widget_destroy (menu_widget);
+
+ return FALSE ;
+}
+
+//When the mouse moves away from the group icon, we trigger a timeout, during which the hover menu will remain
+//if the user moves into the hover menu scope, we disable the timeout, otherwise the timeout triggers
+//and removes the hover menu
+static gboolean trigger_hover_menu_timeout(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 100ms
+ g_timeout_add(100, xfce_taskbar_hover_menu_timeout, menu_widget);
+
+ 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);
+
+ return FALSE ;
+}
+
+//Triggered when the mouse has hovered over the group icon for duration of time
+static gboolean xfce_taskbar_group_button_hover_timeout(gpointer group_ptr)
+{
+ GtkWidget *menu_widget;
+ XfceTaskBarGroup *group = (XfceTaskBarGroup *)group_ptr ;
+
+ //printf("xfce_taskbar_group_button_hover_timeout %s\n", group->window_class_name);
+
+ //Disable the hover timeout
+ DISABLE_HOVER_TIMEOUT(group);
+
+ //Create and raise the menu
+ menu_widget = xfce_taskbar_group_button_menu_show_active (group);
+ //Attach the menu widget to the button widget
+ gtk_menu_attach_to_widget (GTK_MENU (menu_widget), group->button, NULL);
+
+ g_signal_connect (G_OBJECT (menu_widget), "selection-done", G_CALLBACK (xfce_taskbar_group_button_menu_destroy), group);
+ g_signal_connect_after (G_OBJECT (group->button), "leave-notify-event", G_CALLBACK (trigger_hover_menu_timeout), menu_widget);
+
+ {
+ gint x, y ;
+ gboolean push_in=TRUE;
+ GtkMenu *menu = GTK_MENU(menu_widget);
+ GtkWindow *menu_window = GTK_WINDOW (menu->toplevel);
+
+ xfce_panel_plugin_position_menu(menu, &x, &y, &push_in, xfce_taskbar_get_panel_plugin(group->taskbar));
+
+ menu->position_func = xfce_panel_plugin_position_menu;
+ menu->position_func_data = xfce_taskbar_get_panel_plugin(group->taskbar);
+
+ gtk_widget_show (menu->toplevel);
+ gtk_window_move(menu_window, x, y);
+ gtk_widget_show (menu_widget);
+ }
+
+ return FALSE ;
+}
+
+//Triggered when the mouse exits the group button icon
+static gboolean xfce_taskbar_group_button_leave_event(GtkWidget *button, GdkEvent *event, XfceTaskBarGroup *group)
+{
+ //printf("xfce_taskbar_group_button_leave_event\n");
+ DISABLE_HOVER_TIMEOUT(group);
+ return FALSE ;
+}
+
+//Triggered when the mouse enters the group button icon
+static gboolean xfce_taskbar_group_button_enter_event(GtkWidget *button, GdkEvent *event, XfceTaskBarGroup *group)
+{
+ //printf("xfce_taskbar_group_button_enter_event\n");
+ if(xfce_taskbar_group_visible_count(group, wnck_screen_get_active_workspace (group->taskbar->screen)) > 0)
+ {
+ group->popup_timeout = g_timeout_add(250, xfce_taskbar_group_button_hover_timeout, group);
+ }
+
+ return TRUE ;
+}
+
static int xfce_taskbar_group_visible_count(XfceTaskBarGroup *group, WnckWorkspace *active_ws)
{
GSList *wi ;
@@ -2494,6 +2591,12 @@ static XfceTaskBarGroup * xfce_taskbar_group_button_new (const char *group_name,
group->pinned = FALSE;
group->command = NULL ;
+ //The timeout id, used when tracking a mouse hovering over the button
+ group->popup_timeout = 0 ;
+ //Signals ids for quickly enabling and disabling mouse hover events
+ group->enter_signal = 0 ;
+ group->leave_signal = 0 ;
+
group->button = xfce_arrow_button_new (GTK_ARROW_NONE);
gtk_widget_set_parent (group->button, GTK_WIDGET (taskbar));
gtk_widget_set_tooltip_text (group->button, group_name);
@@ -2502,11 +2605,10 @@ static XfceTaskBarGroup * xfce_taskbar_group_button_new (const char *group_name,
gtk_container_add( GTK_CONTAINER(group->align), group->icon);
gtk_container_add (GTK_CONTAINER (group->button), group->align);
- //gtk_button_set_image((GtkButton *)group->button, group->icon);
-
- /* note that the same signals should be in the proxy menu item too */
g_signal_connect (G_OBJECT (group->button), "button-release-event", G_CALLBACK (xfce_taskbar_group_button_release_event), group);
-
+ ENABLE_ENTER_SIGNAL(group);
+ ENABLE_EXIT_SIGNAL(group);
+
/* insert */
taskbar->wgroups = g_list_append(taskbar->wgroups, group);
@@ -2547,8 +2649,6 @@ static void xfce_taskbar_set_include_all_workspaces (XfceTaskBar *taskbar, gbool
}
-
-
static void xfce_taskbar_set_include_all_monitors (XfceTaskBar *taskbar, gboolean all_monitors)
{
panel_return_if_fail (XFCE_IS_taskbar (taskbar));
More information about the Xfce4-commits
mailing list