Track the input shape of the server-side decoration

In order to determine if a window accepts input at specified position,
we need to check if the decorated window and the server-side decoration
contain the given point.

While we have a way to determine if a point falls inside the input shape
of the decorated window, there is no any way to do the same for the deco.
This commit is contained in:
Vlad Zahorodnii 2020-10-17 15:43:16 +03:00
parent ba4f6b35ae
commit fea950f23a
2 changed files with 26 additions and 0 deletions

View file

@ -28,6 +28,7 @@
#include "wayland_server.h"
#include <KWaylandServer/plasmawindowmanagement_interface.h>
#include <KDecoration2/DecoratedClient>
#include <KDecoration2/Decoration>
#include <KDesktopFile>
@ -2303,6 +2304,10 @@ void AbstractClient::createDecoration(const QRect &oldGeometry)
if (decoration) {
QMetaObject::invokeMethod(decoration, "update", Qt::QueuedConnection);
connect(decoration, &KDecoration2::Decoration::shadowChanged, this, &Toplevel::updateShadow);
connect(decoration, &KDecoration2::Decoration::bordersChanged,
this, &AbstractClient::updateDecorationInputShape);
connect(decoration, &KDecoration2::Decoration::resizeOnlyBordersChanged,
this, &AbstractClient::updateDecorationInputShape);
connect(decoration, &KDecoration2::Decoration::bordersChanged, this, [this]() {
GeometryUpdatesBlocker blocker(this);
const QRect oldGeometry = frameGeometry();
@ -2311,9 +2316,12 @@ void AbstractClient::createDecoration(const QRect &oldGeometry)
}
emit geometryShapeChanged(this, oldGeometry);
});
connect(decoratedClient()->decoratedClient(), &KDecoration2::DecoratedClient::sizeChanged,
this, &AbstractClient::updateDecorationInputShape);
}
setDecoration(decoration);
setFrameGeometry(QRect(oldGeometry.topLeft(), clientSizeToFrameSize(clientSize())));
updateDecorationInputShape();
emit geometryShapeChanged(this, oldGeometry);
}
@ -2322,6 +2330,22 @@ void AbstractClient::destroyDecoration()
{
delete m_decoration.decoration;
m_decoration.decoration = nullptr;
m_decoration.inputRegion = QRegion();
}
void AbstractClient::updateDecorationInputShape()
{
if (!isDecorated()) {
return;
}
const QMargins borders = decoration()->borders();
const QMargins resizeBorders = decoration()->resizeOnlyBorders();
const QRect innerRect = QRect(QPoint(borderLeft(), borderTop()), decoratedClient()->size());
const QRect outerRect = innerRect + borders + resizeBorders;
m_decoration.inputRegion = QRegion(outerRect) - innerRect;
}
bool AbstractClient::decorationHasAlpha() const

View file

@ -1192,6 +1192,7 @@ protected:
virtual void destroyDecoration();
void startDecorationDoubleClickTimer();
void invalidateDecorationDoubleClickTimer();
void updateDecorationInputShape();
void setDesktopFileName(QByteArray name);
QString iconFromDesktopFile() const;
@ -1299,6 +1300,7 @@ private:
KDecoration2::Decoration *decoration = nullptr;
QPointer<Decoration::DecoratedClientImpl> client;
QElapsedTimer doubleClickTimer;
QRegion inputRegion;
} m_decoration;
QByteArray m_desktopFileName;