Client: Expose a way to set window margins via native interface

The lack of such API is a big hassle to me since a long time.
All that time I was forced to have my own fork of the
xdg-shell plugin in the application code in order to have
shadows on Wayland with custom client-side decorations.
I hope I won't have to maintain the fork anymore.

Pick-to: 6.4
Change-Id: Iaf498469843b5cac5c458049164065c4ef15877d
Reviewed-by: David Edmundson <davidedmundson@kde.org>
This commit is contained in:
Ilya Fedin 2022-04-12 08:48:34 +04:00
parent e43b382fb3
commit 6939f52984
4 changed files with 40 additions and 2 deletions

View File

@ -129,6 +129,17 @@ void *QWaylandNativeInterface::nativeResourceForContext(const QByteArray &resour
}
#endif // opengl
QPlatformNativeInterface::NativeResourceForWindowFunction QWaylandNativeInterface::nativeResourceFunctionForWindow(const QByteArray &resource)
{
QByteArray lowerCaseResource = resource.toLower();
if (lowerCaseResource == "setmargins") {
return NativeResourceForWindowFunction(reinterpret_cast<void *>(setWindowMargins));
}
return nullptr;
}
QVariantMap QWaylandNativeInterface::windowProperties(QPlatformWindow *window) const
{
QWaylandWindow *waylandWindow = static_cast<QWaylandWindow *>(window);
@ -158,6 +169,12 @@ void QWaylandNativeInterface::emitWindowPropertyChanged(QPlatformWindow *window,
emit windowPropertyChanged(window,name);
}
void QWaylandNativeInterface::setWindowMargins(QWindow *window, const QMargins &margins)
{
QWaylandWindow *wlWindow = static_cast<QWaylandWindow*>(window->handle());
wlWindow->setCustomMargins(margins);
}
}
QT_END_NAMESPACE

View File

@ -24,6 +24,8 @@
QT_BEGIN_NAMESPACE
class QMargins;
namespace QtWaylandClient {
class QWaylandIntegration;
@ -41,6 +43,7 @@ public:
#if QT_CONFIG(opengl)
void *nativeResourceForContext(const QByteArray &resource, QOpenGLContext *context) override;
#endif
NativeResourceForWindowFunction nativeResourceFunctionForWindow(const QByteArray &resource) override;
QVariantMap windowProperties(QPlatformWindow *window) const override;
QVariant windowProperty(QPlatformWindow *window, const QString &name) const override;
QVariant windowProperty(QPlatformWindow *window, const QString &name, const QVariant &defaultValue) const override;
@ -49,6 +52,8 @@ public:
void emitWindowPropertyChanged(QPlatformWindow *window, const QString &name);
private:
static void setWindowMargins(QWindow *window, const QMargins &margins);
QWaylandIntegration *m_integration = nullptr;
QHash<QPlatformWindow*, QVariantMap> m_windowProperties;
};

View File

@ -402,8 +402,12 @@ void QWaylandWindow::resizeFromApplyConfigure(const QSize &sizeWithMargins, cons
// 2) Following resizeFromApplyConfigure() calls should have sizeWithMargins equal to
// windowContentGeometry() which excludes shadows, therefore in this case we have to
// exclude them too in order not to accidentally apply smaller size to the window.
if (mWindowDecorationEnabled && (sizeWithMargins != surfaceSize()))
margins = mWindowDecoration->margins(QWaylandAbstractDecoration::ShadowsExcluded);
if (sizeWithMargins != surfaceSize()) {
if (mWindowDecorationEnabled)
margins = mWindowDecoration->margins(QWaylandAbstractDecoration::ShadowsExcluded);
if (!mCustomMargins.isNull())
margins -= mCustomMargins;
}
int widthWithoutMargins = qMax(sizeWithMargins.width() - (margins.left() + margins.right()), 1);
int heightWithoutMargins = qMax(sizeWithMargins.height() - (margins.top() + margins.bottom()), 1);
@ -740,6 +744,12 @@ QMargins QWaylandWindow::clientSideMargins() const
return mWindowDecorationEnabled ? mWindowDecoration->margins() : QMargins{};
}
void QWaylandWindow::setCustomMargins(const QMargins &margins) {
const QMargins oldMargins = mCustomMargins;
mCustomMargins = margins;
setGeometry(geometry().marginsRemoved(oldMargins).marginsAdded(margins));
}
/*!
* Size, with decorations (including including eventual shadows) in wl_surface coordinates
*/
@ -759,6 +769,9 @@ QRect QWaylandWindow::windowContentGeometry() const
if (mWindowDecorationEnabled)
shadowMargins = mWindowDecoration->margins(QWaylandAbstractDecoration::ShadowsOnly);
if (!mCustomMargins.isNull())
shadowMargins += mCustomMargins;
return QRect(QPoint(shadowMargins.left(), shadowMargins.top()), surfaceSize().shrunkBy(shadowMargins));
}

View File

@ -112,6 +112,7 @@ public:
bool waitForFrameSync(int timeout);
QMargins frameMargins() const override;
void setCustomMargins(const QMargins &margins);
QSize surfaceSize() const;
QRect windowContentGeometry() const;
QPointF mapFromWlSurface(const QPointF &surfacePosition) const;
@ -289,6 +290,8 @@ protected:
QWaylandBuffer *mQueuedBuffer = nullptr;
QRegion mQueuedBufferDamage;
QMargins mCustomMargins;
private:
void setGeometry_helper(const QRect &rect);
void initWindow();