[server] Respect input region of sub-surfaces on pointer surface focus

Summary:
KWayland takes always the top-most child surface at a given position for its
pointer input. But if a sub-surface sets its input region, it should not select
this one when the position is out of its input region, but rather try the
surface below.

Test Plan:
My testing was only on my Xwayland branch. Supposed to also fix a problem
with Firefox native Wayland port.

Reviewers: #frameworks, graesslin, davidedmundson

Reviewed By: davidedmundson

Subscribers: davidedmundson, zzag, kde-frameworks-devel, graesslin, plasma-devel

Tags: #frameworks, #plasma_on_wayland

Differential Revision: https://phabricator.kde.org/D7038
This commit is contained in:
Roman Gilg 2018-10-02 18:11:52 +02:00
parent 1955e15afa
commit 96967485ba
3 changed files with 46 additions and 2 deletions

View file

@ -241,7 +241,7 @@ PointerInterface::PointerInterface(SeatInterface *parent, wl_resource *parentRes
return;
}
const QPointF pos = d->seat->focusedPointerSurfaceTransformation().map(d->seat->pointerPos());
auto targetSurface = d->focusedSurface->surfaceAt(pos);
auto targetSurface = d->focusedSurface->inputSurfaceAt(pos);
if (!targetSurface) {
targetSurface = d->focusedSurface;
}
@ -286,7 +286,7 @@ void PointerInterface::setFocusedSurface(SurfaceInterface *surface, quint32 seri
);
const QPointF pos = d->seat->focusedPointerSurfaceTransformation().map(d->seat->pointerPos());
d->focusedChildSurface = QPointer<SurfaceInterface>(d->focusedSurface->surfaceAt(pos));
d->focusedChildSurface = QPointer<SurfaceInterface>(d->focusedSurface->inputSurfaceAt(pos));
if (!d->focusedChildSurface) {
d->focusedChildSurface = QPointer<SurfaceInterface>(d->focusedSurface);
}

View file

@ -856,6 +856,35 @@ SurfaceInterface *SurfaceInterface::surfaceAt(const QPointF &position)
return nullptr;
}
SurfaceInterface *SurfaceInterface::inputSurfaceAt(const QPointF &position)
{
// TODO: Most of this is very similar to SurfaceInterface::surfaceAt
// Is there a way to reduce the code duplication?
if (!isMapped()) {
return nullptr;
}
Q_D();
// go from top to bottom. Top most child is last in list
QListIterator<QPointer<SubSurfaceInterface>> it(d->current.children);
it.toBack();
while (it.hasPrevious()) {
const auto &current = it.previous();
auto surface = current->surface();
if (surface.isNull()) {
continue;
}
if (auto s = surface->inputSurfaceAt(position - current->position())) {
return s;
}
}
// check whether the geometry and input region contain the pos
if (!size().isEmpty() && QRectF(QPoint(0, 0), size()).contains(position) &&
(inputIsInfinite() || input().contains(position.toPoint()))) {
return this;
}
return nullptr;
}
QPointer<LockedPointerInterface> SurfaceInterface::lockedPointer() const
{
Q_D();

View file

@ -211,6 +211,21 @@ public:
**/
SurfaceInterface *surfaceAt(const QPointF &position);
/**
* Finds the input receiving SurfaceInterface at the given @p position in surface-local coordinates.
* This can be either a descendant SurfaceInterface honoring the stacking order or
* the SurfaceInterface itself if its geometry contains the given @p position.
*
* If no such SurfaceInterface is found, e.g. because the SurfaceInterface is unmapped or there is no
* input region containing the position,
* @c nullptr is returned.
*
* @param position The position in surface-local coordinates
* @returns Input receiving child surface at the given @p position or surface itself at the position, might be @c nullptr
* @since 5.52
**/
SurfaceInterface *inputSurfaceAt(const QPointF &position);
/**
* Sets the @p outputs this SurfaceInterface overlaps with, may be empty.
*