mirror of
https://github.com/ddnet/ddnet.git
synced 2024-11-09 09:38:19 +00:00
Support IME composition strings of arbitrary length
Previously, IME composition strings were limited to at most 32 bytes, e.g. 10 Hiragana characters. Now, `SDL_TextEditingExtEvent` (`SDL_TEXTEDITING_EXT`) is supported, which uses heap-allocated composition strings of arbitrary length. On the other hand, the buffer for input event text was larger than necessary, as SDL text events only contain at most 32 bytes (`SDL_TEXTINPUTEVENT_TEXT_SIZE` is not used directly to avoid the include). With the hint for extended IME handling enabled, long composition text will be sent as multiple text events (without breaking UTF-8).
This commit is contained in:
parent
78cbb45d49
commit
8a3929d48c
|
@ -4562,6 +4562,11 @@ int main(int argc, const char **argv)
|
|||
SDL_SetHint("SDL_TOUCH_MOUSE_EVENTS", "0");
|
||||
SDL_SetHint("SDL_MOUSE_TOUCH_EVENTS", "0");
|
||||
|
||||
// Support longer IME composition strings (enables SDL_TEXTEDITING_EXT).
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 22)
|
||||
SDL_SetHint(SDL_HINT_IME_SUPPORT_EXTENDED_TEXT, "1");
|
||||
#endif
|
||||
|
||||
#if defined(CONF_PLATFORM_MACOS)
|
||||
// Hints will not be set if there is an existing override hint or environment variable that takes precedence.
|
||||
// So this respects cli environment overrides.
|
||||
|
|
|
@ -70,7 +70,6 @@ CInput::CInput()
|
|||
|
||||
m_pClipboardText = nullptr;
|
||||
|
||||
m_CompositionLength = COMP_LENGTH_INACTIVE;
|
||||
m_CompositionCursor = 0;
|
||||
m_CandidateSelectedIndex = -1;
|
||||
|
||||
|
@ -328,9 +327,8 @@ void CInput::StopTextInput()
|
|||
SDL_StopTextInput();
|
||||
// disable system messages for performance
|
||||
SDL_EventState(SDL_SYSWMEVENT, SDL_DISABLE);
|
||||
m_CompositionLength = COMP_LENGTH_INACTIVE;
|
||||
m_CompositionString = "";
|
||||
m_CompositionCursor = 0;
|
||||
m_aComposition[0] = '\0';
|
||||
m_vCandidates.clear();
|
||||
}
|
||||
|
||||
|
@ -574,6 +572,26 @@ void CInput::HandleTouchMotionEvent(const SDL_TouchFingerEvent &Event)
|
|||
}
|
||||
}
|
||||
|
||||
void CInput::HandleTextEditingEvent(const char *pText, int Start, int Length)
|
||||
{
|
||||
if(pText[0] != '\0')
|
||||
{
|
||||
m_CompositionString = pText;
|
||||
m_CompositionCursor = 0;
|
||||
for(int i = 0; i < Start; i++)
|
||||
{
|
||||
m_CompositionCursor = str_utf8_forward(m_CompositionString.c_str(), m_CompositionCursor);
|
||||
}
|
||||
// Length is currently unused on Windows and will always be 0, so we don't support selecting composition text
|
||||
AddTextEvent("");
|
||||
}
|
||||
else
|
||||
{
|
||||
m_CompositionString = "";
|
||||
m_CompositionCursor = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void CInput::SetCompositionWindowPosition(float X, float Y, float H)
|
||||
{
|
||||
SDL_Rect Rect;
|
||||
|
@ -658,29 +676,18 @@ int CInput::Update()
|
|||
break;
|
||||
|
||||
case SDL_TEXTEDITING:
|
||||
{
|
||||
m_CompositionLength = str_length(Event.edit.text);
|
||||
if(m_CompositionLength)
|
||||
{
|
||||
str_copy(m_aComposition, Event.edit.text);
|
||||
m_CompositionCursor = 0;
|
||||
for(int i = 0; i < Event.edit.start; i++)
|
||||
m_CompositionCursor = str_utf8_forward(m_aComposition, m_CompositionCursor);
|
||||
// Event.edit.length is currently unused on Windows and will always be 0, so we don't support selecting composition text
|
||||
AddTextEvent("");
|
||||
}
|
||||
else
|
||||
{
|
||||
m_aComposition[0] = '\0';
|
||||
m_CompositionLength = 0;
|
||||
m_CompositionCursor = 0;
|
||||
}
|
||||
HandleTextEditingEvent(Event.edit.text, Event.edit.start, Event.edit.length);
|
||||
break;
|
||||
}
|
||||
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 22)
|
||||
case SDL_TEXTEDITING_EXT:
|
||||
HandleTextEditingEvent(Event.editExt.text, Event.editExt.start, Event.editExt.length);
|
||||
SDL_free(Event.editExt.text);
|
||||
break;
|
||||
#endif
|
||||
|
||||
case SDL_TEXTINPUT:
|
||||
m_aComposition[0] = '\0';
|
||||
m_CompositionLength = COMP_LENGTH_INACTIVE;
|
||||
m_CompositionString = "";
|
||||
m_CompositionCursor = 0;
|
||||
AddTextEvent(Event.text.text);
|
||||
break;
|
||||
|
@ -861,9 +868,6 @@ int CInput::Update()
|
|||
}
|
||||
}
|
||||
|
||||
if(m_CompositionLength == 0)
|
||||
m_CompositionLength = COMP_LENGTH_INACTIVE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -84,9 +84,8 @@ private:
|
|||
#endif
|
||||
|
||||
// IME support
|
||||
char m_aComposition[MAX_COMPOSITION_ARRAY_SIZE];
|
||||
std::string m_CompositionString;
|
||||
int m_CompositionCursor;
|
||||
int m_CompositionLength;
|
||||
std::vector<std::string> m_vCandidates;
|
||||
int m_CandidateSelectedIndex;
|
||||
|
||||
|
@ -113,6 +112,7 @@ private:
|
|||
void HandleTouchDownEvent(const SDL_TouchFingerEvent &Event);
|
||||
void HandleTouchUpEvent(const SDL_TouchFingerEvent &Event);
|
||||
void HandleTouchMotionEvent(const SDL_TouchFingerEvent &Event);
|
||||
void HandleTextEditingEvent(const char *pText, int Start, int Length);
|
||||
|
||||
char m_aDropFile[IO_MAX_PATH_LENGTH];
|
||||
|
||||
|
@ -155,10 +155,10 @@ public:
|
|||
|
||||
void StartTextInput() override;
|
||||
void StopTextInput() override;
|
||||
const char *GetComposition() const override { return m_aComposition; }
|
||||
bool HasComposition() const override { return m_CompositionLength != COMP_LENGTH_INACTIVE; }
|
||||
const char *GetComposition() const override { return m_CompositionString.c_str(); }
|
||||
bool HasComposition() const override { return !m_CompositionString.empty(); }
|
||||
int GetCompositionCursor() const override { return m_CompositionCursor; }
|
||||
int GetCompositionLength() const override { return m_CompositionLength; }
|
||||
int GetCompositionLength() const override { return m_CompositionString.length(); }
|
||||
const char *GetCandidate(int Index) const override { return m_vCandidates[Index].c_str(); }
|
||||
int GetCandidateCount() const override { return m_vCandidates.size(); }
|
||||
int GetCandidateSelectedIndex() const override { return m_CandidateSelectedIndex; }
|
||||
|
|
|
@ -19,18 +19,13 @@ class IInput : public IInterface
|
|||
{
|
||||
MACRO_INTERFACE("input")
|
||||
public:
|
||||
enum
|
||||
{
|
||||
INPUT_TEXT_SIZE = 32 * UTF8_BYTE_LENGTH + 1,
|
||||
};
|
||||
|
||||
class CEvent
|
||||
{
|
||||
public:
|
||||
int m_Flags;
|
||||
int m_Key;
|
||||
uint32_t m_InputCount;
|
||||
char m_aText[INPUT_TEXT_SIZE];
|
||||
char m_aText[32]; // SDL_TEXTINPUTEVENT_TEXT_SIZE
|
||||
};
|
||||
|
||||
enum
|
||||
|
@ -45,12 +40,6 @@ public:
|
|||
CURSOR_MOUSE,
|
||||
CURSOR_JOYSTICK,
|
||||
};
|
||||
enum
|
||||
{
|
||||
MAX_COMPOSITION_ARRAY_SIZE = 32, // SDL2 limitation
|
||||
|
||||
COMP_LENGTH_INACTIVE = -1,
|
||||
};
|
||||
|
||||
// events
|
||||
virtual void ConsumeEvents(std::function<void(const CEvent &Event)> Consumer) const = 0;
|
||||
|
|
Loading…
Reference in a new issue