summaryrefslogtreecommitdiff
path: root/src/input_handler.cc
diff options
context:
space:
mode:
authorMaxime Coste <mawww@kakoune.org>2024-08-08 12:56:07 +1000
committerMaxime Coste <mawww@kakoune.org>2024-08-08 13:08:01 +1000
commit6af7a847c74a05748ba139aed6386c0a6df0220b (patch)
tree822ce28e64f9898e65650f5ab51d6d7cac71fef5 /src/input_handler.cc
parent31e0c81156a4974c24a52722b98aad9a0d7b1b25 (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.cc49
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;