diff options
author | Hannah von Reth <hannah.vonreth@owncloud.com> | 2021-11-17 13:17:58 +0300 |
---|---|---|
committer | Hannah von Reth <hannah.vonreth@owncloud.com> | 2021-11-17 17:11:11 +0300 |
commit | 53c1ead1d53bfc8d6ae07c5c67053a1797e64f8e (patch) | |
tree | a4bc48567c1da0f269a9092890aa4e8c57a69fff | |
parent | cfb5ed05bebc186c009cdffd6f71c71f0a1cfb08 (diff) |
Create our own message loop to receive WM_ENDSESSION
This ensures we receive the message even if no window is shown
(cherry picked from commit 36311b00be41b1edbe46791f1c44d11f8584c4f8)
-rw-r--r-- | changelog/unreleased/8979 | 5 | ||||
-rw-r--r-- | src/gui/guiutility.cpp | 52 | ||||
-rw-r--r-- | src/gui/settingsdialog.cpp | 17 | ||||
-rw-r--r-- | src/gui/settingsdialog.h | 4 |
4 files changed, 55 insertions, 23 deletions
diff --git a/changelog/unreleased/8979 b/changelog/unreleased/8979 index 8846fe3e6..6dba41338 100644 --- a/changelog/unreleased/8979 +++ b/changelog/unreleased/8979 @@ -1,6 +1,7 @@ Bugfix: Properly handle Windows log off -We worked around a Qt bug which prevented the client from properly shutdown -on Windows logout or during the client update. +We now ensure that we receive the window messages dispatched by the system. https://github.com/owncloud/client/issues/8979 +https://github.com/owncloud/client/pull/9142 +https://github.com/owncloud/client/pull/9220 diff --git a/src/gui/guiutility.cpp b/src/gui/guiutility.cpp index ead4a78ad..b8fbaac92 100644 --- a/src/gui/guiutility.cpp +++ b/src/gui/guiutility.cpp @@ -22,6 +22,11 @@ #include <QUrlQuery> #include <QIcon> +#ifdef Q_OS_WIN +#include <QThread> +#include <QTimer> +#endif + #include "theme.h" #include "common/asserts.h" @@ -30,6 +35,53 @@ using namespace OCC; Q_LOGGING_CATEGORY(lcUtility, "gui.utility", QtInfoMsg) +namespace { + +#ifdef Q_OS_WIN +void watchWM() +{ + // Qt only receives window message if a window was displayed at least once + // create an invisible window to handle WM_ENDSESSION + QThread::create([] { + WNDCLASS wc = {}; + wc.hInstance = GetModuleHandle(nullptr); + wc.lpszClassName = L"ocWindowMessageWatcher"; + wc.lpfnWndProc = [](HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) -> LRESULT { + // qDebug() << MSG { hwnd, msg, wParam, lParam, 0, {} }; + if (msg == WM_QUERYENDSESSION) { + return 1; + } else if (msg == WM_ENDSESSION) { + qCInfo(OCC::lcUtility) << "Received WM_ENDSESSION quitting"; + QTimer::singleShot(0, qApp, &QApplication::quit); + return 0; + } + return DefWindowProc(hwnd, msg, wParam, lParam); + }; + + OC_ASSERT(RegisterClass(&wc)); + + auto window = CreateWindowW(wc.lpszClassName, L"watcher", WS_OVERLAPPED, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, nullptr, nullptr, wc.hInstance, nullptr); + OC_ASSERT_X(window, Utility::formatWinError(GetLastError()).toUtf8().constData()); + + bool run = true; + QObject::connect(qApp, &QApplication::aboutToQuit, [&run] { + run = false; + }); + MSG msg; + while (run) { + if (!PeekMessageW(&msg, window, 0, 0, PM_REMOVE)) { + QThread::msleep(100); + } else { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + })->start(); +} +Q_COREAPP_STARTUP_FUNCTION(watchWM); +#endif +} + bool Utility::openBrowser(const QUrl &url, QWidget *errorWidgetParent) { if (!QDesktopServices::openUrl(url)) { diff --git a/src/gui/settingsdialog.cpp b/src/gui/settingsdialog.cpp index 1b72e2c18..01ebffc9b 100644 --- a/src/gui/settingsdialog.cpp +++ b/src/gui/settingsdialog.cpp @@ -326,23 +326,6 @@ void SettingsDialog::setVisible(bool visible) QMainWindow::setVisible(visible); } -#if defined(Q_OS_WIN) && QT_VERSION < QT_VERSION_CHECK(6, 0, 0) - -bool SettingsDialog::nativeEvent(const QByteArray &eventType, void *message, long *result) -{ - auto msg = reinterpret_cast<MSG *>(message); - // https://github.com/owncloud/client/issues/8979 - // Qt5 has a bug that Windows already get closed on WM_QUERYENDSESSION - // so they never receive WM_ENDSESSION - // Capture the event and go down in style - if (msg->message == WM_QUERYENDSESSION || msg->message == WM_ENDSESSION) { - qCInfo(lcApplication) << "Shutting down" << *msg; - QTimer::singleShot(0, ocApp(), Application::quit); - } - return false; -} -#endif - void SettingsDialog::slotSwitchPage(QAction *action) { _ui->stack->setCurrentWidget(_actionGroupWidgets.value(action)); diff --git a/src/gui/settingsdialog.h b/src/gui/settingsdialog.h index f84734fdd..c96e559e0 100644 --- a/src/gui/settingsdialog.h +++ b/src/gui/settingsdialog.h @@ -71,10 +71,6 @@ protected: void changeEvent(QEvent *) override; void setVisible(bool visible) override; -#if defined(Q_OS_WIN) && QT_VERSION < QT_VERSION_CHECK(6, 0, 0) - bool nativeEvent(const QByteArray &eventType, void *message, long *result) override; -#endif - private slots: void accountAdded(AccountState *); void accountRemoved(AccountState *); |