From e7b89cec3bb1e68f013c35ec9581f35036ad94d4 Mon Sep 17 00:00:00 2001 From: hujianwei Date: Tue, 15 Nov 2022 12:17:26 +0000 Subject: [PATCH] Fix crashes during scale changes * compositor.h (struct _XdgRoleImplementationFuncs): New function `rescale'. * subsurface.c (Rescale): If the parent has been detached, don't call MoveFractional. * xdg_surface.c (Rescale): Call rescale hook. * xdg_toplevel.c (SendOutputBounds): Check that some fields are present. Scale geometry correctly. (Rescale): New function. (ShowWindowMenu): Scale coordinates correctly. (XLGetXdgToplevel): Add Rescale hook. --- compositor.h | 1 + subsurface.c | 5 +++++ xdg_surface.c | 5 +++++ xdg_toplevel.c | 44 ++++++++++++++++++++++++++++++++++++++++---- 4 files changed, 51 insertions(+), 4 deletions(-) diff --git a/compositor.h b/compositor.h index 56d3b3f..54353fd 100644 --- a/compositor.h +++ b/compositor.h @@ -1344,6 +1344,7 @@ struct _XdgRoleImplementationFuncs void (*outputs_changed) (Role *, XdgRoleImplementation *); void (*after_commit) (Role *, Surface *, XdgRoleImplementation *); void (*activate) (Role *, XdgRoleImplementation *, int, Time); + void (*rescale) (Role *, XdgRoleImplementation *); }; struct _XdgRoleImplementation diff --git a/subsurface.c b/subsurface.c index ac3f9cb..bc136c7 100644 --- a/subsurface.c +++ b/subsurface.c @@ -884,6 +884,11 @@ Rescale (Surface *surface, Role *role) subsurface = SubsurfaceFromRole (role); + /* If the parent has been detached, return immediately. */ + + if (!subsurface->parent) + return; + /* The scale factor changed; move the subsurface to the new correct position. */ diff --git a/xdg_surface.c b/xdg_surface.c index 6f8a205..f0fb3ee 100644 --- a/xdg_surface.c +++ b/xdg_surface.c @@ -1332,6 +1332,11 @@ Rescale (Surface *surface, Role *role) if (xdg_role->impl->funcs.handle_geometry_change) xdg_role->impl->funcs.handle_geometry_change (role, xdg_role->impl); + + /* Also update the configure bounds if necessary. */ + + if (xdg_role->impl->funcs.rescale) + xdg_role->impl->funcs.rescale (role, xdg_role->impl); } static void diff --git a/xdg_toplevel.c b/xdg_toplevel.c index 4f0ab1b..2751f90 100644 --- a/xdg_toplevel.c +++ b/xdg_toplevel.c @@ -1235,12 +1235,46 @@ AckConfigure (Role *role, XdgRoleImplementation *impl, uint32_t serial) static void SendOutputBounds (XdgToplevel *toplevel) { - int x_min, y_min, x_max, y_max; + int x_min, y_min, x_max, y_max, width, height; XLGetMaxOutputBounds (&x_min, &y_min, &x_max, &y_max); + + if (!toplevel->role->surface || !toplevel->role->resource) + return; + + /* Adjust these bounds by the scale factor of the surface. The + bounds are specified in the window coordinate system, and have to + be converted to the surface ones. */ + + TruncateScaleToSurface (toplevel->role->surface, + x_max - x_min + 1, + y_max - y_min + 1, + &width, &height); + xdg_toplevel_send_configure_bounds (toplevel->resource, - x_max - x_min + 1, - y_max - y_min + 1); + width, height); +} + +static void +Rescale (Role *role, XdgRoleImplementation *impl) +{ + XdgToplevel *toplevel; + int width, height; + + toplevel = ToplevelFromRoleImpl (impl); + + if (!toplevel->resource) + return; + + /* The scale changed. Send the output bounds again if + necessary. */ + + if (wl_resource_get_version (toplevel->resource) < 4) + return; + + SendOutputBounds (toplevel); + CurrentWindowGeometry (toplevel, &width, &height); + SendConfigure (toplevel, width, height); } /* Forward declaration. */ @@ -1971,7 +2005,8 @@ ShowWindowMenu (struct wl_client *client, struct wl_resource *resource, XLXdgRoleCurrentRootPosition (toplevel->role, &root_x, &root_y); XLSeatShowWindowMenu (seat, toplevel->role->surface, - root_x + x, root_y + y); + root_x + x * toplevel->role->surface->factor, + root_y + y * toplevel->role->surface->factor); } static void @@ -2363,6 +2398,7 @@ XLGetXdgToplevel (struct wl_client *client, struct wl_resource *resource, toplevel->impl.funcs.outputs_changed = OutputsChanged; toplevel->impl.funcs.after_commit = AfterCommit; toplevel->impl.funcs.activate = Activate; + toplevel->impl.funcs.rescale = Rescale; if (!XLWmSupportsHint (_NET_WM_STATE_FOCUSED)) /* If _NET_WM_STATE_FOCUSED is unsupported, fall back to utilizing