mirror of
https://github.com/genodelabs/genode.git
synced 2025-04-20 00:52:01 +00:00
nitpicker: handle touch independent from motion
This patch decouples nitpicker's handling of touch events from the handling of pointer devices. The mouse pointer is no longer following touch position but stays independent. The existing "hover" report has now a counterpart "touch" that reports the most recently touched session, including the initial touch point and last observed sequence number. Issue #5496 Issue #5485
This commit is contained in:
parent
3b28ea3e59
commit
c17653dafa
@ -238,6 +238,7 @@ The 'hover' attribute enables the reporting of the currently hovered session.
|
||||
The 'focus' attribute enables the reporting of the currently focused session.
|
||||
The 'pointer' attribute enables the reporting of the current absolute pointer
|
||||
position.
|
||||
The 'touch' attribute enables the reporting of the currently touched session.
|
||||
The 'keystate' attribute enables the reporting of the currently pressed keys.
|
||||
The 'clicked' attribute enables the reporting of the last clicked-on unfocused
|
||||
client. This report is useful for a focus-managing component to implement a
|
||||
|
@ -100,6 +100,7 @@ class Nitpicker::Gui_root : public Root_component<Gui_session>
|
||||
View &_pointer_origin;
|
||||
View &_builtin_background;
|
||||
Reporter &_focus_reporter;
|
||||
Reporter &_touch_reporter;
|
||||
Focus_updater &_focus_updater;
|
||||
Hover_updater &_hover_updater;
|
||||
|
||||
@ -158,6 +159,11 @@ class Nitpicker::Gui_root : public Root_component<Gui_session>
|
||||
if (result.hover_changed)
|
||||
_hover_updater.update_hover();
|
||||
|
||||
if (result.touch_changed) {
|
||||
Reporter::Xml_generator xml(_touch_reporter, [&] {
|
||||
_user_state.report_touched_view_owner(xml, false); });
|
||||
}
|
||||
|
||||
/* report focus changes */
|
||||
if (_focus_reporter.enabled() && result.focus_changed) {
|
||||
Reporter::Xml_generator xml(_focus_reporter, [&] () {
|
||||
@ -182,6 +188,7 @@ class Nitpicker::Gui_root : public Root_component<Gui_session>
|
||||
View &builtin_background,
|
||||
Allocator &md_alloc,
|
||||
Reporter &focus_reporter,
|
||||
Reporter &touch_reporter,
|
||||
Focus_updater &focus_updater,
|
||||
Hover_updater &hover_updater)
|
||||
:
|
||||
@ -191,8 +198,8 @@ class Nitpicker::Gui_root : public Root_component<Gui_session>
|
||||
_view_stack(view_stack), _user_state(user_state),
|
||||
_pointer_origin(pointer_origin),
|
||||
_builtin_background(builtin_background),
|
||||
_focus_reporter(focus_reporter), _focus_updater(focus_updater),
|
||||
_hover_updater(hover_updater)
|
||||
_focus_reporter(focus_reporter), _touch_reporter(touch_reporter),
|
||||
_focus_updater(focus_updater), _hover_updater(hover_updater)
|
||||
{ }
|
||||
};
|
||||
|
||||
@ -635,6 +642,7 @@ struct Nitpicker::Main : Focus_updater, Hover_updater,
|
||||
Reporter _pointer_reporter = { _env, "pointer" };
|
||||
Reporter _hover_reporter = { _env, "hover" };
|
||||
Reporter _focus_reporter = { _env, "focus" };
|
||||
Reporter _touch_reporter = { _env, "touch" };
|
||||
Reporter _keystate_reporter = { _env, "keystate" };
|
||||
Reporter _clicked_reporter = { _env, "clicked" };
|
||||
Reporter _panorama_reporter = { _env, "panorama" };
|
||||
@ -646,7 +654,7 @@ struct Nitpicker::Main : Focus_updater, Hover_updater,
|
||||
Gui_root _gui_root { _env, *this, _config_rom, _session_list, *_domain_registry,
|
||||
_global_keys, _view_stack, _user_state, _pointer_origin,
|
||||
_builtin_background, _sliced_heap,
|
||||
_focus_reporter, *this, *this };
|
||||
_focus_reporter, _touch_reporter, *this, *this };
|
||||
|
||||
/**
|
||||
* Gui_session::Action interface
|
||||
@ -870,12 +878,15 @@ struct Nitpicker::Main : Focus_updater, Hover_updater,
|
||||
|
||||
bool _reported_button_activity = false;
|
||||
bool _reported_motion_activity = false;
|
||||
bool _reported_touch_activity = false;
|
||||
|
||||
unsigned _reported_focus_count = 0;
|
||||
unsigned _reported_hover_count = 0;
|
||||
unsigned _reported_touch_count = 0;
|
||||
|
||||
unsigned _focus_count = 0;
|
||||
unsigned _hover_count = 0;
|
||||
unsigned _touch_count = 0;
|
||||
|
||||
void _update_motion_and_focus_activity_reports();
|
||||
|
||||
@ -883,7 +894,8 @@ struct Nitpicker::Main : Focus_updater, Hover_updater,
|
||||
* Track when the user was active the last time
|
||||
*/
|
||||
Ticks _last_button_activity { },
|
||||
_last_motion_activity { };
|
||||
_last_motion_activity { },
|
||||
_last_touch_activity { };
|
||||
|
||||
/**
|
||||
* Number of milliseconds since the last user interaction, after which
|
||||
@ -940,6 +952,7 @@ void Nitpicker::Main::handle_input_events(User_state::Input_batch batch)
|
||||
|
||||
if (result.button_activity) _last_button_activity = now;
|
||||
if (result.motion_activity) _last_motion_activity = now;
|
||||
if (result.touch_activity) _last_touch_activity = now;
|
||||
|
||||
/*
|
||||
* Report information about currently pressed keys whenever the key state
|
||||
@ -964,6 +977,9 @@ void Nitpicker::Main::handle_input_events(User_state::Input_batch batch)
|
||||
_view_stack.update_all_views();
|
||||
}
|
||||
|
||||
if (result.touch_activity || result.last_seq_changed)
|
||||
_touch_count++;
|
||||
|
||||
if (result.hover_changed || result.last_seq_changed)
|
||||
_hover_count++;
|
||||
|
||||
@ -987,6 +1003,7 @@ void Nitpicker::Main::_update_motion_and_focus_activity_reports()
|
||||
|
||||
bool const button_activity = (now.ms - _last_button_activity.ms < _activity_threshold.ms);
|
||||
bool const motion_activity = (now.ms - _last_motion_activity.ms < _activity_threshold.ms);
|
||||
bool const touch_activity = (now.ms - _last_touch_activity .ms < _activity_threshold.ms);
|
||||
|
||||
bool const hover_changed = (_reported_hover_count != _hover_count);
|
||||
if (hover_changed || (_reported_motion_activity != motion_activity)) {
|
||||
@ -1002,10 +1019,18 @@ void Nitpicker::Main::_update_motion_and_focus_activity_reports()
|
||||
_user_state.report_focused_view_owner(xml, button_activity); });
|
||||
}
|
||||
|
||||
bool const touch_changed = (_reported_touch_count != _touch_count);
|
||||
if (touch_changed || (_reported_touch_activity != touch_activity)) {
|
||||
Reporter::Xml_generator xml(_touch_reporter, [&] {
|
||||
_user_state.report_touched_view_owner(xml, touch_activity); });
|
||||
}
|
||||
|
||||
_reported_motion_activity = motion_activity;
|
||||
_reported_button_activity = button_activity;
|
||||
_reported_touch_activity = touch_activity;
|
||||
_reported_hover_count = _hover_count;
|
||||
_reported_focus_count = _focus_count;
|
||||
_reported_touch_count = _touch_count;
|
||||
}
|
||||
|
||||
|
||||
@ -1075,6 +1100,7 @@ void Nitpicker::Main::_handle_config()
|
||||
configure_reporter(config, _pointer_reporter);
|
||||
configure_reporter(config, _hover_reporter);
|
||||
configure_reporter(config, _focus_reporter);
|
||||
configure_reporter(config, _touch_reporter);
|
||||
configure_reporter(config, _keystate_reporter);
|
||||
configure_reporter(config, _clicked_reporter);
|
||||
configure_reporter(config, _panorama_reporter);
|
||||
|
@ -111,10 +111,6 @@ void User_state::_handle_input_event(Input::Event ev)
|
||||
[&] (Nowhere) { ev = { }; });
|
||||
});
|
||||
|
||||
/* let pointer position correspond to most recent touch position */
|
||||
ev.handle_touch([&] (Input::Touch_id, float x, float y) {
|
||||
_try_move_pointer({ int(x), int(y) }); });
|
||||
|
||||
/* track key states, drop double press/release events */
|
||||
{
|
||||
bool drop = false;
|
||||
@ -143,7 +139,7 @@ void User_state::_handle_input_event(Input::Event ev)
|
||||
if (ev.press()) _key_cnt++;
|
||||
if (ev.release() && (_key_cnt > 0)) _key_cnt--;
|
||||
|
||||
if (ev.absolute_motion() || ev.relative_motion() || ev.touch()) {
|
||||
if (ev.absolute_motion() || ev.relative_motion()) {
|
||||
update_hover();
|
||||
|
||||
if (_key_cnt > 0) {
|
||||
@ -162,6 +158,16 @@ void User_state::_handle_input_event(Input::Event ev)
|
||||
}
|
||||
}
|
||||
|
||||
ev.handle_touch([&] (Input::Touch_id id, float x, float y) {
|
||||
|
||||
if (id.value == 0) {
|
||||
Point at { int(x), int(y) };
|
||||
View const * const touched_view = _view_stack.find_view(at);
|
||||
_touched = touched_view ? &touched_view->owner() : nullptr;
|
||||
_touched_position = at;
|
||||
}
|
||||
});
|
||||
|
||||
/*
|
||||
* Handle start of a key sequence
|
||||
*/
|
||||
@ -281,6 +287,18 @@ void User_state::_handle_input_event(Input::Event ev)
|
||||
receiver = abs_motion_receiver();
|
||||
}
|
||||
|
||||
if (ev.touch() || ev.touch_release())
|
||||
if (_touched)
|
||||
receiver = _touched;
|
||||
|
||||
if (ev.seq_number()) {
|
||||
receiver = _focused;
|
||||
if (_hovered)
|
||||
receiver = _hovered;
|
||||
if (_touched)
|
||||
receiver = _touched;
|
||||
}
|
||||
|
||||
/*
|
||||
* Route relative motion (exclusive input) to the focused client
|
||||
*/
|
||||
@ -330,6 +348,16 @@ void User_state::_handle_input_event(Input::Event ev)
|
||||
_global_key_sequence = false;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Detect end-of-touch sequence
|
||||
*
|
||||
* Don't reset '_touched' here to retain the information for the 'touch'
|
||||
* report until the activity timeout is reached.
|
||||
*/
|
||||
ev.handle_touch_release([&] (Input::Touch_id id) {
|
||||
if (id.value == 0)
|
||||
_touched_position = Nowhere(); });
|
||||
}
|
||||
|
||||
|
||||
@ -395,8 +423,9 @@ User_state::handle_input_events(Input_batch batch)
|
||||
bool touch_occurred = false;
|
||||
bool key_state_affected = false;
|
||||
for (unsigned i = 0; i < batch.count; i++) {
|
||||
key_state_affected |= (batch.events[i].press() || batch.events[i].release());
|
||||
touch_occurred |= batch.events[i].touch();
|
||||
Input::Event const &ev = batch.events[i];
|
||||
key_state_affected |= (ev.press() || ev.release());
|
||||
touch_occurred |= (ev.touch() || ev.touch_release());
|
||||
}
|
||||
|
||||
_apply_pending_focus_change();
|
||||
@ -435,7 +464,8 @@ User_state::handle_input_events(Input_batch batch)
|
||||
(_input_receiver != old_input_receiver),
|
||||
.key_state_affected = key_state_affected,
|
||||
.button_activity = button_activity,
|
||||
.motion_activity = pointer_changed() || touch_occurred,
|
||||
.motion_activity = pointer_changed(),
|
||||
.touch_activity = touch_occurred,
|
||||
.key_pressed = _key_pressed(),
|
||||
.last_clicked_changed = last_clicked_changed,
|
||||
.last_seq_changed = last_seq_changed
|
||||
@ -482,6 +512,24 @@ void User_state::report_focused_view_owner(Xml_generator &xml, bool active) cons
|
||||
}
|
||||
|
||||
|
||||
void User_state::report_touched_view_owner(Xml_generator &xml, bool active) const
|
||||
{
|
||||
if (_touched)
|
||||
_touched->report(xml);
|
||||
|
||||
if (active) xml.attribute("active", "yes");
|
||||
|
||||
_touched_position.with_result(
|
||||
[&] (Point p) {
|
||||
xml.attribute("xpos", p.x);
|
||||
xml.attribute("ypos", p.y); },
|
||||
[&] (Nowhere) { });
|
||||
|
||||
if (_last_seq_number.constructed())
|
||||
xml.attribute("seq_number", _last_seq_number->value);
|
||||
}
|
||||
|
||||
|
||||
void User_state::report_last_clicked_view_owner(Xml_generator &xml) const
|
||||
{
|
||||
if (_last_seq_number.constructed())
|
||||
@ -501,6 +549,7 @@ User_state::Handle_forget_result User_state::forget(View_owner const &owner)
|
||||
bool const need_to_update_all_views = (&owner == _focused);
|
||||
bool const focus_vanished = (&owner == _focused);
|
||||
bool const hover_vanished = (&owner == _hovered);
|
||||
bool const touch_vanished = (&owner == _touched);
|
||||
|
||||
auto wipe_ptr = [&] (auto &ptr) {
|
||||
if (&owner == ptr)
|
||||
@ -510,6 +559,7 @@ User_state::Handle_forget_result User_state::forget(View_owner const &owner)
|
||||
wipe_ptr(_next_focused);
|
||||
wipe_ptr(_last_clicked);
|
||||
wipe_ptr(_hovered);
|
||||
wipe_ptr(_touched);
|
||||
|
||||
Update_hover_result const update_hover_result = update_hover();
|
||||
|
||||
@ -521,6 +571,7 @@ User_state::Handle_forget_result User_state::forget(View_owner const &owner)
|
||||
return {
|
||||
.hover_changed = update_hover_result.hover_changed
|
||||
|| hover_vanished,
|
||||
.touch_changed = touch_vanished,
|
||||
.focus_changed = focus_vanished,
|
||||
};
|
||||
}
|
||||
|
@ -100,11 +100,21 @@ class Nitpicker::User_state
|
||||
*/
|
||||
Pointer _pointer = Nowhere { };
|
||||
|
||||
/*
|
||||
* Position of initial touch point
|
||||
*/
|
||||
Attempt<Point, Nowhere> _touched_position = Nowhere { };
|
||||
|
||||
/*
|
||||
* Currently pointed-at view owner
|
||||
*/
|
||||
View_owner *_hovered = nullptr;
|
||||
|
||||
/*
|
||||
* Currently touched view owner
|
||||
*/
|
||||
View_owner *_touched = nullptr;
|
||||
|
||||
/*
|
||||
* View owner that receives the current stream of input events
|
||||
*/
|
||||
@ -250,6 +260,7 @@ class Nitpicker::User_state
|
||||
bool const key_state_affected;
|
||||
bool const button_activity;
|
||||
bool const motion_activity;
|
||||
bool const touch_activity;
|
||||
bool const key_pressed;
|
||||
bool const last_clicked_changed;
|
||||
bool const last_seq_changed;
|
||||
@ -269,6 +280,7 @@ class Nitpicker::User_state
|
||||
struct Handle_forget_result
|
||||
{
|
||||
bool const hover_changed;
|
||||
bool const touch_changed;
|
||||
bool const focus_changed;
|
||||
};
|
||||
|
||||
@ -282,6 +294,7 @@ class Nitpicker::User_state
|
||||
void report_pointer_position(Xml_generator &) const;
|
||||
void report_hovered_view_owner(Xml_generator &, bool motion_active) const;
|
||||
void report_focused_view_owner(Xml_generator &, bool button_active) const;
|
||||
void report_touched_view_owner(Xml_generator &, bool touch_active) const;
|
||||
void report_last_clicked_view_owner(Xml_generator &) const;
|
||||
|
||||
/**
|
||||
|
Loading…
x
Reference in New Issue
Block a user