Repository: qtile/qtile

Issue:
Focus Issues in chrome during tiling
# Issue description

When chrome is not floating in a tiling layout (MonadTall/Tile), I can't click on various interface boxes. Here are 2 examples:
- Create a bookmark by clicking star. The Bookmark Added/Edit Bookmark popup appears. You cannot click on any option in this popup. All clicks are captured by the underlying chrome window instead.
- If I type in a query in the chrome bar, I can't click on any of the autocomplete suggestions. I can hit the down arrow to select them though

If chrome is floating and not tiled, then these problems do not occur.

# Qtile version

Tested on latest master: https://github.com/qtile/qtile/commit/e87b32b7c5a8652f077f09441705e20286f2d6f7
Present in 0.15.1

I noticed this problem a long time ago, so it's been around for a few versions.

# Configuration

Same as https://github.com/qtile/qtile/blob/master/libqtile/resources/default_config.py, except with MonadTall.
```
layouts = [
    # layout.Max(),
    # layout.Stack(num_stacks=2),
    # Try more layouts by unleashing below layouts.
    # layout.Bsp(),
    # layout.Columns(),
    # layout.Matrix(),
    layout.MonadTall(),
    # layout.MonadWide(),
    # layout.RatioTile(),
    # layout.Tile(),
    # layout.TreeTab(),
    # layout.VerticalTile(),
    # layout.Zoomy(),
]
```


Discussion:
Yes, I can confirm, thank you for writing it down, super annoying. Can you also confirm that it does not happen with the Max layout? @tych0, that's what I was telling you about during last FOSDEM.
@ramnes I can confirm it doesn't happen with the max layout.
Yep, I can reproduce this on other layouts. Never noticed because I use the max layout for my browser :)
I spent some time thinking about this today. It turns out that the bookmarks window is not actually an X window, so qtile isn't mis-focusing or anything.

That it only works in Max suggests that there's something about the offset calculation in chrome that's weird. One thing of note is that it has:

```_NET_WM_STATE(ATOM) = _NET_WM_STATE_MAXIMIZED_VERT, _NET_WM_STATE_MAXIMIZED_HORZ```

which suggests that it thinks it's fullscreened independently of axis. Qtile doesn't support these settings at all, so it just ignores them. This suggests to me again that maybe if it thinks it's fullscreend, something about the click math is off. I tried just removing these atoms (hoping that chrome would be smart enough to fix itself), but it didn't seem to work: https://github.com/tych0/qtile/commit/fceb46311d54251e3d4c3a7e42f75b3e628e8034

Anyway, that's all for now :)
I think I'm seeing the same issue. When I click on an password or credit card autocomplete dropdown in Chrome, the dropdown is dismissed, but the field is not filled out.
Seems to happen going back to at least v0.10.0
@tych0 If I click Chrome's own maximize/restore button, `_NET_WM_STATE(ATOM)` changes to empty, but I can still repro.

Another thing I notice is that the click seems to be passed thru to whatever was under the autocomplete overlay. e.g. on my bank's login page, the "Remember me" checkbox is under the autocomplete dropdown. If I click the autocomplete suggestion in just the right place, not only is the overlay dismissed, but the "Remember me" checkbox state is toggled.
This problem is driving me crazy. I'm using brave browser but has the same problem as chrome. Normally I use tiling layout for browser because I like the gaps. Now I have to use max layout and no gaps. Do you guys have some updates on this issue? Thanks so much.
+1 for this on brave
I'm afraid that Chrome `89.0.4389.90` is pretty much unusable with qtile regardless of tiling mode. In both max and monadtall, custom menus on all websites are unclickable. Example: the volume control in netflix can no longer be controlled.
I found middle mouse button sometimes works just fine or at least works by
opening the page in the tab. I am curious, what magic is chrome using?

Best wishes,
Andrius Semionovas


On Sat, Mar 27, 2021 at 12:08 AM Piyush Khandelwal ***@***.***>
wrote:

