awesome/lib/revelation.lua.in

139 lines
3.8 KiB
Lua
Raw Normal View History

---------------------------------------------------------------------------
-- @author Espen Wiborg <espenhw@grumblesmurf.org>
-- @author Julien Danjou <julien@danjou.info>
-- @copyright 2008 Espen Wiborg, Julien Danjou
-- @release @AWESOME_VERSION@
---------------------------------------------------------------------------
local math = math
local table = table
local pairs = pairs
local button = button
local otable = otable
local awful =
{
tag = require("awful.tag"),
client = require("awful.client")
}
local capi =
{
tag = tag,
client = client,
keygrabber = keygrabber,
mouse = mouse
}
--- Exposé implementation
module("revelation")
-- Layout functions
layout = {}
--- The default layout function for revelation
-- Tries to arrange clients in an approximated square grid, by
-- calculating c = floor(sqrt(n)) and arranging for c columns in a
-- tile layout.
-- @param t The tag to do revelation on.
-- @param n The number of clients to reveal.
function layout.default (t, n)
t.layout = "tile"
local columns = math.floor(math.sqrt(n))
if columns > 1 then
t.mwfact = 1 / columns
t.ncol = columns - 1
end
t.nmaster = n / columns
end
function clients(class, s)
local clients
if class then
clients = {}
for k, c in pairs(capi.client.get(s)) do
if c.class == class then
table.insert(clients, c)
end
end
else
clients = capi.client.get(s)
end
return clients
end
function selectfn(restore)
return function(c)
restore()
-- Pop to client tag
awful.tag.viewonly(c:tags()[1])
-- Focus and raise
capi.client.focus = c
c:raise()
end
end
--- Returns keyboardhandler.
-- Arrow keys move focus, Return selects, Escape cancels.
-- Ignores modifiers.
function keyboardhandler (restore)
return function (mod, key, event)
if event ~= "press" then return true end
if key == "Escape" then
restore()
awful.tag.history.restore()
return false
elseif key == "Return" then
selectfn(restore)(capi.client.focus)
return false
elseif key == "Left" or key == "Right" or
key == "Up" or key == "Down" then
awful.client.focus.bydirection(key:lower())
end
return true
end
end
--- Implement Exposé (from Mac OS X).
-- @param class The class of clients to expose, or nil for all clients.
-- @param fn A binary function f(t, n) to set the layout for tag t for n clients, or nil for the default layout.
-- @param s The screen to consider clients of, or nil for "current screen".
function revelation(class, fn, s)
local screen = s or capi.mouse.screen
local layout_fn = fn or layout.default
local data = otable()
local clients = clients(class, screen)
if #clients == 0 then
return
end
local tag = capi.tag({ name = "Revelation" })
tag.screen = screen
layout_fn(tag, #clients)
local function restore()
for k, cl in pairs(tag:clients()) do
-- Clear revelation tag
local tags = cl:tags()
if tags[tag] then
tags[tags[tag]] = nil
end
cl:tags(tags)
-- Restore client mouse bindings
cl:buttons(data[cl])
data[cl] = nil
end
tag.screen = nil
capi.keygrabber.stop()
end
for k, c in pairs(clients) do
data[c] = c:buttons()
c:buttons({ button({}, 1, selectfn(restore)) })
end
tag:clients(clients)
awful.tag.viewonly(tag)
capi.keygrabber.run(keyboardhandler(restore))
end