X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/a536e411022b21280532c9daadc806a437fbb4c6..3570a1c6e596c358848c77c5b37d724097340ce8:/src/mac/carbon/display.cpp diff --git a/src/mac/carbon/display.cpp b/src/mac/carbon/display.cpp index e25b2486e3..99c51f04ce 100644 --- a/src/mac/carbon/display.cpp +++ b/src/mac/carbon/display.cpp @@ -1,19 +1,22 @@ ///////////////////////////////////////////////////////////////////////////// -// Name: display.cpp +// Name: src/mac/carbon/display.cpp // Purpose: Mac implementation of wxDisplay class -// Author: Brian Victor -// Modified by: Royce Mitchell III +// Author: Ryan Norton & Brian Victor +// Modified by: Royce Mitchell III, Vadim Zeitlin // Created: 06/21/02 // RCS-ID: $Id$ -// Copyright: (c) wxWindows team +// Copyright: (c) wxWidgets team // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// -#ifdef __GNUG__ - #pragma implementation "display.h" -#endif +// ============================================================================ +// declarations +// ============================================================================ + +// ---------------------------------------------------------------------------- +// headers +// ---------------------------------------------------------------------------- -// For compilers that support precompilation, includes "wx.h". #include "wx/wxprec.h" #ifdef __BORLANDC__ @@ -22,114 +25,231 @@ #if wxUSE_DISPLAY +#include "wx/display.h" + #ifndef WX_PRECOMP - #include "wx/dynarray.h" + #include "wx/dynarray.h" + #include "wx/log.h" + #include "wx/string.h" + #include "wx/gdicmn.h" #endif -#ifdef __DARWIN__ - #include -#else - #include - #include -#endif +#include -#include "wx/display.h" -#include "wx/gdicmn.h" -#include "wx/string.h" +#include "wx/display_impl.h" // ---------------------------------------------------------------------------- -// private classes +// display classes implementation // ---------------------------------------------------------------------------- -class wxDisplayMacPriv +class wxDisplayImplMacOSX : public wxDisplayImpl { public: - GDHandle m_hndl; + wxDisplayImplMacOSX(unsigned n, CGDirectDisplayID id) + : wxDisplayImpl(n), + m_id(id) + { + } + + virtual wxRect GetGeometry() const; + virtual wxRect GetClientArea() const; + virtual wxString GetName() const { return wxString(); } + + virtual wxArrayVideoModes GetModes(const wxVideoMode& mode) const; + virtual wxVideoMode GetCurrentMode() const; + virtual bool ChangeMode(const wxVideoMode& mode); + +private: + CGDirectDisplayID m_id; + + DECLARE_NO_COPY_CLASS(wxDisplayImplMacOSX) }; -size_t wxDisplayBase::GetCount() +class wxDisplayFactoryMacOSX : public wxDisplayFactory { - GDHandle hndl; - size_t num = 0; - hndl = DMGetFirstScreenDevice(true); - while(hndl) - { - num++; - hndl = DMGetNextScreenDevice(hndl, true); - } - return num; +public: + wxDisplayFactoryMacOSX() {} + + virtual wxDisplayImpl *CreateDisplay(unsigned n); + virtual unsigned GetCount(); + virtual int GetFromPoint(const wxPoint& pt); + +protected: + DECLARE_NO_COPY_CLASS(wxDisplayFactoryMacOSX) +}; + +// ============================================================================ +// wxDisplayFactoryMacOSX implementation +// ============================================================================ + +unsigned wxDisplayFactoryMacOSX::GetCount() +{ + CGDisplayCount count; +#ifdef __WXDEBUG__ + CGDisplayErr err = +#endif + CGGetActiveDisplayList(0, NULL, &count); + + wxASSERT(err == CGDisplayNoErr); + + return count; } -int wxDisplayBase::GetFromPoint(const wxPoint &p) +int wxDisplayFactoryMacOSX::GetFromPoint(const wxPoint& p) { - GDHandle hndl; - size_t num = 0; - hndl = DMGetFirstScreenDevice(true); - while(hndl) + CGPoint thePoint = {(float)p.x, (float)p.y}; + CGDirectDisplayID theID; + CGDisplayCount theCount; + CGDisplayErr err = CGGetDisplaysWithPoint(thePoint, 1, &theID, &theCount); + wxASSERT(err == CGDisplayNoErr); + + int nWhich = wxNOT_FOUND; + + if (theCount) { - Rect screenrect = (*hndl)->gdRect; - if (p.x >= screenrect.left && - p.x <= screenrect.right && - p.y >= screenrect.top && - p.y <= screenrect.bottom) + theCount = GetCount(); + CGDirectDisplayID* theIDs = new CGDirectDisplayID[theCount]; + err = CGGetActiveDisplayList(theCount, theIDs, &theCount); + wxASSERT(err == CGDisplayNoErr); + + for (nWhich = 0; nWhich < (int) theCount; ++nWhich) { - return num; + if (theIDs[nWhich] == theID) + break; } - num++; - hndl = DMGetNextScreenDevice(hndl, true); - } - return -1; -} -wxDisplay::wxDisplay(size_t index) : wxDisplayBase ( index ), - m_priv ( new wxDisplayMacPriv() ) -{ - GDHandle hndl; - hndl = DMGetFirstScreenDevice(true); - m_priv->m_hndl = NULL; - while(hndl) - { - if (index == 0) + delete [] theIDs; + + if (nWhich == (int) theCount) { - m_priv->m_hndl = hndl; + wxFAIL_MSG(wxT("Failed to find display in display list")); + nWhich = wxNOT_FOUND; } - index--; - hndl = DMGetNextScreenDevice(hndl, true); } + + return nWhich; +} + +wxDisplayImpl *wxDisplayFactoryMacOSX::CreateDisplay(unsigned n) +{ + CGDisplayCount theCount = GetCount(); + CGDirectDisplayID* theIDs = new CGDirectDisplayID[theCount]; + +#ifdef __WXDEBUG__ + CGDisplayErr err = +#endif + CGGetActiveDisplayList(theCount, theIDs, &theCount); + + wxASSERT( err == CGDisplayNoErr ); + wxASSERT( n < theCount ); + + wxDisplayImplMacOSX *display = new wxDisplayImplMacOSX(n, theIDs[n]); + + delete [] theIDs; + + return display; } -wxRect wxDisplay::GetGeometry() const +// ============================================================================ +// wxDisplayImplMacOSX implementation +// ============================================================================ + +wxRect wxDisplayImplMacOSX::GetGeometry() const { - if (!(m_priv)) return wxRect(0, 0, 0, 0); - if (!(m_priv->m_hndl)) return wxRect(0, 0, 0, 0); - Rect screenrect = (*(m_priv->m_hndl))->gdRect; - return wxRect( screenrect.left, screenrect.top, - screenrect.right - screenrect.left, screenrect.bottom - screenrect.top); + CGRect theRect = CGDisplayBounds(m_id); + return wxRect( (int)theRect.origin.x, + (int)theRect.origin.y, + (int)theRect.size.width, + (int)theRect.size.height ); //floats } -int wxDisplay::GetDepth() const +wxRect wxDisplayImplMacOSX::GetClientArea() const { - if (!(m_priv)) return 0; - if (!(m_priv->m_hndl)) return 0; + // VZ: I don't know how to get client area for arbitrary display but + // wxGetClientDisplayRect() does work correctly for at least the main + // one (TODO: do it correctly for the other displays too) + if ( IsPrimary() ) + return wxGetClientDisplayRect(); - // This cryptic looking code is based on Apple's sample code: - // http://developer.apple.com/samplecode/Sample_Code/Graphics_2D/GDevVideo/Gen.cp.htm - return ((*(*(m_priv->m_hndl))->gdPMap)->pixelSize) & 0x0000FFFF; + return wxDisplayImpl::GetClientArea(); } -wxString wxDisplay::GetName() const +static int wxCFDictKeyToInt( CFDictionaryRef desc, CFStringRef key ) { - // Macs don't name their displays... - return wxT(""); + CFNumberRef value = (CFNumberRef) CFDictionaryGetValue( desc, key ); + if (value == NULL) + return 0; + + int num = 0; + CFNumberGetValue( value, kCFNumberIntType, &num ); + + return num; } -wxDisplay::~wxDisplay() +wxArrayVideoModes wxDisplayImplMacOSX::GetModes(const wxVideoMode& mode) const { - if ( m_priv ) + wxArrayVideoModes resultModes; + + CFArrayRef theArray = CGDisplayAvailableModes( m_id ); + + for (CFIndex i = 0; i < CFArrayGetCount(theArray); ++i) { - delete m_priv; - m_priv = 0; + CFDictionaryRef theValue = (CFDictionaryRef) CFArrayGetValueAtIndex( theArray, i ); + + wxVideoMode theMode( + wxCFDictKeyToInt( theValue, kCGDisplayWidth ), + wxCFDictKeyToInt( theValue, kCGDisplayHeight ), + wxCFDictKeyToInt( theValue, kCGDisplayBitsPerPixel ), + wxCFDictKeyToInt( theValue, kCGDisplayRefreshRate )); + + if (theMode.Matches( mode )) + resultModes.Add( theMode ); } + + return resultModes; +} + +wxVideoMode wxDisplayImplMacOSX::GetCurrentMode() const +{ + CFDictionaryRef theValue = CGDisplayCurrentMode( m_id ); + + return wxVideoMode( + wxCFDictKeyToInt( theValue, kCGDisplayWidth ), + wxCFDictKeyToInt( theValue, kCGDisplayHeight ), + wxCFDictKeyToInt( theValue, kCGDisplayBitsPerPixel ), + wxCFDictKeyToInt( theValue, kCGDisplayRefreshRate )); +} + +bool wxDisplayImplMacOSX::ChangeMode( const wxVideoMode& mode ) +{ + // Changing to default mode (wxDefaultVideoMode) doesn't + // work because we don't have access to the system's 'scrn' + // resource which holds the user's mode which the system + // will return to after this app is done + boolean_t bExactMatch; + CFDictionaryRef theCGMode = CGDisplayBestModeForParametersAndRefreshRate( + m_id, + (size_t)mode.bpp, + (size_t)mode.w, + (size_t)mode.h, + (double)mode.refresh, + &bExactMatch ); + + bool bOK = bExactMatch; + + if (bOK) + bOK = CGDisplaySwitchToMode( m_id, theCGMode ) == CGDisplayNoErr; + + return bOK; +} + +// ============================================================================ +// wxDisplay::CreateFactory() +// ============================================================================ + +/* static */ wxDisplayFactory *wxDisplay::CreateFactory() +{ + return new wxDisplayFactoryMacOSX; } #endif // wxUSE_DISPLAY