From cc3ceda272968456f8fa4c4daed4ab778c4c5df4 Mon Sep 17 00:00:00 2001 From: Nathan Woodburn Date: Wed, 22 Oct 2025 16:24:45 +1100 Subject: [PATCH] feat: Add lockscreen spots effect --- .config/hypr/hyprlock.conf | 14 +- .config/hypr/keybinds.conf | 10 +- .config/hypr/scripts/lock-image.sh | 64 +++++ .config/hypr/scripts/spots.sh | 380 +++++++++++++++++++++++++++++ 4 files changed, 463 insertions(+), 5 deletions(-) create mode 100755 .config/hypr/scripts/lock-image.sh create mode 100755 .config/hypr/scripts/spots.sh diff --git a/.config/hypr/hyprlock.conf b/.config/hypr/hyprlock.conf index f134790..420a7e0 100644 --- a/.config/hypr/hyprlock.conf +++ b/.config/hypr/hyprlock.conf @@ -12,6 +12,8 @@ auth { # GENERAL general { hide_cursor = true + screencopy_mode = 0 + immediate_render = false } animation { @@ -21,13 +23,17 @@ animation { # BACKGROUND background { - path = $HOME/.config/lockpaper - + path = screenshot + blur_passes = 2 #reload_time = 15 #reload_cmd = echo $HOME/.config/lockpaper - blur_passes = 0 + # blur_passes = 0 crossfade_time = 1 } + +# AUTO BACKGROUND +# AUTO BACKGROUND END + # TIME label { text = $TIME @@ -108,4 +114,4 @@ input-field { capslock_color = rgb(255, 0, 0) halign = left valign = center -} \ No newline at end of file +} diff --git a/.config/hypr/keybinds.conf b/.config/hypr/keybinds.conf index 3b98fed..95eb41b 100644 --- a/.config/hypr/keybinds.conf +++ b/.config/hypr/keybinds.conf @@ -16,7 +16,7 @@ bind = $mainMod, Q, killactive, bind = $mainMod, F, togglefloating, bind = $mainMod, space, exec, $menu bind = ALT, SPACE, exec, ~/.config/hypr/scripts/search-windows.sh -bind = $mainMod, L, exec, hyprlock +bind = $mainMod, L, exec, /home/nathan/.config/hypr/scripts/lock-image.sh bind = $mainMod, H, exec, alacritty --class float -e ~/.config/hypr/scripts/help.py #bind = $mainMod, V, exec, [float] alacritty --class clipse -e /home/nathan/.local/bin/clipse @@ -148,6 +148,14 @@ bind = , 2, exec, hyprpanel -q bind = , 2, exec, hyprpanel bind = , 2, submap, reset +bind = CTRL, 3, movetoworkspace, special:alternate +bind = CTRL, 3, submap, reset + +bind = , 3, togglespecialworkspace, alternate +bind = , 3, submap, reset + + + bind = , T, exec, hyprctl notify 5 2000 0 "Select text to copy to clipboard..." bind = , T, exec, ~/.config/OCR4Linux/OCR4Linux.sh --lang eng -r bind = , T, submap, reset diff --git a/.config/hypr/scripts/lock-image.sh b/.config/hypr/scripts/lock-image.sh new file mode 100755 index 0000000..df84718 --- /dev/null +++ b/.config/hypr/scripts/lock-image.sh @@ -0,0 +1,64 @@ +#!/usr/bin/env bash + +# Path to hyprlock configuration file +CONF="$HOME/.config/hypr/hyprlock.conf" + +# Get the list of outputs +mapfile -t outputs < <(hyprctl -j monitors | jq -r '.[].name') + +# Generate the background blocks for each output +block="" +for output in "${outputs[@]}"; do + block+=$'background {\n' + block+=$" monitor = ${output}\n" + block+=$" path = screenshot\n" + block+=$" reload_time = 0\n" + block+=$" reload_cmd = echo \"/tmp/${output}-lockscreen.png\"\n" + block+=$" crossfade_time = 1\n" + block+=$'}\n\n' +done +# Insert the generated blocks into the configuration file +awk -v content="$block" ' + /^# AUTO BACKGROUND$/ { print; print content; inside=1; next } + inside && /^# AUTO BACKGROUND END$/ { print; inside=0; next } + inside { next } + { print } +' "$CONF" > "${CONF}.tmp" && mv "${CONF}.tmp" "$CONF" + +# Take a screenshot of each output before locking (!THIS IS SLOW!) +for output in "${outputs[@]}"; do + grim -o "$output" "/tmp/${output}-lockscreen.png" & +done +wait + + +# Start hyprlock while we process the images +/home/nathan/Git/hyprlock/build/hyprlock & + +# Apply image effect to each screenshot +for output in "${outputs[@]}"; do + # Apply blur effect using spots.sh + /home/nathan/.config/hypr/scripts/spots.sh -s 8 "/tmp/${output}-lockscreen.png" "/tmp/${output}-lockscreen.png" & +done +# Wait for all image processing to complete +while pgrep -x spots.sh >/dev/null; do + sleep 0.1 +done + +# Notify hyprlock to reload backgrounds +echo "Reloading hyprlock backgrounds..." +pkill -USR2 hyprlock + +# Wait for hyprlock to exit +while pgrep -x hyprlock >/dev/null; do + echo "Waiting for hyprlock to exit..." + sleep 1 +done + +# Cleanup: Restore hyprlock.conf to original state +sed -i '/^# AUTO BACKGROUND$/,/^# AUTO BACKGROUND END$/{//!d}' "$CONF" + +# Remove the screenshots +for output in "${outputs[@]}"; do + rm "/tmp/${output}-lockscreen.png" +done diff --git a/.config/hypr/scripts/spots.sh b/.config/hypr/scripts/spots.sh new file mode 100755 index 0000000..8b132ce --- /dev/null +++ b/.config/hypr/scripts/spots.sh @@ -0,0 +1,380 @@ +#!/bin/bash +# +# Developed by Fred Weinhaus 8/4/2011 .......... 5/28/2015 +# +# ------------------------------------------------------------------------------ +# +# Licensing: +# +# Copyright © Fred Weinhaus +# +# My scripts are available free of charge for non-commercial use, ONLY. +# +# For use of my scripts in commercial (for-profit) environments or +# non-free applications, please contact me (Fred Weinhaus) for +# licensing arrangements. My email address is fmw at alink dot net. +# +# If you: 1) redistribute, 2) incorporate any of these scripts into other +# free applications or 3) reprogram them in another scripting language, +# then you must contact me for permission, especially if the result might +# be used in a commercial or for-profit environment. +# +# My scripts are also subject, in a subordinate manner, to the ImageMagick +# license, which can be found at: http://www.imagemagick.org/script/license.php +# +# ------------------------------------------------------------------------------ +# +#### +# +# USAGE: spots [-s size] [-t type] [-p pad] [-b bgcolor] [-e edge] [-E ecolor] [-B brightness] [-C Contrast] infile [spotfile] outfile +# USAGE: spots [-help] +# +# OPTIONS: +# +# -s size spot size expressed as WxH in pixels; default=5x5 +# -t type type of spot shape; choices are: circle (or c), +# square (or s), or diamond (or d); default=circle +# -p pad padding or border around spot cell in pixels on +# each side; integer>=0; default=1 +# -b bgcolor background color to apply to image where spot +# does not cover; any valid IM color; default=black +# -e edge edge thickness accent around spot shape; +# integer>=0; default=0 +# -E ecolor color of accent edge around spot shape; +# any valid IM color; default=gray +# -B brightness percent change in brightness of spots; +# integer; default=0 +# -C contrast percent change in contrast of spots; +# integer; default=0 +# +# +### +# +# NAME: SPOTS +# +# PURPOSE: Converts the image into a series of uniform-colored spots. +# +# DESCRIPTION: SPOTS converts the image into a series of uniform-colored +# spots. The shape of spots allowed are: circle (ellipse), square (rectangle) +# or diamond. The spot size may be adjusted. A colored edge may also be +# placed around each spot. An optional spotfile may be provided to define +# some other shape than those built-in. +# +# +# OPTIONS: +# +# -s size ... SIZE is the WxH dimensions of the spot cell. Values are a +# pair of positive integers separated by an x. The default=5x5. If only +# one value is provided, it will be used for both. This parameter is +# ignored if a spotfile is provided. +# +# -t type ... TYPE is the type of spot shape. The choices are: circle (or c), +# square (or s), diamond (or d). These may be asymmetric as ellipses or +# rectangles as controlled by the size parameters. This parameter is +# ignored if a spotfile is provided. +# +# -p pad ... PAD is the border around the spot cell. Values are integers>=0. +# The default=0. +# +# -b bgcolor ... BGCOLOR is the color to apply to the image between the spots. +# Any valid IM color is allowed. The default=black. +# +# -e edge ... EDGE is the thickness of the optional edge hightlight around +# the spot shape. Values are integers>=0. The default=0. +# +# -E ecolor ... ECOLOR is the color of the edge highlight. Any valid IM color +# is allowed. The default=gray. +# +# -B brightness ... BRIGHTNESS is the percent change in brightness of the +# spot colors. Values are integers. The default=0 +# +# -C contrast ... CONTRAST is the percent change in contrast of the +# spot colors. Values are integers. The default=0 +# +# The spotfile must be a binary mask with white for the shape and black +# for the background and no alpha channel. +# +# REQUIREMENTS: IM 6.3.6-1 or higher due to the use of +# -define distort:viewport=WxH+X+Y with -distort SRT. +# +# CAVEAT: No guarantee that this script will work on all platforms, +# nor that trapping of inconsistent parameters is complete and +# foolproof. Use At Your Own Risk. +# +###### +# + +# set default values +size="5x5" # spot WxH +type="circle" # circle, square, diamond +pad=1 # border padding +edge=0 # edge width +ecolor="gray" # edge color +bgcolor="black" # background color +bri=0 # brightness +con=0 # contrast + +# set directory for temporary files +dir="." # suggestions are dir="." or dir="/tmp" + +# set up functions to report Usage and Usage with Description +PROGNAME=`type $0 | awk '{print $3}'` # search for executable on path +PROGDIR=`dirname $PROGNAME` # extract directory of program +PROGNAME=`basename $PROGNAME` # base name of program +usage1() + { + echo >&2 "" + echo >&2 "$PROGNAME:" "$@" + sed >&2 -e '1,/^####/d; /^###/g; /^#/!q; s/^#//; s/^ //; 4,$p' "$PROGDIR/$PROGNAME" + } +usage2() + { + echo >&2 "" + echo >&2 "$PROGNAME:" "$@" + sed >&2 -e '1,/^####/d; /^######/g; /^#/!q; s/^#*//; s/^ //; 4,$p' "$PROGDIR/$PROGNAME" + } + + +# function to report error messages +errMsg() + { + echo "" + echo $1 + echo "" + usage1 + exit 1 + } + + +# function to test for minus at start of value of second part of option 1 or 2 +checkMinus() + { + test=`echo "$1" | grep -c '^-.*$'` # returns 1 if match; 0 otherwise + [ $test -eq 1 ] && errMsg "$errorMsg" + } + +# test for correct number of arguments and get values +if [ $# -eq 0 ] + then + # help information + echo "" + usage2 + exit 0 +elif [ $# -gt 19 ] + then + errMsg "--- TOO MANY ARGUMENTS WERE PROVIDED ---" +else + while [ $# -gt 0 ] + do + # get parameter values + case "$1" in + -help) # help information + echo "" + usage2 + exit 0 + ;; + -s) # get size + shift # to get the next parameter + # test if parameter starts with minus sign + errorMsg="--- INVALID SIZE SPECIFICATION ---" + checkMinus "$1" + size=`expr "$1" : '\([0-9]*[x]*[0-9]*\)'` + [ "$size" = "" ] && errMsg "--- SIZE=$size MUST BE A PAIR OF POSITIVE INTEGERS (with no sign) SEPARATED BY AN x ---" + ;; + -t) # type + shift # to get the next parameter + # test if parameter starts with minus sign + errorMsg="--- INVALID TYPE SPECIFICATION ---" + checkMinus "$1" + # test mode values + type="$1" + type=`echo "$type" | tr "[:upper:]" "[:lower:]"` + case "$type" in + circle|c) type="circle" ;; + square|s) type="square" ;; + diamond|d) type="diamond" ;; + *) errMsg "--- TYPE=$type IS AN INVALID VALUE ---" + esac + ;; + -p) # get pad + shift # to get the next parameter + # test if parameter starts with minus sign + errorMsg="--- INVALID PAD SPECIFICATION ---" + checkMinus "$1" + pad=`expr "$1" : '\([0-9]*\)'` + [ "$pad" = "" ] && errMsg "--- PAD=$pad MUST BE A NON-NEGATIVE INTEGER (with no sign) ---" + ;; + -b) # get bgcolor + shift # to get the next parameter + # test if parameter starts with minus sign + errorMsg="--- INVALID BGCOLOR SPECIFICATION ---" + checkMinus "$1" + bgcolor="$1" + ;; + -e) # get edge + shift # to get the next parameter + # test if parameter starts with minus sign + errorMsg="--- INVALID EDGE SPECIFICATION ---" + checkMinus "$1" + edge=`expr "$1" : '\([0-9]*\)'` + [ "$edge" = "" ] && errMsg "--- EDGE=$edge MUST BE A NON-NEGATIVE INTEGER (with no sign) ---" + ;; + -E) # get ecolor + shift # to get the next parameter + # test if parameter starts with minus sign + errorMsg="--- INVALID ECOLOR SPECIFICATION ---" + checkMinus "$1" + ecolor="$1" + ;; + -B) # get brightness + shift # to get the next parameter + # test if parameter starts with minus sign + errorMsg="--- INVALID BRIGHTNESS SPECIFICATION ---" + #checkMinus "$1" + bri=`expr "$1" : '\([-0-9]*\)'` + [ "$bri" = "" ] && errMsg "--- BRIGHTNESS=$bri MUST BE AN INTEGER (with no sign) ---" + ;; + -C) # get contrast + shift # to get the next parameter + # test if parameter starts with minus sign + errorMsg="--- INVALID CONTRAST SPECIFICATION ---" + #checkMinus "$1" + con=`expr "$1" : '\([-0-9]*\)'` + [ "$con" = "" ] && errMsg "--- CONTRAST=$con MUST BE AN INTEGER (with no sign) ---" + ;; + -) # STDIN and end of arguments + break + ;; + -*) # any other - argument + errMsg "--- UNKNOWN OPTION ---" + ;; + *) # end of arguments + break + ;; + esac + shift # next option + done + # + # get infile and outfile and spotfile + if [ $# -eq 3 ]; then + infile="$1" + spotfile="$2" + outfile="$3" + elif [ $# -eq 2 ]; then + infile="$1" + outfile="$2" + else + errMsg "--- INCONSISTENT NUMBER OF IMAGES PROVIDED ---" + fi +fi + +# test that infile provided +[ "$infile" = "" ] && errMsg "NO INPUT FILE SPECIFIED" + +# test that outfile provided +[ "$outfile" = "" ] && errMsg "NO OUTPUT FILE SPECIFIED" + +# create temp files +tmpA1="$dir/spots_1_$$.mpc" +tmpB1="$dir/spots_1_$$.cache" +tmpA2="$dir/spots_2_$$.mpc" +tmpB2="$dir/spots_2_$$.cache" +trap "rm -f $tmpA1 $tmpB1 $tmpA2 $tmpB2;" 0 +trap "rm -f $tmpA1 $tmpB1 $tmpA2 $tmpB2; exit 1" 1 2 3 15 +trap "rm -f $tmpA1 $tmpB1 $tmpA2 $tmpB2; exit 1" ERR + +# setup brightness contrast +if [ "$bri" = "0" -a "$con" = "0" ]; then + bricon="" +else + bricon="-brightness-contrast $bri,$con" +fi + +# test input image +convert -quiet "$infile" $bricon -clamp +repage "$tmpA1" || + errMsg "--- FILE $infile DOES NOT EXIST OR IS NOT AN ORDINARY FILE, NOT READABLE OR HAS ZERO SIZE ---" + +# test spot file if exists +if [ "$spotfile" != "" ]; then + convert -quiet "$spotfile" -alpha off +repage "$tmpA2" || + errMsg "--- FILE $spotfile DOES NOT EXIST OR IS NOT AN ORDINARY FILE, NOT READABLE OR HAS ZERO SIZE ---" +fi + +# get image width, height and aspect +ww=`convert $tmpA1 -ping -format "%w" info:` +hh=`convert $tmpA1 -ping -format "%h" info:` + +# get size of spot and center of spot and last pixel of spot and pad size +if [ "$spotfile" = "" ]; then + sw=`echo $size | cut -dx -f1` + sh=`echo $size | cut -dx -f2` + scx=`convert xc: -format "%[fx:($sw-1)/2]" info:` + scy=`convert xc: -format "%[fx:($sh-1)/2]" info:` + lx=$((sw-1)) + ly=$((sh-1)) + + # get pad size + pw=$((sw+2*pad)) + ph=$((sh+2*pad)) + +else + pw=`convert $tmpA2 -ping -format "%w" info:` + ph=`convert $tmpA2 -ping -format "%h" info:` +fi + + +if [ "$spotfile" = "" ]; then + if [ "$pad" = "0" ]; then + padding="" + else + padding="-bordercolor black -border $pad" + fi + + # create spot template + if [ "$type" = "circle" ]; then + convert -size ${sw}x${sh} xc:black \ + +antialias -fill white -draw "ellipse $scx,$scy $scx,$scy 0,360" -alpha off \ + $padding \ + $tmpA2 + + elif [ "$type" = "square" ]; then + convert -size ${sw}x${sh} xc:black \ + +antialias -fill white -draw "rectangle 0,0 $lx,$ly" -alpha off \ + $padding \ + $tmpA2 + + elif [ "$type" = "diamond" ]; then + convert -size ${sw}x${sh} xc:black \ + +antialias -fill white -draw "polygon $scx,0 $lx,$scy $scx,$ly 0,$scy" -alpha off \ + $padding \ + $tmpA2 + fi +fi + +# compute xmin and ymin and virtual canvas size +xmin=`convert xc: -format "%[fx:ceil($ww/$pw)]" info:` +ymin=`convert xc: -format "%[fx:ceil($hh/$ph)]" info:` +www=`convert xc: -format "%[fx:$xmin*$pw]" info:` +hhh=`convert xc: -format "%[fx:$ymin*$ph]" info:` + + +# process image +if [ "$edge" = "0" ]; then + convert \( $tmpA1 -define distort:viewport=${www}x${hhh}+0+0 -virtual-pixel mirror -distort SRT 0 \ + -scale ${xmin}x${ymin}! -scale ${www}x${hhh}! -crop ${ww}x${hh}+0+0 +repage \) \ + \( $tmpA2 -write mpr:tile +delete -size ${ww}x${hh}! tile:mpr:tile \) \ + -alpha off -compose copy_opacity -composite -compose over \ + -background $bgcolor -flatten \ + "$outfile" +else + convert \( $tmpA1 -define distort:viewport=${www}x${hhh}+0 -virtual-pixel mirror -distort SRT 0 \ + -scale ${xmin}x${ymin}! -scale ${www}x${hhh}! -crop ${ww}x${hh}+0+0 +repage \) \ + \( $tmpA2 -write mpr:tile +delete -size ${ww}x${hh}! tile:mpr:tile \) \ + \( -clone 1 -threshold 0 -edge $edge -clamp -fill $ecolor -opaque white -transparent black \) \ + \( -clone 0 -clone 1 -alpha off -compose copy_opacity -composite -compose over \ + -background $bgcolor -flatten \) \ + -delete 0,1 +swap -compose over -composite \ + "$outfile" +fi + +exit 0 \ No newline at end of file