X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/cd17aeff896462de174b440edc58a3e34b69cfa9..5c7b506103cfc078a821860766e31c47d595e07f:/src/mac/carbon/display.cpp diff --git a/src/mac/carbon/display.cpp b/src/mac/carbon/display.cpp index 7b6eb4ef42..99c51f04ce 100644 --- a/src/mac/carbon/display.cpp +++ b/src/mac/carbon/display.cpp @@ -1,14 +1,22 @@ ///////////////////////////////////////////////////////////////////////////// -// Name: display.cpp +// Name: src/mac/carbon/display.cpp // Purpose: Mac implementation of wxDisplay class // Author: Ryan Norton & Brian Victor -// Modified by: Royce Mitchell III +// Modified by: Royce Mitchell III, Vadim Zeitlin // Created: 06/21/02 // RCS-ID: $Id$ // Copyright: (c) wxWidgets team // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// +// ============================================================================ +// declarations +// ============================================================================ + +// ---------------------------------------------------------------------------- +// headers +// ---------------------------------------------------------------------------- + #include "wx/wxprec.h" #ifdef __BORLANDC__ @@ -17,50 +25,77 @@ #if wxUSE_DISPLAY +#include "wx/display.h" + #ifndef WX_PRECOMP - #include "wx/dynarray.h" - #include "wx/log.h" - #include "wx/msgdlg.h" + #include "wx/dynarray.h" + #include "wx/log.h" + #include "wx/string.h" + #include "wx/gdicmn.h" #endif -#ifdef __DARWIN__ - #include -#else - #include - #include - #include - #include // for VDSwitchInfoRec - #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 // ---------------------------------------------------------------------------- -#ifdef __WXMAC_OSX__ - -class wxDisplayMacPriv +class wxDisplayImplMacOSX : public wxDisplayImpl { public: + 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) +}; + +class wxDisplayFactoryMacOSX : public wxDisplayFactory +{ +public: + wxDisplayFactoryMacOSX() {} + + virtual wxDisplayImpl *CreateDisplay(unsigned n); + virtual unsigned GetCount(); + virtual int GetFromPoint(const wxPoint& pt); + +protected: + DECLARE_NO_COPY_CLASS(wxDisplayFactoryMacOSX) }; -size_t wxDisplayBase::GetCount() +// ============================================================================ +// wxDisplayFactoryMacOSX implementation +// ============================================================================ + +unsigned wxDisplayFactoryMacOSX::GetCount() { CGDisplayCount count; - CGDisplayErr err = CGGetActiveDisplayList(0, NULL, &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) { CGPoint thePoint = {(float)p.x, (float)p.y}; CGDirectDisplayID theID; @@ -68,7 +103,7 @@ int wxDisplayBase::GetFromPoint(const wxPoint &p) CGDisplayErr err = CGGetDisplaysWithPoint(thePoint, 1, &theID, &theCount); wxASSERT(err == CGDisplayNoErr); - int nWhich = -1; + int nWhich = wxNOT_FOUND; if (theCount) { @@ -88,48 +123,55 @@ int wxDisplayBase::GetFromPoint(const wxPoint &p) if (nWhich == (int) theCount) { wxFAIL_MSG(wxT("Failed to find display in display list")); - nWhich = -1; + nWhich = wxNOT_FOUND; } } return nWhich; } -wxDisplay::wxDisplay(size_t index) - : wxDisplayBase( index ) , - m_priv( new wxDisplayMacPriv() ) +wxDisplayImpl *wxDisplayFactoryMacOSX::CreateDisplay(unsigned n) { CGDisplayCount theCount = GetCount(); CGDirectDisplayID* theIDs = new CGDirectDisplayID[theCount]; - CGDisplayErr err = CGGetActiveDisplayList(theCount, theIDs, &theCount); +#ifdef __WXDEBUG__ + CGDisplayErr err = +#endif + CGGetActiveDisplayList(theCount, theIDs, &theCount); wxASSERT( err == CGDisplayNoErr ); - wxASSERT( index < theCount ); + wxASSERT( n < theCount ); - m_priv->m_id = theIDs[index]; + wxDisplayImplMacOSX *display = new wxDisplayImplMacOSX(n, theIDs[n]); delete [] theIDs; + + return display; } -wxRect wxDisplay::GetGeometry() const +// ============================================================================ +// wxDisplayImplMacOSX implementation +// ============================================================================ + +wxRect wxDisplayImplMacOSX::GetGeometry() const { - CGRect theRect = CGDisplayBounds(m_priv->m_id); + 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 { - return (int) CGDisplayBitsPerPixel( m_priv->m_id ); //size_t -} + // 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(); -wxString wxDisplay::GetName() const -{ - // Macs don't name their displays... - return wxEmptyString; + return wxDisplayImpl::GetClientArea(); } static int wxCFDictKeyToInt( CFDictionaryRef desc, CFStringRef key ) @@ -144,12 +186,11 @@ static int wxCFDictKeyToInt( CFDictionaryRef desc, CFStringRef key ) return num; } -wxArrayVideoModes - wxDisplay::GetModes(const wxVideoMode& mode) const +wxArrayVideoModes wxDisplayImplMacOSX::GetModes(const wxVideoMode& mode) const { wxArrayVideoModes resultModes; - CFArrayRef theArray = CGDisplayAvailableModes( m_priv->m_id ); + CFArrayRef theArray = CGDisplayAvailableModes( m_id ); for (CFIndex i = 0; i < CFArrayGetCount(theArray); ++i) { @@ -168,9 +209,9 @@ wxArrayVideoModes return resultModes; } -wxVideoMode wxDisplay::GetCurrentMode() const +wxVideoMode wxDisplayImplMacOSX::GetCurrentMode() const { - CFDictionaryRef theValue = CGDisplayCurrentMode( m_priv->m_id ); + CFDictionaryRef theValue = CGDisplayCurrentMode( m_id ); return wxVideoMode( wxCFDictKeyToInt( theValue, kCGDisplayWidth ), @@ -179,7 +220,7 @@ wxVideoMode wxDisplay::GetCurrentMode() const wxCFDictKeyToInt( theValue, kCGDisplayRefreshRate )); } -bool wxDisplay::ChangeMode( const wxVideoMode& mode ) +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' @@ -187,7 +228,7 @@ bool wxDisplay::ChangeMode( const wxVideoMode& mode ) // will return to after this app is done boolean_t bExactMatch; CFDictionaryRef theCGMode = CGDisplayBestModeForParametersAndRefreshRate( - m_priv->m_id, + m_id, (size_t)mode.bpp, (size_t)mode.w, (size_t)mode.h, @@ -197,478 +238,18 @@ bool wxDisplay::ChangeMode( const wxVideoMode& mode ) bool bOK = bExactMatch; if (bOK) - bOK = CGDisplaySwitchToMode( m_priv->m_id, theCGMode ) == CGDisplayNoErr; + bOK = CGDisplaySwitchToMode( m_id, theCGMode ) == CGDisplayNoErr; return bOK; } -wxDisplay::~wxDisplay() -{ - if ( m_priv ) - { - delete m_priv; - m_priv = 0; - } -} - -#else +// ============================================================================ +// wxDisplay::CreateFactory() +// ============================================================================ -class wxDisplayMacPriv +/* static */ wxDisplayFactory *wxDisplay::CreateFactory() { -public: - GDHandle m_hndl; -}; - -size_t wxDisplayBase::GetCount() -{ - GDHandle hndl; - size_t num = 0; - hndl = DMGetFirstScreenDevice(true); - while (hndl) - { - num++; - hndl = DMGetNextScreenDevice(hndl, true); - } - - return num; + return new wxDisplayFactoryMacOSX; } -int wxDisplayBase::GetFromPoint(const wxPoint &p) -{ - GDHandle hndl; - size_t num = 0; - hndl = DMGetFirstScreenDevice(true); - - while (hndl) - { - Rect screenrect = (*hndl)->gdRect; - if (p.x >= screenrect.left && - p.x <= screenrect.right && - p.y >= screenrect.top && - p.y <= screenrect.bottom) - { - return num; - } - - 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) - m_priv->m_hndl = hndl; - - index--; - hndl = DMGetNextScreenDevice(hndl, true); - } -} - -wxRect wxDisplay::GetGeometry() const -{ - if ((m_priv == NULL) || (m_priv->m_hndl == NULL)) - 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 ); -} - -int wxDisplay::GetDepth() const -{ - if ((m_priv == NULL) || (m_priv->m_hndl == NULL)) - return 0; - - // This cryptic looking code is based on Apple's sample code: - // http://developer.apple.com/samplecode/Sample_Code/Graphics_2D/GDevVideo/Gen.cp.htm - - // RN - according to the docs - // gdPMap is a bitmap-type representation of the GDevice, and all - // 0x0000FFFF does is get the lower 16 bits of pixelSize. However, - // since pixelSize is only 16 bits (a short)... - return ((*(*(m_priv->m_hndl))->gdPMap)->pixelSize) & 0x0000FFFF; -} - -wxString wxDisplay::GetName() const -{ - // Macs don't name their displays... - return wxEmptyString; -} - -struct DMModeIteratorRec -{ - wxArrayVideoModes* pModes; - const wxVideoMode* pMatchMode; -}; - -pascal void DMModeListIteratorProc( - void* pData, - DMListIndexType nIndex, - DMDisplayModeListEntryPtr pInfo) -{ - DMModeIteratorRec* pInfoData = (DMModeIteratorRec*) pData; - - // Note that in testing the refresh rate is always 0 on my ibook - RN - int refresh = (int) Fix2Long(pInfo->displayModeResolutionInfo->csRefreshRate); - -#define pDBI pInfo->displayModeDepthBlockInfo->depthVPBlock[i].depthVPBlock - - for (unsigned long i = 0; i < pInfo->displayModeDepthBlockInfo->depthBlockCount; ++i) - { - if (wxVideoMode( (int) pInfo->displayModeResolutionInfo->csHorizontalPixels, - (int) pInfo->displayModeResolutionInfo->csVerticalLines, - (int) pDBI->vpPixelSize, - refresh).Matches(*pInfoData->pMatchMode) ) - { - pInfoData->pModes->Add( - wxVideoMode( - (int) pInfo->displayModeResolutionInfo->csHorizontalPixels, - (int) pInfo->displayModeResolutionInfo->csVerticalLines, - (int) pDBI->vpPixelSize, - refresh ) ); - } - } - -#undef pDBI -} - -struct DMModeInfoRec -{ - const wxVideoMode* pMode; - VDSwitchInfoRec sMode; - bool bMatched; -}; - -pascal void DMModeInfoProc( - void* pData, - DMListIndexType nIndex, - DMDisplayModeListEntryPtr pInfo ) -{ - DMModeInfoRec* pInfoData = (DMModeInfoRec*) pData; - Fixed refresh = Long2Fix(pInfoData->pMode->refresh); - -#define pDBI pInfo->displayModeDepthBlockInfo->depthVPBlock[i].depthVPBlock - - for (unsigned long i = 0; i < pInfo->displayModeDepthBlockInfo->depthBlockCount; ++i) - { - if (pInfoData->pMode->w == (int&) pInfo->displayModeResolutionInfo->csHorizontalPixels && - pInfoData->pMode->h == (int&) pInfo->displayModeResolutionInfo->csVerticalLines && - pInfoData->pMode->bpp == (int) pDBI->vpPixelSize && - refresh == pInfo->displayModeResolutionInfo->csRefreshRate) - { - memcpy( - &pInfoData->sMode, - pInfo->displayModeDepthBlockInfo->depthVPBlock[i].depthSwitchInfo, - sizeof(VDSwitchInfoRec)); - pInfoData->sMode.csMode = pDBI->vpPixelSize; - pInfoData->bMatched = true; - break; - } - } - -#undef pDBI -} - -struct DMModeTransRec -{ - wxVideoMode Mode; - const VDSwitchInfoRec* psMode; - bool bMatched; -}; - -pascal void DMModeTransProc( - void* pData, - DMListIndexType nIndex, - DMDisplayModeListEntryPtr pInfo) -{ - DMModeTransRec* pInfoData = (DMModeTransRec*) pData; - -#define pDBI pInfo->displayModeDepthBlockInfo->depthVPBlock[i].depthVPBlock - - for (unsigned long i = 0; i < pInfo->displayModeDepthBlockInfo->depthBlockCount; ++i) - { - if (pInfoData->psMode->csData == pInfo->displayModeDepthBlockInfo->depthVPBlock[i].depthSwitchInfo->csData) - { - pInfoData->Mode = wxVideoMode( - (int) pInfo->displayModeResolutionInfo->csHorizontalPixels, - (int) pInfo->displayModeResolutionInfo->csVerticalLines, - (int) pDBI->vpPixelSize, - (int) Fix2Long(pInfo->displayModeResolutionInfo->csRefreshRate) ); - pInfoData->bMatched = true; - break; - } - } - -#undef pDBI -} - -wxArrayVideoModes - wxDisplay::GetModes(const wxVideoMode& mode) const -{ - wxArrayVideoModes Modes; - unsigned long dwDMVer; - - // Check DM version == 2 - // (for backward compatibility only - 7.5.3+ use 2.0) - Gestalt( gestaltDisplayMgrVers, (long*) &dwDMVer ); - if (dwDMVer >= 0x020000) - { - DMListIndexType nNumModes; - DMListType pModes; - DMDisplayModeListIteratorUPP uppMLI; - DisplayIDType nDisplayID; - OSErr err; - - err = DMGetDisplayIDByGDevice(m_priv->m_hndl, &nDisplayID, false); - verify_noerr( err ); - - // Create a new list... - err = DMNewDisplayModeList(nDisplayID, NULL, NULL, &nNumModes, &pModes); - wxASSERT_MSG( err == noErr, wxT("Could not create a new display mode list") ); - - uppMLI = NewDMDisplayModeListIteratorUPP(DMModeListIteratorProc); - wxASSERT( uppMLI ); - - DMModeIteratorRec sModeInfo; - sModeInfo.pModes = &Modes; - sModeInfo.pMatchMode = &mode; - - for (DMListIndexType i = 0; i < nNumModes; ++i) - { - err = DMGetIndexedDisplayModeFromList(pModes, i, NULL, uppMLI, &sModeInfo); - verify_noerr( err ); - } - - DisposeDMDisplayModeListIteratorUPP(uppMLI); - err = DMDisposeList(pModes); - verify_noerr( err ); - } - else // DM 1.0, 1.2, 1.x - { - wxLogSysError( - wxString::Format( - wxT("Display Manager Version %u Not Supported! Present? %s"), - (unsigned int) dwDMVer / 0x10000, - (dwDMVer & (1 << gestaltDisplayMgrPresent) ? wxT("Yes") : wxT("No")) ) ); - } - - return Modes; -} - -wxVideoMode wxDisplay::GetCurrentMode() const -{ - unsigned long dwDMVer; - wxVideoMode RetMode; - - // Check DM version == 2 - // (for backward compatibility only - 7.5.3+ use 2.0) - Gestalt( gestaltDisplayMgrVers, (long*) &dwDMVer ); - if (dwDMVer >= 0x020000) - { - VDSwitchInfoRec sMode; // Note: csMode member also contains the bit depth - OSErr err; - - err = DMGetDisplayMode( m_priv->m_hndl, &sMode ); - if (err == noErr) - { - DMListIndexType nNumModes; - DMListType pModes; - DMDisplayModeListIteratorUPP uppMLI; - DisplayIDType nDisplayID; - - err = DMGetDisplayIDByGDevice(m_priv->m_hndl, &nDisplayID, false); - verify_noerr( err ); - - // Create a new list... - err = DMNewDisplayModeList(nDisplayID, NULL, NULL, &nNumModes, &pModes); - wxASSERT_MSG( err == noErr, wxT("Could not create a new display mode list") ); - - uppMLI = NewDMDisplayModeListIteratorUPP(DMModeTransProc); - wxASSERT( uppMLI ); - - DMModeTransRec sModeInfo; - sModeInfo.bMatched = false; - sModeInfo.psMode = &sMode; - for (DMListIndexType i = 0; i < nNumModes; ++i) - { - err = DMGetIndexedDisplayModeFromList(pModes, i, NULL, uppMLI, &sModeInfo); - verify_noerr( err ); - - if ( sModeInfo.bMatched ) - { - RetMode = sModeInfo.Mode; - break; - } - } - - DisposeDMDisplayModeListIteratorUPP(uppMLI); - err = DMDisposeList(pModes); - verify_noerr( err ); - } - else // Can't get current mode? - { - wxLogSysError( - wxString::Format( - wxT("Couldn't obtain current display mode!!!\ndwDMVer:%u"), - (unsigned int) dwDMVer)); - } - } - else // DM ver 1 - { - wxLogSysError( - wxString::Format( - wxT("Display Manager Version %u Not Supported! Present? %s"), - (unsigned int) dwDMVer / 0x10000, - (dwDMVer & (1 << gestaltDisplayMgrPresent) ? wxT("Yes") : wxT("No")) ) ); - } - - return RetMode; -} - -bool wxDisplay::ChangeMode(const wxVideoMode& mode) -{ - unsigned long dwDMVer; - - Gestalt( gestaltDisplayMgrVers, (long*)&dwDMVer ); - if (GetCount() == 1 || dwDMVer >= 0x020000) - { - if (mode == wxDefaultVideoMode) - { - return true; - -#if 0 -//#ifndef __DARWIN__ -// Handle hDisplayState; -// if (DMBeginConfigureDisplays(&hDisplayState) != noErr) -// { -// wxLogSysError(wxT("Could not lock display for display mode changing!")); -// return false; -// } -// -// wxASSERT( DMUseScreenPrefs(true, hDisplayState) == noErr); -// DMEndConfigureDisplays(hDisplayState); -// return true; -//#else - // hmmmmm.... -// return true; -//#endif -#endif - } - - //0 & NULL for params 2 & 3 of DMSetVideoMode signal it to use defaults (current mode) - //DM 2.0+ doesn't use params 2 & 3 of DMSetDisplayMode - //so we have to use this icky structure - VDSwitchInfoRec sMode; - memset( &sMode, 0, sizeof(VDSwitchInfoRec) ); - - DMListIndexType nNumModes; - DMListType pModes; - DMDisplayModeListIteratorUPP uppMLI; - DisplayIDType nDisplayID; - OSErr err; - - err = DMGetDisplayIDByGDevice(m_priv->m_hndl, &nDisplayID, false); - verify_noerr( err ); - - // Create a new list... - err = DMNewDisplayModeList(nDisplayID, NULL, NULL, &nNumModes, &pModes); - wxASSERT_MSG(err == noErr, wxT("Could not create a new display mode list") ); - - uppMLI = NewDMDisplayModeListIteratorUPP(DMModeInfoProc); - wxASSERT(uppMLI); - - DMModeInfoRec sModeInfo; - sModeInfo.bMatched = false; - sModeInfo.pMode = &mode; - unsigned int i; - - for (i = 0; i < nNumModes; ++i) - { - err = DMGetIndexedDisplayModeFromList(pModes, i, NULL, uppMLI, &sModeInfo); - verify_noerr( err ); - - if (sModeInfo.bMatched) - { - sMode = sModeInfo.sMode; - break; - } - } - - if (i == nNumModes) - return false; - - DisposeDMDisplayModeListIteratorUPP(uppMLI); - - err = DMDisposeList(pModes); - verify_noerr( err ); - - // For the really paranoid - - // unsigned long flags; - // Boolean bok; - // wxASSERT(noErr == DMCheckDisplayMode(m_priv->m_hndl, sMode.csData, - // sMode.csMode, &flags, NULL, &bok)); - // wxASSERT(bok); - - Handle hDisplayState; - if (DMBeginConfigureDisplays(&hDisplayState) != noErr) - { - wxLogSysError(wxT("Could not lock display for display mode changing!")); - - return false; - } - - unsigned long dwBPP = (unsigned long) mode.bpp; - err = DMSetDisplayMode( - m_priv->m_hndl, sMode.csData, - (unsigned long*) &(dwBPP), - NULL, //(unsigned long) &sMode - hDisplayState ); - - if (err != noErr) - { - DMEndConfigureDisplays(hDisplayState); - wxMessageBox( wxString::Format(wxT("Could not set the display mode")) ); - - return false; - } - - DMEndConfigureDisplays(hDisplayState); - } - else // DM 1.0, 1.2, 1.x - { - wxLogSysError( - wxString::Format( - wxT("Monitor gravitation not supported yet. dwDMVer:%u"), - (unsigned int) dwDMVer)); - - return false; - } - - return true; -} - -wxDisplay::~wxDisplay() -{ - if ( m_priv ) - { - delete m_priv; - m_priv = 0; - } -} - -#endif // !OSX - #endif // wxUSE_DISPLAY