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