]> git.mdlowis.com Git - proto/anvil.git/commitdiff
rework window handling logic to support floating and tiled window lists. No tiling...
authorMichael D. Lowis <mike.lowis@gentex.com>
Mon, 16 Mar 2020 20:45:53 +0000 (16:45 -0400)
committerMichael D. Lowis <mike.lowis@gentex.com>
Mon, 16 Mar 2020 20:45:53 +0000 (16:45 -0400)
anvil.c
anvil.h
mons.c

diff --git a/anvil.c b/anvil.c
index 76b44d732a2cd6e3050fcc6adb0e53059599d0d6..fe3da5bff7710e724d1fe12f4695a720e06eda7c 100644 (file)
--- a/anvil.c
+++ b/anvil.c
@@ -39,7 +39,7 @@ static void xbtnpress(XEvent* e)
             X.start_y = ev->y_root;
             if (ev->y > (TITLE_HEIGHT + BORDER_WIDTH))
             {
-                X.reshaping = 1;
+                X.mode = M_RESIZE;
                 warp_mouse(c);
             }
         }
@@ -57,7 +57,7 @@ static void xbtnpress(XEvent* e)
 static void xbtnrelease(XEvent* e)
 {
     (void)e;
-    X.reshaping = 0;
+    X.mode = M_IDLE;
 }
 
 static void xbtnmotion(XEvent* e)
