mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-04 02:42:49 -04:00
implement MouseWatcher::inactivity_timeout
This commit is contained in:
parent
8aaf640cd9
commit
e6077a603c
@ -42,6 +42,10 @@ output(ostream &out) const {
|
||||
out << "button " << _button << " up";
|
||||
break;
|
||||
|
||||
case T_repeat:
|
||||
out << "button " << _button << " repeat";
|
||||
break;
|
||||
|
||||
case T_keystroke:
|
||||
out << "keystroke " << _keycode;
|
||||
break;
|
||||
@ -70,6 +74,7 @@ write_datagram(Datagram &dg) const {
|
||||
case T_down:
|
||||
case T_resume_down:
|
||||
case T_up:
|
||||
case T_repeat:
|
||||
// We write the button name. This is not particularly compact, but
|
||||
// presumably we don't get thousands of button events per frame, and
|
||||
// it is robust as the button index may change between sessions but
|
||||
@ -108,6 +113,7 @@ read_datagram(DatagramIterator &scan) {
|
||||
case T_down:
|
||||
case T_resume_down:
|
||||
case T_up:
|
||||
case T_repeat:
|
||||
_button = ButtonRegistry::ptr()->get_button(scan.get_string());
|
||||
break;
|
||||
|
||||
|
@ -70,6 +70,12 @@ public:
|
||||
T_resume_down,
|
||||
T_up,
|
||||
|
||||
// T_repeat is sent for each a keyrepeat event generated by the
|
||||
// system, for a button that is continually held down. If you
|
||||
// want to respect keyrepeat, treat T_down and T_repeat
|
||||
// equivalently.
|
||||
T_repeat,
|
||||
|
||||
// T_keystroke is a special keystroke event, and is sent along
|
||||
// with a Unicode keycode value, not a ButtonHandle.
|
||||
T_keystroke,
|
||||
|
@ -26,6 +26,27 @@ INLINE ButtonEventList::
|
||||
ButtonEventList() {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ButtonEventList::Copy Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE ButtonEventList::
|
||||
ButtonEventList(const ButtonEventList ©) :
|
||||
_events(copy._events)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ButtonEventList::Copy Assignment Operator
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void ButtonEventList::
|
||||
operator = (const ButtonEventList ©) {
|
||||
_events = copy._events;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ButtonEventList::add_event
|
||||
// Access: Public
|
||||
|
@ -41,6 +41,8 @@ class DatagramIterator;
|
||||
class EXPCL_PANDA ButtonEventList : public EventStoreValueBase {
|
||||
public:
|
||||
INLINE ButtonEventList();
|
||||
INLINE ButtonEventList(const ButtonEventList ©);
|
||||
INLINE void operator = (const ButtonEventList ©);
|
||||
|
||||
INLINE void add_event(ButtonEvent event);
|
||||
INLINE int get_num_events() const;
|
||||
|
@ -351,6 +351,19 @@ get_press_prefix() {
|
||||
return "press-";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PGItem::get_repeat_prefix
|
||||
// Access: Published, Static
|
||||
// Description: Returns the prefix that is used to define the repeat
|
||||
// event for all PGItems. The repeat event is the
|
||||
// concatenation of this string followed by a button
|
||||
// name, followed by a hyphen and get_id().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE string PGItem::
|
||||
get_repeat_prefix() {
|
||||
return "repeat-";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PGItem::get_release_prefix
|
||||
// Access: Published, Static
|
||||
@ -465,6 +478,19 @@ get_press_event(const ButtonHandle &button) const {
|
||||
return get_press_prefix() + button.get_name() + "-" + get_id();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PGItem::get_repeat_event
|
||||
// Access: Published
|
||||
// Description: Returns the event name that will be thrown when the
|
||||
// item is active and the indicated mouse or keyboard
|
||||
// button is continuously held down while the mouse is
|
||||
// within the frame.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE string PGItem::
|
||||
get_repeat_event(const ButtonHandle &button) const {
|
||||
return get_repeat_prefix() + button.get_name() + "-" + get_id();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PGItem::get_release_event
|
||||
// Access: Published
|
||||
|
@ -583,7 +583,12 @@ void PGItem::
|
||||
press(const MouseWatcherParameter ¶m, bool background) {
|
||||
if (!background) {
|
||||
PGMouseWatcherParameter *ep = new PGMouseWatcherParameter(param);
|
||||
string event = get_press_event(param.get_button());
|
||||
string event;
|
||||
if (param.is_keyrepeat()) {
|
||||
event = get_repeat_event(param.get_button());
|
||||
} else {
|
||||
event = get_press_event(param.get_button());
|
||||
}
|
||||
play_sound(event);
|
||||
throw_event(event, EventParameter(ep));
|
||||
}
|
||||
|
@ -139,6 +139,7 @@ PUBLISHED:
|
||||
INLINE static string get_focus_in_prefix();
|
||||
INLINE static string get_focus_out_prefix();
|
||||
INLINE static string get_press_prefix();
|
||||
INLINE static string get_repeat_prefix();
|
||||
INLINE static string get_release_prefix();
|
||||
INLINE static string get_keystroke_prefix();
|
||||
|
||||
@ -149,6 +150,7 @@ PUBLISHED:
|
||||
INLINE string get_focus_in_event() const;
|
||||
INLINE string get_focus_out_event() const;
|
||||
INLINE string get_press_event(const ButtonHandle &button) const;
|
||||
INLINE string get_repeat_event(const ButtonHandle &button) const;
|
||||
INLINE string get_release_event(const ButtonHandle &button) const;
|
||||
INLINE string get_keystroke_event() const;
|
||||
|
||||
|
@ -30,6 +30,17 @@ INLINE ButtonHandle::
|
||||
ButtonHandle() {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ButtonHandle::Constructor
|
||||
// Access: Published
|
||||
// Description: Constructs a ButtonHandle with the corresponding
|
||||
// index number, which may have been returned by an
|
||||
// earlier call to ButtonHandle::get_index().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE ButtonHandle::
|
||||
ButtonHandle(int index) : _index(index) {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ButtonHandle::Copy Constructor
|
||||
// Access: Published
|
||||
|
@ -30,6 +30,7 @@
|
||||
class EXPCL_PANDA ButtonHandle {
|
||||
PUBLISHED:
|
||||
INLINE ButtonHandle();
|
||||
INLINE ButtonHandle(int index);
|
||||
|
||||
public:
|
||||
INLINE ButtonHandle(const ButtonHandle ©);
|
||||
|
@ -72,6 +72,38 @@ get_button_up_event() const {
|
||||
return _button_up_event;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ButtonThrower::set_button_repeat_event
|
||||
// Access: Published
|
||||
// Description: Specifies the generic event that is generated (if
|
||||
// any) repeatedly while a key or button is held down.
|
||||
// Unlike the specific events that are unique to each
|
||||
// key, this same event name is used for *all* button
|
||||
// events, and the name of the button pressed (possibly
|
||||
// with modifier prefixes) will be sent as a parameter.
|
||||
//
|
||||
// If this string is empty, no event is generated. It
|
||||
// is possible to generate both generic events and
|
||||
// specific events for the same button.
|
||||
//
|
||||
// See also set_keystroke_event().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void ButtonThrower::
|
||||
set_button_repeat_event(const string &button_repeat_event) {
|
||||
_button_repeat_event = button_repeat_event;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ButtonThrower::get_button_repeat_event
|
||||
// Access: Published
|
||||
// Description: Returns the button_repeat_event that has been set on
|
||||
// this ButtonThrower. See set_button_repeat_event().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE const string &ButtonThrower::
|
||||
get_button_repeat_event() const {
|
||||
return _button_repeat_event;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ButtonThrower::set_keystroke_event
|
||||
// Access: Published
|
||||
@ -83,6 +115,12 @@ get_button_up_event() const {
|
||||
// together will generate the button event "shift-4",
|
||||
// but it will generate the keystroke "$".
|
||||
//
|
||||
// If a key is held down, keyrepeat will cause the same
|
||||
// keystroke event to be generated repeatedly. This is
|
||||
// different from the corresponding down event, which
|
||||
// will only be generated once, followed by a number of
|
||||
// button repeat events.
|
||||
//
|
||||
// This event is generated with a single wstring
|
||||
// parameter, which is a one-character string that
|
||||
// contains the keystroke generated. If this event
|
||||
|
@ -307,6 +307,10 @@ do_general_event(const ButtonEvent &button_event, const string &button_name) {
|
||||
event_name = _button_up_event;
|
||||
break;
|
||||
|
||||
case ButtonEvent::T_repeat:
|
||||
event_name = _button_repeat_event;
|
||||
break;
|
||||
|
||||
case ButtonEvent::T_keystroke:
|
||||
event_name = _keystroke_event;
|
||||
break;
|
||||
@ -388,7 +392,7 @@ do_transmit_data(DataGraphTraverser *, const DataNodeTransmit &input,
|
||||
const ButtonEvent &be = button_events->get_event(i);
|
||||
string event_name = be._button.get_name();
|
||||
|
||||
if (be._type == ButtonEvent::T_down) {
|
||||
if (be._type == ButtonEvent::T_down || be._type == ButtonEvent::T_repeat) {
|
||||
// Button down.
|
||||
if (!_mods.button_down(be._button)) {
|
||||
// We only prepend modifier names on the button-down events,
|
||||
@ -398,7 +402,11 @@ do_transmit_data(DataGraphTraverser *, const DataNodeTransmit &input,
|
||||
|
||||
if (!_throw_buttons_active || has_throw_button(_mods, be._button)) {
|
||||
// Process this button.
|
||||
if (be._type == ButtonEvent::T_repeat) {
|
||||
do_specific_event(event_name + "-repeat", be._time);
|
||||
} else {
|
||||
do_specific_event(event_name, be._time);
|
||||
}
|
||||
do_general_event(be, event_name);
|
||||
|
||||
} else {
|
||||
|
@ -49,6 +49,8 @@ PUBLISHED:
|
||||
INLINE const string &get_button_down_event() const;
|
||||
INLINE void set_button_up_event(const string &button_up_event);
|
||||
INLINE const string &get_button_up_event() const;
|
||||
INLINE void set_button_repeat_event(const string &button_repeat_event);
|
||||
INLINE const string &get_button_repeat_event() const;
|
||||
INLINE void set_keystroke_event(const string &keystroke_event);
|
||||
INLINE const string &get_keystroke_event() const;
|
||||
INLINE void set_candidate_event(const string &candidate_event);
|
||||
@ -92,6 +94,7 @@ private:
|
||||
private:
|
||||
string _button_down_event;
|
||||
string _button_up_event;
|
||||
string _button_repeat_event;
|
||||
string _keystroke_event;
|
||||
string _candidate_event;
|
||||
string _move_event;
|
||||
|
@ -422,7 +422,7 @@ do_transmit_data(DataGraphTraverser *, const DataNodeTransmit &input,
|
||||
for (int i = 0; i < num_events; i++) {
|
||||
const ButtonEvent &be = button_events->get_event(i);
|
||||
if (be._type != ButtonEvent::T_keystroke) {
|
||||
bool down = (be._type == ButtonEvent::T_down);
|
||||
bool down = (be._type != ButtonEvent::T_up);
|
||||
|
||||
if (be._button == KeyboardButton::up()) {
|
||||
_up_arrow.set_key(down);
|
||||
|
@ -138,6 +138,17 @@ get_over_region(float x, float y) const {
|
||||
return get_over_region(LPoint2f(x, y));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MouseWatcher::is_button_down
|
||||
// Access: Published
|
||||
// Description: Returns true if the indicated button is currently
|
||||
// being held down, false otherwise.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool MouseWatcher::
|
||||
is_button_down(ButtonHandle button) const {
|
||||
return _inactivity_state != IS_inactive && _current_buttons_down.get_bit(button.get_index());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MouseWatcher::set_button_down_pattern
|
||||
// Access: Published
|
||||
@ -193,6 +204,39 @@ get_button_up_pattern() const {
|
||||
return _button_up_pattern;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MouseWatcher::set_button_repeat_pattern
|
||||
// Access: Published
|
||||
// Description: Sets the pattern string that indicates how the event
|
||||
// names are generated when a button is continuously
|
||||
// held and generates keyrepeat "down" events. This is
|
||||
// a string that may contain any of the following:
|
||||
//
|
||||
// %r - the name of the region the mouse is over
|
||||
// %b - the name of the button pressed.
|
||||
//
|
||||
// The event name will be based on the in_pattern
|
||||
// string specified here, with all occurrences of the
|
||||
// above strings replaced with the corresponding values.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void MouseWatcher::
|
||||
set_button_repeat_pattern(const string &pattern) {
|
||||
_button_repeat_pattern = pattern;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MouseWatcher::get_button_repeat_pattern
|
||||
// Access: Published
|
||||
// Description: Returns the string that indicates how event names are
|
||||
// names are generated when a button is continuously
|
||||
// held and generates keyrepeat "down" events. See
|
||||
// set_button_repeat_pattern().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE const string &MouseWatcher::
|
||||
get_button_repeat_pattern() const {
|
||||
return _button_repeat_pattern;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MouseWatcher::set_enter_pattern
|
||||
// Access: Published
|
||||
@ -463,6 +507,62 @@ has_display_region() const {
|
||||
return (_display_region != (DisplayRegion *)NULL);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MouseWatcher::set_inactivity_timeout
|
||||
// Access: Published
|
||||
// Description: Sets an inactivity timeout on the mouse activity.
|
||||
// When this timeout (in seconds) is exceed with no
|
||||
// keyboard or mouse activity, all currently-held
|
||||
// buttons are automatically released. This is intended
|
||||
// to help protect against people who inadvertently (or
|
||||
// intentionally) leave a keyboard key stuck down and
|
||||
// then wander away from the keyboard.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void MouseWatcher::
|
||||
set_inactivity_timeout(double timeout) {
|
||||
_has_inactivity_timeout = true;
|
||||
_inactivity_timeout = timeout;
|
||||
note_activity();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MouseWatcher::has_inactivity_timeout
|
||||
// Access: Published
|
||||
// Description: Returns true if an inactivity timeout has been set,
|
||||
// false otherwise.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool MouseWatcher::
|
||||
has_inactivity_timeout() const {
|
||||
return _has_inactivity_timeout;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MouseWatcher::get_inactivity_timeout
|
||||
// Access: Published
|
||||
// Description: Returns the inactivity timeout that has been set.
|
||||
// It is an error to call this if
|
||||
// has_inactivity_timeout() returns false.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE double MouseWatcher::
|
||||
get_inactivity_timeout() const {
|
||||
nassertr(_has_inactivity_timeout, 0.0);
|
||||
return _inactivity_timeout;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MouseWatcher::clear_inactivity_timeout
|
||||
// Access: Published
|
||||
// Description: Removes the inactivity timeout and restores the
|
||||
// MouseWatcher to its default behavior of allowing a
|
||||
// key to be held indefinitely.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void MouseWatcher::
|
||||
clear_inactivity_timeout() {
|
||||
_has_inactivity_timeout = false;
|
||||
_inactivity_timeout = 0.0;
|
||||
note_activity();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MouseWatcher::within_region
|
||||
// Access: Protected
|
||||
|
@ -67,6 +67,10 @@ MouseWatcher(const string &name) :
|
||||
_button_down = false;
|
||||
_eh = (EventHandler *)NULL;
|
||||
_display_region = (DisplayRegion *)NULL;
|
||||
_has_inactivity_timeout = false;
|
||||
_inactivity_timeout = 0.0;
|
||||
_last_activity = 0.0;
|
||||
_inactivity_state = IS_active;
|
||||
|
||||
// When this flag is true, the mouse pointer is allowed to be
|
||||
// "entered" into multiple regions simultaneously; when false, it
|
||||
@ -336,6 +340,41 @@ get_group(int n) const {
|
||||
return _groups[n];
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MouseWatcher::note_activity
|
||||
// Access: Published
|
||||
// Description: Can be used in conjunction with the inactivity
|
||||
// timeout to inform the MouseWatcher that the user has
|
||||
// just performed some action which proves he/she is
|
||||
// present. It may be necessary to call this for
|
||||
// external events, such as joystick action, that the
|
||||
// MouseWatcher might otherwise not know about. This
|
||||
// will reset the current inactivity timer. When the
|
||||
// inactivity timer reaches the length of time specified
|
||||
// by set_inactivity_timeout(), with no keyboard or
|
||||
// mouse activity and no calls to note_activity(), then
|
||||
// any buttons held will be automatically released.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void MouseWatcher::
|
||||
note_activity() {
|
||||
_last_activity = ClockObject::get_global_clock()->get_frame_time();
|
||||
switch (_inactivity_state) {
|
||||
case IS_active:
|
||||
break;
|
||||
|
||||
case IS_inactive:
|
||||
_inactivity_state = IS_inactive_to_active;
|
||||
break;
|
||||
|
||||
case IS_active_to_inactive:
|
||||
_inactivity_state = IS_active;
|
||||
break;
|
||||
|
||||
case IS_inactive_to_active:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MouseWatcher::output
|
||||
@ -810,11 +849,12 @@ move() {
|
||||
// being depressed.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void MouseWatcher::
|
||||
press(ButtonHandle button) {
|
||||
press(ButtonHandle button, bool keyrepeat) {
|
||||
nassertv(_lock.debug_is_locked());
|
||||
|
||||
MouseWatcherParameter param;
|
||||
param.set_button(button);
|
||||
param.set_keyrepeat(keyrepeat);
|
||||
param.set_modifier_buttons(_mods);
|
||||
param.set_mouse(_mouse);
|
||||
|
||||
@ -828,9 +868,14 @@ press(ButtonHandle button) {
|
||||
|
||||
if (_preferred_button_down_region != (MouseWatcherRegion *)NULL) {
|
||||
_preferred_button_down_region->press(param);
|
||||
if (keyrepeat) {
|
||||
throw_event_pattern(_button_repeat_pattern,
|
||||
_preferred_button_down_region, button);
|
||||
} else {
|
||||
throw_event_pattern(_button_down_pattern,
|
||||
_preferred_button_down_region, button);
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
// It's a keyboard button; therefore, send the event to every
|
||||
@ -1186,6 +1231,8 @@ do_transmit_data(DataGraphTraverser *trav, const DataNodeTransmit &input,
|
||||
Thread *current_thread = trav->get_current_thread();
|
||||
MutexHolder holder(_lock);
|
||||
|
||||
bool activity = false;
|
||||
|
||||
// Initially, we do not suppress any events to objects below us in
|
||||
// the data graph.
|
||||
_internal_suppress = 0;
|
||||
@ -1207,6 +1254,7 @@ do_transmit_data(DataGraphTraverser *trav, const DataNodeTransmit &input,
|
||||
// Asad: determine if mouse moved from last position
|
||||
const LVecBase2f &last_f = _xy->get_value();
|
||||
if (f != last_f) {
|
||||
activity = true;
|
||||
move();
|
||||
}
|
||||
|
||||
@ -1260,34 +1308,63 @@ do_transmit_data(DataGraphTraverser *trav, const DataNodeTransmit &input,
|
||||
_internal_suppress |= _preferred_region->get_suppress_flags();
|
||||
}
|
||||
|
||||
// Look for button events.
|
||||
ButtonEventList new_button_events;
|
||||
|
||||
// Look for new button events.
|
||||
if (input.has_data(_button_events_input)) {
|
||||
const ButtonEventList *button_events;
|
||||
DCAST_INTO_V(button_events, input.get_data(_button_events_input).get_ptr());
|
||||
int num_events = button_events->get_num_events();
|
||||
const ButtonEventList *this_button_events;
|
||||
DCAST_INTO_V(this_button_events, input.get_data(_button_events_input).get_ptr());
|
||||
int num_events = this_button_events->get_num_events();
|
||||
for (int i = 0; i < num_events; i++) {
|
||||
const ButtonEvent &be = button_events->get_event(i);
|
||||
const ButtonEvent &be = this_button_events->get_event(i);
|
||||
be.update_mods(_mods);
|
||||
|
||||
switch (be._type) {
|
||||
case ButtonEvent::T_down:
|
||||
press(be._button);
|
||||
if (!_current_buttons_down.get_bit(be._button.get_index())) {
|
||||
// The button was not already depressed; thus, this is not
|
||||
// keyrepeat.
|
||||
activity = true;
|
||||
_current_buttons_down.set_bit(be._button.get_index());
|
||||
press(be._button, false);
|
||||
new_button_events.add_event(be);
|
||||
break;
|
||||
}
|
||||
// The button was already depressed, so this is really just
|
||||
// keyrepeat. Fall through.
|
||||
|
||||
case ButtonEvent::T_repeat:
|
||||
_current_buttons_down.set_bit(be._button.get_index());
|
||||
press(be._button, true);
|
||||
new_button_events.add_event(ButtonEvent(be._button, ButtonEvent::T_repeat,
|
||||
be._time));
|
||||
break;
|
||||
|
||||
case ButtonEvent::T_up:
|
||||
activity = true;
|
||||
_current_buttons_down.clear_bit(be._button.get_index());
|
||||
release(be._button);
|
||||
new_button_events.add_event(be);
|
||||
break;
|
||||
|
||||
case ButtonEvent::T_keystroke:
|
||||
// We don't consider "keystroke" an activity event, because it
|
||||
// might be just keyrepeat.
|
||||
keystroke(be._keycode);
|
||||
new_button_events.add_event(be);
|
||||
break;
|
||||
|
||||
case ButtonEvent::T_candidate:
|
||||
activity = true;
|
||||
candidate(be._candidate_string, be._highlight_start, be._highlight_end, be._cursor_pos);
|
||||
new_button_events.add_event(be);
|
||||
break;
|
||||
|
||||
case ButtonEvent::T_resume_down:
|
||||
// Ignore this, since the button wasn't pressed just now.
|
||||
_current_buttons_down.set_bit(be._button.get_index());
|
||||
// Don't call press(), since the button wasn't actually
|
||||
// pressed just now.
|
||||
new_button_events.add_event(be);
|
||||
break;
|
||||
|
||||
case ButtonEvent::T_move:
|
||||
@ -1297,6 +1374,73 @@ do_transmit_data(DataGraphTraverser *trav, const DataNodeTransmit &input,
|
||||
}
|
||||
}
|
||||
|
||||
// Now check the inactivity timer.
|
||||
if (_has_inactivity_timeout) {
|
||||
if (activity) {
|
||||
note_activity();
|
||||
|
||||
} else {
|
||||
double now = ClockObject::get_global_clock()->get_frame_time();
|
||||
double elapsed = now - _last_activity;
|
||||
|
||||
// Toggle the inactivity state to inactive.
|
||||
if (elapsed > _inactivity_timeout) {
|
||||
switch (_inactivity_state) {
|
||||
case IS_active:
|
||||
_inactivity_state = IS_active_to_inactive;
|
||||
break;
|
||||
|
||||
case IS_inactive:
|
||||
break;
|
||||
|
||||
case IS_active_to_inactive:
|
||||
break;
|
||||
|
||||
case IS_inactive_to_active:
|
||||
_inactivity_state = IS_inactive;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch (_inactivity_state) {
|
||||
case IS_active:
|
||||
case IS_inactive:
|
||||
break;
|
||||
|
||||
case IS_active_to_inactive:
|
||||
// "Release" all of the currently-held buttons.
|
||||
if (tform_cat.is_debug()) {
|
||||
tform_cat.info()
|
||||
<< "MouseWatcher detected " << _inactivity_timeout
|
||||
<< " seconds of inactivity; releasing held buttons.\n";
|
||||
}
|
||||
{
|
||||
for (int i = 0; i < _current_buttons_down.get_num_bits(); ++i) {
|
||||
if (_current_buttons_down.get_bit(i)) {
|
||||
release(ButtonHandle(i));
|
||||
new_button_events.add_event(ButtonEvent(ButtonHandle(i), ButtonEvent::T_up));
|
||||
}
|
||||
}
|
||||
}
|
||||
_inactivity_state = IS_inactive;
|
||||
break;
|
||||
|
||||
case IS_inactive_to_active:
|
||||
// "Press" all of the buttons we "released" before.
|
||||
{
|
||||
for (int i = 0; i < _current_buttons_down.get_num_bits(); ++i) {
|
||||
if (_current_buttons_down.get_bit(i)) {
|
||||
press(ButtonHandle(i), false);
|
||||
new_button_events.add_event(ButtonEvent(ButtonHandle(i), ButtonEvent::T_down));
|
||||
}
|
||||
}
|
||||
}
|
||||
_inactivity_state = IS_active;
|
||||
break;
|
||||
}
|
||||
|
||||
if (_has_mouse &&
|
||||
(_internal_suppress & MouseWatcherRegion::SF_mouse_position) == 0) {
|
||||
// Transmit the mouse position.
|
||||
@ -1306,18 +1450,14 @@ do_transmit_data(DataGraphTraverser *trav, const DataNodeTransmit &input,
|
||||
output.set_data(_pixel_xy_output, EventParameter(_pixel_xy));
|
||||
}
|
||||
|
||||
// Now transmit the buttons events down the graph.
|
||||
int suppress_buttons = ((_internal_suppress | _external_suppress) & MouseWatcherRegion::SF_any_button);
|
||||
|
||||
if (suppress_buttons != 0) {
|
||||
// Suppress some buttons.
|
||||
_button_events->clear();
|
||||
|
||||
if (input.has_data(_button_events_input)) {
|
||||
const ButtonEventList *button_events;
|
||||
DCAST_INTO_V(button_events, input.get_data(_button_events_input).get_ptr());
|
||||
int num_events = button_events->get_num_events();
|
||||
int num_events = new_button_events.get_num_events();
|
||||
for (int i = 0; i < num_events; i++) {
|
||||
const ButtonEvent &be = button_events->get_event(i);
|
||||
const ButtonEvent &be = new_button_events.get_event(i);
|
||||
bool suppress = true;
|
||||
|
||||
if (be._type != ButtonEvent::T_keystroke &&
|
||||
@ -1332,17 +1472,11 @@ do_transmit_data(DataGraphTraverser *trav, const DataNodeTransmit &input,
|
||||
_button_events->add_event(be);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (_button_events->get_num_events() != 0) {
|
||||
output.set_data(_button_events_output, EventParameter(_button_events));
|
||||
}
|
||||
|
||||
} else {
|
||||
// Transmit all buttons.
|
||||
output.set_data(_button_events_output, input.get_data(_button_events_input));
|
||||
}
|
||||
|
||||
// We always pass the pixel_size data through.
|
||||
output.set_data(_pixel_size_output, input.get_data(_pixel_size_input));
|
||||
}
|
||||
|
@ -31,6 +31,8 @@
|
||||
#include "buttonHandle.h"
|
||||
#include "buttonEventList.h"
|
||||
#include "linmath_events.h"
|
||||
#include "bitArray.h"
|
||||
#include "clockObject.h"
|
||||
#include "pvector.h"
|
||||
|
||||
class MouseWatcherParameter;
|
||||
@ -75,12 +77,17 @@ PUBLISHED:
|
||||
INLINE MouseWatcherRegion *get_over_region(float x, float y) const;
|
||||
MouseWatcherRegion *get_over_region(const LPoint2f &pos) const;
|
||||
|
||||
INLINE bool is_button_down(ButtonHandle button) const;
|
||||
|
||||
INLINE void set_button_down_pattern(const string &pattern);
|
||||
INLINE const string &get_button_down_pattern() const;
|
||||
|
||||
INLINE void set_button_up_pattern(const string &pattern);
|
||||
INLINE const string &get_button_up_pattern() const;
|
||||
|
||||
INLINE void set_button_repeat_pattern(const string &pattern);
|
||||
INLINE const string &get_button_repeat_pattern() const;
|
||||
|
||||
INLINE void set_enter_pattern(const string &pattern);
|
||||
INLINE const string &get_enter_pattern() const;
|
||||
|
||||
@ -115,6 +122,12 @@ PUBLISHED:
|
||||
int get_num_groups() const;
|
||||
MouseWatcherGroup *get_group(int n) const;
|
||||
|
||||
INLINE void set_inactivity_timeout(double timeout);
|
||||
INLINE bool has_inactivity_timeout() const;
|
||||
INLINE double get_inactivity_timeout() const;
|
||||
INLINE void clear_inactivity_timeout();
|
||||
void note_activity();
|
||||
|
||||
public:
|
||||
virtual void output(ostream &out) const;
|
||||
virtual void write(ostream &out, int indent_level = 0) const;
|
||||
@ -147,7 +160,7 @@ protected:
|
||||
const ButtonHandle &button);
|
||||
|
||||
void move();
|
||||
void press(ButtonHandle button);
|
||||
void press(ButtonHandle button, bool keyrepeat);
|
||||
void release(ButtonHandle button);
|
||||
void keystroke(int keycode);
|
||||
void candidate(const wstring &candidate, size_t highlight_start,
|
||||
@ -178,6 +191,7 @@ private:
|
||||
int _external_suppress;
|
||||
LPoint2f _mouse;
|
||||
LPoint2f _mouse_pixel;
|
||||
BitArray _current_buttons_down;
|
||||
|
||||
Regions _current_regions;
|
||||
PT(MouseWatcherRegion) _preferred_region;
|
||||
@ -189,6 +203,7 @@ private:
|
||||
|
||||
string _button_down_pattern;
|
||||
string _button_up_pattern;
|
||||
string _button_repeat_pattern;
|
||||
string _enter_pattern;
|
||||
string _leave_pattern;
|
||||
string _within_pattern;
|
||||
@ -200,6 +215,18 @@ private:
|
||||
ModifierButtons _mods;
|
||||
DisplayRegion *_display_region;
|
||||
|
||||
bool _has_inactivity_timeout;
|
||||
double _inactivity_timeout;
|
||||
double _last_activity;
|
||||
|
||||
enum InactivityState {
|
||||
IS_active,
|
||||
IS_inactive,
|
||||
IS_active_to_inactive,
|
||||
IS_inactive_to_active,
|
||||
};
|
||||
InactivityState _inactivity_state;
|
||||
|
||||
#ifndef NDEBUG
|
||||
NodePath _show_regions_render2d;
|
||||
string _show_regions_bin_name;
|
||||
|
@ -77,6 +77,23 @@ set_button(const ButtonHandle &button) {
|
||||
_flags |= F_has_button;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MouseWatcherParameter::set_keyrepeat
|
||||
// Access: Public
|
||||
// Description: Sets the state of the "keyrepeat" flag. This is true
|
||||
// if a button-press event was generated due to
|
||||
// keyrepeat, or false if it is an original button
|
||||
// press.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void MouseWatcherParameter::
|
||||
set_keyrepeat(bool flag) {
|
||||
if (flag) {
|
||||
_flags |= F_is_keyrepeat;
|
||||
} else {
|
||||
_flags &= ~F_is_keyrepeat;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MouseWatcherParameter::set_keycode
|
||||
// Access: Public
|
||||
@ -168,6 +185,18 @@ get_button() const {
|
||||
return _button;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MouseWatcherParameter::is_keyrepeat
|
||||
// Access: Published
|
||||
// Description: Returns true if the button-down even was generated
|
||||
// due to keyrepeat, or false if it was an original
|
||||
// button down.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool MouseWatcherParameter::
|
||||
is_keyrepeat() const {
|
||||
return (_flags & F_is_keyrepeat) != 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MouseWatcherParameter::has_keycode
|
||||
// Access: Published
|
||||
|
@ -40,6 +40,7 @@ public:
|
||||
INLINE ~MouseWatcherParameter();
|
||||
|
||||
INLINE void set_button(const ButtonHandle &button);
|
||||
INLINE void set_keyrepeat(bool flag);
|
||||
INLINE void set_keycode(int keycode);
|
||||
INLINE void set_candidate(const wstring &candidate_string,
|
||||
size_t highlight_start,
|
||||
@ -52,6 +53,7 @@ public:
|
||||
PUBLISHED:
|
||||
INLINE bool has_button() const;
|
||||
INLINE ButtonHandle get_button() const;
|
||||
INLINE bool is_keyrepeat() const;
|
||||
|
||||
INLINE bool has_keycode() const;
|
||||
INLINE int get_keycode() const;
|
||||
@ -93,6 +95,7 @@ public:
|
||||
F_is_outside = 0x004,
|
||||
F_has_keycode = 0x008,
|
||||
F_has_candidate = 0x010,
|
||||
F_is_keyrepeat = 0x020,
|
||||
};
|
||||
int _flags;
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user