Merge pull request #2811 from sigprof/no_overlap-unselected-tags-v2
awful.placement: Fix no_overlap with unselected tags
This commit is contained in:
commit
0ac0a77aab
|
@ -894,6 +894,39 @@ function placement.no_offscreen(c, args)
|
||||||
return fix_new_geometry(geometry, args, true)
|
return fix_new_geometry(geometry, args, true)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Check whether the client is on at least one of selected tags (similar to
|
||||||
|
-- `c:isvisible()`, but without checks for the hidden or minimized state).
|
||||||
|
local function client_on_selected_tags(c)
|
||||||
|
if c.sticky then
|
||||||
|
return true
|
||||||
|
else
|
||||||
|
for _, t in pairs(c:tags()) do
|
||||||
|
if t.selected then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Check whether the client would be visible if the specified set of tags is
|
||||||
|
-- selected (using the same set of conditions as `c:isvisible()`, but checking
|
||||||
|
-- against the specified tags instead of currently selected ones).
|
||||||
|
local function client_visible_on_tags(c, tags)
|
||||||
|
if c.hidden or c.minimized then
|
||||||
|
return false
|
||||||
|
elseif c.sticky then
|
||||||
|
return true
|
||||||
|
else
|
||||||
|
for _, t in pairs(c:tags()) do
|
||||||
|
if gtable.hasitem(tags, t) then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
--- Place the client where there's place available with minimum overlap.
|
--- Place the client where there's place available with minimum overlap.
|
||||||
--@DOC_awful_placement_no_overlap_EXAMPLE@
|
--@DOC_awful_placement_no_overlap_EXAMPLE@
|
||||||
-- @param c The client.
|
-- @param c The client.
|
||||||
|
@ -905,8 +938,22 @@ function placement.no_overlap(c, args)
|
||||||
args = add_context(args, "no_overlap")
|
args = add_context(args, "no_overlap")
|
||||||
local geometry = geometry_common(c, args)
|
local geometry = geometry_common(c, args)
|
||||||
local screen = get_screen(c.screen or a_screen.getbycoord(geometry.x, geometry.y))
|
local screen = get_screen(c.screen or a_screen.getbycoord(geometry.x, geometry.y))
|
||||||
local cls = client.visible(screen)
|
local cls, curlay
|
||||||
local curlay = layout.get()
|
if client_on_selected_tags(c) then
|
||||||
|
cls = client.visible(screen)
|
||||||
|
curlay = layout.get()
|
||||||
|
else
|
||||||
|
-- When placing a client on unselected tags, place it as if all tags of
|
||||||
|
-- that client are selected.
|
||||||
|
local tags = c:tags()
|
||||||
|
cls = {}
|
||||||
|
for _, other_c in pairs(capi.client.get(screen)) do
|
||||||
|
if client_visible_on_tags(other_c, tags) then
|
||||||
|
table.insert(cls, other_c)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
curlay = tags[1] and tags[1].layout
|
||||||
|
end
|
||||||
local areas = { screen.workarea }
|
local areas = { screen.workarea }
|
||||||
for _, cl in pairs(cls) do
|
for _, cl in pairs(cls) do
|
||||||
if cl ~= c
|
if cl ~= c
|
||||||
|
|
|
@ -44,25 +44,25 @@ local function default_test(c, geometry)
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
local client_count = 0
|
|
||||||
local client_data = {}
|
local client_data = {}
|
||||||
local function add_client(args)
|
local function add_client(args)
|
||||||
client_count = client_count + 1
|
local data = {}
|
||||||
local client_index = client_count
|
table.insert(client_data, data)
|
||||||
|
local client_index = #client_data
|
||||||
table.insert(tests, function(count)
|
table.insert(tests, function(count)
|
||||||
local name = string.format("client%010d", client_index)
|
local name = string.format("client%010d", client_index)
|
||||||
if count <= 1 then
|
if count <= 1 then
|
||||||
|
data.prev_client_count = #client.get()
|
||||||
local geometry = args.geometry(mouse.screen.workarea)
|
local geometry = args.geometry(mouse.screen.workarea)
|
||||||
test_client(class, name, nil, nil, nil, {
|
test_client(class, name, args.sn_rules, nil, nil, {
|
||||||
size = {
|
size = {
|
||||||
width = geometry.width,
|
width = geometry.width,
|
||||||
height = geometry.height
|
height = geometry.height
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
client_data[client_index] = { geometry = geometry }
|
data.geometry = geometry
|
||||||
return nil
|
return nil
|
||||||
elseif #client.get() >= client_index then
|
elseif #client.get() > data.prev_client_count then
|
||||||
local data = client_data[client_index]
|
|
||||||
local c = data.c
|
local c = data.c
|
||||||
if not c then
|
if not c then
|
||||||
c = client.get()[1]
|
c = client.get()[1]
|
||||||
|
@ -75,7 +75,25 @@ local function add_client(args)
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- The first 100x100 window should be placed at the top left corner.
|
-- Repeat testing 3 times, placing clients on different tags:
|
||||||
|
--
|
||||||
|
-- - Iteration 1 places clients on the tag 1, which is selected.
|
||||||
|
--
|
||||||
|
-- - Iteration 2 places clients on the tag 2, which is unselected; the
|
||||||
|
-- selected tag 1 remains empty.
|
||||||
|
--
|
||||||
|
-- - Iteration 3 places clients on the tag 3, which is unselected; the
|
||||||
|
-- selected tag 1 contains some clients.
|
||||||
|
--
|
||||||
|
for _, tag_num in ipairs{1, 2, 3} do
|
||||||
|
|
||||||
|
local sn_rules
|
||||||
|
if tag_num > 1 then
|
||||||
|
sn_rules = { tag = root.tags()[tag_num] }
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Put a 100x100 client on the tag 1 before iteration 3.
|
||||||
|
if tag_num == 3 then
|
||||||
add_client {
|
add_client {
|
||||||
geometry = function(wa)
|
geometry = function(wa)
|
||||||
return {
|
return {
|
||||||
|
@ -86,11 +104,30 @@ add_client {
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
|
end
|
||||||
|
|
||||||
-- The second 100x100 window should be placed to the right of the first window.
|
-- The first 100x100 client should be placed at the top left corner.
|
||||||
-- Note that this assumption fails if the screen is in the portrait orientation
|
|
||||||
-- (e.g., the test succeeds with a 600x703 screen and fails with 600x704).
|
|
||||||
add_client {
|
add_client {
|
||||||
|
sn_rules = sn_rules,
|
||||||
|
geometry = function(wa)
|
||||||
|
return {
|
||||||
|
width = 100,
|
||||||
|
height = 100,
|
||||||
|
expected_x = wa.x,
|
||||||
|
expected_y = wa.y
|
||||||
|
}
|
||||||
|
end
|
||||||
|
}
|
||||||
|
|
||||||
|
-- Remember the first client data for the current iteration.
|
||||||
|
local first_client_data = client_data[#client_data]
|
||||||
|
|
||||||
|
-- The second 100x100 client should be placed to the right of the first
|
||||||
|
-- client. Note that this assumption fails if the screen is in the portrait
|
||||||
|
-- orientation (e.g., the test succeeds with a 600x703 screen and fails with
|
||||||
|
-- 600x704).
|
||||||
|
add_client {
|
||||||
|
sn_rules = sn_rules,
|
||||||
geometry = function(wa)
|
geometry = function(wa)
|
||||||
return {
|
return {
|
||||||
width = 100,
|
width = 100,
|
||||||
|
@ -101,8 +138,105 @@ add_client {
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
|
|
||||||
-- The wide window should be placed below the two 100x100 windows.
|
-- Hide last client.
|
||||||
|
do
|
||||||
|
local data = client_data[#client_data]
|
||||||
|
table.insert(tests, function()
|
||||||
|
data.c.hidden = true
|
||||||
|
return true
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Another 100x100 client should be placed to the right of the first client
|
||||||
|
-- (the hidden client should be ignored during placement).
|
||||||
add_client {
|
add_client {
|
||||||
|
sn_rules = sn_rules,
|
||||||
|
geometry = function(wa)
|
||||||
|
return {
|
||||||
|
width = 100,
|
||||||
|
height = 100,
|
||||||
|
expected_x = wa.x + 100 + 2*border_width,
|
||||||
|
expected_y = wa.y
|
||||||
|
}
|
||||||
|
end
|
||||||
|
}
|
||||||
|
|
||||||
|
-- Minimize last client.
|
||||||
|
do
|
||||||
|
local data = client_data[#client_data]
|
||||||
|
table.insert(tests, function()
|
||||||
|
data.c.minimized = true
|
||||||
|
return true
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Another 100x100 client should be placed to the right of the first client
|
||||||
|
-- (the minimized client should be ignored during placement).
|
||||||
|
add_client {
|
||||||
|
sn_rules = sn_rules,
|
||||||
|
geometry = function(wa)
|
||||||
|
return {
|
||||||
|
width = 100,
|
||||||
|
height = 100,
|
||||||
|
expected_x = wa.x + 100 + 2*border_width,
|
||||||
|
expected_y = wa.y
|
||||||
|
}
|
||||||
|
end
|
||||||
|
}
|
||||||
|
|
||||||
|
-- Hide last client, and make the first client sticky.
|
||||||
|
do
|
||||||
|
local data = client_data[#client_data]
|
||||||
|
table.insert(tests, function()
|
||||||
|
data.c.hidden = true
|
||||||
|
first_client_data.c.sticky = true
|
||||||
|
return true
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Another 100x100 client should be placed to the right of the first client
|
||||||
|
-- (the sticky client should be taken into account during placement).
|
||||||
|
add_client {
|
||||||
|
sn_rules = sn_rules,
|
||||||
|
geometry = function(wa)
|
||||||
|
return {
|
||||||
|
width = 100,
|
||||||
|
height = 100,
|
||||||
|
expected_x = wa.x + 100 + 2*border_width,
|
||||||
|
expected_y = wa.y
|
||||||
|
}
|
||||||
|
end
|
||||||
|
}
|
||||||
|
|
||||||
|
-- Hide last client, and put the first client on the tag 9 (because the
|
||||||
|
-- first client is sticky, it should remain visible).
|
||||||
|
do
|
||||||
|
local data = client_data[#client_data]
|
||||||
|
table.insert(tests, function()
|
||||||
|
data.c.hidden = true
|
||||||
|
first_client_data.c:tags{ root.tags()[9] }
|
||||||
|
return true
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Another 100x100 client should be placed to the right of the first client
|
||||||
|
-- (the sticky client should be taken into account during placement even if
|
||||||
|
-- that client seems to be on an unselected tag).
|
||||||
|
add_client {
|
||||||
|
sn_rules = sn_rules,
|
||||||
|
geometry = function(wa)
|
||||||
|
return {
|
||||||
|
width = 100,
|
||||||
|
height = 100,
|
||||||
|
expected_x = wa.x + 100 + 2*border_width,
|
||||||
|
expected_y = wa.y
|
||||||
|
}
|
||||||
|
end
|
||||||
|
}
|
||||||
|
|
||||||
|
-- The wide client should be placed below the two 100x100 client.
|
||||||
|
add_client {
|
||||||
|
sn_rules = sn_rules,
|
||||||
geometry = function(wa)
|
geometry = function(wa)
|
||||||
return {
|
return {
|
||||||
width = wa.width - 50,
|
width = wa.width - 50,
|
||||||
|
@ -113,11 +247,12 @@ add_client {
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
|
|
||||||
-- The first large window which does not completely fit in any free area should
|
-- The first large client which does not completely fit in any free area
|
||||||
-- be placed at the bottom left corner (no_overlap should place it below the
|
-- should be placed at the bottom left corner (no_overlap should place it
|
||||||
-- wide window, and then no_offscreen should shift it up so that it would be
|
-- below the wide client, and then no_offscreen should shift it up so that
|
||||||
-- completely inside the workarea).
|
-- it would be completely inside the workarea).
|
||||||
add_client {
|
add_client {
|
||||||
|
sn_rules = sn_rules,
|
||||||
geometry = function(wa)
|
geometry = function(wa)
|
||||||
return {
|
return {
|
||||||
width = wa.width - 10,
|
width = wa.width - 10,
|
||||||
|
@ -128,8 +263,9 @@ add_client {
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
|
|
||||||
-- The second large window should be placed at the top right corner.
|
-- The second large client should be placed at the top right corner.
|
||||||
add_client {
|
add_client {
|
||||||
|
sn_rules = sn_rules,
|
||||||
geometry = function(wa)
|
geometry = function(wa)
|
||||||
return {
|
return {
|
||||||
width = wa.width - 10,
|
width = wa.width - 10,
|
||||||
|
@ -140,8 +276,9 @@ add_client {
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
|
|
||||||
-- The third large window should be placed at the bottom right corner.
|
-- The third large client should be placed at the bottom right corner.
|
||||||
add_client {
|
add_client {
|
||||||
|
sn_rules = sn_rules,
|
||||||
geometry = function(wa)
|
geometry = function(wa)
|
||||||
return {
|
return {
|
||||||
width = wa.width - 10,
|
width = wa.width - 10,
|
||||||
|
@ -152,9 +289,10 @@ add_client {
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
|
|
||||||
-- The fourth large window should be placed at the top left corner (the whole
|
-- The fourth large client should be placed at the top left corner (the
|
||||||
-- workarea is occupied now).
|
-- whole workarea is occupied now).
|
||||||
add_client {
|
add_client {
|
||||||
|
sn_rules = sn_rules,
|
||||||
geometry = function(wa)
|
geometry = function(wa)
|
||||||
return {
|
return {
|
||||||
width = wa.width - 50,
|
width = wa.width - 50,
|
||||||
|
@ -165,6 +303,23 @@ add_client {
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
|
|
||||||
|
-- Kill test clients to prepare for the next iteration.
|
||||||
|
table.insert(tests, function(count)
|
||||||
|
if count <= 1 then
|
||||||
|
for _, data in ipairs(client_data) do
|
||||||
|
if data.c then
|
||||||
|
data.c:kill()
|
||||||
|
data.c = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if #client.get() == 0 then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
runner.run_steps(tests)
|
runner.run_steps(tests)
|
||||||
|
|
||||||
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
|
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
|
||||||
|
|
Loading…
Reference in New Issue