From: Michael D. Lowis Date: Mon, 16 Mar 2020 20:45:53 +0000 (-0400) Subject: rework window handling logic to support floating and tiled window lists. No tiling... X-Git-Url: https://git.mdlowis.com/?a=commitdiff_plain;h=e96149ee24f86529cd7b2dea0a6908ff16e30087;p=proto%2Fanvil.git rework window handling logic to support floating and tiled window lists. No tiling algorithm yet but scaffolding is there to support it --- diff --git a/anvil.c b/anvil.c index 76b44d7..fe3da5b 100644 --- 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 f5a2b92..cb787d0 100644 --- 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 854d337..2191bdf 100644 --- a/mons.c +++ b/mons.c @@ -1,10 +1,12 @@ #include "anvil.h" #include -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; +}