Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prevent excessive calls to deleteBackward method which may cause crashes on Android #2248

Merged
merged 4 commits into from
Nov 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 20 additions & 8 deletions core/2d/TextFieldTTF.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/

#include <algorithm>

#include "2d/TextFieldTTF.h"

#include "base/Director.h"
Expand Down Expand Up @@ -310,7 +312,7 @@ void TextFieldTTF::insertText(const char* text, size_t len)
detachWithIME();
}

void TextFieldTTF::deleteBackward()
void TextFieldTTF::deleteBackward(size_t numChars)
{
size_t len = _inputText.length();
if (!len)
Expand All @@ -319,23 +321,33 @@ void TextFieldTTF::deleteBackward()
return;
}

// get the delete byte number
size_t deleteLen = 1; // default, erase 1 byte
// Length of characters to delete is based on input editor, but the actual
// length of the displayed text may be less
numChars = std::min(numChars, len);

while (0x80 == (0xC0 & _inputText.at(len - deleteLen)))
size_t totalDeleteLen = 0;
for (auto i = 0; i < numChars; ++i)
{
++deleteLen;
// get the delete byte number
size_t deleteLen = 1; // default, erase 1 byte

// Calculate the actual number of bytes to delete for a specific character
while (0x80 == (0xC0 & _inputText.at(len - totalDeleteLen - deleteLen)))
{
++deleteLen;
}
totalDeleteLen += deleteLen;
}

if (_delegate &&
_delegate->onTextFieldDeleteBackward(this, _inputText.c_str() + len - deleteLen, static_cast<int>(deleteLen)))
_delegate->onTextFieldDeleteBackward(this, _inputText.c_str() + len - totalDeleteLen, static_cast<int>(totalDeleteLen)))
{
// delegate doesn't want to delete backwards
return;
}

// if all text deleted, show placeholder string
if (len <= deleteLen)
if (len <= totalDeleteLen)
{
_inputText = "";
_charCount = 0;
Expand All @@ -362,7 +374,7 @@ void TextFieldTTF::deleteBackward()
}
else
{
std::string text(_inputText.c_str(), len - deleteLen);
std::string text(_inputText.c_str(), len - totalDeleteLen);
setString(text);
}
}
Expand Down
2 changes: 1 addition & 1 deletion core/2d/TextFieldTTF.h
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,7 @@ class AX_DLL TextFieldTTF : public Label, public IMEDelegate
virtual void didAttachWithIME() override;
virtual void didDetachWithIME() override;
virtual void insertText(const char* text, size_t len) override;
virtual void deleteBackward() override;
virtual void deleteBackward(size_t numChars) override;
virtual std::string_view getContentText() override;
virtual void controlKey(EventKeyboard::KeyCode keyCode) override;

Expand Down
2 changes: 1 addition & 1 deletion core/base/IMEDelegate.h
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ class AX_DLL IMEDelegate
* @js NA
* @lua NA
*/
virtual void deleteBackward() {}
virtual void deleteBackward(size_t numChars) {}

/**
@brief Called by IMEDispatcher after the user press control key.
Expand Down
4 changes: 2 additions & 2 deletions core/base/IMEDispatcher.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ void IMEDispatcher::dispatchInsertText(const char* text, size_t len)
} while (0);
}

void IMEDispatcher::dispatchDeleteBackward()
void IMEDispatcher::dispatchDeleteBackward(int numChars)
{
do
{
Expand All @@ -231,7 +231,7 @@ void IMEDispatcher::dispatchDeleteBackward()
// there is no delegate attached to IME
AX_BREAK_IF(!_impl->_delegateWithIme);

_impl->_delegateWithIme->deleteBackward();
_impl->_delegateWithIme->deleteBackward(numChars);
} while (0);
}

Expand Down
2 changes: 1 addition & 1 deletion core/base/IMEDispatcher.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ class AX_DLL IMEDispatcher
* @brief Dispatches the delete-backward operation.
* @lua NA
*/
void dispatchDeleteBackward();
void dispatchDeleteBackward(int numChars);

