#include <stdc.h>
#include <x11.h>
+#include <io.h>
#include "config.h"
typedef struct TWindow {
char* host;
} TWindow;
-char* ARGV0;
-int Foreground = 0;
Atom XA_REGISTRAR, XA_ADD, XA_DEL, XA_OPEN, XA_DONE, XA_TIDE;
TWindow* Windows = NULL;
-void* readprop(XConf* x, Window win, char* prop, Atom type, size_t* length)
+static void* readprop(XConf* x, Window win, char* prop, Atom type, size_t* length)
{
Atom rtype, xa_prop = XInternAtom(x->display, prop, False);
int format;
return (void*)data;
}
-char* read_path(XConf* x, Window id)
+static char* read_path(XConf* x, Window id)
{
int nprops;
char* path = NULL;
Atom xa_file = XInternAtom(x->display, "FILE", False);
Atom* props = XListProperties(x->display, id, &nprops);
- if (!props) return NULL;
- for (int i = 0; i < nprops; i++)
+ if (props)
{
- if (props[i] == xa_file)
+ for (int i = 0; i < nprops; i++)
{
- path = readprop(x, id, "FILE", XA_STRING, 0);
- break;
+ if (props[i] == xa_file)
+ {
+ path = readprop(x, id, "FILE", XA_STRING, 0);
+ break;
+ }
}
+ XFree(props);
}
- XFree(props);
return path;
}
-void win_add(XConf* x, Window id)
+static void win_add(XConf* x, Window id)
{
char* path = read_path(x, id);
if (!path) return;
- printf("ADD 0x%x: '%s'\n", (unsigned int)id, path);
+ telem_send("WIN_ADD(0x%x: '%s')\n", (unsigned int)id, path);
TWindow* win = calloc(1, sizeof(TWindow));
win->win = id;
win->next = Windows;
Windows = win;
}
-void win_del(Window id)
+static void win_del(Window id)
{
if (!Windows) return;
+ telem_send("WIN_DEL(0x%x)\n", id);
if (Windows->win == id)
{
TWindow* deadite = Windows;
}
}
-void win_send(XConf* x, Window from, Window to, int mask, char* atom, size_t val)
+static void win_send(XConf* x, Window from, Window to, int mask, char* atom, size_t val)
{
XEvent ev = {0};
ev.xclient.type = ClientMessage;
XSendEvent(x->display, to, False, mask, &ev);
}
-void win_open(XConf* x, Window winid, char* path, char* addr, char* host)
+static void win_open(XConf* x, Window winid, char* path, char* addr, char* host)
{
- if (!path) return;
- /* search for an existing window */
- for (TWindow* win = Windows; win; win = win->next)
+ if (path)
{
- /* refresh the filepath and crudely determine if window still valid */
- free(win->path);
- win->path = NULL;
- char* file = readprop(x, win->win, "FILE", XA_STRING, NULL);
- win->path = (file ? file : NULL);
-
- if (win->host && !strcmp(win->host, host) &&
- win->path && !strcmp(win->path, path))
+ /* search for an existing window */
+ for (TWindow* win = Windows; win; win = win->next)
{
- /* double check that the window id didnt get reassigned to a non-tide window */
- printf("found open window: 0x%x '%s'\n", (unsigned int)win->win, win->path);
- x11_error_clear();
- char* type = readprop(x, win->win, "TIDE", XA_STRING, 0);
- if (!type || x11_error_get())
- {
- puts("window invalid, marking for cleanup");
- free(win->path), win->path = NULL;
- free(win->host), win->host = NULL;
- free(type);
- break;
- }
- else
+ /* refresh the filepath and crudely determine if window still valid */
+ free(win->path);
+ win->path = NULL;
+ char* file = readprop(x, win->win, "FILE", XA_STRING, NULL);
+ win->path = (file ? file : NULL);
+
+ if (win->host && !strcmp(win->host, host) &&
+ win->path && !strcmp(win->path, path))
{
- puts("window still valid, raising");
- 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);
- win_send(x, x->self, win->win, 0, "GOTO", strtoul(addr, NULL, 0));
- win_send(x, x->self, winid, 0, "DONE", 0);
- free(type);
- return;
+ /* double check that the window id didnt get reassigned to a non-tide window */
+ telem_send("WIN_ACTIVATE(0x%x '%s')\n", (unsigned int)win->win, win->path);
+ x11_error_clear();
+ char* type = readprop(x, win->win, "TIDE", XA_STRING, 0);
+ if (!type || x11_error_get())
+ {
+ puts("window invalid, marking for cleanup");
+ free(win->path), win->path = NULL;
+ free(win->host), win->host = NULL;
+ free(type);
+ break;
+ }
+ else
+ {
+ puts("window still valid, raising");
+ 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);
+ win_send(x, x->self, win->win, 0, "GOTO", strtoul(addr, NULL, 0));
+ win_send(x, x->self, winid, 0, "DONE", 0);
+ free(type);
+ return;
+ }
}
}
- }
- /* if we don't find it, tell sender to spawn a new one */
- win_send(x, x->self, winid, 0, "OPEN", 0);
+ /* if we don't find it, tell sender to spawn a new one */
+ win_send(x, x->self, winid, 0, "OPEN", 0);
+ }
}
-void selclear(XConf* x, XEvent* e)
+static void selclear(XConf* x, XEvent* e)
{
(void)e;
XSync(x->display, False);
- puts("quitting");
+ telem_send("EXITING\n");
exit(0);
}
-void clientmsg(XConf* x, XEvent* e)
+static void clientmsg(XConf* x, XEvent* e)
{
if (XA_REGISTRAR != e->xclient.message_type)
return;
XSync(x->display, False);
}
-TWindow* win_sweep(TWindow* win)
+static TWindow* win_sweep(TWindow* win)
{
if (win)
{
else
{
TWindow* dead = win;
- printf("swept: %x\n", (unsigned)win->win);
+ telem_send("WIN_SWEEP(%x)\n", (unsigned)win->win);
win = win_sweep(win->next);
free(dead);
}
return win;
}
-void propnotify(XConf* x, XEvent* e)
+static void propnotify(XConf* x, XEvent* e)
{
(void)e;
Atom type;
Windows = win_sweep(Windows);
}
-void find_windows(XConf* x)
+static void find_windows(XConf* x)
{
XGrabServer(x->display);
size_t nwindows = 0;
Window* windows = readprop(x, x->root, "_NET_CLIENT_LIST", XA_WINDOW, &nwindows);
- printf("nwindows: %lu\n", nwindows);
+ telem_send("FIND_WINS(nwins: %lu)\n", nwindows);
XUngrabServer(x->display);
for (size_t i = 0; i < nwindows; i++)
win_add(x, windows[i]);
if (windows) XFree(windows);
- puts("done finding windows");
}
-int daemonize(void)
+static int daemonize(void)
{
int status;
/* fork into the background first */
/* clear any inherited umask(2) value */
umask(0);
- if (chdir("/") < 0){}
+ (void)chdir("/");
close(0), close(1), close(2);
return 0;
}
int main(int argc, char** argv)
{
- OPTBEGIN {
- case 'F': Foreground = 1; break;
- } OPTEND;
- if (!Foreground && daemonize() != 0) return 1;
- XConf x = {0};
- puts("start");
- 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_DONE = XInternAtom(x.display, "DONE", 0);
- XA_TIDE = XInternAtom(x.display, "TIDE", 0);
- x.eventfns[SelectionClear] = selclear;
- x.eventfns[ClientMessage] = clientmsg;
- x.eventfns[PropertyNotify] = propnotify;
- puts("inited");
- if (None == XGetSelectionOwner(x.display, XA_REGISTRAR))
+ (void)argc, (void)argv;
+ ARGV0 = argv[0];
+ if (daemonize() >= 0)
{
- XSetSelectionOwner(x.display, XA_REGISTRAR, x.self, CurrentTime);
- puts("made owner");
- if (x.self == XGetSelectionOwner(x.display, XA_REGISTRAR))
- {
- puts("finding windows");
- find_windows(&x);
- puts("event loop");
- x11_event_loop(&x, 0);
- puts("done");
- }
- else
+ 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_DONE = XInternAtom(x.display, "DONE", 0);
+ XA_TIDE = XInternAtom(x.display, "TIDE", 0);
+ x.eventfns[SelectionClear] = selclear;
+ x.eventfns[ClientMessage] = clientmsg;
+ x.eventfns[PropertyNotify] = propnotify;
+ if (None == XGetSelectionOwner(x.display, XA_REGISTRAR))
{
- puts("fail");
+ XSetSelectionOwner(x.display, XA_REGISTRAR, x.self, CurrentTime);
+ if (x.self == XGetSelectionOwner(x.display, XA_REGISTRAR))
+ {
+ find_windows(&x);
+ x11_event_loop(&x, 0);
+ }
+ else
+ {
+ telem_send("FAILED\n");
+ }
}
}
return 1;