From 5fc425fc6459fb3d644bb88d0e413fac339d4051 Mon Sep 17 00:00:00 2001 From: Yuhang Zhao <2546789017@qq.com> Date: Wed, 14 Oct 2020 18:36:13 +0800 Subject: [PATCH] Update. Signed-off-by: Yuhang Zhao <2546789017@qq.com> --- CMakeLists.txt | 9 +- examples/QMainWindow/main.cpp | 40 +-- examples/QWidget/main.cpp | 35 +-- examples/common.pri | 7 +- framelesshelper.cpp | 87 ++----- framelesshelper.h | 20 +- framelessquickhelper.cpp | 449 +++------------------------------ framelessquickhelper.h | 19 +- framelesswindowsmanager.cpp | 454 ++++++++++++++++++++++++++++++++++ framelesswindowsmanager.h | 86 +++++++ resources/qml/main.qml | 2 +- 11 files changed, 627 insertions(+), 581 deletions(-) create mode 100644 framelesswindowsmanager.cpp create mode 100644 framelesswindowsmanager.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 3a6def1..dc21862 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,8 +23,8 @@ find_package(Qt5 COMPONENTS Widgets Quick) set(SOURCES framelesshelper_global.h - framelesshelper.h - framelesshelper.cpp + framelesswindowsmanager.h + framelesswindowsmanager.cpp ) if(Qt5Quick_FOUND) @@ -39,6 +39,11 @@ if(WIN32) winnativeeventfilter.h winnativeeventfilter.cpp ) +else() + list(APPEND SOURCES + framelesshelper.h + framelesshelper.cpp + ) endif() if(WIN32 AND BUILD_SHARED_LIBS) diff --git a/examples/QMainWindow/main.cpp b/examples/QMainWindow/main.cpp index 6748eff..1616741 100644 --- a/examples/QMainWindow/main.cpp +++ b/examples/QMainWindow/main.cpp @@ -22,16 +22,12 @@ * SOFTWARE. */ +#include "../../framelesswindowsmanager.h" #include "ui_MainWindow.h" #include "ui_TitleBar.h" #include #include #include -#ifdef Q_OS_WINDOWS -#include "../../winnativeeventfilter.h" -#else -#include "../../framelesshelper.h" -#endif int main(int argc, char *argv[]) { @@ -59,10 +55,6 @@ int main(int argc, char *argv[]) QApplication application(argc, argv); -#ifndef Q_OS_WINDOWS - FramelessHelper helper; -#endif - QMainWindow *mainWindow = new QMainWindow; Ui::MainWindow appMainWindow; appMainWindow.setupUi(mainWindow); @@ -111,30 +103,16 @@ int main(int argc, char *argv[]) mainWindow->setWindowIcon(icon); mainWindow->setWindowTitle(QObject::tr("Hello, World!")); -#ifdef Q_OS_WINDOWS - WinNativeEventFilter::addFramelessWindow(mainWindow); - const auto data = WinNativeEventFilter::windowData(mainWindow); - if (data) { - data->ignoreObjects << titleBarWidget.iconButton << titleBarWidget.minimizeButton - << titleBarWidget.maximizeButton << titleBarWidget.closeButton - << appMainWindow.menubar; - } -#else - helper.setIgnoreObjects(mainWindow, - {titleBarWidget.iconButton, - titleBarWidget.minimizeButton, - titleBarWidget.maximizeButton, - titleBarWidget.closeButton, - appMainWindow.menubar}); - helper.removeWindowFrame(mainWindow); -#endif + FramelessWindowsManager::addWindow(mainWindow); + + FramelessWindowsManager::addIgnoreObject(mainWindow, titleBarWidget.minimizeButton); + FramelessWindowsManager::addIgnoreObject(mainWindow, titleBarWidget.maximizeButton); + FramelessWindowsManager::addIgnoreObject(mainWindow, titleBarWidget.closeButton); + FramelessWindowsManager::addIgnoreObject(mainWindow, appMainWindow.menubar); mainWindow->resize(800, 600); -#ifdef Q_OS_WINDOWS - WinNativeEventFilter::moveWindowToDesktopCenter(mainWindow); -#else - FramelessHelper::moveWindowToDesktopCenter(mainWindow); -#endif + + FramelessWindowsManager::moveWindowToDesktopCenter(mainWindow); mainWindow->show(); diff --git a/examples/QWidget/main.cpp b/examples/QWidget/main.cpp index 7cff2e1..3e97920 100644 --- a/examples/QWidget/main.cpp +++ b/examples/QWidget/main.cpp @@ -22,17 +22,13 @@ * SOFTWARE. */ +#include "../../framelesswindowsmanager.h" #include #include #include #include #include #include -#ifdef Q_OS_WINDOWS -#include "../../winnativeeventfilter.h" -#else -#include "../../framelesshelper.h" -#endif int main(int argc, char *argv[]) { @@ -60,10 +56,6 @@ int main(int argc, char *argv[]) QApplication application(argc, argv); -#ifndef Q_OS_WINDOWS - FramelessHelper helper; -#endif - QWidget widget; widget.setContentsMargins(2, 2, 2, 2); QLabel *label = new QLabel; @@ -101,22 +93,17 @@ int main(int argc, char *argv[]) mainLayout->addStretch(); widget.setLayout(mainLayout); widget.setWindowTitle(QObject::tr("Hello, World!")); -#ifdef Q_OS_WINDOWS - WinNativeEventFilter::addFramelessWindow(&widget); - const auto data = WinNativeEventFilter::windowData(&widget); - if (data) { - data->ignoreObjects << minimizeButton << maximizeButton << closeButton; - } -#else - helper.setIgnoreObjects(&widget, {minimizeButton, maximizeButton, closeButton}); - helper.removeWindowFrame(&widget); -#endif + + FramelessWindowsManager::addWindow(&widget); + + FramelessWindowsManager::addIgnoreObject(&widget, minimizeButton); + FramelessWindowsManager::addIgnoreObject(&widget, maximizeButton); + FramelessWindowsManager::addIgnoreObject(&widget, closeButton); + widget.resize(800, 600); -#ifdef Q_OS_WINDOWS - WinNativeEventFilter::moveWindowToDesktopCenter(&widget); -#else - FramelessHelper::moveWindowToDesktopCenter(&widget); -#endif + + FramelessWindowsManager::moveWindowToDesktopCenter(&widget); + widget.show(); return QApplication::exec(); diff --git a/examples/common.pri b/examples/common.pri index 046de70..22af8d2 100644 --- a/examples/common.pri +++ b/examples/common.pri @@ -6,8 +6,8 @@ DEFINES += \ FRAMELESSHELPER_STATIC HEADERS += \ $$PWD/../framelesshelper_global.h \ - $$PWD/../framelesshelper.h -SOURCES += $$PWD/../framelesshelper.cpp + $$PWD/../framelesswindowsmanager.h +SOURCES += $$PWD/../framelesswindowsmanager.cpp win32 { DEFINES += WIN32_LEAN_AND_MEAN _CRT_SECURE_NO_WARNINGS CONFIG += windeployqt @@ -21,4 +21,7 @@ win32 { RESOURCES += $$PWD/windows.qrc RC_FILE = $$PWD/windows.rc OTHER_FILES += $$PWD/windows.manifest +} else { + HEADERS += $$PWD/../framelesshelper.h + SOURCES += $$PWD/../framelesshelper.cpp } diff --git a/framelesshelper.cpp b/framelesshelper.cpp index 12465bf..fcfad39 100644 --- a/framelesshelper.cpp +++ b/framelesshelper.cpp @@ -69,8 +69,7 @@ QWindow *getWindowHandle(QObject *val) } #endif else { - qWarning().noquote() << "Can't acquire the window handle: only " - "top level QWidget and QWindow are accepted."; + qFatal("Can't acquire the window handle: only top level QWidget and QWindow are accepted."); } return nullptr; } @@ -139,7 +138,7 @@ void FramelessHelper::moveWindowToDesktopCenter(QObject *obj) } #endif else { - qWarning().noquote() << "The given QObject is not a top level window."; + qFatal("The given QObject is not a top level QWidget or QWindow."); } } @@ -179,12 +178,6 @@ QList FramelessHelper::getIgnoreAreas(QObject *obj) const return m_ignoreAreas.value(obj); } -void FramelessHelper::setIgnoreAreas(QObject *obj, const QList &val) -{ - Q_ASSERT(obj); - m_ignoreAreas[obj] = val; -} - void FramelessHelper::addIgnoreArea(QObject *obj, const QRect &val) { Q_ASSERT(obj); @@ -193,24 +186,12 @@ void FramelessHelper::addIgnoreArea(QObject *obj, const QRect &val) m_ignoreAreas[obj] = areas; } -void FramelessHelper::clearIgnoreAreas(QObject *obj) -{ - Q_ASSERT(obj); - m_ignoreAreas[obj] = {}; -} - QList FramelessHelper::getDraggableAreas(QObject *obj) const { Q_ASSERT(obj); return m_draggableAreas.value(obj); } -void FramelessHelper::setDraggableAreas(QObject *obj, const QList &val) -{ - Q_ASSERT(obj); - m_draggableAreas[obj] = val; -} - void FramelessHelper::addDraggableArea(QObject *obj, const QRect &val) { Q_ASSERT(obj); @@ -219,12 +200,6 @@ void FramelessHelper::addDraggableArea(QObject *obj, const QRect &val) m_draggableAreas[obj] = areas; } -void FramelessHelper::clearDraggableAreas(QObject *obj) -{ - Q_ASSERT(obj); - m_draggableAreas[obj] = {}; -} - QList FramelessHelper::getIgnoreObjects(QObject *obj) const { Q_ASSERT(obj); @@ -240,18 +215,6 @@ QList FramelessHelper::getIgnoreObjects(QObject *obj) const return ret; } -void FramelessHelper::setIgnoreObjects(QObject *obj, const QList &val) -{ - Q_ASSERT(obj); - QList> objs{}; - if (!val.isEmpty()) { - for (auto &&_obj : qAsConst(val)) { - objs.append(_obj); - } - } - m_ignoreObjects[obj] = objs; -} - void FramelessHelper::addIgnoreObject(QObject *obj, QObject *val) { Q_ASSERT(obj); @@ -260,12 +223,6 @@ void FramelessHelper::addIgnoreObject(QObject *obj, QObject *val) m_ignoreObjects[obj] = objs; } -void FramelessHelper::clearIgnoreObjects(QObject *obj) -{ - Q_ASSERT(obj); - m_ignoreObjects[obj] = {}; -} - QList FramelessHelper::getDraggableObjects(QObject *obj) const { Q_ASSERT(obj); @@ -281,18 +238,6 @@ QList FramelessHelper::getDraggableObjects(QObject *obj) const return ret; } -void FramelessHelper::setDraggableObjects(QObject *obj, const QList &val) -{ - Q_ASSERT(obj); - QList> objs{}; - if (!val.isEmpty()) { - for (auto &&_obj : qAsConst(val)) { - objs.append(_obj); - } - } - m_draggableObjects[obj] = objs; -} - void FramelessHelper::addDraggableObject(QObject *obj, QObject *val) { Q_ASSERT(obj); @@ -301,12 +246,6 @@ void FramelessHelper::addDraggableObject(QObject *obj, QObject *val) m_draggableObjects[obj] = objs; } -void FramelessHelper::clearDraggableObjects(QObject *obj) -{ - Q_ASSERT(obj); - m_draggableObjects[obj] = {}; -} - bool FramelessHelper::getResizable(QObject *obj) const { Q_ASSERT(obj); @@ -331,19 +270,21 @@ void FramelessHelper::setTitleBarEnabled(QObject *obj, const bool val) m_disableTitleBar[obj] = !val; } -void FramelessHelper::removeWindowFrame(QObject *obj) +void FramelessHelper::removeWindowFrame(QObject *obj, const bool center) { Q_ASSERT(obj); // Don't miss the Qt::Window flag. const Qt::WindowFlags flags = Qt::Window | Qt::FramelessWindowHint; - const auto window = qobject_cast(obj); - if (window) { - window->setFlags(flags); - // MouseTracking is always enabled for QWindow. - window->installEventFilter(this); + if (obj->isWindowType()) { + const auto window = qobject_cast(obj); + if (window) { + window->setFlags(flags); + // MouseTracking is always enabled for QWindow. + window->installEventFilter(this); + } } #ifdef QT_WIDGETS_LIB - else { + else if (obj->isWidgetType()) { const auto widget = qobject_cast(obj); if (widget && widget->isTopLevel()) { widget->setWindowFlags(flags); @@ -355,6 +296,12 @@ void FramelessHelper::removeWindowFrame(QObject *obj) } } #endif + else { + qFatal("The given QObject is not a top level QWidget or QWindow."); + } + if (center) { + moveWindowToDesktopCenter(obj); + } } bool FramelessHelper::eventFilter(QObject *object, QEvent *event) diff --git a/framelesshelper.h b/framelesshelper.h index e8787a7..7dd6c45 100644 --- a/framelesshelper.h +++ b/framelesshelper.h @@ -45,6 +45,8 @@ public: explicit FramelessHelper(QObject *parent = nullptr); ~FramelessHelper() override = default; + void removeWindowFrame(QObject *obj, const bool center = false); + static void updateQtFrame(QWindow *window, const int titleBarHeight); static void moveWindowToDesktopCenter(QObject *obj); @@ -57,25 +59,17 @@ public: int getTitleBarHeight() const; void setTitleBarHeight(const int val); - QList getIgnoreAreas(QObject *obj) const; - void setIgnoreAreas(QObject *obj, const QList &val); void addIgnoreArea(QObject *obj, const QRect &val); - void clearIgnoreAreas(QObject *obj); + QList getIgnoreAreas(QObject *obj) const; - QList getDraggableAreas(QObject *obj) const; - void setDraggableAreas(QObject *obj, const QList &val); void addDraggableArea(QObject *obj, const QRect &val); - void clearDraggableAreas(QObject *obj); + QList getDraggableAreas(QObject *obj) const; - QList getIgnoreObjects(QObject *obj) const; - void setIgnoreObjects(QObject *obj, const QList &val); void addIgnoreObject(QObject *obj, QObject *val); - void clearIgnoreObjects(QObject *obj); + QList getIgnoreObjects(QObject *obj) const; - QList getDraggableObjects(QObject *obj) const; - void setDraggableObjects(QObject *obj, const QList &val); void addDraggableObject(QObject *obj, QObject *val); - void clearDraggableObjects(QObject *obj); + QList getDraggableObjects(QObject *obj) const; bool getResizable(QObject *obj) const; void setResizable(QObject *obj, const bool val); @@ -83,8 +77,6 @@ public: bool getTitleBarEnabled(QObject *obj) const; void setTitleBarEnabled(QObject *obj, const bool val); - void removeWindowFrame(QObject *obj); - protected: bool eventFilter(QObject *object, QEvent *event) override; diff --git a/framelessquickhelper.cpp b/framelessquickhelper.cpp index b2987af..160dc23 100644 --- a/framelessquickhelper.cpp +++ b/framelessquickhelper.cpp @@ -24,524 +24,131 @@ #include "framelessquickhelper.h" +#include "framelesswindowsmanager.h" #include -#include -#ifdef Q_OS_WINDOWS -#include "winnativeeventfilter.h" -#else -#include "framelesshelper.h" -#endif - -namespace { -#ifdef Q_OS_WINDOWS -const int m_defaultBorderWidth = 8, m_defaultBorderHeight = 8, m_defaultTitleBarHeight = 30; -#else -FramelessHelper m_framelessHelper; -#endif -} // namespace FramelessQuickHelper::FramelessQuickHelper(QQuickItem *parent) : QQuickItem(parent) {} int FramelessQuickHelper::borderWidth() const { -#ifdef Q_OS_WINDOWS - const auto win = window(); - if (win) { - return WinNativeEventFilter::getSystemMetric(win, - WinNativeEventFilter::SystemMetric::BorderWidth); - } - return m_defaultBorderWidth; -#else - return m_framelessHelper.getBorderWidth(); -#endif + return FramelessWindowsManager::getBorderWidth(window()); } void FramelessQuickHelper::setBorderWidth(const int val) { -#ifdef Q_OS_WINDOWS - const auto win = window(); - if (win) { - const auto data = WinNativeEventFilter::windowData(win); - if (data) { - data->borderWidth = val; - Q_EMIT borderWidthChanged(val); - } - } -#else - m_framelessHelper.setBorderWidth(val); + FramelessWindowsManager::setBorderWidth(window(), val); Q_EMIT borderWidthChanged(val); -#endif } int FramelessQuickHelper::borderHeight() const { -#ifdef Q_OS_WINDOWS - const auto win = window(); - if (win) { - return WinNativeEventFilter::getSystemMetric( - win, WinNativeEventFilter::SystemMetric::BorderHeight); - } - return m_defaultBorderHeight; -#else - return m_framelessHelper.getBorderHeight(); -#endif + return FramelessWindowsManager::getBorderHeight(window()); } void FramelessQuickHelper::setBorderHeight(const int val) { -#ifdef Q_OS_WINDOWS - const auto win = window(); - if (win) { - const auto data = WinNativeEventFilter::windowData(win); - if (data) { - data->borderHeight = val; - Q_EMIT borderHeightChanged(val); - } - } -#else - m_framelessHelper.setBorderHeight(val); + FramelessWindowsManager::setBorderHeight(window(), val); Q_EMIT borderHeightChanged(val); -#endif } int FramelessQuickHelper::titleBarHeight() const { -#ifdef Q_OS_WINDOWS - const auto win = window(); - if (win) { - return WinNativeEventFilter::getSystemMetric( - win, WinNativeEventFilter::SystemMetric::TitleBarHeight); - } - return m_defaultTitleBarHeight; -#else - return m_framelessHelper.getTitleBarHeight(); -#endif + return FramelessWindowsManager::getTitleBarHeight(window()); } void FramelessQuickHelper::setTitleBarHeight(const int val) { -#ifdef Q_OS_WINDOWS - const auto win = window(); - if (win) { - const auto data = WinNativeEventFilter::windowData(win); - if (data) { - data->titleBarHeight = val; - Q_EMIT titleBarHeightChanged(val); - } - } -#else - m_framelessHelper.setTitleBarHeight(val); + FramelessWindowsManager::setTitleBarHeight(window(), val); Q_EMIT titleBarHeightChanged(val); -#endif } bool FramelessQuickHelper::resizable() const { - const auto win = window(); - if (win) { -#ifdef Q_OS_WINDOWS - const auto data = WinNativeEventFilter::windowData(win); - if (data) { - return !data->fixedSize; - } -#else - return m_framelessHelper.getResizable(win); -#endif - } - return true; + return FramelessWindowsManager::getResizable(window()); } void FramelessQuickHelper::setResizable(const bool val) { - const auto win = window(); - if (win) { -#ifdef Q_OS_WINDOWS - const auto data = WinNativeEventFilter::windowData(win); - if (data) { - data->fixedSize = !val; - Q_EMIT resizableChanged(val); - } -#else - m_framelessHelper.setResizable(win, val); - Q_EMIT resizableChanged(val); -#endif - } + FramelessWindowsManager::setResizable(window(), val); + Q_EMIT resizableChanged(val); } bool FramelessQuickHelper::titleBarEnabled() const { - const auto win = window(); - if (win) { -#ifdef Q_OS_WINDOWS - const auto data = WinNativeEventFilter::windowData(win); - if (data) { - return !data->disableTitleBar; - } -#else - return m_framelessHelper.getTitleBarEnabled(win); -#endif - } - return true; + return FramelessWindowsManager::getTitleBarEnabled(window()); } void FramelessQuickHelper::setTitleBarEnabled(const bool val) { - const auto win = window(); - if (win) { -#ifdef Q_OS_WINDOWS - const auto data = WinNativeEventFilter::windowData(win); - if (data) { - data->disableTitleBar = !val; - Q_EMIT titleBarEnabledChanged(val); - } -#else - m_framelessHelper.setTitleBarEnabled(win, val); - Q_EMIT titleBarEnabledChanged(val); -#endif - } + FramelessWindowsManager::setTitleBarEnabled(window(), val); + Q_EMIT titleBarEnabledChanged(val); } QSize FramelessQuickHelper::minimumSize() const { - const auto win = window(); - if (win) { -#ifdef Q_OS_WINDOWS - const auto data = WinNativeEventFilter::windowData(win); - if (data) { - return data->minimumSize; - } -#else - return win->minimumSize(); -#endif - } - return {}; + return FramelessWindowsManager::getMinimumSize(window()); } void FramelessQuickHelper::setMinimumSize(const QSize &val) { - const auto win = window(); - if (win) { -#ifdef Q_OS_WINDOWS - const auto data = WinNativeEventFilter::windowData(win); - if (data) { - data->minimumSize = val; - Q_EMIT minimumSizeChanged(val); - } -#else - win->setMinimumSize(val); - Q_EMIT minimumSizeChanged(val); -#endif - } + FramelessWindowsManager::setMinimumSize(window(), val); + Q_EMIT minimumSizeChanged(val); } QSize FramelessQuickHelper::maximumSize() const { - const auto win = window(); - if (win) { -#ifdef Q_OS_WINDOWS - const auto data = WinNativeEventFilter::windowData(win); - if (data) { - return data->maximumSize; - } -#else - return win->maximumSize(); -#endif - } - return {}; + return FramelessWindowsManager::getMaximumSize(window()); } void FramelessQuickHelper::setMaximumSize(const QSize &val) { - const auto win = window(); - if (win) { -#ifdef Q_OS_WINDOWS - const auto data = WinNativeEventFilter::windowData(win); - if (data) { - data->maximumSize = val; - Q_EMIT maximumSizeChanged(val); - } -#else - win->setMaximumSize(val); - Q_EMIT maximumSizeChanged(val); -#endif - } + FramelessWindowsManager::setMaximumSize(window(), val); + Q_EMIT maximumSizeChanged(val); } void FramelessQuickHelper::removeWindowFrame(const bool center) { - const auto win = window(); - if (win) { -#ifdef Q_OS_WINDOWS - WinNativeEventFilter::addFramelessWindow(win); -#else - m_framelessHelper.removeWindowFrame(win); -#endif - } - if (center) { - moveWindowToDesktopCenter(); - } + FramelessWindowsManager::addWindow(window(), center); } QSize FramelessQuickHelper::desktopSize() const { - const auto win = window(); - if (win) { - const auto screen = win->screen(); - if (screen) { - return screen->size(); - } - } - return {}; + return FramelessWindowsManager::getDesktopSize(window()); } QRect FramelessQuickHelper::desktopAvailableGeometry() const { - const auto win = window(); - if (win) { - const auto screen = win->screen(); - if (screen) { - return screen->availableGeometry(); - } - } - return {}; + return FramelessWindowsManager::getDesktopAvailableGeometry(window()); } QSize FramelessQuickHelper::desktopAvailableSize() const { - const auto win = window(); - if (win) { - const auto screen = win->screen(); - if (screen) { - return screen->availableSize(); - } - } - return {}; + return FramelessWindowsManager::getDesktopAvailableSize(window()); } void FramelessQuickHelper::moveWindowToDesktopCenter(const bool realCenter) { - const auto win = window(); - if (win) { - if (realCenter) { -#ifdef Q_OS_WINDOWS - WinNativeEventFilter::moveWindowToDesktopCenter(win); -#else - FramelessHelper::moveWindowToDesktopCenter(win); -#endif - } else { - const QSize windowSize = win->size(); - const QSize screenSize = desktopAvailableSize(); - const int newX = qRound(static_cast(screenSize.width() - windowSize.width()) - / 2.0); - const int newY = qRound(static_cast(screenSize.height() - windowSize.height()) - / 2.0); - const QRect screenGeometry = desktopAvailableGeometry(); - win->setX(newX + screenGeometry.x()); - win->setY(newY + screenGeometry.y()); - } - } -} - -void FramelessQuickHelper::setIgnoreAreas(const QList &val) -{ - const auto win = window(); - if (win) { -#ifdef Q_OS_WINDOWS - const auto data = WinNativeEventFilter::windowData(win); - if (data) { - data->ignoreAreas = val; - } -#else - m_framelessHelper.setIgnoreAreas(win, val); -#endif - } -} - -void FramelessQuickHelper::clearIgnoreAreas() -{ - const auto win = window(); - if (win) { -#ifdef Q_OS_WINDOWS - const auto data = WinNativeEventFilter::windowData(win); - if (data) { - data->ignoreAreas.clear(); - } -#else - m_framelessHelper.clearIgnoreAreas(win); -#endif - } + FramelessWindowsManager::moveWindowToDesktopCenter(window(), realCenter); } void FramelessQuickHelper::addIgnoreArea(const QRect &val) { - const auto win = window(); - if (win) { -#ifdef Q_OS_WINDOWS - const auto data = WinNativeEventFilter::windowData(win); - if (data) { - data->ignoreAreas.append(val); - } -#else - m_framelessHelper.addIgnoreArea(win, val); -#endif - } -} - -void FramelessQuickHelper::setDraggableAreas(const QList &val) -{ - const auto win = window(); - if (win) { -#ifdef Q_OS_WINDOWS - const auto data = WinNativeEventFilter::windowData(win); - if (data) { - data->draggableAreas = val; - } -#else - m_framelessHelper.setDraggableAreas(win, val); -#endif - } -} - -void FramelessQuickHelper::clearDraggableAreas() -{ - const auto win = window(); - if (win) { -#ifdef Q_OS_WINDOWS - const auto data = WinNativeEventFilter::windowData(win); - if (data) { - data->draggableAreas.clear(); - } -#else - m_framelessHelper.clearDraggableAreas(win); -#endif - } + FramelessWindowsManager::addIgnoreArea(window(), val); } void FramelessQuickHelper::addDraggableArea(const QRect &val) { - const auto win = window(); - if (win) { -#ifdef Q_OS_WINDOWS - const auto data = WinNativeEventFilter::windowData(win); - if (data) { - data->draggableAreas.append(val); - } -#else - m_framelessHelper.addDraggableArea(win, val); -#endif - } -} - -void FramelessQuickHelper::setIgnoreObjects(const QList &val) -{ - const auto win = window(); - if (win) { -#ifdef Q_OS_WINDOWS - const auto data = WinNativeEventFilter::windowData(win); - if (data) { - data->ignoreObjects.clear(); - if (!val.isEmpty()) { - for (auto &&obj : qAsConst(val)) { - data->ignoreObjects.append(obj); - } - } - } -#else - QList objs{}; - if (!val.isEmpty()) { - for (auto &&obj : qAsConst(val)) { - objs.append(obj); - } - m_framelessHelper.setIgnoreObjects(win, objs); - } -#endif - } -} - -void FramelessQuickHelper::clearIgnoreObjects() -{ - const auto win = window(); - if (win) { -#ifdef Q_OS_WINDOWS - const auto data = WinNativeEventFilter::windowData(win); - if (data) { - data->ignoreObjects.clear(); - } -#else - m_framelessHelper.clearIgnoreObjects(win); -#endif - } + FramelessWindowsManager::addDraggableArea(window(), val); } void FramelessQuickHelper::addIgnoreObject(QQuickItem *val) { Q_ASSERT(val); - const auto win = window(); - if (win) { -#ifdef Q_OS_WINDOWS - const auto data = WinNativeEventFilter::windowData(win); - if (data) { - data->ignoreObjects.append(val); - } -#else - m_framelessHelper.addIgnoreObject(win, val); -#endif - } -} - -void FramelessQuickHelper::setDraggableObjects(const QList &val) -{ - const auto win = window(); - if (win) { -#ifdef Q_OS_WINDOWS - const auto data = WinNativeEventFilter::windowData(win); - if (data) { - data->draggableObjects.clear(); - if (!val.isEmpty()) { - for (auto &&obj : qAsConst(val)) { - data->draggableObjects.append(obj); - } - } - } -#else - QList objs{}; - if (!val.isEmpty()) { - for (auto &&obj : qAsConst(val)) { - objs.append(obj); - } - m_framelessHelper.setDraggableObjects(win, objs); - } -#endif - } -} - -void FramelessQuickHelper::clearDraggableObjects() -{ - const auto win = window(); - if (win) { -#ifdef Q_OS_WINDOWS - const auto data = WinNativeEventFilter::windowData(win); - if (data) { - data->draggableObjects.clear(); - } -#else - m_framelessHelper.clearDraggableObjects(win); -#endif - } + FramelessWindowsManager::addIgnoreObject(window(), val); } void FramelessQuickHelper::addDraggableObject(QQuickItem *val) { Q_ASSERT(val); - const auto win = window(); - if (win) { -#ifdef Q_OS_WINDOWS - const auto data = WinNativeEventFilter::windowData(win); - if (data) { - data->draggableObjects.append(val); - } -#else - m_framelessHelper.addDraggableObject(win, val); -#endif - } + FramelessWindowsManager::addDraggableObject(window(), val); } diff --git a/framelessquickhelper.h b/framelessquickhelper.h index bffac5b..ff8cc37 100644 --- a/framelessquickhelper.h +++ b/framelessquickhelper.h @@ -27,11 +27,6 @@ #include "framelesshelper_global.h" #include -#if (defined(Q_OS_WIN) || defined(Q_OS_WIN32) || defined(Q_OS_WIN64) || defined(Q_OS_WINRT)) \ - && !defined(Q_OS_WINDOWS) -#define Q_OS_WINDOWS -#endif - #if (QT_VERSION < QT_VERSION_CHECK(5, 13, 0)) #define Q_DISABLE_MOVE(Class) \ Class(Class &&) = delete; \ @@ -85,26 +80,18 @@ public: void setTitleBarEnabled(const bool val); public Q_SLOTS: - void removeWindowFrame(const bool center = true); + void removeWindowFrame(const bool center = false); + void moveWindowToDesktopCenter(const bool realCenter = true); + QSize desktopSize() const; QRect desktopAvailableGeometry() const; QSize desktopAvailableSize() const; - void setIgnoreAreas(const QList &val); - void clearIgnoreAreas(); void addIgnoreArea(const QRect &val); - - void setDraggableAreas(const QList &val); - void clearDraggableAreas(); void addDraggableArea(const QRect &val); - void setIgnoreObjects(const QList &val); - void clearIgnoreObjects(); void addIgnoreObject(QQuickItem *val); - - void setDraggableObjects(const QList &val); - void clearDraggableObjects(); void addDraggableObject(QQuickItem *val); Q_SIGNALS: diff --git a/framelesswindowsmanager.cpp b/framelesswindowsmanager.cpp new file mode 100644 index 0000000..76fbf90 --- /dev/null +++ b/framelesswindowsmanager.cpp @@ -0,0 +1,454 @@ +/* + * MIT License + * + * Copyright (C) 2020 by wangwenx190 (Yuhang Zhao) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "framelesswindowsmanager.h" + +#include +#include +#include +#ifdef QT_WIDGETS_LIB +#include +#endif + +#if (defined(Q_OS_WIN) || defined(Q_OS_WIN32) || defined(Q_OS_WIN64) || defined(Q_OS_WINRT)) \ + && !defined(Q_OS_WINDOWS) +#define Q_OS_WINDOWS +#endif + +#ifdef Q_OS_WINDOWS +#include "winnativeeventfilter.h" +#else +#include "framelesshelper.h" +#endif + +namespace { + +#ifndef Q_OS_WINDOWS +FramelessHelper framelessHelper; +#endif + +void reportError() +{ + qFatal("Only top level QWidgets and QWindows are accepted."); +} + +QScreen *getCurrentScreenFromWindow(QObject *window) +{ + Q_ASSERT(window); + if (window->isWindowType()) { + return qobject_cast(window)->screen(); + } +#ifdef QT_WIDGETS_LIB + else if (window->isWidgetType()) { + return qobject_cast(window)->screen(); + } +#endif + else { + reportError(); + } + return nullptr; +} + +#ifdef Q_OS_WINDOWS +void *getRawHandleFromWindow(QObject *window) +{ + Q_ASSERT(window); + if (window->isWindowType()) { + return reinterpret_cast(qobject_cast(window)->winId()); + } +#ifdef QT_WIDGETS_LIB + else if (window->isWidgetType()) { + return reinterpret_cast(qobject_cast(window)->winId()); + } +#endif + else { + reportError(); + } + return nullptr; +} +#endif + +} // namespace + +FramelessWindowsManager::FramelessWindowsManager() {} + +void FramelessWindowsManager::addWindow(QObject *window, const bool center) +{ + Q_ASSERT(window); +#ifdef Q_OS_WINDOWS + WinNativeEventFilter::addFramelessWindow(window); +#else + framelessHelper.removeWindowFrame(window); +#endif + if (center) { + moveWindowToDesktopCenter(window); + } +} + +void FramelessWindowsManager::moveWindowToDesktopCenter(QObject *window, const bool realCenter) +{ + Q_ASSERT(window); + if (realCenter) { +#ifdef Q_OS_WINDOWS + WinNativeEventFilter::moveWindowToDesktopCenter(getRawHandleFromWindow(window)); +#else + FramelessHelper::moveWindowToDesktopCenter(window); +#endif + } else { + QSize windowSize = {}, screenSize = {}; + QRect screenGeometry = {}; + if (window->isWindowType()) { + const auto win = qobject_cast(window); + if (win) { + windowSize = win->size(); + screenSize = getDesktopAvailableSize(win); + screenGeometry = getDesktopAvailableGeometry(win); + } + } +#ifdef QT_WIDGETS_LIB + else if (window->isWidgetType()) { + const auto widget = qobject_cast(window); + if (widget && widget->isTopLevel()) { + windowSize = widget->size(); + screenSize = getDesktopAvailableSize(widget); + screenGeometry = getDesktopAvailableGeometry(widget); + } + } +#endif + else { + reportError(); + } + const int newX = qRound(static_cast(screenSize.width() - windowSize.width()) / 2.0); + const int newY = qRound(static_cast(screenSize.height() - windowSize.height()) / 2.0); + const int x = newX + screenGeometry.x(); + const int y = newY + screenGeometry.y(); + if (window->isWindowType()) { + const auto win = qobject_cast(window); + if (win) { + win->setX(x); + win->setY(y); + } + } +#ifdef QT_WIDGETS_LIB + else if (window->isWidgetType()) { + const auto widget = qobject_cast(window); + if (widget && widget->isTopLevel()) { + widget->move(x, y); + } + } +#endif + else { + reportError(); + } + } +} + +QSize FramelessWindowsManager::getDesktopSize(QObject *window) +{ + const QScreen *screen = window ? getCurrentScreenFromWindow(window) + : QGuiApplication::primaryScreen(); + return screen ? screen->size() : QSize(); +} + +QRect FramelessWindowsManager::getDesktopAvailableGeometry(QObject *window) +{ + const QScreen *screen = window ? getCurrentScreenFromWindow(window) + : QGuiApplication::primaryScreen(); + return screen ? screen->availableGeometry() : QRect(); +} + +QSize FramelessWindowsManager::getDesktopAvailableSize(QObject *window) +{ + const QScreen *screen = window ? getCurrentScreenFromWindow(window) + : QGuiApplication::primaryScreen(); + return screen ? screen->availableSize() : QSize(); +} + +void FramelessWindowsManager::addIgnoreArea(QObject *window, const QRect &area) +{ + Q_ASSERT(window); +#ifdef Q_OS_WINDOWS + const auto data = WinNativeEventFilter::windowData(window); + if (data) { + data->ignoreAreas.append(area); + } +#else + framelessHelper.addIgnoreArea(window, area); +#endif +} + +void FramelessWindowsManager::addDraggableArea(QObject *window, const QRect &area) +{ + Q_ASSERT(window); +#ifdef Q_OS_WINDOWS + const auto data = WinNativeEventFilter::windowData(window); + if (data) { + data->draggableAreas.append(area); + } +#else + framelessHelper.addDraggableArea(window, area); +#endif +} + +void FramelessWindowsManager::addIgnoreObject(QObject *window, QObject *object) +{ + Q_ASSERT(window); +#ifdef Q_OS_WINDOWS + const auto data = WinNativeEventFilter::windowData(window); + if (data) { + data->ignoreObjects.append(object); + } +#else + framelessHelper.addIgnoreObject(window, object); +#endif +} + +void FramelessWindowsManager::addDraggableObject(QObject *window, QObject *object) +{ + Q_ASSERT(window); +#ifdef Q_OS_WINDOWS + const auto data = WinNativeEventFilter::windowData(window); + if (data) { + data->draggableObjects.append(object); + } +#else + framelessHelper.addDraggableObject(window, object); +#endif +} + +int FramelessWindowsManager::getBorderWidth(QObject *window) +{ +#ifdef Q_OS_WINDOWS + Q_ASSERT(window); + return WinNativeEventFilter::getSystemMetric(getRawHandleFromWindow(window), + WinNativeEventFilter::SystemMetric::BorderWidth); +#else + Q_UNUSED(window) + return framelessHelper.getBorderWidth(); +#endif +} + +void FramelessWindowsManager::setBorderWidth(QObject *window, const int value) +{ +#ifdef Q_OS_WINDOWS + Q_ASSERT(window); + const auto data = WinNativeEventFilter::windowData(window); + if (data) { + data->borderWidth = value; + } +#else + Q_UNUSED(window) + framelessHelper.setBorderWidth(value); +#endif +} + +int FramelessWindowsManager::getBorderHeight(QObject *window) +{ +#ifdef Q_OS_WINDOWS + Q_ASSERT(window); + return WinNativeEventFilter::getSystemMetric(getRawHandleFromWindow(window), + WinNativeEventFilter::SystemMetric::BorderHeight); +#else + Q_UNUSED(window) + return framelessHelper.getBorderHeight(); +#endif +} + +void FramelessWindowsManager::setBorderHeight(QObject *window, const int value) +{ +#ifdef Q_OS_WINDOWS + Q_ASSERT(window); + const auto data = WinNativeEventFilter::windowData(window); + if (data) { + data->borderHeight = value; + } +#else + Q_UNUSED(window) + framelessHelper.setBorderHeight(value); +#endif +} + +int FramelessWindowsManager::getTitleBarHeight(QObject *window) +{ +#ifdef Q_OS_WINDOWS + Q_ASSERT(window); + return WinNativeEventFilter::getSystemMetric(getRawHandleFromWindow(window), + WinNativeEventFilter::SystemMetric::TitleBarHeight); +#else + Q_UNUSED(window) + return framelessHelper.getTitleBarHeight(); +#endif +} + +void FramelessWindowsManager::setTitleBarHeight(QObject *window, const int value) +{ +#ifdef Q_OS_WINDOWS + Q_ASSERT(window); + const auto data = WinNativeEventFilter::windowData(window); + if (data) { + data->titleBarHeight = value; + } +#else + Q_UNUSED(window) + framelessHelper.setTitleBarHeight(value); +#endif +} + +bool FramelessWindowsManager::getResizable(QObject *window) +{ + Q_ASSERT(window); +#ifdef Q_OS_WINDOWS + const auto data = WinNativeEventFilter::windowData(window); + return data ? !data->fixedSize : false; +#else + return framelessHelper.getResizable(window); +#endif +} + +void FramelessWindowsManager::setResizable(QObject *window, const bool value) +{ + Q_ASSERT(window); +#ifdef Q_OS_WINDOWS + const auto data = WinNativeEventFilter::windowData(window); + if (data) { + data->fixedSize = !value; + } +#else + framelessHelper.setResizable(window, value); +#endif +} + +QSize FramelessWindowsManager::getMinimumSize(QObject *window) +{ + Q_ASSERT(window); +#ifdef Q_OS_WINDOWS + const auto data = WinNativeEventFilter::windowData(window); + return data ? data->minimumSize : QSize(); +#else + if (window->isWindowType()) { + return qobject_cast(window)->minimumSize(); + } +#ifdef QT_WIDGETS_LIB + else if (window->isWidgetType()) { + return qobject_cast(window)->minimumSize(); + } +#endif + else { + reportError(); + } + return {}; +#endif +} + +void FramelessWindowsManager::setMinimumSize(QObject *window, const QSize &value) +{ + Q_ASSERT(window); +#ifdef Q_OS_WINDOWS + const auto data = WinNativeEventFilter::windowData(window); + if (data) { + data->minimumSize = value; + } +#else + if (window->isWindowType()) { + qobject_cast(window)->setMinimumSize(value); + } +#ifdef QT_WIDGETS_LIB + else if (window->isWidgetType()) { + qobject_cast(window)->setMinimumSize(value); + } +#endif + else { + reportError(); + } +#endif +} + +QSize FramelessWindowsManager::getMaximumSize(QObject *window) +{ + Q_ASSERT(window); +#ifdef Q_OS_WINDOWS + const auto data = WinNativeEventFilter::windowData(window); + return data ? data->maximumSize : QSize(); +#else + if (window->isWindowType()) { + return qobject_cast(window)->maximumSize(); + } +#ifdef QT_WIDGETS_LIB + else if (window->isWidgetType()) { + return qobject_cast(window)->maximumSize(); + } +#endif + else { + reportError(); + } + return {}; +#endif +} + +void FramelessWindowsManager::setMaximumSize(QObject *window, const QSize &value) +{ + Q_ASSERT(window); +#ifdef Q_OS_WINDOWS + const auto data = WinNativeEventFilter::windowData(window); + if (data) { + data->maximumSize = value; + } +#else + if (window->isWindowType()) { + qobject_cast(window)->setMaximumSize(value); + } +#ifdef QT_WIDGETS_LIB + else if (window->isWidgetType()) { + qobject_cast(window)->setMaximumSize(value); + } +#endif + else { + reportError(); + } +#endif +} + +bool FramelessWindowsManager::getTitleBarEnabled(QObject *window) +{ + Q_ASSERT(window); +#ifdef Q_OS_WINDOWS + const auto data = WinNativeEventFilter::windowData(window); + return data ? !data->disableTitleBar : false; +#else + return framelessHelper.getTitleBarEnabled(window); +#endif +} + +void FramelessWindowsManager::setTitleBarEnabled(QObject *window, const bool value) +{ + Q_ASSERT(window); +#ifdef Q_OS_WINDOWS + const auto data = WinNativeEventFilter::windowData(window); + if (data) { + data->disableTitleBar = !value; + } +#else + framelessHelper.setTitleBarEnabled(window, value); +#endif +} diff --git a/framelesswindowsmanager.h b/framelesswindowsmanager.h new file mode 100644 index 0000000..83a4d02 --- /dev/null +++ b/framelesswindowsmanager.h @@ -0,0 +1,86 @@ +/* + * MIT License + * + * Copyright (C) 2020 by wangwenx190 (Yuhang Zhao) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#pragma once + +#include "framelesshelper_global.h" +#include + +QT_BEGIN_NAMESPACE +QT_FORWARD_DECLARE_CLASS(QObject) +QT_END_NAMESPACE + +#if (QT_VERSION < QT_VERSION_CHECK(5, 13, 0)) +#define Q_DISABLE_MOVE(Class) \ + Class(Class &&) = delete; \ + Class &operator=(Class &&) = delete; + +#define Q_DISABLE_COPY_MOVE(Class) \ + Q_DISABLE_COPY(Class) \ + Q_DISABLE_MOVE(Class) +#endif + +class FRAMELESSHELPER_EXPORT FramelessWindowsManager +{ + Q_DISABLE_COPY_MOVE(FramelessWindowsManager) + +public: + explicit FramelessWindowsManager(); + ~FramelessWindowsManager() = default; + + static void addWindow(QObject *window, const bool center = false); + + static void moveWindowToDesktopCenter(QObject *window, const bool realCenter = true); + + static QSize getDesktopSize(QObject *window = nullptr); + static QRect getDesktopAvailableGeometry(QObject *window = nullptr); + static QSize getDesktopAvailableSize(QObject *window = nullptr); + + static void addIgnoreArea(QObject *window, const QRect &area); + static void addDraggableArea(QObject *window, const QRect &area); + + static void addIgnoreObject(QObject *window, QObject *object); + static void addDraggableObject(QObject *window, QObject *object); + + static int getBorderWidth(QObject *window); + static void setBorderWidth(QObject *window, const int value); + + static int getBorderHeight(QObject *window); + static void setBorderHeight(QObject *window, const int value); + + static int getTitleBarHeight(QObject *window); + static void setTitleBarHeight(QObject *window, const int value); + + static bool getResizable(QObject *window); + static void setResizable(QObject *window, const bool value = true); + + static QSize getMinimumSize(QObject *window); + static void setMinimumSize(QObject *window, const QSize &value); + + static QSize getMaximumSize(QObject *window); + static void setMaximumSize(QObject *window, const QSize &value); + + static bool getTitleBarEnabled(QObject *window); + static void setTitleBarEnabled(QObject *window, const bool value = true); +}; diff --git a/resources/qml/main.qml b/resources/qml/main.qml index f9d5dfc..9d13ffa 100644 --- a/resources/qml/main.qml +++ b/resources/qml/main.qml @@ -103,5 +103,5 @@ Window { } } - Component.onCompleted: framelessHelper.removeWindowFrame() + Component.onCompleted: framelessHelper.removeWindowFrame(true) }