diff --git a/bin/xss-dimmer b/bin/xss-dimmer index 265ed5d..7da0443 100755 --- a/bin/xss-dimmer +++ b/bin/xss-dimmer @@ -15,6 +15,7 @@ from gi.repository import Gtk, Gdk, GLib, GdkPixbuf import cairo import argparse import threading +import time from Xlib import display, X from Xlib.error import BadWindow from Xlib.protocol.event import MapNotify @@ -40,7 +41,7 @@ def on_realize(widget): window.set_override_redirect(True) -def on_draw(widget, event, options, background, elapsed): +def on_draw(widget, event, options, background, start): def _dim(): r = cairo.Region(cairo.RectangleInt(0, 0, *widget.get_size())) dctx = window.begin_draw_frame(r) @@ -52,7 +53,8 @@ def on_draw(widget, event, options, background, elapsed): x, y = widget.get_position() wwidth, wheight = widget.get_size() delta = options.end_opacity - options.start_opacity - current = elapsed[0] / options.delay + elapsed = time.monotonic() - start + current = elapsed / options.delay opacity = delta * current + options.start_opacity # Background @@ -62,39 +64,41 @@ def on_draw(widget, event, options, background, elapsed): cctx.paint() else: scale = widget.get_scale_factor() - bg = background.new_subpixbuf(x, y, wwidth*scale, wheight*scale) + bg = background.new_subpixbuf(x, y, wwidth * scale, wheight * scale) cctx.save() - cctx.scale(1/scale, 1/scale) + cctx.scale(1 / scale, 1 / scale) Gdk.cairo_set_source_pixbuf(cctx, bg, 0, 0) cctx.paint_with_alpha(opacity) cctx.restore() # Remaining time - remaining = str(round(options.delay - elapsed[0])) - cctx.set_source_rgba(1, 1, 1, opacity) + if elapsed >= options.delay: + return + remaining = str(round(options.delay - elapsed)) cctx.select_font_face( options.font, cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_BOLD ) cctx.set_font_size(wheight // 4) _, _, twidth, theight, _, _ = cctx.text_extents(remaining) - cctx.move_to(wwidth // 2 - twidth // 2, wheight // 2 + theight // 2) + text_position = wwidth // 2 - twidth // 2, wheight // 2 + theight // 2 + cctx.move_to(*text_position) + cctx.set_source_rgba(1, 1, 1, opacity) cctx.show_text(remaining) + cctx.move_to(*text_position) cctx.set_source_rgba(0, 0, 0, opacity * 2) - cctx.move_to(wwidth // 2 - twidth // 2, wheight // 2 + theight // 2) - cctx.text_path(remaining) cctx.set_line_width(4) + cctx.text_path(remaining) cctx.stroke() # Rearm timer if not once: - elapsed[0] += options.step - if elapsed[0] <= options.delay: - GLib.timeout_add(options.step * 1000, _dim) + next_step = min(options.step, options.delay - elapsed) + on_draw.timer = GLib.timeout_add(next_step * 1000, _dim) window = widget.get_window() - if not elapsed: + dim(event) + if not hasattr(on_draw, "timer"): # First time we are called. - elapsed.append(0) dim(event) else: # Timers already running, just repaint @@ -102,6 +106,7 @@ def on_draw(widget, event, options, background, elapsed): if __name__ == "__main__": + now = time.monotonic() parser = argparse.ArgumentParser() add = parser.add_argument add("--start-opacity", type=float, default=0, help="initial opacity") @@ -134,7 +139,7 @@ if __name__ == "__main__": window.set_default_size(geom.width, geom.height) window.move(geom.x, geom.y) - window.connect("draw", on_draw, options, background, []) + window.connect("draw", on_draw, options, background, now) window.connect("delete-event", Gtk.main_quit) window.connect("realize", on_realize)