Merge remote-tracking branch 'origin/win32-clean-dependency' into master

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
This commit is contained in:
Yuhang Zhao 2020-11-16 23:01:11 +08:00
commit d3f2ad8658
15 changed files with 260 additions and 471 deletions

View File

@ -53,7 +53,12 @@ If you are using part of or all the code from this repository in your own projec
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
QWidget widget; QWidget widget;
// Do this before the widget is shown. // Do this before the widget is shown.
FramelessWindowsManager::addWindow(&widget); #ifdef Q_OS_WIN
const auto id = reinterpret_cast<FramelessWindowsManager::WindowId>(widget.winId());
#else
const auto id = static_cast<FramelessWindowsManager::WindowId>(&widget);
#endif
FramelessWindowsManager::addWindow(id);
widget.show(); widget.show();
} }
``` ```
@ -65,29 +70,34 @@ Please refer to [the QWidget example](/examples/QWidget/main.cpp) for more detai
```cpp ```cpp
// Only **TOP LEVEL** QWidgets and QWindows are supported. // Only **TOP LEVEL** QWidgets and QWindows are supported.
QMainWindow *mainWindow = new QMainWindow; QMainWindow *mainWindow = new QMainWindow;
#ifdef Q_OS_WIN
const auto id = reinterpret_cast<FramelessWindowsManager::WindowId>(mainWindow->winId());
#else
const auto id = static_cast<FramelessWindowsManager::WindowId>(mainWindow);
#endif
// Disable resizing of the given window. Resizing is enabled by default. // Disable resizing of the given window. Resizing is enabled by default.
FramelessWindowsManager::setResizable(mainWindow, false); FramelessWindowsManager::setResizable(id, false);
// All the following values should not be DPI-aware, just use the // All the following values should not be DPI-aware, just use the
// original numbers, assuming the scale factor is 1.0, don't scale // original numbers, assuming the scale factor is 1.0, don't scale
// them yourself, this code will do the scaling according to DPI // them yourself, this code will do the scaling according to DPI
// internally and automatically. // internally and automatically.
// Maximum window size // Maximum window size
FramelessWindowsManager::setMaximumSize(mainWindow, {1280, 720}); FramelessWindowsManager::setMaximumSize(id, {1280, 720});
// Minimum window size // Minimum window size
FramelessWindowsManager::setMinimumSize(mainWindow, {800, 540}); FramelessWindowsManager::setMinimumSize(id, {800, 540});
// How to set ignore areas: // How to set ignore areas:
// The geometry of something you already know, in window coordinates // The geometry of something you already know, in window coordinates
FramelessWindowsManager::addIgnoreArea(mainWindow, {100, 0, 30, 30}); FramelessWindowsManager::addIgnoreArea(id, {100, 0, 30, 30});
// The geometry of a widget, in window coordinates. // The geometry of a widget, in window coordinates.
// It won't update automatically when the geometry of that widget has // It won't update automatically when the geometry of that widget has
// changed, so if you want to add a widget, which is in a layout and // changed, so if you want to add a widget, which is in a layout and
// it's geometry will possibly change, to the ignore list, try the // it's geometry will possibly change, to the ignore list, try the
// next method (addIgnoreObject) instead. // next method (addIgnoreObject) instead.
FramelessWindowsManager::addIgnoreArea(mainWindow, pushButton_close.geometry()); FramelessWindowsManager::addIgnoreArea(id, pushButton_close.geometry());
// The **POINTER** of a QWidget or QQuickItem // The **POINTER** of a QWidget or QQuickItem
FramelessWindowsManager::addIgnoreObject(mainWindow, ui->pushButton_minimize); FramelessWindowsManager::addIgnoreObject(id, ui->pushButton_minimize);
// Move a QWidget or QWindow to the center of its current desktop. // Move a QWidget or QWindow to the center of its current desktop.
FramelessWindowsManager::moveWindowToDesktopCenter(mainWindow); FramelessWindowsManager::moveWindowToDesktopCenter(id);
``` ```
## Supported Platforms ## Supported Platforms
@ -108,7 +118,7 @@ A not too old version of Linux and macOS, 32 bit & 64 bit.
| Component | Requirement | Additional Information | | Component | Requirement | Additional Information |
| --- | --- | --- | | --- | --- | --- |
| Qt | >= 5.6 | Only the `gui` module is required explicitly, but to make full use of this repository, you'd better install the `widgets` and `quick` modules as well | | Qt | >= 5.6 | Only the `core` and `gui` modules are required |
| Compiler | >= C++11 | MSVC, MinGW, Clang-CL, Intel-CL or cross compile from Linux/macOS are all supported | | Compiler | >= C++11 | MSVC, MinGW, Clang-CL, Intel-CL or cross compile from Linux/macOS are all supported |
### UNIX ### UNIX

View File

@ -32,7 +32,7 @@
```cpp ```cpp
QWidget widget; QWidget widget;
// Do this before the widget is shown. // Do this before the widget is shown.
WinNativeEventFilter::addFramelessWindow(&widget); WinNativeEventFilter::addFramelessWindow(reinterpret_cast<void *>(widget.winId()));
widget.show(); widget.show();
``` ```
@ -41,6 +41,8 @@ Please refer to [the QWidget example](/examples/QWidget/main.cpp) for more detai
### Ignore areas and etc ### Ignore areas and etc
```cpp ```cpp
// Get the window handle (HWND) first.
const auto handle = reinterpret_cast<void *>(widget.winId());
WinNativeEventFilter::WINDOWDATA data = {}; WinNativeEventFilter::WINDOWDATA data = {};
// All the following values should not be DPI-aware, just use the // All the following values should not be DPI-aware, just use the
// original numbers, assuming the scale factor is 1.0, don't scale // original numbers, assuming the scale factor is 1.0, don't scale
@ -62,18 +64,18 @@ data.ignoreAreas.append(pushButton_close.geometry());
// The **POINTER** of a QWidget or QQuickItem // The **POINTER** of a QWidget or QQuickItem
data.ignoreObjects.append(ui->pushButton_minimize); data.ignoreObjects.append(ui->pushButton_minimize);
// Pass data as the second parameter // Pass data as the second parameter
WinNativeEventFilter::addFramelessWindow(&widget, &data); WinNativeEventFilter::addFramelessWindow(handle, &data);
// Or // Or
WinNativeEventFilter::setWindowData(&widget, &data); WinNativeEventFilter::setWindowData(handle, &data);
// Or modify the window data of a specific window directly: // Or modify the window data of a specific window directly:
const auto data = WinNativeEventFilter::getWindowData(&widget); const auto data = WinNativeEventFilter::getWindowData(handle);
if (data) { if (data) {
data->borderWidth = 5; data->borderWidth = 5;
data->borderHeight = 5; data->borderHeight = 5;
data->titleBarHeight = 30; data->titleBarHeight = 30;
} }
// The frameless window is resizable by default. // The frameless window is resizable by default.
WinNativeEventFilter::setWindowResizable(reinterpret_cast<void *>(mainWindow->winId()), false); WinNativeEventFilter::setWindowResizable(handle, false);
``` ```
## Supported Platforms ## Supported Platforms
@ -86,7 +88,7 @@ The code itself should be able to work on Windows Vista in theory, but Qt5 has d
| Component | Requirement | Additional Information | | Component | Requirement | Additional Information |
| --- | --- | --- | | --- | --- | --- |
| Qt | >= 5.6 | Only the `gui` module is required explicitly, but to make full use of this repository, you'd better install the `widgets` and `quick` modules as well | | Qt | >= 5.6 | Only the `core` and `gui` modules are required |
| Compiler | >= C++11 | MSVC, MinGW, Clang-CL, Intel-CL or cross compile from Linux are all supported | | Compiler | >= C++11 | MSVC, MinGW, Clang-CL, Intel-CL or cross compile from Linux are all supported |
## Known Bugs ## Known Bugs

View File