/**
* @brief Dispatches the press control key operation.
Expand Down
2 changes: 1 addition & 1 deletion core/platform/GLViewImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1220,7 +1220,7 @@ void GLViewImpl::onGLFWKeyCallback(GLFWwindow* /*window*/, int key, int /*scanco
switch (g_keyCodeMap[key])
{
case EventKeyboard::KeyCode::KEY_BACKSPACE:
IMEDispatcher::sharedDispatcher()->dispatchDeleteBackward();
IMEDispatcher::sharedDispatcher()->dispatchDeleteBackward(1);
break;
case EventKeyboard::KeyCode::KEY_HOME:
case EventKeyboard::KeyCode::KEY_KP_HOME:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -458,11 +458,11 @@ public void run() {
});
}

public void deleteBackward() {
public void deleteBackward(int numChars) {
this.queueEvent(new Runnable() {
@Override
public void run() {
AxmolGLSurfaceView.this.mRenderer.handleDeleteBackward();
AxmolGLSurfaceView.this.mRenderer.handleDeleteBackward(numChars);
}
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -176,15 +176,15 @@ public void handleOnResume() {
}

private static native void nativeInsertText(final String text);
private static native void nativeDeleteBackward();
private static native void nativeDeleteBackward(final int numChars);
private static native String nativeGetContentText();

public void handleInsertText(final String text) {
AxmolRenderer.nativeInsertText(text);
}

public void handleDeleteBackward() {
AxmolRenderer.nativeDeleteBackward();
public void handleDeleteBackward(final int numChars) {
AxmolRenderer.nativeDeleteBackward(numChars);
}

public String getContentText() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,8 @@ public void afterTextChanged(final Editable s) {
new_i += 1;
}

for (; old_i < this.mText.length(); ++old_i) {
this.mGLSurfaceView.deleteBackward();
if (old_i < this.mText.length()) {
this.mGLSurfaceView.deleteBackward(this.mText.length() - old_i);
}

int nModified = s.length() - new_i;
Expand All @@ -118,13 +118,13 @@ public boolean onEditorAction(final TextView pTextView, final int pActionID, fin
if (this.mGLSurfaceView.getEditText() == pTextView && this.isFullScreenEdit()) {
// user press the action button, delete all old text and insert new text
if (null != mOriginText) {
for (int i = this.mOriginText.length(); i > 0; i--) {
this.mGLSurfaceView.deleteBackward();
if (!this.mOriginText.isEmpty()) {
this.mGLSurfaceView.deleteBackward(this.mOriginText.length());
}
}

String text = pTextView.getText().toString();

if (text != null) {
/* If user input nothing, translate "\n" to engine. */
if ( text.compareTo("") == 0) {
Expand All @@ -135,16 +135,16 @@ public boolean onEditorAction(final TextView pTextView, final int pActionID, fin
text += '\n';
}
}

final String insertText = text;
this.mGLSurfaceView.insertText(insertText);

}

if (pActionID == EditorInfo.IME_ACTION_DONE) {
this.mGLSurfaceView.requestFocus();
}
return false;
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,9 @@ JNIEXPORT void JNICALL Java_org_axmol_lib_AxmolRenderer_nativeInsertText(JNIEnv*
ax::IMEDispatcher::sharedDispatcher()->dispatchInsertText(pszText, strlen(pszText));
}

JNIEXPORT void JNICALL Java_org_axmol_lib_AxmolRenderer_nativeDeleteBackward(JNIEnv*, jclass)
JNIEXPORT void JNICALL Java_org_axmol_lib_AxmolRenderer_nativeDeleteBackward(JNIEnv*, jclass, jint numChars)
{
ax::IMEDispatcher::sharedDispatcher()->dispatchDeleteBackward();
ax::IMEDispatcher::sharedDispatcher()->dispatchDeleteBackward(numChars);
}

JNIEXPORT jstring JNICALL Java_org_axmol_lib_AxmolRenderer_nativeGetContentText(JNIEnv* env, jclass)
Expand Down
2 changes: 1 addition & 1 deletion core/platform/ios/InputView-ios.mm
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ - (void)deleteBackward
[self.myMarkedText release];
self.myMarkedText = nil;
}
ax::IMEDispatcher::sharedDispatcher()->dispatchDeleteBackward();
ax::IMEDispatcher::sharedDispatcher()->dispatchDeleteBackward(1);
}

