]> git.mdlowis.com Git - projs/tide.git/commitdiff
switched to using poll() for event handling. Uniform interface for pty and x11 handli...
authorMichael D. Lowis <mike@mdlowis.com>
Sun, 9 Jul 2017 23:57:35 +0000 (19:57 -0400)
committerMichael D. Lowis <mike@mdlowis.com>
Sun, 9 Jul 2017 23:57:35 +0000 (19:57 -0400)
Makefile
inc/edit.h
inc/x11.h
lib/event.c [new file with mode: 0644]
lib/win.c
lib/x11.c
tide.c

index e8bc34c03eea530b005e41c5705d9987ec591e24..dc65aab1020bbb6c2501b9737cd0836467411008 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -13,7 +13,8 @@ LIBEDIT_OBJS =     \
        lib/x11.o      \
        lib/win.o      \
        lib/colors.o   \
-       lib/config.o
+       lib/config.o   \
+       lib/event.o
 
 TEST_BINS =      \
        tests/tide  \
index 54e38604790eda2838fb7690dc9732518dae06d4..c01c765e972dd74017c05cdccc02f2429dba9b72 100644 (file)
@@ -21,6 +21,15 @@ char* strconcat(char* dest, ...);
 bool file_exists(char* path);
 char* strmcat(char* first, ...);
 
+
+enum { INPUT, OUTPUT, NOTIFY };
+
+typedef void (*event_cbfn_t)(int fd, void* data);
+
+bool event_poll(int ms);
+void event_watchfd(int fd, int iodir, event_cbfn_t fn, void* data);
+
+
 /* Buffer management functions
  *****************************************************************************/
 /* undo/redo list item */