@ -103,17 +103,21 @@ int main(int argc, char *argv[])
mainWindow->setWindowIcon(icon); mainWindow->setWindowIcon(icon);
mainWindow->setWindowTitle(QObject::tr("Hello, World!")); mainWindow->setWindowTitle(QObject::tr("Hello, World!"));
FramelessWindowsManager::addWindow(mainWindow); #ifdef Q_OS_WIN
const auto id = reinterpret_cast<FramelessWindowsManager::WindowId>(mainWindow->winId());
#else
const auto id = static_cast<FramelessWindowsManager::WindowId>(mainWindow);
#endif
FramelessWindowsManager::addIgnoreObject(mainWindow, titleBarWidget.minimizeButton); FramelessWindowsManager::addWindow(id);
FramelessWindowsManager::addIgnoreObject(mainWindow, titleBarWidget.maximizeButton);
FramelessWindowsManager::addIgnoreObject(mainWindow, titleBarWidget.closeButton); FramelessWindowsManager::addIgnoreObject(id, titleBarWidget.minimizeButton);
FramelessWindowsManager::addIgnoreObject(mainWindow, appMainWindow.menubar); FramelessWindowsManager::addIgnoreObject(id, titleBarWidget.maximizeButton);
FramelessWindowsManager::addIgnoreObject(id, titleBarWidget.closeButton);
FramelessWindowsManager::addIgnoreObject(id, appMainWindow.menubar);
mainWindow->resize(800, 600); mainWindow->resize(800, 600);
//FramelessWindowsManager::moveWindowToDesktopCenter(mainWindow);
mainWindow->show(); mainWindow->show();
return QApplication::exec(); return QApplication::exec();

View File

@ -94,16 +94,20 @@ int main(int argc, char *argv[])
widget.setLayout(mainLayout); widget.setLayout(mainLayout);
widget.setWindowTitle(QObject::tr("Hello, World!")); widget.setWindowTitle(QObject::tr("Hello, World!"));
FramelessWindowsManager::addWindow(&widget); #ifdef Q_OS_WIN
const auto id = reinterpret_cast<FramelessWindowsManager::WindowId>(widget.winId());
#else
const auto id = static_cast<FramelessWindowsManager::WindowId>(&widget);
#endif
FramelessWindowsManager::addIgnoreObject(&widget, minimizeButton); FramelessWindowsManager::addWindow(id);
FramelessWindowsManager::addIgnoreObject(&widget, maximizeButton);
FramelessWindowsManager::addIgnoreObject(&widget, closeButton); FramelessWindowsManager::addIgnoreObject(id, minimizeButton);
FramelessWindowsManager::addIgnoreObject(id, maximizeButton);
FramelessWindowsManager::addIgnoreObject(id, closeButton);
widget.resize(800, 600); widget.resize(800, 600);
//FramelessWindowsManager::moveWindowToDesktopCenter(&widget);
widget.show(); widget.show();
return QApplication::exec(); return QApplication::exec();

View File

@ -1,6 +1,7 @@
TARGET = Quick TARGET = Quick
TEMPLATE = app TEMPLATE = app
QT += quick QT += quick
SOURCES += main.cpp HEADERS += ../../framelessquickhelper.h
SOURCES += ../../framelessquickhelper.cpp main.cpp
RESOURCES += qml.qrc RESOURCES += qml.qrc
include($$PWD/../common.pri) include($$PWD/../common.pri)

View File