- (void)insertText:(nonnull NSString*)text
Expand Down
2 changes: 1 addition & 1 deletion core/platform/winrt/InputEvent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ void KeyboardEvent::execute()
//Director::getInstance()()->getKeypadDispatcher()->dispatchKeypadMSG(kTypeBackClicked);
break;
case AxmolKeyEvent::Back:
IMEDispatcher::sharedDispatcher()->dispatchDeleteBackward();
IMEDispatcher::sharedDispatcher()->dispatchDeleteBackward(1);
break;
case AxmolKeyEvent::Enter:
IMEDispatcher::sharedDispatcher()->dispatchInsertText("\n", 1);
Expand Down
2 changes: 1 addition & 1 deletion core/platform/winrt/Keyboard-winrt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -304,7 +304,7 @@ void KeyBoardWinRT::OnWinRTKeyboardEvent(WinRTKeyboardEventType type, KeyEventAr
switch (keyCode)
{
case EventKeyboard::KeyCode::KEY_BACKSPACE:
IMEDispatcher::sharedDispatcher()->dispatchDeleteBackward();
IMEDispatcher::sharedDispatcher()->dispatchDeleteBackward(1);
break;
case EventKeyboard::KeyCode::KEY_HOME:
case EventKeyboard::KeyCode::KEY_KP_HOME:
Expand Down
26 changes: 18 additions & 8 deletions core/ui/UITextFieldEx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -617,7 +617,7 @@ void TextFieldEx::insertText(const char* text, size_t len)
this->closeIME();
}

void TextFieldEx::deleteBackward()
void TextFieldEx::deleteBackward(size_t numChars)
{
if (!_editable || !this->_enabled || 0 == _charCount)
{
Expand All @@ -634,23 +634,33 @@ void TextFieldEx::deleteBackward()
return;
}

// get the delete byte number
size_t deleteLen = 1; // default, erase 1 byte
// Length of characters to delete is based on input editor, but the actual
// length of the displayed text may be less
numChars = std::min(numChars, len);

while (0x80 == (0xC0 & _inputText.at(_insertPos - deleteLen)))
size_t totalDeleteLen = 0;
for (auto i = 0; i < numChars; ++i)
{
++deleteLen;
// get the delete byte number
size_t deleteLen = 1; // default, erase 1 byte

// Calculate the actual number of bytes to delete for a specific character
while (0x80 == (0xC0 & _inputText.at(_insertPos - totalDeleteLen - deleteLen)))
{
++deleteLen;
}
totalDeleteLen += deleteLen;
}

// if (_delegate && _delegate->onTextFieldDeleteBackward(this, _inputText.c_str() + len - deleteLen,
// static_cast<int>(deleteLen)))
//{
// // delegate doesn't wan't to delete backwards
// // delegate doesn't want to delete backwards
// return;
// }

// if all text deleted, show placeholder string
if (len <= deleteLen)
if (len <= totalDeleteLen)
{
__moveCursor(-1);

Expand All @@ -670,7 +680,7 @@ void TextFieldEx::deleteBackward()

// set new input text
std::string text = _inputText; // (inputText.c_str(), len - deleteLen);
text.erase(_insertPos - deleteLen, deleteLen);
text.erase(_insertPos - totalDeleteLen, totalDeleteLen);

__moveCursor(-1);

Expand Down
2 changes: 1 addition & 1 deletion core/ui/UITextFieldEx.h
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ class AX_DLL TextFieldEx : public Widget, public IMEDelegate
bool canAttachWithIME() override;
bool canDetachWithIME() override;

void deleteBackward() override;
void deleteBackward(size_t numChars) override;
std::string_view getContentText() override;

void handleDeleteKeyEvent();
Expand Down
1 change: 1 addition & 0 deletions core/ui/axmol-ui.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ THE SOFTWARE.
#include "ui/UIListView.h"
#include "ui/UISlider.h"
#include "ui/UITextField.h"
#include "ui/UITextFieldEx.h"
#include "ui/UITextBMFont.h"
#include "ui/UIPageView.h"
#include "ui/UIHelper.h"
Expand Down