aboutsummaryrefslogtreecommitdiff
path: root/hildon/hildon-remote-texture.c
diff options
context:
space:
mode:
authorAlberto Garcia <agarcia@igalia.com>2009-04-30 13:10:26 +0200
committerAlberto Garcia <agarcia@igalia.com>2009-04-30 13:33:58 +0200
commit69a11338fe0cc36a868e5812b590f5437622988a (patch)
treeabd1efc835e7e30f7799eac64ff45405f1624528 /hildon/hildon-remote-texture.c
parent8a970bcc0a22925ed90b869c8f7c1ba521e189ac (diff)
Renamed src/ to hildon/
* src/ * Makefile.am * configure.ac * doc/Makefile.am * doc/hildon.types * po/POTFILES.in: Renamed src/ to hildon/ * examples/*.c * debian/changelog * debian/rules: Include <hildon/hildon.h> directly in all examples.
Diffstat (limited to 'hildon/hildon-remote-texture.c')
-rw-r--r--hildon/hildon-remote-texture.c943
1 files changed, 943 insertions, 0 deletions
diff --git a/hildon/hildon-remote-texture.c b/hildon/hildon-remote-texture.c
new file mode 100644
index 0000000..f8bbbd7
--- /dev/null
+++ b/hildon/hildon-remote-texture.c
@@ -0,0 +1,943 @@
+/*
+ * This file is a part of hildon
+ *
+ * Copyright (C) 2008 Nokia Corporation, all rights reserved.
+ *
+ * Contact: Rodrigo Novo <rodrigo.novo@nokia.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+/**
+ * SECTION:hildon-remote-texture
+ * @short_description: Widget representing a Clutter/GLES texture created
+ * from a shared memory area.
+ *
+ * The #HildonRemoteTexture is a GTK+ widget which allows the rendering of
+ * a shared memory area within hildon-desktop. It allows the memory area to
+ * be positioned and scaled, without altering its' contents.
+ */
+
+#include <gdk/gdkx.h>
+#include <X11/Xatom.h>
+
+#include "hildon-remote-texture.h"
+#include "hildon-remote-texture-private.h"
+
+G_DEFINE_TYPE (HildonRemoteTexture, hildon_remote_texture, GTK_TYPE_WINDOW);
+
+static GdkFilterReturn
+hildon_remote_texture_event_filter (GdkXEvent *xevent,
+ GdkEvent *event,
+ gpointer data);
+static void
+hildon_remote_texture_update_ready (HildonRemoteTexture *self);
+static void
+hildon_remote_texture_send_pending_messages (HildonRemoteTexture *self);
+static void
+hildon_remote_texture_send_all_messages (HildonRemoteTexture *self);
+static gboolean
+hildon_remote_texture_parent_map_event (GtkWidget *parent,
+ GdkEvent *event,
+ gpointer user_data);
+static gboolean
+hildon_remote_texture_map_event (GtkWidget *widget,
+ GdkEvent *event,
+ gpointer user_data);
+
+static guint32 shm_atom;
+static guint32 damage_atom;
+static guint32 show_atom;
+static guint32 position_atom;
+static guint32 offset_atom;
+static guint32 scale_atom;
+static guint32 parent_atom;
+static guint32 ready_atom;
+
+static gboolean atoms_initialized = FALSE;
+
+static void
+hildon_remote_texture_realize (GtkWidget *widget)
+{
+ GdkDisplay *display;
+ Atom wm_type, applet_type;
+
+ GTK_WIDGET_CLASS (hildon_remote_texture_parent_class)->realize (widget);
+
+ /* Set remote texture window type. */
+
+ display = gdk_drawable_get_display (widget->window);
+
+ wm_type = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE");
+ applet_type = gdk_x11_get_xatom_by_name_for_display (display, "_HILDON_WM_WINDOW_TYPE_REMOTE_TEXTURE");
+
+ XChangeProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (widget->window), wm_type,
+ XA_ATOM, 32, PropModeReplace,
+ (unsigned char *) &applet_type, 1);
+
+ /* This is a bit of a hack, but for the sake of speed (it is assumed that
+ * once HildonRemoteTexture is created, a lot of ClientMessages will
+ * follow), we cache all ClientMessages atoms in static variables. */
+
+ if (!atoms_initialized)
+ {
+ shm_atom =
+ gdk_x11_get_xatom_by_name_for_display
+ (display, "_HILDON_TEXTURE_CLIENT_MESSAGE_SHM");
+ damage_atom =
+ gdk_x11_get_xatom_by_name_for_display
+ (display, "_HILDON_TEXTURE_CLIENT_MESSAGE_DAMAGE");
+ show_atom =
+ gdk_x11_get_xatom_by_name_for_display
+ (display, "_HILDON_TEXTURE_CLIENT_MESSAGE_SHOW");
+ position_atom =
+ gdk_x11_get_xatom_by_name_for_display
+ (display, "_HILDON_TEXTURE_CLIENT_MESSAGE_POSITION");
+ offset_atom =
+ gdk_x11_get_xatom_by_name_for_display
+ (display, "_HILDON_TEXTURE_CLIENT_MESSAGE_OFFSET");
+ scale_atom =
+ gdk_x11_get_xatom_by_name_for_display
+ (display, "_HILDON_TEXTURE_CLIENT_MESSAGE_SCALE");
+ parent_atom =
+ gdk_x11_get_xatom_by_name_for_display
+ (display, "_HILDON_TEXTURE_CLIENT_MESSAGE_PARENT");
+ ready_atom =
+ gdk_x11_get_xatom_by_name_for_display
+ (display, "_HILDON_TEXTURE_CLIENT_READY");
+#if 0
+ g_debug ("shm atom = %lu\n", shm_atom);
+ g_debug ("damage atom = %lu\n", damage_atom);
+ g_debug ("show atom = %lu\n", show_atom);
+ g_debug ("position atom = %lu\n", position_atom);
+ g_debug ("offset atom = %lu\n", offset_atom);
+ g_debug ("scale atom = %lu\n", scale_atom);
+ g_debug ("parent atom = %lu\n", parent_atom);
+ g_debug ("ready atom = %lu\n", ready_atom);
+#endif
+
+ atoms_initialized = TRUE;
+ }
+
+ /* Wait for a ready message */
+
+ gdk_window_add_filter (widget->window,
+ hildon_remote_texture_event_filter,
+ widget);
+}
+
+static void
+hildon_remote_texture_unrealize (GtkWidget *widget)
+{
+ gdk_window_remove_filter (widget->window,
+ hildon_remote_texture_event_filter,
+ widget);
+
+ GTK_WIDGET_CLASS (hildon_remote_texture_parent_class)->unrealize (widget);
+}
+
+static void
+hildon_remote_texture_show (GtkWidget *widget)
+{
+ HildonRemoteTexture *self = HILDON_REMOTE_TEXTURE (widget);
+
+ GTK_WIDGET_CLASS (hildon_remote_texture_parent_class)->show (widget);
+ hildon_remote_texture_set_show (self, 1);
+}
+
+static void
+hildon_remote_texture_hide (GtkWidget *widget)
+{
+ HildonRemoteTexture *self = HILDON_REMOTE_TEXTURE (widget);
+
+ hildon_remote_texture_set_show (self, 0);
+ GTK_WIDGET_CLASS (hildon_remote_texture_parent_class)->hide (widget);
+}
+
+static void
+hildon_remote_texture_class_init (HildonRemoteTextureClass *klass)
+{
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ widget_class->realize = hildon_remote_texture_realize;
+ widget_class->unrealize = hildon_remote_texture_unrealize;
+ widget_class->show = hildon_remote_texture_show;
+ widget_class->hide = hildon_remote_texture_hide;
+
+ g_type_class_add_private (klass, sizeof (HildonRemoteTexturePrivate));
+}
+
+static void
+hildon_remote_texture_init (HildonRemoteTexture *self)
+{
+ HildonRemoteTexturePrivate
+ *priv = HILDON_REMOTE_TEXTURE_GET_PRIVATE (self);
+
+ /* Default non-zero values for the private variables */
+
+ priv->scale_x = 1;
+ priv->scale_y = 1;
+ priv->opacity = 0xff;
+}
+
+/**
+ * hildon_remote_texture_new:
+ *
+ * Creates a new #HildonRemoteTexture.
+ *
+ * Return value: A #HildonRemoteTexture
+ *
+ * Since: 2.2
+ **/
+GtkWidget*
+hildon_remote_texture_new (void)
+{
+ HildonRemoteTexture *newwindow = g_object_new (HILDON_TYPE_REMOTE_TEXTURE, NULL);
+
+ gtk_window_set_decorated (GTK_WINDOW (newwindow), FALSE);
+
+ return GTK_WIDGET (newwindow);
+}
+
+/*
+ * An filter for GDK X11 events, waiting for PropertyNotify (window property
+ * changes) events, keeping track of remote texture ready atom.
+ * Having the ready atom set on the window by the window manager will trigger
+ * updates of actor parameters (position/rotation/etc...) to be sent off
+ * to the window manager for processing.
+ */
+static GdkFilterReturn
+hildon_remote_texture_event_filter (GdkXEvent *xevent,
+ GdkEvent *event,
+ gpointer data)
+{
+ HildonRemoteTexture *self = HILDON_REMOTE_TEXTURE (data);
+ XAnyEvent *any = xevent;
+
+ if (any->type == PropertyNotify)
+ {
+ XPropertyEvent *property = xevent;
+
+ if (property->atom == ready_atom)
+ {
+ hildon_remote_texture_update_ready (self);
+ }
+ }
+
+ return GDK_FILTER_CONTINUE;
+}
+
+/*
+ * Check for the ready atom on the remote texture X11 window.
+ * If present, send all pending remote texture messages to the
+ * window manager.
+ */
+static void
+hildon_remote_texture_update_ready (HildonRemoteTexture *self)
+{
+ HildonRemoteTexturePrivate
+ *priv = HILDON_REMOTE_TEXTURE_GET_PRIVATE (self);
+ GtkWidget *widget = GTK_WIDGET (self);
+ Display *display = GDK_WINDOW_XDISPLAY (widget->window);
+ Window window = GDK_WINDOW_XID (widget->window);
+
+ int status;
+ gint xerror;
+
+ Atom actual_type;
+ int actual_format;
+ unsigned long nitems, bytes_after;
+ unsigned char *prop = NULL;
+
+ /* Check for the "ready" property */
+
+ gdk_error_trap_push ();
+ status = XGetWindowProperty (display, window,
+ ready_atom, 0, 32,
+ False, XA_ATOM,
+ &actual_type, &actual_format,
+ &nitems, &bytes_after, &prop);
+ xerror = gdk_error_trap_pop();
+
+ if (prop)
+ {
+ /* We do not actually use the property value for anything,
+ * it is enough that the property is set. */
+
+ XFree (prop);
+ }
+
+ if (xerror ||
+ (status != Success) || (actual_type != XA_ATOM) ||
+ (actual_format != 32) || (nitems != 1))
+ {
+ priv->ready = 0;
+ return;
+ }
+
+ if (priv->ready)
+ {
+ /* The ready flag has been set once already. This means that
+ * the WM has restarted. Trigger re-mapping of the widget to
+ * update the texture actor first. Then push all remote
+ * texture settings anew. */
+
+ priv->map_event_cb_id =
+ g_signal_connect (G_OBJECT (self),
+ "map-event",
+ G_CALLBACK(hildon_remote_texture_map_event),
+ self);
+
+ if (GTK_WIDGET_MAPPED (GTK_WIDGET (self)))
+ {
+ gtk_widget_unmap (GTK_WIDGET (self));
+ gtk_widget_map (GTK_WIDGET (self));
+ }
+
+ return;
+ }
+
+ priv->ready = 1;
+
+ /* Send all pending messages */
+
+ hildon_remote_texture_send_pending_messages (self);
+}
+
+static void
+hildon_remote_texture_send_pending_messages (HildonRemoteTexture *self)
+{
+ HildonRemoteTexturePrivate
+ *priv = HILDON_REMOTE_TEXTURE_GET_PRIVATE (self);
+
+ if (priv->set_shm)
+ hildon_remote_texture_set_image(self,
+ priv->shm_key,
+ priv->shm_width, priv->shm_height,
+ priv->shm_bpp);
+
+ if (priv->set_damage)
+ hildon_remote_texture_update_area (self,
+ priv->damage_x1,
+ priv->damage_y1,
+ priv->damage_x2 - priv->damage_x1,
+ priv->damage_y2 - priv->damage_y1);
+
+ if (priv->set_position)
+ hildon_remote_texture_set_position (self,
+ priv->x,
+ priv->y,
+ priv->width,
+ priv->height);
+
+ if (priv->set_offset)
+ hildon_remote_texture_set_offset (self,
+ priv->offset_x,
+ priv->offset_y);
+
+ if (priv->set_scale)
+ hildon_remote_texture_set_scale (self,
+ priv->scale_x,
+ priv->scale_y);
+
+ if (priv->set_parent)
+ hildon_remote_texture_set_parent (self,
+ priv->parent);
+
+ if (priv->set_show)
+ hildon_remote_texture_set_show_full (self,
+ priv->show, priv->opacity);
+}
+
+static void
+hildon_remote_texture_send_all_messages (HildonRemoteTexture *self)
+{
+ HildonRemoteTexturePrivate
+ *priv = HILDON_REMOTE_TEXTURE_GET_PRIVATE (self);
+
+ priv->set_shm = 1;
+ priv->set_damage = 1;
+ priv->set_position = 1;
+ priv->set_scale = 1;
+ priv->set_parent = 1;
+ priv->set_show = 1;
+
+ hildon_remote_texture_send_pending_messages (self);
+}
+
+/* ------------------------------------------------------------- */
+
+/**
+ * hildon_remote_texture_send_message:
+ * @self: A #HildonRemoteTexture
+ * @message_type: Message id for the remote texture message.
+ * @l0: 1st remote texture message parameter.
+ * @l1: 2nd remote texture message parameter.
+ * @l2: 3rd remote texture message parameter.
+ * @l3: 4th remote texture message parameter.
+ * @l4: 5th remote texture message parameter.
+ *
+ * Sends an X11 ClientMessage event to the window manager with
+ * the specified parameters -- id (@message_type) and data (@l0,
+ * @l1, @l2, @l3, @l4).
+ *
+ * This is an internal utility function that application will
+ * not need to call directly.
+ *
+ * Since: 2.2
+ **/
+void
+hildon_remote_texture_send_message (HildonRemoteTexture *self,
+ guint32 message_type,
+ guint32 l0,
+ guint32 l1,
+ guint32 l2,
+ guint32 l3,
+ guint32 l4)
+{
+ GtkWidget *widget = GTK_WIDGET (self);
+ Display *display = GDK_WINDOW_XDISPLAY (widget->window);
+ Window window = GDK_WINDOW_XID (widget->window);
+
+ XEvent event = { 0 };
+
+ event.xclient.type = ClientMessage;
+ event.xclient.window = window;
+ event.xclient.message_type = (Atom)message_type;
+ event.xclient.format = 32;
+ event.xclient.data.l[0] = l0;
+ event.xclient.data.l[1] = l1;
+ event.xclient.data.l[2] = l2;
+ event.xclient.data.l[3] = l3;
+ event.xclient.data.l[4] = l4;
+
+#if 0
+ g_debug ("%lu (%lu %lu %lu %lu %lu) -> %lu\n",
+ message_type,
+ l0, l1, l2, l3, l4,
+ window);
+#endif
+
+ XSendEvent (display, window, True,
+ StructureNotifyMask,
+ (XEvent *)&event);
+}
+
+/**
+ * hildon_remote_texture_set_image:
+ * @self: A #HildonRemoteTexture
+ * @key: The key that would be used with shmget in hildon-desktop. The key
+ * should probably be created with ftok, and the relevant shared memory
+ * area should be created before this call.
+ * @width: width of image in pixels
+ * @height: height of image in pixels
+ * @bpp: BYTES per pixel - usually 2,3 or 4
+ *
+ * Since: 2.2
+ */
+void
+hildon_remote_texture_set_image (HildonRemoteTexture *self,
+ key_t key,
+ guint width,
+ guint height,
+ guint bpp)
+{
+ HildonRemoteTexturePrivate
+ *priv = HILDON_REMOTE_TEXTURE_GET_PRIVATE (self);
+ GtkWidget *widget = GTK_WIDGET (self);
+
+ priv->set_shm = 1;
+ priv->shm_key = key;
+ priv->shm_width = width;
+ priv->shm_height = height;
+ priv->shm_bpp = bpp;
+
+ if (GTK_WIDGET_MAPPED (widget) && priv->ready)
+ {
+ /* Defer messages until the remote texture is parented
+ * and the parent window is mapped */
+ if (!priv->parent || !GTK_WIDGET_MAPPED (GTK_WIDGET (priv->parent)))
+ return;
+ hildon_remote_texture_send_message (self,
+ shm_atom,
+ priv->shm_key,
+ priv->shm_width,
+ priv->shm_height,
+ priv->shm_bpp,
+ 0);
+ priv->set_shm = 0;
+ }
+}
+
+/**
+ * hildon_remote_texture_update_area:
+ * @self: A #HildonRemoteTexture
+ * @x: offset of damaged area in pixels
+ * @y: offset of damaged area in pixels
+ * @width: width of damaged area in pixels
+ * @height: height of damaged area in pixels
+ *
+ * This signals to hildon-desktop that a specific region of the memory area
+ * has changed. This will trigger a redraw and will update the relevant tiles
+ * of the texture.
+ *
+ * Since: 2.2
+ */
+void
+hildon_remote_texture_update_area (HildonRemoteTexture *self,
+ gint x,
+ gint y,
+ gint width,
+ gint height)
+{
+ HildonRemoteTexturePrivate
+ *priv = HILDON_REMOTE_TEXTURE_GET_PRIVATE (self);
+ GtkWidget *widget = GTK_WIDGET (self);
+
+ if (priv->damage_x1==priv->damage_x2 || priv->damage_y1==priv->damage_y2)
+ {
+ priv->damage_x1 = x;
+ priv->damage_y1 = y;
+ priv->damage_x2 = x+width;
+ priv->damage_y2 = y+height;
+ }
+ else
+ {
+ if (x<priv->damage_x1) priv->damage_x1 = x;
+ if (y<priv->damage_y1) priv->damage_y1 = y;
+ if (x+width>priv->damage_x2) priv->damage_x2 = x+width;
+ if (y+height>priv->damage_y2) priv->damage_y2 = y+height;
+ }
+ priv->set_damage = 1;
+
+ if (GTK_WIDGET_MAPPED (widget) && priv->ready)
+ {
+ /* Defer messages until the remote texture is parented
+ * and the parent window is mapped */
+ if (!priv->parent || !GTK_WIDGET_MAPPED (GTK_WIDGET (priv->parent)))
+ return;
+ hildon_remote_texture_send_message (self,
+ damage_atom,
+ priv->damage_x1,
+ priv->damage_y1,
+ priv->damage_x2 - priv->damage_x1,
+ priv->damage_y2 - priv->damage_y1,
+ 0);
+ priv->set_damage = 0;
+ priv->damage_x1 = 0;
+ priv->damage_y1 = 0;
+ priv->damage_x2 = 0;
+ priv->damage_y2 = 0;
+ }
+}
+
+/**
+ * hildon_remote_texture_set_show_full:
+ * @self: A #HildonRemoteTexture
+ * @show: A boolean flag setting the visibility of the remote texture.
+ * @opacity: Desired opacity setting
+ *
+ * Send a message to the window manager setting the visibility of
+ * the remote texture. This will only affect the visibility of
+ * the remote texture set by the compositing window manager in its own
+ * rendering pipeline, after X has drawn the window to the off-screen
+ * buffer. This setting, naturally, has no effect if the #HildonRemoteTexture
+ * widget is not visible in X11 terms (i.e. realized and mapped).
+ *
+ * Furthermore, if a widget is parented, its final visibility will be
+ * affected by that of the parent window.
+ *
+ * The opacity setting ranges from zero (0), being completely transparent
+ * to 255 (0xff) being fully opaque.
+ *
+ * If the remote texture WM-counterpart is not ready, the show message
+ * will be queued until the WM is ready for it.
+ *
+ * Since: 2.2
+ **/
+void
+hildon_remote_texture_set_show_full (HildonRemoteTexture *self,
+ gint show,
+ gint opacity)
+{
+ HildonRemoteTexturePrivate
+ *priv = HILDON_REMOTE_TEXTURE_GET_PRIVATE (self);
+ GtkWidget *widget = GTK_WIDGET (self);
+
+ if (opacity > 255)
+ opacity = 255;
+
+ if (opacity < 0)
+ opacity = 0;
+
+ priv->show = show;
+ priv->opacity = opacity;
+ priv->set_show = 1;
+
+ if (GTK_WIDGET_MAPPED (widget) && priv->ready)
+ {
+ /* Defer show messages until the remote texture is parented
+ * and the parent window is mapped */
+ if (!priv->parent || !GTK_WIDGET_MAPPED (GTK_WIDGET (priv->parent)))
+ return;
+ hildon_remote_texture_send_message (self,
+ show_atom,
+ show, opacity,
+ 0, 0, 0);
+ priv->set_show = 0;
+ }
+}
+
+/**
+ * hildon_remote_texture_set_show:
+ * @self: A #HildonRemoteTexture
+ * @show: A boolean flag setting the visibility of the remote texture.
+ *
+ * This function is a shortcut for hildon_remote_texture_set_show_full(),
+ * setting the overall actor visibility without changing it's opacity
+ * setting.
+ *
+ * Since: 2.2
+ **/
+void
+hildon_remote_texture_set_show (HildonRemoteTexture *self,
+ gint show)
+{
+ HildonRemoteTexturePrivate
+ *priv = HILDON_REMOTE_TEXTURE_GET_PRIVATE (self);
+
+ hildon_remote_texture_set_show_full (self,
+ show, priv->opacity);
+}
+
+/**
+ * hildon_remote_texture_set_opacity:
+ * @self: A #HildonRemoteTexture
+ * @opacity: Desired opacity setting
+ *
+ * This function is a shortcut for hildon_remote_texture_set_show_full(),
+ * setting actor opacity without changing it's overall visibility.
+ *
+ * See hildon_remote_texture_set_show_full() for description of the range
+ * of values @opacity argument takes.
+ *
+ * Since: 2.2
+ **/
+void
+hildon_remote_texture_set_opacity (HildonRemoteTexture *self,
+ gint opacity)
+{
+ HildonRemoteTexturePrivate
+ *priv = HILDON_REMOTE_TEXTURE_GET_PRIVATE (self);
+
+ hildon_remote_texture_set_show_full (self,
+ priv->show, opacity);
+}
+
+/**
+ * hildon_remote_texture_set_position:
+ * @self: A #HildonRemoteTexture
+ * @x: Desired X coordinate
+ * @y: Desired Y coordinate
+ * @width: Desired width
+ * @height: Desired height
+ *
+ * Send a message to the window manager setting the offset of the remote
+ * texture in the window (in Remote texture's pixels). The texture
+ * is also subject to the animation effects rendered by the compositing
+ * window manager on that window (like those by task switcher).
+ *
+ * If the remote texture WM-counterpart is not ready, the show message
+ * will be queued until the WM is ready for it.
+ *
+ * Since: 2.2
+ **/
+void
+hildon_remote_texture_set_position (HildonRemoteTexture *self,
+ gint x,
+ gint y,
+ gint width,
+ gint height)
+{
+ HildonRemoteTexturePrivate
+ *priv = HILDON_REMOTE_TEXTURE_GET_PRIVATE (self);
+ GtkWidget *widget = GTK_WIDGET (self);
+
+ priv->x = x;
+ priv->y = y;
+ priv->width = width;
+ priv->height = height;
+ priv->set_position = 1;
+
+ if (GTK_WIDGET_MAPPED (widget) && priv->ready)
+ {
+ /* Defer messages until the remote texture is parented
+ * and the parent window is mapped */
+
+ if (!priv->parent || !GTK_WIDGET_MAPPED (GTK_WIDGET (priv->parent)))
+ return;
+ hildon_remote_texture_send_message (self,
+ position_atom,
+ x, y,
+ width, height, 0);
+ priv->set_position = 0;
+ }
+}
+
+/**
+ * hildon_remote_texture_set_offset:
+ * @self: A #HildonRemoteTexture
+ * @x: Desired X offset
+ * @y: Desired Y offset
+ *
+ * Send a message to the window manager setting the offset of the remote
+ * texture in the window (in Remote texture's pixels). The texture
+ * is also subject to the animation effects rendered by the compositing
+ * window manager on that window (like those by task switcher).
+ *
+ * If the remote texture WM-counterpart is not ready, the show message
+ * will be queued until the WM is ready for it.
+ *
+ * Since: 2.2
+ **/
+void
+hildon_remote_texture_set_offset (HildonRemoteTexture *self,
+ double x,
+ double y)
+{
+ HildonRemoteTexturePrivate
+ *priv = HILDON_REMOTE_TEXTURE_GET_PRIVATE (self);
+ GtkWidget *widget = GTK_WIDGET (self);
+
+ priv->offset_x = x;
+ priv->offset_y = y;
+ priv->set_offset = 1;
+
+ if (GTK_WIDGET_MAPPED (widget) && priv->ready)
+ {
+ /* Defer messages until the remote texture is parented
+ * and the parent window is mapped */
+
+ if (!priv->parent || !GTK_WIDGET_MAPPED (GTK_WIDGET (priv->parent)))
+ return;
+ hildon_remote_texture_send_message (self,
+ offset_atom,
+ (gint)(x*65536), (gint)(y*65536),
+ 0, 0, 0);
+ priv->set_offset = 0;
+ }
+}
+
+/**
+ * hildon_remote_texture_set_scalex:
+ * @self: A #HildonRemoteTexture
+ * @x_scale: The scale factor for the memory area to be rendered in the X-axis
+ * @y_scale: The scale factor for the memory area to be rendered in the X-axis
+ *
+ * Since: 2.2
+ **/
+void
+hildon_remote_texture_set_scale (HildonRemoteTexture *self,
+ double x_scale,
+ double y_scale)
+{
+ HildonRemoteTexturePrivate
+ *priv = HILDON_REMOTE_TEXTURE_GET_PRIVATE (self);
+ GtkWidget *widget = GTK_WIDGET (self);
+
+ priv->scale_x = x_scale;
+ priv->scale_y = y_scale;
+ priv->set_scale = 1;
+
+ if (GTK_WIDGET_MAPPED (widget) && priv->ready)
+ {
+ /* Defer messages until the remote texture is parented
+ * and the parent window is mapped */
+ if (!priv->parent || !GTK_WIDGET_MAPPED (GTK_WIDGET (priv->parent)))
+ return;
+ hildon_remote_texture_send_message (self,
+ scale_atom,
+ priv->scale_x * (1 << 16),
+ priv->scale_y * (1 << 16),
+ 0, 0, 0);
+ priv->set_scale = 0;
+ }
+}
+
+/*
+ * This callback will be triggered by the parent widget of
+ * an remote texture when it is mapped. The compositing
+ * window manager is now ready to parent the remote texture
+ * into the target parent window.
+ */
+static gboolean
+hildon_remote_texture_parent_map_event (GtkWidget *parent,
+ GdkEvent *event,
+ gpointer user_data)
+{
+ hildon_remote_texture_set_parent (HILDON_REMOTE_TEXTURE (user_data),
+ GTK_WINDOW (parent));
+ return FALSE;
+}
+
+/*
+ * This callback will be triggered by the widget re-mapping
+ * itself in case of WM restarting. The point is to push all
+ * remote texture parameters anew to the WM.
+ */
+static gboolean
+hildon_remote_texture_map_event (GtkWidget *widget,
+ GdkEvent *event,
+ gpointer user_data)
+{
+ HildonRemoteTexture
+ *self = HILDON_REMOTE_TEXTURE (user_data);
+ HildonRemoteTexturePrivate
+ *priv = HILDON_REMOTE_TEXTURE_GET_PRIVATE (self);
+
+ hildon_remote_texture_send_all_messages (self);
+
+ /* Disconnect the "map-event" handler after the "emergency resend all
+ * actor parameters" drill is over. */
+
+ if (priv->map_event_cb_id)
+ {
+ g_signal_handler_disconnect (self,
+ priv->map_event_cb_id);
+ priv->map_event_cb_id = 0;
+ }
+
+ return FALSE;
+}
+
+/**
+ * hildon_remote_texture_set_parent:
+ * @self: A #HildonRemoteTexture
+ * @parent: A #GtkWindow that the actor will be parented to.
+ *
+ * Send a message to the window manager setting the parent window
+ * for the remote texture. Parenting an actor will not affect the
+ * X window that the HildonRemoteTexture represents, but it's off-screen
+ * bitmap as it is handled by the compositing window manager.
+ *
+ * Parenting an remote texture will affect its visibility as set
+ * by the gtk_widget_show(), gtk_widget_hide() and
+ * hildon_remote_texture_set_show(). The remote texture will only be
+ * visible when the top-level window it is parented is visible.
+ *
+ * Passing %NULL as a @parent argument will unparent the remote texture.
+ * This will restore the actor's visibility if it was suppressed by
+ * being unparented or parented to an unmapped window.
+ *
+ * If the remote texture WM-counterpart is not ready, the show message
+ * will be queued until the WM is ready for it.
+ *
+ * Since: 2.2
+ **/
+void
+hildon_remote_texture_set_parent (HildonRemoteTexture *self,
+ GtkWindow *parent)
+{
+ HildonRemoteTexturePrivate
+ *priv = HILDON_REMOTE_TEXTURE_GET_PRIVATE (self);
+ GtkWidget *widget = GTK_WIDGET (self);
+
+ gtk_window_set_transient_for (GTK_WINDOW (self), parent);
+
+ if (priv->parent != parent)
+ {
+ /* Setting a new parent */
+
+ if (priv->parent)
+ {
+ if (priv->parent_map_event_cb_id)
+ g_signal_handler_disconnect (priv->parent,
+ priv->parent_map_event_cb_id);
+
+ /* Might need a synchronized "parent(0)" or "parent(new parent)"
+ * message here before we can safely decrease the reference count. */
+
+ g_object_unref (priv->parent);
+ }
+
+ priv->parent = parent;
+ priv->set_parent = 1;
+
+ if (parent != 0)
+ {
+ /* The widget is being (re)parented, not unparented. */
+
+ g_object_ref (parent);
+
+ priv->parent_map_event_cb_id =
+ g_signal_connect (G_OBJECT (priv->parent),
+ "map-event",
+ G_CALLBACK(hildon_remote_texture_parent_map_event),
+ self);
+ }
+ else
+ {
+ priv->parent_map_event_cb_id = 0;
+ }
+ }
+
+ if (GTK_WIDGET_MAPPED (widget) && priv->ready)
+ {
+ Window win = 0;
+
+ /* If the remote texture is being unparented or parented to an
+ * unmapped widget, force its visibility to "hidden". */
+
+ if (!priv->parent || !GTK_WIDGET_MAPPED (GTK_WIDGET (priv->parent)))
+ {
+ hildon_remote_texture_send_message (self,
+ show_atom,
+ 0, priv->opacity,
+ 0, 0, 0);
+ }
+
+ /* If the widget is being parented (parent != 0), only proceed when
+ * the parent widget is realized, since we need the X window id of
+ * the parent. If the widget is being unparented (parent == 0), pass
+ * the "special" window id of 0 in the message. */
+
+ if (priv->parent)
+ {
+ if (!GTK_WIDGET_MAPPED (GTK_WIDGET (priv->parent)))
+ return;
+
+ GdkWindow *gdk = GTK_WIDGET (parent)->window;
+ win = GDK_WINDOW_XID (gdk);
+ }
+
+ hildon_remote_texture_send_message (self,
+ parent_atom,
+ win,
+ 0, 0, 0, 0);
+ priv->set_parent = 0;
+
+ /* Set remote texture visibility to desired value (in case it was
+ * forced off when the actor was parented into an unmapped widget). */
+
+ hildon_remote_texture_send_message (self,
+ show_atom,
+ priv->show, priv->opacity,
+ 0, 0, 0);
+ priv->set_show = 0;
+ }
+}
+