diff --git a/repos/os/src/server/nitpicker/README b/repos/os/src/server/nitpicker/README index 9d40acf086..934f6676b1 100644 --- a/repos/os/src/server/nitpicker/README +++ b/repos/os/src/server/nitpicker/README @@ -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 diff --git a/repos/os/src/server/nitpicker/main.cc b/repos/os/src/server/nitpicker/main.cc index 86c1a2a063..0d2e700fe0 100644 --- a/repos/os/src/server/nitpicker/main.cc +++ b/repos/os/src/server/nitpicker/main.cc @@ -100,6 +100,7 @@ class Nitpicker::Gui_root : public Root_component 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 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 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 _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); diff --git a/repos/os/src/server/nitpicker/user_state.cc b/repos/os/src/server/nitpicker/user_state.cc index 61c68a1555..8a0a64343b 100644 --- a/repos/os/src/server/nitpicker/user_state.cc +++ b/repos/os/src/server/nitpicker/user_state.cc @@ -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, }; } diff --git a/repos/os/src/server/nitpicker/user_state.h b/repos/os/src/server/nitpicker/user_state.h index 2296aba7fc..3dfcaff6b3 100644 --- a/repos/os/src/server/nitpicker/user_state.h +++ b/repos/os/src/server/nitpicker/user_state.h @@ -100,11 +100,21 @@ class Nitpicker::User_state */ Pointer _pointer = Nowhere { }; + /* + * Position of initial touch point + */ + Attempt _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; /**