mirror of
https://github.com/RetroDECK/ES-DE.git
synced 2024-11-22 22:25:38 +00:00
Improved the behavior and consistency for the virtual keyboard when using non-standard keyboard mappings.
This commit is contained in:
parent
de747a932d
commit
cfc9d54068
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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();
|
||||||
|
|
Loading…
Reference in a new issue