Sine Striker
2023-12-01 027122452a25191b81fef8fe35f5b54768d435f2
Add windows implementations
12个文件已修改
7个文件已添加
4 文件已重命名
2个文件已删除
351 ■■■■ 已修改文件
CMakeLists.txt 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
examples/CMakeLists.txt 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
examples/mainwindow/CMakeLists.txt 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
examples/mainwindow/main.cpp 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
examples/mainwindow/mainwindow.cpp 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
examples/mainwindow/mainwindow.h 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/CMakeLists.txt 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/core/CMakeLists.txt 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/core/contexts/abstractwindowcontext.cpp 补丁 | 查看 | 原始文档 | blame | 历史
src/core/contexts/abstractwindowcontext_p.h 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/core/contexts/qtwindowcontext.cpp 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/core/contexts/qtwindowcontext_p.h 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/core/contexts/win32windowcontext.cpp 65 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/core/contexts/win32windowcontext_p.h 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/core/corewindowagent.cpp 24 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/core/corewindowagent_p.h 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/core/handler/win32windowcontext.cpp 51 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/core/handler/win32windowcontext_p.h 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/core/qwindowkit_windows.cpp 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/core/qwindowkit_windows.h 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/core/qwkcoreglobal.h 9 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/quick/quickwindowagent.cpp 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/quick/quickwindowagent.h 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/widgets/widgetwindowagent.cpp 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/widgets/widgetwindowagent.h 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
CMakeLists.txt
@@ -39,7 +39,7 @@
set(QWINDOWKIT_INSTALL_NAME ${PROJECT_NAME})
# ----------------------------------
# Main Project
# Find basic dependencies
# ----------------------------------
find_package(qmsetup QUIET)
@@ -65,6 +65,12 @@
    set(qmsetup_DIR ${_package_path} CACHE PATH "" FORCE)
endif()
qm_import(Filesystem)
qm_init_directories()
# ----------------------------------
# Add source modules
# ----------------------------------
add_subdirectory(src)
if(QWINDOWKIT_BUILD_EXAMPLES)
examples/CMakeLists.txt
@@ -0,0 +1 @@
add_subdirectory(mainwindow)
examples/mainwindow/CMakeLists.txt
New file
@@ -0,0 +1,15 @@
project(QWKExample_MainWindow)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTORCC ON)
file(GLOB _src *.h *.cpp)
add_executable(${PROJECT_NAME})
qm_configure_target(${PROJECT_NAME}
    SOURCES ${_src}
    QT_LINKS Core Gui Widgets
    LINKS QWKWidgets
)
examples/mainwindow/main.cpp
New file
@@ -0,0 +1,10 @@
#include <QApplication>
#include "mainwindow.h"
int main(int argc, char *argv[]) {
    QApplication a(argc, argv);
    MainWindow w;
    w.show();
    return a.exec();
}
examples/mainwindow/mainwindow.cpp
New file
@@ -0,0 +1,15 @@
#include "mainwindow.h"
#include <QtCore/QDebug>
#include <QWKWidgets/widgetwindowagent.h>
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) {
    auto agent = new QWK::WidgetWindowAgent(this);
    if (!agent->setup(this)) {
        qDebug() << "Frameless handle failed to initialize.";
    }
}
MainWindow::~MainWindow() {
}
examples/mainwindow/mainwindow.h
New file
@@ -0,0 +1,12 @@
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QtWidgets/QMainWindow>
class MainWindow : public QMainWindow {
public:
    explicit MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
};
#endif // MAINWINDOW_H
src/CMakeLists.txt
@@ -1,5 +1,4 @@
qm_import(Filesystem Preprocess)
qm_init_directories()
qm_import(Preprocess)
set(QWINDOWKIT_PROJECT_DESCRIPTION "Cross-platform window customization framework")
set(QWINDOWKIT_PROJECT_COPYRIGHT "Copyright 2023 Stdware Collections")
@@ -106,7 +105,7 @@
    if(NOT FUNC_NO_SYNC_INCLUDE)
        # Generate a standard include directory in build directory
        qm_sync_include(. "${QWINDOWKIT_GENERATED_INCLUDE_DIR}/${_inc_name}" ${_install_options}
            ${FUNC_SYNC_INCLUDE_OPTIONS}
            ${FUNC_SYNC_INCLUDE_OPTIONS} FORCE
        )
        target_include_directories(${_target} PUBLIC
            "$<BUILD_INTERFACE:${QWINDOWKIT_GENERATED_INCLUDE_DIR}>"
src/core/CMakeLists.txt
@@ -9,20 +9,21 @@
    corewindowagent_p.h
    corewindowagent.cpp
    windowitemdelegate.h
    handler/abstractwindowcontext_p.h
    handler/abstractwindowcontext.cpp
    contexts/abstractwindowcontext_p.h
    contexts/abstractwindowcontext.cpp
)
if(WIN32)
    list(APPEND _src
        qwindowkit_windows.h
        handler/win32windowcontext_p.h
        handler/win32windowcontext.cpp
        qwindowkit_windows.cpp
        contexts/win32windowcontext_p.h
        contexts/win32windowcontext.cpp
    )
