I've updated the patch yet again to fix the nil error which was occurring when there were no client windows yet there were still a number of master windows. Stupid error but nonetheless it should be fixed. Also removed trailing whitespace as I could find it.
-- Donald (Wed, Jan 21, 2009 at 09:15:37PM +0100) Gregor Best <[email protected]>: > At Wed, 21 Jan 2009 18:52:16 +0100 > Julien Danjou wrote: > > > At 1232560032 time_t, Gregor Best wrote: > > > I tried your patch (for the first time, i must admit), and I have to say: > > > Damn cool job :) A few issues remained though: > > > > I think you tried the wrong patch, there's another one sent after that > > one. > > Might be, I tried the one from Monday, January 19th, 16:14 :) > > -- > Gregor Best
From 6b82ed529f6b24ec6c28cd0476c623fb5e6c379a Mon Sep 17 00:00:00 2001 From: [email protected] <[email protected]> Date: Tue, 13 Jan 2009 13:31:37 -0600 Subject: [PATCH] vile is a Variable tILE layout that allows the user to select a single client window and resize that in it's layout. This means that the slave windows do not necissarily need to be the same size all the time. Fixed the bug where having only master or other windows would not display full screen. Added mouse resizing to the layout. Updated vile to incorporate the style used by adaptile. Merged the vile layout with the adaptile layout and fixed mouse support. Fixed bug when closing the final window. pass screen when looking for tag selected. Fixed bug with nil values. --- lib/awful/client.lua.in | 119 +++++++++++++++++++++++++ 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 | 73 +++++++++++++++ 5 files changed, 374 insertions(+), 0 deletions(-) create mode 100644 lib/awful/layout/suit/vile.lua.in diff --git a/lib/awful/client.lua.in b/lib/awful/client.lua.in index 65103a8..5be927f 100644 --- a/lib/awful/client.lua.in +++ b/lib/awful/client.lua.in @@ -593,6 +593,125 @@ function floating.delete(c) data.floating[c] = nil end +local function normalize(set, max) + total = 0 + if max then + for i = 1,max do + total = total + set[i] + end + for i = 1,max 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 which {index, column} the client belongs to given the index +function idx(c) + local c = c or capi.client.focus + 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, max=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, max=percol} +end + + +-- Set the window by index (or the currently selected window) +function setwfact(wfact, c) + -- get the currently selected window + local c = c or capi.client.focus + 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.max do + if i ~= w.idx then + total = total + colfact[i] + end + end + + -- normalize the windows + for i = 1,w.max do + if i ~= w.idx then + colfact[i] = (colfact[i] * rest) / total + end + end +end + +-- Change the width factor of a window (indexed by number) +function incwfact(add, c) + local c = c or capi.client.focus + 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.max) + 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 bf45763..c4b7fd9 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 ae83edf..8c57bf7 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 0000000..8e8de91 --- /dev/null +++ b/lib/awful/layout/suit/vile.lua.in @@ -0,0 +1,177 @@ +--------------------------------------------------------------------------- +-- @author Donald Ephraim Curtis <[email protected]> +-- @author Julien Danjou <[email protected]> +-- @copyright 2009 Donald Ephraim Curtis +-- @copyright 2009 Maxime Coste +-- @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 4390506..5822cdd 100644 --- a/lib/awful/mouse.lua.in +++ b/lib/awful/mouse.lua.in @@ -392,6 +392,73 @@ 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 + if lay == layout.suit.vile then + capi.mouse.coords({ x = wa.x + wa.width * mwfact }) + cursor = "sb_h_double_arrow" + elseif lay == layout.suit.vile.left then + capi.mouse.coords({ x = wa.x + wa.width * (1 - mwfact) }) + cursor = "sb_h_double_arrow" + elseif lay == layout.suit.vile.bottom then + capi.mouse.coords({ y = wa.y + wa.height * mwfact }) + cursor = "sb_v_double_arrow" + else + capi.mouse.coords({ y = wa.y + wa.height * (1 - mwfact) }) + cursor = "sb_v_double_arrow" + 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 +550,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 -- 1.6.1
pgpYkkHiPiwVs.pgp
Description: PGP signature
