From 4321dc3aa80627ed73c284b77bfed17fe09ae00b Mon Sep 17 00:00:00 2001 From: Martin Duquesnoy Date: Sat, 17 Sep 2011 18:14:03 +0200 Subject: [PATCH] Add client_resize_ function (New cfactor) --- wmfs2/src/client.c | 52 +++++++++++++++++++++++++++++----- wmfs2/src/client.h | 70 ++++++++++++++++++++++++++++++++++++++++++++++ wmfs2/src/config.h | 8 ++++++ wmfs2/src/layout.c | 48 +++++++++++++++++++++++++++++++ wmfs2/src/layout.h | 68 ++++++-------------------------------------- wmfs2/src/tag.c | 3 ++ wmfs2/src/wmfs.c | 2 +- wmfs2/src/wmfs.h | 2 +- wmfs2/wmfsrc2 | 11 ++++++++ 9 files changed, 195 insertions(+), 69 deletions(-) diff --git a/wmfs2/src/client.c b/wmfs2/src/client.c index a728190..7d0fc57 100644 --- a/wmfs2/src/client.c +++ b/wmfs2/src/client.c @@ -14,6 +14,19 @@ #define CLIENT_MOUSE_MOD Mod1Mask +#define CLIENT_RESIZE_DIR(d) \ +void uicb_client_resize_##d(Uicb cmd) \ +{ \ + if(W->client) \ + client_fac_resize(W->client, d, ATOI(cmd)); \ +} + +/* uicb_client_resize_dir() */ +CLIENT_RESIZE_DIR(Right) +CLIENT_RESIZE_DIR(Left) +CLIENT_RESIZE_DIR(Top) +CLIENT_RESIZE_DIR(Bottom) + /** Send a ConfigureRequest event to the struct client * \param c struct client pointer */ @@ -245,7 +258,7 @@ client_new(Window w, XWindowAttributes *wa) c->geo.y = wa->y; c->geo.w = wa->width; c->geo.h = wa->height; - c->cgeo = c->geo; + c->tgeo = c->geo; /* Set tag */ tag_client(W->screen->seltag, c); @@ -272,10 +285,7 @@ client_new(Window w, XWindowAttributes *wa) void client_moveresize(struct client *c, struct geo g) { - c->geo = c->cgeo = g; - - c->cgeo.w += THEME_DEFAULT->client_border_width << 1; - c->cgeo.h += THEME_DEFAULT->client_border_width << 1; + c->geo = g; XMoveResizeWindow(W->dpy, c->win, g.x, g.y, g.w, g.h); } @@ -292,6 +302,36 @@ client_maximize(struct client *c) client_moveresize(c, c->geo); } +void +client_fac_resize(struct client *c, Position p, int fac) +{ + struct client *gc = client_next_with_pos(c, p); + + if(!gc || gc->screen != c->screen) + return; + + /* Check futur size/pos */ + if(!client_fac_geo(c, p, fac) + || !client_fac_geo(gc, RPOS(p), -fac) + || !client_fac_check_row(c, p, fac) + || !client_fac_check_row(gc, RPOS(p), -fac)) + return; + + + /* Simple resize with only c & gc */ + if(GEO_CHECK2(c->geo, gc->geo, p)) + { + client_moveresize(c, c->tgeo); + client_moveresize(gc, gc->tgeo); + } + /* Resize with row parents */ + else + { + client_fac_arrange_row(c, p, fac); + client_fac_arrange_row(gc, RPOS(p), -fac); + } +} + void client_remove(struct client *c) { @@ -305,8 +345,6 @@ client_remove(struct client *c) XSetInputFocus(W->dpy, W->root, RevertToPointerRoot, CurrentTime); } - layout_split_arrange_closed(c); - /* Remove from global client list */ SLIST_REMOVE(&W->h.client, c, client, next); diff --git a/wmfs2/src/client.h b/wmfs2/src/client.h index 06df224..0e4ab5b 100644 --- a/wmfs2/src/client.h +++ b/wmfs2/src/client.h @@ -7,6 +7,7 @@ #define CLIENT_H #include "wmfs.h" +#include "layout.h" void client_configure(struct client *c); struct client *client_gb_win(Window w); @@ -17,7 +18,76 @@ void client_close(struct client *c); struct client *client_new(Window w, XWindowAttributes *wa); void client_moveresize(struct client *c, struct geo g); void client_maximize(struct client *c); +void client_fac_resize(struct client *c, Position p, int fac); void client_remove(struct client *c); void client_free(void); +void uicb_client_resize_Right(Uicb); +void uicb_client_resize_Left(Uicb); +void uicb_client_resize_Top(Uicb); +void uicb_client_resize_Bottom(Uicb); + +static inline bool +client_fac_geo(struct client *c, Position p, int fac) +{ + struct geo cg = c->geo; + + switch(p) + { + default: + case Right: + cg.w += fac; + break; + case Left: + cg.x -= fac; + cg.w += fac; + break; + case Top: + cg.y -= fac; + cg.h += fac; + break; + case Bottom: + cg.h += fac; + break; + } + + /* Check for incompatible geo */ + if(cg.w > c->screen->ugeo.w || cg.h > c->screen->ugeo.h + || cg.w < 1 || cg.h < 1) + return false; + + /* Set transformed geo in tmp geo */ + c->tgeo = cg; + + return true; +} + +static inline bool +client_fac_check_row(struct client *c, Position p, int fac) +{ + struct geo g = c->geo; + struct client *cc; + + /* Travel clients to search parents of row and check geos */ + SLIST_FOREACH(cc, &c->tag->clients, tnext) + if(GEO_PARENTROW(g, cc->geo, p) && !client_fac_geo(cc, p, fac)) + return false; + + return true; +} + +static inline void +client_fac_arrange_row(struct client *c, Position p, int fac) +{ + struct geo g = c->geo; + struct client *cc; + + /* Travel clients to search row parents and apply fac */ + SLIST_FOREACH(cc, &c->tag->clients, tnext) + if(GEO_PARENTROW(g, cc->geo, p)) + { + client_fac_geo(cc, p, fac); + client_moveresize(cc, cc->tgeo); + } +} #endif /* CLIENT_H */ diff --git a/wmfs2/src/config.h b/wmfs2/src/config.h index 7135cd0..019daa0 100644 --- a/wmfs2/src/config.h +++ b/wmfs2/src/config.h @@ -13,6 +13,7 @@ #include "wmfs.h" #include "util.h" #include "tag.h" +#include "client.h" #define THEME_DEFAULT (SLIST_FIRST(&W->h.theme)) @@ -28,6 +29,13 @@ static const struct { char *name; void (*func)(Uicb cmd); } uicb_list[] = { "tag", uicb_tag_set_with_name }, { "tag_next", uicb_tag_next }, { "tag_prev", uicb_tag_prev }, + + /* Client */ + { "client_resize_right", uicb_client_resize_Right }, + { "client_resize_left", uicb_client_resize_Left }, + { "client_resize_top", uicb_client_resize_Top }, + { "client_resize_bottom", uicb_client_resize_Bottom }, + { NULL, NULL } }; diff --git a/wmfs2/src/layout.c b/wmfs2/src/layout.c index 91ad0d8..8340c7c 100644 --- a/wmfs2/src/layout.c +++ b/wmfs2/src/layout.c @@ -40,6 +40,54 @@ layout_split(struct client *c, bool vertical) return geo; } +static inline void +layout_split_arrange_size(struct geo g, struct client *c, Position p) +{ + if(LDIR(p)) + { + c->geo.w += g.w + (THEME_DEFAULT->client_border_width << 1); + + if(p == Right) + c->geo.x = g.x; + } + else + { + c->geo.h += g.h + (THEME_DEFAULT->client_border_width << 1); + + if(p == Bottom) + c->geo.y = g.y; + } + + client_moveresize(c, c->geo); +} + +static inline bool +layout_split_check_row_dir(struct client *c, struct client *g, Position p) +{ + struct geo cgeo = c->geo; + struct client *cc; + int bord = THEME_DEFAULT->client_border_width; + int i = 0, s = 0, cs = (LDIR(p) ? g->geo.h : g->geo.w ); + + SLIST_FOREACH(cc, &c->tag->clients, tnext) + if(GEO_PARENTROW(cgeo, cc->geo, RPOS(p)) + && GEO_CHECK_ROW(cc->geo, g->geo, p)) + { + s += (LDIR(p) + ? cc->geo.h + bord + : cc->geo.w + bord) + (i > 1 ? bord : 0); + + if(s == cs) + return true; + if(s > cs) + return false; + + ++i; + } + + return false; +} + /* Use ghost client properties to fix holes in tile * .--. ~ ~ * /xx \ ~ ~ diff --git a/wmfs2/src/layout.h b/wmfs2/src/layout.h index 2305e6e..2e7d811 100644 --- a/wmfs2/src/layout.h +++ b/wmfs2/src/layout.h @@ -7,8 +7,6 @@ #define LAYOUT_H #include "wmfs.h" -#include "config.h" -#include "client.h" /* Check lateral direction (if p is Right or Left) */ #define LDIR(P) (P < Top) @@ -17,72 +15,22 @@ #define RPOS(P) (P & 1 ? P - 1 : P + 1) /* geo comparaison */ -#define GEO_CHECK2(g1, g2, p) (LDIR(p) ? (g1.h == g2.h) : (g1.w == g2.w)) -#define GEO_CHECK_ROW(g1, g2, p) \ - (LDIR(p) \ - ? (g1.y >= g2.y && (g1.y + g1.h) <= (g2.y + g2.h)) \ - : (g1.x >= g2.x && (g1.x + g1.w) <= (g2.x + g2.w))) -#define GEO_PARENTROW(g1, g2, p) \ +#define GEO_CHECK2(g1, g2, p) (LDIR(p) ? ((g1).h == (g2).h) : ((g1).w == (g2).w)) +#define GEO_CHECK_ROW(g1, g2, p) \ (LDIR(p) \ - ? (p == Left ? (g1.x == g2.x) : (g1.x + g1.w == g2.x + g2.w)) \ - : (p == Top ? (g1.y == g2.y) : (g1.y + g1.h == g2.y + g2.h))) + ? ((g1).y >= (g2).y && ((g1).y + (g1).h) <= ((g2).y + (g2).h)) \ + : ((g1).x >= (g2).x && ((g1).x + (g1).w) <= ((g2).x + (g2).w))) +#define GEO_PARENTROW(g1, g2, p) \ + (LDIR(p) \ + ? (p == Left ? ((g1).x == (g2).x) : ((g1).x + (g1).w == (g2).x + (g2).w)) \ + : (p == Top ? ((g1).y == (g2).y) : ((g1).y + (g1).h == (g2).y + (g2).h))) /* Debug */ #define DGEO(G) printf(": %d %d %d %d\n", G.x, G.y, G.w, G.h) - void layout_split_integrate(struct client *c, struct client *sc); void layout_split_arrange_closed(struct client *ghost); -static inline void -layout_split_arrange_size(struct geo g, struct client *c, Position p) -{ - if(LDIR(p)) - { - c->geo.w += g.w + (THEME_DEFAULT->client_border_width << 1); - - if(p == Right) - c->geo.x = g.x; - } - else - { - c->geo.h += g.h + (THEME_DEFAULT->client_border_width << 1); - - if(p == Bottom) - c->geo.y = g.y; - } - - client_moveresize(c, c->geo); -} - -static inline bool -layout_split_check_row_dir(struct client *c, struct client *g, Position p) -{ - struct geo cgeo = c->geo; - struct client *cc; - int bord = THEME_DEFAULT->client_border_width; - int i = 0, s = 0, cs = (LDIR(p) ? g->geo.h : g->geo.w ); - - - SLIST_FOREACH(cc, &c->tag->clients, tnext) - if(GEO_PARENTROW(cgeo, cc->geo, RPOS(p)) - && GEO_CHECK_ROW(cc->geo, g->geo, p)) - { - s += (LDIR(p) - ? cc->geo.h + bord - : cc->geo.w + bord) + (i > 1 ? bord : 0);; - - if(s == cs) - return true; - if(s > cs) - return false; - - ++i; - } - - return false; -} - #endif /* LAYOUT_H */ diff --git a/wmfs2/src/tag.c b/wmfs2/src/tag.c index 5235c08..8cd33b6 100644 --- a/wmfs2/src/tag.c +++ b/wmfs2/src/tag.c @@ -89,6 +89,8 @@ tag_client(struct tag *t, struct client *c) if(c->tag == t) return; + layout_split_arrange_closed(c); + SLIST_REMOVE(&c->tag->clients, c, client, tnext); /* TODO: Focus next client */ if(c->tag->sel == c) @@ -105,6 +107,7 @@ tag_client(struct tag *t, struct client *c) if(SLIST_EMPTY(&c->tag->clients)) WIN_STATE(c->tag->frame, Unmap); + return; } diff --git a/wmfs2/src/wmfs.c b/wmfs2/src/wmfs.c index 00f728f..7b1596a 100644 --- a/wmfs2/src/wmfs.c +++ b/wmfs2/src/wmfs.c @@ -151,7 +151,7 @@ wmfs_grab_keys(void) KeyCode c; struct keybind *k; - wmfs_numlockmask(); + /*wmfs_numlockmask();*/ XUngrabKey(W->dpy, AnyKey, AnyModifier, W->root); diff --git a/wmfs2/src/wmfs.h b/wmfs2/src/wmfs.h index 23a4123..6f808b1 100644 --- a/wmfs2/src/wmfs.h +++ b/wmfs2/src/wmfs.h @@ -104,7 +104,7 @@ struct client struct tag *tag; struct screen *screen; struct barwin *titlebar; - struct geo geo, cgeo; /* Complete geo: + border */ + struct geo geo, tgeo; char *title; Flags flags; Window win; diff --git a/wmfs2/wmfsrc2 b/wmfs2/wmfsrc2 index ea7d220..f2780c4 100644 --- a/wmfs2/wmfsrc2 +++ b/wmfs2/wmfsrc2 @@ -113,4 +113,15 @@ [key] mod = {"Super"} key = "a" func = "tag_prev" [/key] [key] mod = {"Super"} key = "z" func = "tag" cmd = "tag2" [/key] + # Resize selected tiled client with direction + [key] mod = {"Super"} key = "h" func = "client_resize_left" cmd = "20" [/key] + [key] mod = {"Super"} key = "l" func = "client_resize_right" cmd = "20" [/key] + [key] mod = {"Super"} key = "k" func = "client_resize_top" cmd = "20" [/key] + [key] mod = {"Super"} key = "j" func = "client_resize_bottom" cmd = "20" [/key] + [key] mod = {"Super", "Control"} key = "h" func = "client_resize_right" cmd = "-20" [/key] + [key] mod = {"Super", "Control"} key = "l" func = "client_resize_left" cmd = "-20" [/key] + [key] mod = {"Super", "Control"} key = "k" func = "client_resize_bottom" cmd = "-20" [/key] + [key] mod = {"Super", "Control"} key = "j" func = "client_resize_top" cmd = "-20" [/key] + + [/keys]