From 6784aaa0d5c54d7655755b975c6af564b9becbf7 Mon Sep 17 00:00:00 2001 From: Tobias Witek Date: Fri, 14 Feb 2020 20:48:09 +0100 Subject: [PATCH 01/20] [doc] Add user-contrib link fixes #554 --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index 72c73d4..035614d 100644 --- a/README.md +++ b/README.md @@ -69,6 +69,7 @@ bar { ``` # Documentation + See [the wiki](https://github.com/tobi-wan-kenobi/bumblebee-status/wiki) for documentation. See [FAQ](https://github.com/tobi-wan-kenobi/bumblebee-status/wiki/FAQ) for, well, FAQs. @@ -79,6 +80,10 @@ Other resources: * [How to write a theme](https://github.com/tobi-wan-kenobi/bumblebee-status/wiki/How-to-write-a-theme) * [How to write a module](https://github.com/tobi-wan-kenobi/bumblebee-status/wiki/How-to-write-a-module) +User contributions: + +[@somospocos:bumblebee-status-contrib](https://github.com/somospocos/bumblebee-status-contrib): Collected resources and useful tricks by @somospocos + # Installation ``` $ git clone git://github.com/tobi-wan-kenobi/bumblebee-status From bff77885142cbb45baeceaece987a566a83bf72e Mon Sep 17 00:00:00 2001 From: Tobias Witek Date: Fri, 14 Feb 2020 20:54:08 +0100 Subject: [PATCH 02/20] [doc] Add missing executables to README.md fixes #551 --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 035614d..91a5077 100644 --- a/README.md +++ b/README.md @@ -240,6 +240,8 @@ Modules and commandline utilities are only required for modules, the core itself * zpool (for module 'zpool') * progress (for module 'progress') * i3exit (for module 'system') +* dunst (for module 'dunst') +* hddtemp (for module 'hddtemp') # Examples Here are some screenshots for all themes that currently exist: From 8ae8fbb98900bcf059ddf4614e673510723a604d Mon Sep 17 00:00:00 2001 From: Tobias Witek Date: Fri, 14 Feb 2020 21:39:01 +0100 Subject: [PATCH 03/20] [engine] Add override for widget IDs Add a generic ".id" parameter that allows a user to override the auto-generated IDs for a widget - the parameter is a list of IDs that will replace each widget's ID in turn. see #547 --- bumblebee/engine.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/bumblebee/engine.py b/bumblebee/engine.py index 1159884..377dfc4 100644 --- a/bumblebee/engine.py +++ b/bumblebee/engine.py @@ -295,8 +295,12 @@ class Engine(object): self._current_module = module module.update_wrapper(module.widgets()) if module.error is None: + widget_ids = module.parameter('id', '').split(',') + idx = 0 for widget in module.widgets(): widget.link_module(module) + widget.id = widget_ids[idx] if idx < len(widget_ids) else widget.id + idx = idx + 1 self._output.draw(widget=widget, module=module, engine=self) else: self._output.draw(widget=module.errorWidget(), module=module, engine=self) From ef35c957b2b25275ab6e6adc9983fcd11f7b10c3 Mon Sep 17 00:00:00 2001 From: Tobias Witek Date: Fri, 14 Feb 2020 21:39:55 +0100 Subject: [PATCH 04/20] [input] Add per-PID UNIX socket for additional commands Allow passing in commands / events via a unix socket. This should allow for "emulating" input events. see #547 --- bumblebee/input.py | 80 ++++++++++++++++++++++++++++++---------------- 1 file changed, 53 insertions(+), 27 deletions(-) diff --git a/bumblebee/input.py b/bumblebee/input.py index af86757..adeaa65 100644 --- a/bumblebee/input.py +++ b/bumblebee/input.py @@ -1,9 +1,11 @@ """Input classes""" +import os import sys import json import uuid import time +import socket import select import logging import threading @@ -23,38 +25,62 @@ def is_terminated(): return True return False +class CommandSocket(object): + def __init__(self): + self._name = "/tmp/.bumblebee-status.{}".format(os.getpid()) + self._socket = None + + def __enter__(self): + self._socket = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) + self._socket.bind(self._name) + self._socket.listen(5) + return self._socket + + def __exit__(self, type, value, traceback): + self._socket.close() + os.unlink(self._name) + def read_input(inp): """Read i3bar input and execute callbacks""" - poll = select.poll() - poll.register(sys.stdin.fileno(), select.POLLIN) - log.debug("starting click event processing") - while inp.running: - if is_terminated(): - return - try: - events = poll.poll(1000) - except Exception: - continue - for fileno, event in events: - line = "[" - while line.startswith("["): - line = sys.stdin.readline().strip(",").strip() - log.debug("new event: {}".format(line)) - inp.has_event = True + with CommandSocket() as cmdsocket: + poll = select.poll() + poll.register(sys.stdin, select.POLLIN) + poll.register(cmdsocket, select.POLLIN) + log.debug("starting click event processing") + while inp.running: + if is_terminated(): + return + try: - event = json.loads(line) - if "instance" in event: - inp.callback(event) - inp.redraw() + events = poll.poll(1000) + except Exception: + continue + for fileno, event in events: + + if fileno == cmdsocket.fileno(): + tmp, _ = cmdsocket.accept() + line = tmp.recv(4096).decode() + tmp.close() else: - log.debug("field 'instance' missing in input, not processing the event") - except ValueError as e: - log.debug("failed to parse event: {}".format(e)) - log.debug("exiting click event processing") - poll.unregister(sys.stdin.fileno()) - inp.has_event = True - inp.clean_exit = True + line = "[" + while line.startswith("["): + line = sys.stdin.readline().strip(",").strip() + log.debug("new event: {}".format(line)) + inp.has_event = True + try: + event = json.loads(line) + if "instance" in event: + inp.callback(event) + inp.redraw() + else: + log.debug("field 'instance' missing in input, not processing the event") + except ValueError as e: + log.debug("failed to parse event: {}".format(e)) + log.debug("exiting click event processing") + poll.unregister(sys.stdin.fileno()) + inp.has_event = True + inp.clean_exit = True class I3BarInput(object): """Process incoming events from the i3bar""" From 65137f294e97b98723de44bd5363b8fa0e8a6be5 Mon Sep 17 00:00:00 2001 From: Tobias Witek Date: Fri, 14 Feb 2020 21:52:23 +0100 Subject: [PATCH 05/20] [engine] Small bugfix if no IDs are configured see #547 --- bumblebee/engine.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/bumblebee/engine.py b/bumblebee/engine.py index 377dfc4..fd3bbe9 100644 --- a/bumblebee/engine.py +++ b/bumblebee/engine.py @@ -295,11 +295,14 @@ class Engine(object): self._current_module = module module.update_wrapper(module.widgets()) if module.error is None: - widget_ids = module.parameter('id', '').split(',') + widget_ids = [] + if module.parameter('id'): + widget_ids = module.parameter('id').split(',') idx = 0 for widget in module.widgets(): widget.link_module(module) - widget.id = widget_ids[idx] if idx < len(widget_ids) else widget.id + if idx < len(widget_ids): + widget.id = widget_ids[idx] idx = idx + 1 self._output.draw(widget=widget, module=module, engine=self) else: From 95ac72d3050ada53419222b9ce79a545f3eb13ee Mon Sep 17 00:00:00 2001 From: Tobias Witek Date: Fri, 14 Feb 2020 21:54:06 +0100 Subject: [PATCH 06/20] [core] Add bumblebee-ctl to trigger remote commands see #547 --- bumblebee-ctl | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100755 bumblebee-ctl diff --git a/bumblebee-ctl b/bumblebee-ctl new file mode 100755 index 0000000..e08d45c --- /dev/null +++ b/bumblebee-ctl @@ -0,0 +1,37 @@ +#!/usr/bin/env python + +import argparse +import json +import glob +import socket + +button = { + 'left-mouse': 1, + 'middle-mouse': 2, + 'right-mouse': 3, + 'wheel-up': 4, + 'wheel-down': 5, +} + +def main(): + parser = argparse.ArgumentParser(description='send commands to bumblebee-status') + parser.add_argument('-b', '--button', choices=['left-mouse', 'right-mouse', 'middle-mouse', 'wheel-up', 'wheel-down'], help='button to emulate', default='left-mouse') + parser.add_argument('-i', '--id', help='ID of widget to trigger', required=True) + parser.add_argument('-n', '--name', help='name of the module to trigger', required=True) + + args = parser.parse_args() + + for f in glob.glob('/tmp/.bumblebee-status.*'): + print('accessing {}'.format(f)) + s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) + s.connect(f) + s.sendall(json.dumps({ + 'name': args.name, + 'instance': args.id, + 'button': button[args.button], + }).encode('ascii')) + +if __name__ == "__main__": + main() + +# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 From 6f6ac9772613208f27401b80454b0d3e1284cbbc Mon Sep 17 00:00:00 2001 From: Tobias Witek Date: Fri, 14 Feb 2020 21:56:35 +0100 Subject: [PATCH 07/20] [bumblebee-ctl] replace name with module see #547 --- bumblebee-ctl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bumblebee-ctl b/bumblebee-ctl index e08d45c..cbb6ad5 100755 --- a/bumblebee-ctl +++ b/bumblebee-ctl @@ -17,7 +17,7 @@ def main(): parser = argparse.ArgumentParser(description='send commands to bumblebee-status') parser.add_argument('-b', '--button', choices=['left-mouse', 'right-mouse', 'middle-mouse', 'wheel-up', 'wheel-down'], help='button to emulate', default='left-mouse') parser.add_argument('-i', '--id', help='ID of widget to trigger', required=True) - parser.add_argument('-n', '--name', help='name of the module to trigger', required=True) + parser.add_argument('-m', '--module', help='name of the module to trigger', required=True) args = parser.parse_args() @@ -26,7 +26,7 @@ def main(): s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) s.connect(f) s.sendall(json.dumps({ - 'name': args.name, + 'name': args.module, 'instance': args.id, 'button': button[args.button], }).encode('ascii')) From 6da755ab84f540103498d325ef39122ba494bb58 Mon Sep 17 00:00:00 2001 From: Tobias Witek Date: Sat, 15 Feb 2020 11:38:36 +0100 Subject: [PATCH 08/20] [core] Fix error widget The parameters for the error widget were wrong (dict vs. Config) --- bumblebee-status | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/bumblebee-status b/bumblebee-status index bb31f94..7e65721 100755 --- a/bumblebee-status +++ b/bumblebee-status @@ -67,7 +67,9 @@ def main(): import time while True: output.begin() - error = bumblebee.modules.error.Module(engine, config) + error = bumblebee.modules.error.Module(engine, { + "config": config, "name": "error" + }) error.set("exception occurred: {} in {}".format(e, module)) widget = error.widgets()[0] widget.link_module(error) From 57e1b1eb81b159d137e3ae75276490d81da67570 Mon Sep 17 00:00:00 2001 From: Tobias Witek Date: Sat, 15 Feb 2020 11:39:00 +0100 Subject: [PATCH 09/20] [modules/battery-upower] Fix capacity default value If the capacity isn't set, get() returns None, which is not comparable. Use -1 instead, which makes the capacity unknown. fixes #555 --- bumblebee/modules/battery-upower.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bumblebee/modules/battery-upower.py b/bumblebee/modules/battery-upower.py index 24efecf..f3d59ba 100644 --- a/bumblebee/modules/battery-upower.py +++ b/bumblebee/modules/battery-upower.py @@ -240,7 +240,7 @@ class Module(bumblebee.engine.Module): def state(self, widget): state = [] - capacity = widget.get("capacity") + capacity = widget.get("capacity", -1) if capacity < 0: return ["critical", "unknown"] From 2cc6fcc5dc7265fb8c4de9d9951557a89c81be7d Mon Sep 17 00:00:00 2001 From: Tobias Witek Date: Sun, 16 Feb 2020 13:40:51 +0100 Subject: [PATCH 10/20] [doc] Add bumblebee-ctl fixes #547 --- README.md | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/README.md b/README.md index 91a5077..dd95423 100644 --- a/README.md +++ b/README.md @@ -188,6 +188,25 @@ For example: `$ bumblebee-status -p disk.left-click="nautilus {instance}"` +Advanced usage: + +You can also "programmatically" trigger click events like this: +``` +$ bumblebee-ctl --button