Do not block when waiting for next event if we have pending input

Handle next event should never block if we have already accumulated
input that we want to process. As we can accumulate new input in
lots of places (everytime we run a shell process for example, we
might end up reading input keys. That can be triggered during the
mode line generation which takes place during display of the window)

Fixes #1804
This commit is contained in:
Maxime Coste 2018-01-21 12:00:40 +11:00
parent 43f50c0852
commit 299e22ca7c
6 changed files with 13 additions and 5 deletions

View File

@ -38,6 +38,7 @@ public:
Client(Client&&) = delete; Client(Client&&) = delete;
bool process_pending_inputs(); bool process_pending_inputs();
bool has_pending_inputs() const { return not m_pending_keys.empty(); }
void menu_show(Vector<DisplayLine> choices, BufferCoord anchor, MenuStyle style); void menu_show(Vector<DisplayLine> choices, BufferCoord anchor, MenuStyle style);
void menu_select(int selected); void menu_select(int selected);

View File

@ -90,6 +90,11 @@ void ClientManager::process_pending_inputs() const
} }
} }
bool ClientManager::has_pending_inputs() const
{
return contains_that(m_clients, [](auto&& c) { return c->has_pending_inputs(); });
}
void ClientManager::remove_client(Client& client, bool graceful, int status) void ClientManager::remove_client(Client& client, bool graceful, int status)
{ {
auto it = find(m_clients, &client); auto it = find(m_clients, &client);

View File

@ -36,6 +36,7 @@ public:
void redraw_clients() const; void redraw_clients() const;
void process_pending_inputs() const; void process_pending_inputs() const;
bool has_pending_inputs() const;
Client* get_client_ifp(StringView name); Client* get_client_ifp(StringView name);
Client& get_client(StringView name); Client& get_client(StringView name);

View File

@ -69,7 +69,7 @@ EventManager::~EventManager()
kak_assert(m_timers.empty()); kak_assert(m_timers.empty());
} }
void EventManager::handle_next_events(EventMode mode, sigset_t* sigmask) void EventManager::handle_next_events(EventMode mode, sigset_t* sigmask, bool block)
{ {
int max_fd = 0; int max_fd = 0;
fd_set rfds, wfds, efds; fd_set rfds, wfds, efds;
@ -92,7 +92,7 @@ void EventManager::handle_next_events(EventMode mode, sigset_t* sigmask)
bool with_timeout = false; bool with_timeout = false;
timespec ts{}; timespec ts{};
if (not m_timers.empty()) if (block and not m_timers.empty())
{ {
auto next_date = (*std::min_element( auto next_date = (*std::min_element(
m_timers.begin(), m_timers.end(), [](Timer* lhs, Timer* rhs) { m_timers.begin(), m_timers.end(), [](Timer* lhs, Timer* rhs) {
@ -109,7 +109,7 @@ void EventManager::handle_next_events(EventMode mode, sigset_t* sigmask)
} }
} }
int res = pselect(max_fd + 1, &rfds, &wfds, &efds, int res = pselect(max_fd + 1, &rfds, &wfds, &efds,
with_timeout ? &ts : nullptr, sigmask); not block or with_timeout ? &ts : nullptr, sigmask);
// copy forced fds *after* select, so that signal handlers can write to // copy forced fds *after* select, so that signal handlers can write to
// m_forced_fd, interupt select, and directly be serviced. // m_forced_fd, interupt select, and directly be serviced.

View File

@ -86,7 +86,7 @@ public:
EventManager(); EventManager();
~EventManager(); ~EventManager();
void handle_next_events(EventMode mode, sigset_t* sigmask = nullptr); void handle_next_events(EventMode mode, sigset_t* sigmask = nullptr, bool block = true);
// force the watchers associated with fd to be executed // force the watchers associated with fd to be executed
// on next handle_next_events call. // on next handle_next_events call.

View File

@ -683,7 +683,8 @@ int run_server(StringView session, StringView server_init,
(flags & ServerFlags::Daemon))) (flags & ServerFlags::Daemon)))
{ {
client_manager.redraw_clients(); client_manager.redraw_clients();
event_manager.handle_next_events(EventMode::Normal); event_manager.handle_next_events(EventMode::Normal, nullptr,
not client_manager.has_pending_inputs());
client_manager.process_pending_inputs(); client_manager.process_pending_inputs();
client_manager.clear_client_trash(); client_manager.clear_client_trash();
client_manager.clear_window_trash(); client_manager.clear_window_trash();