Skip to content

Instantly share code, notes, and snippets.

@academo
Last active December 26, 2023 10:46
Show Gist options
  • Star 16 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save academo/613c8e2caf970fabd260cfd12820bde3 to your computer and use it in GitHub Desktop.
Save academo/613c8e2caf970fabd260cfd12820bde3 to your computer and use it in GitHub Desktop.
#!/bin/bash
# Usage: ww -f "window class filter" -c "run if not found"
# Usage: ww -fa "window title filter" -c "run if not found"
## Find and contribute to a more updated version https://github.com/academo/ww-run-raise
POSITIONAL=()
while [[ $# -gt 0 ]]; do
key="$1"
case $key in
-c | --command)
COMMAND="$2"
shift # past argument
shift # past value
;;
-f | --filter)
FILTERBY="$2"
shift # past argument
shift # past value
;;
-fa | --filter-alternative)
FILTERALT="$2"
shift # past argument
shift # past value
;;
*) # unknown option
POSITIONAL+=("$1") # save it in an array for later
shift # past argument
;;
esac
done
set -- "${POSITIONAL[@]}" # restore positional parameters
SCRIPT_CLASS_NAME=$(
cat <<EOF
function kwinactivateclient(targetApp) {
var clients = workspace.clientList();
for (var i=0; i<clients.length; i++) {
client = clients[i];
if (client.resourceClass == targetApp){
workspace.activeClient = client;
break;
}
}
}
kwinactivateclient('REPLACE_ME');
EOF
)
SCRIPT_CAPTION=$(
cat <<EOF
function kwinactivateclient(targetApp) {
var clients = workspace.clientList();
for (var i=0; i<clients.length; i++) {
client = clients[i];
if (client.caption == targetApp){
workspace.activeClient = client;
break;
}
}
}
kwinactivateclient('REPLACE_ME');
EOF
)
CURRENT_SCRIPT_NAME=$(basename $0)
# ensure the script file exists
function ensure_script {
if [ ! -f SCRIPT_PATH ]; then
if [ ! -d "$SCRIPT_FOLDER" ]; then
mkdir -p "$SCRIPT_FOLDER"
fi
if [ "$1" == "class" ]; then
SCRIPT_CONTENT=${SCRIPT_CLASS_NAME/REPLACE_ME/$2}
else
SCRIPT_CONTENT=${SCRIPT_CAPTION/REPLACE_ME/$2}
fi
echo "$SCRIPT_CONTENT" >"$SCRIPT_PATH"
fi
}
if [ -z "$FILTERBY" ] && [ -z "$FILTERALT" ]; then
echo You need to specify a window filter. Either by class -f or by title -fa
exit 1
fi
IS_RUNNING=$(pgrep -o -a -f "$COMMAND" | grep -v "$CURRENT_SCRIPT_NAME")
if [ -n "$IS_RUNNING" ] || [ -n "$FILTERALT" ]; then
SCRIPT_FOLDER="$HOME/.wwscripts/"
SCRIPT_NAME=$(echo "$FILTERBY$FILTERALT" | md5sum | head -c 32)
SCRIPT_PATH="$SCRIPT_FOLDER$SCRIPT_NAME"
if [ -n "$FILTERBY" ]; then
ensure_script class $FILTERBY
else
ensure_script caption $FILTERALT
fi
#SCRIPT_NAME="ww$RANDOM"
SCRIPT_NAME=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 32 | head -n 1)
# install the script
ID=$(dbus-send --session --dest=org.kde.KWin --print-reply=literal /Scripting org.kde.kwin.Scripting.loadScript "string:$SCRIPT_PATH" "string:$SCRIPT_NAME" | awk '{print $2}')
# run it
dbus-send --session --dest=org.kde.KWin --print-reply=literal "/$ID" org.kde.kwin.Scripting.run
dbus-send --session --dest=org.kde.KWin --print-reply=literal "/$ID" org.kde.kwin.Script.run
# stop it
dbus-send --session --dest=org.kde.KWin --print-reply=literal "/$ID" org.kde.kwin.Scripting.stop
dbus-send --session --dest=org.kde.KWin --print-reply=literal "/$ID" org.kde.kwin.Script.stop
# uninstall it
dbus-send --session --dest=org.kde.KWin --print-reply=literal /Scripting org.kde.kwin.Scripting.unloadScript "string:$SCRIPT_NAME"
elif [ -n "$COMMAND" ]; then
$COMMAND &
fi
@EvanEdwards
Copy link

It appears that you and I have similar workflows. I'm getting ready to flip over to Wayland and looking for tools to replace my various scripts. This was very helpful. Thanks!

@Vaisakhkm2625
Copy link

really thanks for making this...

but, how to get window name & class in kde wayland, is there any tool like xprop?

can you provide some example for how to use this script??

@academo
Copy link
Author

academo commented Jun 5, 2023

@Vaisakhkm2625 I don't really use wayland so I don't know how to get classes and window names from there. You can see all instructions in how to use the script here https://github.com/academo/ww-run-raise

@Vaisakhkm2625
Copy link

@Vaisakhkm2625 I don't really use wayland so I don't know how to get classes and window names from there. You can see all instructions in how to use the script here https://github.com/academo/ww-run-raise

ok thanks.... i open x11 and find class names and switched back to wayland :)

@Ashark
Copy link

Ashark commented Jul 16, 2023

What is the difference in org.kde.kwin.Script.stop and org.kde.kwin.Scripting.unloadScript? Is the latter needed? Please see this.

@academo
Copy link
Author

academo commented Jul 17, 2023

@Ashark if you only stop it but don't uninstall it it starts growing the list of scripts in kwinscript. I could not find a way to re-use an existing "installed" script so this is the solution I found to not pollute the kwinscripts list.

@Ashark
Copy link

Ashark commented Jul 17, 2023

@academo For uninstalling, how do i know the script name, if i did not created it?
Can you try with the plasma-interactiveconsole? Open a dbus viewer. Then run any kwin script in interactiveconsole. Now update the dbus viewer. You will see a new id is resided there (this is a bug, i want to fix this). Now, if you click the stop method for that id, it will disappear.
But you say it remains residing there is not using uninstall method. And the current code of interactiveconsole does not invoke uninstall method.
Can you confirm?

@academo
Copy link
Author

academo commented Jul 18, 2023

@Ashark

how do i know the script name, if i did not created it?
I don't know :) I never went that far with KWin scripts and the documentation is quite vague. I mostly found things by experimentation and bits from forums here and there.

Then run any kwin script in interactiveconsole. Now update the dbus viewer. You will see a new id is resided there (this is a bug, i want to fix this). Now, if you click the stop method for that id, it will disappear.

Yes I can reproduce this.

But you say it remains residing there is not using uninstall method. And the current code of interactiveconsole does not invoke uninstall method.

I can see the ww script showing up briefly and disappearing from qdbusviewer session bus. I commented the uninstall line and this still happened so the uninstall method is not what removes it from the dbus list.

I commented stop and the id didn't remain there either so the stop is not the one removing it from the dbus list either.

My memory fails me since I did this some time ago and I am not working with Kwin scripts anymore but I remember there was a place where I could see the list of scripts installed via the dbus and if stop and unload were not called, the list kept growing and growing. Perhaps this list disappeared from newer kde versions?

@Ashark
Copy link

Ashark commented Jul 18, 2023

Maybe they changed it in KDE, I too do not know.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment