diff options
author | 10:49:20 Tim Janik <timj@imendio.com> | 2008-05-21 19:04:24 +0000 |
---|---|---|
committer | Tim Janik <timj@src.gnome.org> | 2008-05-21 19:04:24 +0000 |
commit | 4111cf2065e1f7edc614a936f1fa35e750f13a0f (patch) | |
tree | 02dc780ca4f81be2b58623b6f293e03ee1cc9af8 /tests | |
parent | e10e51c958b9e981ce458dcfb53c3611246fef15 (diff) | |
download | gtk+-4111cf2065e1f7edc614a936f1fa35e750f13a0f.tar.gz |
Bug 318807 – Offscreen windows and window redirection.
2008-03-18 10:49:20 Tim Janik <timj@imendio.com>
* Applied pixmap redirection patch by Alexander Larsson with
various updates from:
Bug 318807 – Offscreen windows and window redirection.
Updates:
* updated docs to mention "Since 2.16".
* tests/testgtk.c: fixed snapshooting pixmap leak.
convert pixmap to pixbuf after snapshooting, to compensate for different
bit depths (occurs when snapshooting ARGB visuals and displaying the
pixmap in an RGB visual).
* gdk/gdkwindow.[hc]: made GdkWindowRedirect private.
* gdk/gdkwindow.c: removed damage idle handler, there's no aparent
need for it. enqueue damage notification as GDK_DAMAGE events
for each painting redirection at the start of the event queue.
consider windows with a redirection fully visible when invalidating,
and when updating from backing store. cleaned up stale variables.
* gdk/gdkevents.c: added _gdk_event_queue_prepend().
* gtk/gtkwidget.c: fixed coordinates for !NO_WINDOW widgets in
gtk_widget_get_snapshot; this fixes garbage snap offsets for gammacurve,
tree, drawingarea, text, handlebox, etc.
clip the redirected window hierarchy to window sizes, the visible
rectangles don't need to be taken into account here.
extended snapshooting docs to recommend gdk_pixbuf_get_from_drawable()
in case pixmap visuals could mismatch.
* gdk/x11/gdkwindow-x11.c: removed _gdk_windowing_window_get_visible_rect().
Base patch:
* tests/testgtk.c: add a "Snapshot" test to demonstrate snapshooting
of possibly obscured widgets into an offscreen pixmap.
* gtk/gtkwidget.[hc]: add GtkWidget::damage-event signal, add
gtk_widget_get_snapshot() to render a widget's contents to a GdkPixmap.
* gtk/gtkmain.c: dispatch GDK_DAMAGE events.
* gdk/gdkwindow.c: moved outer gdk_window_new() and gdk_window_reparent()
implementations here, adapted them to propagate redirects to child windows.
gdk_window_end_paint(): copy repainted window contents to redirection pixmap,
clipped to visible region. queue GDK_DAMAGE event delivery.
gdk_window_redirect_to_drawable(): install window painting redirection.
gdk_window_remove_redirection(): remove previously installed redirection.
* gdk/x11/gdkwindow-x11.c: added _gdk_windowing_window_get_visible_rect(),
renamed _gdk_window_new() and _gdk_window_reparent().
* gdk/gdkwindow.h: added GdkWindowRedirect* to GdkWindowObject, export
gdk_window_redirect_to_drawable() and gdk_window_remove_redirection().
* gdk/gdkevents.h: added GDK_DAMAGE event type.
* gdk/gdkevents.c: extract time and state from GDK_DAMAGE events.
* gdk/gdkinternals.h: added internal prototypes.
svn path=/trunk/; revision=20122
Diffstat (limited to 'tests')
-rw-r--r-- | tests/testgtk.c | 168 |
1 files changed, 167 insertions, 1 deletions
diff --git a/tests/testgtk.c b/tests/testgtk.c index 1c0dde58e0..e0a47e9b45 100644 --- a/tests/testgtk.c +++ b/tests/testgtk.c @@ -12206,6 +12206,171 @@ create_properties (GtkWidget *widget) } +struct SnapshotData { + GtkWidget *toplevel_button; + GtkWidget **window; + GdkCursor *cursor; + gboolean in_query; + gboolean is_toplevel; + gint handler; +}; + +static void +destroy_snapshot_data (GtkWidget *widget, + struct SnapshotData *data) +{ + if (*data->window) + *data->window = NULL; + + if (data->cursor) + { + gdk_cursor_unref (data->cursor); + data->cursor = NULL; + } + + if (data->handler) + { + g_signal_handler_disconnect (widget, data->handler); + data->handler = 0; + } + + g_free (data); +} + +static gint +snapshot_widget_event (GtkWidget *widget, + GdkEvent *event, + struct SnapshotData *data) +{ + GtkWidget *res_widget = NULL; + + if (!data->in_query) + return FALSE; + + if (event->type == GDK_BUTTON_RELEASE) + { + gtk_grab_remove (widget); + gdk_display_pointer_ungrab (gtk_widget_get_display (widget), + GDK_CURRENT_TIME); + + res_widget = find_widget_at_pointer (gtk_widget_get_display (widget)); + if (data->is_toplevel && res_widget) + res_widget = gtk_widget_get_toplevel (res_widget); + if (res_widget) + { + GdkPixmap *pixmap; + GdkPixbuf *pixbuf = NULL; + GtkWidget *window, *image; + + window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + pixmap = gtk_widget_get_snapshot (res_widget); + gtk_widget_realize (window); + if (gdk_drawable_get_depth (window->window) != gdk_drawable_get_depth (pixmap)) + { + /* this branch is needed to convert ARGB -> RGB */ + int width, height; + gdk_drawable_get_size (pixmap, &width, &height); + pixbuf = gdk_pixbuf_get_from_drawable (NULL, pixmap, + gtk_widget_get_colormap (res_widget), + 0, 0, + 0, 0, + width, height); + image = gtk_image_new_from_pixbuf (pixbuf); + } + else + image = gtk_image_new_from_pixmap (pixmap, NULL); + g_object_unref (pixbuf); + gtk_container_add (GTK_CONTAINER (window), image); + g_object_unref (pixmap); + gtk_widget_show_all (window); + } + + data->in_query = FALSE; + } + return FALSE; +} + + +static void +snapshot_widget (GtkButton *button, + struct SnapshotData *data) +{ + gint failure; + + g_signal_connect (button, "event", + G_CALLBACK (snapshot_widget_event), data); + + data->is_toplevel = GTK_WIDGET (button) == data->toplevel_button; + + if (!data->cursor) + data->cursor = gdk_cursor_new_for_display (gtk_widget_get_display (GTK_WIDGET (button)), + GDK_TARGET); + + failure = gdk_pointer_grab (GTK_WIDGET (button)->window, + TRUE, + GDK_BUTTON_RELEASE_MASK, + NULL, + data->cursor, + GDK_CURRENT_TIME); + + gtk_grab_add (GTK_WIDGET (button)); + + data->in_query = TRUE; +} + +static void +create_snapshot (GtkWidget *widget) +{ + static GtkWidget *window = NULL; + GtkWidget *button; + GtkWidget *vbox; + struct SnapshotData *data; + + data = g_new (struct SnapshotData, 1); + data->window = &window; + data->in_query = FALSE; + data->cursor = NULL; + data->handler = 0; + + if (!window) + { + window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + + gtk_window_set_screen (GTK_WINDOW (window), + gtk_widget_get_screen (widget)); + + data->handler = g_signal_connect (window, "destroy", + G_CALLBACK (destroy_snapshot_data), + data); + + gtk_window_set_title (GTK_WINDOW (window), "test snapshot"); + gtk_container_set_border_width (GTK_CONTAINER (window), 10); + + vbox = gtk_vbox_new (FALSE, 1); + gtk_container_add (GTK_CONTAINER (window), vbox); + + button = gtk_button_new_with_label ("Snapshot widget"); + gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0); + g_signal_connect (button, "clicked", + G_CALLBACK (snapshot_widget), + data); + + button = gtk_button_new_with_label ("Snapshot toplevel"); + data->toplevel_button = button; + gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0); + g_signal_connect (button, "clicked", + G_CALLBACK (snapshot_widget), + data); + } + + if (!GTK_WIDGET_VISIBLE (window)) + gtk_widget_show_all (window); + else + gtk_widget_destroy (window); + +} + + /* * Color Preview @@ -13489,6 +13654,7 @@ struct { { "scrolled windows", create_scrolled_windows }, { "shapes", create_shapes }, { "size groups", create_size_groups }, + { "snapshot", create_snapshot }, { "spinbutton", create_spins }, { "statusbar", create_statusbar }, { "styles", create_styles }, @@ -13524,7 +13690,7 @@ create_main_window (void) window = gtk_window_new (GTK_WINDOW_TOPLEVEL); gtk_widget_set_name (window, "main window"); - gtk_widget_set_uposition (window, 20, 20); + gtk_widget_set_uposition (window, 50, 20); gtk_window_set_default_size (GTK_WINDOW (window), -1, 400); geometry.min_width = -1; |