summaryrefslogtreecommitdiff
path: root/panel.py
diff options
context:
space:
mode:
authorDavid Vazgenovich Shakaryan <dvshakaryan@gmail.com>2024-02-22 12:38:51 -0800
committerDavid Vazgenovich Shakaryan <dvshakaryan@gmail.com>2024-02-22 12:38:51 -0800
commit43c215b4de76bb2a5558c9db4011572274287d36 (patch)
tree83712be0367de3997c90ac78288373abd9ffb2c4 /panel.py
parenta25f5b90664f635afafd50ed2700f04783ee9c4a (diff)
downloadpanel-43c215b4de76bb2a5558c9db4011572274287d36.tar.gz
panel-43c215b4de76bb2a5558c9db4011572274287d36.tar.xz
wait for refreshing modules to finish before repainting panel
If a max paint delay is set, the panel waits up to this amount of time for any refreshing modules to finish before triggering a repaint. A repaint is triggered once either all refreshing modules finish or this delay elapses. Any individual module may request an immediate repaint.
Diffstat (limited to 'panel.py')
-rwxr-xr-xpanel.py53
1 files changed, 40 insertions, 13 deletions
diff --git a/panel.py b/panel.py
index 34dc3d6..b522dc5 100755
--- a/panel.py
+++ b/panel.py
@@ -54,6 +54,8 @@ class Fmt:
class Mod:
def __init__(self, spacing=1, spacing_l=None, spacing_r=None):
self.e_repaint = None
+ self.e_flush = None
+ self.refreshing = False
self.spacing_l = spacing_l if spacing_l is not None else spacing
self.spacing_r = spacing_r if spacing_r is not None else spacing
@@ -62,7 +64,9 @@ class Mod:
# this at any time.
self.out = None
- def repaint(self):
+ def repaint(self, flush=False):
+ if flush:
+ self.e_flush.set()
self.e_repaint.set()
def run(self):
@@ -104,6 +108,7 @@ class ModDate(Mod):
def work(self):
while True:
+ self.refreshing = True
fmt = self.fmts[self.fmt]
tz = self.tzs[self.tz]
tz_id = tz['id']
@@ -120,7 +125,8 @@ class ModDate(Mod):
+ Fmt.spacer()
+ Fmt.clickable(
'', f'{id(self)} fmt', dt.strftime(fmt))))
- self.repaint()
+ self.refreshing = False
+ self.repaint(flush=True)
self.e.wait(1 - (dt.microsecond / 1000000))
self.e.clear()
@@ -221,6 +227,7 @@ class ModHLWMTags(ModHLWMBase):
return Fmt.clickable('', f'{id(self)} use {tag}', buf)
def refresh(self):
+ self.refreshing = True
tags = self.hc('tag_status').lstrip('\t').split('\t')
focused = self.hc('attr', 'tags.focus.name')
@@ -230,6 +237,7 @@ class ModHLWMTags(ModHLWMBase):
5, f'{id(self)} use_index -1',
''.join(
self.fmt_tag(tag[0], tag[1:], focused) for tag in tags)))
+ self.refreshing = False
self.repaint()
def process_cmd(self, cmd):
@@ -246,11 +254,13 @@ class ModHLWMTitle(ModHLWMBase):
self.refresh()
def refresh(self):
+ self.refreshing = True
title = self.hc('attr', 'clients.focus.title')
self.out = (
title[0:self.max_len-1] + '…'
if self.max_len and len(title) > self.max_len
else title)
+ self.refreshing = False
self.repaint()
class ModInputAvail(Mod):
@@ -297,12 +307,14 @@ class ModInputAvail(Mod):
self._update_state(False)
def _update_state(self, avail):
+ self.refreshing = True
if avail and self.avail_text is not None:
self.out = Fmt.bg(self.avail_bg, Fmt.pad(self.avail_text))
elif not avail and self.unavail_text is not None:
self.out = Fmt.bg(self.unavail_bg, Fmt.pad(self.unavail_text))
else:
self.out = None
+ self.refreshing = False
self.repaint()
class IntervalTimer():
@@ -311,7 +323,6 @@ class IntervalTimer():
self.lock = threading.Lock()
self.func_intervals = {}
self.func_next_time = {}
- self.e_repaint = None
def run(self):
with self.lock:
@@ -326,7 +337,6 @@ class IntervalTimer():
if now > self.func_next_time.get(func, 0):
func()
self.func_next_time[func] = now - (now % ival) + ival
- self.e_repaint.set()
time.sleep(min(self.func_next_time.values()) - time.time())
class ModInterval(Mod):
@@ -334,13 +344,17 @@ class ModInterval(Mod):
def __init__(self, interval=1, **kwargs):
super().__init__(**kwargs)
- self.timer.func_intervals[self.refresh] = interval
+ self.timer.func_intervals[self.work] = interval
def run(self):
- if not self.timer.e_repaint:
- self.timer.e_repaint = self.e_repaint
self.timer.run()
+ def work(self):
+ self.refreshing = True
+ self.refresh()
+ self.refreshing = False
+ self.repaint()
+
class ModNetIf(ModInterval):
def __init__(self, ifname, label=None, regex=False, **kwargs):
super().__init__(**kwargs)
@@ -368,12 +382,15 @@ class ModMem(ModInterval):
self.out = Fmt.labelled('MEM', f'{percent:.0f}%%')
class Panel:
- def __init__(self, *mods):
+ def __init__(self, *mods, max_paint_delay=0):
self.e_repaint = threading.Event()
+ self.e_flush = threading.Event()
self.mods = mods
for m in self.mods:
m.e_repaint = self.e_repaint
+ m.e_flush = self.e_flush
self.mod_by_id = {id(m): m for m in self.mods}
+ self.max_paint_delay = max_paint_delay
def process_cmds(self, pipe):
while True:
@@ -404,10 +421,19 @@ class Panel:
).start()
while True:
- self.e_repaint.wait()
- self.e_repaint.clear()
- print(''.join([s for m in self.mods if (s := m.to_paint())]),
- file=self.panel.stdin, flush=True)
+ self.e_repaint.wait()
+ self.e_repaint.clear()
+ if not self.e_flush.is_set() and self.max_paint_delay:
+ max_t = time.monotonic() + self.max_paint_delay
+ while (any(x.refreshing for x in self.mods)
+ and (timeout := max_t - time.monotonic()) > 0):
+ self.e_repaint.wait(timeout)
+ self.e_repaint.clear()
+ if self.e_flush.is_set():
+ break
+ self.e_flush.clear()
+ print(''.join([s for m in self.mods if (s := m.to_paint())]),
+ file=self.panel.stdin, flush=True)
Panel(
ModHLWMTags(spacing=0),
@@ -422,5 +448,6 @@ Panel(
ModDate(
fmts=('%Y-%m-%d %H:%M:%S', '%H:%M'),
tzs=({'id': None}, {'id': 'UTC'},
- {'id': 'Asia/Yerevan', 'label': 'AMT'}))
+ {'id': 'Asia/Yerevan', 'label': 'AMT'})),
+ max_paint_delay=0.01
).run()