aboutsummaryrefslogtreecommitdiffstats
path: root/java/src
diff options
context:
space:
mode:
Diffstat (limited to 'java/src')
-rw-r--r--java/src/com/android/inputmethod/latin/ImportantNoticeDialog.java78
-rw-r--r--java/src/com/android/inputmethod/latin/LatinIME.java56
-rw-r--r--java/src/com/android/inputmethod/latin/RichInputConnection.java14
-rw-r--r--java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java47
-rw-r--r--java/src/com/android/inputmethod/latin/utils/ImportantNoticeUtils.java28
5 files changed, 146 insertions, 77 deletions
diff --git a/java/src/com/android/inputmethod/latin/ImportantNoticeDialog.java b/java/src/com/android/inputmethod/latin/ImportantNoticeDialog.java
new file mode 100644
index 000000000..9870faa98
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/ImportantNoticeDialog.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.inputmethod.latin;
+
+import android.app.AlertDialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.DialogInterface.OnClickListener;
+import android.content.DialogInterface.OnDismissListener;
+import android.content.DialogInterface.OnShowListener;
+
+import com.android.inputmethod.latin.utils.ImportantNoticeUtils;
+
+/**
+ * The dialog box that shows the important notice contents.
+ */
+public final class ImportantNoticeDialog extends AlertDialog implements OnShowListener,
+ OnClickListener, OnDismissListener {
+ public interface ImportantNoticeDialogListener {
+ public void onClickSettingsOfImportantNoticeDialog(final int nextVersion);
+ public void onDismissImportantNoticeDialog(final int nextVersion);
+ }
+
+ private final ImportantNoticeDialogListener mListener;
+ private final int mNextImportantNoticeVersion;
+
+ public ImportantNoticeDialog(
+ final Context context, final ImportantNoticeDialogListener listener) {
+ super(context, THEME_HOLO_DARK);
+ mListener = listener;
+ mNextImportantNoticeVersion = ImportantNoticeUtils.getNextImportantNoticeVersion(context);
+ setMessage(ImportantNoticeUtils.getNextImportantNoticeContents(context));
+ // Create buttons and set listeners.
+ setButton(BUTTON_POSITIVE, context.getString(android.R.string.ok), this);
+ if (shouldHaveSettingsButton()) {
+ setButton(BUTTON_NEGATIVE, context.getString(R.string.go_to_settings), this);
+ }
+ // Set listeners.
+ setOnShowListener(this);
+ setOnDismissListener(this);
+ }
+
+ private boolean shouldHaveSettingsButton() {
+ return mNextImportantNoticeVersion
+ == ImportantNoticeUtils.VERSION_TO_ENABLE_PERSONALIZED_SUGGESTIONS;
+ }
+
+ @Override
+ public void onShow(final DialogInterface dialog) {
+ ImportantNoticeUtils.updateLastImportantNoticeVersion(getContext());
+ }
+
+ @Override
+ public void onClick(final DialogInterface dialog, final int which) {
+ if (shouldHaveSettingsButton() && which == BUTTON_NEGATIVE) {
+ mListener.onClickSettingsOfImportantNoticeDialog(mNextImportantNoticeVersion);
+ }
+ }
+
+ @Override
+ public void onDismiss(final DialogInterface dialog) {
+ mListener.onDismissImportantNoticeDialog(mNextImportantNoticeVersion);
+ }
+}
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index 47a3e9469..9ded5a85e 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -26,8 +26,6 @@ import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
-import android.content.DialogInterface.OnDismissListener;
-import android.content.DialogInterface.OnShowListener;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
@@ -100,7 +98,8 @@ import java.util.concurrent.TimeUnit;
*/
public class LatinIME extends InputMethodService implements KeyboardActionListener,
SuggestionStripView.Listener, SuggestionStripViewAccessor,
- DictionaryFacilitatorForSuggest.DictionaryInitializationListener {
+ DictionaryFacilitatorForSuggest.DictionaryInitializationListener,
+ ImportantNoticeDialog.ImportantNoticeDialogListener {
private static final String TAG = LatinIME.class.getSimpleName();
private static final boolean TRACE = false;
private static boolean DEBUG = false;
@@ -799,19 +798,22 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
suggest = mInputLogic.mSuggest;
}
- // Sometimes, while rotating, for some reason the framework tells the app we are not
- // connected to it and that means we can't refresh the cache. In this case, schedule a
- // refresh later.
// TODO[IL]: Can the following be moved to InputLogic#startInput?
final boolean canReachInputConnection;
if (!mInputLogic.mConnection.resetCachesUponCursorMoveAndReturnSuccess(
editorInfo.initialSelStart, editorInfo.initialSelEnd,
false /* shouldFinishComposition */)) {
+ // Sometimes, while rotating, for some reason the framework tells the app we are not
+ // connected to it and that means we can't refresh the cache. In this case, schedule a
+ // refresh later.
// We try resetting the caches up to 5 times before giving up.
mHandler.postResetCaches(isDifferentTextField, 5 /* remainingTries */);
// mLastSelection{Start,End} are reset later in this method, don't need to do it here
canReachInputConnection = false;
} else {
+ // When rotating, initialSelStart and initialSelEnd sometimes are lying. Make a best
+ // effort to work around this bug.
+ mInputLogic.mConnection.tryFixLyingCursorPosition();
if (isDifferentTextField) {
mHandler.postResumeSuggestions();
}
@@ -1177,39 +1179,23 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
mInputLogic.mSuggest.mDictionaryFacilitator.addWordToUserDictionary(wordToEdit);
}
- // TODO: Move this method out of {@link LatinIME}.
// Callback for the {@link SuggestionStripView}, to call when the important notice strip is
// pressed.
@Override
public void showImportantNoticeContents() {
- final Context context = this;
- final AlertDialog.Builder builder =
- new AlertDialog.Builder(context, AlertDialog.THEME_HOLO_DARK);
- builder.setMessage(ImportantNoticeUtils.getNextImportantNoticeContents(context));
- builder.setPositiveButton(android.R.string.ok, null /* listener */);
- final OnClickListener onClickListener = new OnClickListener() {
- @Override
- public void onClick(final DialogInterface dialog, final int position) {
- if (position == DialogInterface.BUTTON_NEGATIVE) {
- launchSettings();
- }
- }
- };
- builder.setNegativeButton(R.string.go_to_settings, onClickListener);
- final AlertDialog importantNoticeDialog = builder.create();
- importantNoticeDialog.setOnShowListener(new OnShowListener() {
- @Override
- public void onShow(final DialogInterface dialog) {
- ImportantNoticeUtils.updateLastImportantNoticeVersion(context);
- }
- });
- importantNoticeDialog.setOnDismissListener(new OnDismissListener() {
- @Override
- public void onDismiss(final DialogInterface dialog) {
- setNeutralSuggestionStrip();
- }
- });
- showOptionDialog(importantNoticeDialog);
+ showOptionDialog(new ImportantNoticeDialog(this /* context */, this /* listener */));
+ }
+
+ // Implement {@link ImportantNoticeDialog.ImportantNoticeDialogListener}
+ @Override
+ public void onClickSettingsOfImportantNoticeDialog(final int nextVersion) {
+ launchSettings();
+ }
+
+ // Implement {@link ImportantNoticeDialog.ImportantNoticeDialogListener}
+ @Override
+ public void onDismissImportantNoticeDialog(final int nextVersion) {
+ setNeutralSuggestionStrip();
}
public void displaySettingsDialog() {
diff --git a/java/src/com/android/inputmethod/latin/RichInputConnection.java b/java/src/com/android/inputmethod/latin/RichInputConnection.java
index cc2db4c93..0e85b3c77 100644
--- a/java/src/com/android/inputmethod/latin/RichInputConnection.java
+++ b/java/src/com/android/inputmethod/latin/RichInputConnection.java
@@ -172,20 +172,6 @@ public final class RichInputConnection {
Log.d(TAG, "Will try to retrieve text later.");
return false;
}
- final int lengthOfTextBeforeCursor = mCommittedTextBeforeComposingText.length();
- if (lengthOfTextBeforeCursor > newSelStart
- || (newSelStart != lengthOfTextBeforeCursor
- && lengthOfTextBeforeCursor < Constants.EDITOR_CONTENTS_CACHE_SIZE
- && newSelStart < Constants.EDITOR_CONTENTS_CACHE_SIZE)) {
- // newSelStart and newSelEnd may be lying -- when rotating the device (probably a
- // framework bug). If the values don't agree and we have less chars than we asked
- // for, then we know how many chars we have. If we got more than newSelStart says, then
- // we also know it was lying. In both cases the length is more reliable. Note that we
- // only have to check newSelStart (not newSelEnd) since if newSelEnd is wrong, then
- // newSelStart will be wrong as well.
- mExpectedSelStart = lengthOfTextBeforeCursor;
- mExpectedSelEnd = lengthOfTextBeforeCursor;
- }
if (null != mIC && shouldFinishComposition) {
mIC.finishComposingText();
if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
diff --git a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
index 52a6f5f08..eeb5bf536 100644
--- a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
+++ b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
@@ -330,7 +330,13 @@ public final class InputLogic {
// Another option would be to send suggestions each time we set the composing
// text, but that is probably too expensive to do, so we decided to leave things
// as is.
- resetEntireInputState(settingsValues, newSelStart, newSelEnd);
+ // Also, we're posting a resume suggestions message, and this will update the
+ // suggestions strip in a few milliseconds, so if we cleared the suggestion strip here
+ // we'd have the suggestion strip noticeably janky. To avoid that, we don't clear
+ // it here, which means we'll keep outdated suggestions for a split second but the
+ // visual result is better.
+ resetEntireInputState(settingsValues, newSelStart, newSelEnd,
+ false /* clearSuggestionStrip */);
} else {
// resetEntireInputState calls resetCachesUponCursorMove, but forcing the
// composition to end. But in all cases where we don't reset the entire input
@@ -498,7 +504,7 @@ public final class InputLogic {
// If we are in the middle of a recorrection, we need to commit the recorrection
// first so that we can insert the batch input at the current cursor position.
resetEntireInputState(settingsValues, mConnection.getExpectedSelectionStart(),
- mConnection.getExpectedSelectionEnd());
+ mConnection.getExpectedSelectionEnd(), true /* clearSuggestionStrip */);
} else if (wordComposerSize <= 1) {
// We auto-correct the previous (typed, not gestured) string iff it's one character
// long. The reason for this is, even in the middle of gesture typing, you'll still
@@ -651,7 +657,7 @@ public final class InputLogic {
// If we are in the middle of a recorrection, we need to commit the recorrection
// first so that we can insert the character at the current cursor position.
resetEntireInputState(settingsValues, mConnection.getExpectedSelectionStart(),
- mConnection.getExpectedSelectionEnd());
+ mConnection.getExpectedSelectionEnd(), true /* clearSuggestionStrip */);
} else {
commitTyped(settingsValues, LastComposedWord.NOT_A_SEPARATOR);
}
@@ -693,7 +699,7 @@ public final class InputLogic {
// If we are in the middle of a recorrection, we need to commit the recorrection
// first so that we can insert the character at the current cursor position.
resetEntireInputState(settingsValues, mConnection.getExpectedSelectionStart(),
- mConnection.getExpectedSelectionEnd());
+ mConnection.getExpectedSelectionEnd(), true /* clearSuggestionStrip */);
isComposingWord = false;
}
// We want to find out whether to start composing a new word with this character. If so,
@@ -775,7 +781,7 @@ public final class InputLogic {
// If we are in the middle of a recorrection, we need to commit the recorrection
// first so that we can insert the separator at the current cursor position.
resetEntireInputState(settingsValues, mConnection.getExpectedSelectionStart(),
- mConnection.getExpectedSelectionEnd());
+ mConnection.getExpectedSelectionEnd(), true /* clearSuggestionStrip */);
}
// isComposingWord() may have changed since we stored wasComposing
if (mWordComposer.isComposingWord()) {
@@ -881,7 +887,7 @@ public final class InputLogic {
// If we are in the middle of a recorrection, we need to commit the recorrection
// first so that we can remove the character at the current cursor position.
resetEntireInputState(settingsValues, mConnection.getExpectedSelectionStart(),
- mConnection.getExpectedSelectionEnd());
+ mConnection.getExpectedSelectionEnd(), true /* clearSuggestionStrip */);
// When we exit this if-clause, mWordComposer.isComposingWord() will return false.
}
if (mWordComposer.isComposingWord()) {
@@ -1252,18 +1258,28 @@ public final class InputLogic {
// HACK: We may want to special-case some apps that exhibit bad behavior in case of
// recorrection. This is a temporary, stopgap measure that will be removed later.
// TODO: remove this.
- if (settingsValues.isBrokenByRecorrection()) return;
+ if (settingsValues.isBrokenByRecorrection()
// Recorrection is not supported in languages without spaces because we don't know
// how to segment them yet.
- if (!settingsValues.mSpacingAndPunctuations.mCurrentLanguageHasSpaces) return;
+ || !settingsValues.mSpacingAndPunctuations.mCurrentLanguageHasSpaces
// If no suggestions are requested, don't try restarting suggestions.
- if (!settingsValues.isSuggestionsRequested()) return;
+ || !settingsValues.isSuggestionsRequested()
// If the cursor is not touching a word, or if there is a selection, return right away.
- if (mConnection.hasSelection()) return;
+ || mConnection.hasSelection()
// If we don't know the cursor location, return.
- if (mConnection.getExpectedSelectionStart() < 0) return;
+ || mConnection.getExpectedSelectionStart() < 0) {
+ mSuggestionStripViewAccessor.setNeutralSuggestionStrip();
+ return;
+ }
final int expectedCursorPosition = mConnection.getExpectedSelectionStart();
- if (!mConnection.isCursorTouchingWord(settingsValues.mSpacingAndPunctuations)) return;
+ if (!mConnection.isCursorTouchingWord(settingsValues.mSpacingAndPunctuations)) {
+ // Show predictions.
+ mWordComposer.setCapitalizedModeAndPreviousWordAtStartComposingTime(
+ WordComposer.CAPS_MODE_OFF,
+ getNthPreviousWordForSuggestion(settingsValues.mSpacingAndPunctuations, 1));
+ mLatinIME.mHandler.postUpdateSuggestionStrip();
+ return;
+ }
final TextRange range = mConnection.getWordRangeAtCursor(
settingsValues.mSpacingAndPunctuations.mSortedWordSeparators,
0 /* additionalPrecedingWordsCount */);
@@ -1606,14 +1622,17 @@ public final class InputLogic {
* @param settingsValues the current values of the settings.
* @param newSelStart the new selection start, in java characters.
* @param newSelEnd the new selection end, in java characters.
+ * @param clearSuggestionStrip whether this method should clear the suggestion strip.
*/
// TODO: how is this different from startInput ?!
// TODO: remove all references to this in LatinIME and make this private
public void resetEntireInputState(final SettingsValues settingsValues,
- final int newSelStart, final int newSelEnd) {
+ final int newSelStart, final int newSelEnd, final boolean clearSuggestionStrip) {
final boolean shouldFinishComposition = mWordComposer.isComposingWord();
resetComposingState(true /* alsoResetLastComposedWord */);
- mSuggestionStripViewAccessor.setNeutralSuggestionStrip();
+ if (clearSuggestionStrip) {
+ mSuggestionStripViewAccessor.setNeutralSuggestionStrip();
+ }
mConnection.resetCachesUponCursorMoveAndReturnSuccess(newSelStart, newSelEnd,
shouldFinishComposition);
}
diff --git a/java/src/com/android/inputmethod/latin/utils/ImportantNoticeUtils.java b/java/src/com/android/inputmethod/latin/utils/ImportantNoticeUtils.java
index 6b0bb86ac..ca8bef397 100644
--- a/java/src/com/android/inputmethod/latin/utils/ImportantNoticeUtils.java
+++ b/java/src/com/android/inputmethod/latin/utils/ImportantNoticeUtils.java
@@ -60,7 +60,7 @@ public final class ImportantNoticeUtils {
return context.getSharedPreferences(PREFERENCE_NAME, Context.MODE_PRIVATE);
}
- public static int getCurrentImportantNoticeVersion(final Context context) {
+ private static int getCurrentImportantNoticeVersion(final Context context) {
return context.getResources().getInteger(R.integer.config_important_notice_version);
}
@@ -68,7 +68,7 @@ public final class ImportantNoticeUtils {
return getImportantNoticePreferences(context).getInt(KEY_IMPORTANT_NOTICE_VERSION, 0);
}
- private static int getNextImportantNoticeVersion(final Context context) {
+ public static int getNextImportantNoticeVersion(final Context context) {
return getLastImportantNoticeVersion(context) + 1;
}
@@ -92,23 +92,23 @@ public final class ImportantNoticeUtils {
.apply();
}
- // TODO: Make title resource to string array indexed by version.
public static String getNextImportantNoticeTitle(final Context context) {
- switch (getNextImportantNoticeVersion(context)) {
- case VERSION_TO_ENABLE_PERSONALIZED_SUGGESTIONS:
- return context.getString(R.string.important_notice_title);
- default:
- return null;
+ final int nextVersion = getCurrentImportantNoticeVersion(context);
+ final String[] importantNoticeTitleArray = context.getResources().getStringArray(
+ R.array.important_notice_title_array);
+ if (nextVersion > 0 && nextVersion < importantNoticeTitleArray.length) {
+ return importantNoticeTitleArray[nextVersion];
}
+ return null;
}
- // TODO: Make content resource to string array indexed by version.
public static String getNextImportantNoticeContents(final Context context) {
- switch (getNextImportantNoticeVersion(context)) {
- case VERSION_TO_ENABLE_PERSONALIZED_SUGGESTIONS:
- return context.getString(R.string.important_notice_contents);
- default:
- return null;
+ final int nextVersion = getNextImportantNoticeVersion(context);
+ final String[] importantNoticeContentsArray = context.getResources().getStringArray(
+ R.array.important_notice_contents_array);
+ if (nextVersion > 0 && nextVersion < importantNoticeContentsArray.length) {
+ return importantNoticeContentsArray[nextVersion];
}
+ return null;
}
}