diff --git a/ChangeLog b/ChangeLog index a38322636c..81b1aa64d5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2007-01-27 Matthias Clasen + + * gtk/gtkstatusicon.c: + * gtk/gtktrayicon-x11.c: Fix GtkStatusIcon to not + take up space on the panel if it is invisible. (340110, Christian + Persch) + + * tests/teststatusicon.c: + * tests/Makefile.am: Updates + 2007-01-27 Matthias Clasen * gtk/gtkfilesel.h: diff --git a/gtk/gtkstatusicon.c b/gtk/gtkstatusicon.c index 44d3798e59..418db4a435 100755 --- a/gtk/gtkstatusicon.c +++ b/gtk/gtkstatusicon.c @@ -130,6 +130,9 @@ struct _GtkStatusIconPrivate guint visible : 1; }; +static GObject* gtk_status_icon_constructor (GType type, + guint n_construct_properties, + GObjectConstructParam *construct_params); static void gtk_status_icon_finalize (GObject *object); static void gtk_status_icon_set_property (GObject *object, guint prop_id, @@ -162,6 +165,7 @@ gtk_status_icon_class_init (GtkStatusIconClass *class) { GObjectClass *gobject_class = (GObjectClass *) class; + gobject_class->constructor = gtk_status_icon_constructor; gobject_class->finalize = gtk_status_icon_finalize; gobject_class->set_property = gtk_status_icon_set_property; gobject_class->get_property = gtk_status_icon_get_property; @@ -478,13 +482,11 @@ gtk_status_icon_init (GtkStatusIcon *status_icon) G_CALLBACK (gtk_status_icon_screen_changed), status_icon); priv->image = gtk_image_new (); gtk_container_add (GTK_CONTAINER (priv->tray_icon), priv->image); + gtk_widget_show (priv->image); g_signal_connect_swapped (priv->image, "size-allocate", G_CALLBACK (gtk_status_icon_size_allocate), status_icon); - gtk_widget_show (priv->image); - gtk_widget_show (priv->tray_icon); - status_icon->priv->tooltips = gtk_tooltips_new (); g_object_ref_sink (priv->tooltips); #endif @@ -541,6 +543,30 @@ gtk_status_icon_init (GtkStatusIcon *status_icon) #endif } +static GObject* +gtk_status_icon_constructor (GType type, + guint n_construct_properties, + GObjectConstructParam *construct_params) +{ + GObject *object; + GtkStatusIcon *status_icon; + GtkStatusIconPrivate *priv; + + object = G_OBJECT_CLASS (gtk_status_icon_parent_class)->constructor (type, + n_construct_properties, + construct_params); + +#ifdef GDK_WINDOWING_X11 + status_icon = GTK_STATUS_ICON (object); + priv = status_icon->priv; + + if (priv->visible) + gtk_widget_show (priv->tray_icon); +#endif + + return object; +} + static void gtk_status_icon_finalize (GObject *object) { @@ -1651,8 +1677,10 @@ gtk_status_icon_set_visible (GtkStatusIcon *status_icon, #ifdef GDK_WINDOWING_X11 if (visible) gtk_widget_show (priv->tray_icon); - else + else if (GTK_WIDGET_REALIZED (priv->tray_icon)) { gtk_widget_hide (priv->tray_icon); + gtk_widget_unrealize (priv->tray_icon); + } #endif #ifdef GDK_WINDOWING_WIN32 if (priv->nid.hWnd != NULL) diff --git a/gtk/gtktrayicon-x11.c b/gtk/gtktrayicon-x11.c index 16d8bc35c7..826e319638 100755 --- a/gtk/gtktrayicon-x11.c +++ b/gtk/gtktrayicon-x11.c @@ -72,8 +72,7 @@ static gboolean gtk_tray_icon_delete (GtkWidget *widget, static gboolean gtk_tray_icon_expose (GtkWidget *widget, GdkEventExpose *event); -static void gtk_tray_icon_update_manager_window (GtkTrayIcon *icon, - gboolean dock_if_realized); +static void gtk_tray_icon_update_manager_window (GtkTrayIcon *icon); static void gtk_tray_icon_manager_window_destroyed (GtkTrayIcon *icon); G_DEFINE_TYPE (GtkTrayIcon, gtk_tray_icon, GTK_TYPE_PLUG) @@ -213,19 +212,31 @@ gtk_tray_icon_manager_filter (GdkXEvent *xevent, xev->xclient.message_type == icon->priv->manager_atom && xev->xclient.data.l[1] == icon->priv->selection_atom) { - gtk_tray_icon_update_manager_window (icon, TRUE); + GTK_NOTE (PLUGSOCKET, + g_print ("GtkStatusIcon %p: tray manager appeared\n", icon)); + + gtk_tray_icon_update_manager_window (icon); } else if (xev->xany.window == icon->priv->manager_window) { if (xev->xany.type == PropertyNotify && xev->xproperty.atom == icon->priv->orientation_atom) { + GTK_NOTE (PLUGSOCKET, + g_print ("GtkStatusIcon %p: got PropertyNotify on manager window for orientation atom\n", icon)); + gtk_tray_icon_get_orientation_property (icon); } - if (xev->xany.type == DestroyNotify) + else if (xev->xany.type == DestroyNotify) { + GTK_NOTE (PLUGSOCKET, + g_print ("GtkStatusIcon %p: got DestroyNotify for manager window\n", icon)); + gtk_tray_icon_manager_window_destroyed (icon); } + else + GTK_NOTE (PLUGSOCKET, + g_print ("GtkStatusIcon %p: got other message on manager window\n", icon)); } return GDK_FILTER_CONTINUE; @@ -237,6 +248,9 @@ gtk_tray_icon_unrealize (GtkWidget *widget) GtkTrayIcon *icon = GTK_TRAY_ICON (widget); GdkWindow *root_window; + GTK_NOTE (PLUGSOCKET, + g_print ("GtkStatusIcon %p: unrealizing\n", icon)); + if (icon->priv->manager_window != None) { GdkWindow *gdkwin; @@ -245,14 +259,15 @@ gtk_tray_icon_unrealize (GtkWidget *widget) icon->priv->manager_window); gdk_window_remove_filter (gdkwin, gtk_tray_icon_manager_filter, icon); + + icon->priv->manager_window = None; } root_window = gdk_screen_get_root_window (gtk_widget_get_screen (widget)); gdk_window_remove_filter (root_window, gtk_tray_icon_manager_filter, icon); - if (GTK_WIDGET_CLASS (gtk_tray_icon_parent_class)->unrealize) - (* GTK_WIDGET_CLASS (gtk_tray_icon_parent_class)->unrealize) (widget); + GTK_WIDGET_CLASS (gtk_tray_icon_parent_class)->unrealize (widget); } static void @@ -289,6 +304,10 @@ gtk_tray_icon_send_manager_message (GtkTrayIcon *icon, static void gtk_tray_icon_send_dock_request (GtkTrayIcon *icon) { + GTK_NOTE (PLUGSOCKET, + g_print ("GtkStatusIcon %p: sending dock request to manager window %x\n", + icon, icon->priv->manager_window)); + gtk_tray_icon_send_manager_message (icon, SYSTEM_TRAY_REQUEST_DOCK, icon->priv->manager_window, @@ -297,14 +316,22 @@ gtk_tray_icon_send_dock_request (GtkTrayIcon *icon) } static void -gtk_tray_icon_update_manager_window (GtkTrayIcon *icon, - gboolean dock_if_realized) +gtk_tray_icon_update_manager_window (GtkTrayIcon *icon) { Display *xdisplay; - + + g_return_if_fail (GTK_WIDGET_REALIZED (icon)); + + GTK_NOTE (PLUGSOCKET, + g_print ("GtkStatusIcon %p: updating tray icon manager window, current manager window: %x\n", + icon, icon->priv->manager_window)); + if (icon->priv->manager_window != None) return; + GTK_NOTE (PLUGSOCKET, + g_print ("GtkStatusIcon %p: trying to find manager window\n", icon)); + xdisplay = GDK_DISPLAY_XDISPLAY (gtk_widget_get_display (GTK_WIDGET (icon))); XGrabServer (xdisplay); @@ -323,33 +350,40 @@ gtk_tray_icon_update_manager_window (GtkTrayIcon *icon, { GdkWindow *gdkwin; + GTK_NOTE (PLUGSOCKET, + g_print ("GtkStatusIcon %p: is being managed by window %x\n", + icon, icon->priv->manager_window)); + gdkwin = gdk_window_lookup_for_display (gtk_widget_get_display (GTK_WIDGET (icon)), icon->priv->manager_window); gdk_window_add_filter (gdkwin, gtk_tray_icon_manager_filter, icon); - if (dock_if_realized && GTK_WIDGET_REALIZED (icon)) - gtk_tray_icon_send_dock_request (icon); + gtk_tray_icon_send_dock_request (icon); gtk_tray_icon_get_orientation_property (icon); } + else + GTK_NOTE (PLUGSOCKET, + g_print ("GtkStatusIcon %p: no tray manager found\n", icon)); } static void gtk_tray_icon_manager_window_destroyed (GtkTrayIcon *icon) { + GtkWidget *widget = GTK_WIDGET (icon); GdkWindow *gdkwin; - + + g_return_if_fail (GTK_WIDGET_REALIZED (icon)); g_return_if_fail (icon->priv->manager_window != None); - gdkwin = gdk_window_lookup_for_display (gtk_widget_get_display (GTK_WIDGET (icon)), - icon->priv->manager_window); - - gdk_window_remove_filter (gdkwin, gtk_tray_icon_manager_filter, icon); + GTK_NOTE (PLUGSOCKET, + g_print ("GtkStatusIcon %p: tray manager window destroyed\n", icon)); - icon->priv->manager_window = None; + gtk_widget_hide (widget); + gtk_widget_unrealize (widget); - gtk_tray_icon_update_manager_window (icon, TRUE); + gtk_widget_show (widget); } static gboolean @@ -359,17 +393,14 @@ gtk_tray_icon_delete (GtkWidget *widget, GtkTrayIcon *icon = GTK_TRAY_ICON (widget); GdkWindow *gdkwin; - if (icon->priv->manager_window != None) - { - gdkwin = gdk_window_lookup_for_display (gtk_widget_get_display (GTK_WIDGET (icon)), - icon->priv->manager_window); - - gdk_window_remove_filter (gdkwin, gtk_tray_icon_manager_filter, icon); - - icon->priv->manager_window = None; - } + GTK_NOTE (PLUGSOCKET, + g_print ("GtkStatusIcon %p: delete notify, tray manager window %x\n", + icon, icon->priv->manager_window)); - gtk_tray_icon_update_manager_window (icon, TRUE); + gtk_widget_hide (widget); + gtk_widget_unrealize (widget); + + gtk_widget_show (widget); return TRUE; } @@ -384,8 +415,14 @@ gtk_tray_icon_realize (GtkWidget *widget) char buffer[256]; GdkWindow *root_window; - if (GTK_WIDGET_CLASS (gtk_tray_icon_parent_class)->realize) - GTK_WIDGET_CLASS (gtk_tray_icon_parent_class)->realize (widget); + GTK_WIDGET_CLASS (gtk_tray_icon_parent_class)->realize (widget); + + GTK_NOTE (PLUGSOCKET, + g_print ("GtkStatusIcon %p: realized, window: %x, socket window: %x\n", + widget, + GDK_WINDOW_XWINDOW (widget->window), + GTK_PLUG (icon)->socket_window ? + GDK_WINDOW_XWINDOW (GTK_PLUG (icon)->socket_window) : 0)); screen = gtk_widget_get_screen (widget); display = gdk_screen_get_display (screen); @@ -408,8 +445,7 @@ gtk_tray_icon_realize (GtkWidget *widget) "_NET_SYSTEM_TRAY_ORIENTATION", False); - gtk_tray_icon_update_manager_window (icon, FALSE); - gtk_tray_icon_send_dock_request (icon); + gtk_tray_icon_update_manager_window (icon); root_window = gdk_screen_get_root_window (screen); diff --git a/tests/Makefile.am b/tests/Makefile.am index d9458dfd95..6972165a03 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -247,6 +247,7 @@ testspinbutton_SOURCES = \ testspinbutton.c teststatusicon_SOURCES = \ + prop-editor.c \ teststatusicon.c testmerge_SOURCES = \ diff --git a/tests/teststatusicon.c b/tests/teststatusicon.c index 1256152e97..9fe9c99c5d 100755 --- a/tests/teststatusicon.c +++ b/tests/teststatusicon.c @@ -22,6 +22,7 @@ */ #include +#include "prop-editor.h" typedef enum { @@ -56,6 +57,13 @@ orientation_changed_cb (GtkStatusIcon *icon) g_print ("status icon %p orientation changed to %d\n", icon, orientation); } +static void +screen_changed_cb (GtkStatusIcon *icon) +{ + g_print ("status icon %p screen changed to %p\n", icon, + gtk_status_icon_get_screen (icon)); +} + static void update_icons (void) { @@ -215,6 +223,20 @@ check_activated (GtkCheckMenuItem *item) gtk_status_icon_set_screen (GTK_STATUS_ICON (icons->data), screen); } +static void +do_properties (GtkMenuItem *item, + GtkStatusIcon *icon) +{ + static GtkWidget *editor = NULL; + + if (editor == NULL) { + editor = create_prop_editor (G_OBJECT (icon), GTK_TYPE_STATUS_ICON); + g_signal_connect (editor, "destroy", G_CALLBACK (gtk_widget_destroyed), &editor); + } + + gtk_window_present (GTK_WINDOW (editor)); +} + static void do_quit (GtkMenuItem *item) { @@ -255,6 +277,13 @@ popup_menu (GtkStatusIcon *icon, gtk_widget_show (menuitem); + menuitem = gtk_image_menu_item_new_from_stock (GTK_STOCK_PROPERTIES, NULL); + g_signal_connect (menuitem, "activate", G_CALLBACK (do_properties), icon); + + gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); + + gtk_widget_show (menuitem); + menuitem = gtk_menu_item_new_with_label ("Quit"); g_signal_connect (menuitem, "activate", G_CALLBACK (do_quit), NULL); @@ -263,7 +292,8 @@ popup_menu (GtkStatusIcon *icon, gtk_widget_show (menuitem); gtk_menu_popup (GTK_MENU (menu), - NULL, NULL, NULL, NULL, + NULL, NULL, + gtk_status_icon_position_menu, icon, button, activate_time); } @@ -290,6 +320,7 @@ main (int argc, char **argv) g_signal_connect (icon, "size-changed", G_CALLBACK (size_changed_cb), NULL); g_signal_connect (icon, "notify::embedded", G_CALLBACK (embedded_changed_cb), NULL); g_signal_connect (icon, "notify::orientation", G_CALLBACK (orientation_changed_cb), NULL); + g_signal_connect (icon, "notify::screen", G_CALLBACK (screen_changed_cb), NULL); g_print ("icon size %d\n", gtk_status_icon_get_size (icon)); gtk_status_icon_set_blinking (GTK_STATUS_ICON (icon), FALSE); @@ -301,6 +332,8 @@ main (int argc, char **argv) icons = g_slist_append (icons, icon); + update_icons (); + timeout = gdk_threads_add_timeout (2000, timeout_handler, icon); }