From 59531f96168f40716dedfcf7513f4e28bb438ec5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Va=CC=81clav=20Slavi=CC=81k?= Date: Mon, 4 Apr 2016 18:11:14 +0200 Subject: [PATCH] MSW: Fix dialog default positions under RTL locales Toplevel windows use their parent's coordinate system as the reference frame, not desktop's, so need to be adjusted accordingly if its mirrored. Without these changes, default-positioned wxDialogs would end to the right side of the parent window's right border (instead of being slightly inside the window) and changing their size would move them as well. --- src/msw/toplevel.cpp | 7 ++++--- src/msw/window.cpp | 41 ++++++++++++++++++++++++++++++++++++++--- 2 files changed, 42 insertions(+), 6 deletions(-) diff --git a/src/msw/toplevel.cpp b/src/msw/toplevel.cpp index 37b3a3d0a7..eb78795b6e 100644 --- a/src/msw/toplevel.cpp +++ b/src/msw/toplevel.cpp @@ -613,10 +613,11 @@ bool wxTopLevelWindowMSW::Create(wxWindow *parent, memset(dlgTemplate, 0, dlgsize); // these values are arbitrary, they won't be used normally anyhow - dlgTemplate->x = 34; + const LONG baseUnits = ::GetDialogBaseUnits(); + dlgTemplate->x = 34; dlgTemplate->y = 22; - dlgTemplate->cx = 144; - dlgTemplate->cy = 75; + dlgTemplate->cx = ::MulDiv(sizeReal.x, 4, LOWORD(baseUnits)); + dlgTemplate->cy = ::MulDiv(sizeReal.y, 8, HIWORD(baseUnits)); // reuse the code in MSWGetStyle() but correct the results slightly for // the dialog diff --git a/src/msw/window.cpp b/src/msw/window.cpp index 328fca8139..584116a34d 100644 --- a/src/msw/window.cpp +++ b/src/msw/window.cpp @@ -1937,6 +1937,26 @@ wxWindowMSW::DoMoveSibling(WXHWND hwnd, int x, int y, int width, int height) // otherwise (or if deferring failed) move the window in place immediately #endif // wxUSE_DEFERRED_SIZING + + // toplevel window's coordinates are mirrored if the TLW is a child of another + // RTL window and changing width without moving the position would enlarge the + // window in the wrong direction, so we need to adjust for it + if ( IsTopLevel() ) + { + // note that this may be different from GetParent() for wxDialogs + HWND tlwParent = ::GetParent((HWND)hwnd); + if ( tlwParent && (::GetWindowLong(tlwParent, GWL_EXSTYLE) & WS_EX_LAYOUTRTL) != 0 ) + { + RECT old; + ::GetWindowRect((HWND) hwnd, &old); + if ( old.left == x && old.right - old.left != width ) + { + x -= width - (old.right - old.left); + } + // else: not a simple resize + } + } + if ( !::MoveWindow((HWND)hwnd, x, y, width, height, IsShown()) ) { wxLogLastError(wxT("MoveWindow")); @@ -2082,10 +2102,25 @@ void wxWindowMSW::DoSetClientSize(int width, int height) const int widthWin = rectWin.right - rectWin.left, heightWin = rectWin.bottom - rectWin.top; - // MoveWindow positions the child windows relative to the parent, so - // adjust if necessary - if ( !IsTopLevel() ) + if ( IsTopLevel() ) { + // toplevel window's coordinates are mirrored if the TLW is a child of another + // RTL window and changing width without moving the position would enlarge the + // window in the wrong direction, so we need to adjust for it + + // note that this may be different from GetParent() for wxDialogs + HWND tlwParent = ::GetParent(GetHwnd()); + if ( tlwParent && (::GetWindowLong(tlwParent, GWL_EXSTYLE) & WS_EX_LAYOUTRTL) != 0 ) + { + const int diffWidth = width - (rectClient.right - rectClient.left); + rectWin.left -= diffWidth; + rectWin.right -= diffWidth; + } + } + else + { + // MoveWindow positions the child windows relative to the parent, so + // adjust if necessary wxWindow *parent = GetParent(); if ( parent ) {