Added SDL_CleanupEvent()

This is used to free any dynamically allocated memory in events.
main
Sam Lantinga 2023-11-04 00:55:55 -07:00
parent c4bf05fd9d
commit 7e445da569
20 changed files with 146 additions and 232 deletions

View File

@ -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

View File

@ -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.
*

View File

@ -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.

View File

@ -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);

View File

@ -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);
}
}

View File

@ -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: *;
};

View File

@ -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

View File

@ -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),)

View File

@ -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) {

View File

@ -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 */

View File

@ -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);

View File

@ -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)) {

View File

@ -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)

View File

@ -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);

View File

@ -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());

View File

@ -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);

View File

@ -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:

View File

@ -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);

View File

@ -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;
}
}

View File

@ -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);