From 3d9279c444926ba4e3bcf44977989afb8366c3e2 Mon Sep 17 00:00:00 2001 From: Tobias Witek Date: Sat, 19 Jan 2019 14:07:17 +0100 Subject: [PATCH] [core] Update only affected widgets on input event When receiving an input event, only update affected widgets, identified by their instance ID. see #353 --- bumblebee/engine.py | 24 +++++++++++++++++++++--- bumblebee/input.py | 5 +++++ bumblebee/output.py | 23 +++++++++++++++++++++++ bumblebee/util.py | 2 -- 4 files changed, 49 insertions(+), 5 deletions(-) diff --git a/bumblebee/engine.py b/bumblebee/engine.py index f515470..6c4cff5 100644 --- a/bumblebee/engine.py +++ b/bumblebee/engine.py @@ -71,7 +71,7 @@ class Module(object): return widget def errorWidget(self): - msg = self.error + msg = self.error or "n/a" if len(msg) > 10: msg = "{}...".format(msg[0:7]) return bumblebee.output.Widget(full_text="error: {}".format(msg)) @@ -264,14 +264,32 @@ class Engine(object): def run(self): """Start the event loop""" self._output.start() + event = None while self.running(): - self.write_output() + if event: + self.patch_output(event) + else: + self.write_output() if self.running(): - self.input.wait(float(self._config.get("interval", 1))) + event = self.input.wait(float(self._config.get("interval", 1))) self._output.stop() self.input.stop() + def patch_output(self, event): + for module in self._modules: + widget = module.widget_by_id(event["instance"]) + if not widget: continue + # this widget was affected by the event -> update + module.update_wrapper(module.widgets()) + widget = module.errorWidget() + if module.error is None: + widget = module.widget_by_id(event["instance"]) + widget.link_module(module) + self._output.replace(event, module, widget) + self._output.flush() + self._output.end() + def write_output(self): self._output.begin() for module in self._modules: diff --git a/bumblebee/input.py b/bumblebee/input.py index 5fb3032..9b760bc 100644 --- a/bumblebee/input.py +++ b/bumblebee/input.py @@ -45,6 +45,7 @@ def read_input(inp): try: event = json.loads(line) if "instance" in event: + inp.event = event inp.callback(event) inp.redraw() else: @@ -66,6 +67,7 @@ class I3BarInput(object): self.global_id = str(uuid.uuid4()) self.need_event = False self.has_event = False + self.event = None self._condition = threading.Condition() def start(self): @@ -87,6 +89,9 @@ class I3BarInput(object): def wait(self, timeout): self._condition.wait(timeout) + rv = self.event if self.has_event else None + self.has_event = False + return rv def _wait(self): while not self.has_event: diff --git a/bumblebee/output.py b/bumblebee/output.py index 35c1895..733aba4 100644 --- a/bumblebee/output.py +++ b/bumblebee/output.py @@ -105,6 +105,29 @@ class I3BarOutput(object): self._started = False self._config = config + def replace(self, event, module, new_widget): + full_text = new_widget.full_text() + padding = self._theme.padding(new_widget) + prefix = self._theme.prefix(new_widget, padding) + suffix = self._theme.suffix(new_widget, padding) + if prefix: + full_text = u"{}{}".format(prefix, full_text) + if suffix: + full_text = u"{}{}".format(full_text, suffix) + separator = self._theme.separator(new_widget) + widget_data = { + u"full_text": full_text, + "color": self._theme.fg(new_widget), + "background": self._theme.bg(new_widget), + "separator_block_width": self._theme.separator_block_width(new_widget), + "separator": True if separator is None else False, + "min_width": None, + "align": self._theme.align(new_widget), + "instance": new_widget.id, + "name": module.id, + } + self._widgets = [w if not "instance" in w or w["instance"] != event["instance"] else widget_data for w in self._widgets] + def started(self): return self._started diff --git a/bumblebee/util.py b/bumblebee/util.py index f3545ac..d41d024 100644 --- a/bumblebee/util.py +++ b/bumblebee/util.py @@ -20,7 +20,6 @@ def asbool(val): return val in ("t", "true", "y", "yes", "on", "1") def execute(cmd, wait=True): - logging.info("executing command '{}'".format(cmd)) args = shlex.split(cmd) proc = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) rv = None @@ -35,7 +34,6 @@ def execute(cmd, wait=True): else: rv = out - logging.info(u"command returned '{}'".format("" if not rv else rv)) return rv def bytefmt(num):