mirror of
https://github.com/ddnet/ddnet.git
synced 2024-11-09 17:48: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_TOUCH_MOUSE_EVENTS", "0");
|
||||||
SDL_SetHint("SDL_MOUSE_TOUCH_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)
|
#if defined(CONF_PLATFORM_MACOS)
|
||||||
// Hints will not be set if there is an existing override hint or environment variable that takes precedence.
|
// Hints will not be set if there is an existing override hint or environment variable that takes precedence.
|
||||||
// So this respects cli environment overrides.
|
// So this respects cli environment overrides.
|
||||||
|
|
|
@ -70,7 +70,6 @@ CInput::CInput()
|
||||||
|
|
||||||
m_pClipboardText = nullptr;
|
m_pClipboardText = nullptr;
|
||||||
|
|
||||||
m_CompositionLength = COMP_LENGTH_INACTIVE;
|
|
||||||
m_CompositionCursor = 0;
|
m_CompositionCursor = 0;
|
||||||
m_CandidateSelectedIndex = -1;
|
m_CandidateSelectedIndex = -1;
|
||||||
|
|
||||||
|
@ -328,9 +327,8 @@ void CInput::StopTextInput()
|
||||||
SDL_StopTextInput();
|
SDL_StopTextInput();
|
||||||
// disable system messages for performance
|
// disable system messages for performance
|
||||||
SDL_EventState(SDL_SYSWMEVENT, SDL_DISABLE);
|
SDL_EventState(SDL_SYSWMEVENT, SDL_DISABLE);
|
||||||
m_CompositionLength = COMP_LENGTH_INACTIVE;
|
m_CompositionString = "";
|
||||||
m_CompositionCursor = 0;
|
m_CompositionCursor = 0;
|
||||||
m_aComposition[0] = '\0';
|
|
||||||
m_vCandidates.clear();
|
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)
|
void CInput::SetCompositionWindowPosition(float X, float Y, float H)
|
||||||
{
|
{
|
||||||
SDL_Rect Rect;
|
SDL_Rect Rect;
|
||||||
|
@ -658,29 +676,18 @@ int CInput::Update()
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SDL_TEXTEDITING:
|
case SDL_TEXTEDITING:
|
||||||
{
|
HandleTextEditingEvent(Event.edit.text, Event.edit.start, Event.edit.length);
|
||||||
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;
|
|
||||||
}
|
|
||||||
break;
|
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:
|
case SDL_TEXTINPUT:
|
||||||
m_aComposition[0] = '\0';
|
m_CompositionString = "";
|
||||||
m_CompositionLength = COMP_LENGTH_INACTIVE;
|
|
||||||
m_CompositionCursor = 0;
|
m_CompositionCursor = 0;
|
||||||
AddTextEvent(Event.text.text);
|
AddTextEvent(Event.text.text);
|
||||||
break;
|
break;
|
||||||
|
@ -861,9 +868,6 @@ int CInput::Update()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(m_CompositionLength == 0)
|
|
||||||
m_CompositionLength = COMP_LENGTH_INACTIVE;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -84,9 +84,8 @@ private:
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// IME support
|
// IME support
|
||||||
char m_aComposition[MAX_COMPOSITION_ARRAY_SIZE];
|
std::string m_CompositionString;
|
||||||
int m_CompositionCursor;
|
int m_CompositionCursor;
|
||||||
int m_CompositionLength;
|
|
||||||
std::vector<std::string> m_vCandidates;
|
std::vector<std::string> m_vCandidates;
|
||||||
int m_CandidateSelectedIndex;
|
int m_CandidateSelectedIndex;
|
||||||
|
|
||||||
|
@ -113,6 +112,7 @@ private:
|
||||||
void HandleTouchDownEvent(const SDL_TouchFingerEvent &Event);
|
void HandleTouchDownEvent(const SDL_TouchFingerEvent &Event);
|
||||||
void HandleTouchUpEvent(const SDL_TouchFingerEvent &Event);
|
void HandleTouchUpEvent(const SDL_TouchFingerEvent &Event);
|
||||||
void HandleTouchMotionEvent(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];
|
char m_aDropFile[IO_MAX_PATH_LENGTH];
|
||||||
|
|
||||||
|
@ -155,10 +155,10 @@ public:
|
||||||
|
|
||||||
void StartTextInput() override;
|
void StartTextInput() override;
|
||||||
void StopTextInput() override;
|
void StopTextInput() override;
|
||||||
const char *GetComposition() const override { return m_aComposition; }
|
const char *GetComposition() const override { return m_CompositionString.c_str(); }
|
||||||
bool HasComposition() const override { return m_CompositionLength != COMP_LENGTH_INACTIVE; }
|
bool HasComposition() const override { return !m_CompositionString.empty(); }
|
||||||
int GetCompositionCursor() const override { return m_CompositionCursor; }
|
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(); }
|
const char *GetCandidate(int Index) const override { return m_vCandidates[Index].c_str(); }
|
||||||
int GetCandidateCount() const override { return m_vCandidates.size(); }
|
int GetCandidateCount() const override { return m_vCandidates.size(); }
|
||||||
int GetCandidateSelectedIndex() const override { return m_CandidateSelectedIndex; }
|
int GetCandidateSelectedIndex() const override { return m_CandidateSelectedIndex; }
|
||||||
|
|
|
@ -19,18 +19,13 @@ class IInput : public IInterface
|
||||||
{
|
{
|
||||||
MACRO_INTERFACE("input")
|
MACRO_INTERFACE("input")
|
||||||
public:
|
public:
|
||||||
enum
|
|
||||||
{
|
|
||||||
INPUT_TEXT_SIZE = 32 * UTF8_BYTE_LENGTH + 1,
|
|
||||||
};
|
|
||||||
|
|
||||||
class CEvent
|
class CEvent
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
int m_Flags;
|
int m_Flags;
|
||||||
int m_Key;
|
int m_Key;
|
||||||
uint32_t m_InputCount;
|
uint32_t m_InputCount;
|
||||||
char m_aText[INPUT_TEXT_SIZE];
|
char m_aText[32]; // SDL_TEXTINPUTEVENT_TEXT_SIZE
|
||||||
};
|
};
|
||||||
|
|
||||||
enum
|
enum
|
||||||
|
@ -45,12 +40,6 @@ public:
|
||||||
CURSOR_MOUSE,
|
CURSOR_MOUSE,
|
||||||
CURSOR_JOYSTICK,
|
CURSOR_JOYSTICK,
|
||||||
};
|
};
|
||||||
enum
|
|
||||||
{
|
|
||||||
MAX_COMPOSITION_ARRAY_SIZE = 32, // SDL2 limitation
|
|
||||||
|
|
||||||
COMP_LENGTH_INACTIVE = -1,
|
|
||||||
};
|
|
||||||
|
|
||||||
// events
|
// events
|
||||||
virtual void ConsumeEvents(std::function<void(const CEvent &Event)> Consumer) const = 0;
|
virtual void ConsumeEvents(std::function<void(const CEvent &Event)> Consumer) const = 0;
|
||||||
|
|
Loading…
Reference in a new issue