Screwtape's Notepad

Using i3 with GNOME 3

In the bad old days, every computer had a monitor, a keyboard, a mouse, and that was it. These days, computers have all kinds of extra peripherals, like screens that can dim, audio outputs that can change their volume, and keyboards with buttons to control all those things. On a modern Linux kernel, getting those things working can be a hassle, and if they need to work together (say, dimming the screen when battery gets low) it’s even more complex.

Luckily, modern desktop environments handle all this stuff out-of-the-box, and GNOME 3 is one of the more widely-available and best-supported options. Its default configuration is simple and easy for new users to get started with, while its modularity and extensibility allow power-users quite a bit of customisation.

Unluckily, as flexible and extensible as it is, GNOME 3’s desktop environment is not quite as graceful at dealing with many windows as a good tiling window-manager like i3. And the GNOME Shell front-end is fairly tightly linked with the hardware-management backend. It would be lovely if there were a GNOME component that allowed the hardware-management to run independently of GNOME Shell, so I could use it with a different window-manager.

It turns out there is. There’s a thing called GNOME Flashback, which makes the modern GNOME 3 infrastructure available without the GNOME 3 interface, so that people who preferred the old GNOME 2 interface can keep using it, or at least something resembling it. Because GNOME 2 allowed custom window-managers, so does GNOME Flashback, which means we can use it with i3.

Instructions

I’m using GNOME 3.22 on Debian 9 (“stretch”). Your mileage may vary with other versions and other distros.

1. Install dependencies

We’re going to need the GNOME Flashback package, and of course i3.

$ sudo apt-get install gnome-session-flashback i3

2. Teach GNOME about i3

To create a session with all the required GNOME background services, the easiest thing is to use gnome-session. We’ll create a session that includes i3 and the GNOME Flashback goodies.

Save this file as ~/.config/gnome-session/sessions/gnome-plus-i3.session (you may need to create the intervening subdirectories yourself):

[GNOME Session]
Name=GNOME + i3
RequiredComponents=gnome-flashback-init;gnome-flashback;i3;gnome-settings-daemon;

Other GNOME Flashback sessions include additional RequiredComponents like gnome-panel (for the traditional GNOME application menu and taskbar) and nautilus-classic (to draw desktop icons) but since those aren’t related to hardware support, I’ve left them out.

Also note that RequiredComponents aren’t executables, they’re the names of .desktop files in /usr/share/applications (amongst other places).

3. Launch our new session at login.

Adding a new session type to GDM’s list of sessions would require editing system-wide files, but luckily we don’t actually need to do that. If you have a file named .xsession in your home directory, GDM will include a session named “System X11 Default” that will execute that file as a shell script.

So we just need to write a script that launches gnome-session and tells it to run our i3-based session instead. Save the following file as .xsession in your home directory:

# Menu tools use this value to decide which applications
# are approriate for the current session.
if [ -z $XDG_CURRENT_DESKTOP ]; then
    export XDG_CURRENT_DESKTOP="GNOME-Flashback:GNOME"
fi

# Run gnome-session and tell it to use our i3 session.
exec gnome-session --session=gnome-plus-i3 --disable-acceleration-check

4. Teach i3 about GNOME

When gnome-session starts a session component, it typically expects the the component to notify it via DBus that the the component has started correctly. i3 knows nothing of DBus, so gnome-session will launch i3 and wait forever for something to happen.

Instead, teach i3 to notify gnome-session that it has started by putting the following lines at the end of ~/.config/i3/config:

exec --no-startup-id dbus-send \
    --session \
    --print-reply=literal \
    --dest=org.gnome.SessionManager \
    "/org/gnome/SessionManager" \
    org.gnome.SessionManager.RegisterClient \
    "string:i3" \
    "string:$DESKTOP_AUTOSTART_ID"

Also, to log out of an i3-based session, you run (directly, or via a keybinding) i3-msg exit to tell i3 to exit. However, under gnome-session, that doesn’t actually log you out: gnome-session might restart i3, or it might just let it exit, leaving all your applications still running, with no way to manually exit them.

Instead, you should bind your usual logout key to run gnome-session-quit, which will pop up the traditional GNOME log out dialog, and which works as you’d expect.

4. Try it out!

Log out, log back in (and make sure to pick “System X11 Default” as your session) and you should be in i3 with all the GNOME services available.

Update 2017-07-14

After following the above instructions, one difference I noticed between GNOME and i3 was that under GNOME, the terminal bell was a pleasant, subtle sound, while under i3, I got the traditional machine beep.

It turns out that something somewhere wasn’t telling PulseAudio to replace the machine beep. Never mind, we can tell it ourselves. Add the following to ~/.xsession, just before the exec gnome-session ... bit.

# Redirect the X11 beep to PulseAudio
pactl upload-sample \
    /usr/share/sounds/freedesktop/stereo/dialog-information.oga \
    x11-bell
pactl load-module \
    module-x11-bell \
    display=$DISPLAY \
    sample=x11-bell

I happen to like dialog-information.oga because it matches what I remember from GNOME, but feel free to try different sounds.