Skip to content

Commit

Permalink
Dynamically allocate long text for SDL_EVENT_TEXT_INPUT events
Browse files Browse the repository at this point in the history
This prevents input text from being split across Unicode combining or modifier characters, and in practice allocations will rarely happen.
  • Loading branch information
slouken committed Nov 4, 2023
1 parent ad842dd commit 548c0b4
Show file tree
Hide file tree
Showing 8 changed files with 25 additions and 10 deletions.
2 changes: 1 addition & 1 deletion docs/README-migration.md
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,7 @@ 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.
You should call SDL_CleanupEvent() after handling SDL_EVENT_DROP_FILE, SDL_EVENT_DROP_TEXT, SDL_EVENT_SYSWM, SDL_EVENT_TEXT_EDITING, and SDL_EVENT_TEXT_INPUT. 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.
Expand Down
3 changes: 2 additions & 1 deletion include/SDL3/SDL_events.h
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,8 @@ typedef struct SDL_TextInputEvent
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; /**< The input text */
char short_text[SDL_TEXTEDITINGEVENT_TEXT_SIZE]; /**< Memory space for short input text, use 'text' instead */
} SDL_TextInputEvent;

/**
Expand Down
10 changes: 9 additions & 1 deletion src/events/SDL_events.c
Original file line number Diff line number Diff line change
Expand Up @@ -470,11 +470,13 @@ static void SDL_LogEvent(const SDL_Event *event)

static void SDL_CopyEvent(SDL_Event *dst, SDL_Event *src)
{
*dst = *src;
SDL_copyp(dst, src);

/* Pointers to internal static data must be updated when copying. */
if (src->type == SDL_EVENT_TEXT_EDITING && src->edit.text == src->edit.short_text) {
dst->edit.text = dst->edit.short_text;
} else if (src->type == SDL_EVENT_TEXT_INPUT && src->text.text == src->text.short_text) {
dst->text.text = dst->text.short_text;
} else if (src->type == SDL_EVENT_DROP_TEXT && src->drop.data == src->drop.short_data) {
dst->drop.data = dst->drop.short_data;
}
Expand Down Expand Up @@ -1106,6 +1108,12 @@ void SDL_CleanupEvent(SDL_Event *event)
event->edit.text = NULL;
}
break;
case SDL_EVENT_TEXT_INPUT:
if (event->text.text && event->text.text != event->text.short_text) {
SDL_free(event->text.text);
event->text.text = NULL;
}
break;
default:
break;
}
Expand Down
16 changes: 9 additions & 7 deletions src/events/SDL_keyboard.c
Original file line number Diff line number Diff line change
Expand Up @@ -1076,14 +1076,16 @@ int SDL_SendKeyboardText(const char *text)
event.type = SDL_EVENT_TEXT_INPUT;
event.common.timestamp = 0;
event.text.windowID = keyboard->focus ? keyboard->focus->id : 0;
while (pos < length) {
advance = SDL_utf8strlcpy(event.text.text, text + pos, SDL_arraysize(event.text.text));
if (!advance) {
break;
}
pos += advance;
posted |= (SDL_PushEvent(&event) > 0);

size_t len = SDL_strlen(text);
if (len < sizeof(event.text.short_text)) {
SDL_memcpy(event.text.short_text, text, len + 1);
event.text.text = event.text.short_text;
} else {
event.text.text = SDL_strdup(text);
}

posted = (SDL_PushEvent(&event) > 0);
}
return posted;
}
Expand Down
1 change: 1 addition & 0 deletions test/checkkeys.c
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,7 @@ static void loop(void)
case SDL_EVENT_TEXT_INPUT:
PrintText("INPUT", event.text.text);
SDLTest_TextWindowAddText(textwin, "%s", event.text.text);
SDL_CleanupEvent(&event);
break;
case SDL_EVENT_FINGER_DOWN:
if (SDL_TextInputActive()) {
Expand Down
1 change: 1 addition & 0 deletions test/checkkeysthreads.c
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@ static void loop(void)
break;
case SDL_EVENT_TEXT_INPUT:
PrintText("INPUT", event.text.text);
SDL_CleanupEvent(&event);
break;
case SDL_EVENT_MOUSE_BUTTON_DOWN:
/* Left button quits the app, other buttons toggles text input */
Expand Down
1 change: 1 addition & 0 deletions test/testcontroller.c
Original file line number Diff line number Diff line change
Expand Up @@ -1728,6 +1728,7 @@ static void loop(void *arg)
AddControllerNameText(event.text.text);
}
}
SDL_CleanupEvent(&event);
break;
case SDL_EVENT_QUIT:
done = SDL_TRUE;
Expand Down
1 change: 1 addition & 0 deletions test/testime.c
Original file line number Diff line number Diff line change
Expand Up @@ -770,6 +770,7 @@ int main(int argc, char *argv[])
/* is committed */
markedText[0] = 0;
Redraw();
SDL_CleanupEvent(&event);
break;

case SDL_EVENT_TEXT_EDITING:
Expand Down

0 comments on commit 548c0b4

Please sign in to comment.