dotfiles/guides/99_THEMING.md

22 KiB

Theming

This guide will go over setting up Qt and GTK themes on Arch Linux.

My preferred setup uses:

Note

My dotfiles already include most of the necessary theme configuration files, so if you're using them, you can skip a lot of the steps I mention here. This guide assumes a completely un-themed system, to make it easy for anyone to follow.

If there is something that you're expected to do even if you've copied over all of the configuration files from my dotfiles repo, it will be explicitly mentioned in an important markdown block.

Packages

First, we'll install all the required packages:

paru -S --needed \
rose-pine-cursor \
papirus-folders-catppuccin-git \
noto-fonts otf-monaspace \
tokyonight-gtk-theme-git \
kvantum kvantum-qt5 qt5ct qt6ct kvantum-theme-catppuccin-git

Dconf / Gsettings

Dconf is a low-level configuration system that works through D-Bus, serving as backend to GSettings. It's a simple key-based config systems, with the keys existing in an unstructured database.

You can use the dconf command manually to set specific keys to given values, but it's often more a better idea to use gsettings, which provide some abstractions and does consistency checking, but ultimately it will just store the configured values into the dconf database.

Dconf is used by a lot of applications for various things, but a lot of the dconf settings are related to theming and it's crucial that we set them, as some applications will follow these instead of the configuration files.

Important

You will need to perform this step even if you're using my dotfiles. The dconf database is not a part of my dotfiles, so these values won't be set.

# Global configuration that tells applications to prefer dark mode
gsettings set org.gnome.desktop.interface color-scheme prefer-dark

# GTK theme
gsettings set org.gnome.desktop.interface gtk-theme Tokyonight-Dark

# Font settings
gsettings set org.gnome.desktop.interface font-name 'Noto Sans 10'
gsettings set org.gnome.desktop.interface document-font-name 'Noto Sans 10'
gsettings set org.gnome.desktop.interface monospace-font-name 'Source Code Pro 10'

# Cursor settings
gsettings set org.gnome.desktop.interface cursor-theme 'BreezeX-RosePine-Linux'
gsettings set org.gnome.desktop.interface cursor-size 24

Tip

You can find all registered dconf schemas with gsettings list-schemas. To include the keys, you can gsettings list-recursively.

You might want to set some of these according to your preferences.

XSettings

Similarly to dconf/gsettings specification, there's also an XSETTINGS specification, that is used by some Xorg applications (most notably GTK, Java and Wine based apps). It is less useful on Wayland, but since a lot of applications still don't have native wayland support, it may be worth setting up anyways. XWayland applications may still depend on this.

Applications that rely on this specification will ask for the settings from the Xorg server, which itself gets them from a daemon service. On GNOME desktop, this would be gnome-settings-daemon, but anywhere else, you'll want to use xsettingsd, which is a lightweight alternative.

Note

This part of the guide is optional, you don't have to set up xsettings, most applications will work just fine without it.

Important

If you do wish to set up xsettings, you will need to follow these instructions, even if you've populated your system with the configuration files from my dotifiles, as it requires installing a package and activating a systemd service.

First, you will want to install xsettingd package and activate the systemd service, so that applications can ask for this daemon a specific setting:

pacman -S xsettingsd
systemctl --user enable --now xsettingsd

These settings can control various things, but for us, we'll focus on the theming. XSettings are configured simply through a config file in: ~/.config/xsettingsd/xsettingsd.conf.

To configure theming in xsettings, you can put the following settings into your xsettingsd.conf file:

Net/ThemeName "Tokyonight-Dark"
Net/IconThemeName "Papirus-Dark"
Gtk/CursorThemeName "BreezeX-RosePine-Linux"
Net/EnableEventSounds 1
EnableInputFeedbackSounds 0
Xft/Antialias 1
Xft/Hinting 1
Xft/HintStyle "hintslight"
Xft/RGBA "rgb"

GTK

Tip

