Layout Split: Add split layout.
This commit is contained in:
parent
7eb15d595f
commit
911ac2f74a
@ -32,14 +32,6 @@
|
||||
|
||||
#include "wmfs.h"
|
||||
|
||||
#define RPOS(x) (x % 2 ? x - 1 : x + 1)
|
||||
|
||||
char scanfac[4][2] =
|
||||
{
|
||||
{ 1, 0 }, { -1, 0 }, /* Right, Left */
|
||||
{ 0, -1 }, { 0, 1 } /* Top, Bottom */
|
||||
};
|
||||
|
||||
/** Clean client tile factors
|
||||
*\param c Client pointer
|
||||
*/
|
||||
@ -99,7 +91,7 @@ cfactor_geo(XRectangle geo, int fact[4], int *err)
|
||||
*\param ccg Second geo
|
||||
*\param p Direction of resizing
|
||||
*/
|
||||
static Bool
|
||||
Bool
|
||||
cfactor_parentrow(XRectangle cg, XRectangle ccg, Position p)
|
||||
{
|
||||
Bool ret;
|
||||
@ -179,7 +171,7 @@ cfactor_arrange_two(Client *c1, Client *c2, Position p, int fac)
|
||||
*\param p Direction of resizing
|
||||
*\returm 1/0
|
||||
*/
|
||||
static Bool
|
||||
Bool
|
||||
cfactor_check_2pc(XRectangle g1, XRectangle g2, Position p)
|
||||
{
|
||||
if(p < Top)
|
||||
@ -244,19 +236,12 @@ void
|
||||
cfactor_set(Client *c, Position p, int fac)
|
||||
{
|
||||
Client *gc = NULL;
|
||||
int x, y;
|
||||
|
||||
if(!c || !(c->flags & TileFlag) || p > Bottom)
|
||||
return;
|
||||
|
||||
/* 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);
|
||||
y += ((p < Top) ? c->geo.height / 2 : 0);
|
||||
x += ((p > Left) ? c->geo.width / 2 : 0);
|
||||
|
||||
/* 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]);
|
||||
/* Get next client with direction of resize */
|
||||
gc = client_get_next_with_direction(c, p);
|
||||
|
||||
if(!gc || c->screen != gc->screen)
|
||||
return;
|
||||
|
||||
75
src/client.c
75
src/client.c
@ -132,46 +132,34 @@ client_get_prev(void)
|
||||
}
|
||||
|
||||
/** Get client left/right/top/bottom of selected client
|
||||
*\param bc Base client
|
||||
*\param pos Position (Left/Right/Top/Bottom
|
||||
*\return Client found
|
||||
*/
|
||||
static Client*
|
||||
client_get_next_with_direction(Position pos)
|
||||
Client*
|
||||
client_get_next_with_direction(Client *bc, Position pos)
|
||||
{
|
||||
Client *c = NULL;
|
||||
Client *ret = NULL;
|
||||
Client *c;
|
||||
int x, y;
|
||||
char scanfac[4][2] =
|
||||
{
|
||||
{ 1, 0 }, { -1, 0 }, /* Right, Left */
|
||||
{ 0, -1 }, { 0, 1 } /* Top, Bottom */
|
||||
};
|
||||
|
||||
if(!sel || ishide(sel, selscreen))
|
||||
if(!bc || ishide(bc, selscreen))
|
||||
return NULL;
|
||||
|
||||
for(c = clients; c; c = c->next)
|
||||
if(c != sel && !ishide(c, sel->screen))
|
||||
switch(pos)
|
||||
{
|
||||
default:
|
||||
case Right:
|
||||
if(c->geo.x > sel->geo.x
|
||||
&& (!ret || (ret && ret->geo.x > sel->geo.x && c->geo.x < ret->geo.x)))
|
||||
ret = c;
|
||||
break;
|
||||
case Left:
|
||||
if(c->geo.x < sel->geo.x
|
||||
&& (!ret || (ret && ret->geo.x < sel->geo.x && c->geo.x > ret->geo.x)))
|
||||
ret = c;
|
||||
break;
|
||||
case Top:
|
||||
if(c->geo.y < sel->geo.y
|
||||
&& (!ret || (ret && ret->geo.y < sel->geo.y && c->geo.y > ret->geo.y)))
|
||||
ret = c;
|
||||
break;
|
||||
case Bottom:
|
||||
if(c->geo.y > sel->geo.y
|
||||
&& (!ret || (ret && ret->geo.y > sel->geo.y && c->geo.y < ret->geo.y)))
|
||||
ret = c;
|
||||
break;
|
||||
}
|
||||
/* Start place of pointer for faster scanning */
|
||||
x = bc->geo.x + ((pos == Right) ? bc->geo.width : 0);
|
||||
y = bc->geo.y + ((pos == Bottom) ? bc->geo.height : 0);
|
||||
y += ((pos < Top) ? bc->geo.height / 2 : 0);
|
||||
x += ((pos > Left) ? bc->geo.width / 2 : 0);
|
||||
|
||||
return ret;
|
||||
/* Scan in right direction to next(p) physical client */
|
||||
for(; (c = client_gb_pos(bc, x, y)) == bc; x += scanfac[pos][0], y += scanfac[pos][1]);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
/** Switch to the previous client
|
||||
@ -255,7 +243,7 @@ uicb_client_focus_right(uicb_t cmd)
|
||||
Client *c;
|
||||
(void)cmd;
|
||||
|
||||
if((c = client_get_next_with_direction(Right)))
|
||||
if((c = client_get_next_with_direction(sel, Right)))
|
||||
{
|
||||
client_focus(c);
|
||||
client_raise(c);
|
||||
@ -274,7 +262,7 @@ uicb_client_focus_left(uicb_t cmd)
|
||||
Client *c;
|
||||
(void)cmd;
|
||||
|
||||
if((c = client_get_next_with_direction(Left)))
|
||||
if((c = client_get_next_with_direction(sel, Left)))
|
||||
{
|
||||
client_focus(c);
|
||||
client_raise(c);
|
||||
@ -292,7 +280,7 @@ uicb_client_focus_top(uicb_t cmd)
|
||||
Client *c;
|
||||
(void)cmd;
|
||||
|
||||
if((c = client_get_next_with_direction(Top)))
|
||||
if((c = client_get_next_with_direction(sel, Top)))
|
||||
{
|
||||
client_focus(c);
|
||||
client_raise(c);
|
||||
@ -310,7 +298,7 @@ uicb_client_focus_bottom(uicb_t cmd)
|
||||
Client *c;
|
||||
(void)cmd;
|
||||
|
||||
if((c = client_get_next_with_direction(Bottom)))
|
||||
if((c = client_get_next_with_direction(sel, Bottom)))
|
||||
{
|
||||
client_focus(c);
|
||||
client_raise(c);
|
||||
@ -1021,7 +1009,7 @@ void
|
||||
client_moveresize(Client *c, XRectangle geo, Bool r)
|
||||
{
|
||||
int os, e;
|
||||
int rhx = 0, rhy = 0;
|
||||
int rhx = 0;
|
||||
|
||||
if(!c)
|
||||
return;
|
||||
@ -1056,8 +1044,7 @@ client_moveresize(Client *c, XRectangle geo, Bool r)
|
||||
|
||||
/* To balance position of window in frame */
|
||||
rhx = ((c->wrgeo.width) - geo.width) / 2;
|
||||
rhy = ((c->wrgeo.height) - geo.height) / 2;
|
||||
}
|
||||
}
|
||||
|
||||
c->geo = geo;
|
||||
|
||||
@ -1073,7 +1060,7 @@ client_moveresize(Client *c, XRectangle geo, Bool r)
|
||||
|
||||
frame_moveresize(c, c->wrgeo);
|
||||
|
||||
XMoveResizeWindow(dpy, c->win, BORDH + rhx, TBARH + rhy, c->geo.width, c->geo.height);
|
||||
XMoveResizeWindow(dpy, c->win, BORDH + rhx, TBARH, c->geo.width, c->geo.height);
|
||||
|
||||
client_update_attributes(c);
|
||||
client_configure(c);
|
||||
@ -1093,7 +1080,7 @@ client_maximize(Client *c)
|
||||
c->screen = screen_get_with_geo(c->geo.x, c->geo.y);
|
||||
|
||||
c->geo.x = sgeo[c->screen].x;
|
||||
c->geo.y = sgeo[c->screen].y;
|
||||
c->geo.y = sgeo[c->screen].y ;
|
||||
c->geo.width = sgeo[c->screen].width - BORDH * 2;
|
||||
c->geo.height = sgeo[c->screen].height - BORDH;
|
||||
|
||||
@ -1213,8 +1200,8 @@ client_swap(Client *c1, Client *c2)
|
||||
client_size_hints(c2);
|
||||
|
||||
/* Resize the windows */
|
||||
client_moveresize(c1, c1->geo, False);
|
||||
client_moveresize(c2, c2->geo, False);
|
||||
client_moveresize(c1, c1->geo, tags[c1->screen][c1->tag].resizehint);
|
||||
client_moveresize(c2, c2->geo, tags[c2->screen][c2->tag].resizehint);
|
||||
|
||||
/* Get the new client name */
|
||||
client_get_name(c1);
|
||||
@ -1339,7 +1326,7 @@ client_unmanage(Client *c)
|
||||
ewmh_get_client_list();
|
||||
|
||||
if(c->flags & TileFlag)
|
||||
tags[c->screen][c->tag].cleanfact = True;
|
||||
tags[c->screen][c->tag].layout.ghost = *c;
|
||||
|
||||
if(c->tag == MAXTAG + 1)
|
||||
{
|
||||
|
||||
@ -52,6 +52,7 @@ const func_name_list_t layout_list[] =
|
||||
{"maxlayout", maxlayout },
|
||||
{"freelayout", freelayout },
|
||||
{"free", freelayout },
|
||||
{"split", split },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
|
||||
133
src/layout.c
133
src/layout.c
@ -238,6 +238,46 @@ uicb_set_nmaster(uicb_t cmd)
|
||||
return;
|
||||
}
|
||||
|
||||
/** Split layout function
|
||||
*/
|
||||
void
|
||||
split(int screen)
|
||||
{
|
||||
Client *c, *last;
|
||||
unsigned int n, on;
|
||||
|
||||
on = tags[screen][seltag[screen]].nclients;
|
||||
|
||||
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)))
|
||||
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);
|
||||
|
||||
last->flags &= ~(MaxFlag | LMaxFlag);
|
||||
last->flags |= TileFlag;
|
||||
}
|
||||
|
||||
ewmh_update_current_tag_prop();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/** Grid layout function
|
||||
*/
|
||||
static void
|
||||
@ -249,7 +289,7 @@ grid(int screen, Bool horizontal)
|
||||
unsigned int i, n, temp, cols, rows, cpcols = 0;
|
||||
|
||||
for(n = 0, c = tiled_client(screen, clients); c; c = tiled_client(screen, c->next), ++n);
|
||||
CHECK(n);
|
||||
CHECK((tags[screen][seltag[screen]].nclients = n));
|
||||
|
||||
for(rows = 0; rows <= n / 2; ++rows)
|
||||
if(rows * rows >= n)
|
||||
@ -319,7 +359,7 @@ multi_tile(int screen, Position type)
|
||||
uint i, n, tilesize = 0, mwfact, nmaster = tags[screen][seltag[screen]].nmaster;
|
||||
|
||||
for(n = 0, c = tiled_client(screen, clients); c; c = tiled_client(screen, c->next), ++n);
|
||||
CHECK(n);
|
||||
CHECK((tags[screen][seltag[screen]].nclients = n));
|
||||
|
||||
/* FIX NMASTER */
|
||||
nmaster = (n < nmaster) ? n : nmaster;
|
||||
@ -458,7 +498,7 @@ mirror(int screen, Bool horizontal)
|
||||
memset(nextg, 0, sizeof(nextg));
|
||||
|
||||
for(n = 0, c = tiled_client(screen, clients); c; c = tiled_client(screen, c->next), ++n);
|
||||
CHECK(n);
|
||||
CHECK((tags[screen][seltag[screen]].nclients = n));
|
||||
|
||||
/* Fix nmaster */
|
||||
nmaster = (n < nmaster) ? n : nmaster;
|
||||
@ -875,7 +915,7 @@ layout_set_client_master(Client *c)
|
||||
*\param c Client pointer
|
||||
*\param p True = Vertical, False = Horizontal
|
||||
*/
|
||||
static void
|
||||
void
|
||||
layout_split_client(Client *c, Bool p)
|
||||
{
|
||||
XRectangle geo, sgeo;
|
||||
@ -940,6 +980,91 @@ layout_split_apply(Client *c)
|
||||
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)
|
||||
{
|
||||
|
||||
@ -37,7 +37,7 @@
|
||||
|
||||
#define NBUTTON 8
|
||||
#define MAXTAG 36
|
||||
#define NUM_OF_LAYOUT 10
|
||||
#define NUM_OF_LAYOUT 11
|
||||
#define HISTOLEN 128
|
||||
|
||||
/* Clients flags definition */
|
||||
@ -196,6 +196,8 @@ 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;
|
||||
@ -221,6 +223,8 @@ struct Client
|
||||
/* Struct in chains */
|
||||
Client *next;
|
||||
Client *prev;
|
||||
/* Split parents */
|
||||
Client *parent, *child;
|
||||
};
|
||||
|
||||
/* Keybind Structure */
|
||||
@ -257,8 +261,8 @@ typedef struct
|
||||
/* Layout Structure */
|
||||
typedef struct
|
||||
{
|
||||
XRectangle sgeo;
|
||||
int sfact[4];
|
||||
XRectangle sgeo; /* Last splitted geo */
|
||||
Client ghost;
|
||||
char *symbol;
|
||||
char *type;
|
||||
void (*func)(int screen);
|
||||
|
||||
@ -109,6 +109,7 @@
|
||||
#define CHECK(x) if(!(x)) return
|
||||
#define LEN(x) (sizeof(x) / sizeof((x)[0]))
|
||||
#define MAXCLIST (64)
|
||||
#define RPOS(x) (x % 2 ? x - 1 : x + 1)
|
||||
|
||||
/* barwin.c */
|
||||
BarWindow *barwin_create(Window parent,
|
||||
@ -155,6 +156,8 @@ void uicb_toggle_tagautohide(uicb_t);
|
||||
/* cfactor.c */
|
||||
void cfactor_clean(Client *c);
|
||||
XRectangle cfactor_geo(XRectangle geo, int fact[4], int *err);
|
||||
Bool cfactor_check_2pc(XRectangle g1, XRectangle g2, Position p);
|
||||
Bool cfactor_parentrow(XRectangle cg, XRectangle ccg, Position p);
|
||||
void cfactor_set(Client *c, Position p, int fac);
|
||||
void cfactor_multi_set(Client *c, int fac[4]);
|
||||
void uicb_client_resize_right(uicb_t cmd);
|
||||
@ -193,6 +196,7 @@ void client_unmanage(Client *c);
|
||||
void client_unmap(Client *c);
|
||||
void client_update_attributes(Client *c);
|
||||
void client_urgent(Client *c, Bool u);
|
||||
Client* client_get_next_with_direction(Client *bc, Position pos);
|
||||
void uicb_client_raise(uicb_t);
|
||||
void uicb_client_next(uicb_t);
|
||||
void uicb_client_prev(uicb_t);
|
||||
@ -345,6 +349,7 @@ Client *tiled_client(int screen, Client *c);
|
||||
void freelayout(int screen);
|
||||
void layoutswitch(Bool b);
|
||||
void maxlayout(int screen);
|
||||
void split(int screen);
|
||||
/* tile {{{ */
|
||||
void tile(int screen);
|
||||
void tile_left(int screen);
|
||||
@ -365,7 +370,9 @@ void uicb_set_layout(uicb_t);
|
||||
void uicb_toggle_resizehint(uicb_t);
|
||||
void uicb_toggle_abovefc(uicb_t cmd);
|
||||
void layout_set_client_master(Client *c);
|
||||
void layout_split_client(Client *c, Bool p);
|
||||
void layout_split_apply(Client *c);
|
||||
void layout_split_arrange_closed(int screen);
|
||||
void uicb_split_client_vertical(uicb_t);
|
||||
void uicb_split_client_horizontal(uicb_t);
|
||||
Bool uicb_checkmax(uicb_t);
|
||||
|
||||
1
wmfsrc
1
wmfsrc
@ -88,6 +88,7 @@
|
||||
[layout] type = "tile_grid_vertical" symbol = "GRID_V" [/layout]
|
||||
[layout] type = "mirror_vertical" symbol = "MIRROR_V" [/layout]
|
||||
[layout] type = "mirror_horizontal" symbol = "MIRROR_H" [/layout]
|
||||
[layout] type = "split" symbol = "$PLIT" [/layout]
|
||||
|
||||
# Other layouts.
|
||||
[layout] type = "max" symbol = "MAX" [/layout]
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user