From 3a84625888ea341965a9d2de8358febe0568704f Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Tue, 27 Jan 2009 20:29:17 +0000 Subject: [PATCH] Make a ClutterActor subclass that wraps a GtkWindow, and use it for the tray. In particular, this lets us track the actor's location better; the old code didn't work if the actor was put into a container that got moved around. Part of #568712. svn path=/trunk/; revision=167 --- src/Makefile.am | 9 +- src/shell-gtkwindow-actor.c | 174 ++++++++++++++++++++++++++++++++++++ src/shell-gtkwindow-actor.h | 35 ++++++++ src/shell-tray-manager.c | 44 ++------- 4 files changed, 222 insertions(+), 40 deletions(-) create mode 100644 src/shell-gtkwindow-actor.c create mode 100644 src/shell-gtkwindow-actor.h diff --git a/src/Makefile.am b/src/Makefile.am index 8422f7373..feae7603f 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -36,6 +36,8 @@ libgnome_shell_la_SOURCES = \ gnome-shell-plugin.c \ shell-app-monitor.c \ shell-app-monitor.h \ + shell-gtkwindow-actor.c \ + shell-gtkwindow-actor.h \ shell-process.c \ shell-process.h \ shell-global.c \ @@ -45,6 +47,11 @@ libgnome_shell_la_SOURCES = \ shell-wm.c \ shell-wm.h +# ClutterGLXTexturePixmap is currently not wrapped +non_gir_sources = shell-gtkwindow-actor.h +libgnome_shell_la_gir_sources = \ + $(filter-out $(non_gir_sources), $(libgnome_shell_la_SOURCES)) + shell-marshal.h: stamp-shell-marshal.h @true stamp-shell-marshal.h: Makefile shell-marshal.list @@ -86,7 +93,7 @@ Shell-0.1.gir: $(metacity) $(G_IR_SCANNER) libgnome-shell.la Makefile --include=Meta-2.25 \ --program=metacity \ --program-arg=--mutter-plugins=$$(pwd)/libgnome-shell.la \ - $(libgnome_shell_la_SOURCES) \ + $(libgnome_shell_la_gir_sources) \ $(libgnome_shell_la_CPPFLAGS) \ -o $@ CLEANFILES += Shell-1.0.gir diff --git a/src/shell-gtkwindow-actor.c b/src/shell-gtkwindow-actor.c new file mode 100644 index 000000000..bb10a6431 --- /dev/null +++ b/src/shell-gtkwindow-actor.c @@ -0,0 +1,174 @@ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ + +#include "shell-gtkwindow-actor.h" + +#include +#include +#include + +enum { + PROP_0, + + PROP_WINDOW +}; + +G_DEFINE_TYPE (ShellGtkWindowActor, shell_gtk_window_actor, CLUTTER_GLX_TYPE_TEXTURE_PIXMAP); + +struct _ShellGtkWindowActorPrivate { + GtkWidget *window; +}; + +static void +shell_gtk_window_actor_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + ShellGtkWindowActor *wactor = SHELL_GTK_WINDOW_ACTOR (object); + + switch (prop_id) + { + case PROP_WINDOW: + wactor->priv->window = g_value_dup_object (value); + + /* Here automatic=FALSE means to use CompositeRedirectManual. + * That is, the X server shouldn't draw the window onto the + * screen. + */ + clutter_x11_texture_pixmap_set_window (CLUTTER_X11_TEXTURE_PIXMAP (wactor), + GDK_WINDOW_XWINDOW (wactor->priv->window->window), + FALSE); + /* Here automatic has a different meaning--whether + * ClutterX11TexturePixmap should process damage update and + * refresh the pixmap itself. + */ + clutter_x11_texture_pixmap_set_automatic (CLUTTER_X11_TEXTURE_PIXMAP (wactor), TRUE); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +shell_gtk_window_actor_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + ShellGtkWindowActor *wactor = SHELL_GTK_WINDOW_ACTOR (object); + + switch (prop_id) + { + case PROP_WINDOW: + g_value_set_object (value, wactor->priv->window); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +shell_gtk_window_actor_allocate (ClutterActor *actor, + const ClutterActorBox *box, + gboolean absolute_origin_changed) +{ + ShellGtkWindowActor *wactor = SHELL_GTK_WINDOW_ACTOR (actor); + int wx = 0, wy = 0, x, y, ax, ay; + + CLUTTER_ACTOR_CLASS (shell_gtk_window_actor_parent_class)-> + allocate (actor, box, absolute_origin_changed); + + /* Find the actor's new coordinates in terms of the stage (which is + * priv->window's parent window. + */ + while (actor) + { + clutter_actor_get_position (actor, &x, &y); + clutter_actor_get_anchor_point (actor, &ax, &ay); + + wx += x - ax; + wy += y - ay; + + actor = clutter_actor_get_parent (actor); + } + + gtk_window_move (GTK_WINDOW (wactor->priv->window), wx, wy); +} + +static void +shell_gtk_window_actor_show (ClutterActor *actor) +{ + ShellGtkWindowActor *wactor = SHELL_GTK_WINDOW_ACTOR (actor); + + gtk_widget_show (wactor->priv->window); + + CLUTTER_ACTOR_CLASS (shell_gtk_window_actor_parent_class)->show (actor); +} + +static void +shell_gtk_window_actor_hide (ClutterActor *actor) +{ + ShellGtkWindowActor *wactor = SHELL_GTK_WINDOW_ACTOR (actor); + + gtk_widget_hide (wactor->priv->window); + + CLUTTER_ACTOR_CLASS (shell_gtk_window_actor_parent_class)->hide (actor); +} + +static void +shell_gtk_window_actor_dispose (GObject *object) +{ + ShellGtkWindowActor *wactor = SHELL_GTK_WINDOW_ACTOR (object); + + if (wactor->priv->window) + { + gtk_widget_destroy (wactor->priv->window); + wactor->priv->window = NULL; + } + + G_OBJECT_CLASS (shell_gtk_window_actor_parent_class)->dispose (object); +} + +static void +shell_gtk_window_actor_class_init (ShellGtkWindowActorClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass); + + g_type_class_add_private (klass, sizeof (ShellGtkWindowActorPrivate)); + + object_class->get_property = shell_gtk_window_actor_get_property; + object_class->set_property = shell_gtk_window_actor_set_property; + object_class->dispose = shell_gtk_window_actor_dispose; + + actor_class->allocate = shell_gtk_window_actor_allocate; + actor_class->show = shell_gtk_window_actor_show; + actor_class->hide = shell_gtk_window_actor_hide; + + g_object_class_install_property (object_class, + PROP_WINDOW, + g_param_spec_object ("window", + "Window", + "GtkWindow to wrap", + GTK_TYPE_WINDOW, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); +} + +static void +shell_gtk_window_actor_init (ShellGtkWindowActor *actor) +{ + actor->priv = G_TYPE_INSTANCE_GET_PRIVATE (actor, SHELL_TYPE_GTK_WINDOW_ACTOR, + ShellGtkWindowActorPrivate); +} + +ClutterActor * +shell_gtk_window_actor_new (GtkWidget *window) +{ + return g_object_new (SHELL_TYPE_GTK_WINDOW_ACTOR, + "window", window, + NULL); +} diff --git a/src/shell-gtkwindow-actor.h b/src/shell-gtkwindow-actor.h new file mode 100644 index 000000000..d97a01bfb --- /dev/null +++ b/src/shell-gtkwindow-actor.h @@ -0,0 +1,35 @@ +#ifndef __SHELL_GTK_WINDOW_ACTOR_H__ +#define __SHELL_GTK_WINDOW_ACTOR_H__ + +#include +#include + +#define SHELL_TYPE_GTK_WINDOW_ACTOR (shell_gtk_window_actor_get_type ()) +#define SHELL_GTK_WINDOW_ACTOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SHELL_TYPE_GTK_WINDOW_ACTOR, ShellGtkWindowActor)) +#define SHELL_GTK_WINDOW_ACTOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SHELL_TYPE_GTK_WINDOW_ACTOR, ShellGtkWindowActorClass)) +#define SHELL_IS_GTK_WINDOW_ACTOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SHELL_TYPE_GTK_WINDOW_ACTOR)) +#define SHELL_IS_GTK_WINDOW_ACTOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SHELL_TYPE_GTK_WINDOW_ACTOR)) +#define SHELL_GTK_WINDOW_ACTOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SHELL_TYPE_GTK_WINDOW_ACTOR, ShellGtkWindowActorClass)) + +typedef struct _ShellGtkWindowActor ShellGtkWindowActor; +typedef struct _ShellGtkWindowActorClass ShellGtkWindowActorClass; + +typedef struct _ShellGtkWindowActorPrivate ShellGtkWindowActorPrivate; + +struct _ShellGtkWindowActor +{ + ClutterGLXTexturePixmap parent; + + ShellGtkWindowActorPrivate *priv; +}; + +struct _ShellGtkWindowActorClass +{ + ClutterGLXTexturePixmapClass parent_class; + +}; + +GType shell_gtk_window_actor_get_type (void) G_GNUC_CONST; +ClutterActor *shell_gtk_window_actor_new (GtkWidget *window); + +#endif /* __SHELL_GTK_WINDOW_ACTOR_H__ */ diff --git a/src/shell-tray-manager.c b/src/shell-tray-manager.c index 9f15dc6ac..57a11679a 100644 --- a/src/shell-tray-manager.c +++ b/src/shell-tray-manager.c @@ -1,13 +1,14 @@ /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ #include -#include #include #include #include "shell-tray-manager.h" #include "na-tray-manager.h" +#include "shell-gtkwindow-actor.h" + struct _ShellTrayManagerPrivate { NaTrayManager *na_manager; ClutterStage *stage; @@ -204,30 +205,6 @@ shell_tray_manager_manage_stage (ShellTrayManager *manager, gdk_drawable_get_screen (GDK_DRAWABLE (manager->priv->stage_window))); } -static void -actor_moved (GObject *object, GParamSpec *param, gpointer user_data) -{ - ShellTrayManagerChild *child = user_data; - ClutterActor *actor = child->actor; - int wx = 0, wy = 0, x, y, ax, ay; - - /* Find the actor's new coordinates in terms of the stage (which is - * child->window's parent window. - */ - while (actor) - { - clutter_actor_get_position (actor, &x, &y); - clutter_actor_get_anchor_point (actor, &ax, &ay); - - wx += x - ax; - wy += y - ay; - - actor = clutter_actor_get_parent (actor); - } - - gtk_window_move (GTK_WINDOW (child->window), wx, wy); -} - static GdkPixmap * create_bg_pixmap (GdkColormap *colormap, ClutterColor *color) @@ -291,15 +268,9 @@ na_tray_icon_added (NaTrayManager *na_manager, GtkWidget *socket, gdk_window_reparent (win->window, manager->priv->stage_window, 0, 0); gtk_widget_show_all (win); - icon = clutter_glx_texture_pixmap_new (); - /* Here automatic=FALSE means to use CompositeRedirectManual - that is, - * the X server shouldn't draw the window onto the screen */ - clutter_x11_texture_pixmap_set_window (CLUTTER_X11_TEXTURE_PIXMAP (icon), - GDK_WINDOW_XWINDOW (win->window), - FALSE); - /* Here automatic has a different meaning - whether ClutterX11TexturePixmap - * should process damage update and refresh the pixmap itself */ - clutter_x11_texture_pixmap_set_automatic (CLUTTER_X11_TEXTURE_PIXMAP (icon), TRUE); + icon = shell_gtk_window_actor_new (win); + + /* Move to ShellGtkWindowActor? FIXME */ clutter_actor_set_size (icon, 24, 24); child = g_slice_new (ShellTrayManagerChild); @@ -308,11 +279,6 @@ na_tray_icon_added (NaTrayManager *na_manager, GtkWidget *socket, child->actor = g_object_ref (icon); g_hash_table_insert (manager->priv->icons, socket, child); - g_signal_connect (child->actor, "notify::x", - G_CALLBACK (actor_moved), child); - g_signal_connect (child->actor, "notify::y", - G_CALLBACK (actor_moved), child); - g_signal_emit (manager, shell_tray_manager_signals[TRAY_ICON_ADDED], 0, icon);