summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/display.c1
-rw-r--r--src/keyboard.c28
-rw-r--r--src/keyboard.h13
-rw-r--r--src/main.c60
-rw-r--r--src/reactor.c63
-rw-r--r--src/reactor.h19
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);
diff --git a/src/main.c b/src/main.c
index 140b281..1b9aaac 100644
--- a/src/main.c
+++ b/src/main.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);