SDL: Custom Mouse Cursor Appearance

Can I change the mouse cursor's appearance (e.g., to a crosshair)?

Yes, SDL provides functions to hide the default system cursor and display your own custom cursor graphics.

Key Functions

  1. SDL_CreateCursor(): Creates a cursor using monochrome (2-color) bitmap data. This is an older style but universally supported. You provide pointers to the pixel data and a mask, along with the cursor's dimensions and hot-spot coordinates (the precise point of the cursor that corresponds to the mouse position).
  2. SDL_CreateColorCursor(): Creates a cursor from an SDL_Surface. This is more flexible as it allows full-color cursors with alpha transparency. You provide the surface containing the cursor image and the hot-spot coordinates. The surface should typically be small (e.g., 32x32 pixels).
  3. SDL_SetCursor(): Sets the currently active cursor for the application. You pass the SDL_Cursor* returned by one of the creation functions. To revert to the default system cursor, you can call SDL_SetCursor(SDL_GetDefaultCursor());.
  4. SDL_ShowCursor(): Toggles the visibility of the cursor. Use SDL_ShowCursor(SDL_DISABLE) to hide it and SDL_ShowCursor(SDL_ENABLE) to show it. You usually hide the system cursor before setting your custom one if you don't want both potentially visible.
  5. SDL_FreeCursor(): Frees the memory associated with an SDL_Cursor that you created. You should call this when you no longer need the custom cursor.
  6. SDL_GetDefaultCursor(): Returns a pointer to the default system cursor.

Simple Example (using SDL_CreateColorCursor)

This example assumes you have an SDL_Surface* cursorSurface loaded with your desired cursor image (e.g., a crosshair loaded from a BMP or PNG file using SDL_LoadBMP or the SDL_image library).

#include <SDL.h>
// Assume SDL_image is linked for PNG/other formats
// #include <SDL_image.h>

// Function to load a surface (implement elsewhere)
SDL_Surface* LoadSurface(const char* path);

int main(int argc, char** argv) {
  // ... SDL Initialization ...
  SDL_Window* window = SDL_CreateWindow(/*...*/);
  // ... Error handling ...

  SDL_Surface* cursorSurface = LoadSurface("crosshair.png"); // Load your image
  if (!cursorSurface) {
    // Handle error: image not loaded
    return 1;
  }

  // Define hotspot (e.g., center of a 32x32 image)
  int hot_x = cursorSurface->w / 2;
  int hot_y = cursorSurface->h / 2;

  SDL_Cursor* customCursor = SDL_CreateColorCursor( 
    cursorSurface, hot_x, hot_y                   
  );                                              

  if (!customCursor) {
    std::cerr << "Failed to create color cursor: "
              << SDL_GetError() << '\\n';
    SDL_FreeSurface(cursorSurface);
    // ... Cleanup ...
    return 1;
  }

  SDL_SetCursor(customCursor); 

  // --- Main Loop ---
  SDL_Event e;
  bool quit = false;
  while (!quit) {
    while (SDL_PollEvent(&e)) {
      if (e.type == SDL_QUIT) quit = true;
      // ... Handle other events ...
    }
    // ... Update and Render ...
  }
  // --- End Loop ---

  SDL_FreeCursor(customCursor);  Release the cursor resource
  SDL_FreeSurface(cursorSurface); // Release the surface memory
  // ... Other cleanup (Destroy Window, SDL_Quit) ...
  return 0;
}

Important Considerations

  • Surface Format: Ensure the SDL_Surface used for SDL_CreateColorCursor has an appropriate format, often one with an alpha channel for transparency (like SDL_PIXELFORMAT_RGBA32).
  • Performance: Creating cursors can take some time. It's best practice to create your custom cursors once during initialization rather than repeatedly inside the main loop.
  • Resource Management: Remember to free the cursor using SDL_FreeCursor and the surface using SDL_FreeSurface when they are no longer needed to avoid memory leaks.

We cover surface loading, manipulation, and more advanced cursor handling, including system cursors - SDL_CreateSystemCursor() - in greater detail later in the course.

Mouse Input Basics

Discover how to process mouse input, including position tracking and button presses

Questions & Answers

Answers are generated by AI models and may not have been reviewed. Be mindful when running any code on your device.

SDL Coordinate System: Why Y-Down?
Why does SDL use a y-down coordinate system instead of y-up?
SDL: Get Mouse Screen Coordinates
Can I get mouse coordinates relative to the screen instead of the window?
SDL_PollEvent() vs SDL_WaitEvent()
What's the difference between SDL_PollEvent() and SDL_WaitEvent()?
SDL Event Timestamp Field
What does the timestamp field in the event structures mean?
SDL Event which Field
What does the which field in the event structures refer to (e.g., multiple mice)?
SDL Double Click Timing Customization
How does SDL determine the time window for registering a double click? Can I customize this timing?
Retrieve Mouse Position
How do I retrieve the current position of the mouse cursor in SDL?
SDL Mouse Motion Events
What is the difference between SDL_MOUSEMOTION and SDL_MouseMotionEvent?
Detect Double Clicks in SDL
How can I detect double clicks using SDL?
SDL_MouseButtonEvent Structure
What is the SDL_MouseButtonEvent structure used for?
Calculate Mouse Position
How can I calculate the distance of the mouse cursor from the edges of the window?
Or Ask your Own Question
Get an immediate answer to your specific question using our AI assistant