1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/mac/classic/display.cpp
3 // Purpose: Mac implementation of wxDisplay class
4 // Author: Brian Victor
5 // Modified by: Royce Mitchell III & Ryan Norton, Vadim Zeitlin
8 // Copyright: (c) wxWidgets team
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
14 // ============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
20 // For compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
29 #include "wx/display.h"
32 #include "wx/dynarray.h"
34 #include "wx/string.h"
35 #include "wx/gdicmn.h"
39 #include <Carbon/Carbon.h>
43 #include <Quickdraw.h>
44 #include <Video.h> //for VDSwitchInfoRec
48 #include "wx/display_impl.h"
50 // ----------------------------------------------------------------------------
51 // display implementation classes
52 // ----------------------------------------------------------------------------
54 class wxDisplayImplMac
: public wxDisplayImpl
57 wxDisplayImplMac(size_t n
, GDHandle hndl
)
63 virtual wxRect
GetGeometry() const;
64 virtual wxString
GetName() const { return wxString(); }
66 virtual wxArrayVideoModes
GetModes(const wxVideoMode
& mode
) const;
67 virtual wxVideoMode
GetCurrentMode() const;
68 virtual bool ChangeMode(const wxVideoMode
& mode
);
73 DECLARE_NO_COPY_CLASS(wxDisplayImplMac
)
76 class wxDisplayFactoryMac
: public wxDisplayFactory
79 wxDisplayFactoryMac();
81 virtual wxDisplayImpl
*CreateDisplay(size_t n
);
82 virtual size_t GetCount();
83 virtual int GetFromPoint(const wxPoint
& pt
);
86 DECLARE_NO_COPY_CLASS(wxDisplayFactoryMac
)
89 // ============================================================================
90 // wxDisplayFactoryMac implementation
91 // ============================================================================
93 size_t wxDisplayFactoryMac::GetCount()
96 GDHandle hndl
= DMGetFirstScreenDevice(true);
100 hndl
= DMGetNextScreenDevice(hndl
, true);
105 int wxDisplayFactoryMac::GetFromPoint(const wxPoint
&p
)
108 GDHandle hndl
= DMGetFirstScreenDevice(true);
111 Rect screenrect
= (*hndl
)->gdRect
;
112 if (p
.x
>= screenrect
.left
&&
113 p
.x
<= screenrect
.right
&&
114 p
.y
>= screenrect
.top
&&
115 p
.y
<= screenrect
.bottom
)
120 hndl
= DMGetNextScreenDevice(hndl
, true);
126 wxDisplayImpl
*wxDisplayFactoryMac::CreateDisplay(size_t n
)
130 GDHandle hndl
= DMGetFirstScreenDevice(true);
135 return new wxDisplayImplMac(nOrig
, hndl
);
138 hndl
= DMGetNextScreenDevice(hndl
, true);
144 // ============================================================================
145 // wxDisplayImplMac implementation
146 // ============================================================================
148 wxRect
wxDisplayImplMac::GetGeometry() const
150 Rect screenrect
= (*m_hndl
)->gdRect
;
151 return wxRect(screenrect
.left
, screenrect
.top
,
152 screenrect
.right
- screenrect
.left
,
153 screenrect
.bottom
- screenrect
.top
);
156 struct DMModeIteratorRec
158 wxArrayVideoModes
* pModes
;
159 const wxVideoMode
* pMatchMode
;
162 pascal void DMModeListIteratorProc ( void* pData
,
163 DMListIndexType nIndex
,
164 DMDisplayModeListEntryPtr pInfo
)
166 DMModeIteratorRec
* pInfoData
= (DMModeIteratorRec
*) pData
;
168 //Note that in testing the refresh rate is always 0 on my ibook - RN
169 int refresh
= (int) Fix2Long(pInfo
->displayModeResolutionInfo
->csRefreshRate
);
171 for(unsigned long i
= 0; i
< pInfo
->displayModeDepthBlockInfo
->depthBlockCount
; ++i
)
173 #define pDBI pInfo->displayModeDepthBlockInfo->depthVPBlock[i].depthVPBlock
175 if (wxVideoMode((int) pInfo
->displayModeResolutionInfo
->csHorizontalPixels
,
176 (int) pInfo
->displayModeResolutionInfo
->csVerticalLines
,
177 (int) pDBI
->vpPixelSize
,
178 refresh
).Matches(*pInfoData
->pMatchMode
) )
180 pInfoData
->pModes
->Add(wxVideoMode((int) pInfo
->displayModeResolutionInfo
->csHorizontalPixels
,
181 (int) pInfo
->displayModeResolutionInfo
->csVerticalLines
,
182 (int) pDBI
->vpPixelSize
,
191 const wxVideoMode
* pMode
;
192 VDSwitchInfoRec sMode
;
196 pascal void DMModeInfoProc ( void* pData
,
197 DMListIndexType nIndex
,
198 DMDisplayModeListEntryPtr pInfo
)
200 DMModeInfoRec
* pInfoData
= (DMModeInfoRec
*) pData
;
201 Fixed refresh
= Long2Fix(pInfoData
->pMode
->refresh
);
203 for(unsigned long i
= 0; i
< pInfo
->displayModeDepthBlockInfo
->depthBlockCount
; ++i
)
205 #define pDBI pInfo->displayModeDepthBlockInfo->depthVPBlock[i].depthVPBlock
206 if (pInfoData
->pMode
->w
== (int&) pInfo
->displayModeResolutionInfo
->csHorizontalPixels
&&
207 pInfoData
->pMode
->h
== (int&) pInfo
->displayModeResolutionInfo
->csVerticalLines
&&
208 pInfoData
->pMode
->bpp
== (int) pDBI
->vpPixelSize
&&
209 refresh
== pInfo
->displayModeResolutionInfo
->csRefreshRate
)
211 memcpy(&pInfoData
->sMode
, pInfo
->displayModeDepthBlockInfo
->depthVPBlock
[i
].depthSwitchInfo
,
212 sizeof(VDSwitchInfoRec
));
213 pInfoData
->sMode
.csMode
= pDBI
->vpPixelSize
;
214 pInfoData
->bMatched
= true;
221 struct DMModeTransRec
224 const VDSwitchInfoRec
* psMode
;
228 pascal void DMModeTransProc ( void* pData
,
229 DMListIndexType nIndex
,
230 DMDisplayModeListEntryPtr pInfo
)
232 DMModeTransRec
* pInfoData
= (DMModeTransRec
*) pData
;
234 for(unsigned long i
= 0; i
< pInfo
->displayModeDepthBlockInfo
->depthBlockCount
; ++i
)
236 #define pDBI pInfo->displayModeDepthBlockInfo->depthVPBlock[i].depthVPBlock
237 if (pInfoData
->psMode
->csData
== pInfo
->displayModeDepthBlockInfo
->depthVPBlock
[i
].depthSwitchInfo
->csData
)
239 pInfoData
->Mode
= wxVideoMode((int) pInfo
->displayModeResolutionInfo
->csHorizontalPixels
,
240 (int) pInfo
->displayModeResolutionInfo
->csVerticalLines
,
241 (int) pDBI
->vpPixelSize
,
242 (int) Fix2Long(pInfo
->displayModeResolutionInfo
->csRefreshRate
) );
243 pInfoData
->bMatched
= true;
250 wxArrayVideoModes
wxDisplayImplMac::GetModes(const wxVideoMode
& mode
) const
252 wxArrayVideoModes Modes
;
254 unsigned long dwDMVer
;
255 Gestalt(gestaltDisplayMgrVers
, (long*) &dwDMVer
);
257 //Check DM version (for backward compatibility only - 7.5.3+ use 2.0)
258 if (dwDMVer
>= 0x020000) //version 2?
261 DMListIndexType nNumModes
;
263 DMDisplayModeListIteratorUPP uppMLI
;
264 DisplayIDType nDisplayID
;
266 wxASSERT(DMGetDisplayIDByGDevice(m_hndl
, &nDisplayID
, false) == noErr
);
267 //Create a new list...
268 wxASSERT_MSG(DMNewDisplayModeList(nDisplayID
, NULL
, NULL
, &nNumModes
, &pModes
) == noErr
, wxT("Could not create a new display mode list") );
270 uppMLI
= NewDMDisplayModeListIteratorUPP(DMModeListIteratorProc
);
273 DMModeIteratorRec sModeInfo
;
274 sModeInfo
.pModes
= &Modes
;
275 sModeInfo
.pMatchMode
= &mode
;
276 for (DMListIndexType i
= 0; i
< nNumModes
; ++i
)
278 wxASSERT(DMGetIndexedDisplayModeFromList(pModes
, i
, NULL
,
279 uppMLI
, &sModeInfo
) == noErr
);
281 DisposeDMDisplayModeListIteratorUPP(uppMLI
);
282 wxASSERT(DMDisposeList(pModes
) == noErr
);
284 else //DM 1.0, 1.2, 1.x
286 wxLogSysError(wxString::Format(wxT("Display Manager Version %u Not Supported! Present? %s"),
287 (unsigned int) dwDMVer
/ 0x10000,
288 (dwDMVer
& (1 << gestaltDisplayMgrPresent
) ? wxT("Yes") : wxT("No")) )
295 wxVideoMode
wxDisplayImplMac::GetCurrentMode() const
297 unsigned long dwDMVer
;
300 Gestalt(gestaltDisplayMgrVers
, (long*) &dwDMVer
);
301 //Check DM version (for backward compatibility only - 7.5.3+ use 2.0)
302 if (dwDMVer
>= 0x020000) //version 2?
304 VDSwitchInfoRec sMode
; //Note - csMode member also contains the bit depth
305 if (DMGetDisplayMode(m_hndl
, &sMode
) == noErr
)
307 DMListIndexType nNumModes
;
309 DMDisplayModeListIteratorUPP uppMLI
;
310 DisplayIDType nDisplayID
;
312 wxASSERT(DMGetDisplayIDByGDevice(m_hndl
, &nDisplayID
, false) == noErr
);
313 //Create a new list...
314 wxASSERT_MSG(DMNewDisplayModeList(nDisplayID
, NULL
, NULL
, &nNumModes
, &pModes
) == noErr
,
315 wxT("Could not create a new display mode list") );
317 uppMLI
= NewDMDisplayModeListIteratorUPP(DMModeTransProc
);
320 DMModeTransRec sModeInfo
;
321 sModeInfo
.bMatched
= false;
322 sModeInfo
.psMode
= &sMode
;
323 for (DMListIndexType i
= 0; i
< nNumModes
; ++i
)
325 wxASSERT(DMGetIndexedDisplayModeFromList(pModes
, i
, NULL
,
326 uppMLI
, &sModeInfo
) == noErr
);
328 if ( sModeInfo
.bMatched
== true )
330 RetMode
= sModeInfo
.Mode
;
335 DisposeDMDisplayModeListIteratorUPP(uppMLI
);
336 wxASSERT(DMDisposeList(pModes
) == noErr
);
338 else //Can't get current mode?
340 wxLogSysError(wxString::Format(wxT("Couldn't obtain current display mode!!!\ndwDMVer:%u"),
341 (unsigned int) dwDMVer
));
346 wxLogSysError(wxString::Format(wxT("Display Manager Version %u Not Supported! Present? %s"),
347 (unsigned int) dwDMVer
/ 0x10000,
348 (dwDMVer
& (1 << gestaltDisplayMgrPresent
) ? wxT("Yes") : wxT("No")) )
355 bool wxDisplayImplMac::ChangeMode(const wxVideoMode
& mode
)
357 unsigned long dwDMVer
;
358 Gestalt(gestaltDisplayMgrVers
, (long*)&dwDMVer
);
359 if (GetCount() == 1 || dwDMVer
>= 0x020000)
361 if (mode
== wxDefaultVideoMode
)
364 // Handle hDisplayState;
365 // if (DMBeginConfigureDisplays(&hDisplayState) != noErr)
367 // wxLogSysError(wxT("Could not lock display for display mode changing!"));
370 // wxASSERT( DMUseScreenPrefs(true, hDisplayState) == noErr);
371 // DMEndConfigureDisplays(hDisplayState);
379 //0 & NULL for params 2 & 3 of DMSetVideoMode signal it to use defaults (current mode)
380 //DM 2.0+ doesn't use params 2 & 3 of DMSetDisplayMode
381 //so we have to use this icky structure
382 VDSwitchInfoRec sMode
;
383 memset(&sMode
, 0, sizeof(VDSwitchInfoRec
) );
385 DMListIndexType nNumModes
;
387 DMDisplayModeListIteratorUPP uppMLI
;
388 DisplayIDType nDisplayID
;
390 wxASSERT(DMGetDisplayIDByGDevice(m_hndl
, &nDisplayID
, false) == noErr
);
391 //Create a new list...
392 wxASSERT_MSG(DMNewDisplayModeList(nDisplayID
, NULL
, NULL
, &nNumModes
, &pModes
) == noErr
,
393 wxT("Could not create a new display mode list") );
395 uppMLI
= NewDMDisplayModeListIteratorUPP(DMModeInfoProc
);
398 DMModeInfoRec sModeInfo
;
399 sModeInfo
.bMatched
= false;
400 sModeInfo
.pMode
= &mode
;
402 for(i
= 0; i
< nNumModes
; ++i
)
404 wxASSERT(DMGetIndexedDisplayModeFromList(pModes
, i
, NULL
,
405 uppMLI
, &sModeInfo
) == noErr
);
406 if (sModeInfo
.bMatched
== true)
408 sMode
= sModeInfo
.sMode
;
415 DisposeDMDisplayModeListIteratorUPP(uppMLI
);
416 wxASSERT(DMDisposeList(pModes
) == noErr
);
418 // For the really paranoid -
419 // unsigned long flags;
421 // wxASSERT(noErr == DMCheckDisplayMode(m_hndl, sMode.csData,
422 // sMode.csMode, &flags, NULL, &bok));
425 Handle hDisplayState
;
426 if (DMBeginConfigureDisplays(&hDisplayState
) != noErr
)
428 wxLogSysError(wxT("Could not lock display for display mode changing!"));
432 unsigned long dwBPP
= (unsigned long) mode
.bpp
;
433 if (DMSetDisplayMode(m_hndl
, sMode
.csData
,
434 (unsigned long*) &(dwBPP
), NULL
435 //(unsigned long) &sMode
439 DMEndConfigureDisplays(hDisplayState
);
440 wxLogError(wxT("Could not set the display mode"));
443 DMEndConfigureDisplays(hDisplayState
);
445 else //DM 1.0, 1.2, 1.x
447 wxLogSysError(wxString::Format(wxT("Monitor gravitation not supported yet. dwDMVer:%u"),
448 (unsigned int) dwDMVer
));
455 // ============================================================================
456 // wxDisplay::CreateFactory()
457 // ============================================================================
459 /* static */ wxDisplayFactory
*wxDisplay::CreateFactory()
461 return new wxDisplayFactoryMac
;
464 #endif // wxUSE_DISPLAY