Haiku scripting

This thread is meant to share useful scripts between users

5 Likes

winpwnr.sh
winpwnr.sh is a one-liner Haikus’ hey front-end with the only intent to domate windows

#! /bin/sh

Usage()
{
echo "usage: ${script_name} -option <value>
	-a	select the application by name
	
	-l	list windows for the selected application
	
	-s	select application's window by ID number or title

	-d	avoid to overlap the Deskbar

	-t	change the title of the selected window 
	
	-f	force fullscreen for the selected window, no value is needed
	
	-w	show the selected window on {x} workspace(s),
			you can set multiple values separated by any character, like
			\"1,2,4,5\" or \"5.6.1\", use \"all\" to show it in every workspace
			
	-p	move the selected window by x,y pixels (relative)
			
	-P	move the selected window to x,y (absolute) position
			
	-L	change the LOOK of the selected window:
			- b OR bordered
			- n OR no-border
			- t OR titled
			- d OR document
			- m OR modal
			- f OR floating
			
	-F	change the FEEL of the selected window:
			- n OR normal
			- ms OR modal-subset
			- mp OR modal-app
			- ml OR modal-all
			- fs OR floating-subset
			- fp OR floating-app
			- fl OR floating-all
			
	-G	change the FLAGS of the selected window, multiple valuese are accepted separated by commas
			- nm OR not-movable
			- nr OR not-resizable
			- nh OR not-h-resizable
			- nv OR not-v-resizable
			- fs OR accept-first-click
			- nc OR not-closable
			- nz OR not-zoomable
			- af OR avoid-front
			- nw OR no-workspace-activation
			- as OR avoid-focus
			- nb OR not-minimizable
			- na OR not_anchored
			- sp OR same-position
			- ce OR close-on-escape
			
	-M	minimize the selected window (1, t, true, on, y, yes / 0, f, false, off, n, no / toggle)
	
	-A	active the selected window (1, t, true, on, y, yes / 0, f, false, off, n, no / toggle)
	
	-m	move the selected window against the edges and corners of the screen:
		
		7	8	9		ul	u	ur		up-left		up		up-right
		
		4	5	6	OR	l	c	r	OR	left		center		right
		
		1	2	3		dl	d	dr		down-left	down		down-right
			
	-H	as the -m option but the selected window will be moved to the edges resized to half the screen size, a quarter of the screen size to the corners
	
	-r	resize the frame of the selected window to width,height, centered with respect to the original window and avoiding going out of bounds"
	>&2
exit
}

CheckArgs()
{
if [ $(echo -n "$1" | wc -c) -eq 2 ] && [ $(echo -n "$1" | awk '/-/{print}') ]
then
	shift $((OPTIND-1))
	return 1
fi	
}

SetWorkspace ()
{
[ "$1" != "all" ] && hey -o "${app_name}" set Workspaces of Window "${win_ID}" to `echo -n $1 | awk '{for(i=1;i<=NF;i++) print ($i-1)}' FS="[^0-9]" | sort -u | awk '{val+=2^($0)} END {print val}'` || hey -o "${app_name}" set Workspaces of Window "${win_ID}" to -1
}

EnlistWindows()
{
for (( i=0;i<=`echo $(hey "${app_name}" Count of Window | awk '/result/{print $4}') - 1 | bc`;i++ )); do echo -n "$i) ";hey "${app_name}" get Title of Window "$i" | awk '/result/{print $4}' FS="\""; done
}

ChangeTitle ()
{
hey -o "${app_name}" set Title of Window "${win_ID}" TO "$1"
}

