layout/mouse: Add grid layout and mwfact resize with mouse.
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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 }
|
||||
};
|
||||
|
||||
58
src/event.c
58
src/event.c
@@ -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
|
||||
{
|
||||
|
||||
56
src/layout.c
56
src/layout.c
@@ -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)
|
||||
{
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
|
||||
#define NBUTTON 8
|
||||
#define MAXTAG 36
|
||||
#define MAXLAYOUT 6
|
||||
#define MAXLAYOUT 7
|
||||
|
||||
/* Typedef */
|
||||
typedef const char* uicb_t;
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user