awful: add focusbydirection() (FS#166)
Signed-off-by: Julien Danjou <julien@danjou.info>
This commit is contained in:
parent
395e4b46d4
commit
171ece9918
|
@ -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.
|
||||
|
|
Loading…
Reference in New Issue