@ -138,6 +138,7 @@ const QLatin1String g_sCloseButtonImageLight(":/images/button_close_white.svg");
Widget::Widget(QWidget *parent) : QWidget(parent) Widget::Widget(QWidget *parent) : QWidget(parent)
{ {
createWinId(); // Internal function
initializeWindow(); initializeWindow();
} }
@ -373,7 +374,7 @@ bool Widget::eventFilter(QObject *object, QEvent *event)
break; break;
} }
case QEvent::WinIdChange: case QEvent::WinIdChange:
WinNativeEventFilter::addFramelessWindow(this); WinNativeEventFilter::addFramelessWindow(rawHandle());
break; break;
case QEvent::WindowActivate: case QEvent::WindowActivate:
case QEvent::WindowDeactivate: case QEvent::WindowDeactivate:
@ -400,9 +401,7 @@ bool Widget::nativeEvent(const QByteArray &eventType, void *message, long *resul
switch (msg->message) { switch (msg->message) {
case WM_NCRBUTTONUP: { case WM_NCRBUTTONUP: {
if (msg->wParam == HTCAPTION) { if (msg->wParam == HTCAPTION) {
const int x = GET_X_LPARAM(msg->lParam); if (WinNativeEventFilter::displaySystemMenu(msg->hwnd)) {
const int y = GET_Y_LPARAM(msg->lParam);
if (WinNativeEventFilter::displaySystemMenu(msg->hwnd, false, x, y)) {
*result = 0; *result = 0;
return true; return true;
} }
@ -581,6 +580,15 @@ void Widget::setupConnections()
QColorDialog::ShowAlphaChannel); QColorDialog::ShowAlphaChannel);
} }
} }
// Qt will paint a solid white background to the window,
// it will cover the blurred effect, so we need to
// make the background become totally transparent. Achieve
// this by setting a palette to the window.
QPalette palette = {};
if (enable) {
palette.setColor(QPalette::Window, Qt::transparent);
}
setPalette(palette);
WinNativeEventFilter::setBlurEffectEnabled(rawHandle(), enable, color); WinNativeEventFilter::setBlurEffectEnabled(rawHandle(), enable, color);
updateWindow(); updateWindow();
if (useAcrylicEffect && enable && WinNativeEventFilter::isTransparencyEffectEnabled()) { if (useAcrylicEffect && enable && WinNativeEventFilter::isTransparencyEffectEnabled()) {
@ -621,7 +629,7 @@ void Widget::initializeFramelessFunctions()
{ {
WinNativeEventFilter::WINDOWDATA data = {}; WinNativeEventFilter::WINDOWDATA data = {};
data.ignoreObjects << iconButton << minimizeButton << maximizeButton << closeButton; data.ignoreObjects << iconButton << minimizeButton << maximizeButton << closeButton;
WinNativeEventFilter::addFramelessWindow(this, &data); WinNativeEventFilter::addFramelessWindow(rawHandle(), &data);
installEventFilter(this); installEventFilter(this);
} }

View File

@ -14,10 +14,9 @@ win32 {
RC_FILE = $$PWD/windows.rc RC_FILE = $$PWD/windows.rc
OTHER_FILES += $$PWD/windows.manifest OTHER_FILES += $$PWD/windows.manifest
} }
CONFIG(debug, debug|release) { win32 {
LIBS += -L$$OUT_PWD/../../debug CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../../debug -lFramelessHelperd
win32: LIBS += -lFramelessHelperd else: CONFIG(release, debug|release): LIBS += -L$$OUT_PWD/../../release -lFramelessHelper
else: unix: LIBS += -lFramelessHelper_debug } else: unix {
} else: CONFIG(release, debug|release) { LIBS += -L$$OUT_PWD/../../bin -lFramelessHelper
LIBS += -L$$OUT_PWD/../../release -lFramelessHelper
} }

View File

@ -407,29 +407,31 @@ bool FramelessHelper::eventFilter(QObject *object, QEvent *event)
if (!obj) { if (!obj) {
continue; continue;
} }
#ifdef QT_WIDGETS_LIB const bool isWidget = obj->inherits("QWidget");
const auto widget = qobject_cast<QWidget *>(obj); const bool isQuickItem = obj->inherits("QQuickItem");
if (widget) { if (!isWidget && !isQuickItem) {
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) qWarning() << obj << "is not a QWidget or QQuickItem!";
const QPointF pos = widget->mapToGlobal(QPointF{0, 0}); continue;
#else
const QPoint pos = widget->mapToGlobal(QPoint{0, 0});
#endif
if (QRectF(pos.x(), pos.y(), widget->width(), widget->height()).contains(mousePos)) {
return true;
}
} }
#endif const auto mapOriginPointToWindow = [](const QObject *obj) -> QPointF {
#ifdef QT_QUICK_LIB Q_ASSERT(obj);
const auto quickItem = qobject_cast<QQuickItem *>(obj); QPointF point = {obj->property("x").toReal(), obj->property("y").toReal()};
if (quickItem) { for (QObject *parent = obj->parent(); parent; parent = parent->parent()) {
const QPointF pos = quickItem->mapToGlobal({0, 0}); point += {parent->property("x").toReal(),
if (QRectF(pos.x(), pos.y(), quickItem->width(), quickItem->height()) parent->property("y").toReal()};
.contains(mousePos)) {
return true;
} }
return point;
};
const QPointF originPoint = mapOriginPointToWindow(obj);
const qreal width = obj->property("width").toReal();
const qreal height = obj->property("height").toReal();
if (QRectF(originPoint.x(),
originPoint.y(),
width,
height)
.contains(mousePos)) {
return true;
} }
#endif
} }
return false; return false;
}; };
@ -441,13 +443,7 @@ bool FramelessHelper::eventFilter(QObject *object, QEvent *event)
const auto isInIgnoreObjects = [this, &isInSpecificObjects](const QPointF &point, const auto isInIgnoreObjects = [this, &isInSpecificObjects](const QPointF &point,
QObject *window) -> bool { QObject *window) -> bool {
Q_ASSERT(window); Q_ASSERT(window);
#if defined(QT_WIDGETS_LIB) || defined(QT_QUICK_LIB)
return isInSpecificObjects(point, getIgnoreObjects(window)); return isInSpecificObjects(point, getIgnoreObjects(window));
#else
Q_UNUSED(point)
Q_UNUSED(window)
return false;
#endif
}; };
const auto isInDraggableAreas = [this, &isInSpecificAreas](const QPointF &point, const auto isInDraggableAreas = [this, &isInSpecificAreas](const QPointF &point,
QObject *window) -> bool { QObject *window) -> bool {
@ -458,14 +454,8 @@ bool FramelessHelper::eventFilter(QObject *object, QEvent *event)
const auto isInDraggableObjects = [this, &isInSpecificObjects](const QPointF &point, const auto isInDraggableObjects = [this, &isInSpecificObjects](const QPointF &point,
QObject *window) -> bool { QObject *window) -> bool {
Q_ASSERT(window); Q_ASSERT(window);
#if defined(QT_WIDGETS_LIB) || defined(QT_QUICK_LIB)
const auto objs = getDraggableObjects(window); const auto objs = getDraggableObjects(window);
return (objs.isEmpty() ? true : isInSpecificObjects(point, objs)); return (objs.isEmpty() ? true : isInSpecificObjects(point, objs));
#else
Q_UNUSED(point)
Q_UNUSED(window)
return true;
#endif
}; };
const auto isResizePermitted = [&isInIgnoreAreas, &isInIgnoreObjects](const QPointF &globalPoint, const auto isResizePermitted = [&isInIgnoreAreas, &isInIgnoreObjects](const QPointF &globalPoint,
const QPointF &point, const QPointF &point,

View File

@ -31,15 +31,34 @@
#include <QOperatingSystemVersion> #include <QOperatingSystemVersion>
#endif #endif
#ifdef Q_OS_WINDOWS
namespace { namespace {
#ifdef Q_OS_WINDOWS
const char g_sPreserveWindowFrame[] = "WNEF_FORCE_PRESERVE_WINDOW_FRAME"; const char g_sPreserveWindowFrame[] = "WNEF_FORCE_PRESERVE_WINDOW_FRAME";
const char g_sDontExtendFrame[] = "WNEF_DO_NOT_EXTEND_FRAME"; const char g_sDontExtendFrame[] = "WNEF_DO_NOT_EXTEND_FRAME";
const char g_sForceUseAcrylicEffect[] = "WNEF_FORCE_ACRYLIC_ON_WIN10"; const char g_sForceUseAcrylicEffect[] = "WNEF_FORCE_ACRYLIC_ON_WIN10";
#endif
FramelessWindowsManager::WindowId getWindowId(QObject *object)
{
Q_ASSERT(object);
if (!object->isWindowType()) {
qWarning() << object << "is not a window!";
return nullptr;
}
const auto window = qobject_cast<QWindow *>(object);
if (!window) {
qWarning() << "Failed to convert" << object << "to QWindow!";
return nullptr;
}
#ifdef Q_OS_WINDOWS
return reinterpret_cast<FramelessWindowsManager::WindowId>(window->winId());
#else
return static_cast<FramelessWindowsManager::WindowId>(window);
#endif
}
} // namespace } // namespace
#endif
FramelessQuickHelper::FramelessQuickHelper(QQuickItem *parent) : QQuickItem(parent) FramelessQuickHelper::FramelessQuickHelper(QQuickItem *parent) : QQuickItem(parent)
{ {
@ -50,56 +69,56 @@ FramelessQuickHelper::FramelessQuickHelper(QQuickItem *parent) : QQuickItem(pare
int FramelessQuickHelper::borderWidth() const int FramelessQuickHelper::borderWidth() const
{ {
return FramelessWindowsManager::getBorderWidth(window()); return FramelessWindowsManager::getBorderWidth(getWindowId(window()));
} }
void FramelessQuickHelper::setBorderWidth(const int val) void FramelessQuickHelper::setBorderWidth(const int val)
{ {
FramelessWindowsManager::setBorderWidth(window(), val); FramelessWindowsManager::setBorderWidth(getWindowId(window()), val);
Q_EMIT borderWidthChanged(val); Q_EMIT borderWidthChanged(val);
} }
int FramelessQuickHelper::borderHeight() const int FramelessQuickHelper::borderHeight() const
{ {
return FramelessWindowsManager::getBorderHeight(window()); return FramelessWindowsManager::getBorderHeight(getWindowId(window()));
} }
void FramelessQuickHelper::setBorderHeight(const int val) void FramelessQuickHelper::setBorderHeight(const int val)
{ {
FramelessWindowsManager::setBorderHeight(window(), val); FramelessWindowsManager::setBorderHeight(getWindowId(window()), val);
Q_EMIT borderHeightChanged(val); Q_EMIT borderHeightChanged(val);
} }
int FramelessQuickHelper::titleBarHeight() const int FramelessQuickHelper::titleBarHeight() const
{ {
return FramelessWindowsManager::getTitleBarHeight(window()); return FramelessWindowsManager::getTitleBarHeight(getWindowId(window()));
} }
void FramelessQuickHelper::setTitleBarHeight(const int val) void FramelessQuickHelper::setTitleBarHeight(const int val)
{ {
FramelessWindowsManager::setTitleBarHeight(window(), val); FramelessWindowsManager::setTitleBarHeight(getWindowId(window()), val);
Q_EMIT titleBarHeightChanged(val); Q_EMIT titleBarHeightChanged(val);
} }
bool FramelessQuickHelper::resizable() const bool FramelessQuickHelper::resizable() const
{ {
return FramelessWindowsManager::getResizable(window()); return FramelessWindowsManager::getResizable(getWindowId(window()));
} }
void FramelessQuickHelper::setResizable(const bool val) void FramelessQuickHelper::setResizable(const bool val)
{ {
FramelessWindowsManager::setResizable(window(), val); FramelessWindowsManager::setResizable(getWindowId(window()), val);
Q_EMIT resizableChanged(val); Q_EMIT resizableChanged(val);
} }
bool FramelessQuickHelper::titleBarEnabled() const bool FramelessQuickHelper::titleBarEnabled() const
{ {
return FramelessWindowsManager::getTitleBarEnabled(window()); return FramelessWindowsManager::getTitleBarEnabled(getWindowId(window()));
} }
void FramelessQuickHelper::setTitleBarEnabled(const bool val) void FramelessQuickHelper::setTitleBarEnabled(const bool val)
{ {
FramelessWindowsManager::setTitleBarEnabled(window(), val); FramelessWindowsManager::setTitleBarEnabled(getWindowId(window()), val);
Q_EMIT titleBarEnabledChanged(val); Q_EMIT titleBarEnabledChanged(val);
} }
@ -136,7 +155,7 @@ bool FramelessQuickHelper::highContrastModeEnabled() const
bool FramelessQuickHelper::darkFrameEnabled() const bool FramelessQuickHelper::darkFrameEnabled() const
{ {
return WinNativeEventFilter::isDarkFrameEnabled(rawHandle()); return WinNativeEventFilter::isDarkFrameEnabled(rawWindowHandle());
} }
bool FramelessQuickHelper::transparencyEffectEnabled() const bool FramelessQuickHelper::transparencyEffectEnabled() const
@ -147,71 +166,56 @@ bool FramelessQuickHelper::transparencyEffectEnabled() const
QSize FramelessQuickHelper::minimumSize() const QSize FramelessQuickHelper::minimumSize() const
{ {
return FramelessWindowsManager::getMinimumSize(window()); return FramelessWindowsManager::getMinimumSize(getWindowId(window()));
} }
void FramelessQuickHelper::setMinimumSize(const QSize &val) void FramelessQuickHelper::setMinimumSize(const QSize &val)
{ {
FramelessWindowsManager::setMinimumSize(window(), val); FramelessWindowsManager::setMinimumSize(getWindowId(window()), val);
Q_EMIT minimumSizeChanged(val); Q_EMIT minimumSizeChanged(val);
} }
QSize FramelessQuickHelper::maximumSize() const QSize FramelessQuickHelper::maximumSize() const
{ {
return FramelessWindowsManager::getMaximumSize(window()); return FramelessWindowsManager::getMaximumSize(getWindowId(window()));
} }
void FramelessQuickHelper::setMaximumSize(const QSize &val) void FramelessQuickHelper::setMaximumSize(const QSize &val)
{ {
FramelessWindowsManager::setMaximumSize(window(), val); FramelessWindowsManager::setMaximumSize(getWindowId(window()), val);
Q_EMIT maximumSizeChanged(val); Q_EMIT maximumSizeChanged(val);
} }
void FramelessQuickHelper::removeWindowFrame(const bool center) void FramelessQuickHelper::removeWindowFrame(const bool center)
{ {
FramelessWindowsManager::addWindow(window(), center); FramelessWindowsManager::addWindow(getWindowId(window()), center);
} }
QSize FramelessQuickHelper::desktopSize() const void FramelessQuickHelper::moveWindowToDesktopCenter()
{ {
return FramelessWindowsManager::getDesktopSize(window()); FramelessWindowsManager::moveWindowToDesktopCenter(getWindowId(window()));
}
QRect FramelessQuickHelper::desktopAvailableGeometry() const
{
return FramelessWindowsManager::getDesktopAvailableGeometry(window());
}
QSize FramelessQuickHelper::desktopAvailableSize() const
{
return FramelessWindowsManager::getDesktopAvailableSize(window());
}
void FramelessQuickHelper::moveWindowToDesktopCenter(const bool realCenter)
{
FramelessWindowsManager::moveWindowToDesktopCenter(window(), realCenter);
} }
void FramelessQuickHelper::addIgnoreArea(const QRect &val) void FramelessQuickHelper::addIgnoreArea(const QRect &val)
{ {
FramelessWindowsManager::addIgnoreArea(window(), val); FramelessWindowsManager::addIgnoreArea(getWindowId(window()), val);
} }
void FramelessQuickHelper::addDraggableArea(const QRect &val) void FramelessQuickHelper::addDraggableArea(const QRect &val)
{ {
FramelessWindowsManager::addDraggableArea(window(), val); FramelessWindowsManager::addDraggableArea(getWindowId(window()), val);
} }
void FramelessQuickHelper::addIgnoreObject(QQuickItem *val) void FramelessQuickHelper::addIgnoreObject(QQuickItem *val)
{ {
Q_ASSERT(val); Q_ASSERT(val);
FramelessWindowsManager::addIgnoreObject(window(), val); FramelessWindowsManager::addIgnoreObject(getWindowId(window()), val);
} }
void FramelessQuickHelper::addDraggableObject(QQuickItem *val) void FramelessQuickHelper::addDraggableObject(QQuickItem *val)
{ {
Q_ASSERT(val); Q_ASSERT(val);
FramelessWindowsManager::addDraggableObject(window(), val); FramelessWindowsManager::addDraggableObject(getWindowId(window()), val);
} }
#ifdef Q_OS_WINDOWS #ifdef Q_OS_WINDOWS
@ -227,9 +231,9 @@ void FramelessQuickHelper::timerEvent(QTimerEvent *event)
Q_EMIT transparencyEffectEnabledChanged(transparencyEffectEnabled()); Q_EMIT transparencyEffectEnabledChanged(transparencyEffectEnabled());
} }
void *FramelessQuickHelper::rawHandle() const void *FramelessQuickHelper::rawWindowHandle() const
{ {
QWindow *win = window(); const QWindow *win = window();
if (win) { if (win) {
return reinterpret_cast<void *>(win->winId()); return reinterpret_cast<void *>(win->winId());
} }
@ -247,9 +251,9 @@ void FramelessQuickHelper::setWindowFrameVisible(const bool value)
} }
} }
void FramelessQuickHelper::displaySystemMenu(const int x, const int y, const bool isRtl) void FramelessQuickHelper::displaySystemMenu(const QPointF &pos)
{ {
WinNativeEventFilter::displaySystemMenu(rawHandle(), isRtl, x, y); WinNativeEventFilter::displaySystemMenu(rawWindowHandle(), pos);
} }
void FramelessQuickHelper::setBlurEffectEnabled(const bool enabled, void FramelessQuickHelper::setBlurEffectEnabled(const bool enabled,
@ -261,6 +265,6 @@ void FramelessQuickHelper::setBlurEffectEnabled(const bool enabled,
} else { } else {
qunsetenv(g_sForceUseAcrylicEffect); qunsetenv(g_sForceUseAcrylicEffect);
} }
WinNativeEventFilter::setBlurEffectEnabled(rawHandle(), enabled, gradientColor); WinNativeEventFilter::setBlurEffectEnabled(rawWindowHandle(), enabled, gradientColor);
} }
#endif #endif

View File

@ -24,7 +24,6 @@
#pragma once #pragma once
#include "framelesshelper_global.h"
#include <QQuickItem> #include <QQuickItem>
#if (defined(Q_OS_WIN) || defined(Q_OS_WIN32) || defined(Q_OS_WIN64) || defined(Q_OS_WINRT)) \ #if (defined(Q_OS_WIN) || defined(Q_OS_WIN32) || defined(Q_OS_WIN64) || defined(Q_OS_WINRT)) \
@ -42,7 +41,7 @@
Q_DISABLE_MOVE(Class) Q_DISABLE_MOVE(Class)
#endif #endif
class FRAMELESSHELPER_EXPORT FramelessQuickHelper : public QQuickItem class FramelessQuickHelper : public QQuickItem
{ {
Q_OBJECT Q_OBJECT
Q_DISABLE_COPY_MOVE(FramelessQuickHelper) Q_DISABLE_COPY_MOVE(FramelessQuickHelper)
@ -110,11 +109,7 @@ public:
public Q_SLOTS: public Q_SLOTS:
void removeWindowFrame(const bool center = false); void removeWindowFrame(const bool center = false);
void moveWindowToDesktopCenter(const bool realCenter = true); void moveWindowToDesktopCenter();
QSize desktopSize() const;
QRect desktopAvailableGeometry() const;
QSize desktopAvailableSize() const;
void addIgnoreArea(const QRect &val); void addIgnoreArea(const QRect &val);
void addDraggableArea(const QRect &val); void addDraggableArea(const QRect &val);
@ -124,7 +119,7 @@ public Q_SLOTS:
#ifdef Q_OS_WINDOWS #ifdef Q_OS_WINDOWS
void setWindowFrameVisible(const bool value = true); void setWindowFrameVisible(const bool value = true);
void displaySystemMenu(const int x, const int y, const bool isRtl = false); void displaySystemMenu(const QPointF &pos = {});
void setBlurEffectEnabled(const bool enabled = true, void setBlurEffectEnabled(const bool enabled = true,
const bool forceAcrylic = false, const bool forceAcrylic = false,
const QColor &gradientColor = Qt::white); const QColor &gradientColor = Qt::white);
@ -135,7 +130,7 @@ protected:
void timerEvent(QTimerEvent *event) override; void timerEvent(QTimerEvent *event) override;
private: private:
void *rawHandle() const; void *rawWindowHandle() const;
#endif #endif
Q_SIGNALS: Q_SIGNALS:

View File

@ -24,16 +24,9 @@
#include "framelesswindowsmanager.h" #include "framelesswindowsmanager.h"
#ifndef Q_OS_WINDOWS
#include <QGuiApplication> #include <QGuiApplication>
#include <QScreen>
#include <QWindow> #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 #endif
#ifdef Q_OS_WINDOWS #ifdef Q_OS_WINDOWS
@ -42,70 +35,30 @@
#include "framelesshelper.h" #include "framelesshelper.h"
#endif #endif
#ifndef Q_OS_WINDOWS
namespace { namespace {
void reportError() QWindow *toWindow(QObject *object)
{ {
qFatal("Only top level QWidgets and QWindows are accepted."); Q_ASSERT(object);
return object->isWindowType() ? qobject_cast<QWindow *>(object) : nullptr;
} }
QScreen *getCurrentScreenFromWindow(QObject *window)
{
Q_ASSERT(window);
if (window->isWindowType()) {
return qobject_cast<QWindow *>(window)->screen();
}
#ifdef QT_WIDGETS_LIB
else if (window->isWidgetType()) {
#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
return qobject_cast<QWidget *>(window)->screen();
#else
QWindow *win = qobject_cast<QWidget *>(window)->windowHandle();
return win ? win->screen() : nullptr;
#endif
}
#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
#ifndef Q_OS_WINDOWS
using FLWM_CORE_DATA = struct _FLWM_CORE_DATA using FLWM_CORE_DATA = struct _FLWM_CORE_DATA
{ {
FramelessHelper framelessHelper; FramelessHelper framelessHelper;
}; };
#endif
} // namespace } // namespace
#endif
#ifndef Q_OS_WINDOWS #ifndef Q_OS_WINDOWS
Q_GLOBAL_STATIC(FLWM_CORE_DATA, coreData) Q_GLOBAL_STATIC(FLWM_CORE_DATA, coreData)
#endif #endif
FramelessWindowsManager::FramelessWindowsManager() {} FramelessWindowsManager::FramelessWindowsManager() = default;
void FramelessWindowsManager::addWindow(QObject *window, const bool center) void FramelessWindowsManager::addWindow(WindowId window, const bool center)
{ {
Q_ASSERT(window); Q_ASSERT(window);
#ifdef Q_OS_WINDOWS #ifdef Q_OS_WINDOWS
@ -118,86 +71,17 @@ void FramelessWindowsManager::addWindow(QObject *window, const bool center)
} }
} }
void FramelessWindowsManager::moveWindowToDesktopCenter(QObject *window, const bool realCenter) void FramelessWindowsManager::moveWindowToDesktopCenter(WindowId window)
{ {
Q_ASSERT(window); Q_ASSERT(window);
if (realCenter) {
#ifdef Q_OS_WINDOWS #ifdef Q_OS_WINDOWS
WinNativeEventFilter::moveWindowToDesktopCenter(getRawHandleFromWindow(window)); WinNativeEventFilter::moveWindowToDesktopCenter(window);
#else #else
FramelessHelper::moveWindowToDesktopCenter(window); FramelessHelper::moveWindowToDesktopCenter(window);
#endif #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) void FramelessWindowsManager::addIgnoreArea(WindowId window, const QRect &area)
{
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); Q_ASSERT(window);
#ifdef Q_OS_WINDOWS #ifdef Q_OS_WINDOWS
@ -210,7 +94,7 @@ void FramelessWindowsManager::addIgnoreArea(QObject *window, const QRect &area)
#endif #endif
} }
void FramelessWindowsManager::addDraggableArea(QObject *window, const QRect &area) void FramelessWindowsManager::addDraggableArea(WindowId window, const QRect &area)
{ {
Q_ASSERT(window); Q_ASSERT(window);
#ifdef Q_OS_WINDOWS #ifdef Q_OS_WINDOWS
@ -223,7 +107,7 @@ void FramelessWindowsManager::addDraggableArea(QObject *window, const QRect &are
#endif #endif
} }
void FramelessWindowsManager::addIgnoreObject(QObject *window, QObject *object) void FramelessWindowsManager::addIgnoreObject(WindowId window, QObject *object)
{ {
Q_ASSERT(window); Q_ASSERT(window);
#ifdef Q_OS_WINDOWS #ifdef Q_OS_WINDOWS
@ -236,7 +120,7 @@ void FramelessWindowsManager::addIgnoreObject(QObject *window, QObject *object)
#endif #endif
} }
void FramelessWindowsManager::addDraggableObject(QObject *window, QObject *object) void FramelessWindowsManager::addDraggableObject(WindowId window, QObject *object)
{ {
Q_ASSERT(window); Q_ASSERT(window);
#ifdef Q_OS_WINDOWS #ifdef Q_OS_WINDOWS
@ -249,11 +133,11 @@ void FramelessWindowsManager::addDraggableObject(QObject *window, QObject *objec
#endif #endif
} }
int FramelessWindowsManager::getBorderWidth(QObject *window) int FramelessWindowsManager::getBorderWidth(WindowId window)
{ {
#ifdef Q_OS_WINDOWS #ifdef Q_OS_WINDOWS
Q_ASSERT(window); Q_ASSERT(window);
return WinNativeEventFilter::getSystemMetric(getRawHandleFromWindow(window), return WinNativeEventFilter::getSystemMetric(window,
WinNativeEventFilter::SystemMetric::BorderWidth); WinNativeEventFilter::SystemMetric::BorderWidth);
#else #else
Q_UNUSED(window) Q_UNUSED(window)
@ -261,7 +145,7 @@ int FramelessWindowsManager::getBorderWidth(QObject *window)
#endif #endif
} }
void FramelessWindowsManager::setBorderWidth(QObject *window, const int value) void FramelessWindowsManager::setBorderWidth(WindowId window, const int value)
{ {
#ifdef Q_OS_WINDOWS #ifdef Q_OS_WINDOWS
Q_ASSERT(window); Q_ASSERT(window);
@ -275,11 +159,11 @@ void FramelessWindowsManager::setBorderWidth(QObject *window, const int value)
#endif #endif
} }
int FramelessWindowsManager::getBorderHeight(QObject *window) int FramelessWindowsManager::getBorderHeight(WindowId window)
{ {
#ifdef Q_OS_WINDOWS #ifdef Q_OS_WINDOWS
Q_ASSERT(window); Q_ASSERT(window);
return WinNativeEventFilter::getSystemMetric(getRawHandleFromWindow(window), return WinNativeEventFilter::getSystemMetric(window,
WinNativeEventFilter::SystemMetric::BorderHeight); WinNativeEventFilter::SystemMetric::BorderHeight);
#else #else
Q_UNUSED(window) Q_UNUSED(window)
@ -287,7 +171,7 @@ int FramelessWindowsManager::getBorderHeight(QObject *window)
#endif #endif
} }
void FramelessWindowsManager::setBorderHeight(QObject *window, const int value) void FramelessWindowsManager::setBorderHeight(WindowId window, const int value)
{ {
#ifdef Q_OS_WINDOWS #ifdef Q_OS_WINDOWS
Q_ASSERT(window); Q_ASSERT(window);
@ -301,11 +185,11 @@ void FramelessWindowsManager::setBorderHeight(QObject *window, const int value)
#endif #endif
} }
int FramelessWindowsManager::getTitleBarHeight(QObject *window) int FramelessWindowsManager::getTitleBarHeight(WindowId window)
{ {
#ifdef Q_OS_WINDOWS #ifdef Q_OS_WINDOWS
Q_ASSERT(window); Q_ASSERT(window);
return WinNativeEventFilter::getSystemMetric(getRawHandleFromWindow(window), return WinNativeEventFilter::getSystemMetric(window,
WinNativeEventFilter::SystemMetric::TitleBarHeight); WinNativeEventFilter::SystemMetric::TitleBarHeight);
#else #else
Q_UNUSED(window) Q_UNUSED(window)
@ -313,7 +197,7 @@ int FramelessWindowsManager::getTitleBarHeight(QObject *window)
#endif #endif
} }
void FramelessWindowsManager::setTitleBarHeight(QObject *window, const int value) void FramelessWindowsManager::setTitleBarHeight(WindowId window, const int value)
{ {
#ifdef Q_OS_WINDOWS #ifdef Q_OS_WINDOWS
Q_ASSERT(window); Q_ASSERT(window);
@ -327,7 +211,7 @@ void FramelessWindowsManager::setTitleBarHeight(QObject *window, const int value
#endif #endif
} }
bool FramelessWindowsManager::getResizable(QObject *window) bool FramelessWindowsManager::getResizable(WindowId window)
{ {
Q_ASSERT(window); Q_ASSERT(window);
#ifdef Q_OS_WINDOWS #ifdef Q_OS_WINDOWS
@ -338,39 +222,29 @@ bool FramelessWindowsManager::getResizable(QObject *window)
#endif #endif
} }
void FramelessWindowsManager::setResizable(QObject *window, const bool value) void FramelessWindowsManager::setResizable(WindowId window, const bool value)
{ {
Q_ASSERT(window); Q_ASSERT(window);
#ifdef Q_OS_WINDOWS #ifdef Q_OS_WINDOWS
WinNativeEventFilter::setWindowResizable(getRawHandleFromWindow(window), value); WinNativeEventFilter::setWindowResizable(window, value);
#else #else
coreData()->framelessHelper.setResizable(window, value); coreData()->framelessHelper.setResizable(window, value);
#endif #endif
} }
QSize FramelessWindowsManager::getMinimumSize(QObject *window) QSize FramelessWindowsManager::getMinimumSize(WindowId window)
{ {
Q_ASSERT(window); Q_ASSERT(window);
#ifdef Q_OS_WINDOWS #ifdef Q_OS_WINDOWS
const auto data = WinNativeEventFilter::getWindowData(window); const auto data = WinNativeEventFilter::getWindowData(window);
return data ? data->minimumSize : QSize(); return data ? data->minimumSize : QSize();
#else #else
if (window->isWindowType()) { const auto win = toWindow(window);
return qobject_cast<QWindow *>(window)->minimumSize(); return win ? win->minimumSize() : QSize();
}
#ifdef QT_WIDGETS_LIB
else if (window->isWidgetType()) {
return qobject_cast<QWidget *>(window)->minimumSize();
}
#endif
else {
reportError();
}
return {};
#endif #endif
} }
void FramelessWindowsManager::setMinimumSize(QObject *window, const QSize &value) void FramelessWindowsManager::setMinimumSize(WindowId window, const QSize &value)
{ {
Q_ASSERT(window); Q_ASSERT(window);
#ifdef Q_OS_WINDOWS #ifdef Q_OS_WINDOWS
@ -379,43 +253,26 @@ void FramelessWindowsManager::setMinimumSize(QObject *window, const QSize &value
data->minimumSize = value; data->minimumSize = value;
} }
#else #else
if (window->isWindowType()) { const auto win = toWindow(window);
qobject_cast<QWindow *>(window)->setMinimumSize(value); if (win) {
} win->setMinimumSize(value);
#ifdef QT_WIDGETS_LIB
else if (window->isWidgetType()) {
qobject_cast<QWidget *>(window)->setMinimumSize(value);
}
#endif
else {
reportError();
} }
#endif #endif
} }
QSize FramelessWindowsManager::getMaximumSize(QObject *window) QSize FramelessWindowsManager::getMaximumSize(WindowId window)
{ {
Q_ASSERT(window); Q_ASSERT(window);
#ifdef Q_OS_WINDOWS #ifdef Q_OS_WINDOWS
const auto data = WinNativeEventFilter::getWindowData(window); const auto data = WinNativeEventFilter::getWindowData(window);
return data ? data->maximumSize : QSize(); return data ? data->maximumSize : QSize();
#else #else
if (window->isWindowType()) { const auto win = toWindow(window);
return qobject_cast<QWindow *>(window)->maximumSize(); return win ? win->maximumSize() : QSize();
}
#ifdef QT_WIDGETS_LIB
else if (window->isWidgetType()) {
return qobject_cast<QWidget *>(window)->maximumSize();
}
#endif
else {
reportError();
}
return {};
#endif #endif
} }
void FramelessWindowsManager::setMaximumSize(QObject *window, const QSize &value) void FramelessWindowsManager::setMaximumSize(WindowId window, const QSize &value)
{ {
Q_ASSERT(window); Q_ASSERT(window);
#ifdef Q_OS_WINDOWS #ifdef Q_OS_WINDOWS
@ -424,21 +281,14 @@ void FramelessWindowsManager::setMaximumSize(QObject *window, const QSize &value
data->maximumSize = value; data->maximumSize = value;
} }
#else #else
if (window->isWindowType()) { const auto win = toWindow(window);
qobject_cast<QWindow *>(window)->setMaximumSize(value); if (win) {
} win->setMaximumSize(value);
#ifdef QT_WIDGETS_LIB
else if (window->isWidgetType()) {
qobject_cast<QWidget *>(window)->setMaximumSize(value);
}
#endif
else {
reportError();
} }
#endif #endif
} }
bool FramelessWindowsManager::getTitleBarEnabled(QObject *window) bool FramelessWindowsManager::getTitleBarEnabled(WindowId window)
{ {
Q_ASSERT(window); Q_ASSERT(window);
#ifdef Q_OS_WINDOWS #ifdef Q_OS_WINDOWS
@ -449,7 +299,7 @@ bool FramelessWindowsManager::getTitleBarEnabled(QObject *window)
#endif #endif
} }
void FramelessWindowsManager::setTitleBarEnabled(QObject *window, const bool value) void FramelessWindowsManager::setTitleBarEnabled(WindowId window, const bool value)
{ {
Q_ASSERT(window); Q_ASSERT(window);
#ifdef Q_OS_WINDOWS #ifdef Q_OS_WINDOWS

View File

@ -27,6 +27,11 @@
#include "framelesshelper_global.h" #include "framelesshelper_global.h"
#include <QRect> #include <QRect>
#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
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
QT_FORWARD_DECLARE_CLASS(QObject) QT_FORWARD_DECLARE_CLASS(QObject)
QT_END_NAMESPACE QT_END_NAMESPACE
@ -46,41 +51,45 @@ class FRAMELESSHELPER_EXPORT FramelessWindowsManager
Q_DISABLE_COPY_MOVE(FramelessWindowsManager) Q_DISABLE_COPY_MOVE(FramelessWindowsManager)
public: public:
using WindowId =
#ifdef Q_OS_WINDOWS
void *
#else
QObject *
#endif
;
explicit FramelessWindowsManager(); explicit FramelessWindowsManager();
~FramelessWindowsManager() = default; ~FramelessWindowsManager() = default;
static void addWindow(QObject *window, const bool center = false); static void addWindow(WindowId window, const bool center = false);
static void moveWindowToDesktopCenter(QObject *window, const bool realCenter = true); static void moveWindowToDesktopCenter(WindowId window);
static QSize getDesktopSize(QObject *window = nullptr); static void addIgnoreArea(WindowId window, const QRect &area);
static QRect getDesktopAvailableGeometry(QObject *window = nullptr); static void addDraggableArea(WindowId window, const QRect &area);
static QSize getDesktopAvailableSize(QObject *window = nullptr);
static void addIgnoreArea(QObject *window, const QRect &area); static void addIgnoreObject(WindowId window, QObject *object);
static void addDraggableArea(QObject *window, const QRect &area); static void addDraggableObject(WindowId window, QObject *object);
static void addIgnoreObject(QObject *window, QObject *object); static int getBorderWidth(WindowId window);
static void addDraggableObject(QObject *window, QObject *object); static void setBorderWidth(WindowId window, const int value);
static int getBorderWidth(QObject *window); static int getBorderHeight(WindowId window);
static void setBorderWidth(QObject *window, const int value); static void setBorderHeight(WindowId window, const int value);
static int getBorderHeight(QObject *window); static int getTitleBarHeight(WindowId window);
static void setBorderHeight(QObject *window, const int value); static void setTitleBarHeight(WindowId window, const int value);
static int getTitleBarHeight(QObject *window); static bool getResizable(WindowId window);
static void setTitleBarHeight(QObject *window, const int value); static void setResizable(WindowId window, const bool value = true);
static bool getResizable(QObject *window); static QSize getMinimumSize(WindowId window);
static void setResizable(QObject *window, const bool value = true); static void setMinimumSize(WindowId window, const QSize &value);
static QSize getMinimumSize(QObject *window); static QSize getMaximumSize(WindowId window);
static void setMinimumSize(QObject *window, const QSize &value); static void setMaximumSize(WindowId window, const QSize &value);
static QSize getMaximumSize(QObject *window); static bool getTitleBarEnabled(WindowId window);
static void setMaximumSize(QObject *window, const QSize &value); static void setTitleBarEnabled(WindowId window, const bool value = true);
static bool getTitleBarEnabled(QObject *window);
static void setTitleBarEnabled(QObject *window, const bool value = true);
}; };

10
lib.pro
View File

@ -3,8 +3,10 @@ TEMPLATE = lib
win32: DLLDESTDIR = $$OUT_PWD/bin win32: DLLDESTDIR = $$OUT_PWD/bin
else: unix: DESTDIR = $$OUT_PWD/bin else: unix: DESTDIR = $$OUT_PWD/bin
QT += gui-private QT += gui-private
qtHaveModule(widgets): QT += widgets unix {
qtHaveModule(quick): QT += quick qtHaveModule(widgets): QT += widgets
qtHaveModule(quick): QT += quick
}
CONFIG += c++17 strict_c++ utf8_source warn_on CONFIG += c++17 strict_c++ utf8_source warn_on
DEFINES += \ DEFINES += \
QT_NO_CAST_FROM_ASCII \ QT_NO_CAST_FROM_ASCII \
@ -14,10 +16,6 @@ HEADERS += \
framelesshelper_global.h \ framelesshelper_global.h \
framelesswindowsmanager.h framelesswindowsmanager.h
SOURCES += framelesswindowsmanager.cpp SOURCES += framelesswindowsmanager.cpp
qtHaveModule(quick) {
HEADERS += framelessquickhelper.h
SOURCES += framelessquickhelper.cpp
}
win32 { win32 {
DEFINES += WIN32_LEAN_AND_MEAN _CRT_SECURE_NO_WARNINGS DEFINES += WIN32_LEAN_AND_MEAN _CRT_SECURE_NO_WARNINGS
CONFIG += LINK_TO_SYSTEM_DLL CONFIG += LINK_TO_SYSTEM_DLL

View File

@ -46,12 +46,6 @@
#else #else
#include <QSysInfo> #include <QSysInfo>
#endif #endif
#ifdef QT_QUICK_LIB
#include <QQuickItem>
#endif
#ifdef QT_WIDGETS_LIB
#include <QWidget>
#endif
#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0)) #if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
#include <qpa/qplatformnativeinterface.h> #include <qpa/qplatformnativeinterface.h>
#else #else
@ -1115,25 +1109,6 @@ void qCoreAppFixup()
} }
} }
HWND getHWNDFromQObject(QObject *object)
{
Q_ASSERT(object);
WId wid = 0;
if (object->isWindowType()) {
wid = qobject_cast<QWindow *>(object)->winId();
}
#ifdef QT_WIDGETS_LIB
else if (object->isWidgetType()) {
wid = qobject_cast<QWidget *>(object)->winId();
}
#endif
else {
qFatal(
"Can't acquire the window handle: only top level QWidgets and QWindows are accepted.");
}
return reinterpret_cast<HWND>(wid);
}
void updateQtFrame_internal(const HWND handle, const bool resetToDefault = false) void updateQtFrame_internal(const HWND handle, const bool resetToDefault = false)
{ {
Q_ASSERT(handle); Q_ASSERT(handle);
@ -1149,21 +1124,17 @@ void updateQtFrame_internal(const HWND handle, const bool resetToDefault = false
} }
} }
bool displaySystemMenu_internal(const HWND handle, const bool isRtl, const LPARAM lParam) bool displaySystemMenu_internal(const HWND handle, const LPARAM lParam)
{ {
Q_ASSERT(handle); Q_ASSERT(handle);
if (WNEF_EXECUTE_WINAPI_RETURN(IsWindow, FALSE, handle)) { if (WNEF_EXECUTE_WINAPI_RETURN(IsWindow, FALSE, handle)) {
const POINT globalMouse{GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)}; POINT localMouse = {GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)};
POINT localMouse = globalMouse;
WNEF_EXECUTE_WINAPI(ScreenToClient, handle, &localMouse) WNEF_EXECUTE_WINAPI(ScreenToClient, handle, &localMouse)
const int tbh = WinNativeEventFilter::getSystemMetric( const int tbh = WinNativeEventFilter::getSystemMetric(
handle, WinNativeEventFilter::SystemMetric::TitleBarHeight, true); handle, WinNativeEventFilter::SystemMetric::TitleBarHeight, true);
const bool isTitleBar = localMouse.y <= tbh; const bool isTitleBar = localMouse.y <= tbh;
if (isTitleBar && !IsFullScreen(handle)) { if (isTitleBar && !IsFullScreen(handle)) {
return WinNativeEventFilter::displaySystemMenu(handle, return WinNativeEventFilter::displaySystemMenu(handle);
isRtl,
globalMouse.x,
globalMouse.y);
} }
} }
return false; return false;
@ -1256,18 +1227,6 @@ void WinNativeEventFilter::addFramelessWindow(void *window,
} }
} }
void WinNativeEventFilter::addFramelessWindow(QObject *window,
const WINDOWDATA *data,
const bool center,
const int x,
const int y,
const int width,
const int height)
{
Q_ASSERT(window);
addFramelessWindow(getHWNDFromQObject(window), data, center, x, y, width, height);
}
void WinNativeEventFilter::removeFramelessWindow(void *window) void WinNativeEventFilter::removeFramelessWindow(void *window)
{ {
Q_ASSERT(window); Q_ASSERT(window);
@ -1282,12 +1241,6 @@ void WinNativeEventFilter::removeFramelessWindow(void *window)
updateWindow(window, true, false); updateWindow(window, true, false);
} }
void WinNativeEventFilter::removeFramelessWindow(QObject *window)
{
Q_ASSERT(window);
removeFramelessWindow(getHWNDFromQObject(window));
}
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) #if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
bool WinNativeEventFilter::nativeEventFilter(const QByteArray &eventType, bool WinNativeEventFilter::nativeEventFilter(const QByteArray &eventType,
void *message, void *message,
@ -1775,6 +1728,7 @@ bool WinNativeEventFilter::nativeEventFilter(const QByteArray &eventType,
*result = HTTRANSPARENT; *result = HTTRANSPARENT;
return true; return true;
} }
const auto isInSpecificAreas = const auto isInSpecificAreas =
[](const QPointF &mousePos, const QList<QRect> &areas, const qreal dpr) -> bool { [](const QPointF &mousePos, const QList<QRect> &areas, const qreal dpr) -> bool {
if (areas.isEmpty()) { if (areas.isEmpty()) {
@ -1794,7 +1748,6 @@ bool WinNativeEventFilter::nativeEventFilter(const QByteArray &eventType,
} }
return false; return false;
}; };
#if defined(QT_WIDGETS_LIB) || defined(QT_QUICK_LIB)
const auto isInSpecificObjects = [](const QPointF &mousePos, const auto isInSpecificObjects = [](const QPointF &mousePos,
const QList<QObject *> &objects, const QList<QObject *> &objects,
const qreal dpr) -> bool { const qreal dpr) -> bool {
@ -1805,40 +1758,34 @@ bool WinNativeEventFilter::nativeEventFilter(const QByteArray &eventType,
if (!object) { if (!object) {
continue; continue;
} }
#ifdef QT_WIDGETS_LIB const bool isWidget = object->inherits("QWidget");
const auto widget = qobject_cast<QWidget *>(object); const bool isQuickItem = object->inherits("QQuickItem");
if (widget) { if (!isWidget && !isQuickItem) {
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) qWarning() << object << "is not a QWidget or QQuickItem!";
const QPointF pos = widget->mapToGlobal(QPointF{0, 0}); continue;
#else
const QPoint pos = widget->mapToGlobal(QPoint{0, 0});
#endif
if (QRectF(pos.x() * dpr,
pos.y() * dpr,
widget->width() * dpr,
widget->height() * dpr)
.contains(mousePos)) {
return true;
}
} }
#endif const auto mapOriginPointToWindow = [](const QObject *obj) -> QPointF {
#ifdef QT_QUICK_LIB Q_ASSERT(obj);
const auto quickItem = qobject_cast<QQuickItem *>(object); QPointF point = {obj->property("x").toReal(), obj->property("y").toReal()};
if (quickItem) { for (QObject *parent = obj->parent(); parent; parent = parent->parent()) {
const QPointF pos = quickItem->mapToGlobal(QPointF{0, 0}); point += {parent->property("x").toReal(),
if (QRectF(pos.x() * dpr, parent->property("y").toReal()};
pos.y() * dpr,
quickItem->width() * dpr,
quickItem->height() * dpr)
.contains(mousePos)) {
return true;
} }
return point;
};
const QPointF originPoint = mapOriginPointToWindow(object);
const qreal width = object->property("width").toReal();
const qreal height = object->property("height").toReal();
if (QRectF(originPoint.x() * dpr,
originPoint.y() * dpr,
width * dpr,
height * dpr)
.contains(mousePos)) {
return true;
} }
#endif
} }
return false; return false;
}; };
#endif
const qreal dpr = GetDevicePixelRatioForWindow(msg->hwnd); const qreal dpr = GetDevicePixelRatioForWindow(msg->hwnd);
const QPointF globalMouse = QCursor::pos() * dpr; const QPointF globalMouse = QCursor::pos() * dpr;
POINT winLocalMouse = {qRound(globalMouse.x()), qRound(globalMouse.y())}; POINT winLocalMouse = {qRound(globalMouse.x()), qRound(globalMouse.y())};
@ -1852,7 +1799,6 @@ bool WinNativeEventFilter::nativeEventFilter(const QByteArray &eventType,
data->draggableAreas, data->draggableAreas,
dpr) dpr)
: true; : true;
#if defined(QT_WIDGETS_LIB) || defined(QT_QUICK_LIB)
const bool isInIgnoreObjects = isInSpecificObjects(globalMouse, const bool isInIgnoreObjects = isInSpecificObjects(globalMouse,
data->ignoreObjects, data->ignoreObjects,
dpr); dpr);
@ -1862,14 +1808,6 @@ bool WinNativeEventFilter::nativeEventFilter(const QByteArray &eventType,
data->draggableObjects, data->draggableObjects,
dpr) dpr)
: true; : true;
#else
// Don't block resizing if both of the Qt Widgets module and Qt
// Quick module are not compiled in, although there's not much
// significance of using this code in this case.
const bool isInIgnoreObjects = false;
const bool isInDraggableObjects = true;
const bool customDragObjects = false;
#endif
const bool customDrag = customDragAreas || customDragObjects; const bool customDrag = customDragAreas || customDragObjects;
const bool isResizePermitted = !isInIgnoreAreas && !isInIgnoreObjects; const bool isResizePermitted = !isInIgnoreAreas && !isInIgnoreObjects;
const int bh = getSystemMetric(msg->hwnd, SystemMetric::BorderHeight, true); const int bh = getSystemMetric(msg->hwnd, SystemMetric::BorderHeight, true);
@ -2071,7 +2009,7 @@ bool WinNativeEventFilter::nativeEventFilter(const QByteArray &eventType,
// (SHIFT + F10 or the context menu key), lParam will be -1. // (SHIFT + F10 or the context menu key), lParam will be -1.
const LPARAM lParam = (msg->lParam == -1) ? WNEF_EXECUTE_WINAPI_RETURN(GetMessagePos, 0) const LPARAM lParam = (msg->lParam == -1) ? WNEF_EXECUTE_WINAPI_RETURN(GetMessagePos, 0)
: msg->lParam; : msg->lParam;
if (displaySystemMenu_internal(msg->hwnd, false, lParam)) { if (displaySystemMenu_internal(msg->hwnd, lParam)) {
// The WM_CONTEXTMENU message has no return value so there's // The WM_CONTEXTMENU message has no return value so there's
// no need to modify *result. // no need to modify *result.
return true; return true;
@ -2107,12 +2045,6 @@ void WinNativeEventFilter::setWindowData(void *window, const WINDOWDATA *data)
} }
} }
void WinNativeEventFilter::setWindowData(QObject *window, const WINDOWDATA *data)
{
Q_ASSERT(window);
setWindowData(getHWNDFromQObject(window), data);
}
WinNativeEventFilter::WINDOWDATA *WinNativeEventFilter::getWindowData(void *window) WinNativeEventFilter::WINDOWDATA *WinNativeEventFilter::getWindowData(void *window)
{ {
Q_ASSERT(window); Q_ASSERT(window);
@ -2125,12 +2057,6 @@ WinNativeEventFilter::WINDOWDATA *WinNativeEventFilter::getWindowData(void *wind
return nullptr; return nullptr;
} }
WinNativeEventFilter::WINDOWDATA *WinNativeEventFilter::getWindowData(QObject *window)
{
Q_ASSERT(window);
return getWindowData(getHWNDFromQObject(window));
}
void WinNativeEventFilter::setBorderWidth(const int bw) void WinNativeEventFilter::setBorderWidth(const int bw)
{ {
coreData()->m_borderWidth = bw; coreData()->m_borderWidth = bw;
@ -2337,10 +2263,7 @@ void WinNativeEventFilter::updateQtFrame(QWindow *window, const int titleBarHeig
} }
} }
bool WinNativeEventFilter::displaySystemMenu(void *handle, bool WinNativeEventFilter::displaySystemMenu(void *handle, const QPointF &pos)
const bool isRtl,
const int x,
const int y)
{ {
Q_ASSERT(handle); Q_ASSERT(handle);
const auto hwnd = reinterpret_cast<HWND>(handle); const auto hwnd = reinterpret_cast<HWND>(handle);
@ -2376,15 +2299,20 @@ bool WinNativeEventFilter::displaySystemMenu(void *handle,
WNEF_EXECUTE_WINAPI(SetMenuItemInfoW, hMenu, SC_RESTORE, FALSE, &mii) WNEF_EXECUTE_WINAPI(SetMenuItemInfoW, hMenu, SC_RESTORE, FALSE, &mii)
} }
} }
const QPointF mousePos = pos.isNull()
? QCursor::pos() * GetDevicePixelRatioForWindow(hwnd)
: pos;
const LPARAM cmd = WNEF_EXECUTE_WINAPI_RETURN(TrackPopupMenu, const LPARAM cmd = WNEF_EXECUTE_WINAPI_RETURN(TrackPopupMenu,
0, 0,
hMenu, hMenu,
(TPM_LEFTBUTTON | TPM_RIGHTBUTTON (TPM_LEFTBUTTON | TPM_RIGHTBUTTON
| TPM_RETURNCMD | TPM_TOPALIGN | TPM_RETURNCMD | TPM_TOPALIGN
| (isRtl ? TPM_RIGHTALIGN | (QGuiApplication::layoutDirection()
: TPM_LEFTALIGN)), == Qt::RightToLeft
x, ? TPM_RIGHTALIGN
y, : TPM_LEFTALIGN)),
qRound(mousePos.x()),
qRound(mousePos.y()),
0, 0,
hwnd, hwnd,
nullptr); nullptr);