ResizeFrame()
{
PeekDesktop
hey -o "${app_name}" set Frame of Window "${win_ID}" TO BRect[\
$((echo -n "$1,"; hey "${app_name}" get Frame of Window "${win_ID}" | awk '/result/{sub(/^.*\(/,"");sub(/\)/,"");gsub(" ","");printf "%s,",$0}'; echo -n ${dt_frame}) | awk '{\
if ($1<$9) {x_pos=int($3+(($5-$3-$1)/2)); wx_pos=x_pos+$1; if (x_pos<0) {wx_pos-=x_pos;x_pos=0;};if (wx_pos>$9){delta=(wx_pos-$9);wx_pos-=delta;x_pos-=delta;}}\
else {x_pos=0;wx_pos=$9;};\
if ($2<$10) {y_pos=int($4+(($6-$4-$2)/2)); wy_pos=y_pos+$2; if (y_pos<0) {wy_pos-=y_pos;y_pos=0;};if (wy_pos>$10){delta=(wy_pos-$10);wy_pos-=delta;y_pos-=delta;}}\
else {y_pos=0;wy_pos=$10;};\
print x_pos,y_pos,wx_pos,wy_pos}' FS="," OFS=",")]
}
PlaceOnEdges()
{
PeekDesktop
case $1 in
	7|ul|up-left)
		hey -o "${app_name}" set Frame of Window "${win_ID}" TO BRect[$((hey "${app_name}" get Frame of Window "${win_ID}" | awk '/result/{sub(/^.*\(/,"");sub(/\)/,"");gsub(" ","");printf "%s,",$0}' ; echo -n ${dt_frame}) | awk '{print $5,$6,$5+($3-$1),$6+($4-$2)}' FS="," OFS=",")]
		;;		
	8|u|up)
		hey -o "${app_name}" set Frame of Window "${win_ID}" TO BRect[$((hey "${app_name}" get Frame of Window "${win_ID}" | awk '/result/{sub(/^.*\(/,"");sub(/\)/,"");gsub(" ","");printf "%s,",$0}' ; echo -n ${dt_frame}) | awk '{print int(($7-($3-$1))/2),$6,int(($7+($3-$1))/2),$6+($4-$2)}' FS="," OFS=",")]
		;;		
	9|ur|up-right)
		hey -o "${app_name}" set Frame of Window "${win_ID}" TO BRect[$((hey "${app_name}" get Frame of Window "${win_ID}" | awk '/result/{sub(/^.*\(/,"");sub(/\)/,"");gsub(" ","");printf "%s,",$0}' ; echo -n ${dt_frame}) | awk '{print ($7-($3-$1)),$6,$7,$6+($4-$2)}' FS="," OFS=",")]
		;;		
	4|l|left)
		hey -o "${app_name}" set Frame of Window "${win_ID}" TO BRect[$((hey "${app_name}" get Frame of Window "${win_ID}" | awk '/result/{sub(/^.*\(/,"");sub(/\)/,"");gsub(" ","");printf "%s,",$0}' ; echo -n ${dt_frame}) | awk '{print $5,int(($8-($4-$2))/2),$5+($3-$1),int(($8+($4-$2))/2)}' FS="," OFS=",")]
		;;
	5|c|center)
		hey -o "${app_name}" set Frame of Window "${win_ID}" TO BRect[$((hey "${app_name}" get Frame of Window "${win_ID}" | awk '/result/{sub(/^.*\(/,"");sub(/\)/,"");gsub(" ","");printf "%s,",$0}' ; echo -n ${dt_frame}) | awk '{print int(($7-($3-$1))/2),int(($8-($4-$2))/2),int(($7+($3-$1))/2),int(($8+($4-$2))/2)}' FS="," OFS=",")]
		;;		
	6|r|right)
		hey -o "${app_name}" set Frame of Window "${win_ID}" TO BRect[$((hey "${app_name}" get Frame of Window "${win_ID}" | awk '/result/{sub(/^.*\(/,"");sub(/\)/,"");gsub(" ","");printf "%s,",$0}' ; echo -n ${dt_frame}) | awk '{print ($7-($3-$1)),int(($8-($4-$2))/2),$7,int(($8+($4-$2))/2)}' FS="," OFS=",")]
		;;	
	1|dl|down-left)
		hey -o "${app_name}" set Frame of Window "${win_ID}" TO BRect[$((hey "${app_name}" get Frame of Window "${win_ID}" | awk '/result/{sub(/^.*\(/,"");sub(/\)/,"");gsub(" ","");printf "%s,",$0}' ; echo -n ${dt_frame}) | awk '{print $5,($8-($4-$2)),$5+($3-$1),$8}' FS="," OFS=",")]
		;;
	2|d|down)
		hey -o "${app_name}" set Frame of Window "${win_ID}" TO BRect[$((hey "${app_name}" get Frame of Window "${win_ID}" | awk '/result/{sub(/^.*\(/,"");sub(/\)/,"");gsub(" ","");printf "%s,",$0}' ; echo -n ${dt_frame}) | awk '{print ($7-($3-$1))/2,($8-($4-$2)),int(($7+($3-$1))/2),$8}' FS="," OFS=",")]
		;;
	3|dr|down-right) # lower right corner. half screen size
		hey -o "${app_name}" set Frame of Window "${win_ID}" TO BRect[$((hey "${app_name}" get Frame of Window "${win_ID}" | awk '/result/{sub(/^.*\(/,"");sub(/\)/,"");gsub(" ","");printf "%s,",$0}' ; echo -n ${dt_frame}) | awk '{print ($7-($3-$1)),($8-($4-$2)),$7,$8}' FS="," OFS=",")]
		;;
	*)
		Usage
	;;
