63

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.

0

5 Answers 5

92

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
7
  • 8
    Nice to see someone is reading and I'm not just rambling to myself. =)
    – Malabarba
    May 20, 2010 at 14:59
  • 1
    Also try xdotool. Apr 25, 2012 at 7:04
  • 1
    This is awesome for setting focus back to gdb (debugger) when it launches a debugger target with a window that steals focus, like kvm. Use gdb command shell wmctrl -a something, where something is something in your debugger terminal title.
    – doug65536
    Oct 25, 2016 at 3:46
  • Thanks so much, this is pure gold, I was afraid I lost all of my pending work in some Chrome window that just disappeared in the background somehow, it worked!
    – Osmar
    Jan 15, 2019 at 21:45
  • 2
    You could also use xdotool for this: xdotool search --class "class name" windowfocus, or target the window using its name. Find the window info with xev.
    – idontknow
    Aug 8, 2021 at 18:02
16

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
1
  • Also: xvkbd -window firefox -text "hello" or xvkbd -window firefox -text "\C\[t]" (Ctrl+t)
    – Iacchus
    Feb 11 at 0:17
7

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
3

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:

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

1
  • I'm seeing this all over the place. But where exactly do I put gdbus calls? It looks like it's supposed to just evaluate the GJS. But I'm running it in a shell, from a file, and get no output (error or otherwise) on any of the scripts linked above. I've tried to evaluate them through d-feet (org.gnome.Shell.Eval) with: 'invalid syntax (<string>, line 1)' error outputs. Separate GJS files evaluate to "global is not defined". Any help? Thank you for being the first person across dozens of threads to consider Wayland, though. Since it runs just fine on looking glass, it's obviously correct gjs.
    – Nephilim
    Oct 25, 2021 at 8:14
0

As another answer already mentioned, wmctrl is a good choice for this task and wmctrl -a WINDOWTITLE allows one to activate the window whose title contains WINDOWTITLE.

However, in many cases the window title does not contain the name of the program used. For this purpose wmctrl also has the -x option that can be used to focus windows by class name.

You can type wmctrl -lx to print all currently open windows, together with their class name. You can use wmctrl -xa NAME to activate a Window whose class name includes NAME.

For example,I had the issue that I wanted to activate the window of the Evince PDF viewer if it was open, and I couldn't do that from the window name alone as it always only contains the name of the PDF that is viewed. So I used wmctrl -lx and found the line

0x06000007  0 evince.Evince         sejmou-desktop 2. User-User Collaborative Filtering

Where evince.Evince is the window class name mentioned above.

Then, I was able to activate the Evince window programmatically wmctrl -xa Evince. Of course this only works reliably as long as Evince is a unique class name among the windows that are currently open.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.