Signed-off-by: Yuhang Zhao <2546789017@qq.com>
This commit is contained in:
Yuhang Zhao 2020-10-14 18:36:13 +08:00
parent 7aae486ba9
commit 5fc425fc64
11 changed files with 627 additions and 581 deletions

View File

@ -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)

View File

@ -22,16 +22,12 @@
* SOFTWARE.
*/
#include "../../framelesswindowsmanager.h"
#include "ui_MainWindow.h"
#include "ui_TitleBar.h"
#include <QApplication>
#include <QStyleOption>
#include <QWidget>
#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();

View File

@ -22,17 +22,13 @@
* SOFTWARE.
*/
#include "../../framelesswindowsmanager.h"
#include <QApplication>
#include <QHBoxLayout>
#include <QLabel>
#include <QPushButton>
#include <QVBoxLayout>
#include <QWidget>
#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();

View File

@ -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
}

View File

@ -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<QRect> FramelessHelper::getIgnoreAreas(QObject *obj) const
return m_ignoreAreas.value(obj);
}
void FramelessHelper::setIgnoreAreas(QObject *obj, const QList<QRect> &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<QRect> FramelessHelper::getDraggableAreas(QObject *obj) const
{
Q_ASSERT(obj);
return m_draggableAreas.value(obj);
}
void FramelessHelper::setDraggableAreas(QObject *obj, const QList<QRect> &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<QObject *> FramelessHelper::getIgnoreObjects(QObject *obj) const
{
Q_ASSERT(obj);
@ -240,18 +215,6 @@ QList<QObject *> FramelessHelper::getIgnoreObjects(QObject *obj) const
return ret;
}
void FramelessHelper::setIgnoreObjects(QObject *obj, const QList<QObject *> &val)
{
Q_ASSERT(obj);
QList<QPointer<QObject>> 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<QObject *> FramelessHelper::getDraggableObjects(QObject *obj) const
{
Q_ASSERT(obj);
@ -281,18 +238,6 @@ QList<QObject *> FramelessHelper::getDraggableObjects(QObject *obj) const
return ret;
}
void FramelessHelper::setDraggableObjects(QObject *obj, const QList<QObject *> &val)
{
Q_ASSERT(obj);
QList<QPointer<QObject>> 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<QWindow *>(obj);
if (window) {
window->setFlags(flags);
// MouseTracking is always enabled for QWindow.
window->installEventFilter(this);
if (obj->isWindowType()) {
const auto window = qobject_cast<QWindow *>(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<QWidget *>(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)

View File

@ -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<QRect> getIgnoreAreas(QObject *obj) const;
void setIgnoreAreas(QObject *obj, const QList<QRect> &val);
void addIgnoreArea(QObject *obj, const QRect &val);
void clearIgnoreAreas(QObject *obj);
QList<QRect> getIgnoreAreas(QObject *obj) const;
QList<QRect> getDraggableAreas(QObject *obj) const;
void setDraggableAreas(QObject *obj, const QList<QRect> &val);
void addDraggableArea(QObject *obj, const QRect &val);
void clearDraggableAreas(QObject *obj);
QList<QRect> getDraggableAreas(QObject *obj) const;
QList<QObject *> getIgnoreObjects(QObject *obj) const;
void setIgnoreObjects(QObject *obj, const QList<QObject *> &val);
void addIgnoreObject(QObject *obj, QObject *val);
void clearIgnoreObjects(QObject *obj);
QList<QObject *> getIgnoreObjects(QObject *obj) const;
QList<QObject *> getDraggableObjects(QObject *obj) const;
void setDraggableObjects(QObject *obj, const QList<QObject *> &val);
void addDraggableObject(QObject *obj, QObject *val);
void clearDraggableObjects(QObject *obj);
QList<QObject *> 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;

View File

@ -24,524 +24,131 @@
#include "framelessquickhelper.h"
#include "framelesswindowsmanager.h"
#include <QQuickWindow>
#include <QScreen>
#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<qreal>(screenSize.width() - windowSize.width())
/ 2.0);
const int newY = qRound(static_cast<qreal>(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<QRect> &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<QRect> &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<QQuickItem *> &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<QObject *> 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<QQuickItem *> &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<QObject *> 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);
}

View File

@ -27,11 +27,6 @@
#include "framelesshelper_global.h"
#include <QQuickItem>
#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<QRect> &val);
void clearIgnoreAreas();
void addIgnoreArea(const QRect &val);
void setDraggableAreas(const QList<QRect> &val);
void clearDraggableAreas();
void addDraggableArea(const QRect &val);
void setIgnoreObjects(const QList<QQuickItem *> &val);
void clearIgnoreObjects();
void addIgnoreObject(QQuickItem *val);
void setDraggableObjects(const QList<QQuickItem *> &val);
void clearDraggableObjects();
void addDraggableObject(QQuickItem *val);
Q_SIGNALS:

454
framelesswindowsmanager.cpp Normal file
View File

@ -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 <QGuiApplication>
#include <QScreen>
#include <QWindow>
#ifdef QT_WIDGETS_LIB
#include <QWidget>
#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<QWindow *>(window)->screen();
}
#ifdef QT_WIDGETS_LIB
else if (window->isWidgetType()) {
return qobject_cast<QWidget *>(window)->screen();
}
#endif
else {
reportError();
}
return nullptr;
}
#ifdef Q_OS_WINDOWS
void *getRawHandleFromWindow(QObject *window)
{
Q_ASSERT(window);
if (window->isWindowType()) {
return reinterpret_cast<void *>(qobject_cast<QWindow *>(window)->winId());
}
#ifdef QT_WIDGETS_LIB
else if (window->isWidgetType()) {
return reinterpret_cast<void *>(qobject_cast<QWidget *>(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<QWindow *>(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<QWidget *>(window);
if (widget && widget->isTopLevel()) {
windowSize = widget->size();
screenSize = getDesktopAvailableSize(widget);
screenGeometry = getDesktopAvailableGeometry(widget);
}
}
#endif
else {
reportError();
}
const int newX = qRound(static_cast<qreal>(screenSize.width() - windowSize.width()) / 2.0);
const int newY = qRound(static_cast<qreal>(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<QWindow *>(window);
if (win) {
win->setX(x);
win->setY(y);
}
}
#ifdef QT_WIDGETS_LIB
else if (window->isWidgetType()) {
const auto widget = qobject_cast<QWidget *>(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<QWindow *>(window)->minimumSize();
}
#ifdef QT_WIDGETS_LIB
else if (window->isWidgetType()) {
return qobject_cast<QWidget *>(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<QWindow *>(window)->setMinimumSize(value);
}
#ifdef QT_WIDGETS_LIB
else if (window->isWidgetType()) {
qobject_cast<QWidget *>(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<QWindow *>(window)->maximumSize();
}
#ifdef QT_WIDGETS_LIB
else if (window->isWidgetType()) {
return qobject_cast<QWidget *>(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<QWindow *>(window)->setMaximumSize(value);
}
#ifdef QT_WIDGETS_LIB
else if (window->isWidgetType()) {
qobject_cast<QWidget *>(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
}

86
framelesswindowsmanager.h Normal file
View File

@ -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 <QRect>
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);
};

View File

@ -103,5 +103,5 @@ Window {
}
}
Component.onCompleted: framelessHelper.removeWindowFrame()
Component.onCompleted: framelessHelper.removeWindowFrame(true)
}