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

Revision 7071, 41.6 kB (checked in by robert, 7 years ago)

Added support for managing a CompileContext?. Rearranged the DeleteHandler::flushAll call.

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