Allow copying from STK edit box to android edit text
This commit is contained in:
parent
e1a7901c4c
commit
34e680bfbd
@ -17,6 +17,11 @@ public class STKEditText extends EditText
|
|||||||
|
|
||||||
private int m_composing_end;
|
private int m_composing_end;
|
||||||
|
|
||||||
|
STKInputConnection m_stk_input_connection;
|
||||||
|
|
||||||
|
/* Used to avoid infinite calling updateSTKEditBox if setText currently
|
||||||
|
* by jni. */
|
||||||
|
private boolean m_from_stk_editbox;
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
private native static void editText2STKEditbox(String full_text, int start,
|
private native static void editText2STKEditbox(String full_text, int start,
|
||||||
int end, int composing_start,
|
int end, int composing_start,
|
||||||
@ -28,31 +33,29 @@ public class STKEditText extends EditText
|
|||||||
setFocusableInTouchMode(true);
|
setFocusableInTouchMode(true);
|
||||||
m_composing_start = 0;
|
m_composing_start = 0;
|
||||||
m_composing_end = 0;
|
m_composing_end = 0;
|
||||||
|
m_from_stk_editbox = false;
|
||||||
|
m_stk_input_connection = null;
|
||||||
}
|
}
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
@Override
|
@Override
|
||||||
public InputConnection onCreateInputConnection(EditorInfo out_attrs)
|
public InputConnection onCreateInputConnection(EditorInfo out_attrs)
|
||||||
{
|
{
|
||||||
STKInputConnection sic =
|
if (m_stk_input_connection == null)
|
||||||
new STKInputConnection(super.onCreateInputConnection(out_attrs), this);
|
{
|
||||||
|
m_stk_input_connection = new STKInputConnection(
|
||||||
|
super.onCreateInputConnection(out_attrs), this);
|
||||||
|
}
|
||||||
out_attrs.actionLabel = null;
|
out_attrs.actionLabel = null;
|
||||||
out_attrs.inputType = InputType.TYPE_CLASS_TEXT;
|
out_attrs.inputType = InputType.TYPE_CLASS_TEXT;
|
||||||
out_attrs.imeOptions = EditorInfo.IME_ACTION_NEXT |
|
out_attrs.imeOptions = EditorInfo.IME_ACTION_NEXT |
|
||||||
EditorInfo.IME_FLAG_NO_FULLSCREEN |
|
EditorInfo.IME_FLAG_NO_FULLSCREEN |
|
||||||
EditorInfo.IME_FLAG_NO_EXTRACT_UI;
|
EditorInfo.IME_FLAG_NO_EXTRACT_UI;
|
||||||
return sic;
|
return m_stk_input_connection;
|
||||||
}
|
}
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
@Override
|
@Override
|
||||||
public boolean onCheckIsTextEditor() { return true; }
|
public boolean onCheckIsTextEditor() { return true; }
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
public void resetWhenFocus()
|
|
||||||
{
|
|
||||||
clearComposingText();
|
|
||||||
getText().clear();
|
|
||||||
m_composing_start = m_composing_end = 0;
|
|
||||||
}
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
public void setComposingRegion(int start, int end)
|
public void setComposingRegion(int start, int end)
|
||||||
{
|
{
|
||||||
// From doc of InputConnectionWrapper, it says:
|
// From doc of InputConnectionWrapper, it says:
|
||||||
@ -71,7 +74,7 @@ public class STKEditText extends EditText
|
|||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
public void updateSTKEditBox()
|
public void updateSTKEditBox()
|
||||||
{
|
{
|
||||||
if (!isFocused())
|
if (!isFocused() || m_from_stk_editbox)
|
||||||
return;
|
return;
|
||||||
editText2STKEditbox(getText().toString(), getSelectionStart(),
|
editText2STKEditbox(getText().toString(), getSelectionStart(),
|
||||||
getSelectionEnd(), m_composing_start, m_composing_end);
|
getSelectionEnd(), m_composing_start, m_composing_end);
|
||||||
@ -82,4 +85,14 @@ public class STKEditText extends EditText
|
|||||||
clearFocus();
|
clearFocus();
|
||||||
setVisibility(View.GONE);
|
setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
public void setTextFromSTK(final String text)
|
||||||
|
{
|
||||||
|
m_from_stk_editbox = true;
|
||||||
|
super.setText(text);
|
||||||
|
m_from_stk_editbox = false;
|
||||||
|
}
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
public STKInputConnection getSTKInputConnection()
|
||||||
|
{ return m_stk_input_connection; }
|
||||||
}
|
}
|
||||||
|
@ -31,6 +31,9 @@ public class SuperTuxKartActivity extends NativeActivity
|
|||||||
|
|
||||||
InputMethodManager imm = (InputMethodManager)
|
InputMethodManager imm = (InputMethodManager)
|
||||||
getSystemService(Context.INPUT_METHOD_SERVICE);
|
getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||||
|
if (imm == null)
|
||||||
|
return;
|
||||||
|
|
||||||
imm.hideSoftInputFromWindow(m_stk_edittext.getWindowToken(), 0);
|
imm.hideSoftInputFromWindow(m_stk_edittext.getWindowToken(), 0);
|
||||||
}
|
}
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
@ -47,6 +50,34 @@ public class SuperTuxKartActivity extends NativeActivity
|
|||||||
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
|
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
|
||||||
}
|
}
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
|
private void createSTKEditText()
|
||||||
|
{
|
||||||
|
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(
|
||||||
|
FrameLayout.LayoutParams.WRAP_CONTENT,
|
||||||
|
FrameLayout.LayoutParams.WRAP_CONTENT);
|
||||||
|
m_stk_edittext = new STKEditText(this);
|
||||||
|
// For some copy-and-paste text are not done by commitText in
|
||||||
|
// STKInputConnection, so we need an extra watcher
|
||||||
|
m_stk_edittext.addTextChangedListener(new TextWatcher()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void onTextChanged(CharSequence s, int start, int before,
|
||||||
|
int count) {}
|
||||||
|
@Override
|
||||||
|
public void beforeTextChanged(CharSequence s, int start, int count,
|
||||||
|
int after) {}
|
||||||
|
@Override
|
||||||
|
public void afterTextChanged(Editable edit)
|
||||||
|
{
|
||||||
|
if (m_stk_edittext != null)
|
||||||
|
m_stk_edittext.updateSTKEditBox();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
addContentView(m_stk_edittext, params);
|
||||||
|
// Only focus it and make visible when soft keybord is opened
|
||||||
|
m_stk_edittext.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle instance)
|
public void onCreate(Bundle instance)
|
||||||
{
|
{
|
||||||
@ -120,38 +151,12 @@ public class SuperTuxKartActivity extends NativeActivity
|
|||||||
{
|
{
|
||||||
InputMethodManager imm = (InputMethodManager)
|
InputMethodManager imm = (InputMethodManager)
|
||||||
getSystemService(Context.INPUT_METHOD_SERVICE);
|
getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||||
|
if (imm == null)
|
||||||
|
return;
|
||||||
|
|
||||||
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(
|
|
||||||
FrameLayout.LayoutParams.WRAP_CONTENT,
|
|
||||||
FrameLayout.LayoutParams.WRAP_CONTENT);
|
|
||||||
if (m_stk_edittext == null)
|
if (m_stk_edittext == null)
|
||||||
{
|
createSTKEditText();
|
||||||
m_stk_edittext = new STKEditText(context);
|
|
||||||
// For some copy-and-paste text are not done by commitText
|
|
||||||
// in STKInputConnection, so we need an extra watcher
|
|
||||||
m_stk_edittext.addTextChangedListener(new TextWatcher()
|
|
||||||
{
|
|
||||||
@Override
|
|
||||||
public void onTextChanged(CharSequence s,
|
|
||||||
int start, int before,
|
|
||||||
int count) {}
|
|
||||||
@Override
|
|
||||||
public void beforeTextChanged(CharSequence s,
|
|
||||||
int start, int count,
|
|
||||||
int after) {}
|
|
||||||
@Override
|
|
||||||
public void afterTextChanged(Editable edit)
|
|
||||||
{
|
|
||||||
if (m_stk_edittext != null)
|
|
||||||
m_stk_edittext.updateSTKEditBox();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
addContentView(m_stk_edittext, params);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
m_stk_edittext.setLayoutParams(params);
|
|
||||||
|
|
||||||
m_stk_edittext.resetWhenFocus();
|
|
||||||
m_stk_edittext.setVisibility(View.VISIBLE);
|
m_stk_edittext.setVisibility(View.VISIBLE);
|
||||||
m_stk_edittext.requestFocus();
|
m_stk_edittext.requestFocus();
|
||||||
|
|
||||||
@ -173,4 +178,24 @@ public class SuperTuxKartActivity extends NativeActivity
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
/* Called by STK in JNI. */
|
||||||
|
public void fromSTKEditBox(final String text, final int selection_start,
|
||||||
|
final int selection_end)
|
||||||
|
{
|
||||||
|
runOnUiThread(new Runnable()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void run()
|
||||||
|
{
|
||||||
|
if (m_stk_edittext == null)
|
||||||
|
createSTKEditText();
|
||||||
|
m_stk_edittext.setTextFromSTK(text);
|
||||||
|
STKInputConnection ic = m_stk_edittext.getSTKInputConnection();
|
||||||
|
if (ic == null)
|
||||||
|
return;
|
||||||
|
ic.setSelection(selection_start, selection_end);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -92,7 +92,6 @@ CIrrDeviceAndroid::CIrrDeviceAndroid(const SIrrlichtCreationParameters& param)
|
|||||||
Gyroscope(0),
|
Gyroscope(0),
|
||||||
AccelerometerActive(false),
|
AccelerometerActive(false),
|
||||||
GyroscopeActive(false),
|
GyroscopeActive(false),
|
||||||
TextInputEnabled(false),
|
|
||||||
HasTouchDevice(false),
|
HasTouchDevice(false),
|
||||||
IsMousePressed(false),
|
IsMousePressed(false),
|
||||||
GamepadAxisX(0),
|
GamepadAxisX(0),
|
||||||
@ -771,11 +770,6 @@ s32 CIrrDeviceAndroid::handleKeyboard(AInputEvent* androidEvent)
|
|||||||
|
|
||||||
if (event.KeyInput.Key > 0)
|
if (event.KeyInput.Key > 0)
|
||||||
{
|
{
|
||||||
if (TextInputEnabled == true)
|
|
||||||
{
|
|
||||||
event.KeyInput.Char = getUnicodeChar(androidEvent);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (event.KeyInput.Char == 0)
|
if (event.KeyInput.Char == 0)
|
||||||
{
|
{
|
||||||
event.KeyInput.Char = getKeyChar(event);
|
event.KeyInput.Char = getKeyChar(event);
|
||||||
@ -1358,6 +1352,70 @@ void CIrrDeviceAndroid::toggleOnScreenKeyboard(bool show)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CIrrDeviceAndroid::fromSTKEditBox(const core::stringw& text, int selection_start, int selection_end)
|
||||||
|
{
|
||||||
|
if (!Android)
|
||||||
|
return;
|
||||||
|
|
||||||
|
bool was_detached = false;
|
||||||
|
JNIEnv* env = NULL;
|
||||||
|
|
||||||
|
jint status = Android->activity->vm->GetEnv((void**)&env, JNI_VERSION_1_6);
|
||||||
|
if (status == JNI_EDETACHED)
|
||||||
|
{
|
||||||
|
JavaVMAttachArgs args;
|
||||||
|
args.version = JNI_VERSION_1_6;
|
||||||
|
args.name = "NativeThread";
|
||||||
|
args.group = NULL;
|
||||||
|
|
||||||
|
status = Android->activity->vm->AttachCurrentThread(&env, &args);
|
||||||
|
was_detached = true;
|
||||||
|
}
|
||||||
|
if (status != JNI_OK)
|
||||||
|
{
|
||||||
|
os::Printer::log("Cannot attach current thread in fromSTKEditBox.", ELL_DEBUG);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
jobject native_activity = Android->activity->clazz;
|
||||||
|
jclass class_native_activity = env->GetObjectClass(native_activity);
|
||||||
|
|
||||||
|
if (class_native_activity == NULL)
|
||||||
|
{
|
||||||
|
os::Printer::log("fromSTKEditBox unable to find object class.", ELL_ERROR);
|
||||||
|
if (was_detached)
|
||||||
|
{
|
||||||
|
Android->activity->vm->DetachCurrentThread();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
jmethodID method_id = env->GetMethodID(class_native_activity, "fromSTKEditBox", "(Ljava/lang/String;II)V");
|
||||||
|
if (method_id == NULL)
|
||||||
|
{
|
||||||
|
os::Printer::log("fromSTKEditBox unable to find method id.", ELL_ERROR);
|
||||||
|
if (was_detached)
|
||||||
|
{
|
||||||
|
Android->activity->vm->DetachCurrentThread();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<char> utf8;
|
||||||
|
// Use utf32 for emoji later
|
||||||
|
static_assert(sizeof(wchar_t) == sizeof(uint32_t), "wchar_t is not 32bit");
|
||||||
|
uint32_t* chars = (uint32_t*)text.c_str();
|
||||||
|
utf8::unchecked::utf32to8(chars, chars + text.size(), back_inserter(utf8));
|
||||||
|
utf8.push_back(0);
|
||||||
|
jstring jstring_text = env->NewStringUTF(utf8.data());
|
||||||
|
|
||||||
|
env->CallVoidMethod(native_activity, method_id, jstring_text, (jint)selection_start, (jint)selection_end);
|
||||||
|
if (was_detached)
|
||||||
|
{
|
||||||
|
Android->activity->vm->DetachCurrentThread();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int CIrrDeviceAndroid::getRotation()
|
int CIrrDeviceAndroid::getRotation()
|
||||||
{
|
{
|
||||||
bool was_detached = false;
|
bool was_detached = false;
|
||||||
|
@ -73,7 +73,7 @@ namespace irr
|
|||||||
virtual bool deactivateGyroscope();
|
virtual bool deactivateGyroscope();
|
||||||
virtual bool isGyroscopeActive();
|
virtual bool isGyroscopeActive();
|
||||||
virtual bool isGyroscopeAvailable();
|
virtual bool isGyroscopeAvailable();
|
||||||
virtual void setTextInputEnabled(bool enabled) {TextInputEnabled = enabled;}
|
void fromSTKEditBox(const core::stringw& text, int selection_start, int selection_end);
|
||||||
virtual void toggleOnScreenKeyboard(bool show);
|
virtual void toggleOnScreenKeyboard(bool show);
|
||||||
virtual bool supportsTouchDevice() const { return HasTouchDevice; }
|
virtual bool supportsTouchDevice() const { return HasTouchDevice; }
|
||||||
virtual bool hasHardwareKeyboard() const;
|
virtual bool hasHardwareKeyboard() const;
|
||||||
@ -141,7 +141,6 @@ namespace irr
|
|||||||
const ASensor* Gyroscope;
|
const ASensor* Gyroscope;
|
||||||
bool AccelerometerActive;
|
bool AccelerometerActive;
|
||||||
bool GyroscopeActive;
|
bool GyroscopeActive;
|
||||||
bool TextInputEnabled;
|
|
||||||
static AndroidApplicationInfo ApplicationInfo;
|
static AndroidApplicationInfo ApplicationInfo;
|
||||||
|
|
||||||
static bool IsPaused;
|
static bool IsPaused;
|
||||||
|
@ -124,14 +124,6 @@ CGUIEditBox::~CGUIEditBox()
|
|||||||
irr_driver->getDevice());
|
irr_driver->getDevice());
|
||||||
dl->setIMEEnable(false);
|
dl->setIMEEnable(false);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
#ifdef ANDROID
|
|
||||||
if (irr_driver->getDevice()->getType() == irr::EIDT_ANDROID)
|
|
||||||
{
|
|
||||||
CIrrDeviceAndroid* dl = dynamic_cast<CIrrDeviceAndroid*>(
|
|
||||||
irr_driver->getDevice());
|
|
||||||
dl->setTextInputEnabled(false);
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
irr_driver->getDevice()->toggleOnScreenKeyboard(false);
|
irr_driver->getDevice()->toggleOnScreenKeyboard(false);
|
||||||
|
|
||||||
@ -286,14 +278,6 @@ bool CGUIEditBox::OnEvent(const SEvent& event)
|
|||||||
irr_driver->getDevice());
|
irr_driver->getDevice());
|
||||||
dl->setIMEEnable(false);
|
dl->setIMEEnable(false);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
#ifdef ANDROID
|
|
||||||
if (irr_driver->getDevice()->getType() == irr::EIDT_ANDROID)
|
|
||||||
{
|
|
||||||
CIrrDeviceAndroid* dl = dynamic_cast<CIrrDeviceAndroid*>(
|
|
||||||
irr_driver->getDevice());
|
|
||||||
dl->setTextInputEnabled(false);
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
m_from_android_edittext = false;
|
m_from_android_edittext = false;
|
||||||
m_composing_start = 0;
|
m_composing_start = 0;
|
||||||
@ -315,7 +299,7 @@ bool CGUIEditBox::OnEvent(const SEvent& event)
|
|||||||
{
|
{
|
||||||
CIrrDeviceAndroid* dl = dynamic_cast<CIrrDeviceAndroid*>(
|
CIrrDeviceAndroid* dl = dynamic_cast<CIrrDeviceAndroid*>(
|
||||||
irr_driver->getDevice());
|
irr_driver->getDevice());
|
||||||
dl->setTextInputEnabled(true);
|
dl->fromSTKEditBox(Text, MarkBegin, MarkEnd);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@ -1195,6 +1179,15 @@ void CGUIEditBox::setText(const wchar_t* text)
|
|||||||
CursorPos = Text.size();
|
CursorPos = Text.size();
|
||||||
HScrollPos = 0;
|
HScrollPos = 0;
|
||||||
breakText();
|
breakText();
|
||||||
|
#ifdef ANDROID
|
||||||
|
if (irr_driver->getDevice()->hasOnScreenKeyboard() &&
|
||||||
|
irr_driver->getDevice()->getType() == irr::EIDT_ANDROID)
|
||||||
|
{
|
||||||
|
CIrrDeviceAndroid* dl = dynamic_cast<CIrrDeviceAndroid*>(
|
||||||
|
irr_driver->getDevice());
|
||||||
|
dl->fromSTKEditBox(Text, MarkBegin, MarkEnd);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1727,6 +1720,15 @@ void CGUIEditBox::setTextMarkers(s32 begin, s32 end)
|
|||||||
MarkBegin = begin;
|
MarkBegin = begin;
|
||||||
MarkEnd = end;
|
MarkEnd = end;
|
||||||
sendGuiEvent(EGET_EDITBOX_MARKING_CHANGED);
|
sendGuiEvent(EGET_EDITBOX_MARKING_CHANGED);
|
||||||
|
#ifdef ANDROID
|
||||||
|
if (irr_driver->getDevice()->hasOnScreenKeyboard() &&
|
||||||
|
irr_driver->getDevice()->getType() == irr::EIDT_ANDROID)
|
||||||
|
{
|
||||||
|
CIrrDeviceAndroid* dl = dynamic_cast<CIrrDeviceAndroid*>(
|
||||||
|
irr_driver->getDevice());
|
||||||
|
dl->fromSTKEditBox(Text, MarkBegin, MarkEnd);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1823,13 +1825,8 @@ void CGUIEditBox::fromAndroidEditText(const core::stringw& text, int start,
|
|||||||
m_composing_start = 0;
|
m_composing_start = 0;
|
||||||
m_composing_end = 0;
|
m_composing_end = 0;
|
||||||
|
|
||||||
if (start != end)
|
MarkBegin = start;
|
||||||
setTextMarkers(start, end);
|
MarkEnd = end;
|
||||||
else
|
|
||||||
{
|
|
||||||
MarkBegin = 0;
|
|
||||||
MarkEnd = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (composing_start != composing_end)
|
if (composing_start != composing_end)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user