summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xpanel.py127
1 files changed, 90 insertions, 37 deletions
diff --git a/panel.py b/panel.py
index 9efef29..5ef9cbb 100755
--- a/panel.py
+++ b/panel.py
@@ -4,6 +4,7 @@
import glob
import os
+import queue
import subprocess
import threading
import time
@@ -79,14 +80,74 @@ class ModDate(Mod):
self.tz = (self.tz + int(cmd[3:] or 1)) % len(self.tzs)
self.e.set()
-class ModHLWM(Mod):
+class HLWMClient():
+ def __init__(self):
+ self.t = None
+ self.lock = threading.Lock()
+ self.listeners = {}
+
+ def run(self):
+ with self.lock:
+ if self.t is None:
+ self.t = threading.Thread(target=self.work, daemon=True)
+ self.t.start()
+
+ def work(self):
+ p = subprocess.Popen(
+ ('herbstclient', '--idle'),
+ stdout=subprocess.PIPE, text=True)
+
+ for line in iter(p.stdout.readline, ''):
+ for hook, arr in self.listeners.items():
+ if line.startswith(hook):
+ for q, cb_index in arr:
+ q.put((cb_index, line))
+
+ def listen(self, hook, q, cb_index):
+ d = (q, cb_index)
+ if hook in self.listeners:
+ self.listeners[hook].append(d)
+ else:
+ self.listeners[hook] = [d]
+
+ def exec(self, *args):
+ res = subprocess.run(
+ ('herbstclient', *args),
+ stdout=subprocess.PIPE, stderr=subprocess.DEVNULL, text=True)
+ return res.stdout.rstrip()
+
+class ModHLWMBase(Mod):
+ client = HLWMClient()
+
def __init__(self):
super().__init__()
- self.out_tags = None
- self.out_title = None
+ self.q = queue.Queue()
+ self.cbs = []
+
+ def post_start(self):
+ pass
+
+ def listen(self, hook, cb):
+ self.client.listen(hook, self.q, len(self.cbs))
+ self.cbs.append(cb)
- def flush(self):
- self.out = f'{self.out_tags}{spacing()}{self.out_title}'
+ def work(self):
+ self.client.run()
+ self.post_start()
+ while True:
+ cb_index, line = self.q.get()
+ self.cbs[cb_index]()
+
+ def hc(self, *args):
+ return self.client.exec(*args);
+
+class ModHLWMTags(ModHLWMBase):
+ def __init__(self):
+ super().__init__()
+ self.listen('tag_', self.refresh)
+
+ def post_start(self):
+ self.refresh()
def fmt_tag(self, sym, tag, tagstr):
buf = f'%{{A:{id(self)} use {tag}:}}'
@@ -108,49 +169,39 @@ class ModHLWM(Mod):
buf += '%{A}'
return buf
- def refresh_tags(self):
- res = subprocess.run(
- ('herbstclient', 'tag_status'),
- stdout=subprocess.PIPE, text=True)
- tagstr = res.stdout.strip()
- tags = tagstr.split('\t')
+ def refresh(self):
+ tagstr = self.hc('tag_status')
+ tags = tagstr.lstrip('\t').split('\t')
buf = (f'%{{A4:{id(self)} use_index +1:}}'
f'%{{A5:{id(self)} use_index -1:}}')
for tag in tags:
buf += self.fmt_tag(tag[0], tag[1:], tagstr)
buf += '%{A}%{A}'
- with self.cv:
- self.out_tags = buf
- self.flush()
- self.cv.notify()
- def refresh_title(self):
- res = subprocess.run(
- ('herbstclient', 'attr', 'clients.focus.title'),
- stdout=subprocess.PIPE, stderr=subprocess.DEVNULL, text=True)
- title = res.stdout.strip()
- buf = title if len(title) < 65 else title[0:63] + '…'
with self.cv:
- self.out_title = buf
- self.flush()
+ self.out = buf
self.cv.notify()
- def work(self):
- p = subprocess.Popen(
- ('herbstclient', '--idle'),
- stdout=subprocess.PIPE, text=True)
- self.refresh_tags()
- self.refresh_title()
- for line in iter(p.stdout.readline, ''):
- if line.startswith('tag_'):
- self.refresh_tags()
- elif (line.startswith('focus_changed') or
- line.startswith('window_title_changed')):
- self.refresh_title()
-
def process_cmd(self, cmd):
subprocess.run(('herbstclient', *cmd.split()))
+class ModHLWMTitle(ModHLWMBase):
+ def __init__(self):
+ super().__init__()
+ self.listen('focus_changed', self.refresh)
+ self.listen('window_title_changed', self.refresh)
+
+ def post_start(self):
+ self.refresh()
+
+ def refresh(self):
+ title = self.hc('attr', 'clients.focus.title')
+ buf = title if len(title) < 65 else title[0:63] + '…'
+
+ with self.cv:
+ self.out = buf
+ self.cv.notify()
+
class ModInputUnavail(Mod):
def __init__(self, path, label=''):
super().__init__()
@@ -241,7 +292,9 @@ class Bar:
file=self.bar.stdin, flush=True)
Bar(
- ModHLWM(),
+ ModHLWMTags(),
+ ModSpacer(),
+ ModHLWMTitle(),
ModRight(),
ModInputUnavail(
'/dev/input/by-id/usb-HID_Keyboard_HID_Keyboard-event-kbd',