Bug 1464096 - 4. Move SessionTextInput.Delegate to GeckoSession.TextInputDelegate; r=me
I think it's more consumer-friendly to put the text input delegate in
GeckoSession alongside all other delegates.
MozReview-Commit-ID: 1UlBe27vplG
--- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoEditable.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoEditable.java
@@ -1214,17 +1214,17 @@ import android.view.inputmethod.EditorIn
switch (type) {
case SessionTextInput.EditableListener.NOTIFY_IME_OF_FOCUS:
mFocusedChild = child;
mNeedSync = false;
mText.syncShadowText(/* listener */ null);
// Do not reset mIMEState here; see comments in notifyIMEContext
if (mIMEState != SessionTextInput.EditableListener.IME_STATE_DISABLED) {
- icRestartInput(SessionTextInput.Delegate.RESTART_REASON_FOCUS);
+ icRestartInput(GeckoSession.TextInputDelegate.RESTART_REASON_FOCUS);
}
break;
case SessionTextInput.EditableListener.NOTIFY_IME_OF_BLUR:
mFocusedChild = null;
break;
case SessionTextInput.EditableListener.NOTIFY_IME_OPEN_VKB:
@@ -1243,17 +1243,17 @@ import android.view.inputmethod.EditorIn
final Object[] spans = text.getSpans(0, text.length(), Object.class);
for (final Object span : spans) {
if ((text.getSpanFlags(span) & Spanned.SPAN_COMPOSING) != 0) {
// Still have composition; no need to reset.
return; // Don't notify listener.
}
}
// No longer have composition; perform reset.
- icRestartInput(SessionTextInput.Delegate.RESTART_REASON_CONTENT_CHANGE);
+ icRestartInput(GeckoSession.TextInputDelegate.RESTART_REASON_CONTENT_CHANGE);
return; // Don't notify listener.
}
default:
throw new IllegalArgumentException("Invalid notifyIME type: " + type);
}
if (mListener != null) {
@@ -1315,26 +1315,29 @@ import android.view.inputmethod.EditorIn
mListener.notifyIMEContext(state, typeHint, modeHint, actionHint, flags);
}
// On focus, the notifyIMEContext call comes *before* the
// notifyIME(NOTIFY_IME_OF_FOCUS) call, but we need to call restartInput during
// notifyIME, so we skip restartInput here. On blur, the notifyIMEContext call
// comes *after* the notifyIME(NOTIFY_IME_OF_BLUR) call, and we need to call
// restartInput here.
- if (oldState != SessionTextInput.EditableListener.IME_STATE_DISABLED) {
- if (state == SessionTextInput.EditableListener.IME_STATE_DISABLED) {
- icRestartInput(SessionTextInput.Delegate.RESTART_REASON_BLUR);
- } else if (mFocusedChild != null) {
- icRestartInput(SessionTextInput.Delegate.RESTART_REASON_CONTENT_CHANGE);
- }
+
+ // In either case, there is nothing to do here if we were disabled before.
+ if (oldState == SessionTextInput.EditableListener.IME_STATE_DISABLED) {
+ return;
+ }
+ if (state == SessionTextInput.EditableListener.IME_STATE_DISABLED) {
+ icRestartInput(GeckoSession.TextInputDelegate.RESTART_REASON_BLUR);
+ } else if (mFocusedChild != null) {
+ icRestartInput(GeckoSession.TextInputDelegate.RESTART_REASON_CONTENT_CHANGE);
}
}
- private void icRestartInput(@SessionTextInput.Delegate.RestartReason final int reason) {
+ private void icRestartInput(@GeckoSession.TextInputDelegate.RestartReason final int reason) {
if (DEBUG) {
assertOnIcThread();
}
ThreadUtils.postToUiThread(new Runnable() {
@Override
public void run() {
mSoftInputReentrancyGuard.incrementAndGet();
--- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoInputConnection.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoInputConnection.java
@@ -255,17 +255,17 @@ import java.lang.reflect.Proxy;
}
@Override // SessionTextInput.InputConnectionClient
public View getView() {
return mView;
}
@NonNull
- /* package */ SessionTextInput.Delegate getInputDelegate() {
+ /* package */ GeckoSession.TextInputDelegate getInputDelegate() {
return mSession.getTextInput().getDelegate();
}
@Override // SessionTextInput.EditableListener
public void onTextChange() {
final Editable editable = getEditable();
if (mUpdateRequest == null || editable == null) {
return;
--- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoSession.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoSession.java
@@ -41,16 +41,19 @@ import android.os.Parcel;
import android.os.Parcelable;
import android.os.SystemClock;
import android.support.annotation.IntDef;
import android.support.annotation.Nullable;
import android.support.annotation.NonNull;
import android.support.annotation.StringDef;
import android.util.Base64;
import android.util.Log;
+import android.view.inputmethod.CursorAnchorInfo;
+import android.view.inputmethod.ExtractedText;
+import android.view.inputmethod.ExtractedTextRequest;
public class GeckoSession extends LayerSession
implements Parcelable {
private static final String LOGTAG = "GeckoSession";
private static final boolean DEBUG = false;
// Type of changes given to onWindowChanged.
// Window has been cleared due to the session being closed.
@@ -2913,9 +2916,99 @@ public class GeckoSession extends LayerS
* @param uri The URI of the content requesting the permission.
* @param video List of video sources, or null if not requesting video.
* @param audio List of audio sources, or null if not requesting audio.
* @param callback Callback interface.
*/
void onMediaPermissionRequest(GeckoSession session, String uri, MediaSource[] video,
MediaSource[] audio, MediaCallback callback);
}
+
+ /**
+ * Interface that SessionTextInput uses for performing operations such as opening and closing
+ * the software keyboard. If the delegate is not set, these operations are forwarded to the
+ * system {@link android.view.inputmethod.InputMethodManager} automatically.
+ */
+ public interface TextInputDelegate {
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({RESTART_REASON_FOCUS, RESTART_REASON_BLUR, RESTART_REASON_CONTENT_CHANGE})
+ @interface RestartReason {}
+ /** Restarting input due to an input field gaining focus. */
+ int RESTART_REASON_FOCUS = 0;
+ /** Restarting input due to an input field losing focus. */
+ int RESTART_REASON_BLUR = 1;
+ /**
+ * Restarting input due to the content of the input field changing. For example, the
+ * input field type may have changed, or the current composition may have been committed
+ * outside of the input method.
+ */
+ int RESTART_REASON_CONTENT_CHANGE = 2;
+
+ /**
+ * Reset the input method, and discard any existing states such as the current composition
+ * or current autocompletion. Because the current focused editor may have changed, as
+ * part of the reset, a custom input method would normally call {@link
+ * SessionTextInput#onCreateInputConnection} to update its knowledge of the focused editor.
+ * Note that {@code restartInput} should be used to detect changes in focus, rather than
+ * {@link #showSoftInput} or {@link #hideSoftInput}, because focus changes are not always
+ * accompanied by requests to show or hide the soft input. This method is always called,
+ * even in viewless mode.
+ *
+ * @param session Session instance.
+ * @param reason Reason for the reset.
+ */
+ void restartInput(@NonNull GeckoSession session, @RestartReason int reason);
+
+ /**
+ * Display the soft input. May be called consecutively, even if the soft input is
+ * already shown. This method is always called, even in viewless mode.
+ *
+ * @param session Session instance.
+ * @see #hideSoftInput
+ * */
+ void showSoftInput(@NonNull GeckoSession session);
+
+ /**
+ * Hide the soft input. May be called consecutively, even if the soft input is
+ * already hidden. This method is always called, even in viewless mode.
+ *
+ * @param session Session instance.
+ * @see #showSoftInput
+ * */
+ void hideSoftInput(@NonNull GeckoSession session);
+
+ /**
+ * Update the soft input on the current selection. This method is <i>not</i> called
+ * in viewless mode.
+ *
+ * @param session Session instance.
+ * @param selStart Start offset of the selection.
+ * @param selEnd End offset of the selection.
+ * @param compositionStart Composition start offset, or -1 if there is no composition.
+ * @param compositionEnd Composition end offset, or -1 if there is no composition.
+ */
+ void updateSelection(@NonNull GeckoSession session, int selStart, int selEnd,
+ int compositionStart, int compositionEnd);
+
+ /**
+ * Update the soft input on the current extracted text, as requested through
+ * {@link android.view.inputmethod.InputConnection#getExtractedText}.
+ * Consequently, this method is <i>not</i> called in viewless mode.
+ *
+ * @param session Session instance.
+ * @param request The extract text request.
+ * @param text The extracted text.
+ */
+ void updateExtractedText(@NonNull GeckoSession session,
+ @NonNull ExtractedTextRequest request,
+ @NonNull ExtractedText text);
+
+ /**
+ * Update the cursor-anchor information as requested through
+ * {@link android.view.inputmethod.InputConnection#requestCursorUpdates}.
+ * Consequently, this method is <i>not</i> called in viewless mode.
+ *
+ * @param session Session instance.
+ * @param info Cursor-anchor information.
+ */
+ void updateCursorAnchorInfo(@NonNull GeckoSession session, @NonNull CursorAnchorInfo info);
+ }
}
--- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/SessionTextInput.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/SessionTextInput.java
@@ -13,138 +13,44 @@ import org.mozilla.gecko.NativeQueue;
import org.mozilla.gecko.util.ActivityUtils;
import org.mozilla.gecko.util.ThreadUtils;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Context;
import android.graphics.RectF;
import android.os.Handler;
-import android.support.annotation.IntDef;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.text.Editable;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.view.inputmethod.CursorAnchorInfo;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.ExtractedText;
import android.view.inputmethod.ExtractedTextRequest;
import android.view.inputmethod.InputConnection;
import android.view.inputmethod.InputMethodManager;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
/**
* {@code SessionTextInput} handles text input for {@code GeckoSession} through key events or input
* methods. It is typically used to implement certain methods in {@link android.view.View}
* such as {@link android.view.View#onCreateInputConnection}, by forwarding such calls to
* corresponding methods in {@code SessionTextInput}.
* <p>
* For full functionality, {@code SessionTextInput} requires a {@link android.view.View} to be set
* first through {@link #setView}. When a {@link android.view.View} is not set or set to null,
* {@code SessionTextInput} will operate in a reduced functionality mode. See {@link
- * #onCreateInputConnection} and methods in {@link Delegate} for changes in behavior in this
- * viewless mode.
+ * #onCreateInputConnection} and methods in {@link GeckoSession.TextInputDelegate} for changes in
+ * behavior in this viewless mode.
*/
public final class SessionTextInput {
/* package */ static final String LOGTAG = "GeckoSessionTextInput";
- /**
- * Interface that SessionTextInput uses for performing operations such as opening and closing
- * the software keyboard. If the delegate is not set, these operations are forwarded to the
- * system {@link android.view.inputmethod.InputMethodManager} automatically.
- */
- public interface Delegate {
- @Retention(RetentionPolicy.SOURCE)
- @IntDef({RESTART_REASON_FOCUS, RESTART_REASON_BLUR, RESTART_REASON_CONTENT_CHANGE})
- @interface RestartReason {}
- /** Restarting input due to an input field gaining focus. */
- int RESTART_REASON_FOCUS = 0;
- /** Restarting input due to an input field losing focus. */
- int RESTART_REASON_BLUR = 1;
- /**
- * Restarting input due to the content of the input field changing. For example, the
- * input field type may have changed, or the current composition may have been committed
- * outside of the input method.
- */
- int RESTART_REASON_CONTENT_CHANGE = 2;
-
- /**
- * Reset the input method, and discard any existing states such as the current composition
- * or current autocompletion. Because the current focused editor may have changed, as
- * part of the reset, a custom input method would normally call {@link
- * #onCreateInputConnection} to update its knowledge of the focused editor. Note that
- * {@code restartInput} should be used to detect changes in focus, rather than {@link
- * #showSoftInput} or {@link #hideSoftInput}, because focus changes are not always
- * accompanied by requests to show or hide the soft input. This method is always called,
- * even in viewless mode.
- *
- * @param session Session instance.
- * @param reason Reason for the reset.
- */
- void restartInput(@NonNull GeckoSession session, @RestartReason int reason);
-
- /**
- * Display the soft input. May be called consecutively, even if the soft input is
- * already shown. This method is always called, even in viewless mode.
- *
- * @param session Session instance.
- * @see #hideSoftInput
- * */
- void showSoftInput(@NonNull GeckoSession session);
-
- /**
- * Hide the soft input. May be called consecutively, even if the soft input is
- * already hidden. This method is always called, even in viewless mode.
- *
- * @param session Session instance.
- * @see #showSoftInput
- * */
- void hideSoftInput(@NonNull GeckoSession session);
-
- /**
- * Update the soft input on the current selection. This method is <i>not</i> called
- * in viewless mode.
- *
- * @param session Session instance.
- * @param selStart Start offset of the selection.
- * @param selEnd End offset of the selection.
- * @param compositionStart Composition start offset, or -1 if there is no composition.
- * @param compositionEnd Composition end offset, or -1 if there is no composition.
- */
- void updateSelection(@NonNull GeckoSession session, int selStart, int selEnd,
- int compositionStart, int compositionEnd);
-
- /**
- * Update the soft input on the current extracted text, as requested through
- * {@link android.view.inputmethod.InputConnection#getExtractedText}.
- * Consequently, this method is <i>not</i> called in viewless mode.
- *
- * @param session Session instance.
- * @param request The extract text request.
- * @param text The extracted text.
- */
- void updateExtractedText(@NonNull GeckoSession session,
- @NonNull ExtractedTextRequest request,
- @NonNull ExtractedText text);
-
- /**
- * Update the cursor-anchor information as requested through
- * {@link android.view.inputmethod.InputConnection#requestCursorUpdates}.
- * Consequently, this method is <i>not</i> called in viewless mode.
- *
- * @param session Session instance.
- * @param info Cursor-anchor information.
- */
- void updateCursorAnchorInfo(@NonNull GeckoSession session, @NonNull CursorAnchorInfo info);
- }
-
// Interface to access GeckoInputConnection from SessionTextInput.
/* package */ interface InputConnectionClient {
View getView();
Handler getHandler(Handler defHandler);
InputConnection onCreateInputConnection(EditorInfo attrs);
}
// Interface to access GeckoEditable from GeckoInputConnection.
@@ -191,17 +97,17 @@ public final class SessionTextInput {
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 static final class DefaultDelegate implements Delegate {
+ private static final class DefaultDelegate implements GeckoSession.TextInputDelegate {
public static final DefaultDelegate INSTANCE = new DefaultDelegate();
private InputMethodManager getInputMethodManager(@Nullable final View view) {
if (view == null) {
return null;
}
return (InputMethodManager) view.getContext()
.getSystemService(Context.INPUT_METHOD_SERVICE);
@@ -313,17 +219,17 @@ public final class SessionTextInput {
}
}
private final GeckoSession mSession;
private final NativeQueue mQueue;
private final GeckoEditable mEditable;
private final GeckoEditableChild mEditableChild;
private InputConnectionClient mInputConnection;
- private Delegate mDelegate;
+ private GeckoSession.TextInputDelegate mDelegate;
/* package */ SessionTextInput(final @NonNull GeckoSession session,
final @NonNull NativeQueue queue) {
mSession = session;
mQueue = queue;
mEditable = new GeckoEditable(session);
mEditableChild = new GeckoEditableChild(mEditable);
mEditable.setDefaultEditableChild(mEditableChild);
@@ -476,28 +382,28 @@ public final class SessionTextInput {
final @NonNull KeyEvent event) {
ThreadUtils.assertOnUiThread();
return mEditable.onKeyMultiple(getView(), keyCode, repeatCount, event);
}
/**
* Set the current text input delegate.
*
- * @param delegate Delegate instance or null to restore to default.
+ * @param delegate TextInputDelegate instance or null to restore to default.
*/
- public void setDelegate(@Nullable final Delegate delegate) {
+ public void setDelegate(@Nullable final GeckoSession.TextInputDelegate delegate) {
ThreadUtils.assertOnUiThread();
mDelegate = delegate;
}
/**
* Get the current text input delegate.
*
- * @return Delegate instance or a default instance if no delegate has been set.
+ * @return TextInputDelegate instance or a default instance if no delegate has been set.
*/
- public Delegate getDelegate() {
+ public GeckoSession.TextInputDelegate getDelegate() {
ThreadUtils.assertOnUiThread();
if (mDelegate == null) {
mDelegate = DefaultDelegate.INSTANCE;
}
return mDelegate;
}
}