/[pcsx2_0.9.7]/branch/r3113_0.9.7_beta/3rdparty/wxWidgets/src/msw/display.cpp
ViewVC logotype

Contents of /branch/r3113_0.9.7_beta/3rdparty/wxWidgets/src/msw/display.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 32 - (show annotations) (download)
Tue Sep 7 03:29:01 2010 UTC (9 years, 11 months ago) by william
File size: 33064 byte(s)
branching from upstream revision (http://pcsx2.googlecode.com/svn/trunk
): r3113 to
https://svn.netsolutions.dnsalias.com/websvn/ps2/pcsx2/pcsx2_0.9.7/branch/r3113_0.9.7_beta
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/msw/display.cpp
3 // Purpose: MSW Implementation of wxDisplay class
4 // Author: Royce Mitchell III, Vadim Zeitlin
5 // Modified by: Ryan Norton (IsPrimary override)
6 // Created: 06/21/02
7 // RCS-ID: $Id: display.cpp 56865 2008-11-20 17:46:46Z VZ $
8 // Copyright: (c) wxWidgets team
9 // Copyright: (c) 2002-2006 wxWidgets team
10 // Licence: wxWindows licence
11 /////////////////////////////////////////////////////////////////////////////
12
13 // ===========================================================================
14 // declarations
15 // ===========================================================================
16
17 // ---------------------------------------------------------------------------
18 // headers
19 // ---------------------------------------------------------------------------
20
21 // For compilers that support precompilation, includes "wx.h".
22 #include "wx/wxprec.h"
23
24 #ifdef __BORLANDC__
25 #pragma hdrstop
26 #endif
27
28 #if wxUSE_DISPLAY
29
30 #include "wx/display.h"
31
32 #ifndef WX_PRECOMP
33 #include "wx/dynarray.h"
34 #include "wx/app.h"
35 #include "wx/frame.h"
36 #endif
37
38 #include "wx/dynload.h"
39 #include "wx/sysopt.h"
40
41 #include "wx/display_impl.h"
42 #include "wx/msw/wrapwin.h"
43 #include "wx/msw/missing.h"
44
45 // define this to use DirectDraw for display mode switching: this is disabled
46 // by default because ddraw.h is now always available and also it's not really
47 // clear what are the benefits of using DirectDraw compared to the standard API
48
49 #if !defined(wxUSE_DIRECTDRAW)
50 #define wxUSE_DIRECTDRAW 0
51 #endif
52
53 #ifndef __WXWINCE__
54 // Older versions of windef.h don't define HMONITOR. Unfortunately, we
55 // can't directly test whether HMONITOR is defined or not in windef.h as
56 // it's not a macro but a typedef, so we test for an unrelated symbol which
57 // is only defined in winuser.h if WINVER >= 0x0500
58 #if !defined(HMONITOR_DECLARED) && !defined(MNS_NOCHECK)
59 DECLARE_HANDLE(HMONITOR);
60 typedef BOOL(CALLBACK * MONITORENUMPROC )(HMONITOR, HDC, LPRECT, LPARAM);
61 typedef struct tagMONITORINFO
62 {
63 DWORD cbSize;
64 RECT rcMonitor;
65 RECT rcWork;
66 DWORD dwFlags;
67 } MONITORINFO, *LPMONITORINFO;
68 typedef struct tagMONITORINFOEX : public tagMONITORINFO
69 {
70 TCHAR szDevice[CCHDEVICENAME];
71 } MONITORINFOEX, *LPMONITORINFOEX;
72 #define MONITOR_DEFAULTTONULL 0x00000000
73 #define MONITOR_DEFAULTTOPRIMARY 0x00000001
74 #define MONITOR_DEFAULTTONEAREST 0x00000002
75 #define MONITORINFOF_PRIMARY 0x00000001
76 #define HMONITOR_DECLARED
77 #endif
78 #endif // !__WXWINCE__
79
80 #if wxUSE_DIRECTDRAW
81 #include <ddraw.h>
82
83 // we don't want to link with ddraw.lib which contains the real
84 // IID_IDirectDraw2 definition
85 const GUID wxIID_IDirectDraw2 =
86 { 0xB3A6F3E0, 0x2B43, 0x11CF, { 0xA2,0xDE,0x00,0xAA,0x00,0xB9,0x33,0x56 } };
87 #endif // wxUSE_DIRECTDRAW
88
89 // display functions are found in different DLLs under WinCE and normal Win32
90 #ifdef __WXWINCE__
91 static const wxChar displayDllName[] = _T("coredll.dll");
92 #else
93 static const wxChar displayDllName[] = _T("user32.dll");
94 #endif
95
96 // ----------------------------------------------------------------------------
97 // typedefs for dynamically loaded Windows functions
98 // ----------------------------------------------------------------------------
99
100 typedef LONG (WINAPI *ChangeDisplaySettingsEx_t)(LPCTSTR lpszDeviceName,
101 LPDEVMODE lpDevMode,
102 HWND hwnd,
103 DWORD dwFlags,
104 LPVOID lParam);
105
106 #if wxUSE_DIRECTDRAW
107 typedef BOOL (PASCAL *DDEnumExCallback_t)(GUID *pGuid,
108 LPTSTR driverDescription,
109 LPTSTR driverName,
110 LPVOID lpContext,
111 HMONITOR hmon);
112
113 typedef HRESULT (WINAPI *DirectDrawEnumerateEx_t)(DDEnumExCallback_t lpCallback,
114 LPVOID lpContext,
115 DWORD dwFlags);
116
117 typedef HRESULT (WINAPI *DirectDrawCreate_t)(GUID *lpGUID,
118 LPDIRECTDRAW *lplpDD,
119 IUnknown *pUnkOuter);
120 #endif // wxUSE_DIRECTDRAW
121
122 typedef BOOL (WINAPI *EnumDisplayMonitors_t)(HDC,LPCRECT,MONITORENUMPROC,LPARAM);
123 typedef HMONITOR (WINAPI *MonitorFromPoint_t)(POINT,DWORD);
124 typedef HMONITOR (WINAPI *MonitorFromWindow_t)(HWND,DWORD);
125 typedef BOOL (WINAPI *GetMonitorInfo_t)(HMONITOR,LPMONITORINFO);
126
127 #ifndef __WXWINCE__
128 // emulation of ChangeDisplaySettingsEx() for Win95
129 LONG WINAPI ChangeDisplaySettingsExForWin95(LPCTSTR WXUNUSED(lpszDeviceName),
130 LPDEVMODE lpDevMode,
131 HWND WXUNUSED(hwnd),
132 DWORD dwFlags,
133 LPVOID WXUNUSED(lParam))
134 {
135 return ::ChangeDisplaySettings(lpDevMode, dwFlags);
136 }
137 #endif // !__WXWINCE__
138
139 // ----------------------------------------------------------------------------
140 // display information classes
141 // ----------------------------------------------------------------------------
142
143 struct wxDisplayInfo
144 {
145 wxDisplayInfo(HMONITOR hmon = NULL)
146 {
147 m_hmon = hmon;
148 m_flags = (DWORD)-1;
149 }
150
151 virtual ~wxDisplayInfo() { }
152
153
154 // use GetMonitorInfo() to fill in all of our fields if needed (i.e. if it
155 // hadn't been done before)
156 void Initialize();
157
158
159 // handle of this monitor used by MonitorXXX() functions, never NULL
160 HMONITOR m_hmon;
161
162 // the entire area of this monitor in virtual screen coordinates
163 wxRect m_rect;
164
165 // the work or client area, i.e. the area available for the normal windows
166 wxRect m_rectClient;
167
168 // the display device name for this monitor, empty initially and retrieved
169 // on demand by DoGetName()
170 wxString m_devName;
171
172 // the flags of this monitor, also used as initialization marker: if this
173 // is -1, GetMonitorInfo() hadn't been called yet
174 DWORD m_flags;
175 };
176
177 WX_DEFINE_ARRAY_PTR(wxDisplayInfo *, wxDisplayInfoArray);
178
179 // ----------------------------------------------------------------------------
180 // common base class for all Win32 wxDisplayImpl versions
181 // ----------------------------------------------------------------------------
182
183 class wxDisplayImplWin32Base : public wxDisplayImpl
184 {
185 public:
186 wxDisplayImplWin32Base(unsigned n, wxDisplayInfo& info)
187 : wxDisplayImpl(n),
188 m_info(info)
189 {
190 }
191
192 virtual wxRect GetGeometry() const;
193 virtual wxRect GetClientArea() const;
194 virtual wxString GetName() const;
195 virtual bool IsPrimary() const;
196
197 virtual wxVideoMode GetCurrentMode() const;
198
199 protected:
200 // convert a DEVMODE to our wxVideoMode
201 static wxVideoMode ConvertToVideoMode(const DEVMODE& dm)
202 {
203 // note that dmDisplayFrequency may be 0 or 1 meaning "standard one"
204 // and although 0 is ok for us we don't want to return modes with 1hz
205 // refresh
206 return wxVideoMode(dm.dmPelsWidth,
207 dm.dmPelsHeight,
208 dm.dmBitsPerPel,
209 dm.dmDisplayFrequency > 1 ? dm.dmDisplayFrequency : 0);
210 }
211
212 wxDisplayInfo& m_info;
213 };
214
215 // ----------------------------------------------------------------------------
216 // common base class for all Win32 wxDisplayFactory versions
217 // ----------------------------------------------------------------------------
218
219 // functions dynamically bound by wxDisplayFactoryWin32Base::Initialize()
220 static MonitorFromPoint_t gs_MonitorFromPoint = NULL;
221 static MonitorFromWindow_t gs_MonitorFromWindow = NULL;
222 static GetMonitorInfo_t gs_GetMonitorInfo = NULL;
223
224 class wxDisplayFactoryWin32Base : public wxDisplayFactory
225 {
226 public:
227 virtual ~wxDisplayFactoryWin32Base();
228
229 bool IsOk() const { return !m_displays.empty(); }
230
231 virtual unsigned GetCount() { return unsigned(m_displays.size()); }
232 virtual int GetFromPoint(const wxPoint& pt);
233 virtual int GetFromWindow(wxWindow *window);
234
235 protected:
236 // ctor checks if the current system supports multimon API and dynamically
237 // bind the functions we need if this is the case and sets
238 // ms_supportsMultimon if they're available
239 wxDisplayFactoryWin32Base();
240
241 // delete all m_displays elements: can be called from the derived class
242 // dtor if it is important to do this before destroying it (as in
243 // wxDisplayFactoryDirectDraw case), otherwise will be done by our dtor
244 void Clear();
245
246 // find the monitor corresponding to the given handle, return wxNOT_FOUND
247 // if not found
248 int FindDisplayFromHMONITOR(HMONITOR hmon) const;
249
250
251 // flag indicating whether gs_MonitorXXX functions are available
252 static int ms_supportsMultimon;
253
254 // the array containing information about all available displays, should be
255 // filled by the derived class ctors
256 wxDisplayInfoArray m_displays;
257
258
259 DECLARE_NO_COPY_CLASS(wxDisplayFactoryWin32Base)
260 };
261
262 // ----------------------------------------------------------------------------
263 // wxDisplay implementation using Windows multi-monitor support functions
264 // ----------------------------------------------------------------------------
265
266 class wxDisplayImplMultimon : public wxDisplayImplWin32Base
267 {
268 public:
269 wxDisplayImplMultimon(unsigned n, wxDisplayInfo& info)
270 : wxDisplayImplWin32Base(n, info)
271 {
272 }
273
274 virtual wxArrayVideoModes GetModes(const wxVideoMode& mode) const;
275 virtual bool ChangeMode(const wxVideoMode& mode);
276
277 private:
278 DECLARE_NO_COPY_CLASS(wxDisplayImplMultimon)
279 };
280
281 class wxDisplayFactoryMultimon : public wxDisplayFactoryWin32Base
282 {
283 public:
284 wxDisplayFactoryMultimon();
285
286 virtual wxDisplayImpl *CreateDisplay(unsigned n);
287
288 private:
289 // EnumDisplayMonitors() callback
290 static BOOL CALLBACK MultimonEnumProc(HMONITOR hMonitor,
291 HDC hdcMonitor,
292 LPRECT lprcMonitor,
293 LPARAM dwData);
294
295
296 // add a monitor description to m_displays array
297 void AddDisplay(HMONITOR hMonitor, LPRECT lprcMonitor);
298 };
299
300 // ----------------------------------------------------------------------------
301 // wxDisplay implementation using DirectDraw
302 // ----------------------------------------------------------------------------
303
304 #if wxUSE_DIRECTDRAW
305
306 struct wxDisplayInfoDirectDraw : wxDisplayInfo
307 {
308 wxDisplayInfoDirectDraw(const GUID& guid, HMONITOR hmon, LPTSTR name)
309 : wxDisplayInfo(hmon),
310 m_guid(guid)
311 {
312 m_pDD2 = NULL;
313 m_devName = name;
314 }
315
316 virtual ~wxDisplayInfoDirectDraw()
317 {
318 if ( m_pDD2 )
319 m_pDD2->Release();
320 }
321
322
323 // IDirectDraw object used to control this display, may be NULL
324 IDirectDraw2 *m_pDD2;
325
326 // DirectDraw GUID for this display, only valid when using DirectDraw
327 const GUID m_guid;
328
329
330 DECLARE_NO_COPY_CLASS(wxDisplayInfoDirectDraw)
331 };
332
333 class wxDisplayImplDirectDraw : public wxDisplayImplWin32Base
334 {
335 public:
336 wxDisplayImplDirectDraw(unsigned n, wxDisplayInfo& info, IDirectDraw2 *pDD2)
337 : wxDisplayImplWin32Base(n, info),
338 m_pDD2(pDD2)
339 {
340 m_pDD2->AddRef();
341 }
342
343 virtual ~wxDisplayImplDirectDraw()
344 {
345 m_pDD2->Release();
346 }
347
348 virtual wxArrayVideoModes GetModes(const wxVideoMode& mode) const;
349 virtual bool ChangeMode(const wxVideoMode& mode);
350
351 private:
352 IDirectDraw2 *m_pDD2;
353
354 DECLARE_NO_COPY_CLASS(wxDisplayImplDirectDraw)
355 };
356
357 class wxDisplayFactoryDirectDraw : public wxDisplayFactoryWin32Base
358 {
359 public:
360 wxDisplayFactoryDirectDraw();
361 virtual ~wxDisplayFactoryDirectDraw();
362
363 virtual wxDisplayImpl *CreateDisplay(unsigned n);
364
365 private:
366 // callback used with DirectDrawEnumerateEx()
367 static BOOL WINAPI DDEnumExCallback(GUID *pGuid,
368 LPTSTR driverDescription,
369 LPTSTR driverName,
370 LPVOID lpContext,
371 HMONITOR hmon);
372
373 // add a monitor description to m_displays array
374 void AddDisplay(const GUID& guid, HMONITOR hmon, LPTSTR name);
375
376
377 // ddraw.dll
378 wxDynamicLibrary m_dllDDraw;
379
380 // dynamically resolved DirectDrawCreate()
381 DirectDrawCreate_t m_pfnDirectDrawCreate;
382
383 DECLARE_NO_COPY_CLASS(wxDisplayFactoryDirectDraw)
384 };
385
386 #endif // wxUSE_DIRECTDRAW
387
388
389 // ============================================================================
390 // common classes implementation
391 // ============================================================================
392
393 // ----------------------------------------------------------------------------
394 // wxDisplay
395 // ----------------------------------------------------------------------------
396
397 /* static */ wxDisplayFactory *wxDisplay::CreateFactory()
398 {
399 // we have 2 implementations for modern Windows: one using standard Win32
400 // and another using DirectDraw, the choice between them is done using a
401 // system option
402
403 #if wxUSE_DIRECTDRAW
404 if ( wxSystemOptions::GetOptionInt(_T("msw.display.directdraw")) )
405 {
406 wxDisplayFactoryDirectDraw *factoryDD = new wxDisplayFactoryDirectDraw;
407 if ( factoryDD->IsOk() )
408 return factoryDD;
409
410 delete factoryDD;
411 }
412 #endif // wxUSE_DIRECTDRAW
413
414 wxDisplayFactoryMultimon *factoryMM = new wxDisplayFactoryMultimon;
415 if ( factoryMM->IsOk() )
416 return factoryMM;
417
418 delete factoryMM;
419
420
421 // finally fall back to a stub implementation if all else failed (Win95?)
422 return new wxDisplayFactorySingle;
423 }
424
425 // ----------------------------------------------------------------------------
426 // wxDisplayInfo
427 // ----------------------------------------------------------------------------
428
429 void wxDisplayInfo::Initialize()
430 {
431 if ( m_flags == (DWORD)-1 )
432 {
433 WinStruct<MONITORINFOEX> monInfo;
434 if ( !gs_GetMonitorInfo(m_hmon, (LPMONITORINFO)&monInfo) )
435 {
436 wxLogLastError(_T("GetMonitorInfo"));
437 m_flags = 0;
438 return;
439 }
440
441 wxCopyRECTToRect(monInfo.rcMonitor, m_rect);
442 wxCopyRECTToRect(monInfo.rcWork, m_rectClient);
443 m_devName = monInfo.szDevice;
444 m_flags = monInfo.dwFlags;
445 }
446 }
447
448 // ----------------------------------------------------------------------------
449 // wxDisplayImplWin32Base
450 // ----------------------------------------------------------------------------
451
452 wxRect wxDisplayImplWin32Base::GetGeometry() const
453 {
454 if ( m_info.m_rect.IsEmpty() )
455 m_info.Initialize();
456
457 return m_info.m_rect;
458 }
459
460 wxRect wxDisplayImplWin32Base::GetClientArea() const
461 {
462 if ( m_info.m_rectClient.IsEmpty() )
463 m_info.Initialize();
464
465 return m_info.m_rectClient;
466 }
467
468 wxString wxDisplayImplWin32Base::GetName() const
469 {
470 if ( m_info.m_devName.empty() )
471 m_info.Initialize();
472
473 return m_info.m_devName;
474 }
475
476 bool wxDisplayImplWin32Base::IsPrimary() const
477 {
478 if ( m_info.m_flags == (DWORD)-1 )
479 m_info.Initialize();
480
481 return (m_info.m_flags & MONITORINFOF_PRIMARY) != 0;
482 }
483
484 wxVideoMode wxDisplayImplWin32Base::GetCurrentMode() const
485 {
486 wxVideoMode mode;
487
488 // The first parameter of EnumDisplaySettings() must be NULL under Win95
489 // according to MSDN. The version of GetName() we implement for Win95
490 // returns an empty string.
491 const wxString name = GetName();
492 const wxChar * const deviceName = name.empty() ? NULL : name.c_str();
493
494 DEVMODE dm;
495 dm.dmSize = sizeof(dm);
496 dm.dmDriverExtra = 0;
497 if ( !::EnumDisplaySettings(deviceName, ENUM_CURRENT_SETTINGS, &dm) )
498 {
499 wxLogLastError(_T("EnumDisplaySettings(ENUM_CURRENT_SETTINGS)"));
500 }
501 else
502 {
503 mode = ConvertToVideoMode(dm);
504 }
505
506 return mode;
507 }
508
509 // ----------------------------------------------------------------------------
510 // wxDisplayFactoryWin32Base
511 // ----------------------------------------------------------------------------
512
513 int wxDisplayFactoryWin32Base::ms_supportsMultimon = -1;
514
515 wxDisplayFactoryWin32Base::wxDisplayFactoryWin32Base()
516 {
517 if ( ms_supportsMultimon == -1 )
518 {
519 ms_supportsMultimon = 0;
520
521 wxLogNull noLog;
522
523 wxDynamicLibrary dllDisplay(displayDllName, wxDL_VERBATIM);
524
525 gs_MonitorFromPoint = (MonitorFromPoint_t)
526 dllDisplay.GetSymbol(wxT("MonitorFromPoint"));
527 if ( !gs_MonitorFromPoint )
528 return;
529
530 gs_MonitorFromWindow = (MonitorFromWindow_t)
531 dllDisplay.GetSymbol(wxT("MonitorFromWindow"));
532 if ( !gs_MonitorFromWindow )
533 return;
534
535 gs_GetMonitorInfo = (GetMonitorInfo_t)
536 dllDisplay.GetSymbolAorW(wxT("GetMonitorInfo"));
537 if ( !gs_GetMonitorInfo )
538 return;
539
540 ms_supportsMultimon = 1;
541
542 // we can safely let dllDisplay go out of scope, the DLL itself will
543 // still remain loaded as all Win32 programs use it
544 }
545 }
546
547 void wxDisplayFactoryWin32Base::Clear()
548 {
549 WX_CLEAR_ARRAY(m_displays);
550 }
551
552 wxDisplayFactoryWin32Base::~wxDisplayFactoryWin32Base()
553 {
554 Clear();
555 }
556
557 // helper for GetFromPoint() and GetFromWindow()
558 int wxDisplayFactoryWin32Base::FindDisplayFromHMONITOR(HMONITOR hmon) const
559 {
560 if ( hmon )
561 {
562 const size_t count = m_displays.size();
563 for ( size_t n = 0; n < count; n++ )
564 {
565 if ( hmon == m_displays[n]->m_hmon )
566 return n;
567 }
568 }
569
570 return wxNOT_FOUND;
571 }
572
573 int wxDisplayFactoryWin32Base::GetFromPoint(const wxPoint& pt)
574 {
575 POINT pt2;
576 pt2.x = pt.x;
577 pt2.y = pt.y;
578
579 return FindDisplayFromHMONITOR(gs_MonitorFromPoint(pt2,
580 MONITOR_DEFAULTTONULL));
581 }
582
583 int wxDisplayFactoryWin32Base::GetFromWindow(wxWindow *window)
584 {
585 return FindDisplayFromHMONITOR(gs_MonitorFromWindow(GetHwndOf(window),
586 MONITOR_DEFAULTTONULL));
587 }
588
589 // ============================================================================
590 // wxDisplay implementation using Win32 multimon API
591 // ============================================================================
592
593 // ----------------------------------------------------------------------------
594 // wxDisplayFactoryMultimon initialization
595 // ----------------------------------------------------------------------------
596
597 wxDisplayFactoryMultimon::wxDisplayFactoryMultimon()
598 {
599 if ( !ms_supportsMultimon )
600 return;
601
602 // look up EnumDisplayMonitors() which we don't need with DirectDraw
603 // implementation
604 EnumDisplayMonitors_t pfnEnumDisplayMonitors;
605 {
606 wxLogNull noLog;
607
608 wxDynamicLibrary dllDisplay(displayDllName, wxDL_VERBATIM);
609 pfnEnumDisplayMonitors = (EnumDisplayMonitors_t)
610 dllDisplay.GetSymbol(wxT("EnumDisplayMonitors"));
611 if ( !pfnEnumDisplayMonitors )
612 return;
613 }
614
615 // enumerate all displays
616 if ( !pfnEnumDisplayMonitors(NULL, NULL, MultimonEnumProc, (LPARAM)this) )
617 {
618 wxLogLastError(wxT("EnumDisplayMonitors"));
619 }
620 }
621
622 /* static */
623 BOOL CALLBACK
624 wxDisplayFactoryMultimon::MultimonEnumProc(
625 HMONITOR hMonitor, // handle to display monitor
626 HDC WXUNUSED(hdcMonitor), // handle to monitor-appropriate device context
627 LPRECT lprcMonitor, // pointer to monitor intersection rectangle
628 LPARAM dwData // data passed from EnumDisplayMonitors (this)
629 )
630 {
631 wxDisplayFactoryMultimon *const self = (wxDisplayFactoryMultimon *)dwData;
632 self->AddDisplay(hMonitor, lprcMonitor);
633
634 // continue the enumeration
635 return TRUE;
636 }
637
638 // ----------------------------------------------------------------------------
639 // wxDisplayFactoryMultimon helper functions
640 // ----------------------------------------------------------------------------
641
642 void wxDisplayFactoryMultimon::AddDisplay(HMONITOR hMonitor, LPRECT lprcMonitor)
643 {
644 wxDisplayInfo *info = new wxDisplayInfo(hMonitor);
645
646 // we also store the display geometry
647 info->m_rect = wxRect(lprcMonitor->left, lprcMonitor->top,
648 lprcMonitor->right - lprcMonitor->left,
649 lprcMonitor->bottom - lprcMonitor->top);
650
651 // now add this monitor to the array
652 m_displays.Add(info);
653 }
654
655 // ----------------------------------------------------------------------------
656 // wxDisplayFactoryMultimon inherited pure virtuals implementation
657 // ----------------------------------------------------------------------------
658
659 wxDisplayImpl *wxDisplayFactoryMultimon::CreateDisplay(unsigned n)
660 {
661 wxCHECK_MSG( n < m_displays.size(), NULL, _T("invalid display index") );
662
663 return new wxDisplayImplMultimon(n, *(m_displays[n]));
664 }
665
666 // ----------------------------------------------------------------------------
667 // wxDisplayImplMultimon implementation
668 // ----------------------------------------------------------------------------
669
670 wxArrayVideoModes
671 wxDisplayImplMultimon::GetModes(const wxVideoMode& modeMatch) const
672 {
673 wxArrayVideoModes modes;
674
675 // The first parameter of EnumDisplaySettings() must be NULL under Win95
676 // according to MSDN. The version of GetName() we implement for Win95
677 // returns an empty string.
678 const wxString name = GetName();
679 const wxChar * const deviceName = name.empty() ? NULL : name.c_str();
680
681 DEVMODE dm;
682 dm.dmSize = sizeof(dm);
683 dm.dmDriverExtra = 0;
684 for ( int iModeNum = 0;
685 ::EnumDisplaySettings(deviceName, iModeNum, &dm);
686 iModeNum++ )
687 {
688 const wxVideoMode mode = ConvertToVideoMode(dm);
689 if ( mode.Matches(modeMatch) )
690 {
691 modes.Add(mode);
692 }
693 }
694
695 return modes;
696 }
697
698 bool wxDisplayImplMultimon::ChangeMode(const wxVideoMode& mode)
699 {
700 // prepare ChangeDisplaySettingsEx() parameters
701 DEVMODE dm;
702 DEVMODE *pDevMode;
703
704 int flags;
705
706 if ( mode == wxDefaultVideoMode )
707 {
708 // reset the video mode to default
709 pDevMode = NULL;
710 flags = 0;
711 }
712 else // change to the given mode
713 {
714 wxCHECK_MSG( mode.w && mode.h, false,
715 _T("at least the width and height must be specified") );
716
717 wxZeroMemory(dm);
718 dm.dmSize = sizeof(dm);
719 dm.dmDriverExtra = 0;
720 dm.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
721 dm.dmPelsWidth = mode.w;
722 dm.dmPelsHeight = mode.h;
723
724 if ( mode.bpp )
725 {
726 dm.dmFields |= DM_BITSPERPEL;
727 dm.dmBitsPerPel = mode.bpp;
728 }
729
730 if ( mode.refresh )
731 {
732 dm.dmFields |= DM_DISPLAYFREQUENCY;
733 dm.dmDisplayFrequency = mode.refresh;
734 }
735
736 pDevMode = &dm;
737
738 #ifdef __WXWINCE__
739 flags = 0;
740 #else // !__WXWINCE__
741 flags = CDS_FULLSCREEN;
742 #endif // __WXWINCE__/!__WXWINCE__
743 }
744
745
746 // get pointer to the function dynamically
747 //
748 // we're only called from the main thread, so it's ok to use static
749 // variable
750 static ChangeDisplaySettingsEx_t pfnChangeDisplaySettingsEx = NULL;
751 if ( !pfnChangeDisplaySettingsEx )
752 {
753 wxDynamicLibrary dllDisplay(displayDllName, wxDL_VERBATIM);
754 if ( dllDisplay.IsLoaded() )
755 {
756 pfnChangeDisplaySettingsEx = (ChangeDisplaySettingsEx_t)
757 dllDisplay.GetSymbolAorW(_T("ChangeDisplaySettingsEx"));
758 }
759 //else: huh, no user32.dll??
760
761 #ifndef __WXWINCE__
762 if ( !pfnChangeDisplaySettingsEx )
763 {
764 // we must be under Win95 and so there is no multiple monitors
765 // support anyhow
766 pfnChangeDisplaySettingsEx = ChangeDisplaySettingsExForWin95;
767 }
768 #endif // !__WXWINCE__
769 }
770
771 // do change the mode
772 switch ( pfnChangeDisplaySettingsEx
773 (
774 GetName(), // display name
775 pDevMode, // dev mode or NULL to reset
776 NULL, // reserved
777 flags,
778 NULL // pointer to video parameters (not used)
779 ) )
780 {
781 case DISP_CHANGE_SUCCESSFUL:
782 // ok
783 {
784 // If we have a top-level, full-screen frame, emulate
785 // the DirectX behavior and resize it. This makes this
786 // API quite a bit easier to use.
787 wxWindow *winTop = wxTheApp->GetTopWindow();
788 wxFrame *frameTop = wxDynamicCast(winTop, wxFrame);
789 if (frameTop && frameTop->IsFullScreen())
790 {
791 wxVideoMode current = GetCurrentMode();
792 frameTop->SetClientSize(current.w, current.h);
793 }
794 }
795 return true;
796
797 case DISP_CHANGE_BADMODE:
798 // don't complain about this, this is the only "expected" error
799 break;
800
801 default:
802 wxFAIL_MSG( _T("unexpected ChangeDisplaySettingsEx() return value") );
803 }
804
805 return false;
806 }
807
808
809 // ============================================================================
810 // DirectDraw-based wxDisplay implementation
811 // ============================================================================
812
813 #if wxUSE_DIRECTDRAW
814
815 // ----------------------------------------------------------------------------
816 // wxDisplayFactoryDirectDraw initialization
817 // ----------------------------------------------------------------------------
818
819 wxDisplayFactoryDirectDraw::wxDisplayFactoryDirectDraw()
820 {
821 if ( !ms_supportsMultimon )
822 return;
823
824 #if wxUSE_LOG
825 // suppress the errors if ddraw.dll is not found, we're prepared to handle
826 // this
827 wxLogNull noLog;
828 #endif
829
830 m_dllDDraw.Load(_T("ddraw.dll"));
831
832 if ( !m_dllDDraw.IsLoaded() )
833 return;
834
835 DirectDrawEnumerateEx_t pDDEnumEx = (DirectDrawEnumerateEx_t)
836 m_dllDDraw.GetSymbolAorW(_T("DirectDrawEnumerateEx"));
837 if ( !pDDEnumEx )
838 return;
839
840 // we can't continue without DirectDrawCreate() later, so resolve it right
841 // now and fail the initialization if it's not available
842 m_pfnDirectDrawCreate = (DirectDrawCreate_t)
843 m_dllDDraw.GetSymbol(_T("DirectDrawCreate"));
844 if ( !m_pfnDirectDrawCreate )
845 return;
846
847 if ( (*pDDEnumEx)(DDEnumExCallback,
848 this,
849 DDENUM_ATTACHEDSECONDARYDEVICES) != DD_OK )
850 {
851 wxLogLastError(_T("DirectDrawEnumerateEx"));
852 }
853 }
854
855 wxDisplayFactoryDirectDraw::~wxDisplayFactoryDirectDraw()
856 {
857 // we must clear m_displays now, before m_dllDDraw is unloaded as otherwise
858 // calling m_pDD2->Release() later would crash
859 Clear();
860 }
861
862 // ----------------------------------------------------------------------------
863 // callbacks for monitor/modes enumeration stuff
864 // ----------------------------------------------------------------------------
865
866 BOOL WINAPI
867 wxDisplayFactoryDirectDraw::DDEnumExCallback(GUID *pGuid,
868 LPTSTR WXUNUSED(driverDescription),
869 LPTSTR driverName,
870 LPVOID lpContext,
871 HMONITOR hmon)
872 {
873 if ( pGuid )
874 {
875 wxDisplayFactoryDirectDraw * self =
876 wx_static_cast(wxDisplayFactoryDirectDraw *, lpContext);
877 self->AddDisplay(*pGuid, hmon, driverName);
878 }
879 //else: we're called for the primary monitor, skip it
880
881 // continue the enumeration
882 return TRUE;
883 }
884
885 // ----------------------------------------------------------------------------
886 // wxDisplayFactoryDirectDraw helpers
887 // ----------------------------------------------------------------------------
888
889 void wxDisplayFactoryDirectDraw::AddDisplay(const GUID& guid,
890 HMONITOR hmon,
891 LPTSTR name)
892 {
893 m_displays.Add(new wxDisplayInfoDirectDraw(guid, hmon, name));
894 }
895
896 // ----------------------------------------------------------------------------
897 // wxDisplayFactoryDirectDraw inherited pure virtuals implementation
898 // ----------------------------------------------------------------------------
899
900 wxDisplayImpl *wxDisplayFactoryDirectDraw::CreateDisplay(unsigned n)
901 {
902 wxCHECK_MSG( n < m_displays.size(), NULL, _T("invalid display index") );
903
904 wxDisplayInfoDirectDraw *
905 info = wx_static_cast(wxDisplayInfoDirectDraw *, m_displays[n]);
906
907 if ( !info->m_pDD2 )
908 {
909 IDirectDraw *pDD;
910 GUID guid(info->m_guid);
911 HRESULT hr = (*m_pfnDirectDrawCreate)(&guid, &pDD, NULL);
912
913 if ( FAILED(hr) || !pDD )
914 {
915 // what to do??
916 wxLogApiError(_T("DirectDrawCreate"), hr);
917 return NULL;
918 }
919
920 // we got IDirectDraw, but we need IDirectDraw2
921 hr = pDD->QueryInterface(wxIID_IDirectDraw2, (void **)&info->m_pDD2);
922 pDD->Release();
923
924 if ( FAILED(hr) || !info->m_pDD2 )
925 {
926 wxLogApiError(_T("IDirectDraw::QueryInterface(IDD2)"), hr);
927 return NULL;
928 }
929
930 // NB: m_pDD2 will now be only destroyed when m_displays is destroyed
931 // which is ok as we don't want to recreate DD objects all the time
932 }
933 //else: DirectDraw object corresponding to our display already exists
934
935 return new wxDisplayImplDirectDraw(n, *info, info->m_pDD2);
936 }
937
938 // ============================================================================
939 // wxDisplayImplDirectDraw
940 // ============================================================================
941
942 // ----------------------------------------------------------------------------
943 // video modes enumeration
944 // ----------------------------------------------------------------------------
945
946 // tiny helper class used to pass information from GetModes() to
947 // wxDDEnumModesCallback
948 class wxDDVideoModesAdder
949 {
950 public:
951 // our Add() method will add modes matching modeMatch to modes array
952 wxDDVideoModesAdder(wxArrayVideoModes& modes, const wxVideoMode& modeMatch)
953 : m_modes(modes),
954 m_modeMatch(modeMatch)
955 {
956 }
957
958 void Add(const wxVideoMode& mode)
959 {
960 if ( mode.Matches(m_modeMatch) )
961 m_modes.Add(mode);
962 }
963
964 private:
965 wxArrayVideoModes& m_modes;
966 const wxVideoMode& m_modeMatch;
967
968 DECLARE_NO_COPY_CLASS(wxDDVideoModesAdder)
969 };
970
971 HRESULT WINAPI wxDDEnumModesCallback(LPDDSURFACEDESC lpDDSurfaceDesc,
972 LPVOID lpContext)
973 {
974 // we need at least the mode size
975 static const DWORD FLAGS_REQUIRED = DDSD_HEIGHT | DDSD_WIDTH;
976 if ( (lpDDSurfaceDesc->dwFlags & FLAGS_REQUIRED) == FLAGS_REQUIRED )
977 {
978 wxDDVideoModesAdder * const vmodes =
979 wx_static_cast(wxDDVideoModesAdder *, lpContext);
980
981 vmodes->Add(wxVideoMode(lpDDSurfaceDesc->dwWidth,
982 lpDDSurfaceDesc->dwHeight,
983 lpDDSurfaceDesc->ddpfPixelFormat.dwRGBBitCount,
984 lpDDSurfaceDesc->dwRefreshRate));
985 }
986
987 // continue the enumeration
988 return DDENUMRET_OK;
989 }
990
991 wxArrayVideoModes
992 wxDisplayImplDirectDraw::GetModes(const wxVideoMode& modeMatch) const
993 {
994 wxArrayVideoModes modes;
995 wxDDVideoModesAdder modesAdder(modes, modeMatch);
996
997 HRESULT hr = m_pDD2->EnumDisplayModes
998 (
999 DDEDM_REFRESHRATES,
1000 NULL, // all modes
1001 &modesAdder, // callback parameter
1002 wxDDEnumModesCallback
1003 );
1004
1005 if ( FAILED(hr) )
1006 {
1007 wxLogApiError(_T("IDirectDraw::EnumDisplayModes"), hr);
1008 }
1009
1010 return modes;
1011 }
1012
1013 // ----------------------------------------------------------------------------
1014 // video mode switching
1015 // ----------------------------------------------------------------------------
1016
1017 bool wxDisplayImplDirectDraw::ChangeMode(const wxVideoMode& mode)
1018 {
1019 wxWindow *winTop = wxTheApp->GetTopWindow();
1020 wxCHECK_MSG( winTop, false, _T("top level window required for DirectX") );
1021
1022 HRESULT hr = m_pDD2->SetCooperativeLevel
1023 (
1024 GetHwndOf(winTop),
1025 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN
1026 );
1027 if ( FAILED(hr) )
1028 {
1029 wxLogApiError(_T("IDirectDraw2::SetCooperativeLevel"), hr);
1030
1031 return false;
1032 }
1033
1034 hr = m_pDD2->SetDisplayMode(mode.w, mode.h, mode.bpp, mode.refresh, 0);
1035 if ( FAILED(hr) )
1036 {
1037 wxLogApiError(_T("IDirectDraw2::SetDisplayMode"), hr);
1038
1039 return false;
1040 }
1041
1042 return true;
1043 }
1044
1045 #endif // wxUSE_DIRECTDRAW
1046
1047 #endif // wxUSE_DISPLAY

  ViewVC Help
Powered by ViewVC 1.1.22