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