1
1
mirror of https://github.com/mawww/kakoune.git synced 2024-09-11 13:00:41 +03:00

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).
This commit is contained in:
Maxime Coste 2024-08-08 12:56:07 +10:00
parent 31e0c81156
commit 6af7a847c7
7 changed files with 46 additions and 15 deletions

View File

@ -48,6 +48,8 @@ public:
void info_show(DisplayLine title, DisplayLineList content, BufferCoord anchor, InfoStyle style);
void info_show(StringView title, StringView content, BufferCoord anchor, InfoStyle style);
void info_hide(bool even_modal = false);
bool info_pending() const { return m_ui_pending & PendingUI::InfoShow; };
bool status_line_pending() const { return m_ui_pending & PendingUI::StatusLine; };
void print_status(DisplayLine status_line);
const DisplayLine& current_status() const { return m_status_line; }

View File

@ -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;

View File

@ -2,6 +2,6 @@ ui_out '{ "jsonrpc": "2.0", "method": "set_ui_options", "params": [{}] }'
ui_out '{ "jsonrpc": "2.0", "method": "draw", "params": [[[{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": ".." }, { "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "\u000a" }], [{ "face": { "fg": "white", "bg": "blue", "underline": "default", "attributes": [] }, "contents": "1" }, { "face": { "fg": "white", "bg": "blue", "underline": "default", "attributes": [] }, "contents": ".." }, { "face": { "fg": "black", "bg": "white", "underline": "default", "attributes": [] }, "contents": "0" }, { "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "\u000a" }]], { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, { "fg": "blue", "bg": "default", "underline": "default", "attributes": [] }] }'
ui_out '{ "jsonrpc": "2.0", "method": "menu_hide", "params": [] }'
ui_out '{ "jsonrpc": "2.0", "method": "info_hide", "params": [] }'
ui_out '{ "jsonrpc": "2.0", "method": "draw_status", "params": [[], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "out 5:5 " }, { "face": { "fg": "black", "bg": "yellow", "underline": "default", "attributes": [] }, "contents": "[+]" }, { "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": " " }, { "face": { "fg": "blue", "bg": "default", "underline": "default", "attributes": [] }, "contents": "1 sel" }, { "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": " - client0@[kak-tests]" }], { "fg": "cyan", "bg": "default", "underline": "default", "attributes": [] }] }'
ui_out '{ "jsonrpc": "2.0", "method": "draw_status", "params": [[{ "face": { "fg": "black", "bg": "yellow", "underline": "default", "attributes": [] }, "contents": "committed change #1" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "out 5:5 " }, { "face": { "fg": "black", "bg": "yellow", "underline": "default", "attributes": [] }, "contents": "[+]" }, { "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": " " }, { "face": { "fg": "blue", "bg": "default", "underline": "default", "attributes": [] }, "contents": "1 sel" }, { "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": " - client0@[kak-tests]" }], { "fg": "cyan", "bg": "default", "underline": "default", "attributes": [] }] }'
ui_out '{ "jsonrpc": "2.0", "method": "set_cursor", "params": ["buffer", { "line": 2, "column": 3 }] }'
ui_out '{ "jsonrpc": "2.0", "method": "refresh", "params": [true] }'

View File

