diff --git a/include/wx/sizer.h b/include/wx/sizer.h index 0d4fdeac09..4a51b11c3f 100644 --- a/include/wx/sizer.h +++ b/include/wx/sizer.h @@ -106,6 +106,11 @@ public: // default border size used by Border() below static int GetDefaultBorder() + { + return wxRound(GetDefaultBorderFractional()); + } + + static float GetDefaultBorderFractional() { #if wxUSE_BORDER_BY_DEFAULT #ifdef __WXGTK20__ @@ -145,7 +150,7 @@ public: wxSizerFlags& Border(int direction = wxALL) { #if wxUSE_BORDER_BY_DEFAULT - return Border(direction, GetDefaultBorder()); + return Border(direction, wxRound(GetDefaultBorderFractional())); #else // no borders by default on limited size screen wxUnusedVar(direction); @@ -157,7 +162,7 @@ public: wxSizerFlags& DoubleBorder(int direction = wxALL) { #if wxUSE_BORDER_BY_DEFAULT - return Border(direction, 2*GetDefaultBorder()); + return Border(direction, wxRound(2 * GetDefaultBorderFractional())); #else wxUnusedVar(direction); @@ -168,7 +173,7 @@ public: wxSizerFlags& TripleBorder(int direction = wxALL) { #if wxUSE_BORDER_BY_DEFAULT - return Border(direction, 3*GetDefaultBorder()); + return Border(direction, wxRound(3 * GetDefaultBorderFractional())); #else wxUnusedVar(direction); @@ -179,7 +184,7 @@ public: wxSizerFlags& HorzBorder() { #if wxUSE_BORDER_BY_DEFAULT - return Border(wxLEFT | wxRIGHT, GetDefaultBorder()); + return Border(wxLEFT | wxRIGHT, wxRound(GetDefaultBorderFractional())); #else return *this; #endif @@ -188,7 +193,7 @@ public: wxSizerFlags& DoubleHorzBorder() { #if wxUSE_BORDER_BY_DEFAULT - return Border(wxLEFT | wxRIGHT, 2*GetDefaultBorder()); + return Border(wxLEFT | wxRIGHT, wxRound(2 * GetDefaultBorderFractional())); #else return *this; #endif @@ -223,7 +228,7 @@ public: private: #ifdef wxNEEDS_BORDER_IN_PX - static int DoGetDefaultBorderInPx(); + static float DoGetDefaultBorderInPx(); #endif // wxNEEDS_BORDER_IN_PX int m_proportion; diff --git a/interface/wx/sizer.h b/interface/wx/sizer.h index 90b2b5751d..a3ceab8e70 100644 --- a/interface/wx/sizer.h +++ b/interface/wx/sizer.h @@ -1493,9 +1493,21 @@ public: This value is scaled appropriately for the current DPI on the systems where physical pixel values are used for the control positions and sizes, i.e. not with wxGTK or wxOSX. + + @see GetDefaultBorderFractional() */ static int GetDefaultBorder(); + /** + Returns the border used by default, with fractional precision. For + example when the border is scaled to a non-integer DPI. + + @see GetDefaultBorder() + + @since 3.1.4 + */ + static float GetDefaultBorderFractional(); + /** Aligns the object to the left, similar for @c Align(wxALIGN_LEFT). diff --git a/src/common/sizer.cpp b/src/common/sizer.cpp index d6b270e3e8..da1a350598 100644 --- a/src/common/sizer.cpp +++ b/src/common/sizer.cpp @@ -93,7 +93,7 @@ WX_DEFINE_EXPORTED_LIST( wxSizerItemList ) #ifdef wxNEEDS_BORDER_IN_PX /* static */ -int wxSizerFlags::DoGetDefaultBorderInPx() +float wxSizerFlags::DoGetDefaultBorderInPx() { // Hard code 5px as it's the minimal border size between two controls, see // the table at the bottom of @@ -107,9 +107,12 @@ int wxSizerFlags::DoGetDefaultBorderInPx() // as we don't have any associated window -- but, again, without changes // in the API, there is nothing we can do about this. const wxWindow* const win = wxTheApp ? wxTheApp->GetTopWindow() : NULL; - static wxPrivate::DpiDependentValue s_defaultBorderInPx; + static wxPrivate::DpiDependentValue s_defaultBorderInPx; if ( s_defaultBorderInPx.HasChanged(win) ) - s_defaultBorderInPx.SetAtNewDPI(wxWindow::FromDIP(5, win)); + { + s_defaultBorderInPx.SetAtNewDPI( + (float)(5 * (win ? win->GetContentScaleFactor() : 1))); + } return s_defaultBorderInPx.Get(); } diff --git a/src/msw/window.cpp b/src/msw/window.cpp index 8f683c5773..088bc30dcb 100644 --- a/src/msw/window.cpp +++ b/src/msw/window.cpp @@ -4886,11 +4886,42 @@ wxWindowMSW::MSWUpdateOnDPIChange(const wxSize& oldDPI, const wxSize& newDPI) // update font if necessary MSWUpdateFontOnDPIChange(newDPI); - // update children - wxWindowList::compatibility_iterator current = GetChildren().GetFirst(); - while ( current ) + // update sizers + if ( GetSizer() ) { - wxWindow *childWin = current->GetData(); + for ( wxSizerItemList::compatibility_iterator + node = GetSizer()->GetChildren().GetFirst(); + node; + node = node->GetNext() ) + { + wxSizerItem* sizerItem = node->GetData(); + + int border = sizerItem->GetBorder(); + ScaleCoordIfSet(border, scaleFactor); + sizerItem->SetBorder(border); + + // only scale sizers and spacers, not windows + if ( sizerItem->IsSizer() || sizerItem->IsSpacer() ) + { + wxSize min = sizerItem->GetMinSize(); + ScaleCoordIfSet(min.x, scaleFactor); + ScaleCoordIfSet(min.y, scaleFactor); + sizerItem->SetMinSize(min); + + wxSize size = sizerItem->GetSize(); + ScaleCoordIfSet(size.x, scaleFactor); + ScaleCoordIfSet(size.y, scaleFactor); + sizerItem->SetDimension(wxDefaultPosition, size); + } + } + } + + // update children + for ( wxWindowList::compatibility_iterator node = GetChildren().GetFirst(); + node; + node = node->GetNext() ) + { + wxWindow *childWin = node->GetData(); // Update all children, except other top-level windows. // These could be on a different monitor and will get their own // dpi-changed event. @@ -4898,8 +4929,6 @@ wxWindowMSW::MSWUpdateOnDPIChange(const wxSize& oldDPI, const wxSize& newDPI) { childWin->MSWUpdateOnDPIChange(oldDPI, newDPI); } - - current = current->GetNext(); } wxDPIChangedEvent event(oldDPI, newDPI);