DEV Community

Cover image for Keyboard shortcuts to raise specific windows
Igor Santos
Igor Santos

Posted on

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);
    }
}
Enter fullscreen mode Exit fullscreen mode

Top comments (4)

Collapse
 
tanami profile image
Tanami

I wrote a similar script that takes the running program name and the executable path and activates the window if it's already running or otherwise executes it. I have some XFCE shortcuts linked to it.

if pgrep -f ^$2 > /dev/null
then
    wmctrl -a $1
else
    $2
fi
Enter fullscreen mode Exit fullscreen mode
Collapse
 
kevinzhang109 profile image
Kevin zhang

I use Karabiner-Elements in my Macbook,It significantly boosted my workflow efficiency — especially after I assigned shortcut keys to Code Studio, Chrome, WeChat, iTerm2, and Beyond Compare, replacing the need for frequent ALT+Tab switching. It’s made things so much more convenient.

Collapse
 
nadeem_zia_257af7e986ffc6 profile image
nadeem zia

Interesting to read

Collapse
 
dotallio profile image
Dotallio

This is such a fun setup, both the shortcuts and the keycaps! Any chance you'll share the script or more keycap pics in the future?