forked from AuroraMiddleware/gtk
Simplify the widget rendering entry point
Now that GDK has the appropriate API, we can simplify the widget drawing code into a single function. https://bugzilla.gnome.org/show_bug.cgi?id=766675
This commit is contained in:
parent
fc569f1ac6
commit
2c7b21718f
@ -1804,32 +1804,7 @@ gtk_main_do_event (GdkEvent *event)
|
||||
|
||||
case GDK_EXPOSE:
|
||||
if (event->any.window)
|
||||
{
|
||||
gboolean is_double_buffered;
|
||||
|
||||
G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
|
||||
is_double_buffered = gtk_widget_get_double_buffered (event_widget);
|
||||
G_GNUC_END_IGNORE_DEPRECATIONS;
|
||||
|
||||
if (is_double_buffered)
|
||||
{
|
||||
/* We handle exposes only on native windows, relying on the
|
||||
* draw() handler to propagate down to non-native windows.
|
||||
* This is ok now that child windows are always considered
|
||||
* (semi)transparent.
|
||||
*/
|
||||
if (gdk_window_has_native (event->expose.window))
|
||||
{
|
||||
gdk_window_begin_paint_region (event->any.window, event->expose.region);
|
||||
gtk_widget_send_expose (event_widget, event);
|
||||
gdk_window_end_paint (event->any.window);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_widget_send_expose (event_widget, event);
|
||||
}
|
||||
}
|
||||
gtk_widget_render (event_widget, event->any.window, event->expose.region);
|
||||
break;
|
||||
|
||||
case GDK_PROPERTY_NOTIFY:
|
||||
|
114
gtk/gtkwidget.c
114
gtk/gtkwidget.c
@ -6883,21 +6883,22 @@ gtk_widget_real_mnemonic_activate (GtkWidget *widget,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static const cairo_user_data_key_t event_window_key;
|
||||
static const cairo_user_data_key_t mark_for_draw_key;
|
||||
|
||||
static GdkWindow *
|
||||
gtk_cairo_get_event_window (cairo_t *cr)
|
||||
static gboolean
|
||||
gtk_cairo_is_marked_for_draw (cairo_t *cr)
|
||||
{
|
||||
g_return_val_if_fail (cr != NULL, NULL);
|
||||
|
||||
return cairo_get_user_data (cr, &event_window_key);
|
||||
return cairo_get_user_data (cr, &mark_for_draw_key) != NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_cairo_set_event_window (cairo_t *cr,
|
||||
GdkWindow *event_window)
|
||||
gtk_cairo_set_marked_for_draw (cairo_t *cr,
|
||||
gboolean marked)
|
||||
{
|
||||
cairo_set_user_data (cr, &event_window_key, event_window, NULL);
|
||||
if (marked)
|
||||
cairo_set_user_data (cr, &mark_for_draw_key, GINT_TO_POINTER (1), NULL);
|
||||
else
|
||||
cairo_set_user_data (cr, &mark_for_draw_key, NULL, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -6919,25 +6920,28 @@ gtk_cairo_set_event_window (cairo_t *cr,
|
||||
* Returns: %TRUE if @window should be drawn
|
||||
*
|
||||
* Since: 3.0
|
||||
**/
|
||||
*/
|
||||
gboolean
|
||||
gtk_cairo_should_draw_window (cairo_t *cr,
|
||||
gtk_cairo_should_draw_window (cairo_t *cr,
|
||||
GdkWindow *window)
|
||||
{
|
||||
GdkWindow *event_window;
|
||||
GdkWindow *tmp;
|
||||
|
||||
g_return_val_if_fail (cr != NULL, FALSE);
|
||||
g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
|
||||
|
||||
event_window = gtk_cairo_get_event_window (cr);
|
||||
if (gtk_cairo_is_marked_for_draw (cr))
|
||||
return TRUE;
|
||||
|
||||
if (event_window == NULL)
|
||||
tmp = gdk_cairo_get_window (cr);
|
||||
|
||||
if (tmp == NULL)
|
||||
return TRUE;
|
||||
|
||||
while (!gdk_window_has_native (window))
|
||||
window = gdk_window_get_parent (window);
|
||||
|
||||
return event_window == window;
|
||||
return tmp == window;
|
||||
}
|
||||
|
||||
void
|
||||
@ -6964,9 +6968,19 @@ gtk_widget_draw_internal (GtkWidget *widget,
|
||||
gboolean result;
|
||||
gboolean push_group;
|
||||
|
||||
event_window = gtk_cairo_get_event_window (cr);
|
||||
if (event_window)
|
||||
gdk_window_mark_paint_from_clip (event_window, cr);
|
||||
/* If this was a cairo_t passed via gtk_widget_draw() then we don't
|
||||
* require a window
|
||||
*/
|
||||
if (gtk_cairo_is_marked_for_draw (cr))
|
||||
{
|
||||
event_window = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
event_window = gdk_cairo_get_window (cr);
|
||||
if (event_window != NULL)
|
||||
gdk_window_mark_paint_from_clip (event_window, cr);
|
||||
}
|
||||
|
||||
push_group =
|
||||
widget->priv->alpha != 255 &&
|
||||
@ -7077,7 +7091,7 @@ void
|
||||
gtk_widget_draw (GtkWidget *widget,
|
||||
cairo_t *cr)
|
||||
{
|
||||
GdkWindow *tmp_event_window;
|
||||
gboolean was_marked;
|
||||
|
||||
g_return_if_fail (GTK_IS_WIDGET (widget));
|
||||
g_return_if_fail (!widget->priv->alloc_needed);
|
||||
@ -7086,17 +7100,18 @@ gtk_widget_draw (GtkWidget *widget,
|
||||
|
||||
cairo_save (cr);
|
||||
|
||||
/* We have to reset the event here so that draw functions can call
|
||||
* gtk_widget_draw() on random other widgets and get the desired
|
||||
* effect: Drawing all contents, not just the current window.
|
||||
was_marked = gtk_cairo_is_marked_for_draw (cr);
|
||||
|
||||
/* We mark the window so that gtk_cairo_should_draw_window()
|
||||
* will always return TRUE, and all GdkWindows get drawn
|
||||
*/
|
||||
tmp_event_window = gtk_cairo_get_event_window (cr);
|
||||
gtk_cairo_set_event_window (cr, NULL);
|
||||
gtk_cairo_set_marked_for_draw (cr, TRUE);
|
||||
|
||||
gtk_widget_draw_internal (widget, cr, TRUE);
|
||||
|
||||
gtk_cairo_set_marked_for_draw (cr, was_marked);
|
||||
|
||||
cairo_restore (cr);
|
||||
gtk_cairo_set_event_window (cr, tmp_event_window);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@ -7506,32 +7521,12 @@ gint
|
||||
gtk_widget_send_expose (GtkWidget *widget,
|
||||
GdkEvent *event)
|
||||
{
|
||||
cairo_t *cr;
|
||||
int x, y;
|
||||
gboolean do_clip;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_WIDGET (widget), TRUE);
|
||||
g_return_val_if_fail (gtk_widget_get_realized (widget), TRUE);
|
||||
g_return_val_if_fail (event != NULL, TRUE);
|
||||
g_return_val_if_fail (event->type == GDK_EXPOSE, TRUE);
|
||||
|
||||
cr = gdk_cairo_create (event->expose.window);
|
||||
gtk_cairo_set_event_window (cr, event->expose.window);
|
||||
|
||||
gdk_cairo_region (cr, event->expose.region);
|
||||
cairo_clip (cr);
|
||||
|
||||
do_clip = _gtk_widget_get_translation_to_window (widget,
|
||||
event->expose.window,
|
||||
&x, &y);
|
||||
cairo_translate (cr, -x, -y);
|
||||
|
||||
gtk_widget_draw_internal (widget, cr, do_clip);
|
||||
|
||||
/* unset here, so if someone keeps a reference to cr we
|
||||
* don't leak the window. */
|
||||
gtk_cairo_set_event_window (cr, NULL);
|
||||
cairo_destroy (cr);
|
||||
gtk_widget_render (widget, event->any.window, event->expose.region);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
@ -17439,3 +17434,30 @@ gtk_widget_reset_controllers (GtkWidget *widget)
|
||||
gtk_event_controller_reset (controller_data->controller);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gtk_widget_render (GtkWidget *widget,
|
||||
GdkWindow *window,
|
||||
const cairo_region_t *region)
|
||||
{
|
||||
GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
|
||||
gboolean do_clip;
|
||||
cairo_t *cr;
|
||||
int x, y;
|
||||
|
||||
if (priv->double_buffered)
|
||||
{
|
||||
/* We only render double buffered on native windows */
|
||||
if (!gdk_window_has_native (window))
|
||||
return;
|
||||
}
|
||||
|
||||
cr = gdk_window_begin_draw_frame (window, region);
|
||||
|
||||
do_clip = _gtk_widget_get_translation_to_window (widget, window, &x, &y);
|
||||
cairo_translate (cr, -x, -y);
|
||||
|
||||
gtk_widget_draw_internal (widget, cr, do_clip);
|
||||
|
||||
gdk_window_end_draw_frame (window, cr);
|
||||
}
|
||||
|
@ -302,6 +302,11 @@ gboolean gtk_widget_query_tooltip (GtkWidget *widget,
|
||||
gboolean keyboard_mode,
|
||||
GtkTooltip *tooltip);
|
||||
|
||||
void gtk_widget_render (GtkWidget *widget,
|
||||
GdkWindow *window,
|
||||
const cairo_region_t *region);
|
||||
|
||||
|
||||
/* inline getters */
|
||||
|
||||
static inline gboolean
|
||||
|
Loading…
Reference in New Issue
Block a user