13

A big part of my workflow is based on using shortcuts. Currently I use xbindkeys and wmctrl to run-or-raise an application. E.g: Super+F brings up firefox or run it if not running.

Autokey works fine with KDE and I could also use KDE native custom shortcut manager to replace xbindkeys but I can't find (and I googled a lot) a way to determine if a window/application is running and if not, raise it.

I can probably use ps or a similar command to find if an application is running and if not, launch it, but it goes to the final problem: how to raise (or focus) an existing running window/application programmatically?

There seems to be some kind of gdbus solution for GNOME but of course this won't work in KDE.

Does anyone have an idea or clue of what can I do?

2 Answers 2

6

After much research, I got into a solution that will only work for KDE and only KDE: using a kwin script.

The script is:

  1. use pgrep to see if a program is running (useful command grep)
  2. if running:
    1. install an on-the-fly kwin script that will explicitly "activate" a window with a passed className or title
    2. run the script
    3. stop the script
    4. uninstall the script
  3. if not running: run a command to start it.

For example, let's say I want to focus or launch Firefox, I'd do with my script:

ww -f firefox -c firefox

-f: the window classname
-c: the command to run if not running
-fa: alternative filter to use the window title instead of the class

This is the script I am using now and it's been working great.

1

Here is a solution that works on wayland with gnome.

It has following behaviour,

  1. If the app is not running, open it.
  2. If app is running and it is not focused, bring it into focus.
  3. If app is already focused and there are multiple instances of the same app, cycle through them.
  4. If app is focused and it's the only instance, do nothing.
#!/usr/bin/bash

# Usage: path/to/script <wm_class> <wm_class_instance> <command to launch the app>
#
# Please ensure you have the following installed:
# - gdbus
# - jq
# - GNOME Shell Extension: Window Calls
#
# To install extension, you can use the following command:
# gnome-extensions install [email protected]
# OR visit
# https://extensions.gnome.org/extension/4724/window-calls/
#
# You can get the wm_class and wm_class_instance using the command:
# gdbus call --session --dest org.gnome.Shell --object-path /org/gnome/Shell/Extensions/Windows --method org.gnome.Shell.Extensions.Windows.List | cut -c 3- | rev | cut -c4- | rev | jq '.'


wm_class=$1
wm_class_instance=$2

# Get window list for the current workspace using gdbus
win_list=$(gdbus call --session --dest org.gnome.Shell --object-path /org/gnome/Shell/Extensions/Windows \
  --method org.gnome.Shell.Extensions.Windows.List | cut -c 3- | rev | cut -c4- | rev | jq -c '.[] | select(.in_current_workspace == true)')

# Get the ID of the currently focused window
active_win_id=$(echo "$win_list" | jq -r 'select(.focus == true) | .id')

# Find all windows matching the specified application name in the current workspace
matching_windows=$(echo "$win_list" | jq -r --arg app "$wm_class" --arg instance "$wm_class_instance" 'select(.wm_class == $app and .wm_class_instance == $instance) | .id')

# Cycle through windows if there are multiple matches
if [[ "$matching_windows" == *"$active_win_id"* ]]; then
  # Remove the active window from the list and pick the next window ID
  switch_to=$(echo "$matching_windows" | sed "s/$active_win_id//" | awk 'NR==1')

  # If the active window is the last in the list, pick the first window
  if [ -z "$switch_to" ]; then
    switch_to=$(echo "$matching_windows" | awk 'NR==1')
  fi
else
  # Select the first window to switch to if the active window does not match the app
  switch_to=$(echo "$matching_windows" | awk 'NR==1')
fi

# Focus the window if found, or execute the provided command
if [[ -n "$switch_to" ]]; then
  gdbus call --session --dest org.gnome.Shell --object-path /org/gnome/Shell/Extensions/Windows \
    --method org.gnome.Shell.Extensions.Windows.Activate "$switch_to"
else
  # If a command is provided, execute it to open the app
  if [[ -n "${@:3}" ]]; then
    ("${@:3}") &
  fi
fi

exit 0

You can set this as gnome custom keybings,

Bonus tip: If you want to automatically backup keybindings refer this

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.