Client/Layout: Improve client tile factor

This commit is contained in:
Martin Duquesnoy 2011-04-29 14:03:42 +02:00
parent 82eb33df85
commit 11edb78e84
7 changed files with 147 additions and 68 deletions

29
TODO
View File

@ -1,5 +1,24 @@
· Add Doxygen comment <-> OK
· Mouse bindings in the config file
· Can change client position in the tile grid
· Fix all the bug \o/
· XCB ?
,
dM
MMr
4MMML .
MMMMM. xf
. "M6MMM .MM-
Mh.. +MM5MMM .MMMM
.MMM. .MMMMML. MMMMMh
)MMMh. MM5MMM MMMMMMM
3MMMMx. 'MMM3MMf xnMMMMMM"
'*MMMMM MMMMMM. nMMMMMMP"
*MMMMMx "MMM5M\ .MMMMMMM=
*MMMMMh "MMMMM" JMMMMMMP
MMMMMM GMMMM. dMMMMMM .
MMMMMM "MMMM .MMMMM( .nnMP"
.. *MMMMx MMM" dMMMM" .nnMMMMM*
"MMn... 'MMMMr 'MM MMM" .nMMMMMMM*"
"4MMMMnn.. *MMM MM MMP" .dMMMMMMM""
^MMMMMMMMx. *ML "M .M* .MMMMMM**"
*PMMMMMMhn. *x > M .MMMM**""
""**MMMMhx/.h/ .=*"
.3P"%....
nP" "*MMnx

View File

