C-Menu 0.2.9
A User Interface Toolkit
Loading...
Searching...
No Matches
ui_notcurses_input.c File Reference

NotCurses UI backend — input handling. More...

#include "ui_backend.h"
#include "ui_notcurses_internal.h"
#include <errno.h>
#include <notcurses/notcurses.h>
#include <poll.h>
#include <string.h>
#include <termios.h>
Include dependency graph for ui_notcurses_input.c:

Go to the source code of this file.

Functions

void ui_flush_input ()
 Flush any pending input events from the NotCurses context. This function discards any input events that have been queued but not yet processed.
int ui_get_event (UiSurface *s, ss_t w, UiChyron *chyron, UiEvent *ev, int timeout_ms)
 Wait for an input event from the NotCurses context.
int ui_get_event_no_mouse (UiSurface *target, ss_t w, UiEvent *ev)
 Wait for an input event from the NotCurses context, ignoring mouse events.
uint ui_get_plane_idx (UiSurface *s, struct ncplane *plane)
 Get the index of a given ncplane in the UiSurface's plane array.
int ui_getch ()
 Wait for a single input character from the NotCurses context.
int ui_mice_enable (int mask)
 Enable or disable mouse events for the NotCurses context.
int ui_mousemask (int mask)
 Set the mouse event mask for the NotCurses context.
NcPlane * ui_ncplane_clicked (UiSurface *s, ss_t w, ncinput *ni)
 Determine which ncplane was clicked based on the mouse event coordinates.

Detailed Description

NotCurses UI backend — input handling.

Translates NotCurses ncinput events into the portable UiEvent representation defined in ui_backend.h.

Definition in file ui_notcurses_input.c.

Function Documentation

◆ ui_flush_input()

void ui_flush_input ( )

Flush any pending input events from the NotCurses context. This function discards any input events that have been queued but not yet processed.

Definition at line 105 of file ui_notcurses_input.c.

105 {
106 int fd = notcurses_inputready_fd(ui->nc);
107 tcflush(fd, TCIOFLUSH);
108}
UiRuntime * ui
Definition ui_ncurses.c:39

References ui.

◆ ui_get_event()

int ui_get_event ( UiSurface * s,
ss_t w,
UiChyron * chyron,
UiEvent * ev,
int timeout_ms )

Wait for an input event from the NotCurses context.

Parameters
uiUI runtime context.
targetUnused for NotCurses (events are global to the context).
evOutput UiEvent structure.
timeout_msMilliseconds to wait; -1 = block indefinitely.
Returns
0 on success, -1 if ui or ev is NULL.

Definition at line 117 of file ui_notcurses_input.c.

