Minor improvements.

Use global screen coordinates instead of local window coordinates to get more reliable hit test result.

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
This commit is contained in:
Yuhang Zhao 2020-05-13 12:56:03 +08:00
parent 2ca6a90ae2
commit 921b87ab2e
5 changed files with 245 additions and 100 deletions

View File

@ -156,6 +156,20 @@ void FramelessHelper::setIgnoreAreas(QObject *const obj,
} }
} }
void FramelessHelper::addIgnoreArea(QObject *const obj, const QRect &val) {
if (obj) {
QVector<QRect> areas = m_ignoreAreas[obj];
areas.append(val);
m_ignoreAreas[obj] = areas;
}
}
void FramelessHelper::clearIgnoreAreas(QObject *const obj) {
if (obj) {
m_ignoreAreas[obj] = {};
}
}
QVector<QRect> FramelessHelper::getDraggableAreas(QObject *const obj) const { QVector<QRect> FramelessHelper::getDraggableAreas(QObject *const obj) const {
if (!obj) { if (!obj) {
return {}; return {};
@ -170,33 +184,117 @@ void FramelessHelper::setDraggableAreas(QObject *const obj,
} }
} }
QVector<QPointer<QObject>> void FramelessHelper::addDraggableArea(QObject *const obj, const QRect &val) {
FramelessHelper::getIgnoreObjects(QObject *const obj) const { if (obj) {
QVector<QRect> areas = m_draggableAreas[obj];
areas.append(val);
m_draggableAreas[obj] = areas;
}
}
void FramelessHelper::clearDraggableAreas(QObject *const obj) {
if (obj) {
m_draggableAreas[obj] = {};
}
}
QVector<QObject *> FramelessHelper::getIgnoreObjects(QObject *const obj) const {
if (!obj) { if (!obj) {
return {}; return {};
} }
return m_ignoreObjects.value(obj); QVector<QObject *> ret{};
const QVector<QPointer<QObject>> objs = m_ignoreObjects.value(obj);
if (!objs.isEmpty()) {
for (auto &&obj : qAsConst(objs)) {
if (obj) {
ret.append(obj);
}
}
}
return ret;
} }
void FramelessHelper::setIgnoreObjects(QObject *const obj, void FramelessHelper::setIgnoreObjects(QObject *const obj,
const QVector<QPointer<QObject>> &val) { const QVector<QObject *> &val) {
if (obj) { if (obj) {
m_ignoreObjects[obj] = val; QVector<QPointer<QObject>> objs{};
if (!val.isEmpty()) {
for (auto &&obj : qAsConst(val)) {
objs.append(obj);
}
}
m_ignoreObjects[obj] = objs;
} }
} }
QVector<QPointer<QObject>> void FramelessHelper::addIgnoreObject(QObject *const obj, QObject *val) {
if (obj) {
QVector<QPointer<QObject>> objs = m_ignoreObjects[obj];
objs.append(val);
m_ignoreObjects[obj] = objs;
}
}
void FramelessHelper::clearIgnoreObjects(QObject *const obj) {
if (obj) {
m_ignoreObjects[obj] = {};
}
}
QVector<QObject *>
FramelessHelper::getDraggableObjects(QObject *const obj) const { FramelessHelper::getDraggableObjects(QObject *const obj) const {
if (!obj) { if (!obj) {
return {}; return {};
} }
return m_draggableObjects.value(obj); QVector<QObject *> ret{};
const QVector<QPointer<QObject>> objs = m_draggableObjects.value(obj);
if (!objs.isEmpty()) {
for (auto &&obj : qAsConst(objs)) {
if (obj) {
ret.append(obj);
}
}
}
return ret;
} }
void FramelessHelper::setDraggableObjects( void FramelessHelper::setDraggableObjects(QObject *const obj,
QObject *const obj, const QVector<QPointer<QObject>> &val) { const QVector<QObject *> &val) {
if (obj) { if (obj) {
m_draggableObjects[obj] = val; QVector<QPointer<QObject>> objs{};
if (!val.isEmpty()) {
for (auto &&obj : qAsConst(val)) {
objs.append(obj);
}
}
m_draggableObjects[obj] = objs;
}
}
void FramelessHelper::addDraggableObject(QObject *const obj, QObject *val) {
if (obj) {
QVector<QPointer<QObject>> objs = m_draggableObjects[obj];
objs.append(val);
m_draggableObjects[obj] = objs;
}
}
void FramelessHelper::clearDraggableObjects(QObject *const obj) {
if (obj) {
m_draggableObjects[obj] = {};
}
}
bool FramelessHelper::getResizable(QObject *const obj) const {
if (!obj) {
return true;
}
return !m_fixedSize.value(obj);
}
void FramelessHelper::setResizable(QObject *const obj, const bool val) {
if (obj) {
m_fixedSize[obj] = !val;
} }
} }
@ -313,7 +411,7 @@ bool FramelessHelper::eventFilter(QObject *object, QEvent *event) {
}; };
const auto isInSpecificObjects = const auto isInSpecificObjects =
[](const int x, const int y, [](const int x, const int y,
const QVector<QPointer<QObject>> &objects) -> bool { const QVector<QObject *> &objects) -> bool {
if (!objects.isEmpty()) { if (!objects.isEmpty()) {
for (auto &&obj : qAsConst(objects)) { for (auto &&obj : qAsConst(objects)) {
if (!obj) { if (!obj) {
@ -322,7 +420,8 @@ bool FramelessHelper::eventFilter(QObject *object, QEvent *event) {
#ifdef QT_WIDGETS_LIB #ifdef QT_WIDGETS_LIB
const auto widget = qobject_cast<QWidget *>(obj); const auto widget = qobject_cast<QWidget *>(obj);
if (widget) { if (widget) {
if (QRect(widget->x(), widget->y(), widget->width(), const QPoint pos = widget->mapToGlobal({0, 0});
if (QRect(pos.x(), pos.y(), widget->width(),
widget->height()) widget->height())
.contains(x, y)) { .contains(x, y)) {
return true; return true;
@ -332,9 +431,9 @@ bool FramelessHelper::eventFilter(QObject *object, QEvent *event) {
#ifdef QT_QUICK_LIB #ifdef QT_QUICK_LIB
const auto quickItem = qobject_cast<QQuickItem *>(obj); const auto quickItem = qobject_cast<QQuickItem *>(obj);
if (quickItem) { if (quickItem) {
const auto pos = quickItem->mapToScene({0, 0}); const QPointF pos = quickItem->mapToGlobal({0, 0});
if (QRect(pos.x(), pos.y(), quickItem->width(), if (QRectF(pos.x(), pos.y(), quickItem->width(),
quickItem->height()) quickItem->height())
.contains(x, y)) { .contains(x, y)) {
return true; return true;
} }
@ -396,40 +495,44 @@ bool FramelessHelper::eventFilter(QObject *object, QEvent *event) {
#endif #endif
}; };
const auto isResizePermitted = const auto isResizePermitted =
[&isInIgnoreAreas, &isInIgnoreObjects](const QPointF &point, [&isInIgnoreAreas, &isInIgnoreObjects](const QPointF &globalPoint,
const QPointF &point,
QObject *const window) -> bool { QObject *const window) -> bool {
if (!window) { if (!window) {
return false; return false;
} }
return (!isInIgnoreAreas(point, window) && return (!isInIgnoreAreas(point, window) &&
!isInIgnoreObjects(point, window)); !isInIgnoreObjects(globalPoint, window));
}; };
const auto isInTitlebarArea = const auto isInTitlebarArea =
[this, &isInDraggableAreas, &isInDraggableObjects, &isResizePermitted]( [this, &isInDraggableAreas, &isInDraggableObjects,
const QPointF &point, QObject *const window) -> bool { &isResizePermitted](const QPointF &globalPoint, const QPointF &point,
QObject *const window) -> bool {
if (window) { if (window) {
return ((point.y() <= m_titleBarHeight) && return ((point.y() <= m_titleBarHeight) &&
isInDraggableAreas(point, window) && isInDraggableAreas(point, window) &&
isInDraggableObjects(point, window) && isInDraggableObjects(globalPoint, window) &&
isResizePermitted(point, window)); isResizePermitted(globalPoint, point, window));
} }
return false; return false;
}; };
const auto moveOrResize = [&getWindowEdges, &isResizePermitted, const auto moveOrResize = [this, &getWindowEdges, &isResizePermitted,
&isInTitlebarArea](const QPointF &point, &isInTitlebarArea](const QPointF &globalPoint,
const QPointF &point,
QObject *const object) { QObject *const object) {
QWindow *const window = getWindowHandle(object); QWindow *const window = getWindowHandle(object);
if (window) { if (window) {
const Qt::Edges edges = const Qt::Edges edges =
getWindowEdges(point, window->width(), window->height()); getWindowEdges(point, window->width(), window->height());
if (edges == Qt::Edges{}) { if (edges == Qt::Edges{}) {
if (isInTitlebarArea(point, object)) { if (isInTitlebarArea(globalPoint, point, object)) {
window->startSystemMove(); window->startSystemMove();
} }
} else { } else {
if (window->windowStates().testFlag( if (window->windowStates().testFlag(
Qt::WindowState::WindowNoState) && Qt::WindowState::WindowNoState) &&
isResizePermitted(point, object)) { isResizePermitted(globalPoint, point, object) &&
getResizable(object)) {
window->startSystemResize(edges); window->startSystemResize(edges);
} }
} }
@ -445,7 +548,8 @@ bool FramelessHelper::eventFilter(QObject *object, QEvent *event) {
if (mouseEvent->button() != Qt::MouseButton::LeftButton) { if (mouseEvent->button() != Qt::MouseButton::LeftButton) {
break; break;
} }
if (isInTitlebarArea(mouseEvent->localPos(), object)) { if (isInTitlebarArea(mouseEvent->screenPos(),
mouseEvent->windowPos(), object)) {
// ### FIXME: If the current object is a QWidget, we can use // ### FIXME: If the current object is a QWidget, we can use
// getWindowHandle(object) to get the window handle, but if we // getWindowHandle(object) to get the window handle, but if we
// call showMaximized() of that window, it will not be // call showMaximized() of that window, it will not be
@ -494,7 +598,8 @@ bool FramelessHelper::eventFilter(QObject *object, QEvent *event) {
if (mouseEvent->button() != Qt::MouseButton::LeftButton) { if (mouseEvent->button() != Qt::MouseButton::LeftButton) {
break; break;
} }
moveOrResize(mouseEvent->localPos(), object); moveOrResize(mouseEvent->screenPos(), mouseEvent->windowPos(),
object);
} }
} break; } break;
case QEvent::MouseMove: { case QEvent::MouseMove: {
@ -503,9 +608,10 @@ bool FramelessHelper::eventFilter(QObject *object, QEvent *event) {
QWindow *const window = getWindowHandle(object); QWindow *const window = getWindowHandle(object);
if (window) { if (window) {
if (window->windowStates().testFlag( if (window->windowStates().testFlag(
Qt::WindowState::WindowNoState)) { Qt::WindowState::WindowNoState) &&
getResizable(object)) {
window->setCursor(getCursorShape( window->setCursor(getCursorShape(
getWindowEdges(mouseEvent->localPos(), window->width(), getWindowEdges(mouseEvent->windowPos(), window->width(),
window->height()))); window->height())));
} }
} }
@ -514,9 +620,9 @@ bool FramelessHelper::eventFilter(QObject *object, QEvent *event) {
const auto widget = qobject_cast<QWidget *>(object); const auto widget = qobject_cast<QWidget *>(object);
if (widget) { if (widget) {
if (!widget->isMinimized() && !widget->isMaximized() && if (!widget->isMinimized() && !widget->isMaximized() &&
!widget->isFullScreen()) { !widget->isFullScreen() && getResizable(object)) {
widget->setCursor(getCursorShape( widget->setCursor(getCursorShape(
getWindowEdges(mouseEvent->localPos(), getWindowEdges(mouseEvent->windowPos(),
widget->width(), widget->height()))); widget->width(), widget->height())));
} }
} }
@ -525,11 +631,11 @@ bool FramelessHelper::eventFilter(QObject *object, QEvent *event) {
} }
} break; } break;
case QEvent::TouchBegin: case QEvent::TouchBegin:
case QEvent::TouchUpdate: case QEvent::TouchUpdate: {
moveOrResize( const auto point =
static_cast<QTouchEvent *>(event)->touchPoints().first().pos(), static_cast<QTouchEvent *>(event)->touchPoints().first();
object); moveOrResize(point.screenPos(), point.pos(), object);
break; } break;
default: default:
break; break;
} }

View File

@ -24,7 +24,7 @@
#pragma once #pragma once
#include <QMap> #include <QHash>
#include <QObject> #include <QObject>
#include <QPointer> #include <QPointer>
#include <QRect> #include <QRect>
@ -56,17 +56,26 @@ public:
QVector<QRect> getIgnoreAreas(QObject *const obj) const; QVector<QRect> getIgnoreAreas(QObject *const obj) const;
void setIgnoreAreas(QObject *const obj, const QVector<QRect> &val); void setIgnoreAreas(QObject *const obj, const QVector<QRect> &val);
void addIgnoreArea(QObject *const obj, const QRect &val);
void clearIgnoreAreas(QObject *const obj);
QVector<QRect> getDraggableAreas(QObject *const obj) const; QVector<QRect> getDraggableAreas(QObject *const obj) const;
void setDraggableAreas(QObject *const obj, const QVector<QRect> &val); void setDraggableAreas(QObject *const obj, const QVector<QRect> &val);
void addDraggableArea(QObject *const obj, const QRect &val);
void clearDraggableAreas(QObject *const obj);
QVector<QPointer<QObject>> getIgnoreObjects(QObject *const obj) const; QVector<QObject *> getIgnoreObjects(QObject *const obj) const;
void setIgnoreObjects(QObject *const obj, void setIgnoreObjects(QObject *const obj, const QVector<QObject *> &val);
const QVector<QPointer<QObject>> &val); void addIgnoreObject(QObject *const obj, QObject *val);
void clearIgnoreObjects(QObject *const obj);
QVector<QPointer<QObject>> getDraggableObjects(QObject *const obj) const; QVector<QObject *> getDraggableObjects(QObject *const obj) const;
void setDraggableObjects(QObject *const obj, void setDraggableObjects(QObject *const obj, const QVector<QObject *> &val);
const QVector<QPointer<QObject>> &val); void addDraggableObject(QObject *const obj, QObject *val);
void clearDraggableObjects(QObject *const obj);
bool getResizable(QObject *const obj) const;
void setResizable(QObject *const obj, const bool val);
void removeWindowFrame(QObject *const obj); void removeWindowFrame(QObject *const obj);
@ -78,8 +87,8 @@ private:
// the scale factor is 1.0. Don't know how to acquire these values on UNIX // the scale factor is 1.0. Don't know how to acquire these values on UNIX
// platforms through native API. // platforms through native API.
int m_borderWidth = 8, m_borderHeight = 8, m_titleBarHeight = 30; int m_borderWidth = 8, m_borderHeight = 8, m_titleBarHeight = 30;
QMap<QPointer<QObject>, QVector<QRect>> m_ignoreAreas = {}, QHash<QObject *, QVector<QRect>> m_ignoreAreas = {}, m_draggableAreas = {};
m_draggableAreas = {}; QHash<QObject *, QVector<QPointer<QObject>>> m_ignoreObjects = {},
QMap<QPointer<QObject>, QVector<QPointer<QObject>>> m_ignoreObjects = {}, m_draggableObjects = {};
m_draggableObjects = {}; QHash<QObject *, bool> m_fixedSize = {};
}; };

View File

@ -26,8 +26,6 @@
#ifdef Q_OS_WINDOWS #ifdef Q_OS_WINDOWS
#include "winnativeeventfilter.h" #include "winnativeeventfilter.h"
#else
#include "framelesshelper.h"
#endif #endif
#include <QQuickWindow> #include <QQuickWindow>
@ -150,9 +148,9 @@ void FramelessQuickHelper::setTitleBarHeight(const int val) {
} }
bool FramelessQuickHelper::resizable() const { bool FramelessQuickHelper::resizable() const {
#ifdef Q_OS_WINDOWS
const auto win = window(); const auto win = window();
if (win) { if (win) {
#ifdef Q_OS_WINDOWS
const auto hWnd = reinterpret_cast<HWND>(win->winId()); const auto hWnd = reinterpret_cast<HWND>(win->winId());
if (hWnd) { if (hWnd) {
const auto data = WinNativeEventFilter::windowData(hWnd); const auto data = WinNativeEventFilter::windowData(hWnd);
@ -160,18 +158,17 @@ bool FramelessQuickHelper::resizable() const {
return !data->fixedSize; return !data->fixedSize;
} }
} }
#else
return m_framelessHelper.getResizable(win);
#endif
} }
return true; return true;
#else
// ### TODO: impl
return true;
#endif
} }
void FramelessQuickHelper::setResizable(const bool val) { void FramelessQuickHelper::setResizable(const bool val) {
#ifdef Q_OS_WINDOWS
const auto win = window(); const auto win = window();
if (win) { if (win) {
#ifdef Q_OS_WINDOWS
const auto hWnd = reinterpret_cast<HWND>(win->winId()); const auto hWnd = reinterpret_cast<HWND>(win->winId());
if (hWnd) { if (hWnd) {
const auto data = WinNativeEventFilter::windowData(hWnd); const auto data = WinNativeEventFilter::windowData(hWnd);
@ -180,11 +177,10 @@ void FramelessQuickHelper::setResizable(const bool val) {
Q_EMIT resizableChanged(val); Q_EMIT resizableChanged(val);
} }
} }
}
#else #else
// ### TODO: impl m_framelessHelper.setResizable(win, val);
Q_UNUSED(val)
#endif #endif
}
} }
void FramelessQuickHelper::removeWindowFrame(const bool center) { void FramelessQuickHelper::removeWindowFrame(const bool center) {
@ -233,7 +229,7 @@ void FramelessQuickHelper::clearIgnoreAreas() {
} }
} }
#else #else
m_framelessHelper.setIgnoreAreas(win, {}); m_framelessHelper.clearIgnoreAreas(win);
#endif #endif
} }
} }
@ -250,9 +246,7 @@ void FramelessQuickHelper::addIgnoreArea(const QRect &val) {
} }
} }
#else #else
QVector<QRect> areas = m_framelessHelper.getIgnoreAreas(win); m_framelessHelper.addIgnoreArea(win, val);
areas.append(val);
m_framelessHelper.setIgnoreAreas(win, areas);
#endif #endif
} }
} }
@ -286,7 +280,7 @@ void FramelessQuickHelper::clearDraggableAreas() {
} }
} }
#else #else
m_framelessHelper.setDraggableAreas(win, {}); m_framelessHelper.clearDraggableAreas(win);
#endif #endif
} }
} }
@ -303,9 +297,7 @@ void FramelessQuickHelper::addDraggableArea(const QRect &val) {
} }
} }
#else #else
QVector<QRect> areas = m_framelessHelper.getDraggableAreas(win); m_framelessHelper.addDraggableArea(win, val);
areas.append(val);
m_framelessHelper.setDraggableAreas(win, areas);
#endif #endif
} }
} }
@ -327,7 +319,7 @@ void FramelessQuickHelper::setIgnoreObjects(const QVector<QQuickItem *> &val) {
} }
} }
#else #else
QVector<QPointer<QObject>> objs; QVector<QObject *> objs{};
if (!val.isEmpty()) { if (!val.isEmpty()) {
for (auto &&obj : qAsConst(val)) { for (auto &&obj : qAsConst(val)) {
objs.append(obj); objs.append(obj);
@ -350,7 +342,7 @@ void FramelessQuickHelper::clearIgnoreObjects() {
} }
} }
#else #else
m_framelessHelper.setIgnoreObjects(win, {}); m_framelessHelper.clearIgnoreObjects(win);
#endif #endif
} }
} }
@ -367,10 +359,7 @@ void FramelessQuickHelper::addIgnoreObject(QQuickItem *val) {
} }
} }
#else #else
QVector<QPointer<QObject>> objs = m_framelessHelper.addIgnoreObject(win, val);
m_framelessHelper.getIgnoreObjects(win);
objs.append(val);
m_framelessHelper.setIgnoreObjects(win, objs);
#endif #endif
} }
} }
@ -393,7 +382,7 @@ void FramelessQuickHelper::setDraggableObjects(
} }
} }
#else #else
QVector<QPointer<QObject>> objs; QVector<QObject *> objs{};
if (!val.isEmpty()) { if (!val.isEmpty()) {
for (auto &&obj : qAsConst(val)) { for (auto &&obj : qAsConst(val)) {
objs.append(obj); objs.append(obj);
@ -416,7 +405,7 @@ void FramelessQuickHelper::clearDraggableObjects() {
} }
} }
#else #else
m_framelessHelper.setDraggableObjects(win, {}); m_framelessHelper.clearDraggableObjects(win);
#endif #endif
} }
} }
@ -433,10 +422,7 @@ void FramelessQuickHelper::addDraggableObject(QQuickItem *val) {
} }
} }
#else #else
QVector<QPointer<QObject>> objs = m_framelessHelper.addDraggableObject(win, val);
m_framelessHelper.getDraggableObjects(win);
objs.append(val);
m_framelessHelper.setDraggableObjects(win, objs);
#endif #endif
} }
} }

