From 37dab85df7e196c5596dd42d7fe09b95284507bd Mon Sep 17 00:00:00 2001 From: Janek Bevendorff Date: Tue, 22 Dec 2020 01:03:39 +0100 Subject: [PATCH] Implement empty-area drag. Uses Qt 5.15's new QWindow::startSystemMove() to implement empty-area drag, which allows the user to click and drag any empty area on the menubar, toolbar, or tabbar to move the window around. --- src/gui/MainWindow.cpp | 49 ++++++++++++++++++++++++++++++++++++++++++ src/gui/MainWindow.h | 14 ++++++++++++ 2 files changed, 63 insertions(+) diff --git a/src/gui/MainWindow.cpp b/src/gui/MainWindow.cpp index 663f0a5e8..728322b63 100644 --- a/src/gui/MainWindow.cpp +++ b/src/gui/MainWindow.cpp @@ -503,6 +503,14 @@ MainWindow::MainWindow() connect(m_ui->actionOnlineHelp, SIGNAL(triggered()), SLOT(openOnlineHelp())); connect(m_ui->actionKeyboardShortcuts, SIGNAL(triggered()), SLOT(openKeyboardShortcuts())); +#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) + // Install event filter for empty-area drag + auto* eventFilter = new MainWindowEventFilter(this); + m_ui->menubar->installEventFilter(eventFilter); + m_ui->toolBar->installEventFilter(eventFilter); + m_ui->tabWidget->tabBar()->installEventFilter(eventFilter); +#endif + #ifdef Q_OS_MACOS setUnifiedTitleAndToolBarOnMac(true); #endif @@ -1798,3 +1806,44 @@ void MainWindow::initViewMenu() config()->set(Config::GUI_HidePasswords, checked); }); } + +#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) + +MainWindowEventFilter::MainWindowEventFilter(QObject* parent) + : QObject(parent) +{ +} + +/** + * MainWindow event filter to initiate empty-area drag on the toolbar, menubar, and tabbar. + */ +bool MainWindowEventFilter::eventFilter(QObject* watched, QEvent* event) +{ + auto* mainWindow = getMainWindow(); + if (!mainWindow || !mainWindow->m_ui) { + return QObject::eventFilter(watched, event); + } + + if (event->type() == QEvent::MouseButtonPress) { + if (watched == mainWindow->m_ui->menubar) { + mainWindow->windowHandle()->startSystemMove(); + // Continue processing events, so menus keep working. + return false; + } else if (watched == mainWindow->m_ui->toolBar) { + if (!mainWindow->m_ui->toolBar->isMovable() || mainWindow->m_ui->toolBar->cursor() != Qt::SizeAllCursor) { + mainWindow->windowHandle()->startSystemMove(); + return false; + } + } else if (watched == mainWindow->m_ui->tabWidget->tabBar()) { + auto* m = static_cast(event); + if (mainWindow->m_ui->tabWidget->tabBar()->tabAt(m->pos()) == -1) { + mainWindow->windowHandle()->startSystemMove(); + return true; + } + } + } + + return QObject::eventFilter(watched, event); +} + +#endif diff --git a/src/gui/MainWindow.h b/src/gui/MainWindow.h index 187b36d55..63163c8d2 100644 --- a/src/gui/MainWindow.h +++ b/src/gui/MainWindow.h @@ -35,6 +35,7 @@ namespace Ui class InactivityTimer; class SearchWidget; +class MainWindowEventFilter; class MainWindow : public QMainWindow { @@ -182,8 +183,21 @@ private: QTimer m_updateCheckTimer; QTimer m_trayIconTriggerTimer; QSystemTrayIcon::ActivationReason m_trayIconTriggerReason; + + friend class MainWindowEventFilter; }; +#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) +class MainWindowEventFilter : public QObject +{ + Q_OBJECT + +public: + explicit MainWindowEventFilter(QObject* parent); + bool eventFilter(QObject* watched, QEvent* event) override; +}; +#endif + /** * Return instance of MainWindow created on app load * non-gui instances will return nullptr