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

NCurses UI backend — input handling. More...

#include "cm.h"
#include "ui_backend.h"
#include "ui_ncurses_internal.h"
#include <poll.h>
#include <stddef.h>
#include <string.h>
#include <termios.h>
Include dependency graph for ui_ncurses_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)
 Read input events.
int ui_get_event_no_mouse (UiSurface *s, ss_t w, UiEvent *ev)
 Wait for an input event on target (or stdscr if NULL) without mouse support.
int ui_mice_enable (int mask)
 Enable or disable mouse support.
int ui_mousemask (int mask)
 Enable or disable mouse support.

Detailed Description

NCurses UI backend — input handling.

Translates raw NCurses key codes and mouse events into the portable UiEvent representation defined in ui_backend.h.

Definition in file ui_ncurses_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 102 of file ui_ncurses_input.c.

102 {
103 if (ui && ui->tty_fd >= 0) {
104 tcflush(ui->tty_fd, TCIFLUSH);
105 }
106}
UiRuntime * ui
Definition ui_ncurses.c:39

References ui.

Referenced by ui_get_event(), ui_get_event_no_mouse(), and view_init_input().

Here is the caller graph for this function:

◆ ui_get_event()

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

Read input events.

Wait for an input event from the NotCurses context.

Parameters
sSurface - may contain multiple widgets (planes/panels)
wWidget index (A surface may contain multilple widgets)
chyronA zoned group of Actions or Commands
evEvent data structure
timeout_msTimeout in milliseconds (0 for no wait, -1 for infinite wait).
Returns
0 on success, -1 if ev is NULL.
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 116 of file ui_ncurses_input.c.

116 {
117 if (!ev)
118 return -1;
119 int ch;
121 ui_render();
122 if (timeout_ms < 0)
123 timeout_ms = -1; // Block waiting for input
124 if (timeout_ms > 0) {
125 // ------------------------------------------------------------
126 // Poll for input on the TTY and any registered external files
127 // ------------------------------------------------------------
128 struct pollfd fds[1 + MAX_EXT_FDS];
129 int token_id;
130 int reg_idx;
131 memset(fds, 0, sizeof(fds));
132 fds[0].fd = ui->tty_fd;
133 fds[0].events = POLLIN; // also POLLERR | POLLHUP | POLLNVAL
134 nfds_t nfds = 1;
135 nfds_t ext_start_idx = nfds;
136 for (nfds_t i = 0; i < ui_ctx.ext_nfds; i++) {
137 fds[nfds].fd = ui_ctx.ext_fds[i].fd;
138 fds[nfds].events = POLLIN; // also POLLERR | POLLHUP | POLLNVAL
139 nfds++;
140 }
141 int poll_rc = poll(fds, nfds, timeout_ms);
142 if (poll_rc < 0) {
143 if (errno == EINTR)
144 return 0; // continue
145 return -1;
146 }
147 if (poll_rc == 0) { // timed out with no input
148 token_id = UIKEY_TIMEOUT;
149 return token_id;
150 }
151 bool ui_ready = (fds[0].revents & POLLIN);
152 if (!ui_ready) {
153 for (nfds_t i = ext_start_idx; i < nfds; i++) {
154 if (fds[i].revents & (POLLIN | POLLHUP | POLLERR)) {
155 reg_idx = i - ext_start_idx;
156 token_id = ui_ctx.ext_fds[reg_idx].token_id;
157 return token_id;
158 }
159 }
160 } else
161 timeout_ms = -1;
162 }
163 memset(ev, 0, sizeof(*ev));
164 mousemask(ALL_MOUSE_EVENTS | REPORT_MOUSE_POSITION, NULL);
165 wtimeout(s->mwin[w], timeout_ms);
166 do {
167 curs_set(2);
168 ch = wgetch(s->mwin[w]);
169 if (sig_received != 0) {
171 ch = ui_display_error(em0, em1, em2, nullptr);
172 if (ch == 'q' || ch == 'Q' || ch == UIKEY_F09)
173 exit(EXIT_FAILURE);
174 sig_received = 0;
175 return 0;
176 }
177 if (timeout_ms > 0 && ch == ERR) {
178 ch = 0;
179 break;
180 }
181 if (ch == ERR)
182 continue;
183 ev->key = translate_key(ch);
184 if (ev->key == UIKEY_CHAR)
185 ev->ch = (uint32_t)ch; /* Unicode codepoint */
186 else if (ev->key == UIKEY_MOUSE) {
187 MEVENT me;
188 if (getmouse(&me) != OK) {
189 ch = 0;
190 continue;
191 }
192 ev->bstate = me.bstate;
193 ev->y = me.y;
194 ev->x = me.x;
195 if (me.bstate == UIKEY_BUTTON4_PRESSED)
197 else if (me.bstate == UIKEY_BUTTON5_PRESSED)
199 else if (me.bstate == UIKEY_BUTTON1_CLICKED)
201 for (ss_t i = WIN; i < SUB_SFC_MAX; i++) {
202 if (s->mwin[i] != NULL &&
203 wenclose(s->mwin[i], me.y, me.x) &&
204 wmouse_trafo(s->mwin[i], &me.y, &me.x, false)) {
205 ch = ev->mouse_action;
206 ev->bstate = me.bstate;
207 ev->in_win = i;
208 ev->y = me.y;
209 ev->x = me.x;
210 break;
211 }
212 }
213 if (ev->in_win == w)
214 ev->mouse_inside = true;
215 if (chyron && ev->mouse_action == UIKEY_BUTTON1_CLICKED) {
216 if (ev->in_win == chyron->w && ev->y == chyron->y) {
217 ev->key = ui_get_chyron_key(chyron, ev->x);
218 return ev->key;
219 } else
220 return 0;
221 }
222 }
223 } while (ch == ERR);
224 curs_set(0);
225 return ch;
226}
volatile sig_atomic_t sig_received
Definition sig.c:32
bool handle_signal(sig_atomic_t)
void ui_render()
Render the UI by updating panels and refreshing the display.
Definition ui_ncurses.c:884
char em1[MAXLEN]
Definition ui_common.c:47
char em2[MAXLEN]
Definition ui_common.c:48
#define MAX_EXT_FDS
Definition ui_backend.h:131
ui_context_t ui_ctx
Definition ui_common.c:59
ss_t
Definition ui_backend.h:45
@ SUB_SFC_MAX
Definition ui_backend.h:47
#define ERR
Definition ui_backend.h:427
char em0[MAXLEN]
Definition ui_common.c:46
#define UIKEY_TIMEOUT
#define UIKEY_MOUSE
#define UIKEY_BUTTON4_PRESSED
#define UIKEY_BUTTON5_PRESSED
#define UIKEY_F09
#define UIKEY_SCROLL_UP
#define UIKEY_BUTTON1_CLICKED
#define UIKEY_CHAR
#define UIKEY_SCROLL_DOWN
void ui_flush_input()
Flush any pending input events from the NotCurses context. This function discards any input events th...
int ui_get_chyron_key(UiChyron *chyron, uint x)
Get keycode from chyron.
Definition ui_common.c:861
int ui_display_error(char *msg0, char *msg1, char *msg2, char *msg3)
Display an error message window or print to stderr.
Definition ui_common.c:1200
uint32_t ch
Definition ui_backend.h:104
UiMouseAction mouse_action
Definition ui_backend.h:114
int bstate
Definition ui_backend.h:113
ss_t in_win
Definition ui_backend.h:112
UiKey key
Definition ui_backend.h:103
bool mouse_inside
Definition ui_backend.h:115

