mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-12-25 21:21:21 +00:00
Use GdkFrameClock for relayout
Add a ::layout signal to GdkFrameClock and use it instead of an idle handler to drive the restyling and relayout of containers. https://bugzilla.gnome.org/show_bug.cgi?id=685460
This commit is contained in:
parent
77bac0d6ae
commit
7753883add
@ -79,6 +79,7 @@ G_DEFINE_INTERFACE (GdkFrameClock, gdk_frame_clock, G_TYPE_OBJECT)
|
||||
enum {
|
||||
FRAME_REQUESTED,
|
||||
BEFORE_PAINT,
|
||||
LAYOUT,
|
||||
PAINT,
|
||||
AFTER_PAINT,
|
||||
LAST_SIGNAL
|
||||
@ -122,6 +123,23 @@ gdk_frame_clock_default_init (GdkFrameClockInterface *iface)
|
||||
g_cclosure_marshal_VOID__VOID,
|
||||
G_TYPE_NONE, 0);
|
||||
|
||||
/**
|
||||
* GdkFrameClock::layout:
|
||||
* @clock: the frame clock emitting the signal
|
||||
*
|
||||
* This signal is emitted immediately before the paint signal and
|
||||
* indicates that the frame time has been updated, and signal
|
||||
* handlers should perform any preparatory work before painting.
|
||||
*/
|
||||
signals[LAYOUT] =
|
||||
g_signal_new (g_intern_static_string ("layout"),
|
||||
GDK_TYPE_FRAME_CLOCK,
|
||||
G_SIGNAL_RUN_LAST,
|
||||
0,
|
||||
NULL, NULL,
|
||||
g_cclosure_marshal_VOID__VOID,
|
||||
G_TYPE_NONE, 0);
|
||||
|
||||
/**
|
||||
* GdkFrameClock::paint:
|
||||
* @clock: the frame clock emitting the signal
|
||||
@ -279,6 +297,9 @@ gdk_frame_clock_paint (GdkFrameClock *clock)
|
||||
g_signal_emit (G_OBJECT (clock),
|
||||
signals[BEFORE_PAINT], 0);
|
||||
|
||||
g_signal_emit (G_OBJECT (clock),
|
||||
signals[LAYOUT], 0);
|
||||
|
||||
g_signal_emit (G_OBJECT (clock),
|
||||
signals[PAINT], 0);
|
||||
|
||||
|
@ -54,6 +54,7 @@ struct _GdkFrameClockInterface
|
||||
/* signals */
|
||||
/* void (* frame_requested) (GdkFrameClock *clock); */
|
||||
/* void (* before_paint) (GdkFrameClock *clock); */
|
||||
/* void (* layout) 1(GdkFrameClock *clock); */
|
||||
/* void (* paint) (GdkFrameClock *clock); */
|
||||
/* void (* after_paint) (GdkFrameClock *clock); */
|
||||
};
|
||||
|
@ -236,6 +236,9 @@ struct _GtkContainerPrivate
|
||||
{
|
||||
GtkWidget *focus_child;
|
||||
|
||||
guint resize_handler;
|
||||
GdkFrameClock *resize_clock;
|
||||
|
||||
guint border_width : 16;
|
||||
|
||||
guint has_focus_chain : 1;
|
||||
@ -344,8 +347,6 @@ static const gchar vadjustment_key[] = "gtk-vadjustment";
|
||||
static guint vadjustment_key_id = 0;
|
||||
static const gchar hadjustment_key[] = "gtk-hadjustment";
|
||||
static guint hadjustment_key_id = 0;
|
||||
static GSList *container_resize_queue = NULL;
|
||||
static GSList *container_restyle_queue = NULL;
|
||||
static guint container_signals[LAST_SIGNAL] = { 0 };
|
||||
static GtkWidgetClass *parent_class = NULL;
|
||||
extern GParamSpecPool *_gtk_widget_child_property_pool;
|
||||
@ -1357,10 +1358,15 @@ gtk_container_destroy (GtkWidget *widget)
|
||||
|
||||
if (priv->resize_pending)
|
||||
_gtk_container_dequeue_resize_handler (container);
|
||||
|
||||
if (priv->restyle_pending)
|
||||
priv->restyle_pending = FALSE;
|
||||
|
||||
if (priv->resize_handler)
|
||||
{
|
||||
container_restyle_queue = g_slist_remove (container_restyle_queue, container);
|
||||
priv->restyle_pending = FALSE;
|
||||
g_signal_handler_disconnect (priv->resize_clock, priv->resize_handler);
|
||||
priv->resize_handler = 0;
|
||||
priv->resize_clock = NULL;
|
||||
}
|
||||
|
||||
if (priv->focus_child)
|
||||
@ -1553,7 +1559,6 @@ _gtk_container_dequeue_resize_handler (GtkContainer *container)
|
||||
g_return_if_fail (GTK_IS_CONTAINER (container));
|
||||
g_return_if_fail (container->priv->resize_pending);
|
||||
|
||||
container_resize_queue = g_slist_remove (container_resize_queue, container);
|
||||
container->priv->resize_pending = FALSE;
|
||||
}
|
||||
|
||||
@ -1630,12 +1635,10 @@ gtk_container_set_reallocate_redraws (GtkContainer *container,
|
||||
container->priv->reallocate_redraws = needs_redraws ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_container_idle_sizer (gpointer data)
|
||||
static void
|
||||
gtk_container_idle_sizer (GdkFrameClock *clock,
|
||||
GtkContainer *container)
|
||||
{
|
||||
GSList *slist;
|
||||
gint64 current_time;
|
||||
|
||||
/* We validate the style contexts in a single loop before even trying
|
||||
* to handle resizes instead of doing validations inline.
|
||||
* This is mostly necessary for compatibility reasons with old code,
|
||||
@ -1646,16 +1649,13 @@ gtk_container_idle_sizer (gpointer data)
|
||||
* sane values. So the result of an invalid style context will never be
|
||||
* a program crash, but only a wrong layout or rendering.
|
||||
*/
|
||||
current_time = g_get_monotonic_time ();
|
||||
slist = container_restyle_queue;
|
||||
container_restyle_queue = NULL;
|
||||
while (slist)
|
||||
if (container->priv->restyle_pending)
|
||||
{
|
||||
GSList *next = slist->next;
|
||||
GtkContainer *container = slist->data;
|
||||
GtkBitmask *empty;
|
||||
gint64 current_time;
|
||||
|
||||
empty = _gtk_bitmask_new ();
|
||||
current_time = g_get_monotonic_time ();
|
||||
|
||||
container->priv->restyle_pending = FALSE;
|
||||
_gtk_style_context_validate (gtk_widget_get_style_context (GTK_WIDGET (container)),
|
||||
@ -1663,8 +1663,6 @@ gtk_container_idle_sizer (gpointer data)
|
||||
0,
|
||||
empty);
|
||||
|
||||
g_slist_free_1 (slist);
|
||||
slist = next;
|
||||
_gtk_bitmask_free (empty);
|
||||
}
|
||||
|
||||
@ -1674,35 +1672,40 @@ gtk_container_idle_sizer (gpointer data)
|
||||
* than trying to explicitely work around them with some extra flags,
|
||||
* since it doesn't cause any actual harm.
|
||||
*/
|
||||
while (container_resize_queue)
|
||||
if (container->priv->resize_pending)
|
||||
{
|
||||
GtkContainer *container;
|
||||
|
||||
slist = container_resize_queue;
|
||||
container_resize_queue = slist->next;
|
||||
container = slist->data;
|
||||
g_slist_free_1 (slist);
|
||||
|
||||
container->priv->resize_pending = FALSE;
|
||||
gtk_container_check_resize (container);
|
||||
}
|
||||
|
||||
gdk_window_process_all_updates ();
|
||||
|
||||
return container_resize_queue != NULL || container_restyle_queue != NULL;
|
||||
if (!container->priv->restyle_pending && !container->priv->resize_pending)
|
||||
{
|
||||
g_signal_handler_disconnect (clock, container->priv->resize_handler);
|
||||
container->priv->resize_handler = 0;
|
||||
container->priv->resize_clock = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
gdk_frame_clock_request_frame (clock);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_container_start_idle_sizer (GtkContainer *container)
|
||||
{
|
||||
/* already started */
|
||||
if (container_resize_queue != NULL ||
|
||||
container_restyle_queue != NULL)
|
||||
GdkFrameClock *clock;
|
||||
|
||||
if (container->priv->resize_handler != 0)
|
||||
return;
|
||||
|
||||
gdk_threads_add_idle_full (GTK_PRIORITY_RESIZE,
|
||||
gtk_container_idle_sizer,
|
||||
NULL, NULL);
|
||||
clock = gtk_widget_get_frame_clock (GTK_WIDGET (container));
|
||||
if (clock == NULL)
|
||||
return;
|
||||
|
||||
container->priv->resize_clock = clock;
|
||||
container->priv->resize_handler = g_signal_connect (clock, "layout",
|
||||
G_CALLBACK (gtk_container_idle_sizer), container);
|
||||
gdk_frame_clock_request_frame (clock);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1725,7 +1728,6 @@ gtk_container_queue_resize_handler (GtkContainer *container)
|
||||
{
|
||||
container->priv->resize_pending = TRUE;
|
||||
gtk_container_start_idle_sizer (container);
|
||||
container_resize_queue = g_slist_prepend (container_resize_queue, container);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -1780,8 +1782,6 @@ _gtk_container_queue_restyle (GtkContainer *container)
|
||||
return;
|
||||
|
||||
gtk_container_start_idle_sizer (container);
|
||||
|
||||
container_restyle_queue = g_slist_prepend (container_restyle_queue, container);
|
||||
priv->restyle_pending = TRUE;
|
||||
}
|
||||
|
||||
@ -1815,6 +1815,13 @@ _gtk_container_resize_invalidate (GtkContainer *container)
|
||||
_gtk_container_queue_resize_internal (container, TRUE);
|
||||
}
|
||||
|
||||
void
|
||||
_gtk_container_maybe_start_idle_sizer (GtkContainer *container)
|
||||
{
|
||||
if (container->priv->restyle_pending || container->priv->resize_pending)
|
||||
gtk_container_start_idle_sizer (container);
|
||||
}
|
||||
|
||||
void
|
||||
gtk_container_check_resize (GtkContainer *container)
|
||||
{
|
||||
|
@ -39,6 +39,7 @@ GList * _gtk_container_focus_sort (GtkContainer *container,
|
||||
GtkWidget *old_focus);
|
||||
gboolean _gtk_container_get_reallocate_redraws (GtkContainer *container);
|
||||
|
||||
void _gtk_container_maybe_start_idle_sizer (GtkContainer *container);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
@ -4585,6 +4585,9 @@ gtk_widget_realize (GtkWidget *widget)
|
||||
_gtk_widget_enable_device_events (widget);
|
||||
gtk_widget_update_devices_mask (widget, TRUE);
|
||||
|
||||
if (GTK_IS_CONTAINER (widget))
|
||||
_gtk_container_maybe_start_idle_sizer (GTK_CONTAINER (widget));
|
||||
|
||||
gtk_widget_pop_verify_invariants (widget);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user