esac
}
SplitOnEdges()
{
PeekDesktop
case $1 in
	7|ul|up-left) # upper left corner, 1/4 screen size
	hey -o "${app_name}" set Frame of Window "${win_ID}" TO BRect[$(echo ${dt_frame} | awk '{print $1,$2,int($3/2),int($4/2)}' FS="," OFS=",")]
		;;		
	8|u|up) # upper half screen height
	hey -o "${app_name}" set Frame of Window "${win_ID}" TO BRect[$(echo ${dt_frame} | awk '{print $1,$2,$3,int($4/2)}' FS="," OFS=",")]
		;;		
	9|ur|up-right) # upper right corner, 1/4 screen size
	hey -o "${app_name}" set Frame of Window "${win_ID}" TO BRect[$(echo ${dt_frame} | awk '{print int($3/2),$2,$3,int($4/2)}' FS="," OFS=",")]
		;;		
	4|l|left) # left half screen width
	hey -o "${app_name}" set Frame of Window "${win_ID}" TO BRect[$(echo ${dt_frame} | awk '{print $1,$2,int($3/2),$4}' FS="," OFS=",")]
		;;
	5|c|center) # middle screen, half screen size	
	hey -o "${app_name}" set Frame of Window "${win_ID}" TO BRect[$(echo ${dt_frame} | awk '{print int($3/4),int($4/4),int($3*3/4),int($4*3/4)}' FS="," OFS=",")]
		;;		
	6|r|right) # right half screen width
	hey -o "${app_name}" set Frame of Window "${win_ID}" TO BRect[$(echo ${dt_frame} | awk '{print int($3/2),$2,$3,$4}' FS="," OFS=",")]
		;;	
	1|dl|down-left) # lower left corner. half screen size
	hey -o "${app_name}" set Frame of Window "${win_ID}" TO BRect[$(echo ${dt_frame} | awk '{print $1,int($4/2),int($3/2),$4}' FS="," OFS=",")]
		;;
	2|d|down) # lower half screen height
	hey -o "${app_name}" set Frame of Window "${win_ID}" TO BRect[$(echo ${dt_frame} | awk '{print $1,int($4/2),$3,$4}' FS="," OFS=",")]
		;;
	3|dr|down-right) # lower right corner. half screen size
	hey -o "${app_name}" set Frame of Window "${win_ID}" TO BRect[$(echo ${dt_frame} | awk '{print int($3/2),int($4/2),$3,$4}' FS="," OFS=",")]
		;;
	*)
		Usage
	;;
esac
}
FullScreen()
{
PeekDesktop
hey -o "${app_name}" set Frame of Window "${win_ID}" to BRect[${dt_frame}]
}
ChangeLook()
{
case $1 in
	b|bordered)
		hey -o "${app_name}" set Look of Window "${win_ID}" to 20
		;;
	n|no-border)
		hey -o "${app_name}" set Look of Window "${win_ID}" to 19
		;;
	t|titled)
		hey -o "${app_name}" set Look of Window "${win_ID}" to 1
		;;
	d|document)
		hey -o "${app_name}" set Look of Window "${win_ID}" to 11
		;;
	m|modal)
		hey -o "${app_name}" set Look of Window "${win_ID}" to 3
		;;
	f|floating)
		hey -o "${app_name}" set Look of Window "${win_ID}" to 7
		;;
	*)
		Usage
		;;
esac
}
ChangeFeel()
{
case $1 in
	n|normal)
		hey -o "${app_name}" set Feel of Window "${win_ID}" to 0
		;;
	ms|modal-subset)
		hey -o "${app_name}" set Feel of Window "${win_ID}" to 2
		;;
	mp|modal-app)
		hey -o "${app_name}" set Feel of Window "${win_ID}" to 1
		;;
	ml|modal-all)
		hey -o "${app_name}" set Feel of Window "${win_ID}" to 3
		;;
	fs|floating-subset)
		hey -o "${app_name}" set Feel of Window "${win_ID}" to 5
		;;
	fp|floating-app)
		hey -o "${app_name}" set Feel of Window "${win_ID}" to 4
		;;
	fl|floating-all)
		hey -o "${app_name}" set Feel of Window "${win_ID}" to 6
		;;
	*)
		Usage
		;;
esac
}
SumFlags()
{
case $1 in
	nm|not-movable)
		let flags+=1
		;;
	nr|not-resizable)
		let flags+=2
		;;
	nh|not-h-resizable)
		let flags+=4
		;;
	nv|not-v-resizable)
		let flags+=8
		;;
	fs|accept-first-click)
		let flags+=16
		;;
	nc|not-closable)
		let flags+=32
		;;
	nz|not-zoomable)
		let flags+=64
		;;
	af|avoid-front)
		let flags+=128
		;;
	nw|no-workspace-activation)
		let flags+=256
		;;
	as|avoid-focus)
		let flags+=8192
		;;
	nb|not-minimizable)
		let flags+=16384
		;;
	na|not_anchored)
		let flags+=131072
		;;
	sp|same-position)
		let flags+=2097152
		;;
	ce|close-on-escape)
		let flags+=8388608
		;;
	r| reset)
		flags=1572864
		;;
	*)
		Usage
		;;
esac
}
ChangeFlags()
{
flags=1572864
while read line; do
SumFlags ${line}
done <<< $( echo $1 | tr "," "\\n" )
hey -o "${app_name}" set Flags of Window "${win_ID}" to ${flags} 
}
ToggleActive()
{
case $1 in
	1|t|true|on|y|yes)
		hey -o "${app_name}" set Active of Window "${win_ID}" to true
		;;
	0|f|false|off|n|no)
		hey -o "${app_name}" set Active of Window "${win_ID}" to false
		;;
	toggle)
		active=`hey -o "${app_name}" get Active of Window "${win_ID}"`
		[ "${active}" == "true" ] && ToggleActive 0 || ToggleActive 1
		;;
	*)
		Usage
		;;
esac
}
ToggleMinimize()
{
case $1 in
	1|t|true|on|y|yes)
		hey -o "${app_name}" set Minimize of Window "${win_ID}" to true
		;;
	0|f|false|off|n|no)
		hey -o "${app_name}" set Minimize of Window "${win_ID}" to false
		;;
	toggle)
		minimized=`hey -o "${app_name}" get Minimize of Window "${win_ID}"`
		[ "${minimized}" == "true" ] && ToggleMinimize 0 || ToggleMinimize 1
		;;
	*)
		Usage
		;;
