Merge branch 'partial-update-on-input'

This commit is contained in:
Tobias Witek 2019-01-23 20:06:17 +01:00
commit a2cc828e58
4 changed files with 64 additions and 30 deletions

View file

@ -71,7 +71,7 @@ class Module(object):
return widget return widget
def errorWidget(self): def errorWidget(self):
msg = self.error msg = self.error or "n/a"
if len(msg) > 10: if len(msg) > 10:
msg = "{}...".format(msg[0:7]) msg = "{}...".format(msg[0:7])
return bumblebee.output.Widget(full_text="error: {}".format(msg)) return bumblebee.output.Widget(full_text="error: {}".format(msg))
@ -264,14 +264,37 @@ class Engine(object):
def run(self): def run(self):
"""Start the event loop""" """Start the event loop"""
self._output.start() self._output.start()
event = None
last_full = time.time()
interval = float(self._config.get("interval", 1))
while self.running(): while self.running():
self.write_output() if event and time.time() - last_full < interval:
log.debug("partial output update ({} {} {})".format(event, time.time(), last_full))
self.patch_output(event)
else:
log.debug("full update: {} {} ({})".format(time.time(), last_full, time.time() - last_full))
last_full = time.time()
self.write_output()
if self.running(): if self.running():
self.input.wait(float(self._config.get("interval", 1))) event = self.input.wait(interval)
self._output.stop() self._output.stop()
self.input.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): def write_output(self):
self._output.begin() self._output.begin()
for module in self._modules: for module in self._modules:

View file

@ -45,6 +45,7 @@ def read_input(inp):
try: try:
event = json.loads(line) event = json.loads(line)
if "instance" in event: if "instance" in event:
inp.event = event
inp.callback(event) inp.callback(event)
inp.redraw() inp.redraw()
else: else:
@ -66,6 +67,7 @@ class I3BarInput(object):
self.global_id = str(uuid.uuid4()) self.global_id = str(uuid.uuid4())
self.need_event = False self.need_event = False
self.has_event = False self.has_event = False
self.event = None
self._condition = threading.Condition() self._condition = threading.Condition()
def start(self): def start(self):
@ -87,6 +89,10 @@ class I3BarInput(object):
def wait(self, timeout): def wait(self, timeout):
self._condition.wait(timeout) self._condition.wait(timeout)
rv = self.event if self.has_event else None
log.debug("received input event: {}".format(rv))
self.has_event = False
return rv
def _wait(self): def _wait(self):
while not self.has_event: while not self.has_event:

View file

@ -105,6 +105,10 @@ class I3BarOutput(object):
self._started = False self._started = False
self._config = config self._config = config
def replace(self, event, module, new_widget):
data = self.widget_data(module, new_widget)
self._widgets = [w if not "instance" in w or w["instance"] != event["instance"] else data for w in self._widgets]
def started(self): def started(self):
return self._started return self._started
@ -117,22 +121,40 @@ class I3BarOutput(object):
"""Finish i3bar protocol""" """Finish i3bar protocol"""
sys.stdout.write("]\n") sys.stdout.write("]\n")
def widget_data(self, module, widget):
full_text = widget.full_text()
padding = self._theme.padding(widget)
prefix = self._theme.prefix(widget, padding)
suffix = self._theme.suffix(widget, padding)
if prefix:
full_text = u"{}{}".format(prefix, full_text)
if suffix:
full_text = u"{}{}".format(full_text, suffix)
separator = self._theme.separator(widget)
width = self._theme.minwidth(widget)
if width:
full_text = full_text.ljust(len(width) + len(prefix) + len(suffix))
return {
u"full_text": full_text,
"color": self._theme.fg(widget),
"background": self._theme.bg(widget),
"separator_block_width": self._theme.separator_block_width(widget),
"separator": True if separator is None else False,
"min_width": None,
"align": self._theme.align(widget),
"instance": widget.id,
"name": module.id,
}
def draw(self, widget, module=None, engine=None): def draw(self, widget, module=None, engine=None):
"""Draw a single widget""" """Draw a single widget"""
full_text = widget.full_text()
if widget.get_module() and widget.get_module().hidden(): if widget.get_module() and widget.get_module().hidden():
return return
if widget.get_module() and widget.get_module().name in self._config.autohide(): if widget.get_module() and widget.get_module().name in self._config.autohide():
if not any(state in widget.state() for state in ["warning", "critical"]): if not any(state in widget.state() for state in ["warning", "critical"]):
return return
padding = self._theme.padding(widget)
prefix = self._theme.prefix(widget, padding)
suffix = self._theme.suffix(widget, padding)
if prefix:
full_text = u"{}{}".format(prefix, full_text)
if suffix:
full_text = u"{}{}".format(full_text, suffix)
separator = self._theme.separator(widget) separator = self._theme.separator(widget)
if separator: if separator:
@ -143,23 +165,8 @@ class I3BarOutput(object):
"background": self._theme.separator_bg(widget), "background": self._theme.separator_bg(widget),
"separator_block_width": self._theme.separator_block_width(widget), "separator_block_width": self._theme.separator_block_width(widget),
}) })
width = self._theme.minwidth(widget)
if width: self._widgets.append(self.widget_data(module, widget))
full_text = full_text.ljust(len(width) + len(prefix) + len(suffix))
self._widgets.append({
u"full_text": full_text,
"color": self._theme.fg(widget),
"background": self._theme.bg(widget),
"separator_block_width": self._theme.separator_block_width(widget),
"separator": True if separator is None else False,
"min_width": None,
# "min_width": width + "A"*(len(prefix) + len(suffix)) if width else None,
"align": self._theme.align(widget),
"instance": widget.id,
"name": module.id,
})
def begin(self): def begin(self):
"""Start one output iteration""" """Start one output iteration"""

View file

@ -20,7 +20,6 @@ def asbool(val):
return val in ("t", "true", "y", "yes", "on", "1") return val in ("t", "true", "y", "yes", "on", "1")
def execute(cmd, wait=True): def execute(cmd, wait=True):
logging.info("executing command '{}'".format(cmd))
args = shlex.split(cmd) args = shlex.split(cmd)
proc = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) proc = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
rv = None rv = None
@ -35,7 +34,6 @@ def execute(cmd, wait=True):
else: else:
rv = out rv = out
logging.info(u"command returned '{}'".format("" if not rv else rv))
return rv return rv
def bytefmt(num): def bytefmt(num):