Merge branch 'dpi-scaling-factor'

Add DPI scaling factor and revert content scaling factor behaviour in
wxMSW and other ports not using logical pixels to be 3.0 compatible.

See https://github.com/wxWidgets/wxWidgets/pull/1985
This commit is contained in:
Vadim Zeitlin
2020-07-20 15:55:23 +02:00
25 changed files with 92 additions and 88 deletions

View File

@@ -86,7 +86,7 @@ Changes in behaviour not resulting in compilation errors
- wxGLCanvas now uses physical pixels on high DPI displays under platforms - wxGLCanvas now uses physical pixels on high DPI displays under platforms
where they're different from logical ones (wxGTK3, wxOSX). Multiply logical where they're different from logical ones (wxGTK3, wxOSX). Multiply logical
coordinates, e.g. returned by wxWindow::GetSize() by GetOpenGLScaleFactor() coordinates, e.g. returned by wxWindow::GetSize() by GetContentScaleFactor()
before using them with OpenGL functions. before using them with OpenGL functions.
- wxGTK now uses wxID_NONE item ID for wxEVT_MENU_HIGHLIGHT events sent when - wxGTK now uses wxID_NONE item ID for wxEVT_MENU_HIGHLIGHT events sent when

View File

@@ -258,11 +258,6 @@ public:
// as a parameter // as a parameter
wxGLContextAttrs& GetGLCTXAttrs() { return m_GLCTXAttrs; } wxGLContextAttrs& GetGLCTXAttrs() { return m_GLCTXAttrs; }
// Return the factor to apply to transform window coordinates (e.g. sizes)
// to OpenGL coordinates: it can be different from 1 on the platforms where
// logical pixels are different from physical ones (i.e. wxGTK3 and wxOSX).
virtual double GetOpenGLScaleFactor() const;
// deprecated methods using the implicit wxGLContext // deprecated methods using the implicit wxGLContext
#if WXWIN_COMPATIBILITY_2_8 #if WXWIN_COMPATIBILITY_2_8
wxDEPRECATED( wxGLContext* GetContext() const ); wxDEPRECATED( wxGLContext* GetContext() const );

View File

@@ -60,8 +60,6 @@ public:
virtual bool SetBackgroundStyle(wxBackgroundStyle style) wxOVERRIDE; virtual bool SetBackgroundStyle(wxBackgroundStyle style) wxOVERRIDE;
virtual double GetOpenGLScaleFactor() const wxOVERRIDE;
// implement wxGLCanvasX11 methods // implement wxGLCanvasX11 methods
// -------------------------------- // --------------------------------

View File

@@ -77,7 +77,6 @@ public:
virtual bool CanGetTextExtent() const wxOVERRIDE; virtual bool CanGetTextExtent() const wxOVERRIDE;
virtual int GetDepth() const wxOVERRIDE; virtual int GetDepth() const wxOVERRIDE;
virtual wxSize GetPPI() const wxOVERRIDE; virtual wxSize GetPPI() const wxOVERRIDE;
virtual double GetContentScaleFactor() const wxOVERRIDE;
virtual void SetMapMode(wxMappingMode mode) wxOVERRIDE; virtual void SetMapMode(wxMappingMode mode) wxOVERRIDE;

View File

@@ -100,7 +100,6 @@ public:
// implement wxGLCanvasBase methods // implement wxGLCanvasBase methods
virtual bool SwapBuffers() wxOVERRIDE; virtual bool SwapBuffers() wxOVERRIDE;
virtual double GetOpenGLScaleFactor() const wxOVERRIDE;
// Mac-specific functions // Mac-specific functions
// ---------------------- // ----------------------

View File

