]> git.mdlowis.com Git - projs/tide.git/commitdiff
fleshed out registrar a bit to keep track of windows and open files
authorMichael D. Lowis <mike@mdlowis.com>
Fri, 19 Oct 2018 03:26:32 +0000 (23:26 -0400)
committerMichael D. Lowis <mike@mdlowis.com>
Fri, 19 Oct 2018 03:26:32 +0000 (23:26 -0400)
src/edit.c
src/registrar.c
src/tide.c

index bdcbb179f4d2a8f76d76b9ae92081ff220c754b5..648087ec151cb78c1b600f19bf452b43738296c7 100644 (file)
@@ -3,28 +3,43 @@
 
 Atom XA_REGISTRAR, XA_OPEN;
 
-void start_registrar(XConf* x) {
+int spawn(char* cmd) {
+    int pid = fork();
+    if (pid == 0)
+        exit(execvp(cmd, (char*[]){cmd, 0}));
+    return pid;
+}
+
+Window start_registrar(XConf* x) {
     /* launch registrar if it isn't yet running */
-    if (None == XGetSelectionOwner(x.display, XA_REGISTRAR)) {
-        puts("launching registrart");
-        if (!fork()) {
-            char* cmd[] = {"registrar", NULL};
-            exit(execvp(cmd[0], cmd));
-        }
+    if (None == XGetSelectionOwner(x->display, XA_REGISTRAR)) {
+        if (spawn("registrar") > 0)
+            sleep(1);
     }
+    return XGetSelectionOwner(x->display, XA_REGISTRAR);
 }
 
 int main(int argc, char** argv) {
-    XConf x;
+    XConf x = {0};
     x11_init(&x);
     x11_mkwin(&x, 1, 1, 0);
-    XA_REGISTRAR = XInternAtom(x.display, "TIDE_REGISTRAR", 0);
+    XA_REGISTRAR = XInternAtom(x.display, "TIDE_REGISTRAR", PropertyChangeMask);
     XA_OPEN = XInternAtom(x.display, "OPEN", 0);
-    start_registrar(&x);
-    /*
-        Loop over files and send and OPEN message for each one.
-    */
-    return 1;
+    Window registrar = start_registrar(&x);
+
+    if (argc == 1) {
+        spawn("tide");
+    } else {
+        /* Loop over files and send and OPEN message for each one. */
+        for (int i = 1; i < argc; i++) {
+            XChangeProperty(
+                x.display, registrar, XA_OPEN, XA_STRING, 8, PropModeAppend,
+                (const unsigned char *)argv[i], strlen(argv[i])+1);
+        }
+    }
+
+    XSync(x.display, False);
+    return 0;
 }
 
 
index 66b50ccc24ed8f81ca05d2899f87b1912e8cc89c..3aaf455c0df6e2c207ad4a9fea62eb313ad5b3eb 100644 (file)
@@ -4,19 +4,33 @@
 typedef struct TWindow {
     struct TWindow* next;
     Window win;
+    char* path;
 } TWindow;
 
-Atom XA_REGISTRAR, XA_ADD, XA_DEL, XA_OPEN;
+Atom XA_REGISTRAR, XA_ADD, XA_DEL, XA_OPEN, XA_FILE;
 TWindow* Windows = NULL;
 
-static void win_add(Window id) {
+char* readprop(XConf* x, Window win, Atom prop, size_t* length) {
+    Atom type;
+    int format;
+    unsigned long datalen, nleft;
+    unsigned char* data = NULL;
+    XGetWindowProperty(
+        x->display, win, prop, 0, -1, True, XA_STRING,
+        &type, &format, &datalen, &nleft, &data);
+    if (length) *length = datalen;
+    return (char*)data;
+}
+
+void win_add(XConf* x, Window id) {
     TWindow* win = calloc(1, sizeof(TWindow));
     win->win = id;
     win->next = Windows;
+    win->path = readprop(x, id, XA_FILE, 0);
     Windows = win;
 }
 
-static void win_del(Window id) {
+void win_del(Window id) {
     if (!Windows) return;
     if (Windows->win == id) {
         TWindow* deadite = Windows;
@@ -33,6 +47,27 @@ static void win_del(Window id) {
     }
 }
 
+void win_open(XConf* x, char* path) {
+    /* search for an existing window */
+    for (TWindow* win = Windows; win; win = win->next) {
+        if (!strcmp(win->path, path)) {
+            XEvent ev = {0};
+            ev.xclient.type = ClientMessage;
+            ev.xclient.send_event = True;
+            ev.xclient.message_type = XInternAtom(x->display, "_NET_ACTIVE_WINDOW", False);
+            ev.xclient.window = win->win;
+            ev.xclient.format = 32;
+            XSendEvent(x->display, x->root, False, SubstructureRedirectMask|SubstructureNotifyMask, &ev);
+            XMapRaised(x->display, win->win);
+            XFlush(x->display);
+            return;
+        }
+    }
+    /* if we don't find it, spawn a new one */
+    if (!fork())
+        exit(execvp("tide", (char*[]){"tide", path, 0}));
+}
+
 void selclear(XConf* x, XEvent* e) {
     exit(0);
 }
@@ -41,23 +76,35 @@ void clientmsg(XConf* x, XEvent* e) {
     if (XA_REGISTRAR != e->xclient.message_type)
         return;
     if (XA_ADD == e->xclient.data.l[0])
-        win_add(e->xclient.window);
+        win_add(x, e->xclient.window);
     else if (XA_DEL == e->xclient.data.l[0])
         win_del(e->xclient.window);
-    else if (XA_OPEN == e->xclient.data.l[0])
-        puts("open");
+}
+
+void propnotify(XConf* x, XEvent* e) {
+    size_t length;
+    char* paths = readprop(x, x->self, XA_OPEN, &length);
+    char* path = paths;
+    while (length) {
+        size_t sz = strlen((char*)path)+1;
+        win_open(x, (char*)path);
+        path += sz, length -= sz;
+    }
+    XFree(paths);
 }
 
 int main(int argc, char** argv) {
-    XConf x;
+    XConf x = {0};
     x11_init(&x);
     x11_mkwin(&x, 1, 1, PropertyChangeMask);
     XA_REGISTRAR = XInternAtom(x.display, "TIDE_REGISTRAR", 0);
     XA_ADD = XInternAtom(x.display, "ADD", 0);
     XA_DEL = XInternAtom(x.display, "DEL", 0);
     XA_OPEN = XInternAtom(x.display, "OPEN", 0);
+    XA_FILE = XInternAtom(x.display, "FILE", 0);
     x.eventfns[SelectionClear] = selclear;
     x.eventfns[ClientMessage] = clientmsg;
+    x.eventfns[PropertyNotify] = propnotify;
     if (None == XGetSelectionOwner(x.display, XA_REGISTRAR)) {
         XSetSelectionOwner(x.display, XA_REGISTRAR, x.self, CurrentTime);
         if (x.self == XGetSelectionOwner(x.display, XA_REGISTRAR)) {
index 30de94f49d238b441a24c3df1089b26398882bda..42f45b2adc93787c5fb3ee509271a9ecc66f12df 100644 (file)
@@ -263,7 +263,7 @@ static void put(char* arg) {
     }
     char* path = (buf->path ? buf->path : "*scratch*");
     win_title(path);
-    win_prop_set("TIDE_FILE", "file", path);
+    win_prop_set("FILE", "file", path);
 }
 
 static void get(char* arg) {
@@ -503,7 +503,7 @@ int main(int argc, char** argv) {
         view_init(win_view(EDIT), path);
         if (line_num) view_setln(win_view(EDIT), line_num);
         win_title(path);
-        win_prop_set("TIDE_FILE", "file", path);
+        win_prop_set("FILE", "file", path);
     } else {
         win_title("*scratch*");
     }