From c0b2a641020efc2ac2794508af86cdf8690d650b Mon Sep 17 00:00:00 2001 From: nick black Date: Sat, 2 May 2020 12:56:39 -0400 Subject: [PATCH] implement+doc notcurses_inputready_fd() #513 --- doc/man/man3/notcurses_input.3.md | 36 ++++++++++++++++++++----------- include/notcurses/notcurses.h | 6 ++++++ src/lib/notcurses.c | 4 ++++ 3 files changed, 34 insertions(+), 12 deletions(-) diff --git a/doc/man/man3/notcurses_input.3.md b/doc/man/man3/notcurses_input.3.md index c820dc7c9..bfcf071e9 100644 --- a/doc/man/man3/notcurses_input.3.md +++ b/doc/man/man3/notcurses_input.3.md @@ -37,11 +37,13 @@ typedef struct ncinput { **int notcurses_mouse_disable(struct notcurses* n);** +**int notcurses_inputready_fd(struct notcurses* n);** + # DESCRIPTION notcurses supports input from keyboards and mice, and any device that looks like them. Mouse support requires a broker such as GPM, Wayland, or Xorg, and -must be explicitly enabled via **notcurses_mouse_enable(3)**. The full 32-bit +must be explicitly enabled via **notcurses_mouse_enable**. The full 32-bit range of Unicode is supported (see **unicode(7)**), with synthesized events mapped into the [Supplementary Private Use Area-B](https://unicode.org/charts/PDF/U1.0.10.pdf). Unicode characters are returned directly as UCS-32, one codepoint at a time. @@ -52,19 +54,24 @@ mode (see **cfmakeraw(3)**), and thus keys are received without line-buffering. notcurses maintains its own buffer of input characters, which it will attempt to fill whenever it reads. -**notcurses_getc(3)** allows a **struct timespec** to be specified as a timeout. -If **ts** is **NULL**, **notcurses_getc(3)** will block until it reads input, or +**notcurses_getc** allows a **struct timespec** to be specified as a timeout. +If **ts** is **NULL**, **notcurses_getc** will block until it reads input, or is interrupted by a signal. If its values are zeroes, there will be no blocking. Otherwise, **ts** specifies a minimum time to wait for input before giving up. On timeout, 0 is returned. Signals in **sigmask** will be masked and blocked in the same manner as a call to **ppoll(2)**. **sigmask** may be **NULL**. Event details will be reported in **ni**, unless **ni** is NULL. +**notcurses_inputready_fd** provides a file descriptor suitable for use with +I/O multiplexors such as **poll(2)**. This file descriptor might or might not +be the actual input file descriptor. If it readable, **notcurses_getc** can +be called without the possibility of blocking. + ## Mice For mouse events, the additional fields **y** and **x** are set. These fields are not meaningful for keypress events. Mouse events can be distinguished using -the **nckey_mouse_p(3)** predicate. Once enabled, mouse button presses are +the **nckey_mouse_p** predicate. Once enabled, mouse button presses are detected, as are mouse motions made while a button is held down. If no button is depressed, mouse movement _does not result in events_. This is known as "button-event tracking" mode in the nomenclature of [Xterm Control @@ -88,11 +95,11 @@ found in ****. For more details, consult **terminfo(5)**. ## **NCKEY_RESIZE** -Unless the **SIGWINCH** handler has been inhibited (see **notcurses_init(3)**), +Unless the **SIGWINCH** handler has been inhibited (see **notcurses_init**), notcurses will automatically catch screen resizes, and synthesize an **NCKEY_RESIZE** event. Upon receiving this event, the user may call -**notcurses_refresh(3)** to force an immediate reflow, or just wait until the -next call to **notcurses_render(3)**, when notcurses will pick up the resize +**notcurses_refresh** to force an immediate reflow, or just wait until the +next call to **notcurses_render**, when notcurses will pick up the resize itself. If the **SIGWINCH** handler is inhibited, **NCKEY_RESIZE** is never generated. @@ -100,23 +107,28 @@ generated. On error, the **_getc** family of functions returns **(char32_t)-1**. The cause of the error may be determined using **errno(3)**. Unless the error was a temporary one (especially e.g. **EINTR**), -**notcurses_getc(3)** probably cannot be usefully called forthwith. On a +**notcurses_getc** probably cannot be usefully called forthwith. On a timeout, 0 is returned. Otherwise, the UCS-32 value of a Unicode codepoint, or a synthesized event, is returned. -**notcurses_mouse_enable(3)** returns 0 on success, and non-zero on failure, as -does **notcurses_mouse_disable(3)**. +**notcurses_mouse_enable** returns 0 on success, and non-zero on failure, as +does **notcurses_mouse_disable**. # NOTES -Like any other notcurses function, it is an error to call **notcurses_getc(3)** -during or after a call to **notcurses_stop(3)**. If a thread is always sitting +Like any other notcurses function, it is an error to call **notcurses_getc** +during or after a call to **notcurses_stop**. If a thread is always sitting on blocking input, it can be tricky to guarantee that this doesn't happen. Only one thread may call into the input stack at once, but unlike almost every other function in notcurses, **notcurses_getc** and friends can be called concurrently with **notcurses_render**. +Do not simply **poll** the input file descriptor. Instead, use the file +descriptor returned by **notcurses_inputready_fd** to ensure compatibility with +future versions of Notcurses (it is possible that future versions will process +input in their own contexts). + # BUGS Failed escape sequences are not yet played back in their entirety; only an diff --git a/include/notcurses/notcurses.h b/include/notcurses/notcurses.h index 9ab7e049c..6a1ab6fc0 100644 --- a/include/notcurses/notcurses.h +++ b/include/notcurses/notcurses.h @@ -857,6 +857,12 @@ typedef struct ncinput { API char32_t notcurses_getc(struct notcurses* n, const struct timespec* ts, sigset_t* sigmask, ncinput* ni); +// Get a file descriptor suitable for input event poll()ing. When this +// descriptor becomes available, you can call notcureses_getc_nblock(), +// and input ought be ready. This file descriptor is *not* necessarily +// the file descriptor associated with stdin (but it might be!). +API int notcurses_inputready_fd(struct notcurses* n); + // 'ni' may be NULL if the caller is uninterested in event details. If no event // is ready, returns 0. static inline char32_t diff --git a/src/lib/notcurses.c b/src/lib/notcurses.c index 93e44b4eb..1ffed3cca 100644 --- a/src/lib/notcurses.c +++ b/src/lib/notcurses.c @@ -1946,3 +1946,7 @@ int notcurses_lex_margins(const char* op, notcurses_options* opts){ } return 0; } + +int notcurses_inputready_fd(notcurses* n){ + return fileno(n->ttyinfp); +}