Update sizer borders and spacers on DPI change.

Closes #18551.

See https://github.com/wxWidgets/wxWidgets/pull/1628
This commit is contained in:
Vadim Zeitlin
2019-11-02 16:26:14 +01:00
4 changed files with 64 additions and 15 deletions

View File

@@ -106,6 +106,11 @@ public:
// default border size used by Border() below // default border size used by Border() below
static int GetDefaultBorder() static int GetDefaultBorder()
{
return wxRound(GetDefaultBorderFractional());
}
static float GetDefaultBorderFractional()
{ {
#if wxUSE_BORDER_BY_DEFAULT #if wxUSE_BORDER_BY_DEFAULT
#ifdef __WXGTK20__ #ifdef __WXGTK20__
@@ -145,7 +150,7 @@ public:
wxSizerFlags& Border(int direction = wxALL) wxSizerFlags& Border(int direction = wxALL)
{ {
#if wxUSE_BORDER_BY_DEFAULT #if wxUSE_BORDER_BY_DEFAULT
return Border(direction, GetDefaultBorder()); return Border(direction, wxRound(GetDefaultBorderFractional()));
#else #else
// no borders by default on limited size screen // no borders by default on limited size screen
wxUnusedVar(direction); wxUnusedVar(direction);
@@ -157,7 +162,7 @@ public:
wxSizerFlags& DoubleBorder(int direction = wxALL) wxSizerFlags& DoubleBorder(int direction = wxALL)
{ {
#if wxUSE_BORDER_BY_DEFAULT #if wxUSE_BORDER_BY_DEFAULT
return Border(direction, 2*GetDefaultBorder()); return Border(direction, wxRound(2 * GetDefaultBorderFractional()));
#else #else
wxUnusedVar(direction); wxUnusedVar(direction);
@@ -168,7 +173,7 @@ public:
wxSizerFlags& TripleBorder(int direction = wxALL) wxSizerFlags& TripleBorder(int direction = wxALL)
{ {
#if wxUSE_BORDER_BY_DEFAULT #if wxUSE_BORDER_BY_DEFAULT
return Border(direction, 3*GetDefaultBorder()); return Border(direction, wxRound(3 * GetDefaultBorderFractional()));
#else #else
wxUnusedVar(direction); wxUnusedVar(direction);
@@ -179,7 +184,7 @@ public:
wxSizerFlags& HorzBorder() wxSizerFlags& HorzBorder()
{ {
#if wxUSE_BORDER_BY_DEFAULT #if wxUSE_BORDER_BY_DEFAULT
return Border(wxLEFT | wxRIGHT, GetDefaultBorder()); return Border(wxLEFT | wxRIGHT, wxRound(GetDefaultBorderFractional()));
#else #else
return *this; return *this;
#endif #endif
@@ -188,7 +193,7 @@ public:
wxSizerFlags& DoubleHorzBorder() wxSizerFlags& DoubleHorzBorder()
{ {
#if wxUSE_BORDER_BY_DEFAULT #if wxUSE_BORDER_BY_DEFAULT
return Border(wxLEFT | wxRIGHT, 2*GetDefaultBorder()); return Border(wxLEFT | wxRIGHT, wxRound(2 * GetDefaultBorderFractional()));
#else #else
return *this; return *this;
#endif #endif
@@ -223,7 +228,7 @@ public:
private: private:
#ifdef wxNEEDS_BORDER_IN_PX #ifdef wxNEEDS_BORDER_IN_PX
static int DoGetDefaultBorderInPx(); static float DoGetDefaultBorderInPx();
#endif // wxNEEDS_BORDER_IN_PX #endif // wxNEEDS_BORDER_IN_PX
int m_proportion; int m_proportion;

View File

@@ -1493,9 +1493,21 @@ public:
This value is scaled appropriately for the current DPI on the systems This value is scaled appropriately for the current DPI on the systems
where physical pixel values are used for the control positions and where physical pixel values are used for the control positions and
sizes, i.e. not with wxGTK or wxOSX. sizes, i.e. not with wxGTK or wxOSX.
@see GetDefaultBorderFractional()
*/ */
static int GetDefaultBorder(); 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). Aligns the object to the left, similar for @c Align(wxALIGN_LEFT).

View File

@@ -93,7 +93,7 @@ WX_DEFINE_EXPORTED_LIST( wxSizerItemList )
#ifdef wxNEEDS_BORDER_IN_PX #ifdef wxNEEDS_BORDER_IN_PX
/* static */ /* static */
int wxSizerFlags::DoGetDefaultBorderInPx() float wxSizerFlags::DoGetDefaultBorderInPx()
{ {
// Hard code 5px as it's the minimal border size between two controls, see // Hard code 5px as it's the minimal border size between two controls, see
// the table at the bottom of // 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 // as we don't have any associated window -- but, again, without changes
// in the API, there is nothing we can do about this. // in the API, there is nothing we can do about this.
const wxWindow* const win = wxTheApp ? wxTheApp->GetTopWindow() : NULL; const wxWindow* const win = wxTheApp ? wxTheApp->GetTopWindow() : NULL;
static wxPrivate::DpiDependentValue<int> s_defaultBorderInPx; static wxPrivate::DpiDependentValue<float> s_defaultBorderInPx;
if ( s_defaultBorderInPx.HasChanged(win) ) 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(); return s_defaultBorderInPx.Get();
} }

View File

@@ -4886,11 +4886,42 @@ wxWindowMSW::MSWUpdateOnDPIChange(const wxSize& oldDPI, const wxSize& newDPI)
// update font if necessary // update font if necessary
MSWUpdateFontOnDPIChange(newDPI); MSWUpdateFontOnDPIChange(newDPI);
// update children // update sizers
wxWindowList::compatibility_iterator current = GetChildren().GetFirst(); if ( GetSizer() )
while ( current )
{ {
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. // Update all children, except other top-level windows.
// These could be on a different monitor and will get their own // These could be on a different monitor and will get their own
// dpi-changed event. // dpi-changed event.
@@ -4898,8 +4929,6 @@ wxWindowMSW::MSWUpdateOnDPIChange(const wxSize& oldDPI, const wxSize& newDPI)
{ {
childWin->MSWUpdateOnDPIChange(oldDPI, newDPI); childWin->MSWUpdateOnDPIChange(oldDPI, newDPI);
} }
current = current->GetNext();
} }
wxDPIChangedEvent event(oldDPI, newDPI); wxDPIChangedEvent event(oldDPI, newDPI);