Repository: qtile/qtile

Issue:
window.focus() does not necessarily update focus_history
# Issue description

When using `qtile.current_window.focus(warp=False)` (or `warp=True`), the `current_group.focus_history` list is not necessarily updated, particularly in the case of floating windows. 

This is particularly important as the definition of `current_window` gets defined by the `focus_history` list.

# Qtile version

0.17.0

To demonstrate, I have a function that switches between "normal" windows and floating windows (akin to i3's `focus mode_toggle` command).

## Using `group.focus(window)`:
The following works as expected
```python
def toggle_focus_floating():
    '''Toggle focus between floating window and other windows in group'''

    @lazy.function
    def _toggle_focus_floating(qtile):
        group = qtile.current_group
        switch = 'non-float' if qtile.current_window.floating else 'float'
        logger.warning(f'toggle_focus_floating: switch = {switch}\t current_window: {qtile.current_window}')
        logger.warning(f'focus_history: {group.focus_history}')

        for win in reversed(group.focus_history):
            logger.warning(f'{win}: {win.floating}')
            if switch=='float' and win.floating:
                group.focus(win)
                return
            if switch=='non-float' and not win.floating:
                group.focus(win)
                return
    return _toggle_focus_floating
```
![20210601_qtile_toggle_floating_correct](https://user-images.githubusercontent.com/20801821/120357588-d8b33800-c2c2-11eb-99c6-476be0d3e753.gif)

<details>
<summary>Log Output</summary>

```log
2021-06-01 10:09:44,012 WARNING libqtile lifecycle.py:_atexit():L34 Restarting Qtile with os.execv(...)
2021-06-01 10:09:44,503 WARNING libqtile config.py:<module>():L28 Number of monitors: 2
2021-06-01 10:10:02,099 WARNING libqtile functions.py:_toggle_focus_floating():L119 toggle_focus_floating: switch = float        current_window: Window('Terminal - ')
2021-06-01 10:10:02,100 WARNING libqtile functions.py:_toggle_focus_floating():L120 focus_history: [Window('Peek'), Window('KCharSelect'), Window('Terminal - ')]
2021-06-01 10:10:02,100 WARNING libqtile functions.py:_toggle_focus_floating():L124 Window('Terminal - '): False
2021-06-01 10:10:02,100 WARNING libqtile functions.py:_toggle_focus_floating():L124 Window('KCharSelect'): True
2021-06-01 10:10:03,568 WARNING libqtile functions.py:_toggle_focus_floating():L119 toggle_focus_floating: switch = non-float    current_window: Window('KCharSelect')
2021-06-01 10:10:03,568 WARNING libqtile functions.py:_toggle_focus_floating():L120 focus_history: [Window('Peek'), Window('Terminal - '), Window('KCharSelect')]
2021-06-01 10:10:03,568 WARNING libqtile functions.py:_toggle_focus_floating():L124 Window('KCharSelect'): True
2021-06-01 10:10:03,568 WARNING libqtile functions.py:_toggle_focus_floating():L124 Window('Terminal - '): False
2021-06-01 10:10:04,924 WARNING libqtile functions.py:_toggle_focus_floating():L119 toggle_focus_floating: switch = float        current_window: Window('Terminal - ')
2021-06-01 10:10:04,924 WARNING libqtile functions.py:_toggle_focus_floating():L120 focus_history: [Window('Peek'), Window('KCharSelect'), Window('Terminal - ')]
2021-06-01 10:10:04,924 WARNING libqtile functions.py:_toggle_focus_floating():L124 Window('Terminal - '): False
2021-06-01 10:10:04,925 WARNING libqtile functions.py:_toggle_focus_floating():L124 Window('KCharSelect'): True
2021-06-01 10:10:06,294 WARNING libqtile functions.py:_toggle_focus_floating():L119 toggle_focus_floating: switch = non-float    current_window: Window('KCharSelect')
2021-06-01 10:10:06,295 WARNING libqtile functions.py:_toggle_focus_floating():L120 focus_history: [Window('Peek'), Window('Terminal - '), Window('KCharSelect')]
2021-06-01 10:10:06,295 WARNING libqtile functions.py:_toggle_focus_floating():L124 Window('KCharSelect'): True
2021-06-01 10:10:06,295 WARNING libqtile functions.py:_toggle_focus_floating():L124 Window('Terminal - '): False
```

</details>

## Using `window.focus(warp)`
The following does not work as expected:
```python
def toggle_focus_floating():
    '''Toggle focus between floating window and other windows in group'''

    @lazy.function
    def _toggle_focus_floating(qtile):
        group = qtile.current_group
        switch = 'non-float' if qtile.current_window.floating else 'float'
        logger.warning(f'toggle_focus_floating: switch = {switch}\t current_window: {qtile.current_window}')
        logger.warning(f'focus_history: {group.focus_history}')

        for win in reversed(group.focus_history):
            logger.warning(f'{win}: {win.floating}')
            if switch=='float' and win.floating:
                win.focus(warp=False)
                return
            if switch=='non-float' and not win.floating:
                win.focus(warp=False)
                return
    return _toggle_focus_floating
```

Here, the focus does successfully change to the floating window, but `current_window` does not change since `focus_history` is not updated.
![20210601_qtile_toggle_floating_incorrect](https://user-images.githubusercontent.com/20801821/120357620-e10b7300-c2c2-11eb-83c5-f63aee78b263.gif)


<details>
<summary>Log Output</summary>

```log
2021-06-01 10:14:50,048 WARNING libqtile functions.py:_toggle_focus_floating():L119 toggle_focus_floating: switch = float        current_window: Window('Terminal - ')
2021-06-01 10:14:50,049 WARNING libqtile functions.py:_toggle_focus_floating():L120 focus_history: [Window('Peek'), Window('KCharSelect'), Window('Terminal - ')]
2021-06-01 10:14:50,049 WARNING libqtile functions.py:_toggle_focus_floating():L124 Window('Terminal - '): False
2021-06-01 10:14:50,049 WARNING libqtile functions.py:_toggle_focus_floating():L124 Window('KCharSelect'): True
2021-06-01 10:14:51,777 WARNING libqtile functions.py:_toggle_focus_floating():L119 toggle_focus_floating: switch = float        current_window: Window('Terminal - ')
2021-06-01 10:14:51,777 WARNING libqtile functions.py:_toggle_focus_floating():L120 focus_history: [Window('Peek'), Window('KCharSelect'), Window('Terminal - ')]
2021-06-01 10:14:51,778 WARNING libqtile functions.py:_toggle_focus_floating():L124 Window('Terminal - '): False
2021-06-01 10:14:51,778 WARNING libqtile functions.py:_toggle_focus_floating():L124 Window('KCharSelect'): True
2021-06-01 10:14:53,367 WARNING libqtile functions.py:_toggle_focus_floating():L119 toggle_focus_floating: switch = float        current_window: Window('Terminal - ')
2021-06-01 10:14:53,367 WARNING libqtile functions.py:_toggle_focus_floating():L120 focus_history: [Window('Peek'), Window('KCharSelect'), Window('Terminal - ')]
2021-06-01 10:14:53,367 WARNING libqtile functions.py:_toggle_focus_floating():L124 Window('Terminal - '): False
2021-06-01 10:14:53,368 WARNING libqtile functions.py:_toggle_focus_floating():L124 Window('KCharSelect'): True
```

</details>

# Other things to note
Note that for the above GIFs, `cursor_warp = False` in my `config.py`. So for the `window.focus()` example, the cursor warps to the _previously_ focused window instead of the new one, while the `group.focus(window)` warps the cursor to the newly focused window. The warping is desired (I was planning on manually implementing it), but I'm not sure why it's happening.



Discussion:

Resolving patch:
diff --git a/libqtile/backend/wayland/window.py b/libqtile/backend/wayland/window.py
--- a/libqtile/backend/wayland/window.py
+++ b/libqtile/backend/wayland/window.py
@@ -394,6 +394,8 @@ def focus(self, warp: bool) -> None:
                 self.y + self.height // 2,
             )
 
+        if self.group:
+            self.group.current_window = self
         hook.fire("client_focus", self)
 
     def place(self, x, y, width, height, borderwidth, bordercolor,
diff --git a/libqtile/backend/x11/window.py b/libqtile/backend/x11/window.py
--- a/libqtile/backend/x11/window.py
+++ b/libqtile/backend/x11/window.py
@@ -914,6 +914,9 @@ def focus(self, warp: bool) -> None:
                 self.window.set_property('_NET_WM_STATE', state)
 
         self.qtile.core._root.set_property("_NET_ACTIVE_WINDOW", self.window.wid)
+
+        if self.group:
+            self.group.current_window = self
         hook.fire("client_focus", self)
 
     def cmd_focus(self, warp=None):


Test patch: