]> git.mdlowis.com Git - proto/anvil.git/commitdiff
sketched out monitor and workspace initialization based on Xinerama. Probably good...
authorMichael D. Lowis <mike.lowis@gentex.com>
Tue, 10 Mar 2020 16:21:44 +0000 (12:21 -0400)
committerMichael D. Lowis <mike.lowis@gentex.com>
Tue, 10 Mar 2020 16:21:44 +0000 (12:21 -0400)
anvil.c
anvil.h
build.sh
error.c [new file with mode: 0644]
util.c [new file with mode: 0644]

diff --git a/anvil.c b/anvil.c
index 62cb43fe1d6dde55d3fe512b6bf07b92f604d1e8..b27d691f3197720a647798c0609ab35402cb5fe2 100644 (file)
--- a/anvil.c
+++ b/anvil.c
@@ -1,15 +1,70 @@
 #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;
@@ -68,8 +123,12 @@ static void xkeypress(XEvent* 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;
@@ -85,6 +144,7 @@ int main(void)
     X.eventfns[Expose] = xexpose;
 
     /* main event loop */
+    XSync(X.disp, False);
     for (;;)
     {
         XEvent ev;
@@ -94,4 +154,6 @@ int main(void)
             X.eventfns[ev.type](&ev);
         }
     }
+
+    return 0;
 }
\ No newline at end of file
diff --git a/anvil.h b/anvil.h
index 3fe8c4d5af59bd7cb8b4c659f9230eb2b281cf6c..35d5ca330d276f4fbbce97b55440a4204d35dac5 100644 (file)
--- a/anvil.h
+++ b/anvil.h
@@ -1,7 +1,18 @@
 #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;
@@ -12,8 +23,33 @@ typedef struct {
 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);
index f141ac3f439d8ad8aa11760ba4cf52417a479e05..f54eaacf4d93a81313d19eb26d9924a906bdcfec 100755 (executable)
--- a/build.sh
+++ b/build.sh
@@ -1,3 +1,4 @@
 #!/bin/sh
-cc -Wall -Wextra -Werror -o anvil *.c -lX11
+cc -Wall -Wextra -Werror -o anvil *.c -lX11 -lXinerama
 ctags *
+printf "done\n"
\ No newline at end of file
diff --git a/error.c b/error.c
new file mode 100644 (file)
index 0000000..70cfabe
--- /dev/null
+++ b/error.c
@@ -0,0 +1,22 @@
+#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);
+}
diff --git a/util.c b/util.c
new file mode 100644 (file)
index 0000000..b43b6df
--- /dev/null
+++ b/util.c
@@ -0,0 +1,25 @@
+#include "anvil.h"
+
+void die(char* str)
+{
+    printf("anvil: fatal error: %s\n", str);
+    exit(1);
+}
+
+void* ecalloc(size_t n, size_t sz)
+{
+    void* p = calloc(n, sz);
+    if (!p)
+    {
+        die("out of memory");
+    }
+    return p;
+}
+
+void xfree(void* p)
+{
+    if (p)
+    {
+        XFree(p);
+    }
+}