From f2f7d5c89dc4a3fb9504b7a8db0fff4faddd3dca Mon Sep 17 00:00:00 2001 From: "dcurtis@cs.uiowa.edu" Date: Tue, 13 Jan 2009 13:31:37 -0600 Subject: [PATCH] awful.layout.suit.vile: import Signed-off-by: Julien Danjou --- lib/awful/client.lua.in | 138 +++++++++++++++++++ lib/awful/layout/init.lua.in | 4 + lib/awful/layout/suit/init.lua.in | 1 + lib/awful/layout/suit/vile.lua.in | 177 +++++++++++++++++++++++++ lib/awful/mouse.lua.in | 100 ++++++++++++++ themes/default/layouts/vile.png | Bin 0 -> 174 bytes themes/default/layouts/vilebottom.png | Bin 0 -> 195 bytes themes/default/layouts/vilebottomw.png | Bin 0 -> 216 bytes themes/default/layouts/vileleft.png | Bin 0 -> 172 bytes themes/default/layouts/vileleftw.png | Bin 0 -> 170 bytes themes/default/layouts/viletop.png | Bin 0 -> 195 bytes themes/default/layouts/viletopw.png | Bin 0 -> 215 bytes themes/default/layouts/vilew.png | Bin 0 -> 168 bytes themes/default/theme.in | 4 + themes/sky/layouts/vile.png | Bin 0 -> 383 bytes themes/sky/layouts/vilebottom.png | Bin 0 -> 335 bytes themes/sky/layouts/vileleft.png | Bin 0 -> 367 bytes themes/sky/layouts/viletop.png | Bin 0 -> 340 bytes themes/sky/theme.in | 4 + 19 files changed, 428 insertions(+) create mode 100644 lib/awful/layout/suit/vile.lua.in create mode 100644 themes/default/layouts/vile.png create mode 100644 themes/default/layouts/vilebottom.png create mode 100644 themes/default/layouts/vilebottomw.png create mode 100644 themes/default/layouts/vileleft.png create mode 100644 themes/default/layouts/vileleftw.png create mode 100644 themes/default/layouts/viletop.png create mode 100644 themes/default/layouts/viletopw.png create mode 100644 themes/default/layouts/vilew.png create mode 100644 themes/sky/layouts/vile.png create mode 100644 themes/sky/layouts/vilebottom.png create mode 100644 themes/sky/layouts/vileleft.png create mode 100644 themes/sky/layouts/viletop.png diff --git a/lib/awful/client.lua.in b/lib/awful/client.lua.in index 65103a87..77cd7e62 100644 --- a/lib/awful/client.lua.in +++ b/lib/awful/client.lua.in @@ -593,6 +593,144 @@ function floating.delete(c) data.floating[c] = nil end +-- Normalize a set of numbers to 1 +-- @param set the set of numbers to normalize +-- @param num the number of numbers to normalize +local function normalize(set, num) + local num = num or #set + local total = 0 + if num then + for i = 1,num do + total = total + set[i] + end + for i = 1,num do + set[i] = set[i] / total + end + else + for i,v in ipairs(set) do + total = total + v + end + + for i,v in ipairs(set) do + set[i] = v / total + end + end +end + +--- Calculate a client's column number, index in that column, and +-- number of visible clients in this column. +-- @param c the client +-- @return col the column number +-- @return idx index of the client in the column +-- @return num the number of visible clients in the column +local function idx(c) + local c = c or capi.client.focus + if not c then return end + + local clients = tiled(c.screen) + local idx = nil + for k, cl in ipairs(clients) do + if cl == c then + idx = k + break + end + end + + local nmaster = tag.getnmaster(t) + if idx <= nmaster then + return {idx = idx, col=0, num=nmaster} + end + local nother = #clients - nmaster + idx = idx - nmaster + + -- rather than regenerate the column number we can calculate it + -- based on the how the tiling algorithm places clients we calculate + -- the column, we could easily use the for loop in the program but we can + -- calculate it. + local ncol = tag.getncol(t) + -- minimum number of clients per column + local percol = math.floor(nother / ncol) + -- number of columns with an extra client + local overcol = math.mod(nother, ncol) + -- number of columns filled with [percol] clients + local regcol = ncol - overcol + + local col = math.floor( (idx - 1) / percol) + 1 + if col > regcol then + -- col = math.floor( (idx - (percol*regcol) - 1) / (percol + 1) ) + regcol + 1 + -- simplified + col = math.floor( (idx + regcol + percol) / (percol+1) ) + -- calculate the index in the column + idx = idx - percol*regcol - (col - regcol - 1) * (percol+1) + percol = percol+1 + else + idx = idx - percol*(col-1) + end + + return {idx = idx, col=col, num=percol} +end + + +--- Set the window factor of a client +-- @param wfact the window factor value +-- @param c the client +function setwfact(wfact, c) + -- get the currently selected window + local c = c or capi.client.focus + if not c then return end + + local t = tag.selected(c.screen) + local w = idx(c) + + local cls = tiled(t.screen) + local nmaster = tag.getnmaster(t) + + -- n is the number of windows currently visible for which we have to be concerned with the properties + local data = tag.getproperty(t, "windowfact") or {} + local colfact = data[w.col] + + colfact[w.idx] = wfact + rest = 1-wfact + + -- calculate the current denominator + local total = 0 + for i = 1,w.num do + if i ~= w.idx then + total = total + colfact[i] + end + end + + -- normalize the windows + for i = 1,w.num do + if i ~= w.idx then + colfact[i] = (colfact[i] * rest) / total + end + end +end + +--- Increment a client's window factor +-- @param add amount to increase the client's window +-- @param c the client +function incwfact(add, c) + local c = c or capi.client.focus + if not c then return end + + local t = tag.selected(c.screen) + + local w = idx(c) + + local nmaster = tag.getnmaster(t) + local data = tag.getproperty(t, "windowfact") or {} + local colfact = data[w.col] + curr = colfact[w.idx] or 1 + colfact[w.idx] = curr + add + + -- keep our ratios normalized + normalize(colfact, w.num) + capi.hooks.arrange()(t.screen) +end + + -- Register standards hooks hooks.focus.register(focus.history.add) hooks.unmanage.register(focus.history.delete) diff --git a/lib/awful/layout/init.lua.in b/lib/awful/layout/init.lua.in index bf457638..c4b7fd9f 100644 --- a/lib/awful/layout/init.lua.in +++ b/lib/awful/layout/init.lua.in @@ -70,6 +70,10 @@ local layouts_name = [suit.tile.left] = "tileleft", [suit.tile.bottom] = "tilebottom", [suit.tile.top] = "tiletop", + [suit.vile] = "vile", + [suit.vile.left] = "vileleft", + [suit.vile.bottom] = "vilebottom", + [suit.vile.top] = "viletop", [suit.fair] = "fairv", [suit.fair.horizontal] = "fairh", [suit.max] = "max", diff --git a/lib/awful/layout/suit/init.lua.in b/lib/awful/layout/suit/init.lua.in index ae83edf4..8c57bf70 100644 --- a/lib/awful/layout/suit/init.lua.in +++ b/lib/awful/layout/suit/init.lua.in @@ -1,5 +1,6 @@ require("awful.layout.suit.max") require("awful.layout.suit.tile") +require("awful.layout.suit.vile") require("awful.layout.suit.fair") require("awful.layout.suit.floating") require("awful.layout.suit.magnifier") diff --git a/lib/awful/layout/suit/vile.lua.in b/lib/awful/layout/suit/vile.lua.in new file mode 100644 index 00000000..e3f1e5c2 --- /dev/null +++ b/lib/awful/layout/suit/vile.lua.in @@ -0,0 +1,177 @@ +--------------------------------------------------------------------------- +-- @author Donald Ephraim Curtis <dcurtis@cs.uiowa.edu> +-- @author Julien Danjou <julien@danjou.info> +-- @copyright 2009 Donald Ephraim Curtis +-- @copyright 2008 Julien Danjou +-- @release @AWESOME_VERSION@ +--------------------------------------------------------------------------- + +-- Grab environment we need +local setmetatable = setmetatable +local ipairs = ipairs +local math = math +local client = require("awful.client") +local tag = require("awful.tag") +local capi = +{ + screen = screen +} + +--- Tiled layouts module for awful +module("awful.layout.suit.vile") + +local function tile_group(cls, wa, orientation, fact, group) + -- get our orientation right + local height = "height" + local width = "width" + local x = "x" + local y = "y" + if orientation == "top" or orientation == "bottom" then + height = "width" + width = "height" + x = "y" + y = "x" + end + + -- make this more generic (not just width) + available = wa[width] - (group.coord - wa[x]) + + -- find our total values + local total_fact = 0 + local min_fact = 1 + local size = group.size + for c = group.first,group.last do + -- determine the width/height based on the size_hint + local i = c - group.first +1 + local size_hints = cls[c].size_hints + local size_hint = size_hints["min_"..width] or size_hints["base_"..width] or 0 + size_hint = size_hint + cls[c].border_width*2 + size = math.max(size_hint, size) + + -- calculate the height + if not fact[i] then + fact[i] = min_fact + else + min_fact = math.min(fact[i],min_fact) + end + total_fact = total_fact + fact[i] + end + size = math.min(size, available) + + local coord = wa[y] + local geom = {} + local used_size = 0 + local unused = wa[height] + for c = group.first,group.last do + local i = c - group.first +1 + geom[width] = size + geom[height] = math.floor(unused * fact[i] / total_fact) + geom[x] = group.coord + geom[y] = coord + geom = cls[c]:geometry(geom) + coord = coord + geom[height] + unused = unused - geom[height] + total_fact = total_fact - fact[i] + used_size = math.max(used_size, geom[width]) + end + + return used_size + +end + +local function vile(_, screen, orientation) + orientation = orientation or "right" + + -- this handles are different orientations + local height = "height" + local width = "width" + local x = "x" + local y = "y" + if orientation == "top" or orientation == "bottom" then + height = "width" + width = "height" + x = "y" + y = "x" + end + + local t = tag.selected(screen) + local cls = client.tiled(screen) + local nmaster = math.min(tag.getnmaster(t), #cls) + local nother = math.max(#cls - nmaster,0) + + local mwfact = tag.getmwfact(t) + local wa = capi.screen[screen].workarea + local ncol = tag.getncol(t) + + local data = tag.getproperty(t,"windowfact") + + if not data then + data = {} + tag.setproperty(t,"windowfact", data) + end + + -- + local coord = wa[x] + local place_master = true + if orientation == "left" or orientation == "top" then + -- if we are on the left or top we need to render the other windows first + place_master = false + end + + -- this was easier than writing functions because there is a lot of data we need + for d = 1,2 do + if place_master and nmaster > 0 then + local size = wa[width] + if nother > 0 then + size = math.min(wa[width] * mwfact, wa[width] - (coord - wa[x])) + end + if not data[0] then + data[0] = {} + end + coord = coord + tile_group(cls, wa, orientation, data[0], {first=1, last=nmaster, coord = coord, size = size}) + end + + if not place_master and nother > 0 then + local last = nmaster + + -- we have to modify the work area size to consider left and top views + local wasize = wa[width] + if nmaster > 0 and (orientation == "left" or orientation == "top") then + wasize = wa[width] - wa[width]*mwfact + end + for i = 1,ncol do + -- Try to get equal width among remaining columns + local size = math.min( (wasize - (coord - wa[x])) / (ncol - i + 1) ) + local first = last + 1 + last = last + math.floor((#cls - last)/(ncol - i + 1)) + -- tile the column and update our current x coordinate + if not data[i] then + data[i] = {} + end + coord = coord + tile_group(cls, wa, orientation, data[i], { first = first, last = last, coord = coord, size = size }) + end + end + place_master = not place_master + end + +end + +--- The main tile algo, on left. +-- @param screen The screen number to tile. +function left(screen) + return vile(nil, screen, "left") +end + +--- The main tile algo, on bottom. +-- @param screen The screen number to tile. +function bottom(screen) + return vile(nil, screen, "bottom") +end + +--- The main tile algo, on top. +-- @param screen The screen number to tile. +function top(screen) + return vile(nil, screen, "top") +end + +setmetatable(_M, { __call = vile }) diff --git a/lib/awful/mouse.lua.in b/lib/awful/mouse.lua.in index 43905067..29d2f8da 100644 --- a/lib/awful/mouse.lua.in +++ b/lib/awful/mouse.lua.in @@ -392,6 +392,100 @@ local function client_resize_tiled(c, lay) end, cursor) end +local function client_resize_viled(c, lay) + local wa = capi.screen[c.screen].workarea + local mwfact = tag.getmwfact() + local cursor + local g = c:geometry() + local offset = 0 + local x,y + if lay == layout.suit.vile then + cursor = "cross" + if g.height+15 > wa.height then + offset = g.height * .5 + cursor = "sb_h_double_arrow" + elseif not (g.y+g.height+15 > wa.y+wa.height) then + offset = g.height + end + capi.mouse.coords({ x = wa.x + wa.width * mwfact, y = g.y + offset }) + elseif lay == layout.suit.vile.left then + cursor = "cross" + if g.height+15 >= wa.height then + offset = g.height * .5 + cursor = "sb_h_double_arrow" + elseif not (g.y+g.height+15 > wa.y+wa.height) then + offset = g.height + end + capi.mouse.coords({ x = wa.x + wa.width * (1 - mwfact), y = g.y + offset }) + elseif lay == layout.suit.vile.bottom then + cursor = "cross" + if g.width+15 >= wa.width then + offset = g.width * .5 + cursor = "sb_v_double_arrow" + elseif not (g.x+g.width+15 > wa.x+wa.width) then + offset = g.width + end + capi.mouse.coords({ y = wa.y + wa.height * mwfact, x = g.x + offset}) + else + cursor = "cross" + if g.width+15 >= wa.width then + offset = g.width * .5 + cursor = "sb_v_double_arrow" + elseif not (g.x+g.width+15 > wa.x+wa.width) then + offset = g.width + end + capi.mouse.coords({ y = wa.y + wa.height * (1 - mwfact), x= g.x + offset }) + end + + capi.mousegrabber.run(function (mouse) + for k, v in ipairs(mouse.buttons) do + if v then + local fact_x = (mouse.x - wa.x) / wa.width + local fact_y = (mouse.y - wa.y) / wa.height + local mwfact + + local g = c:geometry() + + + -- we have to make sure we're not on the last visible client where we have to use different settings. + local wfact + local wfact_x, wfact_y + if (g.y+g.height+15) > (wa.y+wa.height) then + wfact_y = (g.y + g.height - mouse.y) / wa.height + else + wfact_y = (mouse.y - g.y) / wa.height + end + + if (g.x+g.width+15) > (wa.x+wa.width) then + wfact_x = (g.x + g.width - mouse.x) / wa.width + else + wfact_x = (mouse.x - g.x) / wa.width + end + + + if lay == layout.suit.vile then + mwfact = fact_x + wfact = wfact_y + elseif lay == layout.suit.vile.left then + mwfact = 1 - fact_x + wfact = wfact_y + elseif lay == layout.suit.vile.bottom then + mwfact = fact_y + wfact = wfact_x + else + mwfact = 1 - fact_y + wfact = wfact_x + end + + tag.setmwfact(math.min(math.max(mwfact, 0.01), 0.99), tag.selected(c.screen)) + aclient.setwfact(math.min(math.max(wfact,0.01), 0.99), c) + return true + end + end + return false + end, cursor) +end + local function client_resize_floating(c, corner, fixed_x, fixed_y) local corner, x, y = client.corner(c, corner) local g = c:geometry() @@ -483,6 +577,12 @@ function client.resize(c, corner) or lay == layout.suit.tile.top or lay == layout.suit.tile.bottom then return client_resize_tiled(c, lay) + elseif lay == layout.suit.vile + or lay == layout.suit.vile.left + or lay == layout.suit.vile.top + or lay == layout.suit.vile.bottom + then + return client_resize_viled(c, lay) elseif lay == layout.suit.magnifier then return client_resize_magnifier(c, corner) end diff --git a/themes/default/layouts/vile.png b/themes/default/layouts/vile.png new file mode 100644 index 0000000000000000000000000000000000000000..071a385f1d1c84b1efb108b0c547447f892032da GIT binary patch literal 174 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0L3?#3!&-4XSJOMr-u0Z<#|NlU8`tEwu3HVF>yH3sBsY80av^ zRI9<6LHP&=w-4(hHa0e0E6xLN)EyHVV!DDG<~YdtE?>d)Vxn(NA_K$Q)sm-gi<^NQ Oz~JfX=d#Wzp$Pz0pD-%` literal 0 HcmV?d00001 diff --git a/themes/default/layouts/vilebottom.png b/themes/default/layouts/vilebottom.png new file mode 100644 index 0000000000000000000000000000000000000000..aeedbe23034788bf0502779da1764a7ebd518eea GIT binary patch literal 195 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0P3?wHke>@jRF%}28J29*~C-V}>VGHmHah*QB z9?1M!cjX^Qx+KUin8D%MjWiG^$=lt9p@UV{1IXbl@Q5sCVBi)8VMc~ob0mO*>?NMQ zuIx7$`MG#m=f7kU019b(x;TbtoKOD2&&o5Shn`sf4Mu)0K7pH(TP;B90(?STf%JbcD6UwV4CFAC1o;IsFqBO` z3sSJG28|7OqncwH=G-yxm}6&fkDcL?nyl4Tl{izNDGZ*jelF{r5}E)9bvUX3 literal 0 HcmV?d00001 diff --git a/themes/default/layouts/vileleft.png b/themes/default/layouts/vileleft.png new file mode 100644 index 0000000000000000000000000000000000000000..ab55e087479efb9254f0efabc7720acc3a4eb123 GIT binary patch literal 172 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0L3?#3!&-4XSJOMr-u0Z<#|NlU8`tEwu3HVF>yH9Wk$(OgHkB@Q@b zhcNguhy|%|tVu{nU@AJq=D{Gh{RlVDmdhtOo?I;H(rPgF>D1?8*cqnwWxuBCLZDd; Mp00i_>zopr0Gs+QHvj+t literal 0 HcmV?d00001 diff --git a/themes/default/layouts/vileleftw.png b/themes/default/layouts/vileleftw.png new file mode 100644 index 0000000000000000000000000000000000000000..c18e7b43fc1df32d0a58bd71e81e9973e5bf1cfb GIT binary patch literal 170 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I0wfs{c7_5;rX+877Y2q^y~;*FUb3f)V@Srm zw>KAZF(~k`9{Bs;KU;9J#tVldvk!jY5f?M-DcZ@j;QnJ{|7f{rR*)$`Fu_8QQH4RQ z-_0|RAIP1@jRF%}28J29*~C-V}>VGHmHaRt&q zurz(=c_77D666=m;PC858ivL>4nJa0`PlBg3pY5H=O z_8W}+T)gJtcEJ;XLYkf~jv*T7lYj8D^33RA=c(c0VdZ)AC4omMUEsMK+cP${4UZ-s dIv^{>P_SynnunQ7a)6o`JYD@<);T3K0RSpqFw+14 literal 0 HcmV?d00001 diff --git a/themes/default/layouts/viletopw.png b/themes/default/layouts/viletopw.png new file mode 100644 index 0000000000000000000000000000000000000000..daf965faaaaddca59ffeca4ba2a98c1b1951c95e GIT binary patch literal 215 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0L3?#3!&-4XSjKx9jP7LeL$-D$|I14-?iy0WW zg+Z8+Vb&Z8pdfpRr>`sf4Mu)00UpW7Yb!wN0(?STf%JbcD6UwV4CFAC1o;IsFqBO` zYXRgjCV9KNFm$lWdH^|=o-U3d7QM+4t!xq;+-rDPn?!jW7O*B|@}@REd|zuYkyWij uKtb8&fSHj&fvH2r+Q3FdZHKBi%nXb7ih8`2d0_)Igu&C*&t;ucLK6VF)i@9U literal 0 HcmV?d00001 diff --git a/themes/default/layouts/vilew.png b/themes/default/layouts/vilew.png new file mode 100644 index 0000000000000000000000000000000000000000..c722a358e0618163bbe1a936093d327ce2594d8c GIT binary patch literal 168 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I0wfs{c7_5;rX+877Y2q^y~;*FUZSUqV@Srm zw>J-RF$nN5T=@InKX}q?*?{7T;(~}TT&6DCeGD`12ClIz(>>1&G6V>0n5TrhFeJNv z|5;-KG~CAW6oZ)}kYVWH`(mLGM9l+!ho?`kJpUS6QgnQ=h}(~E0w8fuS3j3^P6g5-u&wghk1yuCM)5S3) z;_%xU`?(Go2(=tEeXQ)^^N&Q%VR7_j+WST5;K{(_Gdk*bMO;{Y z?TYk1#ellE?w4MF6?z_XNknK`r=wfs3-86xHww)AzOu(;!msWa8;4)@Mu%R^ba)XI z;P$=CoIg8j*%qm|`;uptUlA8#h;p5|VOiR*IjW~O_;j8zJ8dQ1V8+^6^;g*F>(sPq zn$rW-;$zSMx&5O@S)5^7;!KXzntvV=5g5-u&wghk1ypp#)5S3) z;_%y>8+i{I2(Vr#N#t=mq2c3ro~_5h^CXXCgO%zc#`~i8PgXYMBuKT)VS1_Iux;m~ z@_(D+i#NSdJ9gvBq-9Y&#@iXfmbT2iyg5-u&wghk1yuCL)5S3) z;_%xU)_jKycpR!(`VO*AuwZCUa+xckZMdO`a|xdeLuV_mY2ed8QK!0&$OI*DFmvn8 zUm|z!!O?4zWxWfN*7_zXD$W#0nIX7xF=xk@tvzi$nTdxPH`$$Hc+7T8;*^))pGUbp zXJ39=bN}TTx!($m2@g(hF*H*TE^;;cctWC3BTFJlqd)75{@j-`lU{l}dvqh|LDahp z#tA$pS(FY>ji@-9y)LmU<=gIa8WG1f&q|*3@RqbOtM9{OEX~?x%UK literal 0 HcmV?d00001 diff --git a/themes/sky/layouts/viletop.png b/themes/sky/layouts/viletop.png new file mode 100644 index 0000000000000000000000000000000000000000..2bcb161cb05955983a1fd7974bd1f1bb68fbd2bf GIT binary patch literal 340 zcmeAS@N?(olHy`uVBq!ia0vp^#z3sV!3HGvKX#A@QY^(zo*^7SP{WbZ0pxQQctjQh z=^PMdjFJAU2V_W=xJHx&=ckpFCl;kLl$V$5W#(lUCnpx9>g5-u&wghk1ypp=)5S3) z;_%xUhI~wl0 zb7FFJq|G1Y;-zwX0&edux^$pxQfI0BUaKnoJDYhtxD># zUEgQBy?grM(jT^f{+>UHb7u-=8m%`Dp7hr&S#nyUFVdQ&MBb@0N7204*&oF literal 0 HcmV?d00001 diff --git a/themes/sky/theme.in b/themes/sky/theme.in index f0cb4378..b720c50d 100644 --- a/themes/sky/theme.in +++ b/themes/sky/theme.in @@ -31,6 +31,10 @@ layout_tilebottom = @AWESOME_THEMES_PATH@/sky/layouts/tilebottom.png layout_tileleft = @AWESOME_THEMES_PATH@/sky/layouts/tileleft.png layout_tile = @AWESOME_THEMES_PATH@/sky/layouts/tile.png layout_tiletop = @AWESOME_THEMES_PATH@/sky/layouts/tiletop.png +layout_vilebottom = @AWESOME_THEMES_PATH@/sky/layouts/vilebottom.png +layout_vileleft = @AWESOME_THEMES_PATH@/sky/layouts/vileleft.png +layout_vile = @AWESOME_THEMES_PATH@/sky/layouts/vile.png +layout_viletop = @AWESOME_THEMES_PATH@/sky/layouts/viletop.png awesome_icon = @AWESOME_THEMES_PATH@/sky/awesome-icon.png tasklist_floating_icon = @AWESOME_THEMES_PATH@/sky/layouts/floating.png