Split: Add split.c

This commit is contained in:
Martin Duquesnoy 2011-05-16 22:19:40 +02:00
parent 911ac2f74a
commit 825620b25c
9 changed files with 279 additions and 256 deletions

View File

@ -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/

View File

@ -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;

View File

@ -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)
{

View File

@ -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 };

View File

@ -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
*/

215
src/split.c Normal file
View File

@ -0,0 +1,215 @@
/*
* split.c
* Copyright © 2011 Martin Duquesnoy <xorg62@gmail.com>
* 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;
}

View File

@ -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;

View File

@ -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 };

View File

@ -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);