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