diff --git a/lib/wibox/init.lua b/lib/wibox/init.lua index e4f4fdf1f..6a4fb4d38 100644 --- a/lib/wibox/init.lua +++ b/lib/wibox/init.lua @@ -63,6 +63,11 @@ function wibox:find_widgets(x, y) end function wibox:get_screen() + if self.screen_assigned and self.screen_assigned.valid then + return self.screen_assigned + else + self.screen_assigned = nil + end local sgeos = {} for s in capi.screen do @@ -78,6 +83,10 @@ function wibox:set_screen(s) self.x = s.geometry.x self.y = s.geometry.y end + + -- Remember this screen so things work correctly if screens overlap and + -- (x,y) is not enough to figure out the correct screen. + self.screen_assigned = s end for _, k in pairs{ "buttons", "struts", "geometry", "get_xproperty", "set_xproperty" } do diff --git a/objects/screen.c b/objects/screen.c index f1ad03a02..c7af47dba 100644 --- a/objects/screen.c +++ b/objects/screen.c @@ -1070,6 +1070,34 @@ luaA_screen_fake_remove(lua_State *L) return 0; } +/** Fake-resize a screen + * @tparam integer x The new X-coordinate for screen. + * @tparam integer y The new Y-coordinate for screen. + * @tparam integer width The new width for screen. + * @tparam integer height The new height for screen. + * @function fake_resize + */ +static int +luaA_screen_fake_resize(lua_State *L) +{ + screen_t *screen = luaA_checkudata(L, 1, &screen_class); + int x = luaL_checkinteger(L, 2); + int y = luaL_checkinteger(L, 3); + int width = luaL_checkinteger(L, 4); + int height = luaL_checkinteger(L, 5); + + screen->geometry.x = x; + screen->geometry.y = y; + screen->geometry.width = width; + screen->geometry.height = height; + + screen_update_workarea(screen); + + luaA_object_emit_signal(L, 1, "property::geometry", 0); + + return 0; +} + void screen_class_setup(lua_State *L) { @@ -1089,6 +1117,7 @@ screen_class_setup(lua_State *L) LUA_OBJECT_META(screen) LUA_CLASS_META { "fake_remove", luaA_screen_fake_remove }, + { "fake_resize", luaA_screen_fake_resize }, { NULL, NULL }, }; diff --git a/tests/test-screen-changes.lua b/tests/test-screen-changes.lua index efc687c3f..7afb70381 100644 --- a/tests/test-screen-changes.lua +++ b/tests/test-screen-changes.lua @@ -3,6 +3,7 @@ local runner = require("_runner") local test_client = require("_client") local naughty = require("naughty") +local max = require("awful.layout.suit.max") local real_screen = screen[1] local fake_screen = screen.fake_add(50, 50, 500, 500) @@ -21,6 +22,9 @@ local steps = { test_client1.screen = real_screen test_client2.screen = fake_screen + -- Use a tiled layout + fake_screen.selected_tag.layout = max + -- Display a notification on the screen-to-be-removed naughty.notify{ text = "test", screen = fake_screen } @@ -28,10 +32,38 @@ local steps = { end end, - -- Step 2: Say goodbye to the screen + -- Step 2: Move the screen + function(count) + if count == 1 then + fake_screen:fake_resize(100, 110, 600, 610) + return + end + + -- Everything should be done by now + local geom = test_client2:geometry() + local bw = test_client2.border_width + assert(geom.x == 100, geom.x) + assert(geom.y == 110, geom.y) + assert(geom.width + 2*bw == 600, geom.width + 2*bw) + assert(geom.height + 2*bw == 610, geom.height + 2*bw) + + local wb = mywibox[fake_screen] + assert(wb.screen == fake_screen, tostring(wb.screen) .. " ~= " .. tostring(fake_screen)) + assert(wb.x == 100, wb.x) + assert(wb.y == 110, wb.y) + assert(wb.width == 600, wb.width) + + return true + end, + + -- Step 3: Say goodbye to the screen function() fake_screen:fake_remove() + -- Now that the screen is invalid, the wibox shouldn't refer to it any + -- more + assert(mywibox[fake_screen].screen ~= fake_screen) + -- TODO: This is a hack to make the test work, how to do this so that it -- also works "in the wild"? mypromptbox[fake_screen] = nil @@ -46,7 +78,7 @@ local steps = { return true end, - -- Step 3: Everything should now be on the main screen, the old screen + -- Step 4: Everything should now be on the main screen, the old screen -- should be garbage collectable function() assert(test_client1.screen == real_screen, test_client1.screen)