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.38 on Debian 10 (“bullseye”). 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, by copying and customising the standard Metacity-based GNOME session.

To copy the files:

$ mkdir -p \
    ~/.config/systemd/user/gnome-session@gnome-flashback-i3.target.d/ \
    ~/.config/gnome-session/sessions/
$ cp \
    /usr/lib/systemd/user/gnome-session@gnome-flashback-metacity.target.d/session.conf \
    ~/.config/systemd/user/gnome-session@gnome-flashback-i3.target.d/session.conf
$ cp \
    /usr/share/gnome-session/sessions/gnome-flashback-metacity.session \
    ~/.config/gnome-session/sessions/gnome-flashback-i3.session

To do the customisation, open up the gnome-flashback-i3.session file in an editor, and on the RequiredComponents line, change “metacity” to “i3”. You can make other modifications to the session file, but note that RequiredComponents aren’t executables, they’re the names of .desktop files in /usr/share/applications (amongst other places).

GNOME Flashback also tries to create a custom window to manage desktop icons. Desktop icons aren’t very useful for a tiling window manager like i3, but more annoyingly, i3 doesn’t seem to understand that the desktop window should be behind all other windows, and tries to manage it as another application window. To disable the custom desktop functionality:

dconf write /org/gnome/gnome-flashback/desktop false

…tells GNOME Flashback to not create a custom desktop window, while:

dconf write /org/gnome/gnome-flashback/root-background true

…tells it to draw the desktop image (“wallpaper”) on the root window, just like in previous versions.

Modern versions of GNOME Terminal will also use client-side decorations if $XDG_CURRENT_DESKTOP contains “GNOME”. Client-side decorations can be nice in regular GNOME, but they’re kind of a waste of space with i3. I haven’t figured out how to prevent that environment variable from being set, but there is an override:

dconf write /org/gnome/terminal/legacy/headerbar false

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. Luckily, GNOME Flashback already includes such a shell script, which we can copy and customise.

Copy the file /usr/libexec/gnome-flashback-metacity to ~/.xsession then open it up in an editor, and change “metacity” to “i3”.

4. Teach i3 about GNOME

When gnome-session starts a session component, it typically expects the component to notify it via DBus that 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 confirmation dialog, and which works as you’d expect.

The GNOME Panel is redundant with the i3 bar, but some GNOME functionality is only available via panel applets, and not via standard notification area icons. As a result, you probably should disable the bar in your i3 configuration, and stick with the Panel.

5. 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.

Future work

For some reason, my GNOME+i3 session never seems to route the X11 bell through PulseAudio, and instead it always stays as a grating beep. I’m not sure why, but you might be able to work around it by adding 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.