Skip to content

Commit

Permalink
Config: Do not match on substrings (#4603)
Browse files Browse the repository at this point in the history
For some reason in the Match class we match on substrings. So e.g. for
wm_class if value = ["test1", "bogus"] and our candidate is "test1what" we
would loop through the list and determine that the test passes because
test1 is a substring of test1what. This leads to confusion and bugs
such as #4602 and #2670.

In the current situation even the default config is pretty broken on
X11 with the float rules (e.g. wm_type dialo would
match dialog and thus result in a floating window).
  • Loading branch information
jwijenbergh committed Nov 28, 2023
1 parent 5512698 commit 40e97a8
Show file tree
Hide file tree
Showing 2 changed files with 5 additions and 5 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
Qtile x.xx.x, released XXXX-XX-XX:
!!! config breakage/changes !!!
- Matches no longer use "include/substring" style matching. But match the string exactly. Previously on X11, if the WM_TYPE of a spawned window is e.g. dialog a match with wm_type dialognoonereadschangelogs would return true. Additionally a window with an empty WM_CLASS (which can happen) would match anything. If you rely this style of substring matching, pass a regex to your match or use a function with func=.
* features
- Change how `tox` runs tests. See https://docs.qtile.org/en/latest/manual/contributing.html#running-tests-locally
for more information on how to run tests locally.
Expand Down
8 changes: 3 additions & 5 deletions libqtile/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -829,7 +829,7 @@ class Match:
against and returns a boolean.
For some properties, :class:`Match` supports both regular expression objects (i.e.
the result of ``re.compile()``) or strings (match as an "include"-match). If a
the result of ``re.compile()``) or strings (match as an exact string). If a
window matches all specified values, it is considered a match.
Parameters
Expand Down Expand Up @@ -896,16 +896,14 @@ def _get_property_predicate(name: str, value: Any) -> Callable[..., bool]:
elif name == "wm_class":

def predicate(other) -> bool: # type: ignore
# match as an "include"-match on any of the received classes
match = getattr(other, "match", lambda v: v in other)
match = getattr(other, "match", lambda v: v == other)
return value and any(match(v) for v in value)

return predicate
else:

def predicate(other) -> bool: # type: ignore
# match as an "include"-match
match = getattr(other, "match", lambda v: v in other)
match = getattr(other, "match", lambda v: v == other)
return match(value)

return predicate
Expand Down

0 comments on commit 40e97a8

Please sign in to comment.