mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 13:21:05 +00:00
Bug 1416918 - 4b. Move GeckoEditable{Client,Listener} to TextInputController; r=esawin
Move GeckoEditableClient and GeckoEditableListener to inside TextInputController, next to TextInputController.Delegate. This consolidates the three internal interfaces used for IME in one place. The patch also changes the last notifyIMEContext parameter to an int flag to indicate private browsing or user action. This allows for future expansion without adding more parameters to notifyIMEContext. MozReview-Commit-ID: BjscdNr9TkO --HG-- extra : rebase_source : 87166a55e5978eda4a7c3065db9b68658e33af35
This commit is contained in:
parent
9db87f4a1c
commit
af3a18ee62
@ -378,8 +378,6 @@ gvjar.sources += [geckoview_source_dir + 'java/org/mozilla/gecko/' + x
|
||||
'GeckoBatteryManager.java',
|
||||
'GeckoEditable.java',
|
||||
'GeckoEditableChild.java',
|
||||
'GeckoEditableClient.java',
|
||||
'GeckoEditableListener.java',
|
||||
'GeckoHalDefines.java',
|
||||
'GeckoInputConnection.java',
|
||||
'GeckoNetworkManager.java',
|
||||
|
@ -16,7 +16,7 @@ interface IGeckoEditableParent {
|
||||
|
||||
// Notify a change in editor state or type.
|
||||
void notifyIMEContext(int state, String typeHint, String modeHint, String actionHint,
|
||||
boolean inPrivateBrowsing, boolean isUserAction);
|
||||
int flags);
|
||||
|
||||
// Notify a change in editor selection.
|
||||
void onSelectionChange(IBinder token, int start, int end);
|
||||
|
@ -46,7 +46,7 @@ import android.view.KeyEvent;
|
||||
extends IGeckoEditableParent.Stub
|
||||
implements InvocationHandler,
|
||||
Editable,
|
||||
GeckoEditableClient {
|
||||
TextInputController.EditableClient {
|
||||
|
||||
private static final boolean DEBUG = false;
|
||||
private static final String LOGTAG = "GeckoEditable";
|
||||
@ -70,7 +70,7 @@ import android.view.KeyEvent;
|
||||
// Parent or content process child that has the focus.
|
||||
/* package */ IGeckoEditableChild mFocusedChild; // Used by IC thread.
|
||||
/* package */ IBinder mFocusedToken; // Used by Gecko/binder thread.
|
||||
/* package */ GeckoEditableListener mListener;
|
||||
/* package */ TextInputController.EditableListener mListener;
|
||||
|
||||
/* package */ boolean mInBatchMode; // Used by IC thread
|
||||
/* package */ boolean mNeedSync; // Used by IC thread
|
||||
@ -276,7 +276,8 @@ import android.view.KeyEvent;
|
||||
return mShadowText;
|
||||
}
|
||||
|
||||
public synchronized void syncShadowText(final GeckoEditableListener listener) {
|
||||
public synchronized void syncShadowText(
|
||||
final TextInputController.EditableListener listener) {
|
||||
if (DEBUG) {
|
||||
assertOnIcThread();
|
||||
}
|
||||
@ -624,7 +625,7 @@ import android.view.KeyEvent;
|
||||
mDefaultChild = child;
|
||||
}
|
||||
|
||||
/* package */ void setListener(final GeckoEditableListener newListener) {
|
||||
/* package */ void setListener(final TextInputController.EditableListener newListener) {
|
||||
if (DEBUG) {
|
||||
// Called by TextInputController.
|
||||
ThreadUtils.assertOnUiThread();
|
||||
@ -844,9 +845,7 @@ import android.view.KeyEvent;
|
||||
} while (rangeStart < composingEnd);
|
||||
}
|
||||
|
||||
// GeckoEditableClient interface
|
||||
|
||||
@Override
|
||||
@Override // TextInputController.EditableClient
|
||||
public void sendKeyEvent(final KeyEvent event, int action, int metaState) {
|
||||
if (DEBUG) {
|
||||
assertOnIcThread();
|
||||
@ -880,7 +879,7 @@ import android.view.KeyEvent;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Override // TextInputController.EditableClient
|
||||
public Editable getEditable() {
|
||||
if (!onIcThread()) {
|
||||
// Android may be holding an old InputConnection; ignore
|
||||
@ -896,7 +895,7 @@ import android.view.KeyEvent;
|
||||
return mProxy;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Override // TextInputController.EditableClient
|
||||
public void setBatchMode(boolean inBatchMode) {
|
||||
if (!onIcThread()) {
|
||||
// Android may be holding an old InputConnection; ignore
|
||||
@ -928,7 +927,7 @@ import android.view.KeyEvent;
|
||||
mText.syncShadowText(mListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Override // TextInputController.EditableClient
|
||||
public void setSuppressKeyUp(boolean suppress) {
|
||||
if (DEBUG) {
|
||||
assertOnIcThread();
|
||||
@ -938,7 +937,7 @@ import android.view.KeyEvent;
|
||||
mSuppressKeyUp = suppress;
|
||||
}
|
||||
|
||||
@Override // GeckoEditableClient
|
||||
@Override // TextInputController.EditableClient
|
||||
public Handler setInputConnectionHandler(final Handler handler) {
|
||||
if (handler == mIcRunHandler) {
|
||||
return mIcRunHandler;
|
||||
@ -978,12 +977,12 @@ import android.view.KeyEvent;
|
||||
return handler;
|
||||
}
|
||||
|
||||
@Override // GeckoEditableClient
|
||||
@Override // TextInputController.EditableClient
|
||||
public void postToInputConnection(final Runnable runnable) {
|
||||
mIcPostHandler.post(runnable);
|
||||
}
|
||||
|
||||
@Override // GeckoEditableClient
|
||||
@Override // TextInputController.EditableClient
|
||||
public void requestCursorUpdates(int requestMode) {
|
||||
try {
|
||||
if (mFocusedChild != null) {
|
||||
@ -1061,15 +1060,16 @@ import android.view.KeyEvent;
|
||||
// On Gecko or binder thread.
|
||||
if (DEBUG) {
|
||||
// NOTIFY_IME_REPLY_EVENT is logged separately, inside geckoActionReply()
|
||||
if (type != GeckoEditableListener.NOTIFY_IME_REPLY_EVENT) {
|
||||
if (type != TextInputController.EditableListener.NOTIFY_IME_REPLY_EVENT) {
|
||||
Log.d(LOGTAG, "notifyIME(" +
|
||||
getConstantName(GeckoEditableListener.class, "NOTIFY_IME_", type) +
|
||||
getConstantName(TextInputController.EditableListener.class,
|
||||
"NOTIFY_IME_", type) +
|
||||
")");
|
||||
}
|
||||
}
|
||||
|
||||
final IBinder token = child.asBinder();
|
||||
if (type == GeckoEditableListener.NOTIFY_IME_OF_TOKEN) {
|
||||
if (type == TextInputController.EditableListener.NOTIFY_IME_OF_TOKEN) {
|
||||
synchronized (this) {
|
||||
if (mFocusedToken != null && mFocusedToken != token &&
|
||||
mFocusedToken.pingBinder()) {
|
||||
@ -1080,20 +1080,20 @@ import android.view.KeyEvent;
|
||||
mFocusedToken = token;
|
||||
return;
|
||||
}
|
||||
} else if (type == GeckoEditableListener.NOTIFY_IME_OPEN_VKB) {
|
||||
} else if (type == TextInputController.EditableListener.NOTIFY_IME_OPEN_VKB) {
|
||||
// Always from parent process.
|
||||
ThreadUtils.assertOnGeckoThread();
|
||||
} else if (!binderCheckToken(token, /* allowNull */ false)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (type == GeckoEditableListener.NOTIFY_IME_OF_BLUR) {
|
||||
if (type == TextInputController.EditableListener.NOTIFY_IME_OF_BLUR) {
|
||||
synchronized (this) {
|
||||
onTextChange(token, "", 0, Integer.MAX_VALUE);
|
||||
mActions.clear();
|
||||
mFocusedToken = null;
|
||||
}
|
||||
} else if (type == GeckoEditableListener.NOTIFY_IME_REPLY_EVENT) {
|
||||
} else if (type == TextInputController.EditableListener.NOTIFY_IME_REPLY_EVENT) {
|
||||
geckoActionReply(mActions.poll());
|
||||
if (!mActions.isEmpty()) {
|
||||
// Only post to IC thread below when the queue is empty.
|
||||
@ -1104,18 +1104,19 @@ import android.view.KeyEvent;
|
||||
mIcPostHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (type == GeckoEditableListener.NOTIFY_IME_REPLY_EVENT) {
|
||||
if (type == TextInputController.EditableListener.NOTIFY_IME_REPLY_EVENT) {
|
||||
if (mNeedSync) {
|
||||
icSyncShadowText();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (type == GeckoEditableListener.NOTIFY_IME_OF_FOCUS && mListener != null) {
|
||||
if (type == TextInputController.EditableListener.NOTIFY_IME_OF_FOCUS &&
|
||||
mListener != null) {
|
||||
mFocusedChild = child;
|
||||
mNeedSync = false;
|
||||
mText.syncShadowText(/* listener */ null);
|
||||
} else if (type == GeckoEditableListener.NOTIFY_IME_OF_BLUR) {
|
||||
} else if (type == TextInputController.EditableListener.NOTIFY_IME_OF_BLUR) {
|
||||
mFocusedChild = null;
|
||||
}
|
||||
|
||||
@ -1129,14 +1130,14 @@ import android.view.KeyEvent;
|
||||
@Override // IGeckoEditableParent
|
||||
public void notifyIMEContext(final int state, final String typeHint,
|
||||
final String modeHint, final String actionHint,
|
||||
final boolean inPrivateBrowsing,
|
||||
final boolean isUserAction) {
|
||||
final int flags) {
|
||||
// On Gecko or binder thread.
|
||||
if (DEBUG) {
|
||||
Log.d(LOGTAG, "notifyIMEContext(" +
|
||||
getConstantName(GeckoEditableListener.class, "IME_STATE_", state) +
|
||||
", \"" + typeHint + "\", \"" + modeHint + "\", \"" + actionHint + "\", " +
|
||||
"inPrivateBrowsing=" + inPrivateBrowsing + ")");
|
||||
getConstantName(TextInputController.EditableListener.class,
|
||||
"IME_STATE_", state) +
|
||||
", \"" + typeHint + "\", \"" + modeHint + "\", \"" + actionHint +
|
||||
"\", 0x" + Integer.toHexString(flags) + ")");
|
||||
}
|
||||
|
||||
// Don't check token for notifyIMEContext, because the calls all come
|
||||
@ -1149,7 +1150,7 @@ import android.view.KeyEvent;
|
||||
if (mListener == null) {
|
||||
return;
|
||||
}
|
||||
mListener.notifyIMEContext(state, typeHint, modeHint, actionHint, inPrivateBrowsing, isUserAction);
|
||||
mListener.notifyIMEContext(state, typeHint, modeHint, actionHint, flags);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -132,9 +132,10 @@ final class GeckoEditableChild extends JNIObject implements IGeckoEditableChild
|
||||
if (DEBUG) {
|
||||
ThreadUtils.assertOnGeckoThread();
|
||||
Log.d(LOGTAG, "notifyIME(" + GeckoEditable.getConstantName(
|
||||
GeckoEditableListener.class, "NOTIFY_IME_", type) + ")");
|
||||
TextInputController.EditableListener.class,
|
||||
"NOTIFY_IME_", type) + ")");
|
||||
}
|
||||
if (type == GeckoEditableListener.NOTIFY_IME_TO_CANCEL_COMPOSITION) {
|
||||
if (type == TextInputController.EditableListener.NOTIFY_IME_TO_CANCEL_COMPOSITION) {
|
||||
// Composition should have been canceled on the parent side through text
|
||||
// update notifications. We cannot verify that here because we don't
|
||||
// keep track of spans on the child side, but it's simple to add the
|
||||
@ -153,17 +154,18 @@ final class GeckoEditableChild extends JNIObject implements IGeckoEditableChild
|
||||
@WrapForJNI(calledFrom = "gecko")
|
||||
private void notifyIMEContext(final int state, final String typeHint,
|
||||
final String modeHint, final String actionHint,
|
||||
final boolean inPrivateBrowsing, final boolean isUserAction) {
|
||||
final int flags) {
|
||||
if (DEBUG) {
|
||||
ThreadUtils.assertOnGeckoThread();
|
||||
Log.d(LOGTAG, "notifyIMEContext(" + GeckoEditable.getConstantName(
|
||||
GeckoEditableListener.class, "IME_STATE_", state) + ", \"" +
|
||||
typeHint + "\", \"" + modeHint + "\", \"" + actionHint + "\", " +
|
||||
"inPrivateBrowsing=" + inPrivateBrowsing + ")");
|
||||
TextInputController.EditableListener.class,
|
||||
"IME_STATE_", state) + ", \"" +
|
||||
typeHint + "\", \"" + modeHint + "\", \"" + actionHint +
|
||||
"\", 0x" + Integer.toHexString(flags) + ")");
|
||||
}
|
||||
|
||||
try {
|
||||
mEditableParent.notifyIMEContext(state, typeHint, modeHint, actionHint, inPrivateBrowsing, isUserAction);
|
||||
mEditableParent.notifyIMEContext(state, typeHint, modeHint, actionHint, flags);
|
||||
} catch (final RemoteException e) {
|
||||
Log.e(LOGTAG, "Remote call failed", e);
|
||||
}
|
||||
|
@ -1,38 +0,0 @@
|
||||
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*-
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
package org.mozilla.gecko;
|
||||
|
||||
import org.mozilla.gecko.annotation.WrapForJNI;
|
||||
|
||||
import android.os.Handler;
|
||||
import android.text.Editable;
|
||||
import android.view.KeyEvent;
|
||||
|
||||
/**
|
||||
* Interface for the IC thread.
|
||||
*/
|
||||
interface GeckoEditableClient {
|
||||
void sendKeyEvent(KeyEvent event, int action, int metaState);
|
||||
Editable getEditable();
|
||||
void setBatchMode(boolean isBatchMode);
|
||||
void setSuppressKeyUp(boolean suppress);
|
||||
Handler setInputConnectionHandler(Handler handler);
|
||||
void postToInputConnection(Runnable runnable);
|
||||
|
||||
// The following value is used by requestCursorUpdates
|
||||
|
||||
// ONE_SHOT calls updateCompositionRects() after getting current composing character rects.
|
||||
@WrapForJNI
|
||||
public static final int ONE_SHOT = 1;
|
||||
// START_MONITOR start the monitor for composing character rects. If is is updaed, call updateCompositionRects()
|
||||
@WrapForJNI
|
||||
public static final int START_MONITOR = 2;
|
||||
// ENDT_MONITOR stops the monitor for composing character rects.
|
||||
@WrapForJNI
|
||||
public static final int END_MONITOR = 3;
|
||||
|
||||
void requestCursorUpdates(int requestMode);
|
||||
}
|
@ -1,44 +0,0 @@
|
||||
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*-
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
package org.mozilla.gecko;
|
||||
|
||||
import org.mozilla.gecko.annotation.WrapForJNI;
|
||||
|
||||
import android.graphics.RectF;
|
||||
import android.view.KeyEvent;
|
||||
|
||||
/**
|
||||
* Interface for the Editable to listen on the Gecko thread, as well as for the IC thread to listen
|
||||
* to the Editable.
|
||||
*/
|
||||
interface GeckoEditableListener {
|
||||
// IME notification type for notifyIME(), corresponding to NotificationToIME enum in Gecko
|
||||
@WrapForJNI
|
||||
int NOTIFY_IME_OF_TOKEN = -3;
|
||||
@WrapForJNI
|
||||
int NOTIFY_IME_OPEN_VKB = -2;
|
||||
@WrapForJNI
|
||||
int NOTIFY_IME_REPLY_EVENT = -1;
|
||||
@WrapForJNI
|
||||
int NOTIFY_IME_OF_FOCUS = 1;
|
||||
@WrapForJNI
|
||||
int NOTIFY_IME_OF_BLUR = 2;
|
||||
@WrapForJNI
|
||||
int NOTIFY_IME_TO_COMMIT_COMPOSITION = 8;
|
||||
@WrapForJNI
|
||||
int NOTIFY_IME_TO_CANCEL_COMPOSITION = 9;
|
||||
// IME enabled state for notifyIMEContext()
|
||||
int IME_STATE_DISABLED = 0;
|
||||
int IME_STATE_ENABLED = 1;
|
||||
int IME_STATE_PASSWORD = 2;
|
||||
|
||||
void notifyIME(int type);
|
||||
void notifyIMEContext(int state, String typeHint, String modeHint, String actionHint, boolean inPrivateBrowsing, boolean isUserAction);
|
||||
void onSelectionChange();
|
||||
void onTextChange();
|
||||
void onDefaultKeyEvent(KeyEvent event);
|
||||
void updateCompositionRects(final RectF[] aRects);
|
||||
}
|
@ -47,7 +47,7 @@ import android.view.inputmethod.InputMethodManager;
|
||||
/* package */ class GeckoInputConnection
|
||||
extends BaseInputConnection
|
||||
implements TextInputController.Delegate,
|
||||
GeckoEditableListener {
|
||||
TextInputController.EditableListener {
|
||||
|
||||
private static final boolean DEBUG = false;
|
||||
protected static final String LOGTAG = "GeckoInputConnection";
|
||||
@ -65,15 +65,14 @@ import android.view.inputmethod.InputMethodManager;
|
||||
private String mIMETypeHint = "";
|
||||
private String mIMEModeHint = "";
|
||||
private String mIMEActionHint = "";
|
||||
private boolean mInPrivateBrowsing;
|
||||
private boolean mIsUserAction;
|
||||
private int mIMEFlags;
|
||||
private boolean mFocused;
|
||||
|
||||
private String mCurrentInputMethod = "";
|
||||
|
||||
private final GeckoSession mSession;
|
||||
private final View mView;
|
||||
private final GeckoEditableClient mEditableClient;
|
||||
private final TextInputController.EditableClient mEditableClient;
|
||||
protected int mBatchEditCount;
|
||||
private ExtractedTextRequest mUpdateRequest;
|
||||
private final ExtractedText mUpdateExtract = new ExtractedText();
|
||||
@ -83,9 +82,10 @@ import android.view.inputmethod.InputMethodManager;
|
||||
// Prevent showSoftInput and hideSoftInput from causing reentrant calls on some devices.
|
||||
private volatile boolean mSoftInputReentrancyGuard;
|
||||
|
||||
public static TextInputController.Delegate create(GeckoSession session,
|
||||
View targetView,
|
||||
GeckoEditableClient editable) {
|
||||
public static TextInputController.Delegate create(
|
||||
final GeckoSession session,
|
||||
final View targetView,
|
||||
final TextInputController.EditableClient editable) {
|
||||
if (DEBUG) {
|
||||
return DebugGeckoInputConnection.create(session, targetView, editable);
|
||||
} else {
|
||||
@ -93,9 +93,9 @@ import android.view.inputmethod.InputMethodManager;
|
||||
}
|
||||
}
|
||||
|
||||
protected GeckoInputConnection(GeckoSession session,
|
||||
View targetView,
|
||||
GeckoEditableClient editable) {
|
||||
protected GeckoInputConnection(final GeckoSession session,
|
||||
final View targetView,
|
||||
final TextInputController.EditableClient editable) {
|
||||
super(targetView, true);
|
||||
mSession = session;
|
||||
mView = targetView;
|
||||
@ -306,7 +306,7 @@ import android.view.inputmethod.InputMethodManager;
|
||||
restartInput();
|
||||
}
|
||||
|
||||
@Override // GeckoEditableListener
|
||||
@Override // TextInputController.EditableListener
|
||||
public void onTextChange() {
|
||||
|
||||
if (mUpdateRequest == null) {
|
||||
@ -334,7 +334,7 @@ import android.view.inputmethod.InputMethodManager;
|
||||
imm.updateExtractedText(v, mUpdateRequest.token, mUpdateExtract);
|
||||
}
|
||||
|
||||
@Override // GeckoEditableListener
|
||||
@Override // TextInputController.EditableListener
|
||||
public void onSelectionChange() {
|
||||
|
||||
final Editable editable = getEditable();
|
||||
@ -357,7 +357,7 @@ import android.view.inputmethod.InputMethodManager;
|
||||
}
|
||||
|
||||
@TargetApi(21)
|
||||
@Override
|
||||
@Override // TextInputController.EditableListener
|
||||
public void updateCompositionRects(final RectF[] rects) {
|
||||
if (!(Build.VERSION.SDK_INT >= 21)) {
|
||||
return;
|
||||
@ -425,18 +425,21 @@ import android.view.inputmethod.InputMethodManager;
|
||||
public boolean requestCursorUpdates(int cursorUpdateMode) {
|
||||
|
||||
if ((cursorUpdateMode & InputConnection.CURSOR_UPDATE_IMMEDIATE) != 0) {
|
||||
mEditableClient.requestCursorUpdates(GeckoEditableClient.ONE_SHOT);
|
||||
mEditableClient.requestCursorUpdates(
|
||||
TextInputController.EditableClient.ONE_SHOT);
|
||||
}
|
||||
|
||||
if ((cursorUpdateMode & InputConnection.CURSOR_UPDATE_MONITOR) != 0) {
|
||||
mEditableClient.requestCursorUpdates(GeckoEditableClient.START_MONITOR);
|
||||
mEditableClient.requestCursorUpdates(
|
||||
TextInputController.EditableClient.START_MONITOR);
|
||||
} else {
|
||||
mEditableClient.requestCursorUpdates(GeckoEditableClient.END_MONITOR);
|
||||
mEditableClient.requestCursorUpdates(
|
||||
TextInputController.EditableClient.END_MONITOR);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Override // TextInputController.EditableListener
|
||||
public void onDefaultKeyEvent(final KeyEvent event) {
|
||||
ThreadUtils.postToUiThread(new Runnable() {
|
||||
@Override
|
||||
@ -612,7 +615,7 @@ import android.view.inputmethod.InputMethodManager;
|
||||
outAttrs.actionLabel = mIMEActionHint;
|
||||
}
|
||||
|
||||
if (mInPrivateBrowsing) {
|
||||
if ((mIMEFlags & IME_FLAG_PRIVATE_BROWSING) != 0) {
|
||||
outAttrs.imeOptions |= InputMethods.IME_FLAG_NO_PERSONALIZED_LEARNING;
|
||||
}
|
||||
|
||||
@ -641,8 +644,9 @@ import android.view.inputmethod.InputMethodManager;
|
||||
outAttrs.initialSelStart = Selection.getSelectionStart(editable);
|
||||
outAttrs.initialSelEnd = Selection.getSelectionEnd(editable);
|
||||
|
||||
if (mIsUserAction) {
|
||||
if ((context instanceof Activity) && ActivityUtils.isFullScreen((Activity) context)) {
|
||||
if ((mIMEFlags & IME_FLAG_USER_ACTION) != 0) {
|
||||
if ((context instanceof Activity) &&
|
||||
ActivityUtils.isFullScreen((Activity) context)) {
|
||||
showSoftInputWithToolbar(false);
|
||||
} else {
|
||||
showSoftInputWithToolbar(true);
|
||||
@ -916,7 +920,7 @@ import android.view.inputmethod.InputMethodManager;
|
||||
return mIMEState != IME_STATE_DISABLED;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Override // TextInputController.EditableListener
|
||||
public void notifyIME(int type) {
|
||||
switch (type) {
|
||||
|
||||
@ -935,7 +939,7 @@ import android.view.inputmethod.InputMethodManager;
|
||||
showSoftInputWithToolbar(false);
|
||||
break;
|
||||
|
||||
case GeckoEditableListener.NOTIFY_IME_TO_COMMIT_COMPOSITION: {
|
||||
case NOTIFY_IME_TO_COMMIT_COMPOSITION: {
|
||||
// Gecko already committed its composition. However, Android keyboards
|
||||
// have trouble dealing with us removing the composition manually on the
|
||||
// Java side. Therefore, we keep the composition intact on the Java side.
|
||||
@ -967,10 +971,10 @@ import android.view.inputmethod.InputMethodManager;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void notifyIMEContext(int state, String typeHint, String modeHint,
|
||||
String actionHint, boolean inPrivateBrowsing,
|
||||
boolean isUserAction) {
|
||||
@Override // TextInputController.EditableListener
|
||||
public synchronized void notifyIMEContext(int state, final String typeHint,
|
||||
final String modeHint, final String actionHint,
|
||||
final int flags) {
|
||||
// For some input type we will use a widget to display the ui, for those we must not
|
||||
// display the ime. We can display a widget for date and time types and, if the sdk version
|
||||
// is 11 or greater, for datetime/month/week as well.
|
||||
@ -997,8 +1001,7 @@ import android.view.inputmethod.InputMethodManager;
|
||||
mIMETypeHint = (typeHint == null) ? "" : typeHint;
|
||||
mIMEModeHint = (modeHint == null) ? "" : modeHint;
|
||||
mIMEActionHint = (actionHint == null) ? "" : actionHint;
|
||||
mInPrivateBrowsing = inPrivateBrowsing;
|
||||
mIsUserAction = isUserAction;
|
||||
mIMEFlags = flags;
|
||||
|
||||
// These fields are reset here and will be updated when restartInput is called below
|
||||
mUpdateRequest = null;
|
||||
@ -1031,19 +1034,20 @@ final class DebugGeckoInputConnection
|
||||
private InputConnection mProxy;
|
||||
private final StringBuilder mCallLevel;
|
||||
|
||||
private DebugGeckoInputConnection(GeckoSession session,
|
||||
View targetView,
|
||||
GeckoEditableClient editable) {
|
||||
private DebugGeckoInputConnection(final GeckoSession session,
|
||||
final View targetView,
|
||||
final TextInputController.EditableClient editable) {
|
||||
super(session, targetView, editable);
|
||||
mCallLevel = new StringBuilder();
|
||||
}
|
||||
|
||||
public static TextInputController.Delegate create(GeckoSession session,
|
||||
View targetView,
|
||||
GeckoEditableClient editable) {
|
||||
public static TextInputController.Delegate create(
|
||||
final GeckoSession session,
|
||||
final View targetView,
|
||||
final TextInputController.EditableClient editable) {
|
||||
final Class<?>[] PROXY_INTERFACES = { InputConnection.class,
|
||||
TextInputController.Delegate.class,
|
||||
GeckoEditableListener.class };
|
||||
TextInputController.EditableListener.class };
|
||||
DebugGeckoInputConnection dgic =
|
||||
new DebugGeckoInputConnection(session, targetView, editable);
|
||||
dgic.mProxy = (InputConnection) Proxy.newProxyInstance(
|
||||
@ -1063,10 +1067,10 @@ final class DebugGeckoInputConnection
|
||||
// translate argument values to constant names
|
||||
if ("notifyIME".equals(method.getName()) && arg == args[0]) {
|
||||
log.append(GeckoEditable.getConstantName(
|
||||
GeckoEditableListener.class, "NOTIFY_IME_", arg));
|
||||
TextInputController.EditableListener.class, "NOTIFY_IME_", arg));
|
||||
} else if ("notifyIMEContext".equals(method.getName()) && arg == args[0]) {
|
||||
log.append(GeckoEditable.getConstantName(
|
||||
GeckoEditableListener.class, "IME_STATE_", arg));
|
||||
TextInputController.EditableListener.class, "IME_STATE_", arg));
|
||||
} else {
|
||||
GeckoEditable.debugAppend(log, arg);
|
||||
}
|
||||
|
@ -5,11 +5,14 @@
|
||||
|
||||
package org.mozilla.gecko;
|
||||
|
||||
import org.mozilla.gecko.annotation.WrapForJNI;
|
||||
import org.mozilla.gecko.util.ThreadUtils;
|
||||
|
||||
import android.graphics.RectF;
|
||||
import android.os.Handler;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.text.Editable;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.View;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
@ -23,6 +26,7 @@ import android.view.inputmethod.InputConnection;
|
||||
*/
|
||||
public final class TextInputController {
|
||||
|
||||
// Interface to access GeckoInputConnection from TextInputController.
|
||||
/* package */ interface Delegate {
|
||||
View getView();
|
||||
Handler getHandler(Handler defHandler);
|
||||
@ -35,6 +39,56 @@ public final class TextInputController {
|
||||
boolean isInputActive();
|
||||
}
|
||||
|
||||
// Interface to access GeckoEditable from GeckoInputConnection.
|
||||
/* package */ interface EditableClient {
|
||||
// The following value is used by requestCursorUpdates
|
||||
// ONE_SHOT calls updateCompositionRects() after getting current composing
|
||||
// character rects.
|
||||
@WrapForJNI final int ONE_SHOT = 1;
|
||||
// START_MONITOR start the monitor for composing character rects. If is is
|
||||
// updaed, call updateCompositionRects()
|
||||
@WrapForJNI final int START_MONITOR = 2;
|
||||
// ENDT_MONITOR stops the monitor for composing character rects.
|
||||
@WrapForJNI final int END_MONITOR = 3;
|
||||
|
||||
void sendKeyEvent(KeyEvent event, int action, int metaState);
|
||||
Editable getEditable();
|
||||
void setBatchMode(boolean isBatchMode);
|
||||
void setSuppressKeyUp(boolean suppress);
|
||||
Handler setInputConnectionHandler(Handler handler);
|
||||
void postToInputConnection(Runnable runnable);
|
||||
void requestCursorUpdates(int requestMode);
|
||||
}
|
||||
|
||||
// Interface to access GeckoInputConnection from GeckoEditable.
|
||||
/* package */ interface EditableListener {
|
||||
// IME notification type for notifyIME(), corresponding to NotificationToIME enum.
|
||||
@WrapForJNI final int NOTIFY_IME_OF_TOKEN = -3;
|
||||
@WrapForJNI final int NOTIFY_IME_OPEN_VKB = -2;
|
||||
@WrapForJNI final int NOTIFY_IME_REPLY_EVENT = -1;
|
||||
@WrapForJNI final int NOTIFY_IME_OF_FOCUS = 1;
|
||||
@WrapForJNI final int NOTIFY_IME_OF_BLUR = 2;
|
||||
@WrapForJNI final int NOTIFY_IME_TO_COMMIT_COMPOSITION = 8;
|
||||
@WrapForJNI final int NOTIFY_IME_TO_CANCEL_COMPOSITION = 9;
|
||||
|
||||
// IME enabled state for notifyIMEContext().
|
||||
final int IME_STATE_DISABLED = 0;
|
||||
final int IME_STATE_ENABLED = 1;
|
||||
final int IME_STATE_PASSWORD = 2;
|
||||
|
||||
// Flags for notifyIMEContext().
|
||||
@WrapForJNI final int IME_FLAG_PRIVATE_BROWSING = 1;
|
||||
@WrapForJNI final int IME_FLAG_USER_ACTION = 2;
|
||||
|
||||
void notifyIME(int type);
|
||||
void notifyIMEContext(int state, String typeHint, String modeHint,
|
||||
String actionHint, int flag);
|
||||
void onSelectionChange();
|
||||
void onTextChange();
|
||||
void onDefaultKeyEvent(KeyEvent event);
|
||||
void updateCompositionRects(final RectF[] aRects);
|
||||
}
|
||||
|
||||
private final GeckoSession mSession;
|
||||
private final GeckoEditable mEditable = new GeckoEditable();
|
||||
private final GeckoEditableChild mEditableChild = new GeckoEditableChild(mEditable);
|
||||
@ -88,7 +142,7 @@ public final class TextInputController {
|
||||
mInputConnection = GeckoInputConnection.create(mSession,
|
||||
/* view */ null,
|
||||
mEditable);
|
||||
mEditable.setListener((GeckoEditableListener) mInputConnection);
|
||||
mEditable.setListener((EditableListener) mInputConnection);
|
||||
}
|
||||
}
|
||||
|
||||
@ -117,7 +171,7 @@ public final class TextInputController {
|
||||
} else if (mInputConnection == null || mInputConnection.getView() != view) {
|
||||
mInputConnection = GeckoInputConnection.create(mSession, view, mEditable);
|
||||
}
|
||||
mEditable.setListener((GeckoEditableListener) mInputConnection);
|
||||
mEditable.setListener((EditableListener) mInputConnection);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -926,7 +926,7 @@ GeckoEditableSupport::OnImeSynchronize()
|
||||
if (!mIMEMaskEventsCount) {
|
||||
FlushIMEChanges();
|
||||
}
|
||||
mEditable->NotifyIME(GeckoEditableListener::NOTIFY_IME_REPLY_EVENT);
|
||||
mEditable->NotifyIME(EditableListener::NOTIFY_IME_REPLY_EVENT);
|
||||
}
|
||||
|
||||
void
|
||||
@ -1175,13 +1175,12 @@ GeckoEditableSupport::OnImeUpdateComposition(int32_t aStart, int32_t aEnd,
|
||||
void
|
||||
GeckoEditableSupport::OnImeRequestCursorUpdates(int aRequestMode)
|
||||
{
|
||||
if (aRequestMode == java::GeckoEditableClient::ONE_SHOT) {
|
||||
if (aRequestMode == EditableClient::ONE_SHOT) {
|
||||
UpdateCompositionRects();
|
||||
return;
|
||||
}
|
||||
|
||||
mIMEMonitorCursor =
|
||||
(aRequestMode == java::GeckoEditableClient::START_MONITOR);
|
||||
mIMEMonitorCursor = (aRequestMode == EditableClient::START_MONITOR);
|
||||
}
|
||||
|
||||
void
|
||||
@ -1207,7 +1206,7 @@ GeckoEditableSupport::NotifyIME(TextEventDispatcher* aTextEventDispatcher,
|
||||
ALOGIME("IME: REQUEST_TO_COMMIT_COMPOSITION");
|
||||
|
||||
RemoveComposition(COMMIT_IME_COMPOSITION);
|
||||
AsyncNotifyIME(GeckoEditableListener::
|
||||
AsyncNotifyIME(EditableListener::
|
||||
NOTIFY_IME_TO_COMMIT_COMPOSITION);
|
||||
break;
|
||||
}
|
||||
@ -1216,7 +1215,7 @@ GeckoEditableSupport::NotifyIME(TextEventDispatcher* aTextEventDispatcher,
|
||||
ALOGIME("IME: REQUEST_TO_CANCEL_COMPOSITION");
|
||||
|
||||
RemoveComposition(CANCEL_IME_COMPOSITION);
|
||||
AsyncNotifyIME(GeckoEditableListener::
|
||||
AsyncNotifyIME(EditableListener::
|
||||
NOTIFY_IME_TO_CANCEL_COMPOSITION);
|
||||
break;
|
||||
}
|
||||
@ -1239,7 +1238,7 @@ GeckoEditableSupport::NotifyIME(TextEventDispatcher* aTextEventDispatcher,
|
||||
}
|
||||
|
||||
mEditable->NotifyIME(
|
||||
GeckoEditableListener::NOTIFY_IME_OF_TOKEN);
|
||||
EditableListener::NOTIFY_IME_OF_TOKEN);
|
||||
|
||||
if (mIsRemote) {
|
||||
if (!mEditableAttached) {
|
||||
@ -1262,7 +1261,7 @@ GeckoEditableSupport::NotifyIME(TextEventDispatcher* aTextEventDispatcher,
|
||||
mIMEMonitorCursor = false;
|
||||
|
||||
mEditable->NotifyIME(
|
||||
GeckoEditableListener::NOTIFY_IME_OF_FOCUS);
|
||||
EditableListener::NOTIFY_IME_OF_FOCUS);
|
||||
});
|
||||
break;
|
||||
}
|
||||
@ -1271,7 +1270,7 @@ GeckoEditableSupport::NotifyIME(TextEventDispatcher* aTextEventDispatcher,
|
||||
ALOGIME("IME: NOTIFY_IME_OF_BLUR");
|
||||
|
||||
if (!mIMEMaskEventsCount) {
|
||||
mEditable->NotifyIME(GeckoEditableListener::NOTIFY_IME_OF_BLUR);
|
||||
mEditable->NotifyIME(EditableListener::NOTIFY_IME_OF_BLUR);
|
||||
OnRemovedFrom(mDispatcher);
|
||||
}
|
||||
|
||||
@ -1357,7 +1356,7 @@ GeckoEditableSupport::SetInputContext(const InputContext& aContext,
|
||||
if (mInputContext.mIMEState.mEnabled != IMEState::DISABLED &&
|
||||
aAction.UserMightRequestOpenVKB()) {
|
||||
// Don't reset keyboard when we should simply open the vkb
|
||||
mEditable->NotifyIME(GeckoEditableListener::NOTIFY_IME_OPEN_VKB);
|
||||
mEditable->NotifyIME(EditableListener::NOTIFY_IME_OPEN_VKB);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1367,8 +1366,13 @@ GeckoEditableSupport::SetInputContext(const InputContext& aContext,
|
||||
mIMEUpdatingContext = true;
|
||||
|
||||
RefPtr<GeckoEditableSupport> self(this);
|
||||
bool isUserAction = aAction.IsHandlingUserInput() || aContext.mHasHandledUserInput;
|
||||
nsAppShell::PostEvent([this, self, isUserAction] {
|
||||
const bool inPrivateBrowsing = mInputContext.mInPrivateBrowsing;
|
||||
const bool isUserAction = aAction.IsHandlingUserInput() || aContext.mHasHandledUserInput;
|
||||
const int32_t flags =
|
||||
(inPrivateBrowsing ? EditableListener::IME_FLAG_PRIVATE_BROWSING : 0) |
|
||||
(isUserAction ? EditableListener::IME_FLAG_USER_ACTION : 0);
|
||||
|
||||
nsAppShell::PostEvent([this, self, flags] {
|
||||
nsCOMPtr<nsIWidget> widget = GetWidget();
|
||||
|
||||
mIMEUpdatingContext = false;
|
||||
@ -1379,8 +1383,7 @@ GeckoEditableSupport::SetInputContext(const InputContext& aContext,
|
||||
mInputContext.mHTMLInputType,
|
||||
mInputContext.mHTMLInputInputmode,
|
||||
mInputContext.mActionHint,
|
||||
mInputContext.mInPrivateBrowsing,
|
||||
isUserAction);
|
||||
flags);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -40,6 +40,8 @@ class GeckoEditableSupport final
|
||||
|
||||
using EditableBase =
|
||||
java::GeckoEditableChild::Natives<GeckoEditableSupport>;
|
||||
using EditableClient = java::TextInputController::EditableClient;
|
||||
using EditableListener = java::TextInputController::EditableListener;
|
||||
|
||||
// RAII helper class that automatically sends an event reply through
|
||||
// OnImeSynchronize, as required by events like OnImeReplaceText.
|
||||
|
Loading…
Reference in New Issue
Block a user