14

I don't imagine this is built into the system, but is it possible to do it without too much hassle?

Say I open a specific program with a hotkey, and when I press that hotkey again, the program window is brought to the front.

I want to do this on Ubuntu 9.04.

Maybe with D-Bus? Any experts?

Update: Here's what I ended up with in case it's of help to somebody:

#!/bin/bash
if [ -f "/tmp/myterm.pid" ]; then
  WID=`cat /tmp/myterm.pid`
  xdotool windowactivate $WID
  if [ "$?" != "0" ]; then
    WID=""
  fi
else
  WID=`xdotool search --title "UNIQUE TITLE" | head -1`
fi

if [ "$WID" == "" ]; then
  /usr/bin/gnome-terminal --window-with-profile=MYPROFILE "$@"
  WID=`xdotool search --title "UNIQUE TITLE" | head -1`
  echo $WID > /tmp/myterm.pid
else
  xdotool windowactivate $WID
fi

Surely it can be simplified, but I'm no bash wiz. Also, for my example to work, I created a custom profile in Terminal that applies a unique title to the window so it can be found later. The possibilities are endless!

1
  • 1
    For this simple task, jtb's method works better, because xdotools sometimes throws X errors, and wmctrl is faster.
    – Ivan
    Commented Aug 1, 2009 at 0:33

7 Answers 7

14

The wmctrl program is just what you're looking for (sudo apt-get install wmctrl). You can use the wmctrl -a "AppTitle" command to bring the app to the front. wmctrl -l will list all available windows, so it should be easy to write a shell script that checks if your program is running and either launches it or brings it to the front. Then you can just bind that to a keyboard shortcut.

First save the following script somewhere, I'll use /home/jtb/code/bringToFront. It takes two arguments, the first is what you would type at the terminal to launch the program, the second is a substring of the program window's title. If there is no constant unique string in the title then you'll need to do a bit more work to find the program's window.

#!/bin/bash
if [ `wmctrl -l | grep -c "$2"` != 0 ]  
then
    wmctrl -a "$2"
else
    $1 &
fi
  1. With the script in your current directory, run chmod +x bringToFront to make the script executable. Then make sure it works; to launch/focus firefox you could run ./bringToFront firefox "Mozilla Firefox".

  2. Now we need to bind a shortcut key. Run gconf-editor and navigate the folder structure to the left to /apps/metacity/keybinding_commands.

  3. Double click on the first command with a blank value, probably command_1. Type the full path to the script and provide the two parameters, e.g. /home/jtb/code/bringToFront firefox Firefox.

  4. From the panel on the left, select global_keybindings, the next folder up. Find the run entry matching the command you just defined, probably run_command_1. Double click it and type the keyboard shortcut you want to use. Put the modifiers in angle brackets, e.g. <Ctrl><Alt>F.

Now Control + Alt + F will bring your firefox window to the front, or launch it if it's not already running.

6
  • Yeah, I found out about that a couple of minutes ago, but I went with xdotool. Thanks!
    – Ivan
    Commented Jul 31, 2009 at 23:41
  • I forgot to mention I also used the global shortcuts and commands in gconf to fully accomplish the effect (a poor man's Quake console!).
    – Ivan
    Commented Jul 31, 2009 at 23:45
  • Ah, yeah I haven't used xdotool myself but it looks like it would give you some more flexibility. Good point about gconf. Since that's pretty non-obvious I might as well edit the answer to include more details for anybody else looking to do this.
    – jtb
    Commented Jul 31, 2009 at 23:57
  • Poort Man's Quake console? You mean like Tilda? freshmeat.net/projects/tilda Commented Aug 3, 2009 at 18:47
  • Yes, I use Tilda too, but I work on several projects through the week, and for each one I always open three or four tabs, so quickly switching to the project's console ("workspace") without cluttering Tilda is very useful for me.
    – Ivan
    Commented Aug 13, 2009 at 19:32
3

Here's another way to do it with xdotools. The process to pop-up is recognized by the command line issued to run it (no pid file or unique window title needed).

#!/bin/bash

cmd="$@"
# command line to be run. Note that the resulting
# process will hold this in /proc/PID/cmdline 

pid=`pgrep -nf "^$cmd$"`
# most recent process having "$cmd" in /proc/PID/cmdline

if [ -z "$pid" ]; then # no pid
    exec $cmd
    # run command
else
    winid=`xdotool search --all --pid $pid --onlyvisible | head -1`
    # first visible window owned by pid
    xdotool windowactivate $winid
    # give window focus
fi
1

I had the same issue and since I didn't find any suiting solution, I made one :

https://hyperkeys.xureilab.com

https://github.com/xurei/hyperkeys

You can pin a window with a shortcut you define. I personally use SHIFT+ALT+[QWER] to pin and ALT+[QWER] to bring to front. You can't open the app if it's not open, though.

This is an open-source, linux-first tool. A Windows version is also available.

Hope it helps ! I'm looking for feedback, so if you have any question, create an issue ;-)

0

The answer posted by jtb earlier is excellent but sometimes you'd want to match exact titles (e.g. you want to open "GitKraken" but your browser's title "GitKraken vs CLI" is also matching the query).

