diff --git a/Makefile b/Makefile index cfe22a2..e031113 100644 --- a/Makefile +++ b/Makefile @@ -16,63 +16,62 @@ # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. # -TOP= . -PROG= wmfs -SRCS= src/barwin.c \ - src/cfactor.c \ - src/client.c \ - src/config.c \ - src/draw.c \ - src/event.c \ - src/ewmh.c \ - src/frame.c \ - src/getinfo.c \ - src/infobar.c \ - src/init.c \ - src/launcher.c \ - src/layout.c \ - src/menu.c \ - src/mouse.c \ - src/parse_api.c \ - src/parse.c \ - src/screen.c \ - src/status.c \ - src/systray.c \ - src/tag.c \ - src/util.c \ - src/viwmfs.c \ - src/color.c \ - src/wmfs.c - +TOP= . +PROG= wmfs +SRCS= src/barwin.c \ + src/cfactor.c \ + src/client.c \ + src/config.c \ + src/draw.c \ + src/event.c \ + src/ewmh.c \ + src/frame.c \ + src/getinfo.c \ + src/infobar.c \ + src/init.c \ + src/launcher.c \ + src/layout.c \ + src/menu.c \ + src/mouse.c \ + src/parse_api.c \ + src/parse.c \ + src/screen.c \ + src/split.c \ + src/status.c \ + src/systray.c \ + src/tag.c \ + src/util.c \ + src/viwmfs.c \ + src/color.c \ + src/wmfs.c include ${TOP}/Makefile.config include ${TOP}/mk/build.prog.mk -CFLAGS+= -Wall +CFLAGS+= -Wall # Include dirs -CFLAGS+= ${X11_CFLAGS} -CFLAGS+= ${XFT_CFLAGS} -CFLAGS+= ${FREETYPE_CFLAGS} -CFLAGS+= ${PTHREADS_CFLAGS} -CFLAGS+= ${XINERAMA_CFLAGS} -CFLAGS+= ${XRANDR_CFLAGS} -CFLAGS+= ${IMLIB2_CFLAGS} +CFLAGS+= ${X11_CFLAGS} +CFLAGS+= ${XFT_CFLAGS} +CFLAGS+= ${FREETYPE_CFLAGS} +CFLAGS+= ${PTHREADS_CFLAGS} +CFLAGS+= ${XINERAMA_CFLAGS} +CFLAGS+= ${XRANDR_CFLAGS} +CFLAGS+= ${IMLIB2_CFLAGS} # XDG Dir and WMFS version -CFLAGS+= -DXDG_CONFIG_DIR=\"${XDG_CONFIG_DIR}\" -CFLAGS+= -DWMFS_VERSION=\"201104\" +CFLAGS+= -DXDG_CONFIG_DIR=\"${XDG_CONFIG_DIR}\" +CFLAGS+= -DWMFS_VERSION=\"201104\" # Libs dirs -LIBS+= ${X11_LIBS} -LIBS+= ${XFT_LIBS} -LIBS+= ${FREETYPE_LIBS} -LIBS+= ${PTHREADS_LIBS} -LIBS+= ${XINERAMA_LIBS} -LIBS+= ${XRANDR_LIBS} -LIBS+= ${IMLIB2_LIBS} +LIBS+= ${X11_LIBS} +LIBS+= ${XFT_LIBS} +LIBS+= ${FREETYPE_LIBS} +LIBS+= ${PTHREADS_LIBS} +LIBS+= ${XINERAMA_LIBS} +LIBS+= ${XRANDR_LIBS} +LIBS+= ${IMLIB2_LIBS} # Install man and wmfsrc -install: - ${INSTALL_DATA} wmfs.1 ${MANDIR}/man1 - ${INSTALL_DATA} wmfsrc ${XDG_CONFIG_DIR}/wmfs/ +install: ${INSTALL_DATA} wmfs.1 ${MANDIR}/man1 \ + ${INSTALL_DATA} wmfsrc ${XDG_CONFIG_DIR}/wmfs/ diff --git a/src/cfactor.c b/src/cfactor.c index 1fb00d1..43cd7f1 100644 --- a/src/cfactor.c +++ b/src/cfactor.c @@ -40,8 +40,7 @@ cfactor_clean(Client *c) { CHECK(c); - if(!tags[c->screen][c->tag].cleanfact - && !tags[c->screen][c->tag].split) + if(!tags[c->screen][c->tag].cleanfact) return; c->tilefact[Right] = c->tilefact[Left] = 0; diff --git a/src/client.c b/src/client.c index cda9d48..dff9f7c 100644 --- a/src/client.c +++ b/src/client.c @@ -926,13 +926,13 @@ client_manage(Window w, XWindowAttributes *wa, Bool ar) ewmh_manage_window_type(c); - if(ar && !tags[c->screen][c->tag].split) + if(ar) arrange(c->screen, True); - if(!conf.client.set_new_win_master && !tags[c->screen][c->tag].split) - layout_set_client_master(c); + split_client_integrate(c, sel); - layout_split_apply(c); + if(!conf.client.set_new_win_master) + layout_set_client_master(c); if(c->tag == (uint)seltag[selscreen]) client_focus(c); @@ -1326,7 +1326,7 @@ client_unmanage(Client *c) ewmh_get_client_list(); if(c->flags & TileFlag) - tags[c->screen][c->tag].layout.ghost = *c; + split_arrange_closed(*c); if(c->tag == MAXTAG + 1) { diff --git a/src/config.c b/src/config.c index 2a81182..8c95c7a 100644 --- a/src/config.c +++ b/src/config.c @@ -104,8 +104,8 @@ const func_name_list_t func_list[] = {"check_clist", uicb_checkclist }, {"toggle_tagautohide", uicb_toggle_tagautohide }, {"toggle_tag_expose", uicb_tag_toggle_expose}, - {"split_client_vertical", uicb_split_client_vertical }, - {"split_client_horizontal", uicb_split_client_horizontal }, + /*{"split_client_vertical", uicb_split_client_vertical }, + {"split_client_horizontal", uicb_split_client_horizontal }, */ {NULL, NULL} }; @@ -532,7 +532,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, False, False, bar_pos, bar_pos, + False, False, False, bar_pos, bar_pos, layout_name_to_struct(conf.layout, fetch_opt_first(def_tag, "tile_right", "layout").str, conf.nlayout, layout_list), 0, NULL, 0, False }; diff --git a/src/layout.c b/src/layout.c index ea4bef7..565b182 100644 --- a/src/layout.c +++ b/src/layout.c @@ -251,20 +251,9 @@ split(int screen) for(n = 0, c = tiled_client(screen, clients); c; c = tiled_client(screen, c->next), ++n); CHECK((tags[screen][seltag[screen]].nclients = n)); - if(!(last = tiled_client(screen, clients))) + if(!(last = tiled_client(screen, clients)) || on == n) return; - /* New client (After manage) */ - if(on && n > on) - { - layout_split_client(sel, (sel->frame_geo.height < sel->frame_geo.width)); - layout_split_apply(last); - } - /* Client in less (After unmanage) */ - else if(on && n < on) - layout_split_arrange_closed(screen); - - /* First or the only client is maximized */ if(n == 1) { client_maximize(last); @@ -911,184 +900,6 @@ layout_set_client_master(Client *c) return; } -/** Split client hor or vert to insert another client in the new area - *\param c Client pointer - *\param p True = Vertical, False = Horizontal -*/ -void -layout_split_client(Client *c, Bool p) -{ - XRectangle geo, sgeo; - - if(!c || !(c->flags & TileFlag) - || tags[c->screen][c->tag].split) - return; - - tags[c->screen][c->tag].split = True; - - cfactor_clean(c); - - /* Use geometry without resizehint applied on it */ - geo = sgeo = c->wrgeo; - - /* Vertical */ - if(p) - { - geo.width /= 2; - sgeo.x = FRAMEW(geo.x + geo.width); - sgeo.width = (sgeo.width / 2) - (BORDH * 2); - - /* Remainder */ - sgeo.width += (c->wrgeo.x + c->wrgeo.width) - (sgeo.x + sgeo.width); - } - /* Horizontal */ - else - { - geo.height = (geo.height / 2) - TBARH; - sgeo.y = FRAMEH(geo.y + geo.height); - sgeo.height = (sgeo.height / 2) - BORDH; - - /* Remainder */ - sgeo.height += (c->wrgeo.y + c->wrgeo.height) - (sgeo.y + sgeo.height); - } - - tags[c->screen][c->tag].layout.sgeo = sgeo; - - client_moveresize(c, (c->pgeo = geo), tags[c->screen][c->tag].resizehint); - - return; -} - -/** Apply new attributes to splitted client - *\param c Client pointer -*/ -void -layout_split_apply(Client *c) -{ - if(!c || !tags[c->screen][c->tag].split) - return; - - c->flags &= ~(MaxFlag | LMaxFlag); - c->flags |= TileFlag; - - cfactor_clean(c); - client_moveresize(c, (c->pgeo = tags[c->screen][c->tag].layout.sgeo), - tags[c->screen][c->tag].resizehint); - - tags[c->screen][c->tag].split = False; - - return; -} - -static void -_layout_split_arrange_size(XRectangle g, XRectangle *cg, Position p) -{ - if(p < Top) - cg->width += FRAMEW(g.width); - else - cg->height += FRAMEH(g.height); - - if(p == Right) - cg->x -= FRAMEW(g.width); - - if(p == Bottom) - cg->y -= FRAMEH(g.height); - - return; -} - -static Bool -_layout_split_check_row(XRectangle g1, XRectangle g2, Position p) -{ - if(p < Top) - return (g1.y >= g2.y && (g1.y + g1.height) <= (g2.y + g2.height)); - else - return (g1.x >= g2.x && (g1.x + g1.width) <= (g2.x + g2.width)); -} - -/* Arrange clients after a client close - *\param screen Screen -*/ -void -layout_split_arrange_closed(int screen) -{ - Position p; - Bool b = False; - XRectangle cgeo; - Client *c, *cc, ghost; - - /* Set GHOST client - * .--. ~ ~ - * /.. \ ~ ~ - * \ø _ (____ ~ - * __.| .--' ~ ~ - * '---\ '. ~ , ~ - * '. '-.___.-'/ ~ - * '-.__ _.' ~ - * ````` ~ - */ - ghost = tags[screen][seltag[screen]].layout.ghost; - - tags[screen][seltag[screen]].split = True; - - /* Search for individual parent for easy resize */ - for(p = Right; p < Bottom + 1; ++p) - if((c = client_get_next_with_direction(&ghost, p))) - if(cfactor_check_2pc(ghost.frame_geo, c->frame_geo, p)) - { - _layout_split_arrange_size(ghost.wrgeo, &c->wrgeo, p); - cfactor_clean(c); - client_moveresize(c, (c->pgeo = c->wrgeo), tags[screen][c->tag].resizehint); - tags[screen][seltag[screen]].split = False; - - return; - } - - /* Check row parent for full resize */ - for(p = Right; p < Bottom + 1 && !b; ++p) - if((c = client_get_next_with_direction(&ghost, p))) - for(cgeo = c->frame_geo, cc = tiled_client(c->screen, clients); - cc; cc = tiled_client(c->screen, cc->next)) - { - if(cfactor_parentrow(cgeo, cc->frame_geo, RPOS(p)) - && _layout_split_check_row(cc->frame_geo, ghost.frame_geo, p)) - { - _layout_split_arrange_size(ghost.wrgeo, &cc->wrgeo, p); - cfactor_clean(cc); - client_moveresize(cc, (cc->pgeo = cc->wrgeo), tags[screen][cc->tag].resizehint); - b = True; - } - } - - tags[screen][seltag[screen]].split = False; - - return; -} - -void -uicb_split_client_vertical(uicb_t cmd) -{ - (void)cmd; - - CHECK(sel); - - layout_split_client(sel, True); - - return; -} - -void -uicb_split_client_horizontal(uicb_t cmd) -{ - (void)cmd; - - CHECK(sel); - - layout_split_client(sel, False); - - return; -} - /** Check the selected client is max * \param cmd uicb_t type unused */ diff --git a/src/split.c b/src/split.c new file mode 100644 index 0000000..04263a8 --- /dev/null +++ b/src/split.c @@ -0,0 +1,215 @@ +/* +* split.c +* Copyright © 2011 Martin Duquesnoy +* All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are +* met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above +* copyright notice, this list of conditions and the following disclaimer +* in the documentation and/or other materials provided with the +* distribution. +* * Neither the name of the nor the names of its +* contributors may be used to endorse or promote products derived from +* this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "wmfs.h" + +static void +_split_arrange_size(XRectangle g, XRectangle *cg, Position p) +{ + if(p < Top) + cg->width += FRAMEW(g.width); + else + cg->height += FRAMEH(g.height); + + if(p == Right) + cg->x -= FRAMEW(g.width); + + if(p == Bottom) + cg->y -= FRAMEH(g.height); + + return; +} + +static Bool +_split_check_row(XRectangle g1, XRectangle g2, Position p) +{ + if(p < Top) + return (g1.y >= g2.y && (g1.y + g1.height) <= (g2.y + g2.height)); + else + return (g1.x >= g2.x && (g1.x + g1.width) <= (g2.x + g2.width)); +} + +/** Arrange clients after a client close + *\param ghost Ghost client + */ +void +split_arrange_closed(Client ghost) +{ + Position p; + Bool b = False; + XRectangle cgeo; + Client *c, *cc; + int screen = ghost.screen; + + /* Use ghost client to fix holes in tile + * .--. ~ ~ + * /.. \ ~ ~ + * \ø _ (____ ~ + * __.| .--' ~ ~ + * '---\ '. ~ , ~ + * '. '-.___.-'/ ~ + * '-.__ _.' ~ + * ````` ~ + */ + + if(tags[screen][seltag[screen]].layout.func != split) + return; + + /* Search for single parent for easy resize + * Example case: + * ___________ ___________ + * | | B | -> -> | | | + * | A |_____| -> Close -> | A | B | + * | | C | -> C -> | |v v v| + * |_____|_____| -> -> |_____|_____| + */ + for(p = Right; p < Bottom + 1; ++p) + if((c = client_get_next_with_direction(&ghost, p))) + if(cfactor_check_2pc(ghost.frame_geo, c->frame_geo, p)) + { + _split_arrange_size(ghost.wrgeo, &c->wrgeo, p); + cfactor_clean(c); + client_moveresize(c, (c->pgeo = c->wrgeo), tags[screen][c->tag].resizehint); + + return; + } + + /* Check row parents for full resize + * Example case: + * ___________ ___________ + * | | B | -> -> | << B | + * | A |_____| -> Close -> |___________| + * | | C | -> A -> | << C | + * |_____|_____| -> -> |___________| + */ + for(p = Right; p < Bottom + 1 && !b; ++p) + if((c = client_get_next_with_direction(&ghost, p))) + for(cgeo = c->frame_geo, cc = tiled_client(c->screen, clients); + cc; cc = tiled_client(c->screen, cc->next)) + { + if(cfactor_parentrow(cgeo, cc->frame_geo, RPOS(p)) + && _split_check_row(cc->frame_geo, ghost.frame_geo, p)) + { + _split_arrange_size(ghost.wrgeo, &cc->wrgeo, p); + cfactor_clean(cc); + client_moveresize(cc, (cc->pgeo = cc->wrgeo), tags[screen][cc->tag].resizehint); + b = True; + } + } + + return; +} + + +/** Split client hor or vert to insert another client in the new area + *\param c Client pointer + *\param p True = Vertical, False = Horizontal +*/ +XRectangle +split_client(Client *c, Bool p) +{ + XRectangle geo, sgeo; + + if(!c || !(c->flags & TileFlag) + || tags[c->screen][c->tag].layout.func != split) + return c->wrgeo; + + cfactor_clean(c); + + /* Use geometry without resizehint applied on it */ + geo = sgeo = c->wrgeo; + + /* Vertical */ + if(p) + { + geo.width /= 2; + sgeo.x = FRAMEW(geo.x + geo.width); + sgeo.width = (sgeo.width / 2) - (BORDH * 2); + + /* Remainder */ + sgeo.width += (c->wrgeo.x + c->wrgeo.width) - (sgeo.x + sgeo.width); + } + /* Horizontal */ + else + { + geo.height = (geo.height / 2) - TBARH; + sgeo.y = FRAMEH(geo.y + geo.height); + sgeo.height = (sgeo.height / 2) - BORDH; + + /* Remainder */ + sgeo.height += (c->wrgeo.y + c->wrgeo.height) - (sgeo.y + sgeo.height); + } + + client_moveresize(c, (c->pgeo = geo), tags[c->screen][c->tag].resizehint); + + return sgeo; +} + +/** Apply new attributes to splitted client + *\param c Client pointer + *\param geo New geo +*/ +void +split_client_fill(Client *c, XRectangle geo) +{ + if(!c || tags[c->screen][c->tag].layout.func != split) + return; + + c->flags &= ~(MaxFlag | LMaxFlag); + c->flags |= TileFlag; + + cfactor_clean(c); + client_moveresize(c, (c->pgeo = geo), tags[c->screen][c->tag].resizehint); + + return; +} + +/** Integrate client in tag + *\param c Client pointer (integrate) + *\param sc Splitted client pointer +*/ +void +split_client_integrate(Client *c, Client *sc) +{ + XRectangle g; + + if(tags[c->screen][c->tag].layout.func != split + || !sc || !c) + return; + + g = split_client(sc, (sc->frame_geo.height < sc->frame_geo.width)); + split_client_fill(c, g); + + return; +} + + diff --git a/src/structs.h b/src/structs.h index bb0a973..6bdc820 100644 --- a/src/structs.h +++ b/src/structs.h @@ -196,8 +196,6 @@ struct Client XRectangle free_geo; /* Free window attribute */ /* Tile size factors */ int tilefact[4]; - /* Split direction */ - Bool splitd; /* For resizehint usage */ int basew, baseh, incw, inch; int maxw, maxh, minw, minh; @@ -223,8 +221,6 @@ struct Client /* Struct in chains */ Client *next; Client *prev; - /* Split parents */ - Client *parent, *child; }; /* Keybind Structure */ @@ -261,8 +257,6 @@ typedef struct /* Layout Structure */ typedef struct { - XRectangle sgeo; /* Last splitted geo */ - Client ghost; char *symbol; char *type; void (*func)(int screen); @@ -285,7 +279,6 @@ typedef struct int nclients; float mwfact; int nmaster; - Bool split; Bool urgent; Bool resizehint; Bool request_update; diff --git a/src/tag.c b/src/tag.c index 7fb07c1..28bf1ea 100644 --- a/src/tag.c +++ b/src/tag.c @@ -605,7 +605,7 @@ tag_new(int s, char *name) Tag t = { displayedName, NULL, 0, conf.default_tag.mwfact, conf.default_tag.nmaster, - False, conf.default_tag.resizehint, False, False, False, 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 }; diff --git a/src/wmfs.h b/src/wmfs.h index b26a25b..dee4022 100644 --- a/src/wmfs.h +++ b/src/wmfs.h @@ -385,6 +385,12 @@ void init(void); /* getinfo.c */ void getinfo(char *info); +/* split.c */ +void split_arrange_closed(Client ghost); +XRectangle split_client(Client *c, Bool p); +void split_client_fill(Client *c, XRectangle geo); +void split_client_integrate(Client *c, Client *sc); + /* viwmfs.c */ void viwmfs(int argc, char **argv);