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

Revision 12003, 69.2 kB (checked in by robert, 3 years ago)

Added TODO notes

  • 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// Fix toggling of fullscreen to window mode as it does enable window decoration with recent linux window managers
22
23#include <osgViewer/api/X11/GraphicsWindowX11>
24#include <osgViewer/api/X11/PixelBufferX11>
25
26#include <osg/DeleteHandler>
27
28#include <X11/Xlib.h>
29#include <X11/Xutil.h>
30
31#include <X11/Xmd.h>
32#include <X11/keysym.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->sampleBuffers) { 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        //  GLX_SAMPLE_BUFFERS
353        //  GLX_SAMPLES
354       
355        attributes.push_back(None);
356       
357        _visualInfo = glXChooseVisual( _display, _traits->screenNum, &(attributes.front()) );
358    #endif
359    }
360
361    return _visualInfo != 0;
362}
363#define MWM_HINTS_FUNCTIONS   (1L << 0)
364#define MWM_HINTS_DECORATIONS (1L << 1)
365#define MWM_HINTS_INPUT_MODE  (1L << 2)
366#define MWM_HINTS_STATUS      (1L << 3)
367
368#define MWM_DECOR_ALL         (1L<<0)
369#define MWM_DECOR_BORDER      (1L<<1)
370#define MWM_DECOR_RESIZEH     (1L<<2)
371#define MWM_DECOR_TITLE       (1L<<3)
372#define MWM_DECOR_MENU        (1L<<4)
373#define MWM_DECOR_MINIMIZE    (1L<<5)
374#define MWM_DECOR_MAXIMIZE    (1L<<6)
375
376#define MWM_FUNC_ALL          (1L<<0)
377#define MWM_FUNC_RESIZE       (1L<<1)
378#define MWM_FUNC_MOVE         (1L<<2)
379#define MWM_FUNC_MINIMIZE     (1L<<3)
380#define MWM_FUNC_MAXIMIZE     (1L<<4)
381#define MWM_FUNC_CLOSE        (1L<<5)
382
383
384bool GraphicsWindowX11::checkAndSendEventFullScreenIfNeeded(Display* display, int x, int y, int width, int height, bool windowDecoration)
385{
386  osg::GraphicsContext::WindowingSystemInterface *wsi = osg::GraphicsContext::getWindowingSystemInterface();
387  if (wsi == NULL) {
388    OSG_NOTICE << "Error, no WindowSystemInterface available, cannot toggle window fullscreen." << std::endl;
389    return false;
390  }
391
392  unsigned int    screenWidth;
393  unsigned int    screenHeight;
394
395  wsi->getScreenResolution(*_traits, screenWidth, screenHeight);
396  bool isFullScreen = x == 0 && y == 0 && width == (int)screenWidth && height == (int)screenHeight && !windowDecoration;
397
398  Atom netWMStateAtom = XInternAtom(display, "_NET_WM_STATE", True);
399  Atom netWMStateFullscreenAtom = XInternAtom(display,
400                                              "_NET_WM_STATE_FULLSCREEN", True);
401
402  if (netWMStateAtom != None && netWMStateFullscreenAtom != None) {
403    XEvent xev;
404    xev.xclient.type = ClientMessage;
405    xev.xclient.serial = 0;
406    xev.xclient.send_event = True;
407    xev.xclient.window = _window;
408    xev.xclient.message_type = netWMStateAtom;
409    xev.xclient.format = 32;
410    xev.xclient.data.l[0] = isFullScreen ? 1 : 0;
411    xev.xclient.data.l[1] = netWMStateFullscreenAtom;
412    xev.xclient.data.l[2] = 0;
413
414    XSendEvent(display, RootWindow(display, DefaultScreen(display)),
415               False,  SubstructureRedirectMask | SubstructureNotifyMask, &xev);
416    return true;
417  }
418  return false;
419}
420
421bool GraphicsWindowX11::setWindowDecorationImplementation(bool flag)
422{
423    Display* display = getDisplayToUse();
424
425    XMapWindow(display, _window );
426
427    checkAndSendEventFullScreenIfNeeded(display, _traits->x, _traits->y, _traits->width, _traits->height, flag);
428    struct
429    {
430        unsigned long flags;
431        unsigned long functions;
432        unsigned long decorations;
433        long          inputMode;
434        unsigned long status;
435    } wmHints;
436
437    Atom atom;
438    bool result = false;
439    if( (atom = XInternAtom( display, "_MOTIF_WM_HINTS", 0 )) != None )
440    {
441       
442        wmHints.flags = 0;
443        wmHints.functions = MWM_FUNC_ALL;
444        wmHints.decorations = MWM_DECOR_ALL;
445        wmHints.inputMode = 0;
446        wmHints.status = 0;       
447       
448        if (!flag)
449        {
450            wmHints.flags = MWM_HINTS_DECORATIONS;
451            wmHints.decorations = 0;
452        }
453        else
454        {
455            wmHints.flags |= MWM_HINTS_FUNCTIONS;
456            if (_traits.valid() && !_traits->supportsResize) wmHints.functions |= MWM_FUNC_RESIZE;
457        }
458        XChangeProperty( display, _window, atom, atom, 32, PropModeReplace, (unsigned char *)&wmHints,  5 );
459        result = true;
460    }
461    else
462    {
463        OSG_NOTICE<<"Error: GraphicsWindowX11::setBorder(" << flag << ") - couldn't change decorations." << std::endl;
464        result = false;
465    }
466
467    XFlush(display);
468    XSync(display,0);
469    // add usleep here to give window manager a chance to handle the request, if
470    // we don't add this sleep then any X11 calls right afterwards can produce
471    // X11 errors.
472    usleep(100000);
473    return result;
474}
475
476bool GraphicsWindowX11::setWindowRectangleImplementation(int x, int y, int width, int height)
477{
478    if (!_initialized) return false;
479   
480    Display* display = getDisplayToUse();
481   
482    XMoveResizeWindow(display, _window, x, y, width, height);
483   
484    XFlush(display);
485    XSync(display, 0);
486
487    checkAndSendEventFullScreenIfNeeded(display, x, y, width, height, _traits->windowDecoration);
488
489    // add usleep here to give window manager a chance to handle the request, if
490    // we don't add this sleep then any X11 calls right afterwards can produce
491    // X11 errors.
492    usleep(100000);
493
494   
495    return true;
496}
497
498void GraphicsWindowX11::setWindowName(const std::string& name)
499{
500    if( _window == 0) return;
501
502    //    char *slist[] = { name.c_str(), 0L };
503    //    XTextProperty xtp;
504
505    //    XStringListToTextProperty( slist, 1, &xtp );
506
507    Display* display = getDisplayToUse();
508    if( !display ) return;
509
510    //    XSetWMName( display, _window, &xtp );
511    XStoreName( display, _window, name.c_str() );
512    XSetIconName( display, _window, name.c_str() );
513
514    XFlush(display);
515    XSync(display,0);
516
517    _traits->windowName = name;
518}
519
520void GraphicsWindowX11::setCursor(MouseCursor mouseCursor)
521{
522    Cursor newCursor = getOrCreateCursor(mouseCursor);
523    if (newCursor == _currentCursor) return;
524
525    _currentCursor = newCursor;
526    if (!_window) return;
527    Display* display = getDisplayToUse();
528    if (!display) return;
529    XDefineCursor( display, _window, _currentCursor );
530    XFlush(display);
531    XSync(display, 0);
532
533    _traits->useCursor = (_currentCursor != getOrCreateCursor(NoCursor));
534}
535
536Cursor GraphicsWindowX11::getOrCreateCursor(MouseCursor mouseCursor)
537{
538    std::map<MouseCursor,Cursor>::iterator i = _mouseCursorMap.find(mouseCursor);
539    if (i != _mouseCursorMap.end()) return i->second;
540
541    Display* display = getDisplayToUse();
542    if (!display) return None;
543
544    switch (mouseCursor) {
545    case NoCursor:
546    {
547        // create an empty mouse cursor, note that it is safe to destroy the Pixmap just past cursor creation
548        // since the resource in the x server is reference counted.
549        char buff[2] = {0,0};
550        XColor ncol = {0,0,0,0,DoRed|DoGreen|DoBlue,0};
551        Pixmap pixmap = XCreateBitmapFromData( display, _parent, buff, 1, 1);
552        _mouseCursorMap[mouseCursor] = XCreatePixmapCursor( display, pixmap, pixmap, &ncol, &ncol, 0, 0 );
553        XFreePixmap(display, pixmap);
554        // Important to have the pixmap and the buffer still available when the request is sent to the server ...
555        XFlush(display);
556        XSync(display, 0);
557        break;
558    }
559    case RightArrowCursor:
560        _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_left_ptr );
561        break;
562    case LeftArrowCursor:
563        _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_top_left_arrow );
564        break;
565    case InfoCursor:
566        _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_hand1 );
567        break;
568    case DestroyCursor:
569        _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_pirate );
570        break;
571    case HelpCursor:
572        _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_question_arrow );
573        break;
574    case CycleCursor:
575        _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_exchange );
576        break;
577    case SprayCursor:
578        _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_spraycan );
579        break;
580    case WaitCursor:
581        _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_watch );
582        break;
583    case TextCursor:
584        _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_xterm );
585        break;
586    case CrosshairCursor:
587        _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_crosshair );
588        break;
589    case UpDownCursor:
590        _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_sb_v_double_arrow );
591        break;
592    case LeftRightCursor:
593        _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_sb_h_double_arrow );
594        break;
595    case TopSideCursor:
596        _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_top_side );
597        break;
598    case BottomSideCursor:
599        _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_bottom_side );
600        break;
601    case LeftSideCursor:
602        _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_left_side );
603        break;
604    case RightSideCursor:
605        _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_right_side );
606        break;
607    case TopLeftCorner:
608        _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_top_left_corner );
609        break;
610    case TopRightCorner:
611        _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_top_right_corner );
612        break;
613    case BottomRightCorner:
614        _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_bottom_right_corner );
615        break;
616    case BottomLeftCorner:
617        _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_bottom_left_corner );
618        break;
619    case HandCursor:
620        _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_hand1 );
621        break;
622
623    case InheritCursor:
624    default:
625        _mouseCursorMap[mouseCursor] = None;
626        break;
627    };
628    return _mouseCursorMap[mouseCursor];
629}
630
631void GraphicsWindowX11::init()
632{
633    if (_initialized) return;
634
635    if (!_traits)
636    {
637        _valid = false;
638        return;
639    }
640
641    // getEventQueue()->setCurrentEventState(osgGA::GUIEventAdapter::getAccumulatedEventState().get());
642
643    WindowData* inheritedWindowData = dynamic_cast<WindowData*>(_traits->inheritedWindowData.get());
644    Window windowHandle = inheritedWindowData ? inheritedWindowData->_window : 0;
645
646    _ownsWindow = windowHandle == 0;
647
648    _display = XOpenDisplay(_traits->displayName().c_str());
649
650    if (!_display)
651    {
652        OSG_NOTICE<<"Error: Unable to open display \"" << XDisplayName(_traits->displayName().c_str()) << "\"."<<std::endl;
653        _valid = false;
654        return;
655    }
656
657    #ifdef OSG_USE_EGL
658
659        _eglDisplay = eglGetDisplay((EGLNativeDisplayType)_display);
660
661        EGLint eglMajorVersion, eglMinorVersion;
662        if (!eglInitialize(_eglDisplay, &eglMajorVersion, &eglMinorVersion))
663        {
664            OSG_NOTICE<<"GraphicsWindowX11::init() - eglInitialize() failed."<<std::endl;
665
666            XCloseDisplay( _display );
667            _display = 0;
668            _valid = false;
669            return;
670        }
671
672        OSG_NOTICE<<"GraphicsWindowX11::init() - eglInitialize() succeded eglMajorVersion="<<eglMajorVersion<<" iMinorVersion="<<eglMinorVersion<<std::endl;
673
674   #else
675        // Query for GLX extension
676        int errorBase, eventBase;
677        if( glXQueryExtension( _display, &errorBase, &eventBase)  == False )
678        {
679            OSG_NOTICE<<"Error: " << XDisplayName(_traits->displayName().c_str()) <<" has no GLX extension." << std::endl;
680
681            XCloseDisplay( _display );
682            _display = 0;
683            _valid = false;
684            return;
685        }
686    #endif
687   
688    // OSG_NOTICE<<"GLX extension, errorBase="<<errorBase<<" eventBase="<<eventBase<<std::endl;
689
690    if (!createVisualInfo())
691    {
692        _traits->red /= 2;
693        _traits->green /= 2;
694        _traits->blue /= 2;
695        _traits->alpha /= 2;
696        _traits->depth /= 2;
697       
698        OSG_INFO<<"Relaxing traits"<<std::endl;
699
700        if (!createVisualInfo())
701        {
702            OSG_NOTICE<<"Error: Not able to create requested visual." << std::endl;
703            XCloseDisplay( _display );
704            _display = 0;
705            _valid = false;
706            return;
707        }   
708    }
709
710    // get any shared GLX contexts
711    GraphicsHandleX11* graphicsHandleX11 = dynamic_cast<GraphicsHandleX11*>(_traits->sharedContext);
712    Context sharedContext = graphicsHandleX11 ? graphicsHandleX11->getContext() : 0;
713
714    #ifdef OSG_USE_EGL
715
716        _valid = _ownsWindow ? createWindow() : setWindow(windowHandle);
717
718        if (!_valid)
719        {
720            XCloseDisplay( _display );
721            _display = 0;
722            return;
723        }
724       
725        OSG_NOTICE<<"GraphicsWindowX11::init() - window created ="<<_valid<<std::endl;
726
727        EGLConfig eglConfig = 0;
728       
729        #if defined(OSG_GLES2_AVAILABLE)
730            #define OSG_EGL_OPENGL_TARGET_BIT EGL_OPENGL_ES2_BIT
731        #else
732            #define OSG_EGL_OPENGL_TARGET_BIT EGL_OPENGL_ES_BIT
733        #endif
734       
735        EGLint configAttribs[] = {
736                EGL_SAMPLE_BUFFERS, 0,
737                EGL_SAMPLES, 0,
738                EGL_RED_SIZE, 1,
739                EGL_GREEN_SIZE, 1,
740                EGL_BLUE_SIZE, 1,
741                EGL_DEPTH_SIZE, 1,
742                EGL_RENDERABLE_TYPE, OSG_EGL_OPENGL_TARGET_BIT,
743                EGL_NONE
744        };
745
746        int numConfigs;
747        if (!eglChooseConfig(_eglDisplay, configAttribs, &eglConfig, 1, &numConfigs) || (numConfigs != 1))
748        {
749            OSG_NOTICE<<"GraphicsWindowX11::init() - eglChooseConfig() failed."<<std::endl;
750            XCloseDisplay( _display );
751            _valid = false;
752            _display = 0;
753            return;
754        }
755
756        eglBindAPI(EGL_OPENGL_ES_API);
757
758        _eglSurface = eglCreateWindowSurface(_eglDisplay, eglConfig, (EGLNativeWindowType)_window, NULL);
759        if (_eglSurface == EGL_NO_SURFACE)
760        {
761            OSG_NOTICE<<"GraphicsWindowX11::init() - eglCreateWindowSurface(..) failed."<<std::endl;
762            XCloseDisplay( _display );
763            _valid = false;
764            _display = 0;
765            return;
766        }
767
768        #if defined(OSG_GLES1_AVAILABLE)
769            EGLint* contextAttribs = 0;
770        #else
771            EGLint contextAttribs[] = {
772                 EGL_CONTEXT_CLIENT_VERSION,
773                2,
774                EGL_NONE
775            };
776        #endif
777
778        _context = eglCreateContext(_eglDisplay, eglConfig, sharedContext, contextAttribs);
779        if (_context == EGL_NO_CONTEXT)
780        {
781            OSG_NOTICE<<"GraphicsWindowX11::init() - eglCreateContext(..) failed."<<std::endl;
782            XCloseDisplay( _display );
783            _valid = false;
784            _display = 0;
785            return;
786        }
787
788        _initialized = true;
789           
790        checkEGLError("after eglCreateContext()");
791
792    #else
793       
794        _context = glXCreateContext( _display, _visualInfo, sharedContext, True );
795   
796        if (!_context)
797        {
798            OSG_NOTICE<<"Error: Unable to create OpenGL graphics context."<<std::endl;
799            XCloseDisplay( _display );
800            _display = 0;
801            _valid = false;
802            return;
803        }
804
805        _initialized = _ownsWindow ? createWindow() : setWindow(windowHandle);
806        _valid = _initialized;
807
808    #endif
809   
810    if (_valid == false)
811    {
812        XCloseDisplay( _display );
813        _display = 0;
814    }
815
816
817
818}
819
820bool GraphicsWindowX11::createWindow()
821{
822    unsigned int screen = _traits->screenNum;
823
824    _eventDisplay = XOpenDisplay(_traits->displayName().c_str());
825
826    _parent = RootWindow( _display, screen );
827
828    XWindowAttributes watt;
829    XGetWindowAttributes( _display, _parent, &watt );
830    // unsigned int parentWindowHeight = watt.height;
831
832    XSetWindowAttributes swatt;
833    swatt.colormap = XCreateColormap( _display, _parent, _visualInfo->visual, AllocNone);
834    //swatt.colormap = DefaultColormap( _dpy, 10 );
835    swatt.background_pixel = 0;
836    swatt.border_pixel = 0;
837    swatt.event_mask =  0;
838    unsigned long mask = CWBackPixel | CWBorderPixel | CWEventMask | CWColormap;
839
840    if (_traits->overrideRedirect)
841    {
842        swatt.override_redirect = true;
843        mask |= CWOverrideRedirect;
844       
845        OSG_INFO<<"Setting override redirect"<<std::endl;
846    }
847
848    _window = XCreateWindow( _display, _parent,
849                             _traits->x,
850                             _traits->y,
851                             _traits->width, _traits->height, 0,
852                             _visualInfo->depth, InputOutput,
853                             _visualInfo->visual, mask, &swatt );                         
854
855    if (!_window)
856    {
857        OSG_NOTICE<<"Error: Unable to create Window."<<std::endl;
858        _context = 0;
859        return false;
860    }
861
862
863    // Give window a class so that user preferences can be saved in the resource database.
864    XClassHint clH;
865    clH.res_name = (char *)"OSG";
866    clH.res_class = (char *)"osgViewer";
867    XSetClassHint( _display, _window, &clH);
868
869    // This positions the window at _windowX, _windowY
870    XSizeHints sh;
871    sh.flags = 0;
872    sh.flags |= USSize;
873    sh.flags &= 0x7;
874    sh.flags |= USPosition;
875    sh.flags &= 0xB;
876    sh.x = _traits->x;
877    sh.y = _traits->y;
878    sh.width  = _traits->width;
879    sh.height = _traits->height;
880    XSetStandardProperties( _display, _window, _traits->windowName.c_str(), _traits->windowName.c_str(), None, 0, 0, &sh);
881
882    setWindowDecoration(_traits->windowDecoration);
883
884    useCursor(_traits->useCursor);
885
886    _deleteWindow = XInternAtom (_display, "WM_DELETE_WINDOW", False);
887    XSetWMProtocols(_display, _window, &_deleteWindow, 1);
888
889
890    XFlush( _display );
891    XSync( _display, 0 );
892
893    // now update the window dimensions to account for any size changes made by the window manager,
894    XGetWindowAttributes( _display, _window, &watt );
895   
896    if (_traits->x != watt.x || _traits->y != watt.y
897        ||_traits->width != watt.width || _traits->height != watt.height)
898    {
899        resized( watt.x, watt.y, watt.width, watt.height );
900    }
901       
902    //OSG_NOTICE<<"After sync apply.x = "<<watt.x<<" watt.y="<<watt.y<<" width="<<watt.width<<" height="<<watt.height<<std::endl;
903
904
905    XSelectInput( _eventDisplay, _window, ExposureMask | StructureNotifyMask |
906                                     KeyPressMask | KeyReleaseMask |
907                                     PointerMotionMask | ButtonPressMask | ButtonReleaseMask |
908                                     KeymapStateMask | FocusChangeMask | EnterWindowMask );
909
910    XFlush( _eventDisplay );
911    XSync( _eventDisplay, 0 );
912    rescanModifierMapping();
913
914    return true;
915}
916
917bool GraphicsWindowX11::setWindow(Window window)
918{
919    if (_initialized)
920    {
921        OSG_NOTICE << "GraphicsWindowX11::setWindow() - Window already created; it cannot be changed";
922        return false;
923    }
924   
925    if (window==0)
926    {
927        OSG_NOTICE << "GraphicsWindowX11::setWindow() - Invalid window handle passed ";
928        return false;
929    }
930   
931    _window = window;
932    if (_window==0)
933    {
934        OSG_NOTICE << "GraphicsWindowX11::setWindow() - Unable to retrieve native window handle";
935        return false;
936    }
937
938    XWindowAttributes watt;
939    XGetWindowAttributes( _display, _window, &watt );
940    _traits->x = watt.x;
941    _traits->y = watt.y;
942    _traits->width = watt.width;
943    _traits->height = watt.height;
944
945    _parent = DefaultRootWindow( _display );
946
947    //_traits->supportsResize = false;
948    _traits->windowDecoration = false;
949
950    if (_traits->windowName.size()) setWindowName(_traits->windowName);
951
952    _eventDisplay = XOpenDisplay(_traits->displayName().c_str());
953
954    XFlush( _eventDisplay );
955    XSync( _eventDisplay, 0 );
956
957    return true;
958}
959
960bool GraphicsWindowX11::realizeImplementation()
961{
962    if (_realized)
963    {
964        OSG_NOTICE<<"GraphicsWindowX11::realizeImplementation() Already realized"<<std::endl;
965        return true;
966    }
967
968    if (!_initialized) init();
969   
970    if (!_initialized) return false;
971   
972    XMapWindow( _display, _window );
973   
974//    Window temp = _window;
975//    XSetWMColormapWindows( _display, _window, &temp, 1);
976   
977    _realized = true;
978
979    return true;
980}
981
982bool GraphicsWindowX11::makeCurrentImplementation()
983{
984    if (!_realized)
985    {
986        OSG_NOTICE<<"Warning: GraphicsWindow not realized, cannot do makeCurrent."<<std::endl;
987        return false;
988    }
989
990    #ifdef OSG_USE_EGL
991        bool result = eglMakeCurrent(_eglDisplay, _eglSurface, _eglSurface, _context)==EGL_TRUE;
992        checkEGLError("after eglMakeCurrent()");
993        return result;
994    #else
995        return glXMakeCurrent( _display, _window, _context )==True;
996    #endif
997}
998
999bool GraphicsWindowX11::releaseContextImplementation()
1000{
1001    if (!_realized)
1002    {
1003        OSG_NOTICE<<"Warning: GraphicsWindow not realized, cannot do release context."<<std::endl;
1004        return false;
1005    }
1006
1007    #ifdef OSG_USE_EGL
1008        bool result = eglMakeCurrent( _eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT )==EGL_TRUE;
1009        checkEGLError("after eglMakeCurrent() release");
1010        return result;
1011    #else
1012        return glXMakeCurrent( _display, None, NULL )==True;
1013    #endif
1014}
1015
1016
1017void GraphicsWindowX11::closeImplementation()
1018{
1019    // OSG_NOTICE<<"Closing GraphicsWindowX11"<<std::endl;
1020
1021    if (_eventDisplay)
1022    {
1023        XCloseDisplay( _eventDisplay );
1024        _eventDisplay = 0;
1025    }
1026
1027    if (_display)
1028    {
1029        if (_context)
1030        {
1031        #ifdef OSG_USE_EGL
1032            eglDestroyContext( _eglDisplay, _context );
1033        #else
1034            glXDestroyContext( _display, _context );
1035        #endif
1036        }
1037   
1038        if (_window && _ownsWindow)
1039        {
1040            XDestroyWindow(_display, _window);
1041        }
1042
1043        XFlush( _display );
1044        XSync( _display,0 );
1045    }
1046   
1047    _window = 0;
1048    _parent = 0;
1049    _context = 0;
1050
1051    if (_visualInfo)
1052    {
1053        #ifdef OSG_USE_EGL
1054            delete _visualInfo;
1055        #else       
1056            XFree(_visualInfo);
1057        #endif
1058        _visualInfo = 0;
1059    }
1060
1061
1062    if (_display)
1063    {
1064        XCloseDisplay( _display );
1065        _display = 0;
1066    }
1067
1068    _initialized = false;
1069    _realized = false;
1070    _valid = false;
1071}
1072
1073void GraphicsWindowX11::swapBuffersImplementation()
1074{
1075    if (!_realized) return;
1076
1077    // OSG_NOTICE<<"swapBuffersImplementation "<<this<<" "<<OpenThreads::Thread::CurrentThread()<<std::endl;
1078
1079    #ifdef OSG_USE_EGL
1080        eglSwapBuffers( _eglDisplay, _eglSurface );
1081        checkEGLError("after eglSwapBuffers()");
1082    #else
1083#if 0
1084        if (_traits.valid() && _traits->vsync) {
1085
1086            unsigned int counter;
1087            glXGetVideoSyncSGI(&counter);
1088            glXWaitVideoSyncSGI(1, 0, &counter);
1089        }
1090#endif
1091        glXSwapBuffers( _display, _window );
1092    #endif
1093
1094
1095    while( XPending(_display) )
1096    {
1097        XEvent ev;
1098        XNextEvent( _display, &ev );
1099
1100        switch( ev.type )
1101        {
1102            case ClientMessage:
1103            {
1104                if (static_cast<Atom>(ev.xclient.data.l[0]) == _deleteWindow)
1105                {
1106                    OSG_INFO<<"DeleteWindow event received"<<std::endl;
1107                    getEventQueue()->closeWindow();
1108                }
1109            }
1110        }
1111    }
1112}
1113
1114void GraphicsWindowX11::checkEvents()
1115{
1116    if (!_realized) return;
1117
1118    Display* display = _eventDisplay;
1119
1120    double baseTime = _timeOfLastCheckEvents;
1121    double eventTime = baseTime;
1122    double resizeTime = eventTime;
1123    _timeOfLastCheckEvents = getEventQueue()->getTime();
1124   
1125    // OSG_NOTICE<<"GraphicsWindowX11::checkEvents() : getEventQueue()->getCurrentEventState()->getGraphicsContext()="<<getEventQueue()->getCurrentEventState()->getGraphicsContext()<<std::endl;
1126
1127    int windowX = _traits->x;
1128    int windowY = _traits->y;
1129    int windowWidth = _traits->width;
1130    int windowHeight = _traits->height;
1131
1132    bool destroyWindowRequested = false;
1133   
1134    Time firstEventTime = 0;
1135     
1136    // OSG_NOTICE<<"Check events"<<std::endl;
1137    while( XPending(display) )
1138    {
1139        XEvent ev;
1140        XNextEvent( display, &ev );
1141
1142        switch( ev.type )
1143        {
1144            case ClientMessage:
1145            {
1146                OSG_NOTICE<<"ClientMessage event received"<<std::endl;
1147                if (static_cast<Atom>(ev.xclient.data.l[0]) == _deleteWindow)
1148                {
1149                    OSG_NOTICE<<"DeleteWindow event received"<<std::endl;
1150                    // FIXME only do if _ownsWindow ?
1151                    destroyWindowRequested = true;
1152                    getEventQueue()->closeWindow(eventTime);
1153                }
1154            }
1155            case Expose :
1156                OSG_INFO<<"Expose x="<<ev.xexpose.x<<" y="<<ev.xexpose.y<<" width="<<ev.xexpose.width<<", height="<<ev.xexpose.height<<std::endl;
1157                break;
1158
1159            case GravityNotify :
1160                OSG_INFO<<"GravityNotify event received"<<std::endl;
1161                break;
1162
1163            case ReparentNotify:
1164                OSG_INFO<<"ReparentNotify event received"<<std::endl;
1165                break;
1166
1167            case DestroyNotify :
1168                OSG_NOTICE<<"DestroyNotify event received"<<std::endl;
1169                _realized =  false;
1170                _valid = false;
1171                break;
1172               
1173            case ConfigureNotify :
1174            {
1175                OSG_INFO<<"ConfigureNotify x="<<ev.xconfigure.x<<" y="<<ev.xconfigure.y<<" width="<<ev.xconfigure.width<<", height="<<ev.xconfigure.height<<std::endl;
1176
1177                if (windowX != ev.xconfigure.x ||
1178                    windowX != ev.xconfigure.y ||
1179                    windowWidth != ev.xconfigure.width ||
1180                    windowHeight != ev.xconfigure.height)
1181                {
1182                    resizeTime = eventTime;
1183
1184                    windowX = ev.xconfigure.x;
1185                    windowY = ev.xconfigure.y;
1186                    windowWidth = ev.xconfigure.width;
1187                    windowHeight = ev.xconfigure.height;
1188                }
1189
1190                break;
1191            }
1192           
1193            case MapNotify :
1194            {
1195                OSG_INFO<<"MapNotify"<<std::endl;
1196                XWindowAttributes watt;
1197                do
1198                    XGetWindowAttributes(display, _window, &watt );
1199                while( watt.map_state != IsViewable );
1200               
1201                OSG_INFO<<"MapNotify x="<<watt.x<<" y="<<watt.y<<" width="<<watt.width<<", height="<<watt.height<<std::endl;
1202
1203                if (windowWidth != watt.width || windowHeight != watt.height)
1204                {
1205                    resizeTime = eventTime;
1206
1207                    windowWidth = watt.width;
1208                    windowHeight = watt.height;
1209                }
1210
1211                break;
1212            }
1213
1214            case FocusIn :
1215                OSG_INFO<<"FocusIn event received"<<std::endl;
1216                flushKeyEvents();
1217                break;
1218
1219            case UnmapNotify :
1220            case FocusOut :
1221            {
1222                OSG_INFO<<"FocusOut/UnmapNotify event received"<<std::endl;
1223                if (ev.type == FocusOut && ev.xfocus.mode != NotifyNormal) break;
1224
1225                char modMap[32];
1226                getModifierMap(modMap);
1227
1228                // release normal (non-modifier) keys
1229                for (unsigned int key = 8; key < 256; key++)
1230                {
1231                    bool isModifier = keyMapGetKey(modMap, key);
1232                    if (!isModifier) forceKey(key, eventTime, false);
1233                }
1234
1235                // release modifier keys
1236                for (unsigned int key = 8; key < 256; key++)
1237                {
1238                    bool isModifier = keyMapGetKey(modMap, key);
1239                    if (isModifier) forceKey(key, eventTime, false);
1240                }
1241                break;
1242            }
1243
1244            case EnterNotify :
1245                OSG_INFO<<"EnterNotify event received"<<std::endl;
1246                _modifierState = ev.xcrossing.state;
1247                syncLocks();
1248                break;
1249
1250            case KeymapNotify :
1251            {
1252                OSG_INFO<<"KeymapNotify event received"<<std::endl;
1253
1254                // KeymapNotify is guaranteed to directly follow either a FocusIn or
1255                // an EnterNotify event. We are only interested in the FocusIn case.
1256                if (_lastEventType != FocusIn) break;
1257
1258                char modMap[32];
1259                getModifierMap(modMap);
1260                syncLocks();
1261
1262                char keyMap[32];
1263                XQueryKeymap(_eventDisplay, keyMap);
1264
1265                // release normal (non-modifier) keys
1266                for (unsigned int key = 8; key < 256; key++)
1267                {
1268                    bool isModifier = keyMapGetKey(modMap, key);
1269                    if (isModifier) continue;
1270                    bool isPressed = keyMapGetKey(keyMap, key);
1271                    if (!isPressed) forceKey(key, eventTime, false);
1272                }
1273
1274                // press/release modifier keys
1275                for (unsigned int key = 8; key < 256; key++)
1276                {
1277                    bool isModifier = keyMapGetKey(modMap, key);
1278                    if (!isModifier) continue;
1279                    bool isPressed = keyMapGetKey(keyMap, key);
1280                    forceKey(key, eventTime, isPressed);
1281                }
1282
1283                // press normal keys
1284                for (unsigned int key = 8; key < 256; key++)
1285                {
1286                    bool isModifier = keyMapGetKey(modMap, key);
1287                    if (isModifier) continue;
1288                    bool isPressed = keyMapGetKey(keyMap, key);
1289                    if (isPressed) forceKey(key, eventTime, true);
1290                }
1291                break;
1292            }
1293
1294            case MappingNotify :
1295                OSG_INFO<<"MappingNotify event received"<<std::endl;
1296                if (ev.xmapping.request == MappingModifier) rescanModifierMapping();
1297                break;
1298
1299            case MotionNotify :
1300            {
1301                if (firstEventTime==0) firstEventTime = ev.xmotion.time;
1302                Time relativeTime = ev.xmotion.time - firstEventTime;
1303                eventTime = baseTime + static_cast<double>(relativeTime)*0.001;
1304           
1305                int  wx, wy;
1306                Window win = 0L;
1307                if( ev.xmotion.same_screen )
1308                {
1309                    wx = ev.xmotion.x;
1310                    wy = ev.xmotion.y;
1311                }
1312                else
1313                {
1314                    // the mouse in on another screen so need to compute the
1315                    // coordinates of the mouse position relative to an absolute position
1316                    // then take away the position of the original window/screen to get
1317                    // the coordinates relative to the original position.
1318                    Window root;
1319                    int rx, ry;
1320                    unsigned int buttons;
1321
1322                    int screenOrigin_x = 0;
1323                    int screenOrigin_y = 0;
1324                    int i;
1325                    for(i= 0; i < ScreenCount(display); i++ )
1326                    {
1327                        if( XQueryPointer( display, RootWindow(display, i),
1328                              &root, &win, &rx, &ry, &wx, &wy, &buttons) )
1329                        {
1330                            break;
1331                        }
1332
1333                        screenOrigin_x += DisplayWidth(display, i);
1334                    }
1335
1336                    for(i= 0; i < static_cast<int>(_traits->screenNum); i++ )
1337                    {
1338                        screenOrigin_x -= DisplayWidth(display, i);
1339                    }
1340
1341                    int dest_x_return, dest_y_return;
1342                    Window child_return;
1343                    XTranslateCoordinates(display, _window, _parent, 0, 0, &dest_x_return, &dest_y_return, &child_return);
1344
1345                    wx += (screenOrigin_x - dest_x_return);
1346                    wy += (screenOrigin_y - dest_y_return);
1347                }
1348               
1349
1350                float mx = wx;
1351                float my = wy;
1352                transformMouseXY(mx, my);
1353                getEventQueue()->mouseMotion(mx, my, eventTime);
1354
1355                // OSG_NOTICE<<"MotionNotify wx="<<wx<<" wy="<<wy<<" mx="<<mx<<" my="<<my<<std::endl;
1356
1357                break;
1358            }
1359           
1360            case ButtonPress :
1361            {
1362                if (firstEventTime==0) firstEventTime = ev.xmotion.time;
1363                Time relativeTime = ev.xmotion.time - firstEventTime;
1364                eventTime = baseTime + static_cast<double>(relativeTime)*0.001;
1365
1366                if( ev.xbutton.button == Button4 )
1367                {
1368                    getEventQueue()->mouseScroll(osgGA::GUIEventAdapter::SCROLL_UP, eventTime);
1369                }
1370                else if( ev.xbutton.button == Button5)
1371                {
1372                    getEventQueue()->mouseScroll(osgGA::GUIEventAdapter::SCROLL_DOWN, eventTime);
1373                }
1374                else
1375                {
1376                    float mx = ev.xbutton.x;
1377                    float my = ev.xmotion.y;
1378                    transformMouseXY(mx, my);
1379                    getEventQueue()->mouseButtonPress(mx, my, ev.xbutton.button, eventTime);
1380                }
1381                break;
1382            }
1383           
1384            case ButtonRelease :
1385            {
1386                if (firstEventTime==0) firstEventTime = ev.xmotion.time;
1387                Time relativeTime = ev.xmotion.time - firstEventTime;
1388                eventTime = baseTime + static_cast<double>(relativeTime)*0.001;
1389
1390                if( ev.xbutton.button == Button4 )
1391                {
1392                    getEventQueue()->mouseScroll(osgGA::GUIEventAdapter::SCROLL_UP, eventTime);
1393                }
1394                else if( ev.xbutton.button == Button5)
1395                {
1396                    getEventQueue()->mouseScroll(osgGA::GUIEventAdapter::SCROLL_DOWN, eventTime);
1397                }
1398                else
1399                {
1400                    float mx = ev.xbutton.x;
1401                    float my = ev.xmotion.y;
1402                    transformMouseXY(mx, my);
1403                    getEventQueue()->mouseButtonRelease(mx, my, ev.xbutton.button, eventTime);
1404                }
1405                break;
1406            }
1407           
1408            case KeyPress:
1409            {
1410                if (firstEventTime==0) firstEventTime = ev.xmotion.time;
1411                Time relativeTime = ev.xmotion.time - firstEventTime;
1412                eventTime = baseTime + static_cast<double>(relativeTime)*0.001;
1413
1414                _modifierState = ev.xkey.state;
1415                keyMapSetKey(_keyMap, ev.xkey.keycode);
1416                int keySymbol = 0;
1417                adaptKey(ev.xkey, keySymbol);
1418
1419                getEventQueue()->keyPress(keySymbol, eventTime);
1420                break;
1421            }
1422           
1423            case KeyRelease:
1424            {
1425                if (firstEventTime==0) firstEventTime = ev.xmotion.time;
1426                Time relativeTime = ev.xmotion.time - firstEventTime;
1427                eventTime = baseTime + static_cast<double>(relativeTime)*0.001;
1428#if 1               
1429                // Check for following KeyPress events and see if
1430                // the pair are the result of auto-repeat. If so, drop
1431                // this one on the floor, to be consistent with
1432                // Windows and Mac ports. The idea comes from libSDL sources.
1433                XEvent nextev;
1434                if (XPending(display))
1435                {
1436                    XPeekEvent(display, &nextev);
1437                    if ((nextev.type == KeyPress)
1438                        && (nextev.xkey.keycode == ev.xkey.keycode)
1439                        && (nextev.xmotion.time - ev.xmotion.time < 2))
1440                    {
1441                        break;
1442                    }
1443                }
1444#endif
1445                _modifierState = ev.xkey.state;
1446                keyMapClearKey(_keyMap, ev.xkey.keycode);
1447                int keySymbol = 0;
1448                adaptKey(ev.xkey, keySymbol);
1449               
1450                getEventQueue()->keyRelease(keySymbol, eventTime);
1451                break;
1452            }
1453           
1454            default:
1455                OSG_NOTICE<<"Other event "<<ev.type<<std::endl;
1456                break;
1457               
1458        }
1459        _lastEventType = ev.type;
1460    }
1461
1462    if (windowX != _traits->x ||
1463        windowY != _traits->y ||
1464        windowWidth != _traits->width ||
1465        windowHeight != _traits->height)
1466    {
1467        resized(windowX, windowY, windowWidth, windowHeight);
1468        getEventQueue()->windowResize(windowX, windowY, windowWidth, windowHeight, resizeTime);
1469    }
1470   
1471#if 0
1472    if (destroyWindowRequested)
1473    {
1474        close();
1475    }
1476#endif
1477}
1478
1479void GraphicsWindowX11::grabFocus()
1480{
1481    Display* display = getDisplayToUse();
1482
1483    XSetInputFocus( display, _window, RevertToNone, CurrentTime );
1484    XFlush(display);
1485    XSync(display,0);
1486}
1487
1488void GraphicsWindowX11::grabFocusIfPointerInWindow()
1489{
1490    Window win, root;
1491    int wx, wy, rx, ry;
1492    unsigned int buttons;
1493
1494    Display* display = getDisplayToUse();
1495
1496    if( XQueryPointer( display, _window,
1497          &root, &win, &rx, &ry, &wx, &wy, &buttons))
1498    {
1499#if 0
1500        if (wx>=0 && wx<_traits->width &&
1501            wy>=0 && wy<_traits->height)
1502        {
1503            grabFocus();
1504        }
1505#else       
1506        grabFocus();
1507#endif
1508    }
1509}
1510
1511void GraphicsWindowX11::transformMouseXY(float& x, float& y)
1512{
1513    if (getEventQueue()->getUseFixedMouseInputRange())
1514    {
1515        osgGA::GUIEventAdapter* eventState = getEventQueue()->getCurrentEventState();
1516        x = eventState->getXmin() + (eventState->getXmax()-eventState->getXmin())*x/float(_traits->width);
1517        y = eventState->getYmin() + (eventState->getYmax()-eventState->getYmin())*y/float(_traits->height);
1518    }
1519}
1520
1521void GraphicsWindowX11::adaptKey(XKeyEvent& keyevent, int& keySymbol)
1522{
1523    unsigned char buffer_return[32];
1524    int bytes_buffer = 32;
1525    KeySym keysym_return;
1526
1527    int numChars = XLookupString(&keyevent, reinterpret_cast<char*>(buffer_return), bytes_buffer, &keysym_return, NULL);
1528    keySymbol = keysym_return;
1529    if (!remapExtendedX11Key(keySymbol) && (numChars==1))
1530    {
1531        keySymbol = buffer_return[0];
1532    }
1533}
1534
1535// Function to inject artificial key presses/releases.
1536void GraphicsWindowX11::forceKey(int key, double time, bool state)
1537{
1538    if (!(state ^ keyMapGetKey(_keyMap, key))) return; // already pressed/released
1539
1540    XKeyEvent event;
1541    event.serial = 0;
1542    event.send_event = True;
1543    event.display = _eventDisplay;
1544    event.window = _window;
1545    event.subwindow = 0;
1546    event.time = 0;
1547    event.x = 0;
1548    event.y = 0;
1549    event.x_root = 0;
1550    event.y_root = 0;
1551    event.state = getModifierMask() | (_modifierState & (LockMask | _numLockMask));
1552    event.keycode = key;
1553    event.same_screen = True;
1554
1555    int keySymbol = 0;
1556    if (state)
1557    {
1558        event.type = KeyPress;
1559        adaptKey(event, keySymbol);
1560        getEventQueue()->keyPress(keySymbol, time);
1561        keyMapSetKey(_keyMap, key);
1562    }
1563    else
1564    {
1565        event.type = KeyRelease;
1566        adaptKey(event, keySymbol);
1567        getEventQueue()->keyRelease(keySymbol, time);
1568        keyMapClearKey(_keyMap, key);
1569    }
1570}
1571
1572void GraphicsWindowX11::syncLocks()
1573{
1574    unsigned int mask = getEventQueue()->getCurrentEventState()->getModKeyMask();
1575
1576    if (_modifierState & LockMask)
1577        mask |= osgGA::GUIEventAdapter::MODKEY_CAPS_LOCK;
1578    else
1579        mask &= ~osgGA::GUIEventAdapter::MODKEY_CAPS_LOCK;
1580
1581    if (_modifierState & _numLockMask)
1582        mask |= osgGA::GUIEventAdapter::MODKEY_NUM_LOCK;
1583    else
1584        mask &= ~osgGA::GUIEventAdapter::MODKEY_NUM_LOCK;
1585
1586    getEventQueue()->getCurrentEventState()->setModKeyMask(mask);
1587}
1588
1589void GraphicsWindowX11::rescanModifierMapping()
1590{
1591    XModifierKeymap *mkm = XGetModifierMapping(_eventDisplay);
1592    KeyCode *m = mkm->modifiermap;
1593    KeyCode numlock = XKeysymToKeycode(_eventDisplay, XK_Num_Lock);
1594    _numLockMask = 0;
1595    for (int i = 0; i < mkm->max_keypermod * 8; i++, m++)
1596    {
1597        if (*m == numlock)
1598        {
1599            _numLockMask = 1 << (i / mkm->max_keypermod);
1600            break;
1601        }
1602    }
1603    XFree(mkm->modifiermap);
1604    XFree(mkm);
1605}
1606
1607void GraphicsWindowX11::flushKeyEvents()
1608{
1609    XEvent e;
1610    while (XCheckMaskEvent(_eventDisplay, KeyPressMask|KeyReleaseMask, &e))
1611        continue;
1612}
1613
1614// Returns char[32] keymap with bits for every modifier key set.
1615void GraphicsWindowX11::getModifierMap(char* keymap) const
1616{
1617    memset(keymap, 0, 32);
1618    XModifierKeymap *mkm = XGetModifierMapping(_eventDisplay);
1619    KeyCode *m = mkm->modifiermap;
1620    for (int i = 0; i < mkm->max_keypermod * 8; i++, m++)
1621    {
1622        if (*m) keyMapSetKey(keymap, *m);
1623    }
1624    XFree(mkm->modifiermap);
1625    XFree(mkm);
1626}
1627
1628int GraphicsWindowX11::getModifierMask() const
1629{
1630    int mask = 0;
1631    XModifierKeymap *mkm = XGetModifierMapping(_eventDisplay);
1632    for (int i = 0; i < mkm->max_keypermod * 8; i++)
1633    {
1634        unsigned int key = mkm->modifiermap[i];
1635        if (key && keyMapGetKey(_keyMap, key))
1636        {
1637            mask |= 1 << (i / mkm->max_keypermod);
1638        }
1639    }
1640    XFree(mkm->modifiermap);
1641    XFree(mkm);
1642    return mask;
1643}
1644
1645void GraphicsWindowX11::requestWarpPointer(float x,float y)
1646{
1647    if (!_realized)
1648    {
1649        OSG_INFO<<"GraphicsWindowX11::requestWarpPointer() - Window not realized; cannot warp pointer, screenNum="<< _traits->screenNum<<std::endl;
1650        return;
1651    }
1652
1653    Display* display = _eventDisplay; // getDisplayToUse();
1654
1655    XWarpPointer( display,
1656                  None,
1657                  _window,
1658                  0, 0, 0, 0,
1659                  static_cast<int>(x), static_cast<int>(y) );
1660
1661    XFlush(display);
1662    XSync(display, 0);
1663   
1664    getEventQueue()->mouseWarped(x,y);
1665}
1666
1667extern "C" 
1668{
1669
1670typedef int (*X11ErrorHandler)(Display*, XErrorEvent*);
1671
1672int X11ErrorHandling(Display* display, XErrorEvent* event)
1673{
1674    OSG_NOTICE<<"Got an X11ErrorHandling call display="<<display<<" event="<<event<<std::endl;
1675
1676    char buffer[256];
1677    XGetErrorText( display, event->error_code, buffer, 256);
1678
1679    OSG_NOTICE << buffer << std::endl;
1680    OSG_NOTICE << "Major opcode: " << (int)event->request_code << std::endl;
1681    OSG_NOTICE << "Minor opcode: " << (int)event->minor_code << std::endl;
1682    OSG_NOTICE << "Error code: " << (int)event->error_code << std::endl;
1683    OSG_NOTICE << "Request serial: " << event->serial << std::endl;
1684    OSG_NOTICE << "Current serial: " << NextRequest( display ) - 1 << std::endl;
1685
1686    switch( event->error_code )
1687    {
1688        case BadValue:
1689            OSG_NOTICE << "  Value: " << event->resourceid << std::endl;
1690            break;
1691
1692        case BadAtom:
1693            OSG_NOTICE << "  AtomID: " << event->resourceid << std::endl;
1694            break;
1695
1696        default:
1697            OSG_NOTICE << "  ResourceID: " << event->resourceid << std::endl;
1698            break;
1699    }
1700    return 0;
1701}
1702
1703}
1704
1705class X11WindowingSystemInterface : public osg::GraphicsContext::WindowingSystemInterface
1706{
1707#ifdef OSGVIEWER_USE_XRANDR
1708    // TODO: Investigate whether or not Robert thinks we should store/restore the original
1709    // resolution in the destructor; I'm not sure the other ones do this, and it may be the
1710    // responsibility of the user.
1711    bool _setScreen(const osg::GraphicsContext::ScreenIdentifier& si, unsigned int width, unsigned int height, unsigned int colorDepth, double rate) {
1712        if (colorDepth>0)
1713            OSG_NOTICE << "X11WindowingSystemInterface::_setScreen() is not fully implemented (missing depth)."<<std::endl;
1714
1715        Display* display = XOpenDisplay(si.displayName().c_str());
1716       
1717        if(display)
1718        {
1719            XRRScreenConfiguration* sc = XRRGetScreenInfo(display, RootWindow(display, si.screenNum));
1720
1721            if(!sc)
1722            {
1723                OSG_NOTICE << "Unable to create XRRScreenConfiguration on display \"" << XDisplayName(si.displayName().c_str()) << "\"."<<std::endl;
1724                return false;
1725            }
1726
1727            int      numScreens = 0;
1728            int      numRates   = 0;
1729            Rotation currentRot = 0;
1730            bool     okay       = false;
1731
1732            XRRConfigRotations(sc, &currentRot);
1733           
1734            // If the width or height are zero, use our defaults.
1735            if(!width || !height)
1736            {
1737                getScreenResolution(si, width, height);
1738            }
1739
1740            // If this somehow fails, okay will still be false, no iteration will take place below,
1741            // and the sc pointer will still be freed later on.
1742            XRRScreenSize* ss = XRRConfigSizes(sc, &numScreens);
1743
1744            for(int i = 0; i < numScreens; i++)
1745            {
1746                if(ss[i].width == static_cast<int>(width) && ss[i].height == static_cast<int>(height))
1747                {
1748                    short* rates     = XRRConfigRates(sc, i, &numRates);
1749                    bool   rateFound = false;
1750                   
1751                    // Search for our rate in the list of acceptable rates given to us by Xrandr.
1752                    // If it's not found, rateFound will still be false and the call will never
1753                    // be made to XRRSetScreenConfigAndRate since the rate will be invalid.
1754                    for(int r = 0; r < numRates; r++)
1755                    {
1756                        if(rates[r] == static_cast<short>(rate))
1757                        {
1758                            rateFound = true;
1759                            break;
1760                        }
1761                    }
1762
1763                    if(rate > 0.0f && !rateFound)
1764                    {
1765                        OSG_NOTICE << "Unable to find valid refresh rate " << rate << " on display \"" << XDisplayName(si.displayName().c_str()) << "\"."<<std::endl;
1766                    }
1767                    else if(XRRSetScreenConfigAndRate(display, sc, DefaultRootWindow(display), i, currentRot, static_cast<short>(rate), CurrentTime) != RRSetConfigSuccess)
1768                    {
1769                        OSG_NOTICE << "Unable to set resolution to " << width << "x" << height << " on display \"" << XDisplayName(si.displayName().c_str()) << "\"."<<std::endl;
1770                    }
1771                    else
1772                    {
1773                        okay = true;
1774                        break;
1775                    }
1776                }
1777            }
1778   
1779            XRRFreeScreenConfigInfo(sc);
1780   
1781            return okay;
1782        }
1783        else
1784        {
1785            OSG_NOTICE << "Unable to open display \"" << XDisplayName(si.displayName().c_str()) << "\"."<<std::endl;
1786            return false;
1787        }
1788    }
1789#endif
1790
1791protected:
1792    bool _errorHandlerSet;
1793   
1794
1795public:
1796    X11WindowingSystemInterface()
1797    {
1798        OSG_INFO<<"X11WindowingSystemInterface()"<<std::endl;
1799
1800
1801        // Install an X11 error handler, if the application has not already done so.
1802       
1803        // Set default handler, and get pointer to current handler.
1804        X11ErrorHandler currentHandler = XSetErrorHandler(NULL);
1805       
1806        // Set our handler, and get pointer to default handler.
1807        X11ErrorHandler defHandler = XSetErrorHandler(X11ErrorHandling);
1808
1809        if ( currentHandler == defHandler )
1810        {
1811            // No application error handler, use ours.
1812            // OSG_INFO<<"Set osgViewer X11 error handler"<<std::endl;
1813            _errorHandlerSet = 1;
1814        }
1815        else
1816        {
1817            // Application error handler exists, leave it set.
1818            // OSG_INFO<<"Existing application X11 error handler set"<<std::endl;
1819            _errorHandlerSet = 0;
1820            XSetErrorHandler(currentHandler);
1821        }
1822   
1823#if 0
1824        if (XInitThreads() == 0)
1825        {
1826            OSG_NOTICE << "Error: XInitThreads() failed. Aborting." << std::endl;
1827            exit(1);
1828        }
1829        else
1830        {
1831            OSG_INFO << "X11WindowingSystemInterface, xInitThreads() multi-threaded X support initialized.\n";
1832        }
1833#endif       
1834
1835    }
1836
1837
1838
1839    ~X11WindowingSystemInterface()
1840    {
1841        if (osg::Referenced::getDeleteHandler())
1842        {
1843            osg::Referenced::getDeleteHandler()->setNumFramesToRetainObjects(0);
1844            osg::Referenced::getDeleteHandler()->flushAll();
1845        }
1846
1847        //OSG_NOTICE<<"~X11WindowingSystemInterface()"<<std::endl;
1848
1849        // Unset our X11 error handler, providing the application has not replaced it.
1850
1851        if ( _errorHandlerSet )
1852        {
1853            X11ErrorHandler currentHandler = XSetErrorHandler(NULL);
1854            if ( currentHandler == X11ErrorHandling )
1855            {
1856                // OSG_INFO<<"osgViewer X11 error handler removed"<<std::endl;
1857            }
1858            else
1859            {
1860                // Not our error handler, leave it set.
1861                // OSG_INFO<<"Application X11 error handler left"<<std::endl;
1862                XSetErrorHandler(currentHandler);
1863            }
1864        }
1865    }
1866
1867    virtual unsigned int getNumScreens(const osg::GraphicsContext::ScreenIdentifier& si)
1868    {
1869        Display* display = XOpenDisplay(si.displayName().c_str());
1870        if(display)
1871        {
1872            unsigned int numScreens = ScreenCount(display);
1873            XCloseDisplay(display);
1874
1875            return numScreens;
1876        }
1877        else
1878        {
1879            OSG_NOTICE << "A Unable to open display \"" << XDisplayName(si.displayName().c_str()) << "\""<<std::endl;
1880            return 0;
1881        }
1882    }
1883
1884    bool supportsRandr(Display* display) const
1885    {
1886#ifdef OSGVIEWER_USE_XRANDR
1887        int event_basep;
1888        int error_basep;
1889        bool supports_randr = XRRQueryExtension( display, &event_basep, &error_basep );
1890        if( supports_randr )
1891        {
1892            int major, minor;
1893            XRRQueryVersion( display, &major, &minor );
1894            return ( major > 1 || ( major == 1 && minor >= 2 ) );
1895        }
1896#endif
1897        return false;
1898    }
1899
1900    virtual void getScreenSettings(const osg::GraphicsContext::ScreenIdentifier& si, osg::GraphicsContext::ScreenSettings & resolution )
1901    {
1902        Display* display = XOpenDisplay(si.displayName().c_str());
1903        if(display)
1904        {
1905            resolution.width = DisplayWidth(display, si.screenNum);
1906            resolution.height = DisplayHeight(display, si.screenNum);
1907            resolution.colorDepth = DefaultDepth(display, si.screenNum);
1908            resolution.refreshRate = 0;            // Missing call. Need a X11 expert.
1909           
1910            XCloseDisplay(display);
1911        }
1912        else
1913        {
1914            OSG_NOTICE << "Unable to open display \"" << XDisplayName(si.displayName().c_str()) << "\"."<<std::endl;
1915            resolution.width = 0;
1916            resolution.height = 0;
1917            resolution.colorDepth = 0;
1918            resolution.refreshRate = 0;
1919        }
1920    }
1921
1922    virtual bool setScreenSettings(const osg::GraphicsContext::ScreenIdentifier& si, const osg::GraphicsContext::ScreenSettings & resolution )
1923    {
1924#ifdef OSGVIEWER_USE_XRANDR
1925        _setScreen(si, resolution.width, resolution.height, resolution.colorDepth, resolution.refreshRate);
1926#else
1927        OSG_NOTICE << "You must build osgViewer with Xrandr 1.2 or higher for setScreenSettings support!" << std::endl;
1928#endif
1929        return false;
1930    }
1931
1932    virtual void enumerateScreenSettings(const osg::GraphicsContext::ScreenIdentifier& si, osg::GraphicsContext::ScreenSettingsList & resolutionList)
1933    {
1934        resolutionList.clear();
1935
1936        Display* display = XOpenDisplay(si.displayName().c_str());
1937        if(display)
1938        {
1939#ifdef OSGVIEWER_USE_XRANDR
1940            int defaultDepth = DefaultDepth(display, si.screenNum);
1941
1942            if (supportsRandr(display))
1943            {
1944                int nsizes = 0;
1945                XRRScreenSize * screenSizes = XRRSizes(display, si.screenNum, &nsizes);
1946                if (screenSizes && nsizes>0)
1947                {
1948                    for(int i=0; i<nsizes; ++i)
1949                    {
1950                        OSG_INFO<<"Screen size "<<screenSizes[i].width<<" "<<screenSizes[i].height<<" "<<screenSizes[i].mwidth<<" "<<screenSizes[i].mheight<<std::endl;
1951
1952                        int nrates;
1953                        short * rates = XRRRates (display, si.screenNum, i, &nrates);
1954                        if (rates && nrates>0)
1955                        {
1956                            for(int j=0; j<nrates; ++j)
1957                            {
1958                                OSG_INFO<<"   rates "<<rates[j]<<std::endl;
1959                               
1960                                resolutionList.push_back(osg::GraphicsContext::ScreenSettings(
1961                                    screenSizes[i].width,
1962                                    screenSizes[i].height,
1963                                    double(rates[j]),
1964                                    defaultDepth));
1965                            }
1966                        }
1967                        else
1968                        {
1969                            resolutionList.push_back(osg::GraphicsContext::ScreenSettings(
1970                                screenSizes[i].width,
1971                                screenSizes[i].height,
1972                                0.0,
1973                                defaultDepth));
1974                        }
1975
1976                    }
1977                }
1978            }
1979#endif           
1980            XCloseDisplay(display);
1981        }
1982
1983        if (resolutionList.empty())
1984        {
1985            OSG_NOTICE << "X11WindowingSystemInterface::enumerateScreenSettings() not supported." << std::endl;
1986        }
1987    }
1988
1989    virtual osg::GraphicsContext* createGraphicsContext(osg::GraphicsContext::Traits* traits)
1990    {
1991        if (traits->pbuffer)
1992        {
1993#if 1
1994            osg::ref_ptr<osgViewer::PixelBufferX11> pbuffer = new PixelBufferX11(traits);
1995            if (pbuffer->valid()) return pbuffer.release();
1996            else return 0;
1997#else
1998            osg::ref_ptr<osgViewer::GraphicsWindowX11> window = new GraphicsWindowX11(traits);
1999            if (window->valid()) return window.release();
2000            else return 0;
2001#endif
2002        }
2003        else
2004        {
2005            osg::ref_ptr<osgViewer::GraphicsWindowX11> window = new GraphicsWindowX11(traits);
2006            if (window->valid()) return window.release();
2007            else return 0;
2008        }
2009    }
2010
2011};
2012
2013struct RegisterWindowingSystemInterfaceProxy
2014{
2015    RegisterWindowingSystemInterfaceProxy()
2016    {
2017        OSG_INFO<<"RegisterWindowingSystemInterfaceProxy()"<<std::endl;
2018        osg::GraphicsContext::setWindowingSystemInterface(new X11WindowingSystemInterface);
2019    }
2020
2021    ~RegisterWindowingSystemInterfaceProxy()
2022    {
2023        OSG_INFO<<"~RegisterWindowingSystemInterfaceProxy()"<<std::endl;
2024
2025        if (osg::Referenced::getDeleteHandler())
2026        {
2027            osg::Referenced::getDeleteHandler()->setNumFramesToRetainObjects(0);
2028            osg::Referenced::getDeleteHandler()->flushAll();
2029        }
2030
2031        osg::GraphicsContext::setWindowingSystemInterface(0);
2032
2033    }
2034};
2035
2036RegisterWindowingSystemInterfaceProxy createWindowingSystemInterfaceProxy;
2037
2038// declare C entry point for static compilation.
2039extern "C" void graphicswindow_X11(void)
2040{
2041    osg::GraphicsContext::setWindowingSystemInterface(new X11WindowingSystemInterface);
2042}
2043
2044
2045void GraphicsWindowX11::raiseWindow()
2046{
2047    Display* display = getDisplayToUse();
2048    XWindowAttributes winAttrib;
2049
2050    Window root_return, parent_return, *children;
2051    unsigned int nchildren, i=0;
2052    XTextProperty windowName;
2053    bool xraise = false;
2054   
2055
2056    XQueryTree(display, _parent, &root_return, &parent_return, &children, &nchildren);
2057    while (!xraise &&  i<nchildren)
2058    {
2059    XGetWMName(display,children[i++],&windowName);
2060        if ((windowName.nitems != 0) && (strcmp(_traits->windowName.c_str(),(const char *)windowName.value) == 0)) xraise = true;
2061    }
2062    if (xraise) XRaiseWindow(display,_window);
2063    else 
2064    {
2065    XGetWindowAttributes(display, _window, &winAttrib);
2066    XReparentWindow(display, _window, _parent, winAttrib.x, winAttrib.y);
2067    }
2068    XFree(children);
2069
2070    XFlush(display);
2071    XSync(display,0);
2072}
Note: See TracBrowser for help on using the browser.