awful: add focusbydirection() (FS#166)

Signed-off-by: Julien Danjou <julien@danjou.info>
This commit is contained in:
Damien Leone 2008-08-06 21:11:47 +02:00 committed by Julien Danjou
parent 395e4b46d4
commit 171ece9918
1 changed files with 82 additions and 0 deletions

View File

@ -13,6 +13,7 @@ local pairs = pairs
local unpack = unpack
local os = os
local io = io
local math = math
local setmetatable = setmetatable
local table = table
local capi =
@ -169,6 +170,87 @@ function client.next(i, c)
end
end
--- Return true whether client B is in the right direction
-- compared to client A.
-- @param dir The direction.
-- @param cA The first client.
-- @param cB The second client.
-- @return True if B is in the direction of A.
local function is_in_direction(dir, cA, cB)
if dir == "up" then
return cA['y'] > cB['y']
elseif dir == "down" then
return cA['y'] < cB['y']
elseif dir == "left" then
return cA['x'] > cB['x']
elseif dir == "right" then
return cA['x'] < cB['x']
end
return false
end
--- Calculate distance between two points.
-- i.e: if we want to move to the right, we will take the right border
-- of the currently focused client and the left side of the checked client.
-- This avoid the focus of an upper client when you move to the right in a
-- tilebottom layout with nmaster=2 and 5 clients open, for instance.
-- @param dir The direction.
-- @param cA The first client.
-- @param cB The second client.
-- @return The distance between the clients.
local function calculate_distance(dir, cA, cB)
local xA = cA['x']
local xB = cB['x']
local yA = cA['y']
local yB = cB['y']
if dir == "up" then
yB = yB + cB['height']
elseif dir == "down" then
yA = yA + cA['height']
elseif dir == "left" then
xB = xB + cB['width']
elseif dir == "right" then
xA = xA + cA['width']
end
return math.sqrt(math.pow(xB - xA, 2) + math.pow(yB - yA, 2))
end
--- Focus a client by the given direction.
-- @param dir The direction, can be either "up", "down", "left" or "right".
-- @param c Optional client.
function client.focusbydirection(dir, c)
local sel = c or capi.client.focus_get()
if sel then
local coords = sel.coords
local dist, dist_min
local target = nil
local cls = capi.client.visible_get(sel.screen)
-- We check each client.
for i, c in ipairs(cls) do
-- Check coords to see if client is located in the right direction.
if is_in_direction(dir, coords, c.coords) then
-- Calculate distance between focused client and checked client.
dist = calculate_distance(dir, coords, c.coords)
-- If distance is shorter then keep the client.
if not target or dist < dist_min then
target = c
dist_min = dist
end
end
end
-- If we found a client to focus, then do it.
if target then
target:focus_set()
end
end
end
--- Focus a client by its relative index.
-- @param i The index.
-- @param c Optional client.