I wrote a small Bash script for launching, then focusing or minimizing any X-compatible Ubuntu process by using the same key bindings for all these actions. If you've been using Tilda, you'll know what I mean.

Tilda used to be my terminal of choice, mainly because of its clever key bindings. It allows you to toggle the terminal on or off over the same key stroke, which kind of gets it out of your way, when the Desktop is clogged with IDEs and browser instances and who knows what.

However, Terminator has a lot more to offer to the terminal-loving world, the only thing it misses by comparison being these easy to use key-bindings.

So I started working on a small Bash script to accomplish the following:

  • launch an instance of any given process, unless a similar process is running
  • focus / activate the process window, if currently hidden or minimized
  • minimize the process window, if currently in focus

The magic act is complete only after binding this script to a key combination of choice. This can be easily accomplished with any of these methods:

  • Ubuntu Keyboard Shortcuts: System Settings > Keyboard > Shortcuts > Custom Shortcuts
  • CompizConfig Settings Manager Commands: CompizConfig > General > Commands

The latter requires CompizConfig, which you can install through the Ubuntu Software Center. I couldn't get the Custom Shortcuts working on my Ubuntu 12.04 (hmm...), but the CompizConfig Commands did the job.

There are two common ways of managing Ubuntu (Linux) windows through the command line: xdotool and wmctrl. Both have similar features, but with wmctrl you can't really minimize a window, just shade it (the title bar remains visible). Also xdotool is easier to use, but I'll post both methods, just in case one of them is not compatible with your Linux distro.

The xdotool way (winner)

  1. Install xdotool via sudo apt-get install xdotool.

  2. Open a text editor and paste in the following content:

    #!/bin/bash
    
    # I'm using terminator as my launcher - replace these values with your desired process
    LAUNCHER="terminator"
    LAUNCHER_PATH="/usr/bin/python\ /usr/bin/terminator"
    
    # Check if app is running by retrieving the first found pid for the given command
    pid=$(pgrep -f "$LAUNCHER_PATH" | head -1)
    if [ $pid ] 
    then
    # Retrieve the window id for the app window (last item, because first ones are dead processes)
    wid=$(xdotool search --all --pid=$pid --name '' | tail -1)
    
    if [ $wid ]
    then
      # Retrieve the window id for the active window
      active_wid=$(xdotool getactivewindow)
    
      if [ $wid -eq $active_wid ]
      then
        # Window is focused - hide!
        xdotool windowminimize $wid
      else
        # Window is not focused - show!
        xdotool windowactivate $wid
      fi
    else
      # Could not find a window for the given launcher - launch!
      eval $LAUNCHER
    fi
    else
    # App not running yet - launch!
    eval $LAUNCHER
    fi
    
    exit 0
    

    The LAUNCHER variable is the command that launches the app (think /usr/bin), while LAUNCHER_PATH is the actual path that the launcher is resolved to. If you're not sure what your command resolves to, you can run ps aux | grep [command] and find the LAUNCHER_PATH in the last column.

  3. Save the file as my-app-launcher.sh or whatever and don't forget to chmod +x my-app-launcher.sh in order to make it executable. You can test it from your command line by running ./my-app-launcher.sh. This should open the desired process or focus it, if already running. If you need to debug it, just run every line individually and check the outputs. It's pretty straightforward.

  4. You can shorten the path to the script by creating a link under /usr/bin:

    sudo ln -s my-app-launcher.sh /usr/bin/my-app-launcher
    
  5. Set up the keyboard shortcut: I chose to use CompizConfig Commands, because for some reason Ubuntu Shortcuts didn't really work. First you'll need to install CompizConfig from the Ubuntu Software Center. Run CompizConfig, then enable and select Commands from the General tab.

    Type in your script path my-app-launcher (or path to ./my-app-launcher.sh) into the Commands tab (let's say on Command line x), then switch to the Key Bindings tab and choose your keyboard shortcut for Run command x. Now close CompizConfig (make sure Commands is checked) and test your cool launcher shortcut.

The wmctrl way (requires some tweaking)

  1. Install wmctrl via sudo apt-get install wmctrl.

  2. Open a text editor and paste in the following content:

    #!/bin/bash
    
    # I'm using terminator as my launcher - replace these values with your desired process
    LAUNCHER="terminator"
    LAUNCHER_PATH="/usr/bin/python\ /usr/bin/terminator"
    
    # Check if app is running by retrieving the first found pid for the given command
    pid=$(pgrep -f "$LAUNCHER_PATH" | head -1)
    if [ $pid ] 
    then
    # Retrieve the window id for the app window
    wline=$(wmctrl -lp | grep $pid)
    wid=$(echo $wline | tr -s ' ' | cut -d ' ' -f 1)
    
    if [ $wid ]
    then
      # Retrieve the window id for the active window
      active_wid=$(xprop -root | awk '/NET_ACTIVE_WINDOW/ { print $5; exit }')
    
      # Need to compare decimal values because active_wid misses a leading "0"
      if [ $((wid)) -eq $((active_wid)) ]
      then
        # Window is focused - hide!
        wmctrl -ir $wid -b add,shaded
      else
        # Window is not focused - show!
        wmctrl -ir $wid -b remove,shaded
        wmctrl -ia $wid
      fi
    else
      # Could not find a window for the given launcher - launch!
      eval $LAUNCHER
    fi
    else
    # App not running yet - launch!
    eval $LAUNCHER
    fi
    
    exit 0
    

Steps 3 - 5 are similar to the xdotool method. You should note that there's no reliable way of minimizing a window with wmctrl. The only thing that works, as stated above, is shading the window (the title bar remains visible) and the suggested

wmctrl -ir ... -b remove,maximized_vert,maximized_horz

doesn't really do the trick.

Terminator tricks

Terminator has an option to skip the taskbar. Combined with the script shortcut, this allows for a more Tilda-like behaviour. Note that xdotool and wmctrl also offer ways of skipping the taskbar, but you'll have to dwell into this on your own.

Conclusion

I wrote this for my Ubuntu 12.04 and didn't have the resources to test it on other Linux distros. However it should work with any modern X-compatible system.

On some systems xdotool and wmctrl can't track down a window by its pid, so you'll have to rely on the window title or window class to get this working - check out the xdotool search arguments.