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