From 13bce88fa0b73c34e4f10769a8e9b3f3eeacc01d Mon Sep 17 00:00:00 2001 From: Uli Schlachter Date: Sun, 15 May 2016 14:37:22 +0200 Subject: [PATCH 1/2] Fix awful.screen.getbycoord() for top-left corner of a screen The problem was that get_square_distance() made the screen one pixel larger to the bottom/right than it really was. Thus, the (x+0,y+0)-pixel of a screen that was below or to the right of some other screen had distance zero to both of these screens. This commit fixes the screen size computation and adds a small unit test for getbycoord() and get_square_distance(). Reported by Elv13 here: https://github.com/awesomeWM/awesome/pull/878#issuecomment-219272864 Signed-off-by: Uli Schlachter --- lib/awful/screen.lua | 4 +- spec/awful/screen_spec.lua | 81 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 83 insertions(+), 2 deletions(-) create mode 100644 spec/awful/screen_spec.lua diff --git a/lib/awful/screen.lua b/lib/awful/screen.lua index 9c089cad..48d531ee 100644 --- a/lib/awful/screen.lua +++ b/lib/awful/screen.lua @@ -68,12 +68,12 @@ function screen.object.get_square_distance(self, x, y) if x < geom.x then dist_x = geom.x - x elseif x >= geom.x + geom.width then - dist_x = x - geom.x - geom.width + dist_x = x - geom.x - geom.width + 1 end if y < geom.y then dist_y = geom.y - y elseif y >= geom.y + geom.height then - dist_y = y - geom.y - geom.height + dist_y = y - geom.y - geom.height + 1 end return dist_x * dist_x + dist_y * dist_y end diff --git a/spec/awful/screen_spec.lua b/spec/awful/screen_spec.lua new file mode 100644 index 00000000..0967b176 --- /dev/null +++ b/spec/awful/screen_spec.lua @@ -0,0 +1,81 @@ +--------------------------------------------------------------------------- +-- @author Uli Schlachter +-- @copyright 2016 Uli Schlachter +--------------------------------------------------------------------------- + +local fake_screens = {} + +_G.screen = setmetatable({ + add_signal = function() end, + set_index_miss_handler = function() end, + set_newindex_miss_handler = function() end, +}, { + __call = function(_, _, prev) + if not prev then + return fake_screens[1] + end + for k, v in ipairs(fake_screens) do + if v == prev then + return fake_screens[k+1] + end + end + end, + + __index = function(_, arg) + if arg == "primary" then + return fake_screens[1] + end + if type(arg) == "number" then + return fake_screens[arg] + end + for _, v in ipairs(fake_screens) do + if v == arg then + return arg + end + end + end, + + __newindex = error, +}) +local ascreen = require("awful.screen") + +describe("awful.screen", function() + describe("two screens each 1x1", function() + before_each(function() + fake_screens = { + { geometry = { x = 0, y = 0, width = 1, height = 1 }, index = 1 }, + { geometry = { x = 0, y = 1, width = 1, height = 1 }, index = 2 }, + } + end) + + it("get_square_distance", function() + assert.is.equal(0, ascreen.object.get_square_distance(fake_screens[1], 0, 0)) + assert.is.equal(1, ascreen.object.get_square_distance(fake_screens[1], 0, 1)) + assert.is.equal(2, ascreen.object.get_square_distance(fake_screens[1], 1, 1)) + assert.is.equal(5, ascreen.object.get_square_distance(fake_screens[1], 2, 1)) + assert.is.equal(2, ascreen.object.get_square_distance(fake_screens[1], -1, 1)) + + assert.is.equal(1, ascreen.object.get_square_distance(fake_screens[2], 0, 0)) + assert.is.equal(0, ascreen.object.get_square_distance(fake_screens[2], 0, 1)) + assert.is.equal(1, ascreen.object.get_square_distance(fake_screens[2], 1, 1)) + assert.is.equal(4, ascreen.object.get_square_distance(fake_screens[2], 2, 1)) + assert.is.equal(1, ascreen.object.get_square_distance(fake_screens[2], -1, 1)) + end) + + it("getbycoord", function() + -- Some exact matches + assert.is.equal(1, ascreen.getbycoord(0, 0)) + assert.is.equal(2, ascreen.getbycoord(0, 1)) + + -- Some "find the closest screen"-cases + assert.is.equal(1, ascreen.getbycoord(-1, -1)) + assert.is.equal(1, ascreen.getbycoord(-1, 0)) + assert.is.equal(2, ascreen.getbycoord(-1, 1)) + assert.is.equal(2, ascreen.getbycoord(-1, 2)) + + assert.is.equal(2, ascreen.getbycoord(1, 1)) + end) + end) +end) + +-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 From ae738db58a230ea5c7e3a94467b11671dad38427 Mon Sep 17 00:00:00 2001 From: Uli Schlachter Date: Sun, 15 May 2016 14:43:25 +0200 Subject: [PATCH 2/2] Fix awful.screen.getbycoord when no screens exist Signed-off-by: Uli Schlachter --- lib/awful/screen.lua | 7 +++++-- spec/awful/screen_spec.lua | 10 ++++++++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/lib/awful/screen.lua b/lib/awful/screen.lua index 48d531ee..b2f2543e 100644 --- a/lib/awful/screen.lua +++ b/lib/awful/screen.lua @@ -86,15 +86,18 @@ end -- @param x The x coordinate -- @param y The y coordinate function screen.getbycoord(x, y) + local dist = math.huge local s = capi.screen.primary - local dist = screen.object.get_square_distance(s, x, y) + if s then + dist = screen.object.get_square_distance(s, x, y) + end for i in capi.screen do local d = screen.object.get_square_distance(i, x, y) if d < dist then s, dist = capi.screen[i], d end end - return s.index + return s and s.index end --- Give the focus to a screen, and move pointer to last known position on this diff --git a/spec/awful/screen_spec.lua b/spec/awful/screen_spec.lua index 0967b176..6c36daad 100644 --- a/spec/awful/screen_spec.lua +++ b/spec/awful/screen_spec.lua @@ -76,6 +76,16 @@ describe("awful.screen", function() assert.is.equal(2, ascreen.getbycoord(1, 1)) end) end) + + describe("no screens", function() + before_each(function() + fake_screens = {} + end) + + it("getbycoord", function() + assert.is_nil(ascreen.getbycoord(0, 0)) + end) + end) end) -- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80