esac
}
AbsPositionIt ()
{
hey -o "${app_name}" let Window "${win_ID}" do MoveTo BPoint[$1]
}
RelPositionIt ()
{
hey -o "${app_name}" let Window "${win_ID}" do MoveBy BPoint[$1]
#\$((echo -n "$1,"; hey "${app_name}" get Frame of Window "${win_ID}" | awk '/result/{sub(/^.*\(/,"");sub(/\)/,"");gsub(" ","");printf "%s",$0}') | awk '{print $3+$1,$4+$2}' FS="," OFS=",")]
}
PeekDesktop ()
{
dt_frame=$((hey Tracker get Frame of Window 0 | awk '/result/{sub(/^.*\(/,"");sub(/\)/,"");gsub(" ","");printf "%s,",$0}' ; echo -n ${db_frame})  | awk '{\
if (($5!=0) && ($7==$3 )) {print "0","0",$5,$4};\
if (($5==0) && ($7!=$3)) {print $7,"0",$3,$4};\
if (($7-$5)==($3-$1)) {if ($6!=0) {print "0","0",$3, $6}\
else {print "0",$8,$3,$4}}\
}' FS="," OFS=",")
}
PeekDeskbar ()
{
db_frame=$(hey Deskbar get Frame of Window 0 | awk '/result/{sub(/^.*\(/,"");sub(/\)/,"");gsub(" ","");printf "%s",$0}')
}
###############
# main script #
###############
script_name="$(basename ${0})"
db_frame="0,0,0,0"
if [ $# -ne 0 ]
then
	while getopts "a:dhlfs:t:w:L:F:p:P:m:H:r:M:A:G:" script_opt
	do
		case ${script_opt} in
		a)
			app_name="$OPTARG"
			;;
		l)
			[ -n "${app_name}" ] && EnlistWindows
			exit
			;;
		s)
			[ -n "${app_name}" ] && win_ID="$OPTARG" || Usage
			;;
		
		P)
			if [ -n "${app_name}" ] && [ -n "${win_ID}" ]
				then
					CheckArgs "$OPTARG"
					[ $? -ne 1 ] &&	AbsPositionIt "$OPTARG"
				else
					Usage
			fi
			;;
		p)
			if [ -n "${app_name}" ] && [ -n "${win_ID}" ]
				then
					CheckArgs "$OPTARG"
					[ $? -ne 1 ] &&	RelPositionIt "$OPTARG"
				else
					Usage
			fi
			;;
			
		d)
			if [ -n "${app_name}" ] && [ -n "${win_ID}" ]
				then
					PeekDeskbar
				else
					Usage
			fi
			;;
		m)
			if [ -n "${app_name}" ] && [ -n "${win_ID}" ]
			then
				CheckArgs "$OPTARG"
				[ $? -ne 1 ] &&	PlaceOnEdges "$OPTARG"
			else
				Usage
			fi
			;;	
		H)
			if [ -n "${app_name}" ] && [ -n "${win_ID}" ]
			then
				CheckArgs "$OPTARG"
				[ $? -ne 1 ] &&	SplitOnEdges "$OPTARG"
			else
				Usage
			fi
			;;
		f)
			if [ -n "${app_name}" ] && [ -n "${win_ID}" ]
			then
				FullScreen
			else
				Usage
			fi
			;;
		t)
			if [ -n "${app_name}" ] && [ -n "${win_ID}" ]
			then
				CheckArgs "$OPTARG"
				[ $? -ne 1 ] &&	ChangeTitle "$OPTARG"
			else
				Usage
			fi
			;;
		w)
			if [ -n "${app_name}" ] && [ -n "${win_ID}" ]
			then
				CheckArgs "$OPTARG"
				[ $? -ne 1 ] &&	SetWorkspace "$OPTARG"
			else
				Usage
			fi
			;;
		r)
			if [ -n "${app_name}" ] && [ -n "${win_ID}" ]
			then
				CheckArgs "$OPTARG"
				[ $? -ne 1 ] &&	ResizeFrame "$OPTARG"
			else
				Usage
			fi
			;;
		L)
			if [ -n "${app_name}" ] && [ -n "${win_ID}" ]
			then
				CheckArgs "$OPTARG"
				[ $? -ne 1 ] &&	ChangeLook "$OPTARG"
			else
				Usage
			fi
			;;
		F)
			if [ -n "${app_name}" ] && [ -n "${win_ID}" ]
			then
				CheckArgs "$OPTARG"
				[ $? -ne 1 ] &&	ChangeFeel "$OPTARG"
			else
				Usage
			fi
			;;
		G)
			if [ -n "${app_name}" ] && [ -n "${win_ID}" ]
			then
				CheckArgs "$OPTARG"
				[ $? -ne 1 ] &&	ChangeFlags "$OPTARG"
			else
				Usage
			fi
			;;
		A)
			if [ -n "${app_name}" ] && [ -n "${win_ID}" ]
			then
				CheckArgs "$OPTARG"
				[ $? -ne 1 ] &&	ToggleActive "$OPTARG"
			else
				Usage
			fi
			;;
		M)
			if [ -n "${app_name}" ] && [ -n "${win_ID}" ]
			then
				CheckArgs "$OPTARG"
				[ $? -ne 1 ] &&	ToggleMinimize "$OPTARG"
			else
				Usage
			fi
			;;
		h|*)
			Usage
			;;
		esac
	done
