]> git.mxchange.org Git - flightgear.git/commitdiff
Canvas: support for pointer grab.
authorThomas Geymayer <tomgey@gmail.com>
Sun, 10 Aug 2014 22:23:10 +0000 (00:23 +0200)
committerThomas Geymayer <tomgey@gmail.com>
Sun, 10 Aug 2014 22:25:26 +0000 (00:25 +0200)
src/Canvas/gui_mgr.cxx
src/Canvas/gui_mgr.hxx
src/Scripting/NasalCanvas.cxx

index b5ac7155ecbae300a596362504b00ff7dc4c823e..6b38d523cdbf69e7cd43e11e9dc6ea889dff3807 100644 (file)
@@ -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<sc::Window*>
-      (
-        static_cast<sc::Element::OSGUserData*>(
-          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<sc::Window*>
+        (
+          static_cast<sc::Element::OSGUserData*>(
+            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<DesktopGroup*>(_desktop.get())->setFocusWindow(window);
 }
 
+//------------------------------------------------------------------------------
+bool GUIMgr::grabPointer(const sc::WindowPtr& window)
+{
+  return static_cast<DesktopGroup*>(_desktop.get())->grabPointer(window);
+}
+
+//------------------------------------------------------------------------------
+void GUIMgr::ungrabPointer(const sc::WindowPtr& window)
+{
+  static_cast<DesktopGroup*>(_desktop.get())->ungrabPointer(window);
+}
+
 //------------------------------------------------------------------------------
 sc::Placements
 GUIMgr::addWindowPlacement( SGPropertyNode* placement,
index c2cd341cd0cb67408987992b94cf09971a2b509e..30ba7c9c7d971baac8620f74f16a58bd991fb586 100644 (file)
@@ -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;
index 61ca9096494f59cc32188c5bfbaeed6444e0b02e..aaa043e3ff963c43210ca8c0c1bca50b2eeded0f 100644 (file)
@@ -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<sc::WindowPtr>(0))
+  );
+}
+
+naRef f_ungrabPointer(const nasal::CallContext& ctx)
+{
+  requireGUIMgr(ctx.c).ungrabPointer(ctx.requireArg<sc::WindowPtr>(0));
+  return naNil();
+}
+
 static naRef f_groupCreateChild(sc::Group& group, const nasal::CallContext& ctx)
 {
   return ctx.to_nasal( group.createChild( ctx.requireArg<std::string>(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();
 }