> I'm afraid that Chrome 89.0.4389.90 is pretty much unusable with qtile
> regardless of tiling mode. In both max and monadtall, a number of custom
> menus on various websites are unclickable. Example: the volume contron in
> netflix can no longer be controlled.
>
> —
> You are receiving this because you are subscribed to this thread.
> Reply to this email directly, view it on GitHub
> <https://github.com/qtile/qtile/issues/1824#issuecomment-808553249>, or
> unsubscribe
> <https://github.com/notifications/unsubscribe-auth/AAAJOLZ2FQ2IYOSPKQOKGADTFUAWPANCNFSM4PAK4VZA>
> .
>

Does https://github.com/qtile/qtile/pull/2506 fix it?
@m-col Thanks for the PR

I tried to switch qtile to the branch in that PR and encountered some problems but it won't start. same for the current qtile master. I assume there's something about my config it doesn't like, but looking at the qtile log with or without xtrace did not help.

I'll test with the default config soon and get back to you.
If you are going from the last release to master then you may have to run `qtile migrate` if something has changed in the way it is configured. Might be worth trying that.

On 210603 10:27, Piyush Khandelwal wrote:
***@***.*** Thanks for the PR
>
>I tried to switch qtile to the branch in that PR and encountered some problems but it won't start. same for the current qtile master. I assume there's something about my config it doesn't like, but looking at the qtile log with or without xtrace did not help.
>
>I'll test with the default config soon and get back to you.
>
>-- 
>You are receiving this because you were mentioned.
>Reply to this email directly or view it on GitHub:
>https://github.com/qtile/qtile/issues/1824#issuecomment-854049170

@m-col After some config wrangling, I was able to test both the latest stable release (0.17.0) and your PR branch. I'm afraid the 2 problems in this issue report are still not solved.

