Skip to content

Commit

Permalink
Add ability to override floating rules
Browse files Browse the repository at this point in the history
Some float rules (e.g. fixed size/aspect ratio) can be too broad and
users may want exceptions to these rules. It is possible to do this with
hooks but they can become unwieldy with multiple exceptions.

This PR adds an `override_rules` argument to the floating layout. Where
a window matches one of these rules then window will not be floated.
  • Loading branch information
elParaguayo committed Apr 28, 2024
1 parent e6c8d6d commit 37a871c
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 3 deletions.
1 change: 1 addition & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ Qtile x.xx.x, released XXXX-XX-XX:
the `qtile cmd-obj` command line
- Add `Plasma` layout. The original layout (https://github.com/numirias/qtile-plasma) appears to be unmaintained
so we have added this to the main codebase.
- Add ability to define exceptions to rules for floating windows.
* bugfixes

Qtile 0.25.0, released 2024-04-06:
Expand Down
20 changes: 18 additions & 2 deletions libqtile/layout/floating.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ class Floating(Layout):
Match(func=lambda c: c.has_fixed_ratio()),
]

default_override_rules: list[Match] = []

defaults = [
("border_focus", "#0000ff", "Border colour(s) for the focused window."),
("border_normal", "#000000", "Border colour(s) for un-focused windows."),
Expand All @@ -74,7 +76,11 @@ class Floating(Layout):
]

def __init__(
self, float_rules: list[Match] | None = None, no_reposition_rules=None, **config
self,
float_rules: list[Match] | None = None,
override_rules: list[Match] | None = None,
no_reposition_rules=None,
**config,
):
"""
If you have certain apps that you always want to float you can provide
Expand All @@ -98,6 +104,10 @@ def __init__(
Specify these in the ``floating_layout`` in your config.
Exceptions to match rules can be set by providing a list of ``Match`` objects
to ``override_rules``. If a client matches any of these rules then it will not be
floated, regardles of whether it matches a rule in ``float_rules``.
Floating layout will try to center most of floating windows by default,
but if you don't want this to happen for certain windows that are
centered by mistake, you can use ``no_reposition_rules`` option to
Expand All @@ -111,13 +121,19 @@ def __init__(
if float_rules is None:
float_rules = self.default_float_rules

if override_rules is None:
override_rules = self.default_override_rules

self.float_rules = float_rules
self.override_rules = override_rules
self.no_reposition_rules = no_reposition_rules or []
self.add_defaults(Floating.defaults)

def match(self, win):
"""Used to default float some windows"""
return any(win.match(rule) for rule in self.float_rules)
matches = any(win.match(rule) for rule in self.float_rules)
overrides = any(win.match(rule) for rule in self.override_rules)
return matches and not overrides

def find_clients(self, group):
"""Find all clients belonging to a given group"""
Expand Down
14 changes: 13 additions & 1 deletion test/test_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
# SOFTWARE.

import logging
import re
from pathlib import Path

import pytest
Expand Down Expand Up @@ -69,7 +70,9 @@ class ManagerConfig(Config):
*libqtile.layout.floating.Floating.default_float_rules,
Match(wm_class="float"),
Match(title="float"),
]
Match(title=re.compile(r"^floatthis")),
],
override_rules=[Match(title=re.compile(r".*nofloat$"))],
)
keys = [
libqtile.config.Key(
Expand Down Expand Up @@ -918,6 +921,15 @@ def test_move_floating(manager):
assert manager.c.window.info()["y"] == 20


@manager_config
def test_float_overrides(manager):
manager.test_window("floatthiswindow-nofloat")
assert manager.c.window.info()["floating"] is False

manager.test_window("floatthiswindow")
assert manager.c.window.info()["floating"] is True


@manager_config
def test_one_screen(manager):
assert len(manager.c.get_screens()) == 1
Expand Down

0 comments on commit 37a871c

Please sign in to comment.