We'll be setting things up manually, however, if you wish, you can also use nwg-look to configure GTK from a graphical settings application. Do note though that by default, it doesn't support GTK 4 theming (see: this github issue).

nwg-look is inspired by the more popular lxappearance, however, it is made for native wayland. That said, either will work, so you can also try lxappearance if you wish, even on wayland.

GTK 2

For GTK 2, we'll first want to change the location of the gtkrc configuration file, to follow proper XDG base directory specification and avoid it cluttering $HOME. To do this, we'll need to set the following environment variable to be exported by your shell:

export GTK2_RC_FILES="$XDG_CONFIG_HOME/gtk-2.0/gtkrc":"$XDG_CONFIG_HOME/gtk-2.0/gtkrc.mine"

We'll now create ~/.config/gtk-2.0 directory, and a gtkrc file inside of it, with the following content:

gtk-theme-name = "Tokyonight-Dark"
gtk-icon-theme-name = "Papirus-Dark"
gtk-cursor-theme-name = "BreezeX-RosePine-Linux"
gtk-cursor-theme-size = 24
gtk-font-name = "Noto Sans 10"
gtk-button-images=1
gtk-menu-images=1
gtk-enable-event-sounds=0
gtk-enable-input-feedback-sounds=0
gtk-toolbar-icon-size=GTK_ICON_SIZE_LARGE_TOOLBAR
gtk-toolbar-style=GTK_TOOLBAR_BOTH_HORIZ
gtk-xft-antialias=1
gtk-xft-hinting=1
gtk-xft-hintstyle="hintslight"
gtk-xft-rgba="rgb"

GTK 3

For GTK 3, we'll put the following into ~/.config/gtk-3.0/settings.ini:

[Settings]
gtk-application-prefer-dark-theme=true
gtk-theme-name=Tokyonight-Dark
gtk-icon-theme-name=Papirus-Dark
gtk-cursor-theme-name=BreezeX-RosePine-Linux
gtk-cursor-theme-size=24
gtk-font-name=Noto Sans 10
gtk-enable-animations=true
gtk-button-images=1
gtk-menu-images=1
gtk-enable-event-sounds=0
gtk-enable-input-feedback-sounds=0
gtk-error-bell=0
gtk-decoration-layout=appmenu:none
gtk-toolbar-icon-size=GTK_ICON_SIZE_LARGE_TOOLBAR
gtk-toolbar-style=GTK_TOOLBAR_BOTH_HORIZ
gtk-xft-antialias=1
gtk-xft-hinting=1
gtk-xft-hintstyle=hintslight

GTK 4

For GTK 4, we'll put the following into ~/.config/gtk-4.0/settings.ini:

[Settings]
gtk-application-prefer-dark-theme=true
gtk-theme-name=Tokyonight-Dark
gtk-icon-theme-name=Papirus-Dark
gtk-cursor-theme-name=BreezeX-RosePine-Linux
gtk-cursor-theme-size=24
gtk-font-name=Noto Sans 10
gtk-enable-event-sounds=0
gtk-enable-input-feedback-sounds=0
gtk-error-bell=0
gtk-decoration-layout=appmenu:none
gtk-xft-antialias=1
gtk-xft-hinting=1
gtk-xft-hintstyle=hintslight

For libadwaita based GTK 4 applications, you will need to force a GTK theme with an environment variable, so you will also want to export the following:

export GTK_THEME="Tokyonight-Dark"

Warning

This will only work if your theme has GTK 4 support.

Tip

As an alternative to exporting the GTK_THEME env var like this, you can also install libadwaita-without-adwaita-git AUR package, which contains a patch to prevent GTK from overriding the system theme.

Another option would be to import the theme in gtk.css: ~/.config/gtk-4.0/gtk.css:

/**
* GTK 4 reads the theme configured by gtk-theme-name, but ignores it.
* It does however respect user CSS, so import the theme from here.
**/
@import url("file:///usr/share/themes/Tokyonight-Dark/gtk-4.0/gtk.css");

Make GTK follow XDG portal settings

Certain things, such as dialogs or file-pickers can be controlled via XDG desktop portals, however, by default, GTK apps will not follow these settings. To force them into doing so, you can export an environment variable:

export GTK_USE_PORTAL=1

Qt

This section goes over configuring QT styles for qt 5 and qt 6.

Kvantum

I like using kvantum to configure QT themes. Kvantum is an SVG style customizer/engine, for which there's a bunch of plugins. It then turns these plugins / kvantum themes into full QT themes. For theme creators, it simplifies making a full QT theme.

Note

Kvantum will only be useful for you if you actually want to use a kvantum theme. If you wish to use a full QT theme that doesn't need kvantum, you can skip this and instead achieve the same with qtct. (I'll say a bit more about qtct in icon theme section.)

Kvantum works as a Qt style instead of a Qt platform theme. To set kvantum for all Qt applications, you can export the following env variable:

export QT_STYLE_OVERRIDE=kvantum

Note

For backwards compatibility, in addition to the kvantum package, you will also need kvantum-qt5 (kvantum works with qt6). If you followed the initial install instructions, you will have both installed already.

Theme

We will now want to tell kvantum which theme to use. To do this, we will need to create a settings file for Kvantum in ~/.config/Kvantum/kvantum.kvconfig, with the following content:

[General]
theme=catppuccin-mocha-blue

Tip

The system-wide kvantum themes are located in /usr/share/Kvantum. The theme variable has to match the directory name of one of these themes.

If you wish to use a custom theme that isn't available as a package, you can also add it as a user theme directly into ~/.config/Kvantum/.

Icon theme & qtct

As a theme qt engine, kvantum can't handle icons. For those, we will use qtct platform theme.

Note

You will need to install qt5ct & qt6ct packages. These will also be installed already if you followed the initial install command though.

Now we'll set the QT platform theme through an environment variable:

export QT_QPA_PLATFORMTHEME="qt5ct"  # keep this value even for qt6ct

Finally, we can add a qtct configuration to use our preferred icon theme:

~/.config/qt5ct/qt5ct.conf:

[Appearance]
icon_theme=Papirus-Dark

Same thing for ~/.config/qt6ct/qt6ct.conf.

Note

qtct is a platform theme and it can do a lot more than just set the icon theme, however, we chose kvantum to serve as our style, so we don't need anything else from qtct.

If you wish to instead use qtct for picking the qt style, unset the QT_STYLE_OVERRIDE variable and pick your theme in both qt5ct & qt6ct applications. This will modify the qt5ct.conf and the qt 6 variant.

Additional things

There are some extra things that you'll probably want to set. To do so, we will yet again use more environment variables. Specifically:

# Enables automatic scaling, based on the monitor's pixel density.
export QT_AUTO_SCREEN_SCALE_FACTOR="1"
# Run QT applications using the wayland plugin, falling back to xcb (X11) plugin
export QT_QPA_PLATFORM="wayland;xcb"
# Disable client side decorations
export QT_WAYLAND_DISABLE_WINDOWDECORATION="1"

Cursor

XCursor

XCursor is the default cursor format for cursor themes. Even though the name might imply that it's connected to X11, it will work just fine on wayland too.

To select a cursor theme to be used, you'll want to export the following environment variables:

export XCURSOR_THEME="BreezeX-RosePine-Linux"
export XCURSOR_SIZE="24"

Additionally, you might want to also modify/set XCURSOR_PATH, to make sure that it includes ~/.local/share/icons, as otherwise, xcursor will not look here for cursor themes by default on some DEs/WMs.

export XCURSOR_PATH=$XCURSOR_PATH${XCURSOR_PATH:+:}~/.local/share/icons

Default cursor config

The cursor theme name "default" is used by an application if it cannot pick up on a configuration. The default cursor theme can live in: ~/.local/share/icons/default or /usr/share/icons/default.

To set the default cursor for your user, create a ~/.local/share/icons/default/index.theme file with the following:

[Icon Theme]
Name=Default
Comment=Default Cursor Theme
Inherits=BreezeX-RosePine-Linux

Tip

Alternatively, we could also symlink the cursor theme into the default directory, like so:

ln -s /usr/share/icons/BreezeX-RosePine-Linux/ ~/.local/share/icons/default

That said, I prefer using Inherits here, as it allows me to easily store the default cursor config in my dotfiles.

Cursor config for GTK

You may have noticed earlier that we've already touched on specifying the cursor configuration for GTK in the gtkrc/gtk settings, this is done via the gtk-cursor-theme-name and gtk-cursor-theme-size setting options. Because of that, there's no need to do anything extra to get GTK apps to use the correct cursor theme.

Cursor config for Qt

There is no Qt configuration for cursors. Qt programs may pick up a cursor theme from the desktop environment (server-side cursors), X resources, or lastly the "default" cursor theme.

Hyprcursor

hyprcursor is a new and efficient a cursor format, that allow for SVG based cursors, resulting in a much better scaling experience and more space-efficient themes.

Hyprcursor is supported out of the box by Hyprland, so if you're using Hyprland, you can benefit from it. That said, this part is entirely optional and you can just stick with xcursor if you wish.

If you do want to use hyprcursor, you will want to install hyprcursor version of the rose-pine-cursor theme. You can simply git clone this repository right into ~/.local/share/icons (sadly, there isn't an AUR package available at this time):

cd ~/.local/share/icons
git clone https://github.com/ndom91/rose-pine-cursor-hyprcursor

Finally, you will want to set the following environment variables:

export HYPRCURSOR_THEME="rose-pine-hyprcursor"
export HYPRCURSOR_SIZE="24"

Alternatively, you can also set these variables right from your hyprland config:

env = HYPRCURSOR_THEME,rose-pine-hyprcursor
env = HYPRCURSOR_SIZE,24

Warning

Make sure to keep the existing xcursor environment variables and themes, as although many apps do support server-side cursors (e.g. Qt, Chromium, Electron, ...), some still don't (looking at you GTK, but also some other, less common things). These applications will then fall back to XCursor (unless they have built-in hyprcursor support, which is rare).

I would therefore also recommend leaving the default theme point to the XCursor theme, not to a hyprcursor theme.

Fonts

Some applications use gsettings/dconf to figure out what font to use. We've already configured these settings, so those applications should pick up which font to use correctly.

Other applications will use GTK config to figure out the default fonts. We've configured this earlier too. (Note that GTK config doesn't support specifying a monospace font).

The rest of the applications will use generic font family names ("standard" fonts), as defined through fontconfig.

Applications also often provide configuration files where you can define which font you wish to be using, so sometimes, you will need to set the font on a per-application basis. We will not cover this, as each application is different.

Installing fonts

In the installation instructions above, I did specify the 2 default font packages that I wanted to use for my system. That said, I did not specify an emoji font there and there are many fonts that are just useful to have on the system, for things like text editing. The command below will install most of the fonts that you might need:

paru -S --needed \
  libxft xorg-font-util \
  ttf-joypixels otf-jost lexend-fonts-git ttf-sarasa-gothic \
  ttf-roboto ttf-work-sans ttf-comic-neue \
  gnu-free-fonts tex-gyre-fonts ttf-liberation otf-unifont \
  inter-font ttf-lato ttf-dejavu noto-fonts noto-fonts-cjk \
  noto-fonts-emoji ttf-material-design-icons-git \
  ttf-font-awesome ttf-twemoji otf-openmoji \
  adobe-source-code-pro-fonts adobe-source-han-mono-otc-fonts \
  adobe-source-sans-fonts ttf-jetbrains-mono otf-monaspace \
  ttf-ms-fonts

Nerd fonts

I have intentionally left out the nerd-fonts package from the above command, as it is fairly large (about 8 gigabytes). If you wish, you can install it, as it does contain some pretty useful fonts, however, if this package is too big for you, you can instead install the fonts individually, as arch does ship all nerd fonts in the package manager individually.

