root/OpenSceneGraph/trunk/src/osgViewer/GraphicsWindowX11.cpp @ 7074

Revision 7074, 42.1 kB (checked in by robert, 7 years ago)

Added include/osg/GLObjects + .cpp which provide osg::flush*DeletedGLObjects() methods.

Added and cleaned up DeleteHandler? calls in osgViewer to help avoid crashes on exit.

Changed DatabasePager? across to dynamically checcking osg::getCompileContext(..)

Updated wrappers.

  • 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
14/* Note, elements of GraphicsWindowX11 have used Prodcer/RenderSurface_X11.cpp as both
15 * a guide to use of X11/GLX and copiying directly in the case of setBorder().
16 * These elements are license under OSGPL as above, with Copyright (C) 2001-2004  Don Burns.
17 */
18
19#include <osgViewer/api/X11/GraphicsWindowX11>
20#include <osgViewer/api/X11/PixelBufferX11>
21
22#include <osg/DeleteHandler>
23
24#include <X11/Xlib.h>
25#include <X11/Xutil.h>
26
27#include <X11/Xmd.h>
28#include <X11/keysym.h>
29#include <X11/Xmu/WinUtil.h>
30#include <X11/cursorfont.h>
31#include <X11/Intrinsic.h>
32
33#include <X11/Xmd.h>        /* For CARD16 */
34
35#include <unistd.h>
36
37using namespace osgViewer;
38
39class X11KeyboardMap
40{
41    public:
42
43        X11KeyboardMap()
44        {
45            _keymap[XK_Escape       ] = osgGA::GUIEventAdapter::KEY_Escape;
46            _keymap[XK_F1           ] = osgGA::GUIEventAdapter::KEY_F1;
47            _keymap[XK_F2           ] = osgGA::GUIEventAdapter::KEY_F2;
48            _keymap[XK_F3           ] = osgGA::GUIEventAdapter::KEY_F3;
49            _keymap[XK_F4           ] = osgGA::GUIEventAdapter::KEY_F4;
50            _keymap[XK_F5           ] = osgGA::GUIEventAdapter::KEY_F5;
51            _keymap[XK_F6           ] = osgGA::GUIEventAdapter::KEY_F6;
52            _keymap[XK_F7           ] = osgGA::GUIEventAdapter::KEY_F7;
53            _keymap[XK_F8           ] = osgGA::GUIEventAdapter::KEY_F8;
54            _keymap[XK_F9           ] = osgGA::GUIEventAdapter::KEY_F9;
55            _keymap[XK_F10          ] = osgGA::GUIEventAdapter::KEY_F10;
56            _keymap[XK_F11          ] = osgGA::GUIEventAdapter::KEY_F11;
57            _keymap[XK_F12          ] = osgGA::GUIEventAdapter::KEY_F12;
58            _keymap[XK_quoteleft    ] = '"';
59            _keymap[XK_1            ] = '1';
60            _keymap[XK_2            ] = '2';
61            _keymap[XK_3            ] = '3';
62            _keymap[XK_4            ] = '4';
63            _keymap[XK_5            ] = '5';
64            _keymap[XK_6            ] = '6';
65            _keymap[XK_7            ] = '7';
66            _keymap[XK_8            ] = '8';
67            _keymap[XK_9            ] = '9';
68            _keymap[XK_0            ] = '0';
69            _keymap[XK_minus        ] = '-';
70            _keymap[XK_equal        ] = '=';
71            _keymap[XK_BackSpace    ] = osgGA::GUIEventAdapter::KEY_BackSpace;
72            _keymap[XK_Tab          ] = osgGA::GUIEventAdapter::KEY_Tab;
73            _keymap[XK_a            ] = 'A';
74            _keymap[XK_b            ] = 'B';
75            _keymap[XK_c            ] = 'C';
76            _keymap[XK_d            ] = 'D';
77            _keymap[XK_e            ] = 'E';
78            _keymap[XK_f            ] = 'F';
79            _keymap[XK_g            ] = 'G';
80            _keymap[XK_h            ] = 'H';
81            _keymap[XK_i            ] = 'I';
82            _keymap[XK_j            ] = 'J';
83            _keymap[XK_k            ] = 'K';
84            _keymap[XK_l            ] = 'L';
85            _keymap[XK_m            ] = 'M';
86            _keymap[XK_n            ] = 'N';
87            _keymap[XK_o            ] = 'O';
88            _keymap[XK_p            ] = 'P';
89            _keymap[XK_q            ] = 'Q';
90            _keymap[XK_r            ] = 'R';
91            _keymap[XK_s            ] = 'S';
92            _keymap[XK_t            ] = 'T';
93            _keymap[XK_u            ] = 'U';
94            _keymap[XK_v            ] = 'V';
95            _keymap[XK_w            ] = 'W';
96            _keymap[XK_x            ] = 'X';
97            _keymap[XK_y            ] = 'Y';
98            _keymap[XK_z            ] = 'Z';
99            _keymap[XK_bracketleft  ] = '(';
100            _keymap[XK_bracketright ] = ')';
101            _keymap[XK_backslash    ] = '\\';
102            _keymap[XK_Caps_Lock    ] = osgGA::GUIEventAdapter::KEY_Caps_Lock;
103            _keymap[XK_semicolon    ] = ';';
104            _keymap[XK_apostrophe   ] = '\'';
105            _keymap[XK_Return       ] = osgGA::GUIEventAdapter::KEY_Return;
106            _keymap[XK_Shift_L      ] = osgGA::GUIEventAdapter::KEY_Shift_L;
107            _keymap[XK_comma        ] = ',';
108            _keymap[XK_period       ] = '.';
109            _keymap[XK_slash        ] = '/';
110            _keymap[XK_Shift_R      ] = osgGA::GUIEventAdapter::KEY_Shift_R;
111            _keymap[XK_Control_L    ] = osgGA::GUIEventAdapter::KEY_Control_L;
112            _keymap[XK_Super_L      ] = osgGA::GUIEventAdapter::KEY_Super_L;
113            _keymap[XK_space        ] = ' ';
114            _keymap[XK_Alt_L        ] = osgGA::GUIEventAdapter::KEY_Alt_L;
115            _keymap[XK_Alt_R        ] = osgGA::GUIEventAdapter::KEY_Alt_R;
116            _keymap[XK_Super_R      ] = osgGA::GUIEventAdapter::KEY_Super_R;
117            _keymap[XK_Menu         ] = osgGA::GUIEventAdapter::KEY_Menu;
118            _keymap[XK_Control_R    ] = osgGA::GUIEventAdapter::KEY_Control_R;
119            _keymap[XK_Print        ] = osgGA::GUIEventAdapter::KEY_Print;
120            _keymap[XK_Scroll_Lock  ] = osgGA::GUIEventAdapter::KEY_Scroll_Lock;
121            _keymap[XK_Pause        ] = osgGA::GUIEventAdapter::KEY_Pause;
122            _keymap[XK_Home         ] = osgGA::GUIEventAdapter::KEY_Home;
123            _keymap[XK_Page_Up      ] = osgGA::GUIEventAdapter::KEY_Page_Up;
124            _keymap[XK_End          ] = osgGA::GUIEventAdapter::KEY_End;
125            _keymap[XK_Page_Down    ] = osgGA::GUIEventAdapter::KEY_Page_Down;
126            _keymap[XK_Delete       ] = osgGA::GUIEventAdapter::KEY_Delete;
127            _keymap[XK_Insert       ] = osgGA::GUIEventAdapter::KEY_Insert;
128            _keymap[XK_Left         ] = osgGA::GUIEventAdapter::KEY_Left;
129            _keymap[XK_Up           ] = osgGA::GUIEventAdapter::KEY_Up;
130            _keymap[XK_Right        ] = osgGA::GUIEventAdapter::KEY_Right;
131            _keymap[XK_Down         ] = osgGA::GUIEventAdapter::KEY_Down;
132            _keymap[XK_Num_Lock     ] = osgGA::GUIEventAdapter::KEY_Num_Lock;
133            _keymap[XK_KP_Divide    ] = osgGA::GUIEventAdapter::KEY_KP_Divide;
134            _keymap[XK_KP_Multiply  ] = osgGA::GUIEventAdapter::KEY_KP_Multiply;
135            _keymap[XK_KP_Subtract  ] = osgGA::GUIEventAdapter::KEY_KP_Subtract;
136            _keymap[XK_KP_Add       ] = osgGA::GUIEventAdapter::KEY_KP_Add;
137            _keymap[XK_KP_Home      ] = osgGA::GUIEventAdapter::KEY_KP_Home;
138            _keymap[XK_KP_Up        ] = osgGA::GUIEventAdapter::KEY_KP_Up;
139            _keymap[XK_KP_Page_Up   ] = osgGA::GUIEventAdapter::KEY_KP_Page_Up;
140            _keymap[XK_KP_Left      ] = osgGA::GUIEventAdapter::KEY_KP_Left;
141            _keymap[XK_KP_Begin     ] = osgGA::GUIEventAdapter::KEY_KP_Begin;
142            _keymap[XK_KP_Right     ] = osgGA::GUIEventAdapter::KEY_KP_Right;
143            _keymap[XK_KP_End       ] = osgGA::GUIEventAdapter::KEY_KP_End;
144            _keymap[XK_KP_Down      ] = osgGA::GUIEventAdapter::KEY_KP_Down;
145            _keymap[XK_KP_Page_Down ] = osgGA::GUIEventAdapter::KEY_KP_Page_Down;
146            _keymap[XK_KP_Insert    ] = osgGA::GUIEventAdapter::KEY_KP_Insert;
147            _keymap[XK_KP_Delete    ] = osgGA::GUIEventAdapter::KEY_KP_Delete;
148            _keymap[XK_KP_Enter     ] = osgGA::GUIEventAdapter::KEY_KP_Enter;
149     
150        }
151
152        ~X11KeyboardMap() {}
153
154        int remapKey(int key)
155        {
156            KeyMap::iterator itr = _keymap.find(key);
157            if (itr == _keymap.end()) return key;
158            else return itr->second;
159        }
160     
161    protected:
162   
163
164        typedef std::map<int, int> KeyMap;
165        KeyMap _keymap;
166};
167
168static int remapX11Key(int key)
169{
170    static X11KeyboardMap s_x11KeyboardMap;
171    return s_x11KeyboardMap.remapKey(key);
172}
173
174GraphicsWindowX11::~GraphicsWindowX11()
175{
176    close(true);
177}
178
179Display* GraphicsWindowX11::getDisplayToUse() const
180{
181    if (_threadOfLastMakeCurrent==0)
182    {
183        return _display;
184    }
185   
186    if (OpenThreads::Thread::CurrentThread()==_threadOfLastMakeCurrent)
187    {
188        return _display;
189    }
190    else 
191    {
192        return _eventDisplay;
193    }
194}
195
196bool GraphicsWindowX11::createVisualInfo()
197{
198    typedef std::vector<int> Attributes;
199    Attributes attributes;
200   
201    attributes.push_back(GLX_USE_GL);
202   
203    attributes.push_back(GLX_RGBA);
204   
205    if (_traits->doubleBuffer) attributes.push_back(GLX_DOUBLEBUFFER);
206   
207    if (_traits->quadBufferStereo) attributes.push_back(GLX_STEREO);
208   
209    attributes.push_back(GLX_RED_SIZE); attributes.push_back(_traits->red);
210    attributes.push_back(GLX_GREEN_SIZE); attributes.push_back(_traits->green);
211    attributes.push_back(GLX_BLUE_SIZE); attributes.push_back(_traits->blue);
212    attributes.push_back(GLX_DEPTH_SIZE); attributes.push_back(_traits->depth);
213   
214    if (_traits->alpha) { attributes.push_back(GLX_ALPHA_SIZE); attributes.push_back(_traits->alpha); }
215   
216    if (_traits->stencil) { attributes.push_back(GLX_STENCIL_SIZE); attributes.push_back(_traits->stencil); }
217
218#if defined(GLX_SAMPLE_BUFFERS) && defined (GLX_SAMPLES)
219
220    if (_traits->sampleBuffers) { attributes.push_back(GLX_SAMPLE_BUFFERS); attributes.push_back(_traits->sampleBuffers); }
221    if (_traits->sampleBuffers) { attributes.push_back(GLX_SAMPLES); attributes.push_back(_traits->samples); }
222
223#endif
224    // TODO
225    //  GLX_AUX_BUFFERS
226    //  GLX_ACCUM_RED_SIZE
227    //  GLX_ACCUM_GREEN_SIZE
228    //  GLX_SAMPLE_BUFFERS
229    //  GLX_SAMPLES
230   
231    attributes.push_back(None);
232   
233    _visualInfo = glXChooseVisual( _display, _traits->screenNum, &(attributes.front()) );
234
235    return _visualInfo != 0;
236}
237#define MWM_HINTS_FUNCTIONS   (1L << 0)
238#define MWM_HINTS_DECORATIONS (1L << 1)
239#define MWM_HINTS_INPUT_MODE  (1L << 2)
240#define MWM_HINTS_STATUS      (1L << 3)
241
242#define MWM_DECOR_ALL         (1L<<0)
243#define MWM_DECOR_BORDER      (1L<<1)
244#define MWM_DECOR_RESIZEH     (1L<<2)
245#define MWM_DECOR_TITLE       (1L<<3)
246#define MWM_DECOR_MENU        (1L<<4)
247#define MWM_DECOR_MINIMIZE    (1L<<5)
248#define MWM_DECOR_MAXIMIZE    (1L<<6)
249
250#define MWM_FUNC_ALL          (1L<<0)
251#define MWM_FUNC_RESIZE       (1L<<1)
252#define MWM_FUNC_MOVE         (1L<<2)
253#define MWM_FUNC_MINIMIZE     (1L<<3)
254#define MWM_FUNC_MAXIMIZE     (1L<<4)
255#define MWM_FUNC_CLOSE        (1L<<5)
256
257
258bool GraphicsWindowX11::setWindowDecorationImplementation(bool flag)
259{
260    Display* display = getDisplayToUse();
261   
262    Atom atom;
263    if( (atom = XInternAtom( display, "_MOTIF_WM_HINTS", 0 )) != None )
264    {
265   
266        struct
267        {
268            unsigned long flags;
269            unsigned long functions;
270            unsigned long decorations;
271            long          inputMode;
272            unsigned long status;
273        } wmHints;
274       
275        wmHints.flags = 0;
276        wmHints.functions = MWM_FUNC_ALL;
277        wmHints.decorations = MWM_DECOR_ALL;
278        wmHints.inputMode = 0;
279        wmHints.status = 0;       
280       
281        if (!flag)
282        {
283            wmHints.flags = MWM_HINTS_DECORATIONS;
284            wmHints.decorations = 0;
285        }
286        else
287        {
288            wmHints.flags |= MWM_HINTS_FUNCTIONS;
289            if (_traits.valid() && !_traits->supportsResize) wmHints.functions |= MWM_FUNC_RESIZE;
290        }
291
292        XMapWindow(display, _window );
293        XChangeProperty( display, _window, atom, atom, 32, PropModeReplace, (unsigned char *)&wmHints,  5 );
294
295        XFlush(display);
296        XSync(display,0);
297
298#if 0
299        // now update the window dimensions to account for any size changes made by the window manager,
300        XGetWindowAttributes( display, _window, &watt );
301        _traits->width = watt.width;
302        _traits->height = watt.height;
303#endif
304
305        // add usleep here to give window manager a chance to handle the request, if
306        // we don't add this sleep then any X11 calls right afterwards can produce
307        // X11 errors.
308        usleep(100000);
309       
310        return true;
311
312    }
313    else
314    {
315        osg::notify(osg::NOTICE)<<"Error: GraphicsWindowX11::setBorder(" << flag << ") - couldn't change decorations." << std::endl;
316        return false;
317    }
318
319   
320}
321
322bool GraphicsWindowX11::setWindowRectangleImplementation(int x, int y, int width, int height)
323{
324    if (!_realized) return false;
325   
326    Display* display = getDisplayToUse();
327   
328    XMoveResizeWindow(display, _window, x, y, width, height);
329   
330    XFlush(display);
331    XSync(display, 0);
332
333    // add usleep here to give window manager a chance to handle the request, if
334    // we don't add this sleep then any X11 calls right afterwards can produce
335    // X11 errors.
336    usleep(100000);
337   
338    return true;
339}
340
341void GraphicsWindowX11::setCursor(MouseCursor mouseCursor)
342{
343    Cursor newCursor = getOrCreateCursor(mouseCursor);
344    if (newCursor == _currentCursor) return;
345
346    _currentCursor = newCursor;
347    if (!_window) return;
348    Display* display = getDisplayToUse();
349    if (!display) return;
350    XDefineCursor( display, _window, _currentCursor );
351    XFlush(display);
352    XSync(display, 0);
353
354    _traits->useCursor = (_currentCursor != getOrCreateCursor(NoCursor));
355}
356
357Cursor GraphicsWindowX11::getOrCreateCursor(MouseCursor mouseCursor)
358{
359    std::map<MouseCursor,Cursor>::iterator i = _mouseCursorMap.find(mouseCursor);
360    if (i != _mouseCursorMap.end()) return i->second;
361
362    Display* display = getDisplayToUse();
363    if (!display) return None;
364
365    switch (mouseCursor) {
366    case NoCursor:
367    {
368        // create an empty mouse cursor, note that it is safe to destroy the Pixmap just past cursor creation
369        // since the resource in the x server is reference counted.
370        char buff[2] = {0,0};
371        XColor ncol = {0,0,0,0,DoRed|DoGreen|DoBlue,0};
372        Pixmap pixmap = XCreateBitmapFromData( display, _parent, buff, 1, 1);
373        _mouseCursorMap[mouseCursor] = XCreatePixmapCursor( display, pixmap, pixmap, &ncol, &ncol, 0, 0 );
374        XFreePixmap(display, pixmap);
375        // Important to have the pixmap and the buffer still available when the request is sent to the server ...
376        XFlush(display);
377        XSync(display, 0);
378        break;
379    }
380    case RightArrowCursor:
381        _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_left_ptr );
382        break;
383    case LeftArrowCursor:
384        _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_top_left_arrow );
385        break;
386    case InfoCursor:
387        _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_hand1 );
388        break;
389    case DestroyCursor:
390        _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_pirate );
391        break;
392    case HelpCursor:
393        _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_question_arrow );
394        break;
395    case CycleCursor:
396        _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_exchange );
397        break;
398    case SprayCursor:
399        _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_spraycan );
400        break;
401    case WaitCursor:
402        _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_watch );
403        break;
404    case TextCursor:
405        _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_xterm );
406        break;
407    case CrosshairCursor:
408        _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_crosshair );
409        break;
410    case UpDownCursor:
411        _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_sb_v_double_arrow );
412        break;
413    case LeftRightCursor:
414        _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_sb_h_double_arrow );
415        break;
416    case TopSideCursor:
417        _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_top_side );
418        break;
419    case BottomSideCursor:
420        _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_bottom_side );
421        break;
422    case LeftSideCursor:
423        _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_left_side );
424        break;
425    case RightSideCursor:
426        _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_right_side );
427        break;
428    case TopLeftCorner:
429        _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_top_left_corner );
430        break;
431    case TopRightCorner:
432        _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_top_right_corner );
433        break;
434    case BottomRightCorner:
435        _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_bottom_right_corner );
436        break;
437    case BottomLeftCorner:
438        _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_bottom_left_corner );
439        break;
440
441    case InheritCursor:
442    default:
443        _mouseCursorMap[mouseCursor] = None;
444        break;
445    };
446    return _mouseCursorMap[mouseCursor];
447}
448
449void GraphicsWindowX11::init()
450{
451    if (_initialized) return;
452
453    if (!_traits)
454    {
455        _valid = false;
456        return;
457    }
458   
459    WindowData* inheritedWindowData =  dynamic_cast<WindowData*>(_traits->inheritedWindowData.get());
460
461    _display = XOpenDisplay(_traits->displayName().c_str());
462   
463    unsigned int screen = _traits->screenNum;
464
465    if (!_display)
466    {
467        osg::notify(osg::NOTICE)<<"Error: Unable to open display \"" << XDisplayName(_traits->displayName().c_str()) << "\"."<<std::endl;
468        _valid = false;
469        return;
470    }
471
472     // Query for GLX extension
473    int errorBase, eventBase;
474    if( glXQueryExtension( _display, &errorBase, &eventBase)  == False )
475    {
476        osg::notify(osg::NOTICE)<<"Error: " << XDisplayName(_traits->displayName().c_str()) <<" has no GLX extension." << std::endl;
477
478        XCloseDisplay( _display );
479        _display = 0;
480        _valid = false;
481        return;
482    }
483   
484    // osg::notify(osg::NOTICE)<<"GLX extension, errorBase="<<errorBase<<" eventBase="<<eventBase<<std::endl;
485
486    if (!createVisualInfo())
487    {
488        _traits->red /= 2;
489        _traits->green /= 2;
490        _traits->blue /= 2;
491        _traits->alpha /= 2;
492        _traits->depth /= 2;
493       
494        osg::notify(osg::INFO)<<"Relaxing traits"<<std::endl;
495
496        if (!createVisualInfo())
497        {
498            osg::notify(osg::NOTICE)<<"Error: Not able to create requested visual." << std::endl;
499            XCloseDisplay( _display );
500            _display = 0;
501            _valid = false;
502            return;
503        }   
504    }
505   
506   
507    GLXContext sharedContextGLX = NULL;
508
509    // get any shared GLX contexts   
510    GraphicsWindowX11* graphicsWindowX11 = dynamic_cast<GraphicsWindowX11*>(_traits->sharedContext);
511    if (graphicsWindowX11)
512    {
513        sharedContextGLX = graphicsWindowX11->getGLXContext();
514    }
515    else
516    {
517        PixelBufferX11* pixelBufferX11 = dynamic_cast<PixelBufferX11*>(_traits->sharedContext);
518        if (pixelBufferX11)
519        {
520            sharedContextGLX = pixelBufferX11->getGLXContext();
521        }
522    }
523   
524    _glxContext = glXCreateContext( _display, _visualInfo, sharedContextGLX, True );
525   
526    if (!_glxContext)
527    {
528        osg::notify(osg::NOTICE)<<"Error: Unable to create OpenGL graphics context."<<std::endl;
529        XCloseDisplay( _display );
530        _display = 0;
531        _valid = false;
532        return;
533    }
534   
535    _eventDisplay = XOpenDisplay(_traits->displayName().c_str());
536
537    _parent = RootWindow( _display, screen );
538
539    XWindowAttributes watt;
540    XGetWindowAttributes( _display, _parent, &watt );
541    // unsigned int parentWindowHeight = watt.height;
542
543    XSetWindowAttributes swatt;
544    swatt.colormap = XCreateColormap( _display, _parent, _visualInfo->visual, AllocNone);
545    //swatt.colormap = DefaultColormap( _dpy, 10 );
546    swatt.background_pixel = 0;
547    swatt.border_pixel = 0;
548    swatt.event_mask =  0;
549    unsigned long mask = CWBackPixel | CWBorderPixel | CWEventMask | CWColormap;
550
551    bool overrideRedirect = false;
552    if (overrideRedirect)
553    {
554        swatt.override_redirect = true;
555        mask |= CWOverrideRedirect;
556    }
557
558    _window = XCreateWindow( _display, _parent,
559                             _traits->x,
560                             _traits->y,
561                             _traits->width, _traits->height, 0,
562                             _visualInfo->depth, InputOutput,
563                             _visualInfo->visual, mask, &swatt );
564                             
565    if (!_window)
566    {
567        osg::notify(osg::NOTICE)<<"Error: Unable to create Window."<<std::endl;
568        XCloseDisplay( _display );
569        _display = 0;
570        _glxContext = 0;
571        _valid = false;
572        return;
573    }
574
575
576    // This positions the window at _windowX, _windowY
577    XSizeHints sh;
578    sh.flags = 0;
579    sh.flags |= USSize;
580    sh.flags &= 0x7;
581    sh.flags |= USPosition;
582    sh.flags &= 0xB;
583    sh.x = _traits->x;
584    sh.y = _traits->y;
585    sh.width  = _traits->width;
586    sh.height = _traits->height;
587    XSetStandardProperties( _display, _window, _traits->windowName.c_str(), _traits->windowName.c_str(), None, 0, 0, &sh);
588
589    setWindowDecoration(_traits->windowDecoration);
590
591    useCursor(_traits->useCursor);
592
593    _deleteWindow = XInternAtom (_display, "WM_DELETE_WINDOW", False);
594    XSetWMProtocols(_display, _window, &_deleteWindow, 1);
595
596
597    XFlush( _display );
598    XSync( _display, 0 );
599
600    // now update the window dimensions to account for any size changes made by the window manager,
601    XGetWindowAttributes( _display, _window, &watt );
602   
603    if (_traits->width != watt.width && _traits->height != watt.height)
604    {
605        resized( _traits->x, _traits->y, _traits->width, _traits->height );
606    }
607       
608    //osg::notify(osg::NOTICE)<<"After sync apply.x = "<<watt.x<<" watt.y="<<watt.y<<" width="<<watt.width<<" height="<<watt.height<<std::endl;
609
610
611    XSelectInput( _eventDisplay, _window, ExposureMask | StructureNotifyMask |
612                                     KeyPressMask | KeyReleaseMask |
613                                     PointerMotionMask  | ButtonPressMask | ButtonReleaseMask);
614
615    XFlush( _eventDisplay );
616    XSync( _eventDisplay, 0 );
617
618    _valid = true;
619    _initialized = true;
620}
621
622bool GraphicsWindowX11::realizeImplementation()
623{
624    if (_realized)
625    {
626        osg::notify(osg::NOTICE)<<"GraphicsWindowX11::realizeImplementation() Already realized"<<std::endl;
627        return true;
628    }
629
630    if (!_initialized) init();
631   
632    if (!_initialized) return false;
633   
634    XMapWindow( _display, _window );
635   
636//    Window temp = _window;
637//    XSetWMColormapWindows( _display, _window, &temp, 1);
638   
639    _realized = true;
640
641    return true;
642}
643
644bool GraphicsWindowX11::makeCurrentImplementation()
645{
646    if (!_realized)
647    {
648        osg::notify(osg::NOTICE)<<"Warning: GraphicsWindow not realized, cannot do makeCurrent."<<std::endl;
649        return false;
650    }
651
652    // osg::notify(osg::NOTICE)<<"GraphicsWindowX11::makeCurrentImplementation "<<this<<" "<<OpenThreads::Thread::CurrentThread()<<std::endl;
653    // osg::notify(osg::NOTICE)<<"   glXMakeCurrent ("<<_display<<","<<_window<<","<<_glxContext<<std::endl;
654
655    return glXMakeCurrent( _display, _window, _glxContext )==True;
656}
657
658bool GraphicsWindowX11::releaseContextImplementation()
659{
660    if (!_realized)
661    {
662        osg::notify(osg::NOTICE)<<"Warning: GraphicsWindow not realized, cannot do makeCurrent."<<std::endl;
663        return false;
664    }
665
666    // osg::notify(osg::NOTICE)<<"GraphicsWindowX11::releaseContextImplementation() "<<this<<" "<<OpenThreads::Thread::CurrentThread()<<std::endl;
667    // osg::notify(osg::NOTICE)<<"   glXMakeCurrent ("<<_display<<std::endl;
668
669    return glXMakeCurrent( _display, None, NULL )==True;
670}
671
672
673void GraphicsWindowX11::closeImplementation()
674{
675    // osg::notify(osg::NOTICE)<<"Closing GraphicsWindowX11"<<std::endl;
676
677    if (_eventDisplay)
678    {
679        XCloseDisplay( _eventDisplay );
680        _eventDisplay = 0;
681    }
682
683    if (_display)
684    {
685        if (_glxContext)
686        {
687            glXDestroyContext(_display, _glxContext );
688        }
689   
690        if (_window)
691        {
692            XDestroyWindow(_display, _window);
693        }
694
695        XFlush( _display );
696        XSync( _display,0 );
697    }
698   
699    _window = 0;
700    _parent = 0;
701    _glxContext = 0;
702
703    if (_visualInfo)
704    {
705        XFree(_visualInfo);
706        _visualInfo = 0;
707    }
708
709
710    if (_display)
711    {
712        XCloseDisplay( _display );
713        _display = 0;
714    }
715
716    _initialized = false;
717    _realized = false;
718    _valid = false;
719}
720
721void GraphicsWindowX11::swapBuffersImplementation()
722{
723    if (!_realized) return;
724
725    // osg::notify(osg::NOTICE)<<"swapBuffersImplementation "<<this<<" "<<OpenThreads::Thread::CurrentThread()<<std::endl;
726
727    glXSwapBuffers(_display, _window);
728
729    while( XPending(_display) )
730    {
731        XEvent ev;
732        XNextEvent( _display, &ev );
733
734        switch( ev.type )
735        {
736            case ClientMessage:
737            {
738                if (static_cast<Atom>(ev.xclient.data.l[0]) == _deleteWindow)
739                {
740                    osg::notify(osg::INFO)<<"DeleteWindow event recieved"<<std::endl;
741                    getEventQueue()->closeWindow();
742                }
743            }
744        }
745    }
746}
747
748void GraphicsWindowX11::checkEvents()
749{
750    if (!_realized) return;
751
752    Display* display = _eventDisplay;
753
754    double baseTime = _timeOfLastCheckEvents;
755    double eventTime = baseTime;
756    double resizeTime = eventTime;
757    _timeOfLastCheckEvents = getEventQueue()->getTime();
758
759    int windowX = _traits->x;
760    int windowY = _traits->y;
761    int windowWidth = _traits->width;
762    int windowHeight = _traits->height;
763
764    bool destroyWindowRequested = false;
765   
766    Time firstEventTime = 0;
767     
768         // osg::notify(osg::NOTICE)<<"Check events"<<std::endl;   
769    while( XPending(display) )
770    {
771        XEvent ev;
772        XNextEvent( display, &ev );
773
774        switch( ev.type )
775        {
776            case ClientMessage:
777            {
778                osg::notify(osg::NOTICE)<<"ClientMessage event recieved"<<std::endl;
779                if (static_cast<Atom>(ev.xclient.data.l[0]) == _deleteWindow)
780                {
781                    osg::notify(osg::NOTICE)<<"DeleteWindow event recieved"<<std::endl;
782                    destroyWindowRequested = true;
783                    getEventQueue()->closeWindow(eventTime);
784                }
785            }
786            case Expose :
787                osg::notify(osg::INFO)<<"Expose x="<<ev.xexpose.x<<" y="<<ev.xexpose.y<<" width="<<ev.xexpose.width<<", height="<<ev.xexpose.height<<std::endl;
788                break;
789
790            case GravityNotify :
791                osg::notify(osg::INFO)<<"GravityNotify event recieved"<<std::endl;
792                break;
793
794            case UnmapNotify :
795                osg::notify(osg::INFO)<<"UnmapNotify event recieved"<<std::endl;
796                break;
797
798            case ReparentNotify:
799                osg::notify(osg::INFO)<<"ReparentNotify event recieved"<<std::endl;
800                break;
801
802            case DestroyNotify :
803                osg::notify(osg::NOTICE)<<"DestroyNotify event recieved"<<std::endl;
804                _realized =  false;
805                _valid = false;
806                break;
807               
808            case ConfigureNotify :
809            {
810                osg::notify(osg::INFO)<<"ConfigureNotify x="<<ev.xconfigure.x<<" y="<<ev.xconfigure.y<<" width="<<ev.xconfigure.width<<", height="<<ev.xconfigure.height<<std::endl;
811
812                if (windowX != ev.xconfigure.x ||
813                    windowX != ev.xconfigure.y ||
814                    windowWidth != ev.xconfigure.width ||
815                    windowHeight != ev.xconfigure.height)
816                {
817                    resizeTime = eventTime;
818
819                    windowX = ev.xconfigure.x;
820                    windowY = ev.xconfigure.y;
821                    windowWidth = ev.xconfigure.width;
822                    windowHeight = ev.xconfigure.height;
823                }
824
825                break;
826            }
827           
828            case MapNotify :
829            {
830                osg::notify(osg::INFO)<<"MapNotify"<<std::endl;
831                XWindowAttributes watt;
832                do
833                    XGetWindowAttributes(display, _window, &watt );
834                while( watt.map_state != IsViewable );
835               
836                osg::notify(osg::INFO)<<"MapNotify x="<<watt.x<<" y="<<watt.y<<" width="<<watt.width<<", height="<<watt.height<<std::endl;
837
838                if (windowWidth != watt.width || windowHeight != watt.height)
839                {
840                    resizeTime = eventTime;
841
842                    windowWidth = watt.width;
843                    windowHeight = watt.height;
844                }
845
846                break;
847            }
848
849           case MotionNotify :
850           {
851                if (firstEventTime==0) firstEventTime = ev.xmotion.time;
852                Time relativeTime = ev.xmotion.time - firstEventTime;
853                eventTime = baseTime + static_cast<double>(relativeTime)*0.001;
854           
855                int  wx, wy;
856                Window win = 0L;
857                if( ev.xmotion.same_screen )
858                {
859                    wx = ev.xmotion.x;
860                    wy = ev.xmotion.y;
861                }
862                else
863                {
864                    // the mouse in on another screen so need to compute the
865                    // coordinates of the mouse position relative to an absolute position
866                    // then take away the position of the original window/screen to get
867                    // the coordinates relative to the original position.
868                    Window root;
869                    int rx, ry;
870                    unsigned int buttons;
871
872                    int screenOrigin_x = 0;
873                    int screenOrigin_y = 0;
874                    int i;
875                    for(i= 0; i < ScreenCount(display); i++ )
876                    {
877                        if( XQueryPointer( display, RootWindow(display, i),
878                              &root, &win, &rx, &ry, &wx, &wy, &buttons) )
879                        {
880                            break;
881                        }
882
883                        screenOrigin_x += DisplayWidth(display, i);
884                    }
885
886                    for(i= 0; i < static_cast<int>(_traits->screenNum); i++ )
887                    {
888                        screenOrigin_x -= DisplayWidth(display, i);
889                    }
890
891                    int dest_x_return, dest_y_return;
892                    Window child_return;
893                    XTranslateCoordinates(display, _window, _parent, 0, 0, &dest_x_return, &dest_y_return, &child_return);
894
895                    wx += (screenOrigin_x - dest_x_return);
896                    wy += (screenOrigin_y - dest_y_return);
897                }
898               
899
900                float mx = wx;
901                float my = wy;
902                transformMouseXY(mx, my);
903                getEventQueue()->mouseMotion(mx, my, eventTime);
904
905                // osg::notify(osg::NOTICE)<<"MotionNotify wx="<<wx<<" wy="<<wy<<" mx="<<mx<<" my="<<my<<std::endl;
906
907                break;
908            }
909           
910            case ButtonPress :
911            {
912                if (firstEventTime==0) firstEventTime = ev.xmotion.time;
913                Time relativeTime = ev.xmotion.time - firstEventTime;
914                eventTime = baseTime + static_cast<double>(relativeTime)*0.001;
915
916                if( ev.xbutton.button == Button4 )
917                {
918                    getEventQueue()->mouseScroll(osgGA::GUIEventAdapter::SCROLL_UP, eventTime);
919                }
920                else if( ev.xbutton.button == Button5)
921                {
922                    getEventQueue()->mouseScroll(osgGA::GUIEventAdapter::SCROLL_DOWN, eventTime);
923                }
924                else
925                {
926                    float mx = ev.xbutton.x;
927                    float my = ev.xmotion.y;
928                    transformMouseXY(mx, my);
929                    getEventQueue()->mouseButtonPress(mx, my, ev.xbutton.button, eventTime);
930                }
931                break;
932            }
933           
934            case ButtonRelease :
935            {
936                if (firstEventTime==0) firstEventTime = ev.xmotion.time;
937                Time relativeTime = ev.xmotion.time - firstEventTime;
938                eventTime = baseTime + static_cast<double>(relativeTime)*0.001;
939
940                if( ev.xbutton.button == Button4 )
941                {
942                    getEventQueue()->mouseScroll(osgGA::GUIEventAdapter::SCROLL_UP, eventTime);
943                }
944                else if( ev.xbutton.button == Button5)
945                {
946                    getEventQueue()->mouseScroll(osgGA::GUIEventAdapter::SCROLL_DOWN, eventTime);
947                }
948                else
949                {
950                    float mx = ev.xbutton.x;
951                    float my = ev.xmotion.y;
952                    transformMouseXY(mx, my);
953                    getEventQueue()->mouseButtonRelease(mx, my, ev.xbutton.button, eventTime);
954                }
955                break;
956            }
957           
958            case KeyPress:
959            {
960                if (firstEventTime==0) firstEventTime = ev.xmotion.time;
961                Time relativeTime = ev.xmotion.time - firstEventTime;
962                eventTime = baseTime + static_cast<double>(relativeTime)*0.001;
963
964                int keySymbol = 0;
965                unsigned int modifierMask = 0;
966                adaptKey(ev.xkey, keySymbol, modifierMask);
967
968                //getEventQueue()->getCurrentEventState()->setModKeyMask(modifierMask);
969                getEventQueue()->keyPress(keySymbol, eventTime);
970                break;
971            }
972           
973            case KeyRelease:
974            {
975                if (firstEventTime==0) firstEventTime = ev.xmotion.time;
976                Time relativeTime = ev.xmotion.time - firstEventTime;
977                eventTime = baseTime + static_cast<double>(relativeTime)*0.001;
978
979                int keySymbol = 0;
980                unsigned int modifierMask = 0;
981                adaptKey(ev.xkey, keySymbol, modifierMask);
982               
983                //getEventQueue()->getCurrentEventState()->setModKeyMask(modifierMask);
984                getEventQueue()->keyRelease(keySymbol, eventTime);
985                break;
986            }
987           
988            default:
989                osg::notify(osg::NOTICE)<<"Other event"<<std::endl;
990                break;
991               
992        }
993    }
994
995    if (windowX != _traits->x ||
996        windowY != _traits->y ||
997        windowWidth != _traits->width ||
998        windowHeight != _traits->height)
999    {
1000        resized(windowX, windowY, windowWidth, windowHeight);
1001        getEventQueue()->windowResize(windowX, windowY, windowWidth, windowHeight, resizeTime);
1002    }
1003   
1004#if 0
1005    if (destroyWindowRequested)
1006    {
1007        close();
1008    }
1009#endif
1010}
1011
1012void GraphicsWindowX11::grabFocus()
1013{
1014    Display* display = getDisplayToUse();
1015
1016    XSetInputFocus( display, _window, RevertToNone, CurrentTime );
1017    XFlush(display);
1018    XSync(display,0);
1019}
1020
1021void GraphicsWindowX11::grabFocusIfPointerInWindow()
1022{
1023    Window win, root;
1024    int wx, wy, rx, ry;
1025    unsigned int buttons;
1026
1027    Display* display = getDisplayToUse();
1028
1029    if( XQueryPointer( display, _window,
1030          &root, &win, &rx, &ry, &wx, &wy, &buttons))
1031    {
1032#if 0
1033        if (wx>=0 && wx<_traits->width &&
1034            wy>=0 && wy<_traits->height)
1035        {
1036            grabFocus();
1037        }
1038#else       
1039        grabFocus();
1040#endif
1041    }
1042}
1043
1044
1045void GraphicsWindowX11::transformMouseXY(float& x, float& y)
1046{
1047    if (getEventQueue()->getUseFixedMouseInputRange())
1048    {
1049        osgGA::GUIEventAdapter* eventState = getEventQueue()->getCurrentEventState();
1050        x = eventState->getXmin() + (eventState->getXmax()-eventState->getXmin())*x/float(_traits->width);
1051        y = eventState->getYmin() + (eventState->getYmax()-eventState->getYmin())*y/float(_traits->height);
1052    }
1053}
1054
1055void GraphicsWindowX11::adaptKey(XKeyEvent& keyevent, int& keySymbol, unsigned int& modifierMask)
1056{
1057    Display* display = _eventDisplay;
1058 
1059    static XComposeStatus state;
1060    unsigned char keybuf[32];
1061    XLookupString( &keyevent, (char *)keybuf, sizeof(keybuf), NULL, &state );
1062
1063    modifierMask = 0;
1064    if( keyevent.state & ShiftMask )
1065    {
1066        modifierMask |= osgGA::GUIEventAdapter::MODKEY_SHIFT;
1067    }
1068    if( keyevent.state & LockMask )
1069    {
1070        modifierMask |= osgGA::GUIEventAdapter::MODKEY_CAPS_LOCK;
1071    }
1072    if( keyevent.state & ControlMask )
1073    {
1074        modifierMask |= osgGA::GUIEventAdapter::MODKEY_CTRL;
1075    }
1076    if( keyevent.state & Mod1Mask )
1077    {
1078        modifierMask |= osgGA::GUIEventAdapter::MODKEY_ALT;
1079    }
1080    if( keyevent.state & Mod2Mask )
1081    {
1082        modifierMask |= osgGA::GUIEventAdapter::MODKEY_NUM_LOCK;
1083    }
1084    if( keyevent.state & Mod4Mask )
1085    {
1086        modifierMask |= osgGA::GUIEventAdapter::MODKEY_META;
1087    }
1088
1089    keySymbol = keybuf[0];
1090   
1091    KeySym ks = XKeycodeToKeysym( display, keyevent.keycode, 0 );
1092    int remappedKey = remapX11Key(ks);
1093    if (remappedKey & 0xff00)
1094    {
1095        // special keyboard character
1096        keySymbol = remappedKey;
1097    }
1098    else
1099    {
1100        // normal ascii key
1101        keySymbol = keybuf[0];
1102    }
1103   
1104   
1105}
1106
1107void GraphicsWindowX11::requestWarpPointer(float x,float y)
1108{
1109    Display* display = getDisplayToUse();
1110
1111    XWarpPointer( display,
1112                  None,
1113                  _window,
1114                  0, 0, 0, 0,
1115                  static_cast<int>(x), static_cast<int>(y) );
1116
1117    XFlush(display);
1118    XSync(display, 0);
1119   
1120    getEventQueue()->mouseWarped(x,y);
1121}
1122
1123extern "C" 
1124{
1125
1126int X11ErrorHandling(Display* display, XErrorEvent* event)
1127{
1128    osg::notify(osg::NOTICE)<<"Got an X11ErrorHandling call display="<<display<<" event="<<event<<std::endl;
1129
1130    char buffer[256];
1131    XGetErrorText( display, event->error_code, buffer, 256);
1132
1133    osg::notify(osg::NOTICE) << buffer << std::endl;
1134    osg::notify(osg::NOTICE) << "Major opcode: " << (int)event->request_code << std::endl;
1135    osg::notify(osg::NOTICE) << "Minor opcode: " << (int)event->minor_code << std::endl;
1136    osg::notify(osg::NOTICE) << "Error code: " << (int)event->error_code << std::endl;
1137    osg::notify(osg::NOTICE) << "Request serial: " << event->serial << std::endl;
1138    osg::notify(osg::NOTICE) << "Current serial: " << NextRequest( display ) - 1 << std::endl;
1139
1140    switch( event->error_code )
1141    {
1142        case BadValue:
1143            osg::notify(osg::NOTICE) << "  Value: " << event->resourceid << std::endl;
1144            break;
1145
1146        case BadAtom:
1147            osg::notify(osg::NOTICE) << "  AtomID: " << event->resourceid << std::endl;
1148            break;
1149
1150        default:
1151            osg::notify(osg::NOTICE) << "  ResourceID: " << event->resourceid << std::endl;
1152            break;
1153    }
1154    return 0;
1155}
1156
1157}
1158
1159struct X11WindowingSystemInterface : public osg::GraphicsContext::WindowingSystemInterface
1160{
1161
1162    X11WindowingSystemInterface()
1163    {
1164        osg::notify(osg::INFO)<<"X11WindowingSystemInterface()"<<std::endl;
1165   
1166        XSetErrorHandler(X11ErrorHandling);
1167   
1168#if 0
1169        if (XInitThreads() == 0)
1170        {
1171            osg::notify(osg::NOTICE) << "Error: XInitThreads() failed. Aborting." << std::endl;
1172            exit(1);
1173        }
1174        else
1175        {
1176            osg::notify(osg::INFO) << "X11WindowingSystemInterface, xInitThreads() multi-threaded X support initialized.\n";
1177        }
1178#endif       
1179    }
1180
1181    ~X11WindowingSystemInterface()
1182    {
1183        if (osg::Referenced::getDeleteHandler())
1184        {
1185            osg::Referenced::getDeleteHandler()->setNumFramesToRetainObjects(0);
1186            osg::Referenced::getDeleteHandler()->flushAll();
1187        }
1188
1189        //osg::notify(osg::NOTICE)<<"~X11WindowingSystemInterface()"<<std::endl;
1190        XSetErrorHandler(0);
1191    }
1192
1193    virtual unsigned int getNumScreens(const osg::GraphicsContext::ScreenIdentifier& si)
1194    {
1195        Display* display = XOpenDisplay(si.displayName().c_str());
1196        if(display)
1197        {
1198            unsigned int numScreens = ScreenCount(display);
1199            XCloseDisplay(display);
1200
1201            return numScreens;
1202        }
1203        else
1204        {
1205            osg::notify(osg::NOTICE) << "A Unable to open display \"" << XDisplayName(si.displayName().c_str()) << "\""<<std::endl;
1206            return 0;
1207        }
1208    }
1209
1210    virtual void getScreenResolution(const osg::GraphicsContext::ScreenIdentifier& si, unsigned int& width, unsigned int& height)
1211    {
1212        Display* display = XOpenDisplay(si.displayName().c_str());
1213        if(display)
1214        {
1215            width = DisplayWidth(display, si.screenNum);
1216            height = DisplayHeight(display, si.screenNum);
1217            XCloseDisplay(display);
1218        }
1219        else
1220        {
1221            osg::notify(osg::NOTICE) << "Unable to open display \"" << XDisplayName(si.displayName().c_str()) << "\"."<<std::endl;
1222            width = 0;
1223            height = 0;
1224        }
1225    }
1226
1227    virtual osg::GraphicsContext* createGraphicsContext(osg::GraphicsContext::Traits* traits)
1228    {
1229        if (traits->pbuffer)
1230        {
1231#if 1
1232            osg::ref_ptr<osgViewer::PixelBufferX11> pbuffer = new PixelBufferX11(traits);
1233            if (pbuffer->valid()) return pbuffer.release();
1234            else return 0;
1235#else
1236            osg::ref_ptr<osgViewer::GraphicsWindowX11> window = new GraphicsWindowX11(traits);
1237            if (window->valid()) return window.release();
1238            else return 0;
1239#endif
1240        }
1241        else
1242        {
1243            osg::ref_ptr<osgViewer::GraphicsWindowX11> window = new GraphicsWindowX11(traits);
1244            if (window->valid()) return window.release();
1245            else return 0;
1246        }
1247    }
1248
1249};
1250
1251struct RegisterWindowingSystemInterfaceProxy
1252{
1253    RegisterWindowingSystemInterfaceProxy()
1254    {
1255        osg::notify(osg::INFO)<<"RegisterWindowingSystemInterfaceProxy()"<<std::endl;
1256        osg::GraphicsContext::setWindowingSystemInterface(new X11WindowingSystemInterface);
1257    }
1258
1259    ~RegisterWindowingSystemInterfaceProxy()
1260    {
1261        osg::notify(osg::INFO)<<"~RegisterWindowingSystemInterfaceProxy()"<<std::endl;
1262
1263        if (osg::Referenced::getDeleteHandler())
1264        {
1265            osg::Referenced::getDeleteHandler()->setNumFramesToRetainObjects(0);
1266            osg::Referenced::getDeleteHandler()->flushAll();
1267        }
1268
1269        osg::GraphicsContext::setWindowingSystemInterface(0);
1270
1271    }
1272};
1273
1274RegisterWindowingSystemInterfaceProxy createWindowingSystemInterfaceProxy;
1275
1276// declare C entry point for static compilation.
1277extern "C" void graphicswindow_X11(void)
1278{
1279    osg::GraphicsContext::setWindowingSystemInterface(new X11WindowingSystemInterface);
1280}
Note: See TracBrowser for help on using the browser.