diff --git a/panda/src/tform/mouseWatcher.cxx b/panda/src/tform/mouseWatcher.cxx index c16188636c..eaa4f96f5a 100644 --- a/panda/src/tform/mouseWatcher.cxx +++ b/panda/src/tform/mouseWatcher.cxx @@ -32,6 +32,7 @@ MouseWatcher:: MouseWatcher(const string &name) : DataNode(name) { _has_mouse = false; _current_region = (MouseWatcherRegion *)NULL; + _button_down_region = (MouseWatcherRegion *)NULL; _button_down = false; } @@ -80,6 +81,9 @@ remove_region(MouseWatcherRegion *region) { if (region == _current_region) { _current_region = (MouseWatcherRegion *)NULL; } + if (region == _button_down_region) { + _button_down_region = (MouseWatcherRegion *)NULL; + } return _regions.erase(region) != 0; } @@ -177,10 +181,12 @@ set_current_region(MouseWatcherRegion *region) { void MouseWatcher:: throw_event_pattern(const string &pattern, const MouseWatcherRegion *region, const string &button_name) { - region->test_ref_count_integrity(); if (pattern.empty()) { return; } + if (region != (MouseWatcherRegion *)NULL) { + region->test_ref_count_integrity(); + } string event; for (size_t p = 0; p < pattern.size(); ++p) { @@ -188,7 +194,9 @@ throw_event_pattern(const string &pattern, const MouseWatcherRegion *region, string cmd = pattern.substr(p + 1, 1); p++; if (cmd == "r") { - event += region->get_name(); + if (region != (MouseWatcherRegion *)NULL) { + event += region->get_name(); + } } else if (cmd == "b") { event += button_name; @@ -247,9 +255,20 @@ transmit_data(NodeAttributes &data) { _has_mouse = true; if (!_button_down) { - // We don't change regions while we are holding down a - // button--only when all buttons are up. + // If the button is not currently being held down, we are free to + // set the mouse into whichever region we like. set_current_region(get_over_region(_mouse)); + + } else { + // If the button *is* currently being held down, we can only move + // the mouse into a region if the region is the same region we + // started from. + MouseWatcherRegion *region = get_over_region(_mouse); + if (region == _button_down_region) { + set_current_region(region); + } else { + set_current_region((MouseWatcherRegion *)NULL); + } } // Look for button events. @@ -267,8 +286,13 @@ transmit_data(NodeAttributes &data) { // more than one button goes down together, we won't detect // both of the button-up events properly. - if (_current_region != (MouseWatcherRegion *)NULL) { - throw_event_pattern(_button_up_pattern, _current_region, + // We should probably throw a different button_up event based + // on whether the _current_region is NULL or not, so the + // calling code can differentiate between button_up within the + // starting region, and button_up outside the region. + // Presently, changing this will break the GUI code. + if (_button_down_region != (MouseWatcherRegion *)NULL) { + throw_event_pattern(_button_up_pattern, _button_down_region, be._button.get_name()); } _button_down = false; @@ -276,14 +300,12 @@ transmit_data(NodeAttributes &data) { } else { // Button down. - if (_button_down) { - // Clicking down a second button while still holding the - // first button down does cause a change in regions. - set_current_region(get_over_region(_mouse)); + if (!_button_down) { + _button_down_region = _current_region; } _button_down = true; - if (_current_region != (MouseWatcherRegion *)NULL) { - throw_event_pattern(_button_down_pattern, _current_region, + if (_button_down_region != (MouseWatcherRegion *)NULL) { + throw_event_pattern(_button_down_pattern, _button_down_region, be._button.get_name()); } } diff --git a/panda/src/tform/mouseWatcher.h b/panda/src/tform/mouseWatcher.h index f0b0ed126b..fdaa33165d 100644 --- a/panda/src/tform/mouseWatcher.h +++ b/panda/src/tform/mouseWatcher.h @@ -93,6 +93,7 @@ private: LPoint2f _mouse; MouseWatcherRegion *_current_region; + MouseWatcherRegion *_button_down_region; bool _button_down; string _button_down_pattern;