Hyprland version
Hyprland 0.53.1 built from branch v0.53.1 at commit ab1d80f3d6aebd57a0971b53a1993b1c1dfe0b09 clean (version: bump to 0.53.1).
Date: Fri Jan 2 21:20:57 2026
Tag: v0.53.1, commits: 6766
Libraries:
Hyprgraphics: built against 0.5.0, system has 0.5.0
Hyprutils: built against 0.11.0, system has 0.11.0
Hyprcursor: built against 0.1.13, system has 0.1.13
Hyprlang: built against 0.6.7, system has 0.6.8
Aquamarine: built against 0.10.0, system has 0.10.0
Version ABI string: ab1d80f3d6aebd57a0971b53a1993b1c1dfe0b09_aq_0.10_hu_0.11_hg_0.5_hc_0.1_hlg_0.6
no flags were set
Describe your issue / feature…
There’s these screensaver-like commands such as cmatrix, cbonsai and so on. Most of these have a flag to run them in screensaver mode, meaning they will exit on any key press.
I like these, so I wrote a couple of scripts to take advantage of these features and put them on ~/bin which is on my path. I tried to achieve this with a single script. But I wanted a bit more control over what runs on the spawn terminal windows. Maybe a skill issue.
These scripts are as follows:
screensaver
This takes a command with options as arguments and spawns a full screen kitty window on each monitor and executes screensaver-cmd. Code:
#!/usr/bin/env bash
SCREENSAVER_CLASS="Screensaver"
LOCKFILE="/tmp/screensaver.lock"
[[ -f $LOCKFILE ]] && exit 0
(($# > 0)) || {
echo "No arguments provided" >&2
exit 1
}
touch "$LOCKFILE"
declare -a cmd=(
kitty
--start-as fullscreen
--class "$SCREENSAVER_CLASS"
-e screensaver-cmd "$@"
)
echo "${cmd[@]}" >/tmp/screensaver_cmd
hyprctl monitors -j | jq --raw-output '.[] | select(.focused == true).name' >/tmp/focused
for m in $(hyprctl monitors -j | jq --raw-output '.[] | .name'); do
hyprctl dispatch focusmonitor "$m"
hyprctl dispatch exec -- "${cmd[@]}"
done
screensaver-cmd
This takes a command with options as arguments and executes it. Code:
#!/usr/bin/env bash
(($# > 0)) || exit 1
EXECUTABLE="$1"
LOCKFILE="/tmp/screensaver.lock"
exit-screensaver() {
rm "$LOCKFILE" 2>/dev/null || return
pkill --exact "$EXECUTABLE"
pkill --full "$(</tmp/screensaver_cmd)"
hyprctl dispatch focusmonitor "$(</tmp/focused)"
}
trap exit-screensaver EXIT SIGINT SIGTERM SIGHUP SIGQUIT
sleep 0.5
"$@"
These are done in this way, so that on key press, the screensaver command will exit and all the spawned kitty windows are closed. There’s also some more cleanup just in case and focus is returned to the monitor that was focused before the screensaver.
hypridle config
general {
lock_cmd = pidof -q hyprlock || hyprlock
before_sleep_cmd = loginctl lock-session
after_sleep_cmd = hyprctl dispatch dpms on
}
listener {
timeout = 300
on-timeout = pidof -q hyprlock || screensaver cmatrix -s
on-resume = pkill --full screensaver-cmd
}
listener {
timeout = 2700
on-timeout = loginctl lock-session
}
listener {
timeout = 3600
on-timeout = hyprctl dispatch dpms off
on-resume = hyprctl dispatch dpms on
}
listener {
timeout = 7200
on-timeout = systemctl suspend
}
The issue
All this works great. But, there has to be at least one window.
For whatever reason, if there’s no window open, then you barely see the kitty window then it closes immediately. I made hypridle log while this happened. It seems that when there are no windows, it resumes immediately after starting the screensaver thing.
Log (truncated):
[LOG] Registered timeout rule for 5s:
on-timeout: pidof -q hyprlock || screensaver cmatrix -s
on-resume: pkill --full screensaver-cmd
ignore_inhibit: false
[LOG] Registered timeout rule for 2700s:
on-timeout: loginctl lock-session
on-resume:
ignore_inhibit: false
[LOG] Registered timeout rule for 3600s:
on-timeout: hyprctl dispatch dpms off
on-resume: hyprctl dispatch dpms on
ignore_inhibit: false
[LOG] Registered timeout rule for 7200s:
on-timeout: systemctl suspend
on-resume:
ignore_inhibit: false
[LOG] | got iface: wl_seat v9
[LOG] > Bound to wl_seat v9
[LOG] | got iface: wl_data_device_manager v3
[LOG] | got iface: wl_compositor v6
[LOG] | got iface: wl_subcompositor v1
[LOG] | got iface: wl_shm v1
[LOG] | got iface: wp_viewporter v1
[LOG] | got iface: wp_tearing_control_manager_v1 v1
[LOG] | got iface: wp_fractional_scale_manager_v1 v1
[LOG] | got iface: zxdg_output_manager_v1 v3
[LOG] | got iface: wp_cursor_shape_manager_v1 v2
[LOG] | got iface: zwp_idle_inhibit_manager_v1 v1
[LOG] | got iface: zwp_relative_pointer_manager_v1 v1
[LOG] | got iface: zxdg_decoration_manager_v1 v1
[LOG] | got iface: wp_alpha_modifier_v1 v1
[LOG] | got iface: zwlr_gamma_control_manager_v1 v1
[LOG] | got iface: ext_foreign_toplevel_list_v1 v1
[LOG] | got iface: zwp_pointer_gestures_v1 v3
[LOG] | got iface: zwlr_foreign_toplevel_manager_v1 v3
[LOG] | got iface: zwp_keyboard_shortcuts_inhibit_manager_v1 v1
[LOG] | got iface: zwp_text_input_manager_v1 v1
[LOG] | got iface: zwp_text_input_manager_v3 v1
[LOG] | got iface: zwp_pointer_constraints_v1 v1
[LOG] | got iface: zwlr_output_power_manager_v1 v1
[LOG] | got iface: xdg_activation_v1 v1
[LOG] | got iface: ext_idle_notifier_v1 v2
[LOG] > Bound to ext_idle_notifier_v1 v2
[LOG] | got iface: hyprland_lock_notifier_v1 v1
[LOG] > Bound to hyprland_lock_notifier_v1 v1
[LOG] | got iface: ext_session_lock_manager_v1 v1
[LOG] | got iface: zwp_input_method_manager_v2 v1
[LOG] | got iface: zwp_virtual_keyboard_manager_v1 v1
[LOG] | got iface: zwlr_virtual_pointer_manager_v1 v2
[LOG] | got iface: zwlr_output_manager_v1 v4
[LOG] | got iface: org_kde_kwin_server_decoration_manager v1
[LOG] | got iface: hyprland_focus_grab_manager_v1 v1
[LOG] | got iface: zwp_tablet_manager_v2 v1
[LOG] | got iface: zwlr_layer_shell_v1 v5
[LOG] | got iface: wp_presentation v2
[LOG] | got iface: xdg_wm_base v7
[LOG] | got iface: zwlr_data_control_manager_v1 v2
[LOG] | got iface: zwp_primary_selection_device_manager_v1 v1
[LOG] | got iface: xwayland_shell_v1 v1
[LOG] | got iface: zwlr_screencopy_manager_v1 v3
[LOG] | got iface: hyprland_toplevel_export_manager_v1 v2
[LOG] | got iface: hyprland_toplevel_mapping_manager_v1 v1
[LOG] | got iface: hyprland_global_shortcuts_manager_v1 v1
[LOG] | got iface: xdg_wm_dialog_v1 v1
[LOG] | got iface: wp_single_pixel_buffer_manager_v1 v1
[LOG] | got iface: wp_security_context_manager_v1 v1
[LOG] | got iface: hyprland_ctm_control_manager_v1 v2
[LOG] | got iface: hyprland_surface_manager_v1 v2
[LOG] | got iface: wp_content_type_manager_v1 v1
[LOG] | got iface: xdg_toplevel_tag_manager_v1 v1
[LOG] | got iface: xdg_system_bell_v1 v1
[LOG] | got iface: ext_workspace_manager_v1 v1
[LOG] | got iface: ext_data_control_manager_v1 v1
[LOG] | got iface: wp_pointer_warp_v1 v1
[LOG] | got iface: wp_fifo_manager_v1 v1
[LOG] | got iface: wp_commit_timing_manager_v1 v1
[LOG] | got iface: wp_color_manager_v1 v1
[LOG] | got iface: wp_drm_lease_device_v1 v1
[LOG] | got iface: wp_linux_drm_syncobj_manager_v1 v1
[LOG] | got iface: wp_drm_lease_device_v1 v1
[LOG] | got iface: wl_drm v2
[LOG] | got iface: zwp_linux_dmabuf_v1 v5
[LOG] | got iface: wl_output v4
[LOG] | got iface: wl_output v4
[LOG] found 4 rules
[LOG] wayland done, registering dbus
[LOG] Sleep inhibition enabled - inhibiting until the wayland session gets locked
[LOG] Using dbus path /org/freedesktop/login1/session/_313
[LOG] Inhibited sleep with fd 16
[TRACE] [core] got poll event
[TRACE] [core] got poll event
[TRACE] [core] got poll event
...many of these...
[TRACE] [core] got poll event
[TRACE] got dbus event
[TRACE] got dbus event
[TRACE] [core] got poll event
[TRACE] [core] got poll event
[TRACE] [core] got poll event
...many of these...
[TRACE] [core] got poll event
[TRACE] got dbus event
[TRACE] got dbus event
[TRACE] [core] got poll event
[TRACE] [core] got poll event
[TRACE] [core] got poll event
...many of these...
[TRACE] [core] got poll event
[TRACE[] TRACE] [core] got poll event
got dbus event
[TRACE] got dbus event
[TRACE] [core] got poll event
[TRACE] [core] got poll event
[TRACE] [core] got poll event
[TRACE] got dbus event
[TRACE] got dbus event
[TRACE] [core] got poll event
[TRACE] [core] got poll event
[TRACE] [core] got poll event
...many of these...
[TRACE] [core] got poll event
[TRACE] got dbus event
[TRACE] got dbus event
[TRACE] [core] got poll event
[TRACE] [core] got poll event
[TRACE] [core] got poll event
...many of these...
[TRACE] [core] got poll event
[TRACE] got dbus event
[TRACE] got dbus event
[TRACE] [core] got poll event
[TRACE] [core] got poll event
[TRACE] [core] got poll event
...many of these...
[TRACE] [core] got poll event
[TRACE] got dbus event
[TRACE] got dbus event
[TRACE] [core] got poll event
[TRACE] [core] got poll event
[TRACE] [core] got poll event
...many of these...
[TRACE] [core] got poll event
[TRACE] got dbus event
[TRACE] got dbus event
[TRACE] [core] got poll event
[TRACE] [core] got poll event
[TRACE] [core] got poll event
...many of these...
[TRACE] [core] got poll event
[TRACE] got dbus event
[TRACE] got dbus event
[TRACE] [core] got poll event
[TRACE] [core] got poll event
[TRACE] [core] got poll event
[TRACE] [core] got poll event
[TRACE] [core] got poll event
[TRACE] [core] got poll event
[TRACE] got dbus event
[TRACE] got dbus event
[TRACE] [core] got poll event
[TRACE] [core] got poll event
[TRACE] [core] got poll event
...many of these...
[TRACE] [core] got poll event
[TRACE] got dbus event
[TRACE] got dbus event
[TRACE] [core] got poll event
[TRACE] [core] got poll event
[TRACE] [core] got poll event
...many of these...
[TRACE] [core] got poll event
[TRACE] got dbus event
[TRACE] got dbus event
[TRACE] [core] got poll event
[TRACE] [core] got poll event
[TRACE] [core] got poll event
...many of these...
[TRACE] [core] got poll event
[TRACE] got dbus event
[TRACE] got dbus event
[TRACE] [core] got poll event
[TRACE] [core] got poll event
[TRACE] [core] got poll event
[TRACE] [core] got poll event
[TRACE] [core] got poll event
[TRACE] got dbus event
[TRACE] got dbus event
[TRACE] [core] got poll event
[TRACE] [core] got poll event
[TRACE] got dbus event
[TRACE] got dbus event
[TRACE] [core] got poll event
[TRACE] [core] got poll event
[TRACE] [core] got poll event
[TRACE] got dbus event
[TRACE] got dbus event
[TRACE] [core] got poll event
[TRACE] [core] got poll event
[TRACE] [core] got poll event
[TRACE] [core] got poll event
[TRACE] got dbus event
[TRACE] got dbus event
[TRACE] [core] got poll event
[TRACE] [core] got poll event
[TRACE] [core] got poll event
[TRACE] [core] got poll event
[TRACE] got dbus event
[TRACE] got dbus event
[TRACE] [core] got poll event
[TRACE] [core] got poll event
[TRACE] [core] got poll event
[TRACE] [core] got poll event
[TRACE] got dbus event
[TRACE] got dbus event
[TRACE] [core] got poll event
[TRACE] [core] got poll event
[TRACE] [core] got poll event
[TRACE] [core] got poll event
[TRACE] [core] got poll event
[TRACE] [core] got poll event
[TRACE] got dbus event
[TRACE] got dbus event
[TRACE] [core] got poll event
[TRACE] [core] got poll event
[TRACE] [core] got poll event
[TRACE] got dbus event
[TRACE] got dbus event
[TRACE] [core] got poll event
[TRACE] [core] got poll event
[TRACE] [[core] got poll event
TRACE] got dbus event
[TRACE] got dbus event
[TRACE] [core] got poll event
[TRACE] [core] got poll event
[TRACE] [core] got poll event
[TRACE] [core] got poll event
[TRACE] got dbus event
[TRACE] got dbus event
[TRACE] [core] got poll event
[TRACE] [core] got poll event
[TRACE] got dbus event
[TRACE] got dbus event
[TRACE] [core] got poll event
[TRACE] [core] got poll event
[TRACE] [core] got poll event
...many of these...
[TRACE] [core] got poll event
[TRACE] got dbus event
[TRACE] got dbus event
[TRACE] [core] got poll event
[TRACE] [core] got poll event
[TRACE] [core] got poll event
...many of these...
[TRACE] [core] got poll event
[TRACE] got dbus event
[TRACE] got dbus event
[TRACE] [core] got poll event
[TRACE] [core] got poll event
[TRACE] [core] got poll event
...many of these...
[TRACE] [core] got poll event
[TRACE] got dbus event
[TRACE] got dbus event
[TRACE] [core] got poll event
[TRACE] [core] got poll event
[TRACE] [core] got poll event
...many of these...
[TRACE] [core] got poll event
[TRACE] got wl event
[LOG] Idled: rule 5571f5a9fda0
[LOG] Running pidof -q hyprlock || screensaver cmatrix -s
[LOG] Executing pidof -q hyprlock || screensaver cmatrix -s
[LOG] Process Created with pid 158112
[TRACE] got wl event
ok
ok
ok
ok
[TRACE] [core] got poll event
[TRACE] [core] got poll event
[TRACE] [core] got poll event
...many of these...
[TRACE] [core] got poll event
[TRACE] got dbus event
[TRACE] got dbus event
[TRACE] [core] got poll event
[TRACE] [core] got poll event
[TRACE] [core] got poll event
...many of these...
[TRACE] [core] got poll event
[TRACE] got dbus event
[TRACE] got dbus event
[TRACE] [core] got poll event
[TRACE] [core] got poll event
[TRACE] [core] got poll event
...many of these...
[TRACE] [core] got poll event
[TRACE] got wl event
[LOG] Resumed: rule 5571f5a9fda0
[LOG] Running pkill --full screensaver-cmd
[LOG] Executing pkill --full screensaver-cmd
[LOG] Process Created with pid 158133
[TRACE] got wl event
[TRACE] [core] got poll event
[TRACE] [core] got poll event
[TRACE] got dbus event
[TRACE] got dbus event
[TRACE] [core] got poll event
...
I have not idea why this happens. It is probably inconsequential as I’d normally have something open anyway.
But I wanted to figure it out.
Thanks in advance.