Skip to content

Commit

Permalink
Add filter to dbus signal handle
Browse files Browse the repository at this point in the history
Custom user handlers receive all messages sent to the service so we need
to filter out unwanted messages. dbus-next messages have a built-in
`_matches` method so we can use this.
  • Loading branch information
elParaguayo committed Dec 16, 2023
1 parent d5b8e19 commit 01a773e
Show file tree
Hide file tree
Showing 5 changed files with 12 additions and 29 deletions.
14 changes: 11 additions & 3 deletions libqtile/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -508,14 +508,14 @@ async def add_signal_receiver(
return False

match_args = {
"type": "signal",
"sender": bus_name,
"member": signal_name,
"path": path,
"interface": dbus_interface,
}

rule = ",".join("{}='{}'".format(k, v) for k, v in match_args.items() if v)
rule = "type='signal',"
rule += ",".join("{}='{}'".format(k, v) for k, v in match_args.items() if v)

logger.debug("Adding dbus match rule: %s", rule)

Expand All @@ -532,7 +532,15 @@ async def add_signal_receiver(

# Check if message sent successfully
if bus and msg and msg.message_type == MessageType.METHOD_RETURN:
bus.add_message_handler(callback)

def signal_callback_wrapper(msg: Message) -> None:
"""Custom wrapper to only run callback if message matches our rule."""
if msg.message_type == MessageType.SIGNAL and msg._matches(
**{k: v for k, v in match_args.items() if v}
):
callback(msg)

bus.add_message_handler(signal_callback_wrapper)
return True

else:
Expand Down
5 changes: 0 additions & 5 deletions libqtile/widget/keyboardkbdd.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,6 @@

import re

from dbus_next.constants import MessageType

from libqtile.log_utils import logger
from libqtile.utils import add_signal_receiver
from libqtile.widget import base
Expand Down Expand Up @@ -90,9 +88,6 @@ async def _config_async(self):
logger.warning("Could not subscribe to kbdd signal.")

def _signal_received(self, message):
if message.message_type != MessageType.SIGNAL:
return

self._layout_changed(*message.body)

def _layout_changed(self, layout_changed):
Expand Down
3 changes: 0 additions & 3 deletions libqtile/widget/mpris2widget.py
Original file line number Diff line number Diff line change
Expand Up @@ -252,9 +252,6 @@ def _name_owner_changed(self, message):
self._set_background_poll(False)

def message(self, message):
if message.message_type != MessageType.SIGNAL:
return

create_task(self.process_message(message))

async def process_message(self, message):
Expand Down
5 changes: 1 addition & 4 deletions test/widgets/docs_screenshots/ss_keyboardkbdd.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,21 +17,18 @@
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
import sys
from importlib import reload

import pytest

from test.widgets.test_keyboardkbdd import Mockconstants, MockSpawn, mock_signal_receiver
from test.widgets.test_keyboardkbdd import MockSpawn, mock_signal_receiver


@pytest.fixture
def widget(monkeypatch):
monkeypatch.setitem(sys.modules, "dbus_next.constants", Mockconstants("dbus_next.constants"))
from libqtile.widget import keyboardkbdd

reload(keyboardkbdd)
monkeypatch.setattr("libqtile.widget.keyboardkbdd.MessageType", Mockconstants.MessageType)
monkeypatch.setattr(
"libqtile.widget.keyboardkbdd.KeyboardKbdd.call_process", MockSpawn.call_process
)
Expand Down
14 changes: 0 additions & 14 deletions test/widgets/test_keyboardkbdd.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,7 @@

# This test file covers the remaining widget code

import sys
from importlib import reload
from types import ModuleType

import pytest

Expand All @@ -38,11 +36,6 @@ async def mock_signal_receiver(*args, **kwargs):
return True


class Mockconstants(ModuleType):
class MessageType:
SIGNAL = 1


class MockSpawn:
call_count = 0

Expand All @@ -62,13 +55,11 @@ def __init__(self, is_signal=True, body=0):

@pytest.fixture
def patched_widget(monkeypatch):
monkeypatch.setitem(sys.modules, "dbus_next.constants", Mockconstants("dbus_next.constants"))
from libqtile.widget import keyboardkbdd

reload(keyboardkbdd)

# The next line shouldn't be necessary but I got occasional failures without it when testing locally
monkeypatch.setattr("libqtile.widget.keyboardkbdd.MessageType", Mockconstants.MessageType)
monkeypatch.setattr(
"libqtile.widget.keyboardkbdd.KeyboardKbdd.call_process", MockSpawn.call_process
)
Expand All @@ -89,11 +80,6 @@ def test_keyboardkbdd_process_running(fake_qtile, patched_widget, fake_window):
kbd._signal_received(message)
assert kbd.keyboard == "us"

# Test non-"signal" message
message = MockMessage(body=0, is_signal=False)
kbd._signal_received(message)
assert kbd.keyboard == "us"


def test_keyboardkbdd_process_not_running(fake_qtile, patched_widget, fake_window):
MockSpawn.call_count = 0
Expand Down

0 comments on commit 01a773e

Please sign in to comment.