#include "anvil.h"
-XConf X;
+XConf X = {0};
+Monitor* Monitors = NULL;
-static void check(intptr_t stat)
+static void check(intptr_t stat, char* msg)
{
if (!stat)
{
- exit(1);
+ die(msg);
}
}
+static void check_for_wm(void)
+{
+ error_default = XSetErrorHandler(error_init);
+ XSelectInput(X.disp, X.root, SubstructureRedirectMask);
+ XSync(X.disp, False);
+ XSetErrorHandler(error_panic);
+ XSync(X.disp, False);
+}
+
+static void find_clients(void)
+{
+ unsigned int nwins;
+ Window d1, d2, *wins = NULL;
+// XWindowAttributes wa;
+ if (XQueryTree(X.disp, X.root, &d1, &d2, &wins, &nwins))
+ {
+ for (unsigned int i = 0; i < nwins; i++)
+ {
+// if (!XGetWindowAttributes(dpy, wins[i], &wa) || wa.override_redirect || XGetTransientForHint(dpy, wins[i], &d1))
+// continue;
+// if (wa.map_state == IsViewable || getstate(wins[i]) == IconicState)
+// manage(wins[i], &wa);
+ }
+ for (unsigned int i = 0; i < nwins; i++) { /* now the transients */
+// if (!XGetWindowAttributes(dpy, wins[i], &wa))
+// continue;
+// if (XGetTransientForHint(dpy, wins[i], &d1)
+// && (wa.map_state == IsViewable || getstate(wins[i]) == IconicState))
+// manage(wins[i], &wa);
+ }
+ xfree(wins);
+ }
+}
+
+static void setup_monitors(void)
+{
+ int nmons;
+ check( XineramaIsActive(X.disp), "Xinerama extension is required");
+ XineramaScreenInfo* mons = XineramaQueryScreens(X.disp, &nmons);
+ for (int i = 0; i < nmons; i++)
+ {
+ Monitor* m = ecalloc(1, sizeof(Monitor));
+ m->wspaces = ecalloc(1, sizeof(Workspace));
+ m->cspace = m->wspaces;
+ m->x = mons[i].x_org;
+ m->y = mons[i].y_org;
+ m->w = mons[i].width;
+ m->h = mons[i].height;
+ m->next = Monitors;
+ Monitors = m;
+ }
+ xfree(mons);
+}
+
static void xbtnpress(XEvent* e)
{
(void)e;
int main(void)
{
/* Initialize X server*/
- check( !(X.disp = XOpenDisplay(0)) );
+ check( (X.disp = XOpenDisplay(0)) != NULL,
+ "could not open display");
X.root = DefaultRootWindow(X.disp);
+ check_for_wm();
+ setup_monitors();
+ find_clients();
/* setup event handlers */
X.eventfns[ButtonPress] = xbtnpress;
X.eventfns[Expose] = xexpose;
/* main event loop */
+ XSync(X.disp, False);
for (;;)
{
XEvent ev;
X.eventfns[ev.type](&ev);
}
}
+
+ return 0;
}
\ No newline at end of file
#include <X11/X.h>
#include <X11/Xlib.h>
+#include <X11/extensions/Xinerama.h>
#include <stdlib.h>
#include <stdint.h>
+#include <stdio.h>
+
+/*
+Management Notes:
+ * N monitors
+ * M workspaces per monitor
+ * O columns per workspace
+ * Windows can tile in a column or float on workspaces
+ * Columns can have different layouts: manual, stacked, monocle
+*/
typedef struct {
Display* disp;
typedef struct Client {
struct Client* next;
char* name;
- Window win;
+ Window frame, win;
int x, y, w, h;
} Client;
+typedef struct Workspace {
+ struct Workspace* next;
+ Client* floating;
+} Workspace;
+
+typedef struct Monitor {
+ struct Monitor* next;
+ int x, y, w, h;
+ Workspace* wspaces;
+ Workspace* cspace;
+} Monitor;
+
+/* anvil.c */
extern XConf X;
+extern Monitor* Monitors;
+
+/* error.c */
+extern int (*error_default)(Display* disp, XErrorEvent* ev);
+int error_ignore(Display* disp, XErrorEvent* ev);
+int error_init(Display* disp, XErrorEvent* ev);
+int error_panic(Display* disp, XErrorEvent* ev);
+
+/* util.c */
+void die(char* str);
+void* ecalloc(size_t n, size_t sz);
+void xfree(void* p);
--- /dev/null
+#include "anvil.h"
+
+int (*error_default)(Display* disp, XErrorEvent* ev) = NULL;
+
+int error_ignore(Display* disp, XErrorEvent* ev)
+{
+ (void)disp, (void)ev;
+ return 0;
+}
+
+int error_init(Display* disp, XErrorEvent* ev)
+{
+ (void)disp, (void)ev;
+ die("another window manager is active");
+ return -1;
+}
+
+int error_panic(Display* disp, XErrorEvent* ev)
+{
+ fprintf(stderr, "anvil: fatal error: request code=%d, error code=%d\n", ev->request_code, ev->error_code);
+ return error_default(disp, ev);
+}