2006-12-21 20:19:14 +08:00
/* -*-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 .
*/
2007-04-10 19:03:37 +08:00
# include <osgViewer/api/X11/GraphicsWindowX11>
2006-12-21 20:19:14 +08:00
2006-12-21 20:24:20 +08:00
# include <X11/Xlib.h>
# include <X11/Xutil.h>
# include <X11/Xmd.h>
# include <X11/keysym.h>
# include <X11/Xmu/WinUtil.h>
# include <X11/cursorfont.h>
2006-12-27 01:38:47 +08:00
# include <X11/Intrinsic.h>
2006-12-21 20:24:20 +08:00
2007-04-25 17:32:12 +08:00
# include <X11/Xmd.h> /* For CARD16 */
2006-12-21 20:24:20 +08:00
2007-04-14 16:31:40 +08:00
# include <unistd.h>
2006-12-21 20:19:14 +08:00
using namespace osgViewer ;
2006-12-25 00:40:19 +08:00
namespace osgViewer
{
2006-12-21 20:19:14 +08:00
class GraphicsContextX11 : public osg : : GraphicsContext
{
public :
GraphicsContextX11 ( osg : : GraphicsContext : : Traits * traits ) :
2006-12-25 00:40:19 +08:00
_valid ( false ) ,
2006-12-21 20:19:14 +08:00
_display ( 0 ) ,
_parent ( 0 ) ,
_window ( 0 )
{
_traits = traits ;
}
2006-12-25 00:40:19 +08:00
virtual bool valid ( ) const { return _valid ; }
2006-12-21 20:19:14 +08:00
/** Realise the GraphicsContext implementation,
* Pure virtual - must be implemented by concrate implementations of GraphicsContext . */
virtual bool realizeImplementation ( ) { osg : : notify ( osg : : NOTICE ) < < " GraphicsWindow::realizeImplementation() not implemented. " < < std : : endl ; return false ; }
/** Return true if the graphics context has been realised, and is ready to use, implementation.
* Pure virtual - must be implemented by concrate implementations of GraphicsContext . */
virtual bool isRealizedImplementation ( ) const { osg : : notify ( osg : : NOTICE ) < < " GraphicsWindow::isRealizedImplementation() not implemented. " < < std : : endl ; return false ; }
/** Close the graphics context implementation.
* Pure virtual - must be implemented by concrate implementations of GraphicsContext . */
virtual void closeImplementation ( ) { osg : : notify ( osg : : NOTICE ) < < " GraphicsWindow::closeImplementation() not implemented. " < < std : : endl ; }
/** Make this graphics context current implementation.
* Pure virtual - must be implemented by concrate implementations of GraphicsContext . */
2007-01-09 03:29:59 +08:00
virtual bool makeCurrentImplementation ( ) { osg : : notify ( osg : : NOTICE ) < < " GraphicsWindow::makeCurrentImplementation() not implemented. " < < std : : endl ; return false ; }
2006-12-21 20:19:14 +08:00
/** Make this graphics context current with specified read context implementation.
* Pure virtual - must be implemented by concrate implementations of GraphicsContext . */
2007-01-09 03:29:59 +08:00
virtual bool makeContextCurrentImplementation ( GraphicsContext * /*readContext*/ ) { osg : : notify ( osg : : NOTICE ) < < " GraphicsWindow::makeContextCurrentImplementation(..) not implemented. " < < std : : endl ; return false ; }
/** Release the graphics context.*/
virtual bool releaseContextImplementation ( ) { osg : : notify ( osg : : NOTICE ) < < " GraphicsWindow::releaseContextImplementation(..) not implemented. " < < std : : endl ; return false ; }
2006-12-21 20:19:14 +08:00
/** Pure virtual, Bind the graphics context to associated texture implementation.
* Pure virtual - must be implemented by concrate implementations of GraphicsContext . */
virtual void bindPBufferToTextureImplementation ( GLenum /*buffer*/ ) { osg : : notify ( osg : : NOTICE ) < < " GraphicsWindow::void bindPBufferToTextureImplementation(..) not implemented. " < < std : : endl ; }
/** Swap the front and back buffers implementation.
* Pure virtual - must be implemented by Concrate implementations of GraphicsContext . */
virtual void swapBuffersImplementation ( ) { osg : : notify ( osg : : NOTICE ) < < " GraphicsWindow:: swapBuffersImplementation() not implemented. " < < std : : endl ; }
protected :
2006-12-25 00:40:19 +08:00
bool _valid ;
Display * _display ;
Window _parent ;
Window _window ;
2006-12-21 20:19:14 +08:00
} ;
2006-12-25 00:40:19 +08:00
}
2006-12-21 20:19:14 +08:00
2007-01-02 02:20:10 +08:00
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 < int , int > KeyMap ;
KeyMap _keymap ;
} ;
static int remapX11Key ( int key )
{
static X11KeyboardMap s_x11KeyboardMap ;
return s_x11KeyboardMap . remapKey ( key ) ;
}
2007-01-04 00:06:12 +08:00
GraphicsWindowX11 : : ~ GraphicsWindowX11 ( )
{
close ( true ) ;
}
2007-04-13 21:22:52 +08:00
Display * GraphicsWindowX11 : : getDisplayToUse ( ) const
{
if ( _threadOfLastMakeCurrent = = 0 )
{
return _display ;
}
if ( OpenThreads : : Thread : : CurrentThread ( ) = = _threadOfLastMakeCurrent )
{
return _display ;
}
else
{
return _eventDisplay ;
}
}
2006-12-21 20:19:14 +08:00
bool GraphicsWindowX11 : : createVisualInfo ( )
{
typedef std : : vector < int > Attributes ;
Attributes attributes ;
attributes . push_back ( GLX_USE_GL ) ;
attributes . push_back ( GLX_RGBA ) ;
2006-12-23 05:53:44 +08:00
if ( _traits - > doubleBuffer ) attributes . push_back ( GLX_DOUBLEBUFFER ) ;
2006-12-21 20:19:14 +08:00
2006-12-23 05:53:44 +08:00
if ( _traits - > quadBufferStereo ) attributes . push_back ( GLX_STEREO ) ;
2006-12-21 20:19:14 +08:00
2006-12-23 05:53:44 +08:00
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 ) ;
2006-12-21 20:19:14 +08:00
2006-12-23 05:53:44 +08:00
if ( _traits - > alpha ) { attributes . push_back ( GLX_ALPHA_SIZE ) ; attributes . push_back ( _traits - > alpha ) ; }
2006-12-21 20:19:14 +08:00
2006-12-23 05:53:44 +08:00
if ( _traits - > stencil ) { attributes . push_back ( GLX_STENCIL_SIZE ) ; attributes . push_back ( _traits - > stencil ) ; }
2006-12-21 20:19:14 +08:00
2006-12-23 05:53:44 +08:00
# 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
2006-12-21 20:19:14 +08:00
// TODO
// GLX_AUX_BUFFERS
// GLX_ACCUM_RED_SIZE
// GLX_ACCUM_GREEN_SIZE
// GLX_SAMPLE_BUFFERS
// GLX_SAMPLES
attributes . push_back ( None ) ;
2006-12-23 05:53:44 +08:00
_visualInfo = glXChooseVisual ( _display , _traits - > screenNum , & ( attributes . front ( ) ) ) ;
2006-12-21 20:19:14 +08:00
return _visualInfo ! = 0 ;
}
void GraphicsWindowX11 : : setWindowDecoration ( bool flag )
{
2007-04-13 21:22:52 +08:00
Display * display = getDisplayToUse ( ) ;
2007-02-09 21:51:28 +08:00
2006-12-21 20:19:14 +08:00
Atom atom ;
2007-02-09 21:51:28 +08:00
if ( ( atom = XInternAtom ( display , " _MOTIF_WM_HINTS " , 0 ) ) ! = None )
2006-12-21 20:19:14 +08:00
{
// Hack for sending 64 bit atom to Xserver
# if defined( _MIPS_SIM) && (_MIPS_SIM == _MIPS_SIM_ABI64) || defined ( __ia64 ) || defined (__amd64 ) || defined(__x86_64__)
struct {
CARD32 flags0 ;
CARD32 flags1 ;
CARD32 functions0 ;
CARD32 functions1 ;
CARD32 decorations0 ;
CARD32 decorations1 ;
INT32 input_mode0 ;
INT32 input_mode1 ;
CARD32 status0 ;
CARD32 status1 ;
} wmHints ;
# if defined( __ia64 ) || defined (__amd64) || defined (__x86_64__)
wmHints . flags0 = ( 1L < < 1 ) ;
wmHints . functions0 = 0 ;
wmHints . decorations0 = flag ;
wmHints . input_mode0 = 0 ;
# else
wmHints . flags1 = ( 1L < < 1 ) ;
wmHints . functions1 = 0 ;
wmHints . decorations1 = flag ;
wmHints . input_mode1 = 0 ;
# endif
# else
struct {
CARD32 flags ;
CARD32 functions ;
CARD32 decorations ;
INT32 input_mode ;
CARD32 status ;
} wmHints ;
wmHints . flags = ( 1L < < 1 ) ;
wmHints . functions = 0 ;
wmHints . decorations = flag ;
wmHints . input_mode = 0 ;
# endif
2007-02-09 21:51:28 +08:00
XUnmapWindow ( display , _window ) ;
XChangeProperty ( display , _window , atom , atom , 32 , PropModeReplace , ( unsigned char * ) & wmHints , 5 ) ;
XMapWindow ( display , _window ) ;
2006-12-21 20:19:14 +08:00
2007-02-09 21:51:28 +08:00
XFlush ( display ) ;
XSync ( display , 0 ) ;
2006-12-21 20:19:14 +08:00
#if 0
// now update the window dimensions to account for any size changes made by the window manager,
2007-02-09 21:51:28 +08:00
XGetWindowAttributes ( display , _window , & watt ) ;
2006-12-23 05:53:44 +08:00
_traits - > width = watt . width ;
_traits - > height = watt . height ;
2006-12-21 20:19:14 +08:00
# endif
2007-04-13 22:54:22 +08:00
// 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 ) ;
2006-12-21 20:19:14 +08:00
}
else
osg : : notify ( osg : : NOTICE ) < < " Error: GraphicsWindowX11::setBorder( " < < flag < < " ) - couldn't change decorations. " < < std : : endl ;
}
2007-04-13 21:22:52 +08:00
void GraphicsWindowX11 : : setWindowRectangle ( int x , int y , int width , int height )
{
if ( ! _realized ) return ;
Display * display = getDisplayToUse ( ) ;
XMoveResizeWindow ( display , _window , x , y , width , height ) ;
XFlush ( display ) ;
XSync ( display , 0 ) ;
2007-04-13 22:54:22 +08:00
// 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 ) ;
2007-04-13 21:22:52 +08:00
}
2007-01-02 20:50:57 +08:00
void GraphicsWindowX11 : : useCursor ( bool cursorOn )
{
2007-04-13 21:22:52 +08:00
Display * display = getDisplayToUse ( ) ;
2007-02-09 21:51:28 +08:00
2007-01-02 20:50:57 +08:00
if ( cursorOn )
{
_currentCursor = _defaultCursor ;
}
else
{
_currentCursor = _nullCursor ;
}
2007-02-09 21:51:28 +08:00
if ( display & & _window )
2007-01-02 20:50:57 +08:00
{
2007-02-09 21:51:28 +08:00
XDefineCursor ( display , _window , _currentCursor ) ;
XFlush ( display ) ;
XSync ( display , 0 ) ;
2007-01-02 20:50:57 +08:00
}
2007-01-18 05:11:57 +08:00
_traits - > useCursor = cursorOn ;
2007-01-02 20:50:57 +08:00
}
2007-03-27 00:28:26 +08:00
void GraphicsWindowX11 : : init ( )
2006-12-21 20:19:14 +08:00
{
2006-12-25 00:40:19 +08:00
if ( _initialized ) return ;
if ( ! _traits )
{
_valid = false ;
return ;
}
2007-03-27 00:28:26 +08:00
WindowData * inheritedWindowData = dynamic_cast < WindowData * > ( _traits - > inheritedWindowData . get ( ) ) ;
2006-12-21 20:19:14 +08:00
2006-12-23 05:53:44 +08:00
_display = XOpenDisplay ( _traits - > displayName ( ) . c_str ( ) ) ;
2006-12-21 20:19:14 +08:00
2006-12-23 05:53:44 +08:00
unsigned int screen = _traits - > screenNum ;
2006-12-21 20:19:14 +08:00
if ( ! _display )
{
2006-12-25 00:40:19 +08:00
osg : : notify ( osg : : NOTICE ) < < " Error: Unable to open display \" " < < XDisplayName ( _traits - > displayName ( ) . c_str ( ) ) < < " \" . " < < std : : endl ;
_valid = false ;
return ;
2006-12-21 20:19:14 +08:00
}
// Query for GLX extension
int errorBase , eventBase ;
if ( glXQueryExtension ( _display , & errorBase , & eventBase ) = = False )
{
2006-12-23 05:53:44 +08:00
osg : : notify ( osg : : NOTICE ) < < " Error: " < < XDisplayName ( _traits - > displayName ( ) . c_str ( ) ) < < " has no GLX extension. " < < std : : endl ;
2006-12-21 20:19:14 +08:00
XCloseDisplay ( _display ) ;
_display = 0 ;
2006-12-25 00:40:19 +08:00
_valid = false ;
2006-12-21 20:19:14 +08:00
return ;
}
// osg::notify(osg::NOTICE)<<"GLX extension, errorBase="<<errorBase<<" eventBase="<<eventBase<<std::endl;
if ( ! createVisualInfo ( ) )
{
2007-01-29 01:32:41 +08:00
_traits - > red / = 2 ;
_traits - > green / = 2 ;
_traits - > blue / = 2 ;
_traits - > alpha / = 2 ;
_traits - > depth / = 2 ;
osg : : notify ( osg : : INFO ) < < " Relaxing traits " < < std : : endl ;
if ( ! createVisualInfo ( ) )
{
osg : : notify ( osg : : NOTICE ) < < " Error: Not able to create requested visual. " < < std : : endl ;
XCloseDisplay ( _display ) ;
_display = 0 ;
_valid = false ;
return ;
}
2006-12-21 20:19:14 +08:00
}
2007-02-15 04:14:45 +08:00
GraphicsWindowX11 * sharedContextX11 = dynamic_cast < GraphicsWindowX11 * > ( _traits - > sharedContext ) ;
2007-02-15 20:24:04 +08:00
if ( sharedContextX11 )
{
_glxContext = glXCreateContext ( _display , _visualInfo , sharedContextX11 - > getGLXContext ( ) , True ) ;
}
else
{
_glxContext = glXCreateContext ( _display , _visualInfo , NULL , True ) ;
}
2006-12-21 20:19:14 +08:00
if ( ! _glxContext )
{
osg : : notify ( osg : : NOTICE ) < < " Error: Unable to create OpenGL graphics context. " < < std : : endl ;
2006-12-25 00:40:19 +08:00
XCloseDisplay ( _display ) ;
_display = 0 ;
_valid = false ;
2006-12-21 20:19:14 +08:00
return ;
}
2007-04-13 21:22:52 +08:00
_eventDisplay = XOpenDisplay ( _traits - > displayName ( ) . c_str ( ) ) ;
2006-12-21 20:19:14 +08:00
_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 ,
2006-12-23 05:53:44 +08:00
_traits - > x ,
_traits - > y ,
_traits - > width , _traits - > height , 0 ,
2006-12-21 20:19:14 +08:00
_visualInfo - > depth , InputOutput ,
_visualInfo - > visual , mask , & swatt ) ;
if ( ! _window )
{
osg : : notify ( osg : : NOTICE ) < < " Error: Unable to create Window. " < < std : : endl ;
2006-12-25 00:40:19 +08:00
XCloseDisplay ( _display ) ;
_display = 0 ;
_glxContext = 0 ;
_valid = false ;
2006-12-21 20:19:14 +08:00
return ;
}
2007-02-09 21:51:28 +08:00
2006-12-21 20:19:14 +08:00
// This positions the window at _windowX, _windowY
XSizeHints sh ;
sh . flags = 0 ;
sh . flags | = USSize ;
sh . flags & = 0x7 ;
sh . flags | = USPosition ;
sh . flags & = 0xB ;
2006-12-23 05:53:44 +08:00
sh . x = _traits - > 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 ) ;
2006-12-21 20:19:14 +08:00
2006-12-23 05:53:44 +08:00
setWindowDecoration ( _traits - > windowDecoration ) ;
2007-04-13 21:22:52 +08:00
2006-12-21 20:19:14 +08:00
// Create default Cursor
_defaultCursor = XCreateFontCursor ( _display , XC_left_ptr ) ;
// Create Null Cursor
{
Pixmap pixmap ;
static char buff [ 2 ] = { 0 , 0 } ;
static XColor ncol = { 0 , 0 , 0 , 0 , DoRed | DoGreen | DoBlue , 0 } ;
pixmap = XCreateBitmapFromData ( _display , _parent , buff , 1 , 1 ) ;
_nullCursor = XCreatePixmapCursor ( _display , pixmap , pixmap , & ncol , & ncol , 0 , 0 ) ;
}
2007-01-18 05:11:57 +08:00
useCursor ( _traits - > useCursor ) ;
2006-12-21 20:19:14 +08:00
2007-02-09 21:51:28 +08:00
_deleteWindow = XInternAtom ( _display , " WM_DELETE_WINDOW " , False ) ;
XSetWMProtocols ( _display , _window , & _deleteWindow , 1 ) ;
2006-12-21 20:19:14 +08:00
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 ) ;
2007-01-02 02:20:10 +08:00
if ( _traits - > width ! = watt . width & & _traits - > height ! = watt . height )
{
resized ( _traits - > x , _traits - > y , _traits - > width , _traits - > height ) ;
}
2006-12-21 20:19:14 +08:00
//osg::notify(osg::NOTICE)<<"After sync apply.x = "<<watt.x<<" watt.y="<<watt.y<<" width="<<watt.width<<" height="<<watt.height<<std::endl;
2007-02-09 21:51:28 +08:00
XSelectInput ( _eventDisplay , _window , ExposureMask | StructureNotifyMask |
KeyPressMask | KeyReleaseMask |
PointerMotionMask | ButtonPressMask | ButtonReleaseMask ) ;
XFlush ( _eventDisplay ) ;
XSync ( _eventDisplay , 0 ) ;
2007-01-04 07:00:05 +08:00
2006-12-25 00:40:19 +08:00
_valid = true ;
2006-12-21 20:19:14 +08:00
_initialized = true ;
}
bool GraphicsWindowX11 : : realizeImplementation ( )
{
2006-12-23 01:46:21 +08:00
if ( _realized )
{
osg : : notify ( osg : : NOTICE ) < < " GraphicsWindowX11::realizeImplementation() Already realized " < < std : : endl ;
return true ;
}
2006-12-21 20:19:14 +08:00
if ( ! _initialized ) init ( ) ;
if ( ! _initialized ) return false ;
XMapWindow ( _display , _window ) ;
2006-12-27 01:38:47 +08:00
// Window temp = _window;
// XSetWMColormapWindows( _display, _window, &temp, 1);
2006-12-21 20:19:14 +08:00
_realized = true ;
return true ;
}
2007-01-09 03:29:59 +08:00
bool GraphicsWindowX11 : : makeCurrentImplementation ( )
2006-12-21 20:19:14 +08:00
{
2007-01-04 00:06:12 +08:00
if ( ! _realized )
{
osg : : notify ( osg : : NOTICE ) < < " Warning: GraphicsWindow not realized, cannot do makeCurrent. " < < std : : endl ;
2007-01-09 03:29:59 +08:00
return false ;
2007-01-04 00:06:12 +08:00
}
2006-12-25 00:40:19 +08:00
2006-12-23 01:46:21 +08:00
// osg::notify(osg::NOTICE)<<"makeCurrentImplementation "<<this<<" "<<OpenThreads::Thread::CurrentThread()<<std::endl;
// osg::notify(osg::NOTICE)<<" glXMakeCurrent ("<<_display<<","<<_window<<","<<_glxContext<<std::endl;
2007-01-09 03:29:59 +08:00
return glXMakeCurrent ( _display , _window , _glxContext ) = = True ;
}
2007-01-04 00:06:12 +08:00
2007-01-09 03:29:59 +08:00
bool GraphicsWindowX11 : : releaseContextImplementation ( )
{
if ( ! _realized )
{
osg : : notify ( osg : : NOTICE ) < < " Warning: GraphicsWindow not realized, cannot do makeCurrent. " < < std : : endl ;
return false ;
2007-01-04 00:06:12 +08:00
}
2007-01-09 03:29:59 +08:00
// osg::notify(osg::NOTICE)<<"makeCurrentImplementation "<<this<<" "<<OpenThreads::Thread::CurrentThread()<<std::endl;
// osg::notify(osg::NOTICE)<<" glXMakeCurrent ("<<_display<<","<<_window<<","<<_glxContext<<std::endl;
return glXMakeCurrent ( _display , None , NULL ) = = True ;
2006-12-21 20:19:14 +08:00
}
void GraphicsWindowX11 : : closeImplementation ( )
{
2007-01-04 00:06:12 +08:00
// osg::notify(osg::NOTICE)<<"Closing GraphicsWindowX11"<<std::endl;
2007-02-09 21:51:28 +08:00
if ( _eventDisplay )
2006-12-25 00:40:19 +08:00
{
2007-02-09 21:51:28 +08:00
XCloseDisplay ( _eventDisplay ) ;
_eventDisplay = 0 ;
}
if ( _display )
{
if ( _glxContext )
{
glXDestroyContext ( _display , _glxContext ) ;
}
if ( _window )
{
XDestroyWindow ( _display , _window ) ;
}
2006-12-25 00:40:19 +08:00
XFlush ( _display ) ;
XSync ( _display , 0 ) ;
}
2007-02-08 19:30:57 +08:00
2006-12-21 20:19:14 +08:00
_window = 0 ;
_parent = 0 ;
2007-01-04 22:34:53 +08:00
_glxContext = 0 ;
2006-12-25 00:40:19 +08:00
2007-02-08 19:30:57 +08:00
if ( _visualInfo )
2006-12-21 20:19:14 +08:00
{
XFree ( _visualInfo ) ;
_visualInfo = 0 ;
}
2007-02-09 21:51:28 +08:00
2007-02-08 19:30:57 +08:00
if ( _display )
{
XCloseDisplay ( _display ) ;
_display = 0 ;
}
2006-12-21 20:19:14 +08:00
_initialized = false ;
_realized = false ;
2007-01-04 19:49:15 +08:00
_valid = false ;
2006-12-21 20:19:14 +08:00
}
void GraphicsWindowX11 : : swapBuffersImplementation ( )
{
2006-12-25 00:40:19 +08:00
if ( ! _realized ) return ;
2006-12-23 01:46:21 +08:00
// osg::notify(osg::NOTICE)<<"swapBuffersImplementation "<<this<<" "<<OpenThreads::Thread::CurrentThread()<<std::endl;
2006-12-21 20:19:14 +08:00
glXSwapBuffers ( _display , _window ) ;
2007-02-09 21:51:28 +08:00
while ( XPending ( _display ) )
{
XEvent ev ;
XNextEvent ( _display , & ev ) ;
switch ( ev . type )
{
case ClientMessage :
{
if ( static_cast < Atom > ( ev . xclient . data . l [ 0 ] ) = = _deleteWindow )
{
osg : : notify ( osg : : INFO ) < < " DeleteWindow event recieved " < < std : : endl ;
getEventQueue ( ) - > closeWindow ( ) ;
}
}
}
}
2006-12-21 20:19:14 +08:00
}
void GraphicsWindowX11 : : checkEvents ( )
{
2006-12-25 00:40:19 +08:00
if ( ! _realized ) return ;
2007-04-16 04:53:09 +08:00
Display * display = _eventDisplay ;
2007-02-09 21:51:28 +08:00
2007-01-05 21:01:08 +08:00
double baseTime = _timeOfLastCheckEvents ;
double eventTime = baseTime ;
double resizeTime = eventTime ;
_timeOfLastCheckEvents = getEventQueue ( ) - > getTime ( ) ;
2007-01-02 02:20:10 +08:00
int windowX = _traits - > x ;
int windowY = _traits - > y ;
int windowWidth = _traits - > width ;
int windowHeight = _traits - > height ;
2007-01-05 00:49:58 +08:00
bool destroyWindowRequested = false ;
2007-01-05 21:01:08 +08:00
Time firstEventTime = 0 ;
2007-01-04 07:00:05 +08:00
// osg::notify(osg::NOTICE)<<"Check events"<<std::endl;
2007-02-09 21:51:28 +08:00
while ( XPending ( display ) )
2006-12-21 20:19:14 +08:00
{
XEvent ev ;
2007-02-09 21:51:28 +08:00
XNextEvent ( display , & ev ) ;
2006-12-21 20:19:14 +08:00
switch ( ev . type )
{
2007-01-04 07:00:05 +08:00
case ClientMessage :
{
2007-02-09 21:51:28 +08:00
osg : : notify ( osg : : NOTICE ) < < " ClientMessage event recieved " < < std : : endl ;
2007-01-04 19:49:15 +08:00
if ( static_cast < Atom > ( ev . xclient . data . l [ 0 ] ) = = _deleteWindow )
2007-01-04 07:00:05 +08:00
{
2007-02-09 21:51:28 +08:00
osg : : notify ( osg : : NOTICE ) < < " DeleteWindow event recieved " < < std : : endl ;
2007-01-05 00:49:58 +08:00
destroyWindowRequested = true ;
2007-01-09 03:29:59 +08:00
getEventQueue ( ) - > closeWindow ( eventTime ) ;
2007-01-04 07:00:05 +08:00
}
}
2006-12-21 20:19:14 +08:00
case Expose :
2006-12-22 00:56:20 +08:00
osg : : notify ( osg : : INFO ) < < " Expose x= " < < ev . xexpose . x < < " y= " < < ev . xexpose . y < < " width= " < < ev . xexpose . width < < " , height= " < < ev . xexpose . height < < std : : endl ;
2006-12-21 20:19:14 +08:00
break ;
case GravityNotify :
2007-01-04 19:49:15 +08:00
osg : : notify ( osg : : INFO ) < < " GravityNotify event recieved " < < std : : endl ;
2006-12-21 20:19:14 +08:00
break ;
case UnmapNotify :
2007-01-04 19:49:15 +08:00
osg : : notify ( osg : : INFO ) < < " UnmapNotify event recieved " < < std : : endl ;
2006-12-21 20:19:14 +08:00
break ;
case ReparentNotify :
2007-01-04 19:49:15 +08:00
osg : : notify ( osg : : INFO ) < < " ReparentNotify event recieved " < < std : : endl ;
2006-12-21 20:19:14 +08:00
break ;
case DestroyNotify :
2007-02-09 21:51:28 +08:00
osg : : notify ( osg : : NOTICE ) < < " DestroyNotify event recieved " < < std : : endl ;
2006-12-21 20:19:14 +08:00
_realized = false ;
2007-01-04 19:49:15 +08:00
_valid = false ;
2006-12-21 20:19:14 +08:00
break ;
case ConfigureNotify :
{
2006-12-22 00:56:20 +08:00
osg : : notify ( osg : : INFO ) < < " ConfigureNotify x= " < < ev . xconfigure . x < < " y= " < < ev . xconfigure . y < < " width= " < < ev . xconfigure . width < < " , height= " < < ev . xconfigure . height < < std : : endl ;
2006-12-21 20:19:14 +08:00
2007-01-02 02:20:10 +08:00
if ( windowX ! = ev . xconfigure . x | |
windowX ! = ev . xconfigure . y | |
windowWidth ! = ev . xconfigure . width | |
windowHeight ! = ev . xconfigure . height )
{
2007-01-05 21:01:08 +08:00
resizeTime = eventTime ;
2007-01-02 02:20:10 +08:00
windowX = ev . xconfigure . x ;
windowY = ev . xconfigure . y ;
windowWidth = ev . xconfigure . width ;
windowHeight = ev . xconfigure . height ;
}
2006-12-21 20:19:14 +08:00
break ;
}
case MapNotify :
{
2006-12-23 01:46:21 +08:00
osg : : notify ( osg : : INFO ) < < " MapNotify " < < std : : endl ;
2006-12-21 20:19:14 +08:00
XWindowAttributes watt ;
do
2007-02-09 21:51:28 +08:00
XGetWindowAttributes ( display , _window , & watt ) ;
2006-12-21 20:19:14 +08:00
while ( watt . map_state ! = IsViewable ) ;
2006-12-23 01:46:21 +08:00
osg : : notify ( osg : : INFO ) < < " MapNotify x= " < < watt . x < < " y= " < < watt . y < < " width= " < < watt . width < < " , height= " < < watt . height < < std : : endl ;
2007-01-02 02:20:10 +08:00
if ( windowWidth ! = watt . width | | windowHeight ! = watt . height )
{
2007-01-05 21:01:08 +08:00
resizeTime = eventTime ;
2007-01-02 02:20:10 +08:00
windowWidth = watt . width ;
windowHeight = watt . height ;
}
2006-12-21 20:19:14 +08:00
break ;
}
case MotionNotify :
{
2007-01-05 21:01:08 +08:00
if ( firstEventTime = = 0 ) firstEventTime = ev . xmotion . time ;
Time relativeTime = ev . xmotion . time - firstEventTime ;
eventTime = baseTime + static_cast < double > ( relativeTime ) * 0.001 ;
2006-12-27 01:38:47 +08:00
2006-12-21 20:19:14 +08:00
int wx , wy ;
Window win = 0L ;
if ( ev . xmotion . same_screen )
{
wx = ev . xmotion . x ;
wy = ev . xmotion . y ;
}
else
{
// the mouse in on another screen so need to compute the
// coordinates of the mouse position relative to an absolute position
// then take away the position of the original window/screen to get
// the coordinates relative to the original position.
Window root ;
int rx , ry ;
unsigned int buttons ;
int screenOrigin_x = 0 ;
int screenOrigin_y = 0 ;
int i ;
2007-02-09 21:51:28 +08:00
for ( i = 0 ; i < ScreenCount ( display ) ; i + + )
2006-12-21 20:19:14 +08:00
{
2007-02-09 21:51:28 +08:00
if ( XQueryPointer ( display , RootWindow ( display , i ) ,
2006-12-21 20:19:14 +08:00
& root , & win , & rx , & ry , & wx , & wy , & buttons ) )
{
break ;
}
2007-02-09 21:51:28 +08:00
screenOrigin_x + = DisplayWidth ( display , i ) ;
2006-12-21 20:19:14 +08:00
}
2006-12-23 05:53:44 +08:00
for ( i = 0 ; i < static_cast < int > ( _traits - > screenNum ) ; i + + )
2006-12-21 20:19:14 +08:00
{
2007-02-09 21:51:28 +08:00
screenOrigin_x - = DisplayWidth ( display , i ) ;
2006-12-21 20:19:14 +08:00
}
int dest_x_return , dest_y_return ;
Window child_return ;
2007-02-09 21:51:28 +08:00
XTranslateCoordinates ( display , _window , _parent , 0 , 0 , & dest_x_return , & dest_y_return , & child_return ) ;
2006-12-21 20:19:14 +08:00
wx + = ( screenOrigin_x - dest_x_return ) ;
wy + = ( screenOrigin_y - dest_y_return ) ;
}
float mx = wx ;
float my = wy ;
transformMouseXY ( mx , my ) ;
2007-01-05 21:01:08 +08:00
getEventQueue ( ) - > mouseMotion ( mx , my , eventTime ) ;
2006-12-21 20:19:14 +08:00
// osg::notify(osg::NOTICE)<<"MotionNotify wx="<<wx<<" wy="<<wy<<" mx="<<mx<<" my="<<my<<std::endl;
break ;
}
case ButtonPress :
{
2007-01-05 21:01:08 +08:00
if ( firstEventTime = = 0 ) firstEventTime = ev . xmotion . time ;
Time relativeTime = ev . xmotion . time - firstEventTime ;
eventTime = baseTime + static_cast < double > ( relativeTime ) * 0.001 ;
2006-12-21 20:19:14 +08:00
if ( ev . xbutton . button = = Button4 )
{
2007-01-05 21:01:08 +08:00
getEventQueue ( ) - > mouseScroll ( osgGA : : GUIEventAdapter : : SCROLL_UP , eventTime ) ;
2006-12-21 20:19:14 +08:00
}
else if ( ev . xbutton . button = = Button5 )
{
2007-01-05 21:01:08 +08:00
getEventQueue ( ) - > mouseScroll ( osgGA : : GUIEventAdapter : : SCROLL_DOWN , eventTime ) ;
2006-12-21 20:19:14 +08:00
}
else
{
float mx = ev . xbutton . x ;
float my = ev . xmotion . y ;
transformMouseXY ( mx , my ) ;
2007-01-05 21:01:08 +08:00
getEventQueue ( ) - > mouseButtonPress ( mx , my , ev . xbutton . button , eventTime ) ;
2006-12-21 20:19:14 +08:00
}
break ;
}
case ButtonRelease :
{
2007-01-05 21:01:08 +08:00
if ( firstEventTime = = 0 ) firstEventTime = ev . xmotion . time ;
Time relativeTime = ev . xmotion . time - firstEventTime ;
eventTime = baseTime + static_cast < double > ( relativeTime ) * 0.001 ;
2006-12-21 20:19:14 +08:00
if ( ev . xbutton . button = = Button4 )
{
2007-01-05 21:01:08 +08:00
getEventQueue ( ) - > mouseScroll ( osgGA : : GUIEventAdapter : : SCROLL_UP , eventTime ) ;
2006-12-21 20:19:14 +08:00
}
else if ( ev . xbutton . button = = Button5 )
{
2007-01-05 21:01:08 +08:00
getEventQueue ( ) - > mouseScroll ( osgGA : : GUIEventAdapter : : SCROLL_DOWN , eventTime ) ;
2006-12-21 20:19:14 +08:00
}
else
{
float mx = ev . xbutton . x ;
float my = ev . xmotion . y ;
transformMouseXY ( mx , my ) ;
2007-01-05 21:01:08 +08:00
getEventQueue ( ) - > mouseButtonRelease ( mx , my , ev . xbutton . button , eventTime ) ;
2006-12-21 20:19:14 +08:00
}
break ;
}
case KeyPress :
{
2007-01-05 21:01:08 +08:00
if ( firstEventTime = = 0 ) firstEventTime = ev . xmotion . time ;
Time relativeTime = ev . xmotion . time - firstEventTime ;
eventTime = baseTime + static_cast < double > ( relativeTime ) * 0.001 ;
2006-12-21 20:19:14 +08:00
int keySymbol = 0 ;
unsigned int modifierMask = 0 ;
adaptKey ( ev . xkey , keySymbol , modifierMask ) ;
getEventQueue ( ) - > getCurrentEventState ( ) - > setModKeyMask ( modifierMask ) ;
2007-04-25 17:32:12 +08:00
getEventQueue ( ) - > keyPress ( keySymbol , eventTime ) ;
2006-12-21 20:19:14 +08:00
break ;
}
case KeyRelease :
{
2007-01-05 21:01:08 +08:00
if ( firstEventTime = = 0 ) firstEventTime = ev . xmotion . time ;
Time relativeTime = ev . xmotion . time - firstEventTime ;
eventTime = baseTime + static_cast < double > ( relativeTime ) * 0.001 ;
2006-12-21 20:19:14 +08:00
int keySymbol = 0 ;
unsigned int modifierMask = 0 ;
adaptKey ( ev . xkey , keySymbol , modifierMask ) ;
getEventQueue ( ) - > getCurrentEventState ( ) - > setModKeyMask ( modifierMask ) ;
2007-04-25 17:32:12 +08:00
getEventQueue ( ) - > keyRelease ( keySymbol , eventTime ) ;
2006-12-21 20:19:14 +08:00
break ;
}
default :
osg : : notify ( osg : : NOTICE ) < < " Other event " < < std : : endl ;
break ;
}
}
2007-01-02 02:20:10 +08:00
if ( windowX ! = _traits - > x | |
windowY ! = _traits - > y | |
windowWidth ! = _traits - > width | |
windowHeight ! = _traits - > height )
{
resized ( windowX , windowY , windowWidth , windowHeight ) ;
2007-01-05 21:01:08 +08:00
getEventQueue ( ) - > windowResize ( windowX , windowY , windowWidth , windowHeight , resizeTime ) ;
2007-01-02 02:20:10 +08:00
}
2007-01-09 03:29:59 +08:00
#if 0
2007-01-05 00:49:58 +08:00
if ( destroyWindowRequested )
{
close ( ) ;
}
2007-01-09 03:29:59 +08:00
# endif
2006-12-21 20:19:14 +08:00
}
void GraphicsWindowX11 : : grabFocus ( )
{
2007-04-13 21:22:52 +08:00
Display * display = getDisplayToUse ( ) ;
XSetInputFocus ( display , _window , RevertToNone , CurrentTime ) ;
XFlush ( display ) ;
XSync ( display , 0 ) ;
2006-12-21 20:19:14 +08:00
}
void GraphicsWindowX11 : : grabFocusIfPointerInWindow ( )
{
Window win , root ;
int wx , wy , rx , ry ;
unsigned int buttons ;
2007-04-13 21:22:52 +08:00
Display * display = getDisplayToUse ( ) ;
if ( XQueryPointer ( display , _window ,
2006-12-21 20:19:14 +08:00
& root , & win , & rx , & ry , & wx , & wy , & buttons ) )
{
2007-02-09 21:51:28 +08:00
#if 0
if ( wx > = 0 & & wx < _traits - > width & &
wy > = 0 & & wy < _traits - > height )
{
grabFocus ( ) ;
}
# else
2006-12-21 20:19:14 +08:00
grabFocus ( ) ;
2007-02-09 21:51:28 +08:00
# endif
2006-12-21 20:19:14 +08:00
}
}
void GraphicsWindowX11 : : transformMouseXY ( float & x , float & y )
{
if ( getEventQueue ( ) - > getUseFixedMouseInputRange ( ) )
{
osgGA : : GUIEventAdapter * eventState = getEventQueue ( ) - > getCurrentEventState ( ) ;
2006-12-23 05:53:44 +08:00
x = eventState - > getXmin ( ) + ( eventState - > getXmax ( ) - eventState - > getXmin ( ) ) * x / float ( _traits - > width ) ;
y = eventState - > getYmin ( ) + ( eventState - > getYmax ( ) - eventState - > getYmin ( ) ) * y / float ( _traits - > height ) ;
2006-12-21 20:19:14 +08:00
}
}
void GraphicsWindowX11 : : adaptKey ( XKeyEvent & keyevent , int & keySymbol , unsigned int & modifierMask )
{
2007-04-16 04:53:09 +08:00
Display * display = _eventDisplay ;
2007-01-02 02:20:10 +08:00
2006-12-21 20:19:14 +08:00
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 ] ;
2007-01-02 02:20:10 +08:00
2007-04-13 21:22:52 +08:00
KeySym ks = XKeycodeToKeysym ( display , keyevent . keycode , 0 ) ;
2007-01-02 02:20:10 +08:00
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 )
{
2007-04-13 21:22:52 +08:00
Display * display = getDisplayToUse ( ) ;
XWarpPointer ( display ,
2007-01-02 02:20:10 +08:00
None ,
_window ,
0 , 0 , 0 , 0 ,
static_cast < int > ( x ) , static_cast < int > ( y ) ) ;
2007-04-13 21:22:52 +08:00
XFlush ( display ) ;
XSync ( display , 0 ) ;
2007-01-02 04:01:45 +08:00
getEventQueue ( ) - > mouseWarped ( x , y ) ;
2006-12-21 20:19:14 +08:00
}
2007-04-14 16:31:40 +08:00
extern " C "
{
2007-01-04 00:06:12 +08:00
int X11ErrorHandling ( Display * display , XErrorEvent * event )
{
2007-01-04 19:49:15 +08:00
osg : : notify ( osg : : NOTICE ) < < " Got an X11ErrorHandling call display= " < < display < < " event= " < < event < < std : : endl ;
2007-02-08 19:26:04 +08:00
char buffer [ 256 ] ;
XGetErrorText ( display , event - > error_code , buffer , 256 ) ;
osg : : notify ( osg : : NOTICE ) < < buffer < < std : : endl ;
osg : : notify ( osg : : NOTICE ) < < " Major opcode: " < < ( int ) event - > 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 ;
}
2007-01-04 19:49:15 +08:00
return 0 ;
2007-01-04 00:06:12 +08:00
}
2007-04-14 16:31:40 +08:00
}
2007-01-04 00:06:12 +08:00
2006-12-21 20:19:14 +08:00
struct X11WindowingSystemInterface : public osg : : GraphicsContext : : WindowingSystemInterface
{
X11WindowingSystemInterface ( )
{
2007-01-04 00:06:12 +08:00
XSetErrorHandler ( X11ErrorHandling ) ;
2007-02-09 21:51:28 +08:00
#if 0
2006-12-23 01:46:21 +08:00
if ( XInitThreads ( ) = = 0 )
{
osg : : notify ( osg : : NOTICE ) < < " Error: XInitThreads() failed. Aborting. " < < std : : endl ;
exit ( 1 ) ;
}
else
{
osg : : notify ( osg : : INFO ) < < " X11WindowingSystemInterface, xInitThreads() multi-threaded X support initialized. \n " ;
}
# endif
2006-12-21 20:19:14 +08:00
}
2007-01-04 00:06:12 +08:00
~ X11WindowingSystemInterface ( )
{
XSetErrorHandler ( 0 ) ;
}
2006-12-21 20:19:14 +08:00
virtual unsigned int getNumScreens ( const osg : : GraphicsContext : : ScreenIdentifier & si )
{
2006-12-23 05:53:44 +08:00
Display * display = XOpenDisplay ( si . displayName ( ) . c_str ( ) ) ;
2006-12-21 20:19:14 +08:00
if ( display )
{
unsigned int numScreens = ScreenCount ( display ) ;
XCloseDisplay ( display ) ;
return numScreens ;
}
else
{
2006-12-25 00:40:19 +08:00
osg : : notify ( osg : : NOTICE ) < < " A Unable to open display \" " < < XDisplayName ( si . displayName ( ) . c_str ( ) ) < < " \" " < < std : : endl ;
2006-12-21 20:19:14 +08:00
return 0 ;
}
}
virtual void getScreenResolution ( const osg : : GraphicsContext : : ScreenIdentifier & si , unsigned int & width , unsigned int & height )
{
2006-12-25 00:40:19 +08:00
Display * display = XOpenDisplay ( si . displayName ( ) . c_str ( ) ) ;
2006-12-21 20:19:14 +08:00
if ( display )
{
2006-12-23 05:53:44 +08:00
width = DisplayWidth ( display , si . screenNum ) ;
height = DisplayHeight ( display , si . screenNum ) ;
2006-12-21 20:19:14 +08:00
XCloseDisplay ( display ) ;
}
else
{
2006-12-25 00:40:19 +08:00
osg : : notify ( osg : : NOTICE ) < < " Unable to open display \" " < < XDisplayName ( si . displayName ( ) . c_str ( ) ) < < " \" . " < < std : : endl ;
2006-12-21 20:19:14 +08:00
width = 0 ;
height = 0 ;
}
}
virtual osg : : GraphicsContext * createGraphicsContext ( osg : : GraphicsContext : : Traits * traits )
{
2006-12-23 05:53:44 +08:00
if ( traits - > pbuffer )
2006-12-21 20:19:14 +08:00
{
2006-12-25 00:40:19 +08:00
osg : : ref_ptr < osgViewer : : GraphicsContextX11 > pbuffer = new GraphicsContextX11 ( traits ) ;
if ( pbuffer - > valid ( ) ) return pbuffer . release ( ) ;
else return 0 ;
2006-12-21 20:19:14 +08:00
}
else
{
2006-12-25 00:40:19 +08:00
osg : : ref_ptr < osgViewer : : GraphicsWindowX11 > window = new GraphicsWindowX11 ( traits ) ;
if ( window - > valid ( ) ) return window . release ( ) ;
else return 0 ;
2006-12-21 20:19:14 +08:00
}
}
} ;
struct RegisterWindowingSystemInterfaceProxy
{
RegisterWindowingSystemInterfaceProxy ( )
{
osg : : GraphicsContext : : setWindowingSystemInterface ( new X11WindowingSystemInterface ) ;
}
~ RegisterWindowingSystemInterfaceProxy ( )
{
osg : : GraphicsContext : : setWindowingSystemInterface ( 0 ) ;
}
} ;
RegisterWindowingSystemInterfaceProxy createWindowingSystemInterfaceProxy ;