summaryrefslogtreecommitdiff
path: root/src/pop-window-view.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/pop-window-view.c')
-rw-r--r--src/pop-window-view.c934
1 files changed, 934 insertions, 0 deletions
diff --git a/src/pop-window-view.c b/src/pop-window-view.c
new file mode 100644
index 0000000..117d4bb
--- /dev/null
+++ b/src/pop-window-view.c
@@ -0,0 +1,934 @@
+/* pop-window-view.c -
+ *
+ * Copyright (C) 2007 Ray Strode <rstrode@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+#include "pop-window-view.h"
+
+#include <errno.h>
+#include <string.h>
+
+#include <glib.h>
+#include <glib-object.h>
+#include <glib/gi18n.h>
+
+#include <cairo.h>
+
+#include <X11/extensions/Xcomposite.h>
+#include <X11/extensions/Xdamage.h>
+#include <X11/extensions/shape.h>
+
+#include <cairo-xlib.h>
+#include <gdk/gdkx.h>
+
+#include <gdk/gdk.h>
+
+#include "pop-event-listener.h"
+
+struct _PopWindowViewPrivate
+{
+ GdkWindow *window;
+ PopEventListener *event_listener;
+
+ Damage damage;
+ cairo_pattern_t *pattern;
+ cairo_path_t *clip_path;
+ GdkRectangle damaged_area;
+
+ guint is_damaged : 1;
+
+ gint x, y;
+ gint width, height;
+};
+
+#if 0
+static void pop_window_view_class_install_signals (PopWindowViewClass * window_class);
+#endif
+static void pop_window_view_class_install_properties (PopWindowViewClass *
+ window_class);
+
+static void pop_window_view_set_property (GObject * object,
+ guint prop_id,
+ const GValue * value,
+ GParamSpec * pspec);
+static void pop_window_view_get_property (GObject * object,
+ guint prop_id,
+ GValue * value, GParamSpec * pspec);
+
+static void pop_window_view_do_finalize (GObject *object);
+
+enum
+{
+ PROP_0 = 0,
+ PROP_WINDOW
+};
+
+#define POP_WINDOW_VIEW_INVALID_WINDOW (Window) 0
+#define POP_WINDOW_VIEW_INVALID_PIXMAP (Pixmap) 0
+#define POP_WINDOW_VIEW_INVALID_DAMAGE (Damage) 0
+
+#if 0
+enum
+{
+ FOO = 0,
+ NUMBER_OF_SIGNALS
+};
+
+static guint pop_window_view_signals[NUMBER_OF_SIGNALS];
+#endif
+
+G_DEFINE_TYPE (PopWindowView, pop_window_view, G_TYPE_OBJECT);
+
+static void
+pop_window_view_class_init (PopWindowViewClass *window_class)
+{
+ GObjectClass *object_class;
+
+ object_class = G_OBJECT_CLASS (window_class);
+
+ object_class->finalize = pop_window_view_do_finalize;
+
+ pop_window_view_class_install_properties (window_class);
+#if 0
+ pop_window_view_class_install_signals (window_class);
+#endif
+
+ g_type_class_add_private (window_class, sizeof (PopWindowViewPrivate));
+}
+
+#if 0
+static void
+pop_window_view_class_install_signals (PopWindowViewClass * window_class)
+{
+ GObjectClass *object_class;
+
+ object_class = G_OBJECT_CLASS (window_class);
+
+ pop_window_view_signals[FOO] =
+ g_signal_new ("foo", G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (PopWindowViewClass, foo),
+ NULL, NULL, g_cclosure_marshal_VOID__NONE; G_TYPE_NONE, 0);
+ window_class->foo = NULL;
+}
+#endif
+
+static void
+pop_window_view_class_install_properties (PopWindowViewClass *window_class)
+{
+ GObjectClass *object_class;
+ GParamSpec *param_spec;
+
+ object_class = G_OBJECT_CLASS (window_class);
+ object_class->set_property = pop_window_view_set_property;
+ object_class->get_property = pop_window_view_get_property;
+
+ param_spec = NULL;
+#if 0
+ param_spec = g_param_spec_ulong ("x-window-id", _("X Window ID"),
+ _("A client-side identifier representing a "
+ "server-side window"), 0, G_MAXULONG,
+ (gulong) POP_WINDOW_VIEW_INVALID_WINDOW,
+ G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
+ g_object_class_install_property (object_class, PROP_WINDOW, param_spec);
+#endif
+}
+
+static void
+pop_window_view_init (PopWindowView *view)
+{
+ g_assert (POP_IS_WINDOW_VIEW (view));
+
+ view->priv = G_TYPE_INSTANCE_GET_PRIVATE (view,
+ POP_TYPE_WINDOW_VIEW,
+ PopWindowViewPrivate);
+
+ view->priv->event_listener = pop_event_listener_get_default ();
+ pop_event_listener_start (view->priv->event_listener);
+}
+
+static void
+pop_window_view_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ PopWindowView *view = POP_WINDOW_VIEW (object);
+
+ switch (prop_id)
+ {
+ case PROP_WINDOW:
+ view = NULL;
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+pop_window_view_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ PopWindowView *view = POP_WINDOW_VIEW (object);
+
+ switch (prop_id)
+ {
+ case PROP_WINDOW:
+ view = NULL;
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+pop_window_view_do_finalize (GObject *object)
+{
+ PopWindowView *view;
+ GObjectClass *parent_class;
+
+ view = POP_WINDOW_VIEW (object);
+
+ if (view->priv->window != NULL)
+ pop_window_view_unset_window (view);
+
+ parent_class = G_OBJECT_CLASS (pop_window_view_parent_class);
+
+ if (parent_class->finalize != NULL)
+ parent_class->finalize (object);
+}
+
+static gboolean
+pop_window_get_initial_geometry (PopWindowView *view)
+{
+ g_assert (POP_IS_WINDOW_VIEW (view));
+ g_assert (view->priv->window != NULL);
+
+ gdk_window_get_geometry (view->priv->window,
+ &view->priv->x,
+ &view->priv->y,
+ &view->priv->width,
+ &view->priv->height,
+ NULL);
+ return TRUE;
+}
+
+static cairo_surface_t *
+pop_window_view_get_surface (PopWindowView *view)
+{
+ cairo_surface_t *surface;
+ cairo_status_t status;
+
+ g_assert (POP_IS_WINDOW_VIEW (view));
+ g_assert (view->priv->pattern != NULL);
+
+ surface = NULL;
+ status = cairo_pattern_get_surface (view->priv->pattern, &surface);
+ g_assert (status != CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
+
+ return surface;
+}
+
+static void
+pop_window_view_free_x_pixmap (PopWindowView *view)
+{
+ cairo_surface_t *surface;
+ Pixmap pixmap;
+
+ g_assert (POP_IS_WINDOW_VIEW (view));
+
+ surface = pop_window_view_get_surface (view);
+
+ g_assert (surface != NULL);
+ pixmap = (Pixmap) cairo_xlib_surface_get_drawable (surface);
+ XFreePixmap (GDK_WINDOW_XDISPLAY (view->priv->window), pixmap);
+}
+
+static void
+pop_window_view_destroy_pattern (PopWindowView *view)
+{
+ g_assert (POP_IS_WINDOW_VIEW (view));
+
+ if (view->priv->pattern == NULL)
+ return;
+
+ pop_window_view_free_x_pixmap (view);
+ cairo_pattern_destroy (view->priv->pattern);
+ view->priv->pattern = NULL;
+}
+
+static void
+pop_window_view_destroy_clip_path (PopWindowView *view)
+{
+ g_assert (POP_IS_WINDOW_VIEW (view));
+
+ if (view->priv->clip_path == NULL)
+ return;
+
+ cairo_path_destroy (view->priv->clip_path);
+ view->priv->clip_path = NULL;
+}
+
+GQuark
+pop_window_view_error_quark (void)
+{
+ static GQuark error_quark = 0;
+
+ if (error_quark == 0)
+ error_quark = g_quark_from_static_string ("pop-window");
+
+ return error_quark;
+}
+
+PopWindowView *
+pop_window_view_new (void)
+{
+ PopWindowView *view;
+
+ view = g_object_new (POP_TYPE_WINDOW_VIEW, NULL);
+
+ return view;
+}
+
+static gboolean
+pop_window_view_redirect_window_off_screen (PopWindowView *view)
+{
+ g_assert (POP_IS_WINDOW_VIEW (view));
+
+ gdk_error_trap_push ();
+ XCompositeRedirectWindow (GDK_WINDOW_XDISPLAY (view->priv->window),
+ GDK_WINDOW_XWINDOW (view->priv->window),
+ CompositeRedirectAutomatic);
+ gdk_flush ();
+ if (gdk_error_trap_pop ())
+ return FALSE;
+
+ return TRUE;
+}
+
+static Pixmap
+pop_window_view_fetch_window_pixmap (PopWindowView *view)
+{
+ Pixmap pixmap;
+ gint status;
+
+ g_assert (POP_IS_WINDOW_VIEW (view));
+
+ gdk_error_trap_push ();
+ pixmap =
+ XCompositeNameWindowPixmap (GDK_WINDOW_XDISPLAY (view->priv->window),
+ GDK_WINDOW_XWINDOW (view->priv->window));
+ gdk_flush ();
+ status = gdk_error_trap_pop ();
+
+ if (status != Success)
+ {
+ char error_message[64];
+
+ XGetErrorText (GDK_WINDOW_XDISPLAY (view->priv->window),
+ status, error_message, sizeof (error_message) - 1);
+ g_print ("could not name pixmap for window 0x%lx: %s\n",
+ GDK_WINDOW_XWINDOW (view->priv->window),
+ error_message);
+
+ return POP_WINDOW_VIEW_INVALID_PIXMAP;
+ }
+
+ return pixmap;
+}
+
+static gboolean
+pop_window_view_create_pattern_from_window (PopWindowView *view)
+{
+ GdkVisual *visual;
+ Pixmap pixmap;
+ cairo_surface_t *surface;
+ cairo_status_t status;
+ int width, height;
+
+ g_assert (POP_IS_WINDOW_VIEW (view));
+ g_assert (view->priv->window != NULL);
+ g_assert (view->priv->pattern == NULL);
+
+ pixmap = pop_window_view_fetch_window_pixmap (view);
+
+ if (pixmap == POP_WINDOW_VIEW_INVALID_PIXMAP)
+ {
+ g_print ("couldn't fetch pixmap for window\n");
+ return FALSE;
+ }
+
+ gdk_drawable_get_size (GDK_DRAWABLE (view->priv->window),
+ &width, &height);
+
+ visual = gdk_drawable_get_visual (GDK_DRAWABLE (view->priv->window));
+ surface = cairo_xlib_surface_create (GDK_WINDOW_XDISPLAY (view->priv->window),
+ (Drawable) pixmap,
+ GDK_VISUAL_XVISUAL (visual),
+ width, height);
+ status = cairo_surface_status (surface);
+ if (status != CAIRO_STATUS_SUCCESS)
+ {
+ g_print ("could create xlib surface for window: %s\n", cairo_status_to_string (status));
+ goto failed;
+ }
+
+ view->priv->pattern = cairo_pattern_create_for_surface (surface);
+ cairo_surface_destroy (surface);
+
+ status = cairo_pattern_status (view->priv->pattern);
+ if (status != CAIRO_STATUS_SUCCESS)
+ {
+ g_print ("couldn't create cairo pattern: %s\n", cairo_status_to_string (status));
+ goto failed;
+ }
+
+ return TRUE;
+
+failed:
+ if (view->priv->pattern != NULL)
+ {
+ cairo_pattern_destroy (view->priv->pattern);
+ view->priv->pattern = NULL;
+ }
+
+ XFreePixmap (GDK_WINDOW_XDISPLAY (view->priv->window),
+ pixmap);
+
+ return FALSE;
+}
+
+static XRectangle *
+pop_window_view_get_tesselated_window_shape (PopWindowView *view,
+ gint *number_of_rectangles)
+{
+ XRectangle *rectangles;
+ gint ordering;
+ gint status;
+
+ g_assert (POP_IS_WINDOW_VIEW (view));
+ g_assert (number_of_rectangles != NULL);
+
+ *number_of_rectangles = 0;
+
+ gdk_error_trap_push ();
+ rectangles = XShapeGetRectangles (GDK_WINDOW_XDISPLAY (view->priv->window),
+ GDK_WINDOW_XWINDOW (view->priv->window),
+ ShapeBounding, number_of_rectangles,
+ &ordering);
+ gdk_flush ();
+ status = gdk_error_trap_pop ();
+
+ if (status != Success)
+ return NULL;
+
+ return rectangles;
+}
+
+
+static gboolean
+pop_window_view_set_clip_path_from_window (PopWindowView *view)
+{
+ XRectangle *rectangles;
+ gint number_of_rectangles;
+ cairo_t *cairo_context;
+ cairo_surface_t *surface;
+ cairo_status_t status;
+ gint i;
+
+ g_assert (POP_IS_WINDOW_VIEW (view));
+ g_assert (view->priv->clip_path == NULL);
+
+ rectangles = pop_window_view_get_tesselated_window_shape (view,
+ &number_of_rectangles);
+
+ if (rectangles == NULL)
+ return FALSE;
+
+ surface = cairo_image_surface_create (CAIRO_FORMAT_A1,
+ view->priv->width, view->priv->height);
+
+ status = cairo_surface_status (surface);
+
+ if (status != CAIRO_STATUS_SUCCESS)
+ {
+ XFree (rectangles);
+ return FALSE;
+ }
+
+ cairo_context = cairo_create (surface);
+
+ for (i = 0; i < number_of_rectangles; i++)
+ {
+ cairo_rectangle (cairo_context,
+ rectangles[i].x,
+ rectangles[i].y,
+ rectangles[i].width,
+ rectangles[i].height);
+ }
+
+ view->priv->clip_path = cairo_copy_path_flat (cairo_context);
+ cairo_destroy (cairo_context);
+
+ return TRUE;
+}
+
+static void
+pop_window_view_enable_window_geometry_reporting (PopWindowView *view)
+{
+ GdkEventMask event_mask;
+
+ g_assert (POP_IS_WINDOW_VIEW (view));
+
+ event_mask = gdk_window_get_events (view->priv->window);
+
+ gdk_window_set_events (view->priv->window, event_mask | GDK_STRUCTURE_MASK | GDK_EXPOSURE_MASK);
+}
+
+static void
+pop_window_view_disable_window_geometry_reporting (PopWindowView *view)
+{
+ GdkEventMask event_mask;
+
+ g_assert (POP_IS_WINDOW_VIEW (view));
+
+ event_mask = gdk_window_get_events (view->priv->window);
+
+ gdk_window_set_events (view->priv->window, event_mask & ~GDK_STRUCTURE_MASK);
+}
+
+static void
+pop_window_view_enable_window_shape_reporting (PopWindowView *view)
+{
+ g_assert (POP_IS_WINDOW_VIEW (view));
+
+ XShapeSelectInput (GDK_WINDOW_XDISPLAY (view->priv->window),
+ GDK_WINDOW_XWINDOW (view->priv->window),
+ ShapeNotifyMask);
+}
+
+static void
+pop_window_view_disable_window_shape_reporting (PopWindowView *view)
+{
+ g_assert (POP_IS_WINDOW_VIEW (view));
+
+ XShapeSelectInput (GDK_WINDOW_XDISPLAY (view->priv->window),
+ GDK_WINDOW_XWINDOW (view->priv->window),
+ 0);
+}
+
+static void
+pop_window_view_enable_window_damage_reporting (PopWindowView *view)
+{
+ g_assert (POP_IS_WINDOW_VIEW (view));
+
+ view->priv->damage =
+ XDamageCreate (GDK_WINDOW_XDISPLAY (view->priv->window),
+ GDK_WINDOW_XWINDOW (view->priv->window),
+ XDamageReportNonEmpty);
+}
+
+static void
+pop_window_view_disable_window_damage_reporting (PopWindowView *view)
+{
+ g_assert (POP_IS_WINDOW_VIEW (view));
+
+ gdk_error_trap_push ();
+ XDamageDestroy (GDK_WINDOW_XDISPLAY (view->priv->window),
+ view->priv->damage);
+ gdk_flush ();
+ gdk_error_trap_pop ();
+ view->priv->damage = POP_WINDOW_VIEW_INVALID_DAMAGE;
+}
+
+static void
+pop_window_view_window_redrawn (PopWindowView *view,
+ GdkWindow *window,
+ GdkRectangle *rectangle)
+{
+ g_print ("window 0x%lx redrawn (area: %dx%d+%d+%d)\n", GDK_WINDOW_XWINDOW (view->priv->window), rectangle->x, rectangle->y, rectangle->width, rectangle->height);
+ if (view->priv->pattern == NULL)
+ pop_window_view_create_pattern_from_window (view);
+
+ if (view->priv->clip_path == NULL)
+ pop_window_view_set_clip_path_from_window (view);
+
+ gdk_rectangle_union (&view->priv->damaged_area,
+ rectangle,
+ &view->priv->damaged_area);
+
+ view->priv->is_damaged = TRUE;
+}
+
+static void
+pop_window_view_window_resized (PopWindowView *view)
+{
+ gint old_width, old_height;
+
+ g_print ("window 0x%lx resized\n", GDK_WINDOW_XWINDOW (view->priv->window));
+
+ old_width = view->priv->width;
+ old_height = view->priv->height;
+
+ gdk_drawable_get_size (GDK_DRAWABLE (view->priv->window),
+ &view->priv->width,
+ &view->priv->height);
+ pop_window_view_destroy_pattern (view);
+ pop_window_view_create_pattern_from_window (view);
+
+ pop_window_view_destroy_clip_path (view);
+ pop_window_view_set_clip_path_from_window (view);
+
+ g_print ("window 0x%lx resized from (%dx%d) to (%dx%d)\n",
+ GDK_WINDOW_XWINDOW (view->priv->window),
+ old_width, old_height,
+ view->priv->width, view->priv->height);
+}
+
+static void
+pop_window_view_window_moved (PopWindowView *view)
+{
+ gint old_x, old_y;
+
+ old_x = view->priv->x;
+ old_y = view->priv->y;
+
+ gdk_window_get_position (GDK_DRAWABLE (view->priv->window),
+ &view->priv->x,
+ &view->priv->y);
+
+ g_print ("window 0x%lx moved from (%d, %d) to (%d, %d)\n",
+ GDK_WINDOW_XWINDOW (view->priv->window),
+ old_x, old_y, view->priv->x, view->priv->y);
+}
+
+static void
+pop_window_view_window_shown (PopWindowView *view)
+{
+ g_print ("window 0x%lx is now visible\n",
+ GDK_WINDOW_XWINDOW (view->priv->window));
+ if (view->priv->pattern == NULL)
+ pop_window_view_create_pattern_from_window (view);
+
+ if (view->priv->clip_path == NULL)
+ pop_window_view_set_clip_path_from_window (view);
+}
+
+static void
+pop_window_view_window_hidden (PopWindowView *view)
+{
+ g_print ("window 0x%lx hidden\n", GDK_WINDOW_XWINDOW (view->priv->window));
+ pop_window_view_destroy_pattern (view);
+}
+
+static void
+pop_window_view_window_destroyed (PopWindowView *view)
+{
+ g_print ("window 0x%lx destroyed\n", GDK_WINDOW_XWINDOW (view->priv->window));
+ pop_window_view_unset_window (view);
+}
+
+static void
+pop_window_view_window_reshaped (PopWindowView *view)
+{
+ gint old_width, old_height;
+
+ g_print ("window 0x%lx reshaped\n", GDK_WINDOW_XWINDOW (view->priv->window));
+ old_width = view->priv->width;
+ old_height = view->priv->height;
+
+ gdk_drawable_get_size (GDK_DRAWABLE (view->priv->window),
+ &view->priv->width,
+ &view->priv->height);
+ pop_window_view_destroy_pattern (view);
+ pop_window_view_create_pattern_from_window (view);
+
+ pop_window_view_destroy_clip_path (view);
+ pop_window_view_set_clip_path_from_window (view);
+}
+
+static void
+pop_window_view_window_reparented (PopWindowView *view)
+{
+ g_print ("window 0x%lx reparented\n", GDK_WINDOW_XWINDOW (view->priv->window));
+ pop_window_view_unset_window (view);
+}
+
+static void
+pop_window_view_listen_to_window (PopWindowView *view)
+{
+ gchar detailed_signal[sizeof ("window-XXXXXXXXXX::ffffffff")];
+
+ g_print ("listening to window 0x%lx\n", GDK_WINDOW_XWINDOW (view->priv->window));
+
+ snprintf (detailed_signal, sizeof (detailed_signal),
+ "window-destroyed::%lx", GDK_WINDOW_XWINDOW (view->priv->window));
+ g_signal_connect_swapped (G_OBJECT (view->priv->event_listener),
+ detailed_signal,
+ G_CALLBACK (pop_window_view_window_destroyed),
+ view);
+ snprintf (detailed_signal, sizeof (detailed_signal),
+ "window-shown::%lx", GDK_WINDOW_XWINDOW (view->priv->window));
+ g_signal_connect_swapped (G_OBJECT (view->priv->event_listener),
+ detailed_signal,
+ G_CALLBACK (pop_window_view_window_shown),
+ view);
+ snprintf (detailed_signal, sizeof (detailed_signal),
+ "window-hidden::%lx", GDK_WINDOW_XWINDOW (view->priv->window));
+ g_signal_connect_swapped (G_OBJECT (view->priv->event_listener),
+ detailed_signal,
+ G_CALLBACK (pop_window_view_window_hidden),
+ view);
+ snprintf (detailed_signal, sizeof (detailed_signal),
+ "window-resized::%lx", GDK_WINDOW_XWINDOW (view->priv->window));
+ g_signal_connect_swapped (G_OBJECT (view->priv->event_listener),
+ detailed_signal,
+ G_CALLBACK (pop_window_view_window_resized),
+ view);
+ snprintf (detailed_signal, sizeof (detailed_signal),
+ "window-reshaped::%lx", GDK_WINDOW_XWINDOW (view->priv->window));
+ g_signal_connect_swapped (G_OBJECT (view->priv->event_listener),
+ detailed_signal,
+ G_CALLBACK (pop_window_view_window_reshaped),
+ view);
+ snprintf (detailed_signal, sizeof (detailed_signal),
+ "window-reparented::%lx", GDK_WINDOW_XWINDOW (view->priv->window));
+ g_signal_connect_swapped (G_OBJECT (view->priv->event_listener),
+ detailed_signal,
+ G_CALLBACK (pop_window_view_window_reparented),
+ view);
+ snprintf (detailed_signal, sizeof (detailed_signal),
+ "window-moved::%lx", GDK_WINDOW_XWINDOW (view->priv->window));
+ g_signal_connect_swapped (G_OBJECT (view->priv->event_listener),
+ detailed_signal,
+ G_CALLBACK (pop_window_view_window_moved),
+ view);
+ snprintf (detailed_signal, sizeof (detailed_signal),
+ "window-redrawn::%lx", GDK_WINDOW_XWINDOW (view->priv->window));
+ g_signal_connect_swapped (G_OBJECT (view->priv->event_listener),
+ detailed_signal,
+ G_CALLBACK (pop_window_view_window_redrawn),
+ view);
+}
+
+static void
+pop_window_view_ignore_window (PopWindowView *view)
+{
+ g_print ("ignoring window 0x%lx\n", GDK_WINDOW_XWINDOW (view->priv->window));
+
+ g_signal_handlers_disconnect_by_func (G_OBJECT (view->priv->event_listener),
+ G_CALLBACK (pop_window_view_window_destroyed),
+ view);
+ g_signal_handlers_disconnect_by_func (G_OBJECT (view->priv->event_listener),
+ G_CALLBACK (pop_window_view_window_shown),
+ view);
+ g_signal_handlers_disconnect_by_func (G_OBJECT (view->priv->event_listener),
+ G_CALLBACK (pop_window_view_window_hidden),
+ view);
+ g_signal_handlers_disconnect_by_func (G_OBJECT (view->priv->event_listener),
+ G_CALLBACK (pop_window_view_window_resized),
+ view);
+ g_signal_handlers_disconnect_by_func (G_OBJECT (view->priv->event_listener),
+ G_CALLBACK (pop_window_view_window_reshaped),
+ view);
+ g_signal_handlers_disconnect_by_func (G_OBJECT (view->priv->event_listener),
+ G_CALLBACK (pop_window_view_window_reparented),
+ view);
+ g_signal_handlers_disconnect_by_func (G_OBJECT (view->priv->event_listener),
+ G_CALLBACK (pop_window_view_window_moved),
+ view);
+ g_signal_handlers_disconnect_by_func (G_OBJECT (view->priv->event_listener),
+ G_CALLBACK (pop_window_view_window_redrawn),
+ view);
+}
+
+static gboolean
+pop_window_view_enable_window_status_reporting (PopWindowView *view)
+{
+ gint status;
+
+ g_assert (POP_IS_WINDOW_VIEW (view));
+
+ gdk_error_trap_push ();
+ pop_window_view_enable_window_geometry_reporting (view);
+ pop_window_view_enable_window_shape_reporting (view);
+ pop_window_view_enable_window_damage_reporting (view);
+ pop_window_view_listen_to_window (view);
+ gdk_flush ();
+ status = gdk_error_trap_pop ();
+
+ return status == Success;
+}
+
+static void
+pop_window_view_disable_window_status_reporting (PopWindowView *view)
+{
+ g_assert (POP_IS_WINDOW_VIEW (view));
+
+ if ((view->priv->window == NULL) || GDK_WINDOW_DESTROYED (view->priv->window))
+ return;
+
+ pop_window_view_disable_window_damage_reporting (view);
+
+ gdk_error_trap_push ();
+ pop_window_view_disable_window_geometry_reporting (view);
+ pop_window_view_disable_window_shape_reporting (view);
+ pop_window_view_ignore_window (view);
+ gdk_flush ();
+ gdk_error_trap_pop ();
+}
+
+gboolean
+pop_window_view_set_window (PopWindowView *view,
+ GdkWindow *window)
+{
+ g_return_val_if_fail (POP_IS_WINDOW_VIEW (view), FALSE);
+ g_return_val_if_fail (window != NULL, FALSE);
+
+ g_return_val_if_fail (view->priv->window == NULL, FALSE);
+ view->priv->window = window;
+
+ if (!pop_window_get_initial_geometry (view))
+ {
+ g_print ("couldn't get initial geometry\n");
+ view->priv->window = NULL;
+ return FALSE;
+ }
+
+ if (!pop_window_view_enable_window_status_reporting (view))
+ {
+ g_print ("couldn't enable damage for window\n");
+ pop_window_view_disable_window_status_reporting (view);
+ view->priv->window = NULL;
+ return FALSE;
+ }
+
+ if (!pop_window_view_redirect_window_off_screen (view))
+ {
+ g_print ("couldn't redirect window off screen\n");
+ view->priv->window = NULL;
+ return FALSE;
+ }
+
+ if (gdk_window_is_visible (view->priv->window))
+ pop_window_view_window_shown (view);
+
+ g_object_ref (window);
+
+ return TRUE;
+}
+
+void
+pop_window_view_unset_window (PopWindowView *view)
+{
+ g_return_if_fail (POP_IS_WINDOW_VIEW (view));
+ g_return_if_fail (view->priv->window != NULL);
+
+ pop_window_view_disable_window_status_reporting (view);
+ pop_window_view_destroy_clip_path (view);
+ pop_window_view_destroy_pattern (view);
+
+ g_object_unref (view->priv->window);
+ view->priv->window = NULL;
+
+ g_object_unref (view->priv->event_listener);
+ view->priv->event_listener = NULL;
+}
+
+GdkWindow *
+pop_window_view_get_window (PopWindowView *view)
+{
+ g_return_val_if_fail (POP_IS_WINDOW_VIEW (view), NULL);
+
+ return view->priv->window;
+}
+
+void
+pop_window_view_report_fixed_damage (PopWindowView *view)
+{
+ gdk_error_trap_push ();
+ XDamageSubtract (GDK_WINDOW_XDISPLAY (view->priv->window),
+ view->priv->damage, None, None);
+ gdk_flush ();
+ gdk_error_trap_pop ();
+
+ view->priv->is_damaged = FALSE;
+ view->priv->damaged_area.x = 0;
+ view->priv->damaged_area.y = 0;
+ view->priv->damaged_area.width = 0;
+ view->priv->damaged_area.height = 0;
+}
+
+void
+pop_window_view_render_to_context (PopWindowView *view,
+ cairo_t *cairo_context)
+{
+ g_return_if_fail (POP_IS_WINDOW_VIEW (view));
+ g_return_if_fail (cairo_context != NULL);
+
+ if (view->priv->pattern == NULL)
+ return;
+
+ pop_window_view_report_fixed_damage (view);
+
+ cairo_save (cairo_context);
+ cairo_translate (cairo_context, view->priv->x, view->priv->y);
+#if 0
+ char *text;
+ text = g_strdup_printf ("0x%lx", GDK_WINDOW_XWINDOW (view->priv->window));
+ cairo_move_to (cairo_context, view->priv->width, view->priv->height);
+ cairo_show_text (cairo_context, text);
+ g_free (text);
+#endif
+
+ cairo_set_source (cairo_context, view->priv->pattern);
+ cairo_move_to (cairo_context, 0.0, 0.0);
+ cairo_append_path (cairo_context, view->priv->clip_path);
+ cairo_clip (cairo_context);
+ cairo_paint (cairo_context);
+
+ cairo_restore (cairo_context);
+}
+
+void
+pop_window_view_get_size (PopWindowView *view,
+ int *width,
+ int *height)
+{
+
+ if (width)
+ *width = view->priv->width;
+
+ if (height)
+ *height = view->priv->height;
+}
+
+void
+pop_window_view_get_position (PopWindowView *view,
+ int *x,
+ int *y)
+{
+ if (x)
+ *x = view->priv->x;
+
+ if (y)
+ *y = view->priv->y;
+}