root/OpenSceneGraph/trunk/src/osgViewer/GraphicsWindowWin32.cpp @ 11812

Revision 11812, 93.9 kB (checked in by robert, 4 years ago)

From Wojciech Lewandowski, "As promised I prepared a patch to expose WGL_SWAP_METHOD / PFD_SWAP_METHOD selection via GraphicsContext::Traits. Since Traits don't define any enums (I guess to be simple to use) I tried to keep it that way and have added two boolean values: swapCopy & swapExchange. It is somewhat similar approach to GDI PixelFormatDescription? were both options can be present together. Feel free to replace it with enum if you find it more appropriate.

I also uderstand that there is a need to select system wide default method and have also modified DisplaySettings? to contain swapMethod parameter. Swap method in Traits uses value set in DisplaySettings? as default. Proper environment and command line args were added. Its possible to define default DeisplaySettings? swap method in standard way via system flags or with comand line.

Env Vars:

OSG_SWAP_METHOD = DEFAULT | COPY | EXCHANGE

or Command Line:

--swap-method DEFAULT | COPY | EXCHANGE

I also added handling of WM_ERASEBKGND in GraphicsWindowWin?32. It may be unneccessary but code should be safer this way than without handling it. I have placed a comment explaining the reason above the change.

Changes were made against today trunk.

PS. I tested only Windows code. I briefly checked X11 & Cocoa files but have not noticed SwapMethod? to be used there.
"

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