Bash command to focus a specific window

Is there a way, in bash command line, to give focus to a specific window of a running process. Assume I know the process' name, number, and anything else I need.

For instance, if I have a single instance of Firefox running, but it's minimized (or there's some other window on top of it). I need a bash command that brings up and gives focus to the Firefox window, by making it the active window.


The wmctrl command seems to do the job. It was already installed for me, but it's available in the repositories in case anyone needs it.

wmctrl -l 

Lists currently open windows (including the gnome panels).

wmctrl -a STRING

Gives focus to a window containing STRING in its title. I'm not sure what happens if more than one window meets that condition.
In my case the command was:

wmctrl -a Firefox

Using wmctrl in combination with xdotool you can switch focus to Firefox and then perform keyboard or mouse actions.

In this example:

wmctrl -R firefox && \
  xdotool key --clearmodifiers ctrl+t ctrl+l && \
  xdotool type --delay=250 google && \
  xdotool key --clearmodifiers Tab Return

The following steps are executed:

  1. Give focus to the first matching Firefox window
  2. Open a new browser tab
  3. Puts focus in the address bar
  4. Type "google"
  5. Tab to the first browser auto-complete result
  6. Press the Return (or Enter) key

How's the below script that I use in my ubuntu pc? use case is like this.

   $ ./focus_win.sh 1            # focus on a application window that executed at first
   $ ./focus_win.sh 2            # second executed application window

I'm using it after assigning it in keyboard custom shortcut. ctrl+1, ctrl+2, ...

cat focus_win.sh

#! /bin/sh

if [ "" = "$1" ] ; then
    echo "usage $0 <win index>"
    exit 1;
fi

WIN_ID=`wmctrl -l | cut -d ' ' -f1 | head -n $1 | tail -n 1`

if [ "" = "$WIN_ID" ] ; then
    echo "fail to get win id of index $1"
    exit 1;
fi
wmctrl -i -a $WIN_ID

Update

Sadly, this no longer works on Gnome 41 for security reasons

Running global.context.unsafe_mode = true in Looking Glass re-enables the functionality, but only temporarily.

Original answer

On Wayland, sadly wmctrl and xdotool do not function. Instead we can talk to the window manager.

For Gnome, we can run gdbus to send a DBUS message to execute some GJS (JavaScript bindings for the GNOME C APIs).

To focus a window:

$ gdbus call \
  --session \
  --dest org.gnome.Shell \
  --object-path /org/gnome/Shell \
  --method org.gnome.Shell.Eval "
var mw =
  global.get_window_actors()
    .map(w=>w.meta_window)
    .find(mw=>mw.get_title().includes('Firefox'));
mw && mw.activate(0)"

See also:

  • How to get a list of windows, with their class and title
  • How to get the class of the currently focused window
  • How to minimise all windows

You can play around with what's possible in GJS using Gnome's 'Looking Glass' debugger: Alt+F2, and run lg