From 11edb78e84b95b05b8db476e7eaab047f8c53ef7 Mon Sep 17 00:00:00 2001 From: Martin Duquesnoy Date: Fri, 29 Apr 2011 14:03:42 +0200 Subject: [PATCH] Client/Layout: Improve client tile factor --- TODO | 29 +++++++++--- src/client.c | 121 ++++++++++++++++++++++++++++++++------------------ src/config.c | 2 +- src/layout.c | 39 +++++++++++----- src/structs.h | 7 +-- src/tag.c | 12 ++--- src/wmfs.h | 5 ++- 7 files changed, 147 insertions(+), 68 deletions(-) diff --git a/TODO b/TODO index 800e268..e17aed0 100644 --- a/TODO +++ b/TODO @@ -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 + diff --git a/src/client.c b/src/client.c index 8b7a650..e1b9c89 100644 --- a/src/client.c +++ b/src/client.c @@ -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); diff --git a/src/config.c b/src/config.c index 42ec3ce..87107cb 100644 --- a/src/config.c +++ b/src/config.c @@ -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 }; diff --git a/src/layout.c b/src/layout.c index a16776c..081362e 100644 --- a/src/layout.c +++ b/src/layout.c @@ -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; diff --git a/src/structs.h b/src/structs.h index 7cf496a..0fdd349 100644 --- a/src/structs.h +++ b/src/structs.h @@ -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; diff --git a/src/tag.c b/src/tag.c index ba35bfb..edab536 100644 --- a/src/tag.c +++ b/src/tag.c @@ -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); diff --git a/src/wmfs.h b/src/wmfs.h index 4479263..55180bf 100644 --- a/src/wmfs.h +++ b/src/wmfs.h @@ -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);