else
	Usage
fi
exit

Pratical example
winpwnr.sh -a Terminal -s 0 -d -H up
move the first opened Terminal window to the upper screen edge occupying half screen vertically, full screen width but avoiding to overlap the Deskbar

winpwnr.sh -a Pe -s Snippets -r 400,400 -m left -w all - G not-closable,not-movable,not-resizable,not-zoomable,not-minimizable -L bordered
Pe’s snippets window is resized to a 400 px squared frame, moved against left screen edge, freeze its position, removing window title tab, shown on all workspaces

I think this can be useful running in a boot script

4 Likes

Another example how I use the script above

Forked Popup/Quake style terminal using the hey command
to use winpwnr.sh, the Terminal will fit the upper half of screen, while not active will be moved upward showing only a thin area, click on that area to make the window active again and bring back the Terminal

#!/bin/sh

### the unique window title prefix for our terminal session
terminalKeyword="QuakeTerm"

### optionally set the location of a custom terminal profile to be used
### it must contain whatever is used as the terminalKeyword at the beginning of the "Window title"
### for example:    "Window title" , "QuakeTerm %i: %t"
# terminalProfile="/boot/home/config/non-packaged/apps/MyCustomTerminal"

### watch and minimize the window even if it was activated by Deskbar/twitcher/....
### otherwise only auto-hide if it's been activated by this script
### comment out the line to disable
continuousWatch=1

### how frequently should we check the status of the window
### lower numbers give faster response and can be decimal numbers like 0.5,1.5,2.2,...
watcherSleepTime=1

move_by=$(hey Tracker get Frame of Window 0 | awk '/result/{sub(/...$/,"");print ($7+1)/2-10}')

### function to find the process ID of our custom terminal session
function findTerminalSession() {
	QTERMPID=-99
	for i in `roster | fgrep /apps/Terminal | awk '{ print $1 }'`;do
		title=`hey -o $i get Title of Window 0 | grep "^${terminalKeyword}"`
		if [ -n "${title}" ];then
			QTERMPID=$i
			break
		fi
	done
}


### initial check to see if we're already running
findTerminalSession

if [ ${QTERMPID} -lt 0 ];then
	### no existing terminal session, start a new one

	if [ -n "${terminalProfile}" ];then
		open "${terminalProfile}"
	else
		/boot/system/apps/Terminal -t "${terminalKeyword}" &
	fi

	### loop a few times to give the terminal process time to start before giving up
	for i in {1..6};do
		findTerminalSession
		if [ ${QTERMPID} -gt 0 ];then
			break;
		elif [ ${i} -eq 6 ];then
			### last time through the loop and we haven't found our terminal
			alert --stop "Error finding custom Terminal process"
			exit 1
		else
			sleep 1
		fi
	done

	### disable the fullscreen button in the tabbar
	hey ${QTERMPID} set Enabled of View 1 of View 1 of Window 0 to false

	### resize and then hide the menubar
	### extract our current BRect(left,top,right,bottom) frame and replace the fourth number with 0.0
	menuFrame=`hey ${QTERMPID} get Frame of View 0 of Window 0 | grep -o 'BRect(.*)$' | sed 's/[0-9]\+.[0-9]\+/0.0/4'`
	hey ${QTERMPID} set Frame of View 0 of Window 0 to "${menuFrame}"
	hey ${QTERMPID} set Hidden of View 0 of Window 0 to true

	### resize the tabview to take up the empty menubar space
	### extract our current BRect(left,top,right,bottom) frame and replace the second number with 0.0
	tabFrame=`hey ${QTERMPID} get Frame of View 1 of Window 0 | grep -o 'BRect(.*)$' | sed 's/[0-9]\+.[0-9]\+/0.0/2'`
	hey ${QTERMPID} set Frame of View 1 of Window 0 to "${tabFrame}"
	
 # shows Terminal on all workspaces, w/o tab only borders, not resizable, movable, minimizable or zoomable, shown in the upper half of the screen not overlapping the Deskbar	
	winpwnr.sh -a Terminal -s ${terminalKeyword} -d -H 8 -w all -G nm,nr,nb,nz -L b
	startWatcher=1
fi


if [ -n "${startWatcher}" ];then
	was_active="true"
	while true;do
		### check to see if our window is inactive but still showing
		active=`hey -o ${QTERMPID} get Active of Window 0`
		if [ "${active}" == "false" ] && [ "${was_active}" == "true" ]
		then
			# when the window is not active it will be moved upward showing a small clickable area of 10x10
			winpwnr.sh -a Terminal -s ${terminalKeyword} -p 0,-${move_by}
			was_active="false"
			[ -z "${continuousWatch}" ] &&	exit
		else
			if [ "${active}" == "true" ] && [ "${was_active}" == "false" ]
				then
					# when the window is active again will be moved downward 
					winpwnr.sh -a Terminal -s ${terminalKeyword} -p 0,${move_by}
					was_active="true"
				fi
			[ -z "${active}" ] && exit
		sleep ${watcherSleepTime}
		fi
	done
