first pass of hyprland config
This commit is contained in:
@@ -0,0 +1,40 @@
|
||||
#####################################################################
|
||||
|
||||
DEPENDENCIES+=(hyprctl)
|
||||
|
||||
#####################################################################
|
||||
|
||||
${scwryptsmodule}() {
|
||||
eval "$(utils.parse.autosetup)"
|
||||
##########################################
|
||||
|
||||
local result="$(hyprctl eval "$(printf '%s\n' "${ARGS[@]}")")"
|
||||
|
||||
[[ "${result}" == ok ]] \
|
||||
|| echo.error "hyprctl eval failed : ${result}" \
|
||||
|| return 1
|
||||
}
|
||||
|
||||
#####################################################################
|
||||
|
||||
${scwryptsmodule}.parse() { return 0; }
|
||||
|
||||
${scwryptsmodule}.parse.locals() {
|
||||
local ARGS=()
|
||||
}
|
||||
|
||||
${scwryptsmodule}.parse.usage() {
|
||||
USAGE__description='
|
||||
run hyprland lua in the current hyprland instance (one statement per
|
||||
argument, evaluated together); fails unless hyprland replies "ok"
|
||||
'
|
||||
|
||||
USAGE__args='
|
||||
\$@ lua statements (e.g. "hl.dispatch(hl.dsp.window.center({}))")
|
||||
'
|
||||
}
|
||||
|
||||
${scwryptsmodule}.parse.validate() {
|
||||
[[ "${#ARGS[@]}" -gt 0 ]] \
|
||||
|| echo.error 'at least one lua statement is required'
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
#####################################################################
|
||||
|
||||
DEPENDENCIES+=(hyprctl jq)
|
||||
|
||||
#####################################################################
|
||||
|
||||
${scwryptsmodule}() {
|
||||
eval "$(utils.parse.autosetup)"
|
||||
##########################################
|
||||
|
||||
hyprctl -j clients \
|
||||
| jq -r --arg class "${CLIENT_CLASS}" '.[] | select(.class | test($class; "i")) | .address' \
|
||||
;
|
||||
}
|
||||
|
||||
#####################################################################
|
||||
|
||||
${scwryptsmodule}.parse() { return 0; }
|
||||
|
||||
${scwryptsmodule}.parse.locals() {
|
||||
local ARGS=()
|
||||
local CLIENT_CLASS
|
||||
}
|
||||
|
||||
${scwryptsmodule}.parse.usage() {
|
||||
USAGE__description='
|
||||
print the address of every hyprland window whose class matches
|
||||
(one per line; case-insensitive regex)
|
||||
'
|
||||
|
||||
USAGE__args='
|
||||
\$1 window class regex
|
||||
'
|
||||
}
|
||||
|
||||
${scwryptsmodule}.parse.validate() {
|
||||
CLIENT_CLASS="${ARGS[1]}"
|
||||
|
||||
[[ "${CLIENT_CLASS}" ]] \
|
||||
|| echo.error 'window class is required'
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
#
|
||||
# interact with the running hyprland instance
|
||||
#
|
||||
|
||||
|
||||
# run hyprland lua (hyprctl eval) with error checking
|
||||
use desktop/wayland/hyprland/eval --group dotwryn
|
||||
|
||||
# list window addresses matching a class regex
|
||||
use desktop/wayland/hyprland/get-window-addresses --group dotwryn
|
||||
+163
@@ -0,0 +1,163 @@
|
||||
#!/usr/bin/env zsh
|
||||
use notify
|
||||
use desktop/wayland/hyprland --group dotwryn
|
||||
|
||||
DEPENDENCIES+=(jq)
|
||||
#####################################################################
|
||||
|
||||
USAGE__usage+=' <path-executable> [...options...]'
|
||||
|
||||
USAGE__options="
|
||||
-c, --client <string> if different from the executable name, the window class (regex)
|
||||
|
||||
-s, --scale <value> (default: 0.8 or 0.5 if screen width >3000px)
|
||||
-x, --x-offset <value> (default: 0.0)
|
||||
-y, --y-offset <value> (default: 0.0)
|
||||
|
||||
-a, --always-launch invoke executable even if a window of client-class exists
|
||||
-n, --no-resize don't resize the window (ignores -sxy flags)
|
||||
-l, --no-center leave the window wherever it was last positioned
|
||||
|
||||
--has-statusbar-icon (accepted for i3 compatibility; no effect)
|
||||
"
|
||||
|
||||
USAGE__description="
|
||||
Hyprland port of 'desktop/xorg/i3/launch-or-show'.
|
||||
|
||||
Makes it easy to bind appications to key shortcuts without having to
|
||||
spin up redundant instances. Each application gets its own special
|
||||
workspace (hyprland's scratchpad), named after the executable:
|
||||
1) starts the application if it is not running
|
||||
2) moves all instances of the application to its special workspace
|
||||
3) (toggle) hides the special workspace if it is showing
|
||||
4) (toggle) shows the special workspace (resized and centered) if it is hidden
|
||||
"
|
||||
|
||||
#####################################################################
|
||||
|
||||
MAIN() {
|
||||
local SCWRYPTS_NOTIFICATION_ENGINES=(echo notify.desktop)
|
||||
|
||||
local application client_class
|
||||
local x_offset=0.0 y_offset=0.0 scale
|
||||
local always_launch=false resize=true center=true
|
||||
|
||||
local _s _p=0
|
||||
while [[ "${#}" -gt 0 ]]
|
||||
do
|
||||
_s=1
|
||||
case "${1}" in
|
||||
( -c | --client ) _s=2; client_class="${2}" ;;
|
||||
( -x | --x-offset ) _s=2; x_offset="${2}" ;;
|
||||
( -y | --y-offset ) _s=2; y_offset="${2}" ;;
|
||||
( -s | --scale ) _s=2; scale="${2}" ;;
|
||||
|
||||
( -a | --always-launch ) always_launch=true ;;
|
||||
( -n | --no-resize ) resize=false ;;
|
||||
( -l | --no-center ) center=false ;;
|
||||
|
||||
( --has-statusbar-icon ) ;;
|
||||
|
||||
( -h | --help ) USAGE; return 0 ;;
|
||||
|
||||
( * )
|
||||
case "$((_p+=1))" in
|
||||
( 1 ) application="${1}" ;;
|
||||
( * ) echo.error "extra positional argument '${1}'" ;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
shift "${_s}" || echo.error "missing value for argument '${1}'" || shift "${#}"
|
||||
done
|
||||
unset _s _p
|
||||
|
||||
[[ "${application}" ]] || echo.error 'path-executable required'
|
||||
[[ "${client_class}" ]] || client_class="${application}"
|
||||
|
||||
[[ "${application}" ]] && {
|
||||
utils.dependencies.check "${application}" \
|
||||
|| notify.error "${application} not found"
|
||||
}
|
||||
|
||||
utils.check-errors --fail
|
||||
|
||||
##########################################
|
||||
|
||||
local special_workspace="special:${application:t}"
|
||||
|
||||
local monitor="$(hyprctl -j monitors | jq -c '.[] | select(.focused)')"
|
||||
[[ "${scale}" ]] || {
|
||||
[[ "$(jq -r '.width' <<< "${monitor}")" -gt 3000 ]] \
|
||||
&& scale=0.5 \
|
||||
|| scale=0.8 \
|
||||
;
|
||||
}
|
||||
|
||||
##########################################
|
||||
|
||||
local addresses=($(dotwryn.desktop.wayland.hyprland.get-window-addresses "${client_class}"))
|
||||
|
||||
[[ "${always_launch}" == true ]] || [[ "${#addresses[@]}" -eq 0 ]] && {
|
||||
echo.status 'launching application'
|
||||
hyprctl dispatch "hl.dsp.exec_cmd(\"${application}\")" >/dev/null
|
||||
|
||||
echo.status 'waiting for application window'
|
||||
local wait_count
|
||||
for wait_count in {1..50}
|
||||
do
|
||||
[[ "$(dotwryn.desktop.wayland.hyprland.get-window-addresses "${client_class}" | wc -l)" -gt "${#addresses[@]}" ]] && break
|
||||
sleep 0.1
|
||||
done
|
||||
addresses=($(dotwryn.desktop.wayland.hyprland.get-window-addresses "${client_class}"))
|
||||
}
|
||||
|
||||
[[ "${#addresses[@]}" -gt 0 ]] \
|
||||
|| notify.error "no '${client_class}' window found for ${application}" \
|
||||
|| return 1
|
||||
|
||||
##########################################
|
||||
|
||||
echo.status 'moving windows to special workspace'
|
||||
local address lua=()
|
||||
for address in "${addresses[@]}"
|
||||
do
|
||||
lua+=(
|
||||
"hl.dispatch(hl.dsp.window.float({ window = \"address:${address}\", action = \"enable\" }))"
|
||||
"hl.dispatch(hl.dsp.window.move({ window = \"address:${address}\", workspace = \"${special_workspace}\", follow = false }))"
|
||||
)
|
||||
done
|
||||
|
||||
local shown_special="$(jq -r '.specialWorkspace.name' <<< "${monitor}")"
|
||||
[[ "${shown_special}" == "${special_workspace}" ]] && {
|
||||
echo.status 'hiding special workspace'
|
||||
lua+=("hl.dispatch(hl.dsp.workspace.toggle_special(\"${application:t}\"))")
|
||||
dotwryn.desktop.wayland.hyprland.eval "${lua[@]}"
|
||||
return $?
|
||||
}
|
||||
|
||||
echo.status 'showing special workspace'
|
||||
lua+=("hl.dispatch(hl.dsp.workspace.toggle_special(\"${application:t}\"))")
|
||||
|
||||
[[ "${resize}" == true ]] && {
|
||||
local window_size=($(jq -r \
|
||||
--argjson f "${scale}" --argjson x "${x_offset}" --argjson y "${y_offset}" \
|
||||
'"\((.width / .scale * $f + $x) | floor) \((.height / .scale * $f + $y) | floor)"' \
|
||||
<<< "${monitor}"
|
||||
))
|
||||
echo.debug "window size: ${window_size[*]}"
|
||||
|
||||
for address in "${addresses[@]}"
|
||||
do
|
||||
lua+=("hl.dispatch(hl.dsp.window.resize({ window = \"address:${address}\", x = ${window_size[1]}, y = ${window_size[2]} }))")
|
||||
done
|
||||
}
|
||||
|
||||
[[ "${center}" == true ]] && {
|
||||
for address in "${addresses[@]}"
|
||||
do
|
||||
lua+=("hl.dispatch(hl.dsp.window.center({ window = \"address:${address}\" }))")
|
||||
done
|
||||
}
|
||||
|
||||
dotwryn.desktop.wayland.hyprland.eval "${lua[@]}"
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
#!/usr/bin/env zsh
|
||||
use notify
|
||||
|
||||
DEPENDENCIES+=(hyprlock)
|
||||
#####################################################################
|
||||
|
||||
USAGE__description='
|
||||
Hyprland port of "desktop/xorg/i3/lock"; locks the session with hyprlock
|
||||
(themed by ~/.config/hypr/hyprlock.conf and the active colorscheme)
|
||||
'
|
||||
|
||||
#####################################################################
|
||||
|
||||
MAIN() {
|
||||
local SCWRYPTS_NOTIFICATION_ENGINES=(echo notify.desktop)
|
||||
|
||||
pgrep -x hyprlock &>/dev/null && return 0
|
||||
|
||||
hyprlock \
|
||||
|| notify.error 'something went wrong; unable to lock' \
|
||||
;
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
#!/usr/bin/env zsh
|
||||
use notify
|
||||
|
||||
DEPENDENCIES+=(qs)
|
||||
#####################################################################
|
||||
|
||||
USAGE__description='
|
||||
Hyprland port of "desktop/xorg/i3/logout"; asks for confirmation
|
||||
(quickshell LogoutPrompt) before exiting hyprland
|
||||
'
|
||||
|
||||
#####################################################################
|
||||
|
||||
MAIN() {
|
||||
local SCWRYPTS_NOTIFICATION_ENGINES=(echo notify.desktop)
|
||||
|
||||
qs ipc call logout show \
|
||||
|| notify.error 'unable to show logout prompt (is quickshell running?)' \
|
||||
;
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
#!/usr/bin/env zsh
|
||||
use notify
|
||||
|
||||
DEPENDENCIES+=(flameshot hyprctl jq)
|
||||
#####################################################################
|
||||
|
||||
USAGE__description='
|
||||
Hyprland equivalent of the i3 flameshot screenshot; freezes the
|
||||
focused monitor in flameshot to select / annotate / copy / save
|
||||
'
|
||||
|
||||
#####################################################################
|
||||
|
||||
MAIN() {
|
||||
local SCWRYPTS_NOTIFICATION_ENGINES=(echo notify.desktop)
|
||||
|
||||
# flameshot screens are numbered from 0 in output order (hyprland ids are not)
|
||||
local screen_number
|
||||
screen_number="$(hyprctl monitors -j | jq -r 'sort_by(.id) | to_entries[] | select(.value.focused) | .key')"
|
||||
[ "${screen_number}" ] \
|
||||
|| { notify.error 'unable to determine focused monitor'; return 1; }
|
||||
|
||||
flameshot screen --edit --number "${screen_number}" \
|
||||
|| notify.error 'unable to take screenshot' \
|
||||
;
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
#!/usr/bin/env zsh
|
||||
use notify
|
||||
use scwrypts/get-realpath
|
||||
|
||||
DEPENDENCIES+=(hyprctl)
|
||||
REQUIRED_ENV+=(DESKTOP__WALLPAPER_PATH)
|
||||
#####################################################################
|
||||
|
||||
USAGE__usage+=' [wallpaper]'
|
||||
|
||||
USAGE__args+='
|
||||
$1 one of:
|
||||
random : any wallpaper (default)
|
||||
theme : the wallpaper named after the active colorscheme (e.g. main.jpg)
|
||||
(optional \$2 : use this theme name instead)
|
||||
<file> : a wallpaper file within DESKTOP__WALLPAPER_PATH
|
||||
'
|
||||
|
||||
USAGE__description='
|
||||
Hyprland port of "desktop/xorg/i3/set-background"; sets the wallpaper
|
||||
on every monitor through hyprpaper
|
||||
'
|
||||
|
||||
#####################################################################
|
||||
|
||||
MAIN() {
|
||||
local SCWRYPTS_NOTIFICATION_ENGINES=(echo notify.desktop)
|
||||
|
||||
# env values are literal (e.g. '$HOME/Pictures/bg'); resolve before use
|
||||
local wallpaper_path="$(scwrypts.get-realpath "${DESKTOP__WALLPAPER_PATH}")"
|
||||
|
||||
[[ -d "${wallpaper_path}" ]] \
|
||||
|| echo.error "no such directory for DESKTOP__WALLPAPER_PATH='${DESKTOP__WALLPAPER_PATH}'" \
|
||||
|| return 1
|
||||
|
||||
local selection="${1:-random}"
|
||||
local wallpaper
|
||||
|
||||
case "${selection}" in
|
||||
( random )
|
||||
wallpaper="$(find "${wallpaper_path}" -type f | shuf -n1)"
|
||||
;;
|
||||
( theme )
|
||||
# optional $2 : theme name (default: the active theme)
|
||||
local theme_name="${2:-$(cat -- "${DOTWRYN}/config/colorschemes/active/name.txt" 2>/dev/null)}"
|
||||
wallpaper="$(find "${wallpaper_path}" -type f -name "${theme_name}.*" | head -n1)"
|
||||
[[ "${wallpaper}" ]] \
|
||||
|| echo.error "no wallpaper for theme '${theme_name}' in wallpaper path" \
|
||||
|| return 2
|
||||
;;
|
||||
( * )
|
||||
wallpaper="${wallpaper_path}/${selection}"
|
||||
[[ -f "${wallpaper}" ]] \
|
||||
|| echo.error "no such wallpaper '${selection}' in wallpaper path" \
|
||||
|| return 2
|
||||
;;
|
||||
esac
|
||||
|
||||
[[ "${wallpaper}" ]] \
|
||||
|| echo.error "no wallpapers found in '${wallpaper_path}'" \
|
||||
|| return 3
|
||||
|
||||
pgrep -x hyprpaper &>/dev/null || {
|
||||
hyprctl dispatch 'hl.dsp.exec_cmd("hyprpaper")' >/dev/null
|
||||
sleep 1
|
||||
}
|
||||
|
||||
# empty monitor : fallback for any monitor without a specific wallpaper
|
||||
hyprctl hyprpaper wallpaper ", ${wallpaper}, cover" >/dev/null \
|
||||
|| notify.error "unable to set wallpaper '${wallpaper}'" \
|
||||
;
|
||||
}
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
#!/usr/bin/env zsh
|
||||
DEPENDENCIES+=(gsettings)
|
||||
#####################################################################
|
||||
|
||||
USAGE__description='
|
||||
On X11, GTK reads its theme from ~/.config/gtk-3.0/settings.ini (written by
|
||||
lxappearance). Wayland GTK apps read gsettings instead, so copy the values
|
||||
across; settings.ini stays the single source of truth for both sessions.
|
||||
'
|
||||
|
||||
#####################################################################
|
||||
|
||||
MAIN() {
|
||||
local settings_file="${XDG_CONFIG_HOME:-${HOME}/.config}/gtk-3.0/settings.ini"
|
||||
|
||||
[[ -f "${settings_file}" ]] \
|
||||
|| echo.error "no gtk settings found at '${settings_file}'" \
|
||||
|| return 1
|
||||
|
||||
local ini_key gsettings_key value
|
||||
for ini_key gsettings_key in \
|
||||
gtk-theme-name gtk-theme \
|
||||
gtk-icon-theme-name icon-theme \
|
||||
gtk-font-name font-name \
|
||||
gtk-cursor-theme-name cursor-theme \
|
||||
;
|
||||
do
|
||||
value="$(sed -n "s/^${ini_key}=//p" "${settings_file}" | tail -n1)"
|
||||
[[ "${value}" ]] || continue
|
||||
|
||||
gsettings set org.gnome.desktop.interface "${gsettings_key}" "${value}" \
|
||||
&& echo.status "${gsettings_key} : ${value}" \
|
||||
|| echo.error "unable to set ${gsettings_key}" \
|
||||
;
|
||||
done
|
||||
|
||||
# libadwaita / portal-aware apps (electron, gtk4) follow color-scheme rather than the theme name
|
||||
local theme="$(gsettings get org.gnome.desktop.interface gtk-theme)"
|
||||
case "${theme:l}" in
|
||||
( *dark* ) gsettings set org.gnome.desktop.interface color-scheme prefer-dark ;;
|
||||
( * ) gsettings set org.gnome.desktop.interface color-scheme default ;;
|
||||
esac
|
||||
|
||||
[[ "${ERRORS}" -eq 0 ]]
|
||||
}
|
||||
@@ -28,21 +28,14 @@ ${scwryptsmodule}.parse() {
|
||||
[[ ${POSITIONAL_ARGS} -eq 0 ]] || return 0
|
||||
|
||||
((POSITIONAL_ARGS+=1))
|
||||
case $1 in
|
||||
( backlight ) SFX_FILE="${DESKTOP__SFX_PATH}/yaru-audio-volume-change.oga" ;;
|
||||
( gamedock ) SFX_FILE="${DESKTOP__SFX_PATH}/gamedock.oga" ;;
|
||||
( homedock ) SFX_FILE="${DESKTOP__SFX_PATH}/homedock.oga" ;;
|
||||
( login ) SFX_FILE="${DESKTOP__SFX_PATH}/yaru-desktop-login.oga" ;;
|
||||
( logout ) SFX_FILE="${DESKTOP__SFX_PATH}/smooth-desktop-login.oga" ;;
|
||||
( mute ) SFX_FILE="${DESKTOP__SFX_PATH}/smooth-dialog-warning.oga" ;;
|
||||
( notify ) SFX_FILE="${DESKTOP__SFX_PATH}/yaru-complete.oga" ;;
|
||||
( undock ) SFX_FILE="${DESKTOP__SFX_PATH}/yaru-desktop-login.oga" ;;
|
||||
( volume ) SFX_FILE="${DESKTOP__SFX_PATH}/yaru-message.oga" ;;
|
||||
|
||||
( * )
|
||||
SFX_FILE="$1"
|
||||
;;
|
||||
esac
|
||||
# mapped names live in $DOTWRYN/config/sfx.map (shared with the hyprland quickshell)
|
||||
local mapped_file="$(awk -v name="${1}" '!/^#/ && $1 == name { print $2; exit }' "${DOTWRYN}/config/sfx.map" 2>/dev/null)"
|
||||
|
||||
[[ "${mapped_file}" ]] \
|
||||
&& SFX_FILE="${DESKTOP__SFX_PATH}/${mapped_file}" \
|
||||
|| SFX_FILE="${1}" \
|
||||
;
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ set -g default-terminal "tmux-256color"
|
||||
set -g mouse off
|
||||
set -sg escape-time 0
|
||||
set-option -g default-shell /bin/zsh
|
||||
set-option -ga update-environment HYPRLAND_INSTANCE_SIGNATURE
|
||||
set-option -gw xterm-keys on
|
||||
set-window-option -g mode-keys vi
|
||||
set-window-option -g status-keys vi
|
||||
|
||||
Reference in New Issue
Block a user