diff --git a/docs/README-migration.md b/docs/README-migration.md index 494d69fce4..e9ea328282 100644 --- a/docs/README-migration.md +++ b/docs/README-migration.md @@ -298,6 +298,8 @@ The timestamp_us member of the sensor events has been renamed sensor_timestamp a You should set the event.common.timestamp field before passing an event to SDL_PushEvent(). If the timestamp is 0 it will be filled in with SDL_GetTicksNS(). +You should call SDL_CleanupEvent() after handling SDL_EVENT_DROP_FILE, SDL_EVENT_DROP_TEXT, SDL_EVENT_SYSWM, and SDL_EVENT_TEXT_EDITING. This cleans up the memory associated with those events, and you no longer have to free the data yourself. + Mouse events use floating point values for mouse coordinates and relative motion values. You can get sub-pixel motion depending on the platform and display scaling. The SDL_DISPLAYEVENT_* events have been moved to top level events, and SDL_DISPLAYEVENT has been removed. In general, handling this change just means checking for the individual events instead of first checking for SDL_DISPLAYEVENT and then checking for display events. You can compare the event >= SDL_EVENT_DISPLAY_FIRST and <= SDL_EVENT_DISPLAY_LAST if you need to see whether it's a display event. @@ -555,6 +557,7 @@ The following hints have been removed: * SDL_HINT_VIDEO_X11_FORCE_EGL - use SDL_HINT_VIDEO_FORCE_EGL instead * SDL_HINT_VIDEO_X11_XINERAMA - Xinerama no longer supported by the X11 backend * SDL_HINT_VIDEO_X11_XVIDMODE - Xvidmode no longer supported by the X11 backend +* SDL_HINT_IME_SUPPORT_EXTENDED_TEXT - the normal text editing event has dynamically allocated text if needed, and should be freed with SDL_CleanupEvent() when processed * Renamed hints SDL_HINT_VIDEODRIVER and SDL_HINT_AUDIODRIVER to SDL_HINT_VIDEO_DRIVER and SDL_HINT_AUDIO_DRIVER * Renamed environment variables SDL_VIDEODRIVER and SDL_AUDIODRIVER to SDL_VIDEO_DRIVER and SDL_AUDIO_DRIVER diff --git a/include/SDL3/SDL_events.h b/include/SDL3/SDL_events.h index 48746d5452..312452444c 100644 --- a/include/SDL3/SDL_events.h +++ b/include/SDL3/SDL_events.h @@ -136,7 +136,6 @@ typedef enum SDL_EVENT_TEXT_INPUT, /**< Keyboard text input */ SDL_EVENT_KEYMAP_CHANGED, /**< Keymap changed due to a system event such as an input language or keyboard layout change. */ - SDL_EVENT_TEXT_EDITING_EXT, /**< Extended keyboard text editing (composition) */ /* Mouse events */ SDL_EVENT_MOUSE_MOTION = 0x400, /**< Mouse moved */ @@ -257,44 +256,35 @@ typedef struct SDL_KeyboardEvent SDL_Keysym keysym; /**< The key that was pressed or released */ } SDL_KeyboardEvent; -#define SDL_TEXTEDITINGEVENT_TEXT_SIZE (32) +#define SDL_TEXTEDITINGEVENT_TEXT_SIZE 64 /** * \brief Keyboard text editing event structure (event.edit.*) + * + * \note This event should be cleaned up with SDL_CleanupEvent() after processing. */ typedef struct SDL_TextEditingEvent { Uint32 type; /**< ::SDL_EVENT_TEXT_EDITING */ Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */ - SDL_WindowID windowID; /**< The window with keyboard focus, if any */ - char text[SDL_TEXTEDITINGEVENT_TEXT_SIZE]; /**< The editing text */ + SDL_WindowID windowID; /**< The window with keyboard focus, if any */ + char *text; /**< The editing text */ + char short_text[SDL_TEXTEDITINGEVENT_TEXT_SIZE]; /**< Memory space for short editing text */ Sint32 start; /**< The start cursor of selected editing text */ Sint32 length; /**< The length of selected editing text */ } SDL_TextEditingEvent; -/** - * \brief Extended keyboard text editing event structure (event.editExt.*) when text would be - * truncated if stored in the text buffer SDL_TextEditingEvent - */ -typedef struct SDL_TextEditingExtEvent -{ - Uint32 type; /**< ::SDL_EVENT_TEXT_EDITING_EXT */ - Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */ - SDL_WindowID windowID; /**< The window with keyboard focus, if any */ - char* text; /**< The editing text, which should be freed with SDL_free(), and will not be NULL */ - Sint32 start; /**< The start cursor of selected editing text */ - Sint32 length; /**< The length of selected editing text */ -} SDL_TextEditingExtEvent; - -#define SDL_TEXTINPUTEVENT_TEXT_SIZE (32) +#define SDL_TEXTINPUTEVENT_TEXT_SIZE 64 /** * \brief Keyboard text input event structure (event.text.*) + * + * \note This event should be cleaned up with SDL_CleanupEvent() after processing. */ typedef struct SDL_TextInputEvent { - Uint32 type; /**< ::SDL_EVENT_TEXT_INPUT */ - Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */ + Uint32 type; /**< ::SDL_EVENT_TEXT_INPUT */ + Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */ SDL_WindowID windowID; /**< The window with keyboard focus, if any */ - char text[SDL_TEXTINPUTEVENT_TEXT_SIZE]; /**< The input text */ + char text[SDL_TEXTINPUTEVENT_TEXT_SIZE]; /**< The input text */ } SDL_TextInputEvent; /** @@ -520,19 +510,21 @@ typedef struct SDL_TouchFingerEvent } SDL_TouchFingerEvent; +#define SDL_DROPEVENT_DATA_SIZE 64 /** - * \brief An event used to request a file open by the system (event.drop.*) - * This event is enabled by default, you can disable it with SDL_SetEventEnabled(). - * \note If this event is enabled, you must free the filename in the event. + * \brief An event used to drop text or request a file open by the system (event.drop.*) + * + * \note This event should be cleaned up with SDL_CleanupEvent() after processing. */ typedef struct SDL_DropEvent { Uint32 type; /**< ::SDL_EVENT_DROP_BEGIN or ::SDL_EVENT_DROP_FILE or ::SDL_EVENT_DROP_TEXT or ::SDL_EVENT_DROP_COMPLETE or ::SDL_EVENT_DROP_POSITION */ Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */ - char *file; /**< The file name, which should be freed with SDL_free(), is NULL on begin/complete */ SDL_WindowID windowID; /**< The window that was dropped on, if any */ float x; /**< X coordinate, relative to window (not on begin) */ float y; /**< Y coordinate, relative to window (not on begin) */ + char *data; /**< The text for SDL_EVENT_DROP_TEXT and the file name for SDL_EVENT_DROP_FILE, NULL for other events */ + char short_data[SDL_DROPEVENT_DATA_SIZE]; /**< Memory space for short data */ } SDL_DropEvent; /** @@ -595,6 +587,8 @@ typedef struct SDL_SysWMmsg SDL_SysWMmsg; * \brief A video driver dependent system event (event.syswm.*) * This event is disabled by default, you can enable it with SDL_SetEventEnabled() * + * \note This event should be cleaned up with SDL_CleanupEvent() after processing. + * * \note If you want to use this event, you should include SDL_syswm.h. */ typedef struct SDL_SysWMEvent @@ -615,7 +609,6 @@ typedef union SDL_Event SDL_WindowEvent window; /**< Window event data */ SDL_KeyboardEvent key; /**< Keyboard event data */ SDL_TextEditingEvent edit; /**< Text editing event data */ - SDL_TextEditingExtEvent editExt; /**< Extended text editing event data */ SDL_TextInputEvent text; /**< Text input event data */ SDL_MouseMotionEvent motion; /**< Mouse motion event data */ SDL_MouseButtonEvent button; /**< Mouse button event data */ @@ -855,10 +848,8 @@ extern DECLSPEC void SDLCALL SDL_FlushEvents(Uint32 minType, Uint32 maxType); * * \since This function is available since SDL 3.0.0. * - * \sa SDL_GetEventFilter - * \sa SDL_PeepEvents + * \sa SDL_CleanupEvent * \sa SDL_PushEvent - * \sa SDL_SetEventFilter * \sa SDL_WaitEvent * \sa SDL_WaitEventTimeout */ @@ -880,8 +871,9 @@ extern DECLSPEC SDL_bool SDLCALL SDL_PollEvent(SDL_Event *event); * * \since This function is available since SDL 3.0.0. * + * \sa SDL_CleanupEvent * \sa SDL_PollEvent - * \sa SDL_PumpEvents + * \sa SDL_PushEvent * \sa SDL_WaitEventTimeout */ extern DECLSPEC SDL_bool SDLCALL SDL_WaitEvent(SDL_Event *event); @@ -908,12 +900,34 @@ extern DECLSPEC SDL_bool SDLCALL SDL_WaitEvent(SDL_Event *event); * * \since This function is available since SDL 3.0.0. * + * \sa SDL_CleanupEvent * \sa SDL_PollEvent - * \sa SDL_PumpEvents + * \sa SDL_PushEvent * \sa SDL_WaitEvent */ extern DECLSPEC SDL_bool SDLCALL SDL_WaitEventTimeout(SDL_Event *event, Sint32 timeoutMS); +/** + * Clean up dynamically allocated memory for an event. + * + * Some events have dynamically allocated data that must be cleaned up when the event is processed. If you handle any of these events, you should call SDL_CleanupEvent() after processing them: + * SDL_EVENT_DROP_FILE + * SDL_EVENT_DROP_TEXT + * SDL_EVENT_SYSWM + * SDL_EVENT_TEXT_EDITING + * + * It is safe, but not necessary, to call this function for other event types. + * + * \param event a pointer to the event that should be cleaned up + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_PollEvent + * \sa SDL_WaitEvent + * \sa SDL_WaitEventTimeout + */ +extern DECLSPEC void SDLCALL SDL_CleanupEvent(SDL_Event *event); + /** * Add an event to the event queue. * diff --git a/include/SDL3/SDL_hints.h b/include/SDL3/SDL_hints.h index 2af3c88fff..fd746553ce 100644 --- a/include/SDL3/SDL_hints.h +++ b/include/SDL3/SDL_hints.h @@ -632,17 +632,6 @@ extern "C" { */ #define SDL_HINT_IME_SHOW_UI "SDL_IME_SHOW_UI" -/** - * \brief A variable to control if extended IME text support is enabled. - * If enabled then SDL_TextEditingExtEvent will be issued if the text would be truncated otherwise. - * Additionally SDL_TextInputEvent will be dispatched multiple times so that it is not truncated. - * - * The variable can be set to the following values: - * "0" - Legacy behavior. Text can be truncated, no heap allocations. (default) - * "1" - Modern behavior. - */ -#define SDL_HINT_IME_SUPPORT_EXTENDED_TEXT "SDL_IME_SUPPORT_EXTENDED_TEXT" - /** * \brief A variable controlling whether the home indicator bar on iPhone X * should be hidden. diff --git a/src/core/linux/SDL_fcitx.c b/src/core/linux/SDL_fcitx.c index d7cfe6be28..bbf3f45376 100644 --- a/src/core/linux/SDL_fcitx.c +++ b/src/core/linux/SDL_fcitx.c @@ -212,26 +212,11 @@ static DBusHandlerResult DBus_MessageFilter(DBusConnection *conn, DBusMessage *m Sint32 start_pos, end_pos; size_t text_bytes = Fcitx_GetPreeditString(dbus, msg, &text, &start_pos, &end_pos); if (text_bytes) { - if (SDL_GetHintBoolean(SDL_HINT_IME_SUPPORT_EXTENDED_TEXT, SDL_FALSE)) { - if (start_pos == -1) { - Sint32 byte_pos = Fcitx_GetPreeditCursorByte(dbus, msg); - start_pos = byte_pos >= 0 ? SDL_utf8strnlen(text, byte_pos) : -1; - } - SDL_SendEditingText(text, start_pos, end_pos >= 0 ? end_pos - start_pos : -1); - } else { - char buf[SDL_TEXTEDITINGEVENT_TEXT_SIZE]; - size_t i = 0; - size_t cursor = 0; - while (i < text_bytes) { - const size_t sz = SDL_utf8strlcpy(buf, text + i, sizeof(buf)); - const size_t chars = SDL_utf8strlen(buf); - - SDL_SendEditingText(buf, cursor, chars); - - i += sz; - cursor += chars; - } + if (start_pos == -1) { + Sint32 byte_pos = Fcitx_GetPreeditCursorByte(dbus, msg); + start_pos = byte_pos >= 0 ? SDL_utf8strnlen(text, byte_pos) : -1; } + SDL_SendEditingText(text, start_pos, end_pos >= 0 ? end_pos - start_pos : -1); SDL_free(text); } else { SDL_SendEditingText("", 0, 0); diff --git a/src/core/linux/SDL_ibus.c b/src/core/linux/SDL_ibus.c index 592dc9d49e..4c1b838635 100644 --- a/src/core/linux/SDL_ibus.c +++ b/src/core/linux/SDL_ibus.c @@ -252,38 +252,23 @@ static DBusHandlerResult IBus_MessageHandler(DBusConnection *conn, DBusMessage * text = IBus_GetVariantText(conn, &iter, dbus); if (text) { - if (SDL_GetHintBoolean(SDL_HINT_IME_SUPPORT_EXTENDED_TEXT, SDL_FALSE)) { - Uint32 pos, start_pos, end_pos; - SDL_bool has_pos = SDL_FALSE; - SDL_bool has_dec_pos = SDL_FALSE; + Uint32 pos, start_pos, end_pos; + SDL_bool has_pos = SDL_FALSE; + SDL_bool has_dec_pos = SDL_FALSE; + dbus->message_iter_init(msg, &iter); + has_dec_pos = IBus_GetDecorationPosition(conn, &iter, dbus, &start_pos, &end_pos); + if (!has_dec_pos) { dbus->message_iter_init(msg, &iter); - has_dec_pos = IBus_GetDecorationPosition(conn, &iter, dbus, &start_pos, &end_pos); - if (!has_dec_pos) { - dbus->message_iter_init(msg, &iter); - has_pos = IBus_GetVariantCursorPos(conn, &iter, dbus, &pos); - } + has_pos = IBus_GetVariantCursorPos(conn, &iter, dbus, &pos); + } - if (has_dec_pos) { - SDL_SendEditingText(text, start_pos, end_pos - start_pos); - } else if (has_pos) { - SDL_SendEditingText(text, pos, -1); - } else { - SDL_SendEditingText(text, -1, -1); - } + if (has_dec_pos) { + SDL_SendEditingText(text, start_pos, end_pos - start_pos); + } else if (has_pos) { + SDL_SendEditingText(text, pos, -1); } else { - char buf[SDL_TEXTEDITINGEVENT_TEXT_SIZE]; - size_t text_bytes = SDL_strlen(text), i = 0; - size_t cursor = 0; - - do { - const size_t sz = SDL_utf8strlcpy(buf, text + i, sizeof(buf)); - const size_t chars = SDL_utf8strlen(buf); - - SDL_SendEditingText(buf, cursor, chars); - i += sz; - cursor += chars; - } while (i < text_bytes); + SDL_SendEditingText(text, -1, -1); } } diff --git a/src/dynapi/SDL_dynapi.sym b/src/dynapi/SDL_dynapi.sym index 6ee8a813a9..75e19c3c1b 100644 --- a/src/dynapi/SDL_dynapi.sym +++ b/src/dynapi/SDL_dynapi.sym @@ -921,6 +921,7 @@ SDL3_0.0.0 { SDL_GetWindowProperties; SDL_ClearProperty; SDL_EnterAppMainCallbacks; + SDL_CleanupEvent; # extra symbols go here (don't modify this line) local: *; }; diff --git a/src/dynapi/SDL_dynapi_overrides.h b/src/dynapi/SDL_dynapi_overrides.h index 09c6dbbd45..4cfa591664 100644 --- a/src/dynapi/SDL_dynapi_overrides.h +++ b/src/dynapi/SDL_dynapi_overrides.h @@ -946,3 +946,4 @@ #define SDL_GetWindowProperties SDL_GetWindowProperties_REAL #define SDL_ClearProperty SDL_ClearProperty_REAL #define SDL_EnterAppMainCallbacks SDL_EnterAppMainCallbacks_REAL +#define SDL_CleanupEvent SDL_CleanupEvent_REAL diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h index d584067fb2..d73e3e312a 100644 --- a/src/dynapi/SDL_dynapi_procs.h +++ b/src/dynapi/SDL_dynapi_procs.h @@ -978,3 +978,4 @@ SDL_DYNAPI_PROC(SDL_PropertiesID,SDL_GetSurfaceProperties,(SDL_Surface *a),(a),r SDL_DYNAPI_PROC(SDL_PropertiesID,SDL_GetWindowProperties,(SDL_Window *a),(a),return) SDL_DYNAPI_PROC(int,SDL_ClearProperty,(SDL_PropertiesID a, const char *b),(a,b),return) SDL_DYNAPI_PROC(int,SDL_EnterAppMainCallbacks,(int a, char *b[], SDL_AppInit_func c, SDL_AppIterate_func d, SDL_AppEvent_func e, SDL_AppQuit_func f),(a,b,c,d,e,f),return) +SDL_DYNAPI_PROC(void,SDL_CleanupEvent,(SDL_Event *a),(a),) diff --git a/src/events/SDL_dropevents.c b/src/events/SDL_dropevents.c index 5aa4a99236..211b8d3b37 100644 --- a/src/events/SDL_dropevents.c +++ b/src/events/SDL_dropevents.c @@ -58,7 +58,15 @@ static int SDL_SendDrop(SDL_Window *window, const SDL_EventType evtype, const ch SDL_zero(event); event.type = evtype; event.common.timestamp = 0; - event.drop.file = data ? SDL_strdup(data) : NULL; + if (data) { + size_t len = SDL_strlen(data); + if (len < sizeof(event.drop.short_data)) { + SDL_memcpy(event.drop.short_data, data, len + 1); + event.drop.data = event.drop.short_data; + } else { + event.drop.data = SDL_strdup(data); + } + } event.drop.windowID = window ? window->id : 0; if (evtype == SDL_EVENT_DROP_POSITION) { diff --git a/src/events/SDL_events.c b/src/events/SDL_events.c index 031e660acc..1ce42ad575 100644 --- a/src/events/SDL_events.c +++ b/src/events/SDL_events.c @@ -75,17 +75,10 @@ static Uint32 SDL_userevents = SDL_EVENT_USER; typedef struct SDL_EventEntry { SDL_Event event; - SDL_SysWMmsg msg; struct SDL_EventEntry *prev; struct SDL_EventEntry *next; } SDL_EventEntry; -typedef struct SDL_SysWMEntry -{ - SDL_SysWMmsg msg; - struct SDL_SysWMEntry *next; -} SDL_SysWMEntry; - static struct { SDL_Mutex *lock; @@ -95,9 +88,7 @@ static struct SDL_EventEntry *head; SDL_EventEntry *tail; SDL_EventEntry *free; - SDL_SysWMEntry *wmmsg_used; - SDL_SysWMEntry *wmmsg_free; -} SDL_EventQ = { NULL, SDL_FALSE, { 0 }, 0, NULL, NULL, NULL, NULL, NULL }; +} SDL_EventQ = { NULL, SDL_FALSE, { 0 }, 0, NULL, NULL, NULL }; #ifndef SDL_JOYSTICK_DISABLED @@ -419,7 +410,7 @@ static void SDL_LogEvent(const SDL_Event *event) break; #undef PRINT_FINGER_EVENT -#define PRINT_DROP_EVENT(event) (void)SDL_snprintf(details, sizeof(details), " (file='%s' timestamp=%u windowid=%u x=%f y=%f)", event->drop.file, (uint)event->drop.timestamp, (uint)event->drop.windowID, event->drop.x, event->drop.y) +#define PRINT_DROP_EVENT(event) (void)SDL_snprintf(details, sizeof(details), " (data='%s' timestamp=%u windowid=%u x=%f y=%f)", event->drop.data, (uint)event->drop.timestamp, (uint)event->drop.windowID, event->drop.x, event->drop.y) SDL_EVENT_CASE(SDL_EVENT_DROP_FILE) PRINT_DROP_EVENT(event); break; @@ -484,7 +475,6 @@ void SDL_StopEventLoop(void) const char *report = SDL_GetHint("SDL_EVENT_QUEUE_STATISTICS"); int i; SDL_EventEntry *entry; - SDL_SysWMEntry *wmmsg; SDL_LockMutex(SDL_EventQ.lock); @@ -506,24 +496,12 @@ void SDL_StopEventLoop(void) SDL_free(entry); entry = next; } - for (wmmsg = SDL_EventQ.wmmsg_used; wmmsg;) { - SDL_SysWMEntry *next = wmmsg->next; - SDL_free(wmmsg); - wmmsg = next; - } - for (wmmsg = SDL_EventQ.wmmsg_free; wmmsg;) { - SDL_SysWMEntry *next = wmmsg->next; - SDL_free(wmmsg); - wmmsg = next; - } SDL_AtomicSet(&SDL_EventQ.count, 0); SDL_EventQ.max_events_seen = 0; SDL_EventQ.head = NULL; SDL_EventQ.tail = NULL; SDL_EventQ.free = NULL; - SDL_EventQ.wmmsg_used = NULL; - SDL_EventQ.wmmsg_free = NULL; SDL_AtomicSet(&SDL_sentinel_pending, 0); /* Clear disabled event state */ @@ -622,9 +600,6 @@ static int SDL_AddEvent(SDL_Event *event) entry->event = *event; if (event->type == SDL_EVENT_POLL_SENTINEL) { SDL_AtomicAdd(&SDL_sentinel_pending, 1); - } else if (event->type == SDL_EVENT_SYSWM) { - entry->msg = *event->syswm.msg; - entry->event.syswm.msg = &entry->msg; } if (SDL_EventQ.tail) { @@ -724,43 +699,14 @@ static int SDL_PeepEventsInternal(SDL_Event *events, int numevents, SDL_eventact } } else { SDL_EventEntry *entry, *next; - SDL_SysWMEntry *wmmsg, *wmmsg_next; Uint32 type; - if (action == SDL_GETEVENT) { - /* Clean out any used wmmsg data - FIXME: Do we want to retain the data for some period of time? - */ - for (wmmsg = SDL_EventQ.wmmsg_used; wmmsg; wmmsg = wmmsg_next) { - wmmsg_next = wmmsg->next; - wmmsg->next = SDL_EventQ.wmmsg_free; - SDL_EventQ.wmmsg_free = wmmsg; - } - SDL_EventQ.wmmsg_used = NULL; - } - for (entry = SDL_EventQ.head; entry && (events == NULL || used < numevents); entry = next) { next = entry->next; type = entry->event.type; if (minType <= type && type <= maxType) { if (events) { events[used] = entry->event; - if (entry->event.type == SDL_EVENT_SYSWM) { - /* We need to copy the wmmsg somewhere safe. - For now we'll guarantee it's valid at least until - the next call to SDL_PeepEvents() - */ - if (SDL_EventQ.wmmsg_free) { - wmmsg = SDL_EventQ.wmmsg_free; - SDL_EventQ.wmmsg_free = wmmsg->next; - } else { - wmmsg = (SDL_SysWMEntry *)SDL_malloc(sizeof(*wmmsg)); - } - wmmsg->msg = *entry->event.syswm.msg; - wmmsg->next = SDL_EventQ.wmmsg_used; - SDL_EventQ.wmmsg_used = wmmsg; - events[used].syswm.msg = &wmmsg->msg; - } if (action == SDL_GETEVENT) { SDL_CutEvent(entry); @@ -818,9 +764,6 @@ void SDL_FlushEvents(Uint32 minType, Uint32 maxType) { SDL_EventEntry *entry, *next; Uint32 type; - /* !!! FIXME: we need to manually SDL_free() the strings in TEXTINPUT and - drag'n'drop events if we're flushing them without passing them to the - app, but I don't know if this is the right place to do that. */ /* Make sure the events are current */ #if 0 @@ -842,6 +785,7 @@ void SDL_FlushEvents(Uint32 minType, Uint32 maxType) next = entry->next; type = entry->event.type; if (minType <= type && type <= maxType) { + SDL_CleanupEvent(&entry->event); SDL_CutEvent(entry); } } @@ -1124,6 +1068,33 @@ SDL_bool SDL_WaitEventTimeoutNS(SDL_Event *event, Sint64 timeoutNS) } } +void SDL_CleanupEvent(SDL_Event *event) +{ + switch (event->type) { + case SDL_EVENT_DROP_FILE: + case SDL_EVENT_DROP_TEXT: + if (event->drop.data && event->drop.data != event->drop.short_data) { + SDL_free(event->drop.data); + event->drop.data = NULL; + } + break; + case SDL_EVENT_SYSWM: + if (event->syswm.msg) { + SDL_free(event->syswm.msg); + event->syswm.msg = NULL; + } + break; + case SDL_EVENT_TEXT_EDITING: + if (event->edit.text && event->edit.text != event->edit.short_text) { + SDL_free(event->edit.text); + event->edit.text = NULL; + } + break; + default: + break; + } +} + int SDL_PushEvent(SDL_Event *event) { if (!event->common.timestamp) { @@ -1380,7 +1351,11 @@ int SDL_SendSysWMEvent(SDL_SysWMmsg *message) SDL_memset(&event, 0, sizeof(event)); event.type = SDL_EVENT_SYSWM; event.common.timestamp = 0; - event.syswm.msg = message; + event.syswm.msg = (SDL_SysWMmsg *)SDL_malloc(sizeof(*message)); + if (!event.syswm.msg) { + return 0; + } + SDL_copyp(event.syswm.msg, message); posted = (SDL_PushEvent(&event) > 0); } /* Update internal event state */ diff --git a/src/events/SDL_keyboard.c b/src/events/SDL_keyboard.c index 59968b55fc..49f38b9f49 100644 --- a/src/events/SDL_keyboard.c +++ b/src/events/SDL_keyboard.c @@ -1098,21 +1098,18 @@ int SDL_SendEditingText(const char *text, int start, int length) if (SDL_EventEnabled(SDL_EVENT_TEXT_EDITING)) { SDL_Event event; - if (SDL_GetHintBoolean(SDL_HINT_IME_SUPPORT_EXTENDED_TEXT, SDL_FALSE) && - SDL_strlen(text) >= SDL_arraysize(event.text.text)) { - event.type = SDL_EVENT_TEXT_EDITING_EXT; - event.common.timestamp = 0; - event.editExt.windowID = keyboard->focus ? keyboard->focus->id : 0; - event.editExt.text = text ? SDL_strdup(text) : NULL; - event.editExt.start = start; - event.editExt.length = length; + event.type = SDL_EVENT_TEXT_EDITING; + event.common.timestamp = 0; + event.edit.windowID = keyboard->focus ? keyboard->focus->id : 0; + event.edit.start = start; + event.edit.length = length; + + size_t len = SDL_strlen(text); + if (len < sizeof(event.edit.short_text)) { + SDL_memcpy(event.edit.short_text, text, len + 1); + event.edit.text = event.edit.short_text; } else { - event.type = SDL_EVENT_TEXT_EDITING; - event.common.timestamp = 0; - event.edit.windowID = keyboard->focus ? keyboard->focus->id : 0; - event.edit.start = start; - event.edit.length = length; - SDL_utf8strlcpy(event.edit.text, text, SDL_arraysize(event.edit.text)); + event.edit.text = SDL_strdup(text); } posted = (SDL_PushEvent(&event) > 0); diff --git a/src/main/SDL_main_callbacks.c b/src/main/SDL_main_callbacks.c index a20f9f6ac8..2ac9abaf8f 100644 --- a/src/main/SDL_main_callbacks.c +++ b/src/main/SDL_main_callbacks.c @@ -83,22 +83,7 @@ int SDL_IterateMainCallbacks(void) { // Just pump events and empty the queue, EventWatcher sends the events to the app. SDL_PumpEvents(); - - for (;;) { - SDL_Event events[32]; - int count = SDL_PeepEvents(events, SDL_arraysize(events), SDL_GETEVENT, SDL_EVENT_FIRST, SDL_EVENT_LAST); - if (count <= 0) { - break; - } - for (int i = 0; i < count; ++i) { - switch (events[i].type) { - case SDL_EVENT_DROP_FILE: - case SDL_EVENT_DROP_TEXT: - SDL_free(events[i].drop.file); - break; - } - } - } + SDL_FlushEvents(SDL_EVENT_FIRST, SDL_EVENT_LAST); int rc = SDL_main_iteration_callback(); if (!SDL_AtomicCAS(&apprc, 0, rc)) { diff --git a/src/test/SDL_test_common.c b/src/test/SDL_test_common.c index b10bc24255..4e179829ce 100644 --- a/src/test/SDL_test_common.c +++ b/src/test/SDL_test_common.c @@ -1823,10 +1823,10 @@ static void SDLTest_PrintEvent(const SDL_Event *event) SDL_Log("SDL EVENT: Drag and drop beginning"); break; case SDL_EVENT_DROP_FILE: - SDL_Log("SDL EVENT: Drag and drop file: '%s'", event->drop.file); + SDL_Log("SDL EVENT: Drag and drop file: '%s'", event->drop.data); break; case SDL_EVENT_DROP_TEXT: - SDL_Log("SDL EVENT: Drag and drop text: '%s'", event->drop.file); + SDL_Log("SDL EVENT: Drag and drop text: '%s'", event->drop.data); break; case SDL_EVENT_DROP_COMPLETE: SDL_Log("SDL EVENT: Drag and drop ending"); @@ -2425,12 +2425,7 @@ void SDLTest_CommonEvent(SDLTest_CommonState *state, SDL_Event *event, int *done { *done = SDLTest_CommonEventMainCallbacks(state, event) ? 1 : 0; - switch (event->type) { - case SDL_EVENT_DROP_FILE: - case SDL_EVENT_DROP_TEXT: - SDL_free(event->drop.file); // SDL frees these if you use SDL_AppEvent, not us, so explicitly handle it here. - break; - } + SDL_CleanupEvent(event); } void SDLTest_CommonQuit(SDLTest_CommonState *state) diff --git a/src/video/wayland/SDL_waylandevents.c b/src/video/wayland/SDL_waylandevents.c index b4700e8db4..c68b49c3c2 100644 --- a/src/video/wayland/SDL_waylandevents.c +++ b/src/video/wayland/SDL_waylandevents.c @@ -2191,33 +2191,19 @@ static void text_input_preedit_string(void *data, char buf[SDL_TEXTEDITINGEVENT_TEXT_SIZE]; text_input->has_preedit = SDL_TRUE; if (text) { - if (SDL_GetHintBoolean(SDL_HINT_IME_SUPPORT_EXTENDED_TEXT, SDL_FALSE)) { - int cursor_begin_utf8 = cursor_begin >= 0 ? (int)SDL_utf8strnlen(text, cursor_begin) : -1; - int cursor_end_utf8 = cursor_end >= 0 ? (int)SDL_utf8strnlen(text, cursor_end) : -1; - int cursor_size_utf8; - if (cursor_end_utf8 >= 0) { - if (cursor_begin_utf8 >= 0) { - cursor_size_utf8 = cursor_end_utf8 - cursor_begin_utf8; - } else { - cursor_size_utf8 = cursor_end_utf8; - } + int cursor_begin_utf8 = cursor_begin >= 0 ? (int)SDL_utf8strnlen(text, cursor_begin) : -1; + int cursor_end_utf8 = cursor_end >= 0 ? (int)SDL_utf8strnlen(text, cursor_end) : -1; + int cursor_size_utf8; + if (cursor_end_utf8 >= 0) { + if (cursor_begin_utf8 >= 0) { + cursor_size_utf8 = cursor_end_utf8 - cursor_begin_utf8; } else { - cursor_size_utf8 = -1; + cursor_size_utf8 = cursor_end_utf8; } - SDL_SendEditingText(text, cursor_begin_utf8, cursor_size_utf8); } else { - int text_bytes = (int)SDL_strlen(text), i = 0; - int cursor = 0; - do { - const int sz = (int)SDL_utf8strlcpy(buf, text + i, sizeof(buf)); - const int chars = (int)SDL_utf8strlen(buf); - - SDL_SendEditingText(buf, cursor, chars); - - i += sz; - cursor += chars; - } while (i < text_bytes); + cursor_size_utf8 = -1; } + SDL_SendEditingText(text, cursor_begin_utf8, cursor_size_utf8); } else { buf[0] = '\0'; SDL_SendEditingText(buf, 0, 0); diff --git a/test/checkkeys.c b/test/checkkeys.c index 0db1528216..11fd5b6ced 100644 --- a/test/checkkeys.c +++ b/test/checkkeys.c @@ -181,10 +181,7 @@ static void loop(void) break; case SDL_EVENT_TEXT_EDITING: PrintText("EDIT", event.edit.text); - break; - case SDL_EVENT_TEXT_EDITING_EXT: - PrintText("EDIT_EXT", event.editExt.text); - SDL_free(event.editExt.text); + SDL_CleanupEvent(&event); break; case SDL_EVENT_TEXT_INPUT: PrintText("INPUT", event.text.text); @@ -261,9 +258,6 @@ int main(int argc, char *argv[]) /* Disable mouse emulation */ SDL_SetHint(SDL_HINT_TOUCH_MOUSE_EVENTS, "0"); - /* Enable extended text editing events */ - SDL_SetHint(SDL_HINT_IME_SUPPORT_EXTENDED_TEXT, "1"); - /* Initialize SDL */ if (!SDLTest_CommonInit(state)) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't initialize SDL: %s\n", SDL_GetError()); diff --git a/test/checkkeysthreads.c b/test/checkkeysthreads.c index cca4740e4c..64e0dc418d 100644 --- a/test/checkkeysthreads.c +++ b/test/checkkeysthreads.c @@ -183,6 +183,7 @@ static void loop(void) break; case SDL_EVENT_TEXT_EDITING: PrintText("EDIT", event.text.text); + SDL_CleanupEvent(&event); break; case SDL_EVENT_TEXT_INPUT: PrintText("INPUT", event.text.text); diff --git a/test/testaudio.c b/test/testaudio.c index e6ee2c1e15..210b9c29b2 100644 --- a/test/testaudio.c +++ b/test/testaudio.c @@ -1178,9 +1178,9 @@ int SDL_AppEvent(const SDL_Event *event) break; case SDL_EVENT_DROP_FILE: - SDL_Log("Drop file! '%s'", event->drop.file); - LoadWavThing(event->drop.file, event->drop.x, event->drop.y); - /* SDL frees event->drop.file for you when you use SDL_AppEvent(). */ + SDL_Log("Drop file! '%s'", event->drop.data); + LoadWavThing(event->drop.data, event->drop.x, event->drop.y); + /* SDL frees event->drop.data for you when you use SDL_AppEvent(). */ break; case SDL_EVENT_WINDOW_RESIZED: diff --git a/test/testdropfile.c b/test/testdropfile.c index 2e4efedbab..3da1a79126 100644 --- a/test/testdropfile.c +++ b/test/testdropfile.c @@ -56,9 +56,6 @@ int main(int argc, char *argv[]) goto quit; } - - SDL_SetEventEnabled(SDL_EVENT_DROP_FILE, SDL_TRUE); - /* Main render loop */ done = 0; while (!done) { @@ -71,16 +68,15 @@ int main(int argc, char *argv[]) SDL_Log("Drop complete on window %u at (%f, %f)", (unsigned int)event.drop.windowID, event.drop.x, event.drop.y); } else if ((event.type == SDL_EVENT_DROP_FILE) || (event.type == SDL_EVENT_DROP_TEXT)) { const char *typestr = (event.type == SDL_EVENT_DROP_FILE) ? "File" : "Text"; - char *dropped_filedir = event.drop.file; - SDL_Log("%s dropped on window %u: %s at (%f, %f)", typestr, (unsigned int)event.drop.windowID, dropped_filedir, event.drop.x, event.drop.y); + SDL_Log("%s dropped on window %u: %s at (%f, %f)", typestr, (unsigned int)event.drop.windowID, event.drop.data, event.drop.x, event.drop.y); /* Normally you'd have to do this, but this is freed in SDLTest_CommonEvent() */ - /*SDL_free(dropped_filedir);*/ + /*SDL_CleanupEvent(&event);*/ } else if (event.type == SDL_EVENT_DROP_POSITION) { is_hover = SDL_TRUE; x = event.drop.x; y = event.drop.y; windowID = event.drop.windowID; - SDL_Log("Drop position on window %u at (%f, %f) file = %s", (unsigned int)event.drop.windowID, event.drop.x, event.drop.y, event.drop.file); + SDL_Log("Drop position on window %u at (%f, %f) data = %s", (unsigned int)event.drop.windowID, event.drop.x, event.drop.y, event.drop.data); } SDLTest_CommonEvent(state, &event, &done); diff --git a/test/testime.c b/test/testime.c index 84d3aecbbd..58010bd485 100644 --- a/test/testime.c +++ b/test/testime.c @@ -779,6 +779,7 @@ int main(int argc, char *argv[]) SDL_strlcpy(markedText, event.edit.text, SDL_TEXTEDITINGEVENT_TEXT_SIZE); cursor = event.edit.start; Redraw(); + SDL_CleanupEvent(&event); break; } } diff --git a/test/testwm.c b/test/testwm.c index 9116700a2e..7de55701ec 100644 --- a/test/testwm.c +++ b/test/testwm.c @@ -265,9 +265,6 @@ int main(int argc, char *argv[]) return 1; } - SDL_SetEventEnabled(SDL_EVENT_DROP_FILE, SDL_TRUE); - SDL_SetEventEnabled(SDL_EVENT_DROP_TEXT, SDL_TRUE); - for (i = 0; i < state->num_windows; ++i) { SDL_Renderer *renderer = state->renderers[i]; SDL_SetRenderDrawColor(renderer, 0xA0, 0xA0, 0xA0, 0xFF);