make your own linux cursor
foreward
did you know it's difficult to find a good guide to making your own linux mouse cursor? like, just one good one, i mean. i had to cross-reference many different threads and articles to make my newest one - and it was still pretty difficult to remember the steps LOL!
so i thought: why not write out my process somewhere people can reference it too? that way, i can link all my sources *and* do things in a straightforward manner! isn't that so niceys.
obviously YMMV. this guide is not made for windows or mac, and was tested solely on my linux mint 22.1 install. if something borks for you, i dunno how to fix it probably LOL. good luck my friend
the guide
step 1: make graphics
mouse cursors come in increments of 16, 32, or 48 pixels square. that means %n wide by %n tall. you can make them larger, certainly, but for most usecases you'll probably be using 32 or 48. (32 is the size on windows, generally.)
i used aseprite to create .png graphics for each state i anticipated myself needing/using regularly. don't feel like you have to do a "full set" unless you're doing this for the public; in any personal project, only go as far as you need to. overscoping brings pain.....
it is nigh impossible to find a real, comprehensive list of all the mouse states you can make. the ones i ended up using are:
all-scroll, cell, default, grab, grabbing, pointer (for hovering links mostly), ns/ew-resize, help, stop, text, wait, zoom in, and zoom out
this does not count the ones i aliased later, but don't worry about it yet.
i created all of my cursor files using aseprite. if you don't have that, you should try libresprite, which is an open-source fork of aseprite. otherwise, use whatever you use for pixel art normally.
step 2: setting up the folder
to create a system-wide cursor theme, you need to create a new folder in ~/usr/share/icons. i titled mine 'forestcursor' for this example.
inside this folder, you want to make a file called 'index.theme'. the inside of the text file should look like this:
[Icon Theme] Name=forestcursor Inherits=Breeze
note that the name needs to match the folder name, and 'inherits' is just what cursors it uses to fill in gaps in your customization, like a minecraft resource pack.
next, make a subfolder named 'cursors', navigate to it, and put all your graphics into it.
step 3: creating cursor files
now you need to create config files for each cursor. each should be titled
size offsetx offsety filename.png
for example:
48 0 0 defaultmouse.png
you can also include animation frame data like so:
48 0 0 link1.png 500 48 0 0 link2.png 500
where '500' is '500ms', so each frame takes 500 milliseconds to display before moving to the next.
right click > open in terminal, so you're in the command prompt while in this folder. check to see if you have xcursorgen installed:
apt search xcursorgen
you should, in theory, because it's included in many distros by default (mine included), but it's good to make sure.
you will now type commands in this format:
xcursorgen cursorname.cursor cursorname
this creates a 'cursor' file named 'cursorname' based on your config file named 'cursorname.cursor'. for example, if i wanted to create one for my default cursor:
xcursorgen defaultcursor.cursor default
this creates a cursor file named 'default' using my defaultcursor config file.
you may find it easier to do this in a batch process rather than line by line. same goes for the next step in this process too. you'll want to generate each cursor like this.
step 4: symlinks
now, these filenames you gave are descriptive, but maybe not the ones the theme identifies as keywords for a cursor state. that's what symlinks are for!
this allows you to create an alias for a file. imagine it like a shortcut to the file. it takes less space than duplicating a file a billion times.
to create a symlink for your cursors, you'll do the following:
ln -s cursorname alias
for example:
ln -s default left_ptr
this takes my cursor file named 'default' and aliases it for 'left-ptr'.
there are a ton of cursor names to cover, and many of them are just ones that you'll want aliases for anyway.
a handy table of most* of the different values (taken from my folder directory of Bibata-Modern-Classic):
| cursor name | notes |
|---|---|
| alias | icon used for symlink drag-n-drop, i think (citation needed) |
| all-scroll | a two-axis cross-section with arrows on the ends |
| arrow | |
| bd_double_arrow | |
| bottom_left_corner | |
| bottom_right_corner | |
| bottom_side | |
| bottom_tee | |
| cell | a crosshair |
| center_ptr | |
| circle | |
| closedhand | a closed hand. |
| default | take a guess |
| color-picker | eyedropper tool |
| col-resize | a horizontal double-ended arrow (like < -- > ); make sure its offset (anchor) is set correctly in the .cursor file before generating |
| context-menu | usually has an 'i' for information next to a smaller cursor; used for context menus of course |
| copy | usually a hand or cursor with a plus sign or two page symbol next to it |
| cross | |
| crossed_circle | |
| crosshair | see 'cell' |
| cross_reverse | |
| default | your best friend |
| diamond_cross | |
| dnd-ask | prompted when hovering over a field that asks for a drag-n-drop element |
| dnd-link | |
| dnd-move | |
| dnd_no_drop | |
| dnd-none | |
| dotbox | |
| dot_box_mask | |
| double_arrow | |
| down-arrow | |
| draft | |
| draft_large | |
| draft_small | |
| draped_box | |
| e-resize | |
| ew-resize | a horizontal double-ended arrow (like < -- > ); make sure its offset (anchor) is set correctly in the .cursor file before generating |
| fd_double_arrow | |
| fleur | |
| forbidden | |
| grab | |
| grabbing | see 'closedhand' |
| hand1 | see 'grab' |
| hand2 | see 'grabbing' |
| h_double_arrow | see 'ew-resize' |
| help | |
| ibeam | |
| icon | |
| left-arrow | |
| left_ptr | i usually just dupe my default icon for this |
| left_ptr_help | |
| left_ptr_watch | |
| left_side | |
| left_tee | |
| link | |
| ll_angle | |
| lr_angle | |
| move | |
| ne-resize | |
| nesw-resize | double-ended-arrow-line angled from north east to south west (forward slash) |
| no-drop | |
| not-allowed | |
| n-resize | |
| ns-resize | vertical line with arrows on the ends, check offset in your cursor file |
| nw-resize | |
| nwse-resize | double-ended-arrow-line angled from north west to south east (back slash) |
| openhand | inverse of closedhand |
| pencil | |
| pirate | and why do we need a pirate cursor |
| plus | |
| pointer | i aliased my hyperlink hover icon for this one |
| pointer-move | |
| pointing_hand | |
| progress | see 'wait' |
| question_arrow | |
| right-arrow | |
| right_ptr | |
| right_side | |
| right_tee | |
| row-resize | see ns-resize |
| sb_down_arrow | |
| sb_h_double_arrow | |
| sb_left_arrow | |
| sb_right_arrow | |
| sb_up_arrow | |
| sb_v_double_arrow | |
| se-resize | |
| size_all | |
| size_bdiag | see 'nwse-resize' |
| size_fdiag | see 'nesw-resize' |
| size-hor | see 'ew-resize' |
| size_hor | see 'size-hor' |
| size-ver | see 'ns-resize' |
| size_ver | see 'size-ver' |
| split_h | |
| split_v | |
| s-resize | |
| sw-resize | |
| target | |
| tcross | |
| text | textbox indicator |
| top_left_arrow | |
| top_left_corner | |
| top_right_corner | |
| top_side | |
| top_tee | |
| ul_angle | |
| up-arrow | |
| ur_angle | |
| v_double_arrow | |
| vertical-text | |
| wait | |
| watch | |
| wayland-cursor | |
| whats_this | owo |
| w-resize | |
| x-cursor | |
| X_cursor | and why is the x capitalized here |
| xterm | vertical text indicator. you heard me. |
| zoom-in | |
| zoom-out |
please be sure to note differences between an underscore and a dash. they are wildly inconsistent, even in groups of the same variable (see: dnd).
* there are a portion of them that have some sort of hashcode name that i dont feel like figuring out or copying so do your own research if you know what they do and want them for some reason
step 4: profit
go to your system settings and open "themes". if it's not already, click 'advanced settings' to get to advanced view.
change 'mouse pointer' to your new cursor. if you don't see it, check to make sure that the name of the folder is the same as the name in index.theme.
and there ya go. now you have your own cursor. good job!!
sources
create your own mouse cursor - kde docs
xcursor theme tutorial - sole on github
there was another guide i used but i cannot find it for the life of me now, sorry!
>> swifty's hq v2.2 > main > blog