Compare commits
3 Commits
add-nightl
...
wip/baeder
Author | SHA1 | Date | |
---|---|---|---|
|
65317ce335 | ||
|
75bfa9b5c5 | ||
|
9ed1e801fe |
@@ -414,7 +414,6 @@ gdk_frame_clock_paint_idle (void *data)
|
||||
case GDK_FRAME_CLOCK_PHASE_LAYOUT:
|
||||
if (priv->freeze_count == 0)
|
||||
{
|
||||
int iter;
|
||||
#ifdef G_ENABLE_DEBUG
|
||||
if (GDK_DEBUG_CHECK (FRAMES))
|
||||
{
|
||||
@@ -430,15 +429,8 @@ gdk_frame_clock_paint_idle (void *data)
|
||||
* happen in some situation like races between user window
|
||||
* resizes and natural size changes.
|
||||
*/
|
||||
iter = 0;
|
||||
while ((priv->requested & GDK_FRAME_CLOCK_PHASE_LAYOUT) &&
|
||||
priv->freeze_count == 0 && iter++ < 4)
|
||||
{
|
||||
priv->requested &= ~GDK_FRAME_CLOCK_PHASE_LAYOUT;
|
||||
_gdk_frame_clock_emit_layout (clock);
|
||||
}
|
||||
if (iter == 5)
|
||||
g_warning ("gdk-frame-clock: layout continuously requested, giving up after 4 tries");
|
||||
priv->requested &= ~GDK_FRAME_CLOCK_PHASE_LAYOUT;
|
||||
_gdk_frame_clock_emit_layout (clock);
|
||||
}
|
||||
/* fallthrough */
|
||||
case GDK_FRAME_CLOCK_PHASE_PAINT:
|
||||
|
@@ -143,12 +143,15 @@
|
||||
*/
|
||||
|
||||
|
||||
#define MAX_RESIZE_ITERATIONS 2
|
||||
|
||||
struct _GtkContainerPrivate
|
||||
{
|
||||
guint resize_handler;
|
||||
|
||||
guint has_focus_chain : 1;
|
||||
guint restyle_pending : 1;
|
||||
guint last_resize_iteration : 1;
|
||||
};
|
||||
|
||||
enum {
|
||||
@@ -1538,7 +1541,18 @@ gtk_container_needs_idle_sizer (GtkContainer *container)
|
||||
if (priv->restyle_pending)
|
||||
return TRUE;
|
||||
|
||||
return gtk_widget_needs_allocate (GTK_WIDGET (container));
|
||||
if (GTK_IS_WINDOW (container))
|
||||
return gtk_window_get_resize_widgets (GTK_WINDOW (container))->len > 0;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gtk_container_in_last_resize_iteration (GtkContainer *container)
|
||||
{
|
||||
GtkContainerPrivate *priv = gtk_container_get_instance_private (container);
|
||||
|
||||
return priv->last_resize_iteration;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1547,42 +1561,71 @@ gtk_container_idle_sizer (GdkFrameClock *clock,
|
||||
{
|
||||
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 style_updated 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)
|
||||
if (GTK_IS_WINDOW (container))
|
||||
{
|
||||
priv->restyle_pending = FALSE;
|
||||
gtk_css_node_validate (gtk_widget_get_css_node (GTK_WIDGET (container)));
|
||||
GPtrArray *resize_widgets = gtk_window_get_resize_widgets (GTK_WINDOW (container));
|
||||
static int k;
|
||||
guint resize_iteration;
|
||||
|
||||
#if 0
|
||||
g_message ("=== %d", k++);
|
||||
#endif
|
||||
|
||||
for (resize_iteration = 0; resize_iteration < MAX_RESIZE_ITERATIONS; resize_iteration ++)
|
||||
{
|
||||
const gboolean last_iteration = (resize_iteration == MAX_RESIZE_ITERATIONS - 1);
|
||||
guint i, p;
|
||||
|
||||
priv->last_resize_iteration = last_iteration;
|
||||
|
||||
/* 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 style_updated 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)));
|
||||
}
|
||||
|
||||
for (i = 0, p = resize_widgets->len; i < p; i ++)
|
||||
{
|
||||
GtkWidget *w = g_ptr_array_index (resize_widgets, i);
|
||||
#if 0
|
||||
g_message (" (%d): %s %s %p", resize_iteration, G_OBJECT_TYPE_NAME (w),
|
||||
gtk_css_node_get_name (gtk_widget_get_css_node (w)), w);
|
||||
#endif
|
||||
gtk_widget_invalidate_size (w);
|
||||
}
|
||||
|
||||
g_ptr_array_remove_range (resize_widgets, 0, p);
|
||||
|
||||
/* 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)))
|
||||
{
|
||||
gtk_container_check_resize (container);
|
||||
}
|
||||
}
|
||||
|
||||
/* Ignore all resize widgets after the last iteration */
|
||||
g_ptr_array_remove_range (resize_widgets, 0, resize_widgets->len);
|
||||
}
|
||||
|
||||
/* 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)))
|
||||
{
|
||||
gtk_container_check_resize (container);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
/* Unconditionally stop the idle sizer, since we are at worst already
|
||||
* MAX_RESIZE_ITERATIONS into resize territory and we don't want to
|
||||
* go any further. */
|
||||
gtk_container_stop_idle_sizer (container);
|
||||
priv->last_resize_iteration = FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
|
@@ -31,6 +31,7 @@ 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);
|
||||
gboolean gtk_container_in_last_resize_iteration (GtkContainer *container);
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
@@ -3870,10 +3870,13 @@ gtk_widget_queue_allocate (GtkWidget *widget)
|
||||
{
|
||||
g_return_if_fail (GTK_IS_WIDGET (widget));
|
||||
|
||||
#if 0
|
||||
if (_gtk_widget_get_realized (widget))
|
||||
gtk_widget_queue_draw (widget);
|
||||
|
||||
gtk_widget_set_alloc_needed (widget);
|
||||
#endif
|
||||
gtk_widget_queue_resize (widget);
|
||||
}
|
||||
|
||||
static inline gboolean
|
||||
@@ -3922,6 +3925,15 @@ gtk_widget_queue_resize_internal (GtkWidget *widget)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gtk_widget_invalidate_size (GtkWidget *widget)
|
||||
{
|
||||
if (_gtk_widget_get_realized (widget))
|
||||
gtk_widget_queue_draw (widget);
|
||||
|
||||
gtk_widget_queue_resize_internal (widget);
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_widget_queue_resize:
|
||||
* @widget: a #GtkWidget
|
||||
@@ -3940,12 +3952,42 @@ gtk_widget_queue_resize_internal (GtkWidget *widget)
|
||||
void
|
||||
gtk_widget_queue_resize (GtkWidget *widget)
|
||||
{
|
||||
GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
|
||||
GtkWidget *toplevel;
|
||||
|
||||
g_return_if_fail (GTK_IS_WIDGET (widget));
|
||||
|
||||
#if 0
|
||||
if (_gtk_widget_get_realized (widget))
|
||||
gtk_widget_queue_draw (widget);
|
||||
|
||||
gtk_widget_queue_resize_internal (widget);
|
||||
#endif
|
||||
|
||||
toplevel = _gtk_widget_get_toplevel (widget);
|
||||
if (GTK_IS_WINDOW (toplevel))
|
||||
{
|
||||
if (gtk_container_in_last_resize_iteration (GTK_CONTAINER (toplevel)))
|
||||
g_warning ("Queueing a resize on %s %s %p inside the last resize iteration. "
|
||||
"This should not happen. The resize request will be ignored.",
|
||||
G_OBJECT_TYPE_NAME (widget),
|
||||
gtk_css_node_get_name (gtk_widget_get_css_node (widget)), widget);
|
||||
else
|
||||
gtk_window_add_resize_widget (GTK_WINDOW (toplevel), widget);
|
||||
}
|
||||
|
||||
/* Clear the size request cache for all the parent widgets, since a change
|
||||
* in size of @widget might cause a change in size of all the parents. */
|
||||
while (widget)
|
||||
{
|
||||
priv = gtk_widget_get_instance_private (widget);
|
||||
|
||||
gtk_widget_invalidate_paintable_size (widget);
|
||||
_gtk_size_request_cache_clear (&priv->requests);
|
||||
|
||||
widget = priv->parent;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3959,8 +4001,10 @@ void
|
||||
gtk_widget_queue_resize_no_redraw (GtkWidget *widget)
|
||||
{
|
||||
g_return_if_fail (GTK_IS_WIDGET (widget));
|
||||
|
||||
#if 0
|
||||
gtk_widget_queue_resize_internal (widget);
|
||||
#endif
|
||||
gtk_widget_queue_resize (widget);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -336,10 +336,7 @@ void gtk_widget_cancel_event_sequence (GtkWidget
|
||||
GtkGesture *gesture,
|
||||
GdkEventSequence *sequence,
|
||||
GtkEventSequenceState state);
|
||||
|
||||
|
||||
|
||||
|
||||
void gtk_widget_invalidate_size (GtkWidget *widget);
|
||||
|
||||
/* inline getters */
|
||||
|
||||
|
@@ -289,6 +289,8 @@ typedef struct
|
||||
GskRenderer *renderer;
|
||||
|
||||
GList *foci;
|
||||
|
||||
GPtrArray *resize_widgets;
|
||||
} GtkWindowPrivate;
|
||||
|
||||
#ifdef GDK_WINDOWING_X11
|
||||
@@ -1920,6 +1922,8 @@ gtk_window_init (GtkWindow *window)
|
||||
toplevel_list = g_slist_prepend (toplevel_list, window);
|
||||
gtk_window_update_debugging ();
|
||||
|
||||
priv->resize_widgets = g_ptr_array_new ();
|
||||
|
||||
#ifdef GDK_WINDOWING_X11
|
||||
g_signal_connect (gtk_settings_get_for_display (priv->display),
|
||||
"notify::gtk-application-prefer-dark-theme",
|
||||
@@ -11303,3 +11307,50 @@ gtk_window_maybe_update_cursor (GtkWindow *window,
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gtk_window_add_resize_widget (GtkWindow *window,
|
||||
GtkWidget *widget)
|
||||
{
|
||||
GtkWindowPrivate *priv = gtk_window_get_instance_private (window);
|
||||
|
||||
g_assert (gtk_widget_get_toplevel (widget) == (GtkWidget *)window);
|
||||
|
||||
/* XXX LEAK */
|
||||
g_ptr_array_add (priv->resize_widgets, g_object_ref (widget));
|
||||
|
||||
gtk_container_start_idle_sizer (GTK_CONTAINER (window));
|
||||
}
|
||||
|
||||
void
|
||||
gtk_window_remove_resize_widget (GtkWindow *window,
|
||||
GtkWidget *widget)
|
||||
{
|
||||
GtkWindowPrivate *priv = gtk_window_get_instance_private (window);
|
||||
guint i, p;
|
||||
|
||||
g_assert (gtk_widget_get_toplevel (widget) == (GtkWidget *)window);
|
||||
|
||||
for (i = 0, p = priv->resize_widgets->len; i < p; i ++)
|
||||
{
|
||||
GtkWidget *w = g_ptr_array_index (priv->resize_widgets, i);
|
||||
|
||||
if (w == widget)
|
||||
{
|
||||
g_ptr_array_remove_index_fast (priv->resize_widgets, i);
|
||||
i --;
|
||||
p --;
|
||||
}
|
||||
}
|
||||
|
||||
if (p == 0)
|
||||
gtk_container_stop_idle_sizer (GTK_CONTAINER (window));
|
||||
}
|
||||
|
||||
GPtrArray *
|
||||
gtk_window_get_resize_widgets (GtkWindow *window)
|
||||
{
|
||||
GtkWindowPrivate *priv = gtk_window_get_instance_private (window);
|
||||
|
||||
return priv->resize_widgets;
|
||||
}
|
||||
|
@@ -167,6 +167,12 @@ void gtk_window_maybe_update_cursor (GtkWindow *window,
|
||||
GtkWidget *widget,
|
||||
GdkDevice *device);
|
||||
|
||||
void gtk_window_add_resize_widget (GtkWindow *window,
|
||||
GtkWidget *widget);
|
||||
void gtk_window_remove_resize_widget (GtkWindow *window,
|
||||
GtkWidget *widget);
|
||||
GPtrArray * gtk_window_get_resize_widgets (GtkWindow *window);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GTK_WINDOW_PRIVATE_H__ */
|
||||
|
Reference in New Issue
Block a user