gdk/x11: Flush layout changes to the frame clack dispatch

This follows the trail of the Wayland backend in that GdkSurface changes
happen during the layout phase, and that a GDK_CONFIGURE no longer being
used to communicate the size changes of a surface; this now also uses
the layout signal on the GdkSurface.
This commit is contained in:
Jonas Ådahl 2020-12-02 09:45:31 +01:00
parent e0f13ecae7
commit 65ad9d6d96
3 changed files with 175 additions and 34 deletions

View File

@ -901,11 +901,16 @@ gdk_x11_display_translate_event (GdkEventTranslator *translator,
xevent->xconfigure.event == xevent->xconfigure.window)
{
int x, y;
int c_w = (xevent->xconfigure.width + surface_impl->surface_scale - 1) / surface_impl->surface_scale;
int c_h = (xevent->xconfigure.height + surface_impl->surface_scale - 1) / surface_impl->surface_scale;
int configured_width;
int configured_height;
int new_abs_x, new_abs_y;
event = gdk_configure_event_new (surface, c_w, c_h);
configured_width =
(xevent->xconfigure.width + surface_impl->surface_scale - 1) /
surface_impl->surface_scale;
configured_height =
(xevent->xconfigure.height + surface_impl->surface_scale - 1) /
surface_impl->surface_scale;
if (!xevent->xconfigure.send_event &&
!xevent->xconfigure.override_redirect &&
@ -915,6 +920,16 @@ gdk_x11_display_translate_event (GdkEventTranslator *translator,
int ty = 0;
Window child_window = 0;
if (surface_impl->pending_configure_events == 1)
{
surface_impl->pending_configure_events = 0;
gdk_surface_thaw_updates (surface);
}
else if (surface_impl->pending_configure_events > 1)
{
surface_impl->pending_configure_events--;
}
x = y = 0;
gdk_x11_display_error_trap_push (display);
if (XTranslateCoordinates (GDK_SURFACE_XDISPLAY (surface),
@ -955,10 +970,11 @@ gdk_x11_display_translate_event (GdkEventTranslator *translator,
{
surface_impl->unscaled_width = xevent->xconfigure.width;
surface_impl->unscaled_height = xevent->xconfigure.height;
gdk_configure_event_get_size (event, &surface->width, &surface->height);
_gdk_surface_update_size (surface);
_gdk_x11_surface_update_size (surface_impl);
surface_impl->next_layout.configured_width = configured_width;
surface_impl->next_layout.configured_height = configured_height;
surface_impl->next_layout.surface_geometry_dirty = TRUE;
gdk_surface_request_layout (surface);
}
if (surface->resize_count >= 1)

View File

@ -192,6 +192,112 @@ gdk_x11_surface_get_unscaled_size (GdkSurface *surface,
*unscaled_height = impl->unscaled_height;
}
static void
update_shadow_size (GdkSurface *surface,
int shadow_left,
int shadow_right,
int shadow_top,
int shadow_bottom)
{
GdkX11Surface *impl = GDK_X11_SURFACE (surface);
Atom frame_extents;
gulong data[4];
if (impl->shadow_left == shadow_left &&
impl->shadow_right == shadow_right &&
impl->shadow_top == shadow_top &&
impl->shadow_bottom == shadow_bottom)
return;
impl->shadow_left = shadow_left;
impl->shadow_right = shadow_right;
impl->shadow_top = shadow_top;
impl->shadow_bottom = shadow_bottom;
data[0] = shadow_left * impl->surface_scale;
data[1] = shadow_right * impl->surface_scale;
data[2] = shadow_top * impl->surface_scale;
data[3] = shadow_bottom * impl->surface_scale;
frame_extents = gdk_x11_get_xatom_by_name_for_display (gdk_surface_get_display (surface),
"_GTK_FRAME_EXTENTS");
XChangeProperty (GDK_SURFACE_XDISPLAY (surface),
GDK_SURFACE_XID (surface),
frame_extents, XA_CARDINAL,
32, PropModeReplace,
(guchar *) &data, 4);
}
static void
gdk_x11_surface_request_layout (GdkSurface *surface)
{
GdkX11Surface *impl = GDK_X11_SURFACE (surface);
impl->next_layout.surface_geometry_dirty = TRUE;
}
static void
gdk_x11_surface_compute_size (GdkSurface *surface)
{
GdkX11Surface *impl = GDK_X11_SURFACE (surface);
if (GDK_IS_TOPLEVEL (surface))
{
if (impl->next_layout.surface_geometry_dirty)
{
GdkDisplay *display = gdk_surface_get_display (surface);
GdkMonitor *monitor;
GdkToplevelSize size;
int bounds_width, bounds_height;
monitor = gdk_display_get_monitor_at_surface (display, surface);
if (monitor)
{
GdkRectangle workarea;
gdk_x11_monitor_get_workarea (monitor, &workarea);
bounds_width = workarea.width;
bounds_height = workarea.height;
}
else
{
bounds_width = G_MAXINT;
bounds_height = G_MAXINT;
}
gdk_toplevel_size_init (&size, bounds_width, bounds_height);
gdk_toplevel_notify_compute_size (GDK_TOPLEVEL (surface), &size);
if (size.margin.is_valid)
{
update_shadow_size (surface,
size.margin.left,
size.margin.right,
size.margin.top,
size.margin.bottom);
}
surface->width = impl->next_layout.configured_width;
surface->height = impl->next_layout.configured_height;
_gdk_surface_update_size (surface);
_gdk_x11_surface_update_size (impl);
impl->next_layout.surface_geometry_dirty = FALSE;
}
}
else
{
surface->width = impl->next_layout.configured_width;
surface->height = impl->next_layout.configured_height;
_gdk_surface_update_size (surface);
_gdk_x11_surface_update_size (impl);
impl->next_layout.surface_geometry_dirty = FALSE;
}
}
gboolean
gdk_x11_surface_supports_edge_constraints (GdkSurface *surface)
{
@ -1424,6 +1530,9 @@ x11_surface_move (GdkSurface *surface,
surface->x = x;
surface->y = y;
}
impl->next_layout.surface_geometry_dirty = TRUE;
gdk_surface_request_layout (surface);
}
}
@ -1450,10 +1559,10 @@ x11_surface_resize (GdkSurface *surface,
{
impl->unscaled_width = width * impl->surface_scale;
impl->unscaled_height = height * impl->surface_scale;
surface->width = width;
surface->height = height;
_gdk_surface_update_size (surface);
_gdk_x11_surface_update_size (GDK_X11_SURFACE (surface));
impl->next_layout.configured_width = width;
impl->next_layout.configured_height = height;
impl->next_layout.surface_geometry_dirty = TRUE;
gdk_surface_request_layout (surface);
}
else
{
@ -1491,10 +1600,10 @@ x11_surface_move_resize (GdkSurface *surface,
impl->unscaled_width = width * impl->surface_scale;
impl->unscaled_height = height * impl->surface_scale;
surface->width = width;
surface->height = height;
_gdk_x11_surface_update_size (GDK_X11_SURFACE (surface));
impl->next_layout.configured_width = width;
impl->next_layout.configured_height = height;
impl->next_layout.surface_geometry_dirty = TRUE;
gdk_surface_request_layout (surface);
if (surface->parent)
{
@ -2822,22 +2931,6 @@ gdk_x11_surface_set_shadow_width (GdkSurface *surface,
int top,
int bottom)
{
GdkX11Surface *impl = GDK_X11_SURFACE (surface);
Atom frame_extents;
gulong data[4] = {
left * impl->surface_scale,
right * impl->surface_scale,
top * impl->surface_scale,
bottom * impl->surface_scale
};
frame_extents = gdk_x11_get_xatom_by_name_for_display (gdk_surface_get_display (surface),
"_GTK_FRAME_EXTENTS");
XChangeProperty (GDK_SURFACE_XDISPLAY (surface),
GDK_SURFACE_XID (surface),
frame_extents, XA_CARDINAL,
32, PropModeReplace,
(guchar *) &data, 4);
}
/**
@ -4568,6 +4661,8 @@ gdk_x11_surface_class_init (GdkX11SurfaceClass *klass)
impl_class->set_shadow_width = gdk_x11_surface_set_shadow_width;
impl_class->create_gl_context = gdk_x11_surface_create_gl_context;
impl_class->get_unscaled_size = gdk_x11_surface_get_unscaled_size;
impl_class->request_layout = gdk_x11_surface_request_layout;
impl_class->compute_size = gdk_x11_surface_compute_size;
}
#define LAST_PROP 1
@ -4854,6 +4949,7 @@ gdk_x11_toplevel_present (GdkToplevel *toplevel,
GdkToplevelLayout *layout)
{
GdkSurface *surface = GDK_SURFACE (toplevel);
GdkX11Surface *impl = GDK_X11_SURFACE (surface);
GdkDisplay *display = gdk_surface_get_display (surface);
GdkMonitor *monitor;
GdkToplevelSize size;
@ -4863,6 +4959,11 @@ gdk_x11_toplevel_present (GdkToplevel *toplevel,
GdkSurfaceHints mask;
gboolean was_mapped;
if (surface->destroyed)
return;
was_mapped = GDK_SURFACE_IS_MAPPED (surface);
gdk_x11_surface_unminimize (surface);
monitor = gdk_display_get_monitor_at_surface (display, surface);
@ -4903,6 +5004,19 @@ gdk_x11_toplevel_present (GdkToplevel *toplevel,
gdk_surface_constrain_size (&geometry, mask, width, height, &width, &height);
gdk_x11_surface_toplevel_resize (surface, width, height);
if (size.margin.is_valid)
{
update_shadow_size (surface,
size.margin.left,
size.margin.right,
size.margin.top,
size.margin.bottom);
}
impl->pending_configure_events++;
if (impl->pending_configure_events == 1)
gdk_surface_freeze_updates (surface);
if (gdk_toplevel_layout_get_maximized (layout))
gdk_x11_surface_maximize (surface);
else
@ -4921,10 +5035,8 @@ gdk_x11_toplevel_present (GdkToplevel *toplevel,
else
gdk_x11_surface_unfullscreen (surface);
if (surface->destroyed)
return;
was_mapped = GDK_SURFACE_IS_MAPPED (surface);
impl->next_layout.surface_geometry_dirty = TRUE;
gdk_surface_request_layout (surface);
if (!was_mapped)
gdk_synthesize_surface_state (surface, GDK_TOPLEVEL_STATE_WITHDRAWN, 0);

View File

@ -59,6 +59,11 @@ struct _GdkX11Surface
int surface_scale;
int shadow_left;
int shadow_right;
int shadow_top;
int shadow_bottom;
/* Width and height not divided by surface_scale - this matters in the
* corner-case where the window manager assigns us a size that isn't
* a multiple of surface_scale - for example for a maximized window
@ -67,6 +72,14 @@ struct _GdkX11Surface
int unscaled_width;
int unscaled_height;
int pending_configure_events;
struct {
int configured_width;
int configured_height;
gboolean surface_geometry_dirty;
} next_layout;
cairo_surface_t *cairo_surface;
int abs_x;