@@ -70,7 +70,7 @@ static void xbtnmotion(XEvent* e)
     {
         if (PRESSED(ev->state, Button1))
         {
-            if (!X.reshaping)
+            if (X.mode != M_RESIZE)
             {
                 client_move(c, ev->x_root - X.start_x, ev->y_root - X.start_y);
             }
@@ -102,7 +102,7 @@ static void xconfigrequest(XEvent* e)
         c->w = wc.width;
         c->h = wc.height;
         client_resize(c, 0, 0);
-        if (X.reshaping && Focused == c)
+        if (X.mode == M_RESIZE && Focused == c)
         {
             warp_mouse(c);
         }
@@ -236,6 +236,7 @@ int main(void)
     /* Initialize X server*/
     check( (X.disp = XOpenDisplay(0)) != NULL,
         "could not open display");
+    X.mode = M_INIT;
     X.root = DefaultRootWindow(X.disp);
     X.screen = DefaultScreen(X.disp);
     X.black = BlackPixel(X.disp, X.screen);
@@ -243,7 +244,7 @@ int main(void)
     XAllocNamedColor(X.disp, DefaultColormap(X.disp, X.screen), "DimGray", &color, &exact);
     X.gray = color.pixel;
 
-    /* initialize anvil-specific stuff */
+    /* initialize all the things */
     check_for_wm();
     init_cursors();
     init_font();
@@ -268,6 +269,7 @@ int main(void)
 
     /* main event loop */
     XSync(X.disp, False);
+    X.mode = M_IDLE;
     for (;;)
     {
         XEvent ev;
diff --git a/anvil.h b/anvil.h
index f5a2b92f76b3eb3d44e164b66824cbf450cee96f..cb787d0bd66838940a9f48be6347f470954de6e6 100644 (file)
--- a/anvil.h
+++ b/anvil.h
@@ -25,13 +25,17 @@ Management Notes:
     * Columns can have different layouts: manual, stacked, monocle
 */
 
+enum {
+    M_INIT,
+    M_IDLE,
+    M_RESIZE
+};
+
 typedef struct {
     Display* disp;
-    int screen;
+    int screen, mode, start_x, start_y;
     Window root;
     unsigned long black, white, gray;
-    int start_x, start_y;
-    int reshaping;
     Cursor csr_root, csr_point;
     XFontSet font;
     XFontSetExtents *font_ext;
@@ -53,19 +57,21 @@ typedef struct Client {
 } Client;
 
 enum {
-    STACKED,
-    EXPAND,
-    MONOCOLE
+    TILE_STACKED,
+    TILE_EXPAND,
+    TILE_MONOCOLE
 } TileMode;
 
+typedef struct Column {
+    struct Column* next;
+    int mode, width;
+    Client* clients;
+} Column;
+
 typedef struct Workspace {
     struct Workspace* next;
-    float mfact;
     Client* floating;
-    struct {
-        int mode;
-        Client* clients;
-    } cols[2];
+    Column* columns;
 } Workspace;
 
 typedef struct Monitor {
@@ -78,6 +84,7 @@ typedef struct Monitor {
 typedef struct Location {
     Monitor* monitor;
     Workspace* workspace;
+    Column* column;
     Client* client;
 } Location;
 
diff --git a/mons.c b/mons.c
index 854d337accd8c02da3ad2c87255388e4174a909a..2191bdf9707b01d224657ffaabe1197e2a8959a0 100644 (file)
--- a/mons.c
+++ b/mons.c
@@ -1,10 +1,12 @@
 #include "anvil.h"
 #include <math.h>
 
-static Monitor* pickmon(void);
+static Monitor* pickmon(int ptrx, int ptry);
+static Column* pickcol(Column* cols, int relx);
 static Workspace* pickws(Monitor* mon, int wsid);
 static Client* delclient(Client* list, Client* dead);
 static void client_visibility(Workspace* wspace, int show);
+static Client* client_find(Client* clients, Window win);
 
 Monitor* Monitors = NULL;
 
@@ -16,13 +18,6 @@ void mons_init(void)
     for (int i = 0; i < nmons; i++)
     {
         Monitor* m = ecalloc(1, sizeof(Monitor));
-        for (int i = 0; i < 10; i++)
-        {
-            Workspace* wspace = ecalloc(1, sizeof(Workspace));
-            wspace->next = m->wspaces;
-            m->wspaces = wspace;
-        }
-        m->cspace = m->wspaces;
         m->x = mons[i].x_org;
         m->y = mons[i].y_org;
         m->w = mons[i].width;
@@ -31,6 +26,17 @@ void mons_init(void)
         m->midy = m->y + m->h/2;
         m->next = Monitors;
         Monitors = m;
+        for (int i = 0; i < 10; i++)
+        {
+            Column* col = ecalloc(1, sizeof(Column));
+            col->mode = TILE_STACKED,
+            col->width = m->w;
+            Workspace* wspace = ecalloc(1, sizeof(Workspace));
+            wspace->columns = col;
+            wspace->next = m->wspaces;
+            m->wspaces = wspace;
+        }
+        m->cspace = m->wspaces;
     }
     xfree(mons);
 }
@@ -38,21 +44,44 @@ void mons_init(void)
 /* adds a new client to the most appropriate monitor */
 void mons_addclient(Client* c)
 {
-    Monitor* mon = pickmon();
-    c->next = mon->cspace->floating;
-    mon->cspace->floating = c;
-    int cw = c->w + 2*BORDER_WIDTH;
-    int ch = c->h + 2*BORDER_WIDTH + TITLE_HEIGHT;
-    c->x = mon->midx - cw/2;
-    c->y = mon->midy - ch/2;
+    Window root = 0, child = 0;
+    int ptrx = 0, ptry = 0, winx = 0, winy = 0, mask = 0;
+    XQueryPointer(X.disp, X.root, &root, &child, &ptrx, &ptry, &winx, &winy, (unsigned int*)&mask);
+    Monitor* mon = pickmon(ptrx, ptry);
+    printf("add win to %p\n", mon);
+    if (X.mode == M_INIT)
+    {
+        c->next = mon->cspace->floating;
+        mon->cspace->floating = c;
+        int cw = c->w + 2*BORDER_WIDTH;
+        int ch = c->h + 2*BORDER_WIDTH + TITLE_HEIGHT;
+        c->x = mon->midx - cw/2;
+        c->y = mon->midy - ch/2;
+    }
+    else
+    {
+        Column* col = pickcol(mon->cspace->columns, ptrx - mon->x);
+        c->next = col->clients;
+        col->clients = c;
+        /* TODO: tile the window approriately */
+    }
+    assert(c != c->next);
 }
 
 void mons_delclient(Client* c)
 {
+    assert(c != c->next);
     Location loc = {0};
     if (mons_find(c->win, &loc))
     {
-        loc.workspace->floating = delclient(loc.workspace->floating, c);
+        if (loc.column)
+        {
+            loc.column->clients = delclient(loc.column->clients, c);
+        }
+        else
+        {
+            loc.workspace->floating = delclient(loc.workspace->floating, c);
+        }
         xfree(c->name);
         XDestroyWindow(X.disp, c->frame);
         free(c);
@@ -65,16 +94,27 @@ int mons_find(Window win, Location* loc)
     {
         for (Workspace* wspace = mon->wspaces; wspace; wspace = wspace->next)
         {
-            for (Client* client = wspace->floating; client; client = client->next)
+            Column* column = NULL;
+            Client* client = client_find(wspace->floating, win);
+            if (!client)
             {
-                if (client->frame == win || client->win == win)
+                for (column = wspace->columns; column; column = column->next)
                 {
-                    loc->monitor = mon;
-                    loc->workspace = wspace;
-                    loc->client = client;
-                    return 1;
+                    if ( (client = client_find(column->clients, win)) )
+                    {
+                        break;
+                    }
                 }
             }
+            /* return the client location if we found it */
+            if (client)
+            {
+                loc->monitor = mon;
+                loc->workspace = wspace;
+                loc->column = column;
+                loc->client = client;
+                return 1;
+            }
         }
     }
     return 0;
@@ -88,7 +128,7 @@ void mons_place(Client* c)
     int cright = (c->x + c->w + 2*BORDER_WIDTH);
     int ctop = (c->y - BORDER_WIDTH);
     int cbot = (c->y + c->h + 2*BORDER_WIDTH + TITLE_HEIGHT);
-    if (mons_find(c->win, &loc))
+    if (mons_find(c->win, &loc) && !loc.column)
     {
         int maxarea = 0;
         Monitor* closest = NULL;
@@ -120,7 +160,10 @@ void mons_place(Client* c)
 
 void mons_wspace(int wsid)
 {
-    Monitor* mon = pickmon();
+    Window root = 0, child = 0;
+    int ptrx = 0, ptry = 0, winx = 0, winy = 0, mask = 0;
+    XQueryPointer(X.disp, X.root, &root, &child, &ptrx, &ptry, &winx, &winy, (unsigned int*)&mask);
+    Monitor* mon = pickmon(ptrx, ptry);
     Workspace* wspace = pickws(mon, wsid);
     if (mon->cspace != wspace)
     {
@@ -146,11 +189,8 @@ void mons_towspace(Client* c, int wsid)
     }
 }
 
-static Monitor* pickmon(void)
+static Monitor* pickmon(int ptrx, int ptry)
 {
-    Window root = 0, child = 0;
-    int ptrx = 0, ptry = 0, winx = 0, winy = 0, mask = 0;
-    XQueryPointer(X.disp, X.root, &root, &child, &ptrx, &ptry, &winx, &winy, (unsigned int*)&mask);
     Monitor* mon = Monitors;
     for (; mon; mon = mon->next)
     {
@@ -163,6 +203,34 @@ static Monitor* pickmon(void)
     return mon;
 }
 
+static Column* pickcol(Column* cols, int relx)
+{
+    Column* col = cols;
+    /* find first empty column, and fill that first */
+    for (; col && col->clients; col = col->next);
+    /* otherwise, return the current column */
+    if (!col)
+    {
+        puts("searching for active col");
+        int left = 0, right = 0;
+        for (col = cols; col; col = col->next)
+        {
+            left = right, right += col->width;
+            printf("%d <= %d < %d\n", left, relx, right);
+            if (left <= relx && relx < right)
+            {
+                break; /* we found the column holding the mouse */
+            }
+        }
+    }
+    else
+    {
+        puts("empty col");
+    }
+    assert(col);
+    return col;
+}
+
 static Workspace* pickws(Monitor* mon, int wsid)
 {
     Workspace* wspace = mon->wspaces;
@@ -179,15 +247,19 @@ static Workspace* pickws(Monitor* mon, int wsid)
 
 static Client* delclient(Client* list, Client* dead)
 {
-    if (list == dead)
+    if (!list)
     {
-        list = list->next;
+        return NULL;
+    }
+    else if (list == dead)
+    {
+        return list->next;
     }
     else
     {
         list->next = delclient(list->next, dead);
+        return list;
     }
-    return list;
 }
 
 static void client_visibility(Workspace* wspace, int show)
@@ -198,3 +270,16 @@ static void client_visibility(Workspace* wspace, int show)
     }
     XSync(X.disp, False);
 }
+
+static Client* client_find(Client* clients, Window win)
+{
+    Client* client = clients;
+    for (; client; client = client->next)
+    {
+        if (client->frame == win || client->win == win)
+        {
+            break;
+        }
+    }
+    return client;
+}