From d75c5f672277c323f6f049d971abc1e27a90c228 Mon Sep 17 00:00:00 2001 From: Norman Feske Date: Thu, 14 Mar 2019 14:15:58 +0100 Subject: [PATCH] window layouter: fix glitch after window resize This patch improves the transition from an interactive window geometry change (dragging a window element) to the point where the resulting new layout rules come into effect. During this short time, no resize request must be issued because such a resize request would be based on stale rules. Fixes #3227 --- .../recipes/src/window_layouter/used_apis | 1 + repos/gems/src/app/window_layouter/main.cc | 50 +++++++++++++++++-- 2 files changed, 48 insertions(+), 3 deletions(-) diff --git a/repos/gems/recipes/src/window_layouter/used_apis b/repos/gems/recipes/src/window_layouter/used_apis index c28524c4d2..401ba72d01 100644 --- a/repos/gems/recipes/src/window_layouter/used_apis +++ b/repos/gems/recipes/src/window_layouter/used_apis @@ -4,3 +4,4 @@ input_session report_session nitpicker_session framebuffer_session +timer_session diff --git a/repos/gems/src/app/window_layouter/main.cc b/repos/gems/src/app/window_layouter/main.cc index f1781c9e57..13872c2190 100644 --- a/repos/gems/src/app/window_layouter/main.cc +++ b/repos/gems/src/app/window_layouter/main.cc @@ -23,6 +23,7 @@ #include #include #include +#include /* local includes */ #include @@ -45,6 +46,13 @@ struct Window_layouter::Main : Operations, Signal_handler
_config_handler { _env.ep(), *this, &Main::_handle_config }; + Timer::Connection _drop_timer { _env }; + + bool _defer_layout_change = false; + + Signal_handler
_drop_timer_handler { + _env.ep(), *this, &Main::_handle_drop_timer }; + Heap _heap { _env.ram(), _env.rm() }; Area _screen_size { }; @@ -126,7 +134,24 @@ struct Window_layouter::Main : Operations, /** * Layout_rules::Change_handler interface */ - void layout_rules_changed() override { _update_window_layout(); } + void layout_rules_changed() override + { + /* + * When re-importing rules generated by the drop operation, issue an + * updated resize request immediately instead of waiting for the + * '_drop_timer_handler'. Clear '_defer_layout_change' before calling + * '_update_window_layout' because '_gen_window_layout' evaluates + * this flag. + */ + bool const issue_resize_request = _defer_layout_change; + + _defer_layout_change = false; + + _update_window_layout(); + + if (issue_resize_request) + _gen_resize_request(); + } /** * Window_list::Change_handler interface @@ -216,6 +241,12 @@ struct Window_layouter::Main : Operations, _gen_resize_request(); } + void _handle_drop_timer() + { + /* discharge '_defer_layout_change' */ + layout_rules_changed(); + } + void finalize_drag(Window_id id, Window::Element, Point, Point) override { /* @@ -229,10 +260,15 @@ struct Window_layouter::Main : Operations, _window_list.with_window(id, [&] (Window &window) { window.finalize_drag_operation(); }); - _gen_resize_request(); + /* + * Mask the generation of resize requests until the updated rules are + * imported the next time. Discharge the masking after a timeout for + * the case where rules fixed and not fed back to the layouter. + */ + _defer_layout_change = true; + _drop_timer.trigger_once(250*1000); } - /** * Install handler for responding to hover changes */ @@ -340,6 +376,8 @@ struct Window_layouter::Main : Operations, _nitpicker.mode_sigh(_mode_change_handler); _handle_mode_change(); + _drop_timer.sigh(_drop_timer_handler); + _hover.sigh(_hover_handler); _decorator_margins_rom.sigh(_decorator_margins_handler); _input.sigh(_input_handler); @@ -360,6 +398,9 @@ struct Window_layouter::Main : Operations, void Window_layouter::Main::_gen_window_layout() { + if (_defer_layout_change) + return; + /* update hover and focus state of each window */ _window_list.for_each_window([&] (Window &window) { @@ -377,6 +418,9 @@ void Window_layouter::Main::_gen_window_layout() void Window_layouter::Main::_gen_resize_request() { + if (_defer_layout_change) + return; + bool resize_needed = false; _window_list.for_each_window([&] (Window const &window) { if (window.resize_request_needed())