@ -523,9 +523,9 @@ client_urgent(Client *c, Bool u)
* \param y y value
* \return The client
*/
Client* get_client_with_pos(int x, int y)
Client* client_gb_pos(Client *c, int x, int y)
{
Client *c, *psel = sel;
Client *ret;
Window w;
int d, dx, dy, basex, basey;
@ -538,12 +538,12 @@ client_urgent(Client *c, Bool u)
XQueryPointer(dpy, ROOT, &w, &w, &dx, &dy, &d, &d, (uint *)&d);
XWarpPointer(dpy, None, ROOT, 0, 0, 0, 0, basex, basey);
if(psel)
client_focus(psel);
if((c = client_gb_frame(w)) || (c = client_gb_win(w)))
if(w == ROOT)
return c;
if((ret = client_gb_frame(w)) || (ret = client_gb_win(w)))
return ret;
return NULL;
}
@ -892,11 +892,12 @@ client_manage(Window w, XWindowAttributes *wa, Bool ar)
c->ogeo.y = c->geo.y = my;
c->ogeo.width = c->geo.width = wa->width;
c->ogeo.height = c->geo.height = wa->height;
c->free_geo = c->geo;
c->free_geo = c->pgeo = c->geo;
c->tag = seltag[c->screen];
c->focusontag = -1;
c->layer = (sel && sel->layer > 0) ? sel->layer : 1;
tags[c->screen][c->tag].cleanfact = True;
client_clean_tile_fact(c);
at.event_mask = PropertyChangeMask;
@ -1052,6 +1053,9 @@ client_moveresize(Client *c, XRectangle geo, Bool r)
&& c->tag != MAXTAG + 1)
c->tag = seltag[c->screen];
if(c->flags & TileFlag)
c->geo = client_get_geo_factor(c->pgeo, c->tilefact);
frame_moveresize(c, c->geo);
XMoveResizeWindow(dpy, c->win, BORDH, TBARH, c->geo.width, c->geo.height);
@ -1322,6 +1326,7 @@ client_unmanage(Client *c)
XUngrabServer(dpy);
ewmh_get_client_list();
tags[c->screen][c->tag].cleanfact = True;
if(c->tag == MAXTAG + 1)
{
@ -1689,6 +1694,51 @@ uicb_client_set_master(uicb_t cmd)
return;
}
/** Clean client tile factors
*\param c Client pointer
*/
void
client_clean_tile_fact(Client *c)
{
CHECK(c);
if(!tags[c->screen][c->tag].cleanfact)
return;
c->tilefact[Right] = c->tilefact[Left] = 0;
c->tilefact[Top] = c->tilefact[Bottom] = 0;
return;
}
/** Return new geo of client with factors applied
*\param c Client pointer
*\return geo
*/
XRectangle
client_get_geo_factor(XRectangle geo, int fact[4])
{
XRectangle cgeo = { 0, 0, 0, 0 };
cgeo = geo;
/* Right factor */
cgeo.width += fact[Right];
/* Left factor */
cgeo.x -= fact[Left];
cgeo.width += fact[Left];
/* Top factor */
cgeo.y -= fact[Top];
cgeo.height += fact[Top];
/* Bottom factor */
cgeo.height += fact[Bottom];
return cgeo;
}
/** Manual resizing of tiled clients
* \param c Client pointer
* \param p Direction of resizing
@ -1700,52 +1750,32 @@ client_tile_factor_set(Client *c, Position p, int fac)
Client *gc = NULL;
int x, y;
XRectangle cgeo, scgeo;
Position reversepos[4] = { Left, Right, Bottom, Top };
int cfact[4] = { 0 }, scfact[4] = { 0 };
char scanfac[4][3] =
{
{ 1, 0 }, { -1, 0 }, /* Right, Left */
{ 0, -1 }, { 0, 1 } /* Top, Bottom */
{ 1, 0 }, { -1, 0 }, /* Right, Left */
{ 0, -1 }, { 0, 1 } /* Top, Bottom */
};
if(!c || !(c->flags & TileFlag) || p > Bottom)
if(!c || p > Bottom)
return;
cgeo = c->geo;
/* Scan in right direction to next(p) physical client */
/* Start place of pointer for faster scanning */
x = c->geo.x + ((p == Right) ? c->geo.width : 0);
y = c->geo.y + ((p == Bottom) ? c->geo.height : 0);
for(; (gc = get_client_with_pos(x, y)) == c; x += scanfac[p][0], y += scanfac[p][1]);
if(!gc)
/* Scan in right direction to next(p) physical client */
for(; (gc = client_gb_pos(c, x, y)) == c; x += scanfac[p][0], y += scanfac[p][1]);
if(!gc || c->screen != gc->screen)
return;
scgeo = gc->geo;
cfact[p] += fac;
scfact[reversepos[p]] -= fac;
/* Modify client geometry */
switch(p)
{
default:
case Right:
scgeo.x += fac;
cgeo.width += fac;
scgeo.width -= fac;
break;
case Left:
cgeo.x -= fac;
cgeo.width += fac;
scgeo.width -= fac;
break;
case Top:
cgeo.y -= fac;
cgeo.height += fac;
scgeo.height -= fac;
break;
case Bottom:
scgeo.y += fac;
cgeo.height += fac;
scgeo.height -= fac;
break;
}
cgeo = client_get_geo_factor(c->geo, cfact);
scgeo = client_get_geo_factor(gc->geo, scfact);
/* Too big */
if(scgeo.width > (1 << 15) || scgeo.height > (1 << 15)
@ -1757,6 +1787,13 @@ client_tile_factor_set(Client *c, Position p, int fac)
|| cgeo.width < 1 || cgeo.height < 1)
return;
/* Check if move/resize is needed for same col/row clients */
/*for(sc = tiled_client(c->screen, clients); sc; tiled_client(c->screen, c->next))
if(sc->geo.*/
c->tilefact[p] += fac;
gc->tilefact[reversepos[p]] -= fac;
/* Magic moment */
client_moveresize(c, cgeo, tags[c->screen][c->tag].resizehint);
client_moveresize(gc, scgeo, tags[gc->screen][gc->tag].resizehint);

View File

@ -530,7 +530,7 @@ conf_tag_section(void)
fetch_opt_first(def_tag, "0.6", "mwfact").fnum,
fetch_opt_first(def_tag, "1", "nmaster").num,
False, fetch_opt_first(def_tag, "False", "resizehint").bool,
False, False, bar_pos, bar_pos,
False, False, False, bar_pos, bar_pos,
layout_name_to_struct(conf.layout, fetch_opt_first(def_tag, "title_right", "layout").str, conf.nlayout, layout_list),
0, NULL, 0, False };

View File

