DEV Community

Cover image for Building a Hyprland Widget Inspired by the "In Time" Movie
Mathis abbaszadeh
Mathis abbaszadeh

Posted on

Building a Hyprland Widget Inspired by the "In Time" Movie

**_

The Inspiration

_**
Have you ever watched a movie and thought, "I want that technology in real life"?

That happened to me with "In Time" (2011) - the dystopian sci-fi film where people have glowing green countdown timers embedded in their arms. When the timer hits zero, they die. Time literally becomes currency - you pay for coffee with minutes, earn years at work, and can transfer time between people.

It's a dark concept, but the visual of a constantly-visible countdown created something powerful: visceral time awareness.

So I built it for my Linux desktop.

### What is InTime Widget?

InTime Widget is a Hyprland overlay that displays countdown timers inspired by the film. Unlike your system clock that you glance at and ignore, InTime creates constant awareness of time passing.

Features

  • 4 Display Modes: Clock, countdown, midnight countdown, horror-style deadline
  • Dynamic Colors: Real-time color sampling from your screen
  • Sci-Fi Effects: 15-layer particle glow inspired by the movie
  • Wayland Native: Built with GTK4 and Layer Shell
  • IPC Control: Remote control via Unix sockets
  • Multi-Monitor: Display on one or all monitors

The Technical Stack

Building a Wayland overlay widget required some interesting technical choices:

GTK4 + Layer Shell

Wayland's security model doesn't allow arbitrary windows to float on top (unlike X11). The solution? Layer Shell - a Wayland protocol that lets you create overlay surfaces legitimately.

import gi
gi.require_version('Gtk', '4.0')
gi.require_version('Gtk4LayerShell', '1.0')
from gi.repository import Gtk, Gtk4LayerShell as LayerShell

class InTimeWidget(Gtk.Window):
    def __init__(self):
        super().__init__()

        # Initialize layer shell
        LayerShell.init_for_window(self)
        LayerShell.set_layer(self, LayerShell.Layer.OVERLAY)
        LayerShell.set_keyboard_mode(self, LayerShell.KeyboardMode.NONE)

        # Set anchors for positioning
        LayerShell.set_anchor(self, LayerShell.Edge.TOP, True)
        LayerShell.set_anchor(self, LayerShell.Edge.BOTTOM, True)
Enter fullscreen mode Exit fullscreen mode

This gives us:

  • ✅ Always-on-top behavior
  • ✅ Click-through transparency
  • ✅ Proper Wayland integration
  • ✅ Multi-monitor support

Cairo Rendering

For the visual effects (glow, particles, text rendering), I used Cairo - a 2D graphics library that integrates beautifully with GTK.

The challenge? Achieving true transparency (not just window opacity).

def on_draw(self, widget, cr):
    # Clear with full transparency
    cr.set_operator(cairo.Operator.SOURCE)
    cr.set_source_rgba(0, 0, 0, 0)
    cr.paint()

    # Now draw content
    cr.set_operator(cairo.Operator.OVER)
    # ... drawing code
Enter fullscreen mode Exit fullscreen mode

Using cairo.Operator.SOURCE clears the canvas to actual transparency, then switching to cairo.Operator.OVER for drawing creates proper alpha compositing.

Dynamic Color Sampling

One of the coolest features is adaptive colors - the widget samples your screen and adjusts its color to match.

On Wayland, this requires the grim screenshot tool:

def sample_screen_color(self):
    # Take screenshot
    subprocess.run(['grim', '/tmp/screen.png'],
                   capture_output=True)

    # Load and analyze
    img = Image.open('/tmp/screen.png')
    pixels = list(img.getdata())

    # Extract dominant color using custom algorithm
    color = self.process_colors(pixels)

    return color
Enter fullscreen mode Exit fullscreen mode

I implemented a hybrid color processor that:

  1. Calculates average RGB
  2. Finds dominant color by frequency
  3. Blends the two for better aesthetics
  4. Throttles updates to avoid performance issues

Multi-Monitor Architecture

Hyprland supports multiple monitors, so the widget needed to as well.

The approach: one GTK application, multiple windows:

class InTimeApplication(Gtk.Application):
    def do_activate(self):
        # Detect monitors
        monitors = self.get_monitors()

        # Create widget per monitor
        for monitor in monitors:
            widget = InTimeWidget(monitor_index=monitor.index)
            self.add_window(widget)
Enter fullscreen mode Exit fullscreen mode

Each window runs independently but can sync via IPC.

IPC Control System

For remote control (start/stop, change modes), I built a Unix socket server:

