Sine Striker
2023-12-02 499afac952920595e6c3d4f94806427f894c7674
src/core/contexts/win32windowcontext.cpp
@@ -4,62 +4,75 @@
namespace QWK {
    using WndProcHash = QHash<HWND, Win32WindowContext *>;
    using WndProcHash = QHash<HWND, Win32WindowContext *>; // hWnd -> context
    Q_GLOBAL_STATIC(WndProcHash, g_wndProcHash);
    static WNDPROC g_qtWindowProc = nullptr; // Original Qt window proc function
    extern "C" LRESULT QT_WIN_CALLBACK QWK_WindowsWndProc(HWND hWnd, UINT message, WPARAM wParam,
                                                          LPARAM lParam) {
        Q_ASSERT(hWnd);
        if (!hWnd) {
            return FALSE;
        }
        // Search window context
        auto ctx = g_wndProcHash->value(hWnd);
        if (!ctx) {
            return ::DefWindowProcW(hWnd, message, wParam, lParam);
        }
        // Try hooked procedure
        LRESULT result;
        if (ctx->windowProc(hWnd, message, wParam, lParam, &result)) {
            return result;
        }
        // Fallback to Qt's procedure
        return ::CallWindowProcW(g_qtWindowProc, hWnd, message, wParam, lParam);
    }
    Win32WindowContext::Win32WindowContext(QWindow *window, WindowItemDelegate *delegate)
        : AbstractWindowContext(window, delegate), windowId(0), qtWindowProc(nullptr) {
        : AbstractWindowContext(window, delegate), windowId(0) {
    }
    Win32WindowContext::~Win32WindowContext() {
        // Remove window handle mapping
        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;
        }
        auto qtWindowProc = reinterpret_cast<WNDPROC>(::GetWindowLongPtrW(hWnd, GWLP_WNDPROC));
        ::SetWindowLongPtrW(hWnd, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(QWK_WindowsWndProc));
        windowId = winId;
        qtWindowProc = orgWndProc;         // Store original window proc
        g_wndProcHash->insert(hWnd, this); // Save window handle mapping
        // Store original window proc
        if (!g_qtWindowProc) {
            g_qtWindowProc = qtWindowProc;
        }
        // Save window handle mapping
        g_wndProcHash->insert(hWnd, this);
        return true;
    }
    LRESULT Win32WindowContext::windowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
        Q_ASSERT(hWnd);
        if (!hWnd) {
            return FALSE;
        }
    bool Win32WindowContext::windowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam,
                                        LRESULT *result) {
        *result = FALSE;
        const auto *ctx = g_wndProcHash->value(hWnd);
        if (!ctx) {
            return ::DefWindowProcW(hWnd, uMsg, wParam, lParam);
        }
        // TODO: Implement
        // ...
        auto winId = reinterpret_cast<WId>(hWnd);
        Q_UNUSED(windowId)
        // Further procedure
        Q_UNUSED(winId)
        return ::CallWindowProcW(ctx->qtWindowProc, hWnd, uMsg, wParam, lParam);
        return false; // Not handled
    }
}