partially applied patch #895170: "Building with minimal setup.h - continuation"
[wxWidgets.git] / src / msw / display.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: display.cpp
3 // Purpose: MSW Implementation of wxDisplay class
4 // Author: Royce Mitchell III
5 // Modified by: VZ (resolutions enumeration/change support, DirectDraw, ...)
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 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
21 #pragma implementation "display.h"
22 #endif
23
24 // For compilers that support precompilation, includes "wx.h".
25 #include "wx/wxprec.h"
26
27 #ifdef __BORLANDC__
28 #pragma hdrstop
29 #endif
30
31 #if wxUSE_DISPLAY
32
33 #ifndef WX_PRECOMP
34 #include "wx/app.h"
35 #include "wx/dynarray.h"
36 #include "wx/frame.h"
37 #endif
38
39 #include "wx/dynload.h"
40
41 #include "wx/display.h"
42
43 // the following define is necessary to access the multi-monitor function
44 // declarations in a manner safe to use w/ Windows 95
45 #define COMPILE_MULTIMON_STUBS
46
47 // if you don't have multimon.h you can download the file from:
48 //
49 // http://www.microsoft.com/msj/0697/monitor/monitortextfigs.htm#fig4
50 //
51
52 #ifdef _MSC_VER
53 // as (m)any standard header(s), this one doesn't compile without warnings
54 // with VC++ 6 <sigh>
55 #pragma warning(disable:4706)
56 #endif
57
58 #include <multimon.h>
59
60 #ifdef _MSC_VER
61 #pragma warning(default:4706)
62 #endif
63
64 #include <ddraw.h>
65
66 // we don't want to link with ddraw.lib which contains the real
67 // IID_IDirectDraw2 definition
68 const GUID wxIID_IDirectDraw2 =
69 { 0xB3A6F3E0, 0x2B43, 0x11CF, { 0xA2,0xDE,0x00,0xAA,0x00,0xB9,0x33,0x56 } };
70
71 // ----------------------------------------------------------------------------
72 // macros
73 // ----------------------------------------------------------------------------
74
75 #ifdef _UNICODE
76 #define WINFUNC(x) _T(#x) L"W"
77 #else
78 #define WINFUNC(x) #x "A"
79 #endif
80
81 // ----------------------------------------------------------------------------
82 // typedefs for dynamically loaded Windows functions
83 // ----------------------------------------------------------------------------
84
85 typedef LONG (WINAPI *ChangeDisplaySettingsEx_t)(LPCTSTR lpszDeviceName,
86 LPDEVMODE lpDevMode,
87 HWND hwnd,
88 DWORD dwFlags,
89 LPVOID lParam);
90
91 typedef BOOL (PASCAL *DDEnumExCallback_t)(GUID *pGuid,
92 LPTSTR driverDescription,
93 LPTSTR driverName,
94 LPVOID lpContext,
95 HMONITOR hmon);
96
97 typedef HRESULT (WINAPI *DirectDrawEnumerateEx_t)(DDEnumExCallback_t lpCallback,
98 LPVOID lpContext,
99 DWORD dwFlags);
100
101 typedef HRESULT (WINAPI *DirectDrawCreate_t)(GUID *lpGUID,
102 LPDIRECTDRAW *lplpDD,
103 IUnknown *pUnkOuter);
104
105 // ----------------------------------------------------------------------------
106 // private classes
107 // ----------------------------------------------------------------------------
108
109 class wxDisplayInfo
110 {
111 public:
112 // handle of this monitor used by MonitorXXX() functions, never NULL
113 HMONITOR m_hmon;
114
115 // IDirectDraw object used to control this display, may be NULL
116 IDirectDraw2 *m_pDD2;
117
118 // DirectDraw GUID for this display, only valid when using DirectDraw
119 GUID m_guid;
120
121 // the entire area of this monitor in virtual screen coordinates
122 wxRect m_rect;
123
124 // the display device name for this monitor, empty initially and retrieved
125 // on demand by DoGetName()
126 wxString m_devName;
127
128 wxDisplayInfo() { m_hmon = NULL; m_pDD2 = NULL; }
129 ~wxDisplayInfo() { if ( m_pDD2 ) m_pDD2->Release(); }
130 };
131
132 WX_DECLARE_OBJARRAY(wxDisplayInfo, wxDisplayInfoArray);
133 #include "wx/arrimpl.cpp"
134 WX_DEFINE_OBJARRAY(wxDisplayInfoArray);
135
136 // this module is used to cleanup gs_displays array
137 class wxDisplayModule : public wxModule
138 {
139 public:
140 virtual bool OnInit() { return true; }
141 virtual void OnExit();
142
143 DECLARE_DYNAMIC_CLASS(wxDisplayModule)
144 };
145
146 IMPLEMENT_DYNAMIC_CLASS(wxDisplayModule, wxModule)
147
148 // ----------------------------------------------------------------------------
149 // globals
150 // ----------------------------------------------------------------------------
151
152 // do we use DirectX?
153 static bool gs_useDirectX = false;
154
155 // dynamically resolved DirectDrawCreate()
156 static DirectDrawCreate_t gs_DirectDrawCreate = NULL;
157
158 // this is not really MT-unsafe as wxDisplay is only going to be used from the
159 // main thread, i.e. we consider that it's a GUI class and so don't protect it
160 static wxDisplayInfoArray *gs_displays = NULL;
161
162 // ===========================================================================
163 // implementation
164 // ===========================================================================
165
166 // ----------------------------------------------------------------------------
167 // callbacks for monitor/modes enumeration stuff
168 // ----------------------------------------------------------------------------
169
170 static BOOL CALLBACK wxmswMonitorEnumProc (
171 HMONITOR hMonitor, // handle to display monitor
172 HDC WXUNUSED(hdcMonitor), // handle to monitor-appropriate device context
173 LPRECT lprcMonitor, // pointer to monitor intersection rectangle
174 LPARAM WXUNUSED(dwData) // data passed from EnumDisplayMonitors (unused)
175 )
176 {
177 wxDisplayInfo *info = new wxDisplayInfo();
178
179 // we need hMonitor to be able to map display id to it which is needed for
180 // MonitorXXX() functions, in particular MonitorFromPoint()
181 info->m_hmon = hMonitor;
182
183 // we also store the display geometry
184 info->m_rect.SetX ( lprcMonitor->left );
185 info->m_rect.SetY ( lprcMonitor->top );
186 info->m_rect.SetWidth ( lprcMonitor->right - lprcMonitor->left );
187 info->m_rect.SetHeight ( lprcMonitor->bottom - lprcMonitor->top );
188
189 // now add this monitor to the array
190 gs_displays->Add(info);
191
192 // continue the enumeration
193 return true;
194 }
195
196 BOOL PASCAL
197 wxDDEnumExCallback(GUID *pGuid,
198 LPTSTR WXUNUSED(driverDescription),
199 LPTSTR driverName,
200 LPVOID WXUNUSED(lpContext),
201 HMONITOR hmon)
202 {
203 if ( pGuid )
204 {
205 wxDisplayInfo *info = new wxDisplayInfo();
206
207 info->m_hmon = hmon;
208 info->m_guid = *pGuid;
209 info->m_devName = driverName;
210
211 gs_displays->Add(info);
212 }
213 //else: we're called for the primary monitor, skip it
214
215 // continue the enumeration
216 return true;
217 }
218
219 HRESULT WINAPI wxDDEnumModesCallback(LPDDSURFACEDESC lpDDSurfaceDesc,
220 LPVOID lpContext)
221 {
222 // we need at least the mode size
223 static const DWORD FLAGS_REQUIRED = DDSD_HEIGHT | DDSD_WIDTH;
224 if ( (lpDDSurfaceDesc->dwFlags & FLAGS_REQUIRED) == FLAGS_REQUIRED )
225 {
226 wxArrayVideoModes * const modes = (wxArrayVideoModes *)lpContext;
227
228 modes->Add(wxVideoMode(lpDDSurfaceDesc->dwWidth,
229 lpDDSurfaceDesc->dwHeight,
230 lpDDSurfaceDesc->ddpfPixelFormat.dwRGBBitCount,
231 lpDDSurfaceDesc->dwRefreshRate));
232 }
233
234 // continue the enumeration
235 return DDENUMRET_OK;
236 }
237
238 // ----------------------------------------------------------------------------
239 // local functions
240 // ----------------------------------------------------------------------------
241
242 // initialize gs_displays using DirectX functions
243 static bool DoInitDirectX()
244 {
245 #if wxUSE_LOG
246 // suppress the errors if ddraw.dll is not found
247 wxLog::EnableLogging(false);
248 #endif
249
250 wxDynamicLibrary dllDX(_T("ddraw.dll"));
251
252 #if wxUSE_LOG
253 wxLog::EnableLogging();
254 #endif
255
256 if ( !dllDX.IsLoaded() )
257 return false;
258
259 DirectDrawEnumerateEx_t pDDEnumEx = (DirectDrawEnumerateEx_t)
260 dllDX.GetSymbol(WINFUNC(DirectDrawEnumerateEx));
261 if ( !pDDEnumEx )
262 return false;
263
264 // we'll also need DirectDrawCreate() later, resolve it right now
265 gs_DirectDrawCreate = (DirectDrawCreate_t)
266 dllDX.GetSymbol(_T("DirectDrawCreate"));
267 if ( !gs_DirectDrawCreate )
268 return false;
269
270 if ( (*pDDEnumEx)(wxDDEnumExCallback,
271 NULL,
272 DDENUM_ATTACHEDSECONDARYDEVICES) != DD_OK )
273 {
274 return false;
275 }
276
277 // ok, it seems like we're going to use DirectDraw and so we're going to
278 // need ddraw.dll all the time, don't unload it
279 dllDX.Detach();
280
281 return true;
282 }
283
284 // initialize gs_displays using the standard Windows functions
285 static void DoInitStdWindows()
286 {
287 // enumerate all displays
288 if ( !::EnumDisplayMonitors(NULL, NULL, wxmswMonitorEnumProc, 0) )
289 {
290 wxLogLastError(wxT("EnumDisplayMonitors"));
291
292 // TODO: still create at least one (valid) entry in gs_displays for the
293 // primary display!
294 }
295 }
296
297 // this function must be called before accessing gs_displays array as it
298 // creates and initializes it
299 static void InitDisplays()
300 {
301 if ( gs_displays )
302 return;
303
304 gs_displays = new wxDisplayInfoArray();
305
306 if ( !gs_useDirectX || !DoInitDirectX() )
307 {
308 // either we were told not to try to use DirectX or fall back to std
309 // functions if DirectX method failed
310 gs_useDirectX = false;
311
312 DoInitStdWindows();
313 }
314 }
315
316 // convert a DEVMODE to our wxVideoMode
317 wxVideoMode ConvertToVideoMode(const DEVMODE& dm)
318 {
319 // note that dmDisplayFrequency may be 0 or 1 meaning "standard one" and
320 // although 0 is ok for us we don't want to return modes with 1hz refresh
321 return wxVideoMode(dm.dmPelsWidth,
322 dm.dmPelsHeight,
323 dm.dmBitsPerPel,
324 dm.dmDisplayFrequency > 1 ? dm.dmDisplayFrequency : 0);
325 }
326
327 // emulation of ChangeDisplaySettingsEx() for Win95
328 LONG WINAPI ChangeDisplaySettingsExForWin95(LPCTSTR WXUNUSED(lpszDeviceName),
329 LPDEVMODE lpDevMode,
330 HWND WXUNUSED(hwnd),
331 DWORD dwFlags,
332 LPVOID WXUNUSED(lParam))
333 {
334 return ::ChangeDisplaySettings(lpDevMode, dwFlags);
335 }
336
337 // ----------------------------------------------------------------------------
338 // wxDisplayModule
339 // ----------------------------------------------------------------------------
340
341 void wxDisplayModule::OnExit()
342 {
343 delete gs_displays;
344 }
345
346 // ---------------------------------------------------------------------------
347 // wxDisplay
348 // ---------------------------------------------------------------------------
349
350 /* static */
351 void wxDisplay::UseDirectX(bool useDX)
352 {
353 wxCHECK_RET( !gs_displays, _T("it is too late to call UseDirectX") );
354
355 gs_useDirectX = useDX;
356 }
357
358 // helper of GetFromPoint() and GetFromWindow()
359 static int DisplayFromHMONITOR(HMONITOR hmon)
360 {
361 if ( hmon )
362 {
363 const size_t count = wxDisplay::GetCount();
364
365 for ( size_t n = 0; n < count; n++ )
366 {
367 if ( hmon == (*gs_displays)[n].m_hmon )
368 return n;
369 }
370 }
371
372 return wxNOT_FOUND;
373 }
374
375 /* static */
376 size_t wxDisplayBase::GetCount()
377 {
378 InitDisplays();
379
380 // I'm not sure if they really always return the same thing and if this is
381 // not true I'd like to know in which situation does it happen
382 wxASSERT_MSG( gs_displays->GetCount() == (size_t)::GetSystemMetrics(SM_CMONITORS),
383 _T("So how many displays does this system have?") );
384
385 return gs_displays->GetCount();
386 }
387
388 /* static */
389 int wxDisplayBase::GetFromPoint ( const wxPoint& pt )
390 {
391 POINT pt2;
392 pt2.x = pt.x;
393 pt2.y = pt.y;
394
395 return DisplayFromHMONITOR(::MonitorFromPoint(pt2, MONITOR_DEFAULTTONULL));
396 }
397
398 /* static */
399 int wxDisplayBase::GetFromWindow(wxWindow *window)
400 {
401 return DisplayFromHMONITOR
402 (
403 ::MonitorFromWindow(GetHwndOf(window), MONITOR_DEFAULTTONULL)
404 );
405 }
406
407 // ----------------------------------------------------------------------------
408 // wxDisplay ctor/dtor
409 // ----------------------------------------------------------------------------
410
411 wxDisplay::wxDisplay ( size_t n )
412 : wxDisplayBase ( n )
413 {
414 // if we do this in ctor we won't have to call it from all the member
415 // functions
416 InitDisplays();
417
418 if ( gs_useDirectX )
419 {
420 wxDisplayInfo& dpyInfo = (*gs_displays)[n];
421
422 LPDIRECTDRAW2& pDD2 = dpyInfo.m_pDD2;
423 if ( !pDD2 )
424 {
425 if ( !gs_DirectDrawCreate )
426 {
427 // what to do??
428 return;
429 }
430
431 IDirectDraw *pDD;
432 HRESULT hr = (*gs_DirectDrawCreate)(&dpyInfo.m_guid, &pDD, NULL);
433
434 if ( FAILED(hr) || !pDD )
435 {
436 // what to do??
437 wxLogApiError(_T("DirectDrawCreate"), hr);
438 }
439 else // got IDirectDraw, we want IDirectDraw2
440 {
441 hr = pDD->QueryInterface(wxIID_IDirectDraw2, (void **)&pDD2);
442 if ( FAILED(hr) || !pDD2 )
443 {
444 wxLogApiError(_T("IDirectDraw::QueryInterface(IDD2)"), hr);
445 }
446
447 pDD->Release();
448 }
449 }
450 //else: DirectDraw object corresponding to our display already exists
451
452 // increment its ref count to account for Release() in dtor
453 //
454 // NB: pDD2 will be only really Release()d when gs_displays is
455 // destroyed which is ok as we don't want to recreate DD objects
456 // all the time
457 pDD2->AddRef();
458 }
459 }
460
461 wxDisplay::~wxDisplay()
462 {
463 wxDisplayInfo& dpyInfo = (*gs_displays)[m_index];
464
465 LPDIRECTDRAW2& pDD2 = dpyInfo.m_pDD2;
466 if ( pDD2 )
467 {
468 pDD2->Release();
469 }
470 }
471
472 // ----------------------------------------------------------------------------
473 // wxDisplay simple accessors
474 // ----------------------------------------------------------------------------
475
476 bool wxDisplay::IsOk() const
477 {
478 return m_index < GetCount() &&
479 (!gs_useDirectX || (*gs_displays)[m_index].m_pDD2);
480 }
481
482 wxRect wxDisplay::GetGeometry() const
483 {
484 wxDisplayInfo& dpyInfo = (*gs_displays)[m_index];
485 wxRect& rect = dpyInfo.m_rect;
486 if ( !rect.width )
487 {
488 MONITORINFO monInfo;
489 wxZeroMemory(monInfo);
490 monInfo.cbSize = sizeof(monInfo);
491
492 if ( !::GetMonitorInfo(dpyInfo.m_hmon, &monInfo) )
493 {
494 wxLogLastError(_T("GetMonitorInfo"));
495 }
496 else
497 {
498 wxCopyRECTToRect(monInfo.rcMonitor, rect);
499 }
500 }
501
502 return rect;
503 }
504
505 wxString wxDisplay::GetName() const
506 {
507 wxDisplayInfo& dpyInfo = (*gs_displays)[m_index];
508 if ( dpyInfo.m_devName.empty() )
509 {
510 MONITORINFOEX monInfo;
511 wxZeroMemory(monInfo);
512 monInfo.cbSize = sizeof(monInfo);
513
514 // NB: Cast from MONITORINFOEX* to MONITORINFO* is done because
515 // Mingw headers - unlike the ones from Microsoft's Platform SDK -
516 // don't derive the former from the latter in C++ mode and so
517 // the pointer's type is not converted implicitly.
518 if ( !::GetMonitorInfo(dpyInfo.m_hmon, (LPMONITORINFO)&monInfo) )
519 {
520 wxLogLastError(_T("GetMonitorInfo"));
521 }
522 else
523 {
524 dpyInfo.m_devName = monInfo.szDevice;
525 }
526 }
527
528 return dpyInfo.m_devName;
529 }
530
531 wxString wxDisplay::GetNameForEnumSettings() const
532 {
533 int major, minor;
534 const bool isWin95 = wxGetOsVersion(&major, &minor) == wxWIN95 &&
535 major == 4 && minor == 0;
536
537 // the first parameter of EnumDisplaySettings() must be NULL under Win95
538 // according to MSDN but GetMonitorInfo() stub in multimon.h still returns
539 // something even in this case, so we have to correct this manually
540 wxString name;
541 if ( !isWin95 )
542 name = GetName();
543
544 return name;
545 }
546
547 // ----------------------------------------------------------------------------
548 // video modes enumeration
549 // ----------------------------------------------------------------------------
550
551 wxArrayVideoModes
552 wxDisplay::DoGetModesDirectX(const wxVideoMode& WXUNUSED(modeMatch)) const
553 {
554 wxArrayVideoModes modes;
555
556 IDirectDraw2 *pDD = (*gs_displays)[m_index].m_pDD2;
557
558 if ( pDD )
559 {
560 HRESULT hr = pDD->EnumDisplayModes
561 (
562 DDEDM_REFRESHRATES,
563 NULL, // all modes (TODO: use modeMatch!)
564 &modes, // callback parameter
565 wxDDEnumModesCallback
566 );
567
568 if ( FAILED(hr) )
569 {
570 wxLogApiError(_T("IDirectDraw::EnumDisplayModes"), hr);
571 }
572 }
573
574 return modes;
575 }
576
577 wxArrayVideoModes
578 wxDisplay::DoGetModesWindows(const wxVideoMode& modeMatch) const
579 {
580 wxArrayVideoModes modes;
581
582 const wxString name = GetNameForEnumSettings();
583
584 const wxChar * const deviceName = name.empty() ? NULL : name.c_str();
585
586 DEVMODE dm;
587 for ( int iModeNum = 0;
588 ::EnumDisplaySettings(deviceName, iModeNum, &dm);
589 iModeNum++ )
590 {
591 const wxVideoMode mode = ConvertToVideoMode(dm);
592 if ( mode.Matches(modeMatch) )
593 {
594 modes.Add(mode);
595 }
596 }
597
598 return modes;
599 }
600
601 wxArrayVideoModes wxDisplay::GetModes(const wxVideoMode& modeMatch) const
602 {
603 return gs_useDirectX ? DoGetModesDirectX(modeMatch)
604 : DoGetModesWindows(modeMatch);
605 }
606
607 wxVideoMode wxDisplay::GetCurrentMode() const
608 {
609 wxVideoMode mode;
610
611 const wxString name = GetNameForEnumSettings();
612
613 DEVMODE dm;
614 if ( !::EnumDisplaySettings(name.empty() ? NULL : name.c_str(),
615 ENUM_CURRENT_SETTINGS,
616 &dm) )
617 {
618 wxLogLastError(_T("EnumDisplaySettings(ENUM_CURRENT_SETTINGS)"));
619 }
620 else
621 {
622 mode = ConvertToVideoMode(dm);
623 }
624
625 return mode;
626 }
627
628 // ----------------------------------------------------------------------------
629 // video mode switching
630 // ----------------------------------------------------------------------------
631
632 bool wxDisplay::DoChangeModeDirectX(const wxVideoMode& mode)
633 {
634 IDirectDraw2 *pDD = (*gs_displays)[m_index].m_pDD2;
635 if ( !pDD )
636 return false;
637
638 wxWindow *winTop = wxTheApp->GetTopWindow();
639 wxCHECK_MSG( winTop, false, _T("top level window required for DirectX") );
640
641 HRESULT hr = pDD->SetCooperativeLevel
642 (
643 GetHwndOf(winTop),
644 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN
645 );
646 if ( FAILED(hr) )
647 {
648 wxLogApiError(_T("IDirectDraw::SetCooperativeLevel"), hr);
649
650 return false;
651 }
652
653 hr = pDD->SetDisplayMode(mode.w, mode.h, mode.bpp, mode.refresh, 0);
654 if ( FAILED(hr) )
655 {
656 wxLogApiError(_T("IDirectDraw::SetDisplayMode"), hr);
657
658 return false;
659 }
660
661
662 return true;
663 }
664
665 bool wxDisplay::DoChangeModeWindows(const wxVideoMode& mode)
666 {
667 // prepare ChangeDisplaySettingsEx() parameters
668 DEVMODE dm,
669 *pDevMode;
670 int flags;
671
672 if ( mode == wxDefaultVideoMode )
673 {
674 // reset the video mode to default
675 pDevMode = NULL;
676 flags = 0;
677 }
678 else // change to the given mode
679 {
680 wxCHECK_MSG( mode.w && mode.h, false,
681 _T("at least the width and height must be specified") );
682
683 wxZeroMemory(dm);
684 dm.dmSize = sizeof(dm);
685 dm.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
686 dm.dmPelsWidth = mode.w;
687 dm.dmPelsHeight = mode.h;
688
689 if ( mode.bpp )
690 {
691 dm.dmFields |= DM_BITSPERPEL;
692 dm.dmBitsPerPel = mode.bpp;
693 }
694
695 if ( mode.refresh )
696 {
697 dm.dmFields |= DM_DISPLAYFREQUENCY;
698 dm.dmDisplayFrequency = mode.refresh;
699 }
700
701 pDevMode = &dm;
702
703 flags = CDS_FULLSCREEN;
704 }
705
706
707 // get pointer to the function dynamically
708 //
709 // we're only called from the main thread, so it's ok to use static
710 // variable
711 static ChangeDisplaySettingsEx_t pfnChangeDisplaySettingsEx = NULL;
712 if ( !pfnChangeDisplaySettingsEx )
713 {
714 wxDynamicLibrary dllUser32(_T("user32.dll"));
715 if ( dllUser32.IsLoaded() )
716 {
717 pfnChangeDisplaySettingsEx = (ChangeDisplaySettingsEx_t)
718 dllUser32.GetSymbol(WINFUNC(ChangeDisplaySettingsEx));
719 }
720 //else: huh, no user32.dll??
721
722 if ( !pfnChangeDisplaySettingsEx )
723 {
724 // we must be under Win95 and so there is no multiple monitors
725 // support anyhow
726 pfnChangeDisplaySettingsEx = ChangeDisplaySettingsExForWin95;
727 }
728 }
729
730 // do change the mode
731 switch ( pfnChangeDisplaySettingsEx
732 (
733 GetName(), // display name
734 pDevMode, // dev mode or NULL to reset
735 NULL, // reserved
736 flags,
737 NULL // pointer to video parameters (not used)
738 ) )
739 {
740 case DISP_CHANGE_SUCCESSFUL:
741 // ok
742 {
743 // If we have a top-level, full-screen frame, emulate
744 // the DirectX behavior and resize it. This makes this
745 // API quite a bit easier to use.
746 wxWindow *winTop = wxTheApp->GetTopWindow();
747 wxFrame *frameTop = wxDynamicCast(winTop, wxFrame);
748 if (frameTop && frameTop->IsFullScreen())
749 {
750 wxVideoMode current = GetCurrentMode();
751 frameTop->SetClientSize(current.w, current.h);
752 }
753 }
754 return true;
755
756 case DISP_CHANGE_BADMODE:
757 // don't complain about this, this is the only "expected" error
758 break;
759
760 default:
761 wxFAIL_MSG( _T("unexpected ChangeDisplaySettingsEx() return value") );
762 }
763
764 return false;
765 }
766
767 bool wxDisplay::ChangeMode(const wxVideoMode& mode)
768 {
769 return gs_useDirectX ? DoChangeModeDirectX(mode)
770 : DoChangeModeWindows(mode);
771 }
772
773 #endif // wxUSE_DISPLAY
774