From 271cf1420db9c5970cf5ba3715723ec0ec9a2cf1 Mon Sep 17 00:00:00 2001 From: Thomas Geymayer Date: Mon, 11 Aug 2014 00:23:10 +0200 Subject: [PATCH] Canvas: support for pointer grab. --- src/Canvas/gui_mgr.cxx | 105 ++++++++++++++++++++++++---------- src/Canvas/gui_mgr.hxx | 11 ++++ src/Scripting/NasalCanvas.cxx | 15 +++++ 3 files changed, 100 insertions(+), 31 deletions(-) diff --git a/src/Canvas/gui_mgr.cxx b/src/Canvas/gui_mgr.cxx index b5ac7155e..6b38d523c 100644 --- a/src/Canvas/gui_mgr.cxx +++ b/src/Canvas/gui_mgr.cxx @@ -103,6 +103,10 @@ class DesktopGroup: DesktopGroup(); void setFocusWindow(const sc::WindowPtr& window); + + bool grabPointer(const sc::WindowPtr& window); + void ungrabPointer(const sc::WindowPtr& window); + bool handleEvent(const osgGA::GUIEventAdapter& ea); protected: @@ -118,7 +122,8 @@ class DesktopGroup: sc::WindowWeakPtr _last_push, _last_mouse_over, _resize_window, - _focus_window; + _focus_window, + _pointer_grab_window; uint8_t _resize; int _last_cursor; @@ -210,6 +215,35 @@ DesktopGroup::DesktopGroup(): _width = _height = -1; } +//------------------------------------------------------------------------------ +void DesktopGroup::setFocusWindow(const sc::WindowPtr& window) +{ + _focus_window = window; +} + +//------------------------------------------------------------------------------ +bool DesktopGroup::grabPointer(const sc::WindowPtr& window) +{ + sc::WindowPtr resize = _resize_window.lock(); + if( (resize && resize != window) || !_pointer_grab_window.expired() ) + // Already grabbed (resize -> implicit grab) + return false; + + _pointer_grab_window = window; + return true; +} + +//------------------------------------------------------------------------------ +void DesktopGroup::ungrabPointer(const sc::WindowPtr& window) +{ + if( _pointer_grab_window.expired() ) + SG_LOG(SG_GUI, SG_WARN, "ungrabPointer: no active grab."); + else if( window != _pointer_grab_window.lock() ) + SG_LOG(SG_GUI, SG_WARN, "ungrabPointer: window is not owner of the grab."); + else + _pointer_grab_window.reset(); +} + //------------------------------------------------------------------------------ bool DesktopGroup::handleEvent(const osgGA::GUIEventAdapter& ea) { @@ -237,12 +271,6 @@ bool DesktopGroup::handleEvent(const osgGA::GUIEventAdapter& ea) } } -//------------------------------------------------------------------------------ -void DesktopGroup::setFocusWindow(const sc::WindowPtr& window) -{ - _focus_window = window; -} - /* RESIZE AREAS ============ @@ -301,32 +329,35 @@ bool DesktopGroup::handleMouse(const osgGA::GUIEventAdapter& ea) } } - sc::WindowPtr window_at_cursor; - for( int i = _transform->getNumChildren() - 1; i >= 0; --i ) + sc::WindowPtr window_at_cursor = _pointer_grab_window.lock(); + if( !window_at_cursor ) { - osg::Group *element = _transform->getChild(i)->asGroup(); - - assert(element); - assert(element->getUserData()); - - sc::WindowPtr window = - dynamic_cast - ( - static_cast( - element->getUserData() - )->element.get() - ); - - if( !window || !window->isCapturingEvents() || !window->isVisible() ) - continue; - - float margin = window->isResizable() ? resize_margin_pos : 0; - if( window->getScreenRegion().contains( event->getScreenX(), - event->getScreenY(), - margin ) ) + for( int i = _transform->getNumChildren() - 1; i >= 0; --i ) { - window_at_cursor = window; - break; + osg::Group *element = _transform->getChild(i)->asGroup(); + + assert(element); + assert(element->getUserData()); + + sc::WindowPtr window = + dynamic_cast + ( + static_cast( + element->getUserData() + )->element.get() + ); + + if( !window || !window->isCapturingEvents() || !window->isVisible() ) + continue; + + float margin = window->isResizable() ? resize_margin_pos : 0; + if( window->getScreenRegion().contains( event->getScreenX(), + event->getScreenY(), + margin ) ) + { + window_at_cursor = window; + break; + } } } @@ -650,6 +681,18 @@ void GUIMgr::setInputFocus(const simgear::canvas::WindowPtr& window) static_cast(_desktop.get())->setFocusWindow(window); } +//------------------------------------------------------------------------------ +bool GUIMgr::grabPointer(const sc::WindowPtr& window) +{ + return static_cast(_desktop.get())->grabPointer(window); +} + +//------------------------------------------------------------------------------ +void GUIMgr::ungrabPointer(const sc::WindowPtr& window) +{ + static_cast(_desktop.get())->ungrabPointer(window); +} + //------------------------------------------------------------------------------ sc::Placements GUIMgr::addWindowPlacement( SGPropertyNode* placement, diff --git a/src/Canvas/gui_mgr.hxx b/src/Canvas/gui_mgr.hxx index c2cd341cd..30ba7c9c7 100644 --- a/src/Canvas/gui_mgr.hxx +++ b/src/Canvas/gui_mgr.hxx @@ -57,6 +57,17 @@ class GUIMgr: */ void setInputFocus(const simgear::canvas::WindowPtr& window); + /** + * Grabs the pointer so that all events are passed to this @a window until + * the pointer is ungrabbed with ungrabPointer(). + */ + bool grabPointer(const simgear::canvas::WindowPtr& window); + + /** + * Releases the grab acquired for this @a window with grabPointer(). + */ + void ungrabPointer(const simgear::canvas::WindowPtr& window); + protected: simgear::canvas::GroupPtr _desktop; diff --git a/src/Scripting/NasalCanvas.cxx b/src/Scripting/NasalCanvas.cxx index 61ca90964..aaa043e3f 100644 --- a/src/Scripting/NasalCanvas.cxx +++ b/src/Scripting/NasalCanvas.cxx @@ -186,6 +186,19 @@ naRef f_setInputFocus(const nasal::CallContext& ctx) return naNil(); } +naRef f_grabPointer(const nasal::CallContext& ctx) +{ + return ctx.to_nasal( + requireGUIMgr(ctx.c).grabPointer(ctx.requireArg(0)) + ); +} + +naRef f_ungrabPointer(const nasal::CallContext& ctx) +{ + requireGUIMgr(ctx.c).ungrabPointer(ctx.requireArg(0)); + return naNil(); +} + static naRef f_groupCreateChild(sc::Group& group, const nasal::CallContext& ctx) { return ctx.to_nasal( group.createChild( ctx.requireArg(0), @@ -564,6 +577,8 @@ naRef initNasalCanvas(naRef globals, naContext c) canvas_module.set("_newWindowGhost", f_createWindow); canvas_module.set("_getDesktopGhost", f_getDesktop); canvas_module.set("setInputFocus", f_setInputFocus); + canvas_module.set("grabPointer", f_grabPointer); + canvas_module.set("ungrabPointer", f_ungrabPointer); return naNil(); } -- 2.39.5