From: Michael D. Lowis Date: Fri, 19 Oct 2018 03:26:32 +0000 (-0400) Subject: fleshed out registrar a bit to keep track of windows and open files X-Git-Url: https://git.mdlowis.com/?a=commitdiff_plain;h=2d473d32491785118136b7b81f1e47904056292f;p=projs%2Ftide.git fleshed out registrar a bit to keep track of windows and open files --- diff --git a/src/edit.c b/src/edit.c index bdcbb17..648087e 100644 --- a/src/edit.c +++ b/src/edit.c @@ -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; } diff --git a/src/registrar.c b/src/registrar.c index 66b50cc..3aaf455 100644 --- a/src/registrar.c +++ b/src/registrar.c @@ -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)) { diff --git a/src/tide.c b/src/tide.c index 30de94f..42f45b2 100644 --- a/src/tide.c +++ b/src/tide.c @@ -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*"); }