Move the idle sizer to GtkWindow

This was only living in gtkcontainer.c for historic
reasons. Move it closer to where it belongs, and
rename it from 'idle' to 'layout', since it is
really about the layout phase of the frame clock,
nowadays.
This commit is contained in:
Matthias Clasen 2020-04-19 11:43:57 -04:00
parent 841c4a8cfe
commit b55195fa2e
23 changed files with 118 additions and 192 deletions

View File

@ -23,7 +23,6 @@ private_headers = [
'gtkcolorscaleprivate.h',
'gtkcolorswatchprivate.h',
'gtkcomboboxprivate.h',
'gtkcontainerprivate.h',
'gtkconstraintexpressionprivate.h',
'gtkconstraintguideprivate.h',
'gtkconstraintlayoutprivate.h',

View File

@ -27,7 +27,6 @@
#include "gtkbox.h"
#include "gtkrevealer.h"
#include "gtkwidgetprivate.h"
#include "gtkcontainerprivate.h"
#include "gtkprivate.h"
#include "gtkcenterbox.h"
#include "gtkbinlayout.h"

View File

@ -57,7 +57,6 @@
#include "gtkactionhelperprivate.h"
#include "gtkcheckbutton.h"
#include "gtkcontainerprivate.h"
#include "gtkgestureclick.h"
#include "gtkeventcontrollerkey.h"
#include "gtkimage.h"

View File

@ -33,7 +33,6 @@
#include "gtkprivate.h"
#include "gtkwidgetprivate.h"
#include "gtkcssnodeprivate.h"
#include "gtkcontainerprivate.h"
#include "gtkstylecontextprivate.h"
#include "gtkcssnumbervalueprivate.h"
#include "gtkradiobutton.h"

View File

@ -24,8 +24,6 @@
#include "config.h"
#include "gtkcontainerprivate.h"
#include "gtkadjustment.h"
#include "gtkbuildable.h"
#include "gtkbuilderprivate.h"
@ -86,14 +84,6 @@
* See more about implementing custom widgets at https://wiki.gnome.org/HowDoI/CustomWidgets
*/
struct _GtkContainerPrivate
{
guint resize_handler;
guint restyle_pending : 1;
};
enum {
ADD,
REMOVE,
@ -120,7 +110,6 @@ static GtkBuildableIface *parent_buildable_iface;
static guint container_signals[LAST_SIGNAL] = { 0 };
G_DEFINE_ABSTRACT_TYPE_WITH_CODE (GtkContainer, gtk_container, GTK_TYPE_WIDGET,
G_ADD_PRIVATE (GtkContainer)
G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
gtk_container_buildable_init))
@ -236,10 +225,6 @@ static void
gtk_container_destroy (GtkWidget *widget)
{
GtkContainer *container = GTK_CONTAINER (widget);
GtkContainerPrivate *priv = gtk_container_get_instance_private (container);
if (priv->restyle_pending)
priv->restyle_pending = FALSE;
gtk_container_foreach (container, (GtkCallback) gtk_widget_destroy, NULL);
@ -324,113 +309,6 @@ gtk_container_remove (GtkContainer *container,
g_object_unref (container);
}
static gboolean
gtk_container_needs_idle_sizer (GtkContainer *container)
{
GtkContainerPrivate *priv = gtk_container_get_instance_private (container);
if (priv->restyle_pending)
return TRUE;
return gtk_widget_needs_allocate (GTK_WIDGET (container));
}
static void
gtk_container_idle_sizer (GdkFrameClock *clock,
GtkContainer *container)
{
GtkContainerPrivate *priv = gtk_container_get_instance_private (container);
/* 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,
* because both css_changed and size_allocate functions often change
* styles and so could cause infinite loops in this function.
*
* It's important to note that even an invalid style context returns
* sane values. So the result of an invalid style context will never be
* a program crash, but only a wrong layout or rendering.
*/
if (priv->restyle_pending)
{
priv->restyle_pending = FALSE;
gtk_css_node_validate (gtk_widget_get_css_node (GTK_WIDGET (container)));
}
/* we may be invoked with a container_resize_queue of NULL, because
* queue_resize could have been adding an extra idle function while
* the queue still got processed. we better just ignore such case
* than trying to explicitly work around them with some extra flags,
* since it doesn't cause any actual harm.
*/
if (gtk_widget_needs_allocate (GTK_WIDGET (container)))
{
if (GTK_IS_ROOT (container))
gtk_native_check_resize (GTK_NATIVE (container));
else
g_warning ("gtk_container_idle_sizer() called on a non-native non-window");
}
if (!gtk_container_needs_idle_sizer (container))
{
gtk_container_stop_idle_sizer (container);
}
else
{
gdk_frame_clock_request_phase (clock,
GDK_FRAME_CLOCK_PHASE_LAYOUT);
}
}
void
gtk_container_start_idle_sizer (GtkContainer *container)
{
GtkContainerPrivate *priv = gtk_container_get_instance_private (container);
GdkFrameClock *clock;
if (priv->resize_handler != 0)
return;
if (!gtk_container_needs_idle_sizer (container))
return;
clock = gtk_widget_get_frame_clock (GTK_WIDGET (container));
if (clock == NULL)
return;
priv->resize_handler = g_signal_connect (clock, "layout",
G_CALLBACK (gtk_container_idle_sizer), container);
gdk_frame_clock_request_phase (clock,
GDK_FRAME_CLOCK_PHASE_LAYOUT);
}
void
gtk_container_stop_idle_sizer (GtkContainer *container)
{
GtkContainerPrivate *priv = gtk_container_get_instance_private (container);
if (priv->resize_handler == 0)
return;
g_signal_handler_disconnect (gtk_widget_get_frame_clock (GTK_WIDGET (container)),
priv->resize_handler);
priv->resize_handler = 0;
}
void
_gtk_container_queue_restyle (GtkContainer *container)
{
GtkContainerPrivate *priv = gtk_container_get_instance_private (container);
g_return_if_fail (GTK_CONTAINER (container));
if (priv->restyle_pending)
return;
priv->restyle_pending = TRUE;
gtk_container_start_idle_sizer (container);
}
static GtkSizeRequestMode
gtk_container_get_request_mode (GtkWidget *widget)
{

View File

@ -1,38 +0,0 @@
/* GTK - The GIMP Toolkit
*
* Copyright (C) 2011 Javier Jardón
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __GTK_CONTAINER_PRIVATE_H__
#define __GTK_CONTAINER_PRIVATE_H__
#include "gtkcontainer.h"
#include <gsk/gsk.h>
G_BEGIN_DECLS
void _gtk_container_queue_restyle (GtkContainer *container);
void gtk_container_stop_idle_sizer (GtkContainer *container);
void gtk_container_start_idle_sizer (GtkContainer *container);
void gtk_container_set_focus_child (GtkContainer *container,
GtkWidget *child);
G_END_DECLS
#endif /* __GTK_CONTAINER_PRIVATE_H__ */

View File

@ -19,12 +19,12 @@
#include "gtkcsswidgetnodeprivate.h"
#include "gtkcontainerprivate.h"
#include "gtkcssanimatedstyleprivate.h"
#include "gtkprivate.h"
#include "gtksettingsprivate.h"
#include "gtkstylecontextprivate.h"
#include "gtkwidgetprivate.h"
#include "gtkwindowprivate.h"
G_DEFINE_TYPE (GtkCssWidgetNode, gtk_css_widget_node, GTK_TYPE_CSS_NODE)
@ -46,7 +46,7 @@ gtk_css_widget_node_queue_callback (GtkWidget *widget,
GtkCssNode *node = user_data;
gtk_css_node_invalidate_frame_clock (node, TRUE);
_gtk_container_queue_restyle (GTK_CONTAINER (widget));
gtk_window_queue_restyle (GTK_WINDOW (widget));
return G_SOURCE_CONTINUE;
}
@ -56,9 +56,7 @@ gtk_css_widget_node_queue_validate (GtkCssNode *node)
{
GtkCssWidgetNode *widget_node = GTK_CSS_WIDGET_NODE (node);
if (widget_node->widget &&
GTK_IS_ROOT (widget_node->widget) &&
GTK_IS_CONTAINER (widget_node->widget))
if (widget_node->widget && GTK_IS_ROOT (widget_node->widget))
widget_node->validate_cb_id = gtk_widget_add_tick_callback (widget_node->widget,
gtk_css_widget_node_queue_callback,
node,

View File

@ -35,7 +35,6 @@
#include "gtklabel.h"
#include "gtkmarshalers.h"
#include "gtkbox.h"
#include "gtkcontainerprivate.h"
#include "gtkmain.h"
#include "gtkintl.h"
#include "gtkprivate.h"

View File

@ -114,7 +114,6 @@
#include "gtkbox.h"
#include "gtkbuildable.h"
#include "gtkcontainerprivate.h"
#include "gtkdropcontrollermotion.h"
#include "gtkbuiltiniconprivate.h"
#include "gtkgestureclick.h"

View File

@ -71,7 +71,6 @@
#include "gtkfixed.h"
#include "gtkcontainerprivate.h"
#include "gtkfixedlayout.h"
#include "gtkintl.h"
#include "gtkprivate.h"

View File

@ -79,7 +79,6 @@
#include "gtkflowboxprivate.h"
#include "gtkadjustment.h"
#include "gtkcontainerprivate.h"
#include "gtkcsscolorvalueprivate.h"
#include "gtkcssnodeprivate.h"
#include "gtkgesturedrag.h"

View File

@ -32,7 +32,6 @@
#include "gtkbuildable.h"
#include "gtkcssnodeprivate.h"
#include "gtkwidgetprivate.h"
#include "gtkcontainerprivate.h"
#include "gtkstylecontextprivate.h"
#include "gtkcssstylepropertyprivate.h"
#include "gtklabel.h"

View File

@ -22,7 +22,6 @@
#include "gtkgrid.h"
#include "gtkcontainerprivate.h"
#include "gtkcsspositionvalueprivate.h"
#include "gtkgridlayout.h"
#include "gtkorientableprivate.h"

View File

@ -44,7 +44,6 @@
#include "gtkgridlayout.h"
#include "gtkcontainerprivate.h"
#include "gtkcsspositionvalueprivate.h"
#include "gtkdebug.h"
#include "gtkintl.h"

View File

@ -25,7 +25,6 @@
#include "gtkbutton.h"
#include "gtkbuildable.h"
#include "gtkcenterlayout.h"
#include "gtkcontainerprivate.h"
#include "gtkcssnodeprivate.h"
#include "gtkimage.h"
#include "gtkintl.h"

View File

@ -22,7 +22,6 @@
#include "gtkactionhelperprivate.h"
#include "gtkadjustmentprivate.h"
#include "gtkbuildable.h"
#include "gtkcontainerprivate.h"
#include "gtkcssnodeprivate.h"
#include "gtkgestureclick.h"
#include "gtkintl.h"

View File

@ -37,7 +37,6 @@
#include "gtkcssnodeprivate.h"
#include "gtkcsstypesprivate.h"
#include "gtkstylecontextprivate.h"
#include "gtkcontainerprivate.h"
#include "gtkbuiltiniconprivate.h"
#include "gtksizegroup.h"
#include "gtkaccellabelprivate.h"

View File

@ -26,7 +26,6 @@
#include "gtkpaned.h"
#include "gtkcontainerprivate.h"
#include "gtkcssnodeprivate.h"
#include "gtkcssstylepropertyprivate.h"
#include "gtkeventcontrollermotion.h"

View File

@ -27,7 +27,6 @@
#include "gtkprivate.h"
#include "gtksizegroup-private.h"
#include "gtkwidgetprivate.h"
#include "gtkcontainerprivate.h"
/**

View File

@ -25,7 +25,6 @@
#include "gtkstack.h"
#include "gtkprivate.h"
#include "gtkintl.h"
#include "gtkcontainerprivate.h"
#include "gtkprogresstrackerprivate.h"
#include "gtksettingsprivate.h"
#include "gtksnapshot.h"

View File

@ -31,7 +31,6 @@
#include "gtkapplicationprivate.h"
#include "gtkbuildable.h"
#include "gtkbuilderprivate.h"
#include "gtkcontainerprivate.h"
#include "gtkcssboxesprivate.h"
#include "gtkcssfiltervalueprivate.h"
#include "gtkcsstransformvalueprivate.h"
@ -3104,9 +3103,6 @@ gtk_widget_connect_frame_clock (GtkWidget *widget)
GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
GdkFrameClock *frame_clock;
if (GTK_IS_CONTAINER (widget) && GTK_IS_ROOT (widget))
gtk_container_start_idle_sizer (GTK_CONTAINER (widget));
frame_clock = gtk_widget_get_frame_clock (widget);
if (priv->tick_callbacks != NULL && !priv->clock_tick_id)
@ -3125,9 +3121,6 @@ gtk_widget_disconnect_frame_clock (GtkWidget *widget)
{
GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
if (GTK_IS_CONTAINER (widget) && GTK_IS_ROOT (widget))
gtk_container_stop_idle_sizer (GTK_CONTAINER (widget));
gtk_css_node_invalidate_frame_clock (priv->cssnode, FALSE);
if (priv->clock_tick_id)
@ -10444,9 +10437,9 @@ gtk_widget_set_alloc_needed (GtkWidget *widget)
if (!priv->visible)
break;
if (GTK_IS_ROOT (widget))
if (GTK_IS_WINDOW (widget))
{
gtk_container_start_idle_sizer (GTK_CONTAINER (widget));
gtk_window_start_layout (GTK_WINDOW (widget));
break;
}

View File

@ -33,7 +33,6 @@
#include "gtkbuilderprivate.h"
#include "gtkbutton.h"
#include "gtkcheckbutton.h"
#include "gtkcontainerprivate.h"
#include "gtkcsscornervalueprivate.h"
#include "gtkcssiconthemevalueprivate.h"
#include "gtkcsscolorvalueprivate.h"
@ -239,8 +238,12 @@ typedef struct
guint hide_on_close : 1;
guint in_emit_close_request : 1;
guint restyle_pending : 1;
GdkSurfaceTypeHint type_hint;
guint resize_handler;
GtkGesture *click_gesture;
GtkGesture *drag_gesture;
GtkGesture *bubble_drag_gesture;
@ -3997,6 +4000,9 @@ gtk_window_destroy (GtkWidget *widget)
if (priv->group)
gtk_window_group_remove_window (priv->group, window);
if (priv->restyle_pending)
priv->restyle_pending = FALSE;
GTK_WIDGET_CLASS (gtk_window_parent_class)->destroy (widget);
}
@ -4798,6 +4804,8 @@ gtk_window_realize (GtkWidget *widget)
GTK_WIDGET_CLASS (gtk_window_parent_class)->realize (widget);
gtk_window_start_layout (window);
if (priv->renderer == NULL)
priv->renderer = gsk_renderer_new_for_surface (surface);
@ -4913,6 +4921,8 @@ gtk_window_unrealize (GtkWidget *widget)
g_signal_handlers_disconnect_by_func (surface, surface_render, widget);
g_signal_handlers_disconnect_by_func (surface, surface_event, widget);
gtk_window_stop_layout (window);
GTK_WIDGET_CLASS (gtk_window_parent_class)->unrealize (widget);
gdk_surface_set_widget (surface, NULL);
@ -8008,3 +8018,100 @@ gtk_window_maybe_update_cursor (GtkWindow *window,
break;
}
}
static gboolean
gtk_window_needs_layout (GtkWindow *window)
{
GtkWindowPrivate *priv = gtk_window_get_instance_private (window);
if (priv->restyle_pending)
return TRUE;
return gtk_widget_needs_allocate (GTK_WIDGET (window));
}
static void
gtk_window_layout_cb (GdkFrameClock *clock,
GtkWindow *window)
{
GtkWindowPrivate *priv = gtk_window_get_instance_private (window);
GtkWidget *widget = GTK_WIDGET (window);
/* 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,
* because both css_changed and size_allocate functions often change
* styles and so could cause infinite loops in this function.
*
* It's important to note that even an invalid style context returns
* sane values. So the result of an invalid style context will never be
* a program crash, but only a wrong layout or rendering.
*/
if (priv->restyle_pending)
{
priv->restyle_pending = FALSE;
gtk_css_node_validate (gtk_widget_get_css_node (widget));
}
/* we may be invoked with a container_resize_queue of NULL, because
* queue_resize could have been adding an extra idle function while
* the queue still got processed. we better just ignore such case
* than trying to explicitly work around them with some extra flags,
* since it doesn't cause any actual harm.
*/
if (gtk_widget_needs_allocate (widget))
gtk_native_check_resize (GTK_NATIVE (window));
if (!gtk_window_needs_layout (window))
gtk_window_stop_layout (window);
else
gdk_frame_clock_request_phase (clock, GDK_FRAME_CLOCK_PHASE_LAYOUT);
}
void
gtk_window_start_layout (GtkWindow *window)
{
GtkWindowPrivate *priv = gtk_window_get_instance_private (window);
GdkFrameClock *clock;
if (priv->resize_handler != 0)
return;
if (!gtk_window_needs_layout (window))
return;
clock = gtk_widget_get_frame_clock (GTK_WIDGET (window));
if (clock == NULL)
return;
priv->resize_handler = g_signal_connect (clock, "layout",
G_CALLBACK (gtk_window_layout_cb), window);
gdk_frame_clock_request_phase (clock, GDK_FRAME_CLOCK_PHASE_LAYOUT);
}
void
gtk_window_stop_layout (GtkWindow *window)
{
GtkWindowPrivate *priv = gtk_window_get_instance_private (window);
GdkFrameClock *clock;
if (priv->resize_handler == 0)
return;
clock = gtk_widget_get_frame_clock (GTK_WIDGET (window));
g_signal_handler_disconnect (clock, priv->resize_handler);
priv->resize_handler = 0;
}
void
gtk_window_queue_restyle (GtkWindow *window)
{
GtkWindowPrivate *priv = gtk_window_get_instance_private (window);
if (priv->restyle_pending)
return;
priv->restyle_pending = TRUE;
gtk_window_start_layout (window);
}

View File

@ -141,6 +141,11 @@ GtkWidget * gtk_window_pick_popover (GtkWindow *window,
void gtk_window_set_extra_input_region (GtkWindow *window,
cairo_region_t *region);
void gtk_window_start_layout (GtkWindow *window);
void gtk_window_stop_layout (GtkWindow *window);
void gtk_window_queue_restyle (GtkWindow *window);
G_END_DECLS
#endif /* __GTK_WINDOW_PRIVATE_H__ */