@@ -529,10 +529,16 @@ public:
return wxSize( wxMax( client.x, best.x ), wxMax( client.y, best.y ) ); return wxSize( wxMax( client.x, best.x ), wxMax( client.y, best.y ) );
} }
// returns the magnification of the content of this window // Return the magnification of the content of this window for the platforms
// e.g. 2.0 for a window on a retina screen // using logical pixels different from physical ones, i.e. those for which
// wxHAVE_DPI_INDEPENDENT_PIXELS is defined. For the other ones, always
// returns 1, regardless of DPI scale factor returned by the function below.
virtual double GetContentScaleFactor() const; virtual double GetContentScaleFactor() const;
// Return the ratio of the DPI used by this window to the standard DPI,
// e.g. 1 for standard DPI screens and 2 for "200% scaling".
double GetDPIScaleFactor() const;
// return the size of the left/right and top/bottom borders in x and y // return the size of the left/right and top/bottom borders in x and y
// components of the result respectively // components of the result respectively
virtual wxSize GetWindowBorderSize() const; virtual wxSize GetWindowBorderSize() const;
@@ -961,7 +967,7 @@ public:
// DPI-independent pixels, or DIPs, are pixel values for the standard // DPI-independent pixels, or DIPs, are pixel values for the standard
// 96 DPI display, they are scaled to take the current resolution into // 96 DPI display, they are scaled to take the current resolution into
// account (i.e. multiplied by the same factor as returned by // account (i.e. multiplied by the same factor as returned by
// GetContentScaleFactor()) if necessary for the current platform. // GetDPIScaleFactor()) if necessary for the current platform.
// //
// To support monitor-specific resolutions, prefer using the non-static // To support monitor-specific resolutions, prefer using the non-static
// member functions or use a valid (non-null) window pointer. // member functions or use a valid (non-null) window pointer.

View File

