Improved the behavior and consistency for the virtual keyboard when using non-standard keyboard mappings.

This commit is contained in:
Leon Styhre 2022-06-10 19:28:01 +02:00
parent de747a932d
commit cfc9d54068
4 changed files with 83 additions and 73 deletions

View file

@ -22,6 +22,7 @@ TextEditComponent::TextEditComponent()
: mRenderer {Renderer::getInstance()} : mRenderer {Renderer::getInstance()}
, mFocused {false} , mFocused {false}
, mEditing {false} , mEditing {false}
, mMaskInput {true}
, mCursor {0} , mCursor {0}
, mBlinkTime {0} , mBlinkTime {0}
, mCursorRepeatDir {0} , mCursorRepeatDir {0}
@ -66,6 +67,9 @@ void TextEditComponent::setValue(const std::string& val)
void TextEditComponent::textInput(const std::string& text) void TextEditComponent::textInput(const std::string& text)
{ {
if (mMaskInput)
return;
if (mEditing) { if (mEditing) {
mBlinkTime = 0; mBlinkTime = 0;
mCursorRepeatDir = 0; mCursorRepeatDir = 0;
@ -114,37 +118,32 @@ void TextEditComponent::stopEditing()
{ {
SDL_StopTextInput(); SDL_StopTextInput();
mEditing = false; mEditing = false;
mMaskInput = false;
mCursorRepeatDir = 0; mCursorRepeatDir = 0;
updateHelpPrompts(); updateHelpPrompts();
} }
bool TextEditComponent::input(InputConfig* config, Input input) bool TextEditComponent::input(InputConfig* config, Input input)
{ {
bool const cursor_left = bool const cursorLeft {config->isMappedLike("left", input)};
(config->getDeviceId() != DEVICE_KEYBOARD && config->isMappedLike("left", input)) || bool const cursorRight {config->isMappedLike("right", input)};
(config->getDeviceId() == DEVICE_KEYBOARD && input.id == SDLK_LEFT); bool const cursorUp {config->isMappedLike("up", input)};
bool const cursor_right = bool const cursorDown {config->isMappedLike("down", input)};
(config->getDeviceId() != DEVICE_KEYBOARD && config->isMappedLike("right", input)) || bool const shoulderLeft {config->isMappedLike("leftshoulder", input)};
(config->getDeviceId() == DEVICE_KEYBOARD && input.id == SDLK_RIGHT); bool const shoulderRight {config->isMappedLike("rightshoulder", input)};
bool const cursor_up = bool const triggerLeft {config->isMappedLike("lefttrigger", input)};
(config->getDeviceId() != DEVICE_KEYBOARD && config->isMappedLike("up", input)) || bool const triggerRight {config->isMappedLike("righttrigger", input)};
(config->getDeviceId() == DEVICE_KEYBOARD && input.id == SDLK_UP);
bool const cursor_down =
(config->getDeviceId() != DEVICE_KEYBOARD && config->isMappedLike("down", input)) ||
(config->getDeviceId() == DEVICE_KEYBOARD && input.id == SDLK_DOWN);
bool const shoulder_left = (config->isMappedLike("leftshoulder", input));
bool const shoulder_right = (config->isMappedLike("rightshoulder", input));
bool const trigger_left = (config->isMappedLike("lefttrigger", input));
bool const trigger_right = (config->isMappedLike("righttrigger", input));
if (input.value == 0) { mMaskInput = true;
if (cursor_left || cursor_right || cursor_up || cursor_down || shoulder_left ||
shoulder_right | trigger_left || trigger_right) { if (cursorLeft || cursorRight || cursorUp || cursorDown || shoulderLeft ||
shoulderRight | triggerLeft || triggerRight) {
if (input.value == 0)
mCursorRepeatDir = 0; mCursorRepeatDir = 0;
} }
if (input.value == 0)
return false; return false;
}
if ((config->isMappedTo("a", input) || if ((config->isMappedTo("a", input) ||
(config->getDeviceId() == DEVICE_KEYBOARD && input.id == SDLK_RETURN)) && (config->getDeviceId() == DEVICE_KEYBOARD && input.id == SDLK_RETURN)) &&
@ -154,7 +153,9 @@ bool TextEditComponent::input(InputConfig* config, Input input)
} }
if (mEditing) { if (mEditing) {
if (config->getDeviceId() == DEVICE_KEYBOARD && input.id == SDLK_RETURN) { if (config->getDeviceId() == DEVICE_KEYBOARD) {
// Special handling for keyboard input as the "A" and "B" buttons are overridden.
if (input.id == SDLK_RETURN) {
if (isMultiline()) if (isMultiline())
textInput("\n"); textInput("\n");
else else
@ -162,55 +163,54 @@ bool TextEditComponent::input(InputConfig* config, Input input)
return true; return true;
} }
else if (input.id == SDLK_DELETE) {
if (cursor_left || cursor_right) {
mBlinkTime = 0;
mCursorRepeatDir = cursor_left ? -1 : 1;
mCursorRepeatTimer = -(CURSOR_REPEAT_START_DELAY - CURSOR_REPEAT_SPEED);
moveCursor(mCursorRepeatDir);
}
// Stop editing and let the button down event be captured by the parent component.
else if (cursor_down) {
stopEditing();
return false;
}
else if (shoulder_left || shoulder_right) {
mBlinkTime = 0;
mCursorRepeatDir = shoulder_left ? -10 : 10;
mCursorRepeatTimer = -(CURSOR_REPEAT_START_DELAY - CURSOR_REPEAT_SPEED);
moveCursor(mCursorRepeatDir);
}
// Jump to beginning of text.
else if (trigger_left) {
mBlinkTime = 0;
setCursor(0);
}
// Jump to end of text.
else if (trigger_right) {
mBlinkTime = 0;
setCursor(mText.length());
}
else if (config->getDeviceId() == DEVICE_KEYBOARD) {
switch (input.id) {
case SDLK_HOME: {
setCursor(0);
break;
}
case SDLK_END: {
setCursor(std::string::npos);
break;
}
case SDLK_DELETE: {
if (mCursor < static_cast<int>(mText.length())) { if (mCursor < static_cast<int>(mText.length())) {
// Fake as Backspace one char to the right. // Fake as Backspace one char to the right.
mMaskInput = false;
moveCursor(1); moveCursor(1);
textInput("\b"); textInput("\b");
} }
break; return true;
}
else if (input.id == SDLK_BACKSPACE) {
mMaskInput = false;
textInput("\b");
return true;
} }
} }
if (cursorLeft || cursorRight) {
mBlinkTime = 0;
mCursorRepeatDir = cursorLeft ? -1 : 1;
mCursorRepeatTimer = -(CURSOR_REPEAT_START_DELAY - CURSOR_REPEAT_SPEED);
moveCursor(mCursorRepeatDir);
return false;
} }
else if (cursorDown) {
// Stop editing and let the button down event be captured by the parent component.
stopEditing();
return false;
}
else if (shoulderLeft) {
mMaskInput = false;
textInput("\b");
return true;
}
else if (triggerLeft) {
// Jump to beginning of text.
mBlinkTime = 0;
setCursor(0);
return true;
}
else if (triggerRight) {
// Jump to end of text.
mBlinkTime = 0;
setCursor(mText.length());
return true;
}
// Consume all input when editing text. // Consume all input when editing text.
mMaskInput = false;
return true; return true;
} }

View file

@ -42,6 +42,7 @@ public:
std::shared_ptr<Font> getFont() const override { return mFont; } std::shared_ptr<Font> getFont() const override { return mFont; }
void setCursor(size_t pos); void setCursor(size_t pos);
void setMaskInput(bool state) { mMaskInput = state; }
std::vector<HelpPrompt> getHelpPrompts() override; std::vector<HelpPrompt> getHelpPrompts() override;
@ -61,6 +62,7 @@ private:
std::string mTextOrig; std::string mTextOrig;
bool mFocused; bool mFocused;
bool mEditing; bool mEditing;
bool mMaskInput;
int mCursor; // Cursor position in characters. int mCursor; // Cursor position in characters.
int mBlinkTime; int mBlinkTime;

View file

@ -340,15 +340,13 @@ bool GuiTextEditKeyboardPopup::input(InputConfig* config, Input input)
mNavigationRepeatDirY = 0; mNavigationRepeatDirY = 0;
} }
// If the keyboard has been configured with backspace as the back button (which is the default // Ignore whatever key is mapped to the back button so it can be used for text input.
// configuration) then ignore this key if we're currently editing or otherwise it would be bool keyboardBack {config->getDeviceId() == DEVICE_KEYBOARD && mText->isEditing() &&
// impossible to erase characters using this key. config->isMappedLike("b", input)};
bool keyboardBackspace = (config->getDeviceId() == DEVICE_KEYBOARD && mText->isEditing() &&
input.id == SDLK_BACKSPACE);
// Pressing back (or the escape key if using keyboard input) closes us. // Pressing back (or the escape key if using keyboard input) closes us.
if ((config->getDeviceId() == DEVICE_KEYBOARD && input.value && input.id == SDLK_ESCAPE) || if ((config->getDeviceId() == DEVICE_KEYBOARD && input.value && input.id == SDLK_ESCAPE) ||
(!keyboardBackspace && input.value && config->isMappedTo("b", input))) { (!keyboardBack && input.value && config->isMappedTo("b", input))) {
if (mText->getValue() != mInitValue) { if (mText->getValue() != mInitValue) {
// Changes were made, ask if the user wants to save them. // Changes were made, ask if the user wants to save them.
mWindow->pushGui(new GuiMsgBox( mWindow->pushGui(new GuiMsgBox(
@ -393,7 +391,9 @@ bool GuiTextEditKeyboardPopup::input(InputConfig* config, Input input)
if (!editing) if (!editing)
mText->startEditing(); mText->startEditing();
mText->setMaskInput(false);
mText->textInput("\b"); mText->textInput("\b");
mText->setMaskInput(true);
if (!editing) if (!editing)
mText->stopEditing(); mText->stopEditing();
@ -410,7 +410,9 @@ bool GuiTextEditKeyboardPopup::input(InputConfig* config, Input input)
if (!editing) if (!editing)
mText->startEditing(); mText->startEditing();
mText->setMaskInput(false);
mText->textInput(" "); mText->textInput(" ");
mText->setMaskInput(true);
if (!editing) if (!editing)
mText->stopEditing(); mText->stopEditing();
@ -523,7 +525,9 @@ void GuiTextEditKeyboardPopup::updateDeleteRepeat(int deltaTime)
if (!editing) if (!editing)
mText->startEditing(); mText->startEditing();
mText->setMaskInput(false);
mText->textInput("\b"); mText->textInput("\b");
mText->setMaskInput(true);
if (!editing) if (!editing)
mText->stopEditing(); mText->stopEditing();

View file

@ -165,15 +165,13 @@ bool GuiTextEditPopup::input(InputConfig* config, Input input)
return true; return true;
} }
// If the keyboard has been configured with backspace as the back button (which is the default // Ignore whatever key is mapped to the back button so it can be used for text input.
// configuration) then ignore this key if we're currently editing or otherwise it would be bool keyboardBack {config->getDeviceId() == DEVICE_KEYBOARD && mText->isEditing() &&
// impossible to erase characters using this key. config->isMappedLike("b", input)};
bool keyboardBackspace = (config->getDeviceId() == DEVICE_KEYBOARD && mText->isEditing() &&
input.id == SDLK_BACKSPACE);
// Pressing back (or the escape key if using keyboard input) closes us. // Pressing back (or the escape key if using keyboard input) closes us.
if ((config->getDeviceId() == DEVICE_KEYBOARD && input.value && input.id == SDLK_ESCAPE) || if ((config->getDeviceId() == DEVICE_KEYBOARD && input.value && input.id == SDLK_ESCAPE) ||
(!keyboardBackspace && input.value && config->isMappedTo("b", input))) { (!keyboardBack && input.value && config->isMappedTo("b", input))) {
if (mText->getValue() != mInitValue) { if (mText->getValue() != mInitValue) {
// Changes were made, ask if the user wants to save them. // Changes were made, ask if the user wants to save them.
mWindow->pushGui(new GuiMsgBox( mWindow->pushGui(new GuiMsgBox(
@ -210,7 +208,9 @@ bool GuiTextEditPopup::input(InputConfig* config, Input input)
if (!editing) if (!editing)
mText->startEditing(); mText->startEditing();
mText->setMaskInput(false);
mText->textInput("\b"); mText->textInput("\b");
mText->setMaskInput(true);
if (!editing) if (!editing)
mText->stopEditing(); mText->stopEditing();
@ -227,7 +227,9 @@ bool GuiTextEditPopup::input(InputConfig* config, Input input)
if (!editing) if (!editing)
mText->startEditing(); mText->startEditing();
mText->setMaskInput(false);
mText->textInput(" "); mText->textInput(" ");
mText->setMaskInput(true);
if (!editing) if (!editing)
mText->stopEditing(); mText->stopEditing();
@ -272,7 +274,9 @@ void GuiTextEditPopup::updateDeleteRepeat(int deltaTime)
if (!editing) if (!editing)
mText->startEditing(); mText->startEditing();
mText->setMaskInput(false);
mText->textInput("\b"); mText->textInput("\b");
mText->setMaskInput(true);
if (!editing) if (!editing)
mText->stopEditing(); mText->stopEditing();