@ -54,7 +54,10 @@ arrange(int screen, Bool update_layout)
if(tags[screen][seltag[screen]].layout.func)
{
if(update_layout)
{
tags[screen][seltag[screen]].cleanfact = True;
tags[screen][seltag[screen]].layout.func(screen);
}
infobar_draw(screen);
}
@ -116,6 +119,7 @@ layoutswitch(Bool b)
}
ewmh_update_current_tag_prop();
tags[selscreen][seltag[selscreen]].cleanfact = True;
tags[selscreen][seltag[selscreen]].layout.func(selscreen);
infobar_draw(selscreen);
@ -151,7 +155,7 @@ uicb_layout_prev(uicb_t cmd)
* \param c Client pointer
* \return a client pointer
*/
static Client*
Client*
tiled_client(int screen, Client *c)
{
for(;c && ((c->flags & MaxFlag)
@ -229,6 +233,7 @@ uicb_set_nmaster(uicb_t cmd)
return;
tags[selscreen][seltag[selscreen]].nmaster += n;
tags[c->screen][c->tag].cleanfact = True;
tags[selscreen][seltag[selscreen]].layout.func(selscreen);
ewmh_update_current_tag_prop();
@ -270,6 +275,9 @@ grid(int screen, Bool horizontal)
c->flags &= ~(MaxFlag | LMaxFlag);
c->flags |= TileFlag;
++cpcols;
client_clean_tile_fact(c);
cgeo.width = (sg.width / cols) - (BORDH * 2);
cgeo.height = (sg.height / rows) - BORDH;
@ -282,19 +290,20 @@ grid(int screen, Bool horizontal)
cgeo.width = sg.width - (cgeo.x - (sg.x - (BORDH * 2)));
/* Resize */
client_moveresize(c, cgeo, tags[screen][seltag[screen]].resizehint);
client_moveresize(c, (c->pgeo = cgeo), tags[screen][seltag[screen]].resizehint);
/* Set all the other size with current client info */
cgeo.y = c->geo.y + c->geo.height + BORDH + TBARH;
cgeo.y = c->pgeo.y + c->pgeo.height + BORDH + TBARH;
if(cpcols + 1 > rows)
{
cpcols = 0;
cgeo.x = c->geo.x + c->geo.width + (BORDH * 2);
cgeo.x = c->pgeo.x + c->pgeo.width + (BORDH * 2);
cgeo.y = sg.y;
}
}
tags[screen][seltag[screen]].cleanfact = False;
ewmh_update_current_tag_prop();
return;
@ -355,6 +364,8 @@ multi_tile(int screen, Position type)
c->flags &= ~(MaxFlag | LMaxFlag);
c->flags |= TileFlag;
client_clean_tile_fact(c);
/* MASTER */
if(i < nmaster)
{
@ -415,15 +426,16 @@ multi_tile(int screen, Position type)
}
/* Magic instant */
client_moveresize(c, cgeo, tags[screen][seltag[screen]].resizehint);
client_moveresize(c, (c->pgeo = cgeo), tags[screen][seltag[screen]].resizehint);
/* Set the position of the next client */
if(type == Top || type == Bottom)
cgeo.x = c->geo.x + c->geo.width + (BORDH * 2);
cgeo.x = c->pgeo.x + c->pgeo.width + (BORDH * 2);
else
cgeo.y = c->geo.y + c->geo.height + BORDH + TBARH;
cgeo.y = c->pgeo.y + c->pgeo.height + BORDH + TBARH;
}
tags[screen][seltag[screen]].cleanfact = False;
ewmh_update_current_tag_prop();
return;
@ -444,7 +456,7 @@ mirror(int screen, Bool horizontal)
uint i, n, tilesize = 0, mwfact;
uint nmaster = tags[screen][seltag[screen]].nmaster;
int pa, imp;
Bool isp = 0;
Bool isp = False;
memset(nextg, 0, sizeof(nextg));
@ -510,6 +522,8 @@ mirror(int screen, Bool horizontal)
c->flags &= ~(MaxFlag | LMaxFlag);
c->flags |= TileFlag;
client_clean_tile_fact(c);
if(i < nmaster)
{
cgeo = mastergeo;
@ -571,10 +585,10 @@ mirror(int screen, Bool horizontal)
}
}
client_moveresize(c, cgeo, tags[screen][seltag[screen]].resizehint);
client_moveresize(c, (c->pgeo = cgeo), tags[screen][seltag[screen]].resizehint);
if(i >= nmaster)
nextg[!isp] = c->geo;
nextg[!isp] = c->pgeo;
/* Next y/x position */
if(i >= nmaster - 1)
@ -604,6 +618,7 @@ mirror(int screen, Bool horizontal)
}
tags[screen][seltag[screen]].cleanfact = False;
ewmh_update_current_tag_prop();
return;
@ -720,6 +735,7 @@ uicb_togglefree(uicb_t cmd)
client_update_attributes(sel);
tags[selscreen][seltag[selscreen]].cleanfact = True;
tags[selscreen][seltag[selscreen]].layout.func(selscreen);
return;
@ -752,6 +768,7 @@ uicb_togglemax(uicb_t cmd)
sel->geo = sel->ogeo;
client_moveresize(sel, sel->geo, True);
sel->flags &= ~MaxFlag;
tags[selscreen][seltag[selscreen]].cleanfact = True;
tags[selscreen][seltag[selscreen]].layout.func(selscreen);
}
@ -796,6 +813,7 @@ uicb_toggle_abovefc(uicb_t cmd)
break;
}
tags[selscreen][seltag[selscreen]].cleanfact = True;
tags[selscreen][seltag[selscreen]].layout.func(selscreen);
}
@ -846,6 +864,7 @@ layout_set_client_master(Client *c)
client_detach(c);
client_attach(c);
tags[selscreen][seltag[selscreen]].cleanfact = True;
tags[selscreen][seltag[selscreen]].layout.func(selscreen);
return;

