From 33a39ce38d8aa1d207aa3c209ee3204086abdf57 Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Tue, 16 Jan 2018 02:38:17 -0500 Subject: [PATCH] placement: Make sure `next_to` result is consistent across calls It depended on a hash `pairs` iteration. This caused an issue only when the primary position wasn't available. --- lib/awful/placement.lua | 48 +++++++++++++++++++++++++++++++---------- 1 file changed, 37 insertions(+), 11 deletions(-) diff --git a/lib/awful/placement.lua b/lib/awful/placement.lua index 47ee330e2..26f95e105 100644 --- a/lib/awful/placement.lua +++ b/lib/awful/placement.lua @@ -1432,39 +1432,65 @@ function placement.next_to(d, args) local regions = get_relative_regions(wgeo, mode, is_absolute) + -- Order the regions with the preferred_positions, then the defaults + local sorted_regions, default_positions = {}, {"left", "right", "bottom", "top"} + + for _, pos in ipairs(original_pos or {}) do + for idx, def in ipairs(default_positions) do + if def == pos then + table.remove(default_positions, idx) + break + end + end + + table.insert(sorted_regions, {name = pos, region = regions[pos]}) + end + + for _, pos in ipairs(default_positions) do + table.insert(sorted_regions, {name = pos, region = regions[pos]}) + end + -- Check each possible slot around the drawable (8 total), see what fits -- and order them by preferred_positions local does_fit = {} - for k,v in pairs(regions) do + for _, pos in ipairs(sorted_regions) do local geo, dir, fit -- Try each anchor until one that fits is found for _, anchor in ipairs(preferred_anchors) do - geo, dir = outer_positions[k.."_"..anchor](v, dgeo.width, dgeo.height) + geo, dir = outer_positions[pos.name.."_"..anchor](pos.region, dgeo.width, dgeo.height) + geo.width, geo.height = dgeo.width, dgeo.height - fit = fit_in_bounding(v.screen, geo, args) + + fit = fit_in_bounding(pos.region.screen, geo, args) + if fit then break end end - does_fit[k] = fit and {geo, dir} or nil + does_fit[pos.name] = fit and {geo, dir} or nil - if fit and preferred_positions[k] and preferred_positions[k] < pref_idx then - pref_idx = preferred_positions[k] - pref_name = k + if fit and preferred_positions[pos.name] and preferred_positions[pos.name] < pref_idx then + pref_idx = preferred_positions[pos.name] + pref_name = pos.name end -- No need to continue - if fit and preferred_positions[k] == 1 then break end + if fit then break end end - local pos_name = pref_name or next(does_fit) - local ngeo, dir = unpack(does_fit[pos_name] or {}) --FIXME why does this happen + local ngeo, dir = unpack(does_fit[pref_name] or {}) --FIXME why does this happen + + -- The requested placement isn't possible due to the lack of space, better + -- do nothing an try random things + if not ngeo then return end + + remove_border(d, args, ngeo) geometry_common(d, args, ngeo) attach(d, placement.next_to, args) - return fix_new_geometry(ngeo, args, true), pos_name, dir + return fix_new_geometry(ngeo, args, true), pref_name, dir end --- Restore the geometry.