]> git.saurik.com Git - wxWidgets.git/blob - src/mac/carbon/display.cpp
listbox cleanup
[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 #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