fi
1 Like

[Edited to use yt-dlp instead of the discontinued youtube-dl]

This is a script that I’ve been using for a while now to download video clips. It uses yt-dlp for the list of supported_sites and wget for all others.
Make it executable, put it on the Desktop, then just copy the clip URL to the clipboard and double-click the script.

If your network connection is fast enough, give it a few seconds to buffer and watch the clip with MediaPlayer while it downloads. (This is pretty much what Ubertuber does, only this script works much more reliably… :stuck_out_tongue: )

    #!/bin/sh

    # The script takes the contents of the clipboard and downloads it
    # with either yt-dlp or - if not a supported site - wget
    #
    # Usage:	0 a) install yt-dlp from HaikuDepot
    #			0 b) make script executable and put it on the Desktop
    #			1) copy a clip URL
    #			2) double click script to download to Desktop

    supported_sites="youtube youtu.be vimeo"
    destination=~/Desktop
    clip=$(clipboard -p)

    cd $destination

    # Use youtube-dl if the clip comes from a supported site
    for item in $supported_sites ; do
    	if [[ $clip == *"$item"* ]] ; then
    	# get the clip's filename
    		filename=$(yt-dlp --restrict-filenames --no-part \
    			--no-cache-dir --get-filename "$clip")
    	# download clip in best quality
    		yt-dlp --continue --restrict-filenames --no-part \
    			--no-cache-dir "$clip"
    	# add the clip's URL as attribute
    		addattr META:url "$clip" "$filename"
    	# identify file type
    	# 	mimeset -F "$filename"
    		exit
    	fi
    done

    # Use wget for anything else
    filename=$(basename "$clip")
    wget "$clip"
    addattr META:url "$clip" "$filename"
    # mimeset -F "$filename"

The META:url attribute stores the download URL for reference. TIP: To display it in a Tracker window, you can temporarily copy a Bookmark file into the clip’s folder, and activate the URL attribute from the Tracker window’s menu.

I commented out the mimeset lines, because then I recognize the unwatched clips by their generic icon. :slight_smile:

7 Likes

I got a script going yesterday that’ll rip metadata from song files (w ffmpeg) to fill the Audio:* and Media:* attributes.

I like sorting songs by track and albums by year, so there’s also a small cpp file to add the ‘audio/x-ablum’ filetype, which can be used. Assuming you’re using a hierarchy like ./artist/album/song, the script can treat the song’s parent dir like the Album and add Media:Year and Audio:Artist.

5 Likes

I got a script today to do “directory templating” (it’ll copy attributes over from a “template hierarchy,” following certain rules, to a target directory). I’m just using it to make all folders of a certain kind have the exact same window placement/size, help keep organized.

1 Like

Bloated version:

  • added notify support
  • added ++ and – args. changes volume by 3 (db?)
  • added -r to reset to 0, normal volume
  • loud and mute args now can toggle to the previous value

save it, chmod +x, and use it with ShortCuts

#! /bin/bash

local_path="$(dirname $0)"
[ "${local_path}" == "." ] && local_path="$(pwd)"
app_path="${local_path}/`basename ${0}`"

restore_volume=

NotifyVolume()
{
	notify --group "Volume" --title "Setting Volume to:" \
				--messageID "Volume" --timeout 10 --type progress --progress "`echo "scale=2;($1-($2))/($3-($2))" | bc`" "`echo "100*($1-($2))/(-($2))" | bc`%"
}

RestoreVolume()
{
	if [ -z ${restore_volume} ] ; then
		NotifyVolume `setvolume ${1} | awk '{gsub(/[:=(),a-zA-Z]/,"");print $1,$2,$3}'`
		sed -i "s/^restore_volume=/&${curr_vol}/" "${app_path}"

	else
		if  ( ( [ ${curr_vol} -eq ${min_vol} ] && [ ${1} -eq ${max_vol} ] ) || ( [ ${curr_vol} -eq ${max_vol} ] && [ ${1} -eq ${min_vol} ] ) ) ; then
			setvolume ${1}
		else
			NotifyVolume `setvolume ${restore_volume} | awk '{gsub(/[:=(),a-zA-Z]/,"");print $1,$2,$3}'`
			sed -i "s/^restore_volume=.*/restore_volume=/" "${app_path}"
		fi
	fi
}

CheckVolume()
{
	if ( [ ! -z ${restore_volume} ] && ( [ ${curr_vol} -eq ${min_vol} ] || [ ${curr_vol} -eq ${min_vol} ] ) ) ; then
		curr_vol=${restore_volume}
		sed -i "s/^restore_volume=.*/restore_volume=/" "${app_path}"
	fi
}

Usage()
{
	case ${1} in
		1)
			echo "error : missing or wrong argument"
			;;
		2)
			echo "error : missing value"
			;;
	esac
	echo "usage: `basename ${0}` [-rlmh] [++][--] [-id value]
++ : increase volume by 3
-- : decrease volume by 3
-i : increase volume by {value}
-d : decrease volume by {value}
-r : reset to 0
-l : set it loud / revert
-m : toggle to mute/unmute
-h : print this help"
}

