Multiple Instances of Gnome Terminal

Gnome 3 introduced a very handy feature, grouping multiple application windows (whether they be separate instances or not) into a single desktop icon. This means when <alt+Tab>ing through your windows, you can skip over the dozen firefox windows, then dive into just your terminal windows. Generally, this works great, and I think most users don’t have any issues.

However, some people (myself included) use a lot of terminals. Some are temporary short-lived generic terminals. Others are long-lived running mail (mutt), or a main development session. Unfortunately, trying to switch to my email terminal can be cumbersome as I squint at thumbnails of 10+ other terminals.

Luckily, the mechanisms to control this are somewhat accessible. Gnome matches a window to .desktop file based on some Window properties. All like matches are grouped together. Luckily, it seems GTK+ exposes functionality to modify these values at the command line. I’ve latched on to window class (WM_CLASS), but there are likely other rules that guide a match.

WM_CLASS seems to be set by some combination of both the –class and –name GTK+ flags. The first step is to see if I can make an appropriate change. In gnome-terminal, I ran the following:

yelp --class=foo --name=foo

Bingo! I got a standard yelp window, but it identified itself to gnome as foo in the title bar, <alt+tab>, and dock! It didn’t get grouped with the yelp shortcut!

Lets do the same with gnome-terminal:

gnome-terminal --class=foo --name=foo

No luck. I got a new window, but it was grouped with my existing one. The above works if this is the first instance, however, so gnome-terminal is certainly capable of changing it’s window properties.

Turns out, gnome-terminal is being clever. It’s actually running a background process, gnome-terminal-server, that owns all windows. Running an additional gnome-terminal simply pokes the existing process to create a new child window.

In gnome 3.6 and earlier, this was easy enough to solve. Adding --disable-factory would disable this functionality. However, since gnome 3.8, it’s now using some sort of dbus activation. I had given up on gnome-terminal.

I tried using alternative terminals. Ultimately, I was frustrated that they didn’t pick up my theme correctly (GTK+-2.0 based), or were weird (terminator), or that I the fonts just looked better in gnome-terminal (xterm, etc), or needed a universe of dependancies (konsole)

Finally, I came across a lead on Stack Exchange: Run true multiple process instances of gnome-terminal. This lead me to a page on Gnome’s Wiki on Running a separate instance of gnome-terminal.

This workaround involves manually starting a new terminal server.

/usr/libexec/gnome-terminal-server --app-id com.example.terminal --name=foo --class=foo &

gnome-terminal --app-id com.example.terminal

Aha, so it is possible to get my desired functionality. However, while this works, it isn’t ideal. This requires running two commands, rather than just one. Additionally, the server dies after 10 seconds if no clients connect, preventing me from spawning it at login.

But this manual server initialization isn’t required with the standard backend. So how does that work?

Turns out, it’s a dbus service definition. You can review the current one /usr/share/dbus-1/services/org.gnome.Terminal.service, then make our own.

I’ve decided to call my session ‘PIM’, as I’m using it for my mail/calendar terminals

cat /usr/share/dbus-1/services/org.gnome.Terminal-PIM.service
[D-BUS Service]
Name=org.gnome.Terminal-PIM
Exec=/usr/libexec/gnome-terminal-server --class=org.gnome.Terminal-PIM --app-id org.gnome.Terminal-PIM

Now, I’ve also created the associated (and like-named) .desktop file (used the /usr/share/applications/org.gnome.Terminal.desktop as a template)

$ cat ${HOME}/.local/share/applications/org.gnome.Terminal-PIM.desktop 
[Desktop Entry]
Name=Mail & PIM
Comment=Mutt and Calendar
Keywords=mail;mutt;calendar
Exec=gnome-terminal --app-id org.gnome.Terminal-PIM -e "screen -DR PIM -c .screenrc-ejpim"
Icon=mail_send
Type=Application
StartupNotify=true
X-GNOME-SingleWindow=false

Note: I’m actually launching it straight into a pre-defined screen session, but you could change the -e parameter to whatever you wish.

Both dbus and gnome-shell need to be restarted to pick up their changes. You can tell gnome-shell to restart itself, but the surest method I’m aware of for dbus is to log out and in again.

Now I can run the “Mail & PIM” shortcut, and get a gnome-terminal window that is grouped separately (with a mail icon!).

At this point, it would be work investigating gnome-terminal profiles, if desired (different colour schemes, etc).

Unfortunately, while I put my .desktop file in ~/.local/share/applications, I couldn’t find a user-specific dbus servicedir. I had to install that in the system itself with sudo. I’d prefer to have it local to my user, so I can move it easily to other systems with my existing vcsh configuration.

Update 2016-10-12

Recently there was some sort of change that caused gnome-terminal-server to run via systemd service file in the users session. This means a slight change is required to the steps above.

The dbus service file should now read:

cat /usr/share/dbus-1/services/org.gnome.Terminal-PIM.service
[D-BUS Service]
Name=org.gnome.Terminal-PIM
SystemdService=gnome-terminal-server-pim.service
Exec=/usr/libexec/gnome-terminal-server --class=org.gnome.Terminal-PIM --app-id org.gnome.Terminal-PIM

Additionally, you’ll need to create a systemd unit file:

cat /usr/lib/systemd/user/gnome-terminal-server-pim.service 
[Unit]
Description=GNOME PIM Terminal Server
[Service]
KillMode=process
Type=dbus
BusName=org.gnome.Terminal-PIM
ExecStart=/usr/libexec/gnome-terminal-server --class=org.gnome.Terminal-PIM --app-id org.gnome.Terminal-PIM

You’ll need to systemd --user daemon-reload for the systemd changes to take effect. You may still need to log out for the dbus change.