Building custom x11 cursors for Linux
Table of Contents
I wanted to use the sort of Starcraft game cursors I enjoyed on my windows machine as a teenager, and this was my first thought of custom cursors in Linux. Note that I use EXWM as a low-level window manager, so these instructions should work for most any Linux system. Spoiler: I got it working, but it took a good deal of time that I hope you might be saved. Here is my story.
1. Acquire the Windows cursor theme
If you already have png of your cursors you can skip this, but I found a windows theme with cursors I want here: http://www.rw-designer.com/cursor-set/starcraft-original
Unpacking, I ended up with a collection of .cur
and .ani
files, which represent static and animated cursors for Windows.
2. Acquire the convert-script and its dependencies
There’s a simple shell script made by paddygord here on git. Grab that file and make sure you have the dependencies of imagemagick
and xcursorgen
(both should be available in your repos).
3. Follow instructions to convert the files with convert.sh
The instructions come with the converter, but basically you put the Windows cursors you acquired in step 1 into your “input” directory of the converter. Note that I had to rename many of the windows files to remove spaces and any other odd characters, which otherwise mess up the naive script in convert.sh.
4. Gather and rename the generated files
Linux cursors have no file extension and so you end up with the output of the script being a folder of folders, where each final folder includes pngs, xcg, ico, and the extensionless x11 cursor file. You need to gather all those latter things into one place. I did it with the following find
invocation from my output dir:
find -type f ! -name "*.*" -exec cp {} ~/tmp/cursors/ \;
This takes all extensionless files (ie files without a .
in their name) and moves them to my /tmp/cursors/
directory.
5. Make your custom cursor theme
You can locate your custom cursor themes in ~/.icons
, where I put mine in ~/.icons/Scraft
. Just stick the files from step 4 in whatever directory there.
6. Associate your theme as the system theme
There are two chief actions here:
I) Inherit your theme in the default (maybe optional?)
# ~/.icons/default/index.theme
[Icon Theme]
Inherits=Scraft
That’s the whole file.
II) Change ~/.config/gtk-3.0/settings.ini
This might be is not optional.
# ~/.config/gtk-3.0/settings.ini
[Settings]
gtk-cursor-theme-name=cursor_theme_name
7. Link & rename files
After completing things so far I had inconsistent results – some cursors appeared in some programs, but others did not. Some programs found most of the cursors but others had no luck. It turns out that different programs seek differerent extensionless-file names. I consulted some of the existing themes on my system for reference (e.g. I found /usr/share/icons/DMZ-Black/cursors/
) and made sure I had soft-links to my theme files to all of the same names necessary in that theme. I included the long gibberish file names that I could see were linked to sensible names; I’m not sure if this last part was necessary, but I wanted to be complete. In the end my cursor directory looked like this:
/home/userme/.icons/Scraft/cursors:
total used in directory 1.2M available 133405516
drwxr-xr-x 1 userme users 1.6K Mar 8 13:30 .
drwxr-xr-x 1 userme users 14 Feb 26 13:51 ..
lrwxrwxrwx 1 userme users 43 Feb 27 09:43 00000000000000020006000e7e9ffc3f -> /home/userme/.icons/Scraft/cursors/progress
lrwxrwxrwx 1 userme users 44 Feb 27 14:04 640fb0e74195791501fd1ed57b41487f -> /home/userme/.icons/Scraft/cursors/progress2
lrwxrwxrwx 1 userme users 39 Feb 27 13:58 9081237383d90e509aa00f00170e968f -> /home/userme/.icons/Scraft/cursors/grab
lrwxrwxrwx 1 userme users 39 Feb 27 13:56 9d800788f1b08800ae810202380a0822 -> /home/userme/.icons/Scraft/cursors/hand
-rw-r--r-- 1 userme users 16K Oct 30 07:55 bd_double_arrow
-rw-r--r-- 1 userme users 16K Oct 30 07:55 bottom_left_corner
lrwxrwxrwx 1 userme users 44 Feb 27 14:11 bottom_right_corner -> /home/userme/.icons/Scraft/cursors/se-resize
-rw-r--r-- 1 userme users 16K Oct 30 07:55 bottom_side
-rw-r--r-- 1 userme users 16K Oct 30 07:55 bottom_tee
-rw-r--r-- 1 userme users 16K Oct 30 07:55 circle
-rw-r--r-- 1 userme users 16K Oct 30 07:55 color-picker
lrwxrwxrwx 1 userme users 44 Feb 27 14:07 col-resize -> /home/userme/.icons/Scraft/cursors/ew-resize
-rw-r--r-- 1 userme users 16K Oct 30 07:55 copy
-rw-r--r-- 1 userme users 16K Oct 30 07:55 cross
lrwxrwxrwx 1 userme users 46 Feb 27 14:01 cross-circle -> /home/userme/.icons/Scraft/cursors/not-allowed
lrwxrwxrwx 1 userme users 46 Feb 27 14:05 crossed_circle -> /home/userme/.icons/Scraft/cursors/not-allowed
-rw-r--r-- 1 userme users 16K Oct 30 07:55 crosshair
lrwxrwxrwx 1 userme users 39 Feb 27 14:08 d9ce0ab605698f320427677b458ad60b -> /home/userme/.icons/Scraft/cursors/help
lrwxrwxrwx 1 userme users 43 Feb 27 14:08 default -> /home/userme/.icons/Scraft/cursors/left_ptr
-rw-r--r-- 1 userme users 16K Oct 30 07:55 dnd-ask
-rw-r--r-- 1 userme users 16K Oct 30 07:55 dnd-copy
-rw-r--r-- 1 userme users 16K Oct 30 07:55 dnd-link
-rw-r--r-- 1 userme users 16K Oct 30 07:55 dnd-move
-rw-r--r-- 1 userme users 16K Oct 30 07:55 dnd-none
-rw-r--r-- 1 userme users 16K Oct 30 07:55 dotbox
-rw-r--r-- 1 userme users 21K Feb 26 14:24 ew-resize
-rw-r--r-- 1 userme users 16K Oct 30 07:55 fd_double_arrow
lrwxrwxrwx 1 userme users 46 Feb 27 14:09 forbidden -> /home/userme/.icons/Scraft/cursors/not-allowed
-rw-r--r-- 1 userme users 21K Feb 26 14:24 grab
-rw-r--r-- 1 userme users 16K Oct 30 07:55 grabbing
-rw-r--r-- 1 userme users 25K Feb 26 14:24 hand
lrwxrwxrwx 1 userme users 39 Feb 27 09:49 hand1 -> /home/userme/.icons/Scraft/cursors/hand
lrwxrwxrwx 1 userme users 39 Feb 27 09:45 hand2 -> /home/userme/.icons/Scraft/cursors/hand
-rw-r--r-- 1 userme users 21K Feb 26 14:24 help
lrwxrwxrwx 1 userme users 39 Feb 27 09:49 ibeam -> /home/userme/.icons/Scraft/cursors/text
-rw-r--r-- 1 userme users 61K Feb 26 13:14 left_ptr
-rw-r--r-- 1 userme users 33K Feb 26 13:14 left_ptr_watch
-rw-r--r-- 1 userme users 16K Oct 30 07:55 left_side
-rw-r--r-- 1 userme users 16K Oct 30 07:55 left_tee
lrwxrwxrwx 1 userme users 44 Feb 27 14:03 link -> /home/userme/.icons/Scraft/cursors/progress2
-rw-r--r-- 1 userme users 16K Oct 30 07:55 ll_angle
-rw-r--r-- 1 userme users 16K Oct 30 07:55 lr_angle
lrwxrwxrwx 1 userme users 39 Feb 27 13:58 move -> /home/userme/.icons/Scraft/cursors/grab
-rw-r--r-- 1 userme users 21K Feb 26 14:24 not-allowed
-rw-r--r-- 1 userme users 21K Feb 26 14:24 ns-resize
-rw-r--r-- 1 userme users 21K Feb 26 14:24 nw-resize
-rw-r--r-- 1 userme users 16K Oct 30 07:55 pencil
-rw-r--r-- 1 userme users 16K Oct 30 07:55 plus
-rw-r--r-- 1 userme users 17K Feb 26 14:24 pointer
-rw-r--r-- 1 userme users 25K Feb 26 14:24 progress
-rw-r--r-- 1 userme users 21K Feb 26 14:24 progress2
lrwxrwxrwx 1 userme users 39 Feb 27 14:06 question_arrow -> /home/userme/.icons/Scraft/cursors/help
-rw-r--r-- 1 userme users 16K Oct 30 07:55 right_ptr
-rw-r--r-- 1 userme users 16K Oct 30 07:55 right_side
-rw-r--r-- 1 userme users 16K Oct 30 07:55 right_tee
-rw-r--r-- 1 userme users 16K Oct 30 07:55 sb_down_arrow
-rw-r--r-- 1 userme users 16K Oct 30 07:55 sb_h_double_arrow
-rw-r--r-- 1 userme users 16K Oct 30 07:55 sb_left_arrow
-rw-r--r-- 1 userme users 16K Oct 30 07:55 sb_right_arrow
-rw-r--r-- 1 userme users 16K Oct 30 07:55 sb_up_arrow
-rw-r--r-- 1 userme users 16K Oct 30 07:55 sb_v_double_arrow
-rw-r--r-- 1 userme users 21K Feb 26 14:24 se-resize
-rw-r--r-- 1 userme users 16K Oct 30 07:55 tcross
-rw-r--r-- 1 userme users 4.1K Mar 8 13:30 text
-rw-r--r-- 1 userme users 4.1K Feb 26 14:24 text_old
-rw-r--r-- 1 userme users 16K Oct 30 07:55 top_left_corner
-rw-r--r-- 1 userme users 16K Oct 30 07:55 top_right_corner
-rw-r--r-- 1 userme users 16K Oct 30 07:55 top_side
-rw-r--r-- 1 userme users 16K Oct 30 07:55 top_tee
-rw-r--r-- 1 userme users 16K Oct 30 07:55 ul_angle
-rw-r--r-- 1 userme users 16K Oct 30 07:55 ur_angle
-rw-r--r-- 1 userme users 33K Feb 26 13:14 wait
lrwxrwxrwx 1 userme users 39 Feb 27 14:12 watch -> /home/userme/.icons/Scraft/cursors/wait
lrwxrwxrwx 1 userme users 39 Feb 27 14:13 whats_this -> /home/userme/.icons/Scraft/cursors/help
-rw-r--r-- 1 userme users 16K Oct 30 07:55 X_cursor
lrwxrwxrwx 1 userme users 39 Feb 27 13:53 xterm -> /home/userme/.icons/Scraft/cursors/text
8. (optional) fix bad cursors
I had one persisting problem: the text-select cursor, though it looked okay, had its hotspots all wrong: when I tried to move a cursor or select text, I really selected a line upward and a character to the left. This was really annoying, so I needed to fix that individual cursor.
First, I found the PNG that was left-over from step 3 above. I then edited it so that the cursor was in the top-left most of its 32x32 frame instead of in the middle. Alternatively, I could have left the image the same and just changed the hotspot info in the xcg file of the next step. I called this file TextSelect2.png
.
Second, make the xcg file what has instructions for the cursor generation, including the reference to my png file:
# text2.xcg
32 1 1 TextSelect2.png
Next, I converted that PNG to a cursor file with a single invocation of what the cursorgen script was doing in bulk.
xcursorgen text2.xcg text2
Finally, replace the original text
icon with this new one. Then, after relogging in to my system, my text cursor worked great.
Resources
- Excellent instructions from Archlinux: https://wiki.archlinux.org/index.php/Cursor_themes
- Cursor Converter shell script: https://github.com/paddygord/cursor-converter
- Additional info and tools for cursors I found later: https://github.com/charakterziffer/cursor-toolbox
- A handy website that will let you see what cursors your browser recognizes: http://www.echoecho.com/csscursors.htm