| | |
| | | |
| | | namespace QWK { |
| | | |
| | | AbstractWindowContext::~AbstractWindowContext() { |
| | | delete m_delegate; |
| | | } |
| | | AbstractWindowContext::~AbstractWindowContext() = default; |
| | | |
| | | void AbstractWindowContext::setupWindow(QWindow *window) { |
| | | Q_ASSERT(window); |
| | | if (!window) { |
| | | return; |
| | | } |
| | | m_windowHandle = window; |
| | | } |
| | | |
| | |
| | | |
| | | class QWK_CORE_EXPORT AbstractWindowContext : public QObject { |
| | | Q_OBJECT |
| | | Q_DISABLE_COPY(AbstractWindowContext) |
| | | |
| | | public: |
| | | inline AbstractWindowContext(QWindow *window, WindowItemDelegate *delegate) |
| | | : m_windowHandle(window), m_delegate(delegate) { |
| | | inline AbstractWindowContext(QWindow *window, WindowItemDelegatePtr delegate) |
| | | : m_windowHandle(window), m_delegate(std::move(delegate)) |
| | | { |
| | | } |
| | | ~AbstractWindowContext(); |
| | | ~AbstractWindowContext() override; |
| | | |
| | | public: |
| | | virtual bool setup() = 0; |
| | |
| | | |
| | | protected: |
| | | QWindow *m_windowHandle; |
| | | WindowItemDelegate *m_delegate; |
| | | WindowItemDelegatePtr m_delegate; |
| | | |
| | | QSet<QObject *> m_hitTestVisibleItems; |
| | | QList<QRect> m_hitTestVisibleRects; |
| | | |
| | | QObject *m_titleBar{}; |
| | | QObject *m_systemButtons[CoreWindowAgent::NumSystemButton]{}; |
| | | std::array<QObject *, CoreWindowAgent::NumSystemButton> m_systemButtons{}; |
| | | |
| | | mutable bool hitTestVisibleShapeDirty{}; |
| | | mutable QPolygon hitTestVisibleShape; |
| | |
| | | return m_titleBar; |
| | | } |
| | | |
| | | using WindowContextPtr = std::shared_ptr<AbstractWindowContext>; |
| | | |
| | | } |
| | | |
| | | #endif // ABSTRACTWINDOWCONTEXT_P_H |
| | |
| | | #endif |
| | | } |
| | | |
| | | QtWindowContext::QtWindowContext(QWindow *window, WindowItemDelegate *delegate) |
| | | QtWindowContext::QtWindowContext(QWindow *window, WindowItemDelegatePtr delegate) |
| | | : AbstractWindowContext(window, delegate) { |
| | | } |
| | | |
| | |
| | | |
| | | class QWK_CORE_EXPORT QtWindowContext : public AbstractWindowContext { |
| | | Q_OBJECT |
| | | Q_DISABLE_COPY(QtWindowContext) |
| | | |
| | | public: |
| | | QtWindowContext(QWindow *window, WindowItemDelegate *delegate); |
| | | QtWindowContext(QWindow *window, WindowItemDelegatePtr delegate); |
| | | ~QtWindowContext(); |
| | | |
| | | public: |
| | |
| | | |
| | | // Try hooked procedure |
| | | LRESULT result; |
| | | bool handled = ctx->windowProc(hWnd, message, wParam, lParam, &result); |
| | | if (handled) { |
| | | if (ctx->windowProc(hWnd, message, wParam, lParam, &result)) { |
| | | return result; |
| | | } |
| | | |
| | |
| | | return ::CallWindowProcW(g_qtWindowProc, hWnd, message, wParam, lParam); |
| | | } |
| | | |
| | | Win32WindowContext::Win32WindowContext(QWindow *window, WindowItemDelegate *delegate) |
| | | : AbstractWindowContext(window, delegate), windowId(0) { |
| | | Win32WindowContext::Win32WindowContext(QWindow *window, WindowItemDelegatePtr delegate) |
| | | : AbstractWindowContext(window, std::move(delegate)), windowId(0) { |
| | | } |
| | | |
| | | Win32WindowContext::~Win32WindowContext() { |
| | |
| | | |
| | | bool Win32WindowContext::setup() { |
| | | auto winId = m_windowHandle->winId(); |
| | | Q_ASSERT(winId); |
| | | if (!winId) { |
| | | return false; |
| | | } |
| | | |
| | | // Install window hook |
| | | auto hWnd = reinterpret_cast<HWND>(winId); |
| | | auto qtWindowProc = reinterpret_cast<WNDPROC>(::GetWindowLongPtrW(hWnd, GWLP_WNDPROC)); |
| | | Q_ASSERT(qtWindowProc); |
| | | if (!qtWindowProc) { |
| | | QWK_WARNING << winLastErrorMessage(); |
| | | return false; |
| | | } |
| | | |
| | | if (::SetWindowLongPtrW(hWnd, GWLP_WNDPROC, |
| | | reinterpret_cast<LONG_PTR>(QWK_WindowsWndProc)) == 0) { |
| | | QWK_WARNING << winLastErrorMessage(); |
| | | return false; |
| | | } |
| | | ::SetWindowLongPtrW(hWnd, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(QWK_WindowsWndProc)); |
| | | |
| | | windowId = winId; |
| | | |
| | |
| | | |
| | | class QWK_CORE_EXPORT Win32WindowContext : public AbstractWindowContext { |
| | | Q_OBJECT |
| | | Q_DISABLE_COPY(Win32WindowContext) |
| | | |
| | | public: |
| | | Win32WindowContext(QWindow *window, WindowItemDelegate *delegate); |
| | | ~Win32WindowContext(); |
| | | Win32WindowContext(QWindow *window, WindowItemDelegatePtr delegate); |
| | | ~Win32WindowContext() override; |
| | | |
| | | public: |
| | | bool setup() override; |
| | |
| | | |
| | | namespace QWK { |
| | | |
| | | CoreWindowAgentPrivate::CoreWindowAgentPrivate() : m_eventHandler(nullptr) { |
| | | CoreWindowAgentPrivate::CoreWindowAgentPrivate() : q_ptr(nullptr), eventHandler(nullptr) { |
| | | } |
| | | |
| | | CoreWindowAgentPrivate::~CoreWindowAgentPrivate() { |
| | | delete m_eventHandler; |
| | | } |
| | | CoreWindowAgentPrivate::~CoreWindowAgentPrivate() = default; |
| | | |
| | | void CoreWindowAgentPrivate::init() { |
| | | } |
| | | |
| | | bool CoreWindowAgentPrivate::setup(QWindow *window, WindowItemDelegate *delegate) { |
| | | bool CoreWindowAgentPrivate::setup(QWindow *window, const WindowItemDelegatePtr &delegate) { |
| | | Q_ASSERT(window); |
| | | if (!window) { |
| | | return false; |
| | | } |
| | | auto handler = |
| | | #ifdef Q_OS_WINDOWS |
| | | new Win32WindowContext(window, delegate) |
| | | std::make_shared<Win32WindowContext>(window, delegate) |
| | | #else |
| | | new QtWindowContext(window, delegate) |
| | | std::make_shared<QtWindowContext>(window, delegate) |
| | | #endif |
| | | ; |
| | | |
| | | if (!handler->setup()) { |
| | | delete handler; |
| | | return false; |
| | | } |
| | | m_eventHandler = handler; |
| | | eventHandler = handler; |
| | | return true; |
| | | } |
| | | |
| | | CoreWindowAgent::~CoreWindowAgent() { |
| | | } |
| | | CoreWindowAgent::~CoreWindowAgent() = default; |
| | | |
| | | void CoreWindowAgent::showSystemMenu(const QPoint &pos) { |
| | | Q_D(CoreWindowAgent); |
| | | d->m_eventHandler->showSystemMenu(pos); |
| | | d->eventHandler->showSystemMenu(pos); |
| | | } |
| | | |
| | | void CoreWindowAgent::startSystemMove(const QPoint &pos) { |
| | | Q_D(CoreWindowAgent); |
| | | auto win = d->m_eventHandler->window(); |
| | | auto win = d->eventHandler->window(); |
| | | if (!win) { |
| | | return; |
| | | } |
| | |
| | | |
| | | void CoreWindowAgent::startSystemResize(Qt::Edges edges, const QPoint &pos) { |
| | | Q_D(CoreWindowAgent); |
| | | auto win = d->m_eventHandler->window(); |
| | | auto win = d->eventHandler->window(); |
| | | if (!win) { |
| | | return; |
| | | } |
| | |
| | | |
| | | class QWK_CORE_EXPORT CoreWindowAgent : public QObject { |
| | | Q_OBJECT |
| | | Q_DISABLE_COPY(CoreWindowAgent) |
| | | Q_DECLARE_PRIVATE(CoreWindowAgent) |
| | | |
| | | public: |
| | | ~CoreWindowAgent(); |
| | | ~CoreWindowAgent() override; |
| | | |
| | | enum SystemButton { |
| | | Unknown, |
| | |
| | | void raise(); |
| | | |
| | | protected: |
| | | CoreWindowAgent(CoreWindowAgentPrivate &d, QObject *parent = nullptr); |
| | | explicit CoreWindowAgent(CoreWindowAgentPrivate &d, QObject *parent = nullptr); |
| | | |
| | | QScopedPointer<CoreWindowAgentPrivate> d_ptr; |
| | | const std::unique_ptr<CoreWindowAgentPrivate> d_ptr; |
| | | }; |
| | | |
| | | } |
| | |
| | | namespace QWK { |
| | | |
| | | class QWK_CORE_EXPORT CoreWindowAgentPrivate { |
| | | Q_DISABLE_COPY(CoreWindowAgentPrivate) |
| | | Q_DECLARE_PUBLIC(CoreWindowAgent) |
| | | |
| | | public: |
| | | CoreWindowAgentPrivate(); |
| | | virtual ~CoreWindowAgentPrivate(); |
| | |
| | | |
| | | CoreWindowAgent *q_ptr; // no need to initialize |
| | | |
| | | bool setup(QWindow *window, WindowItemDelegate *delegate); |
| | | bool setup(QWindow *window, const WindowItemDelegatePtr &delegate); |
| | | |
| | | AbstractWindowContext *m_eventHandler; |
| | | WindowContextPtr eventHandler; |
| | | }; |
| | | |
| | | } |
| | |
| | | #include "qwindowkit_windows.h" |
| | | |
| | | namespace QWK { |
| | | |
| | | QString winErrorMessage(DWORD code) { |
| | | LPWSTR buf = nullptr; |
| | | if (::FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | |
| | | FORMAT_MESSAGE_IGNORE_INSERTS, |
| | | nullptr, code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), |
| | | reinterpret_cast<LPWSTR>(&buf), 0, nullptr) == 0) { |
| | | return {}; |
| | | } |
| | | const QString &errorText = QString::fromWCharArray(buf).trimmed(); |
| | | ::LocalFree(buf); |
| | | return errorText; |
| | | } |
| | | |
| | | QString winLastErrorMessage() { |
| | | return winErrorMessage(::GetLastError()); |
| | | } |
| | | |
| | | } |
| | |
| | | #ifndef QWINDOWKIT_WINDOWS_H |
| | | #define QWINDOWKIT_WINDOWS_H |
| | | |
| | | #include <windows.h> |
| | | |
| | | #include <QString> |
| | | |
| | | #include <QWKCore/qwkcoreglobal.h> |
| | | |
| | | namespace QWK { |
| | | |
| | | QWK_CORE_EXPORT QString winErrorMessage(DWORD code); |
| | | |
| | | QWK_CORE_EXPORT QString winLastErrorMessage(); |
| | | |
| | | } |
| | | #include <QtCore/qt_windows.h> |
| | | |
| | | #endif // QWINDOWKIT_WINDOWS_H |
| | |
| | | #define QWK_DEBUG qCDebug(qWindowKitLog) |
| | | #define QWK_WARNING qCWarning(qWindowKitLog) |
| | | #define QWK_CRITICAL qCCritical(qWindowKitLog) |
| | | #if QT_VERSION >= QT_VERSION_CHECK(6, 6, 0) |
| | | # define QWK_FATAL qCFatal(qWindowKitLog) |
| | | #endif |
| | | |
| | | #endif // QWKCOREGLOBAL_H |
| | |
| | | namespace QWK { |
| | | |
| | | class WindowItemDelegate { |
| | | Q_DISABLE_COPY(WindowItemDelegate) |
| | | |
| | | public: |
| | | WindowItemDelegate() = default; |
| | | virtual ~WindowItemDelegate() = default; |
| | | |
| | | public: |
| | |
| | | virtual bool isVisible(QObject *obj) const = 0; |
| | | }; |
| | | |
| | | using WindowItemDelegatePtr = std::shared_ptr<WindowItemDelegate>; |
| | | |
| | | } |
| | | |
| | | #endif // WINDOWITEMDELEGATE_H |
| | |
| | | |
| | | namespace QWK { |
| | | |
| | | QuickItemDelegate::QuickItemDelegate() { |
| | | QuickItemDelegate::QuickItemDelegate() : WindowItemDelegate() { |
| | | } |
| | | |
| | | QuickItemDelegate::~QuickItemDelegate() { |
| | | } |
| | | QuickItemDelegate::~QuickItemDelegate() = default; |
| | | |
| | | QWindow *QuickItemDelegate::window(QObject *obj) const { |
| | | return static_cast<QQuickItem *>(obj)->window(); |
| | | return qobject_cast<QQuickItem *>(obj)->window(); |
| | | } |
| | | |
| | | bool QuickItemDelegate::isEnabled(QObject *obj) const { |
| | | return static_cast<QQuickItem *>(obj)->isEnabled(); |
| | | return qobject_cast<QQuickItem *>(obj)->isEnabled(); |
| | | } |
| | | |
| | | bool QuickItemDelegate::isVisible(QObject *obj) const { |
| | | return static_cast<QQuickItem *>(obj)->isVisible(); |
| | | return qobject_cast<QQuickItem *>(obj)->isVisible(); |
| | | } |
| | | |
| | | } |
| | |
| | | namespace QWK { |
| | | |
| | | class QWK_QUICK_EXPORT QuickItemDelegate : public WindowItemDelegate { |
| | | Q_DISABLE_COPY(QuickItemDelegate) |
| | | |
| | | public: |
| | | QuickItemDelegate(); |
| | | ~QuickItemDelegate(); |
| | | ~QuickItemDelegate() override; |
| | | |
| | | public: |
| | | QWindow *window(QObject *obj) const override; |
| | |
| | | return false; |
| | | } |
| | | |
| | | if (!d->setup(window, new QuickItemDelegate())) { |
| | | if (!d->setup(window, std::make_shared<QuickItemDelegate>())) { |
| | | return true; |
| | | } |
| | | d->host = window; |
| | |
| | | |
| | | bool QuickWindowAgent::isHitTestVisible(QQuickItem *item) const { |
| | | Q_D(const QuickWindowAgent); |
| | | return d->m_eventHandler->isHitTestVisible(item); |
| | | return d->eventHandler->isHitTestVisible(item); |
| | | } |
| | | |
| | | void QuickWindowAgent::setHitTestVisible(QQuickItem *item, bool visible) { |
| | | Q_D(QuickWindowAgent); |
| | | d->m_eventHandler->setHitTestVisible(item, visible); |
| | | d->eventHandler->setHitTestVisible(item, visible); |
| | | } |
| | | |
| | | void QuickWindowAgent::setHitTestVisible(const QRect &rect, bool visible) { |
| | | Q_D(QuickWindowAgent); |
| | | d->m_eventHandler->setHitTestVisible(rect, visible); |
| | | d->eventHandler->setHitTestVisible(rect, visible); |
| | | } |
| | | |
| | | QQuickItem *QuickWindowAgent::systemButton(SystemButton button) const { |
| | | Q_D(const QuickWindowAgent); |
| | | return static_cast<QQuickItem *>(d->m_eventHandler->systemButton(button)); |
| | | return qobject_cast<QQuickItem *>(d->eventHandler->systemButton(button)); |
| | | } |
| | | |
| | | void QuickWindowAgent::setSystemButton(SystemButton button, QQuickItem *item) { |
| | | Q_D(QuickWindowAgent); |
| | | if (!d->m_eventHandler->setSystemButton(button, item)) { |
| | | if (!d->eventHandler->setSystemButton(button, item)) { |
| | | return; |
| | | } |
| | | Q_EMIT systemButtonChanged(button, item); |
| | |
| | | |
| | | QQuickItem *QuickWindowAgent::titleBar() const { |
| | | Q_D(const QuickWindowAgent); |
| | | return static_cast<QQuickItem *>(d->m_eventHandler->titleBar()); |
| | | return qobject_cast<QQuickItem *>(d->eventHandler->titleBar()); |
| | | } |
| | | |
| | | void QuickWindowAgent::setTitleBar(QQuickItem *item) { |
| | | Q_D(QuickWindowAgent); |
| | | if (!d->m_eventHandler->setTitleBar(item)) { |
| | | if (!d->eventHandler->setTitleBar(item)) { |
| | | return; |
| | | } |
| | | Q_EMIT titleBarWidgetChanged(item); |
| | |
| | | |
| | | class QWK_QUICK_EXPORT QuickWindowAgent : public CoreWindowAgent { |
| | | Q_OBJECT |
| | | Q_DISABLE_COPY(QuickWindowAgent) |
| | | Q_DECLARE_PRIVATE(QuickWindowAgent) |
| | | |
| | | public: |
| | | explicit QuickWindowAgent(QObject *parent = nullptr); |
| | | ~QuickWindowAgent(); |
| | | ~QuickWindowAgent() override; |
| | | |
| | | public: |
| | | bool setup(QQuickWindow *window); |
| | |
| | | namespace QWK { |
| | | |
| | | class QuickWindowAgentPrivate : public CoreWindowAgentPrivate { |
| | | Q_DISABLE_COPY(QuickWindowAgentPrivate) |
| | | Q_DECLARE_PUBLIC(QuickWindowAgent) |
| | | |
| | | public: |
| | | QuickWindowAgentPrivate(); |
| | | ~QuickWindowAgentPrivate(); |
| | | ~QuickWindowAgentPrivate() override; |
| | | |
| | | void init(); |
| | | |
| | |
| | | } |
| | | |
| | | QWindow *WidgetItemDelegate::window(QObject *obj) const { |
| | | return static_cast<QWidget *>(obj)->windowHandle(); |
| | | return qobject_cast<QWidget *>(obj)->windowHandle(); |
| | | } |
| | | |
| | | bool WidgetItemDelegate::isEnabled(QObject *obj) const { |
| | | return static_cast<QWidget *>(obj)->isEnabled(); |
| | | return qobject_cast<QWidget *>(obj)->isEnabled(); |
| | | } |
| | | |
| | | bool WidgetItemDelegate::isVisible(QObject *obj) const { |
| | | return static_cast<QWidget *>(obj)->isVisible(); |
| | | return qobject_cast<QWidget *>(obj)->isVisible(); |
| | | } |
| | | |
| | | } |
| | |
| | | namespace QWK { |
| | | |
| | | class QWK_WIDGETS_EXPORT WidgetItemDelegate : public WindowItemDelegate { |
| | | Q_DISABLE_COPY(WidgetItemDelegate) |
| | | |
| | | public: |
| | | WidgetItemDelegate(); |
| | | ~WidgetItemDelegate(); |
| | | ~WidgetItemDelegate() override; |
| | | |
| | | public: |
| | | QWindow *window(QObject *obj) const override; |
| | |
| | | } |
| | | |
| | | std::ignore = w->winId(); // Make sure the window handle is created |
| | | if (!d->setup(w->windowHandle(), new WidgetItemDelegate())) { |
| | | return true; |
| | | if (!d->setup(w->windowHandle(), std::make_shared<WidgetItemDelegate>())) { |
| | | return false; |
| | | } |
| | | d->host = w; |
| | | return true; |
| | |
| | | |
| | | bool WidgetWindowAgent::isHitTestVisible(QWidget *w) const { |
| | | Q_D(const WidgetWindowAgent); |
| | | return d->m_eventHandler->isHitTestVisible(w); |
| | | return d->eventHandler->isHitTestVisible(w); |
| | | } |
| | | |
| | | void WidgetWindowAgent::setHitTestVisible(QWidget *w, bool visible) { |
| | | Q_D(WidgetWindowAgent); |
| | | d->m_eventHandler->setHitTestVisible(w, visible); |
| | | d->eventHandler->setHitTestVisible(w, visible); |
| | | } |
| | | |
| | | void WidgetWindowAgent::setHitTestVisible(const QRect &rect, bool visible) { |
| | | Q_D(WidgetWindowAgent); |
| | | d->m_eventHandler->setHitTestVisible(rect, visible); |
| | | d->eventHandler->setHitTestVisible(rect, visible); |
| | | } |
| | | |
| | | QWidget *WidgetWindowAgent::systemButton(CoreWindowAgent::SystemButton button) const { |
| | | Q_D(const WidgetWindowAgent); |
| | | return static_cast<QWidget *>(d->m_eventHandler->systemButton(button)); |
| | | return qobject_cast<QWidget *>(d->eventHandler->systemButton(button)); |
| | | } |
| | | |
| | | void WidgetWindowAgent::setSystemButton(CoreWindowAgent::SystemButton button, QWidget *w) { |
| | | Q_D(WidgetWindowAgent); |
| | | if (!d->m_eventHandler->setSystemButton(button, w)) { |
| | | if (!d->eventHandler->setSystemButton(button, w)) { |
| | | return; |
| | | } |
| | | Q_EMIT systemButtonChanged(button, w); |
| | |
| | | |
| | | QWidget *WidgetWindowAgent::titleBar() const { |
| | | Q_D(const WidgetWindowAgent); |
| | | return static_cast<QWidget *>(d->m_eventHandler->titleBar()); |
| | | return qobject_cast<QWidget *>(d->eventHandler->titleBar()); |
| | | } |
| | | |
| | | void WidgetWindowAgent::setTitleBar(QWidget *w) { |
| | | Q_D(WidgetWindowAgent); |
| | | if (!d->m_eventHandler->setTitleBar(w)) { |
| | | if (!d->eventHandler->setTitleBar(w)) { |
| | | return; |
| | | } |
| | | Q_EMIT titleBarWidgetChanged(w); |
| | |
| | | |
| | | class QWK_WIDGETS_EXPORT WidgetWindowAgent : public CoreWindowAgent { |
| | | Q_OBJECT |
| | | Q_DISABLE_COPY(WidgetWindowAgent) |
| | | Q_DECLARE_PRIVATE(WidgetWindowAgent) |
| | | |
| | | public: |
| | | explicit WidgetWindowAgent(QObject *parent = nullptr); |
| | | ~WidgetWindowAgent(); |
| | | ~WidgetWindowAgent() override; |
| | | |
| | | public: |
| | | bool setup(QWidget *w); |
| | |
| | | namespace QWK { |
| | | |
| | | class WidgetWindowAgentPrivate : public CoreWindowAgentPrivate { |
| | | Q_DISABLE_COPY(WidgetWindowAgentPrivate) |
| | | Q_DECLARE_PUBLIC(WidgetWindowAgent) |
| | | |
| | | public: |
| | | WidgetWindowAgentPrivate(); |
| | | ~WidgetWindowAgentPrivate(); |