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(size_t n
, GDHandle hndl
)
62 virtual wxRect
GetGeometry() const;
63 virtual wxString
GetName() const { return wxString(); }
65 virtual wxArrayVideoModes
GetModes(const wxVideoMode
& mode
) const;
66 virtual wxVideoMode
GetCurrentMode() const;
67 virtual bool ChangeMode(const wxVideoMode
& mode
);
72 DECLARE_NO_COPY_CLASS(wxDisplayImplMac
)
75 class wxDisplayFactoryMac
: public wxDisplayFactory
78 wxDisplayFactoryMac();
80 virtual wxDisplayImpl
*CreateDisplay(size_t n
);
81 virtual size_t GetCount();
82 virtual int GetFromPoint(const wxPoint
& pt
);
85 DECLARE_NO_COPY_CLASS(wxDisplayFactoryMac
)
88 // ============================================================================
89 // wxDisplayFactoryMac implementation
90 // ============================================================================
92 size_t wxDisplayFactoryMac::GetCount()
95 GDHandle hndl
= DMGetFirstScreenDevice(true);
99 hndl
= DMGetNextScreenDevice(hndl
, true);
104 int wxDisplayFactoryMac::GetFromPoint(const wxPoint
&p
)
107 GDHandle hndl
= DMGetFirstScreenDevice(true);
110 Rect screenrect
= (*hndl
)->gdRect
;
111 if (p
.x
>= screenrect
.left
&&
112 p
.x
<= screenrect
.right
&&
113 p
.y
>= screenrect
.top
&&
114 p
.y
<= screenrect
.bottom
)
119 hndl
= DMGetNextScreenDevice(hndl
, true);
125 wxDisplayImpl
*wxDisplayFactoryMac::CreateDisplay(size_t n
)
129 GDHandle hndl
= DMGetFirstScreenDevice(true);
134 return new wxDisplayImplMac(nOrig
, hndl
);
137 hndl
= DMGetNextScreenDevice(hndl
, true);
143 // ============================================================================
144 // wxDisplayImplMac implementation
145 // ============================================================================
147 wxRect
wxDisplayImplMac::GetGeometry() const
149 Rect screenrect
= (*m_hndl
)->gdRect
;
150 return wxRect(screenrect
.left
, screenrect
.top
,
151 screenrect
.right
- screenrect
.left
,
152 screenrect
.bottom
- screenrect
.top
);
155 struct DMModeIteratorRec
157 wxArrayVideoModes
* pModes
;
158 const wxVideoMode
* pMatchMode
;
161 pascal void DMModeListIteratorProc ( void* pData
,
162 DMListIndexType nIndex
,
163 DMDisplayModeListEntryPtr pInfo
)
165 DMModeIteratorRec
* pInfoData
= (DMModeIteratorRec
*) pData
;
167 //Note that in testing the refresh rate is always 0 on my ibook - RN
168 int refresh
= (int) Fix2Long(pInfo
->displayModeResolutionInfo
->csRefreshRate
);
170 for(unsigned long i
= 0; i
< pInfo
->displayModeDepthBlockInfo
->depthBlockCount
; ++i
)
172 #define pDBI pInfo->displayModeDepthBlockInfo->depthVPBlock[i].depthVPBlock
174 if (wxVideoMode((int) pInfo
->displayModeResolutionInfo
->csHorizontalPixels
,
175 (int) pInfo
->displayModeResolutionInfo
->csVerticalLines
,
176 (int) pDBI
->vpPixelSize
,
177 refresh
).Matches(*pInfoData
->pMatchMode
) )
179 pInfoData
->pModes
->Add(wxVideoMode((int) pInfo
->displayModeResolutionInfo
->csHorizontalPixels
,
180 (int) pInfo
->displayModeResolutionInfo
->csVerticalLines
,
181 (int) pDBI
->vpPixelSize
,
190 const wxVideoMode
* pMode
;
191 VDSwitchInfoRec sMode
;
195 pascal void DMModeInfoProc ( void* pData
,
196 DMListIndexType nIndex
,
197 DMDisplayModeListEntryPtr pInfo
)
199 DMModeInfoRec
* pInfoData
= (DMModeInfoRec
*) pData
;
200 Fixed refresh
= Long2Fix(pInfoData
->pMode
->refresh
);
202 for(unsigned long i
= 0; i
< pInfo
->displayModeDepthBlockInfo
->depthBlockCount
; ++i
)
204 #define pDBI pInfo->displayModeDepthBlockInfo->depthVPBlock[i].depthVPBlock
205 if (pInfoData
->pMode
->w
== (int&) pInfo
->displayModeResolutionInfo
->csHorizontalPixels
&&
206 pInfoData
->pMode
->h
== (int&) pInfo
->displayModeResolutionInfo
->csVerticalLines
&&
207 pInfoData
->pMode
->bpp
== (int) pDBI
->vpPixelSize
&&
208 refresh
== pInfo
->displayModeResolutionInfo
->csRefreshRate
)
210 memcpy(&pInfoData
->sMode
, pInfo
->displayModeDepthBlockInfo
->depthVPBlock
[i
].depthSwitchInfo
,
211 sizeof(VDSwitchInfoRec
));
212 pInfoData
->sMode
.csMode
= pDBI
->vpPixelSize
;
213 pInfoData
->bMatched
= true;
220 struct DMModeTransRec
223 const VDSwitchInfoRec
* psMode
;
227 pascal void DMModeTransProc ( void* pData
,
228 DMListIndexType nIndex
,
229 DMDisplayModeListEntryPtr pInfo
)
231 DMModeTransRec
* pInfoData
= (DMModeTransRec
*) pData
;
233 for(unsigned long i
= 0; i
< pInfo
->displayModeDepthBlockInfo
->depthBlockCount
; ++i
)
235 #define pDBI pInfo->displayModeDepthBlockInfo->depthVPBlock[i].depthVPBlock
236 if (pInfoData
->psMode
->csData
== pInfo
->displayModeDepthBlockInfo
->depthVPBlock
[i
].depthSwitchInfo
->csData
)
238 pInfoData
->Mode
= wxVideoMode((int) pInfo
->displayModeResolutionInfo
->csHorizontalPixels
,
239 (int) pInfo
->displayModeResolutionInfo
->csVerticalLines
,
240 (int) pDBI
->vpPixelSize
,
241 (int) Fix2Long(pInfo
->displayModeResolutionInfo
->csRefreshRate
) );
242 pInfoData
->bMatched
= true;
249 wxArrayVideoModes
wxDisplayImplMac::GetModes(const wxVideoMode
& mode
) const
251 wxArrayVideoModes Modes
;
253 unsigned long dwDMVer
;
254 Gestalt(gestaltDisplayMgrVers
, (long*) &dwDMVer
);
256 //Check DM version (for backward compatibility only - 7.5.3+ use 2.0)
257 if (dwDMVer
>= 0x020000) //version 2?
260 DMListIndexType nNumModes
;
262 DMDisplayModeListIteratorUPP uppMLI
;
263 DisplayIDType nDisplayID
;
265 wxASSERT(DMGetDisplayIDByGDevice(m_hndl
, &nDisplayID
, false) == noErr
);
266 //Create a new list...
267 wxASSERT_MSG(DMNewDisplayModeList(nDisplayID
, NULL
, NULL
, &nNumModes
, &pModes
) == noErr
, wxT("Could not create a new display mode list") );
269 uppMLI
= NewDMDisplayModeListIteratorUPP(DMModeListIteratorProc
);
272 DMModeIteratorRec sModeInfo
;
273 sModeInfo
.pModes
= &Modes
;
274 sModeInfo
.pMatchMode
= &mode
;
275 for (DMListIndexType i
= 0; i
< nNumModes
; ++i
)
277 wxASSERT(DMGetIndexedDisplayModeFromList(pModes
, i
, NULL
,
278 uppMLI
, &sModeInfo
) == noErr
);
280 DisposeDMDisplayModeListIteratorUPP(uppMLI
);
281 wxASSERT(DMDisposeList(pModes
) == noErr
);
283 else //DM 1.0, 1.2, 1.x
285 wxLogSysError(wxString::Format(wxT("Display Manager Version %u Not Supported! Present? %s"),
286 (unsigned int) dwDMVer
/ 0x10000,
287 (dwDMVer
& (1 << gestaltDisplayMgrPresent
) ? wxT("Yes") : wxT("No")) )
294 wxVideoMode
wxDisplayImplMac::GetCurrentMode() const
296 unsigned long dwDMVer
;
299 Gestalt(gestaltDisplayMgrVers
, (long*) &dwDMVer
);
300 //Check DM version (for backward compatibility only - 7.5.3+ use 2.0)
301 if (dwDMVer
>= 0x020000) //version 2?
303 VDSwitchInfoRec sMode
; //Note - csMode member also contains the bit depth
304 if (DMGetDisplayMode(m_hndl
, &sMode
) == noErr
)
306 DMListIndexType nNumModes
;
308 DMDisplayModeListIteratorUPP uppMLI
;
309 DisplayIDType nDisplayID
;
311 wxASSERT(DMGetDisplayIDByGDevice(m_hndl
, &nDisplayID
, false) == noErr
);
312 //Create a new list...
313 wxASSERT_MSG(DMNewDisplayModeList(nDisplayID
, NULL
, NULL
, &nNumModes
, &pModes
) == noErr
,
314 wxT("Could not create a new display mode list") );
316 uppMLI
= NewDMDisplayModeListIteratorUPP(DMModeTransProc
);
319 DMModeTransRec sModeInfo
;
320 sModeInfo
.bMatched
= false;
321 sModeInfo
.psMode
= &sMode
;
322 for (DMListIndexType i
= 0; i
< nNumModes
; ++i
)
324 wxASSERT(DMGetIndexedDisplayModeFromList(pModes
, i
, NULL
,
325 uppMLI
, &sModeInfo
) == noErr
);
327 if ( sModeInfo
.bMatched
== true )
329 RetMode
= sModeInfo
.Mode
;
334 DisposeDMDisplayModeListIteratorUPP(uppMLI
);
335 wxASSERT(DMDisposeList(pModes
) == noErr
);
337 else //Can't get current mode?
339 wxLogSysError(wxString::Format(wxT("Couldn't obtain current display mode!!!\ndwDMVer:%u"),
340 (unsigned int) dwDMVer
));
345 wxLogSysError(wxString::Format(wxT("Display Manager Version %u Not Supported! Present? %s"),
346 (unsigned int) dwDMVer
/ 0x10000,
347 (dwDMVer
& (1 << gestaltDisplayMgrPresent
) ? wxT("Yes") : wxT("No")) )
354 bool wxDisplayImplMac::ChangeMode(const wxVideoMode
& mode
)
356 unsigned long dwDMVer
;
357 Gestalt(gestaltDisplayMgrVers
, (long*)&dwDMVer
);
358 if (GetCount() == 1 || dwDMVer
>= 0x020000)
360 if (mode
== wxDefaultVideoMode
)
363 // Handle hDisplayState;
364 // if (DMBeginConfigureDisplays(&hDisplayState) != noErr)
366 // wxLogSysError(wxT("Could not lock display for display mode changing!"));
369 // wxASSERT( DMUseScreenPrefs(true, hDisplayState) == noErr);
370 // DMEndConfigureDisplays(hDisplayState);
378 //0 & NULL for params 2 & 3 of DMSetVideoMode signal it to use defaults (current mode)
379 //DM 2.0+ doesn't use params 2 & 3 of DMSetDisplayMode
380 //so we have to use this icky structure
381 VDSwitchInfoRec sMode
;
382 memset(&sMode
, 0, sizeof(VDSwitchInfoRec
) );
384 DMListIndexType nNumModes
;
386 DMDisplayModeListIteratorUPP uppMLI
;
387 DisplayIDType nDisplayID
;
389 wxASSERT(DMGetDisplayIDByGDevice(m_hndl
, &nDisplayID
, false) == noErr
);
390 //Create a new list...
391 wxASSERT_MSG(DMNewDisplayModeList(nDisplayID
, NULL
, NULL
, &nNumModes
, &pModes
) == noErr
,
392 wxT("Could not create a new display mode list") );
394 uppMLI
= NewDMDisplayModeListIteratorUPP(DMModeInfoProc
);
397 DMModeInfoRec sModeInfo
;
398 sModeInfo
.bMatched
= false;
399 sModeInfo
.pMode
= &mode
;
401 for(i
= 0; i
< nNumModes
; ++i
)
403 wxASSERT(DMGetIndexedDisplayModeFromList(pModes
, i
, NULL
,
404 uppMLI
, &sModeInfo
) == noErr
);
405 if (sModeInfo
.bMatched
== true)
407 sMode
= sModeInfo
.sMode
;
414 DisposeDMDisplayModeListIteratorUPP(uppMLI
);
415 wxASSERT(DMDisposeList(pModes
) == noErr
);
417 // For the really paranoid -
418 // unsigned long flags;
420 // wxASSERT(noErr == DMCheckDisplayMode(m_hndl, sMode.csData,
421 // sMode.csMode, &flags, NULL, &bok));
424 Handle hDisplayState
;
425 if (DMBeginConfigureDisplays(&hDisplayState
) != noErr
)
427 wxLogSysError(wxT("Could not lock display for display mode changing!"));
431 unsigned long dwBPP
= (unsigned long) mode
.bpp
;
432 if (DMSetDisplayMode(m_hndl
, sMode
.csData
,
433 (unsigned long*) &(dwBPP
), NULL
434 //(unsigned long) &sMode
438 DMEndConfigureDisplays(hDisplayState
);
439 wxLogError(wxT("Could not set the display mode"));
442 DMEndConfigureDisplays(hDisplayState
);
444 else //DM 1.0, 1.2, 1.x
446 wxLogSysError(wxString::Format(wxT("Monitor gravitation not supported yet. dwDMVer:%u"),
447 (unsigned int) dwDMVer
));
454 // ============================================================================
455 // wxDisplay::CreateFactory()
456 // ============================================================================
458 /* static */ wxDisplayFactory
*wxDisplay::CreateFactory()
460 return new wxDisplayFactoryMac
;
463 #endif // wxUSE_DISPLAY