-typedef BOOL (PASCAL *DDEnumExCallback_t)(GUID *pGuid,
- LPTSTR driverDescription,
- LPTSTR driverName,
- LPVOID lpContext,
- HMONITOR hmon);
-
-typedef HRESULT (WINAPI *DirectDrawEnumerateEx_t)(DDEnumExCallback_t lpCallback,
- LPVOID lpContext,
- DWORD dwFlags);
-
-typedef HRESULT (WINAPI *DirectDrawCreate_t)(GUID *lpGUID,
- LPDIRECTDRAW *lplpDD,
- IUnknown *pUnkOuter);
-
-// ----------------------------------------------------------------------------
-// private classes
-// ----------------------------------------------------------------------------
-
-class wxDisplayInfo
-{
-public:
- // handle of this monitor used by MonitorXXX() functions, never NULL
- HMONITOR m_hmon;
-
- // IDirectDraw object used to control this display, may be NULL
- IDirectDraw2 *m_pDD2;
-
- // DirectDraw GUID for this display, only valid when using DirectDraw
- GUID m_guid;
-
- // the entire area of this monitor in virtual screen coordinates
- wxRect m_rect;
-
- // the display device name for this monitor, empty initially and retrieved
- // on demand by DoGetName()
- wxString m_devName;
-
- wxDisplayInfo() { m_hmon = NULL; m_pDD2 = NULL; }
- ~wxDisplayInfo() { if ( m_pDD2 ) m_pDD2->Release(); }
-};
-
-WX_DECLARE_OBJARRAY(wxDisplayInfo, wxDisplayInfoArray);
-#include "wx/arrimpl.cpp"
-WX_DEFINE_OBJARRAY(wxDisplayInfoArray);
-
-// this module is used to cleanup gs_displays array
-class wxDisplayModule : public wxModule
-{
-public:
- virtual bool OnInit() { return true; }
- virtual void OnExit();
-
- DECLARE_DYNAMIC_CLASS(wxDisplayModule)
-};
-
-IMPLEMENT_DYNAMIC_CLASS(wxDisplayModule, wxModule)
-
-// ----------------------------------------------------------------------------
-// globals
-// ----------------------------------------------------------------------------
-
-// do we use DirectX?
-static bool gs_useDirectX = false;
-
-// dynamically resolved DirectDrawCreate()
-static DirectDrawCreate_t gs_DirectDrawCreate = NULL;
-
-// this is not really MT-unsafe as wxDisplay is only going to be used from the
-// main thread, i.e. we consider that it's a GUI class and so don't protect it
-static wxDisplayInfoArray *gs_displays = NULL;
-
-// ===========================================================================
-// implementation
-// ===========================================================================
-
-// ----------------------------------------------------------------------------
-// callbacks for monitor/modes enumeration stuff
-// ----------------------------------------------------------------------------
-
-static BOOL CALLBACK wxmswMonitorEnumProc (
- HMONITOR hMonitor, // handle to display monitor
- HDC WXUNUSED(hdcMonitor), // handle to monitor-appropriate device context
- LPRECT lprcMonitor, // pointer to monitor intersection rectangle
- LPARAM WXUNUSED(dwData) // data passed from EnumDisplayMonitors (unused)
-)
-{
- wxDisplayInfo *info = new wxDisplayInfo();
-
- // we need hMonitor to be able to map display id to it which is needed for
- // MonitorXXX() functions, in particular MonitorFromPoint()
- info->m_hmon = hMonitor;
-
- // we also store the display geometry
- info->m_rect.SetX ( lprcMonitor->left );
- info->m_rect.SetY ( lprcMonitor->top );
- info->m_rect.SetWidth ( lprcMonitor->right - lprcMonitor->left );
- info->m_rect.SetHeight ( lprcMonitor->bottom - lprcMonitor->top );
-
- // now add this monitor to the array
- gs_displays->Add(info);
-
- // continue the enumeration
- return true;
-}
-
-BOOL PASCAL
-wxDDEnumExCallback(GUID *pGuid,
- LPTSTR WXUNUSED(driverDescription),
- LPTSTR driverName,
- LPVOID WXUNUSED(lpContext),
- HMONITOR hmon)
-{
- if ( pGuid )
- {
- wxDisplayInfo *info = new wxDisplayInfo();
-
- info->m_hmon = hmon;
- info->m_guid = *pGuid;
- info->m_devName = driverName;
-
- gs_displays->Add(info);
- }
- //else: we're called for the primary monitor, skip it
-
- // continue the enumeration
- return true;
-}
-
-HRESULT WINAPI wxDDEnumModesCallback(LPDDSURFACEDESC lpDDSurfaceDesc,
- LPVOID lpContext)
-{
- // we need at least the mode size
- static const DWORD FLAGS_REQUIRED = DDSD_HEIGHT | DDSD_WIDTH;
- if ( (lpDDSurfaceDesc->dwFlags & FLAGS_REQUIRED) == FLAGS_REQUIRED )
- {
- wxArrayVideoModes * const modes = (wxArrayVideoModes *)lpContext;
-
- modes->Add(wxVideoMode(lpDDSurfaceDesc->dwWidth,
- lpDDSurfaceDesc->dwHeight,
- lpDDSurfaceDesc->ddpfPixelFormat.dwRGBBitCount,
- lpDDSurfaceDesc->dwRefreshRate));
- }
-
- // continue the enumeration
- return DDENUMRET_OK;
-}
-
-// ----------------------------------------------------------------------------
-// local functions
-// ----------------------------------------------------------------------------
-
-// initialize gs_displays using DirectX functions
-static bool DoInitDirectX()
-{
-#if wxUSE_LOG
- // suppress the errors if ddraw.dll is not found
- wxLog::EnableLogging(false);
-#endif
-
- wxDynamicLibrary dllDX(_T("ddraw.dll"));
-
-#if wxUSE_LOG
- wxLog::EnableLogging();
-#endif
-
- if ( !dllDX.IsLoaded() )
- return false;
-
- DirectDrawEnumerateEx_t pDDEnumEx = (DirectDrawEnumerateEx_t)
- dllDX.GetSymbol(WINFUNC(DirectDrawEnumerateEx));
- if ( !pDDEnumEx )
- return false;
-
- // we'll also need DirectDrawCreate() later, resolve it right now
- gs_DirectDrawCreate = (DirectDrawCreate_t)
- dllDX.GetSymbol(_T("DirectDrawCreate"));
- if ( !gs_DirectDrawCreate )
- return false;
-
- if ( (*pDDEnumEx)(wxDDEnumExCallback,
- NULL,
- DDENUM_ATTACHEDSECONDARYDEVICES) != DD_OK )
- {
- return false;
- }
-
- // ok, it seems like we're going to use DirectDraw and so we're going to
- // need ddraw.dll all the time, don't unload it
- dllDX.Detach();
-
- return true;
-}
-
-// initialize gs_displays using the standard Windows functions
-static void DoInitStdWindows()
-{
- // enumerate all displays
- if ( !::EnumDisplayMonitors(NULL, NULL, wxmswMonitorEnumProc, 0) )
- {
- wxLogLastError(wxT("EnumDisplayMonitors"));
-
- // TODO: still create at least one (valid) entry in gs_displays for the
- // primary display!
- }
-}
-
-// this function must be called before accessing gs_displays array as it
-// creates and initializes it
-static void InitDisplays()
-{
- if ( gs_displays )
- return;
-
- gs_displays = new wxDisplayInfoArray();
-
- if ( !gs_useDirectX || !DoInitDirectX() )
- {
- // either we were told not to try to use DirectX or fall back to std
- // functions if DirectX method failed
- gs_useDirectX = false;
-
- DoInitStdWindows();
- }
-}
-
-// convert a DEVMODE to our wxVideoMode
-wxVideoMode ConvertToVideoMode(const DEVMODE& dm)
-{
- // note that dmDisplayFrequency may be 0 or 1 meaning "standard one" and
- // although 0 is ok for us we don't want to return modes with 1hz refresh
- return wxVideoMode(dm.dmPelsWidth,
- dm.dmPelsHeight,
- dm.dmBitsPerPel,
- dm.dmDisplayFrequency > 1 ? dm.dmDisplayFrequency : 0);
-}