diff --git a/src/eggtrayicon.c b/src/eggtrayicon.c index 8c6161866..6d564b0a2 100644 --- a/src/eggtrayicon.c +++ b/src/eggtrayicon.c @@ -1,4 +1,3 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* eggtrayicon.c * Copyright (C) 2002 Anders Carlsson * @@ -18,25 +17,30 @@ * Boston, MA 02111-1307, USA. */ -//#include #include +#include #include #include "eggtrayicon.h" +#include +#if defined (GDK_WINDOWING_X11) #include #include +#elif defined (GDK_WINDOWING_WIN32) +#include +#endif -/*#ifndef EGG_COMPILATION +#ifndef EGG_COMPILATION #ifndef _ -#define _(x) dgettext ('gajim', x) +#define _(x) dgettext (GETTEXT_PACKAGE, x) #define N_(x) x #endif #else #define _(x) x #define N_(x) x #endif -*/ + #define SYSTEM_TRAY_REQUEST_DOCK 0 #define SYSTEM_TRAY_BEGIN_MESSAGE 1 #define SYSTEM_TRAY_CANCEL_MESSAGE 2 @@ -48,7 +52,7 @@ enum { PROP_0, PROP_ORIENTATION }; - + static GtkPlugClass *parent_class = NULL; static void egg_tray_icon_init (EggTrayIcon *icon); @@ -59,10 +63,16 @@ static void egg_tray_icon_get_property (GObject *object, GValue *value, GParamSpec *pspec); +static void egg_tray_icon_add (GtkContainer *container, GtkWidget *widget); + static void egg_tray_icon_realize (GtkWidget *widget); static void egg_tray_icon_unrealize (GtkWidget *widget); -static void egg_tray_icon_update_manager_window (EggTrayIcon *icon); +#ifdef GDK_WINDOWING_X11 +static void egg_tray_icon_update_manager_window (EggTrayIcon *icon, + gboolean dock_if_realized); +static void egg_tray_icon_manager_window_destroyed (EggTrayIcon *icon); +#endif GType egg_tray_icon_get_type (void) @@ -95,7 +105,7 @@ egg_tray_icon_init (EggTrayIcon *icon) { icon->stamp = 1; icon->orientation = GTK_ORIENTATION_HORIZONTAL; - + gtk_widget_add_events (GTK_WIDGET (icon), GDK_PROPERTY_CHANGE_MASK); } @@ -104,6 +114,7 @@ egg_tray_icon_class_init (EggTrayIconClass *klass) { GObjectClass *gobject_class = (GObjectClass *)klass; GtkWidgetClass *widget_class = (GtkWidgetClass *)klass; + GtkContainerClass *container_class = (GtkContainerClass *)klass; parent_class = g_type_class_peek_parent (klass); @@ -112,16 +123,24 @@ egg_tray_icon_class_init (EggTrayIconClass *klass) widget_class->realize = egg_tray_icon_realize; widget_class->unrealize = egg_tray_icon_unrealize; + container_class->add = egg_tray_icon_add; + g_object_class_install_property (gobject_class, PROP_ORIENTATION, g_param_spec_enum ("orientation", - "Orientation", - "The orientation of the tray.", -// _("Orientation"), -// _("The orientation of the tray."), + _("Orientation"), + _("The orientation of the tray."), GTK_TYPE_ORIENTATION, GTK_ORIENTATION_HORIZONTAL, G_PARAM_READABLE)); + +#if defined (GDK_WINDOWING_X11) + /* Nothing */ +#elif defined (GDK_WINDOWING_WIN32) + g_warning ("Port eggtrayicon to Win32"); +#else + g_warning ("Port eggtrayicon to this GTK+ backend"); +#endif } static void @@ -143,6 +162,8 @@ egg_tray_icon_get_property (GObject *object, } } +#ifdef GDK_WINDOWING_X11 + static void egg_tray_icon_get_orientation_property (EggTrayIcon *icon) { @@ -158,7 +179,7 @@ egg_tray_icon_get_orientation_property (EggTrayIcon *icon) int error, result; g_assert (icon->manager_window != None); - + xdisplay = GDK_DISPLAY_XDISPLAY (gtk_widget_get_display (GTK_WIDGET (icon))); gdk_error_trap_push (); @@ -205,7 +226,7 @@ egg_tray_icon_manager_filter (GdkXEvent *xevent, GdkEvent *event, gpointer user_ xev->xclient.message_type == icon->manager_atom && xev->xclient.data.l[1] == icon->selection_atom) { - egg_tray_icon_update_manager_window (icon); + egg_tray_icon_update_manager_window (icon, TRUE); } else if (xev->xany.window == icon->manager_window) { @@ -216,16 +237,18 @@ egg_tray_icon_manager_filter (GdkXEvent *xevent, GdkEvent *event, gpointer user_ } if (xev->xany.type == DestroyNotify) { - egg_tray_icon_update_manager_window (icon); + egg_tray_icon_manager_window_destroyed (icon); } } - return GDK_FILTER_CONTINUE; } +#endif + static void egg_tray_icon_unrealize (GtkWidget *widget) { +#ifdef GDK_WINDOWING_X11 EggTrayIcon *icon = EGG_TRAY_ICON (widget); GdkWindow *root_window; @@ -245,8 +268,11 @@ egg_tray_icon_unrealize (GtkWidget *widget) if (GTK_WIDGET_CLASS (parent_class)->unrealize) (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget); +#endif } +#ifdef GDK_WINDOWING_X11 + static void egg_tray_icon_send_manager_message (EggTrayIcon *icon, long message, @@ -257,7 +283,7 @@ egg_tray_icon_send_manager_message (EggTrayIcon *icon, { XClientMessageEvent ev; Display *display; - + ev.type = ClientMessage; ev.window = window; ev.message_type = icon->system_tray_opcode_atom; @@ -269,7 +295,7 @@ egg_tray_icon_send_manager_message (EggTrayIcon *icon, ev.data.l[4] = data3; display = GDK_DISPLAY_XDISPLAY (gtk_widget_get_display (GTK_WIDGET (icon))); - + gdk_error_trap_push (); XSendEvent (display, icon->manager_window, False, NoEventMask, (XEvent *)&ev); @@ -288,24 +314,18 @@ egg_tray_icon_send_dock_request (EggTrayIcon *icon) } static void -egg_tray_icon_update_manager_window (EggTrayIcon *icon) +egg_tray_icon_update_manager_window (EggTrayIcon *icon, + gboolean dock_if_realized) { Display *xdisplay; - - xdisplay = GDK_DISPLAY_XDISPLAY (gtk_widget_get_display (GTK_WIDGET (icon))); - - if (icon->manager_window != None) - { - GdkWindow *gdkwin; - gdkwin = gdk_window_lookup_for_display (gtk_widget_get_display (GTK_WIDGET (icon)), - icon->manager_window); - - gdk_window_remove_filter (gdkwin, egg_tray_icon_manager_filter, icon); - } - + if (icon->manager_window != None) + return; + + xdisplay = GDK_DISPLAY_XDISPLAY (gtk_widget_get_display (GTK_WIDGET (icon))); + XGrabServer (xdisplay); - + icon->manager_window = XGetSelectionOwner (xdisplay, icon->selection_atom); @@ -315,26 +335,76 @@ egg_tray_icon_update_manager_window (EggTrayIcon *icon) XUngrabServer (xdisplay); XFlush (xdisplay); - + if (icon->manager_window != None) { GdkWindow *gdkwin; gdkwin = gdk_window_lookup_for_display (gtk_widget_get_display (GTK_WIDGET (icon)), icon->manager_window); - + gdk_window_add_filter (gdkwin, egg_tray_icon_manager_filter, icon); - /* Send a request that we'd like to dock */ - egg_tray_icon_send_dock_request (icon); + if (dock_if_realized && GTK_WIDGET_REALIZED (icon)) + egg_tray_icon_send_dock_request (icon); egg_tray_icon_get_orientation_property (icon); } } +static gboolean +transparent_expose_event (GtkWidget *widget, GdkEventExpose *event, gpointer user_data) +{ + gdk_window_clear_area (widget->window, event->area.x, event->area.y, + event->area.width, event->area.height); + return FALSE; +} + +static void +make_transparent_again (GtkWidget *widget, GtkStyle *previous_style, + gpointer user_data) +{ + gdk_window_set_back_pixmap (widget->window, NULL, TRUE); +} + +static void +make_transparent (GtkWidget *widget, gpointer user_data) +{ + if (GTK_WIDGET_NO_WINDOW (widget) || GTK_WIDGET_APP_PAINTABLE (widget)) + return; + + gtk_widget_set_app_paintable (widget, TRUE); + gtk_widget_set_double_buffered (widget, FALSE); + gdk_window_set_back_pixmap (widget->window, NULL, TRUE); + g_signal_connect (widget, "expose_event", + G_CALLBACK (transparent_expose_event), NULL); + g_signal_connect_after (widget, "style_set", + G_CALLBACK (make_transparent_again), NULL); +} + +static void +egg_tray_icon_manager_window_destroyed (EggTrayIcon *icon) +{ + GdkWindow *gdkwin; + + g_return_if_fail (icon->manager_window != None); + + gdkwin = gdk_window_lookup_for_display (gtk_widget_get_display (GTK_WIDGET (icon)), + icon->manager_window); + + gdk_window_remove_filter (gdkwin, egg_tray_icon_manager_filter, icon); + + icon->manager_window = None; + + egg_tray_icon_update_manager_window (icon, TRUE); +} + +#endif + static void egg_tray_icon_realize (GtkWidget *widget) { +#ifdef GDK_WINDOWING_X11 EggTrayIcon *icon = EGG_TRAY_ICON (widget); GdkScreen *screen; GdkDisplay *display; @@ -345,6 +415,8 @@ egg_tray_icon_realize (GtkWidget *widget) if (GTK_WIDGET_CLASS (parent_class)->realize) GTK_WIDGET_CLASS (parent_class)->realize (widget); + make_transparent (widget, NULL); + screen = gtk_widget_get_screen (widget); display = gdk_screen_get_display (screen); xdisplay = gdk_x11_display_get_xdisplay (display); @@ -355,9 +427,9 @@ egg_tray_icon_realize (GtkWidget *widget) gdk_screen_get_number (screen)); icon->selection_atom = XInternAtom (xdisplay, buffer, False); - + icon->manager_atom = XInternAtom (xdisplay, "MANAGER", False); - + icon->system_tray_opcode_atom = XInternAtom (xdisplay, "_NET_SYSTEM_TRAY_OPCODE", False); @@ -366,13 +438,23 @@ egg_tray_icon_realize (GtkWidget *widget) "_NET_SYSTEM_TRAY_ORIENTATION", False); - egg_tray_icon_update_manager_window (icon); + egg_tray_icon_update_manager_window (icon, FALSE); + egg_tray_icon_send_dock_request (icon); root_window = gdk_screen_get_root_window (screen); - + /* Add a root window filter so that we get changes on MANAGER */ gdk_window_add_filter (root_window, egg_tray_icon_manager_filter, icon); +#endif +} + +static void +egg_tray_icon_add (GtkContainer *container, GtkWidget *widget) +{ + g_signal_connect (widget, "realize", + G_CALLBACK (make_transparent), NULL); + GTK_CONTAINER_CLASS (parent_class)->add (container, widget); } EggTrayIcon * @@ -396,19 +478,22 @@ egg_tray_icon_send_message (EggTrayIcon *icon, gint len) { guint stamp; - + g_return_val_if_fail (EGG_IS_TRAY_ICON (icon), 0); g_return_val_if_fail (timeout >= 0, 0); g_return_val_if_fail (message != NULL, 0); - + +#ifdef GDK_WINDOWING_X11 if (icon->manager_window == None) return 0; +#endif if (len < 0) len = strlen (message); stamp = icon->stamp++; - + +#ifdef GDK_WINDOWING_X11 /* Get ready to send the message */ egg_tray_icon_send_manager_message (icon, SYSTEM_TRAY_BEGIN_MESSAGE, (Window)gtk_plug_get_id (GTK_PLUG (icon)), @@ -422,7 +507,7 @@ egg_tray_icon_send_message (EggTrayIcon *icon, Display *xdisplay; xdisplay = GDK_DISPLAY_XDISPLAY (gtk_widget_get_display (GTK_WIDGET (icon))); - + ev.type = ClientMessage; ev.window = (Window)gtk_plug_get_id (GTK_PLUG (icon)); ev.format = 8; @@ -445,6 +530,7 @@ egg_tray_icon_send_message (EggTrayIcon *icon, XSync (xdisplay, False); } gdk_error_trap_pop (); +#endif return stamp; } @@ -455,10 +541,11 @@ egg_tray_icon_cancel_message (EggTrayIcon *icon, { g_return_if_fail (EGG_IS_TRAY_ICON (icon)); g_return_if_fail (id > 0); - +#ifdef GDK_WINDOWING_X11 egg_tray_icon_send_manager_message (icon, SYSTEM_TRAY_CANCEL_MESSAGE, (Window)gtk_plug_get_id (GTK_PLUG (icon)), id, 0, 0); +#endif } GtkOrientation diff --git a/src/eggtrayicon.h b/src/eggtrayicon.h index 007f4c18e..557fdb20c 100644 --- a/src/eggtrayicon.h +++ b/src/eggtrayicon.h @@ -22,7 +22,9 @@ #define __EGG_TRAY_ICON_H__ #include +#ifdef GDK_WINDOWING_X11 #include +#endif G_BEGIN_DECLS @@ -32,7 +34,7 @@ G_BEGIN_DECLS #define EGG_IS_TRAY_ICON(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EGG_TYPE_TRAY_ICON)) #define EGG_IS_TRAY_ICON_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EGG_TYPE_TRAY_ICON)) #define EGG_TRAY_ICON_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EGG_TYPE_TRAY_ICON, EggTrayIconClass)) - + typedef struct _EggTrayIcon EggTrayIcon; typedef struct _EggTrayIconClass EggTrayIconClass; @@ -41,13 +43,14 @@ struct _EggTrayIcon GtkPlug parent_instance; guint stamp; - + +#ifdef GDK_WINDOWING_X11 Atom selection_atom; Atom manager_atom; Atom system_tray_opcode_atom; Atom orientation_atom; Window manager_window; - +#endif GtkOrientation orientation; }; @@ -71,7 +74,7 @@ void egg_tray_icon_cancel_message (EggTrayIcon *icon, guint id); GtkOrientation egg_tray_icon_get_orientation (EggTrayIcon *icon); - + G_END_DECLS #endif /* __EGG_TRAY_ICON_H__ */