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