mirror of
https://github.com/neovim/neovim.git
synced 2025-09-12 22:38:16 +00:00
Reimplement input functions on top of libuv
The functions `mch_inchar`, `mch_breakcheck`, `mch_char_avail` were reimplemented on top of libuv. Here's how it works: - When Neovim needs to wait for characters, it will transfer control to libuv event loop. - When the libuv event loop gets user input, it will transfer control back to Neovim - Neovim uses the `input_read` function to get the actual data read by libuv. With this scheme its possible to keep Neovim single-threaded while enjoying the benefits provided by libuv. This commit leaves SIGWINCH broken for now
This commit is contained in:
129
src/os_unix.c
129
src/os_unix.c
@@ -31,7 +31,6 @@
|
||||
|
||||
#include "vim.h"
|
||||
#include "os_unix.h"
|
||||
#include "os/time.h"
|
||||
#include "buffer.h"
|
||||
#include "charset.h"
|
||||
#include "eval.h"
|
||||
@@ -51,6 +50,8 @@
|
||||
#include "ui.h"
|
||||
#include "os/os.h"
|
||||
#include "os/time.h"
|
||||
#include "os/event.h"
|
||||
#include "os/input.h"
|
||||
|
||||
#include "os_unixx.h" /* unix includes for os_unix.c only */
|
||||
|
||||
@@ -108,7 +109,6 @@ typedef int waitstatus;
|
||||
#endif
|
||||
static pid_t wait4pid(pid_t, waitstatus *);
|
||||
|
||||
static int WaitForChar(long);
|
||||
static int RealWaitForChar(int, long, int *);
|
||||
|
||||
|
||||
@@ -248,98 +248,12 @@ void mch_write(char_u *s, int len)
|
||||
RealWaitForChar(read_cmd_fd, p_wd, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* mch_inchar(): low level input function.
|
||||
* Get a characters from the keyboard.
|
||||
* Return the number of characters that are available.
|
||||
* If wtime == 0 do not wait for characters.
|
||||
* If wtime == n wait a short time for characters.
|
||||
* If wtime == -1 wait forever for characters.
|
||||
*/
|
||||
int mch_inchar(
|
||||
char_u *buf,
|
||||
int maxlen,
|
||||
long wtime, /* don't use "time", MIPS cannot handle it */
|
||||
int tb_change_cnt
|
||||
)
|
||||
{
|
||||
int len;
|
||||
|
||||
|
||||
/* Check if window changed size while we were busy, perhaps the ":set
|
||||
* columns=99" command was used. */
|
||||
while (do_resize)
|
||||
handle_resize();
|
||||
|
||||
if (wtime >= 0) {
|
||||
while (WaitForChar(wtime) == 0) { /* no character available */
|
||||
if (!do_resize) /* return if not interrupted by resize */
|
||||
return 0;
|
||||
handle_resize();
|
||||
}
|
||||
} else { /* wtime == -1 */
|
||||
/*
|
||||
* If there is no character available within 'updatetime' seconds
|
||||
* flush all the swap files to disk.
|
||||
* Also done when interrupted by SIGWINCH.
|
||||
*/
|
||||
if (WaitForChar(p_ut) == 0) {
|
||||
if (trigger_cursorhold() && maxlen >= 3
|
||||
&& !typebuf_changed(tb_change_cnt)) {
|
||||
buf[0] = K_SPECIAL;
|
||||
buf[1] = KS_EXTRA;
|
||||
buf[2] = (int)KE_CURSORHOLD;
|
||||
return 3;
|
||||
}
|
||||
before_blocking();
|
||||
}
|
||||
}
|
||||
|
||||
for (;; ) { /* repeat until we got a character */
|
||||
while (do_resize) /* window changed size */
|
||||
handle_resize();
|
||||
|
||||
/*
|
||||
* We want to be interrupted by the winch signal
|
||||
* or by an event on the monitored file descriptors.
|
||||
*/
|
||||
if (WaitForChar(-1L) == 0) {
|
||||
if (do_resize) /* interrupted by SIGWINCH signal */
|
||||
handle_resize();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* If input was put directly in typeahead buffer bail out here. */
|
||||
if (typebuf_changed(tb_change_cnt))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* For some terminals we only get one character at a time.
|
||||
* We want the get all available characters, so we could keep on
|
||||
* trying until none is available
|
||||
* For some other terminals this is quite slow, that's why we don't do
|
||||
* it.
|
||||
*/
|
||||
len = read_from_input_buf(buf, (long)maxlen);
|
||||
if (len > 0) {
|
||||
return len;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void handle_resize()
|
||||
{
|
||||
do_resize = FALSE;
|
||||
shell_resized();
|
||||
}
|
||||
|
||||
/*
|
||||
* return non-zero if a character is available
|
||||
*/
|
||||
int mch_char_avail()
|
||||
{
|
||||
return WaitForChar(0L);
|
||||
}
|
||||
|
||||
#if defined(HAVE_SIGALTSTACK) || defined(HAVE_SIGSTACK)
|
||||
/*
|
||||
@@ -682,6 +596,8 @@ void mch_init()
|
||||
#ifdef MACOS_CONVERT
|
||||
mac_conv_init();
|
||||
#endif
|
||||
|
||||
event_init();
|
||||
}
|
||||
|
||||
static void set_signals()
|
||||
@@ -2460,43 +2376,6 @@ error:
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check for CTRL-C typed by reading all available characters.
|
||||
* In cooked mode we should get SIGINT, no need to check.
|
||||
*/
|
||||
void mch_breakcheck()
|
||||
{
|
||||
if (curr_tmode == TMODE_RAW && RealWaitForChar(read_cmd_fd, 0L, NULL))
|
||||
fill_input_buf(FALSE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait "msec" msec until a character is available from the keyboard or from
|
||||
* inbuf[]. msec == -1 will block forever.
|
||||
* When a GUI is being used, this will never get called -- webb
|
||||
*/
|
||||
static int WaitForChar(msec)
|
||||
long msec;
|
||||
{
|
||||
int avail;
|
||||
|
||||
if (input_available()) /* something in inbuf[] */
|
||||
return 1;
|
||||
|
||||
/* May need to query the mouse position. */
|
||||
if (WantQueryMouse) {
|
||||
WantQueryMouse = FALSE;
|
||||
mch_write((char_u *)IF_EB("\033[1'|", ESC_STR "[1'|"), 5);
|
||||
}
|
||||
|
||||
/*
|
||||
* For FEAT_MOUSE_GPM and FEAT_XCLIPBOARD we loop here to process mouse
|
||||
* events. This is a bit complicated, because they might both be defined.
|
||||
*/
|
||||
avail = RealWaitForChar(read_cmd_fd, msec, NULL);
|
||||
return avail;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait "msec" msec until a character is available from file descriptor "fd".
|
||||
* "msec" == 0 will check for characters once.
|
||||
|
Reference in New Issue
Block a user