Add size negotiation to the tray icons
* Rename ShellGtkWindowActor to ShellGtkEmbed, and make it require a ShellEmbeddedWindow rather than a general GtkWindow. * Add ShellEmbeddedWindow subclass of GtkWindow that bypasses most of the GtkWindow complexity for size negotiation, and calls out to a clutter actor instead; also automatically handle reparenting the GtkWindow into the stage window. * Use the reworked ShellGtkEmbed in ShellTrayManager, this simplifies the code a bit, and more importantly results in the tray icons having the correct size negotiation, rather than having a fixed 24x24 size. http://bugzilla.gnome.org/show_bug.cgi?id=580047
This commit is contained in:
parent
20e755023b
commit
3327a198e1
@ -57,8 +57,11 @@ libgnome_shell_la_SOURCES = \
|
|||||||
shell-app-system.h \
|
shell-app-system.h \
|
||||||
shell-arrow.c \
|
shell-arrow.c \
|
||||||
shell-arrow.h \
|
shell-arrow.h \
|
||||||
shell-gtkwindow-actor.c \
|
shell-embedded-window.c \
|
||||||
shell-gtkwindow-actor.h \
|
shell-embedded-window.h \
|
||||||
|
shell-embedded-window-private.h \
|
||||||
|
shell-gtk-embed.c \
|
||||||
|
shell-gtk-embed.h \
|
||||||
shell-process.c \
|
shell-process.c \
|
||||||
shell-process.h \
|
shell-process.h \
|
||||||
shell-global.c \
|
shell-global.c \
|
||||||
@ -70,8 +73,8 @@ libgnome_shell_la_SOURCES = \
|
|||||||
shell-wm.c \
|
shell-wm.c \
|
||||||
shell-wm.h
|
shell-wm.h
|
||||||
|
|
||||||
# ClutterGLXTexturePixmap is currently not wrapped
|
non_gir_sources = \
|
||||||
non_gir_sources = shell-gtkwindow-actor.h
|
shell-embedded-window-private.h
|
||||||
|
|
||||||
shell_recorder_sources = \
|
shell_recorder_sources = \
|
||||||
shell-recorder.c \
|
shell-recorder.c \
|
||||||
|
19
src/shell-embedded-window-private.h
Normal file
19
src/shell-embedded-window-private.h
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
#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_realize (ShellEmbeddedWindow *window);
|
||||||
|
void _shell_embedded_window_unrealize (ShellEmbeddedWindow *window);
|
||||||
|
|
||||||
|
#endif /* __SHELL_EMBEDDED_WINDOW_PRIVATE_H__ */
|
243
src/shell-embedded-window.c
Normal file
243
src/shell-embedded-window.c
Normal file
@ -0,0 +1,243 @@
|
|||||||
|
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||||
|
|
||||||
|
#include <gdk/gdkx.h>
|
||||||
|
#include <clutter/x11/clutter-x11.h>
|
||||||
|
|
||||||
|
#include "shell-embedded-window-private.h"
|
||||||
|
|
||||||
|
/* This type is a subclass of GtkWindow that ties the window to a
|
||||||
|
* ShellGtkEmbed; the window is reparented into the stage
|
||||||
|
* window for the actor and 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
|
||||||
|
*
|
||||||
|
* Ideally, the way it would work 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]
|
||||||
|
*
|
||||||
|
* Implementing this perfectly is not currently possible, due to problems
|
||||||
|
* in Clutter, see:
|
||||||
|
*
|
||||||
|
* http://bugzilla.openedhand.com/show_bug.cgi?id=1138
|
||||||
|
*
|
||||||
|
* So until that is fixed we use the "realized" state of the ClutterActor
|
||||||
|
* as a stand-in for the ideal mapped state, this will work as long
|
||||||
|
* as the ClutterActor and all its parents are in fact visible.
|
||||||
|
*/
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (ShellEmbeddedWindow, shell_embedded_window, GTK_TYPE_WINDOW);
|
||||||
|
|
||||||
|
struct _ShellEmbeddedWindowPrivate {
|
||||||
|
ShellGtkEmbed *actor;
|
||||||
|
|
||||||
|
GdkRectangle position;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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);
|
||||||
|
|
||||||
|
GTK_WIDGET_SET_FLAGS (widget, GTK_VISIBLE);
|
||||||
|
|
||||||
|
if (window->priv->actor)
|
||||||
|
{
|
||||||
|
/* Size is 0x0 if the GtkWindow is not shown */
|
||||||
|
clutter_actor_queue_relayout (CLUTTER_ACTOR (window->priv->actor));
|
||||||
|
|
||||||
|
if (CLUTTER_ACTOR_IS_REALIZED (window->priv->actor))
|
||||||
|
gtk_widget_map (widget);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
shell_embedded_window_hide (GtkWidget *widget)
|
||||||
|
{
|
||||||
|
ShellEmbeddedWindow *window = SHELL_EMBEDDED_WINDOW (widget);
|
||||||
|
|
||||||
|
clutter_actor_queue_relayout (CLUTTER_ACTOR (window->priv->actor));
|
||||||
|
|
||||||
|
GTK_WIDGET_CLASS (shell_embedded_window_parent_class)->hide (widget);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
shell_embedded_window_realize (GtkWidget *widget)
|
||||||
|
{
|
||||||
|
ShellEmbeddedWindow *window = SHELL_EMBEDDED_WINDOW (widget);
|
||||||
|
ClutterActor *stage;
|
||||||
|
Window stage_xwindow;
|
||||||
|
|
||||||
|
GTK_WIDGET_CLASS (shell_embedded_window_parent_class)->realize (widget);
|
||||||
|
|
||||||
|
stage = clutter_actor_get_stage (CLUTTER_ACTOR (window->priv->actor));
|
||||||
|
|
||||||
|
/* Clutter is buggy and will realize an actor when it has a parent
|
||||||
|
* but no grandparent; this is a workaround until
|
||||||
|
* http://bugzilla.openedhand.com/show_bug.cgi?id=1138 is fixed - we
|
||||||
|
* only have one stage in the shell in any case.
|
||||||
|
*/
|
||||||
|
if (!stage)
|
||||||
|
stage = clutter_stage_get_default ();
|
||||||
|
|
||||||
|
stage_xwindow = clutter_x11_get_stage_window (CLUTTER_STAGE (stage));
|
||||||
|
|
||||||
|
/* Using XReparentWindow() is simpler than using gdk_window_reparent(),
|
||||||
|
* since it avoids maybe having to create a new foreign GDK window for
|
||||||
|
* the stage. However, GDK will be left thinking that the parent of
|
||||||
|
* window->window is the root window - it's not immediately clear
|
||||||
|
* to me whether that is more or less likely to cause problems than
|
||||||
|
* modifying the GDK hierarchy.
|
||||||
|
*/
|
||||||
|
XReparentWindow (GDK_DISPLAY_XDISPLAY (gtk_widget_get_display (widget)),
|
||||||
|
GDK_WINDOW_XWINDOW (widget->window),
|
||||||
|
stage_xwindow,
|
||||||
|
window->priv->position.x, window->priv->position.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
/* 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 (window->priv->actor)
|
||||||
|
clutter_actor_queue_relayout (CLUTTER_ACTOR (window->priv->actor));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
shell_embedded_window_class_init (ShellEmbeddedWindowClass *klass)
|
||||||
|
{
|
||||||
|
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
|
||||||
|
GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass);
|
||||||
|
|
||||||
|
g_type_class_add_private (klass, sizeof (ShellEmbeddedWindowPrivate));
|
||||||
|
|
||||||
|
widget_class->show = shell_embedded_window_show;
|
||||||
|
widget_class->hide = shell_embedded_window_hide;
|
||||||
|
widget_class->realize = shell_embedded_window_realize;
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
window->priv = G_TYPE_INSTANCE_GET_PRIVATE (window, SHELL_TYPE_EMBEDDED_WINDOW,
|
||||||
|
ShellEmbeddedWindowPrivate);
|
||||||
|
|
||||||
|
/* Setting the resize mode to immediate means that calling queue_resize()
|
||||||
|
* on a widget within the window will immmediately 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 (G_OBJECT (window),
|
||||||
|
"resize-mode", GTK_RESIZE_IMMEDIATE,
|
||||||
|
"type", GTK_WINDOW_POPUP,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Private routines called by ShellGtkEmbed
|
||||||
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
_shell_embedded_window_set_actor (ShellEmbeddedWindow *window,
|
||||||
|
ShellGtkEmbed *actor)
|
||||||
|
|
||||||
|
{
|
||||||
|
g_return_if_fail (SHELL_IS_EMBEDDED_WINDOW (window));
|
||||||
|
|
||||||
|
window->priv->actor = actor;
|
||||||
|
|
||||||
|
if (GTK_WIDGET_VISIBLE (window) && CLUTTER_ACTOR_IS_REALIZED (actor))
|
||||||
|
gtk_widget_map (GTK_WIDGET (window));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_shell_embedded_window_allocate (ShellEmbeddedWindow *window,
|
||||||
|
int x,
|
||||||
|
int y,
|
||||||
|
int width,
|
||||||
|
int height)
|
||||||
|
{
|
||||||
|
GtkAllocation allocation;
|
||||||
|
|
||||||
|
g_return_if_fail (SHELL_IS_EMBEDDED_WINDOW (window));
|
||||||
|
|
||||||
|
window->priv->position.x = x;
|
||||||
|
window->priv->position.y = y;
|
||||||
|
window->priv->position.width = width;
|
||||||
|
window->priv->position.height = height;
|
||||||
|
|
||||||
|
if (GTK_WIDGET_REALIZED (window))
|
||||||
|
gdk_window_move_resize (GTK_WIDGET (window)->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_realize (ShellEmbeddedWindow *window)
|
||||||
|
{
|
||||||
|
g_return_if_fail (SHELL_IS_EMBEDDED_WINDOW (window));
|
||||||
|
|
||||||
|
if (GTK_WIDGET_VISIBLE (window))
|
||||||
|
gtk_widget_map (GTK_WIDGET (window));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_shell_embedded_window_unrealize (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);
|
||||||
|
}
|
33
src/shell-embedded-window.h
Normal file
33
src/shell-embedded-window.h
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
#ifndef __SHELL_EMBEDDED_WINDOW_H__
|
||||||
|
#define __SHELL_EMBEDDED_WINDOW_H__
|
||||||
|
|
||||||
|
#include <gtk/gtk.h>
|
||||||
|
|
||||||
|
#define SHELL_TYPE_EMBEDDED_WINDOW (shell_embedded_window_get_type ())
|
||||||
|
#define SHELL_EMBEDDED_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SHELL_TYPE_EMBEDDED_WINDOW, ShellEmbeddedWindow))
|
||||||
|
#define SHELL_EMBEDDED_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SHELL_TYPE_EMBEDDED_WINDOW, ShellEmbeddedWindowClass))
|
||||||
|
#define SHELL_IS_EMBEDDED_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SHELL_TYPE_EMBEDDED_WINDOW))
|
||||||
|
#define SHELL_IS_EMBEDDED_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SHELL_TYPE_EMBEDDED_WINDOW))
|
||||||
|
#define SHELL_EMBEDDED_WINDOW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SHELL_TYPE_EMBEDDED_WINDOW, ShellEmbeddedWindowClass))
|
||||||
|
|
||||||
|
typedef struct _ShellEmbeddedWindow ShellEmbeddedWindow;
|
||||||
|
typedef struct _ShellEmbeddedWindowClass ShellEmbeddedWindowClass;
|
||||||
|
|
||||||
|
typedef struct _ShellEmbeddedWindowPrivate ShellEmbeddedWindowPrivate;
|
||||||
|
|
||||||
|
struct _ShellEmbeddedWindow
|
||||||
|
{
|
||||||
|
GtkWindow parent;
|
||||||
|
|
||||||
|
ShellEmbeddedWindowPrivate *priv;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _ShellEmbeddedWindowClass
|
||||||
|
{
|
||||||
|
GtkWindowClass parent_class;
|
||||||
|
};
|
||||||
|
|
||||||
|
GType shell_embedded_window_get_type (void) G_GNUC_CONST;
|
||||||
|
GtkWidget *shell_embedded_window_new (void);
|
||||||
|
|
||||||
|
#endif /* __SHELL_EMBEDDED_WINDOW_H__ */
|
297
src/shell-gtk-embed.c
Normal file
297
src/shell-gtk-embed.c
Normal file
@ -0,0 +1,297 @@
|
|||||||
|
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||||
|
|
||||||
|
#include "shell-embedded-window-private.h"
|
||||||
|
|
||||||
|
#include <clutter/glx/clutter-glx.h>
|
||||||
|
#include <clutter/x11/clutter-x11.h>
|
||||||
|
#include <gdk/gdkx.h>
|
||||||
|
|
||||||
|
enum {
|
||||||
|
PROP_0,
|
||||||
|
|
||||||
|
PROP_WINDOW
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct _ShellGtkEmbedPrivate ShellGtkEmbedPrivate;
|
||||||
|
|
||||||
|
/* The reason that the instance/class structures are here is to avoid
|
||||||
|
* problems with g-ir-scanner chocking on ClutterGLXTexturePixmap. We
|
||||||
|
* stick with having a separate private structure so that we can move
|
||||||
|
* the instance/class structures back to the public header if this
|
||||||
|
* code is reused in another context where inheritance from C is useful.
|
||||||
|
*/
|
||||||
|
struct _ShellGtkEmbed
|
||||||
|
{
|
||||||
|
ClutterGLXTexturePixmap parent;
|
||||||
|
|
||||||
|
ShellGtkEmbedPrivate *priv;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _ShellGtkEmbedClass
|
||||||
|
{
|
||||||
|
ClutterGLXTexturePixmapClass parent_class;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _ShellGtkEmbedPrivate
|
||||||
|
{
|
||||||
|
ShellEmbeddedWindow *window;
|
||||||
|
};
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (ShellGtkEmbed, shell_gtk_embed, CLUTTER_GLX_TYPE_TEXTURE_PIXMAP);
|
||||||
|
|
||||||
|
static void shell_gtk_embed_set_window (ShellGtkEmbed *embed,
|
||||||
|
ShellEmbeddedWindow *window);
|
||||||
|
|
||||||
|
static void
|
||||||
|
shell_gtk_embed_on_window_destroy (GtkObject *object,
|
||||||
|
ShellGtkEmbed *embed)
|
||||||
|
{
|
||||||
|
shell_gtk_embed_set_window (embed, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
shell_gtk_embed_on_window_realize (GtkWidget *widget,
|
||||||
|
ShellGtkEmbed *embed)
|
||||||
|
{
|
||||||
|
/* 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 (embed),
|
||||||
|
GDK_WINDOW_XWINDOW (widget->window),
|
||||||
|
FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
shell_gtk_embed_set_window (ShellGtkEmbed *embed,
|
||||||
|
ShellEmbeddedWindow *window)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (embed->priv->window)
|
||||||
|
{
|
||||||
|
_shell_embedded_window_set_actor (embed->priv->window, NULL);
|
||||||
|
|
||||||
|
g_object_unref (embed->priv->window);
|
||||||
|
|
||||||
|
clutter_x11_texture_pixmap_set_window (CLUTTER_X11_TEXTURE_PIXMAP (embed),
|
||||||
|
None,
|
||||||
|
FALSE);
|
||||||
|
|
||||||
|
g_signal_handlers_disconnect_by_func (embed->priv->window,
|
||||||
|
(gpointer)shell_gtk_embed_on_window_destroy,
|
||||||
|
embed);
|
||||||
|
g_signal_handlers_disconnect_by_func (embed->priv->window,
|
||||||
|
(gpointer)shell_gtk_embed_on_window_realize,
|
||||||
|
embed);
|
||||||
|
}
|
||||||
|
|
||||||
|
embed->priv->window = window;
|
||||||
|
|
||||||
|
if (embed->priv->window)
|
||||||
|
{
|
||||||
|
g_object_ref (embed->priv->window);
|
||||||
|
|
||||||
|
_shell_embedded_window_set_actor (embed->priv->window, embed);
|
||||||
|
|
||||||
|
g_signal_connect (embed->priv->window, "destroy",
|
||||||
|
G_CALLBACK (shell_gtk_embed_on_window_destroy), embed);
|
||||||
|
g_signal_connect (embed->priv->window, "realize",
|
||||||
|
G_CALLBACK (shell_gtk_embed_on_window_realize), embed);
|
||||||
|
|
||||||
|
if (GTK_WIDGET_REALIZED (window))
|
||||||
|
shell_gtk_embed_on_window_realize (GTK_WIDGET (embed->priv->window), 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);
|
||||||
|
|
||||||
|
switch (prop_id)
|
||||||
|
{
|
||||||
|
case PROP_WINDOW:
|
||||||
|
g_value_set_object (value, embed->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,
|
||||||
|
ClutterUnit for_height,
|
||||||
|
ClutterUnit *min_width_p,
|
||||||
|
ClutterUnit *natural_width_p)
|
||||||
|
{
|
||||||
|
ShellGtkEmbed *embed = SHELL_GTK_EMBED (actor);
|
||||||
|
|
||||||
|
if (embed->priv->window && GTK_WIDGET_VISIBLE (embed->priv->window))
|
||||||
|
{
|
||||||
|
GtkRequisition requisition;
|
||||||
|
gtk_widget_size_request (GTK_WIDGET (embed->priv->window), &requisition);
|
||||||
|
|
||||||
|
*min_width_p = *natural_width_p = requisition.width;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
*min_width_p = *natural_width_p = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
shell_gtk_embed_get_preferred_height (ClutterActor *actor,
|
||||||
|
ClutterUnit for_width,
|
||||||
|
ClutterUnit *min_height_p,
|
||||||
|
ClutterUnit *natural_height_p)
|
||||||
|
{
|
||||||
|
ShellGtkEmbed *embed = SHELL_GTK_EMBED (actor);
|
||||||
|
|
||||||
|
if (embed->priv->window && GTK_WIDGET_VISIBLE (embed->priv->window))
|
||||||
|
{
|
||||||
|
GtkRequisition requisition;
|
||||||
|
gtk_widget_size_request (GTK_WIDGET (embed->priv->window), &requisition);
|
||||||
|
|
||||||
|
*min_height_p = *natural_height_p = requisition.height;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
*min_height_p = *natural_height_p = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
shell_gtk_embed_allocate (ClutterActor *actor,
|
||||||
|
const ClutterActorBox *box,
|
||||||
|
gboolean absolute_origin_changed)
|
||||||
|
{
|
||||||
|
ShellGtkEmbed *embed = SHELL_GTK_EMBED (actor);
|
||||||
|
int wx = 0, wy = 0, x, y, ax, ay;
|
||||||
|
|
||||||
|
CLUTTER_ACTOR_CLASS (shell_gtk_embed_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);
|
||||||
|
}
|
||||||
|
|
||||||
|
_shell_embedded_window_allocate (embed->priv->window,
|
||||||
|
wx, wy,
|
||||||
|
box->x2 - box->x1,
|
||||||
|
box->y2 - box->y1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
shell_gtk_embed_realize (ClutterActor *actor)
|
||||||
|
{
|
||||||
|
ShellGtkEmbed *embed = SHELL_GTK_EMBED (actor);
|
||||||
|
|
||||||
|
_shell_embedded_window_realize (embed->priv->window);
|
||||||
|
|
||||||
|
CLUTTER_ACTOR_CLASS (shell_gtk_embed_parent_class)->realize (actor);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
shell_gtk_embed_unrealize (ClutterActor *actor)
|
||||||
|
{
|
||||||
|
ShellGtkEmbed *embed = SHELL_GTK_EMBED (actor);
|
||||||
|
|
||||||
|
_shell_embedded_window_unrealize (embed->priv->window);
|
||||||
|
|
||||||
|
CLUTTER_ACTOR_CLASS (shell_gtk_embed_parent_class)->unrealize (actor);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
shell_gtk_embed_dispose (GObject *object)
|
||||||
|
{
|
||||||
|
ShellGtkEmbed *embed = SHELL_GTK_EMBED (object);
|
||||||
|
|
||||||
|
shell_gtk_embed_set_window (embed, NULL);
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (shell_gtk_embed_parent_class)->dispose (object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
shell_gtk_embed_class_init (ShellGtkEmbedClass *klass)
|
||||||
|
{
|
||||||
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||||
|
ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
|
||||||
|
|
||||||
|
g_type_class_add_private (klass, sizeof (ShellGtkEmbedPrivate));
|
||||||
|
|
||||||
|
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->realize = shell_gtk_embed_realize;
|
||||||
|
actor_class->unrealize = shell_gtk_embed_unrealize;
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
embed->priv = G_TYPE_INSTANCE_GET_PRIVATE (embed, SHELL_TYPE_GTK_EMBED,
|
||||||
|
ShellGtkEmbedPrivate);
|
||||||
|
|
||||||
|
/* automatic here means whether ClutterX11TexturePixmap should
|
||||||
|
* process damage update and refresh the pixmap itself.
|
||||||
|
*/
|
||||||
|
clutter_x11_texture_pixmap_set_automatic (CLUTTER_X11_TEXTURE_PIXMAP (embed), TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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);
|
||||||
|
}
|
21
src/shell-gtk-embed.h
Normal file
21
src/shell-gtk-embed.h
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
#ifndef __SHELL_GTK_EMBED_H__
|
||||||
|
#define __SHELL_GTK_EMBED_H__
|
||||||
|
|
||||||
|
#include <clutter/glx/clutter-glx.h>
|
||||||
|
|
||||||
|
#include "shell-embedded-window.h"
|
||||||
|
|
||||||
|
#define SHELL_TYPE_GTK_EMBED (shell_gtk_embed_get_type ())
|
||||||
|
#define SHELL_GTK_EMBED(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SHELL_TYPE_GTK_EMBED, ShellGtkEmbed))
|
||||||
|
#define SHELL_GTK_EMBED_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SHELL_TYPE_GTK_EMBED, ShellGtkEmbedClass))
|
||||||
|
#define SHELL_IS_GTK_EMBED(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SHELL_TYPE_GTK_EMBED))
|
||||||
|
#define SHELL_IS_GTK_EMBED_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SHELL_TYPE_GTK_EMBED))
|
||||||
|
#define SHELL_GTK_EMBED_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SHELL_TYPE_GTK_EMBED, ShellGtkEmbedClass))
|
||||||
|
|
||||||
|
typedef struct _ShellGtkEmbed ShellGtkEmbed;
|
||||||
|
typedef struct _ShellGtkEmbedClass ShellGtkEmbedClass;
|
||||||
|
|
||||||
|
GType shell_gtk_embed_get_type (void) G_GNUC_CONST;
|
||||||
|
ClutterActor *shell_gtk_embed_new (ShellEmbeddedWindow *window);
|
||||||
|
|
||||||
|
#endif /* __SHELL_GTK_EMBED_H__ */
|
@ -1,174 +0,0 @@
|
|||||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
|
||||||
|
|
||||||
#include "shell-gtkwindow-actor.h"
|
|
||||||
|
|
||||||
#include <clutter/glx/clutter-glx.h>
|
|
||||||
#include <clutter/x11/clutter-x11.h>
|
|
||||||
#include <gdk/gdkx.h>
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
@ -1,35 +0,0 @@
|
|||||||
#ifndef __SHELL_GTK_WINDOW_ACTOR_H__
|
|
||||||
#define __SHELL_GTK_WINDOW_ACTOR_H__
|
|
||||||
|
|
||||||
#include <clutter/glx/clutter-glx.h>
|
|
||||||
#include <gtk/gtk.h>
|
|
||||||
|
|
||||||
#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__ */
|
|
@ -7,12 +7,12 @@
|
|||||||
#include "shell-tray-manager.h"
|
#include "shell-tray-manager.h"
|
||||||
#include "na-tray-manager.h"
|
#include "na-tray-manager.h"
|
||||||
|
|
||||||
#include "shell-gtkwindow-actor.h"
|
#include "shell-gtk-embed.h"
|
||||||
|
#include "shell-embedded-window.h"
|
||||||
|
|
||||||
struct _ShellTrayManagerPrivate {
|
struct _ShellTrayManagerPrivate {
|
||||||
NaTrayManager *na_manager;
|
NaTrayManager *na_manager;
|
||||||
ClutterStage *stage;
|
ClutterStage *stage;
|
||||||
GdkWindow *stage_window;
|
|
||||||
ClutterColor bg_color;
|
ClutterColor bg_color;
|
||||||
|
|
||||||
GHashTable *icons;
|
GHashTable *icons;
|
||||||
@ -130,7 +130,6 @@ shell_tray_manager_finalize (GObject *object)
|
|||||||
|
|
||||||
g_object_unref (manager->priv->na_manager);
|
g_object_unref (manager->priv->na_manager);
|
||||||
g_object_unref (manager->priv->stage);
|
g_object_unref (manager->priv->stage);
|
||||||
g_object_unref (manager->priv->stage_window);
|
|
||||||
g_hash_table_destroy (manager->priv->icons);
|
g_hash_table_destroy (manager->priv->icons);
|
||||||
|
|
||||||
G_OBJECT_CLASS (shell_tray_manager_parent_class)->finalize (object);
|
G_OBJECT_CLASS (shell_tray_manager_parent_class)->finalize (object);
|
||||||
@ -189,20 +188,35 @@ void
|
|||||||
shell_tray_manager_manage_stage (ShellTrayManager *manager,
|
shell_tray_manager_manage_stage (ShellTrayManager *manager,
|
||||||
ClutterStage *stage)
|
ClutterStage *stage)
|
||||||
{
|
{
|
||||||
Window stage_xwin;
|
Window stage_xwindow;
|
||||||
|
GdkWindow *stage_window;
|
||||||
|
GdkScreen *screen;
|
||||||
|
|
||||||
g_return_if_fail (manager->priv->stage == NULL);
|
g_return_if_fail (manager->priv->stage == NULL);
|
||||||
|
|
||||||
manager->priv->stage = g_object_ref (stage);
|
manager->priv->stage = g_object_ref (stage);
|
||||||
stage_xwin = clutter_x11_get_stage_window (stage);
|
|
||||||
manager->priv->stage_window = gdk_window_lookup (stage_xwin);
|
|
||||||
if (manager->priv->stage_window)
|
|
||||||
g_object_ref (manager->priv->stage_window);
|
|
||||||
else
|
|
||||||
manager->priv->stage_window = gdk_window_foreign_new (stage_xwin);
|
|
||||||
|
|
||||||
na_tray_manager_manage_screen (manager->priv->na_manager,
|
stage_xwindow = clutter_x11_get_stage_window (stage);
|
||||||
gdk_drawable_get_screen (GDK_DRAWABLE (manager->priv->stage_window)));
|
|
||||||
|
/* This is a pretty ugly way to get the GdkScreen for the stage; it
|
||||||
|
* will normally go through the foreign_new() case with a
|
||||||
|
* round-trip to the X server, it might be nicer to pass the screen
|
||||||
|
* in in some way. (The Clutter/Mutter combo is currently incapable
|
||||||
|
* of multi-screen operation, so alternatively we could just assume
|
||||||
|
* that clutter_x11_get_default_screen() gives us the right
|
||||||
|
* screen.)
|
||||||
|
*/
|
||||||
|
stage_window = gdk_window_lookup (stage_xwindow);
|
||||||
|
if (stage_window)
|
||||||
|
g_object_ref (stage_window);
|
||||||
|
else
|
||||||
|
stage_window = gdk_window_foreign_new (stage_xwindow);
|
||||||
|
|
||||||
|
screen = gdk_drawable_get_screen (stage_window);
|
||||||
|
|
||||||
|
g_object_unref (stage_window);
|
||||||
|
|
||||||
|
na_tray_manager_manage_screen (manager->priv->na_manager, screen);
|
||||||
}
|
}
|
||||||
|
|
||||||
static GdkPixmap *
|
static GdkPixmap *
|
||||||
@ -229,6 +243,28 @@ create_bg_pixmap (GdkColormap *colormap,
|
|||||||
return pixmap;
|
return pixmap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
shell_tray_manager_child_on_realize (GtkWidget *widget,
|
||||||
|
ShellTrayManagerChild *child)
|
||||||
|
{
|
||||||
|
GdkPixmap *bg_pixmap;
|
||||||
|
|
||||||
|
/* 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 1x1 pixmap 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)))
|
||||||
|
{
|
||||||
|
bg_pixmap = create_bg_pixmap (gtk_widget_get_colormap (widget),
|
||||||
|
&child->manager->priv->bg_color);
|
||||||
|
gdk_window_set_back_pixmap (widget->window, bg_pixmap, FALSE);
|
||||||
|
g_object_unref (bg_pixmap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
na_tray_icon_added (NaTrayManager *na_manager, GtkWidget *socket,
|
na_tray_icon_added (NaTrayManager *na_manager, GtkWidget *socket,
|
||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
@ -237,7 +273,6 @@ na_tray_icon_added (NaTrayManager *na_manager, GtkWidget *socket,
|
|||||||
GtkWidget *win;
|
GtkWidget *win;
|
||||||
ClutterActor *icon;
|
ClutterActor *icon;
|
||||||
ShellTrayManagerChild *child;
|
ShellTrayManagerChild *child;
|
||||||
GdkPixmap *bg_pixmap;
|
|
||||||
|
|
||||||
/* We don't need the NaTrayIcon to be composited on the window we
|
/* We don't need the NaTrayIcon to be composited on the window we
|
||||||
* put it in: the window is the same size as the tray icon
|
* put it in: the window is the same size as the tray icon
|
||||||
@ -247,43 +282,24 @@ na_tray_icon_added (NaTrayManager *na_manager, GtkWidget *socket,
|
|||||||
*/
|
*/
|
||||||
na_tray_child_set_composited (NA_TRAY_CHILD (socket), FALSE);
|
na_tray_child_set_composited (NA_TRAY_CHILD (socket), FALSE);
|
||||||
|
|
||||||
win = gtk_window_new (GTK_WINDOW_POPUP);
|
win = shell_embedded_window_new ();
|
||||||
gtk_container_add (GTK_CONTAINER (win), socket);
|
gtk_container_add (GTK_CONTAINER (win), socket);
|
||||||
|
|
||||||
/* The colormap of the socket matches that of its contents; make
|
/* The colormap of the socket matches that of its contents; make
|
||||||
* the window we put it in match that as well */
|
* the window we put it in match that as well */
|
||||||
gtk_widget_set_colormap (win, gtk_widget_get_colormap (socket));
|
gtk_widget_set_colormap (win, gtk_widget_get_colormap (socket));
|
||||||
|
|
||||||
gtk_widget_set_size_request (win, 24, 24);
|
|
||||||
gtk_widget_realize (win);
|
|
||||||
|
|
||||||
/* 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 1x1 pixmap 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 (socket)))
|
|
||||||
{
|
|
||||||
bg_pixmap = create_bg_pixmap (gtk_widget_get_colormap (win),
|
|
||||||
&manager->priv->bg_color);
|
|
||||||
gdk_window_set_back_pixmap (win->window, bg_pixmap, FALSE);
|
|
||||||
g_object_unref (bg_pixmap);
|
|
||||||
}
|
|
||||||
|
|
||||||
gtk_widget_set_parent_window (win, manager->priv->stage_window);
|
|
||||||
gdk_window_reparent (win->window, manager->priv->stage_window, 0, 0);
|
|
||||||
gtk_widget_show_all (win);
|
|
||||||
|
|
||||||
icon = shell_gtk_window_actor_new (win);
|
|
||||||
|
|
||||||
/* Move to ShellGtkWindowActor? FIXME */
|
|
||||||
clutter_actor_set_size (icon, 24, 24);
|
|
||||||
|
|
||||||
child = g_slice_new (ShellTrayManagerChild);
|
child = g_slice_new (ShellTrayManagerChild);
|
||||||
child->window = win;
|
child->window = win;
|
||||||
child->socket = socket;
|
child->socket = socket;
|
||||||
|
|
||||||
|
g_signal_connect (win, "realize",
|
||||||
|
G_CALLBACK (shell_tray_manager_child_on_realize), child);
|
||||||
|
|
||||||
|
gtk_widget_show_all (win);
|
||||||
|
|
||||||
|
icon = shell_gtk_embed_new (SHELL_EMBEDDED_WINDOW (win));
|
||||||
|
|
||||||
child->actor = g_object_ref (icon);
|
child->actor = g_object_ref (icon);
|
||||||
g_hash_table_insert (manager->priv->icons, socket, child);
|
g_hash_table_insert (manager->priv->icons, socket, child);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user