Skip to content

Commit

Permalink
Allow bar to float above windows (#4539)
Browse files Browse the repository at this point in the history
Adds `reserve` keyword to `Bar`. Value is `True` by default and, when
set to `False`, the bar will be drawn above windows rather than
reserving screen space.
  • Loading branch information
elParaguayo committed Nov 4, 2023
1 parent 8547c21 commit 8ab739b
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 10 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ Qtile x.xx.x, released XXXX-XX-XX:
- `func: Callable`: Enable call when the result of the callable evaluates to True
- `condition: bool`: a boolean value to determine whether the lazy object should be run. Unlike `func`, the
condition is evaluated once when the config file is first loaded.
- Add ability to have bar drawns over windows by adding `reserve=False` to bar's config to
stop the bar reserving screen space.
* bugfixes
- Fix two bugs in stacking transient windows in X11
- Checking configs containing `qtile.core.name` with `python config.py` don't fail anymore (but `qtile.core.name`
Expand Down
17 changes: 13 additions & 4 deletions libqtile/bar.py
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,11 @@ class Bar(Gap, configurable.Configurable, CommandObject):
("margin", 0, "Space around bar as int or list of ints [N E S W]."),
("border_color", "#000000", "Border colour as str or list of str [N E S W]"),
("border_width", 0, "Width of border as int of list of ints [N E S W]"),
(
"reserve",
True,
"Reserve screen space (when set to 'False', bar will be drawn above windows).",
),
]

def __init__(self, widgets: list[_Widget], size: int, **config: Any) -> None:
Expand Down Expand Up @@ -343,8 +348,8 @@ def _configure(self, qtile: Qtile, screen: Screen, reconfigure: bool = False) ->
)
qtile.renamed_widgets.clear()

hook.subscribe.setgroup(self.keep_below)
hook.subscribe.startup_complete(self.keep_below)
hook.subscribe.setgroup(self.set_layer)
hook.subscribe.startup_complete(self.set_layer)

self._remove_crashed_widgets(crashed_widgets)
self.draw()
Expand Down Expand Up @@ -765,9 +770,13 @@ def fake_button_press(
# TODO: drop the screen and position args, update relevant tests
self.process_button_click(x, y, button)

def keep_below(self) -> None:
def set_layer(self) -> None:
if self.window:
self.window.keep_below(enable=True)
if self.reserve:
self.window.keep_below(enable=True)
else:
# Bar is not reserving screen space so let's keep above other windows
self.window.keep_above(enable=True)


BarType = typing.Union[Bar, Gap]
16 changes: 10 additions & 6 deletions libqtile/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -490,27 +490,31 @@ def gaps(self) -> Iterable[BarType]:

@property
def dx(self) -> int:
return self.x + self.left.size if self.left else self.x
if self.left and getattr(self.left, "reserve", True):
return self.x + self.left.size
return self.x

@property
def dy(self) -> int:
return self.y + self.top.size if self.top else self.y
if self.top and getattr(self.top, "reserve", True):
return self.y + self.top.size
return self.y

@property
def dwidth(self) -> int:
val = self.width
if self.left:
if self.left and getattr(self.left, "reserve", True):
val -= self.left.size
if self.right:
if self.right and getattr(self.right, "reserve", True):
val -= self.right.size
return val

@property
def dheight(self) -> int:
val = self.height
if self.top:
if self.top and getattr(self.top, "reserve", True):
val -= self.top.size
if self.bottom:
if self.bottom and getattr(self.bottom, "reserve", True):
val -= self.bottom.size
return val

Expand Down
27 changes: 27 additions & 0 deletions test/test_bar.py
Original file line number Diff line number Diff line change
Expand Up @@ -632,3 +632,30 @@ class UnsupportedConfig(BareConfig):
manager_nospawn.start(UnsupportedConfig)

assert len(manager_nospawn.c.bar["top"].info()["widgets"]) == 0


class DontReserveBarConfig(GBConfig):
screens = [
libqtile.config.Screen(
top=libqtile.bar.Bar([libqtile.widget.Spacer()], 50, reserve=False),
)
]
layouts = [libqtile.layout.max.Max()]


dont_reserve_bar_config = pytest.mark.parametrize(
"manager", [DontReserveBarConfig], indirect=True
)


@dont_reserve_bar_config
def test_dont_reserve_bar(manager):
"""Bar is drawn over tiled windows."""
manager.test_window("Window")
info = manager.c.window.info()

# Window should fill entire screen
assert info["x"] == 0
assert info["y"] == 0
assert info["width"] == 800
assert info["height"] == 600

0 comments on commit 8ab739b

Please sign in to comment.