read curr_vol min_vol max_vol <<< `setvolume | awk '{gsub(/[:=(),a-zA-Z]/,"");print $1,$2,$3}'`

case ${1} in
	++)
		CheckVolume
		[ ${curr_vol} -lt ${max_vol} ] && ( let curr_vol+=3 ; NotifyVolume `setvolume ${curr_vol} | awk '{gsub(/[:=(),a-zA-Z]/,"");print $1,$2,$3}'` )			
		;;
	--)
		CheckVolume
		[ ${curr_vol} -gt ${min_vol} ] && ( let curr_vol-=3 ; NotifyVolume `setvolume ${curr_vol} | awk '{gsub(/[:=(),a-zA-Z]/,"");print $1,$2,$3}'` )
		;;
	-i)
		if [ -z ${2} ] ; then
			Usage 2
			exit 1
		fi
		CheckVolume
		[ ${curr_vol} -lt ${max_vol} ] && ( let curr_vol+=${2} ; NotifyVolume `setvolume ${curr_vol} | awk '{gsub(/[:=(),a-zA-Z]/,"");print $1,$2,$3}'` )
		;;
	-d)
		if [ -z ${2} ] ; then
			Usage 2
			exit 1
		fi
		CheckVolume
		[ ${curr_vol} -gt ${min_vol} ] && ( let curr_vol-=${2} ; NotifyVolume `setvolume ${curr_vol} | awk '{gsub(/[:=(),a-zA-Z]/,"");print $1,$2,$3}'` )
		;;
	-r)
		CheckVolume
		NotifyVolume `setvolume 0 | awk '{gsub(/[:=(),a-zA-Z]/,"");print $1,$2,$3}'`
		;;
	-l)
		RestoreVolume ${max_vol}
		;;
	-m)
		RestoreVolume ${min_vol}
		;;
	-h)
		Usage
		;;
	*)
		Usage 1
		exit 1
		;;
esac
5 Likes

The script should check sed and awk are installed.

1 Like

Any hint how to:

  • get workspace geometry (rows * columns)?

  • set an image as a wallpaper to a specific workspace?

Both from CLI

To better identify my workspaces I set up a script that split a big image into %workspaces% parts, it works using image magick but I have to choose manually the geometry cited above and set the resulting files as wallpaper manually, so I was wondering if it can be fully automated.

Tnx in advance

 message ~/config/settings/system/app_server/workspaces | egrep -w "columns | rows"
        columns = int32(0x2 or 2)
        rows = int32(0x2 or 2)
2 Likes

That’ll be quite difficult. The paths to background images are saved in the be:bgndimginfo attribute of the ~/Desktop folder. I wouldn’t know how to set those…
You’ll need someone to quickly implement ticket #8629. :slight_smile:

1 Like

:roll_eyes: Never tried that but since it works with colours… drop the image on workspaces app?
I know, I have crazy ideas sometimes… :crazy_face:

2 Likes

Thanks, i didn’t know those data where stored there

Ok, so I can read it but I can’t write that (at least +if there is +no bmessage writer).
So if I won’t change my workspaces geometry, i can split the big image into parts assigning the same names, kill the tracker and when it respawns i can have my brand wallpapers because there is no checksum about the files used as backgrounds.
Rude but it could work

1 Like

Another fun thing is to get the background color of the x workspace, tint the relative wallpaper with that color, in order to have a color coded environment.

And this can be done because the colors are stored in the workspace settings file

1 Like

Ok, it’s almost done, it fits my original design to split 4K images into wallpapers with 1920x1080 res on 2x2 workspaces, with larger images or lower resolution screen it needs a resize+crop routine, it will be done someday;)

You can choose to color the background with the color assigned to the related workspace or have it assign a color automatically, images are converted to grayscale then tinted, this is the way I like it, but you can remove it easily from this amount of pseudo code and tint over the original artwork.

Save this snippet and make it executable, run with or without argument (only image needed)

Assign the resulting images as background for each workspace, currently this cannot be done by script.

dependencies: imagemagick7 only, the script checks by itself and asks if you want to install, the rest are system tools

#! /bin/bash

# your prefs

# be verbose

verbose=0

# found screen and workspace geometry by itself

auto_discovery=1

# tint using workspace color

get_color=1

# or use different hue from the colour spectre

cycle_color=0

# choose where and what to save

output_dir=/boot/home/

default_name=wallpaper

# the cycle-sucker starts here

CheckNumber ()

{

# test if given value is a number

test ${1} -ne -${1} 2>/dev/null

if [ ${?} -gt 0 ] ; then

        echo "Error: not valid"

        exit

fi

}

# check if imagemagick7 is installed

if [ ! `which magick 2>/dev/null` ] ; then

        case `alert --stop "ImageMagick is not installed.
        Do you want to install it now?" "Yes" "No"` in

                "Yes")

                        pkgman install imagemagick7

                ;;

                *)

                        echo "Bye"

                        exit

                ;;

        esac

fi

clear

# screen geometry