To install all nerd fonts, you can simply:

paru -S --needed nerd-fonts

If you instead wish to only install specific nerd fonts, you can use the following command. Note that you may want to add more fonts from nerd-fonts.

paru -S --needed \
  ttf-firacode-nerd otf-firamono-nerd ttf-iosevka-nerd ttf-nerd-fonts-symbols \
  ttf-hack-nerd ttf-heavydata-nerd ttf-gohu-nerd

Important

If you wish to use all of nerd-fonts, you will need to run the above command even after going through the install scripts from my dotfiles, as they only install specific nerd fonts (the above).

Setting standard fonts

These standard fonts are:

  • sans-serif: Standard font for regular text (articles, menus, ...)
  • serif: Like sans-serif, but pure sans fonts shouldn't have the decorative lines or tapers (also known as "tails" or "feet"). Note that these should fall back to sans-serif if unset.
  • monospace: Standard font for fixed-width fonts (text editors, calculators, ...)
  • emoji: Standard font for emoji glyphs

It is possible to register multiple fonts for the standard font, ordered by priorities. That way, if the first font isn't found, or it doesn't contain the given glyph, the search will fall back to the next font in line.

To set a standard font, you will need to create a fontconfig configuration file. You can do this on a per-user basis, in ~/.config/fontconfig/fonts.conf (or ~/.config/fontconfig/conf.d/) or system-wide in /etc/fonts/local.conf (don't modify /etc/fonts/fonts.conf nor the files in /etc/fonts/conf.d, these are managed by the package manager and could get overwritten). Note that the user font settings will take priority if there are overlapping settings.

I prefer using the system-wide settings (/etc/fonts/local.conf):

<?xml version='1.0'?>
<!DOCTYPE fontconfig SYSTEM "urn:fontconfig:fonts.dtd">
<fontconfig>
  <alias binding="same">
    <family>sans-serif</family>
    <prefer>
      <family>Noto Sans</family>
      <family>Jost</family>
      <family>Lexend</family>
      <family>Iosevka Nerd Font</family>
      <family>Symbols Nerd Font</family>
      <family>Noto Color Emoji</family>
    </prefer>
  </alias>

  <alias binding="same">
    <family>serif</family>
    <prefer>
      <family>Noto Serif</family>
      <family>Iosevka Nerd Font</family>
      <family>Symbols Nerd Font</family>
      <family>Noto Color Emoji</family>
    </prefer>
  </alias>

  <alias binding="same">
    <family>monospace</family>
    <prefer>
      <family>Monaspace Krypton</family>
      <family>Source Code Pro Medium</family>
      <family>Source Han Mono</family>
      <family>Iosevka Nerd Font</family>
      <family>Symbols Nerd Font</family>
      <family>Noto Color Emoji</family>
    </prefer>
  </alias>

  <alias binding="same">
    <family>emoji</family>
    <prefer>
      <family>Noto Color Emoji</family>
      <family>Iosevka Nerd Font</family>
      <family>Symbols Nerd Font</family>
      <family>Noto Color Emoji</family>
    </prefer>
  </alias>
</fontconfig>

You will now need to rebuild the font cache with:

fc-cache -vf

Disable Caskaydia Cove Nerd Font

For some reason, having the Caskaydia font installed was causing some issues with other fonts for me. Caskaydia comes from nerd-fonts, so if you installed them, you might want to follow along with this too, if you're also facing issues. I'm honestly not sue why that is, however, all that's needed to solve it is disabling this font entirely. To do so, add the following to your fontconfig config:

<?xml version="1.0"?>
<!DOCTYPE fontconfig SYSTEM "urn:fontconfig:fonts.dtd">

<fontconfig>
  <selectfont>
    <rejectfont>
      <glob>/usr/share/fonts/nerd-fonts-git/TTF/Caskaydia*</glob>
    </rejectfont>
  </selectfont>
</fontconfig>

Font Manager

To preview the installed fonts, I like using font-manager:

paru -S --needed font-manager

Sources