From f40dc661b3f5235c11829dc5e7069fe79766984b Mon Sep 17 00:00:00 2001 From: John Preston Date: Fri, 24 Jun 2022 20:33:02 +0400 Subject: [PATCH 1/7] Revert "Simplify Windows native event filter." With that commit the window frame on Windows 7 is still bugged :( --- ui/platform/ui_platform_window.cpp | 7 --- ui/platform/ui_platform_window.h | 5 -- ui/platform/win/ui_window_win.cpp | 79 ++++++++++++++++++++++-------- ui/platform/win/ui_window_win.h | 9 ++-- ui/widgets/rp_window.cpp | 15 ------ ui/widgets/rp_window.h | 8 --- 6 files changed, 63 insertions(+), 60 deletions(-) diff --git a/ui/platform/ui_platform_window.cpp b/ui/platform/ui_platform_window.cpp index b11831f..2ce63a2 100644 --- a/ui/platform/ui_platform_window.cpp +++ b/ui/platform/ui_platform_window.cpp @@ -70,13 +70,6 @@ rpl::producer BasicWindowHelper::systemButtonDown() const { return rpl::never(); } -bool BasicWindowHelper::nativeEvent( - const QByteArray &eventType, - void *message, - base::NativeEventResult *result) { - return false; -} - void BasicWindowHelper::setTitle(const QString &title) { _window->setWindowTitle(title); } diff --git a/ui/platform/ui_platform_window.h b/ui/platform/ui_platform_window.h index eadcbca..e34f1d7 100644 --- a/ui/platform/ui_platform_window.h +++ b/ui/platform/ui_platform_window.h @@ -8,7 +8,6 @@ #include "base/flags.h" #include "base/object_ptr.h" -#include "base/qt/qt_common_adapters.h" #include "ui/round_rect.h" namespace style { @@ -49,10 +48,6 @@ public: -> rpl::producer; [[nodiscard]] virtual auto systemButtonDown() const -> rpl::producer; - [[nodiscard]] virtual bool nativeEvent( - const QByteArray &eventType, - void *message, - base::NativeEventResult *result); virtual void setTitle(const QString &title); virtual void setTitleStyle(const style::WindowTitle &st); virtual void setNativeFrame(bool enabled); diff --git a/ui/platform/win/ui_window_win.cpp b/ui/platform/win/ui_window_win.cpp index 9357993..95957c0 100644 --- a/ui/platform/win/ui_window_win.cpp +++ b/ui/platform/win/ui_window_win.cpp @@ -17,6 +17,7 @@ #include "styles/palette.h" #include "styles/style_widgets.h" +#include #include #include #include @@ -128,6 +129,50 @@ void FixAeroSnap(HWND handle) { } // namespace +class WindowHelper::NativeFilter final : public QAbstractNativeEventFilter { +public: + void registerWindow(HWND handle, not_null helper); + void unregisterWindow(HWND handle); + + bool nativeEventFilter( + const QByteArray &eventType, + void *message, + long *result) override; + +private: + base::flat_map> _windowByHandle; + +}; + +void WindowHelper::NativeFilter::registerWindow( + HWND handle, + not_null helper) { + _windowByHandle.emplace(handle, helper); +} + +void WindowHelper::NativeFilter::unregisterWindow(HWND handle) { + _windowByHandle.remove(handle); +} + +bool WindowHelper::NativeFilter::nativeEventFilter( + const QByteArray &eventType, + void *message, + long *result) { + auto filtered = false; + const auto msg = static_cast(message); + const auto i = _windowByHandle.find(msg->hwnd); + if (i != end(_windowByHandle)) { + base::Integration::Instance().enterFromEventLoop([&] { + filtered = i->second->handleNativeEvent( + msg->message, + msg->wParam, + msg->lParam, + reinterpret_cast(result)); + }); + } + return filtered; +} + WindowHelper::WindowHelper(not_null window) : BasicWindowHelper(window) , _handle(ResolveWindowHandle(window)) @@ -141,6 +186,7 @@ WindowHelper::WindowHelper(not_null window) } WindowHelper::~WindowHelper() { + GetNativeFilter()->unregisterWindow(_handle); } void WindowHelper::initInWindow(not_null window) { @@ -272,6 +318,7 @@ rpl::producer WindowHelper::systemButtonDown() const { void WindowHelper::init() { _title->show(); + GetNativeFilter()->registerWindow(_handle, this); style::PaletteChanged( ) | rpl::start_with_next([=] { @@ -321,26 +368,6 @@ void WindowHelper::init() { initialShadowUpdate(); } -bool WindowHelper::nativeEvent( - const QByteArray &eventType, - void *message, - base::NativeEventResult *result) { - const auto msg = static_cast(message); - auto lresult = LRESULT(*result); - const auto guard = gsl::finally([&] { - *result = base::NativeEventResult(lresult); - }); - auto filtered = false; - base::Integration::Instance().enterFromEventLoop([&] { - filtered = handleNativeEvent( - msg->message, - msg->wParam, - msg->lParam, - &lresult); - }); - return filtered; -} - bool WindowHelper::handleNativeEvent( UINT msg, WPARAM wParam, @@ -762,6 +789,18 @@ void WindowHelper::fixMaximizedWindow() { } } +not_null WindowHelper::GetNativeFilter() { + Expects(QCoreApplication::instance() != nullptr); + + static const auto GlobalFilter = [&] { + const auto application = QCoreApplication::instance(); + const auto filter = Ui::CreateChild(application); + application->installNativeEventFilter(filter); + return filter; + }(); + return GlobalFilter; +} + HWND GetWindowHandle(not_null widget) { const auto toplevel = widget->window(); toplevel->createWinId(); diff --git a/ui/platform/win/ui_window_win.h b/ui/platform/win/ui_window_win.h index eada67c..d3ec58d 100644 --- a/ui/platform/win/ui_window_win.h +++ b/ui/platform/win/ui_window_win.h @@ -44,12 +44,10 @@ public: [[nodiscard]] auto systemButtonDown() const -> rpl::producer override; - [[nodiscard]] bool nativeEvent( - const QByteArray &eventType, - void *message, - base::NativeEventResult *result) override; - private: + class NativeFilter; + friend class NativeFilter; + void init(); void updateMargins(); void updateWindowFrameColors(); @@ -72,6 +70,7 @@ private: [[nodiscard]] HitTestResult systemButtonHitTest(int result) const; [[nodiscard]] int titleHeight() const; + static not_null GetNativeFilter(); const HWND _handle = nullptr; const not_null _title; diff --git a/ui/widgets/rp_window.cpp b/ui/widgets/rp_window.cpp index f1dc292..d1c38a6 100644 --- a/ui/widgets/rp_window.cpp +++ b/ui/widgets/rp_window.cpp @@ -17,8 +17,6 @@ RpWindow::RpWindow(QWidget *parent) _helper->initInWindow(this); hide(); - - _initialized = true; } RpWindow::~RpWindow() = default; @@ -101,17 +99,4 @@ void RpWindow::setBodyTitleArea( _helper->setBodyTitleArea(std::move(testMethod)); } -bool RpWindow::nativeEvent( - const QByteArray &eventType, - void *message, - base::NativeEventResult *result) { - if (_initialized && _helper->nativeEvent( - eventType, - message, - result)) { - return true; - } - return RpWidget::nativeEvent(eventType, message, result); -} - } // namespace Ui diff --git a/ui/widgets/rp_window.h b/ui/widgets/rp_window.h index 77311fc..04b4d99 100644 --- a/ui/widgets/rp_window.h +++ b/ui/widgets/rp_window.h @@ -8,7 +8,6 @@ #include "ui/rp_widget.h" #include "base/flags.h" -#include "base/qt/qt_common_adapters.h" namespace style { struct WindowTitle; @@ -68,14 +67,7 @@ public: void close(); void setBodyTitleArea(Fn testMethod); -protected: - bool nativeEvent( - const QByteArray &eventType, - void *message, - base::NativeEventResult *result) override; - private: - bool _initialized = false; const std::unique_ptr _helper; }; From 3dbf58c45fb9a184b6e82fc15b21f762c8dc1f1c Mon Sep 17 00:00:00 2001 From: Ilya Fedin Date: Sat, 21 May 2022 17:10:21 +0400 Subject: [PATCH 2/7] Make window resize less lagged on Windows --- ui/platform/win/ui_window_win.cpp | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/ui/platform/win/ui_window_win.cpp b/ui/platform/win/ui_window_win.cpp index 95957c0..72213a0 100644 --- a/ui/platform/win/ui_window_win.cpp +++ b/ui/platform/win/ui_window_win.cpp @@ -244,6 +244,18 @@ void WindowHelper::setNativeFrame(bool enabled) { updateMargins(); updateWindowFrameColors(); fixMaximizedWindow(); + SetWindowPos( + _handle, + 0, + 0, + 0, + 0, + 0, + SWP_FRAMECHANGED + | SWP_NOMOVE + | SWP_NOSIZE + | SWP_NOZORDER + | SWP_NOACTIVATE); } void WindowHelper::initialShadowUpdate() { @@ -403,17 +415,14 @@ bool WindowHelper::handleNativeEvent( } return true; case WM_NCCALCSIZE: { - if (_title->isHidden()) { + if (_title->isHidden() || !wParam) { return false; } WINDOWPLACEMENT wp; wp.length = sizeof(WINDOWPLACEMENT); if (GetWindowPlacement(_handle, &wp) && (wp.showCmd == SW_SHOWMAXIMIZED)) { - const auto params = (LPNCCALCSIZE_PARAMS)lParam; - const auto r = (wParam == TRUE) - ? ¶ms->rgrc[0] - : (LPRECT)lParam; + const auto r = &((LPNCCALCSIZE_PARAMS)lParam)->rgrc[0]; const auto hMonitor = MonitorFromPoint( { (r->left + r->right) / 2, (r->top + r->bottom) / 2 }, MONITOR_DEFAULTTONEAREST); @@ -433,8 +442,10 @@ bool WindowHelper::handleNativeEvent( } } } + if (result) *result = 0; + } else { + if (result) *result = WVR_REDRAW; } - if (result) *result = 0; return true; } From c499a437f8f48322aa5691dfb4419ec4fb1f8394 Mon Sep 17 00:00:00 2001 From: Ilya Fedin Date: Fri, 24 Jun 2022 20:57:27 +0400 Subject: [PATCH 3/7] Fix a crash while updating window extents --- ui/platform/ui_platform_window.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/platform/ui_platform_window.cpp b/ui/platform/ui_platform_window.cpp index 2ce63a2..c60519a 100644 --- a/ui/platform/ui_platform_window.cpp +++ b/ui/platform/ui_platform_window.cpp @@ -262,10 +262,10 @@ void DefaultWindowHelper::init() { Qt::WindowStates windowState) { if (const auto handle = window()->windowHandle()) { handle->setFlag(Qt::FramelessWindowHint, titleShown); + updateWindowExtents(); } else { window()->setWindowFlag(Qt::FramelessWindowHint, titleShown); } - updateWindowExtents(); }, window()->lifetime()); window()->events() | rpl::start_with_next([=](not_null e) { From db2638cf607be96ba121a3ef180e87d533abd613 Mon Sep 17 00:00:00 2001 From: Ilya Fedin Date: Sat, 25 Jun 2022 01:07:56 +0400 Subject: [PATCH 4/7] Fix painting of bottom left shadow corner --- ui/platform/ui_platform_window.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/platform/ui_platform_window.cpp b/ui/platform/ui_platform_window.cpp index c60519a..0a4a70f 100644 --- a/ui/platform/ui_platform_window.cpp +++ b/ui/platform/ui_platform_window.cpp @@ -315,7 +315,7 @@ void DefaultWindowHelper::updateRoundingOverlay() { rect.topRight() - QPoint(radiusWithFix, 0), radiusSize )) || clip.intersects(QRect( - rect.bottomRight() - QPoint(0, radiusWithFix), + rect.bottomLeft() - QPoint(0, radiusWithFix), radiusSize )) || clip.intersects(QRect( rect.bottomRight() - QPoint(radiusWithFix, radiusWithFix), From e91cfd55c243cfd2fa0d04f58616ee4f0a0ccb11 Mon Sep 17 00:00:00 2001 From: Ilya Fedin Date: Thu, 14 Jul 2022 12:54:09 +0400 Subject: [PATCH 5/7] Fix missing include for Qt 6.4 --- ui/effects/animations.h | 1 + 1 file changed, 1 insertion(+) diff --git a/ui/effects/animations.h b/ui/effects/animations.h index bdc3a45..a918cfc 100644 --- a/ui/effects/animations.h +++ b/ui/effects/animations.h @@ -10,6 +10,7 @@ #include #include +#include namespace Ui { namespace Animations { From ba7e3667d6c3bac46cf20c1b9c7a90801947cd41 Mon Sep 17 00:00:00 2001 From: Ilya Fedin Date: Thu, 14 Jul 2022 12:54:15 +0400 Subject: [PATCH 6/7] Adapt for Qt 6.4 device pixel ratio changes QWidget::devicePixelRatioF represents backing store ratio and it's no more equal to native surface ratio --- ui/platform/linux/ui_utility_linux.cpp | 11 +++++++---- ui/platform/win/ui_utility_win.cpp | 7 ++++--- ui/platform/win/ui_window_title_win.cpp | 3 ++- ui/platform/win/ui_window_win.cpp | 6 ++++-- 4 files changed, 17 insertions(+), 10 deletions(-) diff --git a/ui/platform/linux/ui_utility_linux.cpp b/ui/platform/linux/ui_utility_linux.cpp index 9414c55..5066c0b 100644 --- a/ui/platform/linux/ui_utility_linux.cpp +++ b/ui/platform/linux/ui_utility_linux.cpp @@ -21,6 +21,7 @@ #endif // !DESKTOP_APP_DISABLE_X11_INTEGRATION #include +#include #include namespace Ui { @@ -236,9 +237,9 @@ std::optional XCBIsOverlapped( const auto mappedRect = QRect( rect.topLeft() - * widget->devicePixelRatioF() + * widget->windowHandle()->devicePixelRatio() + windowGeometry.topLeft(), - rect.size() * widget->devicePixelRatioF()); + rect.size() * widget->windowHandle()->devicePixelRatio()); const auto cookie = xcb_query_tree(connection, *root); const auto reply = base::Platform::XCB::MakeReplyPointer( @@ -304,7 +305,9 @@ void SetXCBFrameExtents(not_null widget, const QMargins &extents) { return; } - const auto nativeExtents = extents * widget->devicePixelRatioF(); + const auto nativeExtents = extents + * widget->windowHandle()->devicePixelRatio(); + const auto extentsVector = std::vector{ uint(nativeExtents.left()), uint(nativeExtents.right()), @@ -368,7 +371,7 @@ void ShowXCBWindowMenu(not_null widget, const QPoint &point) { } const auto globalPos = point - * widget->devicePixelRatioF() + * widget->windowHandle()->devicePixelRatio() + windowGeometry.topLeft(); xcb_client_message_event_t xev; diff --git a/ui/platform/win/ui_utility_win.cpp b/ui/platform/win/ui_utility_win.cpp index b63a936..6d3154d 100644 --- a/ui/platform/win/ui_utility_win.cpp +++ b/ui/platform/win/ui_utility_win.cpp @@ -9,6 +9,7 @@ #include "base/platform/win/base_windows_h.h" #include +#include #include #include @@ -75,7 +76,7 @@ std::optional IsOverlapped( const auto nativeRect = [&] { const auto topLeft = [&] { const auto qpoints = rect.topLeft() - * widget->devicePixelRatioF(); + * widget->windowHandle()->devicePixelRatio(); POINT result{ qpoints.x(), qpoints.y(), @@ -85,7 +86,7 @@ std::optional IsOverlapped( }(); const auto bottomRight = [&] { const auto qpoints = rect.bottomRight() - * widget->devicePixelRatioF(); + * widget->windowHandle()->devicePixelRatio(); POINT result{ qpoints.x(), qpoints.y(), @@ -122,7 +123,7 @@ std::optional IsOverlapped( void ShowWindowMenu(not_null widget, const QPoint &point) { const auto handle = HWND(widget->winId()); - const auto mapped = point * widget->devicePixelRatioF(); + const auto mapped = point * widget->windowHandle()->devicePixelRatio(); POINT p{ mapped.x(), mapped.y() }; ClientToScreen(handle, &p); SendMessage( diff --git a/ui/platform/win/ui_window_title_win.cpp b/ui/platform/win/ui_window_title_win.cpp index 4defa64..fdb8b89 100644 --- a/ui/platform/win/ui_window_title_win.cpp +++ b/ui/platform/win/ui_window_title_win.cpp @@ -205,7 +205,8 @@ void TitleWidget::refreshAdditionalPaddings( return -1; } const auto pixels = (factor + 50) / 100; - return int(base::SafeRound(pixels / window()->devicePixelRatioF())); + return int(base::SafeRound( + pixels / window()->windowHandle()->devicePixelRatio())); }(); if (padding < 0) { return; diff --git a/ui/platform/win/ui_window_win.cpp b/ui/platform/win/ui_window_win.cpp index 72213a0..995c8d5 100644 --- a/ui/platform/win/ui_window_win.cpp +++ b/ui/platform/win/ui_window_win.cpp @@ -455,7 +455,8 @@ bool WindowHelper::handleNativeEvent( } POINT p{ GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) }; ScreenToClient(_handle, &p); - const auto mapped = QPoint(p.x, p.y) / window()->devicePixelRatioF(); + const auto mapped = QPoint(p.x, p.y) + / window()->windowHandle()->devicePixelRatio(); ShowWindowMenu(window(), mapped); if (result) *result = 0; } return true; @@ -547,7 +548,8 @@ bool WindowHelper::handleNativeEvent( POINT p{ GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) }; ScreenToClient(_handle, &p); - const auto mapped = QPoint(p.x, p.y) / window()->devicePixelRatioF(); + const auto mapped = QPoint(p.x, p.y) + / window()->windowHandle()->devicePixelRatio(); *result = [&] { if (!window()->rect().contains(mapped)) { return HTTRANSPARENT; From 48a34dc7469292ba2b63084d85209d353dc97ab9 Mon Sep 17 00:00:00 2001 From: Ilya Fedin Date: Mon, 18 Jul 2022 22:25:53 +0400 Subject: [PATCH 7/7] Get rid of QSurface::supportsOpenGL check It checks for surface type to be compatible with OpenGL, but there's no guarantee raster surface would return true here and once it's converted to an OpenGL surface, there's no need to check as it's known to support OpenGL. This is the case with all QWidgets in Qt 6.4. --- ui/gl/gl_detection.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/ui/gl/gl_detection.cpp b/ui/gl/gl_detection.cpp index 7c7ea3f..91af67f 100644 --- a/ui/gl/gl_detection.cpp +++ b/ui/gl/gl_detection.cpp @@ -79,10 +79,6 @@ Capabilities CheckCapabilities(QWidget *widget) { LOG(("OpenGL: Could not create window for widget.")); return {}; } - if (!widget->window()->windowHandle()->supportsOpenGL()) { - LOG_ONCE(("OpenGL: Not supported for window.")); - return {}; - } format = widget->window()->windowHandle()->format(); format.setAlphaBufferSize(8); widget->window()->windowHandle()->setFormat(format);