Since there is a minor change since the initial issue description, I'll reiterate the problems that currently exist in chrome:
- In a tiling layout, you can't click on some chrome interfaces. See the bookmark example in my initial issue description. **Different from my initial report making a window floating in a tiling layout no longer fixes the issue.**
- In more recent versions of chrome, various custom menus are not left-clickable. I believe this is true regardless of layout. The volume bar in Netflix is one such example. Middle-click works in these settings.
I just tried it and everything you mentioned in the first post got fixed for me. Are you sure you were using @m-col's branch, @piyushk? Also it's merged in master now so it may be easier to try. I will close the issue based on my own tests but feel free to comment and will try to understand what's happening if you still see this.
I can confirm that the issue persists for me with `mondatall` using the latest master with the default config (w/ `monadtall` uncommented) as well as my usual config.
```
piyushk@bird-person:~/code$ qtile --version
0.17.1.dev315+g67f97604
```
[config.py.txt](https://github.com/qtile/qtile/files/6610698/config.py.txt) (default config with `monadtall` enabled)
[config.py.piyushk.txt](https://github.com/qtile/qtile/files/6610709/config.py.piyushk.txt) (my usual config as is)
@ramnes @m-col chrome seems to have made adding bookmarks a two step process since the original report. Can you try the following? Click Star + Add/Edit Bookmark (works) + More/Remove/Folder Dropdown (does not work, click captured by underlying chrome window). 

I positioned the github "New Issue" button below the Name entry in the "Add/Edit Bookmark dialog", and clicking on the "Name" entry navigates to a new issue page.

I've confirmed that it works in max as expected. 
Sorry! Looks like I didn't test properly, shame on me. :) 

By the way, a simpler test is just to click on an autocompletion suggestion in the navigation bar.
> * In more recent versions of chrome, various custom menus are not left-clickable. I believe this is true regardless of layout. The volume bar in Netflix is one such example. Middle-click works in these settings.

I'm seeing this issue with custom menus using the stable version of Chrome (`v91.0.4472.101-1`) but the beta (`92.0.4515.40-1`) and dev (`93.0.4535.3-1`) versions from the AUR are working correctly! Bookmarks and other chrome interfaces are still not working though.

I'm using `0.17.1.dev319+g6a206138` via the `qtile-git` AUR package.
I used to have this issue but it has recently been fixed for me. On Arch Linux; qtile package version 0.18.1-3; browsers tested: brave nightly (`brave-nightly-bin` from AUR), chromium.
Works for me, too, after upgrading to qtile v0.18.1.
Awesome, thank you for reporting! I believe https://github.com/qtile/qtile/commit/541a3ad1b189675218c5b179ef741b54076a1705 will have fixed it.

If anybody continues to have issues feel free to post and we can re-open.
I still got the issue (easily reproducible with Web form login completions) using latest `brave-bin` and `qtile`.

Edit: given the length of the current thread, let me know whether a new issue is more customary as well as the needed logs or additional details that I could provide for you. For the time being I ignore `qtile` in `pacman.conf` and remain on 17.0 which is the only one I'm able to run atm.
> remain on 17.0 

OK, phew! This bug was fixed after 0.17 was released, so you'll need to upgrade to have this fixed.

What troubles are you having with updating? If you have config changes that are needed, many of them can get corrected automatically if you run `qtile migrate` with the new version before restarting qtile. This will modify your config (it is interactive so you can accept/reject individual changes).

Resolving patch:
diff --git a/libqtile/core/state.py b/libqtile/core/state.py
--- a/libqtile/core/state.py
+++ b/libqtile/core/state.py
@@ -30,6 +30,7 @@ class QtileState:
 
     If `restart` is True, the current set of groups will be saved in the state. This is
     useful when restarting for Qtile version updates rather than reloading the config.
+    ScratchPad groups are saved for both reloading and restarting.
     """
     def __init__(self, qtile, restart=True):
         self.groups = []
@@ -39,12 +40,11 @@ def __init__(self, qtile, restart=True):
         self.orphans = []
         self.restart = restart  # True when restarting, False when config reloading
 
-        if restart:
-            for group in qtile.groups:
-                if isinstance(group, ScratchPad):
-                    self.scratchpads[group.name] = group.get_state(restart)
-                else:
-                    self.groups.append((group.name, group.layout.name, group.label))
+        for group in qtile.groups:
+            if isinstance(group, ScratchPad):
+                self.scratchpads[group.name] = group.get_state()
+            elif restart:
+                self.groups.append((group.name, group.layout.name, group.label))
 
         for index, screen in enumerate(qtile.screens):
             self.screens[index] = screen.group.name
@@ -90,7 +90,7 @@ def handle_orphan_dropdowns(self, client):
         """
         Remove any windows from now non-existent scratchpad groups.
         """
-        client_wid = client.window.wid
+        client_wid = client.wid
         if client_wid in self.orphans:
             self.orphans.remove(client_wid)
             client.group = None
diff --git a/libqtile/scratchpad.py b/libqtile/scratchpad.py
--- a/libqtile/scratchpad.py
+++ b/libqtile/scratchpad.py
@@ -346,7 +346,7 @@ def cmd_dropdown_info(self, name=None):
         else:
             raise ValueError('No DropDown named "%s".' % name)
 
-    def get_state(self, restart):
+    def get_state(self):
         """
         Get the state of existing dropdown windows. Used for restoring state across
         Qtile restarts (`restart` == True) or config reloads (`restart` == False).


Test patch:
diff --git a/test/configs/reloading.py b/test/configs/reloading.py
--- a/test/configs/reloading.py
+++ b/test/configs/reloading.py
@@ -3,8 +3,20 @@
 # The exported configuration variables have a different value depending on whether
 # libqtile has a 'test_data' attribute (see below)
 
+import sys
+from pathlib import Path
+
 from libqtile import bar, layout, qtile, widget
-from libqtile.config import Drag, Group, Key, Match, Rule, Screen
+from libqtile.config import (
+    Drag,
+    DropDown,
+    Group,
+    Key,
+    Match,
+    Rule,
+    ScratchPad,
+    Screen,
+)
 from libqtile.dgroups import simple_key_binder
 from libqtile.lazy import lazy
 
@@ -15,7 +27,7 @@
 groups = [Group(i) for i in "12345"]
 
 layouts = [
-    layout.Columns(border_focus_stack=['#d75f5f', '#8f3d3d'], border_width=4),
+    layout.Columns(border_focus_stack=["#d75f5f", "#8f3d3d"], border_width=4),
 ]
 
 screens = [
@@ -24,7 +36,7 @@
             [
                 widget.CurrentLayout(),
                 widget.GroupBox(),
-                widget.Clock(format='%Y-%m-%d %a %I:%M %p'),
+                widget.Clock(format="%Y-%m-%d %a %I:%M %p"),
                 widget.QuickExit(),
             ],
             24,
@@ -35,13 +47,21 @@
 widget_defaults = dict()
 
 mouse = [
-    Drag(["mod4"], "Button1", lazy.window.set_position_floating(),
-         start=lazy.window.get_position()),
+    Drag(
+        ["mod4"],
+        "Button1",
+        lazy.window.set_position_floating(),
+        start=lazy.window.get_position(),
+    ),
 ]
 
+windowpy = Path(__file__).parent.parent / "scripts" / "window.py"
+script = " ".join([sys.executable, windowpy.as_posix(), "--name", "dd", "dd", "normal"])
+dropdowns = [DropDown("dropdown1", script)]
+
 dgroups_key_binder = None
 dgroups_app_rules = []
-floating_layout = layout.Floating(float_rules=[Match(title='one')])
+floating_layout = layout.Floating(float_rules=[Match(title="one")])
 wmname = "LG3D"
 
 
@@ -59,14 +79,22 @@
         Screen(top=bar.Bar([widget.CurrentLayout()], 32)),
     ]
 
-    widget_defaults['background'] = '#ff0000'
+    widget_defaults["background"] = "#ff0000"
 
     mouse.append(
-        Drag(["mod4"], "Button3", lazy.window.set_size_floating(),
-             start=lazy.window.get_size()),
+        Drag(
+            ["mod4"],
+            "Button3",
+            lazy.window.set_size_floating(),
+            start=lazy.window.get_size(),
+        ),
     )
 
+    dropdowns.append(DropDown("dropdown2", script))
+
     dgroups_key_binder = simple_key_binder
-    dgroups_app_rules = [Rule(Match(wm_class='test'), float=True)]
+    dgroups_app_rules = [Rule(Match(wm_class="test"), float=True)]
     floating_layout = layout.Floating()
     wmname = "TEST"
+
+groups.append(ScratchPad("S", dropdowns))
diff --git a/test/test_manager.py b/test/test_manager.py
--- a/test/test_manager.py
+++ b/test/test_manager.py
@@ -1088,29 +1088,36 @@ def test_cmd_reload_config(manager_nospawn):
     # Here we just want to check configurables are being updated within the live Qtile
     manager_nospawn.start(lambda: BareConfig(file_path=configs_dir / "reloading.py"))
 
+    @Retry(ignore_exceptions=(AssertionError,))
+    def assert_dd_appeared():
+        assert "dd" in manager_nospawn.c.group.info()["windows"]
+
     # Original config
     assert manager_nospawn.c.eval("len(self.keys_map)") == (True, '1')
     assert manager_nospawn.c.eval("len(self.mouse_map)") == (True, '1')
-    assert "".join(manager_nospawn.c.groups().keys()) == "12345"
+    assert "".join(manager_nospawn.c.groups().keys()) == "12345S"
     assert len(manager_nospawn.c.group.info()['layouts']) == 1
     assert manager_nospawn.c.widget['clock'].eval('self.background') == (True, 'None')
     screens = manager_nospawn.c.screens()[0]
     assert screens['gaps']['bottom'][3] == 24 and not screens['gaps']['top']
     assert len(manager_nospawn.c.internal_windows()) == 1
     assert manager_nospawn.c.eval('self.dgroups.key_binder') == (True, 'None')
-    assert manager_nospawn.c.eval('len(self.dgroups.rules)') == (True, '5')
+    assert manager_nospawn.c.eval('len(self.dgroups.rules)') == (True, '6')
     manager_nospawn.test_window("one")
     assert manager_nospawn.c.window.info()['floating'] is True
     manager_nospawn.c.window.kill()
     if manager_nospawn.backend.name == "x11":
         assert manager_nospawn.c.eval('self.core.wmname') == (True, 'LG3D')
+    manager_nospawn.c.group['S'].dropdown_toggle('dropdown1')  # Spawn dropdown
+    assert_dd_appeared()
+    manager_nospawn.c.group['S'].dropdown_toggle('dropdown1')  # Send it to ScratchPad
 
     # Reload #1 - with libqtile.qtile.test_data
     manager_nospawn.c.eval("self.test_data = 1")
     manager_nospawn.c.reload_config()
     assert manager_nospawn.c.eval("len(self.keys_map)") == (True, '2')
     assert manager_nospawn.c.eval("len(self.mouse_map)") == (True, '2')
-    assert "".join(manager_nospawn.c.groups().keys()) == "123456789"
+    assert "".join(manager_nospawn.c.groups().keys()) == "123456789S"
     assert len(manager_nospawn.c.group.info()['layouts']) == 2
     assert manager_nospawn.c.widget['currentlayout'].eval('self.background') == (True, '#ff0000')
     screens = manager_nospawn.c.screens()[0]
@@ -1118,12 +1125,17 @@ def test_cmd_reload_config(manager_nospawn):
     assert len(manager_nospawn.c.internal_windows()) == 1
     _, binder = manager_nospawn.c.eval('self.dgroups.key_binder')
     assert 'function simple_key_binder' in binder
-    assert manager_nospawn.c.eval('len(self.dgroups.rules)') == (True, '10')
+    assert manager_nospawn.c.eval('len(self.dgroups.rules)') == (True, '11')
     manager_nospawn.test_window("one")
     assert manager_nospawn.c.window.info()['floating'] is False
     manager_nospawn.c.window.kill()
     if manager_nospawn.backend.name == "x11":
         assert manager_nospawn.c.eval('self.core.wmname') == (True, 'TEST')
+    manager_nospawn.c.group['S'].dropdown_toggle('dropdown2')  # Spawn second dropdown
+    assert_dd_appeared()
+    manager_nospawn.c.group['S'].dropdown_toggle('dropdown1')  # Send it to ScratchPad
+    assert 'dd' in manager_nospawn.c.groups()['S']['windows']
+    assert 'dd' in manager_nospawn.c.groups()['S']['windows']
 
     # Reload #2 - back to without libqtile.qtile.test_data
     manager_nospawn.c.eval("del self.test_data")
@@ -1131,16 +1143,18 @@ def test_cmd_reload_config(manager_nospawn):
     assert manager_nospawn.c.eval("len(self.keys_map)") == (True, '1')
     assert manager_nospawn.c.eval("len(self.mouse_map)") == (True, '1')
     # The last four groups persist within QtileState
-    assert "".join(manager_nospawn.c.groups().keys()) == "12345"
+    assert "".join(manager_nospawn.c.groups().keys()) == "12345S"
     assert len(manager_nospawn.c.group.info()['layouts']) == 1
     assert manager_nospawn.c.widget['clock'].eval('self.background') == (True, 'None')
     screens = manager_nospawn.c.screens()[0]
     assert screens['gaps']['bottom'][3] == 24 and not screens['gaps']['top']
     assert len(manager_nospawn.c.internal_windows()) == 1
     assert manager_nospawn.c.eval('self.dgroups.key_binder') == (True, 'None')
-    assert manager_nospawn.c.eval('len(self.dgroups.rules)') == (True, '5')
+    assert manager_nospawn.c.eval('len(self.dgroups.rules)') == (True, '6')
     manager_nospawn.test_window("one")
     assert manager_nospawn.c.window.info()['floating'] is True
     manager_nospawn.c.window.kill()
     if manager_nospawn.backend.name == "x11":
         assert manager_nospawn.c.eval('self.core.wmname') == (True, 'LG3D')
+    assert 'dd' in manager_nospawn.c.groups()['S']['windows']  # First dropdown persists
+    assert 'dd' in manager_nospawn.c.groups()['1']['windows']  # Second orphans to group