diff --git a/lib/awful/client.lua b/lib/awful/client.lua index bbc008a7..e4fed3cd 100644 --- a/lib/awful/client.lua +++ b/lib/awful/client.lua @@ -11,6 +11,7 @@ local util = require("awful.util") local spawn = require("awful.spawn") local object = require("gears.object") +local grect = require("gears.geometry").rectangle local pairs = pairs local type = type local ipairs = ipairs @@ -197,7 +198,7 @@ function client.swap.bydirection(dir, c, stacked) for i,cl in ipairs(cltbl) do geomtbl[i] = cl:geometry() end - local target = util.get_rectangle_in_direction(dir, geomtbl, sel:geometry()) + local target = grect.get_in_direction(dir, geomtbl, sel:geometry()) -- If we found a client to swap with, then go for it if target then diff --git a/lib/awful/client/focus.lua b/lib/awful/client/focus.lua index 9847d144..8243f6ba 100644 --- a/lib/awful/client/focus.lua +++ b/lib/awful/client/focus.lua @@ -6,7 +6,7 @@ -- @release @AWESOME_VERSION@ -- @submodule client --------------------------------------------------------------------------- -local util = require("awful.util") +local grect = require("gears.geometry").rectangle local capi = { @@ -168,7 +168,7 @@ function focus.bydirection(dir, c, stacked) geomtbl[i] = cl:geometry() end - local target = util.get_rectangle_in_direction(dir, geomtbl, sel:geometry()) + local target = grect.get_in_direction(dir, geomtbl, sel:geometry()) -- If we found a client to focus, then do it. if target then @@ -200,7 +200,7 @@ function focus.global_bydirection(dir, c, stacked) for i,cl in ipairs(cltbl) do geomtbl[i] = cl:geometry() end - local target = util.get_rectangle_in_direction(dir, geomtbl, scr.geometry) + local target = grect.get_in_direction(dir, geomtbl, scr.geometry) if target then cltbl[target]:emit_signal("request::activate", diff --git a/lib/awful/screen.lua b/lib/awful/screen.lua index b98316fb..cc384f91 100644 --- a/lib/awful/screen.lua +++ b/lib/awful/screen.lua @@ -137,7 +137,7 @@ function screen.focus_bydirection(dir, _screen) for s in capi.screen do geomtbl[s] = capi.screen[s].geometry end - local target = util.get_rectangle_in_direction(dir, geomtbl, sel.geometry) + local target = grect.get_in_direction(dir, geomtbl, sel.geometry) if target then return screen.focus(target) end diff --git a/lib/awful/util.lua b/lib/awful/util.lua index c64c43e2..18587522 100644 --- a/lib/awful/util.lua +++ b/lib/awful/util.lua @@ -20,6 +20,7 @@ local type = type local rtable = table local string = string local lgi = require("lgi") +local grect = require("gears.geometry").rectangle local Gio = require("lgi").Gio local Pango = lgi.Pango local capi = @@ -301,76 +302,18 @@ 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 gAx = _gA.x - local gAy = _gA.y - local gBx = _gB.x - local gBy = _gB.y - - if dir == "up" then - gBy = _gB.y + _gB.height - elseif dir == "down" then - gAy = _gA.y + _gA.height - elseif dir == "left" then - gBx = _gB.x + _gB.width - elseif dir == "right" then - gAx = _gA.x + _gA.width - end - - return math.sqrt(math.pow(gBx - gAx, 2) + math.pow(gBy - gAy, 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. +-- @deprecated awful.util.get_rectangle_in_direction -- @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. +-- @see gears.geometry function util.get_rectangle_in_direction(dir, recttbl, cur) - local dist, dist_min - local target = nil + util.deprecate("gears.geometry.rectangle.get_in_direction") - -- We check each object - for i, rect in pairs(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 + return grect.get_in_direction(dir, recttbl, cur) end --- Join all tables given as parameters. diff --git a/lib/gears/geometry.lua b/lib/gears/geometry.lua index 8fcf7c47..3e98fef8 100644 --- a/lib/gears/geometry.lua +++ b/lib/gears/geometry.lua @@ -76,4 +76,76 @@ function gears.geometry.rectangle.get_by_coord(list, x, y) end 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 gAx = _gA.x + local gAy = _gA.y + local gBx = _gB.x + local gBy = _gB.y + + if dir == "up" then + gBy = _gB.y + _gB.height + elseif dir == "down" then + gAy = _gA.y + _gA.height + elseif dir == "left" then + gBx = _gB.x + _gB.width + elseif dir == "right" then + gAx = _gA.x + _gA.width + end + + return math.sqrt(math.pow(gBx - gAx, 2) + math.pow(gBy - gAy, 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. +-- @tparam string dir The direction, can be either *up*, *down*, *left* or *right*. +-- @tparam table recttbl A table of rectangle specifications. +-- @tparam table cur The current rectangle. +-- @return The index for the rectangle in recttbl closer to cur in the given direction. nil if none found. +function gears.geometry.rectangle.get_in_direction(dir, recttbl, cur) + local dist, dist_min + local target = nil + + -- We check each object + for i, rect in pairs(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 + return gears.geometry