You are not logged in.
I ended up using the sendshortcut Hyprland dispatcher to send Ctrl+v to the active window. See the full discussion in the post below.
I've just started using Hyprland over the past few weeks, and I'm trying to set up a simple key bind to run a script to paste (or type) the ISO-8601 date for today. Here's the script in question(today.zsh; there's nothing zsh-y about this script, I just find zsh seems to do the right thing most times where bash doesn't, or at least didn't the last time I used bash as my interpreter):
#!/usr/bin/env zsh
#set -x
#date +%F | tr -d '\n' | wtype -
date +%F | tr -d '\n' | wl-copy --primary --trim-newline | wl-paste --primary --no-newline
#set +xThis script runs perfectly when I run it from my interactive zsh, so I don't think it's a problem with the script itself. Whether I use wtype or wl-copy/wl-paste, it pastes or types the ISO-8601 date format ('YYYY-mm-dd', or +%Y-%m-%d, or +%F as strftime allows most places).2025-02-18
However, when I try to trigger it from a Hyprland key bind, it doesn't seem to work at all (no text is printed or typed as expected). I've tried the exec, execr, pass, and sendshortcut dispatchers. The latter two I didn't configure properly since they don't seem to be what I want. I've also been testing mostly with Wayland applications (Alacritty and qutebrowser); I'll try XWayland later once I get it working on basic Wayland apps.
Here's the relevant hyprland.conf definitions of the key bind:
$today = ~/.config/hypr/pastes/today.zsh
bind = SUPER CTRL, D, exec, $todayAnd here is what I think is the relevant log (hyprctl rollinglog | grep -C 5 today):
[LOG] Window rule workspace name:shell -> class:(.*[Aa]lacritty.*) matched [Window 64f2f6311530: title: "fluorine:fluorine|local"]
[LOG] Hyprctl: dispatcher focuswindow : class:Alacritty
[LOG] cursorImage request: shape 9 -> text
[LOG] [AQ] drm: Cursor buffer imported into KMS with id 29901
[LOG] Keybind triggered, calling dispatcher (68, , 100, exec)
[LOG] Executing ~/.config/hypr/pastes/today.sh
[LOG] Process Created with pid 1857709Whether I use wl-paste or wtype the behavior is the same, it seems to be executing my script, announces its PID, and nothing appears in Alacritty or qutebrowser. I haven't tried any XWayland programs (where the hyprctl clients output indicates the given window/client is an XWayland program).
Here's my complete hyprctl systeminfo -c:
Hyprland 0.47.2 built from branch at commit 882f7ad7d2bbfc7440d0ccaef93b1cdd78e8e3ff (version: bump to 0.47.2).
Date: Sun Feb 2 00:47:17 2025
Tag: v0.47.2, commits: 5767
built against:
aquamarine 0.7.2
hyprlang 0.6.0
hyprutils 0.5.0
hyprcursor 0.1.11
hyprgraphics 0.1.1
no flags were set
System Information:
System name: Linux
Node name: fluorine
Release: 6.13.2-zen1-1-zen
Version: #1 ZEN SMP PREEMPT_DYNAMIC Sat, 08 Feb 2025 18:54:38 +0000
GPU information:
00:02.0 VGA compatible controller [0300]: Intel Corporation Raptor Lake-P [Iris Xe Graphics] [8086:a7a0] (rev 04) (prog-if 00 [VGA controller])
os-release: NAME="Arch Linux"
PRETTY_NAME="Arch Linux"
ID=arch
BUILD_ID=rolling
ANSI_COLOR="38;2;23;147;209"
HOME_URL="https://archlinux.org/"
DOCUMENTATION_URL="https://wiki.archlinux.org/"
SUPPORT_URL="https://bbs.archlinux.org/"
BUG_REPORT_URL="https://gitlab.archlinux.org/groups/archlinux/-/issues"
PRIVACY_POLICY_URL="https://terms.archlinux.org/docs/privacy-policy/"
LOGO=archlinux-logo
plugins:
======Config-Start======
Config File: /home/trey/.config/hypr/hyprland.conf: Read Succeeded
################
### MONITORS ###
################
source = ~/.config/hypr/monitors.conf
###################
### MY PROGRAMS ###
###################
source = ~/.config/hypr/variables.conf
#############################
### ENVIRONMENT VARIABLES ###
#############################
source = ~/.config/hypr/env.conf
#####################
### LOOK AND FEEL ###
#####################
source = ~/.config/hypr/appearance.conf
#############
### INPUT ###
#############
source = ~/.config/hypr/input.conf
###################
### KEYBINDINGS ###
###################
source = ~/.config/hypr/keybindings.conf
##################
### WORKSPACES ###
##################
source = ~/.config/hypr/workspaces.conf
###################
### WINDOWRULES ###
###################
source = ~/.config/hypr/windowrules.conf
##############
### MACROS ###
##############
source = ~/.config/hypr/macros.conf
#################
### AUTOSTART ###
#################
source = ~/.config/hypr/autostart.conf
Config File: /home/trey/.config/hypr/monitors.conf: Read Succeeded
monitor=,preferred,auto,auto
Config File: /home/trey/.config/hypr/variables.conf: Read Succeeded
$app = ~/.config/hypr/scripts/focusOrLaunch
#$fileManager = dolphin
$launcher = rofi -show run -p "launch"
$kill_hp_systray = ~/.config/hypr/scripts/kill-hp-systray
#$prompt =
$cycle_ws = ~/.config/hypr/scripts/cycleWorkspace
$next_ws = $cycle_ws next
$prev_ws = $cycle_ws prev
$create_ws = ~/.config/hypr/scripts/cycleWorkspace
$today = ~/.config/hypr/pastes/today.zsh
Config File: /home/trey/.config/hypr/env.conf: Read Succeeded
env = GDK_BACKEND,wayland,x11,*
env = HYPRCURSOR_SIZE,18
env = QT_QPA_PLATFORM,wayland;xcb
env = QT_QPA_PLATFORMTHEME,gtk3
env = QT_AUTO_SCREEN_SCALE_FACTOR,1
env = QT_WAYLAND_DISABLE_WINDOWDECORATION,1
env = XCURSOR_SIZE,18
env = XDG_CURRENT_DESKTOP,Hyprland
env = XDG_SESSION_TYPE,wayland
env = XDG_SESSION_DESKTOP,Hyprland
Config File: /home/trey/.config/hypr/appearance.conf: Read Succeeded
#####################
### LOOK AND FEEL ###
#####################
# Refer to https://wiki.hyprland.org/Configuring/Variables/
# https://wiki.hyprland.org/Configuring/Variables/#general
general {
gaps_in = 1
gaps_out = 2
border_size = 2
# https://wiki.hyprland.org/Configuring/Variables/#variable-types for info about colors
col.active_border = rgba(ffd7afaa)
col.inactive_border = rgba(595959aa)
# Set to true enable resizing windows by clicking and dragging on borders and gaps
resize_on_border = false
# Please see https://wiki.hyprland.org/Configuring/Tearing/ before you turn this on
allow_tearing = false
layout = dwindle
}
# https://wiki.hyprland.org/Configuring/Variables/#decoration
decoration {
rounding = 10
rounding_power = 2
# Change transparency of focused and unfocused windows
active_opacity = 1.0
inactive_opacity = 1.0
shadow {
enabled = true
range = 4
render_power = 3
color = rgba(1a1a1aee)
}
# https://wiki.hyprland.org/Configuring/Variables/#blur
blur {
enabled = true
size = 3
passes = 1
vibrancy = 0.1696
}
}
# https://wiki.hyprland.org/Configuring/Variables/#animations
animations {
enabled = yes, please :)
# Default animations, see https://wiki.hyprland.org/Configuring/Animations/ for more
bezier = easeOutQuint,0.23,1,0.32,1
bezier = easeInOutCubic,0.65,0.05,0.36,1
bezier = linear,0,0,1,1
bezier = almostLinear,0.5,0.5,0.75,1.0
bezier = quick,0.15,0,0.1,1
animation = global, 1, 10, default
animation = border, 1, 5.39, easeOutQuint
animation = windows, 1, 4.79, easeOutQuint
animation = windowsIn, 1, 4.1, easeOutQuint, popin 87%
animation = windowsOut, 1, 1.49, linear, popin 87%
animation = fadeIn, 1, 1.73, almostLinear
animation = fadeOut, 1, 1.46, almostLinear
animation = fade, 1, 3.03, quick
animation = layers, 1, 3.81, easeOutQuint
animation = layersIn, 1, 4, easeOutQuint, fade
animation = layersOut, 1, 1.5, linear, fade
animation = fadeLayersIn, 1, 1.79, almostLinear
animation = fadeLayersOut, 1, 1.39, almostLinear
animation = workspaces, 1, 1.94, almostLinear, fade
animation = workspacesIn, 1, 1.21, almostLinear, fade
animation = workspacesOut, 1, 1.94, almostLinear, fade
}
# Ref https://wiki.hyprland.org/Configuring/Workspace-Rules/
# "Smart gaps" / "No gaps when only"
# uncomment all if you wish to use that.
# workspace = w[tv1], gapsout:0, gapsin:0
# workspace = f[1], gapsout:0, gapsin:0
# windowrulev2 = bordersize 0, floating:0, onworkspace:w[tv1]
# windowrulev2 = rounding 0, floating:0, onworkspace:w[tv1]
# windowrulev2 = bordersize 0, floating:0, onworkspace:f[1]
# windowrulev2 = rounding 0, floating:0, onworkspace:f[1]
# See https://wiki.hyprland.org/Configuring/Dwindle-Layout/ for more
dwindle {
pseudotile = true # Master switch for pseudotiling. Enabling is bound to mainMod + P in the keybinds section below
preserve_split = true # You probably want this
}
# See https://wiki.hyprland.org/Configuring/Master-Layout/ for more
master {
new_status = master
}
# https://wiki.hyprland.org/Configuring/Variables/#misc
misc {
new_window_takes_over_fullscreen = 1
force_default_wallpaper = 0 # Set to 0 or 1 to disable the anime mascot wallpapers
disable_hyprland_logo = true # If true disables the random hyprland logo / anime girl background. :(
}
Config File: /home/trey/.config/hypr/input.conf: Read Succeeded
#############
### INPUT ###
#############
# https://wiki.hyprland.org/Configuring/Variables/#input
input {
kb_layout = us
kb_variant =
kb_model =
kb_options =
kb_rules =
follow_mouse = 1
sensitivity = 0 # -1.0 - 1.0, 0 means no modification.
touchpad {
natural_scroll = false
}
}
# https://wiki.hyprland.org/Configuring/Variables/#gestures
gestures {
workspace_swipe = false
}
# Example per-device config
# See https://wiki.hyprland.org/Configuring/Keywords/#per-device-input-configs for more
device {
name = epic-mouse-v1
sensitivity = -0.5
}
Config File: /home/trey/.config/hypr/keybindings.conf: Read Succeeded
# Hyprland
bind = SUPER, Q, exec, hyprctl reload
bind = SUPER SHIFT, Q, exec, $kill_hp_systray
bind = SUPER SHIFT, Q, exit
bind = SUPER, L, exec, hyprlock
# app launchers
bind = SUPER, V, exec, $app "alacritty" "Alacritty"
bind = SUPER, return, exec, $app "alacritty" "Alacritty"
bind = SUPER ALT, H, exec, $app "qutebrowser" "org.qutebrowser.qutebrowser"
bind = SUPER, A, exec, $app "slack"
bind = SUPER, G, exec, $app "vivaldi-stable"
bind = SUPER, P, exec, $launcher
# window control
bind = SUPER, C, killactive,
bind = SUPER, T, togglefloating
bind = SUPER, space, fullscreen, 1 # dwindle
bind = SUPER, H, movefocus, l
bind = SUPER, L, movefocus, r
bind = SUPER, K, movefocus, u
bind = SUPER, J, movefocus, d
#
bind = SUPER, X, exec, dunstctl close
bind = SUPER, Y, exec, dunstctl close-all
# workspace control
bind = SUPER, right, exec, $next_ws
bind = SUPER, left, exec, $prev_ws
bind = SUPER SHIFT, H, exec, $prev_ws
bind = SUPER SHIFT, L, exec, $next_ws
# cliphist
bind = ALT, V, exec, cliphist list | rofi -dmenu -p 'paste' | cliphist decode | wl-copy && wl-paste
# laptop keys
bind = , XF86MonBrightnessUp, exec, brightnessctl -- set +10%
bind = , XF86MonBrightnessDown, exec, brightnessctl -- set -10%
Config File: /home/trey/.config/hypr/workspaces.conf: Read Succeeded
workspace = 1, defaultName:shell, monitor:eDP-1, default:true, persistent:true
workspace = 2, defaultName:browser, monitor:eDP-1, persistent:true
workspace = 3, defaultName:work, monitor:eDP-1, persistent:true
workspace = 4, defaultName:meeting, monitor:eDP-1, persistent:true
Config File: /home/trey/.config/hypr/windowrules.conf: Read Succeeded
# XWayland dragging stuff
windowrulev2 = nofocus,class:^$,title:^$,xwayland:1,floating:1,fullscreen:0,pinned:0
# window classes that should be floating
$float_regex = (gcr-prompter|qt5ct|qt6ct|simple-scan)
windowrulev2 = float,class:$float_regex
# maiximize eveyrthing else
windowrulev2 = maximize,class:negative:$float_regex
# espanso
windowrulev2 = workspace special,title:(Espanso Sync Tool)
# workspace binds for windows
$browsers = (.*qutebrowser.*|.*[Ff]irefox.*)
$pindrop = (.*[Ss]lack|.*[Vv]ivaldi.*)
$meeting = (.*[Zz]oom.*)
windowrulev2 = workspace name:shell,class:(.*[Aa]lacritty.*)
windowrulev2 = workspace name:browser,class:$browsers
windowrulev2 = workspace name:work,class:$pindrop
windowrulev2 = workspace name:meeting,class:$meeting
Config File: /home/trey/.config/hypr/macros.conf: Read Succeeded
bind = SUPER CTRL, D, exec, $today
#bind = SUPER CTRL, T, exec, sleep 0.3 && date -d '+1 day' +%F | wl-copy --type text/plain && wl-paste --no-newline
#bind = SUPER CTRL, Y, exec, sleep 0.3 && date -d '-1 day' +%F | wl-copy --type text/plain && wl-paste --no-newline
Config File: /home/trey/.config/hypr/autostart.conf: Read Succeeded
# Hyprland exosystem stuff
exec-once = hyprpolkitagent
exec-once = hypridle
exec-once = hyprpaper
exec-once = tmux setenv -g HYPRLAND_INSTANCE_SIGNATURE "${HYPRLAND_INSTANCE_SIGNATURE}"
# notification daemon
exec-once = dunst
# systray apps
exec-once = nm-applet
exec-once = signal-desktop
exec-once = sleep 15 && hp-systray
exec-once = sleep 15 && blueman-applet
# status bar
exec-once = eww daemon && eww open bar
# cliphist
exec-once = wl-paste --primary --watch cliphist store
# GUI apps to launch
exec-once = qutebrowser
exec-once = vivaldi-stable
exec-once = slack
exec-once = sleep 10 && alacritty
======Config-End========I've also noticed that cliphist/rofi doesn't paste the clipboard automatically either, it seems I have to press Ctrl-v again to actually paste/type the clipboard item (which also seems to be a workaround for this particular key bind as well). Every other desktop automation/macro program I use across Linux (X.org/autokey), macOS (Keyboard Maestro), and Windows (Auto Hot Key) gets this right, but I've had a helluva time getting it to work as I expect in Hyprland.
Is this a bug? Or am I just missing something basic?
Last edited by ectospasm (2025-02-22 21:24:05)
Offline
I was given a clue from my responses on Reddit r/hyprland, where I was reminded that wl-paste simply copies the active clipboard item to stdout. I did know that, I have two aliases which make use of this:
alias pbcopy='wl-copy '
alias pbpaste='wl-paste 'Yes, these are the macOS commands to pipe stdin/stdout to/from the clipboard. Since I have to use a Mac for work, I typically mimic macOS CLI commands in Linux, through aliases, shell functions, and scripts. For instance, I have an open shell function which calls mimeo underneath.
I finally got this working. First, I generalized my script, and took out the calls to wl-copy and wl-paste:
#!/usr/bin/env zsh
#set -x
case "$(basename ${0})" in
today)
date +%F'
;;
yesterday)
date -d '-1 day' +%F
;;
tomorrow)
date -d '+1 day' +%F
;;
nextweek)
date -d '+1 week' +%F
;;
lastweek)
date -d '-1 week' +%F
;;
nextyear)
date -d '+1 year' +%F
;;
lastyear)
date -d '-1 year' +%F
;;
now)
date +'%FT%T %:z'
;;
*)
date
;;
esac
#set +xThe way this works is I have hard links (e.g. ln date today), so it will behave differently depending on how it is invoked. Then, I set a number of Hyprland variables:
$date = ~/.config/hypr/pastes/date
$today = ~/.config/hypr/pastes/today
$yesterday = ~/.config/hypr/pastes/yesterday
$tomorrow = ~/.config/hypr/pastes/tomorrow
$now = ~/.config/hypr/pastes/now
$nextweek = ~/.config/hypr/pastes/nextweek
$lastweek = ~/.config/hypr/pastes/lastweek
$lastyear = ~/.config/hypr/pastes/lastyear
$nextyear = ~/.config/hypr/pastes/nextyearI did get a little carried away with these, I don't really need all of these (I definitely don't currently have key binds for them). And the thing that solved it was the use of the sendshortcut dispatcher. The trick was remembering dispatcher parameters need ALL of the fields, even if they'll be blank. So, to have sendshortcut apply to the currently active window/client, the last field should be empty (but the trailing comma ',' is absolutely necessary). See here:
# date stuff
bind = SUPER CTRL, D, exec, $today | wl-copy --trim-newline && hyprctl dispatch sendshortcut "CTRL,V,"
bind = SUPER CTRL, N, exec, $now | wl-copy --trim-newline && hyprctl dispatch sendshortcut "CTRL,V,"
bind = SUPER CTRL, Y, exec, $yesterday | wl-copy --trim-newline && hyprctl dispatch sendshortcut "CTRL,V,"
bind = SUPER CTRL, T, exec, $tomorrow | wl-copy --trim-newline && hyprctl dispatch sendshortcut "CTRL,V,"At first I had the call to the sendshortcut dispatcher as a second key bind, but that would paste the last clipboard item (before the desired date string) on the first paste. Subsequent pastes with the keybind would be the correct date string, but doing it the way that I thought it should work didn't.
So, yeah, all this has been learning the idiosyncrasies of Hyprlang, and Wayland itself. It even works in the XWayland app I just tried (Slack), but YMMV.
Offline