]> git.mdlowis.com Git - projs/tide.git/commitdiff
detect dialog windows and float them instead of tile them
authorMichael D. Lowis <mike.lowis@gentex.com>
Fri, 16 Aug 2019 17:11:53 +0000 (13:11 -0400)
committerMichael D. Lowis <mike.lowis@gentex.com>
Fri, 16 Aug 2019 17:11:53 +0000 (13:11 -0400)
TODO.md
src/anvil.c

diff --git a/TODO.md b/TODO.md
index 14a70e93f6894b9c5cbcf18dbda2c0ea6fec4195..bc124a8e7fa78f907da54df195fbf22a904a3815 100644 (file)
--- a/TODO.md
+++ b/TODO.md
@@ -4,10 +4,9 @@
 
 ## STAGING
 
-* anvil: search floating list as well as tiled list for clients
-* anvil: support floating windows for dialogs
-* anvil: add column support
+* anvil: support moving floating windows
 * anvil: add support for multiple workspaces
+* anvil: add column support
 * anvil: add support for multiple monitors
 
 ## BACKLOG
index 6a57bed0de39017f2b119f671ebb3168ab535a41..f9364a51051cc7547ddbca9b584a06cae8ab79ee 100644 (file)
 #define BARHEIGHT(x) \
     ((x)->font->height + 3)
 
+#define TCLIENT(c) \
+    container_of(c, Client, tnode)
+
+#define MCLIENT(c) \
+    container_of(c, Client, mnode)
+
 enum {
     TOO_SMALL = (1 << 0),
     FLOATING = (1 << 1),
 };
 
