Skip to content

Commit

Permalink
Android: QtEditText support for full-screen soft keyboard
Browse files Browse the repository at this point in the history
Full-screen soft keyboard support added. Including functionality
for copy-cut-paste and line change.

Future TODO QTBUG-121522

Task-number: QTBUG-109367
Pick-to: 6.7 6.6 6.5 6.2
Change-Id: Ia5632cacc910c7ebde0e40608c2abd027b8f953a
Reviewed-by: Assam Boudjelthia <assam.boudjelthia@qt.io>
  • Loading branch information
Rami Potinkara committed Feb 14, 2024
1 parent c30195a commit 1f6d7cb
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 15 deletions.
22 changes: 19 additions & 3 deletions src/android/jar/src/org/qtproject/qt/android/QtEditText.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import android.view.View;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputConnection;
import android.view.KeyEvent;

import org.qtproject.qt.android.QtInputConnection.QtInputConnectionListener;

Expand All @@ -19,7 +20,7 @@ class QtEditText extends View
int m_imeOptions = 0;
int m_inputType = InputType.TYPE_CLASS_TEXT;
boolean m_optionsChanged = false;

QtInputConnection m_inputConnection = null;
private QtInputConnectionListener m_qtInputConnectionListener;

public void setQtInputConnectionListener(QtInputConnectionListener listener)
Expand Down Expand Up @@ -65,8 +66,23 @@ public InputConnection onCreateInputConnection(EditorInfo outAttrs)
outAttrs.inputType = m_inputType;
outAttrs.imeOptions = m_imeOptions;
outAttrs.initialCapsMode = m_initialCapsMode;
outAttrs.imeOptions |= EditorInfo.IME_FLAG_NO_EXTRACT_UI;
return new QtInputConnection(this, m_qtInputConnectionListener);
m_inputConnection = new QtInputConnection(this,m_qtInputConnectionListener);
return m_inputConnection;
}

@Override
public boolean onCheckIsTextEditor ()
{
return true;
}

@Override
public boolean onKeyDown (int keyCode, KeyEvent event)
{
if (null != m_inputConnection)
m_inputConnection.restartImmInput();

return super.onKeyDown(keyCode, event);
}

@Override
Expand Down
48 changes: 37 additions & 11 deletions src/android/jar/src/org/qtproject/qt/android/QtInputConnection.java
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ class QtNativeInputConnection
static native boolean copyURL();
static native boolean paste();
static native boolean updateCursorPosition();
static native void reportFullscreenMode(boolean enabled);
static native boolean fullscreenMode();
}

class QtInputConnection extends BaseInputConnection
Expand Down Expand Up @@ -101,6 +103,7 @@ public interface QtInputConnectionListener {
}

private final QtEditText m_view;
private final InputMethodManager m_imm;

private void setClosing(boolean closing)
{
Expand All @@ -114,16 +117,39 @@ public QtInputConnection(QtEditText targetView, QtInputConnectionListener listen
{
super(targetView, true);
m_view = targetView;
m_imm = (InputMethodManager)m_view.getContext().getSystemService(
Context.INPUT_METHOD_SERVICE);
m_qtInputConnectionListener = listener;
}

public void restartImmInput()
{
if (QtNativeInputConnection.fullscreenMode()) {
if (m_imm != null)
m_imm.restartInput(m_view);
}

}

@Override
public boolean beginBatchEdit()
{
setClosing(false);
return QtNativeInputConnection.beginBatchEdit();
}

@Override
public boolean reportFullscreenMode (boolean enabled)
{
QtNativeInputConnection.reportFullscreenMode(enabled);
// Always ignored on calling editor.
// Always false on Android 8 and later, true with earlier.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
return false;

return true;
}

@Override
public boolean endBatchEdit()
{
Expand All @@ -142,6 +168,7 @@ public boolean commitCompletion(CompletionInfo text)
public boolean commitText(CharSequence text, int newCursorPosition)
{
setClosing(false);
restartImmInput();
return QtNativeInputConnection.commitText(text.toString(), newCursorPosition);
}

Expand Down Expand Up @@ -207,23 +234,25 @@ public boolean performContextMenuAction(int id)
{
switch (id) {
case ID_SELECT_ALL:
restartImmInput();
return QtNativeInputConnection.selectAll();
case ID_COPY:
restartImmInput();
return QtNativeInputConnection.copy();
case ID_COPY_URL:
restartImmInput();
return QtNativeInputConnection.copyURL();
case ID_CUT:
restartImmInput();
return QtNativeInputConnection.cut();
case ID_PASTE:
restartImmInput();
return QtNativeInputConnection.paste();

case ID_SWITCH_INPUT_METHOD:
InputMethodManager imm = (InputMethodManager)m_view.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
if (imm != null)
imm.showInputMethodPicker();
if (m_imm != null)
m_imm.showInputMethodPicker();

return true;

case ID_ADD_TO_DICTIONARY:
// TODO
// String word = m_editable.subSequence(0, m_editable.length()).toString();
Expand Down Expand Up @@ -256,25 +285,22 @@ public boolean sendKeyEvent(KeyEvent event)
event.getRepeatCount(),
event.getMetaState());
return super.sendKeyEvent(fakeEvent);

case android.view.inputmethod.EditorInfo.IME_ACTION_PREVIOUS:
case android.view.inputmethod.EditorInfo.IME_ACTION_PREVIOUS:
fakeEvent = new KeyEvent(event.getDownTime(),
event.getEventTime(),
event.getAction(),
KeyEvent.KEYCODE_TAB,
event.getRepeatCount(),
KeyEvent.META_SHIFT_ON);
return super.sendKeyEvent(fakeEvent);

case android.view.inputmethod.EditorInfo.IME_FLAG_NO_ENTER_ACTION:
restartImmInput();
break;

default:
m_qtInputConnectionListener.onSendKeyEventDefaultCase();
break;
break;
}
}

return super.sendKeyEvent(event);
}

Expand Down
40 changes: 39 additions & 1 deletion src/plugins/platforms/android/qandroidinputcontext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,18 @@ static jboolean updateCursorPosition(JNIEnv */*env*/, jobject /*thiz*/)
return true;
}

static void reportFullscreenMode(JNIEnv */*env*/, jobject /*thiz*/, jboolean enabled)
{
if (!m_androidInputContext)
return;

runOnQtThread([&]{m_androidInputContext->reportFullscreenMode(enabled);});
}

static jboolean fullscreenMode(JNIEnv */*env*/, jobject /*thiz*/)
{
return m_androidInputContext ? m_androidInputContext->fullscreenMode() : false;
}

static JNINativeMethod methods[] = {
{"beginBatchEdit", "()Z", (void *)beginBatchEdit},
Expand All @@ -332,7 +344,9 @@ static JNINativeMethod methods[] = {
{"copy", "()Z", (void *)copy},
{"copyURL", "()Z", (void *)copyURL},
{"paste", "()Z", (void *)paste},
{"updateCursorPosition", "()Z", (void *)updateCursorPosition}
{"updateCursorPosition", "()Z", (void *)updateCursorPosition},
{"reportFullscreenMode", "(Z)V", (void *)reportFullscreenMode},
{"fullscreenMode", "()Z", (void *)fullscreenMode}
};

static QRect screenInputItemRectangle()
Expand All @@ -349,6 +363,7 @@ QAndroidInputContext::QAndroidInputContext()
, m_handleMode(Hidden)
, m_batchEditNestingLevel(0)
, m_focusObject(0)
, m_fullScreenMode(false)
{
QJniEnvironment env;
jclass clazz = env.findClass(QtNativeInputConnectionClassName);
Expand Down Expand Up @@ -541,6 +556,10 @@ bool QAndroidInputContext::isImhNoTextHandlesSet()

void QAndroidInputContext::updateSelectionHandles()
{
if (m_fullScreenMode) {
QtAndroidInput::updateHandles(Hidden);
return;
}
static bool noHandles = qEnvironmentVariableIntValue("QT_QPA_NO_TEXT_HANDLES");
if (noHandles || !m_focusObject)
return;
Expand Down Expand Up @@ -1104,6 +1123,25 @@ jboolean QAndroidInputContext::finishComposingText()
return JNI_TRUE;
}

void QAndroidInputContext::reportFullscreenMode(jboolean enabled)
{
m_fullScreenMode = enabled;
BatchEditLock batchEditLock(this);
if (!focusObjectStopComposing())
return;

if (enabled)
m_handleMode = Hidden;

updateSelectionHandles();
}

// Called in calling thread's context
jboolean QAndroidInputContext::fullscreenMode()
{
return m_fullScreenMode;
}

bool QAndroidInputContext::focusObjectIsComposing() const
{
return m_composingCursor != -1;
Expand Down
3 changes: 3 additions & 0 deletions src/plugins/platforms/android/qandroidinputcontext.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,8 @@ class QAndroidInputContext: public QPlatformInputContext
jboolean copy();
jboolean copyURL();
jboolean paste();
void reportFullscreenMode(jboolean enabled);
jboolean fullscreenMode();

public slots:
void safeCall(const std::function<void()> &func, Qt::ConnectionType conType = Qt::BlockingQueuedConnection);
Expand Down Expand Up @@ -132,6 +134,7 @@ private slots:
int m_batchEditNestingLevel;
QPointer<QObject> m_focusObject;
QTimer m_hideCursorHandleTimer;
bool m_fullScreenMode;
};
Q_DECLARE_OPERATORS_FOR_FLAGS(QAndroidInputContext::HandleModes)
QT_END_NAMESPACE
Expand Down

0 comments on commit 1f6d7cb

Please sign in to comment.