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