@ -2,6 +2,6 @@ ui_out '{ "jsonrpc": "2.0", "method": "set_ui_options", "params": [{}] }'
ui_out '{ "jsonrpc": "2.0", "method": "draw", "params": [[[{ "face": { "fg": "black", "bg": "blue", "underline": "default", "attributes": [] }, "contents": "1" }, { "face": { "fg": "black", "bg": "blue", "underline": "default", "attributes": [] }, "contents": "replaced" }, { "face": { "fg": "black", "bg": "blue", "underline": "default", "attributes": [] }, "contents": " text" }, { "face": { "fg": "black", "bg": "white", "underline": "default", "attributes": [] }, "contents": "5" }, { "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "1" }, { "face": { "fg": "black", "bg": "white", "underline": "default", "attributes": [] }, "contents": "replaced" }, { "face": { "fg": "black", "bg": "white", "underline": "default", "attributes": [] }, "contents": " text" }, { "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "5\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "1" }, { "face": { "fg": "black", "bg": "white", "underline": "default", "attributes": [] }, "contents": "2" }, { "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "345\u000a" }]], { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, { "fg": "blue", "bg": "default", "underline": "default", "attributes": [] }] }'
ui_out '{ "jsonrpc": "2.0", "method": "menu_hide", "params": [] }'
ui_out '{ "jsonrpc": "2.0", "method": "info_hide", "params": [] }'
ui_out '{ "jsonrpc": "2.0", "method": "draw_status", "params": [[], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "out 3:2 " }, { "face": { "fg": "black", "bg": "yellow", "underline": "default", "attributes": [] }, "contents": "[+]" }, { "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": " " }, { "face": { "fg": "blue", "bg": "default", "underline": "default", "attributes": [] }, "contents": "3 sels (3)" }, { "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": " - client0@[kak-tests]" }], { "fg": "cyan", "bg": "default", "underline": "default", "attributes": [] }] }'
ui_out '{ "jsonrpc": "2.0", "method": "draw_status", "params": [[{ "face": { "fg": "black", "bg": "yellow", "underline": "default", "attributes": [] }, "contents": "committed change #1" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "out 3:2 " }, { "face": { "fg": "black", "bg": "yellow", "underline": "default", "attributes": [] }, "contents": "[+]" }, { "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": " " }, { "face": { "fg": "blue", "bg": "default", "underline": "default", "attributes": [] }, "contents": "3 sels (3)" }, { "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": " - client0@[kak-tests]" }], { "fg": "cyan", "bg": "default", "underline": "default", "attributes": [] }] }'
ui_out '{ "jsonrpc": "2.0", "method": "set_cursor", "params": ["buffer", { "line": 2, "column": 1 }] }'
ui_out '{ "jsonrpc": "2.0", "method": "refresh", "params": [true] }'

View File

@ -1,6 +1,6 @@
ui_out -ignore 7
ui_in '{ "jsonrpc": "2.0", "method": "keys", "params": [ "i" ] }'
ui_out -ignore 4
ui_out -ignore 3
ui_in '{ "jsonrpc": "2.0", "method": "keys", "params": [ "a" ] }'
ui_out -ignore 4
ui_in '{ "jsonrpc": "2.0", "method": "mouse_press", "params": [ "left", 0, 2 ] }'

View File

@ -1,6 +1,6 @@
ui_out -ignore 7
ui_in '{ "jsonrpc": "2.0", "method": "keys", "params": [ ":my-command " ] }'
ui_out -ignore 7
ui_out -ignore 6
ui_out '{ "jsonrpc": "2.0", "method": "refresh", "params": [false] }'
ui_out '{ "jsonrpc": "2.0", "method": "menu_show", "params": [[[{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "aaa" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "bbb" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "ccc" }]], { "line": 0, "column": 0 }, { "fg": "white", "bg": "blue", "underline": "default", "attributes": [] }, { "fg": "blue", "bg": "white", "underline": "default", "attributes": [] }, "prompt"] }'
ui_in '{ "jsonrpc": "2.0", "method": "keys", "params": [ "<s-tab><ret>" ] }'

View File

@ -7,6 +7,8 @@ ui_out '{ "jsonrpc": "2.0", "method": "set_cursor", "params": ["buffer", { "line
ui_out '{ "jsonrpc": "2.0", "method": "refresh", "params": [true] }'
ui_in '{ "jsonrpc": "2.0", "method": "scroll", "params": [ 2 ] }'
ui_out '{ "jsonrpc": "2.0", "method": "draw", "params": [[[{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "03\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "04\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "05\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "06\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "07\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "08\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "09\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "10\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "11\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "12\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "13\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "14\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "15\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "16\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "17\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "18\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "19\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "20\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "21\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "22\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "23\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "24\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "25\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "26\u000a" }]], { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, { "fg": "blue", "bg": "default", "underline": "default", "attributes": [] }] }'
ui_out '{ "jsonrpc": "2.0", "method": "set_cursor", "params": ["buffer", { "line": 0, "column": 0 }] }'
ui_out '{ "jsonrpc": "2.0", "method": "refresh", "params": [false] }'
ui_out '{ "jsonrpc": "2.0", "method": "info_hide", "params": [] }'
ui_out '{ "jsonrpc": "2.0", "method": "draw_status", "params": [[], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "out 1:1 " }, { "face": { "fg": "black", "bg": "yellow", "underline": "default", "attributes": [] }, "contents": "" }, { "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": " " }, { "face": { "fg": "blue", "bg": "default", "underline": "default", "attributes": [] }, "contents": "1 sel" }, { "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": " - client0@[kak-tests]" }], { "fg": "cyan", "bg": "default", "underline": "default", "attributes": [] }] }'
ui_out '{ "jsonrpc": "2.0", "method": "set_cursor", "params": ["buffer", { "line": 0, "column": 0 }] }'