Add wxDisplay::GetRawPPI()

Return resolution corresponding to the reported display physical size.

Implement the new function for wxMSW, wxGTK and wxOSX.

Show it in the "display" sample if it's different from the logical one.
This commit is contained in:
Vadim Zeitlin
2026-01-08 14:14:53 +01:00
parent 972c874ed5
commit a17cf5d4da
8 changed files with 106 additions and 5 deletions
+3
View File
@@ -94,6 +94,9 @@ public:
// get the resolution of this monitor in pixels per inch
wxSize GetPPI() const;
// get raw resolution in pixels per inch, i.e. without applying any scaling
wxSize GetRawPPI() const;
// get the default resolution for displays on this platform
static int GetStdPPIValue()
{
+4
View File
@@ -102,6 +102,10 @@ public:
// but can be also overridden directly, as is done in wxMSW
virtual wxSize GetPPI() const { return wxDisplay::GetStdPPI()*GetScaleFactor(); }
// return raw resolution of the display, by default returns standard PPI
// but should be overridden
virtual wxSize GetRawPPI() const { return wxDisplay::GetStdPPI(); }
// return the name (may be empty)
virtual wxString GetName() const { return wxString(); }
+13
View File
@@ -167,6 +167,19 @@ public:
*/
wxSize GetPPI() const;
/**
Returns raw display resolution in pixels per inch, i.e.\ without
applying any scaling.
Horizontal and vertical resolution are returned in @c x and @c y
components of the wxSize object respectively.
If the resolution information is not available, returns `wxSize(0, 0)`.
@since 3.3.2
*/
wxSize GetRawPPI() const;
/**
Returns scaling factor used by this display.
+13 -2
View File
@@ -299,8 +299,19 @@ void MyFrame::PopuplateWithDisplayInfo()
sizer->Add(new wxStaticText(page, wxID_ANY, "Resolution: "));
const wxSize ppi = display.GetPPI();
sizer->Add(new wxStaticText(page, wxID_ANY,
wxString::Format("%d*%d", ppi.x, ppi.y)));
const wxSize ppiRaw = display.GetRawPPI();
wxString resolutionText;
if ( ppiRaw == ppi )
{
resolutionText = wxString::Format("%d*%d", ppi.x, ppi.y);
}
else
{
resolutionText = wxString::Format("%d*%d (logical), %d*%d (raw)",
ppi.x, ppi.y, ppiRaw.x, ppiRaw.y);
}
sizer->Add(new wxStaticText(page, wxID_ANY, resolutionText));
sizer->Add(new wxStaticText(page, wxID_ANY, "Depth: "));
sizer->Add(new wxStaticText(page, wxID_ANY,
+10
View File
@@ -167,6 +167,16 @@ wxSize wxDisplay::GetPPI() const
return m_impl->GetPPI();
}
wxSize wxDisplay::GetRawPPI() const
{
wxCHECK_MSG( IsOk(), wxSize(), wxT("invalid wxDisplay object") );
if ( !m_impl->IsConnected() )
return wxSize();
return m_impl->GetRawPPI();
}
double wxDisplay::GetScaleFactor() const
{
wxCHECK_MSG( IsOk(), 0, wxT("invalid wxDisplay object") );
+17
View File
@@ -246,6 +246,7 @@ public:
#if GTK_CHECK_VERSION(3,10,0)
virtual double GetScaleFactor() const override;
#endif // GTK+ 3.10
virtual wxSize GetRawPPI() const override;
#if wxUSE_DISPLAY
virtual bool IsPrimary() const override;
@@ -340,6 +341,22 @@ double wxDisplayImplGTK::GetScaleFactor() const
}
#endif // GTK+ 3.10
wxSize wxDisplayImplGTK::GetRawPPI() const
{
auto const widthInMM = gdk_screen_get_monitor_width_mm(m_screen, m_index);
auto const heightInMM = gdk_screen_get_monitor_height_mm(m_screen, m_index);
// Don't use manifestly invalid values.
if ( widthInMM <= 0 && heightInMM <= 0 )
return wxDisplay::GetStdPPI();
const wxRect geometry = GetGeometry();
const double ppiX = geometry.width * 25.4 / widthInMM;
const double ppiY = geometry.height * 25.4 / heightInMM;
return wxSize(wxRound(ppiX), wxRound(ppiY));
}
#if wxUSE_DISPLAY
bool wxDisplayImplGTK::IsPrimary() const
{
+29 -3
View File
@@ -93,6 +93,7 @@ protected:
#ifndef DPI_ENUMS_DECLARED
#define MDT_EFFECTIVE_DPI 0
#define MDT_RAW_DPI 2
#endif
namespace
@@ -131,6 +132,7 @@ public:
virtual wxRect GetClientArea() const override;
virtual int GetDepth() const override;
virtual wxSize GetPPI() const override;
virtual wxSize GetRawPPI() const override;
virtual double GetScaleFactor() const override;
virtual wxString GetName() const override;
@@ -160,6 +162,12 @@ protected:
wxDisplayInfo m_info;
private:
// Wrapper around GetDpiForMonitor() call: check if it's available and for
// its success.
//
// Return wxSize(0, 0) on failure.
wxSize CallGetDpiForMonitor(int type) const;
wxDECLARE_NO_COPY_CLASS(wxDisplayMSW);
};
@@ -321,7 +329,7 @@ int wxDisplayMSW::GetDepth() const
return m_info.depth;
}
wxSize wxDisplayMSW::GetPPI() const
wxSize wxDisplayMSW::CallGetDpiForMonitor(int type) const
{
if ( const wxDisplayFactoryMSW::GetDpiForMonitor_t
getFunc = wxDisplayFactoryMSW::GetDpiForMonitorPtr() )
@@ -329,14 +337,32 @@ wxSize wxDisplayMSW::GetPPI() const
UINT dpiX = 0,
dpiY = 0;
const HRESULT
hr = (*getFunc)(m_info.hmon, MDT_EFFECTIVE_DPI, &dpiX, &dpiY);
hr = (*getFunc)(m_info.hmon, type, &dpiX, &dpiY);
if ( SUCCEEDED(hr) )
return wxSize(dpiX, dpiY);
wxLogApiError("GetDpiForMonitor", hr);
}
return IsPrimary() ? wxDisplayImplSingleMSW().GetPPI() : wxSize(0, 0);
return wxSize();
}
wxSize wxDisplayMSW::GetPPI() const
{
wxSize ppi = CallGetDpiForMonitor(MDT_EFFECTIVE_DPI);
if ( ppi.IsEmpty() && IsPrimary() )
ppi = wxDisplayImplSingleMSW().GetPPI();
return ppi;
}
wxSize wxDisplayMSW::GetRawPPI() const
{
wxSize ppi = CallGetDpiForMonitor(MDT_RAW_DPI);
if ( ppi.IsEmpty() && IsPrimary() )
ppi = wxDisplayImplSingleMSW().GetRawPPI();
return ppi;
}
double wxDisplayMSW::GetScaleFactor() const
+17
View File
@@ -24,6 +24,7 @@
#ifndef WX_PRECOMP
#include "wx/dynarray.h"
#include "wx/log.h"
#include "wx/math.h"
#include "wx/string.h"
#include "wx/gdicmn.h"
#include "wx/nonownedwnd.h"
@@ -105,6 +106,7 @@ public:
virtual wxRect GetClientArea() const override;
virtual int GetDepth() const override;
virtual double GetScaleFactor() const override;
virtual wxSize GetRawPPI() const override;
virtual wxArrayVideoModes GetModes(const wxVideoMode& mode) const override;
virtual wxVideoMode GetCurrentMode() const override;
@@ -310,6 +312,21 @@ double wxDisplayImplMacOSX::GetScaleFactor() const
return wxGetScaleFactor(m_id);
}
wxSize wxDisplayImplMacOSX::GetRawPPI() const
{
auto const sizeInMM = CGDisplayScreenSize(m_id);
// Don't use manifestly invalid values.
if ( sizeInMM.width <= 0 && sizeInMM.height <= 0 )
return wxDisplay::GetStdPPI();
const wxRect geometry = GetGeometry();
const double ppiX = geometry.width * 25.4 / sizeInMM.width;
const double ppiY = geometry.height * 25.4 / sizeInMM.height;
return wxSize(wxRound(ppiX), wxRound(ppiY));
}
static int wxOSXCGDisplayModeGetBitsPerPixel( CGDisplayModeRef theValue )
{
wxCFRef<CFStringRef> pixelEncoding( CGDisplayModeCopyPixelEncoding(theValue) );