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/docs/changes.txt b/docs/changes.txt index 0f8e04e1e5..3278de9e9d 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 3213d79d97..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 @@ -74,6 +75,12 @@ 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; + + // 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 9f0dce0ad2..1cd7bae8d0 100644 --- a/include/wx/private/display.h +++ b/include/wx/private/display.h @@ -78,6 +78,18 @@ 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 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 6e98d29d88..0e8ffd53c8 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(); @@ -1191,6 +1195,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(); @@ -1248,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 @@ -1262,6 +1274,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 +1293,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} 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 7c97a54c34..7996eac945 100644 --- a/samples/display/display.cpp +++ b/samples/display/display.cpp @@ -275,6 +275,15 @@ 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()))); + sizer->Add(new wxStaticText(page, wxID_ANY, "Name: ")); sizer->Add(new wxStaticText(page, wxID_ANY, display.GetName())); 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/common/dpycmn.cpp b/src/common/dpycmn.cpp index cd49ae60ec..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,20 @@ 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") ); + + return m_impl->GetDepth(); +} + wxString wxDisplay::GetName() const { wxCHECK_MSG( IsOk(), wxString(), wxT("invalid wxDisplay object") ); @@ -173,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 771db4ac72..0b2d514408 100644 --- a/src/common/gdicmn.cpp +++ b/src/common/gdicmn.cpp @@ -845,6 +845,18 @@ wxFont *wxFontList::FindOrCreateFont(int pointSize, return font; } +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(); @@ -877,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 76c84a5c50..4cbd60253f 100644 --- a/src/dfb/utils.cpp +++ b/src/dfb/utils.cpp @@ -68,6 +68,18 @@ public: return wxRect(0, 0, mode.w, mode.h); } + + virtual int GetDepth() const wxOVERRIDE + { + 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 @@ -84,32 +96,6 @@ wxDisplayFactory* wxDisplay::CreateFactory() return new wxDisplayFactorySingleDFB; } -bool wxColourDisplay() -{ - #warning "FIXME: 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 - // 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 2576d0d6c2..07e1fc45f3 100644 --- a/src/gtk/display.cpp +++ b/src/gtk/display.cpp @@ -45,6 +45,8 @@ public: wxDisplayImplGTK(unsigned i); 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; @@ -114,6 +116,20 @@ wxRect wxDisplayImplGTK::GetClientArea() const return wxRect(rect.x, rect.y, rect.width, rect.height); } +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 { @@ -205,6 +221,8 @@ public: wxDisplayImplGTK(unsigned i); 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; @@ -269,6 +287,40 @@ 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())); +} + +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 31a1d9a9ea..137fb2cf16 100644 --- a/src/gtk/utilsgtk.cpp +++ b/src/gtk/utilsgtk.cpp @@ -76,34 +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 -} - -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 c912fc9a9a..b84627535e 100644 --- a/src/gtk1/utilsgtk.cpp +++ b/src/gtk1/utilsgtk.cpp @@ -86,33 +86,11 @@ 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(); - if (height) *height = gdk_screen_height_mm(); -} - void wxGetMousePosition( int* x, int* y ) { gdk_window_get_pointer( NULL, x, y, NULL ); } -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/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; diff --git a/src/motif/utils.cpp b/src/motif/utils.cpp index 16c52e86a8..480faad86e 100644 --- a/src/motif/utils.cpp +++ b/src/motif/utils.cpp @@ -225,30 +225,6 @@ void wxGetMousePosition( int* x, int* y ) #endif } -// Return true if we have a colour display -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(); - - 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 771cb32132..6fd48acd44 100644 --- a/src/msw/display.cpp +++ b/src/msw/display.cpp @@ -26,9 +26,19 @@ #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); +} + // 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 +62,18 @@ public: wxCopyRECTToRect(rc, rectClient); return rectClient; } + + virtual int GetDepth() const wxOVERRIDE + { + return wxGetHDCDepth(ScreenHDC()); + } + + virtual wxSize GetSizeMM() const wxOVERRIDE + { + ScreenHDC dc; + + return wxSize(::GetDeviceCaps(dc, HORZSIZE), ::GetDeviceCaps(dc, VERTSIZE)); + } }; class wxDisplayFactorySingleMSW : public wxDisplayFactorySingle @@ -63,6 +85,8 @@ protected: } }; +} // anonymous namespace + #if wxUSE_DISPLAY #ifndef WX_PRECOMP @@ -77,8 +101,26 @@ 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 +{ + +// 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 +128,17 @@ 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 wxSize GetPPI() const wxOVERRIDE; + virtual wxString GetName() const wxOVERRIDE; virtual bool IsPrimary() const wxOVERRIDE; @@ -118,7 +163,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 +174,6 @@ private: // wxDisplayFactoryMSW declaration // ---------------------------------------------------------------------------- -WX_DEFINE_ARRAY(HMONITOR, wxMonitorHandleArray); - class wxDisplayFactoryMSW : public wxDisplayFactory { public: @@ -153,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 @@ -174,10 +224,52 @@ 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() - wxMonitorHandleArray m_displays; + wxVector m_displays; // The hidden window we use for receiving WM_SETTINGCHANGE and its class // name. @@ -188,6 +280,8 @@ private: }; wxDisplayFactoryMSW* wxDisplayFactoryMSW::ms_factory = NULL; +wxDisplayFactoryMSW::GetDpiForMonitorData + wxDisplayFactoryMSW::ms_getDpiForMonitorData; // ---------------------------------------------------------------------------- // wxDisplay implementation @@ -213,7 +307,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 +338,29 @@ wxRect wxDisplayMSW::GetClientArea() const return rectClient; } +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; @@ -464,14 +581,36 @@ 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(); + 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 +620,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 +647,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..7c7bfcf07c 100644 --- a/src/msw/utilsgui.cpp +++ b/src/msw/utilsgui.cpp @@ -117,44 +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; -} - -// Returns depth of screen -int wxDisplayDepth() -{ - ScreenHDC dc; - return GetDeviceCaps(dc, PLANES) * GetDeviceCaps(dc, BITSPIXEL); -} - -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 3f35ccc1e4..395ef7a8c2 100644 --- a/src/osx/core/display.cpp +++ b/src/osx/core/display.cpp @@ -52,6 +52,35 @@ 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; +} + +wxSize wxGetDisplaySizeMM(CGDirectDisplayID id) +{ + const CGSize size = CGDisplayScreenSize(id); + return wxSize(wxRound(size.width), wxRound(size.height)); +} + } // anonymous namespace #if wxUSE_DISPLAY @@ -73,6 +102,8 @@ 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; @@ -229,6 +260,16 @@ wxRect wxDisplayImplMacOSX::GetClientArea() const return wxDisplayImpl::GetClientArea(); } +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) ); @@ -339,6 +380,16 @@ public: { return wxOSXGetMainDisplayClientArea(); } + + virtual int GetDepth() const wxOVERRIDE + { + 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 2136055e74..af0239e939 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,16 @@ public: return wxRect(0, 0, width, height); } + + virtual int GetDepth() const wxOVERRIDE + { + 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 6860b5e088..2350f16cb6 100644 --- a/src/osx/utils_osx.cpp +++ b/src/osx/utils_osx.cpp @@ -53,40 +53,8 @@ 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 -// 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 // ---------------------------------------------------------------------------- @@ -138,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 52b6af8373..18eb47e286 100644 --- a/src/qt/display.cpp +++ b/src/qt/display.cpp @@ -21,6 +21,8 @@ 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; @@ -44,6 +46,18 @@ wxRect wxDisplayImplQt::GetClientArea() const return wxQtConvertRect( QApplication::desktop()->availableGeometry( GetIndex() )); } +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 92957b8683..428e9e3dd5 100644 --- a/src/qt/utils.cpp +++ b/src/qt/utils.cpp @@ -110,19 +110,6 @@ bool wxGetKeyState(wxKeyCode key) } } -int wxDisplayDepth() -{ - return QApplication::desktop()->depth(); -} - -void wxDisplaySizeMM(int *width, int *height) -{ - if ( width != NULL ) - *width = QApplication::desktop()->widthMM(); - if ( height != NULL ) - *height = QApplication::desktop()->heightMM(); -} - void wxBell() { QApplication::beep(); @@ -145,11 +132,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/unix/displayx11.cpp b/src/unix/displayx11.cpp index 4e317ca6a0..e2e67970c0 100644 --- a/src/unix/displayx11.cpp +++ b/src/unix/displayx11.cpp @@ -34,6 +34,27 @@ static wxRect wxGetMainScreenWorkArea(); +namespace +{ + +inline int wxGetMainScreenDepth() +{ + Display* const dpy = wxGetX11Display(); + + 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: @@ -50,6 +71,16 @@ public: { return wxGetMainScreenWorkArea(); } + + virtual int GetDepth() const wxOVERRIDE + { + return wxGetMainScreenDepth(); + } + + virtual wxSize GetSizeMM() const wxOVERRIDE + { + return wxGetMainScreenSizeMM(); + } }; class wxDisplayFactorySingleX11 : public wxDisplayFactorySingle @@ -61,6 +92,8 @@ protected: } }; +} // anonymous namespace + #if wxUSE_DISPLAY #include @@ -118,6 +151,19 @@ 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 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; @@ -125,7 +171,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..16e7995eba 100644 --- a/src/x11/utils.cpp +++ b/src/x11/utils.cpp @@ -148,30 +148,6 @@ void wxGetMousePosition( int* x, int* y ) #endif }; -// Return true if we have a colour display -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(); - - if ( width ) - *width = DisplayWidthMM(dpy, DefaultScreen (dpy)); - if ( height ) - *height = DisplayHeightMM(dpy, DefaultScreen (dpy)); -} - wxWindow* wxFindWindowAtPoint(const wxPoint& pt) { return wxGenericFindWindowAtPoint(pt);