From f01b205c302ca1f0da622074d3466fe2d2941558 Mon Sep 17 00:00:00 2001 From: Norman Feske Date: Thu, 8 Oct 2015 00:09:10 +0200 Subject: [PATCH] nitpicker: postpone focus updates until idle This patch ensures that focus changes performed via the Session::focus call are made effective the next time, the user is idle. Previously, focus changes during drag operations were simply discarded. --- repos/os/src/server/nitpicker/main.cc | 20 +++++++++++--------- repos/os/src/server/nitpicker/mode.h | 25 +++++++++++++++++++++++-- 2 files changed, 34 insertions(+), 11 deletions(-) diff --git a/repos/os/src/server/nitpicker/main.cc b/repos/os/src/server/nitpicker/main.cc index 3846d249b..e7810af0a 100644 --- a/repos/os/src/server/nitpicker/main.cc +++ b/repos/os/src/server/nitpicker/main.cc @@ -908,23 +908,20 @@ class Nitpicker::Session_component : public Genode::Rpc_object, return; } - /* prevent focus changes during drag operations */ - if (_mode.drag()) - return; - /* lookup targeted session object */ auto lambda = [this] (Session_component *session) { - _mode.focused_session(session); - report_session(_focus_reporter, session); + _mode.next_focused_session(session); }; _ep.apply(session_cap, lambda); /* - * XXX We may skip this if all domains are configured to show the - * raw client content. + * To avoid changing the focus in the middle of a drag operation, + * we cannot perform the focus change immediately. Instead, it + * comes into effect via the 'Mode::apply_pending_focus_change()' + * function called the next time when the user input is handled and + * no drag operation is in flight. */ - _view_stack.update_all_views(); } void session_control(Label suffix, Session_control control) override @@ -1256,10 +1253,15 @@ void Nitpicker::Main::handle_input(unsigned) user_active = true; } + user_state.Mode::apply_pending_focus_change(); + Point const new_pointer_pos = user_state.pointer_pos(); ::Session * const new_pointed_session = user_state.pointed_session(); ::Session * const new_focused_session = user_state.Mode::focused_session(); + if (old_focused_session != new_focused_session) + user_state.update_all_views(); + /* flag user as inactive after activity threshold is reached */ if (period_cnt == last_active_period + activity_threshold) user_active = false; diff --git a/repos/os/src/server/nitpicker/mode.h b/repos/os/src/server/nitpicker/mode.h index dce0ec0aa..3bb6bb735 100644 --- a/repos/os/src/server/nitpicker/mode.h +++ b/repos/os/src/server/nitpicker/mode.h @@ -28,6 +28,8 @@ class Mode Session *_focused_session = nullptr; + Session *_next_focused_session = nullptr; + public: virtual ~Mode() { } @@ -47,16 +49,35 @@ class Mode Session *focused_session() { return _focused_session; } Session const *focused_session() const { return _focused_session; } - virtual void focused_session(Session *session) { _focused_session = session; } + virtual void focused_session(Session *session) + { + _focused_session = session; + _next_focused_session = session; + } bool is_focused(Session const &session) const { return &session == _focused_session; } + void next_focused_session(Session *session) { _next_focused_session = session; } + + /** + * Apply pending focus-change request that was issued during drag state + */ + void apply_pending_focus_change() + { + if (key_is_pressed()) + return; + + if (_focused_session != _next_focused_session) + _focused_session = _next_focused_session; + } + /** * Discard all references to specified view */ virtual void forget(Session const &session) { - if (is_focused(session)) _focused_session = nullptr; + if (&session == _focused_session) _focused_session = nullptr; + if (&session == _next_focused_session) _next_focused_session = nullptr; } };