View File

@ -188,16 +188,16 @@ struct Client
int focusontag;
/* Screen */
int screen;
/* Layer */
int layer;
/* Window attribute */
XRectangle geo;
XRectangle geo, pgeo;
XRectangle tmp_geo;
XRectangle frame_geo;
/* Old window attribute */
XRectangle ogeo;
/* Free window attribute */
XRectangle free_geo;
/* Tile size factors */
int tilefact[4];
/* For resizehint usage */
int basew, baseh, incw, inch;
int maxw, maxh, minw, minh;
@ -286,6 +286,7 @@ typedef struct
Bool resizehint;
Bool request_update;
Bool abovefc;
Bool cleanfact;
int barpos;
int prev_barpos;
Layout layout;

View File

@ -372,7 +372,7 @@ uicb_tag_stay_last(uicb_t cmd)
{
int i;
remove_old_last_tag(selscreen);
for(i = seltag[selscreen]; i <= conf.ntag[selscreen]; i++)
{
tag_swap(selscreen, seltag[selscreen], seltag[selscreen] + 1);
@ -603,9 +603,9 @@ tag_new(int s, char *name)
Tag t = { displayedName, NULL, 0, 0,
conf.default_tag.mwfact, conf.default_tag.nmaster,
False, conf.default_tag.resizehint, False, False,
conf.default_tag.barpos, conf.default_tag.barpos, conf.default_tag.layout,
0, NULL, 0, False };
False, conf.default_tag.resizehint, False, False, False,
conf.default_tag.barpos, conf.default_tag.barpos,
conf.default_tag.layout, 0, NULL, 0, False };
tags[s][conf.ntag[s]] = t;
@ -760,7 +760,7 @@ uicb_tag_toggle_expose(uicb_t cmd)
return;
}
}
tag_new(selscreen, conf.tag_expose_name);
for(i = 0; i < conf.nlayout; ++i)
@ -775,7 +775,7 @@ uicb_tag_toggle_expose(uicb_t cmd)
{
tags[selscreen][conf.ntag[selscreen]].tagad ^= TagFlag(i);
}
tags[selscreen][conf.ntag[selscreen]].request_update = True;
arrange(selscreen, True);

View File

@ -163,7 +163,7 @@ Client* client_gb_frame(Window w);
Client* client_gb_titlebar(Window w);
Client* client_gb_resize(Window w);
Client* client_gb_button(Window w, int *n);
Client* get_client_with_pos(int x, int y);
Client* client_gb_pos(Client *c, int x, int y);
/* }}} */
void client_get_name(Client *c);
void client_hide(Client *c);
@ -183,6 +183,8 @@ void client_unmanage(Client *c);
void client_unmap(Client *c);
void client_update_attributes(Client *c);
void client_urgent(Client *c, Bool u);
void client_clean_tile_fact(Client *c);
XRectangle client_get_geo_factor(XRectangle geo, int fact[4]);
void uicb_client_raise(uicb_t);
void uicb_client_next(uicb_t);
void uicb_client_prev(uicb_t);
@ -335,6 +337,7 @@ void systray_update(void);
/* layout.c */
void arrange(int screen, Bool update_layout);
Client *tiled_client(int screen, Client *c);
void freelayout(int screen);
void layoutswitch(Bool b);
void maxlayout(int screen);