Last active
March 12, 2025 11:42
-
-
Save tyjak/f51b33d10d4e10edc89dde70f7597d6e to your computer and use it in GitHub Desktop.
window
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/sh | |
#set -e | |
#set -u | |
#set -o pipefail | |
export LC_ALL=C | |
POPUP_DEFAULT_WIDTH=800 | |
POPUP_DEFAULT_HEIGHT=600 | |
# TODO refacto | |
# TODO try to simplify with delete class option and use only title, see howto do for default i3 class or in i3 keep only class and delete title in popup window i.e. vimwiki | |
# TODO add notification option ? | |
# FIXME -f option has high CPU usage... | |
# TODO get the user env => try to fix in i3pystatus to path the data | |
POPUP_TOP_POSITION=23 | |
if [ -n "$HIDPI_SCALE" ] | |
then | |
POPUP_TOP_POSITION=$(printf "%.0f" $(echo "$POPUP_TOP_POSITION*$HIDPI_SCALE" | bc)) | |
fi | |
# popup | |
# wrapper to create popup window in i3w | |
# dependancies: i3w, bc | |
# to set default predefined size, add this in your i3 config file for default window parameters : | |
# set $wfM_height 600 | |
# set $wfM_width 1000 | |
# for_window [class="_popup-notitle-medium-sticky"] border 1pixel, floating enable, resize set $wfM_width $wfL_height, move position center, sticky enable | |
# for_window [class="_popup-notitle-medium"] border 1pixel, floating enable, resize set $wfM_width $wfL_height, move position center | |
# for_window [class="_popup-notitle-sticky"] border 1pixel, floating enable, move position center, sticky enable | |
# for_window [class="_popup-notitle"] border 1pixel, floating enable, move position center | |
get_width () | |
{ | |
if [ -z "$width"] && [ -n "$windowsize" ] | |
then | |
width=${windowsize:1} | |
width=${width/x*/} | |
fi | |
echo ${width:-$POPUP_DEFAULT_WIDTH} | |
} | |
get_height () | |
{ | |
if [ -z "$height"] && [ -n "$windowsize" ] | |
then | |
height=${windowsize/*x/} | |
fi | |
echo ${height:-$POPUP_DEFAULT_HEIGHT} | |
} | |
# compute i3 resize | |
get_size () { | |
case "$windowsize" in | |
-small|-medium|-large) size="" ;; | |
*) size=", resize set ${width}px ${height}px" ;; | |
esac | |
echo $size | |
} | |
# compute i3 position | |
get_position () { | |
screen_size=$(xrandr --current | grep " connected" | cut -d" " -f4 | rev | cut -c 5- | rev) | |
screen_width=${screen_size/x*/} | |
screen_height=${screen_size/*x/} | |
pos=(${position//,/ }) # center, or [right|left],[top|bottom], or [0-9]+x[0-9]+ | |
# TODO add env var for ypos (i3bar height) or process with font size get from i3 conf | |
xpos=0 | |
ypos=$POPUP_TOP_POSITION | |
# TODO default width and height by env var ? or get from i3 var conf ? | |
# TODO add condition if borderless or not and add 2 pixel only if a border is defined | |
move_x="center" | |
for p in "${pos[@]}" | |
do | |
case "$p" in | |
right) move_x=$(printf "%.0f px " $(echo "${screen_width}-${width:-802}" | bc));; # +2px because default popup with border 1px | |
left) move_x="$xpos px ";; | |
top) move_y="$ypos px";; | |
bottom) move_y=$(printf "%.0f px" $(echo "${screen_height}-${height:-602}" | bc));; # +2px because default popup with border 1px | |
center) move=center;; | |
[0-9]*x[0-9]*) position_raw=$p;; | |
esac | |
done | |
if [ -n "$move" ] | |
then | |
echo ", move position $move " | |
elif [ -n "$position_raw" ] | |
then | |
echo ", move position ${position_raw/*x/} px ${position_raw/x*/} px " | |
else | |
echo ", move position ${move_x}${move_y} " | |
fi | |
} | |
debug () { | |
if [ -n "${debug}" ] | |
then | |
echo "class: $class" | |
echo "bin: $bin" | |
if [ -n "$position" ] | |
then | |
screen_size=$(xrandr --current | grep " connected" | cut -d" " -f4 | rev | cut -c 5- | rev) | |
screen_width=${screen_size/*x/} | |
screen_height=${screen_size/x*/} | |
pos=(${position//,/ }) | |
echo "width: $(get_width) / height: $(get_height)" | |
echo "screen_size: ${screen_size}" | |
echo "screen_width: ${screen_width} / screen_height: ${screen_height}" | |
echo "move_x: ${move_x} / move_y: ${move_y}" | |
fi | |
fi | |
} | |
usage() { | |
printf >&2 "Usage: $0 [-t (window title)] [-c (window class)] [-s medium] [-p center|[0-9]+x[0-9]+|(left|right)|(top|bottom)] [-S] [-f] [-o (shell option)] (-e) command | |
-t title | |
-c class | |
-s small|medium|large|HxW | |
-p [center|[0-9]+x[0-9]+|[left|right],[top|bottom]] | |
-S : sticky | |
-f : keep cmd in foreground | |
-o : shell option | |
-h hide | |
-e : command (-e optional and deprecated) | |
-d : debug mode" | |
} | |
while getopts "t:c:s:p:H:W:Sfo:e:hd" o | |
do case "$o" in | |
t) options="--title $OPTARG" | |
title=${OPTARG};; | |
c) class="${OPTARG}";; | |
s) windowsize="-${OPTARG}";; | |
p) position="${OPTARG}";; | |
H) height=${OPTARG};; #deprecated | |
W) width=${OPTARG};; #deprecated | |
S) windowsticky="-sticky";; | |
f) foreground=' --hold';; | |
o) shell_option=" -o ${OPTARG}";; | |
e) bin=${OPTARG};; | |
h) hide=1;; | |
d) debug=1;; | |
*) | |
usage | |
exit 1;; | |
esac | |
done | |
shift "$(($OPTIND -1))" | |
if [ -z "$*" ] && [ -z "${bin}" ] | |
then | |
usage | |
exit 1; | |
else | |
bin=${*:-${bin}} | |
fi | |
bin_cleaned=${bin%% *} | |
title=${title:-${bin_cleaned}} | |
is_running=$( ps -eo cmd | grep -c "^${TERMINAL} --title ${title:-${bin_cleaned}}" ) | |
class="${class:-_popup-notitle}${windowsize}${windowsticky}${foreground}" | |
#TODO try to simplify popup run test | |
#is_running=$(pgrep $bin_cleaned | wc -l) | |
exec_i3="exec \"${TERMINAL} --title ${title:-${bin_cleaned}} --class ${class} ${shell_option} -o cursor.style=Underline -e ${bin}\"" | |
if [ -n "${debug}" ] | |
then | |
echo "bin cleaned: $bin_cleaned" | |
echo "is running: $is_running ($( ps -eo cmd | grep "${TERMINAL} --title ${title}}"))" | |
echo "pgrep $bin_cleaned: $(pgrep $bin_cleaned | wc -l)" | |
echo "title: ${title}" | |
echo "bin: ${bin}${foreground}" | |
echo "i3-msg: i3-msg -t command \"${exec_i3}\"" | |
fi | |
if [ ${is_running} -eq 0 ] | |
then | |
width=$(get_width) | |
height=$(get_height) | |
if [ -n "${HIDPI_SCALE}" ] | |
then | |
[ -n "${debug}" ] && echo "HIDPI scale" ${HIDPI_SCALE} | |
if [ -n "${height}" ] && [ -n "${width}" ] | |
then | |
height=$(printf "%.0f" $(echo "${height}*${HIDPI_SCALE}" | bc)) | |
width=$(printf "%.0f" $(echo "${width}*${HIDPI_SCALE}" | bc)) | |
[ -n "${debug}" ] && echo "SIZE: ${width} ${height}" | |
fi | |
fi | |
geo=$(get_size)$(get_position) | |
[ -n "${debug}" ] && echo "geo: $geo" | |
[ -n "${windowsticky}" ] && sticky=', sticky enable' | |
i3-msg -t command "${exec_i3}" | |
if [ -n "$hide" ] | |
then | |
scratchpad='[title="'${title}'"] border 1pixel, floating enable, move scratchpad, scratchpad show '${geo}${sticky} | |
[ -n "${debug}" ] && echo "scratchpad: $scratchpad" | |
#while ! i3-msg -t get_tree | grep -qs "\"class\":\"${class#*,}\"" | |
while ! i3-msg -t get_tree | grep -qs "\"title\":\"${title}\"" | |
do | |
[ -n "${debug}" ] && echo "waiting.." | |
done | |
i3-msg -t command "$scratchpad" | |
elif [ -n "${geo}" ] | |
then | |
while ! i3-msg -t get_tree | grep -qs "\"title\":\"${title}\"" | |
do | |
[ -n "${debug}" ] && echo "${exec_i3}" | |
[ -n "${debug}" ] && echo "${title}" | |
[ -n "${debug}" ] && echo "waiting.." | |
done | |
i3-msg -t command '[title="'${title:-${bin_cleaned}}'" floating] '${geo}${sticky} | |
fi | |
elif [ -n "${hide}" ] | |
then | |
show='[title="'${title:-${bin_cleaned}}'" floating] scratchpad show' | |
[ -n "${debug}" ] && echo "show: $show" | |
i3-msg -t command "$show" | |
else | |
[ -n "${debug}" ] && echo "kill" | |
i3-msg -t command '[title="'${title:-${bin_cleaned}}'" floating] kill' | |
fi | |
# GistID: f51b33d10d4e10edc89dde70f7597d6e |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment