summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRay Strode <rstrode@redhat.com>2007-03-11 22:17:36 -0400
committerRay Strode <rstrode@redhat.com>2007-03-11 22:17:36 -0400
commit1941315592d575eb33e2d0360e8b0c95df70d2a2 (patch)
tree4edff19f99c3938c37c880dc72fba7997dac5b0d
parente0bda1a81a55ba9092a9f5a9850dff46e7a1acc2 (diff)
add random, broken hack to get the basics of damage reporting in
-rw-r--r--Makefile2
-rw-r--r--pop-demo.c142
-rw-r--r--pop-window.c60
3 files changed, 154 insertions, 50 deletions
diff --git a/Makefile b/Makefile
index c57528f..a2d8a44 100644
--- a/Makefile
+++ b/Makefile
@@ -1,3 +1,3 @@
all:
- gcc pop-overlay-window.c pop-window.c pop-demo.c -o pop-demo `pkg-config --cflags --libs glib-2.0 gtk+-2.0 cairo cairo-xlib` -lXcomposite -ggdb3 -O0
+ gcc pop-overlay-window.c pop-window.c pop-demo.c -o pop-demo `pkg-config --cflags --libs glib-2.0 gtk+-2.0 cairo cairo-xlib xcomposite xdamage ` -ggdb3 -O0
diff --git a/pop-demo.c b/pop-demo.c
index 57edea4..8224abf 100644
--- a/pop-demo.c
+++ b/pop-demo.c
@@ -3,6 +3,7 @@
#include <glib.h>
#include <X11/extensions/Xcomposite.h>
+#include <X11/extensions/Xdamage.h>
#include <X11/extensions/Xfixes.h>
#include <cairo.h>
@@ -15,9 +16,12 @@
#include "pop-overlay-window.h"
#include "pop-window.h"
-static GList *window_list = NULL;
+static GList *window_list = NULL, *pending_window_redraw_list = NULL;;
-gboolean
+static int damage_extension_event_base,
+ damage_extension_error_base;
+
+static gboolean
composite_is_available (void)
{
int event_base, error_base;
@@ -25,7 +29,17 @@ composite_is_available (void)
event_base = 0;
error_base = 0;
if (XCompositeQueryExtension (GDK_DISPLAY (), &event_base, &error_base))
- return TRUE;
+ return TRUE;
+ return FALSE;
+}
+
+static gboolean
+initialize_damage_extension (void)
+{
+ if (XDamageQueryExtension (GDK_DISPLAY (), &damage_extension_event_base,
+ &damage_extension_error_base))
+ return TRUE;
+
return FALSE;
}
@@ -34,8 +48,12 @@ draw_windows (cairo_t *cairo_context)
{
GList *tmp;
- for (tmp = window_list; tmp != NULL; tmp = tmp->next)
+ for (tmp = pending_window_redraw_list; tmp != NULL; tmp = tmp->next)
pop_window_draw (POP_WINDOW (tmp->data), cairo_context);
+
+ g_list_foreach (pending_window_redraw_list, (GFunc) g_object_unref, NULL);
+ g_list_free (pending_window_redraw_list);
+ pending_window_redraw_list = NULL;
}
static void
@@ -46,27 +64,53 @@ free_window_list (void)
window_list = NULL;
}
+gint
+window_compare (PopWindow *window_1,
+ Window *x_window_id)
+{
+ return ((gulong ) pop_window_get_x_window_id (window_1))
+ - *x_window_id;
+}
+
+static PopWindow *
+find_window_from_x_window_id (Window x_window_id)
+{
+
+ GList *node;
+
+ node = g_list_find_custom (window_list, &x_window_id,
+ (GCompareFunc) window_compare);
+
+ if (node == NULL)
+ return NULL;
+
+ return (PopWindow *) node->data;
+}
+
static void
-create_window_list (void)
+refresh_window_list (void)
{
Window root, parent;
- Window *windows;
+ Window *x_window_ids;
guint number_of_windows, i;
if (!XQueryTree (GDK_DISPLAY (),
GDK_ROOT_WINDOW (), &root, &parent,
- &windows, &number_of_windows))
+ &x_window_ids, &number_of_windows))
return;
for (i = 0; i < number_of_windows; i++)
{
- PopWindow *window;
-
- window = pop_window_new (windows[i]);
- window_list = g_list_append (window_list, window);
+ if (!find_window_from_x_window_id (x_window_ids[i]))
+ {
+ PopWindow *window;
+
+ window = pop_window_new (x_window_ids[i]);
+ window_list = g_list_append (window_list, window);
+ }
}
- XFree (windows);
+ XFree (x_window_ids);
}
static gboolean
@@ -85,12 +129,11 @@ on_expose_event (GtkWidget *widget,
}
static gboolean
-do_update_state (PopOverlayWindow *window)
+do_update_state (PopOverlayWindow *overlay_window)
{
- free_window_list ();
- create_window_list ();
+ static gboolean ran_before = FALSE;
- gtk_widget_queue_draw (GTK_WIDGET (window));
+ refresh_window_list ();
return TRUE;
}
@@ -107,9 +150,68 @@ on_map (GtkWidget *widget)
XCompositeRedirectSubwindows (GDK_DISPLAY (),
GDK_ROOT_WINDOW (),
CompositeRedirectManual);
+ do_update_state (POP_OVERLAY_WINDOW (widget));
+ pending_window_redraw_list = g_list_copy (window_list);
+ g_list_foreach (pending_window_redraw_list, (GFunc) g_object_ref, NULL);
g_timeout_add (1000 / 60., (GSourceFunc) do_update_state, widget);
}
+static gboolean
+x_event_is_damage_notify_event (XEvent *x_event)
+{
+ return x_event->type == damage_extension_event_base + XDamageNotify;
+}
+
+static void
+on_damage_notify_event (XDamageNotifyEvent *damage_notify_event,
+ PopOverlayWindow *overlay_window)
+{
+ GdkDisplay *display;
+ PopWindow *window;
+ Window x_window_id;
+
+ x_window_id = (Window) damage_notify_event->drawable;
+ window = find_window_from_x_window_id (x_window_id);
+
+ gdk_error_trap_push ();
+
+ XDamageSubtract (GDK_DISPLAY (),
+ damage_notify_event->damage,
+ None, None);
+
+ gdk_flush ();
+ gdk_error_trap_pop ();
+
+
+ if (window == NULL)
+ return;
+
+ pending_window_redraw_list = g_list_append (pending_window_redraw_list,
+ g_object_ref (window));
+}
+
+static gboolean
+redraw_pending_windows (PopOverlayWindow *overlay_window)
+{
+ if (pending_window_redraw_list != NULL)
+ gtk_widget_queue_draw (GTK_WIDGET (overlay_window));
+ return FALSE;
+}
+
+static GdkFilterReturn
+on_event (XEvent *x_event,
+ GdkEvent *event,
+ PopOverlayWindow *overlay_window)
+{
+ if (x_event_is_damage_notify_event (x_event))
+ on_damage_notify_event ((XDamageNotifyEvent *) x_event, overlay_window);
+
+ g_idle_add_full (GDK_PRIORITY_REDRAW, (GSourceFunc) redraw_pending_windows,
+ overlay_window, NULL);
+
+ return GDK_FILTER_CONTINUE;
+}
+
int
main (int argc,
char **argv)
@@ -125,6 +227,12 @@ main (int argc,
return 1;
}
+ if (!initialize_damage_extension ())
+ {
+ g_printerr ("damage extension not found\n");
+ return 2;
+ }
+
overlay_window = pop_overlay_window_new ();
gtk_container_set_border_width (GTK_CONTAINER (overlay_window), 200);
@@ -139,6 +247,8 @@ main (int argc,
gtk_container_add (GTK_CONTAINER (overlay_window), button);
gtk_widget_show_all (overlay_window);
+ gdk_window_add_filter (NULL, (GdkFilterFunc) on_event, overlay_window);
+
gtk_main();
return 0;
diff --git a/pop-window.c b/pop-window.c
index 9186a8c..e2a6f72 100644
--- a/pop-window.c
+++ b/pop-window.c
@@ -26,17 +26,22 @@
#include <glib-object.h>
#include <glib/gi18n.h>
+#include <cairo.h>
+
+#include <X11/extensions/Xcomposite.h>
+#include <X11/extensions/Xdamage.h>
+
+#include <cairo-xlib.h>
#include <gdk/gdkx.h>
+
#include <gdk/gdk.h>
#include <gtk/gtk.h>
-#include <cairo.h>
-#include <cairo-xlib.h>
-
struct _PopWindowPrivate
{
Window x_window_id;
+ Damage x_damage_id;
cairo_pattern_t *pattern;
};
@@ -131,6 +136,24 @@ pop_window_class_install_properties (PopWindowClass *window_class)
}
static void
+pop_window_enable_damage_reporting (PopWindow *window)
+{
+ GtkWidget *widget;
+ GdkDisplay *display;
+
+ g_assert (POP_IS_WINDOW (window));
+
+ display = gdk_display_get_default ();
+
+ gdk_error_trap_push ();
+ window->priv->x_damage_id = XDamageCreate (GDK_DISPLAY_XDISPLAY (display),
+ window->priv->x_window_id,
+ XDamageReportNonEmpty);
+ gdk_flush ();
+ gdk_error_trap_pop ();
+}
+
+static void
pop_window_init (PopWindow *window)
{
g_assert (POP_IS_WINDOW (window));
@@ -224,6 +247,7 @@ pop_window_set_x_window_id (PopWindow *window,
if (window->priv->x_window_id != x_window_id)
{
window->priv->x_window_id = x_window_id;
+ pop_window_enable_damage_reporting (window);
g_object_notify (G_OBJECT (window), "x-window-id");
}
}
@@ -310,33 +334,3 @@ pop_window_draw (PopWindow *window,
cairo_set_source (cairo_context, window->priv->pattern);
cairo_paint (cairo_context);
}
-
-#ifdef POP_WINDOW_ENABLE_TEST
-
-#include <stdio.h>
-#include <glib.h>
-
-int
-main (int argc, char **argv)
-{
- PopWindow *window;
- int exit_code;
-
- g_log_set_always_fatal (G_LOG_LEVEL_ERROR
- | G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_WARNING);
-
- g_type_init ();
-
- g_message ("creating instance of 'window' object...");
- window = pop_window_new ();
- g_message ("'window' object created successfully");
-
- g_message ("destroying previously created 'window' object...");
- g_object_unref (window);
- g_message ("'window' object destroyed successfully");
-
- exit_code = 0;
-
- return exit_code;
-}
-#endif /* POP_WINDOW_ENABLE_TEST */