layout/mouse: Add grid layout and mwfact resize with mouse.

This commit is contained in:
Martin Duquesnoy
2008-11-04 14:41:24 +01:00
parent dbae20cf0f
commit 5c54de2481
8 changed files with 123 additions and 15 deletions

View File

@@ -208,7 +208,6 @@ client_map(Client *c)
XMapWindow(dpy, c->tbar->win);
bar_refresh(c->tbar);
}
XMapWindow(dpy, c->win);
return;
@@ -241,7 +240,6 @@ client_manage(Window w, XWindowAttributes *wa)
grabbuttons(c, False);
XSelectInput(dpy, w, EnterWindowMask | FocusChangeMask
| PropertyChangeMask | StructureNotifyMask);
client_size_hints(c);
titlebar_update(c);
if((rettrans = XGetTransientForHint(dpy, w, &trans) == Success))
@@ -410,7 +408,7 @@ client_size_hints(Client *c)
void
client_raise(Client *c)
{
if(!c || c->tile || c->max)
if(!c || c->max || c->tile)
return;
if(conf.titlebar.exist)

View File

@@ -63,6 +63,7 @@ func_name_list_t layout_list[] =
{"tile_left", tile_left },
{"tile_top", tile_top },
{"tile_bottom", tile_bottom },
{"grid", grid},
{"max", maxlayout },
{"free", freelayout }
};

View File