index a78e0006b27c31738a6c52372a93bdb6598930ff..fdda96b72a43309a557fa05f72abee0fe8d6bf69 100644 (file)
--- a/inc/x11.h
+++ b/inc/x11.h
@@ -115,6 +115,7 @@ enum {
 
 void x11_init(XConfig* cfg);
 void x11_deinit(void);
+int x11_connfd(void);
 char* x11_cfg_get(char* opt);
 int x11_keybtnstate(void);
 bool x11_keymodsset(int mask);
diff --git a/lib/event.c b/lib/event.c
new file mode 100644 (file)
index 0000000..6c2bf3d
--- /dev/null
@@ -0,0 +1,62 @@
+#define _XOPEN_SOURCE 700
+#include <stdc.h>
+#include <utf.h>
+#include <edit.h>
+#include <unistd.h>
+#include <poll.h>
+
+struct event_data {
+    int iodir;
+    void* data;
+    event_cbfn_t fn;
+};
+
+static size_t NumDescriptors = 0;
+static struct pollfd* Descriptors = NULL;
+static struct event_data* EventData = NULL;
+
+bool event_poll(int ms) {
+    /* poll for new events */
+    long n = poll(Descriptors, NumDescriptors, ms);
+    if (n < 0) die("poll() :");
+
+    /* Handle any events that occurred */
+    for (int i = 0; i < NumDescriptors; i++) {
+        /* skip any eventless entries */
+        if (!Descriptors[i].revents) continue;
+
+        /* if a requested event occurred, handle it */
+        if (Descriptors[i].revents & Descriptors[i].events) {
+            EventData[i].fn(Descriptors[i].fd, EventData[i].data);
+            Descriptors[i].revents = 0;
+        }
+
+        /* if the desriptor is done or errored, throw it out */
+        if (Descriptors[i].revents & (POLLERR|POLLHUP)) {
+            close(Descriptors[i].fd);
+            for (int x = i+1; x < NumDescriptors; x++) {
+                Descriptors[x-1] = Descriptors[x];
+                EventData[x-1]   = EventData[x];
+            }
+            NumDescriptors--;
+        }
+    }
+
+    return (n > 0);
+}
+
+void event_watchfd(int fd, int iodir, event_cbfn_t fn, void* data) {
+    int idx = NumDescriptors++;
+    Descriptors = realloc(Descriptors, NumDescriptors * sizeof(struct pollfd));
+    EventData   = realloc(EventData,   NumDescriptors * sizeof(struct event_data));
+    if (!Descriptors || !EventData)
+        die("event_Watchfd() : out of memory\n");
+    Descriptors[idx].fd = fd;
+    EventData[idx].data = data;
+    EventData[idx].fn   = fn;
+    switch (iodir) {
+        case INPUT:  Descriptors[idx].events = POLLIN; break;
+        case OUTPUT: Descriptors[idx].events = POLLOUT; break;
+        case NOTIFY: Descriptors[idx].events = (POLLIN|POLLOUT); break;
+    }
+}
index 59a2df6968087ec79fe916c44cf1312b5581bad8..22a587a5fcd14ad162860539be2d2fb17c2a1cad 100644 (file)
--- a/lib/win.c
+++ b/lib/win.c
@@ -60,18 +60,20 @@ void win_dialog(char* name, void (*errfn)(char*)) {
     x11_dialog(name, config_get_int(WinWidth), config_get_int(WinHeight));
 }
 
+static void win_update(int xfd, void* data) {
+    if (x11_events_queued())
+        x11_events_take();
+    x11_flush();
+}
+
 void win_loop(void) {
     x11_show();
     x11_flip();
+    int ms = config_get_int(EventTimeout);
+    event_watchfd(x11_connfd(), INPUT, win_update, NULL);
     while (x11_running()) {
-        bool pending = x11_events_await(config_get_int(EventTimeout));
-        int nevents  = x11_events_queued();
-        if (update_focus() || pending || nevents || update_needed()) {
-            x11_events_take();
-            if (x11_running())
-                x11_flip();
-        }
-        x11_flush();
+        if (event_poll(ms) || update_focus() || x11_running())
+            x11_flip();
     }
     x11_finish();
 }
index 3e091c22a8812d838761db025ae2e14d7d0ba3b8..3df97cb4d002e8564aa51766138ca25ed6194361 100644 (file)
--- a/lib/x11.c
+++ b/lib/x11.c
@@ -103,6 +103,10 @@ void x11_init(XConfig* cfg) {
     config_init(X.display);
 }
 
+int x11_connfd(void) {
+    return ConnectionNumber(X.display);
+}
+
 int x11_keybtnstate(void) {
     return KeyBtnState;
 }
diff --git a/tide.c b/tide.c
index d7430e04efb24bbac861e50dd2a417a922d1a595..f794f9047e2dba183688a00adfd3eb2972f22727 100644 (file)
--- a/tide.c
+++ b/tide.c
@@ -8,8 +8,6 @@
 #include <ctype.h>
 #include <unistd.h>
 #include <sys/select.h>
-//#include <termios.h>
-//#include <sys/types.h>
 #ifdef __MACH__
     #include <util.h>
 #else
@@ -539,20 +537,6 @@ void onupdate(void) {
     strncat(status, path, remlen);
     win_settext(STATUS, status_bytes);
     win_view(STATUS)->selection = (Sel){0,0,0};
-
-    /* Read from command if we have one */
-    long n = 0, r = 0, i = 0;
-    static char cmdbuf[8192];
-    if (!update_needed()) return;
-    if ((n = read(CmdFD, cmdbuf, sizeof(cmdbuf))) < 0)
-        CmdFD = -1;
-    while (i < n) {
-        Rune rune = 0;
-        size_t length = 0;
-        while (!utf8decode(&rune, &length, cmdbuf[i++]));
-        view_insert(win_view(EDIT), false, rune);
-    }
-    win_buf(EDIT)->outpoint = win_view(EDIT)->selection.end;
 }
 
 void onlayout(void) {
@@ -573,12 +557,7 @@ void onshutdown(void) {
 }
 
 bool update_needed(void) {
-    if (CmdFD < 0) return false;
-    fd_set fds;
-    FD_ZERO(&fds);
-    FD_SET(CmdFD, &fds);
-    struct timeval tv = { .tv_usec = 0 };
-    return (select(CmdFD+1, &fds, NULL, NULL, &tv) > 0);
+    return false;
 }
 
 static void oninput(Rune rune) {
@@ -623,6 +602,21 @@ int pty_spawn(char** argv) {
     return fd;
 }
 
+void pty_update(int fd, void* data) {
+    /* Read from command if we have one */
+    long n = 0, r = 0, i = 0;
+    static char cmdbuf[8192];
+    if ((n = read(CmdFD, cmdbuf, sizeof(cmdbuf))) < 0)
+        CmdFD = -1;
+    while (i < n) {
+        Rune rune = 0;
+        size_t length = 0;
+        while (!utf8decode(&rune, &length, cmdbuf[i++]));
+        view_insert(win_view(EDIT), false, rune);
+    }
+    win_buf(EDIT)->outpoint = win_view(EDIT)->selection.end;
+}
+
 void edit_relative(char* path) {
     char *currdir = NULL, *currpath = NULL, *relpath = NULL;
     char* origdir = getcurrdir();
@@ -679,6 +673,8 @@ void edit_command(char** cmd) {
     win_setlinenums(false);
     win_setruler(0);
     CmdFD = pty_spawn(*cmd ? cmd : shellcmd);
+    event_watchfd(CmdFD, INPUT, pty_update, NULL);
+
 }
 
 #ifndef TEST