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

Revision 9727, 85.3 kB (checked in by robert, 5 years ago)

From Ralf Habacker, "on win32 there is a memory leak in recent svn code in GraphicsWindowWin?32.cpp.

in bool GraphicsWindowWin?32::setWindow( HWND handle )

there is the following if/else statement

if (_traits.valid() && _traits->setInheritedWindowPixelFormat)
....
else

setPixelFormat()

_hglrc = ::wglCreateContext(...) [1]

setPixelFormat() calls wglCreateContext() and saves the result into _hglrc which is overwritten by a second call to wglCreateContext() call at [1]

The same behavior occurs in bool Win32WindowingSystem::getSampleOpenGLContext( OpenGLContext& context, HDC windowHDC, int windowOriginX, int windowOriginY ).

The solution for this issue is to move the wglCreateContext() out of setPixelFormat() and to place it into the caller which is done to the appended file
"

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