mirror of
https://github.com/libsdl-org/SDL.git
synced 2026-02-16 00:24:04 +00:00
Added fallback support for animated cursors
This commit is contained in:
@@ -1477,6 +1477,8 @@ void SDL_PumpEventMaintenance(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
SDL_UpdateCursorAnimation();
|
||||
|
||||
SDL_UpdateTrays();
|
||||
|
||||
SDL_SendPendingSignalEvents(); // in case we had a signal handler fire, etc.
|
||||
|
||||
@@ -1552,6 +1552,79 @@ SDL_Cursor *SDL_CreateCursor(const Uint8 *data, const Uint8 *mask, int w, int h,
|
||||
return cursor;
|
||||
}
|
||||
|
||||
static void SDL_DestroyCursorAnimation(SDL_CursorAnimation *animation)
|
||||
{
|
||||
if (!animation) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < animation->num_frames; ++i) {
|
||||
SDL_DestroyCursor(animation->frames[i]);
|
||||
}
|
||||
SDL_free(animation->frames);
|
||||
SDL_free(animation->durations);
|
||||
SDL_free(animation);
|
||||
}
|
||||
|
||||
static SDL_CursorAnimation *SDL_CreateCursorAnimation(SDL_CursorFrameInfo *frames, int frame_count, int hot_x, int hot_y)
|
||||
{
|
||||
SDL_CursorAnimation *animation = (SDL_CursorAnimation *)SDL_calloc(1, sizeof(*animation));
|
||||
if (!animation) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
animation->frames = (SDL_Cursor **)SDL_calloc(frame_count, sizeof(*animation->frames));
|
||||
animation->durations = (Uint32 *)SDL_calloc(frame_count, sizeof(*animation->durations));
|
||||
if (!animation->frames || !animation->durations) {
|
||||
SDL_DestroyCursorAnimation(animation);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (int i = 0; i < frame_count; ++i) {
|
||||
animation->frames[i] = SDL_CreateColorCursor(frames[i].surface, hot_x, hot_y);
|
||||
if (!animation->frames[i]) {
|
||||
SDL_DestroyCursorAnimation(animation);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
animation->durations[i] = frames[i].duration;
|
||||
}
|
||||
animation->num_frames = frame_count;
|
||||
|
||||
return animation;
|
||||
}
|
||||
|
||||
void SDL_UpdateCursorAnimation(void)
|
||||
{
|
||||
SDL_Mouse *mouse = SDL_GetMouse();
|
||||
SDL_Cursor *cursor = mouse->cur_cursor;
|
||||
|
||||
if (!cursor || !cursor->animation) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!mouse->focus) {
|
||||
return;
|
||||
}
|
||||
|
||||
SDL_CursorAnimation *animation = cursor->animation;
|
||||
Uint32 duration = animation->durations[animation->current_frame];
|
||||
if (!duration) {
|
||||
// We've reached the stop frame of the animation
|
||||
return;
|
||||
}
|
||||
|
||||
Uint64 now = SDL_GetTicks();
|
||||
if (now < (animation->last_update + duration)) {
|
||||
return;
|
||||
}
|
||||
|
||||
animation->current_frame = (animation->current_frame + 1) % animation->num_frames;
|
||||
animation->last_update = now;
|
||||
|
||||
SDL_RedrawCursor();
|
||||
}
|
||||
|
||||
SDL_Cursor *SDL_CreateAnimatedCursor(SDL_CursorFrameInfo *frames, int frame_count, int hot_x, int hot_y)
|
||||
{
|
||||
SDL_Mouse *mouse = SDL_GetMouse();
|
||||
@@ -1572,18 +1645,6 @@ SDL_Cursor *SDL_CreateAnimatedCursor(SDL_CursorFrameInfo *frames, int frame_coun
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Fall back to a static cursor if the platform doesn't support animated cursors.
|
||||
if (!mouse->CreateAnimatedCursor) {
|
||||
// If there is a frame with infinite duration, use it; otherwise, use the first.
|
||||
for (int i = 0; i < frame_count; ++i) {
|
||||
if (!frames[i].duration) {
|
||||
return SDL_CreateColorCursor(frames[i].surface, hot_x, hot_y);
|
||||
}
|
||||
}
|
||||
|
||||
return SDL_CreateColorCursor(frames[0].surface, hot_x, hot_y);
|
||||
}
|
||||
|
||||
// Allow specifying the hot spot via properties on the surface
|
||||
SDL_PropertiesID props = SDL_GetSurfaceProperties(frames[0].surface);
|
||||
hot_x = (int)SDL_GetNumberProperty(props, SDL_PROP_SURFACE_HOTSPOT_X_NUMBER, hot_x);
|
||||
@@ -1630,7 +1691,22 @@ SDL_Cursor *SDL_CreateAnimatedCursor(SDL_CursorFrameInfo *frames, int frame_coun
|
||||
temp_frames[i].duration = frames[i].duration;
|
||||
}
|
||||
|
||||
cursor = mouse->CreateAnimatedCursor(temp_frames, frame_count, hot_x, hot_y);
|
||||
if (mouse->CreateAnimatedCursor) {
|
||||
cursor = mouse->CreateAnimatedCursor(temp_frames, frame_count, hot_x, hot_y);
|
||||
} else {
|
||||
SDL_CursorAnimation *animation = SDL_CreateCursorAnimation(temp_frames, frame_count, hot_x, hot_y);
|
||||
if (!animation) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
cursor = (SDL_Cursor *)SDL_calloc(1, sizeof(*cursor));
|
||||
if (!cursor) {
|
||||
SDL_DestroyCursorAnimation(animation);
|
||||
goto cleanup;
|
||||
}
|
||||
cursor->animation = animation;
|
||||
}
|
||||
|
||||
if (cursor) {
|
||||
cursor->next = mouse->cursors;
|
||||
mouse->cursors = cursor;
|
||||
@@ -1729,6 +1805,11 @@ void SDL_RedrawCursor(void)
|
||||
cursor = NULL;
|
||||
}
|
||||
|
||||
if (cursor && cursor->animation) {
|
||||
SDL_CursorAnimation *animation = cursor->animation;
|
||||
cursor = animation->frames[animation->current_frame];
|
||||
}
|
||||
|
||||
if (mouse->ShowCursor) {
|
||||
mouse->ShowCursor(cursor);
|
||||
}
|
||||
@@ -1761,6 +1842,11 @@ bool SDL_SetCursor(SDL_Cursor *cursor)
|
||||
return SDL_SetError("Cursor not associated with the current mouse");
|
||||
}
|
||||
}
|
||||
if (cursor->animation) {
|
||||
SDL_CursorAnimation *animation = cursor->animation;
|
||||
animation->current_frame = 0;
|
||||
animation->last_update = SDL_GetTicks();
|
||||
}
|
||||
mouse->cur_cursor = cursor;
|
||||
}
|
||||
|
||||
@@ -1814,6 +1900,10 @@ void SDL_DestroyCursor(SDL_Cursor *cursor)
|
||||
mouse->cursors = curr->next;
|
||||
}
|
||||
|
||||
if (curr->animation) {
|
||||
SDL_DestroyCursorAnimation(curr->animation);
|
||||
}
|
||||
|
||||
if (mouse->FreeCursor && curr->internal) {
|
||||
mouse->FreeCursor(curr);
|
||||
} else {
|
||||
|
||||
@@ -31,10 +31,24 @@
|
||||
|
||||
typedef struct SDL_CursorData SDL_CursorData;
|
||||
|
||||
struct SDL_Cursor;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Uint64 last_update;
|
||||
int num_frames;
|
||||
int current_frame;
|
||||
struct SDL_Cursor **frames;
|
||||
Uint32 *durations;
|
||||
} SDL_CursorAnimation;
|
||||
|
||||
struct SDL_Cursor
|
||||
{
|
||||
struct SDL_Cursor *next;
|
||||
SDL_CursorAnimation *animation;
|
||||
|
||||
SDL_CursorData *internal;
|
||||
|
||||
struct SDL_Cursor *next;
|
||||
};
|
||||
|
||||
typedef struct
|
||||
@@ -184,6 +198,9 @@ extern void SDL_SetDefaultCursor(SDL_Cursor *cursor);
|
||||
// Get the preferred default system cursor
|
||||
extern SDL_SystemCursor SDL_GetDefaultSystemCursor(void);
|
||||
|
||||
// Update the current cursor animation if needed
|
||||
extern void SDL_UpdateCursorAnimation(void);
|
||||
|
||||
// Set the mouse focus window
|
||||
extern void SDL_SetMouseFocus(SDL_Window *window);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user