| | |
| | | return ::CallWindowProcW(g_qtWindowProc, hWnd, message, wParam, lParam); |
| | | } |
| | | |
| | | static inline void addManagedWindow(HWND hWnd, Win32WindowContext *ctx) { |
| | | // Store original window proc |
| | | if (!g_qtWindowProc) { |
| | | g_qtWindowProc = reinterpret_cast<WNDPROC>(::GetWindowLongPtrW(hWnd, GWLP_WNDPROC)); |
| | | } |
| | | |
| | | // Hook window proc |
| | | ::SetWindowLongPtrW(hWnd, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(QWKHookedWndProc)); |
| | | |
| | | // Install global native event filter |
| | | WindowsNativeEventFilter::install(); |
| | | |
| | | // Save window handle mapping |
| | | g_wndProcHash->insert(hWnd, ctx); |
| | | } |
| | | |
| | | static inline void removeManagedWindow(HWND hWnd) { |
| | | // Remove window handle mapping |
| | | if (!g_wndProcHash->remove(hWnd)) |
| | | return; |
| | | |
| | | // Remove event filter if the all windows has been destroyed |
| | | if (g_wndProcHash->empty()) { |
| | | WindowsNativeEventFilter::uninstall(); |
| | | } |
| | | } |
| | | |
| | | Win32WindowContext::Win32WindowContext() : AbstractWindowContext() { |
| | | } |
| | | |
| | | Win32WindowContext::~Win32WindowContext() { |
| | | // Remove window handle mapping |
| | | if (auto hWnd = reinterpret_cast<HWND>(windowId); hWnd) { |
| | | g_wndProcHash->remove(hWnd); |
| | | |
| | | // Remove event filter if the all windows has been destroyed |
| | | if (g_wndProcHash->empty()) { |
| | | WindowsNativeEventFilter::uninstall(); |
| | | } |
| | | if (windowId) { |
| | | removeManagedWindow(reinterpret_cast<HWND>(windowId)); |
| | | } |
| | | } |
| | | |
| | |
| | | void Win32WindowContext::virtual_hook(int id, void *data) { |
| | | switch (id) { |
| | | case CentralizeHook: { |
| | | const auto hwnd = reinterpret_cast<HWND>(m_windowHandle->winId()); |
| | | const auto hwnd = reinterpret_cast<HWND>(windowId); |
| | | moveToDesktopCenter(hwnd); |
| | | return; |
| | | } |
| | | |
| | | case RaiseWindowHook: { |
| | | if (m_windowHandle->windowStates() & Qt::WindowMinimized) |
| | | m_windowHandle->showNormal(); |
| | | |
| | | auto hWnd = reinterpret_cast<HWND>(windowId); |
| | | |
| | | // I have no idea what this does, but it works mostly |
| | | // https://www.codeproject.com/Articles/1724/Some-handy-dialog-box-tricks-tips-and-workarounds |
| | | |
| | | ::AttachThreadInput(::GetWindowThreadProcessId(::GetForegroundWindow(), nullptr), |
| | | ::GetCurrentThreadId(), TRUE); |
| | | |
| | | ::SetForegroundWindow(hWnd); |
| | | ::SetFocus(hWnd); |
| | | |
| | | ::AttachThreadInput(GetWindowThreadProcessId(GetForegroundWindow(), nullptr), |
| | | GetCurrentThreadId(), FALSE); |
| | | return; |
| | | } |
| | | |
| | | case ShowSystemMenuHook: { |
| | | const auto &pos = *static_cast<const QPoint *>(data); |
| | | auto hWnd = reinterpret_cast<HWND>(m_windowHandle->winId()); |
| | | auto hWnd = reinterpret_cast<HWND>(windowId); |
| | | #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) |
| | | const QPoint nativeGlobalPos = |
| | | QHighDpi::toNativeGlobalPosition(pos, m_windowHandle); |
| | |
| | | showSystemMenu2(hWnd, qpoint2point(nativeGlobalPos), false, |
| | | m_delegate->isHostSizeFixed(m_host)); |
| | | return; |
| | | } |
| | | |
| | | case WindowAttributeChangedHook: { |
| | | auto args = static_cast<void **>(data); |
| | | const auto &key = *static_cast<const QString *>(args[0]); |
| | | const auto &newVar = *static_cast<const QVariant *>(args[1]); |
| | | const auto &oldVar = *static_cast<const QVariant *>(args[2]); |
| | | |
| | | if (key == QStringLiteral("no-frame-shadow")) { |
| | | if (newVar.toBool()) { |
| | | // TODO: set off |
| | | } else { |
| | | // TODO: set on |
| | | } |
| | | } |
| | | |
| | | break; |
| | | } |
| | | |
| | | case DefaultColorsHook: { |
| | |
| | | auto &painter = *static_cast<QPainter *>(args[0]); |
| | | const auto &rect = *static_cast<const QRect *>(args[1]); |
| | | const auto ®ion = *static_cast<const QRegion *>(args[2]); |
| | | const auto hwnd = reinterpret_cast<HWND>(m_windowHandle->winId()); |
| | | const auto hwnd = reinterpret_cast<HWND>(windowId); |
| | | |
| | | QPen pen; |
| | | pen.setWidth(getWindowFrameBorderThickness(hwnd) * 2); |
| | |
| | | return getWindowFrameBorderThickness(reinterpret_cast<HWND>(windowId)); |
| | | } |
| | | |
| | | bool Win32WindowContext::setupHost() { |
| | | void Win32WindowContext::winIdChanged(QWindow *oldWindow) { |
| | | removeManagedWindow(reinterpret_cast<HWND>(windowId)); |
| | | if (!m_windowHandle) { |
| | | return; |
| | | } |
| | | |
| | | // Install window hook |
| | | auto winId = m_windowHandle->winId(); |
| | | auto hWnd = reinterpret_cast<HWND>(winId); |
| | | |
| | | #if QT_VERSION < QT_VERSION_CHECK(6, 5, 0) |
| | | for (const auto attr : |
| | | {_DWMWA_USE_IMMERSIVE_DARK_MODE_BEFORE_20H1, _DWMWA_USE_IMMERSIVE_DARK_MODE}) { |
| | | for (const auto attr : { |
| | | _DWMWA_USE_IMMERSIVE_DARK_MODE_BEFORE_20H1, |
| | | _DWMWA_USE_IMMERSIVE_DARK_MODE, |
| | | }) { |
| | | const BOOL enable = TRUE; |
| | | DynamicApis::instance().pDwmSetWindowAttribute(hWnd, attr, &enable, sizeof(enable)); |
| | | } |
| | |
| | | // Inform Qt we want and have set custom margins |
| | | updateInternalWindowFrameMargins(hWnd, m_windowHandle); |
| | | |
| | | // Store original window proc |
| | | if (!g_qtWindowProc) { |
| | | g_qtWindowProc = reinterpret_cast<WNDPROC>(::GetWindowLongPtrW(hWnd, GWLP_WNDPROC)); |
| | | } |
| | | // Add managed window |
| | | addManagedWindow(hWnd, this); |
| | | |
| | | // Hook window proc |
| | | ::SetWindowLongPtrW(hWnd, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(QWKHookedWndProc)); |
| | | |
| | | // Install global native event filter |
| | | WindowsNativeEventFilter::install(); |
| | | |
| | | // Cache window ID |
| | | // Cache win id |
| | | windowId = winId; |
| | | |
| | | // Save window handle mapping |
| | | g_wndProcHash->insert(hWnd, this); |
| | | |
| | | return true; |
| | | } |
| | | |
| | | bool Win32WindowContext::windowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, |