From 24b5e256df5a1593c6f47eabc077a017e47350fe Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sat, 6 Oct 2018 15:28:11 +0200 Subject: [PATCH] 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();