Skip to content

Commit

Permalink
Proper text input handling in all known cases (closes #844, closes #1100
Browse files Browse the repository at this point in the history
)

Thanks @Plotja
  • Loading branch information
Xottab-DUTY committed Oct 19, 2023
1 parent f1bd1ab commit 83dce7d
Show file tree
Hide file tree
Showing 9 changed files with 94 additions and 47 deletions.
36 changes: 26 additions & 10 deletions src/xrEngine/editor_base.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,31 @@ void ide::OnAppEnd()
Device.seqRender.Remove(this);
}

void ide::UpdateTextInput(bool force_disable /*= false*/)
{
if (force_disable)
{
if (m_text_input_enabled)
{
pInput->DisableTextInput();
m_text_input_enabled = false;
}
return;
}

const ImGuiIO& io = ImGui::GetIO();

if (m_text_input_enabled != io.WantTextInput)
{
m_text_input_enabled = io.WantTextInput;

if (m_text_input_enabled)
pInput->EnableTextInput();
else
pInput->DisableTextInput();
}
}

void ide::OnFrame()
{
const float frametime = m_timer.GetElapsed_sec();
Expand All @@ -118,22 +143,13 @@ void ide::OnFrame()
ImGuiIO& io = ImGui::GetIO();
io.DeltaTime = frametime;

// When shown, input being is updated
// through IInputReceiver interface
if (m_state == visible_state::full)
{
if (io.WantTextInput)
SDL_StartTextInput();
else
SDL_StopTextInput();
}

m_render->Frame();
ImGui::NewFrame();

switch (m_state)
{
case visible_state::full:
UpdateTextInput();
ShowMain();
[[fallthrough]];

Expand Down
7 changes: 5 additions & 2 deletions src/xrEngine/editor_base.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,8 @@ class ENGINE_API ide final :
void OnAppStart() override;
void OnAppEnd() override;

void IR_Capture() override;
void IR_Release() override;
void IR_OnActivate() override;
void IR_OnDeactivate() override;

void IR_OnMousePress(int key) override;
void IR_OnMouseRelease(int key) override;
Expand Down Expand Up @@ -109,6 +109,8 @@ class ENGINE_API ide final :
void RegisterTool(ide_tool* tool);
void UnregisterTool(const ide_tool* tool);

void UpdateTextInput(bool force_disable = false);

private:
CTimer m_timer;
IImGuiRender* m_render{};
Expand All @@ -117,6 +119,7 @@ class ENGINE_API ide final :

visible_state m_state;
bool m_show_weather_editor; // to be refactored
bool m_text_input_enabled{};

xr_vector<ide_tool*> m_tools;
};
Expand Down
12 changes: 6 additions & 6 deletions src/xrEngine/editor_base_input.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,17 +62,16 @@ void ide::OnAppDeactivate()
io.AddFocusEvent(false);
}

void ide::IR_Capture()
void ide::IR_OnActivate()
{
IInputReceiver::IR_Capture();
ImGuiIO& io = ImGui::GetIO();
io.MouseDrawCursor = true;
}

void ide::IR_Release()
void ide::IR_OnDeactivate()
{
SDL_StopTextInput();
IInputReceiver::IR_Release();
UpdateTextInput(true);

ImGuiIO& io = ImGui::GetIO();
io.MouseDrawCursor = false;
}
Expand Down Expand Up @@ -212,7 +211,8 @@ void ide::IR_OnKeyboardHold(int /*key*/)
void ide::IR_OnTextInput(pcstr text)
{
ImGuiIO& io = ImGui::GetIO();
io.AddInputCharactersUTF8(text);
if (io.WantTextInput)
io.AddInputCharactersUTF8(text);
}

void ide::IR_OnControllerPress(int key, float x, float y)
Expand Down
7 changes: 2 additions & 5 deletions src/xrEngine/line_edit_control.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -152,15 +152,12 @@ void line_edit_control::clear_states()

void line_edit_control::on_ir_capture()
{
SDL_PumpEvents();
SDL_StartTextInput();
SDL_FlushEvents(SDL_TEXTEDITING, SDL_TEXTINPUT);
pInput->EnableTextInput();
}

void line_edit_control::on_ir_release()
{
SDL_StopTextInput();
SDL_FlushEvents(SDL_TEXTEDITING, SDL_TEXTINPUT);
pInput->DisableTextInput();
}

void line_edit_control::init(size_t str_buffer_size, init_mode mode)
Expand Down
10 changes: 2 additions & 8 deletions src/xrEngine/line_editor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,10 @@ void line_editor::IR_OnKeyboardHold(int dik) { m_control.on_key_hold(dik); }
void line_editor::IR_OnKeyboardRelease(int dik) { m_control.on_key_release(dik); }
void line_editor::IR_OnTextInput(const char *text) { m_control.on_text_input(text); }

void line_editor::IR_Capture()
void line_editor::IR_OnActivate()
{
IInputReceiver::IR_Capture();
m_control.on_ir_capture();
}

void line_editor::IR_Release()
{
m_control.on_ir_release();
IInputReceiver::IR_Release();
IInputReceiver::IR_OnDeactivate();
}

void line_editor::IR_OnDeactivate()
Expand Down
3 changes: 1 addition & 2 deletions src/xrEngine/line_editor.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,7 @@ class line_editor : public IInputReceiver
IC line_edit_control& control() { return m_control; }
void on_frame();

void IR_Capture() final;
void IR_Release() final;
void IR_OnActivate() final;
void IR_OnDeactivate() final;

