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:
parent
21de9e4acc
commit
7772da71eb
@ -42,6 +42,15 @@ class OSGVIEWER_EXPORT GraphicsWindow : public osg::GraphicsContext, public osgG
|
||||
|
||||
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:
|
||||
|
||||
/** Realise the GraphicsContext implementation,
|
||||
|
@ -124,10 +124,18 @@ class GraphicsWindowX11 : public osgViewer::GraphicsWindow
|
||||
/** Check to see if any events have been generated.*/
|
||||
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:
|
||||
|
||||
bool createVisualInfo();
|
||||
void setBorder(bool flag);
|
||||
void init();
|
||||
|
||||
void transformMouseXY(float& x, float& y);
|
||||
@ -184,7 +192,7 @@ bool GraphicsWindowX11::createVisualInfo()
|
||||
return _visualInfo != 0;
|
||||
}
|
||||
|
||||
void GraphicsWindowX11::setBorder(bool flag)
|
||||
void GraphicsWindowX11::setWindowDecoration(bool flag)
|
||||
{
|
||||
Atom atom;
|
||||
if( (atom = XInternAtom( _display, "_MOTIF_WM_HINTS", 0 )) != None )
|
||||
@ -239,6 +247,14 @@ void GraphicsWindowX11::setBorder(bool flag)
|
||||
|
||||
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
|
||||
|
||||
}
|
||||
else
|
||||
osg::notify(osg::NOTICE)<<"Error: GraphicsWindowX11::setBorder(" << flag << ") - couldn't change decorations." << std::endl;
|
||||
@ -298,7 +314,7 @@ void GraphicsWindowX11::init()
|
||||
|
||||
XSetWindowAttributes swatt;
|
||||
swatt.colormap = XCreateColormap( _display, _parent, _visualInfo->visual, AllocNone);
|
||||
//swatt.colormap = DefaultColormap( _dpy, 0 );
|
||||
//swatt.colormap = DefaultColormap( _dpy, 10 );
|
||||
swatt.background_pixel = 0;
|
||||
swatt.border_pixel = 0;
|
||||
swatt.event_mask = 0;
|
||||
@ -337,14 +353,15 @@ void GraphicsWindowX11::init()
|
||||
sh.height = _traits->_height;
|
||||
XSetStandardProperties( _display, _window, _traits->_windowName.c_str(), _traits->_windowName.c_str(), None, 0, 0, &sh);
|
||||
|
||||
#if 1
|
||||
setBorder(_traits->_windowDecoration);
|
||||
#if 0
|
||||
setWindowDecoration(_traits->_windowDecoration);
|
||||
#else
|
||||
setBorder(true);
|
||||
setWindowDecoration(true);
|
||||
#endif
|
||||
// Create default Cursor
|
||||
_defaultCursor = XCreateFontCursor( _display, XC_left_ptr );
|
||||
|
||||
|
||||
// Create Null Cursor
|
||||
{
|
||||
Pixmap pixmap;
|
||||
@ -374,6 +391,14 @@ void GraphicsWindowX11::init()
|
||||
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 );
|
||||
_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;
|
||||
}
|
||||
|
||||
@ -439,7 +464,7 @@ void GraphicsWindowX11::checkEvents()
|
||||
switch( ev.type )
|
||||
{
|
||||
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;
|
||||
|
||||
case GravityNotify :
|
||||
@ -462,6 +487,10 @@ void GraphicsWindowX11::checkEvents()
|
||||
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;
|
||||
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->_y = ev.xconfigure.y;
|
||||
_traits->_width = ev.xconfigure.width;
|
||||
@ -477,9 +506,10 @@ void GraphicsWindowX11::checkEvents()
|
||||
do
|
||||
XGetWindowAttributes(_display, _window, &watt );
|
||||
while( watt.map_state != IsViewable );
|
||||
|
||||
XSetInputFocus( _display, _window, RevertToNone, CurrentTime );
|
||||
XFlush(_display); XSync(_display,0);
|
||||
|
||||
osg::notify(osg::NOTICE)<<"MapNotify x="<<watt.x<<" y="<<watt.y<<" width="<<watt.width<<", height="<<watt.height<<std::endl;
|
||||
_traits->_width = watt.width;
|
||||
_traits->_height = watt.height;
|
||||
|
||||
break;
|
||||
}
|
||||
@ -522,15 +552,22 @@ void GraphicsWindowX11::checkEvents()
|
||||
screenOrigin_x -= DisplayWidth(_display, i);
|
||||
}
|
||||
|
||||
wx += (screenOrigin_x - _traits->_x);
|
||||
wy += (screenOrigin_y - _traits->_y);
|
||||
int dest_x_return, dest_y_return;
|
||||
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 my = wy;
|
||||
transformMouseXY(mx, my);
|
||||
getEventQueue()->mouseMotion(mx, my);
|
||||
|
||||
// osg::notify(osg::NOTICE)<<"MotionNotify wx="<<wx<<" wy="<<wy<<" mx="<<mx<<" my="<<my<<std::endl;
|
||||
|
||||
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)
|
||||
{
|
||||
if (getEventQueue()->getUseFixedMouseInputRange())
|
||||
|
@ -70,6 +70,29 @@ void Viewer::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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user