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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 32 - (hide annotations) (download)
Tue Sep 7 03:29:01 2010 UTC (10 years 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 william 31 /////////////////////////////////////////////////////////////////////////////
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