| | |
| | | #include <QtGui/QGuiApplication> |
| | | #include <QtGui/QPainter> |
| | | #include <QtGui/QPalette> |
| | | #include <QtGui/QStyleHints> |
| | | |
| | | #include <QtGui/private/qhighdpiscaling_p.h> |
| | | #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) |
| | |
| | | static WNDPROC g_qtWindowProc = nullptr; |
| | | |
| | | static inline bool |
| | | #if !QWINDOWKIT_CONFIG(ENABLE_WINDOWS_SYSTEM_BORDER) |
| | | #if !QWINDOWKIT_CONFIG(ENABLE_WINDOWS_SYSTEM_BORDERS) |
| | | constexpr |
| | | #endif |
| | | |
| | | isSystemBorderEnabled() { |
| | | return |
| | | #if QWINDOWKIT_CONFIG(ENABLE_WINDOWS_SYSTEM_BORDER) |
| | | #if QWINDOWKIT_CONFIG(ENABLE_WINDOWS_SYSTEM_BORDERS) |
| | | isWin10OrGreater() |
| | | #else |
| | | false |
| | |
| | | return false; |
| | | } |
| | | |
| | | static WindowsNativeEventFilter *instance; |
| | | static Win32WindowContext *lastMessageContext; |
| | | static inline WindowsNativeEventFilter *instance = nullptr; |
| | | static inline Win32WindowContext *lastMessageContext = nullptr; |
| | | |
| | | static inline void install() { |
| | | if (instance) { |
| | |
| | | instance = nullptr; |
| | | } |
| | | }; |
| | | |
| | | WindowsNativeEventFilter *WindowsNativeEventFilter::instance = nullptr; |
| | | Win32WindowContext *WindowsNativeEventFilter::lastMessageContext = nullptr; |
| | | |
| | | // https://github.com/qt/qtbase/blob/e26a87f1ecc40bc8c6aa5b889fce67410a57a702/src/plugins/platforms/windows/qwindowscontext.cpp#L1025 |
| | | // We can see from the source code that Qt will filter out some messages first and then send the |
| | |
| | | case RaiseWindowHook: { |
| | | if (!windowId) |
| | | return; |
| | | m_delegate->setWindowVisible(m_host, true); |
| | | const auto hwnd = reinterpret_cast<HWND>(windowId); |
| | | bringWindowToFront(hwnd); |
| | | return; |
| | |
| | | } |
| | | |
| | | case DrawWindows10BorderHook: { |
| | | #if QWINDOWKIT_CONFIG(ENABLE_WINDOWS_SYSTEM_BORDER) |
| | | #if QWINDOWKIT_CONFIG(ENABLE_WINDOWS_SYSTEM_BORDERS) |
| | | if (!windowId) |
| | | return; |
| | | |
| | |
| | | } |
| | | |
| | | case DrawWindows10BorderHook2: { |
| | | #if QWINDOWKIT_CONFIG(ENABLE_WINDOWS_SYSTEM_BORDER) |
| | | #if QWINDOWKIT_CONFIG(ENABLE_WINDOWS_SYSTEM_BORDERS) |
| | | if (!m_windowHandle) |
| | | return; |
| | | |
| | |
| | | if (!m_windowHandle) |
| | | return {}; |
| | | |
| | | auto hwnd = reinterpret_cast<HWND>(windowId); |
| | | RECT frame{}; |
| | | ::AdjustWindowRectExForDpi(&frame, ::GetWindowLongPtrW(hwnd, GWL_STYLE), FALSE, 0, |
| | | getDpiForWindow(hwnd)); |
| | | auto hwnd = reinterpret_cast<HWND>(windowId); |
| | | // According to MSDN, WS_OVERLAPPED is not allowed for AdjustWindowRect. |
| | | auto style = static_cast<DWORD>(::GetWindowLongPtrW(hwnd, GWL_STYLE) & ~WS_OVERLAPPED); |
| | | auto exStyle = static_cast<DWORD>(::GetWindowLongPtrW(hwnd, GWL_EXSTYLE)); |
| | | const DynamicApis &apis = DynamicApis::instance(); |
| | | if (apis.pAdjustWindowRectExForDpi) { |
| | | apis.pAdjustWindowRectExForDpi(&frame, style, FALSE, exStyle, |
| | | getDpiForWindow(hwnd)); |
| | | } else { |
| | | ::AdjustWindowRectEx(&frame, style, FALSE, exStyle); |
| | | } |
| | | frame.left = std::abs(frame.left); |
| | | frame.top = std::abs(frame.top); |
| | | frame.right = std::abs(frame.right); |
| | | frame.bottom = std::abs(frame.bottom); |
| | | return QVariant::fromValue(rect2qrect(frame)); |
| | | } |
| | | |
| | |
| | | auto hWnd = reinterpret_cast<HWND>(winId); |
| | | |
| | | if (!isSystemBorderEnabled()) { |
| | | setWindowAttribute(QStringLiteral("extra-margins"), |
| | | QVariant::fromValue(QMargins(1, 1, 1, 1))); |
| | | static auto margins = QVariant::fromValue(QMargins(1, 1, 1, 1)); |
| | | |
| | | // If we remove the system border, the window will lose its shadow. If dwm is enabled, |
| | | // then you need to set at least 1px margins, otherwise the following operation will |
| | | // fail with no effect. |
| | | setWindowAttribute(QStringLiteral("extra-margins"), margins); |
| | | } |
| | | |
| | | // We should disable WS_SYSMENU, otherwise the system button icons will be visible if mica |
| | | // is enabled and the title bar is transparent |
| | | { |
| | | auto style = ::GetWindowLongPtrW(hWnd, GWL_STYLE); |
| | | #if QWINDOWKIT_CONFIG(ENABLE_WINDOWS_SYSTEM_BORDER) |
| | | ::SetWindowLongPtrW(hWnd, GWL_STYLE, style & (~WS_SYSMENU)); |
| | | #else |
| | | ::SetWindowLongPtrW(hWnd, GWL_STYLE, |
| | | (style | WS_THICKFRAME | WS_CAPTION) & (~WS_SYSMENU)); |
| | | #endif |
| | | if (isSystemBorderEnabled()) { |
| | | ::SetWindowLongPtrW(hWnd, GWL_STYLE, style & (~WS_SYSMENU)); |
| | | } else { |
| | | ::SetWindowLongPtrW(hWnd, GWL_STYLE, |
| | | (style | WS_THICKFRAME | WS_CAPTION) & (~WS_SYSMENU)); |
| | | } |
| | | } |
| | | |
| | | // Add managed window |
| | |
| | | |
| | | if (key == QStringLiteral("extra-margins")) { |
| | | auto margins = qmargins2margins(attribute.value<QMargins>()); |
| | | DynamicApis::instance().pDwmExtendFrameIntoClientArea(hwnd, &margins); |
| | | return true; |
| | | return apis.pDwmExtendFrameIntoClientArea(hwnd, &margins) == S_OK; |
| | | } |
| | | |
| | | if (key == QStringLiteral("dark-mode")) { |
| | |
| | | } |
| | | |
| | | if (key == QStringLiteral("dwm-blur")) { |
| | | // TODO: Optimize |
| | | // Currently not available!!! |
| | | if (attribute.toBool()) { |
| | | // We need to extend the window frame into the whole client area to be able |
| | | // to see the blurred window background. |
| | | apis.pDwmExtendFrameIntoClientArea(hwnd, &extendedMargins); |
| | | // We can't extend the window frame for this effect. |
| | | restoreMargins(); |
| | | if (isWin8OrGreater()) { |
| | | ACCENT_POLICY policy{}; |
| | | policy.dwAccentState = ACCENT_ENABLE_BLURBEHIND; |
| | |
| | | bb.dwFlags = DWM_BB_ENABLE; |
| | | apis.pDwmEnableBlurBehindWindow(hwnd, &bb); |
| | | } |
| | | restoreMargins(); |
| | | } |
| | | return true; |
| | | } |
| | |
| | | LPARAM lParam, LRESULT *result) { |
| | | switch (message) { |
| | | case WM_SHOWWINDOW: { |
| | | if (!centered) { |
| | | if (!initialCentered) { |
| | | // If wParam is TRUE, the window is being shown. |
| | | // If lParam is zero, the message was sent because of a call to the ShowWindow |
| | | // function. |
| | | if (wParam && !lParam) { |
| | | centered = true; |
| | | initialCentered = true; |
| | | moveWindowToDesktopCenter(hWnd); |
| | | } |
| | | } |