Fix Windows tray show handling

This commit is contained in:
Курнат Андрей
2026-06-10 05:52:40 +03:00
parent d64957dfcd
commit 8f61d0ba8c
2 changed files with 58 additions and 13 deletions
+50 -11
View File
@@ -48,8 +48,11 @@
#endif
#include <QApplication>
#include <QCursor>
#include <QDesktopServices>
#include <QGuiApplication>
#include <QMenuBar>
#include <QScreen>
using namespace Qt::Literals::StringLiterals;
using namespace OCC;
@@ -97,6 +100,32 @@ void setUpInitialSyncFolder(AccountStatePtr accountStatePtr, bool useVfs)
Qt::SingleShotConnection);
accountStatePtr->account()->spacesManager()->checkReady();
}
void ensureWindowIntersectsAvailableScreen(QWidget *window)
{
if (!window) {
return;
}
const auto frame = window->frameGeometry();
for (const auto *screen : QGuiApplication::screens()) {
if (screen->availableGeometry().intersects(frame)) {
return;
}
}
auto *screen = QGuiApplication::screenAt(QCursor::pos());
if (!screen) {
screen = QGuiApplication::primaryScreen();
}
if (!screen) {
return;
}
const auto availableGeometry = screen->availableGeometry();
window->resize(window->size().boundedTo(availableGeometry.size()));
window->move(availableGeometry.center() - window->rect().center());
}
}
QString Application::displayLanguage() const
@@ -244,23 +273,33 @@ AccountStatePtr Application::addNewAccount(AccountPtr newAccount)
void Application::showSettings()
{
auto window = ocApp()->settingsDialog();
ensureWindowIntersectsAvailableScreen(window);
if (window->windowState().testFlag(Qt::WindowMinimized)) {
window->setWindowState(window->windowState() & ~Qt::WindowMinimized);
}
window->show();
ensureWindowIntersectsAvailableScreen(window);
window->raise();
window->activateWindow();
#if defined(Q_OS_WIN)
// Windows disallows raising a Window when you're not the active application.
// Use a common hack to attach to the active application
const auto activeProcessId = GetWindowThreadProcessId(GetForegroundWindow(), nullptr);
if (activeProcessId != qApp->applicationPid()) {
const auto threadId = GetCurrentThreadId();
// don't step here with a debugger...
if (AttachThreadInput(threadId, activeProcessId, true)) {
const auto hwnd = reinterpret_cast<HWND>(window->winId());
SetForegroundWindow(hwnd);
SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
AttachThreadInput(threadId, activeProcessId, false);
}
// Use a common hack to attach to the active application.
const auto foregroundWindow = GetForegroundWindow();
const auto foregroundThreadId = foregroundWindow ? GetWindowThreadProcessId(foregroundWindow, nullptr) : 0;
const auto currentThreadId = GetCurrentThreadId();
const auto attachedToForegroundThread =
foregroundThreadId != 0 && foregroundThreadId != currentThreadId && AttachThreadInput(currentThreadId, foregroundThreadId, true);
const auto hwnd = reinterpret_cast<HWND>(window->winId());
ShowWindow(hwnd, SW_RESTORE);
SetForegroundWindow(hwnd);
SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
if (attachedToForegroundThread) {
AttachThreadInput(currentThreadId, foregroundThreadId, false);
}
#endif
}