117 {
118 if (!ui || !ev)
119 return -1;
120 memset(ev, 0, sizeof(*ev));
121 ncinput ni;
122 memset(&ni, 0, sizeof(ni));
123 ui_render();
125 if (timeout_ms < 0)
126 timeout_ms = -1;
127 if (timeout_ms > 1) {
128 // ------------------------------------------------------------
129 // Poll for input on the TTY and any registered external files
130 // ------------------------------------------------------------
131 struct pollfd fds[1 + MAX_EXT_FDS];
132 int token_id;
133 int reg_idx;
134 memset(fds, 0, sizeof(fds));
135 fds[0].fd = notcurses_inputready_fd(ui->nc);
136 fds[0].events = POLLIN;
137 nfds_t nfds = 1;
138 nfds_t ext_start_idx = nfds;
139 for (nfds_t i = 0; i < ui_ctx.ext_nfds; i++) {
140 fds[nfds].fd = ui_ctx.ext_fds[i].fd;
141 fds[nfds].events = POLLIN;
142 nfds++;
143 }
144 int poll_rc = poll(fds, nfds, timeout_ms);
145 if (poll_rc < 0) {
146 if (errno == EINTR)
147 return 0; // continue
148 return -1;
149 }
150 if (poll_rc == 0) { // timed out with no input
151 ni.id = UIKEY_TIMEOUT;
152 return ni.id;
153 }
154 bool ui_ready = (fds[0].revents & POLLIN);
155 if (!ui_ready) {
156 for (nfds_t i = ext_start_idx; i < nfds; i++) {
157 if (fds[i].revents & (POLLIN | POLLHUP | POLLERR)) {
158 reg_idx = i - ext_start_idx;
159 token_id = ui_ctx.ext_fds[reg_idx].token_id;
160 return token_id;
161 }
162 }
163 } else {
164 timeout_ms = 0;
165 }
166 }
167 memset(ev, 0, sizeof(*ev));
168 ui_render();
169 if (timeout_ms < 0) {
170 do {
171 notcurses_get_blocking(ui->nc, &ni);
172 } while (ni.evtype == NCTYPE_RELEASE ||
173 ni.id == NCKEY_INVALID || ni.id == NCKEY_MOTION || ni.id == NCKEY_SIGNAL);
174 } else {
175 struct timespec ts = {
176 .tv_sec = timeout_ms / 1000,
177 .tv_nsec = (long)(timeout_ms % 1000) * 1000000L,
178 };
179 do {
180 notcurses_get(ui->nc, &ts, &ni);
181 } while (ni.evtype == NCTYPE_RELEASE || ni.id == NCKEY_MOTION || ni.id == NCKEY_INVALID);
182 }
183 ev->key = translate_nckey(ni.id, &ni);
184 ev->alt = ncinput_alt_p(&ni);
185 ev->ctrl = ncinput_ctrl_p(&ni);
186 ev->shift = ncinput_shift_p(&ni);
187 if (ev->key == UIKEY_CHAR)
188 ev->ch = ni.id; /* Unicode codepoint */
189 else if (ev->key == UIKEY_MOUSE) {
190 if (ni.id == NCKEY_BUTTON4)
192 else if (ni.id == NCKEY_BUTTON5)
194 else if (ni.id == NCKEY_BUTTON1 && ni.evtype == NCTYPE_PRESS) {
196 struct ncplane *clicked = ui_ncplane_clicked(s, w, &ni);
197 ev->y = ni.y;
198 ev->x = ni.x;
199 ev->in_win = ui_get_plane_idx(s, clicked);
200 if (chyron) {
201 if (ev->in_win == chyron->w && ev->y == chyron->y) {
203 ev->key = ui_get_chyron_key(chyron, ev->x);
204 return ev->key;
205 } else
206 return 0;
207 } else {
208 if (ev->in_win == w) {
210 ev->key = ev->y;
211 return ev->key;
212 } else
213 return 0;
214 }
215 }
216 }
217 return ni.id;
218}
void ui_render()
Render the UI by updating panels and refreshing the display.
Definition ui_ncurses.c:884
#define MAX_EXT_FDS
Definition ui_backend.h:131
ui_context_t ui_ctx
Definition ui_common.c:59
#define UIKEY_TIMEOUT
#define UIKEY_MOUSE
#define UIKEY_BUTTON1_PRESSED
#define UIKEY_SCROLL_UP
#define UIKEY_BUTTON1_CLICKED
#define UIKEY_CHAR
#define UIKEY_SCROLL_DOWN
int ui_get_chyron_key(UiChyron *chyron, uint x)
Get keycode from chyron.
Definition ui_common.c:861
void ui_flush_input()
Flush any pending input events from the NotCurses context. This function discards any input events th...
NcPlane * ui_ncplane_clicked(UiSurface *s, ss_t w, ncinput *ni)
Determine which ncplane was clicked based on the mouse event coordinates.
uint ui_get_plane_idx(UiSurface *s, struct ncplane *plane)
Get the index of a given ncplane in the UiSurface's plane array.
uint32_t ch
Definition ui_backend.h:104
UiMouseAction mouse_action
Definition ui_backend.h:114
bool shift
Definition ui_backend.h:107
ss_t in_win
Definition ui_backend.h:112
bool ctrl
Definition ui_backend.h:106
UiKey key
Definition ui_backend.h:103
bool alt
Definition ui_backend.h:105

References UiEvent::alt, UiEvent::ch, UiEvent::ctrl, ui_context_t::ext_fds, ui_context_t::ext_nfds, ext_fd_reg_t::fd, UiEvent::in_win, UiEvent::key, UiEvent::mouse_action, UiEvent::shift, ext_fd_reg_t::token_id, ui, ui_ctx, ui_flush_input(), ui_get_chyron_key(), ui_render(), UiEvent::x, and UiEvent::y.

Here is the call graph for this function:

◆ ui_get_event_no_mouse()

int ui_get_event_no_mouse ( UiSurface * target,
ss_t w,
UiEvent * ev )

Wait for an input event from the NotCurses context, ignoring mouse events.

Wait for an input event on target (or stdscr if NULL) without mouse support.

Parameters
targetUnused for NotCurses (events are global to the context).
evOutput UiEvent structure.
Returns
The NotCurses key code, or -1 if ui or ev is NULL.

Definition at line 239 of file ui_notcurses_input.c.

