From 625baf006121e814612dcbc70a115efd4521cdf5 Mon Sep 17 00:00:00 2001 From: Lukas Holecek <hluk@email.cz> Date: Wed, 31 Mar 2021 14:50:23 +0200 Subject: [PATCH] Wayland: Fix saving/restoring window size on multiple screens Getting mouse position on Wayland might be unsupported. --- src/common/config.cpp | 37 +++++++++++++++++++++++++++++---- src/gui/windowgeometryguard.cpp | 13 ++++++++++++ src/gui/windowgeometryguard.h | 4 ++++ 3 files changed, 50 insertions(+), 4 deletions(-) diff --git a/src/common/config.cpp b/src/common/config.cpp index 249a05871..4b15d42c1 100644 --- a/src/common/config.cpp +++ b/src/common/config.cpp @@ -45,6 +45,16 @@ enum class GeometryAction { Restore }; +QPoint mousePos() +{ + // On Wayland, getting mouse position can return + // the last known mouse position in an own Qt application window. + static const bool supported = !QCursor::pos().isNull(); + if (supported) + return QCursor::pos(); + return QPoint(); +} + QString toString(const QRect &geometry) { return QString::fromLatin1("%1x%2,%3,%4") @@ -56,9 +66,28 @@ QString toString(const QRect &geometry) int screenNumber(const QWidget &widget, GeometryAction geometryAction) { - return geometryAction == GeometryAction::Save - ? QApplication::desktop()->screenNumber(&widget) - : screenNumberAt(QCursor::pos()); + if (geometryAction == GeometryAction::Restore) { + const QPoint pos = mousePos(); + if ( !pos.isNull() ) { + const int n = screenNumberAt(pos); + if (n != -1) + return n; + } + } + + QWindow *windowHandle = widget.windowHandle(); + if (windowHandle) { + QScreen *screen = windowHandle->screen(); + if (screen) + return QGuiApplication::screens().indexOf(screen); + } + + const int n = QApplication::desktop()->screenNumber(&widget); + if (n != -1) + return n; + + QScreen *screen = QGuiApplication::primaryScreen(); + return QGuiApplication::screens().indexOf(screen); } QString geometryOptionName(const QWidget &widget, GeometryAction geometryAction, bool openOnCurrentScreen) @@ -192,7 +221,7 @@ void restoreWindowGeometry(QWidget *w, bool openOnCurrentScreen) // If geometry for the screen doesn't exist, move window to the middle of the screen. if (geometry.isEmpty()) { - const QRect availableGeometry = screenAvailableGeometry(QCursor::pos()); + const QRect availableGeometry = screenAvailableGeometry(w->pos()); const QPoint position = availableGeometry.center() - w->rect().center(); w->move(position); } diff --git a/src/gui/windowgeometryguard.cpp b/src/gui/windowgeometryguard.cpp index 3abd5503c..eb4f8261a 100644 --- a/src/gui/windowgeometryguard.cpp +++ b/src/gui/windowgeometryguard.cpp @@ -27,7 +27,9 @@ #include <QApplication> #include <QEvent> #include <QMoveEvent> +#include <QScreen> #include <QVariant> +#include <QWindow> namespace { @@ -53,6 +55,11 @@ bool WindowGeometryGuard::eventFilter(QObject *, QEvent *event) m_timerSaveGeometry.stop(); m_timerRestoreGeometry.start(); } + if (!m_screenChangeConnected && m_window->windowHandle()) { + m_screenChangeConnected = true; + connect(m_window->windowHandle(), &QWindow::screenChanged, + this, &WindowGeometryGuard::onScreenChanged); + } break; case QEvent::Move: @@ -121,3 +128,9 @@ void WindowGeometryGuard::unlockWindowGeometry() { m_timerUnlockGeometry.stop(); } + +void WindowGeometryGuard::onScreenChanged() +{ + m_timerUnlockGeometry.stop(); + restoreWindowGeometry(); +} diff --git a/src/gui/windowgeometryguard.h b/src/gui/windowgeometryguard.h index 8720529e5..bd5137107 100644 --- a/src/gui/windowgeometryguard.h +++ b/src/gui/windowgeometryguard.h @@ -41,11 +41,15 @@ private: void restoreWindowGeometry(); void unlockWindowGeometry(); + void onScreenChanged(); + QWidget *m_window; QTimer m_timerSaveGeometry; QTimer m_timerRestoreGeometry; QTimer m_timerUnlockGeometry; + + bool m_screenChangeConnected = false; }; #endif // WINDOWGEOMETRYGUARD_H -- GitLab