Add client_resize_<direction> function (New cfactor)
This commit is contained in:
parent
961e57f876
commit
4321dc3aa8
@ -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);
|
||||
|
||||
|
||||
@ -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 */
|
||||
|
||||
@ -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 }
|
||||
};
|
||||
|
||||
|
||||
@ -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 \ ~ ~
|
||||
|
||||
@ -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 */
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -151,7 +151,7 @@ wmfs_grab_keys(void)
|
||||
KeyCode c;
|
||||
struct keybind *k;
|
||||
|
||||
wmfs_numlockmask();
|
||||
/*wmfs_numlockmask();*/
|
||||
|
||||
XUngrabKey(W->dpy, AnyKey, AnyModifier, W->root);
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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]
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user