1/////////////////////////////////////////////////////////////////////////////
2// Name:        src/mac/carbon/display.cpp
3// Purpose:     Mac implementation of wxDisplay class
4// Author:      Ryan Norton & Brian Victor
5// Modified by: Royce Mitchell III, Vadim Zeitlin
6// Created:     06/21/02
7// RCS-ID:      $Id: display.cpp 62911 2009-12-17 13:39:54Z SC $
8// Copyright:   (c) wxWidgets team
9// Licence:     wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
20#include "wx/wxprec.h"
21
22#ifdef __BORLANDC__
23    #pragma hdrstop
24#endif
25
26#if wxUSE_DISPLAY
27
28#include "wx/display.h"
29
30#ifndef WX_PRECOMP
31    #include "wx/dynarray.h"
32    #include "wx/log.h"
33    #include "wx/string.h"
34    #include "wx/gdicmn.h"
35#endif
36
37#ifdef __DARWIN__
38    #include <Carbon/Carbon.h>
39#else
40    #include <Gestalt.h>
41    #include <Displays.h>
42    #include <Quickdraw.h>
43    #include <Video.h>  // for VDSwitchInfoRec
44    #include <FixMath.h>
45    #include <Debugging.h>
46#endif
47
48#include "wx/display_impl.h"
49
50// ----------------------------------------------------------------------------
51// display classes implementation
52// ----------------------------------------------------------------------------
53
54#ifdef __WXMAC_OSX__
55
56class wxDisplayImplMacOSX : public wxDisplayImpl
57{
58public:
59    wxDisplayImplMacOSX(unsigned n, CGDirectDisplayID id)
60        : wxDisplayImpl(n),
61          m_id(id)
62    {
63    }
64
65    virtual wxRect GetGeometry() const;
66    virtual wxRect GetClientArea() const;
67    virtual wxString GetName() const { return wxString(); }
68
69    virtual wxArrayVideoModes GetModes(const wxVideoMode& mode) const;
70    virtual wxVideoMode GetCurrentMode() const;
71    virtual bool ChangeMode(const wxVideoMode& mode);
72
73    virtual bool IsPrimary() const;
74
75private:
76    CGDirectDisplayID m_id;
77
78    DECLARE_NO_COPY_CLASS(wxDisplayImplMacOSX)
79};
80
81class wxDisplayFactoryMacOSX : public wxDisplayFactory
82{
83public:
84    wxDisplayFactoryMacOSX() {}
85
86    virtual wxDisplayImpl *CreateDisplay(unsigned n);
87    virtual unsigned GetCount();
88    virtual int GetFromPoint(const wxPoint& pt);
89
90protected:
91    DECLARE_NO_COPY_CLASS(wxDisplayFactoryMacOSX)
92};
93
94// ============================================================================
95// wxDisplayFactoryMacOSX implementation
96// ============================================================================
97
98// gets all displays that are not mirror displays
99
100static CGDisplayErr wxOSXGetDisplayList(CGDisplayCount maxDisplays,
101                                   CGDirectDisplayID *displays,
102                                   CGDisplayCount *displayCount)
103{
104    CGDisplayErr error = kCGErrorSuccess;
105    CGDisplayCount onlineCount;
106
107    error = CGGetOnlineDisplayList(0,NULL,&onlineCount);
108    if ( error == kCGErrorSuccess )
109    {
110        *displayCount = 0;
111        if ( onlineCount > 0 )
112        {
113            CGDirectDisplayID *onlineDisplays = new CGDirectDisplayID[onlineCount];
114            error = CGGetOnlineDisplayList(onlineCount,onlineDisplays,&onlineCount);
115            if ( error == kCGErrorSuccess )
116            {
117                for ( CGDisplayCount i = 0; i < onlineCount; ++i )
118                {
119                    if ( CGDisplayMirrorsDisplay(onlineDisplays[i]) != kCGNullDirectDisplay )
120                        continue;
121
122                    if ( displays == NULL )
123                        *displayCount += 1;
124                    else
125                    {
126                        if ( *displayCount < maxDisplays )
127                        {
128                            displays[*displayCount] = onlineDisplays[i];
129                            *displayCount += 1;
130                        }
131                    }
132                }
133            }
134            delete[] onlineDisplays;
135        }
136
137    }
138    return error;
139}
140
141unsigned wxDisplayFactoryMacOSX::GetCount()
142{
143    CGDisplayCount count;
144    CGDisplayErr err = wxOSXGetDisplayList(0, NULL, &count);
145
146    wxCHECK_MSG( err == CGDisplayNoErr, 0, wxT("wxOSXGetDisplayList() failed") );
147
148    return count;
149}
150
151int wxDisplayFactoryMacOSX::GetFromPoint(const wxPoint& p)
152{
153    CGPoint thePoint = {(float)p.x, (float)p.y};
154    CGDirectDisplayID theID;
155    CGDisplayCount theCount;
156    CGDisplayErr err = CGGetDisplaysWithPoint(thePoint, 1, &theID, &theCount);
157    wxASSERT(err == CGDisplayNoErr);
158
159    int nWhich = wxNOT_FOUND;
160
161    if (theCount)
162    {
163        theCount = GetCount();
164        CGDirectDisplayID* theIDs = new CGDirectDisplayID[theCount];
165        err = wxOSXGetDisplayList(theCount, theIDs, &theCount);
166        wxASSERT(err == CGDisplayNoErr);
167
168        for (nWhich = 0; nWhich < (int) theCount; ++nWhich)
169        {
170            if (theIDs[nWhich] == theID)
171                break;
172        }
173
174        delete [] theIDs;
175
176        if (nWhich == (int) theCount)
177        {
178            wxFAIL_MSG(wxT("Failed to find display in display list"));
179            nWhich = wxNOT_FOUND;
180        }
181    }
182
183    return nWhich;
184}
185
186wxDisplayImpl *wxDisplayFactoryMacOSX::CreateDisplay(unsigned n)
187{
188    CGDisplayCount theCount = GetCount();
189    CGDirectDisplayID* theIDs = new CGDirectDisplayID[theCount];
190
191    CGDisplayErr err = wxOSXGetDisplayList(theCount, theIDs, &theCount);
192    wxCHECK_MSG( err == CGDisplayNoErr, NULL, wxT("wxOSXGetDisplayList() failed") );
193
194    wxASSERT( n < theCount );
195
196    wxDisplayImplMacOSX *display = new wxDisplayImplMacOSX(n, theIDs[n]);
197
198    delete [] theIDs;
199
200    return display;
201}
202
203// ============================================================================
204// wxDisplayImplMacOSX implementation
205// ============================================================================
206
207bool wxDisplayImplMacOSX::IsPrimary() const
208{
209    return CGDisplayIsMain(m_id);
210}
211
212wxRect wxDisplayImplMacOSX::GetGeometry() const
213{
214    CGRect theRect = CGDisplayBounds(m_id);
215    return wxRect( (int)theRect.origin.x,
216                   (int)theRect.origin.y,
217                   (int)theRect.size.width,
218                   (int)theRect.size.height ); //floats
219}
220
221wxRect wxDisplayImplMacOSX::GetClientArea() const
222{
223    // VZ: I don't know how to get client area for arbitrary display but
224    //     wxGetClientDisplayRect() does work correctly for at least the main
225    //     one (TODO: do it correctly for the other displays too)
226    if ( IsPrimary() )
227        return wxGetClientDisplayRect();
228
229    return wxDisplayImpl::GetClientArea();
230}
231
232static int wxCFDictKeyToInt( CFDictionaryRef desc, CFStringRef key )
233{
234    CFNumberRef value = (CFNumberRef) CFDictionaryGetValue( desc, key );
235    if (value == NULL)
236        return 0;
237
238    int num = 0;
239    CFNumberGetValue( value, kCFNumberIntType, &num );
240
241    return num;
242}
243
244wxArrayVideoModes wxDisplayImplMacOSX::GetModes(const wxVideoMode& mode) const
245{
246    wxArrayVideoModes resultModes;
247
248    CFArrayRef theArray = CGDisplayAvailableModes( m_id );
249
250    for (CFIndex i = 0; i < CFArrayGetCount(theArray); ++i)
251    {
252        CFDictionaryRef theValue = (CFDictionaryRef) CFArrayGetValueAtIndex( theArray, i );
253
254        wxVideoMode theMode(
255            wxCFDictKeyToInt( theValue, kCGDisplayWidth ),
256            wxCFDictKeyToInt( theValue, kCGDisplayHeight ),
257            wxCFDictKeyToInt( theValue, kCGDisplayBitsPerPixel ),
258            wxCFDictKeyToInt( theValue, kCGDisplayRefreshRate ));
259
260        if (theMode.Matches( mode ))
261            resultModes.Add( theMode );
262    }
263
264    return resultModes;
265}
266
267wxVideoMode wxDisplayImplMacOSX::GetCurrentMode() const
268{
269    CFDictionaryRef theValue = CGDisplayCurrentMode( m_id );
270
271    return wxVideoMode(
272        wxCFDictKeyToInt( theValue, kCGDisplayWidth ),
273        wxCFDictKeyToInt( theValue, kCGDisplayHeight ),
274        wxCFDictKeyToInt( theValue, kCGDisplayBitsPerPixel ),
275        wxCFDictKeyToInt( theValue, kCGDisplayRefreshRate ));
276}
277
278bool wxDisplayImplMacOSX::ChangeMode( const wxVideoMode& mode )
279{
280    // Changing to default mode (wxDefaultVideoMode) doesn't
281    // work because we don't have access to the system's 'scrn'
282    // resource which holds the user's mode which the system
283    // will return to after this app is done
284    boolean_t bExactMatch;
285    CFDictionaryRef theCGMode = CGDisplayBestModeForParametersAndRefreshRate(
286        m_id,
287        (size_t)mode.bpp,
288        (size_t)mode.w,
289        (size_t)mode.h,
290        (double)mode.refresh,
291        &bExactMatch );
292
293    bool bOK = bExactMatch;
294
295    if (bOK)
296        bOK = CGDisplaySwitchToMode( m_id, theCGMode ) == CGDisplayNoErr;
297
298    return bOK;
299}
300
301// ============================================================================
302// wxDisplay::CreateFactory()
303// ============================================================================
304
305/* static */ wxDisplayFactory *wxDisplay::CreateFactory()
306{
307    return new wxDisplayFactoryMacOSX;
308}
309
310#else // !__WXMAC_OSX__
311
312class wxDisplayImplMac : public wxDisplayImpl
313{
314public:
315    wxDisplayImplMac(unsigned n, GDHandle hndl)
316        : wxDisplayImpl(n),
317          m_hndl(hndl)
318    {
319    }
320
321    virtual wxRect GetGeometry() const;
322    virtual wxString GetName() const { return wxString(); }
323
324    virtual wxArrayVideoModes GetModes(const wxVideoMode& mode) const;
325    virtual wxVideoMode GetCurrentMode() const;
326    virtual bool ChangeMode(const wxVideoMode& mode);
327
328private:
329    GDHandle m_hndl;
330
331    DECLARE_NO_COPY_CLASS(wxDisplayImplMac)
332};
333
334class wxDisplayFactoryMac : public wxDisplayFactory
335{
336public:
337    wxDisplayFactoryMac();
338
339    virtual wxDisplayImpl *CreateDisplay(unsigned n);
340    virtual unsigned GetCount();
341    virtual int GetFromPoint(const wxPoint& pt);
342
343protected:
344    DECLARE_NO_COPY_CLASS(wxDisplayFactoryMac)
345};
346
347// ============================================================================
348// wxDisplayFactoryMac implementation
349// ============================================================================
350
351unsigned wxDisplayFactoryMac::GetCount()
352{
353    unsigned num = 0;
354    GDHandle hndl = DMGetFirstScreenDevice(true);
355    while(hndl)
356    {
357        num++;
358        hndl = DMGetNextScreenDevice(hndl, true);
359    }
360    return num;
361}
362
363int wxDisplayFactoryMac::GetFromPoint(const wxPoint &p)
364{
365    unsigned num = 0;
366    GDHandle hndl = DMGetFirstScreenDevice(true);
367    while(hndl)
368    {
369        Rect screenrect = (*hndl)->gdRect;
370        if (p.x >= screenrect.left &&
371            p.x <= screenrect.right &&
372            p.y >= screenrect.top &&
373            p.y <= screenrect.bottom)
374        {
375            return num;
376        }
377        num++;
378        hndl = DMGetNextScreenDevice(hndl, true);
379    }
380
381    return wxNOT_FOUND;
382}
383
384wxDisplayImpl *wxDisplayFactoryMac::CreateDisplay(unsigned n)
385{
386    unsigned nOrig = n;
387
388    GDHandle hndl = DMGetFirstScreenDevice(true);
389    while(hndl)
390    {
391        if (n == 0)
392        {
393            return new wxDisplayImplMac(nOrig, hndl);
394        }
395        n--;
396        hndl = DMGetNextScreenDevice(hndl, true);
397    }
398
399    return NULL;
400}
401
402// ============================================================================
403// wxDisplayImplMac implementation
404// ============================================================================
405
406wxRect wxDisplayImplMac::GetGeometry() const
407{
408    Rect screenrect = (*m_hndl)->gdRect;
409    return wxRect(screenrect.left, screenrect.top,
410                  screenrect.right - screenrect.left,
411                  screenrect.bottom - screenrect.top);
412}
413
414struct DMModeIteratorRec
415{
416    wxArrayVideoModes* pModes;
417    const wxVideoMode* pMatchMode;
418};
419
420pascal void DMModeListIteratorProc(
421    void* pData,
422    DMListIndexType nIndex,
423    DMDisplayModeListEntryPtr pInfo)
424{
425    DMModeIteratorRec* pInfoData = (DMModeIteratorRec*) pData;
426
427    // Note that in testing the refresh rate is always 0 on my ibook - RN
428    int refresh = (int) Fix2Long(pInfo->displayModeResolutionInfo->csRefreshRate);
429
430#define pDBI pInfo->displayModeDepthBlockInfo->depthVPBlock[i].depthVPBlock
431
432    for (unsigned long i = 0; i < pInfo->displayModeDepthBlockInfo->depthBlockCount; ++i)
433    {
434        if (wxVideoMode( (int) pInfo->displayModeResolutionInfo->csHorizontalPixels,
435                        (int) pInfo->displayModeResolutionInfo->csVerticalLines,
436                        (int) pDBI->vpPixelSize,
437                        refresh).Matches(*pInfoData->pMatchMode) )
438        {
439            pInfoData->pModes->Add(
440                wxVideoMode(
441                    (int) pInfo->displayModeResolutionInfo->csHorizontalPixels,
442                    (int) pInfo->displayModeResolutionInfo->csVerticalLines,
443                    (int) pDBI->vpPixelSize,
444                    refresh ) );
445        }
446    }
447
448#undef pDBI
449}
450
451struct DMModeInfoRec
452{
453    const wxVideoMode* pMode;
454    VDSwitchInfoRec sMode;
455    bool bMatched;
456};
457
458pascal void DMModeInfoProc(
459    void* pData,
460    DMListIndexType nIndex,
461    DMDisplayModeListEntryPtr pInfo )
462{
463    DMModeInfoRec* pInfoData = (DMModeInfoRec*) pData;
464    Fixed refresh = Long2Fix(pInfoData->pMode->refresh);
465
466#define pDBI pInfo->displayModeDepthBlockInfo->depthVPBlock[i].depthVPBlock
467
468    for (unsigned long i = 0; i < pInfo->displayModeDepthBlockInfo->depthBlockCount; ++i)
469    {
470        if (pInfoData->pMode->w == (int&) pInfo->displayModeResolutionInfo->csHorizontalPixels &&
471            pInfoData->pMode->h == (int&) pInfo->displayModeResolutionInfo->csVerticalLines &&
472            pInfoData->pMode->bpp == (int) pDBI->vpPixelSize &&
473            refresh == pInfo->displayModeResolutionInfo->csRefreshRate)
474        {
475            memcpy(
476                &pInfoData->sMode,
477                pInfo->displayModeDepthBlockInfo->depthVPBlock[i].depthSwitchInfo,
478                sizeof(VDSwitchInfoRec));
479            pInfoData->sMode.csMode = pDBI->vpPixelSize;
480            pInfoData->bMatched = true;
481            break;
482        }
483    }
484
485#undef pDBI
486}
487
488struct DMModeTransRec
489{
490    wxVideoMode Mode;
491    const VDSwitchInfoRec* psMode;
492    bool bMatched;
493};
494
495pascal void DMModeTransProc(
496    void* pData,
497    DMListIndexType nIndex,
498    DMDisplayModeListEntryPtr pInfo)
499{
500    DMModeTransRec* pInfoData = (DMModeTransRec*) pData;
501
502#define pDBI pInfo->displayModeDepthBlockInfo->depthVPBlock[i].depthVPBlock
503
504    for (unsigned long i = 0; i < pInfo->displayModeDepthBlockInfo->depthBlockCount; ++i)
505    {
506        if (pInfoData->psMode->csData == pInfo->displayModeDepthBlockInfo->depthVPBlock[i].depthSwitchInfo->csData)
507        {
508            pInfoData->Mode = wxVideoMode(
509                (int) pInfo->displayModeResolutionInfo->csHorizontalPixels,
510                (int) pInfo->displayModeResolutionInfo->csVerticalLines,
511                (int) pDBI->vpPixelSize,
512                (int) Fix2Long(pInfo->displayModeResolutionInfo->csRefreshRate) );
513            pInfoData->bMatched = true;
514            break;
515        }
516    }
517
518#undef pDBI
519}
520
521wxArrayVideoModes wxDisplayImplMac::GetModes(const wxVideoMode& mode) const
522{
523    wxArrayVideoModes Modes;
524    unsigned long dwDMVer;
525
526    // Check DM version == 2
527    // (for backward compatibility only - 7.5.3+ use 2.0)
528    Gestalt( gestaltDisplayMgrVers, (long*) &dwDMVer );
529    if (dwDMVer >= 0x020000)
530    {
531        DMListIndexType nNumModes;
532        DMListType pModes;
533        DMDisplayModeListIteratorUPP uppMLI;
534        DisplayIDType nDisplayID;
535        OSErr err;
536
537        err = DMGetDisplayIDByGDevice(m_hndl, &nDisplayID, false);
538        verify_noerr( err );
539
540        // Create a new list...
541        err = DMNewDisplayModeList(nDisplayID, NULL, NULL, &nNumModes, &pModes);
542        wxASSERT_MSG( err == noErr, wxT("Could not create a new display mode list") );
543
544        uppMLI = NewDMDisplayModeListIteratorUPP(DMModeListIteratorProc);
545        wxASSERT( uppMLI );
546
547        DMModeIteratorRec sModeInfo;
548        sModeInfo.pModes = &Modes;
549        sModeInfo.pMatchMode = &mode;
550
551        for (DMListIndexType i = 0; i < nNumModes; ++i)
552        {
553            err = DMGetIndexedDisplayModeFromList(pModes, i, NULL, uppMLI, &sModeInfo);
554            verify_noerr( err );
555        }
556
557        DisposeDMDisplayModeListIteratorUPP(uppMLI);
558        err = DMDisposeList(pModes);
559        verify_noerr( err );
560    }
561    else // DM 1.0, 1.2, 1.x
562    {
563        wxLogSysError(
564            wxString::Format(
565                wxT("Display Manager Version %u Not Supported!  Present? %s"),
566                (unsigned int) dwDMVer / 0x10000,
567                (dwDMVer & (1 << gestaltDisplayMgrPresent) ? wxT("Yes") : wxT("No")) ) );
568    }
569
570    return Modes;
571}
572
573wxVideoMode wxDisplayImplMac::GetCurrentMode() const
574{
575    unsigned long dwDMVer;
576    wxVideoMode RetMode;
577
578    // Check DM version == 2
579    // (for backward compatibility only - 7.5.3+ use 2.0)
580    Gestalt( gestaltDisplayMgrVers, (long*) &dwDMVer );
581    if (dwDMVer >= 0x020000)
582    {
583        VDSwitchInfoRec sMode; // Note: csMode member also contains the bit depth
584        OSErr err;
585
586        err = DMGetDisplayMode( m_hndl, &sMode );
587        if (err == noErr)
588        {
589            DMListIndexType nNumModes;
590            DMListType pModes;
591            DMDisplayModeListIteratorUPP uppMLI;
592            DisplayIDType nDisplayID;
593
594            err = DMGetDisplayIDByGDevice(m_hndl, &nDisplayID, false);
595            verify_noerr( err );
596
597            // Create a new list...
598            err = DMNewDisplayModeList(nDisplayID, NULL, NULL, &nNumModes, &pModes);
599            wxASSERT_MSG( err == noErr, wxT("Could not create a new display mode list") );
600
601            uppMLI = NewDMDisplayModeListIteratorUPP(DMModeTransProc);
602            wxASSERT( uppMLI );
603
604            DMModeTransRec sModeInfo;
605            sModeInfo.bMatched = false;
606            sModeInfo.psMode = &sMode;
607            for (DMListIndexType i = 0; i < nNumModes; ++i)
608            {
609                err = DMGetIndexedDisplayModeFromList(pModes, i, NULL, uppMLI, &sModeInfo);
610                verify_noerr( err );
611
612                if ( sModeInfo.bMatched )
613                {
614                    RetMode = sModeInfo.Mode;
615                    break;
616                }
617            }
618
619            DisposeDMDisplayModeListIteratorUPP(uppMLI);
620            err = DMDisposeList(pModes);
621            verify_noerr( err );
622        }
623        else // Can't get current mode?
624        {
625            wxLogSysError(
626                wxString::Format(
627                    wxT("Couldn't obtain current display mode!!!\ndwDMVer:%u"),
628                    (unsigned int) dwDMVer));
629        }
630    }
631    else // DM ver 1
632    {
633        wxLogSysError(
634            wxString::Format(
635                wxT("Display Manager Version %u Not Supported!  Present? %s"),
636                (unsigned int) dwDMVer / 0x10000,
637                (dwDMVer & (1 << gestaltDisplayMgrPresent) ? wxT("Yes") : wxT("No")) ) );
638    }
639
640    return RetMode;
641}
642
643bool wxDisplayImplMac::ChangeMode(const wxVideoMode& mode)
644{
645    unsigned long dwDMVer;
646
647    Gestalt( gestaltDisplayMgrVers, (long*)&dwDMVer );
648    if (GetCount() == 1 || dwDMVer >= 0x020000)
649    {
650        if (mode == wxDefaultVideoMode)
651        {
652             return true;
653
654#if 0
655//#ifndef __DARWIN__
656//            Handle hDisplayState;
657//            if (DMBeginConfigureDisplays(&hDisplayState) != noErr)
658//            {
659//                wxLogSysError(wxT("Could not lock display for display mode changing!"));
660//                return false;
661//            }
662//
663//            wxASSERT( DMUseScreenPrefs(true, hDisplayState) == noErr);
664//            DMEndConfigureDisplays(hDisplayState);
665//            return true;
666//#else
667             // hmmmmm....
668//           return true;
669//#endif
670#endif
671        }
672
673        //0 & NULL for params 2 & 3 of DMSetVideoMode signal it to use defaults (current mode)
674        //DM 2.0+ doesn't use params 2 & 3 of DMSetDisplayMode
675        //so we have to use this icky structure
676        VDSwitchInfoRec sMode;
677        memset( &sMode, 0, sizeof(VDSwitchInfoRec) );
678
679        DMListIndexType nNumModes;
680        DMListType pModes;
681        DMDisplayModeListIteratorUPP uppMLI;
682        DisplayIDType nDisplayID;
683        OSErr err;
684
685        err = DMGetDisplayIDByGDevice(m_hndl, &nDisplayID, false);
686        verify_noerr( err );
687
688        // Create a new list...
689        err = DMNewDisplayModeList(nDisplayID, NULL, NULL, &nNumModes, &pModes);
690        wxASSERT_MSG(err == noErr, wxT("Could not create a new display mode list") );
691
692        uppMLI = NewDMDisplayModeListIteratorUPP(DMModeInfoProc);
693        wxASSERT(uppMLI);
694
695        DMModeInfoRec sModeInfo;
696        sModeInfo.bMatched = false;
697        sModeInfo.pMode = &mode;
698        unsigned int i;
699
700        for (i = 0; i < nNumModes; ++i)
701        {
702            err = DMGetIndexedDisplayModeFromList(pModes, i, NULL, uppMLI, &sModeInfo);
703            verify_noerr( err );
704
705            if (sModeInfo.bMatched)
706            {
707                sMode = sModeInfo.sMode;
708                break;
709            }
710        }
711
712        if (i == nNumModes)
713            return false;
714
715        DisposeDMDisplayModeListIteratorUPP(uppMLI);
716
717        err = DMDisposeList(pModes);
718        verify_noerr( err );
719
720        // For the really paranoid -
721        //     unsigned long flags;
722        //      Boolean bok;
723        //     wxASSERT(noErr == DMCheckDisplayMode(m_hndl, sMode.csData,
724        //                                          sMode.csMode, &flags, NULL, &bok));
725        //     wxASSERT(bok);
726
727        Handle hDisplayState;
728        if (DMBeginConfigureDisplays(&hDisplayState) != noErr)
729        {
730            wxLogSysError(wxT("Could not lock display for display mode changing!"));
731
732            return false;
733        }
734
735        unsigned long dwBPP = (unsigned long) mode.bpp;
736        err = DMSetDisplayMode(
737            m_hndl, sMode.csData,
738            (unsigned long*) &(dwBPP),
739            NULL, //(unsigned long) &sMode
740            hDisplayState );
741
742        if (err != noErr)
743        {
744            DMEndConfigureDisplays(hDisplayState);
745            wxLogError(wxT("Could not set the display mode"));
746
747            return false;
748        }
749
750        DMEndConfigureDisplays(hDisplayState);
751    }
752    else  // DM 1.0, 1.2, 1.x
753    {
754        wxLogSysError(
755            wxString::Format(
756                wxT("Monitor gravitation not supported yet.  dwDMVer:%u"),
757                (unsigned int) dwDMVer));
758
759        return false;
760    }
761
762    return true;
763}
764
765// ============================================================================
766// wxDisplay::CreateFactory()
767// ============================================================================
768
769/* static */ wxDisplayFactory *wxDisplay::CreateFactory()
770{
771    return new wxDisplayFactoryMac;
772}
773
774#endif // !OSX
775
776#endif // wxUSE_DISPLAY
777