diff options
author | Ray Strode <rstrode@redhat.com> | 2007-03-11 22:17:36 -0400 |
---|---|---|
committer | Ray Strode <rstrode@redhat.com> | 2007-03-11 22:17:36 -0400 |
commit | 1941315592d575eb33e2d0360e8b0c95df70d2a2 (patch) | |
tree | 4edff19f99c3938c37c880dc72fba7997dac5b0d | |
parent | e0bda1a81a55ba9092a9f5a9850dff46e7a1acc2 (diff) |
add random, broken hack to get the basics of damage reporting in
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | pop-demo.c | 142 | ||||
-rw-r--r-- | pop-window.c | 60 |
3 files changed, 154 insertions, 50 deletions
@@ -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 @@ -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 */ |