From 056ce866b0b529b62aa17c36376163a13d47bd2e Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Wed, 24 Jan 2007 10:02:04 +0000 Subject: [PATCH] =?UTF-8?q?From=20Andr=C3=A9=20Garneau,=20"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Setup proper pixel format for ATI boards (removal of WGL_SWAP_METHOD_ARB specification from the requested pixel format since unsupported by the ATI driver) * Fix to create sample OpenGL window on the proper display device. This is the temporary window used to choose the desired pixel format. In the previous version, this window was always created on the primary display device, even though it had potentially different pixel formats compared to the target display device containing the window to be created. * Implementation of WindowingSystemInterface::setScreenResolution() method * Implementation of WindowingSystemInterface::setScreenRefreshRate() method * Implementation of GraphicsWindow::requestWarpPointer() method * Implementation of GraphicsWindow::useCursor() method and associated trait support. This can be used in two ways; first, when the graphics trait requested indicates that no cursor should be present, a new cursor-less window class is used to create the window. When a cursor-enabled window creation is requested, another window class is used. After creation of a window, it is also possible to toggle the cursor state by using the GraphicsWindow::useCursor method. * The way the mouse behaves is now compatible with the behaviour seen on X11; i.e. when pressing a mouse button, the window where the pointer is located will capture the mouse input and release it only after the button has been released. This results in all mouse movement events being dispatched to the window where the button was pressed initially until it is released. This improves the interaction with graphics windows. * Preparation work has been done to support the ability of moving a window from one screen to another screen and recreating its rendering context when this happens. This has been tested with a mix of NVIDIA and ATI cards and works properly. For the moment being, this feature is commented out due to changes in the core OSG libraries that have been done but need to be submitted later this week for approval by Robert. Upcoming features * Support for moving windows from one screen to another screen seamlessly * Ability to set the window (i.e. the application itself creates the rendering window and passes it to the GraphicsWindowWin32 class) * Other miscellaneous items" --------------------------------------------------- --- include/osgViewer/GraphicsWindowWin32 | 23 +- include/osgViewer/StatsHandler | 2 +- src/osgViewer/GraphicsWindowWin32.cpp | 649 ++++++++++++++++++-------- 3 files changed, 481 insertions(+), 193 deletions(-) diff --git a/include/osgViewer/GraphicsWindowWin32 b/include/osgViewer/GraphicsWindowWin32 index 152519cef..ca60a200a 100644 --- a/include/osgViewer/GraphicsWindowWin32 +++ b/include/osgViewer/GraphicsWindowWin32 @@ -69,6 +69,12 @@ class GraphicsWindowWin32 : public osgViewer::GraphicsWindow /** Get focus on if the pointer is in this window.*/ virtual void grabFocusIfPointerInWindow(); + /** Override from GUIActionAdapter.*/ + virtual void requestWarpPointer(float x,float y); + + /** Switch on/off the cursor.*/ + virtual void useCursor(bool /*cursorOn*/); + /** Handle a native (Win32) windowing event as received from the system */ virtual LRESULT handleNativeWindowingEvent( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam ); @@ -80,6 +86,7 @@ class GraphicsWindowWin32 : public osgViewer::GraphicsWindow HWND createWindow(); void destroyWindow( bool deleteNativeWindow = true ); + void recreateWindow(); bool determineWindowPositionAndStyle( bool decorated, int& x, int& y, unsigned int& w, unsigned int& h, unsigned int& style, unsigned int& extendedStyle ); @@ -89,25 +96,29 @@ class GraphicsWindowWin32 : public osgViewer::GraphicsWindow void transformMouseXY(float& x, float& y); + int getScreenNumberContainingWindow( int& _screenOriginX, int& _screenOriginY ); + HWND _hwnd; - HDC _hdc; - HGLRC _hglrc; + HDC _hdc; + HGLRC _hglrc; double _timeOfLastCheckEvents; - int _screenOriginX; - int _screenOriginY; + int _screenOriginX; + int _screenOriginY; unsigned int _screenWidth; unsigned int _screenHeight; - int _windowOriginXToRealize; - int _windowOriginYToRealize; + int _windowOriginXToRealize; + int _windowOriginYToRealize; unsigned int _windowWidthToRealize; unsigned int _windowHeightToRealize; bool _initialized; bool _valid; bool _realized; + + bool _recreateWindow; bool _destroying; }; diff --git a/include/osgViewer/StatsHandler b/include/osgViewer/StatsHandler index 5fb1d7eb2..21e517a78 100644 --- a/include/osgViewer/StatsHandler +++ b/include/osgViewer/StatsHandler @@ -20,7 +20,7 @@ namespace osgViewer { -class StatsHandler : public osgGA::GUIEventHandler +class OSGVIEWER_EXPORT StatsHandler : public osgGA::GUIEventHandler { public: diff --git a/src/osgViewer/GraphicsWindowWin32.cpp b/src/osgViewer/GraphicsWindowWin32.cpp index 1f44efb47..37594dfcb 100644 --- a/src/osgViewer/GraphicsWindowWin32.cpp +++ b/src/osgViewer/GraphicsWindowWin32.cpp @@ -12,7 +12,7 @@ * * This file is Copyright (C) 2007 - André Garneau (andre@pixdev.com) and licensed under OSGPL. * - * Note, some elements of GraphicsWindowWin32 have used the Producer implementation as a reference. + * Some elements of GraphicsWindowWin32 have used the Producer implementation as a reference. * These elements are licensed under OSGPL as above, with Copyright (C) 2001-2004 Don Burns. */ @@ -81,8 +81,8 @@ namespace osgViewer #define WGL_SWAP_UNDEFINED_ARB 0x202A #define WGL_TYPE_RGBA_ARB 0x202B #define WGL_TYPE_COLORINDEX_ARB 0x202C -#define WGL_SAMPLE_BUFFERS_ARB 0x2041 -#define WGL_SAMPLES_ARB 0x2042 +#define WGL_SAMPLE_BUFFERS_ARB 0x2041 +#define WGL_SAMPLES_ARB 0x2042 // // Entry points used from the WGL extensions @@ -108,13 +108,13 @@ template class WGLAttributes WGLAttributes() {} ~WGLAttributes() {} - void begin() { m_parameters.clear(); } - void set( const T& id, const T& value ) { add(id); add(value); } + void begin() { m_parameters.clear(); } + void set( const T& id, const T& value ) { add(id); add(value); } void enable( const T& id ) { add(id); add(true); } - void disable( const T& id ) { add(id); add(false); } + void disable( const T& id ) { add(id); add(false); } void end() { add(0); } - const T* get() { return &m_parameters.front(); } + const T* get() const { return &m_parameters.front(); } protected: @@ -159,26 +159,38 @@ class Win32WindowingSystem : public osg::GraphicsContext::WindowingSystemInterfa // A class representing an OpenGL rendering context class OpenGLContext { - public: + public: - OpenGLContext() : _previous(0), _hdc(0), _hglrc(0), _restorePreviousOnExit(false) + OpenGLContext() + : _previousHdc(0), + _previousHglrc(0), + _hwnd(0), + _hdc(0), + _hglrc(0), + _restorePreviousOnExit(false) {} - OpenGLContext( HDC hdc, HGLRC hglrc ) : _previous(0), _hdc(hdc), _hglrc(hglrc), _restorePreviousOnExit(false) - {} - - OpenGLContext( const OpenGLContext& context ) - : _previous(context._previous), - _hdc(context._hdc), - _hglrc(context._hglrc), - _restorePreviousOnExit(context._restorePreviousOnExit) + OpenGLContext( HWND hwnd, HDC hdc, HGLRC hglrc ) + : _previousHdc(0), + _previousHglrc(0), + _hwnd(hwnd), + _hdc(hdc), + _hglrc(hglrc), + _restorePreviousOnExit(false) {} ~OpenGLContext(); + void set( HWND hwnd, HDC hdc, HGLRC hglrc ) + { + _hwnd = hwnd; + _hdc = hdc; + _hglrc = hglrc; + } + HDC deviceContext() { return _hdc; } - bool makeCurrent( bool restorePreviousOnExit ); + bool makeCurrent( HDC restoreOnHdc, bool restorePreviousOnExit ); protected: @@ -186,19 +198,22 @@ class Win32WindowingSystem : public osg::GraphicsContext::WindowingSystemInterfa // Data members // - HGLRC _previous; // previously current rendering context - HDC _hdc; // handle to device context - HGLRC _hglrc; // handle to OpenGL rendering context - bool _restorePreviousOnExit; // restore original context on exit + HDC _previousHdc; // previously HDC to restore rendering context on + HGLRC _previousHglrc; // previously current rendering context + HWND _hwnd; // handle to OpenGL window + HDC _hdc; // handle to device context + HGLRC _hglrc; // handle to OpenGL rendering context + bool _restorePreviousOnExit; // restore original context on exit private: - // no implementation for assignment operator - OpenGLContext& operator=( const OpenGLContext& context ); - + // no implementation for these + OpenGLContext( const OpenGLContext& ); + OpenGLContext& operator=( const OpenGLContext& ); }; - static std::string osgGraphicsWindowClassName; //!< Name of Win32 window class used by OSG graphics window instances + static std::string osgGraphicsWindowWithCursorClass; //!< Name of Win32 window class (with cursor) used by OSG graphics window instances + static std::string osgGraphicsWindowWithoutCursorClass; //!< Name of Win32 window class (without cursor) used by OSG graphics window instances Win32WindowingSystem(); ~Win32WindowingSystem(); @@ -217,6 +232,12 @@ class Win32WindowingSystem : public osg::GraphicsContext::WindowingSystemInterfa // (0,0) is returned if screen is unknown virtual void getScreenResolution( const osg::GraphicsContext::ScreenIdentifier& si, unsigned int& width, unsigned int& height ); + // Set the resolution for given screen + virtual bool setScreenResolution( const osg::GraphicsContext::ScreenIdentifier& si, unsigned int width, unsigned int height ); + + // Set the refresh rate for given screen + virtual bool setScreenRefreshRate( const osg::GraphicsContext::ScreenIdentifier& si, double refreshRate ); + // Return the screen position and width/height. // all zeros returned if screen is unknown virtual void getScreenPosition( const osg::GraphicsContext::ScreenIdentifier& si, int& originX, int& originY, unsigned int& width, unsigned int& height ); @@ -236,8 +257,8 @@ class Win32WindowingSystem : public osg::GraphicsContext::WindowingSystemInterfa // Get the application window object associated with a native window virtual osgViewer::GraphicsWindowWin32* getGraphicsWindowFor( HWND hwnd ); - // Return a valid sample OpenGL Device Context and Rendering Context that can be used with wglXYZ extensions - virtual OpenGLContext getSampleOpenGLContext(); + // Return a valid sample OpenGL Device Context and current rendering context that can be used with wglXYZ extensions + virtual bool getSampleOpenGLContext( OpenGLContext& context, HDC windowHDC, int windowOriginX, int windowOriginY ); protected: @@ -251,23 +272,21 @@ class Win32WindowingSystem : public osg::GraphicsContext::WindowingSystemInterfa // Enumerate all display devices and return in passed container void enumerateDisplayDevices( DisplayDevices& displayDevices ) const; - bool getScreenInformation( const osg::GraphicsContext::ScreenIdentifier& si, DEVMODE& deviceMode ); + // Get the screen device current mode information + bool getScreenInformation( const osg::GraphicsContext::ScreenIdentifier& si, DISPLAY_DEVICE& displayDevice, DEVMODE& deviceMode ); - // Register the window class used by OSG graphics window instances - void registerWindowClass(); + // Change the screen settings (resolution, refresh rate, etc.) + bool changeScreenSettings( const osg::GraphicsContext::ScreenIdentifier& si, DISPLAY_DEVICE& displayDevice, DEVMODE& deviceMode ); - // Unregister the window class used by OSG graphics window instances - void unregisterWindowClass(); + // Register the window classes used by OSG graphics window instances + void registerWindowClasses(); - // Release sample GL context - void releaseSampleOpenGLContext(); + // Unregister the window classes used by OSG graphics window instances + void unregisterWindowClasses(); // Data members WindowHandles _activeWindows; //!< handles to active windows - HWND _dummyGLWindow; //!< dummy GL window used to provide a valid context for wglXYZ calls - HDC _dummyGLWindowDC; //!< dummy GL window device context - HGLRC _dummyGLRC; //!< dummy GL rendering context - bool _windowClassRegistered; //!< true after windowing interface has been initialized successfully + bool _windowClassesRegistered; //!< true after window classes have been registered private: @@ -332,9 +351,25 @@ class GraphicsContextWin32 : public osg::GraphicsContext // Error reporting ////////////////////////////////////////////////////////////////////////////// +static void reportError( const std::string& msg ) +{ + osg::notify(osg::WARN) << "Error: " << msg.c_str() << std::endl; +} + static void reportError( const std::string& msg, unsigned int errorCode ) { - osg::notify(osg::WARN) << "Windows System Error #" << errorCode << " : " << msg.c_str(); + // + // Some APIs are documented as returning the error in ::GetLastError but apparently do not + // Skip "Reason" field if the errorCode is still success + // + + if (errorCode==0) + { + reportError(msg); + return; + } + + osg::notify(osg::WARN) << "Windows Error #" << errorCode << ": " << msg.c_str(); LPVOID lpMsgBuf; @@ -346,7 +381,7 @@ static void reportError( const std::string& msg, unsigned int errorCode ) 0, NULL)!=0) { - osg::notify(osg::WARN) << ". Reason : " << LPTSTR(lpMsgBuf) << std::endl; + osg::notify(osg::WARN) << ". Reason: " << LPTSTR(lpMsgBuf) << std::endl; ::LocalFree(lpMsgBuf); } else @@ -355,9 +390,12 @@ static void reportError( const std::string& msg, unsigned int errorCode ) } } -static void reportError( const std::string& msg ) +static void reportErrorForScreen( const std::string& msg, const osg::GraphicsContext::ScreenIdentifier& si, unsigned int errorCode ) { - osg::notify(osg::WARN) << "Error: " << msg.c_str() << std::endl; + std::ostringstream str; + + str << "[Screen #" << si.screenNum << "] " << msg; + reportError(str.str(), errorCode); } ////////////////////////////////////////////////////////////////////////////// @@ -513,23 +551,42 @@ static LRESULT CALLBACK WindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM Win32WindowingSystem::OpenGLContext::~OpenGLContext() { - if (_restorePreviousOnExit && _previous!=_hglrc && !::wglMakeCurrent(_hdc, _previous)) + if (_restorePreviousOnExit && _previousHglrc!=_hglrc && !::wglMakeCurrent(_previousHdc, _previousHglrc)) { reportError("Win32WindowingSystem::OpenGLContext() - Unable to restore current OpenGL rendering context", ::GetLastError()); } - _previous = 0; - _hdc = 0; - _hglrc = 0; + _previousHdc = 0; + _previousHglrc = 0; + + if (_hglrc) + { + ::wglMakeCurrent(_hdc, NULL); + ::wglDeleteContext(_hglrc); + _hglrc = 0; + } + + if (_hdc) + { + ::ReleaseDC(_hwnd, _hdc); + _hdc = 0; + } + + if (_hwnd) + { + ::DestroyWindow(_hwnd); + _hwnd = 0; + } } -bool Win32WindowingSystem::OpenGLContext::makeCurrent( bool restorePreviousOnExit ) +bool Win32WindowingSystem::OpenGLContext::makeCurrent( HDC restoreOnHdc, bool restorePreviousOnExit ) { if (_hdc==0 || _hglrc==0) return false; - _previous = restorePreviousOnExit ? ::wglGetCurrentContext() : 0; + _previousHglrc = restorePreviousOnExit ? ::wglGetCurrentContext() : 0; + _previousHdc = restoreOnHdc; - if (_hglrc==_previous) return true; + if (_hglrc==_previousHglrc) return true; if (!::wglMakeCurrent(_hdc, _hglrc)) { @@ -546,20 +603,17 @@ bool Win32WindowingSystem::OpenGLContext::makeCurrent( bool restorePreviousOnExi // Win32WindowingSystem implementation ////////////////////////////////////////////////////////////////////////////// -std::string Win32WindowingSystem::osgGraphicsWindowClassName; +std::string Win32WindowingSystem::osgGraphicsWindowWithCursorClass; +std::string Win32WindowingSystem::osgGraphicsWindowWithoutCursorClass; Win32WindowingSystem::Win32WindowingSystem() -: _dummyGLWindow(0), - _dummyGLWindowDC(0), - _dummyGLRC(0), - _windowClassRegistered(false) +: _windowClassesRegistered(false) { } Win32WindowingSystem::~Win32WindowingSystem() { - releaseSampleOpenGLContext(); - unregisterWindowClass(); + unregisterWindowClasses(); } void Win32WindowingSystem::enumerateDisplayDevices( DisplayDevices& displayDevices ) const @@ -574,80 +628,102 @@ void Win32WindowingSystem::enumerateDisplayDevices( DisplayDevices& displayDevic // Do not track devices used for remote access (Terminal Services pseudo-displays, etc.) if (displayDevice.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER) continue; - //!@todo when the GraphicsContextWin32 class is implemented, remove this line - // For the time-being only return display devices that are attached to the desktop + // Only return display devices that are attached to the desktop if (!(displayDevice.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP)) continue; displayDevices.push_back(displayDevice); } } -void Win32WindowingSystem::registerWindowClass() +void Win32WindowingSystem::registerWindowClasses() { - if (_windowClassRegistered) return; + if (_windowClassesRegistered) return; // - // Register the window class used by OSG GraphicsWindowWin32 instances + // Register the window classes used by OSG GraphicsWindowWin32 instances // std::ostringstream str; - str << "OpenSceneGraph Graphics Window for Win32 [" << ::GetCurrentProcessId() << "]"; + str << "OSG Graphics Window for Win32 [" << ::GetCurrentProcessId() << "]"; - osgGraphicsWindowClassName = str.str(); + osgGraphicsWindowWithCursorClass = str.str() + "{ with cursor }"; + osgGraphicsWindowWithoutCursorClass = str.str() + "{ without cursor }"; WNDCLASSEX wc; HINSTANCE hinst = ::GetModuleHandle(NULL); - wc.cbSize = sizeof(wc); + // + // First class: class for OSG Graphics Window with a cursor enabled + // + + wc.cbSize = sizeof(wc); wc.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW | CS_OWNDC; - wc.lpfnWndProc = WindowProc; - wc.cbClsExtra = 0; - wc.cbWndExtra = 0; + wc.lpfnWndProc = WindowProc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; wc.hInstance = hinst; wc.hIcon = ::LoadIcon(hinst, "OSG_ICON"); - wc.hCursor = ::LoadCursor(NULL, IDC_ARROW); + wc.hCursor = ::LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = NULL; wc.lpszMenuName = 0; - wc.lpszClassName = osgGraphicsWindowClassName.c_str(); - wc.hIconSm = NULL; + wc.lpszClassName = osgGraphicsWindowWithCursorClass.c_str(); + wc.hIconSm = NULL; if (::RegisterClassEx(&wc)==0) { unsigned int lastError = ::GetLastError(); if (lastError!=ERROR_CLASS_ALREADY_EXISTS) { - reportError("Win32WindowingSystem::registerWindowClass() - Unable to register window class", lastError); + reportError("Win32WindowingSystem::registerWindowClasses() - Unable to register first window class", lastError); return; } } - _windowClassRegistered = true; + // + // Second class: class for OSG Graphics Window without a cursor + // + + wc.hCursor = NULL; + wc.lpszClassName = osgGraphicsWindowWithoutCursorClass.c_str(); + + if (::RegisterClassEx(&wc)==0) + { + unsigned int lastError = ::GetLastError(); + if (lastError!=ERROR_CLASS_ALREADY_EXISTS) + { + reportError("Win32WindowingSystem::registerWindowClasses() - Unable to register second window class", lastError); + return; + } + } + + _windowClassesRegistered = true; } -void Win32WindowingSystem::unregisterWindowClass() +void Win32WindowingSystem::unregisterWindowClasses() { - if (_windowClassRegistered) + if (_windowClassesRegistered) { - ::UnregisterClass(osgGraphicsWindowClassName.c_str(), ::GetModuleHandle(NULL)); - _windowClassRegistered = false; + ::UnregisterClass(osgGraphicsWindowWithCursorClass.c_str(), ::GetModuleHandle(NULL)); + ::UnregisterClass(osgGraphicsWindowWithoutCursorClass.c_str(), ::GetModuleHandle(NULL)); + _windowClassesRegistered = false; } } -Win32WindowingSystem::OpenGLContext Win32WindowingSystem::getSampleOpenGLContext() +bool Win32WindowingSystem::getSampleOpenGLContext( OpenGLContext& context, HDC windowHDC, int windowOriginX, int windowOriginY ) { - if (_dummyGLWindowDC) return OpenGLContext(_dummyGLWindowDC, _dummyGLRC); + context.set(0, 0, 0); - registerWindowClass(); + registerWindowClasses(); HWND hwnd = ::CreateWindowEx(WS_EX_OVERLAPPEDWINDOW, - osgGraphicsWindowClassName.c_str(), + osgGraphicsWindowWithoutCursorClass.c_str(), NULL, WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_DISABLED, - 0, - 0, - 256, - 256, + windowOriginX, + windowOriginY, + 1, + 1, NULL, NULL, ::GetModuleHandle(NULL), @@ -655,7 +731,7 @@ Win32WindowingSystem::OpenGLContext Win32WindowingSystem::getSampleOpenGLContext if (hwnd==0) { reportError("Win32WindowingSystem::getSampleOpenGLContext() - Unable to create window", ::GetLastError()); - return OpenGLContext(); + return false; } // @@ -684,7 +760,7 @@ Win32WindowingSystem::OpenGLContext Win32WindowingSystem::getSampleOpenGLContext { reportError("Win32WindowingSystem::getSampleOpenGLContext() - Unable to get window device context", ::GetLastError()); ::DestroyWindow(hwnd); - return OpenGLContext(); + return false; } int pixelFormatIndex = ::ChoosePixelFormat(hdc, &pixelFormat); @@ -693,7 +769,7 @@ Win32WindowingSystem::OpenGLContext Win32WindowingSystem::getSampleOpenGLContext reportError("Win32WindowingSystem::getSampleOpenGLContext() - Unable to choose pixel format", ::GetLastError()); ::ReleaseDC(hwnd, hdc); ::DestroyWindow(hwnd); - return OpenGLContext(); + return false; } if (!::SetPixelFormat(hdc, pixelFormatIndex, &pixelFormat)) @@ -701,7 +777,7 @@ Win32WindowingSystem::OpenGLContext Win32WindowingSystem::getSampleOpenGLContext reportError("Win32WindowingSystem::getSampleOpenGLContext() - Unable to set pixel format", ::GetLastError()); ::ReleaseDC(hwnd, hdc); ::DestroyWindow(hwnd); - return OpenGLContext(); + return false; } HGLRC hglrc = ::wglCreateContext(hdc); @@ -710,45 +786,22 @@ Win32WindowingSystem::OpenGLContext Win32WindowingSystem::getSampleOpenGLContext reportError("Win32WindowingSystem::getSampleOpenGLContext() - Unable to create an OpenGL rendering context", ::GetLastError()); ::ReleaseDC(hwnd, hdc); ::DestroyWindow(hwnd); - return OpenGLContext(); + return false; } - _dummyGLWindow = hwnd; - _dummyGLWindowDC = hdc; - _dummyGLRC = hglrc; + context.set(hwnd, hdc, hglrc); - return OpenGLContext(_dummyGLWindowDC, _dummyGLRC); -} + if (!context.makeCurrent(windowHDC, true)) return false; -void Win32WindowingSystem::releaseSampleOpenGLContext() -{ - if (_dummyGLRC) - { - ::wglMakeCurrent(_dummyGLWindowDC, NULL); - ::wglDeleteContext(_dummyGLRC); - _dummyGLRC = 0; - } - - if (_dummyGLWindowDC) - { - ::ReleaseDC(_dummyGLWindow, _dummyGLWindowDC); - _dummyGLWindowDC = 0; - } - - if (_dummyGLWindow) - { - ::DestroyWindow(_dummyGLWindow); - _dummyGLWindow = 0; - } + return true; } unsigned int Win32WindowingSystem::getNumScreens( const osg::GraphicsContext::ScreenIdentifier& si ) { - //!@todo change when implementing the GraphicsContextWin32 class. return si.displayNum==0 ? ::GetSystemMetrics(SM_CMONITORS) : 0; } -bool Win32WindowingSystem::getScreenInformation( const osg::GraphicsContext::ScreenIdentifier& si, DEVMODE& deviceMode ) +bool Win32WindowingSystem::getScreenInformation( const osg::GraphicsContext::ScreenIdentifier& si, DISPLAY_DEVICE& displayDevice, DEVMODE& deviceMode ) { if (si.displayNum>0) { @@ -765,10 +818,12 @@ bool Win32WindowingSystem::getScreenInformation( const osg::GraphicsContext::Scr return false; } + displayDevice = displayDevices[si.screenNum]; + deviceMode.dmSize = sizeof(deviceMode); deviceMode.dmDriverExtra = 0; - if (!::EnumDisplaySettings(displayDevices[si.screenNum].DeviceName, ENUM_CURRENT_SETTINGS, &deviceMode)) + if (!::EnumDisplaySettings(displayDevice.DeviceName, ENUM_CURRENT_SETTINGS, &deviceMode)) { std::ostringstream str; str << "Win32WindowingSystem::getScreenInformation() - Unable to query information for screen number " << si.screenNum; @@ -781,9 +836,10 @@ bool Win32WindowingSystem::getScreenInformation( const osg::GraphicsContext::Scr void Win32WindowingSystem::getScreenResolution( const osg::GraphicsContext::ScreenIdentifier& si, unsigned int& width, unsigned int& height ) { - DEVMODE deviceMode; + DISPLAY_DEVICE displayDevice; + DEVMODE deviceMode; - if (getScreenInformation(si, deviceMode)) + if (getScreenInformation(si, displayDevice, deviceMode)) { width = deviceMode.dmPelsWidth; height = deviceMode.dmPelsHeight; @@ -795,11 +851,71 @@ void Win32WindowingSystem::getScreenResolution( const osg::GraphicsContext::Scre } } +bool Win32WindowingSystem::changeScreenSettings( const osg::GraphicsContext::ScreenIdentifier& si, DISPLAY_DEVICE& displayDevice, DEVMODE& deviceMode ) +{ + // + // Start by testing if the change would be successful (without applying it) + // + + unsigned int result = ::ChangeDisplaySettingsEx(displayDevice.DeviceName, &deviceMode, NULL, CDS_TEST, NULL); + if (result==DISP_CHANGE_SUCCESSFUL) + { + result = ::ChangeDisplaySettingsEx(displayDevice.DeviceName, &deviceMode, NULL, 0, NULL); + if (result==DISP_CHANGE_SUCCESSFUL) return true; + } + + std::string msg = "Win32WindowingSystem::changeScreenSettings() - Unable to change the screen settings."; + + switch( result ) + { + case DISP_CHANGE_BADMODE : msg += " The specified graphics mode is not supported."; break; + case DISP_CHANGE_FAILED : msg += " The display driver failed the specified graphics mode."; break; + case DISP_CHANGE_RESTART : msg += " The computer must be restarted for the graphics mode to work."; break; + default : break; + } + + reportErrorForScreen(msg, si, result); + return false; +} + +bool Win32WindowingSystem::setScreenResolution( const osg::GraphicsContext::ScreenIdentifier& si, unsigned int width, unsigned int height ) +{ + DISPLAY_DEVICE displayDevice; + DEVMODE deviceMode; + + if (!getScreenInformation(si, displayDevice, deviceMode)) return false; + + deviceMode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT; + deviceMode.dmPelsWidth = width; + deviceMode.dmPelsHeight = height; + + return changeScreenSettings(si, displayDevice, deviceMode); +} + +bool Win32WindowingSystem::setScreenRefreshRate( const osg::GraphicsContext::ScreenIdentifier& si, double refreshRate ) +{ + DISPLAY_DEVICE displayDevice; + DEVMODE deviceMode; + + unsigned int width, height; + getScreenResolution(si, width, height); + + if (!getScreenInformation(si, displayDevice, deviceMode)) return false; + + deviceMode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFREQUENCY; + deviceMode.dmPelsWidth = width; + deviceMode.dmPelsHeight = height; + deviceMode.dmDisplayFrequency = refreshRate; + + return changeScreenSettings(si, displayDevice, deviceMode); +} + void Win32WindowingSystem::getScreenPosition( const osg::GraphicsContext::ScreenIdentifier& si, int& originX, int& originY, unsigned int& width, unsigned int& height ) { - DEVMODE deviceMode; + DISPLAY_DEVICE displayDevice; + DEVMODE deviceMode; - if (getScreenInformation(si, deviceMode)) + if (getScreenInformation(si, displayDevice, deviceMode)) { originX = deviceMode.dmPosition.x; originY = deviceMode.dmPosition.y; @@ -825,7 +941,7 @@ osg::GraphicsContext* Win32WindowingSystem::createGraphicsContext( osg::Graphics } else { - registerWindowClass(); + registerWindowClasses(); osg::ref_ptr window = new GraphicsWindowWin32(traits); if (window->valid()) return window.release(); @@ -878,6 +994,7 @@ GraphicsWindowWin32::GraphicsWindowWin32( osg::GraphicsContext::Traits* traits ) _initialized(false), _valid(false), _realized(false), + _recreateWindow(false), _destroying(false) { _traits = traits; @@ -888,7 +1005,6 @@ GraphicsWindowWin32::GraphicsWindowWin32( osg::GraphicsContext::Traits* traits ) { setState( new osg::State ); getState()->setContextID( osg::GraphicsContext::createNewContextID() ); - Win32WindowingSystem::getInterface()->registerWindow(_hwnd, this); } } @@ -925,7 +1041,8 @@ HWND GraphicsWindowWin32::createWindow() } _hwnd = ::CreateWindowEx(extendedStyle, - Win32WindowingSystem::osgGraphicsWindowClassName.c_str(), + _traits->useCursor ? Win32WindowingSystem::osgGraphicsWindowWithCursorClass.c_str() : + Win32WindowingSystem::osgGraphicsWindowWithoutCursorClass.c_str(), _traits->windowName.c_str(), windowStyle, _windowOriginXToRealize, @@ -938,14 +1055,14 @@ HWND GraphicsWindowWin32::createWindow() NULL); if (_hwnd==0) { - reportError("GraphicsWindowWin32::createWindow() - Unable to create window", ::GetLastError()); + reportErrorForScreen("GraphicsWindowWin32::createWindow() - Unable to create window", _traits->screenNum, ::GetLastError()); return 0; } _hdc = ::GetDC(_hwnd); if (_hdc==0) { - reportError("GraphicsWindowWin32::createWindow() - Unable to get window device context", ::GetLastError()); + reportErrorForScreen("GraphicsWindowWin32::createWindow() - Unable to get window device context", _traits->screenNum, ::GetLastError()); destroyWindow(); _hwnd = 0; return 0; @@ -963,6 +1080,7 @@ HWND GraphicsWindowWin32::createWindow() return 0; } + Win32WindowingSystem::getInterface()->registerWindow(_hwnd, this); return _hwnd; } @@ -971,8 +1089,6 @@ void GraphicsWindowWin32::destroyWindow( bool deleteNativeWindow ) if (_destroying) return; _destroying = true; - close(); - if (_hdc) { releaseContext(); @@ -997,6 +1113,29 @@ void GraphicsWindowWin32::destroyWindow( bool deleteNativeWindow ) _initialized = false; _realized = false; _valid = false; + _destroying = false; +} + +void GraphicsWindowWin32::recreateWindow() +{ +#ifdef NEXT_RELEASE_ONLY + _recreateWindow = false; + + Win32WindowingSystem::getInterface()->unregisterWindow(_hwnd); + + // + // Delete the original window after now one to prevent window "flashing" on screen + // + + HWND hwnd = _hwnd; + _hwnd = 0; // pretend native window has already been destroyed + + close(true, false); + init(); + realize(); + + ::DestroyWindow(hwnd); // destroy native window +#endif } bool GraphicsWindowWin32::determineWindowPositionAndStyle( bool decorated, int& x, int& y, unsigned int& w, unsigned int& h, unsigned int& style, unsigned int& extendedStyle ) @@ -1050,7 +1189,7 @@ bool GraphicsWindowWin32::determineWindowPositionAndStyle( bool decorated, int& if (!::AdjustWindowRectEx(&corners, style, FALSE, extendedStyle)) { - reportError("GraphicsWindowWin32::determineWindowPositionAndStyle() - Unable to adjust window rectangle", ::GetLastError()); + reportErrorForScreen("GraphicsWindowWin32::determineWindowPositionAndStyle() - Unable to adjust window rectangle", _traits->screenNum, ::GetLastError()); return false; } @@ -1063,28 +1202,10 @@ bool GraphicsWindowWin32::determineWindowPositionAndStyle( bool decorated, int& return true; } -bool GraphicsWindowWin32::setPixelFormat() +static void PreparePixelFormatSpecifications( const osg::GraphicsContext::Traits& traits, + WGLIntegerAttributes& attributes, + bool allowSwapExchangeARB ) { - Win32WindowingSystem::OpenGLContext glContext = Win32WindowingSystem::getInterface()->getSampleOpenGLContext(); - if (!glContext.makeCurrent(true)) return false; - - // - // Access the entry point for the wglChoosePixelFormatARB function - // - - WGLChoosePixelFormatARB wglChoosePixelFormatARB = (WGLChoosePixelFormatARB)wglGetProcAddress("wglChoosePixelFormatARB"); - if (wglChoosePixelFormatARB==0) - { - reportError("GraphicsWindowWin32::setPixelFormat() - wglChoosePixelFormatARB extension not found", ::GetLastError()); - return false; - } - - // - // Build the specifications of the requested pixel format - // - - WGLIntegerAttributes attributes; - attributes.begin(); attributes.enable(WGL_DRAW_TO_WINDOW_ARB); @@ -1093,49 +1214,88 @@ bool GraphicsWindowWin32::setPixelFormat() attributes.set(WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB); attributes.set(WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB); - attributes.set(WGL_COLOR_BITS_ARB, _traits->red + _traits->green + _traits->blue); - attributes.set(WGL_RED_BITS_ARB, _traits->red); - attributes.set(WGL_GREEN_BITS_ARB, _traits->green); - attributes.set(WGL_BLUE_BITS_ARB, _traits->blue); - attributes.set(WGL_DEPTH_BITS_ARB, _traits->depth); + attributes.set(WGL_COLOR_BITS_ARB, traits.red + traits.green + traits.blue); + attributes.set(WGL_RED_BITS_ARB, traits.red); + attributes.set(WGL_GREEN_BITS_ARB, traits.green); + attributes.set(WGL_BLUE_BITS_ARB, traits.blue); + attributes.set(WGL_DEPTH_BITS_ARB, traits.depth); - if (_traits->doubleBuffer) + if (traits.doubleBuffer) { attributes.enable(WGL_DOUBLE_BUFFER_ARB); - attributes.set(WGL_SWAP_METHOD_ARB, WGL_SWAP_EXCHANGE_ARB); + if (allowSwapExchangeARB) attributes.set(WGL_SWAP_METHOD_ARB, WGL_SWAP_EXCHANGE_ARB); } - if (_traits->alpha) attributes.set(WGL_ALPHA_BITS_ARB, _traits->alpha); - if (_traits->stencil) attributes.set(WGL_STENCIL_BITS_ARB, _traits->stencil); - if (_traits->sampleBuffers) attributes.set(WGL_SAMPLE_BUFFERS_ARB, _traits->sampleBuffers); - if (_traits->samples) attributes.set(WGL_SAMPLES_ARB, _traits->samples); + if (traits.alpha) attributes.set(WGL_ALPHA_BITS_ARB, traits.alpha); + if (traits.stencil) attributes.set(WGL_STENCIL_BITS_ARB, traits.stencil); + if (traits.sampleBuffers) attributes.set(WGL_SAMPLE_BUFFERS_ARB, traits.sampleBuffers); + if (traits.samples) attributes.set(WGL_SAMPLES_ARB, traits.samples); - if (_traits->quadBufferStereo) attributes.enable(WGL_STEREO_ARB); + if (traits.quadBufferStereo) attributes.enable(WGL_STEREO_ARB); attributes.end(); +} +static int ChooseMatchingPixelFormat( HDC hdc, int screenNum, const WGLIntegerAttributes& formatSpecifications ) +{ // - // Choose the closest pixel format from the specified traits + // Access the entry point for the wglChoosePixelFormatARB function // + WGLChoosePixelFormatARB wglChoosePixelFormatARB = (WGLChoosePixelFormatARB)wglGetProcAddress("wglChoosePixelFormatARB"); + if (wglChoosePixelFormatARB==0) + { + reportErrorForScreen("ChooseMatchingPixelFormat() - wglChoosePixelFormatARB extension not found", screenNum, ::GetLastError()); + return -1; + } + int pixelFormatIndex = 0; unsigned int numMatchingPixelFormats = 0; - if (!wglChoosePixelFormatARB(glContext.deviceContext(), - attributes.get(), + if (!wglChoosePixelFormatARB(hdc, + formatSpecifications.get(), NULL, 1, &pixelFormatIndex, &numMatchingPixelFormats)) { - reportError("GraphicsWindowWin32::setPixelFormat() - Unable to choose the requested pixel format", ::GetLastError()); - return false; + reportErrorForScreen("ChooseMatchingPixelFormat() - Unable to choose the requested pixel format", screenNum, ::GetLastError()); + return -1; } - if (numMatchingPixelFormats==0) + return numMatchingPixelFormats==0 ? -1 : pixelFormatIndex; +} + +bool GraphicsWindowWin32::setPixelFormat() +{ + Win32WindowingSystem::OpenGLContext openGLContext; + if (!Win32WindowingSystem::getInterface()->getSampleOpenGLContext(openGLContext, _hdc, _screenOriginX, _screenOriginY)) return false; + + // + // Build the specifications of the requested pixel format + // + + WGLIntegerAttributes formatSpecs; + ::PreparePixelFormatSpecifications(*_traits, formatSpecs, true); + + // + // Choose the closest matching pixel format from the specified traits + // + + int pixelFormatIndex = ::ChooseMatchingPixelFormat(openGLContext.deviceContext(), _traits->screenNum, formatSpecs); + if (pixelFormatIndex<0) { - reportError("GraphicsWindowWin32::setPixelFormat() - No matching pixel format found based on traits specified", ::GetLastError()); - return false; + ::PreparePixelFormatSpecifications(*_traits, formatSpecs, false); + pixelFormatIndex = ::ChooseMatchingPixelFormat(openGLContext.deviceContext(), _traits->screenNum, formatSpecs); + if (pixelFormatIndex<0) + { + reportErrorForScreen("GraphicsWindowWin32::setPixelFormat() - No matching pixel format found based on traits specified", _traits->screenNum, 0); + return false; + } + + osg::notify(osg::WARN) << "GraphicsWindowWin32::setPixelFormat() - Found a matching pixel format but without the WGL_SWAP_METHOD_ARB specification for screen #" + << _traits->screenNum + << std::endl; } // @@ -1149,7 +1309,7 @@ bool GraphicsWindowWin32::setPixelFormat() if (!::SetPixelFormat(_hdc, pixelFormatIndex, &pfd)) { - reportError("GraphicsWindowWin32::setPixelFormat() - Unable to set pixel format", ::GetLastError()); + reportErrorForScreen("GraphicsWindowWin32::setPixelFormat() - Unable to set pixel format", _traits->screenNum, ::GetLastError()); return false; } @@ -1160,7 +1320,7 @@ bool GraphicsWindowWin32::setPixelFormat() _hglrc = ::wglCreateContext(_hdc); if (_hglrc==0) { - reportError("GraphicsWindowWin32::setPixelFormat() - Unable to create OpenGL rendering context", ::GetLastError()); + reportErrorForScreen("GraphicsWindowWin32::setPixelFormat() - Unable to create OpenGL rendering context", _traits->screenNum, ::GetLastError()); return false; } @@ -1181,7 +1341,7 @@ void GraphicsWindowWin32::setWindowDecoration( bool decorated ) if (!determineWindowPositionAndStyle(decorated, x, y, w, h, windowStyle, extendedStyle)) { - reportError("GraphicsWindowWin32::setWindowDecoration() - Unable to determine the window position and style"); + reportErrorForScreen("GraphicsWindowWin32::setWindowDecoration() - Unable to determine the window position and style", _traits->screenNum, 0); return; } @@ -1194,7 +1354,7 @@ void GraphicsWindowWin32::setWindowDecoration( bool decorated ) unsigned int error = ::GetLastError(); if (result==0 && error) { - reportError("GraphicsWindowWin32::setWindowDecoration() - Unable to set window style", error); + reportErrorForScreen("GraphicsWindowWin32::setWindowDecoration() - Unable to set window style", _traits->screenNum, error); return; } @@ -1207,7 +1367,7 @@ void GraphicsWindowWin32::setWindowDecoration( bool decorated ) error = ::GetLastError(); if (result==0 && error) { - reportError("GraphicsWindowWin32::setWindowDecoration() - Unable to set window extented style", error); + reportErrorForScreen("GraphicsWindowWin32::setWindowDecoration() - Unable to set window extented style", _traits->screenNum, error); return; } @@ -1217,7 +1377,7 @@ void GraphicsWindowWin32::setWindowDecoration( bool decorated ) if (!::SetWindowPos(_hwnd, HWND_TOP, x, y, w, h, SWP_FRAMECHANGED | SWP_NOZORDER | SWP_SHOWWINDOW)) { - reportError("GraphicsWindowWin32::setWindowDecoration() - Unable to set new window position and size", ::GetLastError()); + reportErrorForScreen("GraphicsWindowWin32::setWindowDecoration() - Unable to set new window position and size", _traits->screenNum, ::GetLastError()); return; } @@ -1257,13 +1417,13 @@ bool GraphicsWindowWin32::realizeImplementation() _windowHeightToRealize, SWP_SHOWWINDOW)) { - reportError("GraphicsWindowWin32::realizeImplementation() - Unable to show window", ::GetLastError()); + reportErrorForScreen("GraphicsWindowWin32::realizeImplementation() - Unable to show window", _traits->screenNum, ::GetLastError()); return false; } - + if (!::UpdateWindow(_hwnd)) { - reportError("GraphicsWindowWin32::realizeImplementation() - Unable to update window", ::GetLastError()); + reportErrorForScreen("GraphicsWindowWin32::realizeImplementation() - Unable to update window", _traits->screenNum, ::GetLastError()); return false; } @@ -1276,13 +1436,13 @@ bool GraphicsWindowWin32::makeCurrentImplementation() { if (!_realized) { - reportError("GraphicsWindowWin32::makeCurrentImplementation() - Window not realized; cannot do makeCurrent."); + reportErrorForScreen("GraphicsWindowWin32::makeCurrentImplementation() - Window not realized; cannot do makeCurrent.", _traits->screenNum, 0); return false; } if (!::wglMakeCurrent(_hdc, _hglrc)) { - reportError("GraphicsWindowWin32::makeCurrentImplementation() - Unable to set current OpenGL rendering context", ::GetLastError()); + reportErrorForScreen("GraphicsWindowWin32::makeCurrentImplementation() - Unable to set current OpenGL rendering context", _traits->screenNum, ::GetLastError()); return false; } @@ -1293,7 +1453,7 @@ bool GraphicsWindowWin32::releaseContextImplementation() { if (!::wglMakeCurrent(_hdc, NULL)) { - reportError("GraphicsWindowWin32::releaseContextImplementation() - Unable to release current OpenGL rendering context", ::GetLastError()); + reportErrorForScreen("GraphicsWindowWin32::releaseContextImplementation() - Unable to release current OpenGL rendering context", _traits->screenNum, ::GetLastError()); return false; } @@ -1314,7 +1474,7 @@ void GraphicsWindowWin32::swapBuffersImplementation() if (!_realized) return; if (!::SwapBuffers(_hdc)) { - reportError("GraphicsWindowWin32::swapBuffersImplementation() - Unable to swap display buffers", ::GetLastError()); + reportErrorForScreen("GraphicsWindowWin32::swapBuffersImplementation() - Unable to swap display buffers", _traits->screenNum, ::GetLastError()); } } @@ -1328,6 +1488,8 @@ void GraphicsWindowWin32::checkEvents() ::TranslateMessage(&msg); ::DispatchMessage(&msg); } + + if (_recreateWindow) recreateWindow(); } void GraphicsWindowWin32::grabFocus() @@ -1343,14 +1505,14 @@ void GraphicsWindowWin32::grabFocusIfPointerInWindow() POINT mousePos; if (!::GetCursorPos(&mousePos)) { - reportError("GraphicsWindowWin32::grabFocusIfPointerInWindow() - Unable to get cursor position", ::GetLastError()); + reportErrorForScreen("GraphicsWindowWin32::grabFocusIfPointerInWindow() - Unable to get cursor position", _traits->screenNum, ::GetLastError()); return; } RECT windowRect; if (!::GetWindowRect(_hwnd, &windowRect)) { - reportError("GraphicsWindowWin32::grabFocusIfPointerInWindow() - Unable to get window position", ::GetLastError()); + reportErrorForScreen("GraphicsWindowWin32::grabFocusIfPointerInWindow() - Unable to get window position", _traits->screenNum, ::GetLastError()); return; } @@ -1361,6 +1523,36 @@ void GraphicsWindowWin32::grabFocusIfPointerInWindow() } } +void GraphicsWindowWin32::requestWarpPointer( float x, float y ) +{ + if (!_realized) + { + reportErrorForScreen("GraphicsWindowWin32::requestWarpPointer() - Window not realized; cannot warp pointer", _traits->screenNum, 0); + return; + } + + RECT windowRect; + + if (!::GetWindowRect(_hwnd, &windowRect)) + { + reportErrorForScreen("GraphicsWindowWin32::requestWarpPointer() - Unable to get window rectangle", _traits->screenNum, ::GetLastError()); + return; + } + + if (!::SetCursorPos(windowRect.left + x, windowRect.top + y)) + { + reportErrorForScreen("GraphicsWindowWin32::requestWarpPointer() - Unable to set cursor position", _traits->screenNum, ::GetLastError()); + return; + } + + getEventQueue()->mouseWarped(x,y); +} + +void GraphicsWindowWin32::useCursor( bool cursorOn ) +{ + _traits->useCursor = cursorOn; +} + void GraphicsWindowWin32::adaptKey( WPARAM wParam, LPARAM lParam, int& keySymbol, unsigned int& modifierMask ) { modifierMask = 0; @@ -1414,11 +1606,52 @@ void GraphicsWindowWin32::transformMouseXY( float& x, float& y ) if (getEventQueue()->getUseFixedMouseInputRange()) { osgGA::GUIEventAdapter* eventState = getEventQueue()->getCurrentEventState(); + x = eventState->getXmin() + (eventState->getXmax()-eventState->getXmin())*x/float(_traits->width); y = eventState->getYmin() + (eventState->getYmax()-eventState->getYmin())*y/float(_traits->height); } } +int GraphicsWindowWin32::getScreenNumberContainingWindow( int& _screenOriginX, int& _screenOriginY ) +{ + RECT clientArea; + + clientArea.left = _traits->x + _screenOriginX; + clientArea.top = _traits->y + _screenOriginY; + clientArea.right = _traits->x + _screenOriginX + _traits->width - 1; + clientArea.bottom = _traits->y + _screenOriginY + _traits->height - 1; + + HMONITOR hMonitor = ::MonitorFromRect(&clientArea, MONITOR_DEFAULTTONULL); + if (hMonitor==NULL) return _traits->screenNum; + + MONITORINFO monitorInfo; + + monitorInfo.cbSize = sizeof(monitorInfo); + if (!::GetMonitorInfo(hMonitor, &monitorInfo)) + { + reportErrorForScreen("GraphicsWindowWin32::getScreenNumberContainingWindow() - Unable to get monitor information", _traits->screenNum, ::GetLastError()); + return _traits->screenNum; + } + + Win32WindowingSystem* windowManager = Win32WindowingSystem::getInterface(); + + for (int screenNum=windowManager->getNumScreens(osg::GraphicsContext::ScreenIdentifier())-1; screenNum>=0; --screenNum) + { + int x, y; + unsigned w, h; + + windowManager->getScreenPosition(osg::GraphicsContext::ScreenIdentifier(screenNum), x, y, w, h); + if (x==monitorInfo.rcWork.left && y==monitorInfo.rcWork.top) + { + _screenOriginX = x; + _screenOriginY = y; + return screenNum; + } + } + + return _traits->screenNum; +} + LRESULT GraphicsWindowWin32::handleNativeWindowingEvent( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) { //!@todo adapt windows event time to osgGA event queue time for better resolution @@ -1461,6 +1694,8 @@ LRESULT GraphicsWindowWin32::handleNativeWindowingEvent( HWND hwnd, UINT uMsg, W ///////////////////// { + ::SetCapture(hwnd); + int button; if (uMsg==WM_LBUTTONDOWN) button = 1; @@ -1481,6 +1716,8 @@ LRESULT GraphicsWindowWin32::handleNativeWindowingEvent( HWND hwnd, UINT uMsg, W ///////////////////// { + ::ReleaseCapture(); + int button; if (uMsg==WM_LBUTTONUP) button = 1; @@ -1548,6 +1785,31 @@ LRESULT GraphicsWindowWin32::handleNativeWindowingEvent( HWND hwnd, UINT uMsg, W } break; +#ifdef NEXT_RELEASE_ONLY + ////////////////////// + case WM_EXITSIZEMOVE : + ////////////////////// + + { + int vx = _traits->x + _screenOriginX; + int vy = _traits->y + _screenOriginY; + + int screenNum = getScreenNumberContainingWindow(_screenOriginX, _screenOriginY); + if (screenNum!=_traits->screenNum) + { + _recreateWindow = true; + + _traits->screenNum = screenNum; + int x = vx - _screenOriginX; + int y = vy - _screenOriginY; + + resized(x, y, _traits->width, _traits->height); + getEventQueue()->windowResize(x, y, _traits->width, _traits->height, _timeOfLastCheckEvents); + } + } + break; +#endif + //////////////////// case WM_KEYDOWN : case WM_SYSKEYDOWN : @@ -1576,6 +1838,14 @@ LRESULT GraphicsWindowWin32::handleNativeWindowingEvent( HWND hwnd, UINT uMsg, W } break; + /////////////////// + case WM_SETCURSOR : + /////////////////// + + if (_traits->useCursor) return ::DefWindowProc(hwnd, uMsg, wParam, lParam); + ::SetCursor(NULL); + return TRUE; + ///////////////// case WM_CLOSE : ///////////////// @@ -1592,6 +1862,13 @@ LRESULT GraphicsWindowWin32::handleNativeWindowingEvent( HWND hwnd, UINT uMsg, W ::PostQuitMessage(0); break; + ////////////// + case WM_QUIT : + ////////////// + + close(); + return wParam; + ///////////////// default : /////////////////