Fix problems seen with some programs in the wild

* subcompositor.c (ViewAttachBuffer): Correctly determine when
to recompute view bounds.
* subsurface.c (AfterParentCommit): Unskip view first, and
commit pending state second.  Explain why.
* xdg_toplevel.c (Unmap, Map): Add new "initial configure" flag.
(Commit): Use it instead of testing current_buffer.  Explain
why.
(XLGetXdgToplevel): Set that flag by default.
This commit is contained in:
hujianwei 2022-10-30 13:53:10 +00:00
parent 0c3e5a0e7d
commit da212fe729
3 changed files with 38 additions and 19 deletions

View file

@ -1472,12 +1472,14 @@ ViewAttachBuffer (View *view, ExtBuffer *buffer)
if (!view->buffer && old && view->subcompositor)
/* The view needs a size update, as it is now 0 by 0. */
ViewAfterSizeUpdate (view);
else if (((buffer && !old)
else if ((buffer && !old)
|| (old && !buffer)
|| (buffer && old
&& (XLBufferWidth (buffer) != XLBufferWidth (old)
|| XLBufferHeight (buffer) != XLBufferHeight (old))))
&& !IsViewported (view))
|| XLBufferHeight (buffer) != XLBufferHeight (old))
/* Buffer width and height changes don't matter if the
view has a viewport. */
&& !IsViewported (view)))
/* Recompute view and subcompositor bounds. */
ViewAfterSizeUpdate (view);

View file

@ -600,6 +600,13 @@ AfterParentCommit (Surface *surface, void *data)
MoveFractional (subsurface);
}
/* Mark the subsurface as unskipped. (IOW, make it visible). This
must come before XLCommitSurface, as doing so will apply the
pending state, which will fail to update the subcompositor bounds
if the subsurface is skipped. */
ViewUnskip (subsurface->role.surface->view);
ViewUnskip (subsurface->role.surface->under);
/* And any cached surface state too. */
if (subsurface->pending_commit)
{
@ -610,10 +617,6 @@ AfterParentCommit (Surface *surface, void *data)
MaybeUpdateOutputs (subsurface);
}
/* Mark the subsurface as unskipped. (IOW, make it visible). */
ViewUnskip (subsurface->role.surface->view);
ViewUnskip (subsurface->role.surface->under);
subsurface->pending_commit = False;
subsurface->pending_substate.flags = 0;
}

View file

@ -44,16 +44,17 @@ typedef enum _DecorationMode DecorationMode;
enum
{
StateIsMapped = 1,
StatePendingMaxSize = (1 << 1),
StatePendingMinSize = (1 << 2),
StatePendingAckMovement = (1 << 3),
StatePendingResize = (1 << 4),
StatePendingConfigureSize = (1 << 5),
StatePendingConfigureStates = (1 << 6),
StateDecorationModeDirty = (1 << 7),
StateEverMapped = (1 << 8),
StateNeedDecorationConfigure = (1 << 9),
StateIsMapped = 1,
StatePendingMaxSize = (1 << 1),
StatePendingMinSize = (1 << 2),
StatePendingAckMovement = (1 << 3),
StatePendingResize = (1 << 4),
StatePendingConfigureSize = (1 << 5),
StatePendingConfigureStates = (1 << 6),
StateDecorationModeDirty = (1 << 7),
StateEverMapped = (1 << 8),
StateNeedDecorationConfigure = (1 << 9),
StateWaitingForInitialConfigure = (1 << 10),
};
enum
@ -1164,7 +1165,7 @@ Unmap (XdgToplevel *toplevel)
/* Clear all the state. */
toplevel->state = 0;
toplevel->state = StateWaitingForInitialConfigure;
toplevel->conf_reply = False;
toplevel->conf_serial = 0;
toplevel->states.size = 0;
@ -1204,6 +1205,7 @@ Map (XdgToplevel *toplevel)
SubcompositorGarbage (XLSubcompositorFromXdgRole (toplevel->role));
toplevel->state |= StateIsMapped | StateEverMapped;
toplevel->state &= ~StateWaitingForInitialConfigure;
/* Update the width and height from the xdg_surface bounds. */
toplevel->width = XLXdgRoleGetWidth (toplevel->role);
@ -1268,8 +1270,16 @@ Commit (Role *role, Surface *surface, XdgRoleImplementation *impl)
toplevel->state &= ~StatePendingMinSize;
}
if (!surface->current_state.buffer)
if (!surface->current_state.buffer
/* Whenever any commit happens without the toplevel being
mapped, send the initial configure event. This is because
some clients attach an initial 1x1 buffer and expect the
compositor to do its thing. */
|| (toplevel->state & StateWaitingForInitialConfigure))
{
/* Stop waiting for initial configure. */
toplevel->state &= ~StateWaitingForInitialConfigure;
/* No buffer was attached, unmap the window and send an empty
configure event. */
if (toplevel->state & StateIsMapped)
@ -2282,6 +2292,10 @@ XLGetXdgToplevel (struct wl_client *client, struct wl_resource *resource,
return;
}
/* Set this flag for some buggy clients. See the comment above the
part of Commit that checks this flag for more details. */
toplevel->state |= StateWaitingForInitialConfigure;
toplevel->impl.funcs.attach = Attach;
toplevel->impl.funcs.commit = Commit;
toplevel->impl.funcs.detach = Detach;