Client: Fix incorrect decoration size when QT_SCALE_FACTOR is set

[ChangeLog][QPA plugin] Fixed a bug where window decorations were to small for
for the content when QT_SCALE_FACTOR was set.

Fixes: QTBUG-72993
Change-Id: I1ed26e038c27f7c4454a6bcc04f0849e4af789e7
Reviewed-by: Paul Olav Tvete <paul.tvete@qt.io>
This commit is contained in:
Johan Klokkhammer Helsing 2019-01-22 14:38:44 +01:00 committed by Johan Helsing
parent db7724afe3
commit f91e358902
4 changed files with 49 additions and 26 deletions

View File

@ -109,19 +109,22 @@ QWaylandBradientDecoration::QWaylandBradientDecoration()
QRectF QWaylandBradientDecoration::closeButtonRect() const QRectF QWaylandBradientDecoration::closeButtonRect() const
{ {
return QRectF(window()->frameGeometry().width() - BUTTON_WIDTH - BUTTON_SPACING * 0 - BUTTONS_RIGHT_MARGIN, const int windowRight = waylandWindow()->windowGeometry().right() + 1;
return QRectF(windowRight - BUTTON_WIDTH - BUTTON_SPACING * 0 - BUTTONS_RIGHT_MARGIN,
(margins().top() - BUTTON_WIDTH) / 2, BUTTON_WIDTH, BUTTON_WIDTH); (margins().top() - BUTTON_WIDTH) / 2, BUTTON_WIDTH, BUTTON_WIDTH);
} }
QRectF QWaylandBradientDecoration::maximizeButtonRect() const QRectF QWaylandBradientDecoration::maximizeButtonRect() const
{ {
return QRectF(window()->frameGeometry().width() - BUTTON_WIDTH * 2 - BUTTON_SPACING * 1 - BUTTONS_RIGHT_MARGIN, const int windowRight = waylandWindow()->windowGeometry().right() + 1;
return QRectF(windowRight - BUTTON_WIDTH * 2 - BUTTON_SPACING * 1 - BUTTONS_RIGHT_MARGIN,
(margins().top() - BUTTON_WIDTH) / 2, BUTTON_WIDTH, BUTTON_WIDTH); (margins().top() - BUTTON_WIDTH) / 2, BUTTON_WIDTH, BUTTON_WIDTH);
} }
QRectF QWaylandBradientDecoration::minimizeButtonRect() const QRectF QWaylandBradientDecoration::minimizeButtonRect() const
{ {
return QRectF(window()->frameGeometry().width() - BUTTON_WIDTH * 3 - BUTTON_SPACING * 2 - BUTTONS_RIGHT_MARGIN, const int windowRight = waylandWindow()->windowGeometry().right() + 1;
return QRectF(windowRight - BUTTON_WIDTH * 3 - BUTTON_SPACING * 2 - BUTTONS_RIGHT_MARGIN,
(margins().top() - BUTTON_WIDTH) / 2, BUTTON_WIDTH, BUTTON_WIDTH); (margins().top() - BUTTON_WIDTH) / 2, BUTTON_WIDTH, BUTTON_WIDTH);
} }
@ -133,13 +136,13 @@ QMargins QWaylandBradientDecoration::margins() const
void QWaylandBradientDecoration::paint(QPaintDevice *device) void QWaylandBradientDecoration::paint(QPaintDevice *device)
{ {
bool active = window()->handle()->isActive(); bool active = window()->handle()->isActive();
QRect surfaceRect(QPoint(), window()->frameGeometry().size()); QRect wg = waylandWindow()->windowGeometry();
QRect clips[] = QRect clips[] =
{ {
QRect(0, 0, surfaceRect.width(), margins().top()), QRect(wg.left(), wg.top(), wg.width(), margins().top()),
QRect(0, surfaceRect.height() - margins().bottom(), surfaceRect.width(), margins().bottom()), QRect(wg.left(), (wg.bottom() + 1) - margins().bottom(), wg.width(), margins().bottom()),
QRect(0, margins().top(), margins().left(), surfaceRect.height() - margins().top() - margins().bottom()), QRect(wg.left(), margins().top(), margins().left(), wg.height() - margins().top() - margins().bottom()),
QRect(surfaceRect.width() - margins().right(), margins().top(), margins().left(), surfaceRect.height() - margins().top() - margins().bottom()) QRect((wg.right() + 1) - margins().right(), wg.top() + margins().top(), margins().right(), wg.height() - margins().top() - margins().bottom())
}; };
QRect top = clips[0]; QRect top = clips[0];
@ -149,7 +152,7 @@ void QWaylandBradientDecoration::paint(QPaintDevice *device)
// Title bar // Title bar
QPainterPath roundedRect; QPainterPath roundedRect;
roundedRect.addRoundedRect(surfaceRect, 3, 3); roundedRect.addRoundedRect(wg, 3, 3);
for (int i = 0; i < 4; ++i) { for (int i = 0; i < 4; ++i) {
p.save(); p.save();
p.setClipRect(clips[i]); p.setClipRect(clips[i]);
@ -264,13 +267,14 @@ bool QWaylandBradientDecoration::handleMouse(QWaylandInputDevice *inputDevice, c
Q_UNUSED(global); Q_UNUSED(global);
// Figure out what area mouse is in // Figure out what area mouse is in
if (local.y() <= margins().top()) { QRect wg = waylandWindow()->windowGeometry();
if (local.y() <= wg.top() + margins().top()) {
processMouseTop(inputDevice,local,b,mods); processMouseTop(inputDevice,local,b,mods);
} else if (local.y() > window()->height() + margins().top()) { } else if (local.y() > wg.bottom() - margins().bottom()) {
processMouseBottom(inputDevice,local,b,mods); processMouseBottom(inputDevice,local,b,mods);
} else if (local.x() <= margins().left()) { } else if (local.x() <= wg.left() + margins().left()) {
processMouseLeft(inputDevice,local,b,mods); processMouseLeft(inputDevice,local,b,mods);
} else if (local.x() > window()->width() + margins().left()) { } else if (local.x() > wg.right() - margins().right()) {
processMouseRight(inputDevice,local,b,mods); processMouseRight(inputDevice,local,b,mods);
} else { } else {
#if QT_CONFIG(cursor) #if QT_CONFIG(cursor)
@ -308,15 +312,16 @@ bool QWaylandBradientDecoration::handleTouch(QWaylandInputDevice *inputDevice, c
void QWaylandBradientDecoration::processMouseTop(QWaylandInputDevice *inputDevice, const QPointF &local, Qt::MouseButtons b, Qt::KeyboardModifiers mods) void QWaylandBradientDecoration::processMouseTop(QWaylandInputDevice *inputDevice, const QPointF &local, Qt::MouseButtons b, Qt::KeyboardModifiers mods)
{ {
QRect wg = waylandWindow()->windowGeometry();
Q_UNUSED(mods); Q_UNUSED(mods);
if (local.y() <= margins().bottom()) { if (local.y() <= wg.top() + margins().bottom()) {
if (local.x() <= margins().left()) { if (local.x() <= margins().left()) {
//top left bit //top left bit
#if QT_CONFIG(cursor) #if QT_CONFIG(cursor)
waylandWindow()->setMouseCursor(inputDevice, Qt::SizeFDiagCursor); waylandWindow()->setMouseCursor(inputDevice, Qt::SizeFDiagCursor);
#endif #endif
startResize(inputDevice, Qt::TopEdge | Qt::LeftEdge, b); startResize(inputDevice, Qt::TopEdge | Qt::LeftEdge, b);
} else if (local.x() > window()->width() + margins().left()) { } else if (local.x() > wg.right() - margins().right()) {
//top right bit //top right bit
#if QT_CONFIG(cursor) #if QT_CONFIG(cursor)
waylandWindow()->setMouseCursor(inputDevice, Qt::SizeBDiagCursor); waylandWindow()->setMouseCursor(inputDevice, Qt::SizeBDiagCursor);
@ -329,9 +334,9 @@ void QWaylandBradientDecoration::processMouseTop(QWaylandInputDevice *inputDevic
#endif #endif
startResize(inputDevice, Qt::TopEdge, b); startResize(inputDevice, Qt::TopEdge, b);
} }
} else if (local.x() <= margins().left()) { } else if (local.x() <= wg.left() + margins().left()) {
processMouseLeft(inputDevice, local, b, mods); processMouseLeft(inputDevice, local, b, mods);
} else if (local.x() > window()->width() + margins().left()) { } else if (local.x() > wg.right() - margins().right()) {
processMouseRight(inputDevice, local, b, mods); processMouseRight(inputDevice, local, b, mods);
} else if (isRightClicked(b)) { } else if (isRightClicked(b)) {
showWindowMenu(inputDevice); showWindowMenu(inputDevice);

View File

@ -115,16 +115,17 @@ const QImage &QWaylandAbstractDecoration::contentImage()
{ {
Q_D(QWaylandAbstractDecoration); Q_D(QWaylandAbstractDecoration);
if (d->m_isDirty) { if (d->m_isDirty) {
//Update the decoration backingstore // Update the decoration backingstore
const int scale = waylandWindow()->scale(); const int bufferScale = waylandWindow()->scale();
const QSize imageSize = window()->frameGeometry().size() * scale; const QSize imageSize = waylandWindow()->surfaceSize() * bufferScale;
d->m_decorationContentImage = QImage(imageSize, QImage::Format_ARGB32_Premultiplied); d->m_decorationContentImage = QImage(imageSize, QImage::Format_ARGB32_Premultiplied);
d->m_decorationContentImage.setDevicePixelRatio(scale); // Only scale by buffer scale, not QT_SCALE_FACTOR etc.
d->m_decorationContentImage.setDevicePixelRatio(bufferScale);
d->m_decorationContentImage.fill(Qt::transparent); d->m_decorationContentImage.fill(Qt::transparent);
this->paint(&d->m_decorationContentImage); this->paint(&d->m_decorationContentImage);
QRegion damage = marginsRegion(window()->geometry().size(), window()->frameMargins()); QRegion damage = marginsRegion(waylandWindow()->surfaceSize(), waylandWindow()->frameMargins());
for (QRect r : damage) for (QRect r : damage)
waylandWindow()->damage(r); waylandWindow()->damage(r);

View File

@ -341,7 +341,7 @@ void QWaylandWindow::setGeometry(const QRect &rect)
sendExposeEvent(exposeGeometry); sendExposeEvent(exposeGeometry);
if (mShellSurface) if (mShellSurface)
mShellSurface->setWindowGeometry(QRect(QPoint(0, 0), window()->frameGeometry().size())); mShellSurface->setWindowGeometry(windowGeometry());
} }
void QWaylandWindow::resizeFromApplyConfigure(const QSize &sizeWithMargins, const QPoint &offset) void QWaylandWindow::resizeFromApplyConfigure(const QSize &sizeWithMargins, const QPoint &offset)
@ -654,6 +654,23 @@ QMargins QWaylandWindow::frameMargins() const
return QPlatformWindow::frameMargins(); return QPlatformWindow::frameMargins();
} }
/*!
* Size, with decorations (including including eventual shadows) in wl_surface coordinates
*/
QSize QWaylandWindow::surfaceSize() const
{
return geometry().marginsAdded(frameMargins()).size();
}
/*!
* Window geometry as defined by the xdg-shell spec (in wl_surface coordinates)
* topLeft is where the shadow stops and the decorations border start.
*/
QRect QWaylandWindow::windowGeometry() const
{
return QRect(QPoint(), surfaceSize());
}
QWaylandShellSurface *QWaylandWindow::shellSurface() const QWaylandShellSurface *QWaylandWindow::shellSurface() const
{ {
return mShellSurface; return mShellSurface;
@ -848,9 +865,7 @@ void QWaylandWindow::handleMouse(QWaylandInputDevice *inputDevice, const QWaylan
#if QT_CONFIG(cursor) #if QT_CONFIG(cursor)
if (e.type == QWaylandPointerEvent::Enter) { if (e.type == QWaylandPointerEvent::Enter) {
QRect windowGeometry = window()->frameGeometry(); QRect contentGeometry = windowGeometry().marginsRemoved(frameMargins());
windowGeometry.moveTopLeft({0, 0}); // convert to wayland surface coordinates
QRect contentGeometry = windowGeometry.marginsRemoved(frameMargins());
if (contentGeometry.contains(e.local.toPoint())) if (contentGeometry.contains(e.local.toPoint()))
restoreMouseCursor(inputDevice); restoreMouseCursor(inputDevice);
} }

View File

@ -125,6 +125,8 @@ public:
void waitForFrameSync(); void waitForFrameSync();
QMargins frameMargins() const override; QMargins frameMargins() const override;
QSize surfaceSize() const;
QRect windowGeometry() const;
static QWaylandWindow *fromWlSurface(::wl_surface *surface); static QWaylandWindow *fromWlSurface(::wl_surface *surface);