]> git.mxchange.org Git - flightgear.git/commitdiff
First steps towards configurable mouse input. Soon, this new code
authordavid <david>
Sat, 23 Mar 2002 23:16:13 +0000 (23:16 +0000)
committerdavid <david>
Sat, 23 Mar 2002 23:16:13 +0000 (23:16 +0000)
(mainly in src/Input/input.cxx) will make src/GUI/mouse.cxx obsolete
and bring the mouse into the same input system as the joystick and
keyboard.  This is just preliminary work allowing, covering mouse
clicks (no motion yet), and it actually crashes on a middle or right
click.

The new mouse support is disabled by default until it become stable;
to try it out, you need to configure --with-new-mouse.

acconfig.h
src/Cockpit/panel.cxx
src/Input/input.cxx
src/Input/input.hxx
src/Main/fg_commands.cxx
src/Main/main.cxx

index c69d2be8f61acc16a5cafd1448b8138174936963..540703f069fc0110c452c6941bd5d7e5c8eae227 100644 (file)
@@ -66,6 +66,9 @@
    
 /* Define to avoid Christian's new weather code */
 #undef FG_NEW_ENVIRONMENT
+
+/* Define to use new experimental mouse input code */
+#undef FG_NEW_MOUSE
    
 /* Define if we are building FGFS (should always be defined) */
 #undef FGFS
index 7538e29b673b5307083e7a2f2df0d9761ff5ed03..25c2c44e4532a1dbf742749e65015b4a2071e93f 100644 (file)
@@ -582,7 +582,7 @@ FGPanel::doMouseAction (int button, int updown, int x, int y)
   if (updown == 1) {
     _mouseDown = false;
     _mouseInstrument = 0;
-    return true;
+    return false;
   }
 
                                // Scale for the real window size.
@@ -613,8 +613,7 @@ FGPanel::doMouseAction (int button, int updown, int x, int y)
       _mouseX = x - ix;
       _mouseY = y - iy;
                                // Always do the action once.
-      _mouseInstrument->doMouseAction(_mouseButton, _mouseX, _mouseY);
-      return true;
+      return _mouseInstrument->doMouseAction(_mouseButton, _mouseX, _mouseY);
     }
   }
   return false;
index baccfb3aafe50d228ad315ed7a54df3ee494565f..ebbc2a62e9ecb9583ada73fcd6de1c8e3294c1d0 100644 (file)
@@ -111,7 +111,7 @@ FGBinding::read (const SGPropertyNode * node)
 
   _command_name = node->getStringValue("command", "");
   if (_command_name.empty()) {
-    SG_LOG(SG_INPUT, SG_ALERT, "No command supplied for binding.");
+    SG_LOG(SG_INPUT, SG_WARN, "No command supplied for binding.");
     _command = 0;
     return;
   }
