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

Revision 11238, 86.1 kB (checked in by paulmartz, 4 years ago)

2.8 branch: Minor bug fixes for ac and 3dc plugins. Merges these revisions from trunk: 10010, 10758, and 11175.

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