diff options
| author | Maxime Coste <mawww@kakoune.org> | 2024-08-08 12:56:07 +1000 |
|---|---|---|
| committer | Maxime Coste <mawww@kakoune.org> | 2024-08-08 13:08:01 +1000 |
| commit | 6af7a847c74a05748ba139aed6386c0a6df0220b (patch) | |
| tree | 822ce28e64f9898e65650f5ab51d6d7cac71fef5 /src/input_handler.cc | |
| parent | 31e0c81156a4974c24a52722b98aad9a0d7b1b25 (diff) | |
Delay NormalMode clearing of status line and info box to next idle
A common pattern is for info/echo messages to be generated by idle
hooks but the clearing of previous info/echo was done immediately on
normal mode events. This led to flickering of the info box especially
when a hook was repeatidly generating the same info (like moving
a cursor in the same word where the hook reacts to the word under
the cursor).
Diffstat (limited to 'src/input_handler.cc')
| -rw-r--r-- | src/input_handler.cc | 49 |
1 files changed, 38 insertions, 11 deletions
diff --git a/src/input_handler.cc b/src/input_handler.cc index 2703b51a..89613aee 100644 --- a/src/input_handler.cc +++ b/src/input_handler.cc @@ -23,13 +23,6 @@ namespace Kakoune { -static void clear_info_and_echo(Context& context) -{ - context.print_status({}); - if (context.has_client()) - context.client().info_hide(); -} - class InputMode : public RefCountable { public: @@ -101,8 +94,6 @@ void InputMode::paste(StringView content) context().print_status({error.what().str(), context().faces()["Error"] }); context().hooks().run_hook(Hook::RuntimeError, error.what(), context()); } - - clear_info_and_echo(context()); } namespace InputModes @@ -221,6 +212,14 @@ constexpr StringView register_doc = class Normal : public InputMode { + enum class PendingClear + { + None = 0, + Info = 0b01, + StatusLine = 0b10 + }; + friend constexpr bool with_bit_ops(Meta::Type<PendingClear>) { return true; } + public: Normal(InputHandler& input_handler, bool single_command = false) : InputMode(input_handler), @@ -228,6 +227,15 @@ public: context().flags() & Context::Flags::Draft ? Timer::Callback{} : [this](Timer&) { RefPtr<InputMode> keep_alive{this}; // hook could trigger pop_mode() + if (context().has_client()) + { + if (m_pending_clear & PendingClear::StatusLine) + context().client().print_status({}); + if (m_pending_clear & PendingClear::Info) + context().client().info_hide(); + } + m_pending_clear = PendingClear::None; + context().hooks().run_hook(Hook::NormalIdle, "", context()); }}, m_fs_check_timer{TimePoint::max(), @@ -275,6 +283,8 @@ public: void on_key(Key key, bool) override { + bool should_clear = false; + kak_assert(m_state != State::PopOnEnabled); ScopedSetBool set_in_on_key{m_in_on_key}; @@ -291,7 +301,7 @@ public: if (m_mouse_handler.handle_key(key, context())) { - clear_info_and_echo(context()); + should_clear = true; if (not transient) m_idle_timer.set_next_date(Clock::now() + get_idle_timeout(context())); @@ -338,7 +348,7 @@ public: m_state = State::PopOnEnabled; }); - clear_info_and_echo(context()); + should_clear = true; // Hack to parse keys sent by terminals using the 8th bit to mark the // meta key. In normal mode, give priority to a potential alt-key than @@ -369,7 +379,12 @@ public: context().hooks().run_hook(Hook::NormalKey, to_string(key), context()); if (enabled() and not transient) // The hook might have changed mode + { + if (should_clear and context().has_client()) + m_pending_clear = (context().client().info_pending() ? PendingClear::None : PendingClear::Info) + | (context().client().status_line_pending() ? PendingClear::None : PendingClear::StatusLine); m_idle_timer.set_next_date(Clock::now() + get_idle_timeout(context())); + } } ModeInfo mode_info() const override @@ -395,6 +410,17 @@ public: return {atoms, m_params}; } + void paste(StringView content) override + { + InputMode::paste(content); + if (not (context().flags() & Context::Flags::Draft)) + { + if (context().has_client()) + m_pending_clear = PendingClear::Info | PendingClear::StatusLine; + m_idle_timer.set_next_date(Clock::now() + get_idle_timeout(context())); + } + } + KeymapMode keymap_mode() const override { return KeymapMode::Normal; } StringView name() const override { return "normal"; } @@ -408,6 +434,7 @@ private: Timer m_idle_timer; Timer m_fs_check_timer; MouseHandler m_mouse_handler; + PendingClear m_pending_clear = PendingClear::None; enum class State { Normal, SingleCommand, PopOnEnabled }; State m_state; |