@@ -134,7 +134,7 @@ FGBinding::fire () const
 {
   if (test()) {
     if (_command == 0) {
-      SG_LOG(SG_INPUT, SG_ALERT, "No command attached to binding");
+      SG_LOG(SG_INPUT, SG_WARN, "No command attached to binding");
     } else if (!(*_command)(_arg, &_command_state)) {
       SG_LOG(SG_INPUT, SG_ALERT, "Failed to execute command "
             << _command_name);
@@ -142,6 +142,18 @@ FGBinding::fire () const
   }
 }
 
+void
+FGBinding::fire (int x, int y) const
+{
+  if (test()) {
+    if (x >= 0)
+      _arg->setIntValue("x-pos", x);
+    if (y >= 0)
+      _arg->setIntValue("y-pos", y);
+    fire();
+  }
+}
+
 void
 FGBinding::fire (double setting) const
 {
@@ -168,6 +180,7 @@ FGInput current_input;
 
 
 FGInput::FGInput ()
+  : _mouse_mode(0)
 {
   // no op
 }
@@ -182,6 +195,7 @@ FGInput::init ()
 {
   _init_keyboard();
   _init_joystick();
+  _init_mouse();
 }
 
 void
@@ -201,17 +215,18 @@ FGInput::update (int dt)
 {
   _update_keyboard();
   _update_joystick();
+  _update_mouse();
 }
 
 void
 FGInput::doKey (int k, int modifiers, int x, int y)
 {
-    // SG_LOG( SG_INPUT, SG_INFO, "User pressed key " << k
-    //                << " with modifiers " << modifiers );
+  SG_LOG( SG_INPUT, SG_DEBUG, "User pressed key " << k
+         << " with modifiers " << modifiers );
 
                                // Sanity check.
   if (k < 0 || k >= MAX_KEYS) {
-    SG_LOG(SG_INPUT, SG_ALERT, "Key value " << k << " out of range");
+    SG_LOG(SG_INPUT, SG_WARN, "Key value " << k << " out of range");
     return;
   }
 
@@ -219,8 +234,8 @@ FGInput::doKey (int k, int modifiers, int x, int y)
 
                                // Key pressed.
   if (modifiers&FG_MOD_UP == 0) {
-    // SG_LOG( SG_INPUT, SG_INFO, "User pressed key " << k
-    //         << " with modifiers " << modifiers );
+    SG_LOG( SG_INPUT, SG_DEBUG, "User pressed key " << k
+           << " with modifiers " << modifiers );
     if (!b.last_state || b.is_repeatable) {
       const binding_list_t &bindings =
        _find_key_bindings(k, modifiers);
@@ -235,8 +250,8 @@ FGInput::doKey (int k, int modifiers, int x, int y)
 
                                // Key released.
   else {
-    // SG_LOG(SG_INPUT, SG_INFO, "User released key " << k
-    //        << " with modifiers " << modifiers);
+    SG_LOG(SG_INPUT, SG_DEBUG, "User released key " << k
+          << " with modifiers " << modifiers);
     if (b.last_state) {
       const binding_list_t &bindings =
        _find_key_bindings(k, modifiers);
@@ -251,7 +266,7 @@ FGInput::doKey (int k, int modifiers, int x, int y)
 
 
                                // Use the old, default actions.
-  // SG_LOG( SG_INPUT, SG_INFO, "(No user binding.)" );
+  SG_LOG( SG_INPUT, SG_DEBUG, "(No user binding.)" );
   if (modifiers&FG_MOD_UP)
     return;
 
@@ -330,22 +345,36 @@ FGInput::doKey (int k, int modifiers, int x, int y)
     }
 }
 
+void
+FGInput::doMouseClick (int b, int updown, int x, int y)
+{
+  std::cout << "Mouse click " << b << ',' << updown << std::endl;
+  int modifiers = FG_MOD_NONE; // FIXME: any way to get the real ones?
+
+  _update_button(_mouse_bindings[0].buttons[b], modifiers, updown, x, y);
+}
+
+void
+FGInput::doMouseMotion (int x, int y)
+{
+  // TODO
+}
 
 void
 FGInput::_init_keyboard ()
 {
                                // TODO: zero the old bindings first.
-  SG_LOG(SG_INPUT, SG_INFO, "Initializing key bindings");
+  SG_LOG(SG_INPUT, SG_DEBUG, "Initializing key bindings");
   SGPropertyNode * key_nodes = fgGetNode("/input/keyboard");
   if (key_nodes == 0) {
-    SG_LOG(SG_INPUT, SG_ALERT, "No key bindings (/input/keyboard)!!");
-    return;
+    SG_LOG(SG_INPUT, SG_WARN, "No key bindings (/input/keyboard)!!");
+    key_nodes = fgGetNode("/input/keyboard", true);
   }
   
   vector<SGPropertyNode *> keys = key_nodes->getChildren("key");
   for (unsigned int i = 0; i < keys.size(); i++) {
     int index = keys[i]->getIndex();
-    SG_LOG(SG_INPUT, SG_INFO, "Binding key " << index);
+    SG_LOG(SG_INPUT, SG_DEBUG, "Binding key " << index);
     _key_bindings[index].is_repeatable = keys[i]->getBoolValue("repeatable");
     _read_bindings(keys[i], _key_bindings[index].bindings, FG_MOD_NONE);
   }
@@ -356,45 +385,45 @@ void
 FGInput::_init_joystick ()
 {
                                // TODO: zero the old bindings first.
-  SG_LOG(SG_INPUT, SG_INFO, "Initializing joystick bindings");
+  SG_LOG(SG_INPUT, SG_DEBUG, "Initializing joystick bindings");
   SGPropertyNode * js_nodes = fgGetNode("/input/joysticks");
   if (js_nodes == 0) {
-    SG_LOG(SG_INPUT, SG_ALERT, "No joystick bindings (/input/joysticks)!!");
-    return;
+    SG_LOG(SG_INPUT, SG_WARN, "No joystick bindings (/input/joysticks)!!");
+    js_nodes = fgGetNode("/input/joysticks", true);
   }
 
   for (int i = 0; i < MAX_JOYSTICKS; i++) {
-    const SGPropertyNode * js_node = js_nodes->getChild("js", i);
+    SGPropertyNode * js_node = js_nodes->getChild("js", i);
     if (js_node == 0) {
-      SG_LOG(SG_INPUT, SG_ALERT, "No bindings for joystick " << i);
-      continue;
+      SG_LOG(SG_INPUT, SG_DEBUG, "No bindings for joystick " << i);
+      js_node = js_nodes->getChild("js", i, true);
     }
     jsJoystick * js = new jsJoystick(i);
     _joystick_bindings[i].js = js;
     if (js->notWorking()) {
-      SG_LOG(SG_INPUT, SG_INFO, "Joystick " << i << " not found");
+      SG_LOG(SG_INPUT, SG_WARN, "Joystick " << i << " not found");
       continue;
     }
 #ifdef WIN32
     JOYCAPS jsCaps ;
     joyGetDevCaps( i, &jsCaps, sizeof(jsCaps) );
     int nbuttons = jsCaps.wNumButtons;
-    if (nbuttons > MAX_BUTTONS) nbuttons = MAX_BUTTONS;
+    if (nbuttons > MAX_JOYSTICK_BUTTONS) nbuttons = MAX_JOYSTICK_BUTTONS;
 #else
-    int nbuttons = MAX_BUTTONS;
+    int nbuttons = MAX_JOYSTICK_BUTTONS;
 #endif
        
     int naxes = js->getNumAxes();
-    if (naxes > MAX_AXES) naxes = MAX_AXES;
+    if (naxes > MAX_JOYSTICK_AXES) naxes = MAX_JOYSTICK_AXES;
     _joystick_bindings[i].naxes = naxes;
     _joystick_bindings[i].nbuttons = nbuttons;
 
-    SG_LOG(SG_INPUT, SG_INFO, "Initializing joystick " << i);
+    SG_LOG(SG_INPUT, SG_DEBUG, "Initializing joystick " << i);
 
                                // Set up range arrays
-    float minRange[MAX_AXES];
-    float maxRange[MAX_AXES];
-    float center[MAX_AXES];
+    float minRange[MAX_JOYSTICK_AXES];
+    float maxRange[MAX_JOYSTICK_AXES];
+    float center[MAX_JOYSTICK_AXES];
 
                                // Initialize with default values
     js->getMinRange(minRange);
@@ -413,8 +442,8 @@ FGInput::_init_joystick ()
     for (j = 0; j < naxes; j++) {
       const SGPropertyNode * axis_node = js_node->getChild("axis", j);
       if (axis_node == 0) {
-       SG_LOG(SG_INPUT, SG_INFO, "No bindings for axis " << j);
-       continue;
+       SG_LOG(SG_INPUT, SG_DEBUG, "No bindings for axis " << j);
+       axis_node = js_node->getChild("axis", j, true);
       }
       
       axis &a = _joystick_bindings[i].axes[j];
@@ -442,7 +471,7 @@ FGInput::_init_joystick ()
     char buf[8];
     for (j = 0; j < nbuttons; j++) {
       sprintf(buf, "%d", j);
-      SG_LOG(SG_INPUT, SG_INFO, "Initializing button " << j);
+      SG_LOG(SG_INPUT, SG_DEBUG, "Initializing button " << j);
       _init_button(js_node->getChild("button", j),
                   _joystick_bindings[i].buttons[j],
                   buf);
@@ -456,14 +485,44 @@ FGInput::_init_joystick ()
 }
 
 
-inline void
+void
+FGInput::_init_mouse ()
+{
+  SG_LOG(SG_INPUT, SG_DEBUG, "Initializing mouse bindings");
+
+  SGPropertyNode * mouse_nodes = fgGetNode("/input/mice");
+  if (mouse_nodes == 0) {
+    SG_LOG(SG_INPUT, SG_WARN, "No mouse bindings (/input/mice)!!");
+    mouse_nodes = fgGetNode("/input/mice", true);
+  }
+
+  for (int i = 0; i < MAX_MICE; i++) {
+    const SGPropertyNode * mouse_node = mouse_nodes->getChild("mouse", i);
+    _mouse_bindings[i].buttons = new button[MAX_MOUSE_BUTTONS];
+    if (mouse_node == 0) {
+      SG_LOG(SG_INPUT, SG_DEBUG, "No bindings for mouse " << i);
+      mouse_node = mouse_nodes->getChild("mouse", i, true);
+    }
+    char buf[8];
+    for (int j = 0; j < MAX_MOUSE_BUTTONS; j++) {
+      sprintf(buf, "%d", j);
+      SG_LOG(SG_INPUT, SG_DEBUG, "Initializing mouse button " << j);
+      _init_button(mouse_node->getChild("button", j),
+                  _mouse_bindings[i].buttons[j],
+                  buf);
+    }
+  }
+}
+
+
+void
 FGInput::_init_button (const SGPropertyNode * node,
                       button &b,
                       const string name)
 {      
-  if (node == 0)
-    SG_LOG(SG_INPUT, SG_INFO, "No bindings for button " << name);
-  else {
+  if (node == 0) {
+    SG_LOG(SG_INPUT, SG_DEBUG, "No bindings for button " << name);
+  else {
     b.is_repeatable = node->getBoolValue("repeatable", b.is_repeatable);
     
                // Get the bindings for the button
@@ -485,7 +544,7 @@ FGInput::_update_joystick ()
   int modifiers = FG_MOD_NONE; // FIXME: any way to get the real ones?
   int buttons;
   // float js_val, diff;
-  float axis_values[MAX_AXES];
+  float axis_values[MAX_JOYSTICK_AXES];
 
   int i;
   int j;
@@ -507,10 +566,10 @@ FGInput::_update_joystick ()
                                // is unchanged; only a change in
                                // position fires the bindings.
       if (fabs(axis_values[j] - a.last_value) > a.tolerance) {
-//     SG_LOG(SG_INPUT, SG_INFO, "Axis " << j << " has moved");
+//     SG_LOG(SG_INPUT, SG_DEBUG, "Axis " << j << " has moved");
        SGPropertyNode node;
        a.last_value = axis_values[j];
-//     SG_LOG(SG_INPUT, SG_INFO, "There are "
+//     SG_LOG(SG_INPUT, SG_DEBUG, "There are "
 //            << a.bindings[modifiers].size() << " bindings");
        for (unsigned int k = 0; k < a.bindings[modifiers].size(); k++)
          a.bindings[modifiers][k]->fire(axis_values[j]);
@@ -520,40 +579,49 @@ FGInput::_update_joystick ()
       if (a.low.bindings[modifiers].size())
        _update_button(_joystick_bindings[i].axes[j].low,
                       modifiers,
-                      axis_values[j] < a.low_threshold);
+                      axis_values[j] < a.low_threshold,
+                      -1, -1);
       
       if (a.high.bindings[modifiers].size())
        _update_button(_joystick_bindings[i].axes[j].high,
                       modifiers,
-                      axis_values[j] > a.high_threshold);
+                      axis_values[j] > a.high_threshold,
+                      -1, -1);
     }
 
                                // Fire bindings for the buttons.
     for (j = 0; j < _joystick_bindings[i].nbuttons; j++) {
       _update_button(_joystick_bindings[i].buttons[j],
                     modifiers,
-                    (buttons & (1 << j)) > 0);
+                    (buttons & (1 << j)) > 0,
+                    -1, -1);
     }
   }
 }
 
+void
+FGInput::_update_mouse ()
+{
+  // no-op
+}
 
 void
-FGInput::_update_button (button &b, int modifiers, bool pressed)
+FGInput::_update_button (button &b, int modifiers, bool pressed,
+                        int x, int y)
 {
   if (pressed) {
                                // The press event may be repeated.
     if (!b.last_state || b.is_repeatable) {
-      // SG_LOG( SG_INPUT, SG_INFO, "Button has been pressed" );
+      SG_LOG( SG_INPUT, SG_DEBUG, "Button has been pressed" );
       for (unsigned int k = 0; k < b.bindings[modifiers].size(); k++)
-       b.bindings[modifiers][k]->fire();
+       b.bindings[modifiers][k]->fire(x, y);
     }
   } else {
                                // The release event is never repeated.
     if (b.last_state) {
-      // SG_LOG( SG_INPUT, SG_INFO, "Button has been released" );
+      SG_LOG( SG_INPUT, SG_DEBUG, "Button has been released" );
       for (unsigned int k = 0; k < b.bindings[modifiers|FG_MOD_UP].size(); k++)
-       b.bindings[modifiers|FG_MOD_UP][k]->fire();
+       b.bindings[modifiers|FG_MOD_UP][k]->fire(x, y);
     }
   }
          
@@ -566,10 +634,10 @@ FGInput::_read_bindings (const SGPropertyNode * node,
                         binding_list_t * binding_list,
                         int modifiers)
 {
-  SG_LOG(SG_INPUT, SG_INFO, "Reading all bindings");
+  SG_LOG(SG_INPUT, SG_DEBUG, "Reading all bindings");
   vector<const SGPropertyNode *> bindings = node->getChildren("binding");
   for (unsigned int i = 0; i < bindings.size(); i++) {
-    SG_LOG(SG_INPUT, SG_INFO, "Reading binding "
+    SG_LOG(SG_INPUT, SG_DEBUG, "Reading binding "
           << bindings[i]->getStringValue("command"));
     binding_list[modifiers].push_back(new FGBinding(bindings[i]));
   }
@@ -678,8 +746,23 @@ FGInput::joystick::joystick ()
 FGInput::joystick::~joystick ()
 {
 //   delete js;
-//   delete[] axes;
-//   delete[] buttons;
+  delete[] axes;
+  delete[] buttons;
+}
+
+
+\f
+////////////////////////////////////////////////////////////////////////
+// Implementation of FGInput::mouse
+////////////////////////////////////////////////////////////////////////
+
+FGInput::mouse::mouse ()
+{
+}
+
+FGInput::mouse::~mouse ()
+{
+  delete [] buttons;
 }
 
 
@@ -708,68 +791,51 @@ static inline int get_mods ()
 }
 
 
-/**
- * Key-down event handler for Glut.
- *
- * <p>Pass the value on to the FGInput module unless PUI wants it.</p>
- *
- * @param k The integer value for the key pressed.
- * @param x (unused)
- * @param y (unused)
- */
-void GLUTkey(unsigned char k, int x, int y)
+\f
+////////////////////////////////////////////////////////////////////////
+// GLUT C callbacks.
+////////////////////////////////////////////////////////////////////////
+
+void
+GLUTkey(unsigned char k, int x, int y)
 {
                                // Give PUI a chance to grab it first.
   if (!puKeyboard(k, PU_DOWN))
     current_input.doKey(k, get_mods(), x, y);
 }
 
-
-/**
- * Key-up event handler for GLUT.
- *
- * <p>PUI doesn't use this, so always pass it to the input manager.</p>
- *
- * @param k The integer value for the key pressed.
- * @param x (unused)
- * @param y (unused)
- */
-void GLUTkeyup(unsigned char k, int x, int y)
+void
+GLUTkeyup(unsigned char k, int x, int y)
 {
   current_input.doKey(k, get_mods()|FGInput::FG_MOD_UP, x, y);
 }
 
-
-/**
- * Special key-down handler for Glut.
- *
- * <p>Pass the value on to the FGInput module unless PUI wants it.
- * The key value will have 256 added to it.</p>
- *
- * @param k The integer value for the key pressed (will have 256 added
- * to it).
- * @param x (unused)
- * @param y (unused)
- */
-void GLUTspecialkey(int k, int x, int y)
+void
+GLUTspecialkey(int k, int x, int y)
 {
                                // Give PUI a chance to grab it first.
   if (!puKeyboard(k + PU_KEY_GLUT_SPECIAL_OFFSET, PU_DOWN))
     current_input.doKey(k + 256, get_mods(), x, y);
 }
 
-
-/**
- * Special key-up handler for Glut.
- *
- * @param k The integer value for the key pressed (will have 256 added
- * to it).
- * @param x (unused)
- * @param y (unused)
- */
-void GLUTspecialkeyup(int k, int x, int y)
+void
+GLUTspecialkeyup(int k, int x, int y)
 {
   current_input.doKey(k + 256, get_mods()|FGInput::FG_MOD_UP, x, y);
 }
 
+void
+GLUTmouse (int button, int updown, int x, int y)
+{
+  current_input.doMouseClick(button, updown == GLUT_DOWN, x, y);
+}
+
+void
+GLUTmotion (int x, int y)
+{
+  puMouse(x, y);
+//   glutPostRedisplay();
+  current_input.doMouseMotion(x, y);
+}
+
 // end of input.cxx
index a2899ab705549092dfd4e398f468b18ee6b16255..6ec7da0f929e66fd0b47e992e51a2170918f9cc2 100644 (file)
@@ -122,6 +122,12 @@ public:
   virtual void fire () const;
 
 
+  /**
+   * Fire a binding with x and y positions.
+   */
+  virtual void fire (int x, int y) const;
+
+
   /**
    * Fire a binding with a setting (i.e. joystick axis).
    *
@@ -205,6 +211,26 @@ public:
   virtual void doKey (int k, int modifiers, int x, int y);
 
 
+  /**
+   * Handle a mouse click event.
+   *
+   * @param button The mouse button selected.
+   * @param updown Button status.
+   * @param x The X position of the mouse event, in screen coordinates.
+   * @param y The Y position of the mouse event, in screen coordinates.
+   */
+  virtual void doMouseClick (int button, int updown, int x, int y);
+
+
+  /**
+   * Handle mouse motion.
+   *
+   * @param x The new mouse x position, in screen coordinates.
+   * @param y The new mouse y position, in screen coordinates.
+   */
+  virtual void doMouseMotion (int x, int y);
+
+
 private:
                                // Constants
   enum 
@@ -216,8 +242,11 @@ private:
   #else
     MAX_JOYSTICKS = 10,
   #endif
-    MAX_AXES = _JS_MAX_AXES,
-    MAX_BUTTONS = 32
+    MAX_JOYSTICK_AXES = _JS_MAX_AXES,
+    MAX_JOYSTICK_BUTTONS = 32,
+
+    MAX_MICE = 1,
+    MAX_MOUSE_BUTTONS
   };
 
 
@@ -266,6 +295,16 @@ private:
   };
 
 
+  /**
+   * Settings for a mouse.
+   */
+  struct mouse {
+    mouse ();
+    virtual ~mouse ();
+    button * buttons;
+  };
+
+
   /**
    * Initialize key bindings.
    */
@@ -278,6 +317,12 @@ private:
   void _init_joystick ();
 
 
+  /**
+   * Initialize mouse bindings.
+   */
+  void _init_mouse ();
+
+
   /**
    * Initialize a single button.
    */
@@ -298,10 +343,17 @@ private:
   void _update_joystick ();
 
 
+  /**
+   * Update the mouse.
+   */
+  void _update_mouse ();
+
+
   /**
    * Update a single button.
    */
-  inline void _update_button (button &b, int modifiers, bool pressed);
+  inline void _update_button (button &b, int modifiers, bool pressed,
+                             int x, int y);
 
 
   /**
@@ -319,6 +371,9 @@ private:
 
   button _key_bindings[MAX_KEYS];
   joystick _joystick_bindings[MAX_JOYSTICKS];
+  mouse _mouse_bindings[MAX_MICE];
+
+  int _mouse_mode;
 
 };
 
@@ -331,10 +386,77 @@ extern FGInput current_input;
 // GLUT callbacks.
 ////////////////////////////////////////////////////////////////////////
 
-// Handle keyboard events
-void GLUTkey(unsigned char k, int x, int y);
-void GLUTkeyup(unsigned char k, int x, int y);
-void GLUTspecialkey(int k, int x, int y);
-void GLUTspecialkeyup(int k, int x, int y);
+// Handle GLUT events.
+extern "C" {
+
+/**
+ * Key-down event handler for Glut.
+ *
+ * <p>Pass the value on to the FGInput module unless PUI wants it.</p>
+ *
+ * @param k The integer value for the key pressed.
+ * @param x (unused)
+ * @param y (unused)
+ */
+void GLUTkey (unsigned char k, int x, int y);
+
+
+/**
+ * Key-up event handler for GLUT.
+ *
+ * <p>PUI doesn't use this, so always pass it to the input manager.</p>
+ *
+ * @param k The integer value for the key pressed.
+ * @param x (unused)
+ * @param y (unused)
+ */
+void GLUTkeyup (unsigned char k, int x, int y);
+
+
+/**
+ * Special key-down handler for Glut.
+ *
+ * <p>Pass the value on to the FGInput module unless PUI wants it.
+ * The key value will have 256 added to it.</p>
+ *
+ * @param k The integer value for the key pressed (will have 256 added
+ * to it).
+ * @param x (unused)
+ * @param y (unused)
+ */
+void GLUTspecialkey (int k, int x, int y);
+
+
+/**
+ * Special key-up handler for Glut.
+ *
+ * @param k The integer value for the key pressed (will have 256 added
+ * to it).
+ * @param x (unused)
+ * @param y (unused)
+ */
+void GLUTspecialkeyup (int k, int x, int y);
+
+
+/**
+ * Mouse click handler for Glut.
+ *
+ * @param button The mouse button pressed.
+ * @param updown Press or release flag.
+ * @param x The x-location of the click.
+ * @param y The y-location of the click.
+ */
+void GLUTmouse (int button, int updown, int x, int y);
+
+
+/**
+ * Mouse motion handler for Glut.
+ *
+ * @param x The new x-location of the mouse.
+ * @param y The new y-location of the mouse.
+ */
+void GLUTmotion (int x, int y);
+
+} // extern "C"
 
-#endif // _CONTROLS_HXX
+#endif // _INPUT_HXX
index 820ae61568b3a732e35925433a123e1ebc5eb1fd..d365ee2fc88782233abcef80afffc717c9d66d33 100644 (file)
@@ -184,6 +184,47 @@ do_save (const SGPropertyNode * arg, SGCommandState ** state)
 }
 
 
+/**
+ * Built-in command: let PUI handle a mouse click.
+ *
+ * button: the mouse button number, zero-based.
+ * is-down: true if the button is down, false if it is up.
+ * x-pos: the x position of the mouse click.
+ * y-pos: the y position of the mouse click.
+ */
+static bool
+do_pui_mouse_click (const SGPropertyNode * arg, SGCommandState ** state)
+{
+  return puMouse(arg->getIntValue("button"),
+                arg->getBoolValue("is-down") ? PU_DOWN : PU_UP,
+                arg->getIntValue("x-pos"),
+                arg->getIntValue("y-pos"));
+}
+
+
+/**
+ * Built-in command: let PUI *or* the panel handle a mouse click.
+ *
+ * button: the mouse button number, zero-based.
+ * is-down: true if the button is down, false if it is up.
+ * x-pos: the x position of the mouse click.
+ * y-pos: the y position of the mouse click.
+ */
+static bool
+do_pui_or_panel_mouse_click (const SGPropertyNode * arg,
+                            SGCommandState ** state)
+{
+  int button = arg->getIntValue("button");
+  bool is_down = arg->getBoolValue("is-down");
+  int x = arg->getIntValue("x-pos");
+  int y = arg->getIntValue("y-pos");
+  return (puMouse(button, is_down ? PU_DOWN : PU_UP, x, y) ||
+         (current_panel != 0 &&
+          current_panel->doMouseAction(button,
+                                       is_down ? PU_DOWN : PU_UP, x, y)));
+}
+
+
 /**
  * Built-in command: (re)load the panel.
  *
@@ -213,6 +254,28 @@ do_panel_load (const SGPropertyNode * arg, SGCommandState ** state)
 }
 
 
+/**
+ * Built-in command: pass a mouse click to the panel.
+ *
+ * button: the mouse button number, zero-based.
+ * is-down: true if the button is down, false if it is up.
+ * x-pos: the x position of the mouse click.
+ * y-pos: the y position of the mouse click.
+ */
+static bool
+do_panel_mouse_click (const SGPropertyNode * arg, SGCommandState ** state)
+{
+  if (current_panel != 0)
+    return current_panel
+      ->doMouseAction(arg->getIntValue("button"),
+                     arg->getBoolValue("is-down") ? PU_DOWN : PU_UP,
+                     arg->getIntValue("x-pos"),
+                     arg->getIntValue("y-pos"));
+  else
+    return false;
+}
+
+
 /**
  * Built-in command: (re)load preferences.
  *
@@ -574,7 +637,10 @@ static struct {
     { "exit", do_exit },
     { "load", do_load },
     { "save", do_save },
+    { "pui-mouse-click", do_pui_mouse_click },
+    { "pui-or-panel-mouse-click", do_pui_or_panel_mouse_click },
     { "panel-load", do_panel_load },
+    { "panel-mouse-click", do_panel_mouse_click },
     { "preferences-load", do_preferences_load },
     { "view-cycle", do_view_cycle },
     { "screen-capture", do_screen_capture },
index 9831d462d2dbcc00851c2888f3217ef5dd17d1d7..6c33b1d30ee1eb541a2bcc234ab0550bd504f0b6 100644 (file)
@@ -1265,10 +1265,16 @@ int fgGlutInitEvents( void ) {
     glutSpecialFunc(GLUTspecialkey);
     glutSpecialUpFunc(GLUTspecialkeyup);
 
+#if FG_NEW_MOUSE
+    glutMouseFunc (GLUTmouse);
+    glutMotionFunc (GLUTmotion);
+    glutPassiveMotionFunc (GLUTmotion);
+#else
     // call guiMouseFunc() whenever our little rodent is used
     glutMouseFunc ( guiMouseFunc );
     glutMotionFunc (guiMotionFunc );
     glutPassiveMotionFunc (guiMotionFunc );
+#endif
 
     // call fgMainLoop() whenever there is
     // nothing else to do