From 55847cb9cc814b7cf23be8062dbda216c2d4ca36 Mon Sep 17 00:00:00 2001 From: Nicolas Fella Date: Thu, 1 Sep 2022 22:58:43 +0200 Subject: [PATCH] Refactor window handling code Currently when we want to show/raise the window in reaction to the tray icon/notification being clicked etc we do this by emitting a signal on the controller. This is connected to in main.qml, which does some things, then calls back to controller to do more things. This is quite convoluted. Instead introduce a new class WindowController that is responsible for all things window, in particular showing/raising and config saving --- CMakeLists.txt | 2 +- qml/main.qml | 21 ++------------ src/CMakeLists.txt | 1 + src/controller.cpp | 30 ++++++-------------- src/controller.h | 6 ++-- src/main.cpp | 34 ++++------------------ src/notificationsmanager.cpp | 11 ++------ src/runner.cpp | 4 ++- src/windowcontroller.cpp | 55 ++++++++++++++++++++++++++++++++++++ src/windowcontroller.h | 26 +++++++++++++++++ 10 files changed, 106 insertions(+), 84 deletions(-) create mode 100644 src/windowcontroller.cpp create mode 100644 src/windowcontroller.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 1b14ba946..1b19dd508 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,7 +9,7 @@ cmake_minimum_required(VERSION 3.16) project(NeoChat) set(PROJECT_VERSION "22.06") -set(KF5_MIN_VERSION "5.88.0") +set(KF5_MIN_VERSION "5.91.0") set(QT_MIN_VERSION "5.15.2") find_package(ECM ${KF5_MIN_VERSION} REQUIRED NO_MODULE) diff --git a/qml/main.qml b/qml/main.qml index 1e615b026..5d939524d 100644 --- a/qml/main.qml +++ b/qml/main.qml @@ -51,7 +51,7 @@ Kirigami.ApplicationWindow { Timer { id: saveWindowGeometryTimer interval: 1000 - onTriggered: Controller.saveWindowGeometry(root) + onTriggered: Controller.saveWindowGeometry() } Connections { @@ -59,7 +59,7 @@ Kirigami.ApplicationWindow { enabled: false // Disable on startup to avoid writing wrong values if the window is hidden target: root - function onClosing() { Controller.saveWindowGeometry(root); } + function onClosing() { Controller.saveWindowGeometry(); } function onWidthChanged() { saveWindowGeometryTimer.restart(); } function onHeightChanged() { saveWindowGeometryTimer.restart(); } function onXChanged() { saveWindowGeometryTimer.restart(); } @@ -139,13 +139,6 @@ Kirigami.ApplicationWindow { } } - function showWindow() { - root.show() - root.raise() - root.requestActivate() - Controller.raiseWindow(root) - } - contextDrawer: RoomDrawer { id: contextDrawer modal: !root.wideScreen || !enabled @@ -353,16 +346,6 @@ Kirigami.ApplicationWindow { showPassiveNotification(i18n("%1: %2", error, detail)); } - function onShowWindow(token = null) { - root.showWindow() - if (token && KWindowSystem) { - KWindowSystem.setCurrentXdgActivationToken(basicNotification.xdgActivationToken) - KWindowSystem.activateWindow(root) - } else { - root.raise() - } - } - function onUserConsentRequired(url) { consentSheet.url = url consentSheet.open() diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ad37bb48b..9527302d6 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -38,6 +38,7 @@ add_library(neochat STATIC joinrulesevent.cpp collapsestateproxymodel.cpp urlhelper.cpp + windowcontroller.cpp ) add_executable(neochat-app diff --git a/src/controller.cpp b/src/controller.cpp index 1b8a0d6fd..32831e4fd 100644 --- a/src/controller.cpp +++ b/src/controller.cpp @@ -12,7 +12,6 @@ #include #ifdef HAVE_WINDOWSYSTEM #include -#include #endif #include @@ -53,6 +52,7 @@ #include "roommanager.h" #include "settings.h" #include "utils.h" +#include "windowcontroller.h" #include #include @@ -131,6 +131,11 @@ Controller &Controller::instance() return _instance; } +void Controller::showWindow() +{ + WindowController::instance().showAndRaiseWindow(QString()); +} + inline QString accessTokenFileName(const AccountSettings &account) { QString fileName = account.userId(); @@ -589,21 +594,9 @@ void Controller::setActiveConnection(Connection *connection) Q_EMIT activeConnectionChanged(); } -void Controller::restoreWindowGeometry(QWindow *window) +void Controller::saveWindowGeometry() { - KConfig dataResource("data", KConfig::SimpleConfig, QStandardPaths::AppDataLocation); - KConfigGroup windowGroup(&dataResource, "Window"); - KWindowConfig::restoreWindowSize(window, windowGroup); - KWindowConfig::restoreWindowPosition(window, windowGroup); -} - -void Controller::saveWindowGeometry(QQuickWindow *window) -{ - KConfig dataResource("data", KConfig::SimpleConfig, QStandardPaths::AppDataLocation); - KConfigGroup windowGroup(&dataResource, "Window"); - KWindowConfig::saveWindowPosition(window, windowGroup); - KWindowConfig::saveWindowSize(window, windowGroup); - dataResource.sync(); + WindowController::instance().saveGeometry(); } NeochatDeleteDeviceJob::NeochatDeleteDeviceJob(const QString &deviceId, const Omittable &auth) @@ -681,13 +674,6 @@ void Controller::setBlur(QQuickItem *item, bool blur) #endif } -void Controller::raiseWindow(QWindow *window) -{ -#ifdef HAVE_WINDOWSYSTEM - KWindowSystem::activateWindow(window->winId()); -#endif -} - bool Controller::hasWindowSystem() const { #ifdef HAVE_WINDOWSYSTEM diff --git a/src/controller.h b/src/controller.h index 441ad85cf..6eafe70bd 100644 --- a/src/controller.h +++ b/src/controller.h @@ -95,7 +95,6 @@ public: Q_INVOKABLE void openOrCreateDirectChat(NeoChatUser *user); Q_INVOKABLE void setBlur(QQuickItem *item, bool blur); - Q_INVOKABLE void raiseWindow(QWindow *window); Q_INVOKABLE QString plainText(QQuickTextDocument *document) const; bool encryptionSupported() const; @@ -118,6 +117,7 @@ private: private Q_SLOTS: void invokeLogin(); + void showWindow(); Q_SIGNALS: void busyChanged(); @@ -137,7 +137,6 @@ Q_SIGNALS: void activeConnectionChanged(); void aboutDataChanged(); void passwordStatus(Controller::PasswordStatus _t1); - void showWindow(); void userConsentRequired(QUrl url); void testConnectionResult(const QString &connection, bool usable); void isOnlineChanged(bool isOnline); @@ -146,8 +145,7 @@ public Q_SLOTS: void logout(Quotient::Connection *conn, bool serverSideLogout); void changeAvatar(Quotient::Connection *conn, const QUrl &localFile); static void markAllMessagesAsRead(Quotient::Connection *conn); - void restoreWindowGeometry(QWindow *); - void saveWindowGeometry(QQuickWindow *); + void saveWindowGeometry(); }; // TODO libQuotient 0.7: Drop diff --git a/src/main.cpp b/src/main.cpp index b65e115be..907af648b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -75,6 +75,7 @@ #include "userdirectorylistmodel.h" #include "userlistmodel.h" #include "webshortcutmodel.h" +#include "windowcontroller.h" #include #ifdef HAVE_COLORSCHEME #include "colorschemer.h" @@ -95,21 +96,6 @@ class NetworkAccessManagerFactory : public QQmlNetworkAccessManagerFactory } }; -#ifdef HAVE_WINDOWSYSTEM -static void raiseWindow(QWindow *window) -{ -#if KWINDOWSYSTEM_VERSION >= QT_VERSION_CHECK(5, 91, 0) - KWindowSystem::updateStartupId(window); -#else - if (KWindowSystem::isPlatformWayland()) { - KWindowSystem::setCurrentXdgActivationToken(qEnvironmentVariable("XDG_ACTIVATION_TOKEN")); - } -#endif - KWindowSystem::activateWindow(window->winId()); - window->raise(); -} -#endif - static QWindow *windowFromEngine(QQmlApplicationEngine *engine) { const auto rootObjects = engine->rootObjects(); @@ -238,12 +224,6 @@ int main(int argc, char *argv[]) qRegisterMetaType("GetRoomEventsJob*"); qRegisterMetaType("QMimeType"); -#ifdef HAVE_WINDOWSYSTEM - qmlRegisterSingletonType("org.kde.kwindowsystem.private", 1, 0, "KWindowSystem", [](QQmlEngine *, QJSEngine *) -> QObject * { - return KWindowSystem::self(); - }); -#endif - #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) qRegisterMetaTypeStreamOperators(); #endif @@ -291,12 +271,9 @@ int main(int argc, char *argv[]) Q_UNUSED(workingDirectory); QWindow *window = windowFromEngine(&engine); + KWindowSystem::updateStartupId(window); - if (!window->isVisible()) { - window->show(); - } - - raiseWindow(window); + WindowController::instance().showAndRaiseWindow(QString()); // Open matrix uri if (arguments.isEmpty()) { @@ -312,9 +289,8 @@ int main(int argc, char *argv[]) QWindow *window = windowFromEngine(&engine); - if (window->isVisible()) { - Controller::instance().restoreWindowGeometry(window); - } + WindowController::instance().setWindow(window); + WindowController::instance().restoreGeometry(); return app.exec(); } diff --git a/src/notificationsmanager.cpp b/src/notificationsmanager.cpp index db584ab83..a849a49f6 100644 --- a/src/notificationsmanager.cpp +++ b/src/notificationsmanager.cpp @@ -19,6 +19,7 @@ #include "controller.h" #include "neochatconfig.h" #include "roommanager.h" +#include "windowcontroller.h" NotificationsManager &NotificationsManager::instance() { @@ -57,11 +58,8 @@ void NotificationsManager::postNotification(NeoChatRoom *room, notification->setDefaultAction(i18n("Open NeoChat in this room")); connect(notification, &KNotification::defaultActivated, this, [=]() { -#if defined(HAVE_WINDOWSYSTEM) && KNOTIFICATIONS_VERSION >= QT_VERSION_CHECK(5, 90, 0) - KWindowSystem::setCurrentXdgActivationToken(notification->xdgActivationToken()); -#endif RoomManager::instance().enterRoom(room); - Q_EMIT Controller::instance().showWindow(); + WindowController::instance().showAndRaiseWindow(notification->xdgActivationToken()); }); if (canReply) { @@ -95,12 +93,9 @@ void NotificationsManager::postInviteNotification(NeoChatRoom *room, const QStri notification->setFlags(KNotification::Persistent); notification->setDefaultAction(i18n("Open this invitation in NeoChat")); connect(notification, &KNotification::defaultActivated, this, [=]() { -#if defined(HAVE_WINDOWSYSTEM) && KNOTIFICATIONS_VERSION >= QT_VERSION_CHECK(5, 90, 0) - KWindowSystem::setCurrentXdgActivationToken(notification->xdgActivationToken()); -#endif notification->close(); RoomManager::instance().enterRoom(room); - Q_EMIT Controller::instance().showWindow(); + WindowController::instance().showAndRaiseWindow(notification->xdgActivationToken()); }); notification->setActions({i18n("Accept Invitation"), i18n("Reject Invitation")}); connect(notification, &KNotification::action1Activated, this, [this, room, notification]() { diff --git a/src/runner.cpp b/src/runner.cpp index af69f8fa2..82ee3d540 100644 --- a/src/runner.cpp +++ b/src/runner.cpp @@ -8,6 +8,7 @@ #include "roomlistmodel.h" #include "roommanager.h" #include "runner.h" +#include "windowcontroller.h" RemoteImage Runner::serializeImage(const QImage &image) { @@ -90,5 +91,6 @@ void Runner::Run(const QString &id, const QString &actionId) } RoomManager::instance().enterRoom(room); - Q_EMIT Controller::instance().showWindow(); + + WindowController::instance().showAndRaiseWindow(QString()); } diff --git a/src/windowcontroller.cpp b/src/windowcontroller.cpp new file mode 100644 index 000000000..05d09d7d0 --- /dev/null +++ b/src/windowcontroller.cpp @@ -0,0 +1,55 @@ +// SPDX-FileCopyrightText: 2022 Nicolas Fella +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "windowcontroller.h" + +#include +#include + +#ifdef HAVE_WINDOWSYSTEM +#include +#endif + +#include + +WindowController &WindowController::instance() +{ + static WindowController instance; + return instance; +} + +void WindowController::setWindow(QWindow *window) +{ + m_window = window; +} + +void WindowController::restoreGeometry() +{ + KConfig dataResource("data", KConfig::SimpleConfig, QStandardPaths::AppDataLocation); + KConfigGroup windowGroup(&dataResource, "Window"); + KWindowConfig::restoreWindowSize(m_window, windowGroup); + KWindowConfig::restoreWindowPosition(m_window, windowGroup); +} + +void WindowController::saveGeometry() +{ + KConfig dataResource("data", KConfig::SimpleConfig, QStandardPaths::AppDataLocation); + KConfigGroup windowGroup(&dataResource, "Window"); + KWindowConfig::saveWindowPosition(m_window, windowGroup); + KWindowConfig::saveWindowSize(m_window, windowGroup); +} + +void WindowController::showAndRaiseWindow(const QString &xdgActivationToken) +{ + if (!m_window->isVisible()) { + m_window->show(); + } + +#ifdef HAVE_WINDOWSYSTEM + if (!xdgActivationToken.isEmpty()) { + KWindowSystem::setCurrentXdgActivationToken(xdgActivationToken); + } + + KWindowSystem::activateWindow(m_window); +#endif +} diff --git a/src/windowcontroller.h b/src/windowcontroller.h new file mode 100644 index 000000000..2e5dc23b3 --- /dev/null +++ b/src/windowcontroller.h @@ -0,0 +1,26 @@ +// SPDX-FileCopyrightText: 2022 Nicolas Fella +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include +#include + +class WindowController : public QObject +{ + Q_OBJECT + +public: + static WindowController &instance(); + + void setWindow(QWindow *window); + + void restoreGeometry(); + void saveGeometry(); + void showAndRaiseWindow(const QString &xdgActivationToken); + +private: + WindowController() = default; + + QWindow *m_window = nullptr; +};