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/contexts/qtwindowcontext.cpp | 165 +++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 files changed, 155 insertions(+), 10 deletions(-) diff --git a/src/core/contexts/qtwindowcontext.cpp b/src/core/contexts/qtwindowcontext.cpp index 732ecf1..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,22 +40,167 @@ #endif } - QtWindowContext::QtWindowContext(QObject *host, WindowItemDelegate *delegate) - : AbstractWindowContext(host, delegate) { + 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 } - QtWindowContext::~QtWindowContext() { - } + class WindowEventFilter : public QObject { + Q_OBJECT - bool QtWindowContext::setup() { - if (!m_windowHandle) { + 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; } - bool QtWindowContext::eventFilter(QObject *obj, QEvent *event) { - return AbstractWindowContext::eventFilter(obj, event); + QtWindowContext::QtWindowContext() : AbstractWindowContext() { } -} \ No newline at end of file + QtWindowContext::~QtWindowContext() = default; + + QString QtWindowContext::key() const { + return QStringLiteral("qt"); + } + + void QtWindowContext::virtual_hook(int id, void *data) { + } + + bool QtWindowContext::setupHost() { + m_delegate->setWindowFlags(m_host, Qt::FramelessWindowHint); + m_windowHandle->installEventFilter(new WindowEventFilter(this, m_windowHandle)); + return true; + } + +} + +#include "qtwindowcontext.moc" -- Gitblit v1.9.1