From d799ac76aa9d182abc4d80810e4c552e6e4d7e17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Abd=C3=B3=20Roig-Maranges?= Date: Fri, 14 Sep 2012 21:49:14 +0200 Subject: [PATCH] Added function to change screen focus by direction The function awful.screen.focus_bydirection changes the screen focus according to physical position. The code is based on awful.client.focus.bydirection. Signed-off-by: Uli Schlachter --- lib/awful/screen.lua.in | 17 +++++++++ lib/awful/util.lua.in | 76 +++++++++++++++++++++++++++++++++++++++-- 2 files changed, 90 insertions(+), 3 deletions(-) diff --git a/lib/awful/screen.lua.in b/lib/awful/screen.lua.in index d9a46258c..5088bdc80 100644 --- a/lib/awful/screen.lua.in +++ b/lib/awful/screen.lua.in @@ -47,6 +47,23 @@ function screen.focus(_screen) capi.mouse.screen = _screen end +--- Give the focus to a screen, and move pointer, by physical position relative to current screen. +-- @param dir The direction, can be either "up", "down", "left" or "right". +-- @param screen Screen number. +function screen.focus_bydirection(dir, _screen) + local sel = _screen or capi.mouse.screen + if sel then + local geomtbl = {} + for s = 1, capi.screen.count() do + geomtbl[s] = capi.screen[s].geometry + end + local target = util.get_rectangle_in_direction(dir, geomtbl, capi.screen[sel].geometry) + if target then + return screen.focus(target) + end + end +end + --- Give the focus to a screen, and move pointer, but relative to the current -- focused screen. -- @param i Value to add to the current focused screen index. 1 will focus next diff --git a/lib/awful/util.lua.in b/lib/awful/util.lua.in index 74ac127cc..ee11d628e 100644 --- a/lib/awful/util.lua.in +++ b/lib/awful/util.lua.in @@ -198,9 +198,9 @@ function util.geticonpath(iconname, exts, dirs, size) icon = d .. iconname .. '.' .. e if util.file_readable(icon) then return icon - end - end - end + end + end + end end --- Check if file exists and is readable. @@ -260,6 +260,76 @@ function util.subsets(set) return ret end +-- Return true whether rectangle B is in the right direction +-- compared to rectangle A. +-- @param dir The direction. +-- @param gA The geometric specification for rectangle A. +-- @param gB The geometric specification for rectangle B. +-- @return True if B is in the direction of A. +local function is_in_direction(dir, gA, gB) + if dir == "up" then + return gA.y > gB.y + elseif dir == "down" then + return gA.y < gB.y + elseif dir == "left" then + return gA.x > gB.x + elseif dir == "right" then + return gA.x < gB.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 screen and the left side of the checked screen. +-- @param dir The direction. +-- @param gA The first rectangle. +-- @param gB The second rectangle. +-- @return The distance between the screens. +local function calculate_distance(dir, _gA, _gB) + local gA = _gA + local gB = _gB + + if dir == "up" then + gB.y = gB.y + gB.height + elseif dir == "down" then + gA.y = gA.y + gA.height + elseif dir == "left" then + gB.x = gB.x + gB.width + elseif dir == "right" then + gA.x = gA.x + gA.width + end + + return math.sqrt(math.pow(gB.x - gA.x, 2) + math.pow(gB.y - gA.y, 2)) +end + +-- Get the nearest rectangle in the given direction. Every rectangle is specified as a table +-- with 'x', 'y', 'width', 'height' keys, the same as client or screen geometries. +-- @param dir The direction, can be either "up", "down", "left" or "right". +-- @param recttbl A table of rectangle specifications. +-- @param cur The current rectangle. +-- @return The index for the rectangle in recttbl closer to cur in the given direction. nil if none found. +function util.get_rectangle_in_direction(dir, recttbl, cur) + local dist, dist_min + local target = nil + + -- We check each object + for i, rect in ipairs(recttbl) do + -- Check geometry to see if object is located in the right direction. + if is_in_direction(dir, cur, rect) then + -- Calculate distance between current and checked object. + dist = calculate_distance(dir, cur, rect) + + -- If distance is shorter then keep the object. + if not target or dist < dist_min then + target = i + dist_min = dist + end + end + end + return target +end + --- Join all tables given as parameters. -- This will iterate all tables and insert all their keys into a new table. -- @param args A list of tables to join