Add wxWindow::FromDIP() for simpler high DPI support.

This method allows to scale a pixel value by a DPI-dependent factor to the
value used by the underlying toolkit only if necessary, i.e. when not using
GTK+ 3 or OS X which already do this internally.
This commit is contained in:
Vadim Zeitlin 2015-03-20 00:01:57 +01:00
parent bc492a9e6e
commit 00748bbaef
4 changed files with 74 additions and 10 deletions

View File

@ -65,6 +65,7 @@ Unix:
All (GUI):
- Allow requesting modern (3.x+) OpenGL version in wxGLCanvas (Fabio Arnold).
- Add wxWindow::FromDIP() for simpler high DPI support.
- Allow customizing window shown by wxBusyInfo.
- Add wxAddRemoveCtrl.
- Add wxAppProgressIndicator for MSW (Chaobin Zhang) and OS X (Tobias Taschner).

View File

@ -950,8 +950,18 @@ public:
#endif // wxUSE_HOTKEY
// dialog units translations
// -------------------------
// translation between different units
// -----------------------------------
// DPI-independent pixels, or DIPs, are pixel values for the standard
// 96 DPI display, they are scaled to take the current resolution into
// account (i.e. by the factor returned by GetContentScaleFactor()) if
// necessary for the current platform.
wxSize FromDIP(const wxSize& sz) const;
// Dialog units are based on the size of the current font.
wxPoint ConvertPixelsToDialog( const wxPoint& pt ) const;
wxPoint ConvertDialogToPixels( const wxPoint& pt ) const;
@ -1891,6 +1901,9 @@ inline void wxWindowBase::SetInitialBestSize(const wxSize& size)
#define wxWindowGTK wxWindow
#endif // wxUniv
#include "wx/gtk/window.h"
#ifdef __WXGTK3__
#define wxHAVE_DPI_INDEPENDENT_PIXELS
#endif
#elif defined(__WXGTK__)
#ifdef __WXUNIVERSAL__
#define wxWindowNative wxWindowGTK
@ -1915,6 +1928,7 @@ inline void wxWindowBase::SetInitialBestSize(const wxSize& size)
#define wxWindowMac wxWindow
#endif // wxUniv
#include "wx/osx/window.h"
#define wxHAVE_DPI_INDEPENDENT_PIXELS
#elif defined(__WXQT__)
#ifdef __WXUNIVERSAL__
#define wxWindowNative wxWindowQt
@ -1944,6 +1958,13 @@ inline wxWindow *wxWindowBase::GetGrandParent() const
return m_parent ? m_parent->GetParent() : NULL;
}
#ifdef wxHAVE_DPI_INDEPENDENT_PIXELS
// FromDIP() becomes trivial in this case, so make it inline to avoid overhead.
inline wxSize wxWindowBase::FromDIP(const wxSize& sz) const { return sz; }
#endif // wxHAVE_DPI_INDEPENDENT_PIXELS
// ----------------------------------------------------------------------------
// global functions
// ----------------------------------------------------------------------------

View File

@ -918,6 +918,35 @@ public:
*/
virtual void FitInside();
/**
Convert DPI-independent pixel values to the value in pixels appropriate
for the current toolkit.
A DPI-independent pixel is just a pixel at the standard 96 DPI
resolution. To keep the same physical size at higher resolution, the
physical pixel value must be scaled by GetContentScaleFactor() but this
scaling may be already done by the underlying toolkit (GTK+, Cocoa,
...) automatically. This method performs the conversion only if it is
not already done by the lower level toolkit and so by using it with
pixel values you can guarantee that the physical size of the
corresponding elements will remain the same in all resolutions under
all platforms. For example, instead of creating a bitmap of the hard
coded size of 32 pixels you should use
@code
wxBitmap bmp(FromDIP(32, 32));
@endcode
to avoid using tiny bitmaps on high DPI screens.
Notice that this function is only needed when using hard coded pixel
values. It is not necessary if the sizes are already based on the
DPI-independent units such as dialog units or if you are relying on the
controls automatic best size determination and using sizers to lay out
them.
@since 3.1.0
*/
wxSize FromDIP(const wxSize& sz) const;
/**
This functions returns the best acceptable minimal size for the window.
@ -1126,13 +1155,14 @@ public:
Returns the magnification of the backing store of this window, eg 2.0
for a window on a retina screen.
This method can be used to adjust hard coded pixel values to the values
appropriate for the current screen resolution. E.g. instead of using
32px icons, which would look tiny on the high resolution (also known as
HiDPI or retina) displays, you should use
@code
wxRound(32*GetContentScaleFactor())
@endcode instead.
This factor should be used to determine the size of bitmaps and similar
"content-containing" windows appropriate for the current resolution.
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, as they
are already scaled by this factor by the underlying toolkit under some
platforms. Use FromDIP() for anything window-related instead.
@since 2.9.5
*/

View File

@ -27,6 +27,7 @@
#include "wx/string.h"
#include "wx/log.h"
#include "wx/intl.h"
#include "wx/math.h"
#include "wx/frame.h"
#include "wx/window.h"
#include "wx/control.h"
@ -2860,9 +2861,20 @@ void wxWindowBase::OnInternalIdle()
}
// ----------------------------------------------------------------------------
// dialog units translations
// DPI-independent pixels and dialog units translations
// ----------------------------------------------------------------------------
#ifndef wxHAVE_DPI_INDEPENDENT_PIXELS
wxSize wxWindowBase::FromDIP(const wxSize& sz) const
{
const double scale = GetContentScaleFactor();
return wxSize(wxRound(scale*sz.x), wxRound(scale*sz.y));
}
#endif // !wxHAVE_DPI_INDEPENDENT_PIXELS
// Windows' computes dialog units using average character width over upper-
// and lower-case ASCII alphabet and not using the average character width
// metadata stored in the font; see