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"
30 #include "wx/dynarray.h"
35 #include <Carbon/Carbon.h>
39 #include <Quickdraw.h>
40 #include <Video.h> //for VDSwitchInfoRec
44 #include "wx/display.h"
45 #include "wx/display_impl.h"
46 #include "wx/gdicmn.h"
47 #include "wx/string.h"
49 // ----------------------------------------------------------------------------
50 // display implementation classes
51 // ----------------------------------------------------------------------------
53 class wxDisplayImplMac
: public wxDisplayImpl
56 wxDisplayImplMac(GDHandle hndl
) : m_hndl(hndl
) { }
58 virtual wxRect
GetGeometry() const;
59 virtual wxString
GetName() const { return wxString(); }
61 virtual wxArrayVideoModes
GetModes(const wxVideoMode
& mode
) const;
62 virtual wxVideoMode
GetCurrentMode() const;
63 virtual bool ChangeMode(const wxVideoMode
& mode
);
68 DECLARE_NO_COPY_CLASS(wxDisplayImplMac
)
71 class wxDisplayFactoryMac
: public wxDisplayFactory
74 wxDisplayFactoryMac();
76 virtual wxDisplayImpl
*CreateDisplay(size_t n
);
77 virtual size_t GetCount();
78 virtual int GetFromPoint(const wxPoint
& pt
);
81 DECLARE_NO_COPY_CLASS(wxDisplayFactoryMac
)
84 // ============================================================================
85 // wxDisplayFactoryMac implementation
86 // ============================================================================
88 size_t wxDisplayFactoryMac::GetCount()
91 GDHandle hndl
= DMGetFirstScreenDevice(true);
95 hndl
= DMGetNextScreenDevice(hndl
, true);
100 int wxDisplayFactoryMac::GetFromPoint(const wxPoint
&p
)
103 GDHandle hndl
= DMGetFirstScreenDevice(true);
106 Rect screenrect
= (*hndl
)->gdRect
;
107 if (p
.x
>= screenrect
.left
&&
108 p
.x
<= screenrect
.right
&&
109 p
.y
>= screenrect
.top
&&
110 p
.y
<= screenrect
.bottom
)
115 hndl
= DMGetNextScreenDevice(hndl
, true);
121 wxDisplayImpl
*wxDisplayFactoryMac::CreateDisplay(size_t n
)
123 GDHandle hndl
= DMGetFirstScreenDevice(true);
128 return new wxDisplayImplMac(hndl
);
131 hndl
= DMGetNextScreenDevice(hndl
, true);
137 // ============================================================================
138 // wxDisplayImplMac implementation
139 // ============================================================================
141 wxRect
wxDisplayImplMac::GetGeometry() const
143 Rect screenrect
= (*m_hndl
)->gdRect
;
144 return wxRect(screenrect
.left
, screenrect
.top
,
145 screenrect
.right
- screenrect
.left
,
146 screenrect
.bottom
- screenrect
.top
);
149 struct DMModeIteratorRec
151 wxArrayVideoModes
* pModes
;
152 const wxVideoMode
* pMatchMode
;
155 pascal void DMModeListIteratorProc ( void* pData
,
156 DMListIndexType nIndex
,
157 DMDisplayModeListEntryPtr pInfo
)
159 DMModeIteratorRec
* pInfoData
= (DMModeIteratorRec
*) pData
;
161 //Note that in testing the refresh rate is always 0 on my ibook - RN
162 int refresh
= (int) Fix2Long(pInfo
->displayModeResolutionInfo
->csRefreshRate
);
164 for(unsigned long i
= 0; i
< pInfo
->displayModeDepthBlockInfo
->depthBlockCount
; ++i
)
166 #define pDBI pInfo->displayModeDepthBlockInfo->depthVPBlock[i].depthVPBlock
168 if (wxVideoMode((int) pInfo
->displayModeResolutionInfo
->csHorizontalPixels
,
169 (int) pInfo
->displayModeResolutionInfo
->csVerticalLines
,
170 (int) pDBI
->vpPixelSize
,
171 refresh
).Matches(*pInfoData
->pMatchMode
) )
173 pInfoData
->pModes
->Add(wxVideoMode((int) pInfo
->displayModeResolutionInfo
->csHorizontalPixels
,
174 (int) pInfo
->displayModeResolutionInfo
->csVerticalLines
,
175 (int) pDBI
->vpPixelSize
,
184 const wxVideoMode
* pMode
;
185 VDSwitchInfoRec sMode
;
189 pascal void DMModeInfoProc ( void* pData
,
190 DMListIndexType nIndex
,
191 DMDisplayModeListEntryPtr pInfo
)
193 DMModeInfoRec
* pInfoData
= (DMModeInfoRec
*) pData
;
194 Fixed refresh
= Long2Fix(pInfoData
->pMode
->refresh
);
196 for(unsigned long i
= 0; i
< pInfo
->displayModeDepthBlockInfo
->depthBlockCount
; ++i
)
198 #define pDBI pInfo->displayModeDepthBlockInfo->depthVPBlock[i].depthVPBlock
199 if (pInfoData
->pMode
->w
== (int&) pInfo
->displayModeResolutionInfo
->csHorizontalPixels
&&
200 pInfoData
->pMode
->h
== (int&) pInfo
->displayModeResolutionInfo
->csVerticalLines
&&
201 pInfoData
->pMode
->bpp
== (int) pDBI
->vpPixelSize
&&
202 refresh
== pInfo
->displayModeResolutionInfo
->csRefreshRate
)
204 memcpy(&pInfoData
->sMode
, pInfo
->displayModeDepthBlockInfo
->depthVPBlock
[i
].depthSwitchInfo
,
205 sizeof(VDSwitchInfoRec
));
206 pInfoData
->sMode
.csMode
= pDBI
->vpPixelSize
;
207 pInfoData
->bMatched
= true;
214 struct DMModeTransRec
217 const VDSwitchInfoRec
* psMode
;
221 pascal void DMModeTransProc ( void* pData
,
222 DMListIndexType nIndex
,
223 DMDisplayModeListEntryPtr pInfo
)
225 DMModeTransRec
* pInfoData
= (DMModeTransRec
*) pData
;
227 for(unsigned long i
= 0; i
< pInfo
->displayModeDepthBlockInfo
->depthBlockCount
; ++i
)
229 #define pDBI pInfo->displayModeDepthBlockInfo->depthVPBlock[i].depthVPBlock
230 if (pInfoData
->psMode
->csData
== pInfo
->displayModeDepthBlockInfo
->depthVPBlock
[i
].depthSwitchInfo
->csData
)
232 pInfoData
->Mode
= wxVideoMode((int) pInfo
->displayModeResolutionInfo
->csHorizontalPixels
,
233 (int) pInfo
->displayModeResolutionInfo
->csVerticalLines
,
234 (int) pDBI
->vpPixelSize
,
235 (int) Fix2Long(pInfo
->displayModeResolutionInfo
->csRefreshRate
) );
236 pInfoData
->bMatched
= true;
243 wxArrayVideoModes
wxDisplayImplMac::GetModes(const wxVideoMode
& mode
) const
245 wxArrayVideoModes Modes
;
247 unsigned long dwDMVer
;
248 Gestalt(gestaltDisplayMgrVers
, (long*) &dwDMVer
);
250 //Check DM version (for backward compatibility only - 7.5.3+ use 2.0)
251 if (dwDMVer
>= 0x020000) //version 2?
254 DMListIndexType nNumModes
;
256 DMDisplayModeListIteratorUPP uppMLI
;
257 DisplayIDType nDisplayID
;
259 wxASSERT(DMGetDisplayIDByGDevice(m_hndl
, &nDisplayID
, false) == noErr
);
260 //Create a new list...
261 wxASSERT_MSG(DMNewDisplayModeList(nDisplayID
, NULL
, NULL
, &nNumModes
, &pModes
) == noErr
, wxT("Could not create a new display mode list") );
263 uppMLI
= NewDMDisplayModeListIteratorUPP(DMModeListIteratorProc
);
266 DMModeIteratorRec sModeInfo
;
267 sModeInfo
.pModes
= &Modes
;
268 sModeInfo
.pMatchMode
= &mode
;
269 for (DMListIndexType i
= 0; i
< nNumModes
; ++i
)
271 wxASSERT(DMGetIndexedDisplayModeFromList(pModes
, i
, NULL
,
272 uppMLI
, &sModeInfo
) == noErr
);
274 DisposeDMDisplayModeListIteratorUPP(uppMLI
);
275 wxASSERT(DMDisposeList(pModes
) == noErr
);
277 else //DM 1.0, 1.2, 1.x
279 wxLogSysError(wxString::Format(wxT("Display Manager Version %u Not Supported! Present? %s"),
280 (unsigned int) dwDMVer
/ 0x10000,
281 (dwDMVer
& (1 << gestaltDisplayMgrPresent
) ? wxT("Yes") : wxT("No")) )
288 wxVideoMode
wxDisplayImplMac::GetCurrentMode() const
290 unsigned long dwDMVer
;
293 Gestalt(gestaltDisplayMgrVers
, (long*) &dwDMVer
);
294 //Check DM version (for backward compatibility only - 7.5.3+ use 2.0)
295 if (dwDMVer
>= 0x020000) //version 2?
297 VDSwitchInfoRec sMode
; //Note - csMode member also contains the bit depth
298 if (DMGetDisplayMode(m_hndl
, &sMode
) == noErr
)
300 DMListIndexType nNumModes
;
302 DMDisplayModeListIteratorUPP uppMLI
;
303 DisplayIDType nDisplayID
;
305 wxASSERT(DMGetDisplayIDByGDevice(m_hndl
, &nDisplayID
, false) == noErr
);
306 //Create a new list...
307 wxASSERT_MSG(DMNewDisplayModeList(nDisplayID
, NULL
, NULL
, &nNumModes
, &pModes
) == noErr
,
308 wxT("Could not create a new display mode list") );
310 uppMLI
= NewDMDisplayModeListIteratorUPP(DMModeTransProc
);
313 DMModeTransRec sModeInfo
;
314 sModeInfo
.bMatched
= false;
315 sModeInfo
.psMode
= &sMode
;
316 for (DMListIndexType i
= 0; i
< nNumModes
; ++i
)
318 wxASSERT(DMGetIndexedDisplayModeFromList(pModes
, i
, NULL
,
319 uppMLI
, &sModeInfo
) == noErr
);
321 if ( sModeInfo
.bMatched
== true )
323 RetMode
= sModeInfo
.Mode
;
328 DisposeDMDisplayModeListIteratorUPP(uppMLI
);
329 wxASSERT(DMDisposeList(pModes
) == noErr
);
331 else //Can't get current mode?
333 wxLogSysError(wxString::Format(wxT("Couldn't obtain current display mode!!!\ndwDMVer:%u"),
334 (unsigned int) dwDMVer
));
339 wxLogSysError(wxString::Format(wxT("Display Manager Version %u Not Supported! Present? %s"),
340 (unsigned int) dwDMVer
/ 0x10000,
341 (dwDMVer
& (1 << gestaltDisplayMgrPresent
) ? wxT("Yes") : wxT("No")) )
348 bool wxDisplayImplMac::ChangeMode(const wxVideoMode
& mode
)
350 unsigned long dwDMVer
;
351 Gestalt(gestaltDisplayMgrVers
, (long*)&dwDMVer
);
352 if (GetCount() == 1 || dwDMVer
>= 0x020000)
354 if (mode
== wxDefaultVideoMode
)
357 // Handle hDisplayState;
358 // if (DMBeginConfigureDisplays(&hDisplayState) != noErr)
360 // wxLogSysError(wxT("Could not lock display for display mode changing!"));
363 // wxASSERT( DMUseScreenPrefs(true, hDisplayState) == noErr);
364 // DMEndConfigureDisplays(hDisplayState);
372 //0 & NULL for params 2 & 3 of DMSetVideoMode signal it to use defaults (current mode)
373 //DM 2.0+ doesn't use params 2 & 3 of DMSetDisplayMode
374 //so we have to use this icky structure
375 VDSwitchInfoRec sMode
;
376 memset(&sMode
, 0, sizeof(VDSwitchInfoRec
) );
378 DMListIndexType nNumModes
;
380 DMDisplayModeListIteratorUPP uppMLI
;
381 DisplayIDType nDisplayID
;
383 wxASSERT(DMGetDisplayIDByGDevice(m_hndl
, &nDisplayID
, false) == noErr
);
384 //Create a new list...
385 wxASSERT_MSG(DMNewDisplayModeList(nDisplayID
, NULL
, NULL
, &nNumModes
, &pModes
) == noErr
,
386 wxT("Could not create a new display mode list") );
388 uppMLI
= NewDMDisplayModeListIteratorUPP(DMModeInfoProc
);
391 DMModeInfoRec sModeInfo
;
392 sModeInfo
.bMatched
= false;
393 sModeInfo
.pMode
= &mode
;
395 for(i
= 0; i
< nNumModes
; ++i
)
397 wxASSERT(DMGetIndexedDisplayModeFromList(pModes
, i
, NULL
,
398 uppMLI
, &sModeInfo
) == noErr
);
399 if (sModeInfo
.bMatched
== true)
401 sMode
= sModeInfo
.sMode
;
408 DisposeDMDisplayModeListIteratorUPP(uppMLI
);
409 wxASSERT(DMDisposeList(pModes
) == noErr
);
411 // For the really paranoid -
412 // unsigned long flags;
414 // wxASSERT(noErr == DMCheckDisplayMode(m_hndl, sMode.csData,
415 // sMode.csMode, &flags, NULL, &bok));
418 Handle hDisplayState
;
419 if (DMBeginConfigureDisplays(&hDisplayState
) != noErr
)
421 wxLogSysError(wxT("Could not lock display for display mode changing!"));
425 unsigned long dwBPP
= (unsigned long) mode
.bpp
;
426 if (DMSetDisplayMode(m_hndl
, sMode
.csData
,
427 (unsigned long*) &(dwBPP
), NULL
428 //(unsigned long) &sMode
432 DMEndConfigureDisplays(hDisplayState
);
433 wxLogError(wxT("Could not set the display mode"));
436 DMEndConfigureDisplays(hDisplayState
);
438 else //DM 1.0, 1.2, 1.x
440 wxLogSysError(wxString::Format(wxT("Monitor gravitation not supported yet. dwDMVer:%u"),
441 (unsigned int) dwDMVer
));
448 // ============================================================================
449 // wxDisplay::CreateFactory()
450 // ============================================================================
452 /* static */ wxDisplayFactory
*wxDisplay::CreateFactory()
454 return new wxDisplayFactoryMac
;
457 #endif // wxUSE_DISPLAY