From be22b9fbb9ecd683b9b41d64144460f41d07f248 Mon Sep 17 00:00:00 2001 From: "Owen W. Taylor" Date: Wed, 30 Jan 2013 15:09:44 -0500 Subject: [PATCH] GdkWindow: make the frame clock an inherent property of the window Instead of making the frame clock a settable property of a window, make toplevel windows inherently have a frame clock when created (getting rid of the default frame clock.) We need to create or destroy frame clocks when reparenting a window to be a toplevel, or to not be a toplevel, but otherwise the frame clock for a window is immutable. --- gdk/gdkwindow.c | 187 ++++++++++++++-------------------------- gdk/gdkwindow.h | 3 +- gdk/x11/gdkwindow-x11.c | 34 ++++++-- gdk/x11/gdkwindow-x11.h | 1 + 4 files changed, 92 insertions(+), 133 deletions(-) diff --git a/gdk/gdkwindow.c b/gdk/gdkwindow.c index 38543ce123..c626b2c6b5 100644 --- a/gdk/gdkwindow.c +++ b/gdk/gdkwindow.c @@ -170,8 +170,7 @@ enum { enum { PROP_0, - PROP_CURSOR, - PROP_FRAME_CLOCK + PROP_CURSOR }; typedef enum { @@ -240,9 +239,8 @@ static void gdk_window_invalidate_rect_full (GdkWindow *window, static void _gdk_window_propagate_has_alpha_background (GdkWindow *window); static cairo_surface_t *gdk_window_ref_impl_surface (GdkWindow *window); -static void gdk_window_process_all_updates_internal (gboolean default_clock_only); - -static void gdk_ensure_default_frame_clock (void); +static void gdk_window_set_frame_clock (GdkWindow *window, + GdkFrameClock *clock); static guint signals[LAST_SIGNAL] = { 0 }; @@ -394,23 +392,6 @@ gdk_window_class_init (GdkWindowClass *klass) GDK_TYPE_CURSOR, G_PARAM_READWRITE)); - /** - * GdkWindow:paint-clock: - * - * The frame clock for a #GdkWindow, see #GdkFrameClock - * - * The frame clock remains the same for the lifetime of the window. - * - * Since: 3.0 - */ - g_object_class_install_property (object_class, - PROP_FRAME_CLOCK, - g_param_spec_object ("paint-clock", - P_("Frame clock"), - P_("Frame clock"), - GDK_TYPE_FRAME_CLOCK, - G_PARAM_READWRITE)); - /** * GdkWindow::pick-embedded-child: * @window: the window on which the signal is emitted @@ -623,10 +604,6 @@ gdk_window_set_property (GObject *object, gdk_window_set_cursor (window, g_value_get_object (value)); break; - case PROP_FRAME_CLOCK: - gdk_window_set_frame_clock (window, g_value_get_object (value)); - break; - default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -647,10 +624,6 @@ gdk_window_get_property (GObject *object, g_value_set_object (value, gdk_window_get_cursor (window)); break; - case PROP_FRAME_CLOCK: - g_value_set_object (value, gdk_window_get_frame_clock (window)); - break; - default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -1496,6 +1469,12 @@ gdk_window_new (GdkWindow *parent, if (window->parent) window->parent->children = g_list_prepend (window->parent->children, window); + if (window->parent->window_type == GDK_WINDOW_ROOT) + { + GdkFrameClock *frame_clock = g_object_new (GDK_TYPE_FRAME_CLOCK_IDLE, NULL); + gdk_window_set_frame_clock (window, frame_clock); + } + native = FALSE; if (window->parent->window_type == GDK_WINDOW_ROOT) native = TRUE; /* Always use native windows for toplevels */ @@ -1746,6 +1725,27 @@ gdk_window_reparent (GdkWindow *window, } } + /* If we changed the window type, we might have to set or + * unset the frame clock on the window + */ + if (GDK_WINDOW_TYPE (new_parent) == GDK_WINDOW_ROOT && + GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN) + { + if (window->frame_clock == NULL) + { + GdkFrameClock *frame_clock = g_object_new (GDK_TYPE_FRAME_CLOCK_IDLE, NULL); + gdk_window_set_frame_clock (window, frame_clock); + } + } + else + { + if (window->frame_clock != NULL) + { + g_object_run_dispose (G_OBJECT (window->frame_clock)); + gdk_window_set_frame_clock (window, NULL); + } + } + /* We might have changed window type for a native windows, so we need to change the event mask too. */ if (gdk_window_has_impl (window)) @@ -2065,6 +2065,12 @@ _gdk_window_destroy_hierarchy (GdkWindow *window, } } + if (window->frame_clock) + { + g_object_run_dispose (G_OBJECT (window->frame_clock)); + gdk_window_set_frame_clock (window, NULL); + } + gdk_window_free_paint_stack (window); if (window->background) @@ -3809,7 +3815,6 @@ gdk_cairo_create (GdkWindow *window) /* Code for dirty-region queueing */ static GSList *update_windows = NULL; -static GdkFrameClock *_gdk_default_frame_clock = NULL; static gboolean debug_updates = FALSE; static inline gboolean @@ -3908,27 +3913,6 @@ gdk_window_remove_update_window (GdkWindow *window) update_windows = g_slist_remove (update_windows, window); } -static void -gdk_window_paint_default_clock_updates (gpointer data) -{ - gdk_window_process_all_updates_internal (TRUE); -} - -static void -gdk_ensure_default_frame_clock (void) -{ - if (_gdk_default_frame_clock == NULL) - { - _gdk_default_frame_clock = g_object_new (GDK_TYPE_FRAME_CLOCK_IDLE, - NULL); - - g_signal_connect (G_OBJECT (_gdk_default_frame_clock), - "paint", - G_CALLBACK (gdk_window_paint_default_clock_updates), - NULL); - } -} - static gboolean gdk_window_is_toplevel_frozen (GdkWindow *window) { @@ -3942,13 +3926,20 @@ gdk_window_is_toplevel_frozen (GdkWindow *window) static void gdk_window_schedule_update (GdkWindow *window) { + GdkFrameClock *frame_clock; + if (window && (window->update_freeze_count || gdk_window_is_toplevel_frozen (window))) return; - gdk_frame_clock_request_phase (gdk_window_get_frame_clock (window), - GDK_FRAME_CLOCK_PHASE_PAINT); + /* If there's no frame clock (a foreign window), then the invalid + * region will just stick around unless gdk_window_process_updates() + * is called. */ + frame_clock = gdk_window_get_frame_clock (window); + if (frame_clock) + gdk_frame_clock_request_phase (gdk_window_get_frame_clock (window), + GDK_FRAME_CLOCK_PHASE_PAINT); } void @@ -4261,19 +4252,6 @@ after_process_all_updates (void) g_slist_free (displays); } -/** - * gdk_window_process_all_updates: - * - * Calls gdk_window_process_updates() for all windows (see #GdkWindow) - * in the application. - * - **/ -void -gdk_window_process_all_updates (void) -{ - gdk_window_process_all_updates_internal (FALSE); -} - /* Currently it is not possible to override * gdk_window_process_all_updates in the same manner as * gdk_window_process_updates and gdk_window_invalidate_maybe_recurse @@ -4284,8 +4262,15 @@ gdk_window_process_all_updates (void) * displays and call the mehod. */ -static void -gdk_window_process_all_updates_internal (gboolean default_clock_only) +/** + * gdk_window_process_all_updates: + * + * Calls gdk_window_process_updates() for all windows (see #GdkWindow) + * in the application. + * + **/ +void +gdk_window_process_all_updates (void) { GSList *old_update_windows = update_windows; GSList *tmp_list = update_windows; @@ -4316,8 +4301,7 @@ gdk_window_process_all_updates_internal (gboolean default_clock_only) if (!GDK_WINDOW_DESTROYED (window)) { if (window->update_freeze_count || - gdk_window_is_toplevel_frozen (window) || - (default_clock_only && window->frame_clock != NULL)) + gdk_window_is_toplevel_frozen (window)) gdk_window_add_update_window (window); else gdk_window_process_updates_internal (window); @@ -11635,38 +11619,17 @@ gdk_window_resume_events (GdkFrameClock *clock, _gdk_display_unpause_events (display); } -/** - * gdk_window_set_frame_clock: - * @window: window to set frame clock on - * @clock: the clock - * - * Sets the frame clock for the window. The frame clock for a window - * cannot be changed while the window is mapped. Set the frame - * clock to #NULL to use the default frame clock. (By default the - * frame clock comes from the window's parent or is a global default - * frame clock.) - * - * Since: 3.0 - */ -void +static void gdk_window_set_frame_clock (GdkWindow *window, GdkFrameClock *clock) { g_return_if_fail (GDK_IS_WINDOW (window)); g_return_if_fail (clock == NULL || GDK_IS_FRAME_CLOCK (clock)); - g_return_if_fail (!GDK_WINDOW_IS_MAPPED (window)); + g_return_if_fail (clock == NULL || gdk_window_is_toplevel (window)); if (clock == window->frame_clock) return; - /* If we are using our parent's clock, then the parent will repaint - * us when that clock fires. If we are using the default clock, then - * it does a gdk_window_process_all_updates() which will repaint us - * when the clock fires. If we are using our own clock, then we have - * to connect to "paint" on it ourselves and paint ourselves and - * any child windows. - */ - if (clock) { g_object_ref (clock); @@ -11699,12 +11662,6 @@ gdk_window_set_frame_clock (GdkWindow *window, } window->frame_clock = clock; - g_object_notify (G_OBJECT (window), "paint-clock"); - - /* We probably should recurse child windows and emit notify on their - * paint-clock properties also, and we should emit notify when a - * window is first parented. - */ } /** @@ -11712,36 +11669,20 @@ gdk_window_set_frame_clock (GdkWindow *window, * @window: window to get frame clock for * * Gets the frame clock for the window. The frame clock for a window - * never changes while the window is mapped. It may be changed at - * other times. + * never changes unless the window is reparented to a new toplevel + * window. * - * Since: 3.0 + * Since: 3.8 * Return value: (transfer none): the frame clock */ GdkFrameClock* gdk_window_get_frame_clock (GdkWindow *window) { + GdkWindow *toplevel; + g_return_val_if_fail (GDK_IS_WINDOW (window), NULL); - if (window->frame_clock != NULL) - { - /* Frame clock set explicitly on this window */ - return window->frame_clock; - } - else - { - GdkWindow *parent; + toplevel = gdk_window_get_toplevel (window); - /* parent's frame clock or default */ - parent = gdk_window_get_effective_parent (window); - if (parent != NULL) - { - return gdk_window_get_frame_clock (parent); - } - else - { - gdk_ensure_default_frame_clock (); - return _gdk_default_frame_clock; - } - } + return toplevel->frame_clock; } diff --git a/gdk/gdkwindow.h b/gdk/gdkwindow.h index ef8bb5eb82..d2ee972cbb 100644 --- a/gdk/gdkwindow.h +++ b/gdk/gdkwindow.h @@ -905,8 +905,7 @@ void gdk_window_set_support_multidevice (GdkWindow *window, gboolean gdk_window_get_support_multidevice (GdkWindow *window); /* Frame clock */ -void gdk_window_set_frame_clock (GdkWindow *window, - GdkFrameClock *clock); +GDK_AVAILABLE_IN_3_8 GdkFrameClock* gdk_window_get_frame_clock (GdkWindow *window); G_END_DECLS diff --git a/gdk/x11/gdkwindow-x11.c b/gdk/x11/gdkwindow-x11.c index 7541e59531..6bb1ee2caa 100644 --- a/gdk/x11/gdkwindow-x11.c +++ b/gdk/x11/gdkwindow-x11.c @@ -35,7 +35,6 @@ #include "gdkasync.h" #include "gdkeventsource.h" #include "gdkdisplay-x11.h" -#include "gdkframeclockidle.h" #include "gdkprivate-x11.h" #include @@ -964,6 +963,25 @@ on_frame_clock_after_paint (GdkFrameClock *clock, } +static void +connect_frame_clock (GdkWindow *window) +{ + GdkWindowImplX11 *impl; + + impl = GDK_WINDOW_IMPL_X11 (window->impl); + if (WINDOW_IS_TOPLEVEL (window) && !impl->frame_clock_connected) + { + GdkFrameClock *frame_clock = gdk_window_get_frame_clock (window); + + g_signal_connect (frame_clock, "before-paint", + G_CALLBACK (on_frame_clock_before_paint), window); + g_signal_connect (frame_clock, "after-paint", + G_CALLBACK (on_frame_clock_after_paint), window); + + impl->frame_clock_connected = TRUE; + } +} + void _gdk_x11_display_create_window_impl (GdkDisplay *display, GdkWindow *window, @@ -976,7 +994,6 @@ _gdk_x11_display_create_window_impl (GdkDisplay *display, GdkWindowImplX11 *impl; GdkX11Screen *x11_screen; GdkX11Display *display_x11; - GdkFrameClock *clock; Window xparent; Visual *xvisual; @@ -1122,12 +1139,7 @@ _gdk_x11_display_create_window_impl (GdkDisplay *display, GDK_WINDOW_XID (window), event_mask, StructureNotifyMask | PropertyChangeMask); - clock = g_object_new (GDK_TYPE_FRAME_CLOCK_IDLE, NULL); - gdk_window_set_frame_clock (window, clock); - g_signal_connect (clock, "before-paint", - G_CALLBACK (on_frame_clock_before_paint), window); - g_signal_connect (clock, "after-paint", - G_CALLBACK (on_frame_clock_after_paint), window); + connect_frame_clock (window); if (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD) gdk_window_freeze_toplevel_updates_libgtk_only (window); @@ -1895,6 +1907,12 @@ gdk_window_x11_reparent (GdkWindow *window, _gdk_x11_window_tmp_reset_parent_bg (window); _gdk_x11_window_tmp_reset_bg (window, TRUE); + if (WINDOW_IS_TOPLEVEL (window)) + connect_frame_clock (window); + else + /* old frame clock was disposed, our signal handlers removed */ + impl->frame_clock_connected = FALSE; + if (GDK_WINDOW_TYPE (new_parent) == GDK_WINDOW_FOREIGN) new_parent = gdk_screen_get_root_window (GDK_WINDOW_SCREEN (window)); diff --git a/gdk/x11/gdkwindow-x11.h b/gdk/x11/gdkwindow-x11.h index aefc88262c..9982a5ee1c 100644 --- a/gdk/x11/gdkwindow-x11.h +++ b/gdk/x11/gdkwindow-x11.h @@ -72,6 +72,7 @@ struct _GdkWindowImplX11 guint no_bg : 1; /* Set when the window background is temporarily * unset during resizing and scaling */ guint override_redirect : 1; + guint frame_clock_connected : 1; cairo_surface_t *cairo_surface;