mirror of
https://codeberg.org/dnkl/foot.git
synced 2026-02-23 01:40:12 -05:00
Merge branch 'async-ptmx'
This commit is contained in:
commit
e1b6aa87fb
12 changed files with 210 additions and 88 deletions
8
csi.c
8
csi.c
|
|
@ -325,7 +325,7 @@ csi_dispatch(struct terminal *term, uint8_t final)
|
||||||
case 0: {
|
case 0: {
|
||||||
switch (final) {
|
switch (final) {
|
||||||
case 'c':
|
case 'c':
|
||||||
vt_to_slave(term, "\033[?6c", 5);
|
term_to_slave(term, "\033[?6c", 5);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'd': {
|
case 'd': {
|
||||||
|
|
@ -690,7 +690,7 @@ csi_dispatch(struct terminal *term, uint8_t final)
|
||||||
snprintf(reply, sizeof(reply), "\x1b[%d;%dR",
|
snprintf(reply, sizeof(reply), "\x1b[%d;%dR",
|
||||||
term->cursor.row + 1,
|
term->cursor.row + 1,
|
||||||
term->cursor.col + 1);
|
term->cursor.col + 1);
|
||||||
vt_to_slave(term, reply, strlen(reply));
|
term_to_slave(term, reply, strlen(reply));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -910,7 +910,7 @@ csi_dispatch(struct terminal *term, uint8_t final)
|
||||||
*/
|
*/
|
||||||
char reply[32];
|
char reply[32];
|
||||||
snprintf(reply, sizeof(reply), "\033[?%u;2$y", param);
|
snprintf(reply, sizeof(reply), "\033[?%u;2$y", param);
|
||||||
vt_to_slave(term, reply, strlen(reply));
|
term_to_slave(term, reply, strlen(reply));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -965,7 +965,7 @@ csi_dispatch(struct terminal *term, uint8_t final)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
vt_to_slave(term, "\033[>41;347;0c", 12);
|
term_to_slave(term, "\033[>41;347;0c", 12);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
80
fdm.c
80
fdm.c
|
|
@ -14,6 +14,7 @@
|
||||||
|
|
||||||
struct handler {
|
struct handler {
|
||||||
int fd;
|
int fd;
|
||||||
|
int events;
|
||||||
fdm_handler_t callback;
|
fdm_handler_t callback;
|
||||||
void *callback_data;
|
void *callback_data;
|
||||||
bool deleted;
|
bool deleted;
|
||||||
|
|
@ -78,6 +79,7 @@ fdm_add(struct fdm *fdm, int fd, int events, fdm_handler_t handler, void *data)
|
||||||
struct handler *fd_data = malloc(sizeof(*fd_data));
|
struct handler *fd_data = malloc(sizeof(*fd_data));
|
||||||
*fd_data = (struct handler) {
|
*fd_data = (struct handler) {
|
||||||
.fd = fd,
|
.fd = fd,
|
||||||
|
.events = events,
|
||||||
.callback = handler,
|
.callback = handler,
|
||||||
.callback_data = data,
|
.callback_data = data,
|
||||||
.deleted = false,
|
.deleted = false,
|
||||||
|
|
@ -91,7 +93,7 @@ fdm_add(struct fdm *fdm, int fd, int events, fdm_handler_t handler, void *data)
|
||||||
};
|
};
|
||||||
|
|
||||||
if (epoll_ctl(fdm->epoll_fd, EPOLL_CTL_ADD, fd, &ev) < 0) {
|
if (epoll_ctl(fdm->epoll_fd, EPOLL_CTL_ADD, fd, &ev) < 0) {
|
||||||
LOG_ERRNO("failed to register FD with epoll");
|
LOG_ERRNO("failed to register FD=%d with epoll", fd);
|
||||||
free(fd_data);
|
free(fd_data);
|
||||||
tll_pop_back(fdm->fds);
|
tll_pop_back(fdm->fds);
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -107,22 +109,23 @@ fdm_del_internal(struct fdm *fdm, int fd, bool close_fd)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
tll_foreach(fdm->fds, it) {
|
tll_foreach(fdm->fds, it) {
|
||||||
if (it->item->fd == fd) {
|
if (it->item->fd != fd)
|
||||||
if (epoll_ctl(fdm->epoll_fd, EPOLL_CTL_DEL, fd, NULL) < 0)
|
continue;
|
||||||
LOG_ERRNO("failed to unregister FD=%d from epoll", fd);
|
|
||||||
|
|
||||||
if (close_fd)
|
if (epoll_ctl(fdm->epoll_fd, EPOLL_CTL_DEL, fd, NULL) < 0)
|
||||||
close(it->item->fd);
|
LOG_ERRNO("failed to unregister FD=%d from epoll", fd);
|
||||||
|
|
||||||
it->item->deleted = true;
|
if (close_fd)
|
||||||
if (fdm->is_polling)
|
close(it->item->fd);
|
||||||
tll_push_back(fdm->deferred_delete, it->item);
|
|
||||||
else
|
|
||||||
free(it->item);
|
|
||||||
|
|
||||||
tll_remove(fdm->fds, it);
|
it->item->deleted = true;
|
||||||
return true;
|
if (fdm->is_polling)
|
||||||
}
|
tll_push_back(fdm->deferred_delete, it->item);
|
||||||
|
else
|
||||||
|
free(it->item);
|
||||||
|
|
||||||
|
tll_remove(fdm->fds, it);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_ERR("no such FD: %d", fd);
|
LOG_ERR("no such FD: %d", fd);
|
||||||
|
|
@ -141,6 +144,55 @@ fdm_del_no_close(struct fdm *fdm, int fd)
|
||||||
return fdm_del_internal(fdm, fd, false);
|
return fdm_del_internal(fdm, fd, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
event_modify(struct fdm *fdm, struct handler *fd, int new_events)
|
||||||
|
{
|
||||||
|
if (new_events == fd->events)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
struct epoll_event ev = {
|
||||||
|
.events = new_events,
|
||||||
|
.data = {.ptr = fd},
|
||||||
|
};
|
||||||
|
|
||||||
|
if (epoll_ctl(fdm->epoll_fd, EPOLL_CTL_MOD, fd->fd, &ev) < 0) {
|
||||||
|
LOG_ERRNO("failed to modify FD=%d with epoll (events 0x%08x -> 0x%08x)",
|
||||||
|
fd->fd, fd->events, new_events);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
fd->events = new_events;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
fdm_event_add(struct fdm *fdm, int fd, int events)
|
||||||
|
{
|
||||||
|
tll_foreach(fdm->fds, it) {
|
||||||
|
if (it->item->fd != fd)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
return event_modify(fdm, it->item, it->item->events | events);
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_ERR("FD=%d not registered with the FDM", fd);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
fdm_event_del(struct fdm *fdm, int fd, int events)
|
||||||
|
{
|
||||||
|
tll_foreach(fdm->fds, it) {
|
||||||
|
if (it->item->fd != fd)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
return event_modify(fdm, it->item, it->item->events & ~events);
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_ERR("FD=%d not registered with the FDM", fd);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
fdm_poll(struct fdm *fdm)
|
fdm_poll(struct fdm *fdm)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
3
fdm.h
3
fdm.h
|
|
@ -13,4 +13,7 @@ bool fdm_add(struct fdm *fdm, int fd, int events, fdm_handler_t handler, void *d
|
||||||
bool fdm_del(struct fdm *fdm, int fd);
|
bool fdm_del(struct fdm *fdm, int fd);
|
||||||
bool fdm_del_no_close(struct fdm *fdm, int fd);
|
bool fdm_del_no_close(struct fdm *fdm, int fd);
|
||||||
|
|
||||||
|
bool fdm_event_add(struct fdm *fdm, int fd, int events);
|
||||||
|
bool fdm_event_del(struct fdm *fdm, int fd, int events);
|
||||||
|
|
||||||
bool fdm_poll(struct fdm *fdm);
|
bool fdm_poll(struct fdm *fdm);
|
||||||
|
|
|
||||||
8
input.c
8
input.c
|
|
@ -258,7 +258,7 @@ keyboard_key(void *data, struct wl_keyboard *wl_keyboard, uint32_t serial,
|
||||||
info->keypad_keys_mode != term->keypad_keys_mode)
|
info->keypad_keys_mode != term->keypad_keys_mode)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
vt_to_slave(term, info->seq, strlen(info->seq));
|
term_to_slave(term, info->seq, strlen(info->seq));
|
||||||
found_map = true;
|
found_map = true;
|
||||||
|
|
||||||
term_reset_view(term);
|
term_reset_view(term);
|
||||||
|
|
@ -314,14 +314,14 @@ keyboard_key(void *data, struct wl_keyboard *wl_keyboard, uint32_t serial,
|
||||||
|
|
||||||
char reply[1024];
|
char reply[1024];
|
||||||
snprintf(reply, sizeof(reply), "\x1b[27;%d;%d~", modify_param, sym);
|
snprintf(reply, sizeof(reply), "\x1b[27;%d;%d~", modify_param, sym);
|
||||||
vt_to_slave(term, reply, strlen(reply));
|
term_to_slave(term, reply, strlen(reply));
|
||||||
}
|
}
|
||||||
|
|
||||||
else {
|
else {
|
||||||
if (effective_mods & alt)
|
if (effective_mods & alt)
|
||||||
vt_to_slave(term, "\x1b", 1);
|
term_to_slave(term, "\x1b", 1);
|
||||||
|
|
||||||
vt_to_slave(term, buf, count);
|
term_to_slave(term, buf, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
term_reset_view(term);
|
term_reset_view(term);
|
||||||
|
|
|
||||||
18
osc.c
18
osc.c
|
|
@ -78,7 +78,7 @@ from_clipboard_cb(const char *text, size_t size, void *user)
|
||||||
assert(chunk != NULL);
|
assert(chunk != NULL);
|
||||||
assert(strlen(chunk) == 4);
|
assert(strlen(chunk) == 4);
|
||||||
|
|
||||||
vt_to_slave(term, chunk, 4);
|
term_to_slave(term, chunk, 4);
|
||||||
free(chunk);
|
free(chunk);
|
||||||
|
|
||||||
ctx->idx = 0;
|
ctx->idx = 0;
|
||||||
|
|
@ -98,7 +98,7 @@ from_clipboard_cb(const char *text, size_t size, void *user)
|
||||||
char *chunk = base64_encode((const uint8_t *)t, left / 3 * 3);
|
char *chunk = base64_encode((const uint8_t *)t, left / 3 * 3);
|
||||||
assert(chunk != NULL);
|
assert(chunk != NULL);
|
||||||
assert(strlen(chunk) % 4 == 0);
|
assert(strlen(chunk) % 4 == 0);
|
||||||
vt_to_slave(term, chunk, strlen(chunk));
|
term_to_slave(term, chunk, strlen(chunk));
|
||||||
free(chunk);
|
free(chunk);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -120,9 +120,9 @@ osc_from_clipboard(struct terminal *term, const char *source)
|
||||||
if (src == 0)
|
if (src == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
vt_to_slave(term, "\033]52;", 5);
|
term_to_slave(term, "\033]52;", 5);
|
||||||
vt_to_slave(term, &src, 1);
|
term_to_slave(term, &src, 1);
|
||||||
vt_to_slave(term, ";", 1);
|
term_to_slave(term, ";", 1);
|
||||||
|
|
||||||
struct clip_context ctx = {
|
struct clip_context ctx = {
|
||||||
.term = term,
|
.term = term,
|
||||||
|
|
@ -141,10 +141,10 @@ osc_from_clipboard(struct terminal *term, const char *source)
|
||||||
if (ctx.idx > 0) {
|
if (ctx.idx > 0) {
|
||||||
char res[4];
|
char res[4];
|
||||||
base64_encode_final(ctx.buf, ctx.idx, res);
|
base64_encode_final(ctx.buf, ctx.idx, res);
|
||||||
vt_to_slave(term, res, 4);
|
term_to_slave(term, res, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
vt_to_slave(term, "\033\\", 2);
|
term_to_slave(term, "\033\\", 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -343,7 +343,7 @@ osc_dispatch(struct terminal *term)
|
||||||
char reply[32];
|
char reply[32];
|
||||||
snprintf(reply, sizeof(reply), "\033]4;%u;rgb:%02x/%02x/%02x\033\\",
|
snprintf(reply, sizeof(reply), "\033]4;%u;rgb:%02x/%02x/%02x\033\\",
|
||||||
idx, r, g, b);
|
idx, r, g, b);
|
||||||
vt_to_slave(term, reply, strlen(reply));
|
term_to_slave(term, reply, strlen(reply));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -377,7 +377,7 @@ osc_dispatch(struct terminal *term)
|
||||||
reply, sizeof(reply), "\033]%u;rgb:%02x/%02x/%02x\033\\",
|
reply, sizeof(reply), "\033]%u;rgb:%02x/%02x/%02x\033\\",
|
||||||
param, r, g, b);
|
param, r, g, b);
|
||||||
|
|
||||||
vt_to_slave(term, reply, strlen(reply));
|
term_to_slave(term, reply, strlen(reply));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
10
selection.c
10
selection.c
|
|
@ -533,7 +533,7 @@ static void
|
||||||
from_clipboard_cb(const char *data, size_t size, void *user)
|
from_clipboard_cb(const char *data, size_t size, void *user)
|
||||||
{
|
{
|
||||||
struct terminal *term = user;
|
struct terminal *term = user;
|
||||||
vt_to_slave(term, data, size);
|
term_to_slave(term, data, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -544,12 +544,12 @@ selection_from_clipboard(struct terminal *term, uint32_t serial)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (term->bracketed_paste)
|
if (term->bracketed_paste)
|
||||||
vt_to_slave(term, "\033[200~", 6);
|
term_to_slave(term, "\033[200~", 6);
|
||||||
|
|
||||||
text_from_clipboard(term, serial, &from_clipboard_cb, term);
|
text_from_clipboard(term, serial, &from_clipboard_cb, term);
|
||||||
|
|
||||||
if (term->bracketed_paste)
|
if (term->bracketed_paste)
|
||||||
vt_to_slave(term, "\033[201~", 6);
|
term_to_slave(term, "\033[201~", 6);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
|
@ -675,12 +675,12 @@ selection_from_primary(struct terminal *term)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (term->bracketed_paste)
|
if (term->bracketed_paste)
|
||||||
vt_to_slave(term, "\033[200~", 6);
|
term_to_slave(term, "\033[200~", 6);
|
||||||
|
|
||||||
text_from_primary(term, &from_clipboard_cb, term);
|
text_from_primary(term, &from_clipboard_cb, term);
|
||||||
|
|
||||||
if (term->bracketed_paste)
|
if (term->bracketed_paste)
|
||||||
vt_to_slave(term, "\033[201~", 6);
|
term_to_slave(term, "\033[201~", 6);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
|
|
|
||||||
5
server.c
5
server.c
|
|
@ -196,7 +196,6 @@ fdm_server(struct fdm *fdm, int fd, int events, void *data)
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!fdm_add(server->fdm, client_fd, EPOLLIN, &fdm_client, client)) {
|
if (!fdm_add(server->fdm, client_fd, EPOLLIN, &fdm_client, client)) {
|
||||||
LOG_ERR("client FD=%d: failed to add client to FDM", client_fd);
|
|
||||||
close(client_fd);
|
close(client_fd);
|
||||||
free(client);
|
free(client);
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -321,10 +320,8 @@ server_init(const struct config *conf, struct fdm *fdm, struct wayland *wayl)
|
||||||
.clients = tll_init(),
|
.clients = tll_init(),
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!fdm_add(fdm, fd, EPOLLIN, &fdm_server, server)) {
|
if (!fdm_add(fdm, fd, EPOLLIN, &fdm_server, server))
|
||||||
LOG_ERR("failed to add server FD to the FDM");
|
|
||||||
goto err;
|
goto err;
|
||||||
}
|
|
||||||
|
|
||||||
return server;
|
return server;
|
||||||
|
|
||||||
|
|
|
||||||
125
terminal.c
125
terminal.c
|
|
@ -26,15 +26,103 @@
|
||||||
#define min(x, y) ((x) < (y) ? (x) : (y))
|
#define min(x, y) ((x) < (y) ? (x) : (y))
|
||||||
#define max(x, y) ((x) > (y) ? (x) : (y))
|
#define max(x, y) ((x) > (y) ? (x) : (y))
|
||||||
|
|
||||||
|
enum ptmx_write_status {PTMX_WRITE_DONE, PTMX_WRITE_REMAIN, PTMX_WRITE_ERR};
|
||||||
|
|
||||||
|
static enum ptmx_write_status
|
||||||
|
to_slave(struct terminal *term, const void *_data, size_t len, size_t *idx)
|
||||||
|
{
|
||||||
|
const uint8_t *const data = _data;
|
||||||
|
size_t left = len - *idx;
|
||||||
|
|
||||||
|
while (left > 0) {
|
||||||
|
ssize_t ret = write(term->ptmx, &data[*idx], left);
|
||||||
|
|
||||||
|
if (ret < 0) {
|
||||||
|
if (errno == EAGAIN || errno == EWOULDBLOCK)
|
||||||
|
return PTMX_WRITE_REMAIN;
|
||||||
|
|
||||||
|
LOG_ERRNO("failed to write to client");
|
||||||
|
return PTMX_WRITE_ERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
*idx += ret;
|
||||||
|
left -= left;
|
||||||
|
}
|
||||||
|
|
||||||
|
return PTMX_WRITE_DONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
term_to_slave(struct terminal *term, const void *_data, size_t len)
|
||||||
|
{
|
||||||
|
if (tll_length(term->ptmx_buffer) > 0) {
|
||||||
|
/* With a non-empty queue, EPOLLOUT has already been enabled */
|
||||||
|
goto enqueue_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (to_slave(term, _data, len, &(size_t){0})) {
|
||||||
|
case PTMX_WRITE_REMAIN:
|
||||||
|
if (!fdm_event_add(term->fdm, term->ptmx, EPOLLOUT))
|
||||||
|
return false;
|
||||||
|
goto enqueue_data;
|
||||||
|
|
||||||
|
case PTMX_WRITE_DONE: return true;
|
||||||
|
case PTMX_WRITE_ERR: return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
enqueue_data:
|
||||||
|
{
|
||||||
|
void *copy = malloc(len);
|
||||||
|
memcpy(copy, _data, len);
|
||||||
|
|
||||||
|
struct ptmx_buffer queued = {
|
||||||
|
.data = copy,
|
||||||
|
.len = len,
|
||||||
|
.idx = 0,
|
||||||
|
};
|
||||||
|
tll_push_back(term->ptmx_buffer, queued);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
fdm_ptmx_out(struct fdm *fdm, int fd, int events, void *data)
|
||||||
|
{
|
||||||
|
struct terminal *term = data;
|
||||||
|
assert(tll_length(term->ptmx_buffer) > 0);
|
||||||
|
|
||||||
|
tll_foreach(term->ptmx_buffer, it) {
|
||||||
|
switch (to_slave(term, it->item.data, it->item.len, &it->item.idx)) {
|
||||||
|
case PTMX_WRITE_DONE:
|
||||||
|
free(it->item.data);
|
||||||
|
tll_remove(term->ptmx_buffer, it);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PTMX_WRITE_REMAIN: return true; /* to_slave() updated it->item.idx */
|
||||||
|
case PTMX_WRITE_ERR: return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fdm_event_del(term->fdm, term->ptmx, EPOLLOUT);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
fdm_ptmx(struct fdm *fdm, int fd, int events, void *data)
|
fdm_ptmx(struct fdm *fdm, int fd, int events, void *data)
|
||||||
{
|
{
|
||||||
struct terminal *term = data;
|
struct terminal *term = data;
|
||||||
|
|
||||||
|
if (events & EPOLLOUT) {
|
||||||
|
if (!fdm_ptmx_out(fdm, fd, events, data))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if ((events & EPOLLHUP) && !(events & EPOLLIN))
|
if ((events & EPOLLHUP) && !(events & EPOLLIN))
|
||||||
return term_shutdown(term);
|
return term_shutdown(term);
|
||||||
|
|
||||||
assert(events & EPOLLIN);
|
if (!(events & EPOLLIN))
|
||||||
|
return true;
|
||||||
|
|
||||||
uint8_t buf[24 * 1024];
|
uint8_t buf[24 * 1024];
|
||||||
ssize_t count = read(term->ptmx, buf, sizeof(buf));
|
ssize_t count = read(term->ptmx, buf, sizeof(buf));
|
||||||
|
|
@ -328,25 +416,20 @@ term_init(const struct config *conf, struct fdm *fdm, struct wayland *wayl,
|
||||||
goto close_fds;
|
goto close_fds;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!fdm_add(fdm, ptmx, EPOLLIN, &fdm_ptmx, term)) {
|
int ptmx_flags;
|
||||||
LOG_ERR("failed to add ptmx to FDM");
|
if ((ptmx_flags = fcntl(ptmx, F_GETFL)) < 0 ||
|
||||||
|
fcntl(ptmx, F_SETFL, ptmx_flags | O_NONBLOCK) < 0)
|
||||||
|
{
|
||||||
|
LOG_ERRNO("failed to configure ptmx as non-blocking");
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!fdm_add(fdm, flash_fd, EPOLLIN, &fdm_flash, term)) {
|
if (!fdm_add(fdm, ptmx, EPOLLIN, &fdm_ptmx, term) ||
|
||||||
LOG_ERR("failed to add flash timer FD to FDM");
|
!fdm_add(fdm, flash_fd, EPOLLIN, &fdm_flash, term) ||
|
||||||
goto err;
|
!fdm_add(fdm, blink_fd, EPOLLIN, &fdm_blink, term) ||
|
||||||
}
|
!fdm_add(fdm, delay_lower_fd, EPOLLIN, &fdm_delayed_render, term) ||
|
||||||
|
|
||||||
if (!fdm_add(fdm, blink_fd, EPOLLIN, &fdm_blink, term)) {
|
|
||||||
LOG_ERR("failed to add blink tiemr FD to FDM");
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!fdm_add(fdm, delay_lower_fd, EPOLLIN, &fdm_delayed_render, term) ||
|
|
||||||
!fdm_add(fdm, delay_upper_fd, EPOLLIN, &fdm_delayed_render, term))
|
!fdm_add(fdm, delay_upper_fd, EPOLLIN, &fdm_delayed_render, term))
|
||||||
{
|
{
|
||||||
LOG_ERR("failed to add delayed rendering timer FDs to FDM");
|
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -355,6 +438,7 @@ term_init(const struct config *conf, struct fdm *fdm, struct wayland *wayl,
|
||||||
.fdm = fdm,
|
.fdm = fdm,
|
||||||
.quit = false,
|
.quit = false,
|
||||||
.ptmx = ptmx,
|
.ptmx = ptmx,
|
||||||
|
.ptmx_buffer = tll_init(),
|
||||||
.cursor_keys_mode = CURSOR_KEYS_NORMAL,
|
.cursor_keys_mode = CURSOR_KEYS_NORMAL,
|
||||||
.keypad_keys_mode = KEYPAD_NUMERICAL,
|
.keypad_keys_mode = KEYPAD_NUMERICAL,
|
||||||
.auto_margin = true,
|
.auto_margin = true,
|
||||||
|
|
@ -538,7 +622,6 @@ term_shutdown(struct terminal *term)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!fdm_add(term->fdm, event_fd, EPOLLIN, &fdm_shutdown, term)) {
|
if (!fdm_add(term->fdm, event_fd, EPOLLIN, &fdm_shutdown, term)) {
|
||||||
LOG_ERR("failed to add terminal shutdown event FD to the FDM");
|
|
||||||
close(event_fd);
|
close(event_fd);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -629,6 +712,10 @@ term_destroy(struct terminal *term)
|
||||||
assert(tll_length(term->render.workers.queue) == 0);
|
assert(tll_length(term->render.workers.queue) == 0);
|
||||||
tll_free(term->render.workers.queue);
|
tll_free(term->render.workers.queue);
|
||||||
|
|
||||||
|
tll_foreach(term->ptmx_buffer, it)
|
||||||
|
free(it->item.data);
|
||||||
|
tll_free(term->ptmx_buffer);
|
||||||
|
|
||||||
int ret = EXIT_SUCCESS;
|
int ret = EXIT_SUCCESS;
|
||||||
|
|
||||||
if (term->slave > 0) {
|
if (term->slave > 0) {
|
||||||
|
|
@ -1070,7 +1157,7 @@ term_focus_in(struct terminal *term)
|
||||||
{
|
{
|
||||||
if (!term->focus_events)
|
if (!term->focus_events)
|
||||||
return;
|
return;
|
||||||
vt_to_slave(term, "\033[I", 3);
|
term_to_slave(term, "\033[I", 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -1078,7 +1165,7 @@ term_focus_out(struct terminal *term)
|
||||||
{
|
{
|
||||||
if (!term->focus_events)
|
if (!term->focus_events)
|
||||||
return;
|
return;
|
||||||
vt_to_slave(term, "\033[O", 3);
|
term_to_slave(term, "\033[O", 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
|
@ -1152,7 +1239,7 @@ report_mouse_click(struct terminal *term, int encoded_button, int row, int col,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
vt_to_slave(term, response, strlen(response));
|
term_to_slave(term, response, strlen(response));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
|
||||||
|
|
@ -145,6 +145,12 @@ enum mouse_reporting {
|
||||||
|
|
||||||
enum cursor_style { CURSOR_BLOCK, CURSOR_UNDERLINE, CURSOR_BAR };
|
enum cursor_style { CURSOR_BLOCK, CURSOR_UNDERLINE, CURSOR_BAR };
|
||||||
|
|
||||||
|
struct ptmx_buffer {
|
||||||
|
void *data;
|
||||||
|
size_t len;
|
||||||
|
size_t idx;
|
||||||
|
};
|
||||||
|
|
||||||
struct terminal {
|
struct terminal {
|
||||||
struct fdm *fdm;
|
struct fdm *fdm;
|
||||||
|
|
||||||
|
|
@ -152,6 +158,8 @@ struct terminal {
|
||||||
int ptmx;
|
int ptmx;
|
||||||
bool quit;
|
bool quit;
|
||||||
|
|
||||||
|
tll(struct ptmx_buffer) ptmx_buffer;
|
||||||
|
|
||||||
enum cursor_keys cursor_keys_mode;
|
enum cursor_keys cursor_keys_mode;
|
||||||
enum keypad_keys keypad_keys_mode;
|
enum keypad_keys keypad_keys_mode;
|
||||||
bool reverse;
|
bool reverse;
|
||||||
|
|
@ -303,6 +311,7 @@ bool term_shutdown(struct terminal *term);
|
||||||
int term_destroy(struct terminal *term);
|
int term_destroy(struct terminal *term);
|
||||||
|
|
||||||
void term_reset(struct terminal *term, bool hard);
|
void term_reset(struct terminal *term, bool hard);
|
||||||
|
bool term_to_slave(struct terminal *term, const void *data, size_t len);
|
||||||
|
|
||||||
void term_damage_rows(struct terminal *term, int start, int end);
|
void term_damage_rows(struct terminal *term, int start, int end);
|
||||||
void term_damage_rows_in_view(struct terminal *term, int start, int end);
|
void term_damage_rows_in_view(struct terminal *term, int start, int end);
|
||||||
|
|
|
||||||
20
vt.c
20
vt.c
|
|
@ -1015,23 +1015,3 @@ vt_from_slave(struct terminal *term, const uint8_t *data, size_t len)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
|
||||||
vt_to_slave(struct terminal *term, const void *_data, size_t len)
|
|
||||||
{
|
|
||||||
const uint8_t *data = _data;
|
|
||||||
size_t left = len;
|
|
||||||
|
|
||||||
while (left > 0) {
|
|
||||||
ssize_t ret = write(term->ptmx, data, left);
|
|
||||||
if (ret < 0) {
|
|
||||||
LOG_ERRNO("failed to write to client");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
data += ret;
|
|
||||||
left -= ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
|
||||||
1
vt.h
1
vt.h
|
|
@ -6,7 +6,6 @@
|
||||||
#include "terminal.h"
|
#include "terminal.h"
|
||||||
|
|
||||||
void vt_from_slave(struct terminal *term, const uint8_t *data, size_t len);
|
void vt_from_slave(struct terminal *term, const uint8_t *data, size_t len);
|
||||||
bool vt_to_slave(struct terminal *term, const void *data, size_t len);
|
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
vt_param_get(const struct terminal *term, size_t idx, int default_value)
|
vt_param_get(const struct terminal *term, size_t idx, int default_value)
|
||||||
|
|
|
||||||
11
wayland.c
11
wayland.c
|
|
@ -522,14 +522,9 @@ wayl_init(struct fdm *fdm)
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
int wl_fd = wl_display_get_fd(wayl->display);
|
if (!fdm_add(fdm, wl_display_get_fd(wayl->display), EPOLLIN, &fdm_wayl, wayl) ||
|
||||||
if (!fdm_add(fdm, wl_fd, EPOLLIN, &fdm_wayl, wayl)) {
|
!fdm_add(fdm, wayl->kbd.repeat.fd, EPOLLIN, &fdm_repeat, wayl))
|
||||||
LOG_ERR("failed to register Wayland connection with the FDM");
|
{
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!fdm_add(fdm, wayl->kbd.repeat.fd, EPOLLIN, &fdm_repeat, wayl)) {
|
|
||||||
LOG_ERR("failed to register keyboard repeat timer with the FDM");
|
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue