I have pretty basic needs from my desktop. I do 99% of my work using just three
programs: a terminal emulator, Emacs, and Firefox. I don’t want a lot of bells
and whistles in my desktop, and I really just want it to get out of the way so I
can do my work.
But just because my needs are basic doesn’t mean that I want a 1990’s window
manager experience. I want good text rendering and windows and buttons with
rounded corners. I want my laptop to work correctly when connecting it to
external displays or projectors without a lot of futzing around. I want vsync to
work with my monitor out of the box, I want to be able to watch video without
tearing, and I want a desktop that has first class support for high-DPI
displays. I also want to have some basic integration with the other system
features provided by my distro, which increasingly means high-quality
integration with NetworkManager and different systemd components. I want to get
integrated notifications when a program segfaults on my computer or in case
there’s an SELinux AVC denial.
In my opinion, in these areas GNOME is far ahead of everything else. The stock
GNOME configuration is beautiful but minimal—I get a discreet black bar across
the top of my screen that shows the time and date, and lets me control the
fundamentals like network access. I think that GNOME Shell is the most
attractive and useful window manager for any operating system out there. And
GNOME has really good integration with the other parts of my system, which
makes sense because it’s the default desktop environment on my distro (Fedora)
and most others, including Debian and Ubuntu. GNOME is also light-years ahead of
everything else in terms of Wayland support. Fedora has been shipping Wayland as
the default GNOME display backend since Fedora 25 (2016), and it works
incredibly well. The most compelling user-visible feature that has come out of
this is GNOME’s “fractional scaling” feature, which is a quantum leap in terms
of how content is scaled on high-DPI screens.
But I’ll be honest: GNOME is huge and kind of bloated, and it’s hard to disable
various unwanted components. GNOME Shell is amazing, but a lot of the other
components of GNOME are simply unwanted. This is what turns a lot of power users
away from GNOME, which I think is a shame given all of the other amazing things
about GNOME. While you won’t find these instructions in the GNOME manuals, if
you know what you’re doing modern GNOME releases make it very easy to lobotomize
a lot of the unneeded and unwanted features.
Configuration With dconf
The first step in improving the GNOME user experience is toggling basic features
on or off. You can do this either by clicking around in the GUI, or using the
dconf command line tool. One of the interesting things about GNOME is that it
has a lot of hidden options that either not at all exposed in the GUI, or only
accessible through a tool like gnome-tweaks. But if you know what you’re doing
you can change a lot of GNOME behavior.
Most people are already in the habit of keeping their dot files in a git repo
somewhere. I recently took this up a notch, and I now maintain my whole desktop
configuration (including my dot files) using
Ansible. To illustrate my GNOME configuration I’ll
be posting snippets from current Ansible configuration. If you’re not familiar
with Ansible don’t worry: it’s just YAML, and can easily be translated into
command line invocations.
Here’s what my GNOME dconf settings look like in Ansible:
- name: update gnome dconf settings
dconf:
key: "{{item.key}}"
value: "{{item.value}}"
loop:
- {key: '/org/gnome/desktop/input-sources/xkb-options', value: "['caps:ctrl_modifier']"}
- {key: '/org/gnome/desktop/interface/clock-show-date', value: 'true'}
- {key: '/org/gnome/desktop/interface/cursor-blink', value: 'false'}
- {key: '/org/gnome/desktop/interface/gtk-theme', value: "'Adwaita-dark'"}
- {key: '/org/gnome/desktop/privacy/old-files-age', value: 'uint32 7'}
- {key: '/org/gnome/desktop/privacy/remove-old-trash-files', value: 'true'}
- {key: '/org/gnome/desktop/privacy/report-technical-problems', value: 'false'}
- {key: '/org/gnome/desktop/search-providers/disable-external', value: 'true'}
- {key: '/org/gnome/desktop/wm/preferences/audible-bell', value: 'false'}
- {key: '/org/gnome/desktop/wm/preferences/focus-mode', value: "'sloppy'"}
- {key: '/org/gnome/settings-daemon/plugins/color/night-light-enabled', value: 'true'}
- {key: '/org/gnome/settings-daemon/plugins/xsettings/antialiasing', value: "'rgba'"}
- {key: '/org/gnome/shell/disable-user-extensions', value: 'true'}
- {key: '/org/gnome/software/allow-updates', value: 'false'}
- {key: '/org/gnome/software/download-updates', value: 'false'}
- {key: '/org/gnome/terminal/legacy/default-show-menubar', value: 'false'}
You can probably guess what most of these options do based on the key name. A
lot of them turn off various options, or change basic features of the window
manager (such as setting “sloppy” focus, a must-have for me).
There’s one I want to call out in particular though: I set
/org/gnome/shell/disable-user-extensions to false, which completely disables
the user extensions feature of GNOME. User extensions are a mechanism that allow
users to write GNOME extensions in Javascript, similar to how Chrome and Firefox
extensions work. In my opinion this idea has dubious merit, and my personal
feeling is the less Javascript in my life the better. I felt somewhat vindicated
about this decision during recent
coverage
of a memory leak in GNOME Shell. The underlying issue was related to the
Javascript garbage collector in GNOME Shell not collecting object references in
a timely manner. I’m not sure that disabling user extensions actually disables
the Javascript engine completely, but it definitely minimizes it to the least
possible scope.
You might wonder how you’re actually supposed to find these options in the first
place—how are you supposed to know what keys are available, and what values
they take? In practice I found most of these in a kind of hacky way. The dconf
command lets you dump the entire database using dconf dump /. So what I did to
find most of these options was some process kind of like the following:
# Get the initial dconf state.
$ dconf dump / >a
# Click around in the GUI, change things in gnome-tweaks, etc.
# Dump the final dconf state.
$ dconf dump / >b
# Manually look at the diff of the two states.
$ diff -u a b
This is simple and effective, and just takes a minute or so of work. The more
robust (but much more labor intensive) way to do this is to look at the GNOME
settings schemas. GNOME packages install files ending in a .gschema.xml
extension, which are XML descriptions of all of the possible options supported
by the application, a description of what the options do, and their default
values. In principle you could discover all of these options by digging around
in /usr/share/glib-2.0/schemas and reading a bunch of XML schema descriptions.
In practice I do this very rarely, really only when if I need to read the
complete documentation for an option.
Removing Unneeded Components
GNOME bundles a lot of components that I find to be really annoying and
unwelcome. These are the biggest offenders:
Tracker is a file daemon that is
supposed to work like Spotlight on macOS. I don’t want this. Between find
and locate I can find all of my files quickly. I don’t need yet another
thing trying to index my files.
Evolution is the standard GNOME
email application, which I don’t want to use. If Evolution was just an email
program I could ignore that would be fine. Unfortunately, Evolution evolved
into a weird half-baked clone of Microsoft Exchange complete with contact
integration, calendar capabilities, and a host of other office productivity
features that are not useful to me. Evolution provides a component called
evolution-data-server that is a daemon that ties these things together.
GNOME Online Accounts
is a feature that lets you connect your GNOME account to things like your
Google or Facebook login. The idea is supposed to be that you can connect
things like your Google calendar and email to the GNOME calendar and
Evolution. It’s a cool idea, but I’m not comfortable with the idea of giving
my online credentials to a bundle of tens or hundreds of thousands of lines
of hand-written C code with manual memory management.
GNOME Software is this weird app
store that I don’t care to use. It always gives me notifications about GNOME
updates that don’t actually correlate with updates in my distro package
manager. The dconf configuration I showed above will actually tell GNOME
Software not to do this, but I don’t really want GNOME Software running at
all.
It turns out that you can remove a lot of these components without breaking
anything. I remove as much of these as possible, as well as a number of programs
that I know I don’t plan on using. The following list is specific to Fedora 28,
but shows what I remove:
# remove unwanted gnome packages
- name: dnf remove gnome bloat
dnf:
name:
- cheese
- evolution
- evolution-ews
- evolution-help
- gfbgraph
- gnome-boxes
- gnome-calendar
- gnome-contacts
- gnome-dictionary
- gnome-documents
- gnome-getting-started-docs
- gnome-initial-setup
- gnome-maps
- gnome-online-miners
- gnome-photos
- gnome-software
- gnome-user-docs
- gnome-user-share
- gnome-video-effects
- gnome-weather
- simple-scan
- totem
- tracker-miners
- yelp
state: absent
Some of these are harmless programs that don’t actually install session daemons,
but are also programs I don’t plan on using. In other cases (e.g.
gnome-software) uninstalling the program actually removes daemons that are run
by default in the session, so removing those components actually causes less
programs to run and waste memory.
They key thing here is to make sure you don’t remove dependencies of any of the
core components, which includes gnome-shell but also some other programs like
nautilus. To double check that I didn’t actually break anything, I also have
the following stanza in my config. This is just a sanity check to make sure that
nothing critical was accidentally removed.
# double-check that we still have the basics
- name: ensure core gnome packages are installed
dnf:
name:
- eog
- evince
- evolution-data-server
- flatpak
- gdm
- gnome-keyring
- gnome-menus
- gnome-screenshot
- gnome-shell
- gnome-terminal
- gnome-tweaks
- nautilus
- redhat-menus
state: present
I’m removing a lot of stuff here, including some things you might want to keep.
So look at the list for yourself and apply caution before removing anything.
After removing these packages there are still a few annoying components like
evolution-data-server and tracker that still remain because they can’t be
completely uninstalled without breaking critical components. But they can still
be disabled in user sessions, as I’ll explain below.
Disabling evolution-data-server, Tracker, and other bloat
GNOME used to have a horribly complicated system that was used to manage start
user session services, and in the past it was very difficult or impossible to
disable certain components. As part of the Wayland effort, GNOME moved to
managing user services using systemd. This is really awesome because it means
you can control GNOME startup services using systemctl just like regular
system services.
On Wayland GNOME services run as part of your systemd user session. To see these
services, use one of the following commands:
# Show running user services.
$ systemctl --user status
# Show all user units and their status.
$ systemctl --user list-unit-files
From these commands I identified various services I want to disable. The trick
to disabling these is to use the systemctl --user mask command, which inhibits
the system installed service units from running. In theory masking services
could cause problems, but at least for the set presented here I haven’t observed
any issues.
Here’s my Ansible code:
- name: mask unwanted gnome services
systemd:
name: "{{item}}"
user: yes
masked: yes
state: stopped
loop:
- evolution-addressbook-factory.service
- evolution-calendar-factory.service
- evolution-source-registry.service
- gvfs-goa-volume-monitor.service
- tracker-store.service
This list lobotomizes evolution-data-server, GNOME Online Accounts, and
Tracker. I also have an Ansible command to ensure that the tracker database is
completely removed from my system:
- name: remove tracker databases
file:
name: ~/.cache/tracker
state: absent
I’ll note that even after removing these services there are still a lot of GNOME
user services running in my session. If you wanted to you could mask a lot more
services. In general the approach I take is to only mask services whose behavior
I understand. Most of the remaining services in my GNOME session are daemons
that use very little memory and zero CPU, so I don’t mind keeping them around.
Firefox/GNOME Integration
I version control my Firefox preferences using Firefox’s obscure
user.js feature, which essentially
lets you put about:config preferences in a Javascript file. I have a fairly
extensive user.js file that is a relaxed version of options suggested by
pyllyukko/user.js, which I might write
about in more detail another time. Two of the options I set in this file are
specific to GNOME, so I’ll cover them here.
The GNOME Extensions site lets you install
GNOME extensions from Firefox. This is done using a native plugin, meaning that
unlike normal extensions it runs in a privileged context that allows it to
interact with GNOME. Since I have user extensions disabled anyway this serves no
purpose, and could possibly do nasty things if a security flaw is found in it
later. Therefore I disable this plugin:
// Disable GNOME browser plugin.
user_pref("plugin.state.libgnome-shell-browser-plugin", 0);
The second option is related to a Firefox bug (present as of Firefox 60.0)
related to GNOME 3.28 when using the Adwaita dark theme. When using this theme
Firefox will render certain widgets/text areas with inverted colors. This is
more than just strange looking: in some cases it can cause things to be
completely unreadable (e.g. a white text color can get applied to text in a
white text area). This can be fixed by forcing Firefox to render widgets use the
Adwaita light theme:
// Force Adwaita light theme.
user_pref("widget.content.gtk-theme-override", "Adwaita:light");
Parting Thoughts
The configuration listed above is the accumulation of a few years of efforts for
me. Things change from release to release, and therefore I revisit things from
time to time. Generally though I’m very happy with the direction GNOME has been
doing, and it’s a much more pleasant experience dealing with certain aspects of
it today than it was a few years ago. I hope the information presented here is
useful, and I hope to see more great things from the GNOME project in the
future.