From dddf96c011723a12b11acc2980c10eb370961021 Mon Sep 17 00:00:00 2001 From: Zhao Yuhang <2546789017@qq.com> Date: 周五, 15 12月 2023 21:35:17 +0800 Subject: [PATCH] add qt impl --- src/core/windowitemdelegate.cpp | 4 src/widgets/widgetitemdelegate.cpp | 33 +++++ src/widgets/widgetitemdelegate_p.h | 12 + src/core/windowitemdelegate_p.h | 12 + src/core/contexts/cocoawindowcontext.mm | 11 - src/core/contexts/abstractwindowcontext_p.h | 5 + src/quick/quickitemdelegate_p.h | 11 + src/core/contexts/qtwindowcontext.cpp | 151 +++++++++++++++++++++++++++++ src/quick/quickitemdelegate.cpp | 30 +++++ src/core/contexts/qtwindowcontext_p.h | 2 src/widgets/widgetwindowagent_cocoa.cpp | 6 11 files changed, 248 insertions(+), 29 deletions(-) diff --git a/src/core/contexts/abstractwindowcontext_p.h b/src/core/contexts/abstractwindowcontext_p.h index bcc6ae8..db12f87 100644 --- a/src/core/contexts/abstractwindowcontext_p.h +++ b/src/core/contexts/abstractwindowcontext_p.h @@ -25,6 +25,7 @@ inline QObject *host() const; inline QWindow *window() const; + inline WindowItemDelegate *delegate() const; inline bool isHitTestVisible(const QObject *obj) const; bool setHitTestVisible(const QObject *obj, bool visible); @@ -79,6 +80,10 @@ return m_windowHandle; } + inline WindowItemDelegate *AbstractWindowContext::delegate() const { + return m_delegate.get(); + } + inline bool AbstractWindowContext::isHitTestVisible(const QObject *obj) const { return m_hitTestVisibleItems.contains(obj); } diff --git a/src/core/contexts/cocoawindowcontext.mm b/src/core/contexts/cocoawindowcontext.mm index fc91cad..ffd3b87 100644 --- a/src/core/contexts/cocoawindowcontext.mm +++ b/src/core/contexts/cocoawindowcontext.mm @@ -238,11 +238,9 @@ return it.value(); } - CocoaWindowContext::CocoaWindowContext() { - } + CocoaWindowContext::CocoaWindowContext() : AbstractWindowContext() {} - CocoaWindowContext::~CocoaWindowContext() { - } + CocoaWindowContext::~CocoaWindowContext() = default; QString CocoaWindowContext::key() const { return QStringLiteral("cocoa"); @@ -255,10 +253,7 @@ #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) m_windowHandle->setProperty("_q_mac_wantsLayer", 1); #endif - WId winId = m_windowHandle->winId(); - ensureWindowProxy(winId)->setSystemTitleBarVisible(false); - // Cache window ID - windowId = winId; + ensureWindowProxy(m_windowHandle->winId())->setSystemTitleBarVisible(false); return true; } diff --git a/src/core/contexts/qtwindowcontext.cpp b/src/core/contexts/qtwindowcontext.cpp index ee5d27d..6887cfd 100644 --- a/src/core/contexts/qtwindowcontext.cpp +++ b/src/core/contexts/qtwindowcontext.cpp @@ -2,7 +2,7 @@ namespace QWK { - static constexpr const int kDefaultResizeBorderThickness = 8; + static constexpr const quint8 kDefaultResizeBorderThickness = 8; static Qt::CursorShape calculateCursorShape(const QWindow *window, const QPoint &pos) { #ifdef Q_OS_MACOS @@ -40,6 +40,149 @@ #endif } + static inline Qt::Edges calculateWindowEdges(const QWindow *window, const QPoint &pos) + { +#ifdef Q_OS_MACOS + Q_UNUSED(window); + Q_UNUSED(pos); + return {}; +#else + Q_ASSERT(window); + if (!window) { + return {}; + } + if (window->visibility() != QWindow::Windowed) { + return {}; + } + Qt::Edges edges = {}; + const int x = pos.x(); + const int y = pos.y(); + if (x < kDefaultResizeBorderThickness) { + edges |= Qt::LeftEdge; + } + if (x >= (window->width() - kDefaultResizeBorderThickness)) { + edges |= Qt::RightEdge; + } + if (y < kDefaultResizeBorderThickness) { + edges |= Qt::TopEdge; + } + if (y >= (window->height() - kDefaultResizeBorderThickness)) { + edges |= Qt::BottomEdge; + } + return edges; +#endif + } + + class WindowEventFilter : public QObject { + Q_OBJECT + + public: + explicit WindowEventFilter(AbstractWindowContext *context, QObject *parent = nullptr); + ~WindowEventFilter() override; + + protected: + bool eventFilter(QObject *object, QEvent *event) override; + + private: + AbstractWindowContext *m_context; + bool m_leftButtonPressed; + bool m_cursorShapeChanged; + }; + + WindowEventFilter::WindowEventFilter(AbstractWindowContext *context, QObject *parent) : QObject(parent), m_context(context), m_leftButtonPressed(false), m_cursorShapeChanged(false) {} + + WindowEventFilter::~WindowEventFilter() = default; + + bool WindowEventFilter::eventFilter(QObject *object, QEvent *event) { + const auto type = event->type(); + if (type < QEvent::MouseButtonPress || type > QEvent::MouseMove) { + return false; + } + QObject *host = m_context->host(); + QWindow *window = m_context->window(); + WindowItemDelegate *delegate = m_context->delegate(); + const bool fixedSize = delegate->isHostSizeFixed(host); + const auto mouseEvent = static_cast<const QMouseEvent *>(event); +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + const QPoint scenePos = mouseEvent->scenePosition().toPoint(); + const QPoint globalPos = mouseEvent->globalPosition().toPoint(); +#else + const QPoint scenePos = mouseEvent->windowPos().toPoint(); + const QPoint globalPos = mouseEvent->screenPos().toPoint(); +#endif + const bool inTitleBar = m_context->isInTitleBarDraggableArea(scenePos); + switch (type) { + case QEvent::MouseButtonPress: { + if (mouseEvent->button() == Qt::LeftButton) { + m_leftButtonPressed = true; + if (!fixedSize) { + const Qt::Edges edges = calculateWindowEdges(window, scenePos); + if (edges != Qt::Edges{}) { + window->startSystemResize(edges); + event->accept(); + return true; + } + } + if (inTitleBar) { + event->accept(); + return true; + } + } + break; + } + case QEvent::MouseButtonRelease: { + if (mouseEvent->button() == Qt::LeftButton) { + m_leftButtonPressed = false; + if (inTitleBar) { + event->accept(); + return true; + } + } + break; + } + case QEvent::MouseMove: { + if (!fixedSize) { + const Qt::CursorShape shape = calculateCursorShape(window, scenePos); + if (shape == Qt::ArrowCursor) { + if (m_cursorShapeChanged) { + delegate->restoreCursorShape(host); + m_cursorShapeChanged = false; + } + } else { + delegate->setCursorShape(host, shape); + m_cursorShapeChanged = true; + } + } + if (m_leftButtonPressed && inTitleBar) { + window->startSystemMove(); + event->accept(); + return true; + } + break; + } + case QEvent::MouseButtonDblClick: { + if (mouseEvent->button() == Qt::LeftButton && inTitleBar && !fixedSize) { + const Qt::WindowStates windowState = delegate->getWindowState(host); + if (!(windowState & Qt::WindowFullScreen)) { + if (windowState & Qt::WindowMaximized) { + delegate->setWindowState(host, windowState & ~Qt::WindowMaximized); + } else { + delegate->setWindowState(host, windowState | Qt::WindowMaximized); + } + event->accept(); + return true; + } + } + break; + } + default: { + Q_UNREACHABLE(); + return false; + } + } + return false; + } + QtWindowContext::QtWindowContext() : AbstractWindowContext() { } @@ -53,7 +196,11 @@ } bool QtWindowContext::setupHost() { + m_delegate->setWindowFlags(m_host, Qt::FramelessWindowHint); + m_windowHandle->installEventFilter(new WindowEventFilter(this, m_windowHandle)); return true; } -} \ No newline at end of file +} + +#include "qtwindowcontext.moc" diff --git a/src/core/contexts/qtwindowcontext_p.h b/src/core/contexts/qtwindowcontext_p.h index 8b70610..107353a 100644 --- a/src/core/contexts/qtwindowcontext_p.h +++ b/src/core/contexts/qtwindowcontext_p.h @@ -9,7 +9,7 @@ Q_OBJECT public: QtWindowContext(); - ~QtWindowContext(); + ~QtWindowContext() override; QString key() const override; void virtual_hook(int id, void *data) override; diff --git a/src/core/windowitemdelegate.cpp b/src/core/windowitemdelegate.cpp index a460add..c045a46 100644 --- a/src/core/windowitemdelegate.cpp +++ b/src/core/windowitemdelegate.cpp @@ -6,6 +6,8 @@ WindowItemDelegate::~WindowItemDelegate() = default; - void WindowItemDelegate::resetQtGrabbedControl() const {} + void WindowItemDelegate::resetQtGrabbedControl(QObject *host) const { + Q_UNUSED(host); + } } \ No newline at end of file diff --git a/src/core/windowitemdelegate_p.h b/src/core/windowitemdelegate_p.h index feb65cc..ab2d066 100644 --- a/src/core/windowitemdelegate_p.h +++ b/src/core/windowitemdelegate_p.h @@ -16,18 +16,24 @@ public: // Item property query - virtual QWindow *window(QObject *obj) const = 0; + virtual QWindow *window(const QObject *obj) const = 0; virtual bool isEnabled(const QObject *obj) const = 0; virtual bool isVisible(const QObject *obj) const = 0; virtual QRect mapGeometryToScene(const QObject *obj) const = 0; // Host property query - virtual QWindow *hostWindow(QObject *host) const = 0; + virtual QWindow *hostWindow(const QObject *host) const = 0; virtual bool isHostSizeFixed(const QObject *host) const = 0; virtual bool isWindowActive(const QObject *host) const = 0; + virtual Qt::WindowStates getWindowState(const QObject *host) const = 0; + virtual Qt::WindowFlags getWindowFlags(const QObject *host) const = 0; // Callbacks - virtual void resetQtGrabbedControl() const; + virtual void resetQtGrabbedControl(QObject *host) const; + virtual void setWindowState(QObject *host, const Qt::WindowStates &state) const = 0; + virtual void setCursorShape(QObject *host, const Qt::CursorShape shape) const = 0; + virtual void restoreCursorShape(QObject *host) const = 0; + virtual void setWindowFlags(QObject *host, const Qt::WindowFlags &flags) const = 0; private: Q_DISABLE_COPY(WindowItemDelegate) diff --git a/src/quick/quickitemdelegate.cpp b/src/quick/quickitemdelegate.cpp index 7bd1259..c2d4230 100644 --- a/src/quick/quickitemdelegate.cpp +++ b/src/quick/quickitemdelegate.cpp @@ -10,7 +10,7 @@ QuickItemDelegate::~QuickItemDelegate() = default; - QWindow *QuickItemDelegate::window(QObject *obj) const { + QWindow *QuickItemDelegate::window(const QObject *obj) const { return static_cast<const QQuickItem *>(obj)->window(); } @@ -29,8 +29,8 @@ return QRectF(originPoint, size).toRect(); } - QWindow *QuickItemDelegate::hostWindow(QObject *host) const { - return static_cast<QQuickWindow *>(host); + QWindow *QuickItemDelegate::hostWindow(const QObject *host) const { + return static_cast<QQuickWindow *>(const_cast<QObject *>(host)); } bool QuickItemDelegate::isHostSizeFixed(const QObject *host) const { @@ -42,4 +42,28 @@ return static_cast<const QQuickWindow *>(host)->isActive(); } + Qt::WindowStates QuickItemDelegate::getWindowState(const QObject *host) const { + return static_cast<const QQuickWindow *>(host)->windowStates(); + } + + void QuickItemDelegate::setWindowState(QObject *host, const Qt::WindowStates &state) const { + static_cast<QQuickWindow *>(host)->setWindowStates(state); + } + + void QuickItemDelegate::setCursorShape(QObject *host, const Qt::CursorShape shape) const { + static_cast<QQuickWindow *>(host)->setCursor(QCursor(shape)); + } + + void QuickItemDelegate::restoreCursorShape(QObject *host) const { + static_cast<QQuickWindow *>(host)->unsetCursor(); + } + + Qt::WindowFlags QuickItemDelegate::getWindowFlags(const QObject *host) const { + return static_cast<const QQuickWindow *>(host)->flags(); + } + + void QuickItemDelegate::setWindowFlags(QObject *host, const Qt::WindowFlags &flags) const { + static_cast<QQuickWindow *>(host)->setFlags(flags); + } + } \ No newline at end of file diff --git a/src/quick/quickitemdelegate_p.h b/src/quick/quickitemdelegate_p.h index 31056d0..636d2d8 100644 --- a/src/quick/quickitemdelegate_p.h +++ b/src/quick/quickitemdelegate_p.h @@ -15,14 +15,21 @@ ~QuickItemDelegate() override; public: - QWindow *window(QObject *obj) const override; + QWindow *window(const QObject *obj) const override; bool isEnabled(const QObject *obj) const override; bool isVisible(const QObject *obj) const override; QRect mapGeometryToScene(const QObject *obj) const override; - QWindow *hostWindow(QObject *host) const override; + QWindow *hostWindow(const QObject *host) const override; bool isHostSizeFixed(const QObject *host) const override; bool isWindowActive(const QObject *host) const override; + Qt::WindowStates getWindowState(const QObject *host) const override; + Qt::WindowFlags getWindowFlags(const QObject *host) const override; + + void setWindowState(QObject *host, const Qt::WindowStates &state) const override; + void setCursorShape(QObject *host, const Qt::CursorShape shape) const override; + void restoreCursorShape(QObject *host) const override; + void setWindowFlags(QObject *host, const Qt::WindowFlags &flags) const override; }; } diff --git a/src/widgets/widgetitemdelegate.cpp b/src/widgets/widgetitemdelegate.cpp index ca8bb99..d838a0f 100644 --- a/src/widgets/widgetitemdelegate.cpp +++ b/src/widgets/widgetitemdelegate.cpp @@ -12,7 +12,7 @@ WidgetItemDelegate::~WidgetItemDelegate() = default; - QWindow *WidgetItemDelegate::window(QObject *obj) const { + QWindow *WidgetItemDelegate::window(const QObject *obj) const { return static_cast<const QWidget *>(obj)->windowHandle(); } @@ -31,7 +31,7 @@ return {originPoint, size}; } - QWindow *WidgetItemDelegate::hostWindow(QObject *host) const { + QWindow *WidgetItemDelegate::hostWindow(const QObject *host) const { return static_cast<const QWidget *>(host)->windowHandle(); } @@ -60,7 +60,8 @@ return static_cast<const QWidget *>(host)->isActiveWindow(); } - void WidgetItemDelegate::resetQtGrabbedControl() const { + void WidgetItemDelegate::resetQtGrabbedControl(QObject *host) const { + Q_UNUSED(host); if (!qt_button_down) { return; } @@ -69,8 +70,32 @@ const auto event = new QMouseEvent( QEvent::MouseButtonRelease, invalidPos, invalidPos, invalidPos, Qt::LeftButton, QGuiApplication::mouseButtons() ^ Qt::LeftButton, QGuiApplication::keyboardModifiers()); - QApplication::postEvent(qt_button_down, event); + QCoreApplication::postEvent(qt_button_down, event); qt_button_down = nullptr; } + Qt::WindowStates WidgetItemDelegate::getWindowState(const QObject *host) const { + return static_cast<const QWidget *>(host)->windowState(); + } + + void WidgetItemDelegate::setWindowState(QObject *host, const Qt::WindowStates &state) const { + static_cast<QWidget *>(host)->setWindowState(state); + } + + void WidgetItemDelegate::setCursorShape(QObject *host, const Qt::CursorShape shape) const { + static_cast<QWidget *>(host)->setCursor(QCursor(shape)); + } + + void WidgetItemDelegate::restoreCursorShape(QObject *host) const { + static_cast<QWidget *>(host)->unsetCursor(); + } + + Qt::WindowFlags WidgetItemDelegate::getWindowFlags(const QObject *host) const { + return static_cast<const QWidget *>(host)->windowFlags(); + } + + void WidgetItemDelegate::setWindowFlags(QObject *host, const Qt::WindowFlags &flags) const { + static_cast<QWidget *>(host)->setWindowFlags(flags); + } + } \ No newline at end of file diff --git a/src/widgets/widgetitemdelegate_p.h b/src/widgets/widgetitemdelegate_p.h index 3ba34af..1753222 100644 --- a/src/widgets/widgetitemdelegate_p.h +++ b/src/widgets/widgetitemdelegate_p.h @@ -15,16 +15,22 @@ ~WidgetItemDelegate() override; public: - QWindow *window(QObject *obj) const override; + QWindow *window(const QObject *obj) const override; bool isEnabled(const QObject *obj) const override; bool isVisible(const QObject *obj) const override; QRect mapGeometryToScene(const QObject *obj) const override; - QWindow *hostWindow(QObject *host) const override; + QWindow *hostWindow(const QObject *host) const override; bool isHostSizeFixed(const QObject *host) const override; bool isWindowActive(const QObject *host) const override; + Qt::WindowStates getWindowState(const QObject *host) const override; + Qt::WindowFlags getWindowFlags(const QObject *host) const override; - void resetQtGrabbedControl() const override; + void resetQtGrabbedControl(QObject *host) const override; + void setWindowState(QObject *host, const Qt::WindowStates &state) const override; + void setCursorShape(QObject *host, const Qt::CursorShape shape) const override; + void restoreCursorShape(QObject *host) const override; + void setWindowFlags(QObject *host, const Qt::WindowFlags &flags) const override; }; } diff --git a/src/widgets/widgetwindowagent_cocoa.cpp b/src/widgets/widgetwindowagent_cocoa.cpp index d381f6d..815aadd 100644 --- a/src/widgets/widgetwindowagent_cocoa.cpp +++ b/src/widgets/widgetwindowagent_cocoa.cpp @@ -77,8 +77,10 @@ } break; } - default: - break; + default: { + Q_UNREACHABLE(); + return false; + } } return false; } -- Gitblit v1.9.1