else()
    list(APPEND _src
        handler/qtwindowcontext_p.h
        handler/qtwindowcontext.cpp
        contexts/qtwindowcontext_p.h
        contexts/qtwindowcontext.cpp
    )
    if(APPLE)
        # add files
@@ -38,6 +39,7 @@
    LINKS
    QT_LINKS Core Gui
    QT_INCLUDE_PRIVATE Core Gui
    INCLUDE_PRIVATE contexts
    PREFIX QWK_CORE
)
src/core/contexts/abstractwindowcontext.cpp
src/core/contexts/abstractwindowcontext_p.h
File was renamed from src/core/handler/abstractwindowcontext_p.h
@@ -19,6 +19,8 @@
        ~AbstractWindowContext();
    public:
        virtual bool setup() = 0;
        inline QWindow *window() const;
        void setupWindow(QWindow *window);
src/core/contexts/qtwindowcontext.cpp
File was renamed from src/core/handler/qtwindowcontext.cpp
@@ -47,6 +47,10 @@
    QtWindowContext::~QtWindowContext() {
    }
    bool QtWindowContext::setup() {
        return false;
    }
    bool QtWindowContext::eventFilter(QObject *obj, QEvent *event) {
        return AbstractWindowContext::eventFilter(obj, event);
    }
src/core/contexts/qtwindowcontext_p.h
File was renamed from src/core/handler/qtwindowcontext_p.h
@@ -11,6 +11,9 @@
        QtWindowContext(QWindow *window, WindowItemDelegate *delegate);
        ~QtWindowContext();
    public:
        bool setup() override;
    protected:
        bool eventFilter(QObject *obj, QEvent *event) override;
    };
