139 lines
3.8 KiB
Lua
139 lines
3.8 KiB
Lua
---------------------------------------------------------------------------
|
|
-- @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
|