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:
parent
2ca6a90ae2
commit
921b87ab2e
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 = {};
|
||||||
};
|
};
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue