diff --git a/lib/wibox/layout/fixed.lua b/lib/wibox/layout/fixed.lua index ee910a347..58779174d 100644 --- a/lib/wibox/layout/fixed.lua +++ b/lib/wibox/layout/fixed.lua @@ -33,39 +33,71 @@ function fixed:layout(context, width, height) spacing_widget = spacing ~= 0 and self._private.spacing_widget or nil for k, v in pairs(self._private.widgets) do - local w, h = width - x, height - y + local w, h, local_spacing = width - x, height - y, spacing + + -- Some widget might be zero sized either because this is their + -- minimum space or just because they are really empty. In this case, + -- they must still be added to the layout. Otherwise, if their size + -- change and this layout is resizable, they are lost "forever" until + -- a full relayout is called on this fixed layout object. + local zero = false if is_y then if k ~= widgets_nr or not self._private.fill_space then h = select(2, base.fit_widget(self, context, v, w, h)) + zero = h == 0 end if y - spacing >= height then -- pop the spacing widget added in previous iteration if used if spacing_widget then table.remove(result) + + -- Avoid adding zero-sized widgets at an out-of-bound + -- position. + y = y - spacing + end + + -- Never display "random" widgets as soon as a non-zero sized + -- one doesn't fit. + if not zero then + break end - break end else if k ~= widgets_nr or not self._private.fill_space then w = select(1, base.fit_widget(self, context, v, w, h)) + zero = w == 0 end if x - spacing >= width then -- pop the spacing widget added in previous iteration if used if spacing_widget then table.remove(result) + + -- Avoid adding zero-sized widgets at an out-of-bound + -- position. + x = x - spacing + end + + -- Never display "random" widgets as soon as a non-zero sized + -- one doesn't fit. + if not zero then + break end - break end end - -- Place widget + if zero then + local_spacing = 0 + end + + -- Place widget, even if it has zero width/height. Otherwise + -- any layout change for zero-sized widget would become invisible. table.insert(result, base.place_widget_at(v, x, y, w, h)) - x = is_x and x + w + spacing or x - y = is_y and y + h + spacing or y + x = is_x and x + w + local_spacing or x + y = is_y and y + h + local_spacing or y -- Add the spacing widget (if needed) if k < widgets_nr and spacing_widget then diff --git a/spec/wibox/layout/fixed_spec.lua b/spec/wibox/layout/fixed_spec.lua index 3d50163ec..a272b7910 100644 --- a/spec/wibox/layout/fixed_spec.lua +++ b/spec/wibox/layout/fixed_spec.lua @@ -78,6 +78,7 @@ describe("wibox.layout.fixed", function() assert.widget_layout(layout, { 100, 20 }, { p(first, 0, 0, 100, 10), p(second, 0, 10, 100, 10), + p(third, 0, 20, 100, 0), }) end) end) @@ -121,6 +122,7 @@ describe("wibox.layout.fixed", function() p(first, 0, 0, 100, 10), p(spacing_widget, 0, 10, 100, 10), p(second, 0, 20, 100, 15), + p(third, 0, 35, 100, 0), }) end) end)