View File

@ -79,26 +79,16 @@ public:
const int y = -1, const int y = -1,
const int width = -1, const int width = -1,
const int height = -1); const int height = -1);
static void addFramelessWindow(QObject *window,
const WINDOWDATA *data = nullptr,
const bool center = false,
const int x = -1,
const int y = -1,
const int width = -1,
const int height = -1);
static void removeFramelessWindow(void *window /* HWND */); static void removeFramelessWindow(void *window /* HWND */);
static void removeFramelessWindow(QObject *window);
// Set borderWidth, borderHeight or titleBarHeight to a negative value to // Set borderWidth, borderHeight or titleBarHeight to a negative value to
// restore default behavior. // restore default behavior.
// Note that it can only affect one specific window. // Note that it can only affect one specific window.
// If you want to change these values globally, use setBorderWidth instead. // If you want to change these values globally, use setBorderWidth instead.
static void setWindowData(void *window /* HWND */, const WINDOWDATA *data); static void setWindowData(void *window /* HWND */, const WINDOWDATA *data);
static void setWindowData(QObject *window, const WINDOWDATA *data);
// You can modify the given window's data directly, it's the same with using // You can modify the given window's data directly, it's the same with using
// setWindowData. // setWindowData.
static WINDOWDATA *getWindowData(void *window /* HWND */); static WINDOWDATA *getWindowData(void *window /* HWND */);
static WINDOWDATA *getWindowData(QObject *window);
// Change settings globally, not a specific window. // Change settings globally, not a specific window.
// These values will be scaled automatically according to DPI, don't scale // These values will be scaled automatically according to DPI, don't scale
@ -135,10 +125,7 @@ public:
static void updateQtFrame(QWindow *window, const int titleBarHeight); static void updateQtFrame(QWindow *window, const int titleBarHeight);
// Display the system context menu. // Display the system context menu.
static bool displaySystemMenu(void *handle /* HWND */, static bool displaySystemMenu(void *handle /* HWND */, const QPointF &pos = {});
const bool isRtl,
const int x,
const int y);
// Enable or disable the blur effect for a specific window. // Enable or disable the blur effect for a specific window.
// On Win10 it's the Acrylic effect. // On Win10 it's the Acrylic effect.