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 unpack = unpack
|
||||||
local os = os
|
local os = os
|
||||||
local io = io
|
local io = io
|
||||||
|
local math = math
|
||||||
local setmetatable = setmetatable
|
local setmetatable = setmetatable
|
||||||
local table = table
|
local table = table
|
||||||
local capi =
|
local capi =
|
||||||
|
@ -169,6 +170,87 @@ function client.next(i, c)
|
||||||
end
|
end
|
||||||
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.
|
--- Focus a client by its relative index.
|
||||||
-- @param i The index.
|
-- @param i The index.
|
||||||
-- @param c Optional client.
|
-- @param c Optional client.
|
||||||
|
|
Loading…
Reference in New Issue