From 49b4e65facbe84018c2726431e87f642339fa731 Mon Sep 17 00:00:00 2001 From: AliKet Date: Mon, 20 Apr 2026 00:23:20 +0100 Subject: [PATCH] wxDC::LogicalToDevice{Rel}() now return unmirrored coordinates in RTL under wxMSW Ditto for wxDC::DeviceToLogical{Rel}() functions. In RTL layout, these functions always return unmirrored coordinates under wxGTK3 and wxQt. This is now the case under wxMSW too for consistency and also to fix double-mirroring problem when passing the transformed coordinates to GDI drawing functions. See wxGrid::Render() for example. --- include/wx/msw/private/dc.h | 28 ++++++++++++++++++++++++++++ src/msw/dc.cpp | 8 ++++++++ 2 files changed, 36 insertions(+) diff --git a/include/wx/msw/private/dc.h b/include/wx/msw/private/dc.h index 303cd19df6..b6355154bf 100644 --- a/include/wx/msw/private/dc.h +++ b/include/wx/msw/private/dc.h @@ -141,6 +141,34 @@ private: wxDECLARE_NO_COPY_CLASS(wxBkModeChanger); }; +// ---------------------------------------------------------------------------- +// Class to temporarily disable RTL layout if already set on the device context +// ---------------------------------------------------------------------------- + +// For consistency with wxGTK and wxQt, wxDC::LogicalToDevice{Rel}() and +// DeviceToLogical{Rel}() functions should return unmirrored coordinates +// in RTL layout to avoid double-mirroring when their results are passed +// to GDI drawing functions. +class wxScopedRTLDisabler +{ +public: + explicit wxScopedRTLDisabler(HDC hdc) + : m_hdc(hdc), m_oldLayoutDir(::SetLayout(hdc, 0)) + { + } + + ~wxScopedRTLDisabler() + { + ::SetLayout(m_hdc, m_oldLayoutDir); + } + +private: + HDC m_hdc; + const DWORD m_oldLayoutDir; + + wxDECLARE_NO_COPY_CLASS(wxScopedRTLDisabler); +}; + } // namespace wxMSWImpl #endif // _MSW_PRIVATE_DC_H_ diff --git a/src/msw/dc.cpp b/src/msw/dc.cpp index 486ba71a71..08b8bb4dc1 100644 --- a/src/msw/dc.cpp +++ b/src/msw/dc.cpp @@ -1969,6 +1969,8 @@ void wxMSWDCImpl::SetDeviceOrigin(wxCoord x, wxCoord y) wxPoint wxMSWDCImpl::DeviceToLogical(wxCoord x, wxCoord y) const { + wxScopedRTLDisabler disableRTL(GetHdc()); + POINT p; p.x = x; p.y = y; @@ -2015,6 +2017,8 @@ wxPoint wxMSWDCImpl::DeviceToLogical(wxCoord x, wxCoord y) const wxPoint wxMSWDCImpl::LogicalToDevice(wxCoord x, wxCoord y) const { + wxScopedRTLDisabler disableRTL(GetHdc()); + POINT p; p.x = x; p.y = y; @@ -2024,6 +2028,8 @@ wxPoint wxMSWDCImpl::LogicalToDevice(wxCoord x, wxCoord y) const wxSize wxMSWDCImpl::DeviceToLogicalRel(int x, int y) const { + wxScopedRTLDisabler disableRTL(GetHdc()); + POINT p[2]; p[0].x = 0; p[0].y = 0; @@ -2035,6 +2041,8 @@ wxSize wxMSWDCImpl::DeviceToLogicalRel(int x, int y) const wxSize wxMSWDCImpl::LogicalToDeviceRel(int x, int y) const { + wxScopedRTLDisabler disableRTL(GetHdc()); + POINT p[2]; p[0].x = 0; p[0].y = 0;