How to Turn GNOME terminal to a Pop-up Terminal

A pop-up terminal is great and handy on Linux and similar OS. On KDE, Yakuake is great. On Gnome or GTK, I ever tried Guake. It is quite good. However, it has not been as mature, stable and figure-rich as gnome-terminal. One day, I got this idea: why not using a script/program to manage the gnome-terminal and take action upon hotkey hits? The top-down effect is non-important to me. What I want is simple: use a hotkey (like F12) to activate/deactivate the terminal.

It turns out the Linux software have sufficient tools for this: bash for scripting, Gnome/Cinnamon native keyboard tools to catch hotkey (F12 is my favorite for this) and xdotool for checking/searching/activating/minimizing X windows. What I need to do is to write the bash script to connect them together.

For those who are in hurry to try: install the xdotool, download the script at here, map a hotkey in your desktop environment to invoke this script and just hit that key.

In the remaining part, I will introduce the design of the script and why it is like this.

The script is invoked multiple times. Each time it is invoked, it may 1) Check whether the terminal is opened. If not, open the terminal. 2) Check whether the terminal is currently activated. If it is, minimize it to hide it. Otherwise, activate the terminal.

The first problem is how to track the state? The state is the ID of the terminal managed by this script. And the state should be persistent across different runs of the script. The solution is to save it into a file. Causing disk I/O each time we activate/deactivate the terminal is not a good choice. Hence, I use the ramdisk /dev/shm/. The “$USER” prefix is to avoid multiple users conflict with each other.

    # save the state
    echo "$term" >$state_file
# read the state
term=$(cat $state_file)

The next problem: what if the state file exists while the terminal is closed? The solution is to heck whether it exists and create it if it does not exist:

# check whether it exists
term_exists "$term"
if < "$exists" != "0" />; then
    exit 0

The term_exists and create_terminal is tricky at several parts. I leave the readers to figure it out by yourselves.

term_exists () {
    allterms=`xdotool search --class "$termtype"`
    for e in $allterms; do < "$e" == "$1" /> && return 0; done
    return 1

create_terminal () {
    echo "Create new terminal"
    gnome-terminal --maximize &

    until [ "$exists" == "0" ]; do
        # sleep a while
        sleep $wait_sec

        # Note that the focus window may be from a terminal that
        # already exists; the makes create_terminal choose the existing terminal
        # Making the wait_sec large enough so that the terminal can be created and
        # displayed can make the false choosing more unlikely.

        term=$(xdotool getwindowfocus)
        term_exists "$term"
        # avoid infinite wait
        let wait_cnt=wait_cnt+1
        if [ $wait_cnt -gt $max_wait_cnt ]; then
            echo "Wait for too long. Give up."

    echo "Created terminal window $term"
    # save the state
    echo "$term" >$state_file

The create_terminal may possibly fail by choosing another terminal that it is not created by this script (why?). In practice, I never find this since I usually use one terminal with many tabs. Please comment if you have a better solution.

Now, we ensured that there is a terminal created by the script exists. The last step is to check whether it is activated and activate/deactivate it accordingly using xdotool.

# check whether it is already activated
curwin=$(xdotool getwindowfocus)

if [ "$term" == "$curwin" ]; then
    # deactivate (minimize) the terminal if it is currently activated
    xdotool windowminimize $curwin
    # activate the terminal if it is not currently activated
    xdotool windowactivate $term

Eric Ma

Eric is a systems guy. Eric is interested in building high-performance and scalable distributed systems and related technologies. The views or opinions expressed here are solely Eric's own and do not necessarily represent those of any third parties.


Leave a Reply

Your email address will not be published. Required fields are marked *