src/core/contexts/win32windowcontext.cpp
New file
@@ -0,0 +1,65 @@
#include "win32windowcontext_p.h"
#include <QtCore/QHash>
namespace QWK {
    using WndProcHash = QHash<HWND, Win32WindowContext *>;
    Q_GLOBAL_STATIC(WndProcHash, g_wndProcHash);
    Win32WindowContext::Win32WindowContext(QWindow *window, WindowItemDelegate *delegate)
        : AbstractWindowContext(window, delegate), windowId(0), qtWindowProc(nullptr) {
    }
    Win32WindowContext::~Win32WindowContext() {
        auto hWnd = reinterpret_cast<HWND>(windowId);
        g_wndProcHash->remove(hWnd);
    }
    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 orgWndProc = reinterpret_cast<WNDPROC>(::GetWindowLongPtrW(hWnd, GWLP_WNDPROC));
        Q_ASSERT(orgWndProc);
        if (!orgWndProc) {
            QWK_WARNING << winLastErrorMessage();
            return false;
        }
        if (::SetWindowLongPtrW(hWnd, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(windowProc)) == 0) {
            QWK_WARNING << winLastErrorMessage();
            return false;
        }
        windowId = winId;
        qtWindowProc = orgWndProc;         // Store original window proc
        g_wndProcHash->insert(hWnd, this); // Save window handle mapping
        return true;
    }
    LRESULT Win32WindowContext::windowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
        Q_ASSERT(hWnd);
        if (!hWnd) {
            return FALSE;
        }
        const auto *ctx = g_wndProcHash->value(hWnd);
        if (!ctx) {
            return ::DefWindowProcW(hWnd, uMsg, wParam, lParam);
        }
        auto winId = reinterpret_cast<WId>(hWnd);
        // Further procedure
        Q_UNUSED(winId)
        return ::CallWindowProcW(ctx->qtWindowProc, hWnd, uMsg, wParam, lParam);
    }
}
src/core/contexts/win32windowcontext_p.h
New file
@@ -0,0 +1,27 @@
#ifndef WIN32WINDOWCONTEXT_P_H
#define WIN32WINDOWCONTEXT_P_H
#include <QWKCore/qwindowkit_windows.h>
#include <QWKCore/private/abstractwindowcontext_p.h>
namespace QWK {
    class QWK_CORE_EXPORT Win32WindowContext : public AbstractWindowContext {
        Q_OBJECT
    public:
        Win32WindowContext(QWindow *window, WindowItemDelegate *delegate);
        ~Win32WindowContext();
    public:
        bool setup() override;
    protected:
        WId windowId;
        WNDPROC qtWindowProc; // Original Qt window proc function
        static LRESULT windowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
    };
}
#endif // WIN32WINDOWCONTEXT_P_H
src/core/corewindowagent.cpp
@@ -2,28 +2,40 @@
#include "corewindowagent_p.h"
#ifdef Q_OS_WINDOWS
#  include "handler/win32windowcontext_p.h"
#  include "win32windowcontext_p.h"
#else
#  include "handler/qtwindowcontext_p.h"
#  include "qtwindowcontext_p.h"
#endif
Q_LOGGING_CATEGORY(qWindowKitLog, "qwindowkit")
namespace QWK {
    CoreWindowAgentPrivate::CoreWindowAgentPrivate() {
    CoreWindowAgentPrivate::CoreWindowAgentPrivate() : m_eventHandler(nullptr) {
    }
    CoreWindowAgentPrivate::~CoreWindowAgentPrivate() {
        delete m_eventHandler;
    }
    void CoreWindowAgentPrivate::init() {
    }
    void CoreWindowAgentPrivate::setup(QWindow *window, WindowItemDelegate *delegate) {
    bool CoreWindowAgentPrivate::setup(QWindow *window, WindowItemDelegate *delegate) {
        auto handler =
#ifdef Q_OS_WINDOWS
        m_eventHandler = new Win32WindowContext(window, delegate);
            new Win32WindowContext(window, delegate)
#else
        m_eventHandler = new QtWindowContext(window, delegate);
            new QtWindowContext(window, delegate)
#endif
            ;
        if (!handler->setup()) {
            delete handler;
            return false;
        }
        m_eventHandler = handler;
        return true;
    }
    CoreWindowAgent::~CoreWindowAgent() {
src/core/corewindowagent_p.h
@@ -16,9 +16,9 @@
        CoreWindowAgent *q_ptr; // no need to initialize
        void setup(QWindow *window, WindowItemDelegate *delegate);
        bool setup(QWindow *window, WindowItemDelegate *delegate);
        AbstractWindowContext *m_eventHandler{};
        AbstractWindowContext *m_eventHandler;
    };
}
src/core/handler/win32windowcontext.cpp
File was deleted
src/core/handler/win32windowcontext_p.h
File was deleted
src/core/qwindowkit_windows.cpp
New file
@@ -0,0 +1,22 @@
#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());
    }
}
src/core/qwindowkit_windows.h
@@ -1,5 +1,18 @@
#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();
}
#endif // QWINDOWKIT_WINDOWS_H
src/core/qwkcoreglobal.h
@@ -1,7 +1,7 @@
#ifndef QWKCOREGLOBAL_H
#define QWKCOREGLOBAL_H
#include <QtGlobal>
#include <QLoggingCategory>
#ifndef QWK_CORE_EXPORT
#  ifdef QWK_CORE_STATIC
@@ -15,4 +15,11 @@
#  endif
#endif
QWK_CORE_EXPORT Q_DECLARE_LOGGING_CATEGORY(qWindowKitLog)
#define QWK_INFO     qCInfo(qWindowKitLog)
#define QWK_DEBUG    qCDebug(qWindowKitLog)
#define QWK_WARNING  qCWarning(qWindowKitLog)
#define QWK_CRITICAL qCCritical(qWindowKitLog)
#endif // QWKCOREGLOBAL_H
src/quick/quickwindowagent.cpp
@@ -23,19 +23,22 @@
    QuickWindowAgent::~QuickWindowAgent() {
    }
    void QuickWindowAgent::setup(QQuickWindow *window) {
    bool QuickWindowAgent::setup(QQuickWindow *window) {
        Q_ASSERT(window);
        if (!window) {
            return;
            return false;
        }
        Q_D(QuickWindowAgent);
        if (d->host) {
            return;
            return false;
        }
        if (!d->setup(window, new QuickItemDelegate())) {
            return true;
        }
        d->host = window;
        d->setup(window, new QuickItemDelegate());
        return true;
    }
    bool QuickWindowAgent::isHitTestVisible(QQuickItem *item) const {
src/quick/quickwindowagent.h
@@ -19,7 +19,7 @@
        ~QuickWindowAgent();
    public:
        void setup(QQuickWindow *window);
        bool setup(QQuickWindow *window);
        bool isHitTestVisible(QQuickItem *item) const;
        void setHitTestVisible(QQuickItem *item, bool visible);
src/widgets/widgetwindowagent.cpp
@@ -21,20 +21,23 @@
    WidgetWindowAgent::~WidgetWindowAgent() {
    }
    void WidgetWindowAgent::setup(QWidget *w) {
    bool WidgetWindowAgent::setup(QWidget *w) {
        Q_ASSERT(w);
        if (!w) {
            return;
            return false;
        }
        Q_D(WidgetWindowAgent);
        if (d->host) {
            return;
            return false;
        }
        d->host = w;
        std::ignore = w->winId(); // Make sure the window handle is created
        d->setup(w->windowHandle(), new WidgetItemDelegate());
        if (!d->setup(w->windowHandle(), new WidgetItemDelegate())) {
            return true;
        }
        d->host = w;
        return true;
    }
    bool WidgetWindowAgent::isHitTestVisible(QWidget *w) const {
src/widgets/widgetwindowagent.h
@@ -18,7 +18,7 @@
        ~WidgetWindowAgent();
    public:
        void setup(QWidget *w);
        bool setup(QWidget *w);
        bool isHitTestVisible(QWidget *w) const;
        void setHitTestVisible(QWidget *w, bool visible);