Improved the handling of moving the mouse pointer across screens, and add

grab focus support that honours where the mouse pointer was originally.
This commit is contained in:
Robert Osfield 2006-12-21 11:20:42 +00:00
parent 21de9e4acc
commit 7772da71eb
3 changed files with 101 additions and 12 deletions

View File

@ -42,6 +42,15 @@ class OSGVIEWER_EXPORT GraphicsWindow : public osg::GraphicsContext, public osgG
virtual void checkEvents() {} virtual void checkEvents() {}
/** Set Window decoration.*/
virtual void setWindowDecoration(bool /*flag*/) {}
/** Get focus.*/
virtual void grabFocus() {}
/** Get focus on if the pointer is in this window.*/
virtual void grabFocusIfPointerInWindow() {}
public: public:
/** Realise the GraphicsContext implementation, /** Realise the GraphicsContext implementation,

View File

@ -124,10 +124,18 @@ class GraphicsWindowX11 : public osgViewer::GraphicsWindow
/** Check to see if any events have been generated.*/ /** Check to see if any events have been generated.*/
virtual void checkEvents(); virtual void checkEvents();
/** Set Window decoration.*/
virtual void setWindowDecoration(bool flag);
/** Get focus.*/
virtual void grabFocus();
/** Get focus on if the pointer is in this window.*/
virtual void grabFocusIfPointerInWindow();
protected: protected:
bool createVisualInfo(); bool createVisualInfo();
void setBorder(bool flag);
void init(); void init();
void transformMouseXY(float& x, float& y); void transformMouseXY(float& x, float& y);
@ -184,7 +192,7 @@ bool GraphicsWindowX11::createVisualInfo()
return _visualInfo != 0; return _visualInfo != 0;
} }
void GraphicsWindowX11::setBorder(bool flag) void GraphicsWindowX11::setWindowDecoration(bool flag)
{ {
Atom atom; Atom atom;
if( (atom = XInternAtom( _display, "_MOTIF_WM_HINTS", 0 )) != None ) if( (atom = XInternAtom( _display, "_MOTIF_WM_HINTS", 0 )) != None )
@ -239,6 +247,14 @@ void GraphicsWindowX11::setBorder(bool flag)
XFlush(_display); XFlush(_display);
XSync(_display,0); 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
} }
else else
osg::notify(osg::NOTICE)<<"Error: GraphicsWindowX11::setBorder(" << flag << ") - couldn't change decorations." << std::endl; osg::notify(osg::NOTICE)<<"Error: GraphicsWindowX11::setBorder(" << flag << ") - couldn't change decorations." << std::endl;
@ -298,7 +314,7 @@ void GraphicsWindowX11::init()
XSetWindowAttributes swatt; XSetWindowAttributes swatt;
swatt.colormap = XCreateColormap( _display, _parent, _visualInfo->visual, AllocNone); swatt.colormap = XCreateColormap( _display, _parent, _visualInfo->visual, AllocNone);
//swatt.colormap = DefaultColormap( _dpy, 0 ); //swatt.colormap = DefaultColormap( _dpy, 10 );
swatt.background_pixel = 0; swatt.background_pixel = 0;
swatt.border_pixel = 0; swatt.border_pixel = 0;
swatt.event_mask = 0; swatt.event_mask = 0;
@ -337,14 +353,15 @@ void GraphicsWindowX11::init()
sh.height = _traits->_height; sh.height = _traits->_height;
XSetStandardProperties( _display, _window, _traits->_windowName.c_str(), _traits->_windowName.c_str(), None, 0, 0, &sh); XSetStandardProperties( _display, _window, _traits->_windowName.c_str(), _traits->_windowName.c_str(), None, 0, 0, &sh);
#if 1 #if 0
setBorder(_traits->_windowDecoration); setWindowDecoration(_traits->_windowDecoration);
#else #else
setBorder(true); setWindowDecoration(true);
#endif #endif
// Create default Cursor // Create default Cursor
_defaultCursor = XCreateFontCursor( _display, XC_left_ptr ); _defaultCursor = XCreateFontCursor( _display, XC_left_ptr );
// Create Null Cursor // Create Null Cursor
{ {
Pixmap pixmap; Pixmap pixmap;
@ -374,6 +391,14 @@ void GraphicsWindowX11::init()
XFlush( _display ); XFlush( _display );
XSync( _display, 0 ); XSync( _display, 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;
//osg::notify(osg::NOTICE)<<"After sync apply.x = "<<watt.x<<" watt.y="<<watt.y<<" width="<<watt.width<<" height="<<watt.height<<std::endl;
_initialized = true; _initialized = true;
} }
@ -439,7 +464,7 @@ void GraphicsWindowX11::checkEvents()
switch( ev.type ) switch( ev.type )
{ {
case Expose : case Expose :
osg::notify(osg::NOTICE)<<"Expose"<<std::endl; osg::notify(osg::NOTICE)<<"Expose x="<<ev.xexpose.x<<" y="<<ev.xexpose.y<<" width="<<ev.xexpose.width<<", height="<<ev.xexpose.height<<std::endl;
break; break;
case GravityNotify : case GravityNotify :
@ -462,6 +487,10 @@ void GraphicsWindowX11::checkEvents()
case ConfigureNotify : case ConfigureNotify :
{ {
osg::notify(osg::NOTICE)<<"ConfigureNotify x="<<ev.xconfigure.x<<" y="<<ev.xconfigure.y<<" width="<<ev.xconfigure.width<<", height="<<ev.xconfigure.height<<std::endl; osg::notify(osg::NOTICE)<<"ConfigureNotify x="<<ev.xconfigure.x<<" y="<<ev.xconfigure.y<<" width="<<ev.xconfigure.width<<", height="<<ev.xconfigure.height<<std::endl;
XWindowAttributes watt;
XGetWindowAttributes( _display, _window, &watt );
osg::notify(osg::NOTICE)<<"After sync apply.x = "<<watt.x<<" watt.y="<<watt.y<<" width="<<watt.width<<" height="<<watt.height<<std::endl;
_traits->_x = ev.xconfigure.x; _traits->_x = ev.xconfigure.x;
_traits->_y = ev.xconfigure.y; _traits->_y = ev.xconfigure.y;
_traits->_width = ev.xconfigure.width; _traits->_width = ev.xconfigure.width;
@ -477,9 +506,10 @@ void GraphicsWindowX11::checkEvents()
do do
XGetWindowAttributes(_display, _window, &watt ); XGetWindowAttributes(_display, _window, &watt );
while( watt.map_state != IsViewable ); while( watt.map_state != IsViewable );
XSetInputFocus( _display, _window, RevertToNone, CurrentTime ); osg::notify(osg::NOTICE)<<"MapNotify x="<<watt.x<<" y="<<watt.y<<" width="<<watt.width<<", height="<<watt.height<<std::endl;
XFlush(_display); XSync(_display,0); _traits->_width = watt.width;
_traits->_height = watt.height;
break; break;
} }
@ -522,15 +552,22 @@ void GraphicsWindowX11::checkEvents()
screenOrigin_x -= DisplayWidth(_display, i); screenOrigin_x -= DisplayWidth(_display, i);
} }
wx += (screenOrigin_x - _traits->_x); int dest_x_return, dest_y_return;
wy += (screenOrigin_y - _traits->_y); Window child_return;
Bool result = XTranslateCoordinates(_display, _window, _parent, 0, 0, &dest_x_return, &dest_y_return, &child_return);
wx += (screenOrigin_x - dest_x_return);
wy += (screenOrigin_y - dest_y_return);
} }
float mx = wx; float mx = wx;
float my = wy; float my = wy;
transformMouseXY(mx, my); transformMouseXY(mx, my);
getEventQueue()->mouseMotion(mx, my); getEventQueue()->mouseMotion(mx, my);
// osg::notify(osg::NOTICE)<<"MotionNotify wx="<<wx<<" wy="<<wy<<" mx="<<mx<<" my="<<my<<std::endl;
break; break;
} }
@ -604,6 +641,26 @@ void GraphicsWindowX11::checkEvents()
} }
} }
void GraphicsWindowX11::grabFocus()
{
XSetInputFocus( _display, _window, RevertToNone, CurrentTime );
XFlush(_display); XSync(_display,0);
}
void GraphicsWindowX11::grabFocusIfPointerInWindow()
{
Window win, root;
int wx, wy, rx, ry;
unsigned int buttons;
if( XQueryPointer( _display, _window,
&root, &win, &rx, &ry, &wx, &wy, &buttons))
{
grabFocus();
}
}
void GraphicsWindowX11::transformMouseXY(float& x, float& y) void GraphicsWindowX11::transformMouseXY(float& x, float& y)
{ {
if (getEventQueue()->getUseFixedMouseInputRange()) if (getEventQueue()->getUseFixedMouseInputRange())

View File

@ -70,6 +70,29 @@ void Viewer::realize()
slave._camera->getGraphicsContext()->realize(); slave._camera->getGraphicsContext()->realize();
} }
} }
bool grabFocus = true;
if (grabFocus)
{
if (_camera.valid() && _camera->getGraphicsContext())
{
osgViewer::GraphicsWindow* gw = dynamic_cast<osgViewer::GraphicsWindow*>(_camera->getGraphicsContext());
gw->grabFocusIfPointerInWindow();
}
for(unsigned int i=0; i<getNumSlaves(); ++i)
{
Slave& slave = getSlave(i);
if (slave._camera.valid() && slave._camera->getGraphicsContext())
{
osg::notify(osg::NOTICE)<<" slave realize()"<<std::endl;
slave._camera->getGraphicsContext()->realize();
osgViewer::GraphicsWindow* gw = dynamic_cast<osgViewer::GraphicsWindow*>(slave._camera->getGraphicsContext());
gw->grabFocusIfPointerInWindow();
}
}
}
} }