View File

@ -1,5 +1,9 @@
#include "framelesshelper.h" #include "framelesshelper.h"
#include <QApplication> #include <QApplication>
#include <QHBoxLayout>
#include <QLabel>
#include <QPushButton>
#include <QVBoxLayout>
#include <QWidget> #include <QWidget>
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
@ -26,6 +30,48 @@ int main(int argc, char *argv[]) {
FramelessHelper helper; FramelessHelper helper;
QWidget widget; QWidget widget;
widget.setContentsMargins(0, 0, 0, 0);
QLabel *label = new QLabel;
label->setText(QObject::tr("Hello, World!"));
QObject::connect(&widget, &QWidget::windowTitleChanged, label,
&QLabel::setText);
QPushButton *minimizeButton = new QPushButton;
minimizeButton->setText(QObject::tr("Minimize"));
QObject::connect(minimizeButton, &QPushButton::clicked, &widget,
&QWidget::showMinimized);
QPushButton *maximizeButton = new QPushButton;
maximizeButton->setText(QObject::tr("Maximize"));
QObject::connect(maximizeButton, &QPushButton::clicked,
[&widget, &maximizeButton]() {
if (widget.isMaximized()) {
widget.showNormal();
maximizeButton->setText(QObject::tr("Maximize"));
} else {
widget.showMaximized();
maximizeButton->setText(QObject::tr("Restore"));
}
});
QPushButton *closeButton = new QPushButton;
closeButton->setText(QObject::tr("Close"));
QObject::connect(closeButton, &QPushButton::clicked, &widget,
&QWidget::close);
QHBoxLayout *tbLayout = new QHBoxLayout;
tbLayout->setContentsMargins(0, 0, 0, 0);
tbLayout->setSpacing(0);
tbLayout->addSpacing(15);
tbLayout->addWidget(label);
tbLayout->addStretch();
tbLayout->addWidget(minimizeButton);
tbLayout->addWidget(maximizeButton);
tbLayout->addWidget(closeButton);
QVBoxLayout *mainLayout = new QVBoxLayout;
mainLayout->setContentsMargins(0, 0, 0, 0);
mainLayout->setSpacing(0);
mainLayout->addLayout(tbLayout);
mainLayout->addStretch();
widget.setLayout(mainLayout);
helper.setIgnoreObjects(&widget,
{minimizeButton, maximizeButton, closeButton});
helper.removeWindowFrame(&widget); helper.removeWindowFrame(&widget);
widget.resize(800, 600); widget.resize(800, 600);
FramelessHelper::moveWindowToDesktopCenter(&widget); FramelessHelper::moveWindowToDesktopCenter(&widget);

View File

@ -950,6 +950,7 @@ bool WinNativeEventFilter::nativeEventFilter(const QByteArray &eventType,
m_lpSetWindowLongPtrW(msg->hwnd, GWL_STYLE, m_lpSetWindowLongPtrW(msg->hwnd, GWL_STYLE,
WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN |
WS_CLIPSIBLINGS); WS_CLIPSIBLINGS);
updateWindow(msg->hwnd, true, false);
} }
if (!data->windowData.doNotEnableLayeredWindow) { if (!data->windowData.doNotEnableLayeredWindow) {
// Turn our window into a layered window to get better // Turn our window into a layered window to get better
@ -961,6 +962,7 @@ bool WinNativeEventFilter::nativeEventFilter(const QByteArray &eventType,
// currently. // currently.
m_lpSetWindowLongPtrW(msg->hwnd, GWL_EXSTYLE, m_lpSetWindowLongPtrW(msg->hwnd, GWL_EXSTYLE,
WS_EX_APPWINDOW | WS_EX_LAYERED); WS_EX_APPWINDOW | WS_EX_LAYERED);
updateWindow(msg->hwnd, true, false);
// A layered window can't be visible unless we call // A layered window can't be visible unless we call
// SetLayeredWindowAttributes or UpdateLayeredWindow once. // SetLayeredWindowAttributes or UpdateLayeredWindow once.
m_lpSetLayeredWindowAttributes(msg->hwnd, RGB(255, 0, 255), 0, m_lpSetLayeredWindowAttributes(msg->hwnd, RGB(255, 0, 255), 0,
@ -968,9 +970,6 @@ bool WinNativeEventFilter::nativeEventFilter(const QByteArray &eventType,
} }
// Bring our frame shadow back through DWM, don't draw it manually. // Bring our frame shadow back through DWM, don't draw it manually.
UpdateFrameMarginsForWindow(msg->hwnd); UpdateFrameMarginsForWindow(msg->hwnd);
// Trigger a frame change event to let us enter the WM_NCCALCSIZE
// message to remove our title bar as early as possible.
updateWindow(msg->hwnd, true, false);
} }
switch (msg->message) { switch (msg->message) {
case WM_NCCALCSIZE: { case WM_NCCALCSIZE: {
@ -1287,10 +1286,8 @@ bool WinNativeEventFilter::nativeEventFilter(const QByteArray &eventType,
if (!area.isValid()) { if (!area.isValid()) {
continue; continue;
} }
if (QRect(qRound(area.x() * dpr), if (QRectF(area.x() * dpr, area.y() * dpr,
qRound(area.y() * dpr), area.width() * dpr, area.height() * dpr)
qRound(area.width() * dpr),
qRound(area.height() * dpr))
.contains(x, y)) { .contains(x, y)) {
return true; return true;
} }
@ -1311,10 +1308,10 @@ bool WinNativeEventFilter::nativeEventFilter(const QByteArray &eventType,
#ifdef QT_WIDGETS_LIB #ifdef QT_WIDGETS_LIB
const auto widget = qobject_cast<QWidget *>(object); const auto widget = qobject_cast<QWidget *>(object);
if (widget) { if (widget) {
if (QRect(qRound(widget->x() * dpr), const QPoint pos = widget->mapToGlobal({0, 0});
qRound(widget->y() * dpr), if (QRectF(pos.x() * dpr, pos.y() * dpr,
qRound(widget->width() * dpr), widget->width() * dpr,
qRound(widget->height() * dpr)) widget->height() * dpr)
.contains(x, y)) { .contains(x, y)) {
return true; return true;
} }
@ -1324,11 +1321,11 @@ bool WinNativeEventFilter::nativeEventFilter(const QByteArray &eventType,
const auto quickItem = const auto quickItem =
qobject_cast<QQuickItem *>(object); qobject_cast<QQuickItem *>(object);
if (quickItem) { if (quickItem) {
const auto pos = quickItem->mapToScene({0, 0}); const QPointF pos =
if (QRect(qRound(pos.x() * dpr), quickItem->mapToGlobal({0, 0});
qRound(pos.y() * dpr), if (QRectF(pos.x() * dpr, pos.y() * dpr,
qRound(quickItem->width() * dpr), quickItem->width() * dpr,
qRound(quickItem->height() * dpr)) quickItem->height() * dpr)
.contains(x, y)) { .contains(x, y)) {
return true; return true;
} }
@ -1343,13 +1340,13 @@ bool WinNativeEventFilter::nativeEventFilter(const QByteArray &eventType,
m_lpGetClientRect(_hWnd, &clientRect); m_lpGetClientRect(_hWnd, &clientRect);
const LONG ww = clientRect.right; const LONG ww = clientRect.right;
const LONG wh = clientRect.bottom; const LONG wh = clientRect.bottom;
POINT mouse;
// Don't use HIWORD(lParam) and LOWORD(lParam) to get cursor // Don't use HIWORD(lParam) and LOWORD(lParam) to get cursor
// coordinates because their results are unsigned numbers, // coordinates because their results are unsigned numbers,
// however the cursor position may be negative due to in a // however the cursor position may be negative due to in a
// different monitor. // different monitor.
mouse.x = GET_X_LPARAM(_lParam); const POINT globalMouse{GET_X_LPARAM(_lParam),
mouse.y = GET_Y_LPARAM(_lParam); GET_Y_LPARAM(_lParam)};
POINT mouse = globalMouse;
m_lpScreenToClient(_hWnd, &mouse); m_lpScreenToClient(_hWnd, &mouse);
// These values are DPI-aware. // These values are DPI-aware.
const LONG bw = const LONG bw =
@ -1367,12 +1364,13 @@ bool WinNativeEventFilter::nativeEventFilter(const QByteArray &eventType,
: isInSpecificAreas(mouse.x, mouse.y, : isInSpecificAreas(mouse.x, mouse.y,
_data->windowData.draggableAreas, dpr); _data->windowData.draggableAreas, dpr);
#if defined(QT_WIDGETS_LIB) || defined(QT_QUICK_LIB) #if defined(QT_WIDGETS_LIB) || defined(QT_QUICK_LIB)
const bool isInIgnoreObjects = isInSpecificObjects( const bool isInIgnoreObjects =
mouse.x, mouse.y, _data->windowData.ignoreObjects, dpr); isInSpecificObjects(globalMouse.x, globalMouse.y,
_data->windowData.ignoreObjects, dpr);
const bool isInDraggableObjects = const bool isInDraggableObjects =
_data->windowData.draggableObjects.isEmpty() _data->windowData.draggableObjects.isEmpty()
? true ? true
: isInSpecificObjects(mouse.x, mouse.y, : isInSpecificObjects(globalMouse.x, globalMouse.y,
_data->windowData.draggableObjects, _data->windowData.draggableObjects,
dpr); dpr);
#else #else