+typedef struct Node {
+    struct Node* next;
+    struct Node* prev;
+} Node;
+
+typedef void* (*Reducer)(Node* node, void* accum);
+
+typedef void (*Iterator)(Node* node);
+
 typedef struct Client {
-    struct Client *next, *prev;
+    Node mnode, tnode;
     Window win;
     Window frame;
     char* name;
@@ -28,6 +43,11 @@ typedef struct Client {
     int flags, x, y, w, h;
 } Client;
 
+typedef struct {
+    Client* c;
+    size_t nclients, nexty, sh;
+} GrowState;
+
 typedef struct Column {
     struct Column *next;
     struct Client* clients;
@@ -35,8 +55,8 @@ typedef struct Column {
 } Column;
 
 XConf X = {0};
-Client* Clients = NULL;
-Client* Floating = NULL;
+Node* All_Clients = NULL;
+Node* Tiled_Clients = NULL;
 Cursor Move_Cursor;
 Cursor Main_Cursor;
 int StartY = 0;
@@ -75,23 +95,100 @@ int get_prop(XConf* x, Window w, Atom name, Atom* type, int* format, void** data
         x->display, w, name, 0, -1, False, AnyPropertyType, type, format, ndata, &nleft, (unsigned char**)data);
 }
 
+/* List Handling
+ *****************************************************************************/
+void list_add(Node** list, Node* parent, Node* node) {
+    if (!parent) {
+        node->next = *list;
+        if (*list) (*list)->prev = node;
+        *list = node;
+    } else {
+        node->next = parent->next;
+        node->prev = parent;
+        parent->next = node;
+        if (node->next) node->next->prev = node;
+    }
+}
+
+void list_del(Node** list, Node* node) {
+    if (node->prev) node->prev->next = node->next;
+    if (node->next) node->next->prev = node->prev;
+    if (*list == node) *list = node->next;
+}
+
+void* list_reduce(Node* list, Reducer rfn, void* accum) {
+    return (list ? list_reduce(list->next, rfn, rfn(list, accum)) : accum);
+}
+
+void list_each(Node* list, Iterator ifn) {
+    if (!list) return;
+    ifn(list);
+    list_each(list->next, ifn);
+}
+
+size_t list_count(Node* curr) {
+    size_t nclients = 0;
+    for (; curr; curr = curr->next, nclients++);
+    return nclients;
+}
+
 /* Client Handling
  *****************************************************************************/
+void client_reconfig(XConf* xs, Client* c);
+
+void* biggest(Node* node, void* accum) {
+    if (!accum || TCLIENT(node)->h > ((Client*)accum)->h)
+        accum = TCLIENT(node);
+    return accum;
+}
+
+void* find_win(Node* n, void* env) {
+    struct { Window w; Client* c; }* state = env;
+    if ((MCLIENT(n)->frame == state->w) || (MCLIENT(n)->win == state->w))
+        state->c = MCLIENT(n);
+    return env;
+}
+
+void* grow_client(Node* node, void* env) {
+    GrowState* state = env;
+    Client* curr = TCLIENT(node);
+    state->nclients--;
+    curr->y = state->nexty;
+    if (curr == state->c)
+        curr->h = state->sh - state->nexty - (state->nclients * BARHEIGHT(&X));
+    else
+        curr->h = BARHEIGHT(&X);
+    client_reconfig(&X, curr);
+    state->nexty += curr->h;
+    return state;
+}
+
 int client_flags(Client* c, int mask) {
     return (c->flags & mask);
 }
 
 void client_add(Client* parent, Client* c) {
-    c->next = parent->next;
-    c->prev = parent;
-    parent->next = c;
-    if (c->next) c->next->prev = c;
+    list_add(&All_Clients, NULL, &(c->mnode));
+    if (!client_flags(c, FLOATING))
+        list_add(&Tiled_Clients, (parent ? &(parent->tnode) : NULL), &(c->tnode));
 }
 
 void client_del(Client* c) {
-    if (c->prev) c->prev->next = c->next;
-    if (c->next) c->next->prev = c->prev;
-    if (Clients == c) Clients = c->next;
+    list_del(&All_Clients, &(c->mnode));
+    if (!client_flags(c, FLOATING))
+        list_del(&Tiled_Clients, &(c->tnode));
+}
+
+void client_redraw(XConf* x, Client* c) {
+    puts("redraw");
+    XftColor fgclr, bgclr;
+    if (!c->name) return;
+    xftcolor(x, &fgclr, -1);
+    xftcolor(x, &bgclr, BackgroundColor);
+    XftDrawRect(c->xft, &bgclr, 0, 0, c->w, BARHEIGHT(x));
+    XftDrawStringUtf8(c->xft, &fgclr, x->font, 0, x->font->ascent, (const FcChar8*)c->name, strlen(c->name));
+    XftColorFree(x->display, x->visual, x->colormap, &fgclr);
+    XftColorFree(x->display, x->visual, x->colormap, &bgclr);
 }
 
 void client_reconfig(XConf* xs, Client* c) {
@@ -107,12 +204,14 @@ void client_reconfig(XConf* xs, Client* c) {
             XMapWindow(xs->display, c->win);
         }
     }
+    client_redraw(xs, c);
     XSync(xs->display, False);
 }
 
 void client_config(XConf* xs, Client* c, int x, int y, int w, int h) {
     c->x = x, c->y = y, c->w = w, c->h = h;
     client_reconfig(xs, c);
+    client_redraw(xs, c);
 }
 
 void client_raise(XConf* x, Client* c) {
@@ -175,26 +274,19 @@ void client_create(XConf* x, Window win) {
         EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask);
 
     /* position the window and frame */
+    Client* parent = NULL;
     if (!client_flags(c, FLOATING)) {
-        Client* biggy = Clients;
-        for (Client* curr = Clients; curr; curr = curr->next)
-            if (curr->h > biggy->h) biggy = curr;
-        if (biggy) {
-            c->h = (biggy->h - (biggy->h / 2));
-            biggy->h /= 2;
-            c->y = biggy->y + biggy->h;
-            client_config(x, biggy, biggy->x, biggy->y, biggy->w, biggy->h);
-            client_add(biggy, c);
-        } else {
-            Clients = c;
+        parent = list_reduce(Tiled_Clients, biggest, NULL);
+        if (parent) {
+            c->h = (parent->h - (parent->h / 2));
+            parent->h /= 2;
+            c->y = parent->y + parent->h;
+            client_config(x, parent, parent->x, parent->y, parent->w, parent->h);
         }
-    } else {
-        if (Floating)
-            client_add(c, Floating);
-        else
-            Floating = c;
     }
+    client_add(parent, c);
     client_config(x, c, c->x, c->y, c->w, c->h);
+    client_redraw(x, c);
     client_raise(x, c);
 
     XSync(x->display, False);
@@ -213,58 +305,34 @@ void client_destroy(XConf* x, Client* c) {
 }
 
 Client* client_find(Window win) {
-    Client *c;
-    for (c = Clients; c; c = c->next)
-        if ((c->frame == win) || (c->win == win))
-            return c;
-//    for (c = Floating; c; c = c->next)
-//        if ((c->frame == win) || (c->win == win))
-//            return c;
-    return NULL;
-}
-
-void client_redraw(XConf* x, Client* c) {
-    puts("redraw");
-    XftColor fgclr, bgclr;
-    if (!c->name) return;
-    xftcolor(x, &fgclr, -1);
-    xftcolor(x, &bgclr, BackgroundColor);
-    XftDrawRect(c->xft, &bgclr, 0, 0, c->w, BARHEIGHT(x));
-    XftDrawStringUtf8(c->xft, &fgclr, x->font, 0, x->font->ascent, (const FcChar8*)c->name, strlen(c->name));
-    XftColorFree(x->display, x->visual, x->colormap, &fgclr);
-    XftColorFree(x->display, x->visual, x->colormap, &bgclr);
+    struct { Window w; Client* c; } state = { .w = win };
+    list_reduce(All_Clients, find_win, &state);
+    return state.c;
 }
 
 void client_resize(XConf* x, Client* c, int dir) {
-    if (!c->prev) return;
-    Client* prev = c->prev;
+    (void)x, (void)c, (void)dir;
+    if (!c->tnode.prev) return;
+    Client* prev = TCLIENT(c->tnode.prev);
     dir = (!abs(dir) ? -BARHEIGHT(x) : dir);
     int sh = HeightOfScreen(DefaultScreenOfDisplay(x->display));
     int miny = prev->y + BARHEIGHT(x);
-    int maxy = (c->next ? c->next->y : sh) - BARHEIGHT(x);
+    int maxy = (c->tnode.next ? TCLIENT(c->tnode.next)->y : sh) - BARHEIGHT(x);
     int newy = min(max(miny, (c->y + dir)), maxy);
     prev->h = newy - prev->y;
-    c->h = (c->next ? (c->next->y - newy) : (sh - newy));
+    c->h = (c->tnode.next ? (TCLIENT(c->tnode.next)->y - newy) : (sh - newy));
     c->y = newy;
     client_reconfig(x, prev);
     client_reconfig(x, c);
 }
 
 void client_grow(XConf* x, Client* c) {
-    Client* curr;
-    int nclients = 0, nexty = 0;
-    int sh = HeightOfScreen(DefaultScreenOfDisplay(x->display));
-    for (curr = Clients; curr; curr = curr->next, nclients++);
-    for (curr = Clients; curr; curr = curr->next) {
-        nclients--;
-        curr->y = nexty;
-        if (curr == c)
-            curr->h = sh - nexty - (nclients * BARHEIGHT(x));
-        else
-            curr->h = BARHEIGHT(x);
-        client_reconfig(x, curr);
-        nexty += curr->h;
-    }
+    GrowState state = {
+        .c = c,
+        .nclients  = list_count(Tiled_Clients),
+        .sh = HeightOfScreen(DefaultScreenOfDisplay(x->display))
+    };
+    list_reduce(Tiled_Clients, grow_client, &state);
 }
 
 void client_maximize(XConf* xs, Client* c) {
@@ -369,14 +437,14 @@ static void xdestroynotify(XConf* x, XEvent* e) {
     if (c) {
         if (!client_flags(c, FLOATING)) {
             int y = c->y, h = c->h;
-            if (c->prev) {
-                c->prev->h += h;
-                client_config(x, c->prev, c->prev->x, c->prev->y, c->prev->w, c->prev->h);
-                client_raise(x, c->prev);
-            } else if (c->next) {
-                c->next->y = y, c->next->h += h;
-                client_config(x, c->next, c->next->x, c->next->y, c->next->w, c->next->h);
-                client_raise(x, c->next);
+            Node* nsucc = (c->tnode.prev ? c->tnode.prev : c->tnode.next);
+            if (nsucc) {
+                Client* succ = TCLIENT(nsucc);
+                succ->h += h;
+                if (nsucc == c->tnode.next)
+                    succ->y = y;
+                client_config(x, succ, succ->x, succ->y, succ->w, succ->h);
+                client_raise(x, succ);
             }
         }
         client_destroy(x, c);