From 1614f7337d7f85da26681d1e1aaf700448c8544e Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Thu, 4 Oct 2018 15:28:56 +0200 Subject: [PATCH 1/6] Mention that wxDisplaySize() shouldn't be used in the new code Prefer to use wxDisplay::GetGeometry() which works for any display, not just the primary one. --- interface/wx/gdicmn.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/interface/wx/gdicmn.h b/interface/wx/gdicmn.h index 6e98d29d88..fe7a62a783 100644 --- a/interface/wx/gdicmn.h +++ b/interface/wx/gdicmn.h @@ -1262,6 +1262,10 @@ wxSize wxGetDisplayPPI(); /** Returns the display size in pixels. + @note Use of this function is not recommended in the new code as it only + works for the primary display. Use wxDisplay::GetGeometry() to retrieve + the size of the appropriate display instead. + Either of output pointers can be @NULL if the caller is not interested in the corresponding value. @@ -1277,6 +1281,10 @@ void wxDisplaySize(int* width, int* height); /** Returns the display size in pixels. + @note Use of this function is not recommended in the new code as it only + works for the primary display. Use wxDisplay::GetGeometry() to retrieve + the size of the appropriate display instead. + @see wxDisplay @header{wx/gdicmn.h} From e834585cf78cbf411eb7f66e6755e4be3257dddd Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sat, 6 Oct 2018 15:24:13 +0200 Subject: [PATCH 2/6] Remove wxDisplaySize() implementation from wxGTK1 This is now implemented in common code, in terms of wxDisplay. --- src/gtk1/utilsgtk.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/gtk1/utilsgtk.cpp b/src/gtk1/utilsgtk.cpp index c912fc9a9a..9f18a26436 100644 --- a/src/gtk1/utilsgtk.cpp +++ b/src/gtk1/utilsgtk.cpp @@ -86,12 +86,6 @@ void *wxGetDisplay() return GDK_DISPLAY(); } -void wxDisplaySize( int *width, int *height ) -{ - if (width) *width = gdk_screen_width(); - if (height) *height = gdk_screen_height(); -} - void wxDisplaySizeMM( int *width, int *height ) { if (width) *width = gdk_screen_width_mm(); From 24b5e256df5a1593c6f47eabc077a017e47350fe Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sat, 6 Oct 2018 15:28:11 +0200 Subject: [PATCH 3/6] Add wxDisplay::GetDepth() and use it for wxDisplayDepth() Allow getting the depth of any display, not just the primary one, even though this is not implemented for Unix ports currently. Mostly do this for consistency with the other display-related functions. --- include/wx/display.h | 3 ++ include/wx/private/display.h | 3 ++ interface/wx/gdicmn.h | 4 +++ samples/display/display.cpp | 4 +++ src/common/dpycmn.cpp | 7 +++++ src/common/gdicmn.cpp | 5 ++++ src/dfb/utils.cpp | 10 +++---- src/gtk/display.cpp | 13 +++++++++ src/gtk/utilsgtk.cpp | 9 ------ src/gtk1/utilsgtk.cpp | 5 ---- src/motif/utils.cpp | 8 ------ src/msw/display.cpp | 55 ++++++++++++++++++++++++++++-------- src/msw/utilsgui.cpp | 7 ----- src/osx/core/display.cpp | 34 ++++++++++++++++++++++ src/osx/iphone/utils.mm | 11 ++++---- src/osx/utils_osx.cpp | 24 ---------------- src/qt/display.cpp | 6 ++++ src/qt/utils.cpp | 5 ---- src/unix/displayx11.cpp | 26 ++++++++++++++++- src/x11/utils.cpp | 8 ------ 20 files changed, 157 insertions(+), 90 deletions(-) diff --git a/include/wx/display.h b/include/wx/display.h index 3213d79d97..726dfee418 100644 --- a/include/wx/display.h +++ b/include/wx/display.h @@ -74,6 +74,9 @@ public: // get the client area of the display, i.e. without taskbars and such wxRect GetClientArea() const; + // get the depth, i.e. number of bits per pixel (0 if unknown) + int GetDepth() const; + // name may be empty wxString GetName() const; diff --git a/include/wx/private/display.h b/include/wx/private/display.h index 9f0dce0ad2..686e703101 100644 --- a/include/wx/private/display.h +++ b/include/wx/private/display.h @@ -78,6 +78,9 @@ public: // return the area of the display available for normal windows virtual wxRect GetClientArea() const { return GetGeometry(); } + // return the depth or 0 if unknown + virtual int GetDepth() const = 0; + // return the name (may be empty) virtual wxString GetName() const { return wxString(); } diff --git a/interface/wx/gdicmn.h b/interface/wx/gdicmn.h index fe7a62a783..fc27e066d9 100644 --- a/interface/wx/gdicmn.h +++ b/interface/wx/gdicmn.h @@ -1191,6 +1191,10 @@ bool wxColourDisplay(); Returns the depth of the display (a value of 1 denotes a monochrome display). + @note Use of this function is not recommended in the new code as it only + works for the primary display. Use wxDisplay::GetDepth() to retrieve + the depth of the appropriate display instead. + @header{wx/gdicmn.h} */ int wxDisplayDepth(); diff --git a/samples/display/display.cpp b/samples/display/display.cpp index 7c97a54c34..5b715f88ec 100644 --- a/samples/display/display.cpp +++ b/samples/display/display.cpp @@ -275,6 +275,10 @@ MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size, rc.x, rc.y, rc.width, rc.height) )); + sizer->Add(new wxStaticText(page, wxID_ANY, "Depth: ")); + sizer->Add(new wxStaticText(page, wxID_ANY, + wxString::Format("%d", display.GetDepth()))); + sizer->Add(new wxStaticText(page, wxID_ANY, "Name: ")); sizer->Add(new wxStaticText(page, wxID_ANY, display.GetName())); diff --git a/src/common/dpycmn.cpp b/src/common/dpycmn.cpp index cd49ae60ec..9968f3cbfa 100644 --- a/src/common/dpycmn.cpp +++ b/src/common/dpycmn.cpp @@ -122,6 +122,13 @@ wxRect wxDisplay::GetClientArea() const return m_impl->GetClientArea(); } +int wxDisplay::GetDepth() const +{ + wxCHECK_MSG( IsOk(), 0, wxT("invalid wxDisplay object") ); + + return m_impl->GetDepth(); +} + wxString wxDisplay::GetName() const { wxCHECK_MSG( IsOk(), wxString(), wxT("invalid wxDisplay object") ); diff --git a/src/common/gdicmn.cpp b/src/common/gdicmn.cpp index 771db4ac72..22ba30ef37 100644 --- a/src/common/gdicmn.cpp +++ b/src/common/gdicmn.cpp @@ -845,6 +845,11 @@ wxFont *wxFontList::FindOrCreateFont(int pointSize, return font; } +int wxDisplayDepth() +{ + return wxDisplay().GetDepth(); +} + void wxDisplaySize(int *width, int *height) { const wxSize size = wxGetDisplaySize(); diff --git a/src/dfb/utils.cpp b/src/dfb/utils.cpp index 76c84a5c50..7226d63002 100644 --- a/src/dfb/utils.cpp +++ b/src/dfb/utils.cpp @@ -68,6 +68,11 @@ public: return wxRect(0, 0, mode.w, mode.h); } + + virtual int GetDepth() const wxOVERRIDE + { + return wxTheApp->GetDisplayMode().bpp; + } }; class wxDisplayFactorySingleDFB : public wxDisplayFactorySingle @@ -90,11 +95,6 @@ bool wxColourDisplay() return true; } -int wxDisplayDepth() -{ - return wxTheApp->GetDisplayMode().bpp; -} - void wxDisplaySizeMM(int *width, int *height) { // FIXME: there's no way to get physical resolution using the DirectDB diff --git a/src/gtk/display.cpp b/src/gtk/display.cpp index 2576d0d6c2..2cc424c8db 100644 --- a/src/gtk/display.cpp +++ b/src/gtk/display.cpp @@ -45,6 +45,7 @@ public: wxDisplayImplGTK(unsigned i); virtual wxRect GetGeometry() const wxOVERRIDE; virtual wxRect GetClientArea() const wxOVERRIDE; + virtual int GetDepth() const wxOVERRIDE; #if wxUSE_DISPLAY virtual bool IsPrimary() const wxOVERRIDE; @@ -114,6 +115,11 @@ wxRect wxDisplayImplGTK::GetClientArea() const return wxRect(rect.x, rect.y, rect.width, rect.height); } +int wxDisplayImplGTK::GetDepth() const +{ + return 24; +} + #if wxUSE_DISPLAY bool wxDisplayImplGTK::IsPrimary() const { @@ -205,6 +211,7 @@ public: wxDisplayImplGTK(unsigned i); virtual wxRect GetGeometry() const wxOVERRIDE; virtual wxRect GetClientArea() const wxOVERRIDE; + virtual int GetDepth() const wxOVERRIDE; #if wxUSE_DISPLAY virtual bool IsPrimary() const wxOVERRIDE; @@ -269,6 +276,12 @@ wxRect wxDisplayImplGTK::GetClientArea() const return wxRect(rect.x, rect.y, rect.width, rect.height); } +int wxDisplayImplGTK::GetDepth() const +{ + // TODO: How to get the depth of the specific display? + return gdk_visual_get_depth(gdk_window_get_visual(wxGetTopLevelGDK())); +} + #if wxUSE_DISPLAY bool wxDisplayImplGTK::IsPrimary() const { diff --git a/src/gtk/utilsgtk.cpp b/src/gtk/utilsgtk.cpp index 31a1d9a9ea..2ce561ff13 100644 --- a/src/gtk/utilsgtk.cpp +++ b/src/gtk/utilsgtk.cpp @@ -95,15 +95,6 @@ bool wxColourDisplay() return true; } -int wxDisplayDepth() -{ -#ifdef __WXGTK4__ - return 24; -#else - return gdk_visual_get_depth(gdk_window_get_visual(wxGetTopLevelGDK())); -#endif -} - wxWindow* wxFindWindowAtPoint(const wxPoint& pt) { return wxGenericFindWindowAtPoint(pt); diff --git a/src/gtk1/utilsgtk.cpp b/src/gtk1/utilsgtk.cpp index 9f18a26436..c027686ad5 100644 --- a/src/gtk1/utilsgtk.cpp +++ b/src/gtk1/utilsgtk.cpp @@ -102,11 +102,6 @@ bool wxColourDisplay() return true; } -int wxDisplayDepth() -{ - return gdk_window_get_visual( wxGetRootWindow()->window )->depth; -} - wxWindow* wxFindWindowAtPoint(const wxPoint& pt) { return wxGenericFindWindowAtPoint(pt); diff --git a/src/motif/utils.cpp b/src/motif/utils.cpp index 16c52e86a8..621b89cc27 100644 --- a/src/motif/utils.cpp +++ b/src/motif/utils.cpp @@ -231,14 +231,6 @@ bool wxColourDisplay() return wxDisplayDepth() > 1; } -// Returns depth of screen -int wxDisplayDepth() -{ - Display *dpy = wxGlobalDisplay(); - - return DefaultDepth (dpy, DefaultScreen (dpy)); -} - void wxDisplaySizeMM(int *width, int *height) { Display *dpy = wxGlobalDisplay(); diff --git a/src/msw/display.cpp b/src/msw/display.cpp index 771cb32132..e6ea6486a8 100644 --- a/src/msw/display.cpp +++ b/src/msw/display.cpp @@ -29,6 +29,11 @@ #include "wx/msw/private.h" #include "wx/msw/wrapwin.h" +int wxGetHDCDepth(HDC hdc) +{ + return ::GetDeviceCaps(hdc, PLANES) * GetDeviceCaps(hdc, BITSPIXEL); +} + // This implementation is always available, whether wxUSE_DISPLAY is 1 or not, // as we fall back to it in case of error. class wxDisplayImplSingleMSW : public wxDisplayImplSingle @@ -52,6 +57,11 @@ public: wxCopyRECTToRect(rc, rectClient); return rectClient; } + + virtual int GetDepth() const wxOVERRIDE + { + return wxGetHDCDepth(ScreenHDC()); + } }; class wxDisplayFactorySingleMSW : public wxDisplayFactorySingle @@ -79,6 +89,20 @@ protected: static const wxChar displayDllName[] = wxT("user32.dll"); +namespace +{ + +// Simple struct storing the information needed by wxDisplayMSW. +struct wxDisplayInfo +{ + wxDisplayInfo(HMONITOR hmon_, int depth_) : hmon(hmon_), depth(depth_) {} + + HMONITOR hmon; + int depth; +}; + +} // anonymous namespace + // ---------------------------------------------------------------------------- // wxDisplayMSW declaration // ---------------------------------------------------------------------------- @@ -86,14 +110,15 @@ static const wxChar displayDllName[] = wxT("user32.dll"); class wxDisplayMSW : public wxDisplayImpl { public: - wxDisplayMSW(unsigned n, HMONITOR hmon) + wxDisplayMSW(unsigned n, const wxDisplayInfo& info) : wxDisplayImpl(n), - m_hmon(hmon) + m_info(info) { } virtual wxRect GetGeometry() const wxOVERRIDE; virtual wxRect GetClientArea() const wxOVERRIDE; + virtual int GetDepth() const wxOVERRIDE; virtual wxString GetName() const wxOVERRIDE; virtual bool IsPrimary() const wxOVERRIDE; @@ -118,7 +143,7 @@ protected: // it succeeded, otherwise return false. bool GetMonInfo(MONITORINFOEX& monInfo) const; - HMONITOR m_hmon; + wxDisplayInfo m_info; private: wxDECLARE_NO_COPY_CLASS(wxDisplayMSW); @@ -129,8 +154,6 @@ private: // wxDisplayFactoryMSW declaration // ---------------------------------------------------------------------------- -WX_DEFINE_ARRAY(HMONITOR, wxMonitorHandleArray); - class wxDisplayFactoryMSW : public wxDisplayFactory { public: @@ -177,7 +200,7 @@ private: // the array containing information about all available displays, filled by // MultimonEnumProc() - wxMonitorHandleArray m_displays; + wxVector m_displays; // The hidden window we use for receiving WM_SETTINGCHANGE and its class // name. @@ -213,7 +236,7 @@ wxDisplayFactoryMSW* wxDisplayFactoryMSW::ms_factory = NULL; bool wxDisplayMSW::GetMonInfo(MONITORINFOEX& monInfo) const { - if ( !::GetMonitorInfo(m_hmon, &monInfo) ) + if ( !::GetMonitorInfo(m_info.hmon, &monInfo) ) { wxLogLastError(wxT("GetMonitorInfo")); return false; @@ -244,6 +267,11 @@ wxRect wxDisplayMSW::GetClientArea() const return rectClient; } +int wxDisplayMSW::GetDepth() const +{ + return m_info.depth; +} + wxString wxDisplayMSW::GetName() const { WinStruct monInfo; @@ -469,9 +497,12 @@ wxDisplayFactoryMSW::~wxDisplayFactoryMSW() void wxDisplayFactoryMSW::DoRefreshMonitors() { - m_displays.Clear(); + m_displays.clear(); - if ( !::EnumDisplayMonitors(NULL, NULL, MultimonEnumProc, (LPARAM)this) ) + // We need to pass a valid HDC here in order to get valid hdcMonitor in our + // callback. + ScreenHDC dc; + if ( !::EnumDisplayMonitors(dc, NULL, MultimonEnumProc, (LPARAM)this) ) { wxLogLastError(wxT("EnumDisplayMonitors")); } @@ -481,13 +512,13 @@ void wxDisplayFactoryMSW::DoRefreshMonitors() BOOL CALLBACK wxDisplayFactoryMSW::MultimonEnumProc( HMONITOR hMonitor, // handle to display monitor - HDC WXUNUSED(hdcMonitor), // handle to monitor-appropriate device context + HDC hdcMonitor, // handle to monitor-appropriate device context LPRECT WXUNUSED(lprcMonitor), // pointer to monitor intersection rectangle LPARAM dwData) // data passed from EnumDisplayMonitors (this) { wxDisplayFactoryMSW *const self = (wxDisplayFactoryMSW *)dwData; - self->m_displays.Add(hMonitor); + self->m_displays.push_back(wxDisplayInfo(hMonitor, wxGetHDCDepth(hdcMonitor))); // continue the enumeration return TRUE; @@ -508,7 +539,7 @@ int wxDisplayFactoryMSW::FindDisplayFromHMONITOR(HMONITOR hmon) const const size_t count = m_displays.size(); for ( size_t n = 0; n < count; n++ ) { - if ( hmon == m_displays[n] ) + if ( hmon == m_displays[n].hmon ) return n; } } diff --git a/src/msw/utilsgui.cpp b/src/msw/utilsgui.cpp index 1ebbd36259..a475bc6290 100644 --- a/src/msw/utilsgui.cpp +++ b/src/msw/utilsgui.cpp @@ -138,13 +138,6 @@ bool wxColourDisplay() return s_isColour != 0; } -// Returns depth of screen -int wxDisplayDepth() -{ - ScreenHDC dc; - return GetDeviceCaps(dc, PLANES) * GetDeviceCaps(dc, BITSPIXEL); -} - void wxDisplaySizeMM(int *width, int *height) { ScreenHDC dc; diff --git a/src/osx/core/display.cpp b/src/osx/core/display.cpp index 3f35ccc1e4..2e55b346b8 100644 --- a/src/osx/core/display.cpp +++ b/src/osx/core/display.cpp @@ -52,6 +52,29 @@ wxRect wxGetDisplayGeometry(CGDirectDisplayID id) (int)theRect.size.height ); //floats } +int wxGetDisplayDepth(CGDirectDisplayID id) +{ + CGDisplayModeRef currentMode = CGDisplayCopyDisplayMode(id); + CFStringRef encoding = CGDisplayModeCopyPixelEncoding(currentMode); + + int theDepth = 32; // some reasonable default + if(encoding) + { + if(CFStringCompare(encoding, CFSTR(IO32BitDirectPixels), kCFCompareCaseInsensitive) == kCFCompareEqualTo) + theDepth = 32; + else if(CFStringCompare(encoding, CFSTR(IO16BitDirectPixels), kCFCompareCaseInsensitive) == kCFCompareEqualTo) + theDepth = 16; + else if(CFStringCompare(encoding, CFSTR(IO8BitIndexedPixels), kCFCompareCaseInsensitive) == kCFCompareEqualTo) + theDepth = 8; + + CFRelease(encoding); + } + + CGDisplayModeRelease(currentMode); + + return theDepth; +} + } // anonymous namespace #if wxUSE_DISPLAY @@ -73,6 +96,7 @@ public: virtual wxRect GetGeometry() const wxOVERRIDE; virtual wxRect GetClientArea() const wxOVERRIDE; + virtual int GetDepth() const wxOVERRIDE; virtual wxArrayVideoModes GetModes(const wxVideoMode& mode) const wxOVERRIDE; virtual wxVideoMode GetCurrentMode() const wxOVERRIDE; @@ -229,6 +253,11 @@ wxRect wxDisplayImplMacOSX::GetClientArea() const return wxDisplayImpl::GetClientArea(); } +int wxDisplayImplMacOSX::GetDepth() const +{ + return wxGetDisplayDepth(m_id); +} + static int wxOSXCGDisplayModeGetBitsPerPixel( CGDisplayModeRef theValue ) { wxCFRef pixelEncoding( CGDisplayModeCopyPixelEncoding(theValue) ); @@ -339,6 +368,11 @@ public: { return wxOSXGetMainDisplayClientArea(); } + + virtual int GetDepth() const wxOVERRIDE + { + return wxGetDisplayDepth(CGMainDisplayID()); + } }; class wxDisplayFactorySingleMacOSX : public wxDisplayFactorySingle diff --git a/src/osx/iphone/utils.mm b/src/osx/iphone/utils.mm index 2136055e74..dd77cfd5e6 100644 --- a/src/osx/iphone/utils.mm +++ b/src/osx/iphone/utils.mm @@ -130,12 +130,6 @@ wxMouseState wxGetMouseState() return ms; } -// Returns depth of screen -int wxDisplayDepth() -{ - return 32; // TODO can we determine this ? -} - // Get size of display class wxDisplayImplSingleiOS : public wxDisplayImplSingle @@ -161,6 +155,11 @@ public: return wxRect(0, 0, width, height); } + + virtual int GetDepth() const wxOVERRIDE + { + return 32; // TODO can we determine this ? + } }; class wxDisplayFactorySingleiOS : public wxDisplayFactorySingle diff --git a/src/osx/utils_osx.cpp b/src/osx/utils_osx.cpp index 6860b5e088..d53c47f753 100644 --- a/src/osx/utils_osx.cpp +++ b/src/osx/utils_osx.cpp @@ -63,30 +63,6 @@ bool wxColourDisplay() #if wxOSX_USE_COCOA_OR_CARBON -// Returns depth of screen -int wxDisplayDepth() -{ - CGDisplayModeRef currentMode = CGDisplayCopyDisplayMode(kCGDirectMainDisplay); - CFStringRef encoding = CGDisplayModeCopyPixelEncoding(currentMode); - - int theDepth = 32; // some reasonable default - if(encoding) - { - if(CFStringCompare(encoding, CFSTR(IO32BitDirectPixels), kCFCompareCaseInsensitive) == kCFCompareEqualTo) - theDepth = 32; - else if(CFStringCompare(encoding, CFSTR(IO16BitDirectPixels), kCFCompareCaseInsensitive) == kCFCompareEqualTo) - theDepth = 16; - else if(CFStringCompare(encoding, CFSTR(IO8BitIndexedPixels), kCFCompareCaseInsensitive) == kCFCompareEqualTo) - theDepth = 8; - - CFRelease(encoding); - } - - CGDisplayModeRelease(currentMode); - - return theDepth; -} - #if wxUSE_GUI // ---------------------------------------------------------------------------- diff --git a/src/qt/display.cpp b/src/qt/display.cpp index 52b6af8373..6d3de3ac2e 100644 --- a/src/qt/display.cpp +++ b/src/qt/display.cpp @@ -21,6 +21,7 @@ public: virtual wxRect GetGeometry() const wxOVERRIDE; virtual wxRect GetClientArea() const wxOVERRIDE; + virtual int GetDepth() const wxOVERRIDE; #if wxUSE_DISPLAY virtual wxArrayVideoModes GetModes(const wxVideoMode& mode) const wxOVERRIDE; @@ -44,6 +45,11 @@ wxRect wxDisplayImplQt::GetClientArea() const return wxQtConvertRect( QApplication::desktop()->availableGeometry( GetIndex() )); } +int wxDisplayImplQt::GetDepth() const +{ + return IsPrimary() ? QApplication::desktop()->depth() : 0; +} + #if wxUSE_DISPLAY wxArrayVideoModes wxDisplayImplQt::GetModes(const wxVideoMode& WXUNUSED(mode)) const { diff --git a/src/qt/utils.cpp b/src/qt/utils.cpp index 92957b8683..bcaedc95e2 100644 --- a/src/qt/utils.cpp +++ b/src/qt/utils.cpp @@ -110,11 +110,6 @@ bool wxGetKeyState(wxKeyCode key) } } -int wxDisplayDepth() -{ - return QApplication::desktop()->depth(); -} - void wxDisplaySizeMM(int *width, int *height) { if ( width != NULL ) diff --git a/src/unix/displayx11.cpp b/src/unix/displayx11.cpp index 4e317ca6a0..b352e5392f 100644 --- a/src/unix/displayx11.cpp +++ b/src/unix/displayx11.cpp @@ -34,6 +34,16 @@ static wxRect wxGetMainScreenWorkArea(); +namespace +{ + +inline int wxGetMainScreenDepth() +{ + Display* const dpy = wxGetX11Display(); + + return DefaultDepth(dpy, DefaultScreen (dpy)); +} + class wxDisplayImplSingleX11 : public wxDisplayImplSingle { public: @@ -50,6 +60,11 @@ public: { return wxGetMainScreenWorkArea(); } + + virtual int GetDepth() const wxOVERRIDE + { + return wxGetMainScreenDepth(); + } }; class wxDisplayFactorySingleX11 : public wxDisplayFactorySingle @@ -61,6 +76,8 @@ protected: } }; +} // anonymous namespace + #if wxUSE_DISPLAY #include @@ -118,6 +135,14 @@ public: // we don't currently react to its changes return IsPrimary() ? wxGetMainScreenWorkArea() : m_rect; } + virtual int GetDepth() const wxOVERRIDE + { + const wxVideoMode& mode = GetCurrentMode(); + if ( mode.bpp ) + return mode.bpp; + + return wxGetMainScreenDepth(); + } virtual wxArrayVideoModes GetModes(const wxVideoMode& mode) const wxOVERRIDE; virtual wxVideoMode GetCurrentMode() const wxOVERRIDE; @@ -125,7 +150,6 @@ public: private: wxRect m_rect; - int m_depth; wxDECLARE_NO_COPY_CLASS(wxDisplayImplX11); }; diff --git a/src/x11/utils.cpp b/src/x11/utils.cpp index 4312a3da8e..7a917354ab 100644 --- a/src/x11/utils.cpp +++ b/src/x11/utils.cpp @@ -154,14 +154,6 @@ bool wxColourDisplay() return wxDisplayDepth() > 1; } -// Returns depth of screen -int wxDisplayDepth() -{ - Display *dpy = (Display*) wxGetDisplay(); - - return DefaultDepth (dpy, DefaultScreen (dpy)); -} - void wxDisplaySizeMM(int *width, int *height) { Display *dpy = (Display*) wxGetDisplay(); From 382404f0a7389a547aab5c3ecd7ee53b49679074 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sat, 6 Oct 2018 16:12:48 +0200 Subject: [PATCH 4/6] Stop using wxColourDisplay() inside wxWidgets code This function always returns true in practice and it's completely useless to call it during each wxDC object construction, especially because wxDC::m_colour itself is not used anywhere. --- demos/poem/wxpoem.cpp | 31 +++++++++++++------------------ src/common/dcbase.cpp | 2 +- src/common/dcsvg.cpp | 1 - src/motif/dcclient.cpp | 1 - 4 files changed, 14 insertions(+), 21 deletions(-) diff --git a/demos/poem/wxpoem.cpp b/demos/poem/wxpoem.cpp index cfca656f6e..36206c8753 100644 --- a/demos/poem/wxpoem.cpp +++ b/demos/poem/wxpoem.cpp @@ -163,7 +163,7 @@ void MainWindow::ScanBuffer(wxDC *dc, bool DrawIt, int *max_x, int *max_y) height = *max_y; } - if (DrawIt && wxColourDisplay()) + if (DrawIt) { dc->SetBrush(*wxLIGHT_GREY_BRUSH); dc->SetPen(*wxGREY_PEN); @@ -347,20 +347,18 @@ void MainWindow::ScanBuffer(wxDC *dc, bool DrawIt, int *max_x, int *max_y) if (DrawIt) { // Draw dark grey thick border - if (wxColourDisplay()) - { - dc->SetBrush(*wxGREY_BRUSH); - dc->SetPen(*wxGREY_PEN); + dc->SetBrush(*wxGREY_BRUSH); + dc->SetPen(*wxGREY_PEN); + + // Left side + dc->DrawRectangle(0, 0, THIN_LINE_BORDER, height); + // Top side + dc->DrawRectangle(THIN_LINE_BORDER, 0, width-THIN_LINE_BORDER, THIN_LINE_BORDER); + // Right side + dc->DrawRectangle(width-THIN_LINE_BORDER, THIN_LINE_BORDER, width, height-THIN_LINE_BORDER); + // Bottom side + dc->DrawRectangle(THIN_LINE_BORDER, height-THIN_LINE_BORDER, width-THIN_LINE_BORDER, height); - // Left side - dc->DrawRectangle(0, 0, THIN_LINE_BORDER, height); - // Top side - dc->DrawRectangle(THIN_LINE_BORDER, 0, width-THIN_LINE_BORDER, THIN_LINE_BORDER); - // Right side - dc->DrawRectangle(width-THIN_LINE_BORDER, THIN_LINE_BORDER, width, height-THIN_LINE_BORDER); - // Bottom side - dc->DrawRectangle(THIN_LINE_BORDER, height-THIN_LINE_BORDER, width-THIN_LINE_BORDER, height); - } // Draw border // Have grey background, plus 3-d border - // One black rectangle. @@ -376,10 +374,7 @@ void MainWindow::ScanBuffer(wxDC *dc, bool DrawIt, int *max_x, int *max_y) // Right and bottom white lines - 'grey' (black!) if // we're running on a mono display. - if (wxColourDisplay()) - dc->SetPen(*wxWHITE_PEN); - else - dc->SetPen(*wxBLACK_PEN); + dc->SetPen(*wxWHITE_PEN); dc->DrawLine(width-THICK_LINE_BORDER, THICK_LINE_BORDER, width-THICK_LINE_BORDER, height-THICK_LINE_BORDER); diff --git a/src/common/dcbase.cpp b/src/common/dcbase.cpp index 1363984b7e..8b070995d8 100644 --- a/src/common/dcbase.cpp +++ b/src/common/dcbase.cpp @@ -318,7 +318,7 @@ wxIMPLEMENT_ABSTRACT_CLASS(wxDCImpl, wxObject); wxDCImpl::wxDCImpl( wxDC *owner ) : m_window(NULL) - , m_colour(wxColourDisplay()) + , m_colour(true) , m_ok(true) , m_clipping(false) , m_isInteractive(0) diff --git a/src/common/dcsvg.cpp b/src/common/dcsvg.cpp index 7a02bebb4f..2913548a12 100644 --- a/src/common/dcsvg.cpp +++ b/src/common/dcsvg.cpp @@ -402,7 +402,6 @@ void wxSVGFileDCImpl::Init(const wxString &filename, int Width, int Height, m_backgroundBrush = *wxTRANSPARENT_BRUSH; m_textForegroundColour = *wxBLACK; m_textBackgroundColour = *wxWHITE; - m_colour = wxColourDisplay(); m_pen = *wxBLACK_PEN; m_font = *wxNORMAL_FONT; diff --git a/src/motif/dcclient.cpp b/src/motif/dcclient.cpp index 6bf809572f..a85f36bfc2 100644 --- a/src/motif/dcclient.cpp +++ b/src/motif/dcclient.cpp @@ -139,7 +139,6 @@ void wxWindowDCImpl::Init() m_currentPenDash = NULL; m_currentStyle = -1; m_currentFill = -1; - m_colour = wxColourDisplay(); m_display = NULL; m_pixmap = (WXPixmap) 0; m_autoSetting = 0; From e3e883bbd226c9fe6308b47e5842940129cc9f5f Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sat, 6 Oct 2018 16:14:45 +0200 Subject: [PATCH 5/6] Implement wxColourDisplay() in terms of wxDisplay::GetDepth() Get rid of another global display-related function, even though this one only had non-trivial implementation under MSW. --- interface/wx/gdicmn.h | 4 ++++ src/common/gdicmn.cpp | 7 +++++++ src/dfb/utils.cpp | 6 ------ src/gtk/utilsgtk.cpp | 5 ----- src/gtk1/utilsgtk.cpp | 5 ----- src/motif/utils.cpp | 6 ------ src/msw/utilsgui.cpp | 21 --------------------- src/osx/utils_osx.cpp | 8 -------- src/qt/utils.cpp | 5 ----- src/x11/utils.cpp | 6 ------ 10 files changed, 11 insertions(+), 62 deletions(-) diff --git a/interface/wx/gdicmn.h b/interface/wx/gdicmn.h index fc27e066d9..2033b5461d 100644 --- a/interface/wx/gdicmn.h +++ b/interface/wx/gdicmn.h @@ -1183,6 +1183,10 @@ const wxSize wxDefaultSize; /** Returns @true if the display is colour, @false otherwise. + @note Use of this function is not recommended in the new code as it only + works for the primary display. Use wxDisplay::GetDepth() to retrieve + the depth of the appropriate display and compare it with 1 instead. + @header{wx/gdicmn.h} */ bool wxColourDisplay(); diff --git a/src/common/gdicmn.cpp b/src/common/gdicmn.cpp index 22ba30ef37..a584eccc5f 100644 --- a/src/common/gdicmn.cpp +++ b/src/common/gdicmn.cpp @@ -850,6 +850,13 @@ int wxDisplayDepth() return wxDisplay().GetDepth(); } +bool wxColourDisplay() +{ + // If GetDepth() returns 0, meaning unknown, we assume it's a colour + // display, hence the use of "!=" rather than ">" here. + return wxDisplay().GetDepth() != 1; +} + void wxDisplaySize(int *width, int *height) { const wxSize size = wxGetDisplaySize(); diff --git a/src/dfb/utils.cpp b/src/dfb/utils.cpp index 7226d63002..b4e97dc727 100644 --- a/src/dfb/utils.cpp +++ b/src/dfb/utils.cpp @@ -89,12 +89,6 @@ wxDisplayFactory* wxDisplay::CreateFactory() return new wxDisplayFactorySingleDFB; } -bool wxColourDisplay() -{ - #warning "FIXME: wxColourDisplay" - return true; -} - void wxDisplaySizeMM(int *width, int *height) { // FIXME: there's no way to get physical resolution using the DirectDB diff --git a/src/gtk/utilsgtk.cpp b/src/gtk/utilsgtk.cpp index 2ce561ff13..f0a36126f1 100644 --- a/src/gtk/utilsgtk.cpp +++ b/src/gtk/utilsgtk.cpp @@ -90,11 +90,6 @@ void wxDisplaySizeMM( int *width, int *height ) #endif } -bool wxColourDisplay() -{ - return true; -} - wxWindow* wxFindWindowAtPoint(const wxPoint& pt) { return wxGenericFindWindowAtPoint(pt); diff --git a/src/gtk1/utilsgtk.cpp b/src/gtk1/utilsgtk.cpp index c027686ad5..bdcadfa5e7 100644 --- a/src/gtk1/utilsgtk.cpp +++ b/src/gtk1/utilsgtk.cpp @@ -97,11 +97,6 @@ void wxGetMousePosition( int* x, int* y ) gdk_window_get_pointer( NULL, x, y, NULL ); } -bool wxColourDisplay() -{ - return true; -} - wxWindow* wxFindWindowAtPoint(const wxPoint& pt) { return wxGenericFindWindowAtPoint(pt); diff --git a/src/motif/utils.cpp b/src/motif/utils.cpp index 621b89cc27..87a1af7da0 100644 --- a/src/motif/utils.cpp +++ b/src/motif/utils.cpp @@ -225,12 +225,6 @@ void wxGetMousePosition( int* x, int* y ) #endif } -// Return true if we have a colour display -bool wxColourDisplay() -{ - return wxDisplayDepth() > 1; -} - void wxDisplaySizeMM(int *width, int *height) { Display *dpy = wxGlobalDisplay(); diff --git a/src/msw/utilsgui.cpp b/src/msw/utilsgui.cpp index a475bc6290..9ac17ef4b1 100644 --- a/src/msw/utilsgui.cpp +++ b/src/msw/utilsgui.cpp @@ -117,27 +117,6 @@ void wxGetMousePosition( int* x, int* y ) if ( y ) *y = pt.y; } -// Return true if we have a colour display -bool wxColourDisplay() -{ - // this function is called from wxDC ctor so it is called a *lot* of times - // hence we optimize it a bit but doing the check only once - // - // this should be MT safe as only the GUI thread (holding the GUI mutex) - // can call us - static int s_isColour = -1; - - if ( s_isColour == -1 ) - { - ScreenHDC dc; - int noCols = ::GetDeviceCaps(dc, NUMCOLORS); - - s_isColour = (noCols == -1) || (noCols > 2); - } - - return s_isColour != 0; -} - void wxDisplaySizeMM(int *width, int *height) { ScreenHDC dc; diff --git a/src/osx/utils_osx.cpp b/src/osx/utils_osx.cpp index d53c47f753..b1c1975997 100644 --- a/src/osx/utils_osx.cpp +++ b/src/osx/utils_osx.cpp @@ -53,14 +53,6 @@ bool wxCheckForInterrupt(wxWindow *WXUNUSED(wnd)) return false; } -// Return true if we have a colour display -bool wxColourDisplay() -{ - // always the case on OS X - return true; -} - - #if wxOSX_USE_COCOA_OR_CARBON #if wxUSE_GUI diff --git a/src/qt/utils.cpp b/src/qt/utils.cpp index bcaedc95e2..fb6dce807e 100644 --- a/src/qt/utils.cpp +++ b/src/qt/utils.cpp @@ -140,11 +140,6 @@ wxWindow *wxGetActiveWindow() return NULL; } -bool wxColourDisplay() -{ - return QApplication::desktop()->depth() > 1; -} - bool wxLaunchDefaultApplication(const wxString& path, int WXUNUSED( flags ) ) { return QDesktopServices::openUrl( QUrl::fromLocalFile( wxQtConvertString( path ) ) ); diff --git a/src/x11/utils.cpp b/src/x11/utils.cpp index 7a917354ab..a5d71d4046 100644 --- a/src/x11/utils.cpp +++ b/src/x11/utils.cpp @@ -148,12 +148,6 @@ void wxGetMousePosition( int* x, int* y ) #endif }; -// Return true if we have a colour display -bool wxColourDisplay() -{ - return wxDisplayDepth() > 1; -} - void wxDisplaySizeMM(int *width, int *height) { Display *dpy = (Display*) wxGetDisplay(); From ded2894b787b647f1f311c5954c95c7042f9bf5f Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sat, 6 Oct 2018 23:21:45 +0200 Subject: [PATCH 6/6] Add wxDisplay::GetPPI() to use instead of wxGetDisplayPPI() While this is not done for all the ports yet, the new API allows returning different PPI values for different monitors, unlike the old (and still existing, but implemented in terms of the new one) global function. --- docs/changes.txt | 1 + include/wx/display.h | 4 ++ include/wx/gdicmn.h | 3 + include/wx/private/display.h | 9 +++ interface/wx/display.h | 15 ++++- interface/wx/gdicmn.h | 4 ++ interface/wx/vidmode.h | 2 - samples/display/display.cpp | 5 ++ src/common/dpycmn.cpp | 29 ++++++++++ src/common/gdicmn.cpp | 25 +++++--- src/dfb/utils.cpp | 22 +++---- src/gtk/display.cpp | 39 +++++++++++++ src/gtk/utilsgtk.cpp | 14 ----- src/gtk1/utilsgtk.cpp | 6 -- src/motif/utils.cpp | 10 ---- src/msw/display.cpp | 108 +++++++++++++++++++++++++++++++++++ src/msw/utilsgui.cpp | 10 ---- src/osx/core/display.cpp | 17 ++++++ src/osx/iphone/utils.mm | 5 ++ src/osx/utils_osx.cpp | 22 ------- src/qt/display.cpp | 8 +++ src/qt/utils.cpp | 8 --- src/unix/displayx11.cpp | 21 +++++++ src/x11/utils.cpp | 10 ---- 24 files changed, 290 insertions(+), 107 deletions(-) diff --git a/docs/changes.txt b/docs/changes.txt index f229181029..f7fc4f8e2f 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -127,6 +127,7 @@ All (GUI): - Allow binding to events generated by their items in submenus too. - Add wxGrid::SetCornerLabelValue() (Pavel Kalugin). - Add strikethrough support for fonts defined in XRC. +- Add wxDisplay::GetPPI(). wxGTK: diff --git a/include/wx/display.h b/include/wx/display.h index 726dfee418..af299a74e0 100644 --- a/include/wx/display.h +++ b/include/wx/display.h @@ -11,6 +11,7 @@ #define _WX_DISPLAY_H_BASE_ #include "wx/defs.h" +#include "wx/gdicmn.h" // wxSize // NB: no #if wxUSE_DISPLAY here, the display geometry part of this class (but // not the video mode stuff) is always available but if wxUSE_DISPLAY == 0 @@ -77,6 +78,9 @@ public: // get the depth, i.e. number of bits per pixel (0 if unknown) int GetDepth() const; + // get the resolution of this monitor in pixels per inch + wxSize GetPPI() const; + // name may be empty wxString GetName() const; diff --git a/include/wx/gdicmn.h b/include/wx/gdicmn.h index f7d39c017b..e415f1c115 100644 --- a/include/wx/gdicmn.h +++ b/include/wx/gdicmn.h @@ -1080,6 +1080,9 @@ extern WXDLLIMPEXP_DATA_CORE(const wxPoint) wxDefaultPosition; extern void WXDLLIMPEXP_CORE wxInitializeStockLists(); extern void WXDLLIMPEXP_CORE wxDeleteStockLists(); +// Note: all the display-related functions here exist for compatibility only, +// please use wxDisplay class in the new code + // is the display colour (or monochrome)? extern bool WXDLLIMPEXP_CORE wxColourDisplay(); diff --git a/include/wx/private/display.h b/include/wx/private/display.h index 686e703101..1cd7bae8d0 100644 --- a/include/wx/private/display.h +++ b/include/wx/private/display.h @@ -81,6 +81,15 @@ public: // return the depth or 0 if unknown virtual int GetDepth() const = 0; + // return the resolution of the display, uses GetSizeMM() by default but + // can be also overridden directly + virtual wxSize GetPPI() const; + + // return the physical size of the display or (0, 0) if unknown: this is + // only used by GetPPI() implementation in the base class, so if GetPPI() + // is overridden, this one doesn't have to be implemented + virtual wxSize GetSizeMM() const { return wxSize(0, 0); } + // return the name (may be empty) virtual wxString GetName() const { return wxString(); } diff --git a/interface/wx/display.h b/interface/wx/display.h index 7e82ef1af1..1a3ca71450 100644 --- a/interface/wx/display.h +++ b/interface/wx/display.h @@ -12,8 +12,6 @@ @library{wxcore} @category{cfg} - - @see wxClientDisplayRect(), wxDisplaySize(), wxDisplaySizeMM() */ class wxDisplay { @@ -109,6 +107,19 @@ public: */ wxString GetName() const; + /** + Returns display resolution in pixels per inch. + + 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 @code wxSize(0, + 0) @endcode. + + @since 3.1.2 + */ + wxSize GetPPI() const; + /** Returns @true if the display is the primary display. The primary display is the one whose index is 0. diff --git a/interface/wx/gdicmn.h b/interface/wx/gdicmn.h index 2033b5461d..0e8ffd53c8 100644 --- a/interface/wx/gdicmn.h +++ b/interface/wx/gdicmn.h @@ -1256,6 +1256,10 @@ wxRect wxGetClientDisplayRect(); The @c x component of the returned wxSize object contains the horizontal resolution and the @c y one -- the vertical resolution. + @note Use of this function is not recommended in the new code as it only + works for the primary display. Use wxDisplay::GetPPI() to retrieve + the resolution of the appropriate display instead. + @header{wx/gdicmn.h} @see wxDisplay diff --git a/interface/wx/vidmode.h b/interface/wx/vidmode.h index b8a1bcf7ff..9097e67b23 100644 --- a/interface/wx/vidmode.h +++ b/interface/wx/vidmode.h @@ -15,8 +15,6 @@ @stdobjects ::wxDefaultVideoMode - - @see wxClientDisplayRect(), wxDisplaySize(), wxDisplaySizeMM() */ struct wxVideoMode { diff --git a/samples/display/display.cpp b/samples/display/display.cpp index 5b715f88ec..7996eac945 100644 --- a/samples/display/display.cpp +++ b/samples/display/display.cpp @@ -275,6 +275,11 @@ MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size, rc.x, rc.y, rc.width, rc.height) )); + 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))); + sizer->Add(new wxStaticText(page, wxID_ANY, "Depth: ")); sizer->Add(new wxStaticText(page, wxID_ANY, wxString::Format("%d", display.GetDepth()))); diff --git a/src/common/dpycmn.cpp b/src/common/dpycmn.cpp index 9968f3cbfa..d0073ee32c 100644 --- a/src/common/dpycmn.cpp +++ b/src/common/dpycmn.cpp @@ -29,6 +29,8 @@ #include "wx/module.h" #endif //WX_PRECOMP +#include "wx/math.h" + #include "wx/private/display.h" #if wxUSE_DISPLAY @@ -122,6 +124,13 @@ wxRect wxDisplay::GetClientArea() const return m_impl->GetClientArea(); } +wxSize wxDisplay::GetPPI() const +{ + wxCHECK_MSG( IsOk(), wxSize(), wxT("invalid wxDisplay object") ); + + return m_impl->GetPPI(); +} + int wxDisplay::GetDepth() const { wxCHECK_MSG( IsOk(), 0, wxT("invalid wxDisplay object") ); @@ -180,6 +189,26 @@ bool wxDisplay::ChangeMode(const wxVideoMode& mode) return *gs_factory; } +// ============================================================================ +// wxDisplayImpl implementation +// ============================================================================ + +wxSize wxDisplayImpl::GetPPI() const +{ + const wxSize pixels = GetGeometry().GetSize(); + const wxSize mm = GetSizeMM(); + + if ( !mm.x || !mm.y ) + { + // Physical size is unknown, return a special value indicating that we + // can't compute the resolution -- what else can we do? + return wxSize(0, 0); + } + + return wxSize(wxRound((pixels.x * inches2mm) / mm.x), + wxRound((pixels.y * inches2mm) / mm.y)); +} + // ============================================================================ // wxDisplayFactory implementation // ============================================================================ diff --git a/src/common/gdicmn.cpp b/src/common/gdicmn.cpp index a584eccc5f..0b2d514408 100644 --- a/src/common/gdicmn.cpp +++ b/src/common/gdicmn.cpp @@ -889,20 +889,29 @@ wxRect wxGetClientDisplayRect() return wxDisplay().GetClientArea(); } +void wxDisplaySizeMM(int *width, int *height) +{ + const wxSize size = wxGetDisplaySizeMM(); + if ( width ) + *width = size.x; + if ( height ) + *height = size.y; +} + wxSize wxGetDisplaySizeMM() { - int x, y; - wxDisplaySizeMM(& x, & y); - return wxSize(x, y); + const wxSize ppi = wxGetDisplayPPI(); + if ( !ppi.x || !ppi.y ) + return wxSize(0, 0); + + const wxSize pixels = wxGetDisplaySize(); + return wxSize(wxRound(pixels.x * inches2mm / ppi.x), + wxRound(pixels.y * inches2mm / ppi.y)); } wxSize wxGetDisplayPPI() { - const wxSize pixels = wxGetDisplaySize(); - const wxSize mm = wxGetDisplaySizeMM(); - - return wxSize((int)((pixels.x * inches2mm) / mm.x), - (int)((pixels.y * inches2mm) / mm.y)); + return wxDisplay().GetPPI(); } wxResourceCache::~wxResourceCache () diff --git a/src/dfb/utils.cpp b/src/dfb/utils.cpp index b4e97dc727..4cbd60253f 100644 --- a/src/dfb/utils.cpp +++ b/src/dfb/utils.cpp @@ -73,6 +73,13 @@ public: { return wxTheApp->GetDisplayMode().bpp; } + + virtual wxSize GetPPI() const wxOVERRIDE + { + // FIXME: there's no way to get physical resolution using the DirectDB + // API, we hardcode a commonly used value of 72dpi + return wxSize(72, 72); + } }; class wxDisplayFactorySingleDFB : public wxDisplayFactorySingle @@ -89,21 +96,6 @@ wxDisplayFactory* wxDisplay::CreateFactory() return new wxDisplayFactorySingleDFB; } -void wxDisplaySizeMM(int *width, int *height) -{ - // FIXME: there's no way to get physical resolution using the DirectDB - // API, we hardcode a commonly used value of 72dpi - #define DPI 72.0 - #define PX_TO_MM(x) (int(((x) / DPI) * inches2mm)) - - wxDisplaySize(width, height); - if ( width ) *width = PX_TO_MM(*width); - if ( height ) *height = PX_TO_MM(*height); - - #undef DPI - #undef PX_TO_MM -} - //----------------------------------------------------------------------------- // mouse //----------------------------------------------------------------------------- diff --git a/src/gtk/display.cpp b/src/gtk/display.cpp index 2cc424c8db..07e1fc45f3 100644 --- a/src/gtk/display.cpp +++ b/src/gtk/display.cpp @@ -46,6 +46,7 @@ public: virtual wxRect GetGeometry() const wxOVERRIDE; virtual wxRect GetClientArea() const wxOVERRIDE; virtual int GetDepth() const wxOVERRIDE; + virtual wxSize GetSizeMM() const wxOVERRIDE; #if wxUSE_DISPLAY virtual bool IsPrimary() const wxOVERRIDE; @@ -120,6 +121,15 @@ int wxDisplayImplGTK::GetDepth() const return 24; } +wxSize wxDisplayImplGTK::GetSizeMM() const +{ + return wxSize + ( + gdk_monitor_get_width_mm(m_monitor), + gdk_monitor_get_height_mm(m_monitor) + ); +} + #if wxUSE_DISPLAY bool wxDisplayImplGTK::IsPrimary() const { @@ -212,6 +222,7 @@ public: virtual wxRect GetGeometry() const wxOVERRIDE; virtual wxRect GetClientArea() const wxOVERRIDE; virtual int GetDepth() const wxOVERRIDE; + virtual wxSize GetSizeMM() const wxOVERRIDE; #if wxUSE_DISPLAY virtual bool IsPrimary() const wxOVERRIDE; @@ -282,6 +293,34 @@ int wxDisplayImplGTK::GetDepth() const return gdk_visual_get_depth(gdk_window_get_visual(wxGetTopLevelGDK())); } +wxSize wxDisplayImplGTK::GetSizeMM() const +{ + // At least in some configurations, gdk_screen_xxx_mm() functions return + // valid values when gdk_screen_get_monitor_xxx_mm() only return -1, so + // handle this case specially. + if ( IsPrimary() ) + { + return wxSize(gdk_screen_width_mm(), gdk_screen_height_mm()); + } + + wxSize sizeMM; +#if GTK_CHECK_VERSION(2,14,0) + if ( wx_is_at_least_gtk2(14) ) + { + // Take care not to return (-1, -1) from here, the caller expects us to + // return (0, 0) if we can't retrieve this information. + int rc = gdk_screen_get_monitor_width_mm(m_screen, m_index); + if ( rc != -1 ) + sizeMM.x = rc; + + rc = gdk_screen_get_monitor_height_mm(m_screen, m_index); + if ( rc != -1 ) + sizeMM.y = rc; + } +#endif // GTK+ 2.14 + return sizeMM; +} + #if wxUSE_DISPLAY bool wxDisplayImplGTK::IsPrimary() const { diff --git a/src/gtk/utilsgtk.cpp b/src/gtk/utilsgtk.cpp index f0a36126f1..137fb2cf16 100644 --- a/src/gtk/utilsgtk.cpp +++ b/src/gtk/utilsgtk.cpp @@ -76,20 +76,6 @@ void *wxGetDisplay() } #endif -void wxDisplaySizeMM( int *width, int *height ) -{ -#ifdef __WXGTK4__ - GdkMonitor* monitor = gdk_display_get_primary_monitor(gdk_display_get_default()); - if (width) *width = gdk_monitor_get_width_mm(monitor); - if (height) *height = gdk_monitor_get_height_mm(monitor); -#else - wxGCC_WARNING_SUPPRESS(deprecated-declarations) - if (width) *width = gdk_screen_width_mm(); - if (height) *height = gdk_screen_height_mm(); - wxGCC_WARNING_RESTORE() -#endif -} - wxWindow* wxFindWindowAtPoint(const wxPoint& pt) { return wxGenericFindWindowAtPoint(pt); diff --git a/src/gtk1/utilsgtk.cpp b/src/gtk1/utilsgtk.cpp index bdcadfa5e7..b84627535e 100644 --- a/src/gtk1/utilsgtk.cpp +++ b/src/gtk1/utilsgtk.cpp @@ -86,12 +86,6 @@ void *wxGetDisplay() return GDK_DISPLAY(); } -void wxDisplaySizeMM( int *width, int *height ) -{ - if (width) *width = gdk_screen_width_mm(); - if (height) *height = gdk_screen_height_mm(); -} - void wxGetMousePosition( int* x, int* y ) { gdk_window_get_pointer( NULL, x, y, NULL ); diff --git a/src/motif/utils.cpp b/src/motif/utils.cpp index 87a1af7da0..480faad86e 100644 --- a/src/motif/utils.cpp +++ b/src/motif/utils.cpp @@ -225,16 +225,6 @@ void wxGetMousePosition( int* x, int* y ) #endif } -void wxDisplaySizeMM(int *width, int *height) -{ - Display *dpy = wxGlobalDisplay(); - - if ( width ) - *width = DisplayWidthMM(dpy, DefaultScreen (dpy)); - if ( height ) - *height = DisplayHeightMM(dpy, DefaultScreen (dpy)); -} - // Configurable display in wxX11 and wxMotif static WXDisplay *gs_currentDisplay = NULL; static wxString gs_displayName; diff --git a/src/msw/display.cpp b/src/msw/display.cpp index e6ea6486a8..6fd48acd44 100644 --- a/src/msw/display.cpp +++ b/src/msw/display.cpp @@ -26,9 +26,14 @@ #include "wx/private/display.h" +#include "wx/dynlib.h" + #include "wx/msw/private.h" #include "wx/msw/wrapwin.h" +namespace +{ + int wxGetHDCDepth(HDC hdc) { return ::GetDeviceCaps(hdc, PLANES) * GetDeviceCaps(hdc, BITSPIXEL); @@ -62,6 +67,13 @@ public: { return wxGetHDCDepth(ScreenHDC()); } + + virtual wxSize GetSizeMM() const wxOVERRIDE + { + ScreenHDC dc; + + return wxSize(::GetDeviceCaps(dc, HORZSIZE), ::GetDeviceCaps(dc, VERTSIZE)); + } }; class wxDisplayFactorySingleMSW : public wxDisplayFactorySingle @@ -73,6 +85,8 @@ protected: } }; +} // anonymous namespace + #if wxUSE_DISPLAY #ifndef WX_PRECOMP @@ -87,6 +101,10 @@ protected: #include "wx/msw/missing.h" #include "wx/msw/private/hiddenwin.h" +#ifndef DPI_ENUMS_DECLARED + #define MDT_EFFECTIVE_DPI 0 +#endif + static const wxChar displayDllName[] = wxT("user32.dll"); namespace @@ -119,6 +137,8 @@ public: virtual wxRect GetGeometry() const wxOVERRIDE; virtual wxRect GetClientArea() const wxOVERRIDE; virtual int GetDepth() const wxOVERRIDE; + virtual wxSize GetPPI() const wxOVERRIDE; + virtual wxString GetName() const wxOVERRIDE; virtual bool IsPrimary() const wxOVERRIDE; @@ -176,6 +196,13 @@ public: // handles. static void RefreshMonitors() { ms_factory->DoRefreshMonitors(); } + // Declare the second argument as int to avoid problems with older SDKs not + // declaring MONITOR_DPI_TYPE enum. + typedef HRESULT (WINAPI *GetDpiForMonitor_t)(HMONITOR, int, UINT*, UINT*); + + // Return the pointer to GetDpiForMonitor() function which may be null if + // not running under new enough Windows version. + static GetDpiForMonitor_t GetDpiForMonitorPtr(); private: // EnumDisplayMonitors() callback @@ -197,6 +224,48 @@ private: // variable (also making it of correct type for us) here). static wxDisplayFactoryMSW* ms_factory; + // The pointer to GetDpiForMonitorPtr(), retrieved on demand, and the + // related data, including the DLL containing the function that we must + // keep loaded. + struct GetDpiForMonitorData + { + GetDpiForMonitorData() + { + m_pfnGetDpiForMonitor = NULL; + m_initialized = false; + } + + bool TryLoad() + { + if ( !m_dllShcore.Load("shcore.dll", wxDL_VERBATIM | wxDL_QUIET) ) + return false; + + wxDL_INIT_FUNC(m_pfn, GetDpiForMonitor, m_dllShcore); + + if ( !m_pfnGetDpiForMonitor ) + { + m_dllShcore.Unload(); + return false; + } + + return true; + } + + void UnloadIfNecessary() + { + if ( m_dllShcore.IsLoaded() ) + { + m_dllShcore.Unload(); + m_pfnGetDpiForMonitor = NULL; + } + } + + wxDynamicLibrary m_dllShcore; + GetDpiForMonitor_t m_pfnGetDpiForMonitor; + bool m_initialized; + }; + static GetDpiForMonitorData ms_getDpiForMonitorData; + // the array containing information about all available displays, filled by // MultimonEnumProc() @@ -211,6 +280,8 @@ private: }; wxDisplayFactoryMSW* wxDisplayFactoryMSW::ms_factory = NULL; +wxDisplayFactoryMSW::GetDpiForMonitorData + wxDisplayFactoryMSW::ms_getDpiForMonitorData; // ---------------------------------------------------------------------------- // wxDisplay implementation @@ -272,6 +343,24 @@ int wxDisplayMSW::GetDepth() const return m_info.depth; } +wxSize wxDisplayMSW::GetPPI() const +{ + if ( const wxDisplayFactoryMSW::GetDpiForMonitor_t + getFunc = wxDisplayFactoryMSW::GetDpiForMonitorPtr() ) + { + UINT dpiX = 0, + dpiY = 0; + const HRESULT + hr = (*getFunc)(m_info.hmon, MDT_EFFECTIVE_DPI, &dpiX, &dpiY); + if ( SUCCEEDED(hr) ) + return wxSize(dpiX, dpiY); + + wxLogApiError("GetDpiForMonitor", hr); + } + + return IsPrimary() ? wxDisplayImplSingleMSW().GetPPI() : wxSize(0, 0); +} + wxString wxDisplayMSW::GetName() const { WinStruct monInfo; @@ -492,9 +581,28 @@ wxDisplayFactoryMSW::~wxDisplayFactoryMSW() } } + if ( ms_getDpiForMonitorData.m_initialized ) + { + ms_getDpiForMonitorData.UnloadIfNecessary(); + ms_getDpiForMonitorData.m_initialized = false; + } + ms_factory = NULL; } +/* static */ +wxDisplayFactoryMSW::GetDpiForMonitor_t +wxDisplayFactoryMSW::GetDpiForMonitorPtr() +{ + if ( !ms_getDpiForMonitorData.m_initialized ) + { + ms_getDpiForMonitorData.m_initialized = true; + ms_getDpiForMonitorData.TryLoad(); + } + + return ms_getDpiForMonitorData.m_pfnGetDpiForMonitor; +} + void wxDisplayFactoryMSW::DoRefreshMonitors() { m_displays.clear(); diff --git a/src/msw/utilsgui.cpp b/src/msw/utilsgui.cpp index 9ac17ef4b1..7c7bfcf07c 100644 --- a/src/msw/utilsgui.cpp +++ b/src/msw/utilsgui.cpp @@ -117,16 +117,6 @@ void wxGetMousePosition( int* x, int* y ) if ( y ) *y = pt.y; } -void wxDisplaySizeMM(int *width, int *height) -{ - ScreenHDC dc; - - if ( width ) - *width = ::GetDeviceCaps(dc, HORZSIZE); - if ( height ) - *height = ::GetDeviceCaps(dc, VERTSIZE); -} - // --------------------------------------------------------------------------- // window information functions // --------------------------------------------------------------------------- diff --git a/src/osx/core/display.cpp b/src/osx/core/display.cpp index 2e55b346b8..395ef7a8c2 100644 --- a/src/osx/core/display.cpp +++ b/src/osx/core/display.cpp @@ -75,6 +75,12 @@ int wxGetDisplayDepth(CGDirectDisplayID id) return theDepth; } +wxSize wxGetDisplaySizeMM(CGDirectDisplayID id) +{ + const CGSize size = CGDisplayScreenSize(id); + return wxSize(wxRound(size.width), wxRound(size.height)); +} + } // anonymous namespace #if wxUSE_DISPLAY @@ -97,6 +103,7 @@ public: virtual wxRect GetGeometry() const wxOVERRIDE; virtual wxRect GetClientArea() const wxOVERRIDE; virtual int GetDepth() const wxOVERRIDE; + virtual wxSize GetSizeMM() const wxOVERRIDE; virtual wxArrayVideoModes GetModes(const wxVideoMode& mode) const wxOVERRIDE; virtual wxVideoMode GetCurrentMode() const wxOVERRIDE; @@ -258,6 +265,11 @@ int wxDisplayImplMacOSX::GetDepth() const return wxGetDisplayDepth(m_id); } +wxSize wxDisplayImplMacOSX::GetSizeMM() const +{ + return wxGetDisplaySizeMM(m_id); +} + static int wxOSXCGDisplayModeGetBitsPerPixel( CGDisplayModeRef theValue ) { wxCFRef pixelEncoding( CGDisplayModeCopyPixelEncoding(theValue) ); @@ -373,6 +385,11 @@ public: { return wxGetDisplayDepth(CGMainDisplayID()); } + + virtual wxSize GetSizeMM() const wxOVERRIDE + { + return wxGetDisplaySizeMM(CGMainDisplayID()); + } }; class wxDisplayFactorySingleMacOSX : public wxDisplayFactorySingle diff --git a/src/osx/iphone/utils.mm b/src/osx/iphone/utils.mm index dd77cfd5e6..af0239e939 100644 --- a/src/osx/iphone/utils.mm +++ b/src/osx/iphone/utils.mm @@ -160,6 +160,11 @@ public: { return 32; // TODO can we determine this ? } + + virtual wxSize GetPPI() const wxOVERRIDE + { + return wxSize(72, 72); + } }; class wxDisplayFactorySingleiOS : public wxDisplayFactorySingle diff --git a/src/osx/utils_osx.cpp b/src/osx/utils_osx.cpp index b1c1975997..2350f16cb6 100644 --- a/src/osx/utils_osx.cpp +++ b/src/osx/utils_osx.cpp @@ -106,28 +106,6 @@ bool wxDoLaunchDefaultBrowser(const wxLaunchBrowserParams& params) #endif -void wxDisplaySizeMM(int *width, int *height) -{ -#if wxOSX_USE_IPHONE - wxDisplaySize(width, height); - // on mac 72 is fixed (at least now;-) - double cvPt2Mm = 25.4 / 72; - - if (width != NULL) - *width = int( *width * cvPt2Mm ); - - if (height != NULL) - *height = int( *height * cvPt2Mm ); -#else - CGSize size = CGDisplayScreenSize(CGMainDisplayID()); - if ( width ) - *width = (int)size.width ; - if ( height ) - *height = (int)size.height; -#endif -} - - wxPortId wxGUIAppTraits::GetToolkitVersion(int *verMaj, int *verMin, int *verMicro) const diff --git a/src/qt/display.cpp b/src/qt/display.cpp index 6d3de3ac2e..18eb47e286 100644 --- a/src/qt/display.cpp +++ b/src/qt/display.cpp @@ -22,6 +22,7 @@ public: virtual wxRect GetGeometry() const wxOVERRIDE; virtual wxRect GetClientArea() const wxOVERRIDE; virtual int GetDepth() const wxOVERRIDE; + virtual wxSize GetSizeMM() const wxOVERRIDE; #if wxUSE_DISPLAY virtual wxArrayVideoModes GetModes(const wxVideoMode& mode) const wxOVERRIDE; @@ -50,6 +51,13 @@ int wxDisplayImplQt::GetDepth() const return IsPrimary() ? QApplication::desktop()->depth() : 0; } +wxSize wxDisplayImplQt::GetSizeMM() const +{ + return IsPrimary() ? wxSize(QApplication::desktop()->widthMM(), + QApplication::desktop()->heightMM()) + : wxSize(0, 0); +} + #if wxUSE_DISPLAY wxArrayVideoModes wxDisplayImplQt::GetModes(const wxVideoMode& WXUNUSED(mode)) const { diff --git a/src/qt/utils.cpp b/src/qt/utils.cpp index fb6dce807e..428e9e3dd5 100644 --- a/src/qt/utils.cpp +++ b/src/qt/utils.cpp @@ -110,14 +110,6 @@ bool wxGetKeyState(wxKeyCode key) } } -void wxDisplaySizeMM(int *width, int *height) -{ - if ( width != NULL ) - *width = QApplication::desktop()->widthMM(); - if ( height != NULL ) - *height = QApplication::desktop()->heightMM(); -} - void wxBell() { QApplication::beep(); diff --git a/src/unix/displayx11.cpp b/src/unix/displayx11.cpp index b352e5392f..e2e67970c0 100644 --- a/src/unix/displayx11.cpp +++ b/src/unix/displayx11.cpp @@ -44,6 +44,17 @@ inline int wxGetMainScreenDepth() return DefaultDepth(dpy, DefaultScreen (dpy)); } +inline wxSize wxGetMainScreenSizeMM() +{ + Display* const dpy = wxGetX11Display(); + + return wxSize + ( + DisplayWidthMM(dpy, DefaultScreen(dpy)), + DisplayHeightMM(dpy, DefaultScreen(dpy)) + ); +} + class wxDisplayImplSingleX11 : public wxDisplayImplSingle { public: @@ -65,6 +76,11 @@ public: { return wxGetMainScreenDepth(); } + + virtual wxSize GetSizeMM() const wxOVERRIDE + { + return wxGetMainScreenSizeMM(); + } }; class wxDisplayFactorySingleX11 : public wxDisplayFactorySingle @@ -143,6 +159,11 @@ public: return wxGetMainScreenDepth(); } + virtual wxSize GetSizeMM() const wxOVERRIDE + { + // TODO: how to get physical size or resolution of the other monitors? + return IsPrimary() ? wxGetMainScreenSizeMM() : wxSize(0, 0); + } virtual wxArrayVideoModes GetModes(const wxVideoMode& mode) const wxOVERRIDE; virtual wxVideoMode GetCurrentMode() const wxOVERRIDE; diff --git a/src/x11/utils.cpp b/src/x11/utils.cpp index a5d71d4046..16e7995eba 100644 --- a/src/x11/utils.cpp +++ b/src/x11/utils.cpp @@ -148,16 +148,6 @@ void wxGetMousePosition( int* x, int* y ) #endif }; -void wxDisplaySizeMM(int *width, int *height) -{ - Display *dpy = (Display*) wxGetDisplay(); - - if ( width ) - *width = DisplayWidthMM(dpy, DefaultScreen (dpy)); - if ( height ) - *height = DisplayHeightMM(dpy, DefaultScreen (dpy)); -} - wxWindow* wxFindWindowAtPoint(const wxPoint& pt) { return wxGenericFindWindowAtPoint(pt);