I’ve noticed with SDL2 that color cursors seem to be incorrectly offset on OS X. Below is a test program with an 8x8 cursor sprite that reproduces the bug. Expected behavior is that the top left corner of the cursor indicates the mouse coordinates precisely, and when it passes the edge of the window, a leave/enter event occurs. On Ubuntu 14.04 for example, that is exactly what happens.
However, on OS X there is about a 3 pixel offset both rightward and downward, so that the tip of the rendered cursor doesn’t match the mouse coordinates. This is independent of the cursor texture or its size as far as I can tell. I spent some time debugging, but couldn’t discover where the offset is introduced. Using a hotspot of X=3, Y=3 when creating the cursor basically covers up the bug, of course I’d rather not rely on that…
The interesting thing is that we previously used native Cocoa API directly to create color cursors, with nearly the same calls as SDL2, and our texture loading is unchanged, but while the cursors worked before, they have this offset with SDL2.
Tested with latest SDL2 Hg snapshot on OS X Yosemite (though I’ve confirmed as far back as Lion).
Code:
// Test for color cursor behavior on OS X
#include “SDL.h”
#include <stdio.h>
// 8x8 red sprite for test cursor
unsigned int pixels[] = {
0xFFFF0000, 0xFFFF0000, 0xFFFF0000, 0xFFFF0000,
0xFFFF0000, 0xFFFF0000, 0xFFFF0000, 0xFFFF0000,
0xFFFF0000, 0xFFFF0000, 0xFFFF0000, 0xFFFF0000,
0xFFFF0000, 0xFFFF0000, 0xFFFF0000, 0xFFFF0000,
0xFFFF0000, 0xFFFF0000, 0xFFFF0000, 0xFFFF0000,
0xFFFF0000, 0xFFFF0000, 0xFFFF0000, 0xFFFF0000,
0xFFFF0000, 0xFFFF0000, 0xFFFF0000, 0xFFFF0000,
0xFFFF0000, 0xFFFF0000, 0xFFFF0000, 0xFFFF0000,
0xFFFF0000, 0xFFFF0000, 0xFFFF0000, 0xFFFF0000,
0xFFFF0000, 0xFFFF0000, 0xFFFF0000, 0xFFFF0000,
0xFFFF0000, 0xFFFF0000, 0xFFFF0000, 0xFFFF0000,
0xFFFF0000, 0xFFFF0000, 0xFFFF0000, 0xFFFF0000,
0xFFFF0000, 0xFFFF0000, 0xFFFF0000, 0xFFFF0000,
0xFFFF0000, 0xFFFF0000, 0xFFFF0000, 0xFFFF0000,
0xFFFF0000, 0xFFFF0000, 0xFFFF0000, 0xFFFF0000,
0xFFFF0000, 0xFFFF0000, 0xFFFF0000, 0xFFFF0000
};
int main(int argc, char* argv[]) {
SDL_Window *window;
SDL_Init(SDL_INIT_VIDEO);
window = SDL_CreateWindow(
"SDL2 Color Cursor Test",
SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
150,
100,
SDL_WINDOW_OPENGL
);
if (window == NULL) {
printf("Could not create window: %s\n", SDL_GetError());
return 1;
}
SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
if (renderer == NULL) {
printf("Could not create renderer: %s\n", SDL_GetError());
return 1;
}
SDL_Surface* surface = SDL_CreateRGBSurfaceFrom(pixels, 8, 8, 32, 32, 0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000);
if (surface == NULL) {
printf("Could not create surface: %s\n", SDL_GetError());
return 1;
}
// Hotspot of (3,3) here "fixes" the bug on OS X
SDL_Cursor* cursor = SDL_CreateColorCursor(surface, 0, 0);
if (cursor == NULL) {
printf("Could not create cursor: %s\n", SDL_GetError());
return 1;
}
SDL_SetCursor(cursor);
while (1) {
SDL_Event event;
if (SDL_PollEvent(&event)) {
if (event.type == SDL_QUIT)
break;
else if (event.type == SDL_WINDOWEVENT) {
switch (event.window.event) {
case SDL_WINDOWEVENT_ENTER:
printf("Mouse entered window %d\n",
event.window.windowID);
break;
case SDL_WINDOWEVENT_LEAVE:
printf("Mouse left window %d\n", event.window.windowID);
break;
default:
break;
}
}
}
SDL_RenderClear(renderer);
SDL_RenderPresent(renderer);
}
SDL_FreeCursor(cursor);
SDL_FreeSurface(surface);
SDL_DestroyWindow(window);
SDL_DestroyRenderer(renderer);
SDL_Quit();
return 0;
}