From c60696c6f80d29256fc75abadcbc2a5ae76a584c Mon Sep 17 00:00:00 2001 From: "Michael D. Lowis" Date: Mon, 16 Mar 2020 23:25:49 -0400 Subject: [PATCH] added layer logic to mons.c to ensure floating windows always appear above tiled --- anvil.c | 78 ++++++++++++++++++++++--------------- anvil.h | 11 +++--- client.c | 11 +++--- mons.c | 114 ++++++++++++++++++++++++++++++++++++++++++++----------- 4 files changed, 150 insertions(+), 64 deletions(-) diff --git a/anvil.c b/anvil.c index 3f9ebde..ce8a47f 100644 --- a/anvil.c +++ b/anvil.c @@ -29,28 +29,36 @@ static void warp_mouse(Client* c) static void xbtnpress(XEvent* e) { XButtonEvent* ev = &(e->xbutton); - Client* c = client_get(e->xbutton.window); X.start_x = ev->x_root; X.start_y = ev->y_root; + Location loc; + Client* c = client_get(e->xbutton.window, &loc); if (c && (ev->window == c->frame)) { -// client_btnclick(c, ev->button, ev->x, ev->y); - if (ev->button == Button1) + if (loc.column) { - client_raise(c); - if (ev->y > (TITLE_HEIGHT + BORDER_WIDTH)) - { - X.mode = M_RESIZE; - warp_mouse(c); - } - } - else if (ev->button == Button2) - { - client_close(c); + puts("tiled mouse click"); } - else if (ev->button == Button3) + else { - client_lower(c); +// client_btnclick(c, ev->button, ev->x, ev->y); + if (ev->button == Button1) + { + mons_raise(loc.monitor, c); + if (ev->y > (TITLE_HEIGHT + BORDER_WIDTH)) + { + X.mode = M_RESIZE; + warp_mouse(c); + } + } + else if (ev->button == Button2) + { + client_close(c); + } + else if (ev->button == Button3) + { + mons_lower(loc.monitor, c); + } } } } @@ -66,19 +74,27 @@ static void xbtnmotion(XEvent* e) /* make sure we get just the latest event */ XMotionEvent *ev = &e->xmotion; while (XCheckTypedWindowEvent(X.disp, ev->window, ev->type, e)); - Client* c = client_get(ev->window); + Location loc; + Client* c = client_get(ev->window, &loc); if (c && (ev->window == c->frame)) { -// client_btnmove(c, ev->button, ev->x, ev->y); - if (PRESSED(ev->state, Button1)) + if (loc.column) { - if (X.mode != M_RESIZE) - { - client_move(c, ev->x_root - X.start_x, ev->y_root - X.start_y); - } - else + puts("tiled mouse drag"); + } + else + { +// client_btnmove(c, ev->button, ev->x, ev->y); + if (PRESSED(ev->state, Button1)) { - client_resize(c, ev->x_root - X.start_x, ev->y_root - X.start_y); + if (X.mode != M_RESIZE) + { + client_move(c, ev->x_root - X.start_x, ev->y_root - X.start_y); + } + else + { + client_resize(c, ev->x_root - X.start_x, ev->y_root - X.start_y); + } } } } @@ -98,7 +114,7 @@ static void xconfigrequest(XEvent* e) wc.sibling = ev->above; wc.stack_mode = ev->detail; XConfigureWindow(X.disp, ev->window, ev->value_mask, &wc); - Client* c = client_get(ev->window); + Client* c = client_get(ev->window, NULL); if (c && c->win == ev->window) { c->w = wc.width; @@ -115,7 +131,7 @@ static void xmaprequest(XEvent* e) { XMapRequestEvent* ev = &(e->xmaprequest); XWindowAttributes attr; - if (!client_get(ev->window)) + if (!client_get(ev->window, NULL)) { if (XGetWindowAttributes(X.disp, ev->window, &attr) && !attr.override_redirect) { @@ -127,7 +143,7 @@ static void xmaprequest(XEvent* e) static void xunmapnotify(XEvent* e) { XUnmapEvent* ev = &(e->xunmap); - Client* c = client_get(ev->window); + Client* c = client_get(ev->window, NULL); if (c && c->win == ev->window) { XUnmapWindow(X.disp, c->frame); @@ -137,7 +153,7 @@ static void xunmapnotify(XEvent* e) static void xdestroynotify(XEvent* e) { XDestroyWindowEvent* ev = &(e->xdestroywindow); - Client* c = client_get(ev->window); + Client* c = client_get(ev->window, NULL); if (c) { if (Focused == c) @@ -156,7 +172,7 @@ static void xclientmsg(XEvent* e) static void xpropnotify(XEvent* e) { XPropertyEvent* ev = &(e->xproperty); - Client* c = client_get(ev->window); + Client* c = client_get(ev->window, NULL); if (c) { client_readprops(c); @@ -167,7 +183,7 @@ static void xpropnotify(XEvent* e) static void xenternotify(XEvent* e) { XCrossingEvent* ev = &(e->xcrossing); - Client* c = client_get(ev->window); + Client* c = client_get(ev->window, NULL); if (c) { client_focus(c); @@ -178,7 +194,7 @@ static void xexpose(XEvent* e) { if (e->xexpose.count == 0) { - Client* c = client_get(e->xexpose.window); + Client* c = client_get(e->xexpose.window, NULL); if (c) { client_draw(c); diff --git a/anvil.h b/anvil.h index cb787d0..b465e1c 100644 --- a/anvil.h +++ b/anvil.h @@ -57,9 +57,9 @@ typedef struct Client { } Client; enum { + TILE_MONOCLE, TILE_STACKED, - TILE_EXPAND, - TILE_MONOCOLE + TILE_EXPAND } TileMode; typedef struct Column { @@ -114,21 +114,22 @@ void keys_run(XKeyEvent* ev); /* mons.c */ extern Monitor* Monitors; void mons_init(void); +void mons_layer(Monitor* mon); void mons_addclient(Client* c); void mons_delclient(Client* c); int mons_find(Window win, Location* loc); void mons_place(Client* c); void mons_wspace(int i); void mons_towspace(Client* c, int i); +void mons_raise(Monitor* mon, Client* c); +void mons_lower(Monitor* mon, Client* c); /* client.c */ extern Client* Focused; void client_initall(void); Client* client_add(Window win, XWindowAttributes* attr); void client_draw(Client* c); -Client* client_get(Window w); -void client_raise(Client* c); -void client_lower(Client* c); +Client* client_get(Window w, Location* loc); void client_move(Client* c, int xdiff, int ydiff); void client_resize(Client* c, int xdiff, int ydiff); void client_close(Client* c); diff --git a/client.c b/client.c index f518b38..7019815 100644 --- a/client.c +++ b/client.c @@ -28,7 +28,6 @@ Client* client_add(Window win, XWindowAttributes* attr) c->y = attr->y; c->w = attr->width; c->h = attr->height; - mons_addclient(c); client_readprops(c); /* Reparent the window if applicable */ @@ -51,6 +50,7 @@ Client* client_add(Window win, XWindowAttributes* attr) /* Map the window and draw the frame */ XAddToSaveSet(X.disp, c->win); + mons_addclient(c); client_show(c, 1); client_draw(c); @@ -74,13 +74,14 @@ void client_draw(Client* c) } } -Client* client_get(Window w) +Client* client_get(Window w, Location* loc) { + Location local_loc; Client* c = NULL; - Location loc = {0}; - if (mons_find(w, &loc)) + loc = (loc ? loc : &local_loc); + if (mons_find(w, loc)) { - c = loc.client; + c = loc->client; } return c; } diff --git a/mons.c b/mons.c index 6a3c213..b842801 100644 --- a/mons.c +++ b/mons.c @@ -29,7 +29,7 @@ void mons_init(void) for (int i = 0; i < 10; i++) { Column* col = ecalloc(1, sizeof(Column)); - col->mode = TILE_STACKED, + col->mode = TILE_MONOCLE, col->width = m->w; Workspace* wspace = ecalloc(1, sizeof(Workspace)); wspace->columns = col; @@ -41,6 +41,58 @@ void mons_init(void) xfree(mons); } +static void coldims(Monitor* mon, Column* col, int *x, int *y, int *w, int *h) +{ + *x = mon->x, *y = mon->y, *w = col->width, *h = mon->h; + for (Column* c = mon->cspace->columns; c != col; *x += c->width, c = c->next); + *x += BORDER_WIDTH; + *y += BORDER_WIDTH + TITLE_HEIGHT; + *w -= 2*BORDER_WIDTH; + *h -= 2*BORDER_WIDTH + TITLE_HEIGHT; +} + +void mons_layer(Monitor* mon) +{ + /* lower all of the floating windows first */ + for (Client* client = mon->cspace->floating; client; client = client->next) + { + XLowerWindow(X.disp, client->win); + XLowerWindow(X.disp, client->frame); + } + /* now lower all of the tiled windows */ + for (Column* col = mon->cspace->columns; col; col = col->next) + { + for (Client* client = col->clients; client; client = client->next) + { + XLowerWindow(X.disp, client->win); + XLowerWindow(X.disp, client->frame); + } + } +} + +static void tile_monocle(Monitor* mon, Column* col, Client* c) +{ + coldims(mon, col, &(c->x), &(c->y), &(c->w), &(c->h)); + client_move(c, 0, 0); + client_resize(c, 0, 0); + c->next = col->clients; + col->clients = c; +} + +static void tile_expand(Monitor* mon, Column* col, Client* client) +{ + (void)mon, (void)col; + client->next = col->clients; + col->clients = client; +} + +static void tile_stacked(Monitor* mon, Column* col, Client* client) +{ + (void)mon, (void)col; + client->next = col->clients; + col->clients = client; +} + /* adds a new client to the most appropriate monitor */ void mons_addclient(Client* c) { @@ -48,7 +100,6 @@ void mons_addclient(Client* c) 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; @@ -57,34 +108,30 @@ void mons_addclient(Client* c) int ch = c->h + 2*BORDER_WIDTH + TITLE_HEIGHT; c->x = mon->midx - cw/2; c->y = mon->midy - ch/2; + client_move(c, 0, 0); + client_resize(c, 0, 0); } else { Column* col = pickcol(mon->cspace->columns, ptrx - mon->x); - /* - Client* c = find_max(col->clients); - if (c) + if (col->mode == TILE_MONOCLE) { - c->next = col->clients; - col->clients = c; + tile_monocle(mon, col, c); } - else + else if (col->mode == TILE_EXPAND) { - shrink the window; - fill the gap with the new window; + tile_expand(mon, col, c); + } + else if (col->mode == TILE_STACKED) + { + tile_stacked(mon, col, c); } - */ - - c->next = col->clients; - col->clients = c; - /* TODO: tile the window approriately */ } - assert(c != c->next); + mons_layer(mon); } void mons_delclient(Client* c) { - assert(c != c->next); Location loc = {0}; if (mons_find(c->win, &loc)) { @@ -203,6 +250,31 @@ void mons_towspace(Client* c, int wsid) } } +void mons_raise(Monitor* mon, Client* c) +{ + mon->cspace->floating = delclient(mon->cspace->floating, c); + c->next = mon->cspace->floating; + mon->cspace->floating = c; + mons_layer(mon); +} + +void mons_lower(Monitor* mon, Client* c) +{ + mon->cspace->floating = delclient(mon->cspace->floating, c); + c->next = NULL; + if (mon->cspace->floating) + { + Client* curr = mon->cspace->floating; + for (; curr && curr->next; curr = curr->next); + curr->next = c; + } + else + { + mon->cspace->floating = c; + } + mons_layer(mon); +} + static Monitor* pickmon(int ptrx, int ptry) { Monitor* mon = Monitors; @@ -225,22 +297,18 @@ static Column* pickcol(Column* cols, int relx) /* otherwise, return the current column */ if (!col) { - puts("searching for active 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); +// 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; } -- 2.52.0