@@ -280,24 +280,25 @@ maprequest(XEvent ev)
if(at.override_redirect)
return;
if(!client_get(ev.xmaprequest.window))
{
client_focus(NULL);
client_manage(ev.xmaprequest.window, &at);
}
return;
}
double ROUND(double x) { return (x > 0) ? x + 0.5 : x - 0.5; }
/* If the type is 0, this function will move, else,
* this will resize */
void
mouseaction(Client *c, int x, int y, int type)
{
int ocx, ocy;
int my = sgeo.y, mx = 0;
double fy, fx, mwf;
XRectangle geo;
XEvent ev;
if(c->max || c->tile || c->lmax)
if(c->max || (c->tile && !type) || c->lmax)
return;
ocx = c->geo.x;
@@ -305,15 +306,36 @@ mouseaction(Client *c, int x, int y, int type)
if(XGrabPointer(dpy, root, False, MouseMask, GrabModeAsync, GrabModeAsync,
None, cursor[((type) ?CurResize:CurMove)], CurrentTime) != GrabSuccess)
return;
if(type)
/* Warp pointer for resize */
if(type && !c->tile)
XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->geo.width, c->geo.height);
/* Warp pointer for mwfact resize */
if(type && c->tile)
{
if(tags[seltag].layout.func == tile)
mx = tags[seltag].mwfact * sgeo.width;
else if(tags[seltag].layout.func == tile_left)
mx = sgeo.width - (tags[seltag].mwfact * sgeo.width);
else if(tags[seltag].layout.func == tile_top)
{
mx = event.xmotion.x;
my = sgeo.height - (tags[seltag].mwfact * sgeo.height);
}
else if(tags[seltag].layout.func == tile_bottom)
{
mx = event.xmotion.x;
my = tags[seltag].mwfact * sgeo.height;
}
XWarpPointer(dpy, None, root, 0, 0, 0, 0, mx, my);
}
for(;;)
{
XMaskEvent(dpy, MouseMask | ExposureMask | SubstructureRedirectMask, &ev);
if(ev.type == ButtonRelease)
{
if(type)
if(type && !c->tile)
XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->geo.width, c->geo.height);
XUngrabPointer(dpy, CurrentTime);
updatebar();
@@ -323,13 +345,35 @@ mouseaction(Client *c, int x, int y, int type)
{
XSync(dpy, False);
/* Resize */
if(type)
if(type && !c->tile)
{
geo.x = c->geo.x; geo.y = c->geo.y;
geo.width = ((ev.xmotion.x - ocx < 1) ? 1 : ev.xmotion.x - ocx);
geo.height = ((ev.xmotion.y - ocy < 1) ? 1 : ev.xmotion.y - ocy);
client_moveresize(c, geo, True);
}
/* Set mwfact in tiled mode */
else if(type && c->tile)
{
fy = (ROUND( ((ev.xmotion.y * 50) / sgeo.height)) ) / 50;
fx = (ROUND( ((ev.xmotion.x * 50) / sgeo.width)) ) / 50;
if(tags[seltag].layout.func == tile)
mwf = fx;
else if(tags[seltag].layout.func == tile_left)
mwf = 1 - fx;
else if(tags[seltag].layout.func == tile_top)
mwf = 1 - fy;
else if(tags[seltag].layout.func == tile_bottom)
mwf = fy;
tags[seltag].mwfact =
(((0.01) > (mwf) ? (0.01) : (mwf) ) < 0.99)
? ((0.01) > (mwf) ? (0.01): (mwf))
: 0.99;
arrange();
}
/* Move */
else
{

View File

@@ -186,6 +186,62 @@ uicb_set_nmaster(uicb_t cmd)
return;
}
void
grid(void)
{
Client *c;
XRectangle cgeo = {sgeo.x, sgeo.y, 0, 0};
unsigned int i, n, cols, rows, cpcols = 0;
unsigned int border = conf.client.borderheight * 2;
for(n = 0, c = nexttiled(clients); c; c = nexttiled(c->next), ++n);
if(!n)
return;
for(rows = 0; rows <= n / 2; ++rows)
if(rows * rows >= n)
break;
cols = (rows && ((rows - 1) * rows) >= n)
? rows - 1
: rows;
for(i = 0, c = nexttiled(clients); c; c = nexttiled(c->next), ++i)
{
/* Set client property */
c->max = c->lmax = False;
c->tile = True;
c->ogeo.x = c->geo.x; c->ogeo.y = c->geo.y;
c->ogeo.width = c->geo.width; c->ogeo.height = c->geo.height;
++cpcols;
cgeo.width = (sgeo.width / cols) - border;
cgeo.height = (sgeo.height / rows) - border;
/* Last row's and last client remainder */
if(cpcols == rows || i + 1 == n)
cgeo.height = (sgeo.y + sgeo.height) - cgeo.y - border;
/* Last column's client remainder */
if(i >= rows * (cols - 1))
cgeo.width = sgeo.width - cgeo.x - border;
/* Resize */
client_moveresize(c, cgeo, False);
/* Set all the other size with current client info */
cgeo.y = c->geo.y + c->geo.height + border + conf.titlebar.height;
if(cpcols + 1 > rows)
{
cpcols = 0;
cgeo.x = c->geo.x + c->geo.width + border;
cgeo.y = sgeo.y;
}
}
return;
}
void
multi_tile(Position type)
{

View File

@@ -37,7 +37,7 @@
#define NBUTTON 8
#define MAXTAG 36
#define MAXLAYOUT 6
#define MAXLAYOUT 7
/* Typedef */
typedef const char* uicb_t;

View File

@@ -62,6 +62,12 @@ getcolor(char *color)
return xcolor.pixel;
}
double
round(double x)
{
return (x > 0) ? x + 0.5 : x - 0.5;
}
void
setwinstate(Window win, long state)
{

View File

@@ -57,8 +57,8 @@
#define ButtonMask (ButtonPressMask | ButtonReleaseMask | ButtonMotionMask)
#define MouseMask (ButtonMask | PointerMotionMask)
#define KeyMask (KeyPressMask | KeyReleaseMask)
#define ITOA(p ,n) sprintf(p, "%i", n)
#define debug(p) fprintf(stderr, "debug: %i\n", p)
#define ITOA(p ,n) sprintf(p, "%d", n)
#define debug(p) fprintf(stderr, "debug: %f\n", p)
#define PAD 8
/* bar.c */
@@ -124,6 +124,7 @@ void getevent(void);
void *emalloc(uint element, uint size);
void efree(void *ptr);
ulong getcolor(char *color);
double round(double x);
void setwinstate(Window win, long state);
long getwinstate(Window win);
void uicb_spawn(uicb_t);
@@ -149,6 +150,7 @@ void maxlayout(void);
Client *nexttiled(Client *c);
/* tile */
void grid(void);
void tile(void);
void tile_left(void);
void tile_top(void);