Added SDL_CleanupEvent()

This is used to free any dynamically allocated memory in events.
This commit is contained in:
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

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