diff --git a/bumblebee/engine.py b/bumblebee/engine.py index 40cd152..caf43a7 100644 --- a/bumblebee/engine.py +++ b/bumblebee/engine.py @@ -39,6 +39,11 @@ class Module(object): """Return the widgets to draw for this module""" return self._widgets + def widget(self, name): + for widget in self._widgets: + if widget.name == name: + return widget + def update(self, widgets): """By default, update() is a NOP""" pass diff --git a/bumblebee/input.py b/bumblebee/input.py index b28c237..b9f36f5 100644 --- a/bumblebee/input.py +++ b/bumblebee/input.py @@ -27,7 +27,6 @@ class I3BarInput(object): """Process incoming events from the i3bar""" def __init__(self): self.running = True - self._thread = threading.Thread(target=read_input, args=(self,)) self._callbacks = {} self.clean_exit = False self.global_id = str(uuid.uuid4()) @@ -36,17 +35,24 @@ class I3BarInput(object): def start(self): """Start asynchronous input processing""" + self.has_event = False + self.running = True + self._thread = threading.Thread(target=read_input, args=(self,)) self._thread.start() def alive(self): """Check whether the input processing is still active""" return self._thread.is_alive() + def _wait(self): + while not self.has_event: + time.sleep(0.1) + self.has_event = False + def stop(self): """Stop asynchronous input processing""" if self.need_event: - while not self.has_event: - time.sleep(0.1) + self._wait() self.running = False self._thread.join() return self.clean_exit diff --git a/tests/modules/test_cmus.py b/tests/modules/test_cmus.py index dfb3c56..f31b65a 100644 --- a/tests/modules/test_cmus.py +++ b/tests/modules/test_cmus.py @@ -12,6 +12,8 @@ from tests.util import MockEngine, MockConfig, assertPopen class TestCmusModule(unittest.TestCase): def setUp(self): self.engine = MockEngine() + self.engine.input = I3BarInput() + self.engine.input.need_event = True self.module = Module(engine=self.engine, config={"config": MockConfig()}) @mock.patch("subprocess.Popen") @@ -27,4 +29,26 @@ class TestCmusModule(unittest.TestCase): def test_widgets(self): self.assertTrue(len(self.module.widgets()), 5) + @mock.patch("subprocess.Popen") + @mock.patch("sys.stdin") + def test_interaction(self, mock_input, mock_output): + events = [ + {"widget": "cmus.shuffle", "action": "cmus-remote -S"}, + {"widget": "cmus.repeat", "action": "cmus-remote -R"}, + {"widget": "cmus.next", "action": "cmus-remote -n"}, + {"widget": "cmus.prev", "action": "cmus-remote -r"}, + {"widget": "cmus.main", "action": "cmus-remote -u"}, + ] + + for event in events: + mock_input.readline.return_value = json.dumps({ + "name": self.module.id, + "button": bumblebee.input.LEFT_MOUSE, + "instance": self.module.widget(event["widget"]).id + }) + self.engine.input.start() + self.engine.input.stop() + mock_input.readline.assert_any_call() + assertPopen(mock_output, event["action"]) + # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4