if [ -n ${screen_width} ] && [ -n ${screen_height} ] ; then

        if [ ${auto_discovery} -eq 1 ] ; then

                answer=$(hey Tracker get Frame of Window 0 | awk -F'[^0-9]' '/result/ {printf "%s,
%s",$(NF-5)+1,$(NF-2)+1}')

        else

                echo "Type screen size (width*height):"

                read answer

        fi

        read -r screen_width screen_height <<< `echo ${answer} | awk -F'[^0-9]' '{print $1,
$2}'`

        CheckNumber ${screen_width}

        CheckNumber ${screen_height}

fi

# workspace geometry

if [ -n ${rows} ] && [ -n ${columns} ] ; then

        if [ ${auto_discovery} -eq 1 ] ; then

                answer=`message /boot/home/config/settings/system/app_server/workspaces | awk -
F'[^0-9]' '/columns/,/rows/ {printf "%s,",$(NF-1)}'`

        else

                echo "Type workspace geometry (columns*rows):"

                read answer

        fi

        read -r columns rows <<< `echo ${answer} | awk -F'[^0-9]' '{print $1,$2}'`

        CheckNumber ${columns}

        CheckNumber ${rows}

fi

# choose image

if [ -z ${media_file} ] ; then

        if [ ! -z ${1} ] && [ -f ${1} ] ; then

                media_file="${1}"

        else

                echo "Type media file path"

                read media_file

        fi

        read -r media_width media_height <<< `magick identify -format "%[fx:w]*%[fx:h]"
"${media_file}"  | awk -F* '{print $1,$2}'`

        CheckNumber ${media_width}

        CheckNumber ${media_height}

        if [ ${media_width} -lt ${screen_width} ] && [ ${media_height} -lt ${screen_height} ]
; then

                echo "Sorry, the image must be larger or taller than screen"

                exit 1

        fi

fi

# split and tint image

workspace=0

let workspaces=(${rows}*${columns})-1

let rows-=1

let columns-=1

for ((row_index=0;row_index<=rows;row_index++)) ; do

        for ((column_index=0;column_index<=columns;column_index++)) ; do

                [ ${columns} -gt 0 ] && let x_offset=(${media_width}-
${screen_width})/${columns}*${column_index}

                [ ${rows} -gt 0 ] && let y_offset=(${media_height}-
${screen_height})/${rows}*${row_index}

                [[ ${cycle_color} -eq 1 ]] && let tint=${workspace}*255/${workspaces}

                [[  ${get_color} -eq 1 ]] && tint=`message
/boot/home/config/settings/system/app_server/workspaces | awk -F'[x )]'
'/\['"${workspace}"'\]/,/color/ {print $(NF-3)}' 2>/dev/null | awk '/^ff/ {for(i=3;i>=1;
i--) printf substr($0,i*2+1,2)}'`

                [ ${verbose} -eq 1 ] &&  echo "Frame of ${screen_width}x${screen_height} from
(${frame_width}x${frame_height})${x_offset}x${y_offset} of
${resize_width}x${resize_height}, tint: ${tint}"

                let workspace+=1

                echo "Processing : ${workspace}"

                if [ ! -z "${tint}" ] ; then


                [[ ${get_color} -eq 0 ]] && [[ ${cycle_color} -eq 1 ]] && magick "${media_file}" -
crop "${screen_width}x${screen_height}+${x_offset}+${y_offset}" -colorspace gray -fill
"hsl(${tint},100,50)" -colorize 25 ${output_dir}/${default_name}-${workspace}

                [[  ${get_color} -eq 1 ]] && [[ ${cycle_color} -eq 0 ]] && magick "${media_file}"
-crop "${screen_width}x${screen_height}+${x_offset}+${y_offset}" -colorspace gray -fill
"#${tint}" -colorize 25 ${output_dir}/${default_name}-${workspace}

                else

                        magick "${media_file}" -crop
"${screen_width}x${screen_height}+${x_offset}+${y_offset}" ${output_dir}/${default_name}-
${workspace}

                fi

        done

done

echo "I'm done!"

3 Likes

This time I’m sharing a small yab script, it lets you to launch web searches from a tiny window.

The interface is minimal, and requires a little room on you desktop, it can float, it can be locked, and it is meant to be used especially with shortcuts, so there is no need to use mouse.
Web hosts are saved in a plain text file, so they can be customized easily.

The only depedency is yab, tested 1.8
There is no particular need to bind to yab so run it as a it is, it is even better because if it is bound the lock function doesn’t work ( the window is just bmessaged to use a particular flag, but this doesn’t work when it’s bound)

It gave it a weird name, I know, but all the cool ones were already taken :sweat_smile:

It should not potentially harm your system, but the disclaimer is the usual, use it at your own peril :wink:

http://0x0.st/-n6J.zip [updated]

2 Likes

I didn’t research the problem or solution, but here are my 2 cents.

In Haiku, it is possible to place the wallpaper at certain offset. Is it possible to create a large wallpaper that covers all 4 desktops and only change its position offset when switching between the desktops, leaving the wallpaper image the same? The effect would be the same as changing the wallpaper.

1 Like

The script basically do this, calculates the x-y offset and crops the area x_offset,y_offset,screen_width,screen_height from the given image file, until we have a scripting feature for background it’s a dirty workaround, plus with the benefit to colorize the image to better distinguish the different workspaces, as you can see from these screenshots the tint is taken from +the workspace background color
screenshot1
screenshot2

5 Likes