From f746be7c7f57354121c8cb4cf3c824710f3672ab Mon Sep 17 00:00:00 2001 From: Johan Klokkhammer Helsing Date: Mon, 27 Aug 2018 09:25:50 +0200 Subject: [PATCH 1/3] Client: Fix regression; drawing decorations of active windows as inactive We can't trust QWindow::isActive, because it relies on focusWindow, which may be updated too late, and there might also be multiple active toplevel windows at once on Wayland. Even though Qt doesn't support multiple seats, we should still draw the decorations of active windows correctly. This implements QPlatformWindow::isActive and uses it in the decorations. Change-Id: I34d79b354e2d26694533e2319a26f24085212243 Reviewed-by: Paul Olav Tvete --- .../platforms/wayland/plugins/decorations/bradient/main.cpp | 5 +++-- src/plugins/platforms/wayland/qwaylanddisplay.cpp | 5 +++++ src/plugins/platforms/wayland/qwaylanddisplay_p.h | 1 + src/plugins/platforms/wayland/qwaylandwindow.cpp | 5 +++++ src/plugins/platforms/wayland/qwaylandwindow_p.h | 1 + 5 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/plugins/platforms/wayland/plugins/decorations/bradient/main.cpp b/src/plugins/platforms/wayland/plugins/decorations/bradient/main.cpp index 1df3ac62b21..3fa723446db 100644 --- a/src/plugins/platforms/wayland/plugins/decorations/bradient/main.cpp +++ b/src/plugins/platforms/wayland/plugins/decorations/bradient/main.cpp @@ -132,6 +132,7 @@ QMargins QWaylandBradientDecoration::margins() const void QWaylandBradientDecoration::paint(QPaintDevice *device) { + bool active = window()->handle()->isActive(); QRect surfaceRect(QPoint(), window()->frameGeometry().size()); QRect clips[] = { @@ -183,7 +184,7 @@ void QWaylandBradientDecoration::paint(QPaintDevice *device) p.save(); p.setClipRect(titleBar); - p.setPen(window()->isActive() ? m_foregroundColor : m_foregroundInactiveColor); + p.setPen(active ? m_foregroundColor : m_foregroundInactiveColor); QSizeF size = m_windowTitle.size(); int dx = (top.width() - size.width()) /2; int dy = (top.height()- size.height()) /2; @@ -199,7 +200,7 @@ void QWaylandBradientDecoration::paint(QPaintDevice *device) QRectF rect; // Default pen - QPen pen(window()->isActive() ? m_foregroundColor : m_foregroundInactiveColor); + QPen pen(active ? m_foregroundColor : m_foregroundInactiveColor); p.setPen(pen); // Close button diff --git a/src/plugins/platforms/wayland/qwaylanddisplay.cpp b/src/plugins/platforms/wayland/qwaylanddisplay.cpp index 5e67cd3a693..c57dc13add2 100644 --- a/src/plugins/platforms/wayland/qwaylanddisplay.cpp +++ b/src/plugins/platforms/wayland/qwaylanddisplay.cpp @@ -413,6 +413,11 @@ void QWaylandDisplay::setLastInputDevice(QWaylandInputDevice *device, uint32_t s mLastInputWindow = win; } +bool QWaylandDisplay::isWindowActivated(const QWaylandWindow *window) +{ + return mActiveWindows.contains(const_cast(window)); +} + void QWaylandDisplay::handleWindowActivated(QWaylandWindow *window) { if (mActiveWindows.contains(window)) diff --git a/src/plugins/platforms/wayland/qwaylanddisplay_p.h b/src/plugins/platforms/wayland/qwaylanddisplay_p.h index 8839bbe4cc0..71a39dd928c 100644 --- a/src/plugins/platforms/wayland/qwaylanddisplay_p.h +++ b/src/plugins/platforms/wayland/qwaylanddisplay_p.h @@ -176,6 +176,7 @@ public: QWaylandWindow *lastInputWindow() const; void setLastInputDevice(QWaylandInputDevice *device, uint32_t serial, QWaylandWindow *window); + bool isWindowActivated(const QWaylandWindow *window); void handleWindowActivated(QWaylandWindow *window); void handleWindowDeactivated(QWaylandWindow *window); void handleKeyboardFocusChanged(QWaylandInputDevice *inputDevice); diff --git a/src/plugins/platforms/wayland/qwaylandwindow.cpp b/src/plugins/platforms/wayland/qwaylandwindow.cpp index 76039091711..e58e87221df 100644 --- a/src/plugins/platforms/wayland/qwaylandwindow.cpp +++ b/src/plugins/platforms/wayland/qwaylandwindow.cpp @@ -943,6 +943,11 @@ bool QWaylandWindow::isExposed() const return QPlatformWindow::isExposed(); } +bool QWaylandWindow::isActive() const +{ + return mDisplay->isWindowActivated(this); +} + int QWaylandWindow::scale() const { return mScale; diff --git a/src/plugins/platforms/wayland/qwaylandwindow_p.h b/src/plugins/platforms/wayland/qwaylandwindow_p.h index b6b499a3b71..d11ed871bf8 100644 --- a/src/plugins/platforms/wayland/qwaylandwindow_p.h +++ b/src/plugins/platforms/wayland/qwaylandwindow_p.h @@ -146,6 +146,7 @@ public: void requestActivateWindow() override; bool isExposed() const override; + bool isActive() const override; void unfocus(); QWaylandAbstractDecoration *decoration() const; From 3c4ea05c754bfdc7e353f60e3bf3498867c4b0ea Mon Sep 17 00:00:00 2001 From: Johan Klokkhammer Helsing Date: Tue, 28 Aug 2018 16:07:06 +0200 Subject: [PATCH 2/3] Scanner: Don't crash when calling fromResource with nullptr Change-Id: I85c17e50cf917a51e74fa03fcdc647def6e4bdfd Reviewed-by: Paul Olav Tvete Reviewed-by: Pier Luigi Fiorini --- src/tools/qtwaylandscanner/qtwaylandscanner.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/tools/qtwaylandscanner/qtwaylandscanner.cpp b/src/tools/qtwaylandscanner/qtwaylandscanner.cpp index bdcbffa0d3c..c08c00f4fc3 100644 --- a/src/tools/qtwaylandscanner/qtwaylandscanner.cpp +++ b/src/tools/qtwaylandscanner/qtwaylandscanner.cpp @@ -806,6 +806,8 @@ bool Scanner::process() printf(" %s::Resource *%s::Resource::fromResource(struct ::wl_resource *resource)\n", interfaceName, interfaceName); printf(" {\n"); + printf(" if (Q_UNLIKELY(!resource))\n"); + printf(" return nullptr;\n"); printf(" if (wl_resource_instance_of(resource, &::%s_interface, %s))\n", interfaceName, interfaceMember.constData()); printf(" return static_cast(resource->data);\n"); printf(" return nullptr;\n"); From db0838a117db11152903fc58fcd601cc326318ff Mon Sep 17 00:00:00 2001 From: Johan Klokkhammer Helsing Date: Tue, 28 Aug 2018 16:29:38 +0200 Subject: [PATCH 3/3] Compositor: Fix nullptr dereferences in fromResource functions If there was no resource for the given wl_resource*, don't try to dereference it. Change-Id: I3a27a5805699148bb26029e8b4179042c3c1117a Reviewed-by: Paul Olav Tvete Reviewed-by: Pier Luigi Fiorini --- tests/auto/wayland/shared/mocksurface.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/auto/wayland/shared/mocksurface.cpp b/tests/auto/wayland/shared/mocksurface.cpp index 82ce37acb4c..4de4265d773 100644 --- a/tests/auto/wayland/shared/mocksurface.cpp +++ b/tests/auto/wayland/shared/mocksurface.cpp @@ -107,7 +107,9 @@ bool Surface::isMapped() const Surface *Surface::fromResource(struct ::wl_resource *resource) { - return static_cast(Resource::fromResource(resource)->surface_object); + if (auto *r = Resource::fromResource(resource)) + return static_cast(r->surface_object); + return nullptr; } void Surface::surface_destroy_resource(Resource *)