Ensure all available input is handled before going back to main loop

We were not handling keys that could have been generated while handling
other keys (like during a shell evaluation).
This commit is contained in:
Maxime Coste 2016-11-30 09:47:38 +00:00
parent 3a81260917
commit 540e504e68
3 changed files with 22 additions and 15 deletions

View File

@ -55,15 +55,14 @@ Client::~Client()
m_window->set_client(nullptr);
}
void Client::process_pending_inputs()
bool Client::process_pending_inputs()
{
try
const bool debug_keys = (bool)(context().options()["debug"].get<DebugFlags>() & DebugFlags::Keys);
// steal keys as we might receive new keys while handling them.
Vector<Key, MemoryDomain::Client> keys = std::move(m_pending_keys);
for (auto& key : keys)
{
const bool debug_keys = (bool)(context().options()["debug"].get<DebugFlags>() & DebugFlags::Keys);
// steal keys as we might receive new keys while handling them.
Vector<Key, MemoryDomain::Client> keys = std::move(m_pending_keys);
for (auto& key : keys)
try
{
if (debug_keys)
write_to_debug_buffer(format("Client '{}' got key '{}'",
@ -81,12 +80,13 @@ void Client::process_pending_inputs()
else
m_input_handler.handle_key(key);
}
catch (Kakoune::runtime_error& error)
{
context().print_status({ error.what().str(), get_face("Error") });
context().hooks().run_hook("RuntimeError", error.what(), context());
}
}
catch (Kakoune::runtime_error& error)
{
context().print_status({ error.what().str(), get_face("Error") });
context().hooks().run_hook("RuntimeError", error.what(), context());
}
return not keys.empty();
}
void Client::print_status(DisplayLine status_line, bool immediate)

View File

@ -34,7 +34,7 @@ public:
Client(Client&&) = delete;
void process_pending_inputs();
bool process_pending_inputs();
void menu_show(Vector<DisplayLine> choices, BufferCoord anchor, MenuStyle style);
void menu_select(int selected);

View File

@ -63,8 +63,15 @@ Client* ClientManager::create_client(std::unique_ptr<UserInterface>&& ui,
void ClientManager::process_pending_inputs() const
{
for (auto& client : m_clients)
client->process_pending_inputs();
while (true)
{
bool had_input = false;
for (auto& client : m_clients)
had_input = client->process_pending_inputs() or had_input;
if (not had_input)
break;
}
}
void ClientManager::remove_client(Client& client, bool graceful)