/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. */ /* Note, elements of GraphicsWindowX11 have used Prodcer/RenderSurface_X11.cpp as both * a guide to use of X11/GLX and copiying directly in the case of setBorder(). * These elements are license under OSGPL as above, with Copyright (C) 2001-2004 Don Burns. */ #include #include #include #include #include #include #include #include #include #include /* For CARD16 */ #include using namespace osgViewer; class X11KeyboardMap { public: X11KeyboardMap() { _keymap[XK_Escape ] = osgGA::GUIEventAdapter::KEY_Escape; _keymap[XK_F1 ] = osgGA::GUIEventAdapter::KEY_F1; _keymap[XK_F2 ] = osgGA::GUIEventAdapter::KEY_F2; _keymap[XK_F3 ] = osgGA::GUIEventAdapter::KEY_F3; _keymap[XK_F4 ] = osgGA::GUIEventAdapter::KEY_F4; _keymap[XK_F5 ] = osgGA::GUIEventAdapter::KEY_F5; _keymap[XK_F6 ] = osgGA::GUIEventAdapter::KEY_F6; _keymap[XK_F7 ] = osgGA::GUIEventAdapter::KEY_F7; _keymap[XK_F8 ] = osgGA::GUIEventAdapter::KEY_F8; _keymap[XK_F9 ] = osgGA::GUIEventAdapter::KEY_F9; _keymap[XK_F10 ] = osgGA::GUIEventAdapter::KEY_F10; _keymap[XK_F11 ] = osgGA::GUIEventAdapter::KEY_F11; _keymap[XK_F12 ] = osgGA::GUIEventAdapter::KEY_F12; _keymap[XK_quoteleft ] = '"'; _keymap[XK_1 ] = '1'; _keymap[XK_2 ] = '2'; _keymap[XK_3 ] = '3'; _keymap[XK_4 ] = '4'; _keymap[XK_5 ] = '5'; _keymap[XK_6 ] = '6'; _keymap[XK_7 ] = '7'; _keymap[XK_8 ] = '8'; _keymap[XK_9 ] = '9'; _keymap[XK_0 ] = '0'; _keymap[XK_minus ] = '-'; _keymap[XK_equal ] = '='; _keymap[XK_BackSpace ] = osgGA::GUIEventAdapter::KEY_BackSpace; _keymap[XK_Tab ] = osgGA::GUIEventAdapter::KEY_Tab; _keymap[XK_a ] = 'A'; _keymap[XK_b ] = 'B'; _keymap[XK_c ] = 'C'; _keymap[XK_d ] = 'D'; _keymap[XK_e ] = 'E'; _keymap[XK_f ] = 'F'; _keymap[XK_g ] = 'G'; _keymap[XK_h ] = 'H'; _keymap[XK_i ] = 'I'; _keymap[XK_j ] = 'J'; _keymap[XK_k ] = 'K'; _keymap[XK_l ] = 'L'; _keymap[XK_m ] = 'M'; _keymap[XK_n ] = 'N'; _keymap[XK_o ] = 'O'; _keymap[XK_p ] = 'P'; _keymap[XK_q ] = 'Q'; _keymap[XK_r ] = 'R'; _keymap[XK_s ] = 'S'; _keymap[XK_t ] = 'T'; _keymap[XK_u ] = 'U'; _keymap[XK_v ] = 'V'; _keymap[XK_w ] = 'W'; _keymap[XK_x ] = 'X'; _keymap[XK_y ] = 'Y'; _keymap[XK_z ] = 'Z'; _keymap[XK_bracketleft ] = '('; _keymap[XK_bracketright ] = ')'; _keymap[XK_backslash ] = '\\'; _keymap[XK_Caps_Lock ] = osgGA::GUIEventAdapter::KEY_Caps_Lock; _keymap[XK_semicolon ] = ';'; _keymap[XK_apostrophe ] = '\''; _keymap[XK_Return ] = osgGA::GUIEventAdapter::KEY_Return; _keymap[XK_Shift_L ] = osgGA::GUIEventAdapter::KEY_Shift_L; _keymap[XK_comma ] = ','; _keymap[XK_period ] = '.'; _keymap[XK_slash ] = '/'; _keymap[XK_Shift_R ] = osgGA::GUIEventAdapter::KEY_Shift_R; _keymap[XK_Control_L ] = osgGA::GUIEventAdapter::KEY_Control_L; _keymap[XK_Super_L ] = osgGA::GUIEventAdapter::KEY_Super_L; _keymap[XK_space ] = ' '; _keymap[XK_Alt_L ] = osgGA::GUIEventAdapter::KEY_Alt_L; _keymap[XK_Alt_R ] = osgGA::GUIEventAdapter::KEY_Alt_R; _keymap[XK_Super_R ] = osgGA::GUIEventAdapter::KEY_Super_R; _keymap[XK_Menu ] = osgGA::GUIEventAdapter::KEY_Menu; _keymap[XK_Control_R ] = osgGA::GUIEventAdapter::KEY_Control_R; _keymap[XK_Print ] = osgGA::GUIEventAdapter::KEY_Print; _keymap[XK_Scroll_Lock ] = osgGA::GUIEventAdapter::KEY_Scroll_Lock; _keymap[XK_Pause ] = osgGA::GUIEventAdapter::KEY_Pause; _keymap[XK_Home ] = osgGA::GUIEventAdapter::KEY_Home; _keymap[XK_Page_Up ] = osgGA::GUIEventAdapter::KEY_Page_Up; _keymap[XK_End ] = osgGA::GUIEventAdapter::KEY_End; _keymap[XK_Page_Down ] = osgGA::GUIEventAdapter::KEY_Page_Down; _keymap[XK_Delete ] = osgGA::GUIEventAdapter::KEY_Delete; _keymap[XK_Insert ] = osgGA::GUIEventAdapter::KEY_Insert; _keymap[XK_Left ] = osgGA::GUIEventAdapter::KEY_Left; _keymap[XK_Up ] = osgGA::GUIEventAdapter::KEY_Up; _keymap[XK_Right ] = osgGA::GUIEventAdapter::KEY_Right; _keymap[XK_Down ] = osgGA::GUIEventAdapter::KEY_Down; _keymap[XK_Num_Lock ] = osgGA::GUIEventAdapter::KEY_Num_Lock; _keymap[XK_KP_Divide ] = osgGA::GUIEventAdapter::KEY_KP_Divide; _keymap[XK_KP_Multiply ] = osgGA::GUIEventAdapter::KEY_KP_Multiply; _keymap[XK_KP_Subtract ] = osgGA::GUIEventAdapter::KEY_KP_Subtract; _keymap[XK_KP_Add ] = osgGA::GUIEventAdapter::KEY_KP_Add; _keymap[XK_KP_Home ] = osgGA::GUIEventAdapter::KEY_KP_Home; _keymap[XK_KP_Up ] = osgGA::GUIEventAdapter::KEY_KP_Up; _keymap[XK_KP_Page_Up ] = osgGA::GUIEventAdapter::KEY_KP_Page_Up; _keymap[XK_KP_Left ] = osgGA::GUIEventAdapter::KEY_KP_Left; _keymap[XK_KP_Begin ] = osgGA::GUIEventAdapter::KEY_KP_Begin; _keymap[XK_KP_Right ] = osgGA::GUIEventAdapter::KEY_KP_Right; _keymap[XK_KP_End ] = osgGA::GUIEventAdapter::KEY_KP_End; _keymap[XK_KP_Down ] = osgGA::GUIEventAdapter::KEY_KP_Down; _keymap[XK_KP_Page_Down ] = osgGA::GUIEventAdapter::KEY_KP_Page_Down; _keymap[XK_KP_Insert ] = osgGA::GUIEventAdapter::KEY_KP_Insert; _keymap[XK_KP_Delete ] = osgGA::GUIEventAdapter::KEY_KP_Delete; _keymap[XK_KP_Enter ] = osgGA::GUIEventAdapter::KEY_KP_Enter; } ~X11KeyboardMap() {} int remapKey(int key) { KeyMap::iterator itr = _keymap.find(key); if (itr == _keymap.end()) return key; else return itr->second; } protected: typedef std::map KeyMap; KeyMap _keymap; }; static int remapX11Key(int key) { static X11KeyboardMap s_x11KeyboardMap; return s_x11KeyboardMap.remapKey(key); } GraphicsWindowX11::~GraphicsWindowX11() { close(true); } Display* GraphicsWindowX11::getDisplayToUse() const { if (_threadOfLastMakeCurrent==0) { return _display; } if (OpenThreads::Thread::CurrentThread()==_threadOfLastMakeCurrent) { return _display; } else { return _eventDisplay; } } bool GraphicsWindowX11::createVisualInfo() { typedef std::vector Attributes; Attributes attributes; attributes.push_back(GLX_USE_GL); attributes.push_back(GLX_RGBA); if (_traits->doubleBuffer) attributes.push_back(GLX_DOUBLEBUFFER); if (_traits->quadBufferStereo) attributes.push_back(GLX_STEREO); attributes.push_back(GLX_RED_SIZE); attributes.push_back(_traits->red); attributes.push_back(GLX_GREEN_SIZE); attributes.push_back(_traits->green); attributes.push_back(GLX_BLUE_SIZE); attributes.push_back(_traits->blue); attributes.push_back(GLX_DEPTH_SIZE); attributes.push_back(_traits->depth); if (_traits->alpha) { attributes.push_back(GLX_ALPHA_SIZE); attributes.push_back(_traits->alpha); } if (_traits->stencil) { attributes.push_back(GLX_STENCIL_SIZE); attributes.push_back(_traits->stencil); } #if defined(GLX_SAMPLE_BUFFERS) && defined (GLX_SAMPLES) if (_traits->sampleBuffers) { attributes.push_back(GLX_SAMPLE_BUFFERS); attributes.push_back(_traits->sampleBuffers); } if (_traits->sampleBuffers) { attributes.push_back(GLX_SAMPLES); attributes.push_back(_traits->samples); } #endif // TODO // GLX_AUX_BUFFERS // GLX_ACCUM_RED_SIZE // GLX_ACCUM_GREEN_SIZE // GLX_SAMPLE_BUFFERS // GLX_SAMPLES attributes.push_back(None); _visualInfo = glXChooseVisual( _display, _traits->screenNum, &(attributes.front()) ); return _visualInfo != 0; } #define MWM_HINTS_FUNCTIONS (1L << 0) #define MWM_HINTS_DECORATIONS (1L << 1) #define MWM_HINTS_INPUT_MODE (1L << 2) #define MWM_HINTS_STATUS (1L << 3) #define MWM_DECOR_ALL (1L<<0) #define MWM_DECOR_BORDER (1L<<1) #define MWM_DECOR_RESIZEH (1L<<2) #define MWM_DECOR_TITLE (1L<<3) #define MWM_DECOR_MENU (1L<<4) #define MWM_DECOR_MINIMIZE (1L<<5) #define MWM_DECOR_MAXIMIZE (1L<<6) #define MWM_FUNC_ALL (1L<<0) #define MWM_FUNC_RESIZE (1L<<1) #define MWM_FUNC_MOVE (1L<<2) #define MWM_FUNC_MINIMIZE (1L<<3) #define MWM_FUNC_MAXIMIZE (1L<<4) #define MWM_FUNC_CLOSE (1L<<5) bool GraphicsWindowX11::setWindowDecorationImplementation(bool flag) { Display* display = getDisplayToUse(); Atom atom; if( (atom = XInternAtom( display, "_MOTIF_WM_HINTS", 0 )) != None ) { struct { unsigned long flags; unsigned long functions; unsigned long decorations; long inputMode; unsigned long status; } wmHints; wmHints.flags = 0; wmHints.functions = MWM_FUNC_ALL; wmHints.decorations = MWM_DECOR_ALL; wmHints.inputMode = 0; wmHints.status = 0; if (!flag) { wmHints.flags = MWM_HINTS_DECORATIONS; wmHints.decorations = 0; } else { wmHints.flags |= MWM_HINTS_FUNCTIONS; if (_traits.valid() && !_traits->supportsResize) wmHints.functions |= MWM_FUNC_RESIZE; } XMapWindow(display, _window ); XChangeProperty( display, _window, atom, atom, 32, PropModeReplace, (unsigned char *)&wmHints, 5 ); XFlush(display); XSync(display,0); #if 0 // now update the window dimensions to account for any size changes made by the window manager, XGetWindowAttributes( display, _window, &watt ); _traits->width = watt.width; _traits->height = watt.height; #endif // add usleep here to give window manager a chance to handle the request, if // we don't add this sleep then any X11 calls right afterwards can produce // X11 errors. usleep(100000); return true; } else { osg::notify(osg::NOTICE)<<"Error: GraphicsWindowX11::setBorder(" << flag << ") - couldn't change decorations." << std::endl; return false; } } bool GraphicsWindowX11::setWindowRectangleImplementation(int x, int y, int width, int height) { if (!_realized) return false; Display* display = getDisplayToUse(); XMoveResizeWindow(display, _window, x, y, width, height); XFlush(display); XSync(display, 0); // add usleep here to give window manager a chance to handle the request, if // we don't add this sleep then any X11 calls right afterwards can produce // X11 errors. usleep(100000); return true; } void GraphicsWindowX11::setCursor(MouseCursor mouseCursor) { Cursor newCursor = getOrCreateCursor(mouseCursor); if (newCursor == _currentCursor) return; _currentCursor = newCursor; if (!_window) return; Display* display = getDisplayToUse(); if (!display) return; XDefineCursor( display, _window, _currentCursor ); XFlush(display); XSync(display, 0); _traits->useCursor = (_currentCursor != getOrCreateCursor(NoCursor)); } Cursor GraphicsWindowX11::getOrCreateCursor(MouseCursor mouseCursor) { std::map::iterator i = _mouseCursorMap.find(mouseCursor); if (i != _mouseCursorMap.end()) return i->second; Display* display = getDisplayToUse(); if (!display) return None; switch (mouseCursor) { case NoCursor: { // create an empty mouse cursor, note that it is safe to destroy the Pixmap just past cursor creation // since the resource in the x server is reference counted. char buff[2] = {0,0}; XColor ncol = {0,0,0,0,DoRed|DoGreen|DoBlue,0}; Pixmap pixmap = XCreateBitmapFromData( display, _parent, buff, 1, 1); _mouseCursorMap[mouseCursor] = XCreatePixmapCursor( display, pixmap, pixmap, &ncol, &ncol, 0, 0 ); XFreePixmap(display, pixmap); // Important to have the pixmap and the buffer still available when the request is sent to the server ... XFlush(display); XSync(display, 0); break; } case RightArrowCursor: _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_left_ptr ); break; case LeftArrowCursor: _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_top_left_arrow ); break; case InfoCursor: _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_hand1 ); break; case DestroyCursor: _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_pirate ); break; case HelpCursor: _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_question_arrow ); break; case CycleCursor: _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_exchange ); break; case SprayCursor: _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_spraycan ); break; case WaitCursor: _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_watch ); break; case TextCursor: _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_xterm ); break; case CrosshairCursor: _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_crosshair ); break; case UpDownCursor: _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_sb_v_double_arrow ); break; case LeftRightCursor: _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_sb_h_double_arrow ); break; case TopSideCursor: _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_top_side ); break; case BottomSideCursor: _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_bottom_side ); break; case LeftSideCursor: _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_left_side ); break; case RightSideCursor: _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_right_side ); break; case TopLeftCorner: _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_top_left_corner ); break; case TopRightCorner: _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_top_right_corner ); break; case BottomRightCorner: _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_bottom_right_corner ); break; case BottomLeftCorner: _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_bottom_left_corner ); break; case InheritCursor: default: _mouseCursorMap[mouseCursor] = None; break; }; return _mouseCursorMap[mouseCursor]; } void GraphicsWindowX11::init() { if (_initialized) return; if (!_traits) { _valid = false; return; } getEventQueue()->setCurrentEventState(osgGA::GUIEventAdapter::getAccumulatedEventState().get()); WindowData* inheritedWindowData = dynamic_cast(_traits->inheritedWindowData.get()); _display = XOpenDisplay(_traits->displayName().c_str()); unsigned int screen = _traits->screenNum; if (!_display) { osg::notify(osg::NOTICE)<<"Error: Unable to open display \"" << XDisplayName(_traits->displayName().c_str()) << "\"."<displayName().c_str()) <<" has no GLX extension." << std::endl; XCloseDisplay( _display ); _display = 0; _valid = false; return; } // osg::notify(osg::NOTICE)<<"GLX extension, errorBase="<(_traits->sharedContext); if (graphicsWindowX11) { sharedContextGLX = graphicsWindowX11->getGLXContext(); } else { PixelBufferX11* pixelBufferX11 = dynamic_cast(_traits->sharedContext); if (pixelBufferX11) { sharedContextGLX = pixelBufferX11->getGLXContext(); } } _glxContext = glXCreateContext( _display, _visualInfo, sharedContextGLX, True ); if (!_glxContext) { osg::notify(osg::NOTICE)<<"Error: Unable to create OpenGL graphics context."<displayName().c_str()); _parent = RootWindow( _display, screen ); XWindowAttributes watt; XGetWindowAttributes( _display, _parent, &watt ); // unsigned int parentWindowHeight = watt.height; XSetWindowAttributes swatt; swatt.colormap = XCreateColormap( _display, _parent, _visualInfo->visual, AllocNone); //swatt.colormap = DefaultColormap( _dpy, 10 ); swatt.background_pixel = 0; swatt.border_pixel = 0; swatt.event_mask = 0; unsigned long mask = CWBackPixel | CWBorderPixel | CWEventMask | CWColormap; bool overrideRedirect = false; if (overrideRedirect) { swatt.override_redirect = true; mask |= CWOverrideRedirect; } _window = XCreateWindow( _display, _parent, _traits->x, _traits->y, _traits->width, _traits->height, 0, _visualInfo->depth, InputOutput, _visualInfo->visual, mask, &swatt ); if (!_window) { osg::notify(osg::NOTICE)<<"Error: Unable to create Window."<x; sh.y = _traits->y; sh.width = _traits->width; sh.height = _traits->height; XSetStandardProperties( _display, _window, _traits->windowName.c_str(), _traits->windowName.c_str(), None, 0, 0, &sh); setWindowDecoration(_traits->windowDecoration); useCursor(_traits->useCursor); _deleteWindow = XInternAtom (_display, "WM_DELETE_WINDOW", False); XSetWMProtocols(_display, _window, &_deleteWindow, 1); XFlush( _display ); XSync( _display, 0 ); // now update the window dimensions to account for any size changes made by the window manager, XGetWindowAttributes( _display, _window, &watt ); if (_traits->width != watt.width && _traits->height != watt.height) { resized( _traits->x, _traits->y, _traits->width, _traits->height ); } //osg::notify(osg::NOTICE)<<"After sync apply.x = "<(ev.xclient.data.l[0]) == _deleteWindow) { osg::notify(osg::INFO)<<"DeleteWindow event recieved"<closeWindow(); } } } } } void GraphicsWindowX11::checkEvents() { if (!_realized) return; Display* display = _eventDisplay; double baseTime = _timeOfLastCheckEvents; double eventTime = baseTime; double resizeTime = eventTime; _timeOfLastCheckEvents = getEventQueue()->getTime(); int windowX = _traits->x; int windowY = _traits->y; int windowWidth = _traits->width; int windowHeight = _traits->height; bool destroyWindowRequested = false; Time firstEventTime = 0; // osg::notify(osg::NOTICE)<<"Check events"<(ev.xclient.data.l[0]) == _deleteWindow) { osg::notify(osg::NOTICE)<<"DeleteWindow event recieved"<closeWindow(eventTime); } } case Expose : osg::notify(osg::INFO)<<"Expose x="<x || windowY != _traits->y || windowWidth != _traits->width || windowHeight != _traits->height) { resized(windowX, windowY, windowWidth, windowHeight); getEventQueue()->windowResize(windowX, windowY, windowWidth, windowHeight, resizeTime); } #if 0 if (destroyWindowRequested) { close(); } #endif } void GraphicsWindowX11::grabFocus() { Display* display = getDisplayToUse(); XSetInputFocus( display, _window, RevertToNone, CurrentTime ); XFlush(display); XSync(display,0); } void GraphicsWindowX11::grabFocusIfPointerInWindow() { Window win, root; int wx, wy, rx, ry; unsigned int buttons; Display* display = getDisplayToUse(); if( XQueryPointer( display, _window, &root, &win, &rx, &ry, &wx, &wy, &buttons)) { #if 0 if (wx>=0 && wx<_traits->width && wy>=0 && wy<_traits->height) { grabFocus(); } #else grabFocus(); #endif } } void GraphicsWindowX11::transformMouseXY(float& x, float& y) { if (getEventQueue()->getUseFixedMouseInputRange()) { osgGA::GUIEventAdapter* eventState = getEventQueue()->getCurrentEventState(); x = eventState->getXmin() + (eventState->getXmax()-eventState->getXmin())*x/float(_traits->width); y = eventState->getYmin() + (eventState->getYmax()-eventState->getYmin())*y/float(_traits->height); } } void GraphicsWindowX11::adaptKey(XKeyEvent& keyevent, int& keySymbol, unsigned int& modifierMask) { Display* display = _eventDisplay; static XComposeStatus state; unsigned char keybuf[32]; XLookupString( &keyevent, (char *)keybuf, sizeof(keybuf), NULL, &state ); modifierMask = 0; if( keyevent.state & ShiftMask ) { modifierMask |= osgGA::GUIEventAdapter::MODKEY_SHIFT; } if( keyevent.state & LockMask ) { modifierMask |= osgGA::GUIEventAdapter::MODKEY_CAPS_LOCK; } if( keyevent.state & ControlMask ) { modifierMask |= osgGA::GUIEventAdapter::MODKEY_CTRL; } if( keyevent.state & Mod1Mask ) { modifierMask |= osgGA::GUIEventAdapter::MODKEY_ALT; } if( keyevent.state & Mod2Mask ) { modifierMask |= osgGA::GUIEventAdapter::MODKEY_NUM_LOCK; } if( keyevent.state & Mod4Mask ) { modifierMask |= osgGA::GUIEventAdapter::MODKEY_META; } keySymbol = keybuf[0]; KeySym ks = XKeycodeToKeysym( display, keyevent.keycode, 0 ); int remappedKey = remapX11Key(ks); if (remappedKey & 0xff00) { // special keyboard character keySymbol = remappedKey; } else { // normal ascii key keySymbol = keybuf[0]; } } void GraphicsWindowX11::requestWarpPointer(float x,float y) { Display* display = getDisplayToUse(); XWarpPointer( display, None, _window, 0, 0, 0, 0, static_cast(x), static_cast(y) ); XFlush(display); XSync(display, 0); getEventQueue()->mouseWarped(x,y); } extern "C" { int X11ErrorHandling(Display* display, XErrorEvent* event) { osg::notify(osg::NOTICE)<<"Got an X11ErrorHandling call display="<request_code << std::endl; osg::notify(osg::NOTICE) << "Minor opcode: " << (int)event->minor_code << std::endl; osg::notify(osg::NOTICE) << "Error code: " << (int)event->error_code << std::endl; osg::notify(osg::NOTICE) << "Request serial: " << event->serial << std::endl; osg::notify(osg::NOTICE) << "Current serial: " << NextRequest( display ) - 1 << std::endl; switch( event->error_code ) { case BadValue: osg::notify(osg::NOTICE) << " Value: " << event->resourceid << std::endl; break; case BadAtom: osg::notify(osg::NOTICE) << " AtomID: " << event->resourceid << std::endl; break; default: osg::notify(osg::NOTICE) << " ResourceID: " << event->resourceid << std::endl; break; } return 0; } } struct X11WindowingSystemInterface : public osg::GraphicsContext::WindowingSystemInterface { X11WindowingSystemInterface() { osg::notify(osg::INFO)<<"X11WindowingSystemInterface()"<setNumFramesToRetainObjects(0); osg::Referenced::getDeleteHandler()->flushAll(); } //osg::notify(osg::NOTICE)<<"~X11WindowingSystemInterface()"<pbuffer) { #if 1 osg::ref_ptr pbuffer = new PixelBufferX11(traits); if (pbuffer->valid()) return pbuffer.release(); else return 0; #else osg::ref_ptr window = new GraphicsWindowX11(traits); if (window->valid()) return window.release(); else return 0; #endif } else { osg::ref_ptr window = new GraphicsWindowX11(traits); if (window->valid()) return window.release(); else return 0; } } }; struct RegisterWindowingSystemInterfaceProxy { RegisterWindowingSystemInterfaceProxy() { osg::notify(osg::INFO)<<"RegisterWindowingSystemInterfaceProxy()"<setNumFramesToRetainObjects(0); osg::Referenced::getDeleteHandler()->flushAll(); } osg::GraphicsContext::setWindowingSystemInterface(0); } }; RegisterWindowingSystemInterfaceProxy createWindowingSystemInterfaceProxy; // declare C entry point for static compilation. extern "C" void graphicswindow_X11(void) { osg::GraphicsContext::setWindowingSystemInterface(new X11WindowingSystemInterface); }