]> git.mdlowis.com Git - proto/anvil.git/commitdiff
sketched out enough that i will reframe windows that exist when the WM launches
authorMichael D. Lowis <mike.lowis@gentex.com>
Tue, 10 Mar 2020 20:50:41 +0000 (16:50 -0400)
committerMichael D. Lowis <mike.lowis@gentex.com>
Tue, 10 Mar 2020 20:50:41 +0000 (16:50 -0400)
anvil.c
anvil.h
build.sh
client.c [new file with mode: 0644]
mons.c [new file with mode: 0644]
util.c

diff --git a/anvil.c b/anvil.c
index b27d691f3197720a647798c0609ab35402cb5fe2..f0bcc560a832a85c2d7d6564f33d85d79f57b5fb 100644 (file)
--- a/anvil.c
+++ b/anvil.c
@@ -1,15 +1,6 @@
 #include "anvil.h"
 
 XConf X = {0};
-Monitor* Monitors = NULL;
-
-static void check(intptr_t stat, char* msg)
-{
-    if (!stat)
-    {
-        die(msg);
-    }
-}
 
 static void check_for_wm(void)
 {
@@ -20,54 +11,23 @@ static void check_for_wm(void)
     XSync(X.disp, False);
 }
 
-static void find_clients(void)
+static void xbtnpress(XEvent* e)
 {
-    unsigned int nwins;
-    Window d1, d2, *wins = NULL;
-//    XWindowAttributes wa;
-    if (XQueryTree(X.disp, X.root, &d1, &d2, &wins, &nwins))
+    Client* c = client_get(e->xbutton.window);
+    if (c && (e->xbutton.window == c->frame))
     {
-        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);
+        if (e->xbutton.button == Button1) {
+            /* TODO: handle move and resize */
+//            XMapWindow(X.disp, c->frame);
+//            client_raise(c);
+        } else if (e->xbutton.button == Button2) {
+            /* TODO: handle close */
+//            client_close(c);
+        } else if (e->xbutton.button == Button3) {
+            /* TODO: handle lowering */
+//            client_lower(c);
         }
-        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;
 }
 
 static void xbtnrelease(XEvent* e)
@@ -112,7 +72,14 @@ static void xenternotify(XEvent* e)
 
 static void xexpose(XEvent* e)
 {
-    (void)e;
+    if (e->xexpose.count == 0)
+    {
+        Client* c = client_get(e->xexpose.window);
+        if (c)
+        {
+            client_draw(c, 0);
+        }
+    }
 }
 
 static void xkeypress(XEvent* e)
@@ -122,13 +89,24 @@ static void xkeypress(XEvent* e)
 
 int main(void)
 {
+    XColor color, exact;
+
     /* Initialize X server*/
     check( (X.disp = XOpenDisplay(0)) != NULL,
         "could not open display");
+puts("opened display");
     X.root = DefaultRootWindow(X.disp);
+    X.screen = DefaultScreen(X.disp);
+    X.black = BlackPixel(X.disp, X.screen);
+    X.white = WhitePixel(X.disp, X.screen);
+    XAllocNamedColor(X.disp, DefaultColormap(X.disp, X.screen), "DimGray", &color, &exact);
+    X.gray = color.pixel;
     check_for_wm();
-    setup_monitors();
-    find_clients();
+puts("locked WM");
+    mons_init();
+puts("setup monitors");
+    client_initall();
+puts("found existing clients");
 
     /* setup event handlers */
     X.eventfns[ButtonPress] = xbtnpress;
@@ -149,6 +127,7 @@ int main(void)
     {
         XEvent ev;
         XNextEvent(X.disp, &ev);
+printf("event: %d\n", ev.type);
         if (X.eventfns[ev.type])
         {
             X.eventfns[ev.type](&ev);
@@ -156,4 +135,4 @@ int main(void)
     }
 
     return 0;
-}
\ No newline at end of file
+}
diff --git a/anvil.h b/anvil.h
index 35d5ca330d276f4fbbce97b55440a4204d35dac5..42c860de27662db5f0ce87836859f9d3b3a650b7 100644 (file)
--- a/anvil.h
+++ b/anvil.h
@@ -16,7 +16,9 @@ Management Notes:
 
 typedef struct {
     Display* disp;
+    int screen;
     Window root;
+    unsigned long black, white, gray;
     void (*eventfns[LASTEvent])(XEvent*);
 } XConf;
 
@@ -39,9 +41,21 @@ typedef struct Monitor {
     Workspace* cspace;
 } Monitor;
 
+#define BORDER_WIDTH 5
+
 /* anvil.c */
 extern XConf X;
+
+/* mons.c */
 extern Monitor* Monitors;
+void mons_init(void);
+void mons_addclient(Client* c);
+
+/* client.c */
+void client_initall(void);
+Client* client_add(Window win, XWindowAttributes* attr);
+void client_draw(Client* c, int active);
+Client* client_get(Window w);
 
 /* error.c */
 extern int (*error_default)(Display* disp, XErrorEvent* ev);
@@ -50,6 +64,7 @@ int error_init(Display* disp, XErrorEvent* ev);
 int error_panic(Display* disp, XErrorEvent* ev);
 
 /* util.c */
+void check(intptr_t stat, char* msg);
 void die(char* str);
 void* ecalloc(size_t n, size_t sz);
 void xfree(void* p);
