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