#!/bin/bash
if [ $1 == "-exact" ]
then
    additional_arguments="-F "
    app_launch_command=$2
    app_title=$3
else
    additional_arguments=""
    app_launch_command=$1
    app_title=$2
fi

if [ `wmctrl -l $additional_arguments| grep -c "$app_title"` != 0 ]
then
    wmctrl $additional_arguments -a "$app_title"
else
    $app_launch_command &
fi

So now you can call your bringToFront script like following:

#exact match
./bringToFront.sh -exact "flatpak run com.axosoft.GitKraken" "GitKraken"
#or
./bringToFront.sh -exact <command_to_launch_the_app> <app_title

#partial match like the old script
./bringToFront.sh "flatpak run com.axosoft.GitKraken" "GitKraken"
#or
./bringToFront.sh <command_to_launch_the_app> <app_title>

0

This solution is not parameterised, but I have used it to bring-to-focus or start the gnome-calculator.

The -R option finds the window or fails, if found it is moved to the current desktop, raised and given focused. The gnome-calculator names it's window with the name Calculator, it could easily be parameterised, but I have never found the need to do so. I have it mapped to Ctrl-Alt-c.

#!/bin/bash
# start the calculator and raise and focus (requires wmctrl)
# X Tian 06sep2017 created

wmctrl -R Calculator
if [[ $? -ne 0 ]]
  then 
    gnome-calculator &
fi
0

Disclaimer: This answer is specific to Linux Mint MATE (which is what I have) however it may point you in the right direction or give you ideas still.


On Mint you can do it without having to write scripts:

  1. Open "Mint Menu" -> "Control Center".
  2. Search for/open "Keyboard Shortcuts".
  3. At the buttom click "Add".
  4. "Browse applications..." > and select whatever application you want to switch to.
  5. Modify "Command" field to be wmctrl -a "<substring of app's title>". For example wmctrl -a "Firefox".
  6. "Keyboard Shortcut" window now has a new entry for that program. Double click it and assign shortcut.
0

I use a modified version of it to create a window shortcut script which also supports cycling through multiple instances. If you are interested: Window Shortcuts for Linux.

The script makes use of the wmctrl utility which can easily be installed with

sudo aptitude install wmctrl

Here is the “focus” script:

#!/usr/bin/env python
import os
import sys
import commands
 
program_name = sys.argv[1] # the program to be focused
 
# get all windows which contain "program_name" from wmcontrol
candidates = sorted([x.strip() for x in commands.getoutput(""" wmctrl -l -x | awk -v win="%s" 'tolower($0) ~ win {print $1;}' """ % (program_name, )).split("\n") if x !=''])
 
if candidates : # at least one candidate found , we need to check if the active window is among the candidates (for cycling)
 
        # Get the id of the active window
 
        # Note: wmctrl currently does not support getting information about the active window.  In order to realize this
        #       we use xprop here. Unfortunately xprop gives us the window id of the active window in a different format:
        #       Window ids from wmctrl always begin with 0x followed by 8 digits (leading zeroes for padding). xprop
        #       does not do the padding and might give a window id starting with 0x followed by only 6 digits. The
        #       lines below get the id of the current window and make the id returned by xprop comaptible with
        #       the window ids returned by wmctrl.
        active_window_string = commands.getoutput("""xprop -root | grep "_NET_ACTIVE_WINDOW(WINDOW)" """)
        active_window_string =  active_window_string[active_window_string.find("#")+4:].strip()
        active_window = "0x" + "0" * (8-len(active_window_string)) + active_window_string
 
        next_window = None # the window to display. (one of the windows in candidates)
        if active_window not in candidates: # if the active window is not among the candidate windows
                next_window = candidates[0] # ..just show the first candidate window
        else:# we are already showing one of the candidate windows
                next_window = candidates[ (candidates.index(active_window)+1) % len(candidates)] # show the *next* candidate in the list (cycling)
 
        if next_window:
                os.system(""" wmctrl -i -a "%s" """ % (next_window,) ) # tell wmcontrol to display the next_window
else : # no windows open which fit the pattern of program_name
    os.system("%s &" % (program_name,)) # open new window
0

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .