diff --git a/src/client.c b/src/client.c index 0977721..235084f 100644 --- a/src/client.c +++ b/src/client.c @@ -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) diff --git a/src/config.c b/src/config.c index ddb24d1..73a64ac 100644 --- a/src/config.c +++ b/src/config.c @@ -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 } }; diff --git a/src/event.c b/src/event.c index 12b9fe1..e71ba24 100644 --- a/src/event.c +++ b/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 { diff --git a/src/layout.c b/src/layout.c index 19ec0d8..ff4be1c 100644 --- a/src/layout.c +++ b/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) { diff --git a/src/structs.h b/src/structs.h index 0522e33..5b2acf4 100644 --- a/src/structs.h +++ b/src/structs.h @@ -37,7 +37,7 @@ #define NBUTTON 8 #define MAXTAG 36 -#define MAXLAYOUT 6 +#define MAXLAYOUT 7 /* Typedef */ typedef const char* uicb_t; diff --git a/src/util.c b/src/util.c index 39fdc3e..becd762 100644 --- a/src/util.c +++ b/src/util.c @@ -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) { diff --git a/src/wmfs.h b/src/wmfs.h index caf4090..8c3e351 100644 --- a/src/wmfs.h +++ b/src/wmfs.h @@ -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); diff --git a/wmfsrc b/wmfsrc index c72e1b1..186a289 100644 --- a/wmfsrc +++ b/wmfsrc @@ -28,8 +28,9 @@ layouts layout { type = "tile_left" symbol = "TILE <" } layout { type = "tile_top" symbol = "TILE ^" } layout { type = "tile_bottom" symbol = "TILE v" } - layout { type = "max" symbol = "MAX" } - layout { type = "free" symbol = "FREE" } + layout { type = "grid" symbol = "GRID" } + layout { type = "max" symbol = "MAX" } + layout { type = "free" symbol = "FREE" } } tags