References UiEvent::bstate, UiEvent::ch, em0, em1, em2, ui_context_t::ext_fds, ui_context_t::ext_nfds, ext_fd_reg_t::fd, handle_signal(), UiEvent::in_win, UiEvent::key, UiEvent::mouse_action, UiEvent::mouse_inside, sig_received, SUB_SFC_MAX, ext_fd_reg_t::token_id, ui, ui_ctx, ui_display_error(), ui_flush_input(), ui_get_chyron_key(), ui_render(), UiEvent::x, and UiEvent::y.

Referenced by cf_accept(), field_editor(), form_post(), form_process(), get_cmd_char(), main(), menu_cmd_processor(), picker(), ui_action_disposition(), ui_answer_yn(), ui_display_error(), ui_perror(), and ui_timeout_prompt().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ ui_get_event_no_mouse()

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

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

Parameters
uiUI runtime context (unused — event comes from the window).
targetSurface to read from, or NULL for stdscr.
evOutput UiEvent structure.
Returns
0 on success, -1 if ev is NULL.

Definition at line 234 of file ui_ncurses_input.c.

234 {
235 int ch;
236 mousemask(0, NULL);
237 curs_set(2);
239 cbreak();
240 do {
241 curs_set(2);
242 ch = wgetch(s->mwin[w]);
243 curs_set(0);
244 ev->key = translate_key(ch);
245 if (ev->key == UIKEY_CHAR) {
246 ev->ch = (uint32_t)ch;
247 break;
248 }
249 } while (ch == ERR);
250 curs_set(0);
251 return ch;
252}

◆ ui_mice_enable()

int ui_mice_enable ( int mask)

Enable or disable mouse support.

Parameters
maskMouse event mask (0 to disable, non-zero to enable).
Returns
0 on success, -1 if UI is not initialized.

Definition at line 274 of file ui_ncurses_input.c.

274 {
275 if (!ui)
276 return -1;
277 if (mask)
278 mousemask(mask, nullptr);
279 else
280 mousemask(ALL_MOUSE_EVENTS | REPORT_MOUSE_POSITION, nullptr);
281 return 0;
282}

◆ ui_mousemask()

int ui_mousemask ( int mask)

Enable or disable mouse support.

Parameters
maskMouse event mask (0 to disable, non-zero to enable).
Returns
0 on success, -1 if UI is not initialized.

Definition at line 261 of file ui_ncurses_input.c.

261 {
262 if (!ui)
263 return -1;
264 if (mask)
265 mousemask(mask, nullptr);
266 else
267 mousemask(ALL_MOUSE_EVENTS | REPORT_MOUSE_POSITION, nullptr);
268 return 0;
269}