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;
}
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;
}
}
+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);
}
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)) {