| 140 | | // ---------------------------------------------------------------------------- |
| 141 | | // display information classes |
| 142 | | // ---------------------------------------------------------------------------- |
| 143 | | |
| 144 | | struct wxDisplayInfo |
| 145 | | { |
| 146 | | wxDisplayInfo(HMONITOR hmon = NULL) |
| 147 | | { |
| 148 | | m_hmon = hmon; |
| 149 | | m_flags = (DWORD)-1; |
| 150 | | } |
| 151 | | |
| 152 | | virtual ~wxDisplayInfo() { } |
| 153 | | |
| 154 | | |
| 155 | | // use GetMonitorInfo() to fill in all of our fields if needed (i.e. if it |
| 156 | | // hadn't been done before) |
| 157 | | void Initialize(); |
| 158 | | |
| 159 | | |
| 160 | | // handle of this monitor used by MonitorXXX() functions, never NULL |
| 161 | | HMONITOR m_hmon; |
| 162 | | |
| 163 | | // the entire area of this monitor in virtual screen coordinates |
| 164 | | wxRect m_rect; |
| 165 | | |
| 166 | | // the work or client area, i.e. the area available for the normal windows |
| 167 | | wxRect m_rectClient; |
| 168 | | |
| 169 | | // the display device name for this monitor, empty initially and retrieved |
| 170 | | // on demand by DoGetName() |
| 171 | | wxString m_devName; |
| 172 | | |
| 173 | | // the flags of this monitor, also used as initialization marker: if this |
| 174 | | // is -1, GetMonitorInfo() hadn't been called yet |
| 175 | | DWORD m_flags; |
| 176 | | }; |
| 177 | | |
| 178 | | WX_DEFINE_ARRAY_PTR(wxDisplayInfo *, wxDisplayInfoArray); |
| 179 | | |
| 180 | | // ---------------------------------------------------------------------------- |
| 181 | | // common base class for all Win32 wxDisplayImpl versions |
| 182 | | // ---------------------------------------------------------------------------- |
| 183 | | |
| 184 | | class wxDisplayImplWin32Base : public wxDisplayImpl |
| | 107 | |
| | 108 | // ---------------------------------------------------------------------------- |
| | 109 | // wxDisplayMSW declaration |
| | 110 | // ---------------------------------------------------------------------------- |
| | 111 | |
| | 112 | class wxDisplayMSW : public wxDisplayImpl |
| 235 | | |
| 236 | | protected: |
| 237 | | // ctor checks if the current system supports multimon API and dynamically |
| 238 | | // bind the functions we need if this is the case and sets |
| 239 | | // ms_supportsMultimon if they're available |
| 240 | | wxDisplayFactoryWin32Base(); |
| 241 | | |
| 242 | | // delete all m_displays elements: can be called from the derived class |
| 243 | | // dtor if it is important to do this before destroying it (as in |
| 244 | | // wxDisplayFactoryDirectDraw case), otherwise will be done by our dtor |
| 245 | | void Clear(); |
| 246 | | |
| 247 | | // find the monitor corresponding to the given handle, return wxNOT_FOUND |
| 248 | | // if not found |
| 249 | | int FindDisplayFromHMONITOR(HMONITOR hmon) const; |
| 250 | | |
| 251 | | |
| 252 | | // flag indicating whether gs_MonitorXXX functions are available |
| 253 | | static int ms_supportsMultimon; |
| 254 | | |
| 255 | | // the array containing information about all available displays, should be |
| 256 | | // filled by the derived class ctors |
| 257 | | wxDisplayInfoArray m_displays; |
| 258 | | |
| 259 | | |
| 260 | | wxDECLARE_NO_COPY_CLASS(wxDisplayFactoryWin32Base); |
| 261 | | }; |
| 262 | | |
| 263 | | // ---------------------------------------------------------------------------- |
| 264 | | // wxDisplay implementation using Windows multi-monitor support functions |
| 265 | | // ---------------------------------------------------------------------------- |
| 266 | | |
| 267 | | class wxDisplayImplMultimon : public wxDisplayImplWin32Base |
| 268 | | { |
| 269 | | public: |
| 270 | | wxDisplayImplMultimon(unsigned n, wxDisplayInfo& info) |
| 271 | | : wxDisplayImplWin32Base(n, info) |
| 272 | | { |
| 273 | | } |
| 274 | | |
| 275 | | virtual wxArrayVideoModes GetModes(const wxVideoMode& mode) const; |
| 276 | | virtual bool ChangeMode(const wxVideoMode& mode); |
| 277 | | |
| 278 | | private: |
| 279 | | wxDECLARE_NO_COPY_CLASS(wxDisplayImplMultimon); |
| 280 | | }; |
| 281 | | |
| 282 | | class wxDisplayFactoryMultimon : public wxDisplayFactoryWin32Base |
| 283 | | { |
| 284 | | public: |
| 285 | | wxDisplayFactoryMultimon(); |
| 286 | | |
| 287 | | virtual wxDisplayImpl *CreateDisplay(unsigned n); |
| 301 | | // ---------------------------------------------------------------------------- |
| 302 | | // wxDisplay implementation using DirectDraw |
| 303 | | // ---------------------------------------------------------------------------- |
| 304 | | |
| 305 | | #if wxUSE_DIRECTDRAW |
| 306 | | |
| 307 | | struct wxDisplayInfoDirectDraw : wxDisplayInfo |
| 308 | | { |
| 309 | | wxDisplayInfoDirectDraw(const GUID& guid, HMONITOR hmon, LPTSTR name) |
| 310 | | : wxDisplayInfo(hmon), |
| 311 | | m_guid(guid) |
| 312 | | { |
| 313 | | m_pDD2 = NULL; |
| 314 | | m_devName = name; |
| 315 | | } |
| 316 | | |
| 317 | | virtual ~wxDisplayInfoDirectDraw() |
| 318 | | { |
| 319 | | if ( m_pDD2 ) |
| 320 | | m_pDD2->Release(); |
| 321 | | } |
| 322 | | |
| 323 | | |
| 324 | | // IDirectDraw object used to control this display, may be NULL |
| 325 | | IDirectDraw2 *m_pDD2; |
| 326 | | |
| 327 | | // DirectDraw GUID for this display, only valid when using DirectDraw |
| 328 | | const GUID m_guid; |
| 329 | | |
| 330 | | |
| 331 | | wxDECLARE_NO_COPY_CLASS(wxDisplayInfoDirectDraw); |
| 332 | | }; |
| 333 | | |
| 334 | | class wxDisplayImplDirectDraw : public wxDisplayImplWin32Base |
| 335 | | { |
| 336 | | public: |
| 337 | | wxDisplayImplDirectDraw(unsigned n, wxDisplayInfo& info, IDirectDraw2 *pDD2) |
| 338 | | : wxDisplayImplWin32Base(n, info), |
| 339 | | m_pDD2(pDD2) |
| 340 | | { |
| 341 | | m_pDD2->AddRef(); |
| 342 | | } |
| 343 | | |
| 344 | | virtual ~wxDisplayImplDirectDraw() |
| 345 | | { |
| 346 | | m_pDD2->Release(); |
| 347 | | } |
| 348 | | |
| 349 | | virtual wxArrayVideoModes GetModes(const wxVideoMode& mode) const; |
| 350 | | virtual bool ChangeMode(const wxVideoMode& mode); |
| 351 | | |
| 352 | | private: |
| 353 | | IDirectDraw2 *m_pDD2; |
| 354 | | |
| 355 | | wxDECLARE_NO_COPY_CLASS(wxDisplayImplDirectDraw); |
| 356 | | }; |
| 357 | | |
| 358 | | class wxDisplayFactoryDirectDraw : public wxDisplayFactoryWin32Base |
| 359 | | { |
| 360 | | public: |
| 361 | | wxDisplayFactoryDirectDraw(); |
| 362 | | virtual ~wxDisplayFactoryDirectDraw(); |
| 363 | | |
| 364 | | virtual wxDisplayImpl *CreateDisplay(unsigned n); |
| 365 | | |
| 366 | | private: |
| 367 | | // callback used with DirectDrawEnumerateEx() |
| 368 | | static BOOL WINAPI DDEnumExCallback(GUID *pGuid, |
| 369 | | LPTSTR driverDescription, |
| 370 | | LPTSTR driverName, |
| 371 | | LPVOID lpContext, |
| 372 | | HMONITOR hmon); |
| 373 | | |
| 374 | | // add a monitor description to m_displays array |
| 375 | | void AddDisplay(const GUID& guid, HMONITOR hmon, LPTSTR name); |
| 376 | | |
| 377 | | |
| 378 | | // ddraw.dll |
| 379 | | wxDynamicLibrary m_dllDDraw; |
| 380 | | |
| 381 | | // dynamically resolved DirectDrawCreate() |
| 382 | | DirectDrawCreate_t m_pfnDirectDrawCreate; |
| 383 | | |
| 384 | | wxDECLARE_NO_COPY_CLASS(wxDisplayFactoryDirectDraw); |
| 385 | | }; |
| 386 | | |
| 387 | | #endif // wxUSE_DIRECTDRAW |
| 388 | | |
| 389 | | |
| 390 | | // ============================================================================ |
| 391 | | // common classes implementation |
| 392 | | // ============================================================================ |
| 393 | | |
| 394 | | // ---------------------------------------------------------------------------- |
| 395 | | // wxDisplay |
| | 195 | |
| | 196 | // ---------------------------------------------------------------------------- |
| | 197 | // wxDisplay implementation |
| 426 | | // ---------------------------------------------------------------------------- |
| 427 | | // wxDisplayInfo |
| 428 | | // ---------------------------------------------------------------------------- |
| 429 | | |
| 430 | | void wxDisplayInfo::Initialize() |
| 431 | | { |
| 432 | | if ( m_flags == (DWORD)-1 ) |
| 433 | | { |
| 434 | | WinStruct<MONITORINFOEX> monInfo; |
| 435 | | if ( !gs_GetMonitorInfo(m_hmon, (LPMONITORINFO)&monInfo) ) |
| 436 | | { |
| 437 | | wxLogLastError(wxT("GetMonitorInfo")); |
| 438 | | m_flags = 0; |
| 439 | | return; |
| 440 | | } |
| 441 | | |
| 442 | | wxCopyRECTToRect(monInfo.rcMonitor, m_rect); |
| 443 | | wxCopyRECTToRect(monInfo.rcWork, m_rectClient); |
| 444 | | m_devName = monInfo.szDevice; |
| 445 | | m_flags = monInfo.dwFlags; |
| 446 | | } |
| 447 | | } |
| 448 | | |
| 449 | | // ---------------------------------------------------------------------------- |
| 450 | | // wxDisplayImplWin32Base |
| 451 | | // ---------------------------------------------------------------------------- |
| 452 | | |
| 453 | | wxRect wxDisplayImplWin32Base::GetGeometry() const |
| 454 | | { |
| 455 | | if ( m_info.m_rect.IsEmpty() ) |
| 456 | | m_info.Initialize(); |
| 457 | | |
| 458 | | return m_info.m_rect; |
| 459 | | } |
| 460 | | |
| 461 | | wxRect wxDisplayImplWin32Base::GetClientArea() const |
| 462 | | { |
| 463 | | if ( m_info.m_rectClient.IsEmpty() ) |
| 464 | | m_info.Initialize(); |
| 465 | | |
| 466 | | return m_info.m_rectClient; |
| 467 | | } |
| 468 | | |
| 469 | | wxString wxDisplayImplWin32Base::GetName() const |
| 470 | | { |
| 471 | | if ( m_info.m_devName.empty() ) |
| 472 | | m_info.Initialize(); |
| 473 | | |
| 474 | | return m_info.m_devName; |
| 475 | | } |
| 476 | | |
| 477 | | bool wxDisplayImplWin32Base::IsPrimary() const |
| 478 | | { |
| 479 | | if ( m_info.m_flags == (DWORD)-1 ) |
| 480 | | m_info.Initialize(); |
| 481 | | |
| 482 | | return (m_info.m_flags & MONITORINFOF_PRIMARY) != 0; |
| 483 | | } |
| 484 | | |
| 485 | | wxVideoMode wxDisplayImplWin32Base::GetCurrentMode() const |
| | 213 | |
| | 214 | // ---------------------------------------------------------------------------- |
| | 215 | // wxDisplayMSW implementation |
| | 216 | // ---------------------------------------------------------------------------- |
| | 217 | |
| | 218 | wxRect wxDisplayMSW::GetGeometry() const |
| | 219 | { |
| | 220 | WinStruct<MONITORINFOEX> monInfo; |
| | 221 | |
| | 222 | if ( !gs_GetMonitorInfo(m_hmon, (LPMONITORINFO)&monInfo) ) |
| | 223 | { |
| | 224 | wxLogLastError(wxT(__FUNCTION__)); |
| | 225 | return wxRect(); |
| | 226 | } |
| | 227 | |
| | 228 | wxRect rect; |
| | 229 | wxCopyRECTToRect(monInfo.rcMonitor, rect); |
| | 230 | |
| | 231 | return rect; |
| | 232 | } |
| | 233 | |
| | 234 | wxRect wxDisplayMSW::GetClientArea() const |
| | 235 | { |
| | 236 | WinStruct<MONITORINFOEX> monInfo; |
| | 237 | |
| | 238 | if ( !gs_GetMonitorInfo(m_hmon, (LPMONITORINFO)&monInfo) ) |
| | 239 | { |
| | 240 | wxLogLastError(wxT(__FUNCTION__)); |
| | 241 | return wxRect(); |
| | 242 | } |
| | 243 | |
| | 244 | wxRect rectClient; |
| | 245 | wxCopyRECTToRect(monInfo.rcWork, rectClient); |
| | 246 | |
| | 247 | return rectClient; |
| | 248 | } |
| | 249 | |
| | 250 | wxString wxDisplayMSW::GetName() const |
| | 251 | { |
| | 252 | WinStruct<MONITORINFOEX> monInfo; |
| | 253 | |
| | 254 | if ( !gs_GetMonitorInfo(m_hmon, (LPMONITORINFO)&monInfo) ) |
| | 255 | { |
| | 256 | wxLogLastError(wxT(__FUNCTION__)); |
| | 257 | return ""; |
| | 258 | } |
| | 259 | |
| | 260 | return monInfo.szDevice; |
| | 261 | } |
| | 262 | |
| | 263 | bool wxDisplayMSW::IsPrimary() const |
| | 264 | { |
| | 265 | WinStruct<MONITORINFOEX> monInfo; |
| | 266 | |
| | 267 | if ( !gs_GetMonitorInfo(m_hmon, (LPMONITORINFO)&monInfo) ) |
| | 268 | { |
| | 269 | wxLogLastError(wxT(__FUNCTION__)); |
| | 270 | return false; |
| | 271 | } |
| | 272 | |
| | 273 | return (monInfo.dwFlags & MONITORINFOF_PRIMARY) != 0; |
| | 274 | } |
| | 275 | |
| | 276 | wxVideoMode wxDisplayMSW::GetCurrentMode() const |
| 512 | | // ---------------------------------------------------------------------------- |
| 513 | | // wxDisplayFactoryWin32Base |
| 514 | | // ---------------------------------------------------------------------------- |
| 515 | | |
| 516 | | int wxDisplayFactoryWin32Base::ms_supportsMultimon = -1; |
| 517 | | |
| 518 | | wxDisplayFactoryWin32Base::wxDisplayFactoryWin32Base() |
| 519 | | { |
| 520 | | if ( ms_supportsMultimon == -1 ) |
| 521 | | { |
| 522 | | ms_supportsMultimon = 0; |
| 523 | | |
| 524 | | wxDynamicLibrary dllDisplay(displayDllName, wxDL_VERBATIM | wxDL_QUIET); |
| 525 | | |
| 526 | | if ( (wxDL_INIT_FUNC(gs_, MonitorFromPoint, dllDisplay)) == NULL || |
| 527 | | (wxDL_INIT_FUNC(gs_, MonitorFromWindow, dllDisplay)) == NULL || |
| 528 | | (wxDL_INIT_FUNC_AW(gs_, GetMonitorInfo, dllDisplay)) == NULL ) |
| 529 | | return; |
| 530 | | |
| 531 | | ms_supportsMultimon = 1; |
| 532 | | |
| 533 | | // we can safely let dllDisplay go out of scope, the DLL itself will |
| 534 | | // still remain loaded as all programs link to it statically anyhow |
| 535 | | } |
| 536 | | } |
| 537 | | |
| 538 | | void wxDisplayFactoryWin32Base::Clear() |
| 539 | | { |
| 540 | | WX_CLEAR_ARRAY(m_displays); |
| 541 | | } |
| 542 | | |
| 543 | | wxDisplayFactoryWin32Base::~wxDisplayFactoryWin32Base() |
| 544 | | { |
| 545 | | Clear(); |
| 546 | | } |
| 547 | | |
| 548 | | // helper for GetFromPoint() and GetFromWindow() |
| 549 | | int wxDisplayFactoryWin32Base::FindDisplayFromHMONITOR(HMONITOR hmon) const |
| 550 | | { |
| 551 | | if ( hmon ) |
| 552 | | { |
| 553 | | const size_t count = m_displays.size(); |
| 554 | | for ( size_t n = 0; n < count; n++ ) |
| 555 | | { |
| 556 | | if ( hmon == m_displays[n]->m_hmon ) |
| 557 | | return n; |
| 558 | | } |
| 559 | | } |
| 560 | | |
| 561 | | return wxNOT_FOUND; |
| 562 | | } |
| 563 | | |
| 564 | | int wxDisplayFactoryWin32Base::GetFromPoint(const wxPoint& pt) |
| 565 | | { |
| 566 | | POINT pt2; |
| 567 | | pt2.x = pt.x; |
| 568 | | pt2.y = pt.y; |
| 569 | | |
| 570 | | return FindDisplayFromHMONITOR(gs_MonitorFromPoint(pt2, |
| 571 | | MONITOR_DEFAULTTONULL)); |
| 572 | | } |
| 573 | | |
| 574 | | int wxDisplayFactoryWin32Base::GetFromWindow(const wxWindow *window) |
| 575 | | { |
| 576 | | return FindDisplayFromHMONITOR(gs_MonitorFromWindow(GetHwndOf(window), |
| 577 | | MONITOR_DEFAULTTONULL)); |
| 578 | | } |
| 579 | | |
| 580 | | // ============================================================================ |
| 581 | | // wxDisplay implementation using Win32 multimon API |
| 582 | | // ============================================================================ |
| 583 | | |
| 584 | | // ---------------------------------------------------------------------------- |
| 585 | | // wxDisplayFactoryMultimon initialization |
| 586 | | // ---------------------------------------------------------------------------- |
| 587 | | |
| 588 | | wxDisplayFactoryMultimon::wxDisplayFactoryMultimon() |
| 589 | | { |
| 590 | | if ( !ms_supportsMultimon ) |
| 591 | | return; |
| 592 | | |
| 593 | | // look up EnumDisplayMonitors() which we don't need with DirectDraw |
| 594 | | // implementation |
| 595 | | EnumDisplayMonitors_t pfnEnumDisplayMonitors; |
| 596 | | { |
| 597 | | wxDynamicLibrary dllDisplay(displayDllName, wxDL_VERBATIM | wxDL_QUIET); |
| 598 | | if ( (wxDL_INIT_FUNC(pfn, EnumDisplayMonitors, dllDisplay)) == NULL ) |
| 599 | | return; |
| 600 | | } |
| 601 | | |
| 602 | | // enumerate all displays |
| 603 | | if ( !pfnEnumDisplayMonitors(NULL, NULL, MultimonEnumProc, (LPARAM)this) ) |
| 604 | | { |
| 605 | | wxLogLastError(wxT("EnumDisplayMonitors")); |
| 606 | | } |
| 607 | | } |
| 608 | | |
| 609 | | /* static */ |
| 610 | | BOOL CALLBACK |
| 611 | | wxDisplayFactoryMultimon::MultimonEnumProc( |
| 612 | | HMONITOR hMonitor, // handle to display monitor |
| 613 | | HDC WXUNUSED(hdcMonitor), // handle to monitor-appropriate device context |
| 614 | | LPRECT lprcMonitor, // pointer to monitor intersection rectangle |
| 615 | | LPARAM dwData // data passed from EnumDisplayMonitors (this) |
| 616 | | ) |
| 617 | | { |
| 618 | | wxDisplayFactoryMultimon *const self = (wxDisplayFactoryMultimon *)dwData; |
| 619 | | self->AddDisplay(hMonitor, lprcMonitor); |
| 620 | | |
| 621 | | // continue the enumeration |
| 622 | | return TRUE; |
| 623 | | } |
| 624 | | |
| 625 | | // ---------------------------------------------------------------------------- |
| 626 | | // wxDisplayFactoryMultimon helper functions |
| 627 | | // ---------------------------------------------------------------------------- |
| 628 | | |
| 629 | | void wxDisplayFactoryMultimon::AddDisplay(HMONITOR hMonitor, LPRECT lprcMonitor) |
| 630 | | { |
| 631 | | wxDisplayInfo *info = new wxDisplayInfo(hMonitor); |
| 632 | | |
| 633 | | // we also store the display geometry |
| 634 | | info->m_rect = wxRect(lprcMonitor->left, lprcMonitor->top, |
| 635 | | lprcMonitor->right - lprcMonitor->left, |
| 636 | | lprcMonitor->bottom - lprcMonitor->top); |
| 637 | | |
| 638 | | // now add this monitor to the array |
| 639 | | m_displays.Add(info); |
| 640 | | } |
| 641 | | |
| 642 | | // ---------------------------------------------------------------------------- |
| 643 | | // wxDisplayFactoryMultimon inherited pure virtuals implementation |
| 644 | | // ---------------------------------------------------------------------------- |
| 645 | | |
| 646 | | wxDisplayImpl *wxDisplayFactoryMultimon::CreateDisplay(unsigned n) |
| 647 | | { |
| 648 | | wxCHECK_MSG( n < m_displays.size(), NULL, wxT("invalid display index") ); |
| 649 | | |
| 650 | | return new wxDisplayImplMultimon(n, *(m_displays[n])); |
| 651 | | } |
| 652 | | |
| 653 | | // ---------------------------------------------------------------------------- |
| 654 | | // wxDisplayImplMultimon implementation |
| 655 | | // ---------------------------------------------------------------------------- |
| 656 | | |
| 657 | | wxArrayVideoModes |
| 658 | | wxDisplayImplMultimon::GetModes(const wxVideoMode& modeMatch) const |
| | 304 | wxArrayVideoModes wxDisplayMSW::GetModes(const wxVideoMode& modeMatch) const |
| 797 | | // ============================================================================ |
| 798 | | // DirectDraw-based wxDisplay implementation |
| 799 | | // ============================================================================ |
| 800 | | |
| 801 | | #if wxUSE_DIRECTDRAW |
| 802 | | |
| 803 | | // ---------------------------------------------------------------------------- |
| 804 | | // wxDisplayFactoryDirectDraw initialization |
| 805 | | // ---------------------------------------------------------------------------- |
| 806 | | |
| 807 | | wxDisplayFactoryDirectDraw::wxDisplayFactoryDirectDraw() |
| 808 | | { |
| 809 | | if ( !ms_supportsMultimon ) |
| | 444 | // ---------------------------------------------------------------------------- |
| | 445 | // wxDisplayFactoryMSW implementation |
| | 446 | // ---------------------------------------------------------------------------- |
| | 447 | |
| | 448 | wxDisplayFactoryMSW::wxDisplayFactoryMSW() |
| | 449 | { |
| | 450 | if ( gs_MonitorFromPoint==NULL || gs_MonitorFromWindow==NULL |
| | 451 | || gs_GetMonitorInfo==NULL || gs_EnumDisplayMonitors==NULL ) |
| | 452 | { |
| | 453 | // First initialization, or last initialization failed. |
| | 454 | wxDynamicLibrary dllDisplay(displayDllName, wxDL_VERBATIM | wxDL_QUIET); |
| | 455 | |
| | 456 | wxDL_INIT_FUNC(gs_, MonitorFromPoint, dllDisplay); |
| | 457 | wxDL_INIT_FUNC(gs_, MonitorFromWindow, dllDisplay); |
| | 458 | wxDL_INIT_FUNC_AW(gs_, GetMonitorInfo, dllDisplay); |
| | 459 | wxDL_INIT_FUNC(gs_, EnumDisplayMonitors, dllDisplay); |
| | 460 | |
| | 461 | // we can safely let dllDisplay go out of scope, the DLL itself will |
| | 462 | // still remain loaded as all programs link to it statically anyhow |
| | 463 | } |
| | 464 | |
| | 465 | if ( gs_MonitorFromPoint==NULL || gs_MonitorFromWindow==NULL |
| | 466 | || gs_GetMonitorInfo==NULL || gs_EnumDisplayMonitors==NULL ) |
| 812 | | m_dllDDraw.Load(wxT("ddraw.dll"), wxDL_VERBATIM | wxDL_QUIET); |
| 813 | | |
| 814 | | if ( !m_dllDDraw.IsLoaded() ) |
| 815 | | return; |
| 816 | | |
| 817 | | DirectDrawEnumerateEx_t |
| 818 | | wxDL_INIT_FUNC_AW(pfn, DirectDrawEnumerateEx, m_dllDDraw); |
| 819 | | if ( !pfnDirectDrawEnumerateEx ) |
| 820 | | return; |
| 821 | | |
| 822 | | // we can't continue without DirectDrawCreate() later, so resolve it right |
| 823 | | // now and fail the initialization if it's not available |
| 824 | | if ( !wxDL_INIT_FUNC(m_pfn, DirectDrawCreate, m_dllDDraw) ) |
| 825 | | return; |
| 826 | | |
| 827 | | if ( (*pfnDirectDrawEnumerateEx)(DDEnumExCallback, |
| 828 | | this, |
| 829 | | DDENUM_ATTACHEDSECONDARYDEVICES) != DD_OK ) |
| 830 | | { |
| 831 | | wxLogLastError(wxT("DirectDrawEnumerateEx")); |
| 832 | | } |
| 833 | | } |
| 834 | | |
| 835 | | wxDisplayFactoryDirectDraw::~wxDisplayFactoryDirectDraw() |
| 836 | | { |
| 837 | | // we must clear m_displays now, before m_dllDDraw is unloaded as otherwise |
| 838 | | // calling m_pDD2->Release() later would crash |
| 839 | | Clear(); |
| 840 | | } |
| 841 | | |
| 842 | | // ---------------------------------------------------------------------------- |
| 843 | | // callbacks for monitor/modes enumeration stuff |
| 844 | | // ---------------------------------------------------------------------------- |
| 845 | | |
| 846 | | BOOL WINAPI |
| 847 | | wxDisplayFactoryDirectDraw::DDEnumExCallback(GUID *pGuid, |
| 848 | | LPTSTR WXUNUSED(driverDescription), |
| 849 | | LPTSTR driverName, |
| 850 | | LPVOID lpContext, |
| 851 | | HMONITOR hmon) |
| 852 | | { |
| 853 | | if ( pGuid ) |
| 854 | | { |
| 855 | | wxDisplayFactoryDirectDraw * self = |
| 856 | | static_cast<wxDisplayFactoryDirectDraw *>(lpContext); |
| 857 | | self->AddDisplay(*pGuid, hmon, driverName); |
| 858 | | } |
| 859 | | //else: we're called for the primary monitor, skip it |
| | 469 | // enumerate all displays |
| | 470 | if ( !gs_EnumDisplayMonitors(NULL, NULL, MultimonEnumProc, (LPARAM)this) ) |
| | 471 | { |
| | 472 | wxLogLastError(wxT("EnumDisplayMonitors")); |
| | 473 | } |
| | 474 | } |
| | 475 | |
| | 476 | /* static */ |
| | 477 | BOOL CALLBACK |
| | 478 | wxDisplayFactoryMSW::MultimonEnumProc( |
| | 479 | HMONITOR hMonitor, // handle to display monitor |
| | 480 | HDC WXUNUSED(hdcMonitor), // handle to monitor-appropriate device context |
| | 481 | LPRECT WXUNUSED(lprcMonitor), // pointer to monitor intersection rectangle |
| | 482 | LPARAM dwData) // data passed from EnumDisplayMonitors (this) |
| | 483 | { |
| | 484 | wxDisplayFactoryMSW *const self = (wxDisplayFactoryMSW *)dwData; |
| | 485 | |
| | 486 | self->m_displays.Add(hMonitor); |
| 865 | | // ---------------------------------------------------------------------------- |
| 866 | | // wxDisplayFactoryDirectDraw helpers |
| 867 | | // ---------------------------------------------------------------------------- |
| 868 | | |
| 869 | | void wxDisplayFactoryDirectDraw::AddDisplay(const GUID& guid, |
| 870 | | HMONITOR hmon, |
| 871 | | LPTSTR name) |
| 872 | | { |
| 873 | | m_displays.Add(new wxDisplayInfoDirectDraw(guid, hmon, name)); |
| 874 | | } |
| 875 | | |
| 876 | | // ---------------------------------------------------------------------------- |
| 877 | | // wxDisplayFactoryDirectDraw inherited pure virtuals implementation |
| 878 | | // ---------------------------------------------------------------------------- |
| 879 | | |
| 880 | | wxDisplayImpl *wxDisplayFactoryDirectDraw::CreateDisplay(unsigned n) |
| 881 | | { |
| 882 | | wxCHECK_MSG( n < m_displays.size(), NULL, wxT("invalid display index") ); |
| 883 | | |
| 884 | | wxDisplayInfoDirectDraw * |
| 885 | | info = static_cast<wxDisplayInfoDirectDraw *>(m_displays[n]); |
| 886 | | |
| 887 | | if ( !info->m_pDD2 ) |
| 888 | | { |
| 889 | | IDirectDraw *pDD; |
| 890 | | GUID guid(info->m_guid); |
| 891 | | HRESULT hr = (*m_pfnDirectDrawCreate)(&guid, &pDD, NULL); |
| 892 | | |
| 893 | | if ( FAILED(hr) || !pDD ) |
| 894 | | { |
| 895 | | // what to do?? |
| 896 | | wxLogApiError(wxT("DirectDrawCreate"), hr); |
| 897 | | return NULL; |
| | 492 | wxDisplayImpl *wxDisplayFactoryMSW::CreateDisplay(unsigned n) |
| | 493 | { |
| | 494 | wxCHECK_MSG( n < m_displays.size(), NULL, wxT("An invalid index was passed to wxDisplay") ); |
| | 495 | |
| | 496 | return new wxDisplayMSW(n, m_displays[n]); |
| | 497 | } |
| | 498 | |
| | 499 | // helper for GetFromPoint() and GetFromWindow() |
| | 500 | int wxDisplayFactoryMSW::FindDisplayFromHMONITOR(HMONITOR hmon) const |
| | 501 | { |
| | 502 | if ( hmon ) |
| | 503 | { |
| | 504 | const size_t count = m_displays.size(); |
| | 505 | for ( size_t n = 0; n < count; n++ ) |
| | 506 | { |
| | 507 | if ( hmon == m_displays[n] ) |
| | 508 | return n; |
| 899 | | |
| 900 | | // we got IDirectDraw, but we need IDirectDraw2 |
| 901 | | hr = pDD->QueryInterface(wxIID_IDirectDraw2, (void **)&info->m_pDD2); |
| 902 | | pDD->Release(); |
| 903 | | |
| 904 | | if ( FAILED(hr) || !info->m_pDD2 ) |
| 905 | | { |
| 906 | | wxLogApiError(wxT("IDirectDraw::QueryInterface(IDD2)"), hr); |
| 907 | | return NULL; |
| 908 | | } |
| 909 | | |
| 910 | | // NB: m_pDD2 will now be only destroyed when m_displays is destroyed |
| 911 | | // which is ok as we don't want to recreate DD objects all the time |
| 912 | | } |
| 913 | | //else: DirectDraw object corresponding to our display already exists |
| 914 | | |
| 915 | | return new wxDisplayImplDirectDraw(n, *info, info->m_pDD2); |
| 916 | | } |
| 917 | | |
| 918 | | // ============================================================================ |
| 919 | | // wxDisplayImplDirectDraw |
| 920 | | // ============================================================================ |
| 921 | | |
| 922 | | // ---------------------------------------------------------------------------- |
| 923 | | // video modes enumeration |
| 924 | | // ---------------------------------------------------------------------------- |
| 925 | | |
| 926 | | // tiny helper class used to pass information from GetModes() to |
| 927 | | // wxDDEnumModesCallback |
| 928 | | class wxDDVideoModesAdder |
| 929 | | { |
| 930 | | public: |
| 931 | | // our Add() method will add modes matching modeMatch to modes array |
| 932 | | wxDDVideoModesAdder(wxArrayVideoModes& modes, const wxVideoMode& modeMatch) |
| 933 | | : m_modes(modes), |
| 934 | | m_modeMatch(modeMatch) |
| 935 | | { |
| 936 | | } |
| 937 | | |
| 938 | | void Add(const wxVideoMode& mode) |
| 939 | | { |
| 940 | | if ( mode.Matches(m_modeMatch) ) |
| 941 | | m_modes.Add(mode); |
| 942 | | } |
| 943 | | |
| 944 | | private: |
| 945 | | wxArrayVideoModes& m_modes; |
| 946 | | const wxVideoMode& m_modeMatch; |
| 947 | | |
| 948 | | wxDECLARE_NO_COPY_CLASS(wxDDVideoModesAdder); |
| 949 | | }; |
| 950 | | |
| 951 | | HRESULT WINAPI wxDDEnumModesCallback(LPDDSURFACEDESC lpDDSurfaceDesc, |
| 952 | | LPVOID lpContext) |
| 953 | | { |
| 954 | | // we need at least the mode size |
| 955 | | static const DWORD FLAGS_REQUIRED = DDSD_HEIGHT | DDSD_WIDTH; |
| 956 | | if ( (lpDDSurfaceDesc->dwFlags & FLAGS_REQUIRED) == FLAGS_REQUIRED ) |
| 957 | | { |
| 958 | | wxDDVideoModesAdder * const vmodes = |
| 959 | | static_cast<wxDDVideoModesAdder *>(lpContext); |
| 960 | | |
| 961 | | vmodes->Add(wxVideoMode(lpDDSurfaceDesc->dwWidth, |
| 962 | | lpDDSurfaceDesc->dwHeight, |
| 963 | | lpDDSurfaceDesc->ddpfPixelFormat.dwRGBBitCount, |
| 964 | | lpDDSurfaceDesc->dwRefreshRate)); |
| 965 | | } |
| 966 | | |
| 967 | | // continue the enumeration |
| 968 | | return DDENUMRET_OK; |
| 969 | | } |
| 970 | | |
| 971 | | wxArrayVideoModes |
| 972 | | wxDisplayImplDirectDraw::GetModes(const wxVideoMode& modeMatch) const |
| 973 | | { |
| 974 | | wxArrayVideoModes modes; |
| 975 | | wxDDVideoModesAdder modesAdder(modes, modeMatch); |
| 976 | | |
| 977 | | HRESULT hr = m_pDD2->EnumDisplayModes |
| 978 | | ( |
| 979 | | DDEDM_REFRESHRATES, |
| 980 | | NULL, // all modes |
| 981 | | &modesAdder, // callback parameter |
| 982 | | wxDDEnumModesCallback |
| 983 | | ); |
| 984 | | |
| 985 | | if ( FAILED(hr) ) |
| 986 | | { |
| 987 | | wxLogApiError(wxT("IDirectDraw::EnumDisplayModes"), hr); |
| 988 | | } |
| 989 | | |
| 990 | | return modes; |
| 991 | | } |
| 992 | | |
| 993 | | // ---------------------------------------------------------------------------- |
| 994 | | // video mode switching |
| 995 | | // ---------------------------------------------------------------------------- |
| 996 | | |
| 997 | | bool wxDisplayImplDirectDraw::ChangeMode(const wxVideoMode& mode) |
| 998 | | { |
| 999 | | wxWindow *winTop = wxTheApp->GetTopWindow(); |
| 1000 | | wxCHECK_MSG( winTop, false, wxT("top level window required for DirectX") ); |
| 1001 | | |
| 1002 | | HRESULT hr = m_pDD2->SetCooperativeLevel |
| 1003 | | ( |
| 1004 | | GetHwndOf(winTop), |
| 1005 | | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN |
| 1006 | | ); |
| 1007 | | if ( FAILED(hr) ) |
| 1008 | | { |
| 1009 | | wxLogApiError(wxT("IDirectDraw2::SetCooperativeLevel"), hr); |
| 1010 | | |
| 1011 | | return false; |
| 1012 | | } |
| 1013 | | |
| 1014 | | hr = m_pDD2->SetDisplayMode(mode.w, mode.h, mode.bpp, mode.refresh, 0); |
| 1015 | | if ( FAILED(hr) ) |
| 1016 | | { |
| 1017 | | wxLogApiError(wxT("IDirectDraw2::SetDisplayMode"), hr); |
| 1018 | | |
| 1019 | | return false; |
| 1020 | | } |
| 1021 | | |
| 1022 | | return true; |
| 1023 | | } |
| 1024 | | |
| 1025 | | #endif // wxUSE_DIRECTDRAW |
| | 510 | } |
| | 511 | |
| | 512 | return wxNOT_FOUND; |
| | 513 | } |
| | 514 | |
| | 515 | int wxDisplayFactoryMSW::GetFromPoint(const wxPoint& pt) |
| | 516 | { |
| | 517 | POINT pt2; |
| | 518 | pt2.x = pt.x; |
| | 519 | pt2.y = pt.y; |
| | 520 | |
| | 521 | return FindDisplayFromHMONITOR(gs_MonitorFromPoint(pt2, |
| | 522 | MONITOR_DEFAULTTONULL)); |
| | 523 | } |
| | 524 | |
| | 525 | int wxDisplayFactoryMSW::GetFromWindow(const wxWindow *window) |
| | 526 | { |
| | 527 | return FindDisplayFromHMONITOR(gs_MonitorFromWindow(GetHwndOf(window), |
| | 528 | MONITOR_DEFAULTTONULL)); |
| | 529 | } |