summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorCarlos Garnacho <carlosg@gnome.org>2022-12-22 20:02:28 +0100
committerMarge Bot <marge-bot@gnome.org>2023-03-03 13:34:44 +0000
commitab609020581236df14f8b211baaddab82fc4dd08 (patch)
tree37dd8ef6b62da6755cfc6a0508f76333e10ee2b8 /src
parentf9519f4a55d95e51b7397206d9d7c6cf570fa125 (diff)
downloadgnome-shell-ab609020581236df14f8b211baaddab82fc4dd08.tar.gz
shell: Move tray implementation away from GtkSocket
Reimplement tray icon support on top of NaXembed. NaTrayIcon now becomes a subclass of this type, replacing GtkSocket. The ShellTrayIcon wrapper now embeds directly a NaTrayIcon, the ShellEmbeddedWindow GTK widget and ShellGtkEmbed ClutterClone objects are no longer necessary to wrap a NaXembed socket window. Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2590>
Diffstat (limited to 'src')
-rw-r--r--src/meson.build6
-rw-r--r--src/shell-embedded-window-private.h20
-rw-r--r--src/shell-embedded-window.c247
-rw-r--r--src/shell-embedded-window.h19
-rw-r--r--src/shell-gtk-embed.c364
-rw-r--r--src/shell-gtk-embed.h20
-rw-r--r--src/shell-tray-icon-private.h11
-rw-r--r--src/shell-tray-icon.c300
-rw-r--r--src/shell-tray-icon.h10
-rw-r--r--src/shell-tray-manager.c106
-rw-r--r--src/tray/meson.build2
-rw-r--r--src/tray/na-tray-child.c365
-rw-r--r--src/tray/na-tray-child.h38
-rw-r--r--src/tray/na-tray-manager.c668
-rw-r--r--src/tray/na-tray-manager.h78
15 files changed, 558 insertions, 1696 deletions
diff --git a/src/meson.build b/src/meson.build
index de88a45d9..b06b043a0 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -98,9 +98,7 @@ libshell_public_headers = [
'shell-app-system.h',
'shell-app-usage.h',
'shell-blur-effect.h',
- 'shell-embedded-window.h',
'shell-glsl-effect.h',
- 'shell-gtk-embed.h',
'shell-global.h',
'shell-invert-lightness-effect.h',
'shell-action-modes.h',
@@ -128,6 +126,7 @@ libshell_private_headers = [
'shell-app-cache-private.h',
'shell-app-system-private.h',
'shell-global-private.h',
+ 'shell-tray-icon-private.h',
'shell-window-tracker-private.h',
'shell-wm-private.h'
]
@@ -138,11 +137,8 @@ libshell_sources = [
'shell-app-system.c',
'shell-app-usage.c',
'shell-blur-effect.c',
- 'shell-embedded-window.c',
- 'shell-embedded-window-private.h',
'shell-global.c',
'shell-glsl-effect.c',
- 'shell-gtk-embed.c',
'shell-invert-lightness-effect.c',
'shell-keyring-prompt.c',
'shell-keyring-prompt.h',
diff --git a/src/shell-embedded-window-private.h b/src/shell-embedded-window-private.h
deleted file mode 100644
index 5714af99b..000000000
--- a/src/shell-embedded-window-private.h
+++ /dev/null
@@ -1,20 +0,0 @@
-/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
-#ifndef __SHELL_EMBEDDED_WINDOW_PRIVATE_H__
-#define __SHELL_EMBEDDED_WINDOW_PRIVATE_H__
-
-#include "shell-embedded-window.h"
-#include "shell-gtk-embed.h"
-
-void _shell_embedded_window_set_actor (ShellEmbeddedWindow *window,
- ShellGtkEmbed *embed);
-
-void _shell_embedded_window_allocate (ShellEmbeddedWindow *window,
- int x,
- int y,
- int width,
- int height);
-
-void _shell_embedded_window_map (ShellEmbeddedWindow *window);
-void _shell_embedded_window_unmap (ShellEmbeddedWindow *window);
-
-#endif /* __SHELL_EMBEDDED_WINDOW_PRIVATE_H__ */
diff --git a/src/shell-embedded-window.c b/src/shell-embedded-window.c
deleted file mode 100644
index 8fd611287..000000000
--- a/src/shell-embedded-window.c
+++ /dev/null
@@ -1,247 +0,0 @@
-/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
-
-#include "config.h"
-
-#include <gdk/gdkx.h>
-
-#include "shell-embedded-window-private.h"
-
-/* This type is a subclass of GtkWindow that ties the window to a
- * ShellGtkEmbed; the resizing logic is bound to the clutter logic.
- *
- * The typical usage we might expect is
- *
- * - ShellEmbeddedWindow is created and filled with content
- * - ShellEmbeddedWindow is shown with gtk_widget_show_all()
- * - ShellGtkEmbed is created for the ShellEmbeddedWindow
- * - actor is added to a stage
- *
- * The way it works is that the GtkWindow is mapped if and only if both:
- *
- * - gtk_widget_visible (window) [widget has been shown]
- * - Actor is mapped [actor and all parents visible, actor in stage]
- */
-
-enum {
- PROP_0
-};
-
-typedef struct _ShellEmbeddedWindowPrivate ShellEmbeddedWindowPrivate;
-
-struct _ShellEmbeddedWindowPrivate {
- ShellGtkEmbed *actor;
-
- GdkRectangle position;
-};
-
-G_DEFINE_TYPE_WITH_PRIVATE (ShellEmbeddedWindow,
- shell_embedded_window,
- GTK_TYPE_WINDOW);
-
-/*
- * The normal gtk_window_show() starts all of the complicated asynchronous
- * window resizing code running; we don't want or need any of that.
- * Bypassing the normal code does mean that the extra geometry management
- * available on GtkWindow: gridding, maximum sizes, etc, is ignored; we
- * don't really want that anyways - we just want a way of embedding a
- * GtkWidget into a Clutter stage.
- */
-static void
-shell_embedded_window_show (GtkWidget *widget)
-{
- ShellEmbeddedWindow *window = SHELL_EMBEDDED_WINDOW (widget);
- ShellEmbeddedWindowPrivate *priv;
- GtkWidgetClass *widget_class;
-
- priv = shell_embedded_window_get_instance_private (window);
-
- /* Skip GtkWindow, but run the default GtkWidget handling which
- * marks the widget visible */
- widget_class = g_type_class_peek (GTK_TYPE_WIDGET);
- widget_class->show (widget);
-
- if (priv->actor)
- {
- /* Size is 0x0 if the GtkWindow is not shown */
- clutter_actor_queue_relayout (CLUTTER_ACTOR (priv->actor));
-
- if (clutter_actor_is_realized (CLUTTER_ACTOR (priv->actor)))
- gtk_widget_map (widget);
- }
-}
-
-static void
-shell_embedded_window_hide (GtkWidget *widget)
-{
- ShellEmbeddedWindow *window = SHELL_EMBEDDED_WINDOW (widget);
- ShellEmbeddedWindowPrivate *priv;
-
- priv = shell_embedded_window_get_instance_private (window);
-
- if (priv->actor)
- clutter_actor_queue_relayout (CLUTTER_ACTOR (priv->actor));
-
- GTK_WIDGET_CLASS (shell_embedded_window_parent_class)->hide (widget);
-}
-
-static gboolean
-shell_embedded_window_configure_event (GtkWidget *widget,
- GdkEventConfigure *event)
-{
- /* Normally a configure event coming back from X triggers the
- * resizing logic inside GtkWindow; we just ignore them
- * since we are handling the resizing logic separately.
- */
- return FALSE;
-}
-
-static void
-shell_embedded_window_check_resize (GtkContainer *container)
-{
- ShellEmbeddedWindow *window = SHELL_EMBEDDED_WINDOW (container);
- ShellEmbeddedWindowPrivate *priv;
-
- priv = shell_embedded_window_get_instance_private (window);
-
- /* Check resize is called when a resize is queued on something
- * inside the GtkWindow; we need to make sure that in response
- * to this gtk_widget_size_request() and then
- * gtk_widget_size_allocate() are called; we defer to the Clutter
- * logic and assume it will do the right thing.
- */
- if (priv->actor)
- clutter_actor_queue_relayout (CLUTTER_ACTOR (priv->actor));
-}
-
-static GObject *
-shell_embedded_window_constructor (GType gtype,
- guint n_properties,
- GObjectConstructParam *properties)
-{
- GObject *object;
- GObjectClass *parent_class;
-
- parent_class = G_OBJECT_CLASS (shell_embedded_window_parent_class);
- object = parent_class->constructor (gtype, n_properties, properties);
-
- /* Setting the resize mode to immediate means that calling queue_resize()
- * on a widget within the window will immediately call check_resize()
- * to be called, instead of having it queued to an idle. From our perspective,
- * this is ideal since we just are going to queue a resize to Clutter's
- * idle resize anyways.
- */
- g_object_set (object,
- "app-paintable", TRUE,
- "resize-mode", GTK_RESIZE_IMMEDIATE,
- "type", GTK_WINDOW_POPUP,
- NULL);
-
- return object;
-}
-
-static void
-shell_embedded_window_class_init (ShellEmbeddedWindowClass *klass)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
- GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
- GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass);
-
- object_class->constructor = shell_embedded_window_constructor;
-
- widget_class->show = shell_embedded_window_show;
- widget_class->hide = shell_embedded_window_hide;
- widget_class->configure_event = shell_embedded_window_configure_event;
-
- container_class->check_resize = shell_embedded_window_check_resize;
-}
-
-static void
-shell_embedded_window_init (ShellEmbeddedWindow *window)
-{
-}
-
-/*
- * Private routines called by ShellGtkEmbed
- */
-
-void
-_shell_embedded_window_set_actor (ShellEmbeddedWindow *window,
- ShellGtkEmbed *actor)
-
-{
- ShellEmbeddedWindowPrivate *priv;
-
- g_return_if_fail (SHELL_IS_EMBEDDED_WINDOW (window));
-
- priv = shell_embedded_window_get_instance_private (window);
- priv->actor = actor;
-
- if (actor &&
- clutter_actor_is_mapped (CLUTTER_ACTOR (actor)) &&
- gtk_widget_get_visible (GTK_WIDGET (window)))
- gtk_widget_map (GTK_WIDGET (window));
-}
-
-void
-_shell_embedded_window_allocate (ShellEmbeddedWindow *window,
- int x,
- int y,
- int width,
- int height)
-{
- ShellEmbeddedWindowPrivate *priv;
- GtkAllocation allocation;
-
- g_return_if_fail (SHELL_IS_EMBEDDED_WINDOW (window));
-
- priv = shell_embedded_window_get_instance_private (window);
-
- if (priv->position.x == x &&
- priv->position.y == y &&
- priv->position.width == width &&
- priv->position.height == height)
- return;
-
- priv->position.x = x;
- priv->position.y = y;
- priv->position.width = width;
- priv->position.height = height;
-
- if (gtk_widget_get_realized (GTK_WIDGET (window)))
- gdk_window_move_resize (gtk_widget_get_window (GTK_WIDGET (window)),
- x, y, width, height);
-
- allocation.x = 0;
- allocation.y = 0;
- allocation.width = width;
- allocation.height = height;
-
- gtk_widget_size_allocate (GTK_WIDGET (window), &allocation);
-}
-
-void
-_shell_embedded_window_map (ShellEmbeddedWindow *window)
-{
- g_return_if_fail (SHELL_IS_EMBEDDED_WINDOW (window));
-
- if (gtk_widget_get_visible (GTK_WIDGET (window)))
- gtk_widget_map (GTK_WIDGET (window));
-}
-
-void
-_shell_embedded_window_unmap (ShellEmbeddedWindow *window)
-{
- g_return_if_fail (SHELL_IS_EMBEDDED_WINDOW (window));
-
- gtk_widget_unmap (GTK_WIDGET (window));
-}
-
-/*
- * Public API
- */
-GtkWidget *
-shell_embedded_window_new (void)
-{
- return g_object_new (SHELL_TYPE_EMBEDDED_WINDOW,
- NULL);
-}
diff --git a/src/shell-embedded-window.h b/src/shell-embedded-window.h
deleted file mode 100644
index 835165ba9..000000000
--- a/src/shell-embedded-window.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
-#ifndef __SHELL_EMBEDDED_WINDOW_H__
-#define __SHELL_EMBEDDED_WINDOW_H__
-
-#include <gtk/gtk.h>
-#include <clutter/clutter.h>
-
-#define SHELL_TYPE_EMBEDDED_WINDOW (shell_embedded_window_get_type ())
-G_DECLARE_DERIVABLE_TYPE (ShellEmbeddedWindow, shell_embedded_window,
- SHELL, EMBEDDED_WINDOW, GtkWindow)
-
-struct _ShellEmbeddedWindowClass
-{
- GtkWindowClass parent_class;
-};
-
-GtkWidget *shell_embedded_window_new (void);
-
-#endif /* __SHELL_EMBEDDED_WINDOW_H__ */
diff --git a/src/shell-gtk-embed.c b/src/shell-gtk-embed.c
deleted file mode 100644
index 2ad18a185..000000000
--- a/src/shell-gtk-embed.c
+++ /dev/null
@@ -1,364 +0,0 @@
-/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
-
-#include "config.h"
-
-#include "shell-embedded-window-private.h"
-#include "shell-global.h"
-#include "shell-util.h"
-
-#include <gdk/gdkx.h>
-#include <meta/display.h>
-#include <meta/window.h>
-
-enum {
- PROP_0,
-
- PROP_WINDOW
-};
-
-typedef struct _ShellGtkEmbedPrivate ShellGtkEmbedPrivate;
-
-struct _ShellGtkEmbedPrivate
-{
- ShellEmbeddedWindow *window;
-
- ClutterActor *window_actor;
- gulong window_actor_destroyed_handler;
-
- gulong window_created_handler;
-};
-
-G_DEFINE_TYPE_WITH_PRIVATE (ShellGtkEmbed, shell_gtk_embed, CLUTTER_TYPE_CLONE);
-
-static void shell_gtk_embed_set_window (ShellGtkEmbed *embed,
- ShellEmbeddedWindow *window);
-
-static void
-shell_gtk_embed_on_window_destroy (GtkWidget *object,
- ShellGtkEmbed *embed)
-{
- shell_gtk_embed_set_window (embed, NULL);
-}
-
-static void
-shell_gtk_embed_remove_window_actor (ShellGtkEmbed *embed)
-{
- ShellGtkEmbedPrivate *priv = shell_gtk_embed_get_instance_private (embed);
-
- if (priv->window_actor)
- {
- g_clear_signal_handler (&priv->window_actor_destroyed_handler,
- priv->window_actor);
-
- g_object_unref (priv->window_actor);
- priv->window_actor = NULL;
- }
-
- clutter_clone_set_source (CLUTTER_CLONE (embed), NULL);
-}
-
-static void
-shell_gtk_embed_window_created_cb (MetaDisplay *display,
- MetaWindow *window,
- ShellGtkEmbed *embed)
-{
- ShellGtkEmbedPrivate *priv = shell_gtk_embed_get_instance_private (embed);
- Window xwindow = meta_window_get_xwindow (window);
- GdkWindow *gdk_window = gtk_widget_get_window (GTK_WIDGET (priv->window));
-
- if (gdk_window && xwindow == gdk_x11_window_get_xid (gdk_window))
- {
- ClutterActor *window_actor =
- CLUTTER_ACTOR (meta_window_get_compositor_private (window));
- GCallback remove_cb = G_CALLBACK (shell_gtk_embed_remove_window_actor);
- cairo_region_t *empty_region;
-
- clutter_clone_set_source (CLUTTER_CLONE (embed), window_actor);
-
- /* We want to explicitly clear the clone source when the window
- actor is destroyed because otherwise we might end up keeping
- it alive after it has been disposed. Otherwise this can cause
- a crash if there is a paint after mutter notices that the top
- level window has been destroyed, which causes it to dispose
- the window, and before the tray manager notices that the
- window is gone which would otherwise reset the window and
- unref the clone */
- priv->window_actor = g_object_ref (window_actor);
- priv->window_actor_destroyed_handler =
- g_signal_connect_swapped (window_actor,
- "destroy",
- remove_cb,
- embed);
-
- /* Hide the original actor otherwise it will appear in the scene
- as a normal window */
- clutter_actor_set_opacity (window_actor, 0);
-
- /* Also make sure it (or any of its children) doesn't block
- events on wayland */
- shell_util_set_hidden_from_pick (window_actor, TRUE);
-
- /* Set an empty input shape on the window so that it can't get
- any input. This probably isn't the ideal way to achieve this.
- It would probably be better to force the window to go behind
- Mutter's guard window, but this is quite difficult to do as
- Mutter doesn't manage the stacking for override redirect
- windows and the guard window is repeatedly lowered to the
- bottom of the stack. */
- empty_region = cairo_region_create ();
- gdk_window_input_shape_combine_region (gdk_window,
- empty_region,
- 0, 0 /* offset x/y */);
- cairo_region_destroy (empty_region);
-
- gdk_window_lower (gdk_window);
-
- /* Now that we've found the window we don't need to listen for
- new windows anymore */
- g_clear_signal_handler (&priv->window_created_handler,
- display);
- }
-}
-
-static void
-shell_gtk_embed_on_window_mapped (GtkWidget *object,
- ShellGtkEmbed *embed)
-{
- ShellGtkEmbedPrivate *priv = shell_gtk_embed_get_instance_private (embed);
- MetaDisplay *display = shell_global_get_display (shell_global_get ());
-
- if (priv->window_created_handler == 0 && priv->window_actor == NULL)
- /* Listen for new windows so we can detect when Mutter has
- created a MutterWindow for this window */
- priv->window_created_handler =
- g_signal_connect (display,
- "window-created",
- G_CALLBACK (shell_gtk_embed_window_created_cb),
- embed);
-}
-
-static void
-shell_gtk_embed_set_window (ShellGtkEmbed *embed,
- ShellEmbeddedWindow *window)
-{
- ShellGtkEmbedPrivate *priv = shell_gtk_embed_get_instance_private (embed);
- MetaDisplay *display = shell_global_get_display (shell_global_get ());
-
- if (priv->window)
- {
- g_clear_signal_handler (&priv->window_created_handler, display);
-
- shell_gtk_embed_remove_window_actor (embed);
-
- _shell_embedded_window_set_actor (priv->window, NULL);
-
- g_object_unref (priv->window);
-
- g_signal_handlers_disconnect_by_func (priv->window,
- (gpointer)shell_gtk_embed_on_window_destroy,
- embed);
-
- g_signal_handlers_disconnect_by_func (priv->window,
- (gpointer)shell_gtk_embed_on_window_mapped,
- embed);
- }
-
- priv->window = window;
-
- if (priv->window)
- {
- g_object_ref (priv->window);
-
- _shell_embedded_window_set_actor (priv->window, embed);
-
- g_signal_connect (priv->window, "destroy",
- G_CALLBACK (shell_gtk_embed_on_window_destroy), embed);
-
- g_signal_connect (priv->window, "map",
- G_CALLBACK (shell_gtk_embed_on_window_mapped), embed);
- }
-
- clutter_actor_queue_relayout (CLUTTER_ACTOR (embed));
-}
-
-static void
-shell_gtk_embed_set_property (GObject *object,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- ShellGtkEmbed *embed = SHELL_GTK_EMBED (object);
-
- switch (prop_id)
- {
- case PROP_WINDOW:
- shell_gtk_embed_set_window (embed, (ShellEmbeddedWindow *)g_value_get_object (value));
- break;
-
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-shell_gtk_embed_get_property (GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec)
-{
- ShellGtkEmbed *embed = SHELL_GTK_EMBED (object);
- ShellGtkEmbedPrivate *priv = shell_gtk_embed_get_instance_private (embed);
-
- switch (prop_id)
- {
- case PROP_WINDOW:
- g_value_set_object (value, priv->window);
- break;
-
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-shell_gtk_embed_get_preferred_width (ClutterActor *actor,
- float for_height,
- float *min_width_p,
- float *natural_width_p)
-{
- ShellGtkEmbed *embed = SHELL_GTK_EMBED (actor);
- ShellGtkEmbedPrivate *priv = shell_gtk_embed_get_instance_private (embed);
-
- if (priv->window
- && gtk_widget_get_visible (GTK_WIDGET (priv->window)))
- {
- GtkRequisition min_req, natural_req;
- gtk_widget_get_preferred_size (GTK_WIDGET (priv->window), &min_req, &natural_req);
-
- *min_width_p = min_req.width;
- *natural_width_p = natural_req.width;
- }
- else
- *min_width_p = *natural_width_p = 0;
-}
-
-static void
-shell_gtk_embed_get_preferred_height (ClutterActor *actor,
- float for_width,
- float *min_height_p,
- float *natural_height_p)
-{
- ShellGtkEmbed *embed = SHELL_GTK_EMBED (actor);
- ShellGtkEmbedPrivate *priv = shell_gtk_embed_get_instance_private (embed);
-
- if (priv->window
- && gtk_widget_get_visible (GTK_WIDGET (priv->window)))
- {
- GtkRequisition min_req, natural_req;
- gtk_widget_get_preferred_size (GTK_WIDGET (priv->window), &min_req, &natural_req);
-
- *min_height_p = min_req.height;
- *natural_height_p = natural_req.height;
- }
- else
- *min_height_p = *natural_height_p = 0;
-}
-
-static void
-shell_gtk_embed_allocate (ClutterActor *actor,
- const ClutterActorBox *box)
-{
- ShellGtkEmbed *embed = SHELL_GTK_EMBED (actor);
- ShellGtkEmbedPrivate *priv = shell_gtk_embed_get_instance_private (embed);
- float wx, wy;
-
- CLUTTER_ACTOR_CLASS (shell_gtk_embed_parent_class)->
- allocate (actor, box);
-
- /* Find the actor's new coordinates in terms of the stage (which is
- * priv->window's parent window.
- */
- clutter_actor_get_transformed_position (actor, &wx, &wy);
-
- _shell_embedded_window_allocate (priv->window,
- (int)(0.5 + wx), (int)(0.5 + wy),
- box->x2 - box->x1,
- box->y2 - box->y1);
-}
-
-static void
-shell_gtk_embed_map (ClutterActor *actor)
-{
- ShellGtkEmbed *embed = SHELL_GTK_EMBED (actor);
- ShellGtkEmbedPrivate *priv = shell_gtk_embed_get_instance_private (embed);
-
- _shell_embedded_window_map (priv->window);
-
- CLUTTER_ACTOR_CLASS (shell_gtk_embed_parent_class)->map (actor);
-}
-
-static void
-shell_gtk_embed_unmap (ClutterActor *actor)
-{
- ShellGtkEmbed *embed = SHELL_GTK_EMBED (actor);
- ShellGtkEmbedPrivate *priv = shell_gtk_embed_get_instance_private (embed);
-
- _shell_embedded_window_unmap (priv->window);
-
- CLUTTER_ACTOR_CLASS (shell_gtk_embed_parent_class)->unmap (actor);
-}
-
-static void
-shell_gtk_embed_dispose (GObject *object)
-{
- ShellGtkEmbed *embed = SHELL_GTK_EMBED (object);
-
- G_OBJECT_CLASS (shell_gtk_embed_parent_class)->dispose (object);
-
- shell_gtk_embed_set_window (embed, NULL);
-}
-
-static void
-shell_gtk_embed_class_init (ShellGtkEmbedClass *klass)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
- ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
-
- object_class->get_property = shell_gtk_embed_get_property;
- object_class->set_property = shell_gtk_embed_set_property;
- object_class->dispose = shell_gtk_embed_dispose;
-
- actor_class->get_preferred_width = shell_gtk_embed_get_preferred_width;
- actor_class->get_preferred_height = shell_gtk_embed_get_preferred_height;
- actor_class->allocate = shell_gtk_embed_allocate;
- actor_class->map = shell_gtk_embed_map;
- actor_class->unmap = shell_gtk_embed_unmap;
-
- g_object_class_install_property (object_class,
- PROP_WINDOW,
- g_param_spec_object ("window",
- "Window",
- "ShellEmbeddedWindow to embed",
- SHELL_TYPE_EMBEDDED_WINDOW,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
-}
-
-static void
-shell_gtk_embed_init (ShellGtkEmbed *embed)
-{
-}
-
-/*
- * Public API
- */
-ClutterActor *
-shell_gtk_embed_new (ShellEmbeddedWindow *window)
-{
- g_return_val_if_fail (SHELL_IS_EMBEDDED_WINDOW (window), NULL);
-
- return g_object_new (SHELL_TYPE_GTK_EMBED,
- "window", window,
- NULL);
-}
diff --git a/src/shell-gtk-embed.h b/src/shell-gtk-embed.h
deleted file mode 100644
index 4cfc489be..000000000
--- a/src/shell-gtk-embed.h
+++ /dev/null
@@ -1,20 +0,0 @@
-/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
-#ifndef __SHELL_GTK_EMBED_H__
-#define __SHELL_GTK_EMBED_H__
-
-#include <clutter/clutter.h>
-
-#include "shell-embedded-window.h"
-
-#define SHELL_TYPE_GTK_EMBED (shell_gtk_embed_get_type ())
-G_DECLARE_DERIVABLE_TYPE (ShellGtkEmbed, shell_gtk_embed,
- SHELL, GTK_EMBED, ClutterClone)
-
-struct _ShellGtkEmbedClass
-{
- ClutterCloneClass parent_class;
-};
-
-ClutterActor *shell_gtk_embed_new (ShellEmbeddedWindow *window);
-
-#endif /* __SHELL_GTK_EMBED_H__ */
diff --git a/src/shell-tray-icon-private.h b/src/shell-tray-icon-private.h
new file mode 100644
index 000000000..e77ac0aae
--- /dev/null
+++ b/src/shell-tray-icon-private.h
@@ -0,0 +1,11 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+#ifndef SHELL_TRAY_ICON_PRIVATE_H
+#define SHELL_TRAY_ICON_PRIVATE_H
+
+#include "shell-tray-icon.h"
+
+#include "na-tray-child.h"
+
+ClutterActor * shell_tray_icon_new (NaTrayChild *tray_child);
+
+#endif /* SHELL_TRAY_ICON_PRIVATE_H */
diff --git a/src/shell-tray-icon.c b/src/shell-tray-icon.c
index 14b219100..cac801654 100644
--- a/src/shell-tray-icon.c
+++ b/src/shell-tray-icon.c
@@ -2,13 +2,14 @@
#include "config.h"
-#include "shell-tray-icon.h"
-#include "shell-gtk-embed.h"
+#include "shell-global.h"
+#include "shell-tray-icon-private.h"
+#include "shell-util.h"
#include "tray/na-tray-child.h"
-#include <gdk/gdkx.h>
-#include <X11/Xatom.h>
#include "st.h"
+#include <X11/Xatom.h>
+
enum {
PROP_0,
@@ -21,76 +22,86 @@ typedef struct _ShellTrayIconPrivate ShellTrayIconPrivate;
struct _ShellTrayIcon
{
- ShellGtkEmbed parent;
-
- ShellTrayIconPrivate *priv;
-};
-
-struct _ShellTrayIconPrivate
-{
- NaTrayChild *socket;
+ ClutterClone parent;
+ NaTrayChild *tray_child;
+ ClutterActor *window_actor;
+ gulong window_actor_destroyed_handler;
+ gulong window_created_handler;
pid_t pid;
- char *title, *wm_class;
+ char *title;
+ char *wm_class;
};
-G_DEFINE_TYPE_WITH_PRIVATE (ShellTrayIcon, shell_tray_icon, SHELL_TYPE_GTK_EMBED);
+G_DEFINE_TYPE (ShellTrayIcon, shell_tray_icon, CLUTTER_TYPE_CLONE);
static void
shell_tray_icon_finalize (GObject *object)
{
ShellTrayIcon *icon = SHELL_TRAY_ICON (object);
- g_free (icon->priv->title);
- g_free (icon->priv->wm_class);
+ g_free (icon->title);
+ g_free (icon->wm_class);
G_OBJECT_CLASS (shell_tray_icon_parent_class)->finalize (object);
}
static void
-shell_tray_icon_constructed (GObject *object)
+shell_tray_icon_remove_window_actor (ShellTrayIcon *tray_icon)
{
- GdkWindow *icon_app_window;
- ShellTrayIcon *icon = SHELL_TRAY_ICON (object);
- ShellEmbeddedWindow *window;
- GdkDisplay *display;
- Window plug_xid;
- Atom _NET_WM_PID, type;
- int result, format;
- gulong nitems, bytes_after, *val = NULL;
-
- /* We do all this now rather than computing it on the fly later,
- * because the shell may want to see their values from a
- * tray-icon-removed signal handler, at which point the plug has
- * already been removed from the socket.
- */
-
- g_object_get (object, "window", &window, NULL);
- g_return_if_fail (window != NULL);
- icon->priv->socket = NA_TRAY_CHILD (gtk_bin_get_child (GTK_BIN (window)));
- g_object_unref (window);
-
- icon->priv->title = na_tray_child_get_title (icon->priv->socket);
- na_tray_child_get_wm_class (icon->priv->socket, NULL, &icon->priv->wm_class);
+ if (tray_icon->window_actor)
+ {
+ g_clear_signal_handler (&tray_icon->window_actor_destroyed_handler,
+ tray_icon->window_actor);
+ g_clear_object (&tray_icon->window_actor);
+ }
- icon_app_window = gtk_socket_get_plug_window (GTK_SOCKET (icon->priv->socket));
- plug_xid = GDK_WINDOW_XID (icon_app_window);
+ clutter_clone_set_source (CLUTTER_CLONE (tray_icon), NULL);
+}
- display = gtk_widget_get_display (GTK_WIDGET (icon->priv->socket));
- gdk_x11_display_error_trap_push (display);
- _NET_WM_PID = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_PID");
- result = XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), plug_xid,
- _NET_WM_PID, 0, G_MAXLONG, False, XA_CARDINAL,
- &type, &format, &nitems,
- &bytes_after, (guchar **)&val);
- if (!gdk_x11_display_error_trap_pop (display) &&
- result == Success &&
- type == XA_CARDINAL &&
- nitems == 1)
- icon->priv->pid = *val;
+static void
+shell_tray_icon_window_created_cb (MetaDisplay *display,
+ MetaWindow *window,
+ ShellTrayIcon *tray_icon)
+{
+ Window xwindow = meta_window_get_xwindow (window);
- if (val)
- XFree (val);
+ if (tray_icon->tray_child &&
+ xwindow == na_xembed_get_socket_window (NA_XEMBED (tray_icon->tray_child)))
+ {
+ ClutterActor *window_actor =
+ CLUTTER_ACTOR (meta_window_get_compositor_private (window));
+
+ clutter_clone_set_source (CLUTTER_CLONE (tray_icon), window_actor);
+
+ /* We want to explicitly clear the clone source when the window
+ actor is destroyed because otherwise we might end up keeping
+ it alive after it has been disposed. Otherwise this can cause
+ a crash if there is a paint after mutter notices that the top
+ level window has been destroyed, which causes it to dispose
+ the window, and before the tray manager notices that the
+ window is gone which would otherwise reset the window and
+ unref the clone */
+ tray_icon->window_actor = g_object_ref (window_actor);
+ tray_icon->window_actor_destroyed_handler =
+ g_signal_connect_swapped (window_actor,
+ "destroy",
+ G_CALLBACK (shell_tray_icon_remove_window_actor),
+ tray_icon);
+
+ /* Hide the original actor otherwise it will appear in the scene
+ as a normal window */
+ clutter_actor_set_opacity (window_actor, 0);
+
+ /* Also make sure it (or any of its children) doesn't block
+ events on wayland */
+ shell_util_set_hidden_from_pick (window_actor, TRUE);
+
+ /* Now that we've found the window we don't need to listen for
+ new windows anymore */
+ g_clear_signal_handler (&tray_icon->window_created_handler,
+ display);
+ }
}
static void
@@ -104,15 +115,15 @@ shell_tray_icon_get_property (GObject *object,
switch (prop_id)
{
case PROP_PID:
- g_value_set_uint (value, icon->priv->pid);
+ g_value_set_uint (value, icon->pid);
break;
case PROP_TITLE:
- g_value_set_string (value, icon->priv->title);
+ g_value_set_string (value, icon->title);
break;
case PROP_WM_CLASS:
- g_value_set_string (value, icon->priv->wm_class);
+ g_value_set_string (value, icon->wm_class);
break;
default:
@@ -122,13 +133,77 @@ shell_tray_icon_get_property (GObject *object,
}
static void
+shell_tray_icon_dispose (GObject *object)
+{
+ ShellTrayIcon *tray_icon = SHELL_TRAY_ICON (object);
+ MetaDisplay *display = shell_global_get_display (shell_global_get ());
+
+ g_clear_signal_handler (&tray_icon->window_created_handler,
+ display);
+ shell_tray_icon_remove_window_actor (tray_icon);
+
+ G_OBJECT_CLASS (shell_tray_icon_parent_class)->dispose (object);
+}
+
+static void
+shell_tray_icon_get_preferred_width (ClutterActor *actor,
+ float for_height,
+ float *min_width_p,
+ float *natural_width_p)
+{
+ ShellTrayIcon *tray_icon = SHELL_TRAY_ICON (actor);
+ int width;
+
+ na_xembed_get_size (NA_XEMBED (tray_icon->tray_child), &width, NULL);
+
+ *min_width_p = width;
+ *natural_width_p = width;
+}
+
+static void
+shell_tray_icon_get_preferred_height (ClutterActor *actor,
+ float for_width,
+ float *min_height_p,
+ float *natural_height_p)
+{
+ ShellTrayIcon *tray_icon = SHELL_TRAY_ICON (actor);
+ int height;
+
+ na_xembed_get_size (NA_XEMBED (tray_icon->tray_child), NULL, &height);
+
+ *min_height_p = height;
+ *natural_height_p = height;
+}
+
+static void
+shell_tray_icon_allocate (ClutterActor *actor,
+ const ClutterActorBox *box)
+{
+ ShellTrayIcon *tray_icon = SHELL_TRAY_ICON (actor);
+ float wx, wy;
+
+ CLUTTER_ACTOR_CLASS (shell_tray_icon_parent_class)->allocate (actor, box);
+
+ /* Find the actor's new coordinates in terms of the stage.
+ */
+ clutter_actor_get_transformed_position (actor, &wx, &wy);
+ na_xembed_set_root_position (NA_XEMBED (tray_icon->tray_child),
+ (int)(0.5 + wx), (int)(0.5 + wy));
+}
+
+static void
shell_tray_icon_class_init (ShellTrayIconClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
object_class->get_property = shell_tray_icon_get_property;
- object_class->constructed = shell_tray_icon_constructed;
- object_class->finalize = shell_tray_icon_finalize;
+ object_class->finalize = shell_tray_icon_finalize;
+ object_class->dispose = shell_tray_icon_dispose;
+
+ actor_class->get_preferred_width = shell_tray_icon_get_preferred_width;
+ actor_class->get_preferred_height = shell_tray_icon_get_preferred_height;
+ actor_class->allocate = shell_tray_icon_allocate;
g_object_class_install_property (object_class,
PROP_PID,
@@ -156,20 +231,77 @@ shell_tray_icon_class_init (ShellTrayIconClass *klass)
static void
shell_tray_icon_init (ShellTrayIcon *icon)
{
- icon->priv = shell_tray_icon_get_instance_private (icon);
+}
+
+static void
+shell_tray_icon_set_child (ShellTrayIcon *tray_icon,
+ NaTrayChild *tray_child)
+{
+ MetaDisplay *display = shell_global_get_display (shell_global_get ());
+ MetaX11Display *x11_display;
+ Display *xdisplay;
+ Window plug_xid;
+ Atom type;
+ int result, format;
+ gulong nitems, bytes_after, *val = NULL;
+
+ g_return_if_fail (tray_icon != NULL);
+ g_return_if_fail (tray_child != NULL);
+
+ x11_display = meta_display_get_x11_display (display);
+
+ /* We do all this now rather than computing it on the fly later,
+ * because the shell may want to see their values from a
+ * tray-icon-removed signal handler, at which point the plug has
+ * already been removed from the socket.
+ */
+
+ tray_icon->tray_child = tray_child;
+
+ tray_icon->title = na_tray_child_get_title (tray_icon->tray_child);
+ na_tray_child_get_wm_class (tray_icon->tray_child,
+ NULL, &tray_icon->wm_class);
+
+ plug_xid = na_xembed_get_plug_window (NA_XEMBED (tray_icon->tray_child));
+
+ xdisplay = meta_x11_display_get_xdisplay (x11_display);
+ meta_x11_error_trap_push (x11_display);
+ result = XGetWindowProperty (xdisplay, plug_xid,
+ XInternAtom (xdisplay, "_NET_WM_PID", False),
+ 0, G_MAXLONG, False, XA_CARDINAL,
+ &type, &format, &nitems,
+ &bytes_after, (guchar **)&val);
+
+ if (!meta_x11_error_trap_pop_with_return (x11_display) &&
+ result == Success &&
+ type == XA_CARDINAL &&
+ nitems == 1)
+ tray_icon->pid = *val;
+
+ if (val)
+ XFree (val);
+
+ tray_icon->window_created_handler =
+ g_signal_connect (display,
+ "window-created",
+ G_CALLBACK (shell_tray_icon_window_created_cb),
+ tray_icon);
}
/*
* Public API
*/
ClutterActor *
-shell_tray_icon_new (ShellEmbeddedWindow *window)
+shell_tray_icon_new (NaTrayChild *tray_child)
{
- g_return_val_if_fail (SHELL_IS_EMBEDDED_WINDOW (window), NULL);
+ ShellTrayIcon *tray_icon;
+
+ g_return_val_if_fail (NA_IS_TRAY_CHILD (tray_child), NULL);
- return g_object_new (SHELL_TYPE_TRAY_ICON,
- "window", window,
- NULL);
+ tray_icon = g_object_new (SHELL_TYPE_TRAY_ICON, NULL);
+ shell_tray_icon_set_child (tray_icon, tray_child);
+
+ return CLUTTER_ACTOR (tray_icon);
}
/**
@@ -187,37 +319,37 @@ void
shell_tray_icon_click (ShellTrayIcon *icon,
ClutterEvent *event)
{
+ MetaDisplay *display = shell_global_get_display (shell_global_get ());
+ MetaX11Display *x11_display;
XKeyEvent xkevent;
XButtonEvent xbevent;
XCrossingEvent xcevent;
- GdkDisplay *display;
- GdkWindow *remote_window;
- GdkScreen *screen;
- int x_root, y_root;
Display *xdisplay;
Window xwindow, xrootwindow;
ClutterEventType event_type = clutter_event_type (event);
+ int width, height;
g_return_if_fail (event_type == CLUTTER_BUTTON_RELEASE ||
event_type == CLUTTER_KEY_PRESS ||
event_type == CLUTTER_KEY_RELEASE);
- remote_window = gtk_socket_get_plug_window (GTK_SOCKET (icon->priv->socket));
- if (remote_window == NULL)
+ x11_display = meta_display_get_x11_display (display);
+ if (!x11_display)
+ return;
+
+ xwindow = na_xembed_get_plug_window (NA_XEMBED (icon->tray_child));
+ if (xwindow == None)
{
g_warning ("shell tray: plug window is gone");
return;
}
- xdisplay = GDK_WINDOW_XDISPLAY (remote_window);
- display = gdk_x11_lookup_xdisplay (xdisplay);
- gdk_x11_display_error_trap_push (display);
+ na_xembed_get_size (NA_XEMBED (icon->tray_child), &width, &height);
- xwindow = GDK_WINDOW_XID (remote_window);
- screen = gdk_window_get_screen (remote_window);
- xrootwindow = GDK_WINDOW_XID (gdk_screen_get_root_window (screen));
- gdk_window_get_origin (remote_window, &x_root, &y_root);
+ meta_x11_error_trap_push (x11_display);
+ xdisplay = meta_x11_display_get_xdisplay (x11_display);
+ xrootwindow = XDefaultRootWindow (xdisplay);
/* First make the icon believe the pointer is inside it */
xcevent.type = EnterNotify;
@@ -225,10 +357,10 @@ shell_tray_icon_click (ShellTrayIcon *icon,
xcevent.root = xrootwindow;
xcevent.subwindow = None;
xcevent.time = clutter_event_get_time (event);
- xcevent.x = gdk_window_get_width (remote_window) / 2;
- xcevent.y = gdk_window_get_height (remote_window) / 2;
- xcevent.x_root = x_root + xcevent.x;
- xcevent.y_root = y_root + xcevent.y;
+ xcevent.x = width / 2;
+ xcevent.y = height / 2;
+ xcevent.x_root = xcevent.x;
+ xcevent.y_root = xcevent.y;
xcevent.mode = NotifyNormal;
xcevent.detail = NotifyNonlinear;
xcevent.same_screen = True;
@@ -290,5 +422,5 @@ shell_tray_icon_click (ShellTrayIcon *icon,
xcevent.type = LeaveNotify;
XSendEvent (xdisplay, xwindow, False, 0, (XEvent *)&xcevent);
- gdk_x11_display_error_trap_pop_ignored (display);
+ meta_x11_error_trap_pop (x11_display);
}
diff --git a/src/shell-tray-icon.h b/src/shell-tray-icon.h
index f0e119114..434bd3d12 100644
--- a/src/shell-tray-icon.h
+++ b/src/shell-tray-icon.h
@@ -2,15 +2,13 @@
#ifndef __SHELL_TRAY_ICON_H__
#define __SHELL_TRAY_ICON_H__
-#include "shell-gtk-embed.h"
+#include <clutter/clutter.h>
#define SHELL_TYPE_TRAY_ICON (shell_tray_icon_get_type ())
G_DECLARE_FINAL_TYPE (ShellTrayIcon, shell_tray_icon,
- SHELL, TRAY_ICON, ShellGtkEmbed)
+ SHELL, TRAY_ICON, ClutterClone)
-ClutterActor *shell_tray_icon_new (ShellEmbeddedWindow *window);
-
-void shell_tray_icon_click (ShellTrayIcon *icon,
- ClutterEvent *event);
+void shell_tray_icon_click (ShellTrayIcon *icon,
+ ClutterEvent *event);
#endif /* __SHELL_TRAY_ICON_H__ */
diff --git a/src/shell-tray-manager.c b/src/shell-tray-manager.c
index c8e325978..4b332a87c 100644
--- a/src/shell-tray-manager.c
+++ b/src/shell-tray-manager.c
@@ -4,14 +4,12 @@
#include <clutter/clutter.h>
#include <girepository.h>
-#include <gtk/gtk.h>
#include <meta/display.h>
#include "shell-tray-manager.h"
#include "na-tray-manager.h"
-#include "shell-tray-icon.h"
-#include "shell-embedded-window.h"
+#include "shell-tray-icon-private.h"
#include "shell-global.h"
typedef struct _ShellTrayManagerPrivate ShellTrayManagerPrivate;
@@ -33,8 +31,7 @@ struct _ShellTrayManagerPrivate {
typedef struct {
ShellTrayManager *manager;
- GtkWidget *socket;
- GtkWidget *window;
+ NaTrayChild *tray_child;
ClutterActor *actor;
} ShellTrayManagerChild;
@@ -60,15 +57,19 @@ static const ClutterColor default_color = { 0x00, 0x00, 0x00, 0xff };
static void shell_tray_manager_release_resources (ShellTrayManager *manager);
-static void na_tray_icon_added (NaTrayManager *na_manager, GtkWidget *child, gpointer manager);
-static void na_tray_icon_removed (NaTrayManager *na_manager, GtkWidget *child, gpointer manager);
+static void na_tray_icon_added (NaTrayManager *na_manager,
+ NaTrayChild *child,
+ gpointer manager);
+
+static void na_tray_icon_removed (NaTrayManager *na_manager,
+ NaTrayChild *child,
+ gpointer manager);
static void
free_tray_icon (gpointer data)
{
ShellTrayManagerChild *child = data;
- gtk_widget_destroy (child->window);
if (child->actor)
{
g_signal_handlers_disconnect_matched (child->actor, G_SIGNAL_MATCH_DATA,
@@ -188,13 +189,19 @@ shell_tray_manager_new (void)
static void
shell_tray_manager_ensure_resources (ShellTrayManager *manager)
{
+ MetaDisplay *display;
+ MetaX11Display *x11_display;
+
if (manager->priv->na_manager != NULL)
return;
manager->priv->icons = g_hash_table_new_full (NULL, NULL,
NULL, free_tray_icon);
- manager->priv->na_manager = na_tray_manager_new ();
+ display = shell_global_get_display (shell_global_get ());
+ x11_display = meta_display_get_x11_display (display);
+
+ manager->priv->na_manager = na_tray_manager_new (x11_display);
g_signal_connect (manager->priv->na_manager, "tray-icon-added",
G_CALLBACK (na_tray_icon_added), manager);
@@ -231,7 +238,7 @@ static void
shell_tray_manager_manage_screen_internal (ShellTrayManager *manager)
{
shell_tray_manager_ensure_resources (manager);
- na_tray_manager_manage_screen (manager->priv->na_manager);
+ na_tray_manager_manage (manager->priv->na_manager);
}
void
@@ -277,98 +284,63 @@ shell_tray_manager_unmanage_screen (ShellTrayManager *manager)
}
static void
-shell_tray_manager_child_on_realize (GtkWidget *widget,
- ShellTrayManagerChild *child)
-{
- /* If the tray child is using an RGBA colormap (and so we have real
- * transparency), we don't need to worry about the background. If
- * not, we obey the bg-color property by creating a cairo pattern of
- * that color and setting it as our background. Then "parent-relative"
- * background on the socket and the plug within that will cause
- * the icons contents to appear on top of our background color.
- */
- if (!na_tray_child_has_alpha (NA_TRAY_CHILD (child->socket)))
- {
- ClutterColor color = child->manager->priv->bg_color;
- cairo_pattern_t *bg_pattern;
-
- bg_pattern = cairo_pattern_create_rgb (color.red / 255.,
- color.green / 255.,
- color.blue / 255.);
-G_GNUC_BEGIN_IGNORE_DEPRECATIONS
- gdk_window_set_background_pattern (gtk_widget_get_window (widget),
- bg_pattern);
-G_GNUC_END_IGNORE_DEPRECATIONS
-
- cairo_pattern_destroy (bg_pattern);
- }
-}
-
-static void
-on_plug_added (GtkSocket *socket,
+on_plug_added (NaTrayChild *tray_child,
ShellTrayManager *manager)
{
ShellTrayManagerChild *child;
- g_signal_handlers_disconnect_by_func (socket, on_plug_added, manager);
+ g_signal_handlers_disconnect_by_func (tray_child, on_plug_added, manager);
- child = g_hash_table_lookup (manager->priv->icons, socket);
+ child = g_hash_table_lookup (manager->priv->icons, tray_child);
- child->actor = shell_tray_icon_new (SHELL_EMBEDDED_WINDOW (child->window));
+ child->actor = shell_tray_icon_new (tray_child);
g_object_ref_sink (child->actor);
+ na_xembed_set_background_color (NA_XEMBED (tray_child),
+ &manager->priv->bg_color);
+
g_signal_emit (manager, shell_tray_manager_signals[TRAY_ICON_ADDED], 0,
child->actor);
}
static void
-na_tray_icon_added (NaTrayManager *na_manager, GtkWidget *socket,
- gpointer user_data)
+na_tray_icon_added (NaTrayManager *na_manager,
+ NaTrayChild *tray_child,
+ gpointer user_data)
{
ShellTrayManager *manager = user_data;
- GtkWidget *win;
ShellTrayManagerChild *child;
- win = shell_embedded_window_new ();
- gtk_container_add (GTK_CONTAINER (win), socket);
-
- /* The visual of the socket matches that of its contents; make
- * the window we put it in match that as well */
- gtk_widget_set_visual (win, gtk_widget_get_visual (socket));
-
child = g_new0 (ShellTrayManagerChild, 1);
child->manager = manager;
- child->window = win;
- child->socket = socket;
-
- g_signal_connect (win, "realize",
- G_CALLBACK (shell_tray_manager_child_on_realize), child);
+ child->tray_child = tray_child;
- gtk_widget_show_all (win);
+ g_hash_table_insert (manager->priv->icons, tray_child, child);
- g_hash_table_insert (manager->priv->icons, socket, child);
-
- g_signal_connect (socket, "plug-added", G_CALLBACK (on_plug_added), manager);
+ g_signal_connect (tray_child, "plug-added",
+ G_CALLBACK (on_plug_added), manager);
}
static void
-na_tray_icon_removed (NaTrayManager *na_manager, GtkWidget *socket,
- gpointer user_data)
+na_tray_icon_removed (NaTrayManager *na_manager,
+ NaTrayChild *tray_child,
+ gpointer user_data)
{
ShellTrayManager *manager = user_data;
ShellTrayManagerChild *child;
- child = g_hash_table_lookup (manager->priv->icons, socket);
+ child = g_hash_table_lookup (manager->priv->icons, tray_child);
g_return_if_fail (child != NULL);
if (child->actor != NULL)
{
/* Only emit signal if a corresponding tray-icon-added signal was emitted,
- that is, if embedding did not fail and we got a plug-added
- */
+ * that is, if embedding did not fail and we got a plug-added
+ */
g_signal_emit (manager,
shell_tray_manager_signals[TRAY_ICON_REMOVED], 0,
child->actor);
}
- g_hash_table_remove (manager->priv->icons, socket);
+
+ g_hash_table_remove (manager->priv->icons, tray_child);
}
diff --git a/src/tray/meson.build b/src/tray/meson.build
index 092e7f689..9d28e8cf1 100644
--- a/src/tray/meson.build
+++ b/src/tray/meson.build
@@ -9,6 +9,6 @@ tray_sources = [
libtray = static_library('tray', tray_sources,
c_args: ['-DG_LOG_DOMAIN="notification_area"'],
- dependencies: [mutter_dep, gtk_dep],
+ dependencies: [mutter_dep],
include_directories: conf_inc
)
diff --git a/src/tray/na-tray-child.c b/src/tray/na-tray-child.c
index 175ac8a5a..1f1bae9b1 100644
--- a/src/tray/na-tray-child.c
+++ b/src/tray/na-tray-child.c
@@ -22,203 +22,16 @@
#include "na-tray-child.h"
-#include <gdk/gdk.h>
-#include <gdk/gdkx.h>
#include <X11/Xatom.h>
+#include <X11/Xutil.h>
-G_DEFINE_TYPE (NaTrayChild, na_tray_child, GTK_TYPE_SOCKET)
-
-static void
-na_tray_child_finalize (GObject *object)
-{
- G_OBJECT_CLASS (na_tray_child_parent_class)->finalize (object);
-}
-
-static void
-na_tray_child_realize (GtkWidget *widget)
-{
- NaTrayChild *child = NA_TRAY_CHILD (widget);
- GdkVisual *visual = gtk_widget_get_visual (widget);
- GdkWindow *window;
-
- GTK_WIDGET_CLASS (na_tray_child_parent_class)->realize (widget);
-
- window = gtk_widget_get_window (widget);
-
- if (child->has_alpha)
- {
- /* We have real transparency with an ARGB visual and the Composite
- * extension. */
-
- /* Set a transparent background */
- cairo_pattern_t *transparent = cairo_pattern_create_rgba (0, 0, 0, 0);
-G_GNUC_BEGIN_IGNORE_DEPRECATIONS
- gdk_window_set_background_pattern (window, transparent);
-G_GNUC_END_IGNORE_DEPRECATIONS
- cairo_pattern_destroy (transparent);
-
- child->parent_relative_bg = FALSE;
- }
- else if (visual == gdk_window_get_visual (gdk_window_get_parent (window)))
- {
- /* Otherwise, if the visual matches the visual of the parent window, we
- * can use a parent-relative background and fake transparency. */
-G_GNUC_BEGIN_IGNORE_DEPRECATIONS
- gdk_window_set_background_pattern (window, NULL);
-G_GNUC_END_IGNORE_DEPRECATIONS
-
- child->parent_relative_bg = TRUE;
- }
- else
- {
- /* Nothing to do; the icon will sit on top of an ugly gray box */
- child->parent_relative_bg = FALSE;
- }
-
- gtk_widget_set_app_paintable (GTK_WIDGET (child),
- child->parent_relative_bg || child->has_alpha);
-
- /* Double-buffering will interfere with the parent-relative-background fake
- * transparency, since the double-buffer code doesn't know how to fill in the
- * background of the double-buffer correctly.
- * The function is deprecated because it is only meaningful on X11 - the
- * same is true for XEmbed of course, so just ignore the warning.
- */
-G_GNUC_BEGIN_IGNORE_DEPRECATIONS
- gtk_widget_set_double_buffered (GTK_WIDGET (child),
- child->parent_relative_bg);
-G_GNUC_END_IGNORE_DEPRECATIONS
-}
-
-static void
-na_tray_child_style_set (GtkWidget *widget,
- GtkStyle *previous_style)
-{
- /* The default handler resets the background according to the new style.
- * We either use a transparent background or a parent-relative background
- * and ignore the style background. So, just don't chain up.
- */
-}
-
-#if 0
-/* This is adapted from code that was commented out in na-tray-manager.c; the
- * code in na-tray-manager.c wouldn't have worked reliably, this will. So maybe
- * it can be re-enabled. On other hand, things seem to be working fine without
- * it.
- *
- * If reenabling, you need to hook it up in na_tray_child_class_init().
- */
-static void
-na_tray_child_size_request (GtkWidget *widget,
- GtkRequisition *request)
-{
- GTK_WIDGET_CLASS (na_tray_child_parent_class)->size_request (widget, request);
-
- /*
- * Make sure the icons have a meaningful size ..
- */
- if ((request->width < 16) || (request->height < 16))
- {
- gint nw = MAX (24, request->width);
- gint nh = MAX (24, request->height);
- g_warning ("Tray icon has requested a size of (%ix%i), resizing to (%ix%i)",
- req.width, req.height, nw, nh);
- request->width = nw;
- request->height = nh;
- }
-}
-#endif
-
-static void
-na_tray_child_size_allocate (GtkWidget *widget,
- GtkAllocation *allocation)
-{
- NaTrayChild *child = NA_TRAY_CHILD (widget);
- GtkAllocation widget_allocation;
- gboolean moved, resized;
-
- gtk_widget_get_allocation (widget, &widget_allocation);
-
- moved = (allocation->x != widget_allocation.x ||
- allocation->y != widget_allocation.y);
- resized = (allocation->width != widget_allocation.width ||
- allocation->height != widget_allocation.height);
-
- /* When we are allocating the widget while mapped we need special handling
- * for both real and fake transparency.
- *
- * Real transparency: we need to invalidate and trigger a redraw of the old
- * and new areas. (GDK really should handle this for us, but doesn't as of
- * GTK+-2.14)
- *
- * Fake transparency: if the widget moved, we need to force the contents to
- * be redrawn with the new offset for the parent-relative background.
- */
- if ((moved || resized) && gtk_widget_get_mapped (widget))
- {
- if (na_tray_child_has_alpha (child))
- gdk_window_invalidate_rect (gdk_window_get_parent (gtk_widget_get_window (widget)),
- &widget_allocation, FALSE);
- }
-
- GTK_WIDGET_CLASS (na_tray_child_parent_class)->size_allocate (widget,
- allocation);
-
- if ((moved || resized) && gtk_widget_get_mapped (widget))
- {
- if (na_tray_child_has_alpha (NA_TRAY_CHILD (widget)))
- gdk_window_invalidate_rect (gdk_window_get_parent (gtk_widget_get_window (widget)),
- &widget_allocation, FALSE);
- else if (moved && child->parent_relative_bg)
- na_tray_child_force_redraw (child);
- }
-}
-
-/* The plug window should completely occupy the area of the child, so we won't
- * get a draw event. But in case we do (the plug unmaps itself, say), this
- * draw handler draws with real or fake transparency.
- */
-static gboolean
-na_tray_child_draw (GtkWidget *widget,
- cairo_t *cr)
+struct _NaTrayChild
{
- NaTrayChild *child = NA_TRAY_CHILD (widget);
+ NaXembed parent_instance;
+ guint parent_relative_bg : 1;
+};
- if (na_tray_child_has_alpha (child))
- {
- /* Clear to transparent */
- cairo_set_source_rgba (cr, 0, 0, 0, 0);
- cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
- cairo_paint (cr);
- }
- else if (child->parent_relative_bg)
- {
- GdkWindow *window;
- cairo_surface_t *target;
- GdkRectangle clip_rect;
-
- window = gtk_widget_get_window (widget);
- target = cairo_get_group_target (cr);
-
- gdk_cairo_get_clip_rectangle (cr, &clip_rect);
-
- /* Clear to parent-relative pixmap
- * We need to use direct X access here because GDK doesn't know about
- * the parent relative pixmap. */
- cairo_surface_flush (target);
-
- XClearArea (GDK_WINDOW_XDISPLAY (window),
- GDK_WINDOW_XID (window),
- clip_rect.x, clip_rect.y,
- clip_rect.width, clip_rect.height,
- False);
- cairo_surface_mark_dirty_rectangle (target,
- clip_rect.x, clip_rect.y,
- clip_rect.width, clip_rect.height);
- }
-
- return FALSE;
-}
+G_DEFINE_TYPE (NaTrayChild, na_tray_child, NA_TYPE_XEMBED)
static void
na_tray_child_init (NaTrayChild *child)
@@ -228,78 +41,47 @@ na_tray_child_init (NaTrayChild *child)
static void
na_tray_child_class_init (NaTrayChildClass *klass)
{
- GObjectClass *gobject_class;
- GtkWidgetClass *widget_class;
-
- gobject_class = (GObjectClass *)klass;
- widget_class = (GtkWidgetClass *)klass;
-
- gobject_class->finalize = na_tray_child_finalize;
- widget_class->style_set = na_tray_child_style_set;
- widget_class->realize = na_tray_child_realize;
- widget_class->size_allocate = na_tray_child_size_allocate;
- widget_class->draw = na_tray_child_draw;
}
-GtkWidget *
-na_tray_child_new (GdkScreen *screen,
- Window icon_window)
+NaTrayChild *
+na_tray_child_new (MetaX11Display *x11_display,
+ Window icon_window)
{
XWindowAttributes window_attributes;
- GdkDisplay *display;
Display *xdisplay;
NaTrayChild *child;
- GdkVisual *visual;
- gboolean visual_has_alpha;
- int red_prec, green_prec, blue_prec, depth;
int result;
- g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
+ g_return_val_if_fail (META_IS_X11_DISPLAY (x11_display), NULL);
g_return_val_if_fail (icon_window != None, NULL);
- xdisplay = GDK_SCREEN_XDISPLAY (screen);
- display = gdk_x11_lookup_xdisplay (xdisplay);
+ xdisplay = meta_x11_display_get_xdisplay (x11_display);
/* We need to determine the visual of the window we are embedding and create
* the socket in the same visual.
*/
- gdk_x11_display_error_trap_push (display);
+ meta_x11_error_trap_push (x11_display);
result = XGetWindowAttributes (xdisplay, icon_window,
&window_attributes);
- gdk_x11_display_error_trap_pop_ignored (display);
+ meta_x11_error_trap_pop (x11_display);
if (!result) /* Window already gone */
return NULL;
- visual = gdk_x11_screen_lookup_visual (screen,
- window_attributes.visual->visualid);
- if (!visual) /* Icon window is on another screen? */
- return NULL;
-
- child = g_object_new (NA_TYPE_TRAY_CHILD, NULL);
- child->icon_window = icon_window;
-
- gtk_widget_set_visual (GTK_WIDGET (child), visual);
-
- /* We have alpha if the visual has something other than red, green,
- * and blue */
- gdk_visual_get_red_pixel_details (visual, NULL, NULL, &red_prec);
- gdk_visual_get_green_pixel_details (visual, NULL, NULL, &green_prec);
- gdk_visual_get_blue_pixel_details (visual, NULL, NULL, &blue_prec);
- depth = gdk_visual_get_depth (visual);
-
- visual_has_alpha = red_prec + blue_prec + green_prec < depth;
- child->has_alpha = visual_has_alpha;
+ child = g_object_new (NA_TYPE_TRAY_CHILD,
+ "x11-display", x11_display,
+ NULL);
- return GTK_WIDGET (child);
+ return child;
}
char *
na_tray_child_get_title (NaTrayChild *child)
{
char *retval = NULL;
- GdkDisplay *display;
+ MetaX11Display *x11_display;
+ Display *xdisplay;
Atom utf8_string, atom, type;
int result;
int format;
@@ -309,22 +91,23 @@ na_tray_child_get_title (NaTrayChild *child)
g_return_val_if_fail (NA_IS_TRAY_CHILD (child), NULL);
- display = gtk_widget_get_display (GTK_WIDGET (child));
+ x11_display = na_xembed_get_x11_display (NA_XEMBED (child));
+ xdisplay = meta_x11_display_get_xdisplay (x11_display);
- utf8_string = gdk_x11_get_xatom_by_name_for_display (display, "UTF8_STRING");
- atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_NAME");
+ utf8_string = XInternAtom (xdisplay, "UTF8_STRING", False);
+ atom = XInternAtom (xdisplay, "_NET_WM_NAME", False);
- gdk_x11_display_error_trap_push (display);
+ meta_x11_error_trap_push (x11_display);
- result = XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display),
- child->icon_window,
+ result = XGetWindowProperty (xdisplay,
+ na_xembed_get_plug_window (NA_XEMBED (child)),
atom,
0, G_MAXLONG,
False, utf8_string,
&type, &format, &nitems,
&bytes_after, (guchar **)&val);
-
- if (gdk_x11_display_error_trap_pop (display) || result != Success)
+
+ if (meta_x11_error_trap_pop_with_return (x11_display) || result != Success)
return NULL;
if (type != utf8_string ||
@@ -349,73 +132,6 @@ na_tray_child_get_title (NaTrayChild *child)
return retval;
}
-/**
- * na_tray_child_has_alpha;
- * @child: a #NaTrayChild
- *
- * Checks if the child has an ARGB visual and real alpha transparence.
- * (as opposed to faked alpha transparency with an parent-relative
- * background)
- *
- * Return value: %TRUE if the child has an alpha transparency
- */
-gboolean
-na_tray_child_has_alpha (NaTrayChild *child)
-{
- g_return_val_if_fail (NA_IS_TRAY_CHILD (child), FALSE);
-
- return child->has_alpha;
-}
-
-/* If we are faking transparency with a window-relative background, force a
- * redraw of the icon. This should be called if the background changes or if
- * the child is shifted with respect to the background.
- */
-void
-na_tray_child_force_redraw (NaTrayChild *child)
-{
- GtkWidget *widget = GTK_WIDGET (child);
-
- if (gtk_widget_get_mapped (widget) && child->parent_relative_bg)
- {
-#if 1
- /* Sending an ExposeEvent might cause redraw problems if the
- * icon is expecting the server to clear-to-background before
- * the redraw. It should be ok for GtkStatusIcon or EggTrayIcon.
- */
- GdkDisplay *display = gtk_widget_get_display (widget);
- Display *xdisplay = GDK_DISPLAY_XDISPLAY (display);
- XEvent xev;
- GdkWindow *plug_window;
- GtkAllocation allocation;
-
- plug_window = gtk_socket_get_plug_window (GTK_SOCKET (child));
- gtk_widget_get_allocation (widget, &allocation);
-
- xev.xexpose.type = Expose;
- xev.xexpose.window = GDK_WINDOW_XID (plug_window);
- xev.xexpose.x = 0;
- xev.xexpose.y = 0;
- xev.xexpose.width = allocation.width;
- xev.xexpose.height = allocation.height;
- xev.xexpose.count = 0;
-
- gdk_x11_display_error_trap_push (display);
- XSendEvent (xdisplay,
- xev.xexpose.window,
- False, ExposureMask,
- &xev);
- gdk_x11_display_error_trap_pop_ignored (display);
-#else
- /* Hiding and showing is the safe way to do it, but can result in more
- * flickering.
- */
- gdk_window_hide (widget->window);
- gdk_window_show (widget->window);
-#endif
- }
-}
-
/* from libwnck/xutils.c, comes as LGPLv2+ */
static char *
latin1_to_utf8 (const char *latin1)
@@ -437,21 +153,22 @@ latin1_to_utf8 (const char *latin1)
/* derived from libwnck/xutils.c, comes as LGPLv2+ */
static void
-_get_wmclass (Display *xdisplay,
- Window xwindow,
- char **res_class,
- char **res_name)
+_get_wmclass (MetaX11Display *x11_display,
+ Window xwindow,
+ char **res_class,
+ char **res_name)
{
- GdkDisplay *display;
XClassHint ch;
+ Display *xdisplay;
ch.res_name = NULL;
ch.res_class = NULL;
- display = gdk_x11_lookup_xdisplay (xdisplay);
- gdk_x11_display_error_trap_push (display);
+ xdisplay = meta_x11_display_get_xdisplay (x11_display);
+
+ meta_x11_error_trap_push (x11_display);
XGetClassHint (xdisplay, xwindow, &ch);
- gdk_x11_display_error_trap_pop_ignored (display);
+ meta_x11_error_trap_pop (x11_display);
if (res_class)
*res_class = NULL;
@@ -491,14 +208,14 @@ na_tray_child_get_wm_class (NaTrayChild *child,
char **res_name,
char **res_class)
{
- GdkDisplay *display;
+ MetaX11Display *x11_display;
g_return_if_fail (NA_IS_TRAY_CHILD (child));
- display = gtk_widget_get_display (GTK_WIDGET (child));
+ x11_display = na_xembed_get_x11_display (NA_XEMBED (child));
- _get_wmclass (GDK_DISPLAY_XDISPLAY (display),
- child->icon_window,
+ _get_wmclass (x11_display,
+ na_xembed_get_plug_window (NA_XEMBED (child)),
res_class,
res_name);
}
diff --git a/src/tray/na-tray-child.h b/src/tray/na-tray-child.h
index d14367642..c50a0f928 100644
--- a/src/tray/na-tray-child.h
+++ b/src/tray/na-tray-child.h
@@ -21,42 +21,18 @@
#ifndef __NA_TRAY_CHILD_H__
#define __NA_TRAY_CHILD_H__
-#include <gtk/gtk.h>
-#include <gtk/gtkx.h>
+#include "na-xembed.h"
-G_BEGIN_DECLS
-
-#define NA_TYPE_TRAY_CHILD (na_tray_child_get_type ())
-#define NA_TRAY_CHILD(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NA_TYPE_TRAY_CHILD, NaTrayChild))
-#define NA_TRAY_CHILD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NA_TYPE_TRAY_CHILD, NaTrayChildClass))
-#define NA_IS_TRAY_CHILD(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NA_TYPE_TRAY_CHILD))
-#define NA_IS_TRAY_CHILD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NA_TYPE_TRAY_CHILD))
-#define NA_TRAY_CHILD_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NA_TYPE_TRAY_CHILD, NaTrayChildClass))
-
-typedef struct _NaTrayChild NaTrayChild;
-typedef struct _NaTrayChildClass NaTrayChildClass;
-typedef struct _NaTrayChildChild NaTrayChildChild;
+#include <meta/meta-x11-errors.h>
-struct _NaTrayChild
-{
- GtkSocket parent_instance;
- Window icon_window;
- guint has_alpha : 1;
- guint parent_relative_bg : 1;
-};
-
-struct _NaTrayChildClass
-{
- GtkSocketClass parent_class;
-};
+G_BEGIN_DECLS
-GType na_tray_child_get_type (void);
+#define NA_TYPE_TRAY_CHILD (na_tray_child_get_type ())
+G_DECLARE_FINAL_TYPE (NaTrayChild, na_tray_child, NA, TRAY_CHILD, NaXembed)
-GtkWidget *na_tray_child_new (GdkScreen *screen,
- Window icon_window);
+NaTrayChild *na_tray_child_new (MetaX11Display *x11_display,
+ Window icon_window);
char *na_tray_child_get_title (NaTrayChild *child);
-gboolean na_tray_child_has_alpha (NaTrayChild *child);
-void na_tray_child_force_redraw (NaTrayChild *child);
void na_tray_child_get_wm_class (NaTrayChild *child,
char **res_name,
char **res_class);
diff --git a/src/tray/na-tray-manager.c b/src/tray/na-tray-manager.c
index 15e1d80ec..1fbb7ac20 100644
--- a/src/tray/na-tray-manager.c
+++ b/src/tray/na-tray-manager.c
@@ -24,13 +24,8 @@
#include "na-tray-manager.h"
-#if defined (GDK_WINDOWING_X11)
-#include <gdk/gdkx.h>
#include <X11/Xatom.h>
-#elif defined (GDK_WINDOWING_WIN32)
-#include <gdk/gdkwin32.h>
-#endif
-#include <gtk/gtk.h>
+#include <X11/Xutil.h>
/* Signals */
enum
@@ -43,36 +38,53 @@ enum
LAST_SIGNAL
};
-enum {
+static guint manager_signals[LAST_SIGNAL];
+
+enum
+{
PROP_0,
- PROP_ORIENTATION
+ PROP_X11_DISPLAY,
+ N_PROPS,
};
+static GParamSpec *props[N_PROPS];
+
typedef struct
{
long id, len;
long remaining_len;
-
+
long timeout;
char *str;
-#ifdef GDK_WINDOWING_X11
Window window;
-#endif
} PendingMessage;
-static guint manager_signals[LAST_SIGNAL];
+struct _NaTrayManager
+{
+ GObject parent_instance;
+
+ MetaX11Display *x11_display;
+
+ Atom selection_atom;
+ Atom opcode_atom;
+ Atom message_data_atom;
+
+ Window window;
+ ClutterColor fg;
+ ClutterColor error;
+ ClutterColor warning;
+ ClutterColor success;
+
+ unsigned int event_func_id;
+
+ GList *messages;
+ GHashTable *children;
+};
#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
-
-#ifdef GDK_WINDOWING_X11
-static gboolean na_tray_manager_check_running_screen_x11 (void);
-#endif
-
static void na_tray_manager_finalize (GObject *object);
static void na_tray_manager_set_property (GObject *object,
guint prop_id,
@@ -90,8 +102,8 @@ G_DEFINE_TYPE (NaTrayManager, na_tray_manager, G_TYPE_OBJECT)
static void
na_tray_manager_init (NaTrayManager *manager)
{
- manager->invisible = NULL;
- manager->socket_table = g_hash_table_new (NULL, NULL);
+ manager->window = None;
+ manager->children = g_hash_table_new (NULL, NULL);
manager->fg.red = 0;
manager->fg.green = 0;
@@ -121,83 +133,69 @@ na_tray_manager_class_init (NaTrayManagerClass *klass)
gobject_class->set_property = na_tray_manager_set_property;
gobject_class->get_property = na_tray_manager_get_property;
- g_object_class_install_property (gobject_class,
- PROP_ORIENTATION,
- g_param_spec_enum ("orientation",
- "orientation",
- "orientation",
- GTK_TYPE_ORIENTATION,
- GTK_ORIENTATION_HORIZONTAL,
- G_PARAM_READWRITE |
- G_PARAM_STATIC_STRINGS |
- G_PARAM_CONSTRUCT));
-
manager_signals[TRAY_ICON_ADDED] =
g_signal_new ("tray_icon_added",
- G_OBJECT_CLASS_TYPE (klass),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (NaTrayManagerClass, tray_icon_added),
+ G_OBJECT_CLASS_TYPE (klass),
+ G_SIGNAL_RUN_LAST, 0,
NULL, NULL, NULL,
- G_TYPE_NONE, 1,
- GTK_TYPE_SOCKET);
+ G_TYPE_NONE, 1,
+ NA_TYPE_TRAY_CHILD);
manager_signals[TRAY_ICON_REMOVED] =
g_signal_new ("tray_icon_removed",
- G_OBJECT_CLASS_TYPE (klass),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (NaTrayManagerClass, tray_icon_removed),
+ G_OBJECT_CLASS_TYPE (klass),
+ G_SIGNAL_RUN_LAST, 0,
NULL, NULL, NULL,
- G_TYPE_NONE, 1,
- GTK_TYPE_SOCKET);
+ G_TYPE_NONE, 1,
+ NA_TYPE_TRAY_CHILD);
manager_signals[MESSAGE_SENT] =
g_signal_new ("message_sent",
- G_OBJECT_CLASS_TYPE (klass),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (NaTrayManagerClass, message_sent),
+ G_OBJECT_CLASS_TYPE (klass),
+ G_SIGNAL_RUN_LAST, 0,
NULL, NULL, NULL,
- G_TYPE_NONE, 4,
- GTK_TYPE_SOCKET,
- G_TYPE_STRING,
- G_TYPE_LONG,
- G_TYPE_LONG);
+ G_TYPE_NONE, 4,
+ NA_TYPE_TRAY_CHILD,
+ G_TYPE_STRING,
+ G_TYPE_LONG,
+ G_TYPE_LONG);
manager_signals[MESSAGE_CANCELLED] =
g_signal_new ("message_cancelled",
- G_OBJECT_CLASS_TYPE (klass),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (NaTrayManagerClass, message_cancelled),
+ G_OBJECT_CLASS_TYPE (klass),
+ G_SIGNAL_RUN_LAST, 0,
NULL, NULL, NULL,
- G_TYPE_NONE, 2,
- GTK_TYPE_SOCKET,
- G_TYPE_LONG);
+ G_TYPE_NONE, 2,
+ NA_TYPE_TRAY_CHILD,
+ G_TYPE_LONG);
manager_signals[LOST_SELECTION] =
g_signal_new ("lost_selection",
- G_OBJECT_CLASS_TYPE (klass),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (NaTrayManagerClass, lost_selection),
+ G_OBJECT_CLASS_TYPE (klass),
+ G_SIGNAL_RUN_LAST, 0,
NULL, NULL, NULL,
- G_TYPE_NONE, 0);
-
-#if defined (GDK_WINDOWING_X11)
- /* Nothing */
-#elif defined (GDK_WINDOWING_WIN32)
- g_warning ("Port NaTrayManager to Win32");
-#else
- g_warning ("Port NaTrayManager to this GTK+ backend");
-#endif
+ G_TYPE_NONE, 0);
+
+ props[PROP_X11_DISPLAY] =
+ g_param_spec_object ("x11-display",
+ "x11-display",
+ "x11-display",
+ META_TYPE_X11_DISPLAY,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY);
+
+ g_object_class_install_properties (gobject_class, N_PROPS, props);
}
static void
na_tray_manager_finalize (GObject *object)
{
NaTrayManager *manager;
-
+
manager = NA_TRAY_MANAGER (object);
na_tray_manager_unmanage (manager);
g_list_free (manager->messages);
- g_hash_table_destroy (manager->socket_table);
-
+ g_hash_table_destroy (manager->children);
+
G_OBJECT_CLASS (na_tray_manager_parent_class)->finalize (object);
}
@@ -211,8 +209,8 @@ na_tray_manager_set_property (GObject *object,
switch (prop_id)
{
- case PROP_ORIENTATION:
- na_tray_manager_set_orientation (manager, g_value_get_enum (value));
+ case PROP_X11_DISPLAY:
+ manager->x11_display = g_value_get_object (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -230,8 +228,8 @@ na_tray_manager_get_property (GObject *object,
switch (prop_id)
{
- case PROP_ORIENTATION:
- g_value_set_enum (value, manager->orientation);
+ case PROP_X11_DISPLAY:
+ g_value_set_object (value, manager->x11_display);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -240,26 +238,24 @@ na_tray_manager_get_property (GObject *object,
}
NaTrayManager *
-na_tray_manager_new (void)
+na_tray_manager_new (MetaX11Display *x11_display)
{
- NaTrayManager *manager;
-
- manager = g_object_new (NA_TYPE_TRAY_MANAGER, NULL);
-
- return manager;
+ return g_object_new (NA_TYPE_TRAY_MANAGER,
+ "x11-display", x11_display,
+ NULL);
}
-#ifdef GDK_WINDOWING_X11
-
static gboolean
-na_tray_manager_plug_removed (GtkSocket *socket,
- NaTrayManager *manager)
+na_tray_manager_plug_removed (NaTrayChild *tray_child,
+ NaTrayManager *manager)
{
- NaTrayChild *child = NA_TRAY_CHILD (socket);
+ Window icon_window;
+
+ icon_window = na_xembed_get_plug_window (NA_XEMBED (tray_child));
- g_hash_table_remove (manager->socket_table,
- GINT_TO_POINTER (child->icon_window));
- g_signal_emit (manager, manager_signals[TRAY_ICON_REMOVED], 0, child);
+ g_hash_table_remove (manager->children,
+ GINT_TO_POINTER (icon_window));
+ g_signal_emit (manager, manager_signals[TRAY_ICON_REMOVED], 0, tray_child);
/* This destroys the socket. */
return FALSE;
@@ -267,49 +263,40 @@ na_tray_manager_plug_removed (GtkSocket *socket,
static void
na_tray_manager_handle_dock_request (NaTrayManager *manager,
- XClientMessageEvent *xevent)
+ XClientMessageEvent *xevent)
{
Window icon_window = xevent->data.l[2];
- GtkWidget *child;
+ NaTrayChild *child;
- if (g_hash_table_lookup (manager->socket_table,
+ if (g_hash_table_lookup (manager->children,
GINT_TO_POINTER (icon_window)))
{
/* We already got this notification earlier, ignore this one */
return;
}
- child = na_tray_child_new (manager->screen, icon_window);
+ child = na_tray_child_new (manager->x11_display, icon_window);
if (child == NULL) /* already gone or other error */
return;
g_signal_emit (manager, manager_signals[TRAY_ICON_ADDED], 0,
- child);
-
- /* If the child wasn't attached, then destroy it */
-
- if (!GTK_IS_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (child))))
- {
- gtk_widget_destroy (child);
- return;
- }
+ child);
- g_signal_connect (child, "plug_removed",
- G_CALLBACK (na_tray_manager_plug_removed), manager);
+ g_signal_connect (child, "plug-removed",
+ G_CALLBACK (na_tray_manager_plug_removed), manager);
- gtk_socket_add_id (GTK_SOCKET (child), icon_window);
+ na_xembed_add_id (NA_XEMBED (child), icon_window);
- if (!gtk_socket_get_plug_window (GTK_SOCKET (child)))
+ if (!na_xembed_get_plug_window (NA_XEMBED (child)))
{
/* Embedding failed, we won't get a plug-removed signal */
- /* This signal destroys the socket */
+ /* This signal destroys the tray child */
g_signal_emit (manager, manager_signals[TRAY_ICON_REMOVED], 0, child);
return;
}
- g_hash_table_insert (manager->socket_table,
+ g_hash_table_insert (manager->children,
GINT_TO_POINTER (icon_window), child);
- gtk_widget_show (child);
}
static void
@@ -321,11 +308,11 @@ pending_message_free (PendingMessage *message)
static void
na_tray_manager_handle_message_data (NaTrayManager *manager,
- XClientMessageEvent *xevent)
+ XClientMessageEvent *xevent)
{
GList *p;
- int len;
-
+ int len;
+
/* Try to see if we can find the pending message in the list */
for (p = manager->messages; p; p = p->next)
{
@@ -340,21 +327,23 @@ na_tray_manager_handle_message_data (NaTrayManager *manager,
&xevent->data, len);
msg->remaining_len -= len;
- if (msg->remaining_len == 0)
- {
- GtkSocket *socket;
+ if (msg->remaining_len == 0)
+ {
+ NaTrayChild *child;
- socket = g_hash_table_lookup (manager->socket_table,
- GINT_TO_POINTER (msg->window));
+ child = g_hash_table_lookup (manager->children,
+ GINT_TO_POINTER (msg->window));
- if (socket)
- g_signal_emit (manager, manager_signals[MESSAGE_SENT], 0,
- socket, msg->str, msg->id, msg->timeout);
+ if (child)
+ {
+ g_signal_emit (manager, manager_signals[MESSAGE_SENT], 0,
+ child, msg->str, msg->id, msg->timeout);
+ }
- pending_message_free (msg);
- manager->messages = g_list_remove_link (manager->messages, p);
+ pending_message_free (msg);
+ manager->messages = g_list_remove_link (manager->messages, p);
g_list_free_1 (p);
- }
+ }
break;
}
@@ -363,24 +352,22 @@ na_tray_manager_handle_message_data (NaTrayManager *manager,
static void
na_tray_manager_handle_begin_message (NaTrayManager *manager,
- XClientMessageEvent *xevent)
+ XClientMessageEvent *xevent)
{
- GtkSocket *socket;
- GList *p;
+ NaTrayChild *child;
+ GList *p;
PendingMessage *msg;
- long timeout;
- long len;
- long id;
+ long timeout, len, id;
- socket = g_hash_table_lookup (manager->socket_table,
- GINT_TO_POINTER (xevent->window));
+ child = g_hash_table_lookup (manager->children,
+ GINT_TO_POINTER (xevent->window));
/* we don't know about this tray icon, so ignore the message */
- if (!socket)
+ if (!child)
return;
timeout = xevent->data.l[2];
- len = xevent->data.l[3];
- id = xevent->data.l[4];
+ len = xevent->data.l[3];
+ id = xevent->data.l[4];
/* Check if the same message is already in the queue and remove it if so */
for (p = manager->messages; p; p = p->next)
@@ -401,7 +388,7 @@ na_tray_manager_handle_begin_message (NaTrayManager *manager,
if (len == 0)
{
g_signal_emit (manager, manager_signals[MESSAGE_SENT], 0,
- socket, "", id, timeout);
+ child, "", id, timeout);
}
else
{
@@ -420,14 +407,14 @@ na_tray_manager_handle_begin_message (NaTrayManager *manager,
static void
na_tray_manager_handle_cancel_message (NaTrayManager *manager,
- XClientMessageEvent *xevent)
+ XClientMessageEvent *xevent)
{
- GList *p;
- GtkSocket *socket;
- long id;
+ NaTrayChild *child;
+ GList *p;
+ long id;
id = xevent->data.l[2];
-
+
/* Check if the message is in the queue and remove it if so */
for (p = manager->messages; p; p = p->next)
{
@@ -443,166 +430,98 @@ na_tray_manager_handle_cancel_message (NaTrayManager *manager,
}
}
- socket = g_hash_table_lookup (manager->socket_table,
- GINT_TO_POINTER (xevent->window));
-
- if (socket)
+ child = g_hash_table_lookup (manager->children,
+ GINT_TO_POINTER (xevent->window));
+
+ if (child)
{
g_signal_emit (manager, manager_signals[MESSAGE_CANCELLED], 0,
- socket, xevent->data.l[2]);
+ child, xevent->data.l[2]);
}
}
-static GdkFilterReturn
-na_tray_manager_window_filter (GdkXEvent *xev,
- GdkEvent *event,
- gpointer data)
+static void
+na_tray_manager_event_func (MetaX11Display *x11_display,
+ XEvent *xevent,
+ gpointer data)
{
- XEvent *xevent = (GdkXEvent *)xev;
NaTrayManager *manager = data;
- if (xevent->type == ClientMessage)
+ if (xevent->type == ClientMessage &&
+ xevent->xany.window == manager->window)
{
/* _NET_SYSTEM_TRAY_OPCODE: SYSTEM_TRAY_REQUEST_DOCK */
if (xevent->xclient.message_type == manager->opcode_atom &&
- xevent->xclient.data.l[1] == SYSTEM_TRAY_REQUEST_DOCK)
- {
+ xevent->xclient.data.l[1] == SYSTEM_TRAY_REQUEST_DOCK)
+ {
na_tray_manager_handle_dock_request (manager,
(XClientMessageEvent *) xevent);
- return GDK_FILTER_REMOVE;
- }
+ }
/* _NET_SYSTEM_TRAY_OPCODE: SYSTEM_TRAY_BEGIN_MESSAGE */
else if (xevent->xclient.message_type == manager->opcode_atom &&
- xevent->xclient.data.l[1] == SYSTEM_TRAY_BEGIN_MESSAGE)
+ xevent->xclient.data.l[1] == SYSTEM_TRAY_BEGIN_MESSAGE)
{
na_tray_manager_handle_begin_message (manager,
- (XClientMessageEvent *) event);
- return GDK_FILTER_REMOVE;
+ (XClientMessageEvent *) xevent);
}
/* _NET_SYSTEM_TRAY_OPCODE: SYSTEM_TRAY_CANCEL_MESSAGE */
else if (xevent->xclient.message_type == manager->opcode_atom &&
- xevent->xclient.data.l[1] == SYSTEM_TRAY_CANCEL_MESSAGE)
+ xevent->xclient.data.l[1] == SYSTEM_TRAY_CANCEL_MESSAGE)
{
na_tray_manager_handle_cancel_message (manager,
- (XClientMessageEvent *) event);
- return GDK_FILTER_REMOVE;
+ (XClientMessageEvent *) xevent);
}
/* _NET_SYSTEM_TRAY_MESSAGE_DATA */
else if (xevent->xclient.message_type == manager->message_data_atom)
{
na_tray_manager_handle_message_data (manager,
- (XClientMessageEvent *) event);
- return GDK_FILTER_REMOVE;
+ (XClientMessageEvent *) xevent);
}
}
- else if (xevent->type == SelectionClear)
+ else if (xevent->type == SelectionClear &&
+ xevent->xany.window == manager->window)
{
g_signal_emit (manager, manager_signals[LOST_SELECTION], 0);
na_tray_manager_unmanage (manager);
}
-
- return GDK_FILTER_CONTINUE;
-}
-
-#if 0
-//FIXME investigate why this doesn't work
-static gboolean
-na_tray_manager_selection_clear_event (GtkWidget *widget,
- GdkEventSelection *event,
- NaTrayManager *manager)
-{
- g_signal_emit (manager, manager_signals[LOST_SELECTION], 0);
- na_tray_manager_unmanage (manager);
-
- return FALSE;
}
-#endif
-#endif
static void
na_tray_manager_unmanage (NaTrayManager *manager)
{
-#ifdef GDK_WINDOWING_X11
- GdkDisplay *display;
- guint32 timestamp;
- GtkWidget *invisible;
- GdkWindow *window;
+ Display *xdisplay;
- if (manager->invisible == NULL)
+ if (manager->window == None)
return;
- invisible = manager->invisible;
- window = gtk_widget_get_window (invisible);
+ xdisplay = meta_x11_display_get_xdisplay (manager->x11_display);
- g_assert (GTK_IS_INVISIBLE (invisible));
- g_assert (gtk_widget_get_realized (invisible));
- g_assert (GDK_IS_WINDOW (window));
-
- display = gtk_widget_get_display (invisible);
-
- if (gdk_selection_owner_get_for_display (display, manager->selection_atom) ==
- window)
+ if (XGetSelectionOwner (xdisplay, manager->selection_atom) == manager->window)
{
- timestamp = gdk_x11_get_server_time (window);
- gdk_selection_owner_set_for_display (display,
- NULL,
- manager->selection_atom,
- timestamp,
- TRUE);
+ XSetSelectionOwner (xdisplay,
+ manager->selection_atom,
+ None,
+ CurrentTime);
}
- gdk_window_remove_filter (window,
- na_tray_manager_window_filter, manager);
-
- manager->invisible = NULL; /* prior to destroy for reentrancy paranoia */
- gtk_widget_destroy (invisible);
- g_object_unref (G_OBJECT (invisible));
-#endif
-}
+ meta_x11_display_remove_event_func (manager->x11_display,
+ manager->event_func_id);
+ manager->event_func_id = 0;
-static void
-na_tray_manager_set_orientation_property (NaTrayManager *manager)
-{
-#ifdef GDK_WINDOWING_X11
- GdkWindow *window;
- GdkDisplay *display;
- Atom orientation_atom;
- gulong data[1];
-
- g_return_if_fail (manager->invisible != NULL);
- window = gtk_widget_get_window (manager->invisible);
- g_return_if_fail (window != NULL);
-
- display = gtk_widget_get_display (manager->invisible);
- orientation_atom = gdk_x11_get_xatom_by_name_for_display (display,
- "_NET_SYSTEM_TRAY_ORIENTATION");
-
- data[0] = manager->orientation == GTK_ORIENTATION_HORIZONTAL ?
- SYSTEM_TRAY_ORIENTATION_HORZ :
- SYSTEM_TRAY_ORIENTATION_VERT;
-
- XChangeProperty (GDK_DISPLAY_XDISPLAY (display),
- GDK_WINDOW_XID (window),
- orientation_atom,
- XA_CARDINAL, 32,
- PropModeReplace,
- (guchar *) &data, 1);
-#endif
+ XDestroyWindow (xdisplay, manager->window);
+ manager->window = None;
}
static void
na_tray_manager_set_visual_property (NaTrayManager *manager)
{
-#ifdef GDK_WINDOWING_X11
- GdkWindow *window;
- GdkDisplay *display;
- Visual *xvisual;
- Atom visual_atom;
- gulong data[1];
+ Display *xdisplay;
+ Atom visual_atom;
+ XVisualInfo xvisual_info;
+ gulong data[1];
+ int result;
- g_return_if_fail (manager->invisible != NULL);
- window = gtk_widget_get_window (manager->invisible);
- g_return_if_fail (window != NULL);
+ g_return_if_fail (manager->window != None);
/* The visual property is a hint to the tray icons as to what visual they
* should use for their windows. If the X server has RGBA colormaps, then
@@ -611,49 +530,35 @@ na_tray_manager_set_visual_property (NaTrayManager *manager)
* the icon to use our colormap, and we'll do some hacks with parent
* relative backgrounds to simulate transparency.
*/
+ xdisplay = meta_x11_display_get_xdisplay (manager->x11_display);
+ visual_atom = XInternAtom (xdisplay, "_NET_SYSTEM_TRAY_VISUAL", False);
- display = gtk_widget_get_display (manager->invisible);
- visual_atom = gdk_x11_get_xatom_by_name_for_display (display,
- "_NET_SYSTEM_TRAY_VISUAL");
+ result = XMatchVisualInfo (xdisplay, DefaultScreen (xdisplay), 32, TrueColor, &xvisual_info);
- if (gdk_screen_get_rgba_visual (manager->screen) != NULL)
- xvisual = GDK_VISUAL_XVISUAL (gdk_screen_get_rgba_visual (manager->screen));
+ if (result == Success)
+ data[0] = xvisual_info.visualid;
else
- {
- /* We actually want the visual of the tray where the icons will
- * be embedded. In almost all cases, this will be the same as the visual
- * of the screen.
- */
- xvisual = GDK_VISUAL_XVISUAL (gdk_screen_get_system_visual (manager->screen));
- }
+ data[0] = XVisualIDFromVisual (DefaultVisual (xdisplay, DefaultScreen (xdisplay)));
- data[0] = XVisualIDFromVisual (xvisual);
-
- XChangeProperty (GDK_DISPLAY_XDISPLAY (display),
- GDK_WINDOW_XID (window),
+ XChangeProperty (xdisplay,
+ manager->window,
visual_atom,
XA_VISUALID, 32,
PropModeReplace,
(guchar *) &data, 1);
-#endif
}
static void
na_tray_manager_set_colors_property (NaTrayManager *manager)
{
-#ifdef GDK_WINDOWING_X11
- GdkWindow *window;
- GdkDisplay *display;
- Atom atom;
- gulong data[12];
+ Display *xdisplay;
+ Atom atom;
+ gulong data[12];
- g_return_if_fail (manager->invisible != NULL);
- window = gtk_widget_get_window (manager->invisible);
- g_return_if_fail (window != NULL);
+ g_return_if_fail (manager->window != None);
- display = gtk_widget_get_display (manager->invisible);
- atom = gdk_x11_get_xatom_by_name_for_display (display,
- "_NET_SYSTEM_TRAY_COLORS");
+ xdisplay = meta_x11_display_get_xdisplay (manager->x11_display);
+ atom = XInternAtom (xdisplay, "_NET_SYSTEM_TRAY_COLORS", False);
data[0] = manager->fg.red * 0x101;
data[1] = manager->fg.green * 0x101;
@@ -668,194 +573,87 @@ na_tray_manager_set_colors_property (NaTrayManager *manager)
data[10] = manager->success.green * 0x101;
data[11] = manager->success.blue * 0x101;
- XChangeProperty (GDK_DISPLAY_XDISPLAY (display),
- GDK_WINDOW_XID (window),
+ XChangeProperty (xdisplay,
+ manager->window,
atom,
XA_CARDINAL, 32,
PropModeReplace,
(guchar *) &data, 12);
-#endif
}
-#ifdef GDK_WINDOWING_X11
-
-static gboolean
-na_tray_manager_manage_screen_x11 (NaTrayManager *manager)
+gboolean
+na_tray_manager_manage (NaTrayManager *manager)
{
- GdkDisplay *display;
- GdkScreen *screen;
- Screen *xscreen;
- GtkWidget *invisible;
- GdkWindow *window;
- char *selection_atom_name;
- guint32 timestamp;
-
+ Display *xdisplay;
+
g_return_val_if_fail (NA_IS_TRAY_MANAGER (manager), FALSE);
- g_return_val_if_fail (manager->screen == NULL, FALSE);
- /* If there's already a manager running on the screen
- * we can't create another one.
- */
-#if 0
- if (na_tray_manager_check_running_screen_x11 ())
- return FALSE;
-#endif
-
- screen = gdk_screen_get_default ();
- manager->screen = screen;
+ xdisplay = meta_x11_display_get_xdisplay (manager->x11_display);
- display = gdk_screen_get_display (screen);
- xscreen = GDK_SCREEN_XSCREEN (screen);
-
- invisible = gtk_invisible_new_for_screen (screen);
- gtk_widget_realize (invisible);
-
- gtk_widget_add_events (invisible,
- GDK_PROPERTY_CHANGE_MASK | GDK_STRUCTURE_MASK);
+ meta_x11_error_trap_push (manager->x11_display);
+ manager->window = XCreateSimpleWindow (xdisplay,
+ XDefaultRootWindow (xdisplay),
+ 0, 0, 1, 1,
+ 0, 0, 0);
+ XSelectInput (xdisplay, manager->window,
+ StructureNotifyMask | PropertyChangeMask);
- selection_atom_name = g_strdup_printf ("_NET_SYSTEM_TRAY_S%d",
- gdk_x11_get_default_screen ());
- manager->selection_atom = gdk_atom_intern (selection_atom_name, FALSE);
- g_free (selection_atom_name);
+ if (meta_x11_error_trap_pop_with_return (manager->x11_display) ||
+ !manager->window)
+ return FALSE;
- manager->invisible = invisible;
- g_object_ref (G_OBJECT (manager->invisible));
+ manager->selection_atom = XInternAtom (xdisplay, "_NET_SYSTEM_TRAY_S0", False);
- na_tray_manager_set_orientation_property (manager);
na_tray_manager_set_visual_property (manager);
na_tray_manager_set_colors_property (manager);
-
- window = gtk_widget_get_window (invisible);
- timestamp = gdk_x11_get_server_time (window);
+ meta_x11_error_trap_push (manager->x11_display);
+
+ XSetSelectionOwner (xdisplay, manager->selection_atom,
+ manager->window, CurrentTime);
/* Check if we could set the selection owner successfully */
- if (gdk_selection_owner_set_for_display (display,
- window,
- manager->selection_atom,
- timestamp,
- TRUE))
+ if (!meta_x11_error_trap_pop_with_return (manager->x11_display))
{
XClientMessageEvent xev;
- GdkAtom opcode_atom;
- GdkAtom message_data_atom;
xev.type = ClientMessage;
- xev.window = RootWindowOfScreen (xscreen);
- xev.message_type = gdk_x11_get_xatom_by_name_for_display (display,
- "MANAGER");
+ xev.window = XDefaultRootWindow (xdisplay);
+ xev.message_type = XInternAtom (xdisplay, "MANAGER", False);
xev.format = 32;
- xev.data.l[0] = timestamp;
- xev.data.l[1] = gdk_x11_atom_to_xatom_for_display (display,
- manager->selection_atom);
- xev.data.l[2] = GDK_WINDOW_XID (window);
- xev.data.l[3] = 0; /* manager specific data */
- xev.data.l[4] = 0; /* manager specific data */
-
- XSendEvent (GDK_DISPLAY_XDISPLAY (display),
- RootWindowOfScreen (xscreen),
- False, StructureNotifyMask, (XEvent *)&xev);
-
- opcode_atom = gdk_atom_intern ("_NET_SYSTEM_TRAY_OPCODE", FALSE);
- manager->opcode_atom = gdk_x11_atom_to_xatom_for_display (display,
- opcode_atom);
-
- message_data_atom = gdk_atom_intern ("_NET_SYSTEM_TRAY_MESSAGE_DATA",
- FALSE);
- manager->message_data_atom = gdk_x11_atom_to_xatom_for_display (display,
- message_data_atom);
-
- /* Add a window filter */
-#if 0
- /* This is for when we lose the selection of _NET_SYSTEM_TRAY_Sx */
- g_signal_connect (invisible, "selection-clear-event",
- G_CALLBACK (na_tray_manager_selection_clear_event),
- manager);
-#endif
- gdk_window_add_filter (window,
- na_tray_manager_window_filter, manager);
+ xev.data.l[0] = CurrentTime;
+ xev.data.l[1] = manager->selection_atom;
+ xev.data.l[2] = manager->window;
+ xev.data.l[3] = 0; /* manager specific data */
+ xev.data.l[4] = 0; /* manager specific data */
+
+ XSendEvent (xdisplay,
+ XDefaultRootWindow (xdisplay),
+ False, StructureNotifyMask, (XEvent *)&xev);
+
+ manager->opcode_atom =
+ XInternAtom (xdisplay, "_NET_SYSTEM_TRAY_OPCODE", False);
+ manager->message_data_atom =
+ XInternAtom (xdisplay, "_NET_SYSTEM_TRAY_MESSAGE_DATA", False);
+
+ /* Add an event filter */
+ manager->event_func_id =
+ meta_x11_display_add_event_func (manager->x11_display,
+ na_tray_manager_event_func,
+ manager,
+ NULL);
return TRUE;
}
else
{
- gtk_widget_destroy (invisible);
- g_object_unref (invisible);
- manager->invisible = NULL;
+ XDestroyWindow (xdisplay, manager->window);
+ manager->window = None;
- manager->screen = NULL;
-
return FALSE;
}
}
-#endif
-
-gboolean
-na_tray_manager_manage_screen (NaTrayManager *manager)
-{
- g_return_val_if_fail (manager->screen == NULL, FALSE);
-
-#ifdef GDK_WINDOWING_X11
- return na_tray_manager_manage_screen_x11 (manager);
-#else
- return FALSE;
-#endif
-}
-
-#ifdef GDK_WINDOWING_X11
-
-static gboolean
-na_tray_manager_check_running_screen_x11 (void)
-{
- GdkDisplay *display;
- GdkScreen *screen;
- Atom selection_atom;
- char *selection_atom_name;
-
- screen = gdk_screen_get_default ();
- display = gdk_screen_get_display (screen);
- selection_atom_name = g_strdup_printf ("_NET_SYSTEM_TRAY_S%d",
- gdk_x11_get_default_screen ());
- selection_atom = gdk_x11_get_xatom_by_name_for_display (display,
- selection_atom_name);
- g_free (selection_atom_name);
-
- if (XGetSelectionOwner (GDK_DISPLAY_XDISPLAY (display),
- selection_atom) != None)
- return TRUE;
- else
- return FALSE;
-}
-
-#endif
-
-gboolean
-na_tray_manager_check_running (void)
-{
-#ifdef GDK_WINDOWING_X11
- return na_tray_manager_check_running_screen_x11 ();
-#else
- return FALSE;
-#endif
-}
-
-void
-na_tray_manager_set_orientation (NaTrayManager *manager,
- GtkOrientation orientation)
-{
- g_return_if_fail (NA_IS_TRAY_MANAGER (manager));
-
- if (manager->orientation != orientation)
- {
- manager->orientation = orientation;
-
- na_tray_manager_set_orientation_property (manager);
-
- g_object_notify (G_OBJECT (manager), "orientation");
- }
-}
-
void
na_tray_manager_set_colors (NaTrayManager *manager,
ClutterColor *fg,
@@ -878,11 +676,3 @@ na_tray_manager_set_colors (NaTrayManager *manager,
na_tray_manager_set_colors_property (manager);
}
}
-
-GtkOrientation
-na_tray_manager_get_orientation (NaTrayManager *manager)
-{
- g_return_val_if_fail (NA_IS_TRAY_MANAGER (manager), GTK_ORIENTATION_HORIZONTAL);
-
- return manager->orientation;
-}
diff --git a/src/tray/na-tray-manager.h b/src/tray/na-tray-manager.h
index 727b02d40..a417ce726 100644
--- a/src/tray/na-tray-manager.h
+++ b/src/tray/na-tray-manager.h
@@ -22,84 +22,24 @@
#ifndef __NA_TRAY_MANAGER_H__
#define __NA_TRAY_MANAGER_H__
-#ifdef GDK_WINDOWING_X11
-#include <gdk/gdkx.h>
-#endif
-#include <gtk/gtk.h>
#include <clutter/clutter.h>
#include "na-tray-child.h"
G_BEGIN_DECLS
-#define NA_TYPE_TRAY_MANAGER (na_tray_manager_get_type ())
-#define NA_TRAY_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NA_TYPE_TRAY_MANAGER, NaTrayManager))
-#define NA_TRAY_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NA_TYPE_TRAY_MANAGER, NaTrayManagerClass))
-#define NA_IS_TRAY_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NA_TYPE_TRAY_MANAGER))
-#define NA_IS_TRAY_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NA_TYPE_TRAY_MANAGER))
-#define NA_TRAY_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NA_TYPE_TRAY_MANAGER, NaTrayManagerClass))
-
-typedef struct _NaTrayManager NaTrayManager;
-typedef struct _NaTrayManagerClass NaTrayManagerClass;
+#define NA_TYPE_TRAY_MANAGER (na_tray_manager_get_type ())
+G_DECLARE_FINAL_TYPE (NaTrayManager, na_tray_manager, NA, TRAY_MANAGER, GObject)
-struct _NaTrayManager
-{
- GObject parent_instance;
+NaTrayManager *na_tray_manager_new (MetaX11Display *x11_display);
-#ifdef GDK_WINDOWING_X11
- GdkAtom selection_atom;
- Atom opcode_atom;
- Atom message_data_atom;
-#endif
-
- GtkWidget *invisible;
- GdkScreen *screen;
- GtkOrientation orientation;
- ClutterColor fg;
- ClutterColor error;
- ClutterColor warning;
- ClutterColor success;
-
- GList *messages;
- GHashTable *socket_table;
-};
-
-struct _NaTrayManagerClass
-{
- GObjectClass parent_class;
-
- void (* tray_icon_added) (NaTrayManager *manager,
- NaTrayChild *child);
- void (* tray_icon_removed) (NaTrayManager *manager,
- NaTrayChild *child);
-
- void (* message_sent) (NaTrayManager *manager,
- NaTrayChild *child,
- const gchar *message,
- glong id,
- glong timeout);
-
- void (* message_cancelled) (NaTrayManager *manager,
- NaTrayChild *child,
- glong id);
-
- void (* lost_selection) (NaTrayManager *manager);
-};
-
-GType na_tray_manager_get_type (void);
-
-gboolean na_tray_manager_check_running (void);
-NaTrayManager *na_tray_manager_new (void);
-gboolean na_tray_manager_manage_screen (NaTrayManager *manager);
-void na_tray_manager_set_orientation (NaTrayManager *manager,
- GtkOrientation orientation);
-GtkOrientation na_tray_manager_get_orientation (NaTrayManager *manager);
-void na_tray_manager_set_colors (NaTrayManager *manager,
- ClutterColor *fg,
- ClutterColor *error,
- ClutterColor *warning,
- ClutterColor *success);
+gboolean na_tray_manager_manage (NaTrayManager *manager);
+void na_tray_manager_set_colors (NaTrayManager *manager,
+ ClutterColor *fg,
+ ClutterColor *error,
+ ClutterColor *warning,
+ ClutterColor *success);
G_END_DECLS