Procházet zdrojové kódy

Added SDL_CleanupEvent()

This is used to free any dynamically allocated memory in events.
Sam Lantinga před 1 rokem
rodič
revize
7e445da569

+ 3 - 0
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

+ 46 - 32
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.
  *

+ 0 - 11
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.

+ 4 - 19
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);

+ 13 - 28
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);
             }
         }
 

+ 1 - 0
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: *;
 };

+ 1 - 0
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

+ 1 - 0
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),)

+ 9 - 1
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) {

+ 35 - 60
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 */

+ 11 - 14
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);

+ 1 - 16
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)) {

+ 3 - 8
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)

+ 9 - 23
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);

+ 1 - 7
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());

+ 1 - 0
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);

+ 3 - 3
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:

+ 3 - 7
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);

+ 1 - 0
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;
             }
         }

+ 0 - 3
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);