239 {
240 (void)target;
241 (void)w;
242 if (!ui || !ev)
243 return -1;
244 memset(ev, 0, sizeof(*ev));
245 ncinput ni;
246 notcurses_mice_disable(ui->nc);
247 do {
248 notcurses_get(ui->nc, NULL, &ni);
249 } while (ni.id == NCKEY_INVALID);
250 ev->key = translate_nckey(ni.id, &ni);
251 ev->alt = ncinput_alt_p(&ni);
252 ev->ctrl = ncinput_ctrl_p(&ni);
253 ev->shift = ncinput_shift_p(&ni);
254 if (ev->key == UIKEY_CHAR)
255 ev->ch = ni.id;
256 return ni.id;
257}

References UiEvent::alt, UiEvent::ch, UiEvent::ctrl, UiEvent::key, UiEvent::shift, ui, and ui_flush_input().

Here is the call graph for this function:

◆ ui_get_plane_idx()

uint ui_get_plane_idx ( UiSurface * s,
struct ncplane * plane )

Get the index of a given ncplane in the UiSurface's plane array.

Parameters
sThe UiSurface containing the planes.
planeThe ncplane to find.
Returns
The index of the plane in the UiSurface's mplane array, or -1 if not found.

Definition at line 263 of file ui_notcurses_input.c.

263 {
264 for (ss_t w = BOX; w < SUB_SFC_MAX; ++w) {
265 if (s->mplane[w] == plane)
266 return w;
267 }
268 return -1;
269}
ss_t
Definition ui_backend.h:45
@ SUB_SFC_MAX
Definition ui_backend.h:47
struct ncplane * mplane[SUB_SFC_MAX]
Definition ui_backend.h:351

References SUB_SFC_MAX.

◆ ui_getch()

int ui_getch ( )

Wait for a single input character from the NotCurses context.

Returns
The NotCurses key code, or -1 if ui is NULL.

Definition at line 222 of file ui_notcurses_input.c.

222 {
223 if (!ui)
224 return -1;
225 ncinput ni;
226 do {
227 notcurses_get(ui->nc, NULL, &ni);
228 } while (ni.evtype == NCTYPE_RELEASE ||
229 ni.id == NCKEY_INVALID ||
230 ni.id == NCKEY_MOTION ||
231 ni.id == NCKEY_SIGNAL);
232 return ni.id;
233}

References ui.

◆ ui_mice_enable()

int ui_mice_enable ( int mask)

Enable or disable mouse events for the NotCurses context.

Enable or disable mouse support.

Parameters
maskThe mouse event mask to enable. If 0, all mouse events are enabled.
Returns
0 on success, or -1 if ui is NULL.

Definition at line 310 of file ui_notcurses_input.c.

310 {
311 if (mask)
312 notcurses_mice_enable(ui->nc, mask);
313 else {
314 notcurses_mice_enable(ui->nc, NCMICE_BUTTON_EVENT);
315 }
316 return 0;
317}

References ui.

◆ ui_mousemask()

int ui_mousemask ( int mask)

Set the mouse event mask for the NotCurses context.

Enable or disable mouse support.

Parameters
maskThe mouse event mask to set. If 0, all mouse events are enabled.
Returns
0 on success, or -1 if ui is NULL.

Definition at line 297 of file ui_notcurses_input.c.

297 {
298 if (!ui)
299 return 0;
300 if (mask)
301 notcurses_mice_enable(ui->nc, mask);
302 else
303 notcurses_mice_enable(ui->nc, NCMICE_BUTTON_EVENT);
304 return 0;
305}

References ui.

Referenced by menu_cmd_processor(), and picker().

Here is the caller graph for this function:

◆ ui_ncplane_clicked()

NcPlane * ui_ncplane_clicked ( UiSurface * s,
ss_t w,
ncinput * ni )

Determine which ncplane was clicked based on the mouse event coordinates.

Parameters
sThe UiSurface containing the planes.
wThe index of the plane to check for clicks.
niThe NotCurses input event containing mouse coordinates.
Returns
The ncplane that was clicked, or NULL if no plane was clicked.

Definition at line 276 of file ui_notcurses_input.c.

276 {
277 NcPlane *pile_member = s->mplane[w];
278 struct ncplane *cur = ncpile_top(pile_member);
279 while (cur != NULL) {
280 int y = ni->y, x = ni->x;
281 if (ncplane_translate_abs(cur, &y, &x)) {
282 ni->y = y;
283 ni->x = x;
284 return cur;
285 }
286 cur = ncplane_below(cur);
287 }
288 return NULL;
289}
struct ncplane NcPlane
Definition ui_backend.h:419