class IPCServer(threading.Thread):
    def __init__(self, widget, socket_path='/tmp/intime_widget.sock'):
        super().__init__(daemon=True)
        self.widget = widget
        self.socket_path = socket_path

    def run(self):
        with socket.socket(socket.AF_UNIX) as sock:
            sock.bind(self.socket_path)
            sock.listen(1)

            while True:
                conn, _ = sock.accept()
                data = conn.recv(1024).decode()
                self.handle_command(data)
Enter fullscreen mode Exit fullscreen mode

Commands like reload_config, forbidden_alarm, and toggle_screen_sampling work via simple netcat:

echo "reload_config" | nc -U /tmp/intime_widget.sock
Enter fullscreen mode Exit fullscreen mode

The Visual Effects

The "lightbulb" mode deserved special attention. It creates a 15-layer particle glow effect:

def draw_lightbulb(self, cr, text, x, y, r, g, b):
    # Draw 15 layers of decreasing opacity
    for i in range(15, 0, -1):
        size_offset = i * 3
        opacity = 0.4 - (i * 0.02)

        cr.set_source_rgba(r, g, b, opacity)
        # ... draw enlarged text with blur
Enter fullscreen mode Exit fullscreen mode

The effect builds from large, faint outer layers to sharp inner text - creating a sci-fi glow reminiscent of the movie's bio-clocks.

Performance Optimization

Desktop widgets need to be lightweight. Nobody wants a clock eating 10% CPU.

Optimizations:

  • Variable frame rates: 1fps for clock mode, 3fps for deadline, 20fps for lightbulb
  • Lazy updates: Only redraw when something changes
  • Low layer counts: 15 layers sounds like a lot, but it's tuned for efficiency
  • Throttled color sampling: Max once per 0.5 seconds

Result: <1% CPU idle, ~30-50MB RAM

The "Forbidden Alarm"

My favorite feature: an urgent visual alarm that takes over your screen.

Inspired by the movie scene where the protagonist's time runs out, this creates:

  • 12-layer glow effect
  • Pulsing waves
  • Screen shake (via positioning offsets)
  • Red color shift

Perfect for "oh crap, deadline is NOW" moments.

Challenges & Lessons

Challenge 1: Wayland Transparency

X11 made overlay windows trivial. Wayland's security model required learning Layer Shell protocol. Worth it for proper integration.

Challenge 2: Color Sampling Performance

Initial implementation took screenshots every frame - CPU usage spiked. Solution: throttling and caching.

Challenge 3: Multi-Monitor Sync

Keeping multiple widget instances in sync required careful IPC design. Used broadcasting to all instances.

Challenge 4: Font Rendering

Getting crisp, bold text at large sizes required Pango (GTK's text layout engine):

layout = PangoCairo.create_layout(cr)
font = Pango.FontDescription("Monospace Bold 78")
layout.set_font_description(font)
layout.set_text(time_str, -1)
PangoCairo.show_layout(cr, layout)
Enter fullscreen mode Exit fullscreen mode

What I Learned

  1. Wayland is different - Security model requires proper protocol support
  2. GTK4 is powerful - Once you learn it, complex UIs become simple
  3. Visual polish matters - The glow effects took 20% of dev time but create 80% of the appeal
  4. Performance first - Easy to build pretty effects; hard to make them efficient
  5. Community loves themes - Open source projects need good aesthetics

Try It Yourself

The widget is fully open source (MIT license) and ready to use:

GitHub: https://github.com/mathis0/InTime

Quick Start:

git clone https://github.com/mathis0/InTime.git
cd InTime
./scripts/install.sh
intime-widget start --mode countdown --duration 25m --style lightbulb
Enter fullscreen mode Exit fullscreen mode

What's Next?

Future ideas:

  • More color themes (Nord, Dracula, Catppuccin presets)
  • Integration with task managers
  • Sound effects for alarms
  • Customizable alarm triggers
  • Better multi-monitor configuration

Conclusion

Building InTime Widget taught me that time awareness changes behavior. With a countdown always visible, I find myself:

  • More focused during work sessions
  • Less likely to waste time
  • More aware of how I spend each hour

It's "Memento Mori" for the desktop age - a constant reminder that time is the ultimate currency.

If you've ever wanted that visceral time-awareness from "In Time" on your Linux desktop, give it a try!


Questions? Feedback? Drop a comment or open an issue on GitHub!

If you found this interesting, follow me on GitHub for more open source projects!



Enter fullscreen mode Exit fullscreen mode

Top comments (0)