diff --git a/src/client.c b/src/client.c index 63d657d..f32313e 100644 --- a/src/client.c +++ b/src/client.c @@ -7,6 +7,7 @@ #include "client.h" #include "config.h" +#include "event.h" #include "util.h" #include "barwin.h" #include "ewmh.h" @@ -537,7 +538,7 @@ _fac_apply(struct client *c, enum position p, int fac) static inline void _fac_arrange_row(struct client *c, enum position p, int fac) { - struct geo g = c->geo; + struct geo g = c->tgeo; struct client *cc; /* Travel clients to search row parents and apply fac */ @@ -546,8 +547,8 @@ _fac_arrange_row(struct client *c, enum position p, int fac) _fac_apply(cc, p, fac); } -void -client_fac_resize(struct client *c, enum position p, int fac) +static void +_fac_resize(struct client *c, enum position p, int fac) { struct client *cc, *gc = client_next_with_pos(c, p); enum position rp = RPOS(p); @@ -587,10 +588,109 @@ client_fac_resize(struct client *c, enum position p, int fac) return; } +} - /* It's ok, resize */ - SLIST_FOREACH(gc, &c->tag->clients, tnext) - client_moveresize(gc, &gc->tgeo); +#define _REV_BORDER() \ + SLIST_FOREACH(gc, &c->tag->clients, tnext) \ + draw_reversed_rect(c->tag->frame, rgc, gc->tgeo); +void +client_fac_resize(struct client *c, enum position p, int fac) +{ + struct keybind *k; + struct client *gc; + bool b = true; + XEvent ev; + KeySym keysym; + GC rgc; + XGCValues xgc = + { + .function = GXinvert, + .subwindow_mode = IncludeInferiors, + .line_width = THEME_DEFAULT->client_border_width + }; + + /* Do it once before */ + _fac_resize(c, p, fac); + + /* TODO + if(option_simple_manual_resize) + returnl + */ + + XGrabKeyboard(W->dpy, W->root, True, GrabModeAsync, GrabModeAsync, CurrentTime); + + rgc = XCreateGC(W->dpy, c->tag->frame, GCFunction | GCSubwindowMode | GCLineWidth, &xgc); + + _REV_BORDER(); + + do + { + XMaskEvent(W->dpy, KeyPressMask, &ev); + + if(ev.type == KeyPress) + { + XKeyPressedEvent *ke = &ev.xkey; + keysym = XKeycodeToKeysym(W->dpy, (KeyCode)ke->keycode, 0); + + _REV_BORDER(); + + SLIST_FOREACH(k, &W->h.keybind, next) + if(k->keysym == keysym && KEYPRESS_MASK(k->mod) == KEYPRESS_MASK(ke->state) + && k->func) + { + if(k->func == uicb_client_resize_Right) + _fac_resize(c, Right, ATOI(k->cmd)); + else if(k->func == uicb_client_resize_Left) + _fac_resize(c, Left, ATOI(k->cmd)); + else if(k->func == uicb_client_resize_Top) + _fac_resize(c, Top, ATOI(k->cmd)); + else if(k->func == uicb_client_resize_Bottom) + _fac_resize(c, Bottom, ATOI(k->cmd)); + else + { + k->func(k->cmd); + keysym = XK_Escape; + } + } + + _REV_BORDER(); + + /* Gtfo of this loop */ + if(keysym == XK_Return) + break; + else if(keysym == XK_Escape) + { + b = false; + break; + } + + XSync(W->dpy, False); + } + + XNextEvent(W->dpy, &ev); + + } while(ev.type != KeyPress); + + _REV_BORDER(); + + /* Success, resize clients */ + if(b) + { + SLIST_FOREACH(gc, &c->tag->clients, tnext) + client_moveresize(gc, &gc->tgeo); + } + /* Aborted with escape, Set back original geos */ + else + { + SLIST_FOREACH(gc, &c->tag->clients, tnext) + { + gc->tgeo = gc->geo; + gc->flags &= ~CLIENT_DID_WINSIZE; + } + } + + XFreeGC(W->dpy, rgc); + XUngrabKeyboard(W->dpy, CurrentTime); } void diff --git a/src/draw.h b/src/draw.h index f4cb968..1ac5151 100644 --- a/src/draw.h +++ b/src/draw.h @@ -11,6 +11,7 @@ #include #include "wmfs.h" +#include "config.h" #define TEXTY(t, w) ((t->font.height - t->font.de) + ((w - t->font.height) >> 1)) #define PAD (8) @@ -29,6 +30,18 @@ draw_rect(Drawable d, struct geo g, Color bg) XFillRectangle(W->dpy, d, W->gc, g.x, g.y, g.w, g.h); } +/* + * For client use + */ +static inline void +draw_reversed_rect(Drawable dr, GC gc, struct geo g) +{ + int i = THEME_DEFAULT->client_border_width; + + XDrawRectangle(W->dpy, dr, gc, g.x + i, g.y + i, + g.w - (i << 1), g.h - (i << 1)); +} + static inline unsigned short draw_textw(struct theme *t, const char *str) { diff --git a/src/layout.c b/src/layout.c index 165320a..8676786 100644 --- a/src/layout.c +++ b/src/layout.c @@ -8,6 +8,93 @@ #include "client.h" #include "util.h" +static void +layout_save_set(struct tag *t) +{ + struct client *c; + struct layout_set *l; + struct geo_list *g; + int n = 0; + + l = xcalloc(1, sizeof(struct layout_set)); + SLIST_INIT(&l->geos); + + SLIST_FOREACH(c, &t->clients, tnext) + { + g = xcalloc(1, sizeof(struct geo_list)); + g->geo = c->geo; + SLIST_INSERT_HEAD(&l->geos, g, next); + ++n; + } + + l->n = n; + + SLIST_INSERT_HEAD(&t->sets, l, next); +} + +static void +layout_apply_set(struct tag *t, struct layout_set *l) +{ + struct geo_list *g; + struct client *c, cc; + + for(g = SLIST_FIRST(&l->geos), c = SLIST_FIRST(&t->clients); + c; + c = SLIST_NEXT(c, tnext), g = SLIST_NEXT(g, next)) + { + if(g) + { + if(!client_winsize(c, &g->geo, &c->wgeo)) + client_moveresize(c, &g->geo); + + } + /* + * Not enough geos in the set; + * then integrate remains of client + */ + else + layout_split_integrate(c, SLIST_FIRST(&t->clients)); + } + + /* + * Not enough clients for geos in set; + * arrange clients with not set geo. + */ + if(g) + { + cc.tag = t; + while(g) + { + cc.geo = g->geo; + layout_split_arrange_closed(&cc); + g = SLIST_NEXT(g, next); + } + } + + /* Re-insert set in historic */ + SLIST_INSERT_HEAD(&t->sets, l, next); +} + + +void +layout_free_set(struct tag *t) +{ + struct layout_set *l; + + while(!SLIST_EMPTY(&t->sets)) + { + l = SLIST_FIRST(&t->sets); + SLIST_REMOVE_HEAD(&t->sets, next); + + /* Set can be several times in list */ + if(l) + { + FREE_LIST(geo_list, l->geos); + free(l); + } + } +} + static struct geo layout_split(struct client *c, bool vertical) { diff --git a/src/layout.h b/src/layout.h index 0cdc7a7..2e6e833 100644 --- a/src/layout.h +++ b/src/layout.h @@ -29,6 +29,7 @@ /* Debug */ #define DGEO(G) printf(": %d %d %d %d\n", G.x, G.y, G.w, G.h) +void layout_free_set(struct tag *t); void layout_split_integrate(struct client *c, struct client *sc); void layout_split_arrange_closed(struct client *ghost); void uicb_layout_vmirror(Uicb cmd); diff --git a/src/tag.c b/src/tag.c index 842e83f..255e688 100644 --- a/src/tag.c +++ b/src/tag.c @@ -45,6 +45,7 @@ tag_new(struct screen *s, char *name) &at); SLIST_INIT(&t->clients); + SLIST_INIT(&t->sets); TAILQ_INSERT_TAIL(&s->tags, t, next); @@ -182,6 +183,8 @@ tag_remove(struct tag *t) XDestroyWindow(W->dpy, t->frame); + layout_free_set(t); + free(t); } diff --git a/src/wmfs.h b/src/wmfs.h index f3c1b29..c2e4a65 100644 --- a/src/wmfs.h +++ b/src/wmfs.h @@ -69,6 +69,12 @@ struct geo int x, y, w, h; }; +struct geo_list +{ + struct geo geo; + SLIST_ENTRY(geo_list) next; +}; + struct barwin { struct geo geo; @@ -124,6 +130,7 @@ struct tag Flags flags; Window frame; SLIST_HEAD(, client) clients; + SLIST_HEAD(, layout_set) sets; TAILQ_ENTRY(tag) next; }; @@ -142,7 +149,13 @@ struct client Window win; SLIST_ENTRY(client) next; /* Global list */ SLIST_ENTRY(client) tnext; /* struct tag list */ - SLIST_ENTRY(client) vnext; /* various list */ +}; + +struct layout_set +{ + int n; + SLIST_HEAD(, geo_list) geos; + SLIST_ENTRY(layout_set) next; }; struct keybind