root/OpenSceneGraph/branches/OpenSceneGraph-2.8/src/osgViewer/GraphicsWindowWin32.cpp @ 10148

Revision 10148, 85.4 kB (checked in by robert, 5 years ago)

From Chris Denham, fix for swapBuffers warning when window is minimized under Windows.

svn merge -r 10146:10147 http://www.openscenegraph.org/svn/osg/OpenSceneGraph/trunk/src/osgViewer/

  • Property svn:mergeinfo set to /OpenSceneGraph/trunk/src/osgViewer/GraphicsWindowWin32.cpp:9824,10147
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
2 *
3 * This library is open source and may be redistributed and/or modified under 
4 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
5 * (at your option) any later version.  The full license is in LICENSE file
6 * included with this distribution, and on the openscenegraph.org website.
7 *
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 * OpenSceneGraph Public License for more details.
12 *
13 * This file is Copyright (C) 2007 - André Garneau (andre@pixdev.com) and licensed under OSGPL.
14 *
15 * Some elements of GraphicsWindowWin32 have used the Producer implementation as a reference.
16 * These elements are licensed under OSGPL as above, with Copyright (C) 2001-2004  Don Burns.
17 */
18
19#include <osgViewer/api/Win32/GraphicsWindowWin32>
20#include <osgViewer/api/Win32/PixelBufferWin32>
21
22#include <osg/DeleteHandler>
23#include <osg/ApplicationUsage>
24
25#include <vector>
26#include <map>
27#include <sstream>
28#include <windowsx.h>
29
30using namespace osgViewer;
31
32namespace osgViewer
33{
34
35static osg::ApplicationUsageProxy GraphicsWindowWin32_e0(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_WIN32_NV_MULTIMON_MULTITHREAD_WORKAROUND on/off","Enable/disable duplicate makeCurrentContext call used as workaround for WinXP/NVidia/MultiView/MulitThread isues (pre 178.13 drivers).");
36
37//
38// Defines from the WGL_ARB_pixel_format specification document
39// See http://www.opengl.org/registry/specs/ARB/wgl_pixel_format.txt
40//
41
42#define WGL_NUMBER_PIXEL_FORMATS_ARB            0x2000
43#define WGL_DRAW_TO_WINDOW_ARB                  0x2001
44#define WGL_DRAW_TO_BITMAP_ARB                  0x2002
45#define WGL_ACCELERATION_ARB                    0x2003
46#define WGL_NEED_PALETTE_ARB                    0x2004
47#define WGL_NEED_SYSTEM_PALETTE_ARB             0x2005
48#define WGL_SWAP_LAYER_BUFFERS_ARB              0x2006
49#define WGL_SWAP_METHOD_ARB                     0x2007
50#define WGL_NUMBER_OVERLAYS_ARB                 0x2008
51#define WGL_NUMBER_UNDERLAYS_ARB                0x2009
52#define WGL_TRANSPARENT_ARB                     0x200A
53#define WGL_TRANSPARENT_RED_VALUE_ARB           0x2037
54#define WGL_TRANSPARENT_GREEN_VALUE_ARB         0x2038
55#define WGL_TRANSPARENT_BLUE_VALUE_ARB          0x2039
56#define WGL_TRANSPARENT_ALPHA_VALUE_ARB         0x203A
57#define WGL_TRANSPARENT_INDEX_VALUE_ARB         0x203B
58#define WGL_SHARE_DEPTH_ARB                     0x200C
59#define WGL_SHARE_STENCIL_ARB                   0x200D
60#define WGL_SHARE_ACCUM_ARB                     0x200E
61#define WGL_SUPPORT_GDI_ARB                     0x200F
62#define WGL_SUPPORT_OPENGL_ARB                  0x2010
63#define WGL_DOUBLE_BUFFER_ARB                   0x2011
64#define WGL_STEREO_ARB                          0x2012
65#define WGL_PIXEL_TYPE_ARB                      0x2013
66#define WGL_COLOR_BITS_ARB                      0x2014
67#define WGL_RED_BITS_ARB                        0x2015
68#define WGL_RED_SHIFT_ARB                       0x2016
69#define WGL_GREEN_BITS_ARB                      0x2017
70#define WGL_GREEN_SHIFT_ARB                     0x2018
71#define WGL_BLUE_BITS_ARB                       0x2019
72#define WGL_BLUE_SHIFT_ARB                      0x201A
73#define WGL_ALPHA_BITS_ARB                      0x201B
74#define WGL_ALPHA_SHIFT_ARB                     0x201C
75#define WGL_ACCUM_BITS_ARB                      0x201D
76#define WGL_ACCUM_RED_BITS_ARB                  0x201E
77#define WGL_ACCUM_GREEN_BITS_ARB                0x201F
78#define WGL_ACCUM_BLUE_BITS_ARB                 0x2020
79#define WGL_ACCUM_ALPHA_BITS_ARB                0x2021
80#define WGL_DEPTH_BITS_ARB                      0x2022
81#define WGL_STENCIL_BITS_ARB                    0x2023
82#define WGL_AUX_BUFFERS_ARB                     0x2024
83#define WGL_NO_ACCELERATION_ARB                 0x2025
84#define WGL_GENERIC_ACCELERATION_ARB            0x2026
85#define WGL_FULL_ACCELERATION_ARB               0x2027
86#define WGL_SWAP_EXCHANGE_ARB                   0x2028
87#define WGL_SWAP_COPY_ARB                       0x2029
88#define WGL_SWAP_UNDEFINED_ARB                  0x202A
89#define WGL_TYPE_RGBA_ARB                       0x202B
90#define WGL_TYPE_COLORINDEX_ARB                 0x202C
91#define WGL_SAMPLE_BUFFERS_ARB                  0x2041
92#define WGL_SAMPLES_ARB                         0x2042
93
94//
95// Entry points used from the WGL extensions
96//
97//    BOOL wglChoosePixelFormatARB(HDC hdc,
98//                                 const int *piAttribIList,
99//                                 const FLOAT *pfAttribFList,
100//                                 UINT nMaxFormats,
101//                                 int *piFormats,
102//                                 UINT *nNumFormats);
103//
104
105typedef bool (WINAPI * WGLChoosePixelFormatARB) ( HDC, const int *, const float *, unsigned int, int *, unsigned int * );
106
107//
108// Utility class to specify the visual attributes for wglChoosePixelFormatARB() function
109//
110
111template <typename T> class WGLAttributes
112{
113  public:
114
115      WGLAttributes()  {}
116      ~WGLAttributes() {}
117
118      void begin()                              { m_parameters.clear(); }
119      void set( const T& id, const T& value )   { add(id); add(value); }
120      void enable( const T& id )                { add(id); add(true); }
121      void disable( const T& id )               { add(id); add(false); }
122      void end()                                { add(0); }
123
124      const T* get() const                      { return &m_parameters.front(); }
125
126  protected:
127
128      void add( const T& t )                    { m_parameters.push_back(t); }
129
130      std::vector<T>    m_parameters;        // parameters added
131
132  private:
133
134      // No implementation for these
135      WGLAttributes( const WGLAttributes& );
136      WGLAttributes& operator=( const WGLAttributes& );
137};
138
139typedef WGLAttributes<int>     WGLIntegerAttributes;
140typedef WGLAttributes<float> WGLFloatAttributes;
141
142//
143// Class responsible for interfacing with the Win32 Window Manager
144// The behavior of this class is specific to OSG needs and is not a
145// generic Windowing interface.
146//
147// NOTE: This class is intended to be used by a single-thread.
148//         Multi-threading is not enabled for performance reasons.
149//         The creation/deletion of graphics windows should be done
150//         by a single controller thread. That thread should then
151//         call the checkEvents() method of all created windows periodically.
152//         This is the case with OSG as a "main" thread does all
153//         setup, update & event processing. Rendering is done (optionally) by other threads.
154//
155// !@todo Have a dedicated thread managed by the Win32WindowingSystem class handle the
156//        creation and event message processing for all windows it manages. This
157//        is to relieve the "main" thread from having to do this synchronously
158//        during frame generation. The "main" thread would only have to process
159//          each osgGA-type window event queue.
160//
161
162class Win32WindowingSystem : public osg::GraphicsContext::WindowingSystemInterface
163{
164  public:
165
166    // A class representing an OpenGL rendering context
167    class OpenGLContext
168    {
169      public:
170
171        OpenGLContext()
172        : _previousHdc(0),
173          _previousHglrc(0),
174          _hwnd(0),
175          _hdc(0),
176          _hglrc(0),
177          _restorePreviousOnExit(false)
178        {}
179
180        OpenGLContext( HWND hwnd, HDC hdc, HGLRC hglrc )
181        : _previousHdc(0),
182          _previousHglrc(0),
183          _hwnd(hwnd),
184          _hdc(hdc),
185          _hglrc(hglrc),
186          _restorePreviousOnExit(false)
187        {}
188
189        ~OpenGLContext();
190
191        void set( HWND hwnd, HDC hdc, HGLRC hglrc )
192        {
193            _hwnd  = hwnd;
194            _hdc   = hdc;
195            _hglrc = hglrc;
196        }
197
198        HDC deviceContext() { return _hdc; }
199
200        bool makeCurrent( HDC restoreOnHdc, bool restorePreviousOnExit );
201
202      protected:
203
204        //
205        // Data members
206        //
207
208        HDC   _previousHdc;                // previously HDC to restore rendering context on
209        HGLRC _previousHglrc;           // previously current rendering context
210        HWND  _hwnd;                    // handle to OpenGL window
211        HDC   _hdc;                     // handle to device context
212        HGLRC _hglrc;                   // handle to OpenGL rendering context
213        bool  _restorePreviousOnExit;   // restore original context on exit
214
215        private:
216
217        // no implementation for these
218        OpenGLContext( const OpenGLContext& );
219        OpenGLContext& operator=( const OpenGLContext& );
220    };
221
222    static std::string osgGraphicsWindowWithCursorClass;    //!< Name of Win32 window class (with cursor) used by OSG graphics window instances
223    static std::string osgGraphicsWindowWithoutCursorClass; //!< Name of Win32 window class (without cursor) used by OSG graphics window instances
224
225    Win32WindowingSystem();
226    ~Win32WindowingSystem();
227
228    // Access the Win32 windowing system through this singleton class.
229    static Win32WindowingSystem* getInterface()
230    {
231        static Win32WindowingSystem* win32Interface = new Win32WindowingSystem;
232        return win32Interface;
233    }
234
235    // Return the number of screens present in the system
236    virtual unsigned int getNumScreens( const osg::GraphicsContext::ScreenIdentifier& si );
237
238    // Return the resolution of specified screen
239    // (0,0) is returned if screen is unknown
240    virtual void getScreenSettings( const osg::GraphicsContext::ScreenIdentifier& si, osg::GraphicsContext::ScreenSettings & resolution );
241
242    // Return the bits per pixel of specified screen
243    // (0) is returned if screen is unknown
244    virtual void getScreenColorDepth( const osg::GraphicsContext::ScreenIdentifier& si, unsigned int& dmBitsPerPel );
245
246    // Set the resolution for given screen
247    virtual bool setScreenSettings( const osg::GraphicsContext::ScreenIdentifier& si, const osg::GraphicsContext::ScreenSettings & resolution );
248
249    // Enumerates available resolutions
250    virtual void enumerateScreenSettings(const osg::GraphicsContext::ScreenIdentifier& screenIdentifier, osg::GraphicsContext::ScreenSettingsList & resolution);
251
252    // Return the screen position and width/height.
253    // all zeros returned if screen is unknown
254    virtual void getScreenPosition( const osg::GraphicsContext::ScreenIdentifier& si, int& originX, int& originY, unsigned int& width, unsigned int& height );
255
256    // Create a graphics context with given traits
257    virtual osg::GraphicsContext* createGraphicsContext( osg::GraphicsContext::Traits* traits );
258
259    // Register a newly created native window along with its application counterpart
260    // This is required to maintain a link between Windows messages and the application window object
261    // at event processing time
262    virtual void registerWindow( HWND hwnd, osgViewer::GraphicsWindowWin32* window );
263
264    // Unregister a window
265    // This is called as part of a window being torn down
266    virtual void unregisterWindow( HWND hwnd );
267
268    // Get the application window object associated with a native window
269    virtual osgViewer::GraphicsWindowWin32* getGraphicsWindowFor( HWND hwnd );
270
271    // Return a valid sample OpenGL Device Context and current rendering context that can be used with wglXYZ extensions
272    virtual bool getSampleOpenGLContext( OpenGLContext& context, HDC windowHDC, int windowOriginX, int windowOriginY );
273
274  protected:
275
276    // Display devices present in the system
277    typedef std::vector<DISPLAY_DEVICE> DisplayDevices;
278
279    // Map Win32 window handles to GraphicsWindowWin32 instance
280    typedef std::pair< HWND, osgViewer::GraphicsWindowWin32* >  WindowHandleEntry;
281    typedef std::map<  HWND, osgViewer::GraphicsWindowWin32* >  WindowHandles;
282
283    // Enumerate all display devices and return in passed container
284    void enumerateDisplayDevices( DisplayDevices& displayDevices ) const;
285
286    // Get the screen device current mode information
287    bool getScreenInformation( const osg::GraphicsContext::ScreenIdentifier& si, DISPLAY_DEVICE& displayDevice, DEVMODE& deviceMode );
288
289    // Change the screen settings (resolution, refresh rate, etc.)
290    bool changeScreenSettings( const osg::GraphicsContext::ScreenIdentifier& si, DISPLAY_DEVICE& displayDevice, DEVMODE& deviceMode );
291
292    // Register the window classes used by OSG graphics window instances
293    void registerWindowClasses();
294
295    // Unregister the window classes used by OSG graphics window instances
296    void unregisterWindowClasses();
297
298    // Data members
299    WindowHandles       _activeWindows;                //!< handles to active windows
300    bool                _windowClassesRegistered;      //!< true after window classes have been registered
301
302 private:
303
304     // No implementation for these
305     Win32WindowingSystem( const Win32WindowingSystem& );
306     Win32WindowingSystem& operator=( const Win32WindowingSystem& );
307};
308
309///////////////////////////////////////////////////////////////////////////////
310//                             Error reporting
311//////////////////////////////////////////////////////////////////////////////
312
313static void reportError( const std::string& msg )
314{
315    osg::notify(osg::WARN) << "Error: " << msg.c_str() << std::endl;
316}
317
318static void reportError( const std::string& msg, unsigned int errorCode )
319{
320    //
321    // Some APIs are documented as returning the error in ::GetLastError but apparently do not
322    // Skip "Reason" field if the errorCode is still success
323    //
324
325    if (errorCode==0)
326    {
327        reportError(msg);
328        return;
329    }
330
331    osg::notify(osg::WARN) << "Windows Error #"   << errorCode << ": " << msg.c_str();
332
333    LPVOID lpMsgBuf;
334
335    if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
336                      NULL,
337                      errorCode,
338                      0, // Default language
339                      (LPTSTR) &lpMsgBuf,
340                      0,
341                      NULL)!=0)
342    {
343        osg::notify(osg::WARN) << ". Reason: " << LPTSTR(lpMsgBuf) << std::endl;
344        ::LocalFree(lpMsgBuf);
345    }
346    else
347    {
348        osg::notify(osg::WARN) << std::endl;
349    }
350}
351
352static void reportErrorForScreen( const std::string& msg, const osg::GraphicsContext::ScreenIdentifier& si, unsigned int errorCode )
353{
354    std::ostringstream str;
355
356    str << "[Screen #" << si.screenNum << "] " << msg;
357    reportError(str.str(), errorCode);
358}
359
360//////////////////////////////////////////////////////////////////////////////
361//                       Keyboard key mapping for Win32
362//////////////////////////////////////////////////////////////////////////////
363
364class Win32KeyboardMap
365{
366    public:
367
368        Win32KeyboardMap()
369        {
370            _keymap[VK_ESCAPE       ] = osgGA::GUIEventAdapter::KEY_Escape;
371            _keymap[VK_F1           ] = osgGA::GUIEventAdapter::KEY_F1;
372            _keymap[VK_F2           ] = osgGA::GUIEventAdapter::KEY_F2;
373            _keymap[VK_F3           ] = osgGA::GUIEventAdapter::KEY_F3;
374            _keymap[VK_F4           ] = osgGA::GUIEventAdapter::KEY_F4;
375            _keymap[VK_F5           ] = osgGA::GUIEventAdapter::KEY_F5;
376            _keymap[VK_F6           ] = osgGA::GUIEventAdapter::KEY_F6;
377            _keymap[VK_F7           ] = osgGA::GUIEventAdapter::KEY_F7;
378            _keymap[VK_F8           ] = osgGA::GUIEventAdapter::KEY_F8;
379            _keymap[VK_F9           ] = osgGA::GUIEventAdapter::KEY_F9;
380            _keymap[VK_F10          ] = osgGA::GUIEventAdapter::KEY_F10;
381            _keymap[VK_F11          ] = osgGA::GUIEventAdapter::KEY_F11;
382            _keymap[VK_F12          ] = osgGA::GUIEventAdapter::KEY_F12;
383            _keymap[0xc0            ] = '`';
384            _keymap['0'             ] = '0';
385            _keymap['1'             ] = '1';
386            _keymap['2'             ] = '2';
387            _keymap['3'             ] = '3';
388            _keymap['4'             ] = '4';
389            _keymap['5'             ] = '5';
390            _keymap['6'             ] = '6';
391            _keymap['7'             ] = '7';
392            _keymap['8'             ] = '8';
393            _keymap['9'             ] = '9';
394            _keymap[0xbd            ] = '-';
395            _keymap[0xbb            ] = '=';
396            _keymap[VK_BACK         ] = osgGA::GUIEventAdapter::KEY_BackSpace;
397            _keymap[VK_TAB          ] = osgGA::GUIEventAdapter::KEY_Tab;
398            _keymap['A'             ] = 'A';
399            _keymap['B'             ] = 'B';
400            _keymap['C'             ] = 'C';
401            _keymap['D'             ] = 'D';
402            _keymap['E'             ] = 'E';
403            _keymap['F'             ] = 'F';
404            _keymap['G'             ] = 'G';
405            _keymap['H'             ] = 'H';
406            _keymap['I'             ] = 'I';
407            _keymap['J'             ] = 'J';
408            _keymap['K'             ] = 'K';
409            _keymap['L'             ] = 'L';
410            _keymap['M'             ] = 'M';
411            _keymap['N'             ] = 'N';
412            _keymap['O'             ] = 'O';
413            _keymap['P'             ] = 'P';
414            _keymap['Q'             ] = 'Q';
415            _keymap['R'             ] = 'R';
416            _keymap['S'             ] = 'S';
417            _keymap['T'             ] = 'T';
418            _keymap['U'             ] = 'U';
419            _keymap['V'             ] = 'V';
420            _keymap['W'             ] = 'W';
421            _keymap['X'             ] = 'X';
422            _keymap['Y'             ] = 'Y';
423            _keymap['Z'             ] = 'Z';
424            _keymap[0xdb            ] = '[';
425            _keymap[0xdd            ] = ']';
426            _keymap[0xdc            ] = '\\';
427            _keymap[VK_CAPITAL      ] = osgGA::GUIEventAdapter::KEY_Caps_Lock;
428            _keymap[0xba            ] = ';';
429            _keymap[0xde            ] = '\'';
430            _keymap[VK_RETURN       ] = osgGA::GUIEventAdapter::KEY_Return;
431            _keymap[VK_LSHIFT       ] = osgGA::GUIEventAdapter::KEY_Shift_L;
432            _keymap[0xbc            ] = ',';
433            _keymap[0xbe            ] = '.';
434            _keymap[0xbf            ] = '/';
435            _keymap[VK_RSHIFT       ] = osgGA::GUIEventAdapter::KEY_Shift_R;
436            _keymap[VK_LCONTROL     ] = osgGA::GUIEventAdapter::KEY_Control_L;
437            _keymap[VK_LWIN         ] = osgGA::GUIEventAdapter::KEY_Super_L;
438            _keymap[VK_SPACE        ] = ' ';
439            _keymap[VK_LMENU        ] = osgGA::GUIEventAdapter::KEY_Alt_L;
440            _keymap[VK_RMENU        ] = osgGA::GUIEventAdapter::KEY_Alt_R;
441            _keymap[VK_RWIN         ] = osgGA::GUIEventAdapter::KEY_Super_R;
442            _keymap[VK_APPS         ] = osgGA::GUIEventAdapter::KEY_Menu;
443            _keymap[VK_RCONTROL     ] = osgGA::GUIEventAdapter::KEY_Control_R;
444            _keymap[VK_SNAPSHOT     ] = osgGA::GUIEventAdapter::KEY_Print;
445            _keymap[VK_SCROLL       ] = osgGA::GUIEventAdapter::KEY_Scroll_Lock;
446            _keymap[VK_PAUSE        ] = osgGA::GUIEventAdapter::KEY_Pause;
447            _keymap[VK_HOME         ] = osgGA::GUIEventAdapter::KEY_Home;
448            _keymap[VK_PRIOR        ] = osgGA::GUIEventAdapter::KEY_Page_Up;
449            _keymap[VK_END          ] = osgGA::GUIEventAdapter::KEY_End;
450            _keymap[VK_NEXT         ] = osgGA::GUIEventAdapter::KEY_Page_Down;
451            _keymap[VK_DELETE       ] = osgGA::GUIEventAdapter::KEY_Delete;
452            _keymap[VK_INSERT       ] = osgGA::GUIEventAdapter::KEY_Insert;
453            _keymap[VK_LEFT         ] = osgGA::GUIEventAdapter::KEY_Left;
454            _keymap[VK_UP           ] = osgGA::GUIEventAdapter::KEY_Up;
455            _keymap[VK_RIGHT        ] = osgGA::GUIEventAdapter::KEY_Right;
456            _keymap[VK_DOWN         ] = osgGA::GUIEventAdapter::KEY_Down;
457            _keymap[VK_NUMLOCK      ] = osgGA::GUIEventAdapter::KEY_Num_Lock;
458            _keymap[VK_DIVIDE       ] = osgGA::GUIEventAdapter::KEY_KP_Divide;
459            _keymap[VK_MULTIPLY     ] = osgGA::GUIEventAdapter::KEY_KP_Multiply;
460            _keymap[VK_SUBTRACT     ] = osgGA::GUIEventAdapter::KEY_KP_Subtract;
461            _keymap[VK_ADD          ] = osgGA::GUIEventAdapter::KEY_KP_Add;
462            _keymap[VK_NUMPAD7      ] = osgGA::GUIEventAdapter::KEY_KP_Home;
463            _keymap[VK_NUMPAD8      ] = osgGA::GUIEventAdapter::KEY_KP_Up;
464            _keymap[VK_NUMPAD9      ] = osgGA::GUIEventAdapter::KEY_KP_Page_Up;
465            _keymap[VK_NUMPAD4      ] = osgGA::GUIEventAdapter::KEY_KP_Left;
466            _keymap[VK_NUMPAD5      ] = osgGA::GUIEventAdapter::KEY_KP_Begin;
467            _keymap[VK_NUMPAD6      ] = osgGA::GUIEventAdapter::KEY_KP_Right;
468            _keymap[VK_NUMPAD1      ] = osgGA::GUIEventAdapter::KEY_KP_End;
469            _keymap[VK_NUMPAD2      ] = osgGA::GUIEventAdapter::KEY_KP_Down;
470            _keymap[VK_NUMPAD3      ] = osgGA::GUIEventAdapter::KEY_KP_Page_Down;
471            _keymap[VK_NUMPAD0      ] = osgGA::GUIEventAdapter::KEY_KP_Insert;
472            _keymap[VK_DECIMAL      ] = osgGA::GUIEventAdapter::KEY_KP_Delete;
473            _keymap[VK_CLEAR        ] = osgGA::GUIEventAdapter::KEY_Clear;
474        }
475
476        ~Win32KeyboardMap() {}
477
478        int remapKey(int key)
479        {
480            KeyMap::const_iterator map = _keymap.find(key);
481            return map==_keymap.end() ? key : map->second;
482        }
483
484    protected:
485
486        typedef std::map<int, int> KeyMap;
487        KeyMap _keymap;
488};
489
490static Win32KeyboardMap s_win32KeyboardMap;
491static int remapWin32Key(int key)
492{
493    return s_win32KeyboardMap.remapKey(key);
494}
495
496//////////////////////////////////////////////////////////////////////////////
497//         Window procedure for all GraphicsWindowWin32 instances
498//           Dispatches the call to the actual instance
499//////////////////////////////////////////////////////////////////////////////
500
501static LRESULT CALLBACK WindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
502{
503    osgViewer::GraphicsWindowWin32* window = Win32WindowingSystem::getInterface()->getGraphicsWindowFor(hwnd);
504    return window ? window->handleNativeWindowingEvent(hwnd, uMsg, wParam, lParam) :
505                    ::DefWindowProc(hwnd, uMsg, wParam, lParam);
506}
507
508//////////////////////////////////////////////////////////////////////////////
509//              Win32WindowingSystem::OpenGLContext implementation
510//////////////////////////////////////////////////////////////////////////////
511
512Win32WindowingSystem::OpenGLContext::~OpenGLContext()
513{
514    if (_restorePreviousOnExit && _previousHglrc!=_hglrc && !::wglMakeCurrent(_previousHdc, _previousHglrc))
515    {
516        reportError("Win32WindowingSystem::OpenGLContext() - Unable to restore current OpenGL rendering context", ::GetLastError());
517    }
518
519    _previousHdc   = 0;
520    _previousHglrc = 0;
521
522    if (_hglrc)
523    {
524        ::wglMakeCurrent(_hdc, NULL);
525        ::wglDeleteContext(_hglrc);
526        _hglrc = 0;
527    }
528
529    if (_hdc)
530    {
531        ::ReleaseDC(_hwnd, _hdc);
532        _hdc = 0;
533    }
534
535    if (_hwnd)
536    {
537        ::DestroyWindow(_hwnd);
538        _hwnd = 0;
539    }
540}
541
542bool Win32WindowingSystem::OpenGLContext::makeCurrent( HDC restoreOnHdc, bool restorePreviousOnExit )
543{
544    if (_hdc==0 || _hglrc==0) return false;
545
546    _previousHglrc = restorePreviousOnExit ? ::wglGetCurrentContext() : 0;
547    _previousHdc   = restoreOnHdc;
548
549    if (_hglrc==_previousHglrc) return true;
550
551    if (!::wglMakeCurrent(_hdc, _hglrc))
552    {
553        reportError("Win32WindowingSystem::OpenGLContext() - Unable to set current OpenGL rendering context", ::GetLastError());
554        return false;
555    }
556
557    _restorePreviousOnExit = restorePreviousOnExit;
558
559    return true;
560}
561
562//////////////////////////////////////////////////////////////////////////////
563//              Win32WindowingSystem implementation
564//////////////////////////////////////////////////////////////////////////////
565
566std::string Win32WindowingSystem::osgGraphicsWindowWithCursorClass;
567std::string Win32WindowingSystem::osgGraphicsWindowWithoutCursorClass;
568
569Win32WindowingSystem::Win32WindowingSystem()
570: _windowClassesRegistered(false)
571{
572}
573
574Win32WindowingSystem::~Win32WindowingSystem()
575{
576    if (osg::Referenced::getDeleteHandler())
577    {
578        osg::Referenced::getDeleteHandler()->setNumFramesToRetainObjects(0);
579        osg::Referenced::getDeleteHandler()->flushAll();
580    }
581   
582    unregisterWindowClasses();
583}
584
585void Win32WindowingSystem::enumerateDisplayDevices( DisplayDevices& displayDevices ) const
586{
587    for (unsigned int deviceNum=0;; ++deviceNum)
588    {
589        DISPLAY_DEVICE displayDevice;
590        displayDevice.cb = sizeof(displayDevice);
591
592        if (!::EnumDisplayDevices(NULL, deviceNum, &displayDevice, 0)) break;
593
594        // Do not track devices used for remote access (Terminal Services pseudo-displays, etc.)
595        if (displayDevice.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER) continue;
596
597        // Only return display devices that are attached to the desktop
598        if (!(displayDevice.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP)) continue;
599
600        displayDevices.push_back(displayDevice);
601    }
602}
603
604void Win32WindowingSystem::registerWindowClasses()
605{
606    if (_windowClassesRegistered) return;
607
608    //
609    // Register the window classes used by OSG GraphicsWindowWin32 instances
610    //
611
612    std::ostringstream str;
613    str << "OSG Graphics Window for Win32 [" << ::GetCurrentProcessId() << "]";
614
615    osgGraphicsWindowWithCursorClass    = str.str() + "{ with cursor }";
616    osgGraphicsWindowWithoutCursorClass = str.str() + "{ without cursor }";
617
618    WNDCLASSEX wc;
619
620    HINSTANCE hinst = ::GetModuleHandle(NULL);
621
622    //
623    // First class: class for OSG Graphics Window with a cursor enabled
624    //
625
626    wc.cbSize        = sizeof(wc);
627    wc.style         = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
628    wc.lpfnWndProc   = WindowProc;
629    wc.cbClsExtra    = 0;
630    wc.cbWndExtra    = 0;
631    wc.hInstance     = hinst;
632    wc.hIcon         = ::LoadIcon(hinst, "OSG_ICON");
633    wc.hCursor       = ::LoadCursor(NULL, IDC_ARROW);
634    wc.hbrBackground = NULL;
635    wc.lpszMenuName  = 0;
636    wc.lpszClassName = osgGraphicsWindowWithCursorClass.c_str();
637    wc.hIconSm       = NULL;
638
639    if (::RegisterClassEx(&wc)==0)
640    {
641        unsigned int lastError = ::GetLastError();
642        if (lastError!=ERROR_CLASS_ALREADY_EXISTS)
643        {
644            reportError("Win32WindowingSystem::registerWindowClasses() - Unable to register first window class", lastError);
645            return;
646        }
647    }
648
649    //
650    // Second class: class for OSG Graphics Window without a cursor
651    //
652
653    wc.hCursor       = NULL;
654    wc.lpszClassName = osgGraphicsWindowWithoutCursorClass.c_str();
655
656    if (::RegisterClassEx(&wc)==0)
657    {
658        unsigned int lastError = ::GetLastError();
659        if (lastError!=ERROR_CLASS_ALREADY_EXISTS)
660        {
661            reportError("Win32WindowingSystem::registerWindowClasses() - Unable to register second window class", lastError);
662            return;
663        }
664    }
665
666    _windowClassesRegistered = true;
667}
668
669void Win32WindowingSystem::unregisterWindowClasses()
670{
671    if (_windowClassesRegistered)
672    {
673        ::UnregisterClass(osgGraphicsWindowWithCursorClass.c_str(),    ::GetModuleHandle(NULL));
674        ::UnregisterClass(osgGraphicsWindowWithoutCursorClass.c_str(), ::GetModuleHandle(NULL));
675        _windowClassesRegistered = false;
676    }
677}
678
679bool Win32WindowingSystem::getSampleOpenGLContext( OpenGLContext& context, HDC windowHDC, int windowOriginX, int windowOriginY )
680{
681    context.set(0, 0, 0);
682
683    registerWindowClasses();
684
685    HWND hwnd = ::CreateWindowEx(WS_EX_OVERLAPPEDWINDOW,
686                                 osgGraphicsWindowWithoutCursorClass.c_str(),
687                                 NULL,
688                                 WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_DISABLED,
689                                 windowOriginX,
690                                 windowOriginY,
691                                 1,
692                                 1,
693                                 NULL,
694                                 NULL,
695                                 ::GetModuleHandle(NULL),
696                                 NULL);
697    if (hwnd==0)
698    {
699        reportError("Win32WindowingSystem::getSampleOpenGLContext() - Unable to create window", ::GetLastError());
700        return false;
701    }
702
703    //
704    // Set the pixel format of the window
705    //
706
707    PIXELFORMATDESCRIPTOR pixelFormat =
708    {
709        sizeof(PIXELFORMATDESCRIPTOR),
710        1,
711        PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL,
712        PFD_TYPE_RGBA,
713        24,
714        0, 0, 0, 0, 0, 0, 0, 0,
715        0, 0, 0, 0, 0,
716        24,
717        0,
718        0,
719        PFD_MAIN_PLANE,
720        0,
721        0, 0, 0
722    };
723
724    HDC hdc = ::GetDC(hwnd);
725    if (hdc==0)
726    {
727        reportError("Win32WindowingSystem::getSampleOpenGLContext() - Unable to get window device context", ::GetLastError());
728        ::DestroyWindow(hwnd);
729        return false;
730    }
731
732    int pixelFormatIndex = ::ChoosePixelFormat(hdc, &pixelFormat);
733    if (pixelFormatIndex==0)
734    {
735        reportError("Win32WindowingSystem::getSampleOpenGLContext() - Unable to choose pixel format", ::GetLastError());
736        ::ReleaseDC(hwnd, hdc);
737        ::DestroyWindow(hwnd);
738        return false;
739    }
740
741    if (!::SetPixelFormat(hdc, pixelFormatIndex, &pixelFormat))
742    {
743        reportError("Win32WindowingSystem::getSampleOpenGLContext() - Unable to set pixel format", ::GetLastError());
744        ::ReleaseDC(hwnd, hdc);
745        ::DestroyWindow(hwnd);
746        return false;
747    }
748
749    HGLRC hglrc = ::wglCreateContext(hdc);
750    if (hglrc==0)
751    {
752        reportError("Win32WindowingSystem::getSampleOpenGLContext() - Unable to create an OpenGL rendering context", ::GetLastError());
753        ::ReleaseDC(hwnd, hdc);
754        ::DestroyWindow(hwnd);
755        return false;
756    }
757
758    context.set(hwnd, hdc, hglrc);
759
760    if (!context.makeCurrent(windowHDC, true)) return false;
761
762    return true;
763}
764
765unsigned int Win32WindowingSystem::getNumScreens( const osg::GraphicsContext::ScreenIdentifier& si )
766{
767    return si.displayNum==0 ? ::GetSystemMetrics(SM_CMONITORS) : 0;
768}
769
770bool Win32WindowingSystem::getScreenInformation( const osg::GraphicsContext::ScreenIdentifier& si, DISPLAY_DEVICE& displayDevice, DEVMODE& deviceMode )
771{
772    if (si.displayNum>0)
773    {
774        osg::notify(osg::WARN) << "Win32WindowingSystem::getScreenInformation() - The screen identifier on the Win32 platform must always use display number 0. Value received was " << si.displayNum << std::endl;
775        return false;
776    }
777
778    DisplayDevices displayDevices;
779    enumerateDisplayDevices(displayDevices);
780
781    if (si.screenNum>=static_cast<int>(displayDevices.size()))
782    {
783        osg::notify(osg::WARN) << "Win32WindowingSystem::getScreenInformation() - Cannot get information for screen " << si.screenNum << " because it does not exist." << std::endl;
784        return false;
785    }
786
787    displayDevice = displayDevices[si.screenNum];
788
789    deviceMode.dmSize        = sizeof(deviceMode);
790    deviceMode.dmDriverExtra = 0;
791
792    if (!::EnumDisplaySettings(displayDevice.DeviceName, ENUM_CURRENT_SETTINGS, &deviceMode))
793    {
794        std::ostringstream str;
795        str << "Win32WindowingSystem::getScreenInformation() - Unable to query information for screen number " << si.screenNum;
796        reportError(str.str(), ::GetLastError());
797        return false;
798    }
799
800    return true;
801}
802
803void Win32WindowingSystem::getScreenSettings( const osg::GraphicsContext::ScreenIdentifier& si, osg::GraphicsContext::ScreenSettings & resolution )
804{
805    DISPLAY_DEVICE displayDevice;
806    DEVMODE        deviceMode;
807
808    if (!getScreenInformation(si, displayDevice, deviceMode))
809        deviceMode.dmFields = 0;        // Set the fields to 0 so that it says 'nothing'.
810
811    // Get resolution
812    if ((deviceMode.dmFields & (DM_PELSWIDTH | DM_PELSHEIGHT)) != 0) {
813        resolution.width  = deviceMode.dmPelsWidth;
814        resolution.height = deviceMode.dmPelsHeight;
815    } else {
816        resolution.width  = 0;
817        resolution.height = 0;
818    }
819
820    // Get refersh rate
821    if ((deviceMode.dmFields & DM_DISPLAYFREQUENCY) != 0) {
822        resolution.refreshRate = deviceMode.dmDisplayFrequency;
823        if (resolution.refreshRate == 0 || resolution.refreshRate == 1) {
824            // Windows specific: 0 and 1 represent the hhardware's default refresh rate.
825            // If someone knows how to get this refresh rate (in Hz)...
826            osg::notify(osg::NOTICE) << "Win32WindowingSystem::getScreenSettings() is not fully implemented (cannot retreive the hardware's default refresh rate)."<<std::endl;
827            resolution.refreshRate = 0;
828        }
829    } else
830        resolution.refreshRate = 0;
831
832    // Get bits per pixel for color buffer
833    if ((deviceMode.dmFields & DM_BITSPERPEL) != 0)
834        resolution.colorDepth = deviceMode.dmBitsPerPel;
835    else
836        resolution.colorDepth = 0;
837}
838
839void Win32WindowingSystem::getScreenColorDepth( const osg::GraphicsContext::ScreenIdentifier& si, unsigned int& dmBitsPerPel )
840{
841    DISPLAY_DEVICE displayDevice;
842    DEVMODE        deviceMode;
843
844    if (getScreenInformation(si, displayDevice, deviceMode))
845    {
846        dmBitsPerPel = deviceMode.dmBitsPerPel;
847    }
848    else
849    {
850        dmBitsPerPel  = 0;
851    }
852}
853
854bool Win32WindowingSystem::changeScreenSettings( const osg::GraphicsContext::ScreenIdentifier& si, DISPLAY_DEVICE& displayDevice, DEVMODE& deviceMode )
855{
856    //
857    // Start by testing if the change would be successful (without applying it)
858    //
859
860    unsigned int result = ::ChangeDisplaySettingsEx(displayDevice.DeviceName, &deviceMode, NULL, CDS_TEST, NULL);
861    if (result==DISP_CHANGE_SUCCESSFUL)
862    {
863        result = ::ChangeDisplaySettingsEx(displayDevice.DeviceName, &deviceMode, NULL, 0, NULL);
864        if (result==DISP_CHANGE_SUCCESSFUL) return true;
865    }
866
867    std::string msg = "Win32WindowingSystem::changeScreenSettings() - Unable to change the screen settings.";
868
869    switch( result )
870    {
871        case DISP_CHANGE_BADMODE     : msg += " The specified graphics mode is not supported."; break;
872        case DISP_CHANGE_FAILED      : msg += " The display driver failed the specified graphics mode."; break;
873        case DISP_CHANGE_RESTART     : msg += " The computer must be restarted for the graphics mode to work."; break;
874        default : break;
875    }
876
877    reportErrorForScreen(msg, si, result);
878    return false;
879}
880
881bool Win32WindowingSystem::setScreenSettings( const osg::GraphicsContext::ScreenIdentifier& si, const osg::GraphicsContext::ScreenSettings & resolution )
882{
883    DISPLAY_DEVICE displayDevice;
884    DEVMODE        deviceMode;
885
886    if (!getScreenInformation(si, displayDevice, deviceMode)) return false;
887
888    deviceMode.dmFields = 0;
889    // Set resolution
890    if (resolution.width>0 && resolution.height>0) {
891        deviceMode.dmFields    |= DM_PELSWIDTH | DM_PELSHEIGHT;
892        deviceMode.dmPelsWidth  = static_cast<DWORD>(resolution.width);
893        deviceMode.dmPelsHeight = static_cast<DWORD>(resolution.height);
894    }
895    // Set refersh rate
896    if (resolution.refreshRate>0) {
897        deviceMode.dmFields           |= DM_DISPLAYFREQUENCY;
898        deviceMode.dmDisplayFrequency  = static_cast<DWORD>(resolution.refreshRate);
899    }
900    // Set bits per pixel for color buffer
901    if (resolution.colorDepth>0) {
902        deviceMode.dmFields     |= DM_BITSPERPEL;
903        deviceMode.dmBitsPerPel  = static_cast<DWORD>(resolution.colorDepth);
904    }
905   
906    return changeScreenSettings(si, displayDevice, deviceMode);
907}
908
909void Win32WindowingSystem::enumerateScreenSettings(const osg::GraphicsContext::ScreenIdentifier& si, osg::GraphicsContext::ScreenSettingsList & resolutionList) {
910    resolutionList.clear();
911
912    if (si.displayNum>0)
913    {
914        osg::notify(osg::WARN) << "Win32WindowingSystem::enumerateScreenSettings() - The screen identifier on the Win32 platform must always use display number 0. Value received was " << si.displayNum << std::endl;
915        return;
916    }
917
918    DisplayDevices displayDevices;
919    enumerateDisplayDevices(displayDevices);
920
921    if (si.screenNum>=static_cast<int>(displayDevices.size()))
922    {
923        osg::notify(osg::WARN) << "Win32WindowingSystem::enumerateScreenSettings() - Cannot get information for screen " << si.screenNum << " because it does not exist." << std::endl;
924        return;
925    }
926
927    DISPLAY_DEVICE displayDevice = displayDevices[si.screenNum];
928
929    // Do the enumeration
930    DEVMODE deviceMode;
931    static const unsigned int MAX_RESOLUTIONS = 4046;        // Upper limit to avoid infinite (= very long) loop.
932    for (unsigned int i=0; i<MAX_RESOLUTIONS; ++i)
933    {
934        if (!::EnumDisplaySettings(displayDevice.DeviceName, i, &deviceMode))
935            break;
936        deviceMode.dmSize        = sizeof(deviceMode);
937        deviceMode.dmDriverExtra = 0;
938        resolutionList.push_back(osg::GraphicsContext::ScreenSettings(deviceMode.dmPelsWidth, deviceMode.dmPelsHeight, deviceMode.dmDisplayFrequency, deviceMode.dmBitsPerPel));
939    }
940}
941
942void Win32WindowingSystem::getScreenPosition( const osg::GraphicsContext::ScreenIdentifier& si, int& originX, int& originY, unsigned int& width, unsigned int& height )
943{
944    DISPLAY_DEVICE displayDevice;
945    DEVMODE        deviceMode;
946
947    if (getScreenInformation(si, displayDevice, deviceMode))
948    {
949        originX = deviceMode.dmPosition.x;
950        originY = deviceMode.dmPosition.y;
951        width   = deviceMode.dmPelsWidth;
952        height  = deviceMode.dmPelsHeight;
953    }
954    else
955    {
956        originX = 0;
957        originY = 0;
958        width   = 0;
959        height  = 0;
960    }
961}
962
963osg::GraphicsContext* Win32WindowingSystem::createGraphicsContext( osg::GraphicsContext::Traits* traits )
964{
965    if (traits->pbuffer)
966    {
967        osg::ref_ptr<osgViewer::PixelBufferWin32> pbuffer = new PixelBufferWin32(traits);
968        if (pbuffer->valid()) return pbuffer.release();
969        else return 0;
970    }
971    else
972    {
973        registerWindowClasses();
974
975        osg::ref_ptr<osgViewer::GraphicsWindowWin32> window = new GraphicsWindowWin32(traits);
976        if (window->valid()) return window.release();
977        else return 0;
978    }
979}
980
981void Win32WindowingSystem::registerWindow( HWND hwnd, osgViewer::GraphicsWindowWin32* window )
982{
983    if (hwnd) _activeWindows.insert(WindowHandleEntry(hwnd, window));
984}
985
986//
987// Unregister a window
988// This is called as part of a window being torn down
989//
990
991void Win32WindowingSystem::unregisterWindow( HWND hwnd )
992{
993    if (hwnd) _activeWindows.erase(hwnd);
994}
995
996//
997// Get the application window object associated with a native window
998//
999
1000osgViewer::GraphicsWindowWin32* Win32WindowingSystem::getGraphicsWindowFor( HWND hwnd )
1001{
1002    WindowHandles::const_iterator entry = _activeWindows.find(hwnd);
1003    return entry==_activeWindows.end() ? 0 : entry->second;
1004}
1005
1006//////////////////////////////////////////////////////////////////////////////
1007//                    GraphicsWindowWin32 implementation
1008//////////////////////////////////////////////////////////////////////////////
1009
1010GraphicsWindowWin32::GraphicsWindowWin32( osg::GraphicsContext::Traits* traits )
1011: _hwnd(0),
1012  _hdc(0),
1013  _hglrc(0),
1014  _currentCursor(0),
1015  _windowProcedure(0),
1016  _timeOfLastCheckEvents(-1.0),
1017  _screenOriginX(0),
1018  _screenOriginY(0),
1019  _screenWidth(0),
1020  _screenHeight(0),
1021  _windowOriginXToRealize(0),
1022  _windowOriginYToRealize(0),
1023  _windowWidthToRealize(0),
1024  _windowHeightToRealize(0),
1025  _initialized(false),
1026  _valid(false),
1027  _realized(false),
1028  _ownsWindow(true),
1029  _closeWindow(false),
1030  _destroyWindow(false),
1031  _destroying(false),
1032  _appMouseCursor(LeftArrowCursor),
1033  _applyWorkaroundForMultimonitorMultithreadNVidiaWin32Issues( false )
1034{
1035    _traits = traits;
1036    if (_traits->useCursor) setCursor(LeftArrowCursor);
1037
1038    init();
1039   
1040    if (valid())
1041    {
1042        setState( new osg::State );
1043        getState()->setGraphicsContext(this);
1044
1045        if (_traits.valid() && _traits->sharedContext)
1046        {
1047            getState()->setContextID( _traits->sharedContext->getState()->getContextID() );
1048            incrementContextIDUsageCount( getState()->getContextID() );   
1049        }
1050        else
1051        {
1052            getState()->setContextID( osg::GraphicsContext::createNewContextID() );
1053        }
1054    }
1055}
1056
1057GraphicsWindowWin32::~GraphicsWindowWin32()
1058{
1059    close();
1060    destroyWindow();
1061}
1062
1063void GraphicsWindowWin32::init()
1064{
1065    if (_initialized) return;
1066
1067    // getEventQueue()->setCurrentEventState(osgGA::GUIEventAdapter::getAccumulatedEventState().get());
1068
1069    WindowData *windowData = _traits.get() ? dynamic_cast<WindowData*>(_traits->inheritedWindowData.get()) : 0;
1070    HWND windowHandle = windowData ? windowData->_hwnd : 0;
1071
1072    _ownsWindow    = windowHandle==0;
1073    _closeWindow   = false;
1074    _destroyWindow = false;
1075    _destroying    = false;
1076
1077    _initialized = _ownsWindow ? createWindow() : setWindow(windowHandle);
1078    _valid       = _initialized;
1079
1080    // 2008/10/03
1081    // Few days ago NVidia released WHQL certified drivers ver 178.13.
1082    // These drivers (as well as former beta ver 177.92) were free from the bug described below.
1083    // So it looks like its high time to make the workaround inactive by default.
1084    // If you happen to still use earlier drivers and have problems consider changing to new ones or
1085    // activate OSG_MULTIMONITOR_MULTITHREAD_WIN32_NVIDIA_WORKAROUND macro def through CMake advanced vars.
1086#ifdef OSG_MULTIMONITOR_MULTITHREAD_WIN32_NVIDIA_WORKAROUND
1087
1088    // 2008/05/12
1089    // Workaround for Bugs in NVidia drivers for windows XP / multithreaded / dualview / multicore CPU
1090    // affects GeForce 6x00, 7x00, 8x00 boards (others were not tested) driver versions 174.xx - 175.xx
1091    // pre 174.xx had other issues so reverting is not an option (statitistics, fbo)
1092    // drivers release 175.16 is the latest currently available
1093    //
1094    // When using OpenGL in threaded app ( main thread sets up context / renderer thread draws using it )
1095    // first wglMakeCurrent seems to not work right and screw OpenGL context driver data:
1096    // 1: succesive drawing shows a number of artifacts in TriangleStrips and TriangleFans
1097    // 2: weird behaviour of FramBufferObjects (glGenFramebuffer generates already generated ids ...)
1098    // Looks like repeating wglMakeCurrent call fixes all these issues
1099    // wglMakeCurrent call can impact performance so I try to minimize number of
1100    // wglMakeCurrent calls by checking current HDC and GL context
1101    // and repeat wglMakeCurrent only when they change for current thread
1102
1103    _applyWorkaroundForMultimonitorMultithreadNVidiaWin32Issues = true;
1104#endif
1105
1106    const char* str = getenv("OSG_WIN32_NV_MULTIMON_MULTITHREAD_WORKAROUND");
1107    if (str)
1108    {
1109        _applyWorkaroundForMultimonitorMultithreadNVidiaWin32Issues = (strcmp(str, "on")==0 || strcmp(str, "ON")==0 || strcmp(str, "On")==0 );
1110    }
1111}
1112
1113bool GraphicsWindowWin32::createWindow()
1114{
1115    unsigned int extendedStyle;
1116    unsigned int windowStyle;
1117
1118    if (!determineWindowPositionAndStyle(_traits->screenNum,
1119                                         _traits->x,
1120                                         _traits->y,
1121                                         _traits->width,
1122                                         _traits->height,
1123                                         _traits->windowDecoration,
1124                                         _windowOriginXToRealize,
1125                                         _windowOriginYToRealize,
1126                                         _windowWidthToRealize,
1127                                         _windowHeightToRealize,
1128                                         windowStyle,
1129                                         extendedStyle))
1130    {
1131        reportError("GraphicsWindowWin32::createWindow() - Unable to determine the window position and style");
1132        return false;
1133    }
1134
1135    _hwnd = ::CreateWindowEx(extendedStyle,
1136                             _traits->useCursor ? Win32WindowingSystem::osgGraphicsWindowWithCursorClass.c_str() :
1137                                                  Win32WindowingSystem::osgGraphicsWindowWithoutCursorClass.c_str(),
1138                             _traits->windowName.c_str(),
1139                             windowStyle,
1140                             _windowOriginXToRealize,
1141                             _windowOriginYToRealize,
1142                             _windowWidthToRealize,
1143                             _windowHeightToRealize,
1144                             NULL,
1145                             NULL,
1146                             ::GetModuleHandle(NULL),
1147                             NULL);
1148    if (_hwnd==0)
1149    {
1150        reportErrorForScreen("GraphicsWindowWin32::createWindow() - Unable to create window", _traits->screenNum, ::GetLastError());
1151        return false;
1152    }
1153
1154    _hdc = ::GetDC(_hwnd);
1155    if (_hdc==0)
1156    {
1157        reportErrorForScreen("GraphicsWindowWin32::createWindow() - Unable to get window device context", _traits->screenNum, ::GetLastError());
1158        destroyWindow();
1159        _hwnd = 0;
1160        return false;
1161    }
1162
1163    //
1164    // Set the pixel format according to traits specified
1165    //
1166
1167    if (!setPixelFormat())
1168    {
1169        ::ReleaseDC(_hwnd, _hdc);
1170        _hdc  = 0;
1171        destroyWindow();
1172        return false;
1173    }
1174
1175    //
1176    // Create the OpenGL rendering context associated with this window
1177    //
1178
1179    _hglrc = ::wglCreateContext(_hdc);
1180    if (_hglrc==0)
1181    {
1182        reportErrorForScreen("GraphicsWindowWin32::createWindow() - Unable to create OpenGL rendering context", _traits->screenNum, ::GetLastError());
1183        ::ReleaseDC(_hwnd, _hdc);
1184        _hdc  = 0;
1185        destroyWindow();
1186        return false;
1187    }
1188
1189    Win32WindowingSystem::getInterface()->registerWindow(_hwnd, this);
1190    return true;
1191}
1192
1193bool GraphicsWindowWin32::setWindow( HWND handle )
1194{
1195    if (_initialized)
1196    {
1197        reportErrorForScreen("GraphicsWindowWin32::setWindow() - Window already created; it cannot be changed", _traits->screenNum, ::GetLastError());
1198        return false;
1199    }
1200
1201    if (handle==0)
1202    {
1203        reportErrorForScreen("GraphicsWindowWin32::setWindow() - Invalid window handle passed", _traits->screenNum, ::GetLastError());
1204        return false;
1205    }
1206
1207    _hwnd = handle;
1208    if (_hwnd==0)
1209    {
1210        reportErrorForScreen("GraphicsWindowWin32::setWindow() - Unable to retrieve native window handle", _traits->screenNum, ::GetLastError());
1211        return false;
1212    }
1213
1214    _hdc = ::GetDC(_hwnd);
1215    if (_hdc==0)
1216    {
1217        reportErrorForScreen("GraphicsWindowWin32::setWindow() - Unable to get window device context", _traits->screenNum, ::GetLastError());
1218        _hwnd = 0;
1219        return false;
1220    }
1221
1222    //
1223    // Check if we must set the pixel format of the inherited window
1224    //
1225
1226    if (!setPixelFormat())
1227    {
1228        reportErrorForScreen("GraphicsWindowWin32::setWindow() - Unable to set the inherited window pixel format", _traits->screenNum, ::GetLastError());
1229        ::ReleaseDC(_hwnd, _hdc);
1230        _hdc  = 0;
1231        _hwnd = 0;
1232        return false;
1233    }
1234
1235    _hglrc = ::wglCreateContext(_hdc);
1236    if (_hglrc==0)
1237    {
1238        reportErrorForScreen("GraphicsWindowWin32::setWindow() - Unable to create OpenGL rendering context", _traits->screenNum, ::GetLastError());
1239        ::ReleaseDC(_hwnd, _hdc);
1240        _hdc  = 0;
1241        _hwnd = 0;
1242        return false;
1243    }
1244
1245    if (!registerWindowProcedure())
1246    {
1247        ::wglDeleteContext(_hglrc);
1248        _hglrc = 0;
1249        ::ReleaseDC(_hwnd, _hdc);
1250        _hdc  = 0;
1251        _hwnd = 0;
1252        return false;
1253    }
1254
1255    Win32WindowingSystem::getInterface()->registerWindow(_hwnd, this);
1256
1257    _initialized = true;
1258    _valid       = true;
1259
1260    return true;
1261}
1262
1263void GraphicsWindowWin32::destroyWindow( bool deleteNativeWindow )
1264{
1265    if (_destroying) return;
1266    _destroying = true;
1267
1268    if (_hdc)
1269    {
1270        releaseContext();
1271
1272        if (_hglrc)
1273        {
1274            ::wglDeleteContext(_hglrc);
1275            _hglrc = 0;
1276        }
1277
1278        ::ReleaseDC(_hwnd, _hdc);
1279        _hdc = 0;
1280    }
1281
1282    (void)unregisterWindowProcedure();
1283
1284    if (_hwnd)
1285    {
1286        Win32WindowingSystem::getInterface()->unregisterWindow(_hwnd);
1287        if (_ownsWindow && deleteNativeWindow) ::DestroyWindow(_hwnd);
1288        _hwnd = 0;
1289    }
1290
1291    _initialized = false;
1292    _realized    = false;
1293    _valid       = false;
1294    _destroying  = false;
1295}
1296
1297bool GraphicsWindowWin32::registerWindowProcedure()
1298{
1299    ::SetLastError(0);
1300    _windowProcedure = (WNDPROC)::SetWindowLongPtr(_hwnd, GWLP_WNDPROC, LONG_PTR(WindowProc));
1301    unsigned int error = ::GetLastError();
1302
1303    if (_windowProcedure==0 && error)
1304    {
1305        reportErrorForScreen("GraphicsWindowWin32::registerWindowProcedure() - Unable to register window procedure", _traits->screenNum, error);
1306        return false;
1307    }
1308
1309    return true;
1310}
1311
1312bool GraphicsWindowWin32::unregisterWindowProcedure()
1313{
1314    if (_windowProcedure==0 || _hwnd==0) return true;
1315
1316    ::SetLastError(0);
1317    WNDPROC wndProc = (WNDPROC)::SetWindowLongPtr(_hwnd, GWLP_WNDPROC, LONG_PTR(_windowProcedure));
1318    unsigned int error = ::GetLastError();
1319
1320    if (wndProc==0 && error)
1321    {
1322        reportErrorForScreen("GraphicsWindowWin32::unregisterWindowProcedure() - Unable to unregister window procedure", _traits->screenNum, error);
1323        return false;
1324    }
1325
1326    _windowProcedure = 0;
1327
1328    return true;
1329}
1330
1331bool GraphicsWindowWin32::determineWindowPositionAndStyle( unsigned int  screenNum,
1332                                                           int           clientAreaX,
1333                                                           int           clientAreaY,
1334                                                           unsigned int  clientAreaWidth,
1335                                                           unsigned int  clientAreaHeight,
1336                                                           bool          decorated,
1337                                                           int&          x,
1338                                                           int&          y,
1339                                                           unsigned int& w,
1340                                                           unsigned int& h,
1341                                                           unsigned int& style,
1342                                                           unsigned int& extendedStyle )
1343{
1344    if (_traits==0) return false;
1345
1346    //
1347    // Query the screen position and size
1348    //
1349
1350    osg::GraphicsContext::ScreenIdentifier screenId(screenNum);
1351    Win32WindowingSystem* windowManager = Win32WindowingSystem::getInterface();
1352
1353    windowManager->getScreenPosition(screenId, _screenOriginX, _screenOriginY, _screenWidth, _screenHeight);
1354    if (_screenWidth==0 || _screenHeight==0) return false;
1355
1356    x = clientAreaX + _screenOriginX;
1357    y = clientAreaY + _screenOriginY;
1358    w = clientAreaWidth;
1359    h = clientAreaHeight;
1360
1361    style = WS_POPUP | WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
1362
1363    extendedStyle = 0;
1364
1365    if (decorated)
1366    {
1367        style |= WS_CAPTION     |
1368                 WS_SYSMENU     |
1369                 WS_MINIMIZEBOX |
1370                 WS_MAXIMIZEBOX;
1371
1372        if (_traits->supportsResize) style |= WS_SIZEBOX;
1373
1374        extendedStyle = WS_EX_APPWINDOW           |
1375                        WS_EX_OVERLAPPEDWINDOW |
1376                        WS_EX_ACCEPTFILES      |
1377                        WS_EX_LTRREADING;
1378
1379        RECT corners;
1380
1381        corners.left   = x;
1382        corners.top    = y;
1383        corners.right  = x + w - 1;
1384        corners.bottom = y + h - 1;
1385
1386        //
1387        // Determine the location of the window corners in order to have
1388        // a client area of the requested size
1389        //
1390
1391        if (!::AdjustWindowRectEx(&corners, style, FALSE, extendedStyle))
1392        {
1393            reportErrorForScreen("GraphicsWindowWin32::determineWindowPositionAndStyle() - Unable to adjust window rectangle", _traits->screenNum, ::GetLastError());
1394            return false;
1395        }
1396
1397        x = corners.left;
1398        y = corners.top;
1399        w = corners.right  - corners.left + 1;
1400        h = corners.bottom - corners.top  + 1;
1401    }
1402
1403    return true;
1404}
1405
1406static void PreparePixelFormatSpecifications( const osg::GraphicsContext::Traits& traits,
1407                                              WGLIntegerAttributes&               attributes,
1408                                              bool                                allowSwapExchangeARB )
1409{
1410    attributes.begin();
1411
1412    attributes.enable(WGL_DRAW_TO_WINDOW_ARB);
1413    attributes.enable(WGL_SUPPORT_OPENGL_ARB);
1414
1415    attributes.set(WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB);
1416    attributes.set(WGL_PIXEL_TYPE_ARB,   WGL_TYPE_RGBA_ARB);
1417
1418    attributes.set(WGL_COLOR_BITS_ARB,   traits.red + traits.green + traits.blue);
1419    attributes.set(WGL_RED_BITS_ARB,     traits.red);
1420    attributes.set(WGL_GREEN_BITS_ARB,   traits.green);
1421    attributes.set(WGL_BLUE_BITS_ARB,    traits.blue);
1422    attributes.set(WGL_DEPTH_BITS_ARB,   traits.depth);
1423
1424    if (traits.doubleBuffer)
1425    {
1426        attributes.enable(WGL_DOUBLE_BUFFER_ARB);
1427        if (allowSwapExchangeARB) attributes.set(WGL_SWAP_METHOD_ARB, WGL_SWAP_EXCHANGE_ARB);
1428    }
1429
1430    if (traits.alpha)         attributes.set(WGL_ALPHA_BITS_ARB,     traits.alpha);
1431    if (traits.stencil)       attributes.set(WGL_STENCIL_BITS_ARB,   traits.stencil);
1432    if (traits.sampleBuffers) attributes.set(WGL_SAMPLE_BUFFERS_ARB, traits.sampleBuffers);
1433    if (traits.samples)       attributes.set(WGL_SAMPLES_ARB,        traits.samples);
1434
1435    if (traits.quadBufferStereo) attributes.enable(WGL_STEREO_ARB);
1436
1437    attributes.end();
1438}
1439
1440static int ChooseMatchingPixelFormat( HDC hdc, int screenNum, const WGLIntegerAttributes& formatSpecifications ,osg::GraphicsContext::Traits* _traits)
1441{
1442    //
1443    // Access the entry point for the wglChoosePixelFormatARB function
1444    //
1445
1446    WGLChoosePixelFormatARB wglChoosePixelFormatARB = (WGLChoosePixelFormatARB)wglGetProcAddress("wglChoosePixelFormatARB");
1447    if (wglChoosePixelFormatARB==0)
1448    {
1449        // = openGLContext.getTraits()
1450        reportErrorForScreen("ChooseMatchingPixelFormat() - wglChoosePixelFormatARB extension not found, trying GDI", screenNum, ::GetLastError());
1451        PIXELFORMATDESCRIPTOR pixelFormat = {
1452            sizeof(PIXELFORMATDESCRIPTOR),  //  size of this pfd
1453            1,                     // version number
1454            PFD_DRAW_TO_WINDOW |   // support window
1455            PFD_SUPPORT_OPENGL |   // support OpenGL
1456            (_traits->doubleBuffer ? PFD_DOUBLEBUFFER : NULL),      // double buffered ?
1457            PFD_TYPE_RGBA,         // RGBA type
1458            _traits->red + _traits->green + _traits->blue,                // color depth
1459            _traits->red ,0, _traits->green ,0, _traits->blue, 0,          // shift bits ignored
1460            _traits->alpha,          // alpha buffer ?
1461            0,                     // shift bit ignored
1462            0,                     // no accumulation buffer
1463            0, 0, 0, 0,            // accum bits ignored
1464            _traits->depth,          // 32 or 16 bit z-buffer ?
1465            _traits->stencil,        // stencil buffer ?
1466            0,                     // no auxiliary buffer
1467            PFD_MAIN_PLANE,        // main layer
1468            0,                     // reserved
1469            0, 0, 0                // layer masks ignored
1470        };
1471        int pixelFormatIndex = ::ChoosePixelFormat(hdc, &pixelFormat);
1472        if (pixelFormatIndex == 0)
1473        {
1474            reportErrorForScreen("ChooseMatchingPixelFormat() - GDI ChoosePixelFormat Failed.", screenNum, ::GetLastError());
1475            return -1;
1476        }
1477
1478        ::DescribePixelFormat(hdc, pixelFormatIndex ,sizeof(PIXELFORMATDESCRIPTOR),&pixelFormat);
1479        if (((pixelFormat.dwFlags & PFD_GENERIC_FORMAT) != 0)  && ((pixelFormat.dwFlags & PFD_GENERIC_ACCELERATED) == 0))
1480        {
1481            osg::notify(osg::WARN) << "Rendering in software: pixelFormatIndex " << pixelFormatIndex << std::endl;
1482        }
1483        return pixelFormatIndex;
1484    }
1485
1486    int pixelFormatIndex = 0;
1487    unsigned int numMatchingPixelFormats = 0;
1488
1489    if (!wglChoosePixelFormatARB(hdc,
1490                                 formatSpecifications.get(),
1491                                 NULL,
1492                                 1,
1493                                 &pixelFormatIndex,
1494                                 &numMatchingPixelFormats))
1495    {
1496        reportErrorForScreen("ChooseMatchingPixelFormat() - Unable to choose the requested pixel format", screenNum, ::GetLastError());
1497        return -1;
1498    }
1499
1500    return numMatchingPixelFormats==0 ? -1 : pixelFormatIndex;
1501}
1502
1503bool GraphicsWindowWin32::setPixelFormat()
1504{
1505    Win32WindowingSystem::OpenGLContext openGLContext;
1506    if (!Win32WindowingSystem::getInterface()->getSampleOpenGLContext(openGLContext, _hdc, _screenOriginX, _screenOriginY)) return false;
1507
1508    //
1509    // Build the specifications of the requested pixel format
1510    //
1511
1512    WGLIntegerAttributes formatSpecs;
1513    ::PreparePixelFormatSpecifications(*_traits, formatSpecs, true);
1514
1515    //
1516    // Choose the closest matching pixel format from the specified traits
1517    //
1518
1519    int pixelFormatIndex = ::ChooseMatchingPixelFormat(openGLContext.deviceContext(), _traits->screenNum, formatSpecs,_traits.get());
1520
1521    if (pixelFormatIndex<0)
1522    {
1523            unsigned int bpp;
1524            Win32WindowingSystem::getInterface()->getScreenColorDepth(*_traits.get(), bpp);
1525            if (bpp < 32) {
1526                osg::notify(osg::INFO)    << "GraphicsWindowWin32::setPixelFormat() - Display setting is not 32 bit colors, "
1527                                        << bpp
1528                                        << " bits per pixel on screen #"
1529                                        << _traits->screenNum
1530                                        << std::endl;
1531
1532                _traits->red = bpp / 4; //integer devide, determine minimum number of bits we will accept
1533                _traits->green = bpp / 4;
1534                _traits->blue = bpp / 4;
1535                ::PreparePixelFormatSpecifications(*_traits, formatSpecs, true);// try again with WGL_SWAP_METHOD_ARB
1536                pixelFormatIndex = ::ChooseMatchingPixelFormat(openGLContext.deviceContext(), _traits->screenNum, formatSpecs,_traits.get());
1537            }
1538    }
1539    if (pixelFormatIndex<0)
1540    {
1541        ::PreparePixelFormatSpecifications(*_traits, formatSpecs, false);
1542        pixelFormatIndex = ::ChooseMatchingPixelFormat(openGLContext.deviceContext(), _traits->screenNum, formatSpecs,_traits.get());
1543        if (pixelFormatIndex<0)
1544        {
1545            reportErrorForScreen("GraphicsWindowWin32::setPixelFormat() - No matching pixel format found based on traits specified", _traits->screenNum, 0);
1546            return false;
1547        }
1548
1549        osg::notify(osg::INFO) << "GraphicsWindowWin32::setPixelFormat() - Found a matching pixel format but without the WGL_SWAP_METHOD_ARB specification for screen #"
1550                               << _traits->screenNum
1551                               << std::endl;
1552    }
1553
1554    //
1555    // Set the pixel format found
1556    //
1557
1558    PIXELFORMATDESCRIPTOR pfd;
1559    ::memset(&pfd, 0, sizeof(pfd));
1560    pfd.nSize    = sizeof(PIXELFORMATDESCRIPTOR);
1561    pfd.nVersion = 1;
1562
1563    if (!::SetPixelFormat(_hdc, pixelFormatIndex, &pfd))
1564    {
1565        reportErrorForScreen("GraphicsWindowWin32::setPixelFormat() - Unable to set pixel format", _traits->screenNum, ::GetLastError());
1566        return false;
1567    }
1568
1569    return true;
1570}
1571
1572bool GraphicsWindowWin32::setWindowDecorationImplementation( bool decorated )
1573{
1574    unsigned int windowStyle;
1575    unsigned int extendedStyle;
1576
1577    //
1578    // Determine position and size of window with/without decorations to retain the size specified in traits
1579    //
1580
1581    int x, y;
1582    unsigned int w, h;
1583
1584    if (!determineWindowPositionAndStyle(_traits->screenNum,
1585                                 _traits->x,
1586                     _traits->y,
1587                     _traits->width,
1588                     _traits->height,
1589                     decorated,
1590                     x,
1591                     y,
1592                     w,
1593                     h,
1594                     windowStyle,
1595                     extendedStyle))
1596    {
1597        reportErrorForScreen("GraphicsWindowWin32::setWindowDecoration() - Unable to determine the window position and style", _traits->screenNum, 0);
1598        return false;
1599    }
1600
1601    //
1602    // Change the window style
1603    //
1604
1605    ::SetLastError(0);
1606    unsigned int result = ::SetWindowLong(_hwnd, GWL_STYLE, windowStyle);
1607    unsigned int error  = ::GetLastError();
1608    if (result==0 && error)
1609    {
1610        reportErrorForScreen("GraphicsWindowWin32::setWindowDecoration() - Unable to set window style", _traits->screenNum, error);
1611        return false;
1612    }
1613
1614    //
1615    // Change the window extended style
1616    //
1617
1618    ::SetLastError(0);
1619    result = ::SetWindowLong(_hwnd, GWL_EXSTYLE, extendedStyle);
1620    error  = ::GetLastError();
1621    if (result==0 && error)
1622    {
1623        reportErrorForScreen("GraphicsWindowWin32::setWindowDecoration() - Unable to set window extented style", _traits->screenNum, error);
1624        return false;
1625    }
1626
1627    //
1628    // Change the window position and size and realize the style changes
1629    //
1630
1631    if (!::SetWindowPos(_hwnd, HWND_TOP, x, y, w, h, SWP_FRAMECHANGED | SWP_NOZORDER | SWP_SHOWWINDOW))
1632    {
1633        reportErrorForScreen("GraphicsWindowWin32::setWindowDecoration() - Unable to set new window position and size", _traits->screenNum, ::GetLastError());
1634        return false;
1635    }
1636
1637    //
1638    // Force a repaint of the desktop
1639    //
1640
1641    ::InvalidateRect(NULL, NULL, TRUE);
1642   
1643    return true;
1644}
1645
1646bool GraphicsWindowWin32::realizeImplementation()
1647{
1648    if (_realized) return true;
1649
1650    if (!_initialized)
1651    {
1652        init();
1653        if (!_initialized) return false;
1654    }
1655    {
1656       
1657        if (_traits.valid() && _traits->sharedContext)
1658        {
1659            GraphicsWindowWin32* sharedContextWin32 = dynamic_cast<GraphicsWindowWin32*>(_traits->sharedContext);
1660            if (sharedContextWin32)
1661            {
1662                struct RestoreContext
1663                {
1664                    RestoreContext()
1665                    {
1666                        _hdc = wglGetCurrentDC();
1667                        _hglrc = wglGetCurrentContext();
1668                    }
1669                    ~RestoreContext()
1670                    {
1671                        if (_hdc)
1672                        {
1673                            wglMakeCurrent(_hdc,_hglrc);
1674                        }
1675                    }
1676                protected:
1677                    HDC        _hdc;
1678                    HGLRC    _hglrc;
1679                } restoreContext;
1680               
1681                _realized = true;
1682                bool result = makeCurrent();
1683                _realized = false;
1684
1685                if (!result)
1686                {
1687                    return false;       
1688                }
1689                if (!wglShareLists(sharedContextWin32->getWGLContext(), getWGLContext()))
1690                {
1691                    reportErrorForScreen("GraphicsWindowWin32::realizeImplementation() - Unable to share OpenGL context", _traits->screenNum, ::GetLastError());
1692                    return false;
1693                }
1694            }
1695        }
1696    }
1697
1698    if (_ownsWindow)
1699    {
1700        //
1701        // Bring the window on top of other ones (including the taskbar if it covers it completely)
1702        //
1703        // NOTE: To cover the taskbar with a window that does not completely cover it, the HWND_TOPMOST
1704        // Z-order must be used in the code below instead of HWND_TOP.
1705        // @todo: This should be controlled through a flag in the traits (topMostWindow)
1706        //
1707
1708        if (!::SetWindowPos(_hwnd,
1709                            HWND_TOP,
1710                            _windowOriginXToRealize,
1711                            _windowOriginYToRealize,
1712                            _windowWidthToRealize,
1713                            _windowHeightToRealize,
1714                            SWP_SHOWWINDOW))
1715        {
1716            reportErrorForScreen("GraphicsWindowWin32::realizeImplementation() - Unable to show window", _traits->screenNum, ::GetLastError());
1717            return false;
1718        }
1719 
1720        if (!::UpdateWindow(_hwnd))
1721        {
1722            reportErrorForScreen("GraphicsWindowWin32::realizeImplementation() - Unable to update window", _traits->screenNum, ::GetLastError());
1723            return false;
1724        }
1725    }
1726
1727    _realized = true;
1728
1729    return true;
1730}
1731
1732bool GraphicsWindowWin32::makeCurrentImplementation()
1733{
1734    if (!_realized)
1735    {
1736        reportErrorForScreen("GraphicsWindowWin32::makeCurrentImplementation() - Window not realized; cannot do makeCurrent.", _traits->screenNum, 0);
1737        return false;
1738    }
1739
1740    if( _applyWorkaroundForMultimonitorMultithreadNVidiaWin32Issues )
1741    {
1742        if( ::wglGetCurrentDC() != _hdc ||
1743            ::wglGetCurrentContext() != _hglrc )
1744        {
1745            if (!::wglMakeCurrent(_hdc, _hglrc))
1746            {
1747                reportErrorForScreen("GraphicsWindowWin32::makeCurrentImplementation() - Unable to set current OpenGL rendering context", _traits->screenNum, ::GetLastError());
1748                return false;
1749            }
1750        }
1751    }
1752
1753    if (!::wglMakeCurrent(_hdc, _hglrc))
1754    {
1755        reportErrorForScreen("GraphicsWindowWin32::makeCurrentImplementation() - Unable to set current OpenGL rendering context", _traits->screenNum, ::GetLastError());
1756        return false;
1757    }
1758
1759    return true;
1760}
1761
1762bool GraphicsWindowWin32::releaseContextImplementation()
1763{
1764    if (!::wglMakeCurrent(_hdc, NULL))
1765    {
1766        reportErrorForScreen("GraphicsWindowWin32::releaseContextImplementation() - Unable to release current OpenGL rendering context", _traits->screenNum, ::GetLastError());
1767        return false;
1768    }
1769
1770    return true;
1771}
1772
1773void GraphicsWindowWin32::closeImplementation()
1774{
1775    destroyWindow();
1776
1777    _initialized = false;
1778    _valid       = false;
1779    _realized    = false;
1780}
1781
1782void GraphicsWindowWin32::swapBuffersImplementation()
1783{
1784    if (!_realized) return;
1785    if (!::SwapBuffers(_hdc) && ::GetLastError() != 0)
1786    {
1787        reportErrorForScreen("GraphicsWindowWin32::swapBuffersImplementation() - Unable to swap display buffers", _traits->screenNum, ::GetLastError());
1788    }
1789}
1790
1791void GraphicsWindowWin32::checkEvents()
1792{
1793    if (!_realized) return;
1794
1795    MSG msg;
1796    while (::PeekMessage(&msg, _hwnd, 0, 0, PM_REMOVE))
1797    {
1798        ::TranslateMessage(&msg);
1799        ::DispatchMessage(&msg);
1800    }
1801
1802    if (_closeWindow)
1803    {
1804        _closeWindow = false;
1805        close();
1806    }
1807
1808    if (_destroyWindow)
1809    {
1810        _destroyWindow = false;
1811        destroyWindow(false);
1812    }
1813}
1814
1815void GraphicsWindowWin32::grabFocus()
1816{
1817    if (!::SetForegroundWindow(_hwnd))
1818    {
1819        osg::notify(osg::WARN) << "Warning: GraphicsWindowWin32::grabFocus() - Failed grabbing the focus" << std::endl;
1820    }
1821}
1822
1823void GraphicsWindowWin32::grabFocusIfPointerInWindow()
1824{
1825    POINT mousePos;
1826    if (!::GetCursorPos(&mousePos))
1827    {
1828        reportErrorForScreen("GraphicsWindowWin32::grabFocusIfPointerInWindow() - Unable to get cursor position", _traits->screenNum, ::GetLastError());
1829        return;
1830    }
1831
1832    RECT windowRect;
1833    if (!::GetWindowRect(_hwnd, &windowRect))
1834    {
1835        reportErrorForScreen("GraphicsWindowWin32::grabFocusIfPointerInWindow() - Unable to get window position", _traits->screenNum, ::GetLastError());
1836        return;
1837    }
1838
1839    if (mousePos.x>=windowRect.left && mousePos.x<=windowRect.right &&
1840        mousePos.y>=windowRect.top  && mousePos.y<=windowRect.bottom)
1841    {
1842        grabFocus();
1843    }
1844}
1845
1846void GraphicsWindowWin32::requestWarpPointer( float x, float y )
1847{
1848    if (!_realized)
1849    {
1850        reportErrorForScreen("GraphicsWindowWin32::requestWarpPointer() - Window not realized; cannot warp pointer", _traits->screenNum, 0);
1851        return;
1852    }
1853
1854#if 0
1855    RECT windowRect;
1856    if (!::GetWindowRect(_hwnd, &windowRect))
1857    {
1858        reportErrorForScreen("GraphicsWindowWin32::requestWarpPointer() - Unable to get window rectangle", _traits->screenNum, ::GetLastError());
1859        return;
1860    }
1861
1862    if (!::SetCursorPos(windowRect.left + x, windowRect.top + y))
1863    {
1864        reportErrorForScreen("GraphicsWindowWin32::requestWarpPointer() - Unable to set cursor position", _traits->screenNum, ::GetLastError());
1865        return;
1866    }
1867#else
1868    // MIKEC: NEW CODE
1869    POINT pt;
1870    pt.x = (LONG)x;
1871    pt.y = (LONG)y;
1872
1873    // convert point in client area coordinates to screen coordinates
1874    if (!::ClientToScreen(_hwnd, &pt))
1875    {
1876        reportErrorForScreen("GraphicsWindowWin32::requestWarpPointer() - Unable to convert cursor position to screen coordinates", _traits->screenNum, ::GetLastError());
1877    }
1878    if (!::SetCursorPos(pt.x, pt.y))
1879    {
1880        reportErrorForScreen("GraphicsWindowWin32::requestWarpPointer() - Unable to set cursor position", _traits->screenNum, ::GetLastError());
1881        return;
1882    }
1883#endif
1884   
1885    getEventQueue()->mouseWarped(x,y);
1886}
1887
1888bool GraphicsWindowWin32::setWindowRectangleImplementation(int x, int y, int width, int height)
1889{
1890    unsigned int windowStyle;
1891    unsigned int extendedStyle;
1892
1893    //
1894    // Determine position and size of window with/without decorations to retain the size specified in traits
1895    //
1896
1897    int wx, wy;
1898    unsigned int ww, wh;
1899
1900    if (!determineWindowPositionAndStyle(_traits->screenNum,
1901                                         x,
1902                                         y,
1903                                         width,
1904                                         height,
1905                                         _traits->windowDecoration,
1906                                         wx,
1907                                         wy,
1908                                         ww,
1909                                         wh,
1910                                         windowStyle,
1911                                         extendedStyle))
1912    {
1913        reportErrorForScreen("GraphicsWindowWin32::setWindowRectangleImplementation() - Unable to determine the window position and style", _traits->screenNum, 0);
1914        return false;
1915    }
1916
1917    if (!::SetWindowPos(_hwnd, HWND_TOP, wx, wy, ww, wh, SWP_SHOWWINDOW | SWP_FRAMECHANGED))
1918    {
1919        reportErrorForScreen("GraphicsWindowWin32::setWindowRectangleImplementation() - Unable to set new window position and size", _traits->screenNum, ::GetLastError());
1920        return false;
1921    }
1922    return true;
1923}
1924
1925void GraphicsWindowWin32::setWindowName( const std::string & name )
1926{
1927    _traits->windowName = name;
1928    SetWindowText(_hwnd, name.c_str());
1929}
1930
1931void GraphicsWindowWin32::useCursor( bool cursorOn )
1932{
1933    _traits->useCursor = cursorOn;
1934}
1935
1936void GraphicsWindowWin32::setCursor( MouseCursor mouseCursor )
1937{
1938    if (_mouseCursor != mouseCursor)
1939    {
1940        if (mouseCursor != LeftRightCursor &&
1941            mouseCursor != UpDownCursor &&
1942            mouseCursor != TopLeftCorner &&
1943            mouseCursor != TopRightCorner &&
1944            mouseCursor != BottomLeftCorner &&
1945            mouseCursor != BottomRightCorner)
1946        {
1947            _appMouseCursor = mouseCursor;
1948        }
1949
1950        _mouseCursor = mouseCursor;
1951        HCURSOR newCursor = getOrCreateCursor( mouseCursor);
1952        if (newCursor == _currentCursor) return;
1953
1954        _currentCursor = newCursor;
1955        _traits->useCursor = (_currentCursor != NULL);
1956
1957        if (_mouseCursor != InheritCursor)
1958            ::SetCursor(_currentCursor);
1959    }
1960}
1961
1962HCURSOR GraphicsWindowWin32::getOrCreateCursor(MouseCursor mouseCursor)
1963{
1964    std::map<MouseCursor,HCURSOR>::iterator i = _mouseCursorMap.find(mouseCursor);
1965    if (i != _mouseCursorMap.end()) return i->second;
1966
1967    switch (mouseCursor) {
1968    case NoCursor:
1969        _mouseCursorMap[mouseCursor] = NULL;
1970    break;
1971    case RightArrowCursor:
1972        _mouseCursorMap[mouseCursor] = LoadCursor( NULL, IDC_ARROW);
1973        break;
1974    case LeftArrowCursor:
1975        _mouseCursorMap[mouseCursor] = LoadCursor( NULL, IDC_ARROW);
1976        break;
1977    case InfoCursor:
1978        _mouseCursorMap[mouseCursor] = LoadCursor( NULL, IDC_SIZEALL);
1979        break;
1980    case DestroyCursor:
1981        _mouseCursorMap[mouseCursor] = LoadCursor( NULL, IDC_NO );
1982        break;
1983    case HelpCursor:
1984        _mouseCursorMap[mouseCursor] = LoadCursor( NULL, IDC_HELP );
1985        break;
1986    case CycleCursor:
1987        _mouseCursorMap[mouseCursor] = LoadCursor( NULL, IDC_NO );
1988        break;
1989    case SprayCursor:
1990        _mouseCursorMap[mouseCursor] = LoadCursor( NULL, IDC_SIZEALL );
1991        break;
1992    case WaitCursor:
1993        _mouseCursorMap[mouseCursor] = LoadCursor( NULL, IDC_WAIT);
1994        break;
1995    case TextCursor:
1996        _mouseCursorMap[mouseCursor] = LoadCursor( NULL, IDC_IBEAM );
1997        break;
1998    case CrosshairCursor:
1999        _mouseCursorMap[mouseCursor] = LoadCursor( NULL, IDC_CROSS );
2000        break;
2001    case UpDownCursor:
2002        _mouseCursorMap[mouseCursor] = LoadCursor( NULL, IDC_SIZENS );
2003        break;
2004    case LeftRightCursor:
2005        _mouseCursorMap[mouseCursor] = LoadCursor( NULL, IDC_SIZEWE );
2006        break;
2007    case TopSideCursor:
2008        _mouseCursorMap[mouseCursor] = LoadCursor( NULL, IDC_UPARROW );
2009        break;
2010    case BottomSideCursor:
2011        _mouseCursorMap[mouseCursor] = LoadCursor( NULL, IDC_UPARROW );
2012        break;
2013    case LeftSideCursor:
2014        _mouseCursorMap[mouseCursor] = LoadCursor( NULL, IDC_SIZEWE);
2015        break;
2016    case RightSideCursor:
2017        _mouseCursorMap[mouseCursor] = LoadCursor( NULL, IDC_SIZEWE );
2018        break;
2019    case TopLeftCorner:
2020        _mouseCursorMap[mouseCursor] = LoadCursor( NULL, IDC_SIZENWSE );
2021        break;
2022    case TopRightCorner:
2023        _mouseCursorMap[mouseCursor] = LoadCursor( NULL, IDC_SIZENESW );
2024        break;
2025    case BottomRightCorner:
2026        _mouseCursorMap[mouseCursor] = LoadCursor( NULL, IDC_SIZENWSE );
2027        break;
2028    case BottomLeftCorner:
2029        _mouseCursorMap[mouseCursor] = LoadCursor( NULL, IDC_SIZENESW );
2030        break;
2031    default:
2032        break;
2033    }
2034   
2035    return _mouseCursorMap[mouseCursor];
2036}
2037
2038void GraphicsWindowWin32::adaptKey( WPARAM wParam, LPARAM lParam, int& keySymbol, unsigned int& modifierMask )
2039{
2040    modifierMask = 0;
2041
2042    bool rightSide = (lParam & 0x01000000)!=0;
2043    int virtualKey = ::MapVirtualKeyEx((lParam>>16) & 0xff, 3, ::GetKeyboardLayout(0));
2044
2045    BYTE keyState[256];
2046
2047    if (virtualKey==0 || !::GetKeyboardState(keyState))
2048    {
2049        keySymbol = 0;
2050        return;
2051    }
2052
2053    switch (virtualKey)
2054    {
2055        //////////////////
2056        case VK_LSHIFT   :
2057        //////////////////
2058
2059        modifierMask |= osgGA::GUIEventAdapter::MODKEY_LEFT_SHIFT;
2060            break;
2061
2062        //////////////////
2063        case VK_RSHIFT   :
2064        //////////////////
2065
2066        modifierMask |= osgGA::GUIEventAdapter::MODKEY_RIGHT_SHIFT;
2067            break;
2068
2069        //////////////////
2070        case VK_CONTROL  :
2071        case VK_LCONTROL :
2072        //////////////////
2073
2074            virtualKey    = rightSide ? VK_RCONTROL : VK_LCONTROL;
2075            modifierMask |= rightSide ? osgGA::GUIEventAdapter::MODKEY_RIGHT_CTRL : osgGA::GUIEventAdapter::MODKEY_LEFT_CTRL;
2076            break;
2077
2078        //////////////////
2079        case VK_MENU     :
2080        case VK_LMENU    :
2081        //////////////////
2082
2083            virtualKey    = rightSide ? VK_RMENU : VK_LMENU;
2084            modifierMask |= rightSide ? osgGA::GUIEventAdapter::MODKEY_RIGHT_ALT : osgGA::GUIEventAdapter::MODKEY_LEFT_ALT;
2085            break;
2086
2087        //////////////////
2088        default          :
2089        //////////////////
2090
2091            virtualKey = wParam;
2092            break;
2093    }
2094
2095    if (keyState[VK_CAPITAL] & 0x01) modifierMask |= osgGA::GUIEventAdapter::MODKEY_CAPS_LOCK;
2096    if (keyState[VK_NUMLOCK] & 0x01) modifierMask |= osgGA::GUIEventAdapter::MODKEY_NUM_LOCK;
2097
2098    keySymbol = remapWin32Key(virtualKey);
2099
2100    if (keySymbol==osgGA::GUIEventAdapter::KEY_Return && rightSide)
2101    {
2102        keySymbol = osgGA::GUIEventAdapter::KEY_KP_Enter;
2103    }
2104    else if ((keySymbol & 0xff00)==0)
2105    {
2106        char asciiKey[2];
2107        int numChars = ::ToAscii(wParam, (lParam>>16)&0xff, keyState, reinterpret_cast<WORD*>(asciiKey), 0);
2108        if (numChars>0) keySymbol = asciiKey[0];
2109    }
2110}
2111
2112void GraphicsWindowWin32::transformMouseXY( float& x, float& y )
2113{
2114    if (getEventQueue()->getUseFixedMouseInputRange())
2115    {
2116        osgGA::GUIEventAdapter* eventState = getEventQueue()->getCurrentEventState();
2117
2118        x = eventState->getXmin() + (eventState->getXmax()-eventState->getXmin())*x/float(_traits->width);
2119        y = eventState->getYmin() + (eventState->getYmax()-eventState->getYmin())*y/float(_traits->height);
2120    }
2121}
2122
2123LRESULT GraphicsWindowWin32::handleNativeWindowingEvent( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
2124{
2125    //!@todo adapt windows event time to osgGA event queue time for better resolution
2126    double eventTime  = getEventQueue()->getTime();
2127    double resizeTime = eventTime;
2128    _timeOfLastCheckEvents = eventTime;
2129
2130    switch(uMsg)
2131    {
2132        /////////////////
2133        case WM_PAINT   :
2134        /////////////////
2135
2136            if (_ownsWindow)
2137            {
2138                PAINTSTRUCT paint;
2139                ::BeginPaint(hwnd, &paint);
2140                ::EndPaint(hwnd, &paint);
2141            }
2142            break;
2143
2144        ///////////////////
2145        case WM_MOUSEMOVE :
2146        ///////////////////
2147
2148            {
2149                float mx = GET_X_LPARAM(lParam);
2150                float my = GET_Y_LPARAM(lParam);
2151                transformMouseXY(mx, my);
2152                getEventQueue()->mouseMotion(mx, my, eventTime);
2153            }
2154            break;
2155
2156        /////////////////////
2157        case WM_LBUTTONDOWN :
2158        case WM_MBUTTONDOWN :
2159        case WM_RBUTTONDOWN :
2160        /////////////////////
2161
2162            {
2163                ::SetCapture(hwnd);
2164
2165                int button;
2166
2167                if (uMsg==WM_LBUTTONDOWN)      button = 1;
2168                else if (uMsg==WM_MBUTTONDOWN) button = 2;
2169                else button = 3;
2170
2171                float mx = GET_X_LPARAM(lParam);
2172                float my = GET_Y_LPARAM(lParam);
2173                transformMouseXY(mx, my);
2174                getEventQueue()->mouseButtonPress(mx, my, button, eventTime);
2175            }
2176            break;
2177
2178        /////////////////////
2179        case WM_LBUTTONUP   :
2180        case WM_MBUTTONUP   :
2181        case WM_RBUTTONUP   :
2182        /////////////////////
2183           
2184            {
2185                ::ReleaseCapture();
2186
2187                int button;
2188
2189                if (uMsg==WM_LBUTTONUP)      button = 1;
2190                else if (uMsg==WM_MBUTTONUP) button = 2;
2191                else button = 3;
2192
2193                float mx = GET_X_LPARAM(lParam);
2194                float my = GET_Y_LPARAM(lParam);
2195                transformMouseXY(mx, my);
2196                getEventQueue()->mouseButtonRelease(mx, my, button, eventTime);
2197            }
2198            break;
2199
2200        ///////////////////////
2201        case WM_LBUTTONDBLCLK :
2202        case WM_MBUTTONDBLCLK :
2203        case WM_RBUTTONDBLCLK :
2204        ///////////////////////
2205
2206            {
2207                ::SetCapture(hwnd);
2208
2209                int button;
2210
2211                if (uMsg==WM_LBUTTONDBLCLK)            button = 1;
2212                else if (uMsg==WM_MBUTTONDBLCLK)    button = 2;
2213                else button = 3;
2214
2215                float mx = GET_X_LPARAM(lParam);
2216                float my = GET_Y_LPARAM(lParam);
2217                transformMouseXY(mx, my);
2218                getEventQueue()->mouseDoubleButtonPress(mx, my, button, eventTime);
2219            }
2220            break;
2221
2222        ////////////////////
2223        case WM_MOUSEWHEEL :
2224        ////////////////////
2225
2226            getEventQueue()->mouseScroll(GET_WHEEL_DELTA_WPARAM(wParam)<0 ? osgGA::GUIEventAdapter::SCROLL_DOWN :
2227                                                                            osgGA::GUIEventAdapter::SCROLL_UP,
2228                                         eventTime);
2229            break;
2230
2231        /////////////////
2232        case WM_MOVE    :
2233        case WM_SIZE    :
2234        /////////////////
2235
2236            {
2237                POINT origin;
2238                origin.x = 0;
2239                origin.y = 0;
2240
2241                ::ClientToScreen(hwnd, &origin);
2242
2243                int windowX = origin.x - _screenOriginX;
2244                int windowY = origin.y - _screenOriginY;
2245                resizeTime  = eventTime;
2246
2247                RECT clientRect;
2248                ::GetClientRect(hwnd, &clientRect);
2249
2250                int windowWidth = (clientRect.right == 0) ? 1 : clientRect.right ;
2251                int windowHeight = (clientRect.bottom == 0) ? 1 : clientRect.bottom;;
2252
2253                if (windowX!=_traits->x || windowY!=_traits->y || windowWidth!=_traits->width || windowHeight!=_traits->height)
2254                {
2255                    resized(windowX, windowY, windowWidth, windowHeight);
2256                    getEventQueue()->windowResize(windowX, windowY, windowWidth, windowHeight, resizeTime);
2257                }
2258            }
2259            break;
2260
2261        ////////////////////
2262        case WM_KEYDOWN    :
2263        case WM_SYSKEYDOWN :
2264        ////////////////////
2265
2266            {
2267                int keySymbol = 0;
2268                unsigned int modifierMask = 0;
2269                adaptKey(wParam, lParam, keySymbol, modifierMask);
2270                _keyMap[keySymbol] = true;
2271                //getEventQueue()->getCurrentEventState()->setModKeyMask(modifierMask);
2272                getEventQueue()->keyPress(keySymbol, eventTime);
2273            }
2274            break;
2275
2276        //////////////////
2277        case WM_KEYUP    :
2278        case WM_SYSKEYUP :
2279        //////////////////
2280
2281            {
2282                int keySymbol = 0;
2283                unsigned int modifierMask = 0;
2284                adaptKey(wParam, lParam, keySymbol, modifierMask);
2285                _keyMap[keySymbol] = false;
2286                //getEventQueue()->getCurrentEventState()->setModKeyMask(modifierMask);
2287                getEventQueue()->keyRelease(keySymbol, eventTime);
2288            }
2289            break;
2290
2291        ///////////////////
2292        case WM_SETCURSOR :
2293        ///////////////////
2294            //The cursor is only modified in response to the WM_SETCURSOR message if the mouse cursor isn't set to
2295            //InheritCursor.  InheritCursor lets the user manage the cursor externally.
2296            if (_mouseCursor != InheritCursor)
2297            {
2298                if (_traits->useCursor)
2299                    ::SetCursor( _currentCursor);
2300                else
2301                    ::SetCursor(NULL);
2302                return TRUE;
2303            }
2304            break;
2305
2306        ///////////////////
2307        case WM_SETFOCUS :
2308        ///////////////////
2309
2310            // Check keys and send a message if the key is pressed when the
2311            // focus comes back to the window.
2312            // I don't really like this hard-coded loop, but the key codes
2313            // (VK_* constants) seem to go from 0x08 to 0xFE so it should be
2314            // ok. See winuser.h for the key codes.
2315            for (unsigned int i = 0x08; i < 0xFF; i++)
2316            {
2317                if ((::GetAsyncKeyState(i) & 0x8000) != 0)
2318                    ::SendMessage(hwnd, WM_KEYDOWN, i, 0);
2319            }
2320            break;
2321
2322        ///////////////////
2323        case WM_KILLFOCUS :
2324        ///////////////////
2325
2326            // Release all keys that were pressed when the window lost focus.
2327            for (std::map<int, bool>::iterator key = _keyMap.begin();
2328                 key != _keyMap.end(); ++key)
2329            {
2330                if (key->second)
2331                {
2332                    getEventQueue()->keyRelease(key->first);
2333                    key->second = false;
2334                }
2335            }
2336            break;
2337
2338        ///////////////////
2339        case WM_NCHITTEST :
2340        ///////////////////
2341            {
2342                LONG_PTR result = _windowProcedure==0 ? ::DefWindowProc(hwnd, uMsg, wParam, lParam) :
2343                                                        ::CallWindowProc(_windowProcedure, hwnd, uMsg, wParam, lParam);
2344
2345                switch(result)
2346                {
2347                case HTLEFT:
2348                case HTRIGHT:
2349                    setCursor(LeftRightCursor);
2350                    break;
2351                case HTTOP:
2352                case HTBOTTOM:
2353                    setCursor(UpDownCursor);
2354                    break;
2355                case HTTOPLEFT:
2356                    setCursor(TopLeftCorner);
2357                    break;
2358                case HTTOPRIGHT:
2359                    setCursor(TopRightCorner);
2360                    break;
2361                case HTBOTTOMLEFT:
2362                    setCursor(BottomLeftCorner);
2363                    break;
2364                case HTBOTTOMRIGHT:
2365                case HTGROWBOX:
2366                    setCursor(BottomRightCorner);
2367                    break;
2368                default:
2369                    if (_traits->useCursor && _appMouseCursor != InheritCursor)
2370                        setCursor(LeftArrowCursor);
2371                    break;
2372                }
2373                return result;
2374            }
2375            break;
2376
2377        /////////////////
2378        case WM_CLOSE   :
2379        /////////////////
2380
2381            getEventQueue()->closeWindow(eventTime);
2382            break;
2383
2384        /////////////////
2385        case WM_DESTROY :
2386        /////////////////
2387
2388            _destroyWindow = true;
2389            if (_ownsWindow)
2390            {
2391                ::PostQuitMessage(0);
2392            }
2393            break;
2394
2395        //////////////
2396        case WM_QUIT :
2397        //////////////
2398
2399            _closeWindow = true;
2400            return wParam;
2401
2402        /////////////////
2403        default         :
2404        /////////////////
2405
2406            if (_ownsWindow) return ::DefWindowProc(hwnd, uMsg, wParam, lParam);
2407            break;
2408    }
2409
2410    if (_ownsWindow) return 0;
2411
2412    return _windowProcedure==0 ? ::DefWindowProc(hwnd, uMsg, wParam, lParam) :
2413                                 ::CallWindowProc(_windowProcedure, hwnd, uMsg, wParam, lParam);
2414}
2415
2416
2417//////////////////////////////////////////////////////////////////////////////
2418//  Class responsible for registering the Win32 Windowing System interface
2419//////////////////////////////////////////////////////////////////////////////
2420
2421struct RegisterWindowingSystemInterfaceProxy
2422{
2423    RegisterWindowingSystemInterfaceProxy()
2424    {
2425        osg::GraphicsContext::setWindowingSystemInterface(Win32WindowingSystem::getInterface());
2426    }
2427
2428    ~RegisterWindowingSystemInterfaceProxy()
2429    {
2430        if (osg::Referenced::getDeleteHandler())
2431        {
2432            osg::Referenced::getDeleteHandler()->setNumFramesToRetainObjects(0);
2433            osg::Referenced::getDeleteHandler()->flushAll();
2434        }
2435
2436        osg::GraphicsContext::setWindowingSystemInterface(0);
2437    }
2438};
2439
2440static RegisterWindowingSystemInterfaceProxy createWindowingSystemInterfaceProxy;
2441
2442} // namespace OsgViewer
2443
2444
2445// declare C entry point for static compilation.
2446extern "C" void graphicswindow_Win32(void)
2447{
2448    osg::GraphicsContext::setWindowingSystemInterface(osgViewer::Win32WindowingSystem::getInterface());
2449}
2450
2451
2452void GraphicsWindowWin32::raiseWindow()
2453{
2454
2455    SetWindowPos(_hwnd, HWND_TOPMOST, _traits->x, _traits->y, _traits->width, _traits->height, SWP_NOMOVE|SWP_NOSIZE);
2456    SetWindowPos(_hwnd, HWND_NOTOPMOST, _traits->x, _traits->y, _traits->width, _traits->height, SWP_NOMOVE|SWP_NOSIZE);
2457
2458}
Note: See TracBrowser for help on using the browser.