diff options
| -rw-r--r-- | src/display.c | 1 | ||||
| -rw-r--r-- | src/keyboard.c | 28 | ||||
| -rw-r--r-- | src/keyboard.h | 13 | ||||
| -rw-r--r-- | src/main.c | 60 | ||||
| -rw-r--r-- | src/reactor.c | 63 | ||||
| -rw-r--r-- | src/reactor.h | 19 |
6 files changed, 133 insertions, 51 deletions
diff --git a/src/display.c b/src/display.c index b34cbf1..a9fc405 100644 --- a/src/display.c +++ b/src/display.c @@ -27,7 +27,6 @@ struct display display_create() { // set terminal to raw mode struct termios term; cfmakeraw(&term); - // non-blocking input // TODO: move to kbd? term.c_cc[VMIN] = 0; term.c_cc[VTIME] = 0; diff --git a/src/keyboard.c b/src/keyboard.c index 2cf9e8c..012ec5a 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -1,11 +1,17 @@ #include "keyboard.h" +#include "reactor.h" +#include <errno.h> #include <string.h> #include <unistd.h> -struct keyboard keyboard_create() { +struct keyboard keyboard_create(struct reactor *reactor) { // TODO: should input term stuff be set here? - return (struct keyboard){}; + return (struct keyboard){ + .reactor_event_id = + reactor_register_interest(reactor, STDIN_FILENO, ReadInterest), + .has_data = false, + }; } void parse_keys(uint8_t *bytes, uint32_t nbytes, struct key *out_keys, @@ -35,15 +41,27 @@ void parse_keys(uint8_t *bytes, uint32_t nbytes, struct key *out_keys, *out_nkeys = nkps; } -struct keyboard_update keyboard_begin_frame(struct keyboard *kbd) { - uint8_t bytes[32] = {0}; - int nbytes = read(STDIN_FILENO, bytes, 32); +struct keyboard_update keyboard_begin_frame(struct keyboard *kbd, + struct reactor *reactor) { struct keyboard_update upd = (struct keyboard_update){.keys = {0}, .nkeys = 0}; + if (!kbd->has_data) { + if (reactor_poll_event(reactor, kbd->reactor_event_id)) { + kbd->has_data = true; + } else { + return upd; + } + } + + uint8_t bytes[32] = {0}; + int nbytes = read(STDIN_FILENO, bytes, 32); + if (nbytes > 0) { parse_keys(bytes, nbytes, upd.keys, &upd.nkeys); + } else if (nbytes == EAGAIN) { + kbd->has_data = false; } return upd; diff --git a/src/keyboard.h b/src/keyboard.h index 439e60d..1a437fc 100644 --- a/src/keyboard.h +++ b/src/keyboard.h @@ -13,16 +13,23 @@ struct key { uint8_t mod; }; -struct keyboard {}; +struct keyboard { + uint32_t reactor_event_id; + bool has_data; +}; struct keyboard_update { struct key keys[32]; uint32_t nkeys; }; -struct keyboard keyboard_create(); +struct reactor; + +struct keyboard keyboard_create(struct reactor *reactor); + +struct keyboard_update keyboard_begin_frame(struct keyboard *kbd, + struct reactor *reactor); -struct keyboard_update keyboard_begin_frame(struct keyboard *kbd); void keyboard_end_frame(struct keyboard *kbd); bool key_equal(struct key *key, uint8_t mod, uint8_t c); @@ -6,18 +6,11 @@ #include <assert.h> #include <signal.h> -#include <sys/epoll.h> #include "binding.h" #include "buffer.h" #include "display.h" - -struct reactor { - int epoll_fd; -}; - -struct reactor reactor_create(); -int reactor_register_interest(struct reactor *reactor, int fd); +#include "reactor.h" struct frame_allocator { uint8_t *buf; @@ -67,6 +60,7 @@ int main(int argc, char *argv[]) { } setlocale(LC_ALL, ""); + signal(SIGTERM, terminate); frame_allocator = frame_allocator_create(1024 * 1024); @@ -79,7 +73,7 @@ int main(int argc, char *argv[]) { display_clear(&display); // init keyboard - struct keyboard kbd = keyboard_create(); + struct keyboard kbd = keyboard_create(&reactor); // commands struct commands commands = command_list_create(32); @@ -102,10 +96,22 @@ int main(int argc, char *argv[]) { buffer_add_text(&curbuf, (uint8_t *)welcome_txt, strlen(welcome_txt)); while (running) { - // update keyboard + + // update current buffer + struct buffer_update buf_upd = buffer_begin_frame( + &curbuf, display.width, display.height - 1, frame_alloc); + + // update screen + if (buf_upd.ncmds > 0) { + display_update(&display, buf_upd.cmds, buf_upd.ncmds, curbuf.dot_line, + curbuf.dot_col); + } + + reactor_update(&reactor); + struct keymap *local_keymaps = NULL; uint32_t nbuffer_keymaps = buffer_keymaps(&curbuf, &local_keymaps); - struct keyboard_update kbd_upd = keyboard_begin_frame(&kbd); + struct keyboard_update kbd_upd = keyboard_begin_frame(&kbd, &reactor); for (uint32_t ki = 0; ki < kbd_upd.nkeys; ++ki) { struct key *k = &kbd_upd.keys[ki]; @@ -122,16 +128,7 @@ int main(int argc, char *argv[]) { } } - // update current buffer - struct buffer_update buf_upd = buffer_begin_frame( - &curbuf, display.width, display.height - 1, frame_alloc); - - // update screen - if (buf_upd.ncmds > 0) { - display_update(&display, buf_upd.cmds, buf_upd.ncmds, curbuf.dot_line, - curbuf.dot_col); - } - + keyboard_end_frame(&kbd); buffer_end_frame(&curbuf, &buf_upd); frame_allocator_clear(&frame_allocator); } @@ -143,24 +140,3 @@ int main(int argc, char *argv[]) { return 0; } - -struct reactor reactor_create() { - int epollfd = epoll_create1(0); - if (epollfd == -1) { - perror("epoll_create1"); - } - - return (struct reactor){.epoll_fd = epollfd}; -} - -int reactor_register_interest(struct reactor *reactor, int fd) { - struct epoll_event ev; - ev.events = EPOLLIN; - ev.data.fd = fd; - if (epoll_ctl(reactor->epoll_fd, EPOLL_CTL_ADD, fd, &ev) < 0) { - perror("epoll_ctl"); - return -1; - } - - return fd; -} diff --git a/src/reactor.c b/src/reactor.c new file mode 100644 index 0000000..eb70047 --- /dev/null +++ b/src/reactor.c @@ -0,0 +1,63 @@ +#include "reactor.h" + +#include <stdio.h> +#include <stdlib.h> +#include <sys/epoll.h> + +struct events { + struct epoll_event events[10]; + uint32_t nevents; +}; + +struct reactor reactor_create() { + int epollfd = epoll_create1(0); + if (epollfd == -1) { + perror("epoll_create1"); + } + + return (struct reactor){ + .epoll_fd = epollfd, + .events = calloc(1, sizeof(struct events)), + }; +} + +void reactor_destroy(struct reactor *reactor) { free(reactor->events); } + +uint32_t reactor_register_interest(struct reactor *reactor, int fd, + enum interest interest) { + struct epoll_event ev; + ev.events = 0; + ev.events |= (interest & ReadInterest) != 0 ? EPOLLIN : 0; + ev.events |= (interest & WriteInterest) != 0 ? EPOLLOUT : 0; + ev.data.fd = fd; + if (epoll_ctl(reactor->epoll_fd, EPOLL_CTL_ADD, fd, &ev) < 0) { + perror("epoll_ctl"); + return -1; + } + + return fd; +} + +bool reactor_poll_event(struct reactor *reactor, uint32_t ev_id) { + struct events *events = (struct events *)reactor->events; + for (uint32_t ei = 0; ei < events->nevents; ++ei) { + struct epoll_event *ev = &events->events[ei]; + + if (ev->data.fd == ev_id) { + return true; + } + } + + return false; +} + +void reactor_update(struct reactor *reactor) { + struct events *events = (struct events *)reactor->events; + int nfds = epoll_wait(reactor->epoll_fd, events->events, 10, -1); + + if (nfds == -1) { + // TODO: log failure + } + + events->nevents = nfds; +} diff --git a/src/reactor.h b/src/reactor.h new file mode 100644 index 0000000..7e028e8 --- /dev/null +++ b/src/reactor.h @@ -0,0 +1,19 @@ +#include <stdbool.h> +#include <stdint.h> + +enum interest { + ReadInterest = 1, + WriteInterest = 2, +}; + +struct reactor { + int epoll_fd; + void *events; +}; + +struct reactor reactor_create(); +void reactor_destroy(struct reactor *reactor); +void reactor_update(struct reactor *reactor); +bool reactor_poll_event(struct reactor *reactor, uint32_t ev_id); +uint32_t reactor_register_interest(struct reactor *reactor, int fd, + enum interest interest); |
