Custom Cursors and Pointer Sizes in GNOME Shell

This article explores how GNOME Shell manages cursor themes and pointer sizing across the Linux desktop environment. It covers the directory hierarchy for cursor installations, the GSettings schemas used by Mutter and GTK, how GNOME Shell synchronizes pointer adjustments across legacy X11 and modern Wayland sessions, and the technical mechanics behind cursor scaling.

Cursor Theme Directory Structure and Discovery

GNOME Shell relies on standard freedesktop.org icon theme specifications to discover custom cursors. When searching for cursor themes, the compositor and its underlying toolkits look inside specific file system directories in a defined hierarchy:

  • Local user installations: ~/.local/share/icons/ and legacy ~/.icons/
  • System-wide installations: /usr/share/icons/ and /usr/local/share/icons/

For a cursor package to be recognized, it must contain a valid layout. The root of the theme folder requires an index.theme file containing the theme metadata (such as the name and inherited themes) and a dedicated cursors/ subdirectory housing the binary cursor images.

Applying Themes via GSettings

GNOME Shell does not directly manage theme settings via static configuration files; instead, it uses the dconf configuration system. The cursor theme selection is tracked by the org.gnome.desktop.interface schema.

To view the active cursor theme:

gsettings get org.gnome.desktop.interface cursor-theme

To assign a new cursor theme manually:

gsettings set org.gnome.desktop.interface cursor-theme 'Custom-Theme-Name'

Utility applications like GNOME Tweaks modify this same key under the hood. When this value updates, the GNOME Settings Daemon (gsd-xsettings) broadcast the change to active graphical applications.

Adjusting Pointer Size

GNOME Shell provides built-in accessibility options to scale the cursor size. In the GNOME Control Center, users can select predefined sizes via Accessibility > Seeing > Cursor Size.

For arbitrary sizes, GNOME uses the integer-based cursor-size key in the same interface schema. The standard default is 24 pixels.

To read the current pointer size:

gsettings get org.gnome.desktop.interface cursor-size

To set a custom size (such as 32, 48, or 64 pixels):

gsettings set org.gnome.desktop.interface cursor-size 32

When this value is updated, the window manager and applications query the active theme for matching cursor bitmaps. If a theme does not supply pre-rendered assets at the requested pixel dimension, the rendering engine scales the closest available bitmap, which can occasionally lead to visual artifacts or blurriness if vector formats are not supported by the asset pack.

Wayland vs. X11 Pointer Management

The implementation of cursor rendering differs significantly depending on the display server protocol in use.

Wayland Sessions

In a Wayland session, Mutter (GNOME's compositor) handles the cursor display directly on the hardware plane or software composition layer.

  • Over the desktop shell, top bar, and compositor surfaces, Mutter renders the cursor based on the org.gnome.desktop.interface settings.
  • Inside client windows, Wayland clients are technically responsible for drawing their own pointer surfaces using the wl_pointer interface.
  • To maintain visual consistency, GTK and Qt runtimes automatically pull the cursor theme and size configurations from GSettings, ensuring the pointer matches when moving between the desktop shell and individual application windows.

X11 Sessions

In legacy X11 sessions, the X server itself maintains cursor state. GNOME Shell sets the root cursor via xsetroot and updates the XCURSOR_THEME and XCURSOR_SIZE environment variables through the session startup scripts.

Additionally, the GNOME Settings Daemon mirrors the settings to the ~/.Xresources database or XSettings registry, allowing non-GTK toolkits (like Qt or legacy Athena widgets) to honor the size and theme configurations without desynchronizing from GNOME Shell's native chrome.

Display Scaling and HiDPI Interactions

When system fractional scaling or integer scaling (200%) is enabled in GNOME Display Settings, cursor scaling behavior adapts:

  • Under Wayland, Mutter automatically multiplies the base cursor-size by the integer scale factor of the monitor the pointer currently occupies. When crossing between monitors of differing pixel densities, Mutter dynamically swaps the cursor buffer size to match the target display's scale factor.
  • Under X11, global scaling scales the base cursor globally, which can sometimes lead to oversized pointers on secondary monitors with lower DPI.