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

Revision 13326, 73.0 kB (checked in by robert, 11 days ago)

Moved widgets from VolumeEditorWidget? to TransferFunctionWidget?, and widget utilities into WidgetUtils?.

  • 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 copying directly in the case of setBorder().
16 * These elements are licensed under OSGPL as above, with Copyright (C) 2001-2004  Don Burns.
17 */
18
19// TODO:
20// implement http://www.opengl.org/registry/specs/OML/glx_swap_method.txt
21
22#include <osgViewer/api/X11/GraphicsWindowX11>
23#include <osgViewer/api/X11/PixelBufferX11>
24
25#include <osg/DeleteHandler>
26
27#include <X11/Xlib.h>
28#include <X11/Xutil.h>
29
30#include <X11/Xmd.h>
31#include <X11/keysym.h>
32#include <X11/XKBlib.h>
33#include <X11/cursorfont.h>
34
35#include <X11/Xmd.h>        /* For CARD16 */
36
37#ifdef OSGVIEWER_USE_XRANDR
38#include <X11/extensions/Xrandr.h>
39#endif
40
41#include <unistd.h>
42
43using namespace osgViewer;
44
45#ifdef OSG_USE_EGL
46bool checkEGLError(const char* str)
47{
48    EGLint err = eglGetError();
49    if (err != EGL_SUCCESS)
50    {
51        OSG_WARN<<"Warning: "<<str<<" EGL error "<<std::hex<<err<<std::dec<<std::endl;
52        return true;
53    }
54    else
55    {
56        // OSG_WARN<<"EGL reports no errors: "<<str<<std::endl;
57        return false;
58    }
59}
60#endif
61
62class X11KeyboardMap
63{
64    public:
65
66        X11KeyboardMap()
67        {
68#if 0
69            _extendKeymap[8               ] = osgGA::GUIEventAdapter::KEY_BackSpace;
70            _extendKeymap[127             ] = osgGA::GUIEventAdapter::KEY_Delete;
71            _extendKeymap[27              ] = osgGA::GUIEventAdapter::KEY_Escape;
72            // _extendKeymap[13              ] = osgGA::GUIEventAdapter::KEY_Enter;
73#endif
74            _extendedKeymap[XK_Escape       ] = osgGA::GUIEventAdapter::KEY_Escape;
75            _extendedKeymap[XK_F1           ] = osgGA::GUIEventAdapter::KEY_F1;
76            _extendedKeymap[XK_F2           ] = osgGA::GUIEventAdapter::KEY_F2;
77            _extendedKeymap[XK_F3           ] = osgGA::GUIEventAdapter::KEY_F3;
78            _extendedKeymap[XK_F4           ] = osgGA::GUIEventAdapter::KEY_F4;
79            _extendedKeymap[XK_F5           ] = osgGA::GUIEventAdapter::KEY_F5;
80            _extendedKeymap[XK_F6           ] = osgGA::GUIEventAdapter::KEY_F6;
81            _extendedKeymap[XK_F7           ] = osgGA::GUIEventAdapter::KEY_F7;
82            _extendedKeymap[XK_F8           ] = osgGA::GUIEventAdapter::KEY_F8;
83            _extendedKeymap[XK_F9           ] = osgGA::GUIEventAdapter::KEY_F9;
84            _extendedKeymap[XK_F10          ] = osgGA::GUIEventAdapter::KEY_F10;
85            _extendedKeymap[XK_F11          ] = osgGA::GUIEventAdapter::KEY_F11;
86            _extendedKeymap[XK_F12          ] = osgGA::GUIEventAdapter::KEY_F12;
87            _extendedKeymap[XK_quoteleft    ] = '`';
88            _extendedKeymap[XK_minus        ] = '-';
89            _extendedKeymap[XK_equal        ] = '=';
90            _extendedKeymap[XK_BackSpace    ] = osgGA::GUIEventAdapter::KEY_BackSpace;
91            _extendedKeymap[XK_Tab          ] = osgGA::GUIEventAdapter::KEY_Tab;
92            _extendedKeymap[XK_bracketleft  ] = '[';
93            _extendedKeymap[XK_bracketright ] = ']';
94            _extendedKeymap[XK_backslash    ] = '\\';
95            _extendedKeymap[XK_Caps_Lock    ] = osgGA::GUIEventAdapter::KEY_Caps_Lock;
96            _extendedKeymap[XK_semicolon    ] = ';';
97            _extendedKeymap[XK_apostrophe   ] = '\'';
98            _extendedKeymap[XK_Return       ] = osgGA::GUIEventAdapter::KEY_Return;
99            _extendedKeymap[XK_comma        ] = ',';
100            _extendedKeymap[XK_period       ] = '.';
101            _extendedKeymap[XK_slash        ] = '/';
102            _extendedKeymap[XK_space        ] = ' ';
103            _extendedKeymap[XK_Shift_L      ] = osgGA::GUIEventAdapter::KEY_Shift_L;
104            _extendedKeymap[XK_Shift_R      ] = osgGA::GUIEventAdapter::KEY_Shift_R;
105            _extendedKeymap[XK_Control_L    ] = osgGA::GUIEventAdapter::KEY_Control_L;
106            _extendedKeymap[XK_Control_R    ] = osgGA::GUIEventAdapter::KEY_Control_R;
107            _extendedKeymap[XK_Meta_L       ] = osgGA::GUIEventAdapter::KEY_Meta_L;
108            _extendedKeymap[XK_Meta_R       ] = osgGA::GUIEventAdapter::KEY_Meta_R;
109            _extendedKeymap[XK_Alt_L        ] = osgGA::GUIEventAdapter::KEY_Alt_L;
110            _extendedKeymap[XK_Alt_R        ] = osgGA::GUIEventAdapter::KEY_Alt_R;
111            _extendedKeymap[XK_Super_L      ] = osgGA::GUIEventAdapter::KEY_Super_L;
112            _extendedKeymap[XK_Super_R      ] = osgGA::GUIEventAdapter::KEY_Super_R;
113            _extendedKeymap[XK_Hyper_L      ] = osgGA::GUIEventAdapter::KEY_Hyper_L;
114            _extendedKeymap[XK_Hyper_R      ] = osgGA::GUIEventAdapter::KEY_Hyper_R;
115            _extendedKeymap[XK_Menu         ] = osgGA::GUIEventAdapter::KEY_Menu;
116            _extendedKeymap[XK_Print        ] = osgGA::GUIEventAdapter::KEY_Print;
117            _extendedKeymap[XK_Scroll_Lock  ] = osgGA::GUIEventAdapter::KEY_Scroll_Lock;
118            _extendedKeymap[XK_Pause        ] = osgGA::GUIEventAdapter::KEY_Pause;
119            _extendedKeymap[XK_Home         ] = osgGA::GUIEventAdapter::KEY_Home;
120            _extendedKeymap[XK_Page_Up      ] = osgGA::GUIEventAdapter::KEY_Page_Up;
121            _extendedKeymap[XK_End          ] = osgGA::GUIEventAdapter::KEY_End;
122            _extendedKeymap[XK_Page_Down    ] = osgGA::GUIEventAdapter::KEY_Page_Down;
123            _extendedKeymap[XK_Delete       ] = osgGA::GUIEventAdapter::KEY_Delete;
124            _extendedKeymap[XK_Insert       ] = osgGA::GUIEventAdapter::KEY_Insert;
125            _extendedKeymap[XK_Left         ] = osgGA::GUIEventAdapter::KEY_Left;
126            _extendedKeymap[XK_Up           ] = osgGA::GUIEventAdapter::KEY_Up;
127            _extendedKeymap[XK_Right        ] = osgGA::GUIEventAdapter::KEY_Right;
128            _extendedKeymap[XK_Down         ] = osgGA::GUIEventAdapter::KEY_Down;
129            _extendedKeymap[XK_Num_Lock     ] = osgGA::GUIEventAdapter::KEY_Num_Lock;
130            _extendedKeymap[XK_KP_Divide    ] = osgGA::GUIEventAdapter::KEY_KP_Divide;
131            _extendedKeymap[XK_KP_Multiply  ] = osgGA::GUIEventAdapter::KEY_KP_Multiply;
132            _extendedKeymap[XK_KP_Subtract  ] = osgGA::GUIEventAdapter::KEY_KP_Subtract;
133            _extendedKeymap[XK_KP_Add       ] = osgGA::GUIEventAdapter::KEY_KP_Add;
134            _extendedKeymap[XK_KP_Home      ] = osgGA::GUIEventAdapter::KEY_KP_Home;
135            _extendedKeymap[XK_KP_Up        ] = osgGA::GUIEventAdapter::KEY_KP_Up;
136            _extendedKeymap[XK_KP_Page_Up   ] = osgGA::GUIEventAdapter::KEY_KP_Page_Up;
137            _extendedKeymap[XK_KP_Left      ] = osgGA::GUIEventAdapter::KEY_KP_Left;
138            _extendedKeymap[XK_KP_Begin     ] = osgGA::GUIEventAdapter::KEY_KP_Begin;
139            _extendedKeymap[XK_KP_Right     ] = osgGA::GUIEventAdapter::KEY_KP_Right;
140            _extendedKeymap[XK_KP_End       ] = osgGA::GUIEventAdapter::KEY_KP_End;
141            _extendedKeymap[XK_KP_Down      ] = osgGA::GUIEventAdapter::KEY_KP_Down;
142            _extendedKeymap[XK_KP_Page_Down ] = osgGA::GUIEventAdapter::KEY_KP_Page_Down;
143            _extendedKeymap[XK_KP_Insert    ] = osgGA::GUIEventAdapter::KEY_KP_Insert;
144            _extendedKeymap[XK_KP_Delete    ] = osgGA::GUIEventAdapter::KEY_KP_Delete;
145            _extendedKeymap[XK_KP_Enter     ] = osgGA::GUIEventAdapter::KEY_KP_Enter;
146
147            _standardKeymap[XK_1            ] = '1';
148            _standardKeymap[XK_2            ] = '2';
149            _standardKeymap[XK_3            ] = '3';
150            _standardKeymap[XK_4            ] = '4';
151            _standardKeymap[XK_5            ] = '5';
152            _standardKeymap[XK_6            ] = '6';
153            _standardKeymap[XK_7            ] = '7';
154            _standardKeymap[XK_8            ] = '8';
155            _standardKeymap[XK_9            ] = '9';
156            _standardKeymap[XK_0            ] = '0';
157            _standardKeymap[XK_A            ] = 'A';
158            _standardKeymap[XK_B            ] = 'B';
159            _standardKeymap[XK_C            ] = 'C';
160            _standardKeymap[XK_D            ] = 'D';
161            _standardKeymap[XK_E            ] = 'E';
162            _standardKeymap[XK_F            ] = 'F';
163            _standardKeymap[XK_G            ] = 'G';
164            _standardKeymap[XK_H            ] = 'H';
165            _standardKeymap[XK_I            ] = 'I';
166            _standardKeymap[XK_J            ] = 'J';
167            _standardKeymap[XK_K            ] = 'K';
168            _standardKeymap[XK_L            ] = 'L';
169            _standardKeymap[XK_M            ] = 'M';
170            _standardKeymap[XK_N            ] = 'N';
171            _standardKeymap[XK_O            ] = 'O';
172            _standardKeymap[XK_P            ] = 'P';
173            _standardKeymap[XK_Q            ] = 'Q';
174            _standardKeymap[XK_R            ] = 'R';
175            _standardKeymap[XK_S            ] = 'S';
176            _standardKeymap[XK_T            ] = 'T';
177            _standardKeymap[XK_U            ] = 'U';
178            _standardKeymap[XK_V            ] = 'V';
179            _standardKeymap[XK_W            ] = 'W';
180            _standardKeymap[XK_X            ] = 'X';
181            _standardKeymap[XK_Y            ] = 'Y';
182            _standardKeymap[XK_Z            ] = 'Z';
183            _standardKeymap[XK_a            ] = 'a';
184            _standardKeymap[XK_b            ] = 'b';
185            _standardKeymap[XK_c            ] = 'c';
186            _standardKeymap[XK_d            ] = 'd';
187            _standardKeymap[XK_e            ] = 'e';
188            _standardKeymap[XK_f            ] = 'f';
189            _standardKeymap[XK_g            ] = 'g';
190            _standardKeymap[XK_h            ] = 'h';
191            _standardKeymap[XK_i            ] = 'i';
192            _standardKeymap[XK_j            ] = 'j';
193            _standardKeymap[XK_k            ] = 'k';
194            _standardKeymap[XK_l            ] = 'l';
195            _standardKeymap[XK_m            ] = 'm';
196            _standardKeymap[XK_n            ] = 'n';
197            _standardKeymap[XK_o            ] = 'o';
198            _standardKeymap[XK_p            ] = 'p';
199            _standardKeymap[XK_q            ] = 'q';
200            _standardKeymap[XK_r            ] = 'r';
201            _standardKeymap[XK_s            ] = 's';
202            _standardKeymap[XK_t            ] = 't';
203            _standardKeymap[XK_u            ] = 'u';
204            _standardKeymap[XK_v            ] = 'v';
205            _standardKeymap[XK_w            ] = 'w';
206            _standardKeymap[XK_x            ] = 'x';
207            _standardKeymap[XK_y            ] = 'y';
208            _standardKeymap[XK_z            ] = 'z';
209        }
210
211        ~X11KeyboardMap() {}
212
213        int remapKey(int key)
214        {
215            KeyMap::iterator itr = _extendedKeymap.find(key);
216            if (itr != _extendedKeymap.end()) return itr->second;
217
218            itr = _standardKeymap.find(key);
219            if (itr != _standardKeymap.end()) return itr->second;
220
221            return key;
222        }
223
224        bool remapExtendedKey(int& key)
225        {
226            KeyMap::iterator itr = _extendedKeymap.find(key);
227            if (itr != _extendedKeymap.end())
228            {
229                key = itr->second;
230                return true;
231            }
232            else return false;
233        }
234
235    protected:
236
237        typedef std::map<int, int> KeyMap;
238        KeyMap _extendedKeymap;
239        KeyMap _standardKeymap;
240};
241
242static bool remapExtendedX11Key(int& key)
243{
244    static X11KeyboardMap s_x11KeyboardMap;
245    return s_x11KeyboardMap.remapExtendedKey(key);
246}
247
248// Functions to handle key maps of type char[32] as contained in
249// an XKeymapEvent or returned by XQueryKeymap().
250static inline bool keyMapGetKey(const char* map, unsigned int key)
251{
252    return (map[(key & 0xff) / 8] & (1 << (key & 7))) != 0;
253}
254
255static inline void keyMapSetKey(char* map, unsigned int key)
256{
257    map[(key & 0xff) / 8] |= (1 << (key & 7));
258}
259
260static inline void keyMapClearKey(char* map, unsigned int key)
261{
262    map[(key & 0xff) / 8] &= ~(1 << (key & 7));
263}
264
265GraphicsWindowX11::~GraphicsWindowX11()
266{
267    close(true);
268}
269
270Display* GraphicsWindowX11::getDisplayToUse() const
271{
272    if (_threadOfLastMakeCurrent==0)
273    {
274        return _display;
275    }
276
277    if (OpenThreads::Thread::CurrentThread()==_threadOfLastMakeCurrent)
278    {
279        return _display;
280    }
281    else
282    {
283        return _eventDisplay;
284    }
285}
286
287bool GraphicsWindowX11::createVisualInfo()
288{
289    if (_visualInfo)
290    {
291    #ifdef OSG_USE_EGL
292        delete _visualInfo;
293    #else
294        XFree(_visualInfo);
295    #endif
296        _visualInfo = 0;
297    }
298
299    if( _window != 0 )
300    {
301        XWindowAttributes watt;
302        XGetWindowAttributes( _display, _window, &watt );
303        XVisualInfo temp;
304        temp.visualid = XVisualIDFromVisual(watt.visual);
305        int n;
306        _visualInfo = XGetVisualInfo( _display, VisualIDMask, &temp, &n );
307    }
308    else
309    {
310    #ifdef OSG_USE_EGL
311
312        _visualInfo = new XVisualInfo;
313        int depth = DefaultDepth( _display, _traits->screenNum );
314        if (XMatchVisualInfo( _display, _traits->screenNum, depth, TrueColor, _visualInfo )==0)
315        {
316            OSG_NOTICE<<"GraphicsWindowX11::createVisualInfo() failed."<<std::endl;
317            return false;
318        }
319
320    #else
321
322        typedef std::vector<int> Attributes;
323        Attributes attributes;
324
325        attributes.push_back(GLX_USE_GL);
326
327        attributes.push_back(GLX_RGBA);
328
329        if (_traits->doubleBuffer) attributes.push_back(GLX_DOUBLEBUFFER);
330
331        if (_traits->quadBufferStereo) attributes.push_back(GLX_STEREO);
332
333        attributes.push_back(GLX_RED_SIZE); attributes.push_back(_traits->red);
334        attributes.push_back(GLX_GREEN_SIZE); attributes.push_back(_traits->green);
335        attributes.push_back(GLX_BLUE_SIZE); attributes.push_back(_traits->blue);
336        attributes.push_back(GLX_DEPTH_SIZE); attributes.push_back(_traits->depth);
337
338        if (_traits->alpha) { attributes.push_back(GLX_ALPHA_SIZE); attributes.push_back(_traits->alpha); }
339
340        if (_traits->stencil) { attributes.push_back(GLX_STENCIL_SIZE); attributes.push_back(_traits->stencil); }
341
342        #if defined(GLX_SAMPLE_BUFFERS) && defined (GLX_SAMPLES)
343
344            if (_traits->sampleBuffers) { attributes.push_back(GLX_SAMPLE_BUFFERS); attributes.push_back(_traits->sampleBuffers); }
345            if (_traits->samples) { attributes.push_back(GLX_SAMPLES); attributes.push_back(_traits->samples); }
346
347        #endif
348        // TODO
349        //  GLX_AUX_BUFFERS
350        //  GLX_ACCUM_RED_SIZE
351        //  GLX_ACCUM_GREEN_SIZE
352
353        attributes.push_back(None);
354
355        _visualInfo = glXChooseVisual( _display, _traits->screenNum, &(attributes.front()) );
356    #endif
357    }
358
359    return _visualInfo != 0;
360}
361
362bool GraphicsWindowX11::checkAndSendEventFullScreenIfNeeded(Display* display, int x, int y, int width, int height, bool windowDecoration)
363{
364    osg::GraphicsContext::WindowingSystemInterface *wsi = osg::GraphicsContext::getWindowingSystemInterface();
365    if (wsi == NULL)
366    {
367        OSG_NOTICE << "Error, no WindowSystemInterface available, cannot toggle window fullscreen." << std::endl;
368        return false;
369    }
370
371    unsigned int    screenWidth;
372    unsigned int    screenHeight;
373
374    wsi->getScreenResolution(*_traits, screenWidth, screenHeight);
375    bool isFullScreen = x == 0 && y == 0 && width == (int)screenWidth && height == (int)screenHeight && !windowDecoration;
376
377    if (isFullScreen) {
378        resized(x, y, width, height);
379        getEventQueue()->windowResize(x, y, width, height, getEventQueue()->getTime());
380    }
381
382    Atom netWMStateAtom = XInternAtom(display, "_NET_WM_STATE", True);
383    Atom netWMStateFullscreenAtom = XInternAtom(display, "_NET_WM_STATE_FULLSCREEN", True);
384
385    if (netWMStateAtom != None && netWMStateFullscreenAtom != None)
386    {
387        XEvent xev;
388        xev.xclient.type = ClientMessage;
389        xev.xclient.serial = 0;
390        xev.xclient.send_event = True;
391        xev.xclient.window = _window;
392        xev.xclient.message_type = netWMStateAtom;
393        xev.xclient.format = 32;
394        xev.xclient.data.l[0] = isFullScreen ? 1 : 0;
395        xev.xclient.data.l[1] = netWMStateFullscreenAtom;
396        xev.xclient.data.l[2] = 0;
397
398        XSendEvent(display, RootWindow(display, DefaultScreen(display)),
399                    False,  SubstructureRedirectMask | SubstructureNotifyMask, &xev);
400        return true;
401    }
402    return false;
403}
404
405#define MWM_HINTS_FUNCTIONS   (1L << 0)
406#define MWM_HINTS_DECORATIONS (1L << 1)
407#define MWM_HINTS_INPUT_MODE  (1L << 2)
408#define MWM_HINTS_STATUS      (1L << 3)
409
410#define MWM_DECOR_ALL         (1L<<0)
411#define MWM_DECOR_BORDER      (1L<<1)
412#define MWM_DECOR_RESIZEH     (1L<<2)
413#define MWM_DECOR_TITLE       (1L<<3)
414#define MWM_DECOR_MENU        (1L<<4)
415#define MWM_DECOR_MINIMIZE    (1L<<5)
416#define MWM_DECOR_MAXIMIZE    (1L<<6)
417
418#define MWM_FUNC_ALL          (1L<<0)
419#define MWM_FUNC_RESIZE       (1L<<1)
420#define MWM_FUNC_MOVE         (1L<<2)
421#define MWM_FUNC_MINIMIZE     (1L<<3)
422#define MWM_FUNC_MAXIMIZE     (1L<<4)
423#define MWM_FUNC_CLOSE        (1L<<5)
424
425bool GraphicsWindowX11::setWindowDecorationImplementation(bool flag)
426{
427    Display* display = getDisplayToUse();
428
429    XMapWindow(display, _window );
430
431    checkAndSendEventFullScreenIfNeeded(display, _traits->x, _traits->y, _traits->width, _traits->height, flag);
432    struct
433    {
434        unsigned long flags;
435        unsigned long functions;
436        unsigned long decorations;
437        long          inputMode;
438        unsigned long status;
439    } wmHints;
440
441    Atom atom;
442    bool result = false;
443    if( (atom = XInternAtom( display, "_MOTIF_WM_HINTS", 0 )) != None )
444    {
445
446        if (flag)
447        {
448            wmHints.flags = MWM_HINTS_DECORATIONS | MWM_HINTS_FUNCTIONS;
449            wmHints.functions = MWM_FUNC_ALL;
450            wmHints.decorations = MWM_DECOR_ALL;
451            wmHints.inputMode = 0;
452            wmHints.status = 0;
453
454            // if traits says not resize we want to set the functions to exlude MWM_FUNC_RESIZE,
455            // but this bitmask needs to be set if the MWM_FUNC_ALL bit is already set in order to toggle it off.
456            if (_traits.valid() && !_traits->supportsResize) wmHints.functions = wmHints.functions | MWM_FUNC_RESIZE;
457
458        }
459        else
460        {
461            wmHints.flags = MWM_HINTS_DECORATIONS;
462            wmHints.functions = 0;
463            wmHints.decorations = 0;
464            wmHints.inputMode = 0;
465            wmHints.status = 0;
466        }
467
468        XChangeProperty( display, _window, atom, atom, 32, PropModeReplace, (unsigned char *)&wmHints,  5 );
469        result = true;
470    }
471    else
472    {
473        OSG_NOTICE<<"Error: GraphicsWindowX11::setWindowDecorationImplementation(" << flag << ") - couldn't change decorations." << std::endl;
474        result = false;
475    }
476
477    XFlush(display);
478    XSync(display,0);
479    // add usleep here to give window manager a chance to handle the request, if
480    // we don't add this sleep then any X11 calls right afterwards can produce
481    // X11 errors.
482    usleep(100000);
483    return result;
484}
485
486bool GraphicsWindowX11::setWindowRectangleImplementation(int x, int y, int width, int height)
487{
488    if (!_initialized) return false;
489
490    Display* display = getDisplayToUse();
491
492    checkAndSendEventFullScreenIfNeeded(display, x, y, width, height, _traits->windowDecoration);
493
494    XMoveResizeWindow(display, _window, x, y, width, height);
495
496    XFlush(display);
497    XSync(display, 0);
498
499    // add usleep here to give window manager a chance to handle the request, if
500    // we don't add this sleep then any X11 calls right afterwards can produce
501    // X11 errors.
502    usleep(100000);
503
504
505    return true;
506}
507
508void GraphicsWindowX11::setWindowName(const std::string& name)
509{
510    if( _window == 0) return;
511
512    //    char *slist[] = { name.c_str(), 0L };
513    //    XTextProperty xtp;
514
515    //    XStringListToTextProperty( slist, 1, &xtp );
516
517    Display* display = getDisplayToUse();
518    if( !display ) return;
519
520    //    XSetWMName( display, _window, &xtp );
521    XStoreName( display, _window, name.c_str() );
522    XSetIconName( display, _window, name.c_str() );
523
524    XFlush(display);
525    XSync(display,0);
526
527    _traits->windowName = name;
528}
529
530void GraphicsWindowX11::setCursor(MouseCursor mouseCursor)
531{
532    Cursor newCursor = getOrCreateCursor(mouseCursor);
533    if (newCursor == _currentCursor) return;
534
535    _currentCursor = newCursor;
536    if (!_window) return;
537    Display* display = getDisplayToUse();
538    if (!display) return;
539    XDefineCursor( display, _window, _currentCursor );
540    XFlush(display);
541    XSync(display, 0);
542
543    _traits->useCursor = (_currentCursor != getOrCreateCursor(NoCursor));
544}
545
546Cursor GraphicsWindowX11::getOrCreateCursor(MouseCursor mouseCursor)
547{
548    std::map<MouseCursor,Cursor>::iterator i = _mouseCursorMap.find(mouseCursor);
549    if (i != _mouseCursorMap.end()) return i->second;
550
551    Display* display = getDisplayToUse();
552    if (!display) return None;
553
554    switch (mouseCursor) {
555    case NoCursor:
556    {
557        // create an empty mouse cursor, note that it is safe to destroy the Pixmap just past cursor creation
558        // since the resource in the x server is reference counted.
559        char buff[2] = {0,0};
560        XColor ncol = {0,0,0,0,DoRed|DoGreen|DoBlue,0};
561        Pixmap pixmap = XCreateBitmapFromData( display, _parent, buff, 1, 1);
562        _mouseCursorMap[mouseCursor] = XCreatePixmapCursor( display, pixmap, pixmap, &ncol, &ncol, 0, 0 );
563        XFreePixmap(display, pixmap);
564        // Important to have the pixmap and the buffer still available when the request is sent to the server ...
565        XFlush(display);
566        XSync(display, 0);
567        break;
568    }
569    case RightArrowCursor:
570        _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_left_ptr );
571        break;
572    case LeftArrowCursor:
573        _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_top_left_arrow );
574        break;
575    case InfoCursor:
576        _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_hand1 );
577        break;
578    case DestroyCursor:
579        _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_pirate );
580        break;
581    case HelpCursor:
582        _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_question_arrow );
583        break;
584    case CycleCursor:
585        _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_exchange );
586        break;
587    case SprayCursor:
588        _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_spraycan );
589        break;
590    case WaitCursor:
591        _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_watch );
592        break;
593    case TextCursor:
594        _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_xterm );
595        break;
596    case CrosshairCursor:
597        _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_crosshair );
598        break;
599    case UpDownCursor:
600        _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_sb_v_double_arrow );
601        break;
602    case LeftRightCursor:
603        _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_sb_h_double_arrow );
604        break;
605    case TopSideCursor:
606        _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_top_side );
607        break;
608    case BottomSideCursor:
609        _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_bottom_side );
610        break;
611    case LeftSideCursor:
612        _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_left_side );
613        break;
614    case RightSideCursor:
615        _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_right_side );
616        break;
617    case TopLeftCorner:
618        _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_top_left_corner );
619        break;
620    case TopRightCorner:
621        _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_top_right_corner );
622        break;
623    case BottomRightCorner:
624        _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_bottom_right_corner );
625        break;
626    case BottomLeftCorner:
627        _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_bottom_left_corner );
628        break;
629    case HandCursor:
630        _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_hand1 );
631        break;
632
633    case InheritCursor:
634    default:
635        _mouseCursorMap[mouseCursor] = None;
636        break;
637    };
638    return _mouseCursorMap[mouseCursor];
639}
640
641void GraphicsWindowX11::init()
642{
643    if (_initialized) return;
644
645    if (!_traits)
646    {
647        _valid = false;
648        return;
649    }
650
651    // getEventQueue()->setCurrentEventState(osgGA::GUIEventAdapter::getAccumulatedEventState().get());
652
653    WindowData* inheritedWindowData = dynamic_cast<WindowData*>(_traits->inheritedWindowData.get());
654    Window windowHandle = inheritedWindowData ? inheritedWindowData->_window : 0;
655
656    _ownsWindow = windowHandle == 0;
657
658    _display = XOpenDisplay(_traits->displayName().c_str());
659
660    if (!_display)
661    {
662        OSG_NOTICE<<"Error: Unable to open display \"" << XDisplayName(_traits->displayName().c_str()) << "\"."<<std::endl;
663        _valid = false;
664        return;
665    }
666
667    #ifdef OSG_USE_EGL
668
669        _eglDisplay = eglGetDisplay((EGLNativeDisplayType)_display);
670
671        EGLint eglMajorVersion, eglMinorVersion;
672        if (!eglInitialize(_eglDisplay, &eglMajorVersion, &eglMinorVersion))
673        {
674            OSG_NOTICE<<"GraphicsWindowX11::init() - eglInitialize() failed."<<std::endl;
675
676            XCloseDisplay( _display );
677            _display = 0;
678            _valid = false;
679            return;
680        }
681
682        OSG_NOTICE<<"GraphicsWindowX11::init() - eglInitialize() succeded eglMajorVersion="<<eglMajorVersion<<" iMinorVersion="<<eglMinorVersion<<std::endl;
683
684   #else
685        // Query for GLX extension
686        int errorBase, eventBase;
687        if( glXQueryExtension( _display, &errorBase, &eventBase)  == False )
688        {
689            OSG_NOTICE<<"Error: " << XDisplayName(_traits->displayName().c_str()) <<" has no GLX extension." << std::endl;
690
691            XCloseDisplay( _display );
692            _display = 0;
693            _valid = false;
694            return;
695        }
696    #endif
697
698    // OSG_NOTICE<<"GLX extension, errorBase="<<errorBase<<" eventBase="<<eventBase<<std::endl;
699
700    if (!createVisualInfo())
701    {
702        _traits->red /= 2;
703        _traits->green /= 2;
704        _traits->blue /= 2;
705        _traits->alpha /= 2;
706        _traits->depth /= 2;
707
708        OSG_INFO<<"Relaxing traits"<<std::endl;
709
710        if (!createVisualInfo())
711        {
712            OSG_NOTICE<<"Error: Not able to create requested visual." << std::endl;
713            XCloseDisplay( _display );
714            _display = 0;
715            _valid = false;
716            return;
717        }
718    }
719
720    // get any shared GLX contexts
721    GraphicsHandleX11* graphicsHandleX11 = dynamic_cast<GraphicsHandleX11*>(_traits->sharedContext.get());
722    Context sharedContext = graphicsHandleX11 ? graphicsHandleX11->getContext() : 0;
723
724    #ifdef OSG_USE_EGL
725
726        _valid = _ownsWindow ? createWindow() : setWindow(windowHandle);
727
728        if (!_valid)
729        {
730            XCloseDisplay( _display );
731            _display = 0;
732            return;
733        }
734
735        OSG_NOTICE<<"GraphicsWindowX11::init() - window created ="<<_valid<<std::endl;
736
737        eglBindAPI(EGL_OPENGL_ES_API);
738
739        EGLConfig eglConfig = 0;
740
741        #if defined(OSG_GLES2_AVAILABLE)
742            #define OSG_EGL_OPENGL_TARGET_BIT EGL_OPENGL_ES2_BIT
743        #else
744            #define OSG_EGL_OPENGL_TARGET_BIT EGL_OPENGL_ES_BIT
745        #endif
746
747        typedef std::vector<EGLint> Attributes;
748        Attributes attributes;
749
750        attributes.push_back(EGL_RED_SIZE); attributes.push_back(_traits->red);
751        attributes.push_back(EGL_GREEN_SIZE); attributes.push_back(_traits->green);
752        attributes.push_back(EGL_BLUE_SIZE); attributes.push_back(_traits->blue);
753        attributes.push_back(EGL_DEPTH_SIZE); attributes.push_back(_traits->depth);
754
755        if (_traits->alpha) { attributes.push_back(EGL_ALPHA_SIZE); attributes.push_back(_traits->alpha); }
756        if (_traits->stencil) { attributes.push_back(EGL_STENCIL_SIZE); attributes.push_back(_traits->stencil); }
757
758        if (_traits->sampleBuffers) { attributes.push_back(EGL_SAMPLE_BUFFERS); attributes.push_back(_traits->sampleBuffers); }
759        if (_traits->samples) { attributes.push_back(EGL_SAMPLES); attributes.push_back(_traits->samples); }
760
761        attributes.push_back(EGL_RENDERABLE_TYPE); attributes.push_back(OSG_EGL_OPENGL_TARGET_BIT);
762
763        attributes.push_back(EGL_NONE);
764        attributes.push_back(EGL_NONE);
765
766        int numConfigs;
767        if (!eglChooseConfig(_eglDisplay, &(attributes.front()), &eglConfig, 1, &numConfigs) || (numConfigs != 1))
768        {
769            OSG_NOTICE<<"GraphicsWindowX11::init() - eglChooseConfig() failed."<<std::endl;
770            XCloseDisplay( _display );
771            _valid = false;
772            _display = 0;
773            return;
774        }
775
776
777        _eglSurface = eglCreateWindowSurface(_eglDisplay, eglConfig, (EGLNativeWindowType)_window, NULL);
778        if (_eglSurface == EGL_NO_SURFACE)
779        {
780            OSG_NOTICE<<"GraphicsWindowX11::init() - eglCreateWindowSurface(..) failed."<<std::endl;
781            XCloseDisplay( _display );
782            _valid = false;
783            _display = 0;
784            return;
785        }
786
787        #if defined(OSG_GLES1_AVAILABLE)
788            EGLint* contextAttribs = 0;
789        #else
790            EGLint contextAttribs[] = {
791                 EGL_CONTEXT_CLIENT_VERSION,
792                2,
793                EGL_NONE
794            };
795        #endif
796
797        _context = eglCreateContext(_eglDisplay, eglConfig, sharedContext, contextAttribs);
798        if (_context == EGL_NO_CONTEXT)
799        {
800            OSG_NOTICE<<"GraphicsWindowX11::init() - eglCreateContext(..) failed."<<std::endl;
801            XCloseDisplay( _display );
802            _valid = false;
803            _display = 0;
804            return;
805        }
806
807        _initialized = true;
808
809        checkEGLError("after eglCreateContext()");
810
811    #else
812
813        _context = glXCreateContext( _display, _visualInfo, sharedContext, True );
814
815        if (!_context)
816        {
817            OSG_NOTICE<<"Error: Unable to create OpenGL graphics context."<<std::endl;
818            XCloseDisplay( _display );
819            _display = 0;
820            _valid = false;
821            return;
822        }
823
824        _initialized = _ownsWindow ? createWindow() : setWindow(windowHandle);
825        _valid = _initialized;
826
827    #endif
828
829    if (_valid == false)
830    {
831        if (_display)
832        {
833            XCloseDisplay( _display );
834            _display = 0;
835        }
836
837        if (_eventDisplay)
838        {
839            XCloseDisplay( _eventDisplay );
840            _eventDisplay = 0;
841        }
842    }
843
844
845
846}
847
848bool GraphicsWindowX11::createWindow()
849{
850    unsigned int screen = _traits->screenNum;
851
852    _eventDisplay = XOpenDisplay(_traits->displayName().c_str());
853
854    _parent = RootWindow( _display, screen );
855
856    XWindowAttributes watt;
857    XGetWindowAttributes( _display, _parent, &watt );
858    // unsigned int parentWindowHeight = watt.height;
859
860    XSetWindowAttributes swatt;
861    swatt.colormap = XCreateColormap( _display, _parent, _visualInfo->visual, AllocNone);
862    //swatt.colormap = DefaultColormap( _dpy, 10 );
863    swatt.background_pixel = 0;
864    swatt.border_pixel = 0;
865    swatt.event_mask =  0;
866    unsigned long mask = CWBackPixel | CWBorderPixel | CWEventMask | CWColormap;
867
868    if (_traits->overrideRedirect)
869    {
870        swatt.override_redirect = true;
871        mask |= CWOverrideRedirect;
872
873        OSG_INFO<<"Setting override redirect"<<std::endl;
874    }
875
876
877    osg::GraphicsContext::WindowingSystemInterface *wsi = osg::GraphicsContext::getWindowingSystemInterface();
878    if (wsi == NULL) {
879    OSG_NOTICE << "Error, no WindowSystemInterface available, cannot toggle window fullscreen." << std::endl;
880    return false;
881    }
882
883    int x = _traits->x;
884    int y = _traits->y;
885    int width = _traits->width;
886    int height = _traits->height;
887
888
889    unsigned int screenWidth;
890    unsigned int screenHeight;
891    wsi->getScreenResolution(*_traits, screenWidth, screenHeight);
892
893    bool doFullSceenWorkAround = false;
894    bool isFullScreen = x == 0 && y == 0 && width == (int)screenWidth && height == (int)screenHeight && !_traits->windowDecoration;
895    if (isFullScreen && !_traits->overrideRedirect)
896    {
897        // follows is hack to get around problems with toggling off full screen with modern X11 window
898        // managers that try to be too clever when toggling off full screen and ignore the window size
899        // calls made by the OSG when the initial window size is full screen.
900
901        Atom netWMStateAtom = XInternAtom(_display, "_NET_WM_STATE", True);
902        Atom netWMStateFullscreenAtom = XInternAtom(_display, "_NET_WM_STATE_FULLSCREEN", True);
903
904        // we have a modern X11 server so assume we need the do the full screen hack.
905        if (netWMStateAtom != None && netWMStateFullscreenAtom != None)
906        {
907            // artifically reduce the initial window size so that the windowing
908            // system has a size to go back to when toggling off full screen,
909            // we don't have to worry about the window being initially smaller as the
910            // setWindowDecoration(..) implementation with enable full screen for us
911            x = width/4;
912            y = height/4;
913            width /= 2;
914            height /= 2;
915
916            doFullSceenWorkAround = true;
917        }
918    }
919
920    _window = XCreateWindow( _display, _parent,
921                             x,
922                             y,
923                             width, height, 0,
924                             _visualInfo->depth, InputOutput,
925                             _visualInfo->visual, mask, &swatt );
926
927    if (!_window)
928    {
929        OSG_NOTICE<<"Error: Unable to create Window."<<std::endl;
930        _context = 0;
931        return false;
932    }
933
934
935    // Give window a class so that user preferences can be saved in the resource database.
936    XClassHint clH;
937    clH.res_name = (char *)"OSG";
938    clH.res_class = (char *)"osgViewer";
939    XSetClassHint( _display, _window, &clH);
940
941    // This positions the window at _windowX, _windowY
942    XSizeHints sh;
943    sh.flags = 0;
944    sh.flags |= USSize;
945    sh.flags &= 0x7;
946    sh.flags |= USPosition;
947    sh.flags &= 0xB;
948    sh.x = _traits->x;
949    sh.y = _traits->y;
950    sh.width  = _traits->width;
951    sh.height = _traits->height;
952    XSetStandardProperties( _display, _window, _traits->windowName.c_str(), _traits->windowName.c_str(), None, 0, 0, &sh);
953
954    setWindowDecoration(_traits->windowDecoration);
955
956
957    useCursor(_traits->useCursor);
958
959    _deleteWindow = XInternAtom (_display, "WM_DELETE_WINDOW", False);
960    XSetWMProtocols(_display, _window, &_deleteWindow, 1);
961
962
963    XFlush( _display );
964    XSync( _display, 0 );
965
966    // now update the window dimensions to account for any size changes made by the window manager,
967    XGetWindowAttributes( _display, _window, &watt );
968
969    if (_traits->x != watt.x || _traits->y != watt.y
970        ||_traits->width != watt.width || _traits->height != watt.height)
971    {
972
973        if (doFullSceenWorkAround)
974        {
975            OSG_INFO<<"Full Screen failed, resizing manually"<<std::endl;
976            XMoveResizeWindow(_display, _window, _traits->x, _traits->y, _traits->width, _traits->height);
977
978            XFlush(_display);
979            XSync(_display, 0);
980
981            XGetWindowAttributes( _display, _window, &watt );
982        }
983
984        resized( watt.x, watt.y, watt.width, watt.height );
985    }
986
987    //OSG_NOTICE<<"After sync apply.x = "<<watt.x<<" watt.y="<<watt.y<<" width="<<watt.width<<" height="<<watt.height<<std::endl;
988
989
990    XSelectInput( _eventDisplay, _window, ExposureMask | StructureNotifyMask |
991                                     KeyPressMask | KeyReleaseMask |
992                                     PointerMotionMask | ButtonPressMask | ButtonReleaseMask |
993                                     KeymapStateMask | FocusChangeMask | EnterWindowMask );
994
995    XFlush( _eventDisplay );
996    XSync( _eventDisplay, 0 );
997    rescanModifierMapping();
998
999    return true;
1000}
1001
1002bool GraphicsWindowX11::setWindow(Window window)
1003{
1004    if (_initialized)
1005    {
1006        OSG_NOTICE << "GraphicsWindowX11::setWindow() - Window already created; it cannot be changed";
1007        return false;
1008    }
1009
1010    if (window==0)
1011    {
1012        OSG_NOTICE << "GraphicsWindowX11::setWindow() - Invalid window handle passed ";
1013        return false;
1014    }
1015
1016    _window = window;
1017    if (_window==0)
1018    {
1019        OSG_NOTICE << "GraphicsWindowX11::setWindow() - Unable to retrieve native window handle";
1020        return false;
1021    }
1022
1023    XWindowAttributes watt;
1024    XGetWindowAttributes( _display, _window, &watt );
1025    _traits->x = watt.x;
1026    _traits->y = watt.y;
1027    _traits->width = watt.width;
1028    _traits->height = watt.height;
1029
1030    _parent = DefaultRootWindow( _display );
1031
1032    //_traits->supportsResize = false;
1033    _traits->windowDecoration = false;
1034
1035    if (_traits->windowName.size()) setWindowName(_traits->windowName);
1036
1037    _eventDisplay = XOpenDisplay(_traits->displayName().c_str());
1038
1039    XFlush( _eventDisplay );
1040    XSync( _eventDisplay, 0 );
1041
1042    return true;
1043}
1044
1045bool GraphicsWindowX11::realizeImplementation()
1046{
1047    if (_realized)
1048    {
1049        OSG_NOTICE<<"GraphicsWindowX11::realizeImplementation() Already realized"<<std::endl;
1050        return true;
1051    }
1052
1053    if (!_initialized) init();
1054
1055    if (!_initialized) return false;
1056
1057    XMapWindow( _display, _window );
1058
1059//    Window temp = _window;
1060//    XSetWMColormapWindows( _display, _window, &temp, 1);
1061
1062    _realized = true;
1063
1064    return true;
1065}
1066
1067bool GraphicsWindowX11::makeCurrentImplementation()
1068{
1069    if (!_realized)
1070    {
1071        OSG_NOTICE<<"Warning: GraphicsWindow not realized, cannot do makeCurrent."<<std::endl;
1072        return false;
1073    }
1074
1075    #ifdef OSG_USE_EGL
1076        bool result = eglMakeCurrent(_eglDisplay, _eglSurface, _eglSurface, _context)==EGL_TRUE;
1077        checkEGLError("after eglMakeCurrent()");
1078        return result;
1079    #else
1080        return glXMakeCurrent( _display, _window, _context )==True;
1081    #endif
1082}
1083
1084bool GraphicsWindowX11::releaseContextImplementation()
1085{
1086    if (!_realized)
1087    {
1088        OSG_NOTICE<<"Warning: GraphicsWindow not realized, cannot do release context."<<std::endl;
1089        return false;
1090    }
1091
1092    #ifdef OSG_USE_EGL
1093        bool result = eglMakeCurrent( _eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT )==EGL_TRUE;
1094        checkEGLError("after eglMakeCurrent() release");
1095        return result;
1096    #else
1097        return glXMakeCurrent( _display, None, NULL )==True;
1098    #endif
1099}
1100
1101
1102void GraphicsWindowX11::closeImplementation()
1103{
1104    // OSG_NOTICE<<"Closing GraphicsWindowX11"<<std::endl;
1105
1106    if (_eventDisplay)
1107    {
1108        XCloseDisplay( _eventDisplay );
1109        _eventDisplay = 0;
1110    }
1111
1112    if (_display)
1113    {
1114        if (_context)
1115        {
1116        #ifdef OSG_USE_EGL
1117            eglDestroyContext( _eglDisplay, _context );
1118        #else
1119            glXDestroyContext( _display, _context );
1120        #endif
1121        }
1122
1123        if (_window && _ownsWindow)
1124        {
1125            XDestroyWindow(_display, _window);
1126        }
1127
1128        XFlush( _display );
1129        XSync( _display,0 );
1130    }
1131
1132    _window = 0;
1133    _parent = 0;
1134    _context = 0;
1135
1136    if (_visualInfo)
1137    {
1138        #ifdef OSG_USE_EGL
1139            delete _visualInfo;
1140        #else
1141            XFree(_visualInfo);
1142        #endif
1143        _visualInfo = 0;
1144    }
1145
1146
1147    if (_display)
1148    {
1149        XCloseDisplay( _display );
1150        _display = 0;
1151    }
1152
1153    _initialized = false;
1154    _realized = false;
1155    _valid = false;
1156}
1157
1158void GraphicsWindowX11::swapBuffersImplementation()
1159{
1160    if (!_realized) return;
1161
1162    // OSG_NOTICE<<"swapBuffersImplementation "<<this<<" "<<OpenThreads::Thread::CurrentThread()<<std::endl;
1163
1164    #ifdef OSG_USE_EGL
1165        eglSwapBuffers( _eglDisplay, _eglSurface );
1166        checkEGLError("after eglSwapBuffers()");
1167    #else
1168#if 0
1169        if (_traits.valid() && _traits->vsync) {
1170
1171            unsigned int counter;
1172            glXGetVideoSyncSGI(&counter);
1173            glXWaitVideoSyncSGI(1, 0, &counter);
1174        }
1175#endif
1176        glXSwapBuffers( _display, _window );
1177    #endif
1178
1179
1180    while( XPending(_display) )
1181    {
1182        XEvent ev;
1183        XNextEvent( _display, &ev );
1184
1185        switch( ev.type )
1186        {
1187            case ClientMessage:
1188            {
1189                if (static_cast<Atom>(ev.xclient.data.l[0]) == _deleteWindow)
1190                {
1191                    OSG_INFO<<"DeleteWindow event received"<<std::endl;
1192                    getEventQueue()->closeWindow();
1193                }
1194            }
1195        }
1196    }
1197}
1198
1199void GraphicsWindowX11::checkEvents()
1200{
1201    if (!_realized) return;
1202
1203    Display* display = _eventDisplay;
1204
1205    double baseTime = _timeOfLastCheckEvents;
1206    double eventTime = baseTime;
1207    double resizeTime = eventTime;
1208    _timeOfLastCheckEvents = getEventQueue()->getTime();
1209    if (baseTime>_timeOfLastCheckEvents) baseTime = _timeOfLastCheckEvents;
1210
1211
1212    // OSG_NOTICE<<"GraphicsWindowX11::checkEvents() : getEventQueue()->getCurrentEventState()->getGraphicsContext()="<<getEventQueue()->getCurrentEventState()->getGraphicsContext()<<std::endl;
1213
1214    int windowX = _traits->x;
1215    int windowY = _traits->y;
1216    int windowWidth = _traits->width;
1217    int windowHeight = _traits->height;
1218
1219    Time firstEventTime = 0;
1220
1221    // OSG_NOTICE<<"Check events"<<std::endl;
1222    while( XPending(display) )
1223    {
1224        XEvent ev;
1225        XNextEvent( display, &ev );
1226
1227        switch( ev.type )
1228        {
1229            case ClientMessage:
1230            {
1231                OSG_NOTICE<<"ClientMessage event received"<<std::endl;
1232                if (static_cast<Atom>(ev.xclient.data.l[0]) == _deleteWindow)
1233                {
1234                    OSG_NOTICE<<"DeleteWindow event received"<<std::endl;
1235                    // FIXME only do if _ownsWindow ?
1236                    getEventQueue()->closeWindow(eventTime);
1237                }
1238                break;
1239            }
1240            case Expose :
1241                OSG_INFO<<"Expose x="<<ev.xexpose.x<<" y="<<ev.xexpose.y<<" width="<<ev.xexpose.width<<", height="<<ev.xexpose.height<<std::endl;
1242                requestRedraw();
1243                break;
1244
1245            case GravityNotify :
1246                OSG_INFO<<"GravityNotify event received"<<std::endl;
1247                break;
1248
1249            case ReparentNotify:
1250                OSG_INFO<<"ReparentNotify event received"<<std::endl;
1251                break;
1252
1253            case DestroyNotify :
1254                OSG_NOTICE<<"DestroyNotify event received"<<std::endl;
1255                _realized =  false;
1256                _valid = false;
1257                break;
1258
1259            case ConfigureNotify :
1260            {
1261                OSG_INFO<<"ConfigureNotify x="<<ev.xconfigure.x<<" y="<<ev.xconfigure.y<<" width="<<ev.xconfigure.width<<", height="<<ev.xconfigure.height<<std::endl;
1262
1263                if (windowX != ev.xconfigure.x ||
1264                    windowY != ev.xconfigure.y ||
1265                    windowWidth != ev.xconfigure.width ||
1266                    windowHeight != ev.xconfigure.height)
1267                {
1268                    resizeTime = eventTime;
1269
1270                    windowX = ev.xconfigure.x;
1271                    windowY = ev.xconfigure.y;
1272                    windowWidth = ev.xconfigure.width;
1273                    windowHeight = ev.xconfigure.height;
1274                }
1275
1276                break;
1277            }
1278
1279            case MapNotify :
1280            {
1281                OSG_INFO<<"MapNotify"<<std::endl;
1282                XWindowAttributes watt;
1283                do
1284                    XGetWindowAttributes(display, _window, &watt );
1285                while( watt.map_state != IsViewable );
1286
1287                OSG_INFO<<"MapNotify x="<<watt.x<<" y="<<watt.y<<" width="<<watt.width<<", height="<<watt.height<<std::endl;
1288
1289                if (windowWidth != watt.width || windowHeight != watt.height)
1290                {
1291                    resizeTime = eventTime;
1292
1293                    windowWidth = watt.width;
1294                    windowHeight = watt.height;
1295                }
1296
1297                break;
1298            }
1299
1300            case FocusIn :
1301                OSG_INFO<<"FocusIn event received"<<std::endl;
1302                flushKeyEvents();
1303                break;
1304
1305            case UnmapNotify :
1306            case FocusOut :
1307            {
1308                OSG_INFO<<"FocusOut/UnmapNotify event received"<<std::endl;
1309                if (ev.type == FocusOut && ev.xfocus.mode != NotifyNormal) break;
1310
1311                char modMap[32];
1312                getModifierMap(modMap);
1313
1314                // release normal (non-modifier) keys
1315                for (unsigned int key = 8; key < 256; key++)
1316                {
1317                    bool isModifier = keyMapGetKey(modMap, key);
1318                    if (!isModifier) forceKey(key, eventTime, false);
1319                }
1320
1321                // release modifier keys
1322                for (unsigned int key = 8; key < 256; key++)
1323                {
1324                    bool isModifier = keyMapGetKey(modMap, key);
1325                    if (isModifier) forceKey(key, eventTime, false);
1326                }
1327                break;
1328            }
1329
1330            case EnterNotify :
1331                OSG_INFO<<"EnterNotify event received"<<std::endl;
1332                _modifierState = ev.xcrossing.state;
1333                syncLocks();
1334                break;
1335
1336            case KeymapNotify :
1337            {
1338                OSG_INFO<<"KeymapNotify event received"<<std::endl;
1339
1340                // KeymapNotify is guaranteed to directly follow either a FocusIn or
1341                // an EnterNotify event. We are only interested in the FocusIn case.
1342                if (_lastEventType != FocusIn) break;
1343
1344                char modMap[32];
1345                getModifierMap(modMap);
1346                syncLocks();
1347
1348                char keyMap[32];
1349                XQueryKeymap(_eventDisplay, keyMap);
1350
1351                // release normal (non-modifier) keys
1352                for (unsigned int key = 8; key < 256; key++)
1353                {
1354                    bool isModifier = keyMapGetKey(modMap, key);
1355                    if (isModifier) continue;
1356                    bool isPressed = keyMapGetKey(keyMap, key);
1357                    if (!isPressed) forceKey(key, eventTime, false);
1358                }
1359
1360                // press/release modifier keys
1361                for (unsigned int key = 8; key < 256; key++)
1362                {
1363                    bool isModifier = keyMapGetKey(modMap, key);
1364                    if (!isModifier) continue;
1365                    bool isPressed = keyMapGetKey(keyMap, key);
1366                    forceKey(key, eventTime, isPressed);
1367                }
1368
1369                // press normal keys
1370                for (unsigned int key = 8; key < 256; key++)
1371                {
1372                    bool isModifier = keyMapGetKey(modMap, key);
1373                    if (isModifier) continue;
1374                    bool isPressed = keyMapGetKey(keyMap, key);
1375                    if (isPressed) forceKey(key, eventTime, true);
1376                }
1377                break;
1378            }
1379
1380            case MappingNotify :
1381                OSG_INFO<<"MappingNotify event received"<<std::endl;
1382                if (ev.xmapping.request == MappingModifier) rescanModifierMapping();
1383                break;
1384
1385            case MotionNotify :
1386            {
1387                if (firstEventTime==0) firstEventTime = ev.xmotion.time;
1388                Time relativeTime = ev.xmotion.time - firstEventTime;
1389                eventTime = baseTime + static_cast<double>(relativeTime)*0.001;
1390
1391                int  wx, wy;
1392                Window win = 0L;
1393                if( ev.xmotion.same_screen )
1394                {
1395                    wx = ev.xmotion.x;
1396                    wy = ev.xmotion.y;
1397                }
1398                else
1399                {
1400                    // the mouse in on another screen so need to compute the
1401                    // coordinates of the mouse position relative to an absolute position
1402                    // then take away the position of the original window/screen to get
1403                    // the coordinates relative to the original position.
1404                    Window root;
1405                    int rx, ry;
1406                    unsigned int buttons;
1407
1408                    int screenOrigin_x = 0;
1409                    int screenOrigin_y = 0;
1410                    int i;
1411                    for(i= 0; i < ScreenCount(display); i++ )
1412                    {
1413                        if( XQueryPointer( display, RootWindow(display, i),
1414                              &root, &win, &rx, &ry, &wx, &wy, &buttons) )
1415                        {
1416                            break;
1417                        }
1418
1419                        screenOrigin_x += DisplayWidth(display, i);
1420                    }
1421
1422                    for(i= 0; i < static_cast<int>(_traits->screenNum); i++ )
1423                    {
1424                        screenOrigin_x -= DisplayWidth(display, i);
1425                    }
1426
1427                    int dest_x_return, dest_y_return;
1428                    Window child_return;
1429                    XTranslateCoordinates(display, _window, _parent, 0, 0, &dest_x_return, &dest_y_return, &child_return);
1430
1431                    wx += (screenOrigin_x - dest_x_return);
1432                    wy += (screenOrigin_y - dest_y_return);
1433                }
1434
1435
1436                float mx = wx;
1437                float my = wy;
1438                transformMouseXY(mx, my);
1439                getEventQueue()->mouseMotion(mx, my, eventTime);
1440
1441                // OSG_NOTICE<<"MotionNotify wx="<<wx<<" wy="<<wy<<" mx="<<mx<<" my="<<my<<std::endl;
1442
1443                break;
1444            }
1445
1446            case ButtonPress :
1447            {
1448                if (firstEventTime==0) firstEventTime = ev.xmotion.time;
1449                Time relativeTime = ev.xmotion.time - firstEventTime;
1450                eventTime = baseTime + static_cast<double>(relativeTime)*0.001;
1451
1452                if( ev.xbutton.button == Button4 )
1453                {
1454                    getEventQueue()->mouseScroll(osgGA::GUIEventAdapter::SCROLL_UP, eventTime);
1455                }
1456                else if( ev.xbutton.button == Button5)
1457                {
1458                    getEventQueue()->mouseScroll(osgGA::GUIEventAdapter::SCROLL_DOWN, eventTime);
1459                }
1460                else
1461                {
1462                    float mx = ev.xbutton.x;
1463                    float my = ev.xmotion.y;
1464                    transformMouseXY(mx, my);
1465                    getEventQueue()->mouseButtonPress(mx, my, ev.xbutton.button, eventTime);
1466                }
1467                break;
1468            }
1469
1470            case ButtonRelease :
1471            {
1472                if (firstEventTime==0) firstEventTime = ev.xmotion.time;
1473                Time relativeTime = ev.xmotion.time - firstEventTime;
1474                eventTime = baseTime + static_cast<double>(relativeTime)*0.001;
1475
1476                if( ev.xbutton.button == Button4 )
1477                {
1478                    getEventQueue()->mouseScroll(osgGA::GUIEventAdapter::SCROLL_UP, eventTime);
1479                }
1480                else if( ev.xbutton.button == Button5)
1481                {
1482                    getEventQueue()->mouseScroll(osgGA::GUIEventAdapter::SCROLL_DOWN, eventTime);
1483                }
1484                else
1485                {
1486                    float mx = ev.xbutton.x;
1487                    float my = ev.xmotion.y;
1488                    transformMouseXY(mx, my);
1489                    getEventQueue()->mouseButtonRelease(mx, my, ev.xbutton.button, eventTime);
1490                }
1491                break;
1492            }
1493
1494            case KeyPress:
1495            {
1496                if (firstEventTime==0) firstEventTime = ev.xmotion.time;
1497                Time relativeTime = ev.xmotion.time - firstEventTime;
1498                eventTime = baseTime + static_cast<double>(relativeTime)*0.001;
1499
1500                _modifierState = ev.xkey.state;
1501                keyMapSetKey(_keyMap, ev.xkey.keycode);
1502                int keySymbol = 0;
1503                int unmodifiedKeySymbol = 0;
1504                adaptKey(ev.xkey, keySymbol, unmodifiedKeySymbol);
1505
1506                getEventQueue()->keyPress(keySymbol, eventTime, unmodifiedKeySymbol);
1507                break;
1508            }
1509
1510            case KeyRelease:
1511            {
1512                if (firstEventTime==0) firstEventTime = ev.xmotion.time;
1513                Time relativeTime = ev.xmotion.time - firstEventTime;
1514                eventTime = baseTime + static_cast<double>(relativeTime)*0.001;
1515#if 1
1516                // Check for following KeyPress events and see if
1517                // the pair are the result of auto-repeat. If so, drop
1518                // this one on the floor, to be consistent with
1519                // Windows and Mac ports. The idea comes from libSDL sources.
1520                XEvent nextev;
1521                if (XPending(display))
1522                {
1523                    XPeekEvent(display, &nextev);
1524                    if ((nextev.type == KeyPress)
1525                        && (nextev.xkey.keycode == ev.xkey.keycode)
1526                        && (nextev.xmotion.time - ev.xmotion.time < 2))
1527                    {
1528                        break;
1529                    }
1530                }
1531#endif
1532                _modifierState = ev.xkey.state;
1533                keyMapClearKey(_keyMap, ev.xkey.keycode);
1534                int keySymbol = 0;
1535                int unmodifiedKeySymbol = 0;
1536                adaptKey(ev.xkey, keySymbol, unmodifiedKeySymbol);
1537
1538                getEventQueue()->keyRelease(keySymbol, eventTime, unmodifiedKeySymbol);
1539                break;
1540            }
1541
1542            default:
1543                OSG_NOTICE<<"Other event "<<ev.type<<std::endl;
1544                break;
1545
1546        }
1547        _lastEventType = ev.type;
1548    }
1549
1550    // send window resize event if window position or size was changed
1551    if (windowX != _traits->x ||
1552        windowY != _traits->y ||
1553        windowWidth != _traits->width ||
1554        windowHeight != _traits->height)
1555    {
1556        resized(windowX, windowY, windowWidth, windowHeight);
1557        getEventQueue()->windowResize(windowX, windowY, windowWidth, windowHeight, resizeTime);
1558
1559        // request window repaint if window size was changed
1560        if (windowWidth != _traits->width ||
1561            windowHeight != _traits->height)
1562        {
1563            requestRedraw();
1564        }
1565    }
1566}
1567
1568void GraphicsWindowX11::grabFocus()
1569{
1570    Display* display = getDisplayToUse();
1571
1572    XSetInputFocus( display, _window, RevertToNone, CurrentTime );
1573    XFlush(display);
1574    XSync(display,0);
1575}
1576
1577void GraphicsWindowX11::grabFocusIfPointerInWindow()
1578{
1579    Window win, root;
1580    int wx, wy, rx, ry;
1581    unsigned int buttons;
1582
1583    Display* display = getDisplayToUse();
1584
1585    if( XQueryPointer( display, _window,
1586          &root, &win, &rx, &ry, &wx, &wy, &buttons))
1587    {
1588#if 0
1589        if (wx>=0 && wx<_traits->width &&
1590            wy>=0 && wy<_traits->height)
1591        {
1592            grabFocus();
1593        }
1594#else
1595        grabFocus();
1596#endif
1597    }
1598}
1599
1600void GraphicsWindowX11::transformMouseXY(float& x, float& y)
1601{
1602    if (getEventQueue()->getUseFixedMouseInputRange())
1603    {
1604        osgGA::GUIEventAdapter* eventState = getEventQueue()->getCurrentEventState();
1605        x = eventState->getXmin() + (eventState->getXmax()-eventState->getXmin())*x/float(_traits->width);
1606        y = eventState->getYmin() + (eventState->getYmax()-eventState->getYmin())*y/float(_traits->height);
1607    }
1608}
1609
1610void GraphicsWindowX11::adaptKey(XKeyEvent& keyevent, int& keySymbol, int& unmodifiedKeySymbol)
1611{
1612    unsigned char buffer_return[32];
1613    int bytes_buffer = 32;
1614    KeySym keysym_return;
1615
1616    int numChars = XLookupString(&keyevent, reinterpret_cast<char*>(buffer_return), bytes_buffer, &keysym_return, NULL);
1617    keySymbol = keysym_return;
1618    if (!remapExtendedX11Key(keySymbol) && (numChars==1))
1619    {
1620        keySymbol = buffer_return[0];
1621    }
1622
1623    unmodifiedKeySymbol = XkbKeycodeToKeysym(keyevent.display, keyevent.keycode, 0, 0);
1624}
1625
1626// Function to inject artificial key presses/releases.
1627void GraphicsWindowX11::forceKey(int key, double time, bool state)
1628{
1629    if (!(state ^ keyMapGetKey(_keyMap, key))) return; // already pressed/released
1630
1631    XKeyEvent event;
1632    event.serial = 0;
1633    event.send_event = True;
1634    event.display = _eventDisplay;
1635    event.window = _window;
1636    event.subwindow = 0;
1637    event.time = 0;
1638    event.x = 0;
1639    event.y = 0;
1640    event.x_root = 0;
1641    event.y_root = 0;
1642    event.state = getModifierMask() | (_modifierState & (LockMask | _numLockMask));
1643    event.keycode = key;
1644    event.same_screen = True;
1645
1646    int keySymbol = 0;
1647    int unmodifiedKeySymbol = 0;
1648    if (state)
1649    {
1650        event.type = KeyPress;
1651        adaptKey(event, keySymbol, unmodifiedKeySymbol);
1652        getEventQueue()->keyPress(keySymbol, time, unmodifiedKeySymbol);
1653        keyMapSetKey(_keyMap, key);
1654    }
1655    else
1656    {
1657        event.type = KeyRelease;
1658        adaptKey(event, keySymbol, unmodifiedKeySymbol);
1659        getEventQueue()->keyRelease(keySymbol, time, unmodifiedKeySymbol);
1660        keyMapClearKey(_keyMap, key);
1661    }
1662}
1663
1664void GraphicsWindowX11::syncLocks()
1665{
1666    unsigned int mask = getEventQueue()->getCurrentEventState()->getModKeyMask();
1667
1668    if (_modifierState & LockMask)
1669        mask |= osgGA::GUIEventAdapter::MODKEY_CAPS_LOCK;
1670    else
1671        mask &= ~osgGA::GUIEventAdapter::MODKEY_CAPS_LOCK;
1672
1673    if (_modifierState & _numLockMask)
1674        mask |= osgGA::GUIEventAdapter::MODKEY_NUM_LOCK;
1675    else
1676        mask &= ~osgGA::GUIEventAdapter::MODKEY_NUM_LOCK;
1677
1678    getEventQueue()->getCurrentEventState()->setModKeyMask(mask);
1679}
1680
1681void GraphicsWindowX11::rescanModifierMapping()
1682{
1683    XModifierKeymap *mkm = XGetModifierMapping(_eventDisplay);
1684    KeyCode *m = mkm->modifiermap;
1685    KeyCode numlock = XKeysymToKeycode(_eventDisplay, XK_Num_Lock);
1686    _numLockMask = 0;
1687    for (int i = 0; i < mkm->max_keypermod * 8; i++, m++)
1688    {
1689        if (*m == numlock)
1690        {
1691            _numLockMask = 1 << (i / mkm->max_keypermod);
1692            break;
1693        }
1694    }
1695    XFree(mkm->modifiermap);
1696    XFree(mkm);
1697}
1698
1699void GraphicsWindowX11::flushKeyEvents()
1700{
1701    XEvent e;
1702    while (XCheckMaskEvent(_eventDisplay, KeyPressMask|KeyReleaseMask, &e))
1703        continue;
1704}
1705
1706// Returns char[32] keymap with bits for every modifier key set.
1707void GraphicsWindowX11::getModifierMap(char* keymap) const
1708{
1709    memset(keymap, 0, 32);
1710    XModifierKeymap *mkm = XGetModifierMapping(_eventDisplay);
1711    KeyCode *m = mkm->modifiermap;
1712    for (int i = 0; i < mkm->max_keypermod * 8; i++, m++)
1713    {
1714        if (*m) keyMapSetKey(keymap, *m);
1715    }
1716    XFree(mkm->modifiermap);
1717    XFree(mkm);
1718}
1719
1720int GraphicsWindowX11::getModifierMask() const
1721{
1722    int mask = 0;
1723    XModifierKeymap *mkm = XGetModifierMapping(_eventDisplay);
1724    for (int i = 0; i < mkm->max_keypermod * 8; i++)
1725    {
1726        unsigned int key = mkm->modifiermap[i];
1727        if (key && keyMapGetKey(_keyMap, key))
1728        {
1729            mask |= 1 << (i / mkm->max_keypermod);
1730        }
1731    }
1732    XFree(mkm->modifiermap);
1733    XFree(mkm);
1734    return mask;
1735}
1736
1737void GraphicsWindowX11::requestWarpPointer(float x,float y)
1738{
1739    if (!_realized)
1740    {
1741        OSG_INFO<<"GraphicsWindowX11::requestWarpPointer() - Window not realized; cannot warp pointer, screenNum="<< _traits->screenNum<<std::endl;
1742        return;
1743    }
1744
1745    Display* display = _eventDisplay; // getDisplayToUse();
1746
1747    XWarpPointer( display,
1748                  None,
1749                  _window,
1750                  0, 0, 0, 0,
1751                  static_cast<int>(x), static_cast<int>(y) );
1752
1753    XFlush(display);
1754    XSync(display, 0);
1755
1756    getEventQueue()->mouseWarped(x,y);
1757}
1758
1759extern "C"
1760{
1761
1762typedef int (*X11ErrorHandler)(Display*, XErrorEvent*);
1763
1764int X11ErrorHandling(Display* display, XErrorEvent* event)
1765{
1766    OSG_NOTICE<<"Got an X11ErrorHandling call display="<<display<<" event="<<event<<std::endl;
1767
1768    char buffer[256];
1769    XGetErrorText( display, event->error_code, buffer, 256);
1770
1771    OSG_NOTICE << buffer << std::endl;
1772    OSG_NOTICE << "Major opcode: " << (int)event->request_code << std::endl;
1773    OSG_NOTICE << "Minor opcode: " << (int)event->minor_code << std::endl;
1774    OSG_NOTICE << "Error code: " << (int)event->error_code << std::endl;
1775    OSG_NOTICE << "Request serial: " << event->serial << std::endl;
1776    OSG_NOTICE << "Current serial: " << NextRequest( display ) - 1 << std::endl;
1777
1778    switch( event->error_code )
1779    {
1780        case BadValue:
1781            OSG_NOTICE << "  Value: " << event->resourceid << std::endl;
1782            break;
1783
1784        case BadAtom:
1785            OSG_NOTICE << "  AtomID: " << event->resourceid << std::endl;
1786            break;
1787
1788        default:
1789            OSG_NOTICE << "  ResourceID: " << event->resourceid << std::endl;
1790            break;
1791    }
1792    return 0;
1793}
1794
1795}
1796
1797class X11WindowingSystemInterface : public osg::GraphicsContext::WindowingSystemInterface
1798{
1799#ifdef OSGVIEWER_USE_XRANDR
1800    // TODO: Investigate whether or not Robert thinks we should store/restore the original
1801    // resolution in the destructor; I'm not sure the other ones do this, and it may be the
1802    // responsibility of the user.
1803    bool _setScreen(const osg::GraphicsContext::ScreenIdentifier& si, unsigned int width, unsigned int height, unsigned int colorDepth, double rate) {
1804        if (colorDepth>0)
1805            OSG_NOTICE << "X11WindowingSystemInterface::_setScreen() is not fully implemented (missing depth)."<<std::endl;
1806
1807        Display* display = XOpenDisplay(si.displayName().c_str());
1808
1809        if(display)
1810        {
1811            XRRScreenConfiguration* sc = XRRGetScreenInfo(display, RootWindow(display, si.screenNum));
1812
1813            if(!sc)
1814            {
1815                OSG_NOTICE << "Unable to create XRRScreenConfiguration on display \"" << XDisplayName(si.displayName().c_str()) << "\"."<<std::endl;
1816                return false;
1817            }
1818
1819            int      numScreens = 0;
1820            int      numRates   = 0;
1821            Rotation currentRot = 0;
1822            bool     okay       = false;
1823
1824            XRRConfigRotations(sc, &currentRot);
1825
1826            // If the width or height are zero, use our defaults.
1827            if(!width || !height)
1828            {
1829                getScreenResolution(si, width, height);
1830            }
1831
1832            // If this somehow fails, okay will still be false, no iteration will take place below,
1833            // and the sc pointer will still be freed later on.
1834            XRRScreenSize* ss = XRRConfigSizes(sc, &numScreens);
1835
1836            for(int i = 0; i < numScreens; i++)
1837            {
1838                if(ss[i].width == static_cast<int>(width) && ss[i].height == static_cast<int>(height))
1839                {
1840                    short* rates     = XRRConfigRates(sc, i, &numRates);
1841                    bool   rateFound = false;
1842
1843                    // Search for our rate in the list of acceptable rates given to us by Xrandr.
1844                    // If it's not found, rateFound will still be false and the call will never
1845                    // be made to XRRSetScreenConfigAndRate since the rate will be invalid.
1846                    for(int r = 0; r < numRates; r++)
1847                    {
1848                        if(rates[r] == static_cast<short>(rate))
1849                        {
1850                            rateFound = true;
1851                            break;
1852                        }
1853                    }
1854
1855                    if(rate > 0.0f && !rateFound)
1856                    {
1857                        OSG_NOTICE << "Unable to find valid refresh rate " << rate << " on display \"" << XDisplayName(si.displayName().c_str()) << "\"."<<std::endl;
1858                    }
1859                    else if(XRRSetScreenConfigAndRate(display, sc, DefaultRootWindow(display), i, currentRot, static_cast<short>(rate), CurrentTime) != RRSetConfigSuccess)
1860                    {
1861                        OSG_NOTICE << "Unable to set resolution to " << width << "x" << height << " on display \"" << XDisplayName(si.displayName().c_str()) << "\"."<<std::endl;
1862                    }
1863                    else
1864                    {
1865                        okay = true;
1866                        break;
1867                    }
1868                }
1869            }
1870
1871            XRRFreeScreenConfigInfo(sc);
1872
1873            return okay;
1874        }
1875        else
1876        {
1877            OSG_NOTICE << "Unable to open display \"" << XDisplayName(si.displayName().c_str()) << "\"."<<std::endl;
1878            return false;
1879        }
1880    }
1881#endif
1882
1883protected:
1884    bool _errorHandlerSet;
1885
1886
1887public:
1888    X11WindowingSystemInterface()
1889    {
1890        OSG_INFO<<"X11WindowingSystemInterface()"<<std::endl;
1891
1892
1893        // Install an X11 error handler, if the application has not already done so.
1894
1895        // Set default handler, and get pointer to current handler.
1896        X11ErrorHandler currentHandler = XSetErrorHandler(NULL);
1897
1898        // Set our handler, and get pointer to default handler.
1899        X11ErrorHandler defHandler = XSetErrorHandler(X11ErrorHandling);
1900
1901        if ( currentHandler == defHandler )
1902        {
1903            // No application error handler, use ours.
1904            // OSG_INFO<<"Set osgViewer X11 error handler"<<std::endl;
1905            _errorHandlerSet = 1;
1906        }
1907        else
1908        {
1909            // Application error handler exists, leave it set.
1910            // OSG_INFO<<"Existing application X11 error handler set"<<std::endl;
1911            _errorHandlerSet = 0;
1912            XSetErrorHandler(currentHandler);
1913        }
1914
1915#if 0
1916        if (XInitThreads() == 0)
1917        {
1918            OSG_NOTICE << "Error: XInitThreads() failed. Aborting." << std::endl;
1919            exit(1);
1920        }
1921        else
1922        {
1923            OSG_INFO << "X11WindowingSystemInterface, xInitThreads() multi-threaded X support initialized.\n";
1924        }
1925#endif
1926
1927    }
1928
1929
1930
1931    ~X11WindowingSystemInterface()
1932    {
1933        if (osg::Referenced::getDeleteHandler())
1934        {
1935            osg::Referenced::getDeleteHandler()->setNumFramesToRetainObjects(0);
1936            osg::Referenced::getDeleteHandler()->flushAll();
1937        }
1938
1939        //OSG_NOTICE<<"~X11WindowingSystemInterface()"<<std::endl;
1940
1941        // Unset our X11 error handler, providing the application has not replaced it.
1942
1943        if ( _errorHandlerSet )
1944        {
1945            X11ErrorHandler currentHandler = XSetErrorHandler(NULL);
1946            if ( currentHandler == X11ErrorHandling )
1947            {
1948                // OSG_INFO<<"osgViewer X11 error handler removed"<<std::endl;
1949            }
1950            else
1951            {
1952                // Not our error handler, leave it set.
1953                // OSG_INFO<<"Application X11 error handler left"<<std::endl;
1954                XSetErrorHandler(currentHandler);
1955            }
1956        }
1957    }
1958
1959    virtual unsigned int getNumScreens(const osg::GraphicsContext::ScreenIdentifier& si)
1960    {
1961        Display* display = XOpenDisplay(si.displayName().c_str());
1962        if(display)
1963        {
1964            unsigned int numScreens = ScreenCount(display);
1965            XCloseDisplay(display);
1966
1967            return numScreens;
1968        }
1969        else
1970        {
1971            OSG_NOTICE << "A Unable to open display \"" << XDisplayName(si.displayName().c_str()) << "\""<<std::endl;
1972            return 0;
1973        }
1974    }
1975
1976    bool supportsRandr(Display* display) const
1977    {
1978#ifdef OSGVIEWER_USE_XRANDR
1979        int event_basep;
1980        int error_basep;
1981        bool supports_randr = XRRQueryExtension( display, &event_basep, &error_basep );
1982        if( supports_randr )
1983        {
1984            int major, minor;
1985            XRRQueryVersion( display, &major, &minor );
1986            return ( major > 1 || ( major == 1 && minor >= 2 ) );
1987        }
1988#endif
1989        return false;
1990    }
1991
1992    virtual void getScreenSettings(const osg::GraphicsContext::ScreenIdentifier& si, osg::GraphicsContext::ScreenSettings & resolution )
1993    {
1994        Display* display = XOpenDisplay(si.displayName().c_str());
1995        if(display)
1996        {
1997            resolution.width = DisplayWidth(display, si.screenNum);
1998            resolution.height = DisplayHeight(display, si.screenNum);
1999            resolution.colorDepth = DefaultDepth(display, si.screenNum);
2000
2001            resolution.refreshRate = 0;            // Missing call. Need a X11 expert.
2002
2003
2004#ifdef OSGVIEWER_USE_XRANDR
2005           if (supportsRandr(display))
2006           {
2007
2008               XRRScreenConfiguration* screenConfig = XRRGetScreenInfo ( display, RootWindow(display, si.screenNum) );
2009
2010               resolution.refreshRate = XRRConfigCurrentRate ( screenConfig );
2011
2012               XRRFreeScreenConfigInfo( screenConfig );
2013           }
2014#endif
2015
2016
2017            XCloseDisplay(display);
2018        }
2019        else
2020        {
2021            OSG_NOTICE << "Unable to open display \"" << XDisplayName(si.displayName().c_str()) << "\"."<<std::endl;
2022            resolution.width = 0;
2023            resolution.height = 0;
2024            resolution.colorDepth = 0;
2025            resolution.refreshRate = 0;
2026        }
2027    }
2028
2029    virtual bool setScreenSettings(const osg::GraphicsContext::ScreenIdentifier& si, const osg::GraphicsContext::ScreenSettings & resolution )
2030    {
2031#ifdef OSGVIEWER_USE_XRANDR
2032        _setScreen(si, resolution.width, resolution.height, resolution.colorDepth, resolution.refreshRate);
2033#else
2034        OSG_NOTICE << "You must build osgViewer with Xrandr 1.2 or higher for setScreenSettings support!" << std::endl;
2035#endif
2036        return false;
2037    }
2038
2039    virtual void enumerateScreenSettings(const osg::GraphicsContext::ScreenIdentifier& si, osg::GraphicsContext::ScreenSettingsList & resolutionList)
2040    {
2041        resolutionList.clear();
2042
2043        Display* display = XOpenDisplay(si.displayName().c_str());
2044        if(display)
2045        {
2046#ifdef OSGVIEWER_USE_XRANDR
2047            int defaultDepth = DefaultDepth(display, si.screenNum);
2048
2049            if (supportsRandr(display))
2050            {
2051                int nsizes = 0;
2052                XRRScreenSize * screenSizes = XRRSizes(display, si.screenNum, &nsizes);
2053                if (screenSizes && nsizes>0)
2054                {
2055                    for(int i=0; i<nsizes; ++i)
2056                    {
2057                        OSG_INFO<<"Screen size "<<screenSizes[i].width<<" "<<screenSizes[i].height<<" "<<screenSizes[i].mwidth<<" "<<screenSizes[i].mheight<<std::endl;
2058
2059                        int nrates;
2060                        short * rates = XRRRates (display, si.screenNum, i, &nrates);
2061                        if (rates && nrates>0)
2062                        {
2063                            for(int j=0; j<nrates; ++j)
2064                            {
2065                                OSG_INFO<<"   rates "<<rates[j]<<std::endl;
2066
2067                                resolutionList.push_back(osg::GraphicsContext::ScreenSettings(
2068                                    screenSizes[i].width,
2069                                    screenSizes[i].height,
2070                                    double(rates[j]),
2071                                    defaultDepth));
2072                            }
2073                        }
2074                        else
2075                        {
2076                            resolutionList.push_back(osg::GraphicsContext::ScreenSettings(
2077                                screenSizes[i].width,
2078                                screenSizes[i].height,
2079                                0.0,
2080                                defaultDepth));
2081                        }
2082
2083                    }
2084                }
2085            }
2086#endif
2087            XCloseDisplay(display);
2088        }
2089
2090        if (resolutionList.empty())
2091        {
2092            OSG_NOTICE << "X11WindowingSystemInterface::enumerateScreenSettings() not supported." << std::endl;
2093        }
2094    }
2095
2096    virtual osg::GraphicsContext* createGraphicsContext(osg::GraphicsContext::Traits* traits)
2097    {
2098        if (traits->pbuffer)
2099        {
2100#if 1
2101            osg::ref_ptr<osgViewer::PixelBufferX11> pbuffer = new PixelBufferX11(traits);
2102            if (pbuffer->valid()) return pbuffer.release();
2103            else return 0;
2104#else
2105            osg::ref_ptr<osgViewer::GraphicsWindowX11> window = new GraphicsWindowX11(traits);
2106            if (window->valid()) return window.release();
2107            else return 0;
2108#endif
2109        }
2110        else
2111        {
2112            osg::ref_ptr<osgViewer::GraphicsWindowX11> window = new GraphicsWindowX11(traits);
2113            if (window->valid()) return window.release();
2114            else return 0;
2115        }
2116    }
2117
2118};
2119
2120struct RegisterWindowingSystemInterfaceProxy
2121{
2122    RegisterWindowingSystemInterfaceProxy()
2123    {
2124        OSG_INFO<<"RegisterWindowingSystemInterfaceProxy()"<<std::endl;
2125        osg::GraphicsContext::setWindowingSystemInterface(new X11WindowingSystemInterface);
2126    }
2127
2128    ~RegisterWindowingSystemInterfaceProxy()
2129    {
2130        OSG_INFO<<"~RegisterWindowingSystemInterfaceProxy()"<<std::endl;
2131
2132        if (osg::Referenced::getDeleteHandler())
2133        {
2134            osg::Referenced::getDeleteHandler()->setNumFramesToRetainObjects(0);
2135            osg::Referenced::getDeleteHandler()->flushAll();
2136        }
2137
2138        osg::GraphicsContext::setWindowingSystemInterface(0);
2139
2140    }
2141};
2142
2143RegisterWindowingSystemInterfaceProxy createWindowingSystemInterfaceProxy;
2144
2145// declare C entry point for static compilation.
2146extern "C" void graphicswindow_X11(void)
2147{
2148    osg::GraphicsContext::setWindowingSystemInterface(new X11WindowingSystemInterface);
2149}
2150
2151
2152void GraphicsWindowX11::raiseWindow()
2153{
2154    Display* display = getDisplayToUse();
2155    XWindowAttributes winAttrib;
2156
2157    Window root_return, parent_return, *children;
2158    unsigned int nchildren, i=0;
2159    XTextProperty windowName;
2160    bool xraise = false;
2161
2162
2163    XQueryTree(display, _parent, &root_return, &parent_return, &children, &nchildren);
2164    while (!xraise &&  i<nchildren)
2165    {
2166    XGetWMName(display,children[i++],&windowName);
2167        if ((windowName.nitems != 0) && (strcmp(_traits->windowName.c_str(),(const char *)windowName.value) == 0)) xraise = true;
2168    }
2169    if (xraise) XRaiseWindow(display,_window);
2170    else
2171    {
2172    XGetWindowAttributes(display, _window, &winAttrib);
2173    XReparentWindow(display, _window, _parent, winAttrib.x, winAttrib.y);
2174    }
2175    XFree(children);
2176
2177    XFlush(display);
2178    XSync(display,0);
2179}
Note: See TracBrowser for help on using the browser.