Repository: qtile/qtile

Issue:
Gaps on bar toggle
When you use a keybind to toggle a bar qtile does not correctly put the gaps in when the bar returns to the screen. 

I noticed that it seems to have issue with existing windows on the screen so the gaps worked fine around the top and side but on the bottom underneath where I had the bar return, my gap settings were ignored.

I guess that maybe the existing windows on the screen need to be redrawn to take in the bar again and have the correct gaps

Prior to toggle
![21-03-09_08-12_366x94](https://user-images.githubusercontent.com/80286865/110382903-a9b86c00-80af-11eb-8255-edfe31f6061d.png)

After toggling the bar
![21-03-09_08-12_358x113](https://user-images.githubusercontent.com/80286865/110382889-a58c4e80-80af-11eb-9887-112a0c688734.png)

The only way to get it back to normal is to restart qtile 



Discussion:
Bug reproduced.

### Quick workaround
Reload config  file.

### Analysis

The "show" method of the "Bar" class is suspicious.

When we hide the bar, the size of the bar is set to 0, losing the calculation of the size if a margin was specified (see _configure).
When we unhide the bar, the size is put to the initial size of the bar, whatsoever margin was specified.

### Possible Fix

When hidding, before setting the size to 0, save its value with an additionnal attribut.
When unhidding, set the size with this new attribut instead of the initial size.

Resolving patch:
diff --git a/libqtile/bar.py b/libqtile/bar.py
--- a/libqtile/bar.py
+++ b/libqtile/bar.py
@@ -164,6 +164,7 @@ def __init__(self, widgets, size, **config):
         self.saved_focus = None
         self.cursor_in = None
         self.window = None
+        self.size_calculated = 0
 
         self.queued_draws = 0
 
@@ -433,9 +434,10 @@ def is_show(self):
     def show(self, is_show=True):
         if is_show != self.is_show():
             if is_show:
-                self.size = self.initial_size
+                self.size = self.size_calculated
                 self.window.unhide()
             else:
+                self.size_calculated = self.size
                 self.size = 0
                 self.window.hide()
             self.screen.group.layout_all()


Test patch:
diff --git a/test/test_bar.py b/test/test_bar.py
--- a/test/test_bar.py
+++ b/test/test_bar.py
@@ -460,3 +460,39 @@ def test_configure_broken_widgets(manager_nospawn):
     for index, widget in enumerate(widget_list):
         if isinstance(widget, BrokenWidget):
             assert i["widgets"][index]["name"] == "configerrorwidget"
+
+
+def test_bar_hide_show_with_margin(manager_nospawn):
+    """ Check :
+            - the height of a horizontal bar with its margins,
+            - the ordinate of a unique window.
+        after 3 successive actions :
+            - creation
+            - hidding the bar
+            - unhidding the bar
+    """
+    config = GeomConf
+
+    config.screens = [
+        libqtile.config.Screen(
+            top=libqtile.bar.Bar(
+                [],
+                12,
+                margin=[5, 5, 5, 5]
+            )
+        )
+    ]
+
+    manager_nospawn.start(config)
+    manager_nospawn.test_window("w")
+
+    assert manager_nospawn.c.bar["top"].info().get("size") == 22
+    assert manager_nospawn.c.windows()[0]["y"] == 22
+
+    manager_nospawn.c.hide_show_bar("top")
+    assert manager_nospawn.c.bar["top"].info().get("size") == 0
+    assert manager_nospawn.c.windows()[0]["y"] == 0
+
+    manager_nospawn.c.hide_show_bar("top")
+    assert manager_nospawn.c.bar["top"].info().get("size") == 22
+    assert manager_nospawn.c.windows()[0]["y"] == 22