Skip to content

Fix cursor icon search paths to follow XDG Icon Theme Specification#4731

Draft
Copilot wants to merge 4 commits intomainfrom
copilot/fix-cursor-theming-issues
Draft

Fix cursor icon search paths to follow XDG Icon Theme Specification#4731
Copilot wants to merge 4 commits intomainfrom
copilot/fix-cursor-theming-issues

Conversation

Copy link
Contributor

Copilot AI commented Feb 27, 2026

Mir's cursor icon search path (XCURSORPATH) was a hardcoded legacy list that omitted $XDG_DATA_DIRS/icons — meaning /usr/local/share/icons and any custom data dirs were never searched.

Per the XDG Icon Theme Specification, apps should look in $HOME/.icons, $XDG_DATA_DIRS/icons, and /usr/share/pixmaps (in that order).

What's new?

  • Added _XcursorBuildXdgPath() in src/miral/xcursor.c that dynamically constructs the cursor search path when XCURSOR_PATH is not set
  • New default search order (no duplicate entries):
    1. $HOME/.icons (backwards compat)
    2. $XDG_DATA_DIRS/icons — expanded per-entry; defaults to /usr/local/share/icons:/usr/share/icons when XDG_DATA_DIRS is unset
    3. /usr/share/pixmaps
    4. Truly legacy-only fallback entries (~/.cursors, /usr/share/cursors/xorg-x11, ICONDIR) via new XCURSORLEGACYPATH macro — entries already covered by the XDG prefix are excluded to avoid redundant filesystem searches
  • XCURSOR_PATH env var override continues to take priority (unchanged behaviour)
  • Full XCURSORPATH macro retained as last-resort fallback when dynamic path allocation fails
  • Path is built once per process lifetime; snprintf with remaining-buffer tracking used throughout
  • Variables declared at the point of initialization throughout _XcursorBuildXdgPath()

How to test

Set a cursor theme via miral::CursorTheme and verify cursors load from paths under $XDG_DATA_DIRS/icons (e.g. /usr/local/share/icons/<theme>/cursors/). Setting a custom XDG_DATA_DIRS should cause that directory's icons subtree to be searched.

Checklist

  • Tests added and pass
  • Adequate documentation added
  • (optional) Added Screenshots or videos
Original prompt

This section details on the original issue you should resolve

<issue_title>Cursor theming may need a refresh</issue_title>
<issue_description>Mir looks for icons in the wrong places.

By default it uses some internal cursor images

When miral::CursorTheme is used then it searches XCURSOR_PATH or ~/.icons:/usr/share/icons:/usr/share/pixmaps:~/.cursors:/usr/share/cursors/xorg-x11:/usr/X11R6/lib/X11/icons, which is not quite right now:

Icons and themes are looked for in a set of directories. By default, apps should look in $HOME/.icons (for backwards compatibility), in $XDG_DATA_DIRS/icons and in /usr/share/pixmaps (in that order). https://specifications.freedesktop.org/icon-theme-spec/latest/

We likely want to correct where we search and use that as a default. (The current default becoming a fallback if there are no cursors on the system)</issue_description>

Comments on the Issue (you are @copilot in this section)


💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

Copilot AI changed the title [WIP] Fix cursor theming by updating search paths Fix cursor icon search paths to follow XDG Icon Theme Specification Feb 27, 2026
@AlanGriffiths
Copy link
Contributor

@copilot it is poor style to declare variables before they can be initialized

Copy link
Contributor Author

Copilot AI commented Mar 2, 2026

@copilot it is poor style to declare variables before they can be initialized

Fixed in bc8d61c — variables are now declared at the point where they can be initialized, using for-init declarations for the loop variables and int const written declared inside each block.

@github-actions
Copy link

github-actions bot commented Mar 2, 2026

TICS Quality Gate

✔️ Passed

mir

Coding Standards: ✔️ Passed

✔️ Condition “No new Coding Standard Violations for level 1, 2, 3 with respect to Previous analysis” passed.

See the results in the TICS Viewer

The following files have been checked for this project
  • src/miral/xcursor.c

TICS / TICS / Run TICS analysis

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes cursor icon search paths in src/miral/xcursor.c to comply with the XDG Icon Theme Specification. Previously, Mir used a hardcoded XCURSORPATH that omitted $XDG_DATA_DIRS/icons. The fix introduces a dynamic path builder that constructs the correct XDG-spec-compliant search order at runtime, falling back to the legacy path.

Changes:

  • Added _XcursorBuildXdgPath() that dynamically constructs the cursor search path per the XDG Icon Theme spec: $HOME/.icons, $XDG_DATA_DIRS/icons (expanded), /usr/share/pixmaps, then legacy XCURSORPATH entries
  • XcursorLibraryPath() updated to call _XcursorBuildXdgPath() when XCURSOR_PATH env var is not set, with XCURSORPATH macro as last resort fallback

}

{
int const written = snprintf (p_out, remaining, "/usr/share/pixmaps:%s", XCURSORPATH);
Copy link

Copilot AI Mar 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The generated path contains duplicate entries. /usr/share/pixmaps is explicitly added at line 667 (before XCURSORPATH), but XCURSORPATH itself already contains /usr/share/pixmaps. Similarly, when using the default XDG_DATA_DIRS, /usr/share/icons appears both in the XDG expansion and in XCURSORPATH. Additionally, $HOME/.icons (expanded on line 648) appears again as ~/.icons in the legacy XCURSORPATH fallback (which gets tilde-expanded at runtime in _XcursorBuildThemeDir).

These duplicates cause each directory to be searched twice, resulting in redundant filesystem operations. To avoid this, /usr/share/pixmaps could be stripped from XCURSORPATH before appending, or the snprintf format on line 667 could use a trimmed version of the legacy path that excludes entries already covered by the XDG prefix entries.

Copilot uses AI. Check for mistakes.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot apply changes based on this feedback

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 790607b. Introduced XCURSORLEGACYPATH containing only the entries not already covered by the XDG prefix (~/.cursors:/usr/share/cursors/xorg-x11:ICONDIR) and used that in _XcursorBuildXdgPath instead of the full XCURSORPATH. The generated path now has no duplicates — ~/.icons, $XDG_DATA_DIRS/icons entries, and /usr/share/pixmaps each appear exactly once. The full XCURSORPATH is retained as the last-resort fallback when malloc fails.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Cursor theming may need a refresh

3 participants