From 9709dcb30718477dd38da1bb4e876a11f3032691 Mon Sep 17 00:00:00 2001 From: david Date: Sat, 23 Mar 2002 23:16:13 +0000 Subject: [PATCH] First steps towards configurable mouse input. Soon, this new code (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 | 3 + src/Cockpit/panel.cxx | 5 +- src/Input/input.cxx | 254 ++++++++++++++++++++++++--------------- src/Input/input.hxx | 140 +++++++++++++++++++-- src/Main/fg_commands.cxx | 66 ++++++++++ src/Main/main.cxx | 6 + 6 files changed, 368 insertions(+), 106 deletions(-) diff --git a/acconfig.h b/acconfig.h index c69d2be8f..540703f06 100644 --- a/acconfig.h +++ b/acconfig.h @@ -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 diff --git a/src/Cockpit/panel.cxx b/src/Cockpit/panel.cxx index 7538e29b6..25c2c44e4 100644 --- a/src/Cockpit/panel.cxx +++ b/src/Cockpit/panel.cxx @@ -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; diff --git a/src/Input/input.cxx b/src/Input/input.cxx index baccfb3aa..ebbc2a62e 100644 --- a/src/Input/input.cxx +++ b/src/Input/input.cxx @@ -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 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 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; +} + + + +//////////////////////////////////////////////////////////////////////// +// 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. - * - *

Pass the value on to the FGInput module unless PUI wants it.

- * - * @param k The integer value for the key pressed. - * @param x (unused) - * @param y (unused) - */ -void GLUTkey(unsigned char k, int x, int y) + +//////////////////////////////////////////////////////////////////////// +// 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. - * - *

PUI doesn't use this, so always pass it to the input manager.

- * - * @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. - * - *

Pass the value on to the FGInput module unless PUI wants it. - * The key value will have 256 added to it.

- * - * @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 diff --git a/src/Input/input.hxx b/src/Input/input.hxx index a2899ab70..6ec7da0f9 100644 --- a/src/Input/input.hxx +++ b/src/Input/input.hxx @@ -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" { -#endif // _CONTROLS_HXX +/** + * Key-down event handler for Glut. + * + *

Pass the value on to the FGInput module unless PUI wants it.

+ * + * @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. + * + *

PUI doesn't use this, so always pass it to the input manager.

+ * + * @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. + * + *

Pass the value on to the FGInput module unless PUI wants it. + * The key value will have 256 added to it.

+ * + * @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 // _INPUT_HXX diff --git a/src/Main/fg_commands.cxx b/src/Main/fg_commands.cxx index 820ae6156..d365ee2fc 100644 --- a/src/Main/fg_commands.cxx +++ b/src/Main/fg_commands.cxx @@ -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 }, diff --git a/src/Main/main.cxx b/src/Main/main.cxx index 9831d462d..6c33b1d30 100644 --- a/src/Main/main.cxx +++ b/src/Main/main.cxx @@ -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