[PATCH] input: Fix BorderSizeNotEmpty for redirected windows

Keith Packard keithp at keithp.com
Wed Jul 30 16:48:12 PDT 2014

Adam Jackson <ajax at redhat.com> writes:

> In the words of the spec, grabs are meant to fail "if the confine-to
> window lies completely outside the boundaries of the root window".
> Redirected windows (and therefore windows with backing store enabled)
> have a pWin->borderSize that's not clipped to the root window, which
> means BorderSizeNotEmpty() is always true and the grab will succeed when
> it oughtn't.

As discussed on IRC, this points out a bug in the Composite support, but
the fix doesn't match the existing server semantics. The saved composite
border clip is clipped to siblings, while borderSize is not. I didn't
consider that borderSize was used for input computations.

Let's look at where borderSize is used for events

 * ConfineCursorToWindow. This ensures that the pointer remains
   contained within a window. Currently, that's using borderSize, but
   that's actually wrong. The protocol says that a grab's 'confine-to'
   window restricts the pointer to remain 'contained' in the window:

    "If a confine-to window is specified, then the pointer will be
     restricted to stay contained in that window."

   Containment is defined in the glossary:

    "A window ‘‘contains’’ the pointer if the window is viewable and the
     hotspot of the cursor is within a visible region of the window or a
     visible region of one of its inferiors. The border of the window is
     included as part of the window for containment. The pointer is
     ‘‘in’’ a window if the window contains the pointer but no inferior
     contains the pointer."

   This doesn't match borderSize, which is only clipped by ancestors,
   not by siblings. It does match the classic borderClip however.

 * PointInBorderSize. This is used only by miSpriteTrace to check
   whether the cursor is inside the window shape, which is the union of
   the bounding shape and the clip shape. Computing the sprite trace
   already starts from the top of the tree, so it's effectively
   computing the input border size; so the existing borderSize will
   work correctly.

 * BorderSizeNotEmpty. This is used to tell whether the grab confine-to
   window is outside the boundaries of the root window. By checking
   borderSize, the grab will fail if the window is within the root but
   it or some ancestor is outside one of their ancestors. I think the
   spec is busted here; if you want to confine a cursor to a window,
   then some portion of that window should probably be visible. In which
   case, we should be using the borderClip instead of borderSize here too.

 * CheckVirtualMotion. This is used to keep the logical position of the
   pointer confined while replaying events, and so the semantics must
   match ConfineCursorToWindow.

It seems like the old server code was just broken. We can almost use the
borderClip saved by composite, except when there are nested composited
windows. In that case, we would need to recursively intersect the
saved borderClips to the root.

keith.packard at intel.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 810 bytes
Desc: not available
URL: <http://lists.x.org/archives/xorg-devel/attachments/20140730/8a8daf3f/attachment.sig>

More information about the xorg-devel mailing list