protected:
Expand Down
38 changes: 38 additions & 0 deletions src/xrEngine/xr_input.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,13 @@ void CInput::KeyUpdate()
if (count)
SetCurrentInputType(KeyboardMouse);

// If textInputCounter has changed,
// we assume that text input target changed.
// Theoretically, this is not always true, though.
// But we always can change the solution.
// If we find out something not work as expected.
const auto cnt = textInputCounter;

for (int i = 0; i < count; ++i)
{
const SDL_Event& event = events[i];
Expand All @@ -245,6 +252,8 @@ void CInput::KeyUpdate()
break;

case SDL_TEXTINPUT:
if (cnt != textInputCounter)
continue; // if input target changed, skip this frame
cbStack.back()->IR_OnTextInput(event.text.text);
break;

Expand Down Expand Up @@ -536,6 +545,35 @@ bool CInput::InputIsGrabbed() const
return inputGrabbed;
}

void CInput::EnableTextInput()
{
++textInputCounter;

if (textInputCounter == 1)
SDL_StartTextInput();

SDL_PumpEvents();
SDL_FlushEvents(SDL_TEXTEDITING, SDL_TEXTINPUT);
}

void CInput::DisableTextInput()
{
--textInputCounter;
if (textInputCounter < 0)
textInputCounter = 0;

if (textInputCounter == 0)
SDL_StopTextInput();

SDL_PumpEvents();
SDL_FlushEvents(SDL_TEXTEDITING, SDL_TEXTINPUT);
}

bool CInput::IsTextInputEnabled() const
{
return textInputCounter > 0;
}

void CInput::RegisterKeyMapChangeWatcher(pureKeyMapChanged* watcher, int priority /*= REG_PRIORITY_NORMAL*/)
{
seqKeyMapChanged.Add(watcher, priority);
Expand Down
5 changes: 5 additions & 0 deletions src/xrEngine/xr_input.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ class ENGINE_API CInput
InputStatistics stats;
bool exclusiveInput;
bool inputGrabbed;
int textInputCounter{};

MessageRegistry<pureKeyMapChanged> seqKeyMapChanged;

Expand All @@ -144,6 +145,10 @@ class ENGINE_API CInput
void GrabInput(const bool grab);
bool InputIsGrabbed() const;

void EnableTextInput();
void DisableTextInput();
bool IsTextInputEnabled() const;

void RegisterKeyMapChangeWatcher(pureKeyMapChanged* watcher, int priority = REG_PRIORITY_NORMAL);
void RemoveKeyMapChangeWatcher(pureKeyMapChanged* watcher);

Expand Down
23 changes: 9 additions & 14 deletions src/xrUICore/EditBox/UICustomEdit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,13 +93,9 @@ void CUICustomEdit::SendMessage(CUIWindow* pWnd, s16 msg, void* pData)
//кто-то другой захватил клавиатуру
if (msg == WINDOW_KEYBOARD_CAPTURE_LOST && m_bInputFocus)
{
m_bInputFocus = false;
CaptureFocus(false);
GetMessageTarget()->SendMessage(this, EDIT_TEXT_COMMIT, NULL);
}
else if (msg == WINDOW_FOCUS_RECEIVED)
ec().on_ir_capture();
else if (msg == WINDOW_FOCUS_LOST)
ec().on_ir_release();
}

bool CUICustomEdit::OnMouseAction(float x, float y, EUIMessages mouse_action)
Expand All @@ -108,25 +104,21 @@ bool CUICustomEdit::OnMouseAction(float x, float y, EUIMessages mouse_action)
{
if (mouse_action == WINDOW_LBUTTON_DB_CLICK && !m_bInputFocus)
{
GetParent()->SetKeyboardCapture(this, true);
m_bInputFocus = true;
CaptureFocus(true);
}
}

if (mouse_action == WINDOW_LBUTTON_DOWN && !m_bInputFocus)
{
GetParent()->SetKeyboardCapture(this, true);
m_bInputFocus = true;
CaptureFocus(true);
}
return false;
}

bool CUICustomEdit::OnKeyboardAction(int dik, EUIMessages keyboard_action)
{
if (!m_bInputFocus)
{
return false;
}

switch (keyboard_action)
{
Expand All @@ -148,6 +140,9 @@ bool CUICustomEdit::OnKeyboardAction(int dik, EUIMessages keyboard_action)

bool CUICustomEdit::OnTextInput(pcstr text)
{
if (!m_bInputFocus)
return false;

ec().on_text_input(text);
return true;
}
Expand Down Expand Up @@ -274,15 +269,15 @@ void CUICustomEdit::press_escape()
}
else
{
m_bInputFocus = false;
CaptureFocus(false);
GetParent()->SetKeyboardCapture(this, false);
GetMessageTarget()->SendMessage(this, EDIT_TEXT_CANCEL, NULL);
}
}

void CUICustomEdit::press_commit()
{
m_bInputFocus = false;
CaptureFocus(false);
GetParent()->SetKeyboardCapture(this, false);
GetMessageTarget()->SendMessage(this, EDIT_TEXT_COMMIT, NULL);
}
Expand All @@ -292,7 +287,7 @@ void CUICustomEdit::press_tab()
if (!m_next_focus_capturer)
return;

m_bInputFocus = false;
CaptureFocus(false);
GetParent()->SetKeyboardCapture(this, false);
GetMessageTarget()->SendMessage(this, EDIT_TEXT_COMMIT, NULL);
GetParent()->SetKeyboardCapture(m_next_focus_capturer, true);
Expand Down

0 comments on commit 83dce7d

Please sign in to comment.