Keyboard shortcuts to raise specific windows
As soon as I got a Keychron K10 Pro, I started to wonder what to do with those extra 4 keys on the corner.
First, of course, I needed some cooler keycaps than square/circle/triangle/cross. So I got a couple from AliExpress - Pokémon not only because yes but also because cooler keycaps were waaaay too expensive (RIP One Piece).
Then, I had to do something with those damn keycaps.
For years and years, I already had a tiny script that only allowed me to open a single instance of SpeedCrunch (a simpler but smarter calculator, with no keyboard because I always used full keyboards lol). If the calculator was already opened somewhere, the script would raise the window instead.
Over the last year or so, that script suffered multiple iterations, until the current siwm
version, which is PHP-based and uses wmctrl
and xprop
to play around with the windows.
Right now, my keyboard can directly focus all the routine apps I use:
- Bulbasaur opens Home Assistant and Spotify;
- Pikachu opens Slack and PHPStorm;
- Squirtle opens my time-tracking apps;
- Charmander opens WhatsApp and Telegram.
I hope this is useful for more people! It's not public on GitHub because it's inside my private dotfiles repo 🙃
#!/usr/bin/env php
<?php
array_shift($argv); //script name
$search = array_shift($argv);
function has_arg(string $arg): bool {
return (in_array("--$arg", $GLOBALS['argv']) || preg_match("/(?<!-)-[a-z]*$arg[0]/", join(' ', $GLOBALS['argv'])));
}
function debug(string $msg): void {
if (DEBUG) {
echo "[DEBUG] $msg\n";
}
}
define('DEBUG', has_arg('debug'));
if (!$search || $search[0] == '-' || has_arg('help')) {
echo <<<HELP
Usage: siwm <search> [executable] [-hdc]
Args:
search : what you're searching for (window title, or class together with --class)
executable: what to run if nothing is found - if this is not given, it tries to execute the search string
Options:
-h/--help : show this and quit 🙃
-d/--debug: show extra debug info
-c/--class: search by window classes instead of titles
HELP;
echo "\n";
exit;
}
if (has_arg('class')) {
$wmctrlSearch = 'wmctrl -x';
debug("Searching by class: $search");
} else {
$wmctrlSearch = 'wmctrl';
debug("Searching through window titles: $search");
}
$search = preg_replace('/([\[\]])/', '\\\$1', $search);
$searchCmd = "$wmctrlSearch -l | grep -iw -m1 \"$search\"";
debug("$> $searchCmd");
$isOpen = shell_exec($searchCmd);
if ($isOpen) {
$wmctrl = 'wmctrl -i'; //selects the window by its ID, which is more reliable
debug('Window found: "'.trim($isOpen).'"');
[$id] = explode(' ', $isOpen);
echo "Raising window $id...\n";
if (str_contains(shell_exec("xprop -id \$id"), 'STICKY')) {
echo "[DEBUG] Hmmmm, it's sticky! Let's do it differently.\n";
shell_exec("$wmctrl -R $id; $wmctrl -r $id -b add,sticky");
} else {
shell_exec("$wmctrl -a $id");
}
} else {
echo "No window found matching '$search' 🤨 \n";
$app = join(' ', array_filter($argv, static fn($arg)=> !str_starts_with($arg, '-')));
if (!$app && !str_contains(' ', $search) && shell_exec("which $search")) {
$app = $search;
}
if (!$app) {
echo "Also, nothing to execute related to that. Try [...]\n";
exit;
}
//https://stackoverflow.com/a/11921855/102960
echo "Running `$app`...\n";
if (pcntl_fork() == 0) {
shell_exec($app);
}
}