index f54eaacf4d93a81313d19eb26d9924a906bdcfec..7ce3e681827d30bbbbbca5aa1bfd1d04d0d3f93f 100755 (executable)
--- a/build.sh
+++ b/build.sh
@@ -1,4 +1,4 @@
 #!/bin/sh
 cc -Wall -Wextra -Werror -o anvil *.c -lX11 -lXinerama
 ctags *
-printf "done\n"
\ No newline at end of file
+grep -n 'TODO' *.c | sed -e 's/: \+/: /' -e 's/\/\* *//g' -e 's/ *\*\/$//' -e 's/TODO: *//'
\ No newline at end of file
diff --git a/client.c b/client.c
new file mode 100644 (file)
index 0000000..3c38e1d
--- /dev/null
+++ b/client.c
@@ -0,0 +1,97 @@
+#include "anvil.h"
+
+static int title_height(void)
+{
+    return 10;
+}
+
+void client_initall(void)
+{
+    unsigned int nwins;
+    Window d1, d2, *wins = NULL;
+    XWindowAttributes attr;
+    if (XQueryTree(X.disp, X.root, &d1, &d2, &wins, &nwins))
+    {
+        for (unsigned int i = 0; i < nwins; i++)
+        {
+            if (XGetWindowAttributes(X.disp, wins[i], &attr) && !attr.override_redirect)
+            {
+                (void)client_add(wins[i], &attr);
+            }
+        }
+        xfree(wins);
+    }
+}
+
+Client* client_add(Window win, XWindowAttributes* attr)
+{
+    Client* c = ecalloc(1, sizeof(Client));
+    c->win = win;
+    c->x = attr->x;
+    c->y = attr->y;
+    c->w = attr->width;
+    c->h = attr->height;
+    mons_addclient(c);
+
+    /* get window name */
+    /* get normal hints ? */
+    /* get registered protocols */
+    /* get transient_for property ? */
+    /* set client flags appropriately */
+    /* get size and position */
+        /* Find monitor, add to that monitors cspace */
+
+    /* Reparent the window if applicable */
+    c->frame = XCreateSimpleWindow(X.disp, X.root,
+        c->x, c->y - title_height(),
+        c->w, c->h + title_height(),
+        1, X.black, X.white);
+    XSelectInput(X.disp, c->frame,
+        ExposureMask | EnterWindowMask |
+        ButtonPressMask | ButtonReleaseMask |
+        SubstructureRedirectMask | SubstructureNotifyMask |
+        PointerMotionMask
+    );
+    XResizeWindow(X.disp, c->win, c->w - 2 * BORDER_WIDTH, c->h - 2 * BORDER_WIDTH);
+    XSetWindowAttributes wa;
+    wa.event_mask = EnterWindowMask | PropertyChangeMask | FocusChangeMask;
+    wa.win_gravity = StaticGravity;
+    wa.do_not_propagate_mask = ButtonPressMask | ButtonReleaseMask;
+    XChangeWindowAttributes(X.disp, c->win, CWEventMask | CWWinGravity | CWDontPropagate, &wa);
+    XReparentWindow(X.disp, c->win, c->frame, BORDER_WIDTH, BORDER_WIDTH + title_height());
+
+    /* Map the window and draw the frame */
+    XAddToSaveSet(X.disp, c->win);
+    XMapWindow(X.disp, c->frame);
+    XMapWindow(X.disp, c->win);
+    client_draw(c, 0);
+
+    /* Set focus and state? */
+
+    return c;
+}
+
+void client_draw(Client* c, int active)
+{
+    if (c->frame)
+    {
+        XSetWindowBackground(X.disp, c->frame, active ? X.black : X.gray);
+        XClearWindow(X.disp, c->frame);
+
+    //    int quarter = (border + titleHeight()) / 4;
+    //    /* Draw window title. */
+    //    if (c->name != 0) {
+    //        Xutf8DrawString(dpy, c->parent, font_set,
+    //            gc, border + 2 + (3 * quarter),
+    //            2 + ascent(font_set_ext),
+    //            c->name, c->namelen);
+    //    }
+    }
+}
+
+Client* client_get(Window w)
+{
+    (void)w;
+    /* TODO: Actually find the window correctly... */
+    return NULL;
+}
diff --git a/mons.c b/mons.c
new file mode 100644 (file)
index 0000000..af35b63
--- /dev/null
+++ b/mons.c
@@ -0,0 +1,32 @@
+#include "anvil.h"
+
+Monitor* Monitors = NULL;
+
+void mons_init(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);
+}
+
+/* adds a new client to the most appropriate monitor */
+void mons_addclient(Client* c)
+{
+    /* for now just add it to the first monitor in the list */
+    c->next = Monitors->cspace->floating;
+    Monitors->cspace->floating = c;
+    /* TODO: using size and position to pick the "right" monitor */
+}
\ No newline at end of file
diff --git a/util.c b/util.c
index b43b6dfda771bd81ac47751261c31d0686edafdb..6396ea451348cddb38d352ea0d9d78f2d5c8c46a 100644 (file)
--- a/util.c
+++ b/util.c
@@ -1,5 +1,13 @@
 #include "anvil.h"
 
+void check(intptr_t stat, char* msg)
+{
+    if (!stat)
+    {
+        die(msg);
+    }
+}
+
 void die(char* str)
 {
     printf("anvil: fatal error: %s\n", str);