Update to recent eggtrayicon version. Should be converted to GTK+ 2.10 code.
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@48527 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
		| @@ -106,8 +106,6 @@ Anders | ||||
|  | ||||
| #include "wx/platform.h" | ||||
|  | ||||
| #include <gdk/gdkx.h> | ||||
|  | ||||
| #ifdef __WXGTK20__ | ||||
| #include <gtk/gtkversion.h> | ||||
| #if GTK_CHECK_VERSION(2, 1, 0) | ||||
| @@ -115,18 +113,48 @@ Anders | ||||
| #include <string.h> | ||||
| #include "eggtrayicon.h" | ||||
|  | ||||
| #include <gdkconfig.h> | ||||
| #if defined (GDK_WINDOWING_X11) | ||||
| #include <gdk/gdkx.h> | ||||
| #include <X11/Xatom.h> | ||||
| #elif defined (GDK_WINDOWING_WIN32) | ||||
| #include <gdk/gdkwin32.h> | ||||
| #endif | ||||
|  | ||||
|  | ||||
| #define SYSTEM_TRAY_REQUEST_DOCK    0 | ||||
| #define SYSTEM_TRAY_BEGIN_MESSAGE   1 | ||||
| #define SYSTEM_TRAY_CANCEL_MESSAGE  2 | ||||
|  | ||||
| #define SYSTEM_TRAY_ORIENTATION_HORZ 0 | ||||
| #define SYSTEM_TRAY_ORIENTATION_VERT 1 | ||||
|  | ||||
| enum { | ||||
|   PROP_0, | ||||
|   PROP_ORIENTATION | ||||
| }; | ||||
|           | ||||
| static GtkPlugClass *parent_class = NULL; | ||||
|  | ||||
| static void egg_tray_icon_init (EggTrayIcon *icon); | ||||
| static void egg_tray_icon_class_init (EggTrayIconClass *klass); | ||||
|  | ||||
| static void egg_tray_icon_get_property (GObject    *object, | ||||
| 					guint       prop_id, | ||||
| 					GValue     *value, | ||||
| 					GParamSpec *pspec); | ||||
|  | ||||
| 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); | ||||
| static void egg_tray_icon_add (GtkContainer *container, | ||||
| 			       GtkWidget    *widget); | ||||
|  | ||||
| #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) | ||||
| @@ -135,7 +163,7 @@ egg_tray_icon_get_type (void) | ||||
|  | ||||
|   if (our_type == 0) | ||||
|     { | ||||
|       const GTypeInfo our_info = | ||||
|       static const GTypeInfo our_info = | ||||
|       { | ||||
| 	sizeof (EggTrayIconClass), | ||||
| 	(GBaseInitFunc) NULL, | ||||
| @@ -148,8 +176,7 @@ egg_tray_icon_get_type (void) | ||||
| 	(GInstanceInitFunc) egg_tray_icon_init | ||||
|       }; | ||||
|  | ||||
|       our_type = g_type_register_static (GTK_TYPE_PLUG, "EggTrayIcon", | ||||
|                                           &our_info, (GTypeFlags)0); | ||||
|       our_type = g_type_register_static (GTK_TYPE_PLUG, "EggTrayIcon", &our_info, 0); | ||||
|     } | ||||
|  | ||||
|   return our_type; | ||||
| @@ -159,6 +186,7 @@ static void | ||||
| 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); | ||||
| } | ||||
| @@ -166,11 +194,100 @@ egg_tray_icon_init (EggTrayIcon *icon) | ||||
| static void | ||||
| 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); | ||||
|  | ||||
|   gobject_class->get_property = egg_tray_icon_get_property; | ||||
|  | ||||
|   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.", | ||||
| 						      GTK_TYPE_ORIENTATION, | ||||
| 						      GTK_ORIENTATION_HORIZONTAL, | ||||
| 						      G_PARAM_READABLE)); | ||||
| } | ||||
|  | ||||
| static void | ||||
| egg_tray_icon_get_property (GObject    *object, | ||||
| 			    guint       prop_id, | ||||
| 			    GValue     *value, | ||||
| 			    GParamSpec *pspec) | ||||
| { | ||||
|   EggTrayIcon *icon = EGG_TRAY_ICON (object); | ||||
|  | ||||
|   switch (prop_id) | ||||
|     { | ||||
|     case PROP_ORIENTATION: | ||||
|       g_value_set_enum (value, icon->orientation); | ||||
|       break; | ||||
|     default: | ||||
|       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); | ||||
|       break; | ||||
|     } | ||||
| } | ||||
|  | ||||
| #ifdef GDK_WINDOWING_X11 | ||||
|  | ||||
| static void | ||||
| egg_tray_icon_get_orientation_property (EggTrayIcon *icon) | ||||
| { | ||||
|   Display *xdisplay; | ||||
|   Atom type; | ||||
|   int format; | ||||
|   union { | ||||
| 	gulong *prop; | ||||
| 	guchar *prop_ch; | ||||
|   } prop = { NULL }; | ||||
|   gulong nitems; | ||||
|   gulong bytes_after; | ||||
|   int error, result; | ||||
|  | ||||
|   g_assert (icon->manager_window != None); | ||||
|    | ||||
|   xdisplay = GDK_DISPLAY_XDISPLAY (gtk_widget_get_display (GTK_WIDGET (icon))); | ||||
|  | ||||
|   gdk_error_trap_push (); | ||||
|   type = None; | ||||
|   result = XGetWindowProperty (xdisplay, | ||||
| 			       icon->manager_window, | ||||
| 			       icon->orientation_atom, | ||||
| 			       0, G_MAXLONG, FALSE, | ||||
| 			       XA_CARDINAL, | ||||
| 			       &type, &format, &nitems, | ||||
| 			       &bytes_after, &(prop.prop_ch)); | ||||
|   error = gdk_error_trap_pop (); | ||||
|  | ||||
|   if (error || result != Success) | ||||
|     return; | ||||
|  | ||||
|   if (type == XA_CARDINAL) | ||||
|     { | ||||
|       GtkOrientation orientation; | ||||
|  | ||||
|       orientation = (prop.prop [0] == SYSTEM_TRAY_ORIENTATION_HORZ) ? | ||||
| 					GTK_ORIENTATION_HORIZONTAL : | ||||
| 					GTK_ORIENTATION_VERTICAL; | ||||
|  | ||||
|       if (icon->orientation != orientation) | ||||
| 	{ | ||||
| 	  icon->orientation = orientation; | ||||
|  | ||||
| 	  g_object_notify (G_OBJECT (icon), "orientation"); | ||||
| 	} | ||||
|     } | ||||
|  | ||||
|   if (prop.prop) | ||||
|     XFree (prop.prop); | ||||
| } | ||||
|  | ||||
| static GdkFilterReturn | ||||
| @@ -183,22 +300,29 @@ 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) | ||||
|     { | ||||
|       if (xev->xany.type == PropertyNotify && | ||||
| 	  xev->xproperty.atom == icon->orientation_atom) | ||||
| 	{ | ||||
| 	  egg_tray_icon_get_orientation_property (icon); | ||||
| 	} | ||||
|       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; | ||||
|  | ||||
| @@ -218,8 +342,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, | ||||
| @@ -261,21 +388,15 @@ 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; | ||||
|     return; | ||||
|  | ||||
|       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); | ||||
|     } | ||||
|   xdisplay = GDK_DISPLAY_XDISPLAY (gtk_widget_get_display (GTK_WIDGET (icon))); | ||||
|    | ||||
|   XGrabServer (xdisplay); | ||||
|    | ||||
| @@ -284,7 +405,7 @@ egg_tray_icon_update_manager_window (EggTrayIcon *icon) | ||||
|  | ||||
|   if (icon->manager_window != None) | ||||
|     XSelectInput (xdisplay, | ||||
| 		  icon->manager_window, StructureNotifyMask); | ||||
| 		  icon->manager_window, StructureNotifyMask|PropertyChangeMask); | ||||
|  | ||||
|   XUngrabServer (xdisplay); | ||||
|   XFlush (xdisplay); | ||||
| @@ -298,58 +419,116 @@ egg_tray_icon_update_manager_window (EggTrayIcon *icon) | ||||
|        | ||||
|       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); | ||||
|     } | ||||
| } | ||||
|  | ||||
| EggTrayIcon * | ||||
| egg_tray_icon_new_for_xscreen (Screen *xscreen, const char *name) | ||||
| static void | ||||
| egg_tray_icon_manager_window_destroyed (EggTrayIcon *icon) | ||||
| { | ||||
|   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 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_realize (GtkWidget *widget) | ||||
| { | ||||
| #ifdef GDK_WINDOWING_X11 | ||||
|   EggTrayIcon *icon = EGG_TRAY_ICON (widget); | ||||
|   GdkScreen *screen; | ||||
|   GdkDisplay *display; | ||||
|   Display *xdisplay; | ||||
|   char buffer[256]; | ||||
|   GdkWindow *root_window; | ||||
|   GdkDisplay *display; | ||||
|   GdkScreen *screen; | ||||
|    | ||||
|   g_return_val_if_fail (xscreen != NULL, NULL); | ||||
|    | ||||
|   icon = g_object_new (EGG_TYPE_TRAY_ICON, NULL); | ||||
|   gtk_window_set_title (GTK_WINDOW (icon), name); | ||||
|  | ||||
|   display = gdk_x11_lookup_xdisplay (DisplayOfScreen (xscreen)); | ||||
|   screen = gdk_display_get_screen (display, XScreenNumberOfScreen (xscreen)); | ||||
|    | ||||
|   gtk_plug_construct_for_display (GTK_PLUG (icon), | ||||
| 				  display, 0); | ||||
|   if (GTK_WIDGET_CLASS (parent_class)->realize) | ||||
|     GTK_WIDGET_CLASS (parent_class)->realize (widget); | ||||
|  | ||||
|   gtk_window_set_screen (GTK_WINDOW (icon), screen);	  | ||||
|    | ||||
|   gtk_widget_realize (GTK_WIDGET (icon)); | ||||
|   make_transparent (widget, NULL); | ||||
|  | ||||
|   screen = gtk_widget_get_screen (widget); | ||||
|   display = gdk_screen_get_display (screen); | ||||
|   xdisplay = gdk_x11_display_get_xdisplay (display); | ||||
|  | ||||
|   /* Now see if there's a manager window around */ | ||||
|   g_snprintf (buffer, sizeof (buffer), | ||||
| 	      "_NET_SYSTEM_TRAY_S%d", | ||||
| 	      XScreenNumberOfScreen (xscreen)); | ||||
|    | ||||
|   icon->selection_atom = XInternAtom (DisplayOfScreen (xscreen), | ||||
| 				      buffer, False); | ||||
|    | ||||
|   icon->manager_atom = XInternAtom (DisplayOfScreen (xscreen), | ||||
| 				    "MANAGER", False); | ||||
|    | ||||
|   icon->system_tray_opcode_atom = XInternAtom (DisplayOfScreen (xscreen), | ||||
| 					       "_NET_SYSTEM_TRAY_OPCODE", False); | ||||
| 	      gdk_screen_get_number (screen)); | ||||
|  | ||||
|   egg_tray_icon_update_manager_window (icon); | ||||
|   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); | ||||
|  | ||||
|   root_window = gdk_screen_get_root_window (gtk_widget_get_screen (GTK_WIDGET (icon))); | ||||
|   icon->orientation_atom = XInternAtom (xdisplay, | ||||
| 					"_NET_SYSTEM_TRAY_ORIENTATION", | ||||
| 					False); | ||||
|  | ||||
|   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); | ||||
| 		       | ||||
|   return 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 * | ||||
| @@ -357,13 +536,13 @@ egg_tray_icon_new_for_screen (GdkScreen *screen, const char *name) | ||||
| { | ||||
|   g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL); | ||||
|  | ||||
|   return egg_tray_icon_new_for_xscreen (GDK_SCREEN_XSCREEN (screen), name); | ||||
|   return g_object_new (EGG_TYPE_TRAY_ICON, "screen", screen, "title", name, NULL); | ||||
| } | ||||
|  | ||||
| EggTrayIcon* | ||||
| egg_tray_icon_new (const gchar *name) | ||||
| { | ||||
|   return egg_tray_icon_new_for_xscreen (DefaultScreenOfDisplay (gdk_display), name); | ||||
|   return g_object_new (EGG_TYPE_TRAY_ICON, "title", name, NULL); | ||||
| } | ||||
|  | ||||
| guint | ||||
| @@ -378,17 +557,20 @@ egg_tray_icon_send_message (EggTrayIcon *icon, | ||||
|   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)), | ||||
| 				      icon->manager_window, | ||||
| 				      timeout, len, stamp); | ||||
|  | ||||
|   /* Now to send the actual message */ | ||||
| @@ -401,7 +583,7 @@ egg_tray_icon_send_message (EggTrayIcon *icon, | ||||
|       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.window = icon->manager_window; | ||||
|       ev.format = 8; | ||||
|       ev.message_type = XInternAtom (xdisplay, | ||||
| 				     "_NET_SYSTEM_TRAY_MESSAGE_DATA", False); | ||||
| @@ -422,6 +604,7 @@ egg_tray_icon_send_message (EggTrayIcon *icon, | ||||
|       XSync (xdisplay, False); | ||||
|     } | ||||
|   gdk_error_trap_pop (); | ||||
| #endif | ||||
|  | ||||
|   return stamp; | ||||
| } | ||||
| @@ -432,11 +615,24 @@ 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 | ||||
| egg_tray_icon_get_orientation (EggTrayIcon *icon) | ||||
| { | ||||
|   g_return_val_if_fail (EGG_IS_TRAY_ICON (icon), GTK_ORIENTATION_HORIZONTAL); | ||||
|  | ||||
|   return icon->orientation; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| #endif /* __WXGTK20__ */ | ||||
| #endif /* GTK_CHECK_VERSION(2, 1, 0) */ | ||||
|   | ||||
		Reference in New Issue
	
	Block a user