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