diff options
author | David Vazgenovich Shakaryan <dvshakaryan@gmail.com> | 2024-02-22 12:38:51 -0800 |
---|---|---|
committer | David Vazgenovich Shakaryan <dvshakaryan@gmail.com> | 2024-02-22 12:38:51 -0800 |
commit | 43c215b4de76bb2a5558c9db4011572274287d36 (patch) | |
tree | 83712be0367de3997c90ac78288373abd9ffb2c4 /panel.py | |
parent | a25f5b90664f635afafd50ed2700f04783ee9c4a (diff) | |
download | panel-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-x | panel.py | 53 |
1 files changed, 40 insertions, 13 deletions
@@ -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() |