Repository: qtile/qtile

Issue:
Support for single_margin in bsp layout
The MonadTall layout supports `single_margin` for configuring a specific margin (i.e. `0`) when there is only one window. And for the Columns layout there's the same option but it's called `margin_on_single`. I'd like to request the same configuration option for the bsp layout.


Discussion:
Seems reasonable and, hopefully, not too hard to implement.

Resolving patch:
diff --git a/libqtile/layout/bsp.py b/libqtile/layout/bsp.py
--- a/libqtile/layout/bsp.py
+++ b/libqtile/layout/bsp.py
@@ -153,6 +153,11 @@ class Bsp(Layout):
         ("border_normal", "#220000", "Border colour(s) for un-focused windows."),
         ("border_width", 2, "Border width."),
         ("border_on_single", False, "Draw border when there is only one window."),
+        (
+            "margin_on_single",
+            None,
+            "Margin when there is only one window (int or list of ints [N E S W], 'None' to use 'margin' value).",
+        ),
         ("margin", 0, "Margin of the layout (int or list of ints [N E S W])."),
         ("ratio", 1.6, "Width/height ratio that defines the partition direction."),
         ("grow_amount", 10, "Amount by which to grow a window/column."),
@@ -165,6 +170,8 @@ def __init__(self, **config):
         self.add_defaults(Bsp.defaults)
         self.root = _BspNode()
         self.current = self.root
+        if self.margin_on_single is None:
+            self.margin_on_single = self.margin
 
     def clone(self, group):
         c = Layout.clone(self, group)
@@ -209,6 +216,8 @@ def configure(self, client, screen_rect):
         node = self.get_node(client)
         color = self.border_focus if client.has_focus else self.border_normal
         border = 0 if node is self.root and not self.border_on_single else self.border_width
+        margin = self.margin_on_single if node is self.root else self.margin
+
         if node is not None:
             client.place(
                 node.x,
@@ -217,7 +226,7 @@ def configure(self, client, screen_rect):
                 node.h - 2 * border,
                 border,
                 color,
-                margin=self.margin,
+                margin=margin,
             )
         client.unhide()
 


Test patch:
diff --git a/test/layouts/test_bsp.py b/test/layouts/test_bsp.py
--- a/test/layouts/test_bsp.py
+++ b/test/layouts/test_bsp.py
@@ -33,9 +33,7 @@ class BspConfig(Config):
         libqtile.config.Group("c"),
         libqtile.config.Group("d"),
     ]
-    layouts = [
-        layout.Bsp(),
-    ]
+    layouts = [layout.Bsp(), layout.Bsp(margin_on_single=10)]
     floating_layout = libqtile.resources.default_config.floating_layout
     keys = []
     mouse = []
@@ -66,3 +64,22 @@ def test_bsp_window_focus_cycle(manager):
 
     # assert window focus cycle, according to order in layout
     assert_focus_path(manager, "two", "float1", "float2", "one", "three")
+
+
+@bsp_config
+def test_bsp_margin_on_single(manager):
+    manager.test_window("one")
+
+    info = manager.c.window.info()
+    assert info["x"] == 0
+    assert info["y"] == 0
+
+    manager.c.next_layout()
+    info = manager.c.window.info()
+    assert info["x"] == 10
+    assert info["y"] == 10
+
+    manager.test_window("two")
+    # No longer single window so margin reverts to "margin" which is 0
+    info = manager.c.window.info()
+    assert info["x"] == 0