win: Terminal UI #6315

For CI builds unibilium is provided through msys2 packages, and
libtermkey is built from source in third-party from equalsraf/libtermkey.

In Windows we cannot read terminal input from the stdin file descriptor,
instead use libuv's uv_tty API. It should handle key input and encoding.

The UI suspend is not implemented for Windows, because the
SIGSTP/SIGCONT do not exist in windows. Currently this is a NOOP.

Closes #3902
Closes #6640
This commit is contained in:
Rui Abreu Ferreira
2017-03-18 00:06:47 +00:00
committed by Justin M. Keyes
parent 31e5053253
commit 685ca180f7
7 changed files with 60 additions and 18 deletions

View File

@@ -47,7 +47,13 @@ void term_input_init(TermInput *input, Loop *loop)
int curflags = termkey_get_canonflags(input->tk);
termkey_set_canonflags(input->tk, curflags | TERMKEY_CANON_DELBS);
// setup input handle
#ifdef WIN32
uv_tty_init(loop, &input->tty_in, 0, 1);
uv_tty_set_mode(&input->tty_in, UV_TTY_MODE_RAW);
rstream_init_stream(&input->read_stream, &input->tty_in, 0xfff);
#else
rstream_init_fd(loop, &input->read_stream, input->in_fd, 0xfff);
#endif
// initialize a timer handle for handling ESC with libtermkey
time_watcher_init(loop, &input->timer_handle, input);
}

View File

@@ -17,6 +17,9 @@ typedef struct term_input {
#endif
TimeWatcher timer_handle;
Loop *loop;
#ifdef WIN32
uv_tty_t tty_in;
#endif
Stream read_stream;
RBuffer *key_buffer;
uv_mutex_t key_buffer_mutex;

View File

@@ -251,7 +251,9 @@ static void tui_main(UIBridgeData *bridge, UI *ui)
kv_init(data->invalid_regions);
signal_watcher_init(data->loop, &data->winch_handle, ui);
signal_watcher_init(data->loop, &data->cont_handle, data);
#ifdef UNIX
signal_watcher_start(&data->cont_handle, sigcont_cb, SIGCONT);
#endif
tui_terminal_start(ui);
data->stop = false;
// allow the main thread to continue, we are ready to start handling UI
@@ -280,10 +282,12 @@ static void tui_scheduler(Event event, void *d)
loop_schedule(data->loop, event);
}
#ifdef UNIX
static void sigcont_cb(SignalWatcher *watcher, int signum, void *data)
{
((TUIData *)data)->cont_received = true;
}
#endif
static void sigwinch_cb(SignalWatcher *watcher, int signum, void *data)
{
@@ -744,6 +748,7 @@ static void tui_flush(UI *ui)
flush_buf(ui, true);
}
#ifdef UNIX
static void suspend_event(void **argv)
{
UI *ui = argv[0];
@@ -765,15 +770,18 @@ static void suspend_event(void **argv)
// resume the main thread
CONTINUE(data->bridge);
}
#endif
static void tui_suspend(UI *ui)
{
#ifdef UNIX
TUIData *data = ui->data;
// kill(0, SIGTSTP) won't stop the UI thread, so we must poll for SIGCONT
// before continuing. This is done in another callback to avoid
// loop_poll_events recursion
multiqueue_put_event(data->loop->fast_events,
event_create(suspend_event, 1, ui));
#endif
}
static void tui_set_title(UI *ui, char *title)