rpc: allow handling of nvim_ui_try_resize at the pager

This makes external UI behave consistenly with TUI w.r.t resizes.
Which will be needed anyway as TUI will use the external UI protocol
soon.
This commit is contained in:
Björn Linse 2019-09-07 13:00:51 +02:00
parent bf9ff5148a
commit 19993bca4a
2 changed files with 48 additions and 2 deletions

View File

@ -78,6 +78,13 @@ struct multiqueue {
size_t size;
};
typedef struct {
Event event;
bool fired;
int refcount;
} SplitEvent;
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "event/multiqueue.c.generated.h"
#endif
@ -245,3 +252,33 @@ static MultiQueueItem *multiqueue_node_data(QUEUE *q)
{
return QUEUE_DATA(q, MultiQueueItem, node);
}
/// Allow an event to be processed by multiple child queues to the main queue
///
/// The handler will be fired once by the _first_ queue that processes the
/// event. Later processing will do nothing (just memory cleanup).
///
/// @param ev the event
/// @param num number of queues that the split event will be put on
/// @return an Event that is safe to put onto `num` queues
Event event_split(Event ev, int num)
{
SplitEvent *data = xmalloc(sizeof(*data));
data->event = ev;
data->fired = false;
data->refcount = num;
return event_create(split_event, 1, data);
}
static void split_event(void ** argv)
{
SplitEvent *data = argv[0];
if (!data->fired) {
data->fired = true;
if (data->event.handler) {
data->event.handler(data->event.argv);
}
}
if ((--data->refcount) == 0) {
xfree(data);
}
}

View File

@ -31,6 +31,7 @@
#include "nvim/misc1.h"
#include "nvim/lib/kvec.h"
#include "nvim/os/input.h"
#include "nvim/ui.h"
#if MIN_LOG_LEVEL > DEBUG_LOG_LEVEL
#define log_client_msg(...)
@ -355,11 +356,19 @@ static void handle_request(Channel *channel, msgpack_object *request)
request_event((void **)&evdata);
}
} else {
multiqueue_put(channel->events, request_event, 1, evdata);
DLOG("RPC: scheduled %.*s", method->via.bin.size, method->via.bin.ptr);
bool is_resize = handler.fn == handle_nvim_ui_try_resize;
if (is_resize) {
Event ev = event_split(event_create(request_event, 1, evdata), 2);
multiqueue_put_event(channel->events, ev);
multiqueue_put_event(resize_events, ev);
} else {
multiqueue_put(channel->events, request_event, 1, evdata);
DLOG("RPC: scheduled %.*s", method->via.bin.size, method->via.bin.ptr);
}
}
}
/// Handles a message, depending on the type:
/// - Request: invokes method and writes the response (or error).
/// - Notification: invokes method (emits `nvim_error_event` on error).