@@ -752,7 +752,7 @@ enum
platforms where wxWindow uses logical pixels, affected by the coordinate platforms where wxWindow uses logical pixels, affected by the coordinate
scaling, on high DPI displays. Thus, if you want to set the OpenGL view scaling, on high DPI displays. Thus, if you want to set the OpenGL view
port to the size of entire window, you must multiply the result returned by port to the size of entire window, you must multiply the result returned by
wxWindow::GetClientSize() by wxGLCanvas::GetOpenGLScaleFactor() before wxWindow::GetClientSize() by wxGLCanvas::GetContentScaleFactor() before
passing it to @c glViewport(). Same considerations apply to other OpenGL passing it to @c glViewport(). Same considerations apply to other OpenGL
functions and other coordinates, notably those retrieved from wxMouseEvent functions and other coordinates, notably those retrieved from wxMouseEvent
in the event handlers. in the event handlers.
@@ -936,23 +936,6 @@ public:
*/ */
bool SetCurrent(const wxGLContext& context) const; bool SetCurrent(const wxGLContext& context) const;
/**
Returns the scale factor for transformation between logical and
physical OpenGL coordinates.
This factor is always 1 on the platforms where logical pixels are the
same as physical ones, in any DPI (such as MSW), but can be different
from it on the platforms where logical and physical pixels may differ
due to DPI scaling (such as GTK 3 or macOS).
To handle the differences between the platforms, always multiply the
values expressed in window coordinates (window sizes, mouse position
etc) by this factor before passing them to OpenGL functions.
@since 3.1.4
*/
double GetOpenGLScaleFactor() const;
/** /**
Swaps the double-buffer of this window, making the back-buffer the Swaps the double-buffer of this window, making the back-buffer the
front-buffer and vice versa, so that the output of the previous OpenGL front-buffer and vice versa, so that the output of the previous OpenGL

View File

@@ -1045,7 +1045,7 @@ public:
A DPI-independent pixel is just a pixel at the standard 96 DPI A DPI-independent pixel is just a pixel at the standard 96 DPI
resolution. To keep the same physical size at higher resolution, the resolution. To keep the same physical size at higher resolution, the
physical pixel value must be scaled by GetContentScaleFactor() but this physical pixel value must be scaled by GetDPIScaleFactor() but this
scaling may be already done by the underlying toolkit (GTK+, Cocoa, scaling may be already done by the underlying toolkit (GTK+, Cocoa,
...) automatically. This method performs the conversion only if it is ...) automatically. This method performs the conversion only if it is
not already done by the lower level toolkit and so by using it with not already done by the lower level toolkit and so by using it with
@@ -1121,7 +1121,7 @@ public:
A DPI-independent pixel is just a pixel at the standard 96 DPI A DPI-independent pixel is just a pixel at the standard 96 DPI
resolution. To keep the same physical size at higher resolution, the resolution. To keep the same physical size at higher resolution, the
physical pixel value must be scaled by GetContentScaleFactor() but this physical pixel value must be scaled by GetDPIScaleFactor() but this
scaling may be already done by the underlying toolkit (GTK+, Cocoa, scaling may be already done by the underlying toolkit (GTK+, Cocoa,
...) automatically. This method performs the conversion only if it is ...) automatically. This method performs the conversion only if it is
not already done by the lower level toolkit, For example, you may not already done by the lower level toolkit, For example, you may
@@ -1387,22 +1387,57 @@ public:
virtual wxSize GetBestVirtualSize() const; virtual wxSize GetBestVirtualSize() const;
/** /**
Returns the magnification of the backing store of this window, eg 2.0 Returns the factor mapping logical pixels of this window to physical
for a window on a retina screen. pixels.
This factor should be used to determine the size of bitmaps and similar This function can be used to portably determine the number of physical
"content-containing" windows appropriate for the current resolution. pixels in a window of the given size, by multiplying the window size by
E.g. the program may load a 32px bitmap if the content scale factor is the value returned from it. I.e. it returns the factor converting window
1.0 or 64px version of the same bitmap if it is 2.0 or bigger. coordinates to "content view" coordinates, where the view can be just a
simple window displaying a wxBitmap or wxGLCanvas or any other kind of
window rendering arbitrary "content" on screen.
Notice that this method should @e not be used for window sizes, as they For the platforms not doing any pixel mapping, i.e. where logical and
are already scaled by this factor by the underlying toolkit under some physical pixels are one and the same, this function always returns 1.0
platforms. Use FromDIP() for anything window-related instead. and so using it is, in principle, unnecessary and could be avoided by
using preprocessor check for @c wxHAVE_DPI_INDEPENDENT_PIXELS @e not
being defined, however using this function unconditionally under all
platforms is usually simpler and so preferable.
@note Current behaviour of this function is compatible with wxWidgets
3.0, but different from its behaviour in versions 3.1.0 to 3.1.3,
where it returned the same value as GetDPIScaleFactor(). Please use
the other function if you need to use a scaling factor greater than
1.0 even for the platforms without @c wxHAVE_DPI_INDEPENDENT_PIXELS,
such as wxMSW.
@since 2.9.5 @since 2.9.5
*/ */
double GetContentScaleFactor() const; double GetContentScaleFactor() const;
/**
Returns the ratio of the DPI used by this window to the standard DPI.
The returned value is 1 for standard DPI screens or 2 for "200%
scaling" and, unlike for GetContentScaleFactor(), is the same under all
platforms.
This factor should be used to increase the size of icons and similar
windows whose best size is not based on text metrics when using DPI
scaling.
E.g. the program may load a 32px bitmap if the content scale factor is
1.0 or 64px version of the same bitmap if it is 2.0 or bigger.
Notice that this method should @e not be used for window sizes expressed
in pixels, as they are already scaled by this factor by the underlying
toolkit under some platforms. Use FromDIP() for anything window-related
instead.
@since 3.1.4
*/
double GetDPIScaleFactor() const;
/** /**
Returns the size of the left/right and top/bottom borders of this window in x Returns the size of the left/right and top/bottom borders of this window in x
and y components of the result respectively. and y components of the result respectively.

View File

@@ -349,7 +349,7 @@ void TestGLCanvas::OnPaint(wxPaintEvent& WXUNUSED(event))
// multiple canvases: If we updated the viewport in the wxSizeEvent // multiple canvases: If we updated the viewport in the wxSizeEvent
// handler, changing the size of one canvas causes a viewport setting that // handler, changing the size of one canvas causes a viewport setting that
// is wrong when next another canvas is repainted. // is wrong when next another canvas is repainted.
const wxSize ClientSize = GetClientSize() * GetOpenGLScaleFactor(); const wxSize ClientSize = GetClientSize() * GetContentScaleFactor();
TestGLContext& canvas = wxGetApp().GetContext(this, m_useStereo); TestGLContext& canvas = wxGetApp().GetContext(this, m_useStereo);
glViewport(0, 0, ClientSize.x, ClientSize.y); glViewport(0, 0, ClientSize.x, ClientSize.y);

View File

@@ -280,7 +280,7 @@ void TestGLCanvas::OnSize(wxSizeEvent& event)
// This is OK here only because there is only one canvas that uses the // This is OK here only because there is only one canvas that uses the
// context. See the cube sample for that case that multiple canvases are // context. See the cube sample for that case that multiple canvases are
// made current with one context. // made current with one context.
const wxSize size = event.GetSize() * GetOpenGLScaleFactor(); const wxSize size = event.GetSize() * GetContentScaleFactor();
glViewport(0, 0, size.x, size.y); glViewport(0, 0, size.x, size.y);
} }

View File

@@ -306,7 +306,7 @@ void TestGLCanvas::ResetProjectionMode()
// or more than one wxGLContext in the application. // or more than one wxGLContext in the application.
SetCurrent(*m_glRC); SetCurrent(*m_glRC);
const wxSize ClientSize = GetClientSize() * GetOpenGLScaleFactor(); const wxSize ClientSize = GetClientSize() * GetContentScaleFactor();
// It's up to the application code to update the OpenGL viewport settings. // It's up to the application code to update the OpenGL viewport settings.
// In order to avoid extensive context switching, consider doing this in // In order to avoid extensive context switching, consider doing this in

View File

@@ -565,7 +565,7 @@ void MyGLCanvas::OnSize(wxSizeEvent& event)
SetCurrent(*m_oglContext); SetCurrent(*m_oglContext);
// It's up to the application code to update the OpenGL viewport settings. // It's up to the application code to update the OpenGL viewport settings.
const wxSize size = event.GetSize() * GetOpenGLScaleFactor(); const wxSize size = event.GetSize() * GetContentScaleFactor();
m_winHeight = size.y; m_winHeight = size.y;
m_oglManager->SetViewport(0, 0, size.x, m_winHeight); m_oglManager->SetViewport(0, 0, size.x, m_winHeight);

View File

@@ -802,7 +802,7 @@ void wxAuiDefaultDockArt::DrawPaneButton(wxDC& dc,
break; break;
} }
wxAuiScaleBitmap(bmp, window->GetContentScaleFactor()); wxAuiScaleBitmap(bmp, window->GetDPIScaleFactor());
wxRect rect = _rect; wxRect rect = _rect;

View File

@@ -578,7 +578,7 @@ void wxAuiGenericTabArt::DrawTab(wxDC& dc,
bmp = m_activeCloseBmp; bmp = m_activeCloseBmp;
} }
wxAuiScaleBitmap(bmp, wnd->GetContentScaleFactor()); wxAuiScaleBitmap(bmp, wnd->GetDPIScaleFactor());
int offsetY = tab_y-1; int offsetY = tab_y-1;
if (m_flags & wxAUI_NB_BOTTOM) if (m_flags & wxAUI_NB_BOTTOM)
@@ -755,7 +755,7 @@ void wxAuiGenericTabArt::DrawButton(wxDC& dc,
if (!bmp.IsOk()) if (!bmp.IsOk())
return; return;
wxAuiScaleBitmap(bmp, wnd->GetContentScaleFactor()); wxAuiScaleBitmap(bmp, wnd->GetDPIScaleFactor());
rect = in_rect; rect = in_rect;
@@ -1125,7 +1125,7 @@ void wxAuiSimpleTabArt::DrawTab(wxDC& dc,
else else
bmp = m_disabledCloseBmp; bmp = m_disabledCloseBmp;
wxAuiScaleBitmap(bmp, wnd->GetContentScaleFactor()); wxAuiScaleBitmap(bmp, wnd->GetDPIScaleFactor());
wxRect rect(tab_x + tab_width - bmp.GetScaledWidth() - 1, wxRect rect(tab_x + tab_width - bmp.GetScaledWidth() - 1,
tab_y + (tab_height/2) - (bmp.GetScaledHeight()/2) + 1, tab_y + (tab_height/2) - (bmp.GetScaledHeight()/2) + 1,
@@ -1273,7 +1273,7 @@ void wxAuiSimpleTabArt::DrawButton(wxDC& dc,
if (!bmp.IsOk()) if (!bmp.IsOk())
return; return;
wxAuiScaleBitmap(bmp, wnd->GetContentScaleFactor()); wxAuiScaleBitmap(bmp, wnd->GetDPIScaleFactor());
rect = in_rect; rect = in_rect;

View File

@@ -358,7 +358,13 @@ wxString CreateBrushFill(const wxBrush& brush, wxSVGShapeRenderingMode mode)
void SetScaledScreenDCFont(wxScreenDC& sDC, const wxFont& font) void SetScaledScreenDCFont(wxScreenDC& sDC, const wxFont& font)
{ {
const double scale = sDC.GetContentScaleFactor(); // When using DPI-independent pixels, the results of GetTextExtent() and
// similar don't depend on DPI anyhow.
#ifndef wxHAVE_DPI_INDEPENDENT_PIXELS
static const int SVG_DPI = 96;
const double screenDPI = sDC.GetPPI().y;
const double scale = screenDPI / SVG_DPI;
if ( scale > 1 ) if ( scale > 1 )
{ {
// wxScreenDC uses the DPI of the main screen to determine the text // wxScreenDC uses the DPI of the main screen to determine the text
@@ -373,6 +379,7 @@ void SetScaledScreenDCFont(wxScreenDC& sDC, const wxFont& font)
sDC.SetFont(scaledFont); sDC.SetFont(scaledFont);
} }
else else
#endif // !wxHAVE_DPI_INDEPENDENT_PIXELS
{ {
sDC.SetFont(font); sDC.SetFont(font);
} }

View File

@@ -376,11 +376,6 @@ bool wxGLCanvasBase::ParseAttribList(const int *attribList,
return true; return true;
} }
double wxGLCanvasBase::GetOpenGLScaleFactor() const
{
return 1.0;
}
// ============================================================================ // ============================================================================
// compatibility layer for OpenGL 3 and OpenGL ES // compatibility layer for OpenGL 3 and OpenGL ES
// ============================================================================ // ============================================================================

View File

@@ -111,7 +111,7 @@ float wxSizerFlags::DoGetDefaultBorderInPx()
if ( s_defaultBorderInPx.HasChanged(win) ) if ( s_defaultBorderInPx.HasChanged(win) )
{ {
s_defaultBorderInPx.SetAtNewDPI( s_defaultBorderInPx.SetAtNewDPI(
(float)(5 * (win ? win->GetContentScaleFactor() : 1))); (float)(5 * (win ? win->GetDPIScaleFactor() : 1.0)));
} }
return s_defaultBorderInPx.Get(); return s_defaultBorderInPx.Get();
} }

View File

@@ -101,9 +101,12 @@ bool IsInCaptureStack(wxWindowBase* win);
} // wxMouseCapture } // wxMouseCapture
// We consider 96 DPI to be the standard value, this is correct at least for // Most platforms use 96 DPI by default, but Mac traditionally uses 72.
// MSW, but could conceivably need adjustment for the other platforms. #ifdef __WXOSX__
static const int BASELINE_DPI = 72;
#else
static const int BASELINE_DPI = 96; static const int BASELINE_DPI = 96;
#endif
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// static data // static data
@@ -810,6 +813,16 @@ static wxSize GetDPIHelper(const wxWindowBase* w)
} }
double wxWindowBase::GetContentScaleFactor() const double wxWindowBase::GetContentScaleFactor() const
{
// By default, we assume that there is no mapping between logical and
// physical pixels and so the content scale factor is just 1. Only the
// platforms that do perform such mapping (currently ports for Apple
// platforms and GTK 3) override this function to return something
// different.
return 1.0;
}
double wxWindowBase::GetDPIScaleFactor() const
{ {
const wxSize dpi = GetDPIHelper(this); const wxSize dpi = GetDPIHelper(this);

View File

@@ -271,13 +271,4 @@ void wxGLCanvas::GTKInitImplicitContext()
#endif // WXWIN_COMPATIBILITY_2_8 #endif // WXWIN_COMPATIBILITY_2_8
double wxGLCanvas::GetOpenGLScaleFactor() const
{
#ifdef __WXGTK3__
return GetContentScaleFactor();
#else
return 1.0;
#endif
}
#endif // wxUSE_GLCANVAS #endif // wxUSE_GLCANVAS

View File

@@ -493,7 +493,7 @@ bool wxHtmlWindow::DoSetPage(const wxString& source)
double pixelScale = 1.0; double pixelScale = 1.0;
#ifndef wxHAVE_DPI_INDEPENDENT_PIXELS #ifndef wxHAVE_DPI_INDEPENDENT_PIXELS
pixelScale = GetContentScaleFactor(); pixelScale = GetDPIScaleFactor();
#endif #endif
m_Parser->SetDC(&dc, pixelScale, 1.0); m_Parser->SetDC(&dc, pixelScale, 1.0);

View File

@@ -2555,11 +2555,6 @@ wxSize wxMSWDCImpl::GetPPI() const
return ppi; return ppi;
} }
double wxMSWDCImpl::GetContentScaleFactor() const
{
return GetPPI().y / 96.0;
}
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// DC caching // DC caching
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------

View File

@@ -562,11 +562,6 @@ bool wxGLCanvas::IsAGLMultiSampleAvailable()
return s_isMultiSampleAvailable != 0; return s_isMultiSampleAvailable != 0;
} }
double wxGLCanvas::GetOpenGLScaleFactor() const
{
return GetContentScaleFactor();
}
/* static */ /* static */
bool wxGLCanvasBase::IsDisplaySupported(const wxGLAttributes& dispAttrs) bool wxGLCanvasBase::IsDisplaySupported(const wxGLAttributes& dispAttrs)
{ {

View File

@@ -4610,7 +4610,7 @@ void wxPropertyGrid::OnResize( wxSizeEvent& event )
if ( !HasExtraStyle(wxPG_EX_NATIVE_DOUBLE_BUFFERING) ) if ( !HasExtraStyle(wxPG_EX_NATIVE_DOUBLE_BUFFERING) )
{ {
double scaleFactor = GetContentScaleFactor(); double scaleFactor = GetDPIScaleFactor();
int dblh = (m_lineHeight*2); int dblh = (m_lineHeight*2);
if ( !m_doubleBuffer ) if ( !m_doubleBuffer )
{ {

View File

@@ -12687,11 +12687,8 @@ bool wxRichTextImage::LoadAndScaleImageCache(wxImage& image, const wxSize& sz, w
else else
{ {
double scaleFactor = 1.0; double scaleFactor = 1.0;
// Scaled bitmaps only work on Mac currently
#ifdef __WXOSX_COCOA__
if (context.GetBuffer() && context.GetBuffer()->GetRichTextCtrl()) if (context.GetBuffer() && context.GetBuffer()->GetRichTextCtrl())
scaleFactor = context.GetBuffer()->GetRichTextCtrl()->GetContentScaleFactor(); scaleFactor = context.GetBuffer()->GetRichTextCtrl()->GetContentScaleFactor();
#endif
// If the original width and height is small, e.g. 400 or below, // If the original width and height is small, e.g. 400 or below,
// scale up and then down to improve image quality. This can make // scale up and then down to improve image quality. This can make

View File

@@ -301,12 +301,8 @@ void SurfaceImpl::InitPixMap(int width, int height, Surface *surface, WindowID w
hdcOwned = true; hdcOwned = true;
if (width < 1) width = 1; if (width < 1) width = 1;
if (height < 1) height = 1; if (height < 1) height = 1;
#ifdef __WXMSW__
bitmap = new wxBitmap(width, height);
#else
bitmap = new wxBitmap(); bitmap = new wxBitmap();
bitmap->CreateScaled(width, height,wxBITMAP_SCREEN_DEPTH,(GETWIN(winid))->GetContentScaleFactor()); bitmap->CreateScaled(width, height,wxBITMAP_SCREEN_DEPTH,(GETWIN(winid))->GetContentScaleFactor());
#endif
mdc->SelectObject(*bitmap); mdc->SelectObject(*bitmap);
} }