Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2162)

Unified Diff: chrome/android/java_staging/src/org/chromium/chrome/browser/widget/findinpage/FindToolbar.java

Issue 1141283003: Upstream oodles of Chrome for Android code into Chromium. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: final patch? Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/android/java_staging/src/org/chromium/chrome/browser/widget/findinpage/FindToolbar.java
diff --git a/chrome/android/java_staging/src/org/chromium/chrome/browser/widget/findinpage/FindToolbar.java b/chrome/android/java_staging/src/org/chromium/chrome/browser/widget/findinpage/FindToolbar.java
new file mode 100644
index 0000000000000000000000000000000000000000..576b8e71c5f02dace85ebc069111c43310d40284
--- /dev/null
+++ b/chrome/android/java_staging/src/org/chromium/chrome/browser/widget/findinpage/FindToolbar.java
@@ -0,0 +1,636 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.widget.findinpage;
+
+import android.annotation.SuppressLint;
+import android.content.Context;
+import android.graphics.Rect;
+import android.os.Handler;
+import android.os.Vibrator;
+import android.provider.Settings;
+import android.support.v4.view.accessibility.AccessibilityEventCompat;
+import android.text.Editable;
+import android.text.InputType;
+import android.text.TextWatcher;
+import android.util.AttributeSet;
+import android.view.ActionMode;
+import android.view.Gravity;
+import android.view.KeyEvent;
+import android.view.View;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import com.google.android.apps.chrome.R;
+
+import org.chromium.base.VisibleForTesting;
+import org.chromium.chrome.browser.ChromeWebContentsDelegateAndroid;
+import org.chromium.chrome.browser.EmptyTabObserver;
+import org.chromium.chrome.browser.FindMatchRectsDetails;
+import org.chromium.chrome.browser.FindNotificationDetails;
+import org.chromium.chrome.browser.Tab;
+import org.chromium.chrome.browser.TabObserver;
+import org.chromium.chrome.browser.findinpage.FindInPageBridge;
+import org.chromium.chrome.browser.tabmodel.EmptyTabModelObserver;
+import org.chromium.chrome.browser.tabmodel.EmptyTabModelSelectorObserver;
+import org.chromium.chrome.browser.tabmodel.TabModel;
+import org.chromium.chrome.browser.tabmodel.TabModel.TabSelectionType;
+import org.chromium.chrome.browser.tabmodel.TabModelObserver;
+import org.chromium.chrome.browser.tabmodel.TabModelSelector;
+import org.chromium.chrome.browser.tabmodel.TabModelSelectorObserver;
+import org.chromium.chrome.browser.widget.TintedImageButton;
+import org.chromium.chrome.browser.widget.VerticallyFixedEditText;
+import org.chromium.ui.UiUtils;
+
+/** A toolbar providing find in page functionality. */
+public class FindToolbar extends LinearLayout
+ implements ChromeWebContentsDelegateAndroid.FindResultListener,
+ ChromeWebContentsDelegateAndroid.FindMatchRectsListener {
+ private static final long ACCESSIBLE_ANNOUNCEMENT_DELAY_MILLIS = 500;
+
+ // Toolbar UI
+ private TextView mFindStatus;
+ protected FindQuery mFindQuery;
+ protected TintedImageButton mCloseFindButton;
+ protected TintedImageButton mFindPrevButton;
+ protected TintedImageButton mFindNextButton;
+
+ private FindResultBar mResultBar = null;
+
+ protected TabModelSelector mTabModelSelector;
+ private final TabModelSelectorObserver mTabModelSelectorObserver;
+ private final TabModelObserver mTabModelObserver;
+ private Tab mCurrentTab;
+ private final TabObserver mTabObserver;
+ private FindInPageBridge mFindInPageBridge;
+ private FindToolbarObserver mObserver;
+
+ /** Most recently entered search text (globally, in non-incognito tabs). */
+ private String mLastUserSearch = "";
+
+ /** Whether toolbar text is being set automatically (not typed by user). */
+ private boolean mSettingFindTextProgrammatically = false;
+
+ /** Whether the search key should trigger a new search. */
+ private boolean mSearchKeyShouldTriggerSearch = false;
+
+ private boolean mActive = false;
+
+ private Handler mHandler = new Handler();
+ private Runnable mAccessibleAnnouncementRunnable;
+ private boolean mAccessibilityDidActivateResult;
+
+ /** Subclasses EditText in order to intercept BACK key presses. */
+ @SuppressLint("Instantiatable")
+ static class FindQuery extends VerticallyFixedEditText {
+ private FindToolbar mFindToolbar;
+
+ public FindQuery(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ void setFindToolbar(FindToolbar findToolbar) {
+ mFindToolbar = findToolbar;
+ }
+
+ @Override
+ public boolean onKeyPreIme(int keyCode, KeyEvent event) {
+ if (keyCode == KeyEvent.KEYCODE_BACK) {
+ if (event.getAction() == KeyEvent.ACTION_DOWN
+ && event.getRepeatCount() == 0) {
+ // Tell the framework to start tracking this event.
+ getKeyDispatcherState().startTracking(event, this);
+ return true;
+ } else if (event.getAction() == KeyEvent.ACTION_UP) {
+ getKeyDispatcherState().handleUpEvent(event);
+ if (event.isTracking() && !event.isCanceled()) {
+ mFindToolbar.deactivate();
+ return true;
+ }
+ }
+ }
+ return super.onKeyPreIme(keyCode, event);
+ }
+
+ @Override
+ public boolean onKeyDown(int keyCode, KeyEvent event) {
+ if (keyCode == KeyEvent.KEYCODE_ENTER || keyCode == KeyEvent.KEYCODE_F3
+ || (keyCode == KeyEvent.KEYCODE_G && event.isCtrlPressed())) {
+ mFindToolbar.hideKeyboardAndStartFinding(!event.isShiftPressed());
+ return true;
+ }
+ return super.onKeyDown(keyCode, event);
+ }
+ }
+
+ public FindToolbar(Context context, AttributeSet attrs) {
+ super(context, attrs);
+
+ mTabObserver = new EmptyTabObserver() {
+ @Override
+ public void onPageLoadStarted(Tab tab) {
+ deactivate();
+ }
+
+ @Override
+ public void onContentChanged(Tab tab) {
+ deactivate();
+ }
+
+ @Override
+ public void onClosingStateChanged(Tab tab, boolean closing) {
+ if (closing) deactivate();
+ }
+ };
+
+ mTabModelSelectorObserver = new EmptyTabModelSelectorObserver() {
+ @Override
+ public void onTabModelSelected(TabModel newModel, TabModel oldModel) {
+ deactivate();
+ updateVisualsForTabModel(newModel.isIncognito());
+ }
+ };
+
+ mTabModelObserver = new EmptyTabModelObserver() {
+ @Override
+ public void didSelectTab(Tab tab, TabSelectionType type, int lastId) {
+ deactivate();
+ }
+ };
+ }
+
+ @Override
+ public void onFinishInflate() {
+ setOrientation(HORIZONTAL);
+ setGravity(Gravity.CENTER_VERTICAL);
+
+ mFindQuery = (FindQuery) findViewById(R.id.find_query);
+ mFindQuery.setFindToolbar(this);
+ mFindQuery.setInputType(InputType.TYPE_TEXT_VARIATION_FILTER);
+ mFindQuery.setSelectAllOnFocus(true);
+ mFindQuery.setOnFocusChangeListener(new View.OnFocusChangeListener() {
+ @Override
+ public void onFocusChange(View v, boolean hasFocus) {
+ mAccessibilityDidActivateResult = false;
+ if (!hasFocus) {
+ if (mFindQuery.getText().length() > 0) {
+ mSearchKeyShouldTriggerSearch = true;
+ }
+ UiUtils.hideKeyboard(mFindQuery);
+ }
+ }
+ });
+ mFindQuery.addTextChangedListener(new TextWatcher() {
+ @Override
+ public void onTextChanged(CharSequence s, int start, int before, int count) {
+ mAccessibilityDidActivateResult = false;
+ setPrevNextEnabled(s.length() > 0);
+
+ if (mSettingFindTextProgrammatically) return;
+
+ // If we're called during onRestoreInstanceState() the current
+ // view won't have been set yet. TODO(husky): Find a better fix.
+ assert mCurrentTab != null;
+ assert mCurrentTab.getContentViewCore() != null;
+ if (mCurrentTab.getContentViewCore() == null) return;
+
+ if (s.length() > 0) {
+ // Don't clearResults() as that would cause flicker.
+ // Just wait until onFindResultReceived updates it.
+ mSearchKeyShouldTriggerSearch = false;
+ mFindInPageBridge.startFinding(s.toString(), true, false);
+ } else {
+ clearResults();
+ mFindInPageBridge.stopFinding();
+ }
+
+ if (!mCurrentTab.isIncognito()) {
+ mLastUserSearch = s.toString();
+ }
+ }
+
+ @Override
+ public void beforeTextChanged(CharSequence s,
+ int start, int count, int after) {
+ }
+
+ @Override
+ public void afterTextChanged(Editable s) {
+ }
+ });
+ mFindQuery.setOnEditorActionListener(new TextView.OnEditorActionListener() {
+ @Override
+ public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
+ if (event != null && event.getAction() == KeyEvent.ACTION_UP) return false;
+
+ // Only trigger a new find if the text was set programmatically.
+ // Otherwise just revisit the current active match.
+ if (mSearchKeyShouldTriggerSearch) {
+ mSearchKeyShouldTriggerSearch = false;
+ hideKeyboardAndStartFinding(true);
+ } else {
+ UiUtils.hideKeyboard(mFindQuery);
+ mFindInPageBridge.activateFindInPageResultForAccessibility();
+ mAccessibilityDidActivateResult = true;
+ }
+ return true;
+ }
+ });
+
+ mFindStatus = (TextView) findViewById(R.id.find_status);
+
+ mFindPrevButton = (TintedImageButton) findViewById(R.id.find_prev_button);
+ mFindPrevButton.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ hideKeyboardAndStartFinding(false);
+ }
+ });
+
+ mFindNextButton = (TintedImageButton) findViewById(R.id.find_next_button);
+ mFindNextButton.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ hideKeyboardAndStartFinding(true);
+ }
+ });
+
+ setPrevNextEnabled(false);
+
+ mCloseFindButton = (TintedImageButton) findViewById(R.id.close_find_button);
+ mCloseFindButton.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ deactivate();
+ }
+ });
+ }
+
+ // Overriden by subclasses.
+ protected void findResultSelected(Rect rect) {
+ }
+
+ private void hideKeyboardAndStartFinding(boolean forward) {
+ final String findQuery = mFindQuery.getText().toString();
+ if (findQuery.length() == 0) return;
+
+ UiUtils.hideKeyboard(mFindQuery);
+ mFindInPageBridge.startFinding(findQuery, forward, false);
+ mFindInPageBridge.activateFindInPageResultForAccessibility();
+ mAccessibilityDidActivateResult = true;
+ }
+
+ private boolean mShowKeyboardOnceWindowIsFocused = false;
+
+ @Override
+ public void onWindowFocusChanged(boolean hasFocus) {
+ super.onWindowFocusChanged(hasFocus);
+
+ if (mShowKeyboardOnceWindowIsFocused) {
+ mShowKeyboardOnceWindowIsFocused = false;
+ // See showKeyboard() for explanation.
+ // By this point we've already waited till the window regains focus
+ // from the options menu, but we still need to use postDelayed with
+ // a zero wait time to delay until all the side-effects are complete
+ // (e.g. becoming the target of the Input Method).
+ mHandler.postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ showKeyboard();
+
+ // This is also a great time to set accessibility focus to the query box -
+ // this also fails if we don't wait until the window regains focus.
+ // Sending a HOVER_ENTER event before the ACCESSIBILITY_FOCUSED event
+ // is a widely-used hack to force TalkBack to move accessibility focus
+ // to a view, which is discouraged in general but reasonable in this case.
+ mFindQuery.sendAccessibilityEvent(
+ AccessibilityEventCompat.TYPE_VIEW_HOVER_ENTER);
+ mFindQuery.sendAccessibilityEvent(
+ AccessibilityEventCompat.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
+ }
+ }, 0);
+ }
+ }
+
+ @Override
+ public void onFindMatchRects(FindMatchRectsDetails matchRects) {
+ if (mResultBar == null) return;
+ if (mFindQuery.getText().length() > 0) {
+ mResultBar.setMatchRects(matchRects.version, matchRects.rects, matchRects.activeRect);
+ } else {
+ // Since we don't issue a request for an empty string we never get a 'no rects' response
+ // in that case. This could cause us to display stale state if the user is deleting the
+ // search string. If the response for the last character comes in after we've issued a
+ // clearReslts in TextChangedListener that response will be accepted and we will end up
+ // showing stale results for an empty query.
+ // Sending an empty string message seems a bit wasteful, so instead we simply ignore all
+ // results that come in if the query is empty.
+ mResultBar.clearMatchRects();
+ }
+ }
+
+ @Override
+ public void onFindResult(FindNotificationDetails result) {
+ if (mResultBar != null) mResultBar.mWaitingForActivateAck = false;
+
+ if ((result.activeMatchOrdinal == -1 || result.numberOfMatches == 1)
+ && !result.finalUpdate) {
+ // Wait until activeMatchOrdinal has been determined (is no longer
+ // -1) before showing counts. Additionally, to reduce flicker,
+ // ignore short-lived interim notifications with numberOfMatches set
+ // to 1, which are sent as soon as something has been found (see bug
+ // 894389 and FindBarController::UpdateFindBarForCurrentResult).
+ // Instead wait until the scoping effort starts returning real
+ // match counts (or the search actually finishes with 1 result).
+ // This also protects against receiving bogus rendererSelectionRects
+ // at the start (see below for why we can't filter them out).
+ return;
+ }
+
+ if (result.finalUpdate) {
+ if (result.numberOfMatches > 0) {
+ // TODO(johnme): Don't wait till end of find, stream rects live!
+ mFindInPageBridge.requestFindMatchRects(
+ mResultBar != null ? mResultBar.mRectsVersion : -1);
+ } else {
+ clearResults();
+ }
+
+ findResultSelected(result.rendererSelectionRect);
+ }
+
+ // Even though we wait above until activeMatchOrdinal is no longer -1,
+ // it's possible for it to still be -1 (unknown) in the final find
+ // notification. This happens very rarely, e.g. if the m_activeMatch
+ // found by WebFrameImpl::find has been removed from the DOM by the time
+ // WebFrameImpl::scopeStringMatches tries to find the ordinal of the
+ // active match (while counting the matches), as in b/4147049. In such
+ // cases it looks less broken to show 0 instead of -1 (as desktop does).
+ Context context = getContext();
+ String text = context.getResources().getString(
+ R.string.find_in_page_count,
+ Math.max(result.activeMatchOrdinal, 0),
+ result.numberOfMatches);
+ setStatus(text, result.numberOfMatches == 0);
+
+ // The accessible version will be something like "Result 1 of 9".
+ String accessibleText = getAccessibleStatusText(
+ Math.max(result.activeMatchOrdinal, 0),
+ result.numberOfMatches);
+ mFindStatus.setContentDescription(accessibleText);
+ announceStatusForAccessibility(accessibleText);
+
+ // Vibrate when no results are found, unless you're just deleting chars.
+ if (result.numberOfMatches == 0 && result.finalUpdate
+ && !mFindInPageBridge.getPreviousFindText().startsWith(
+ mFindQuery.getText().toString())) {
+ final boolean hapticFeedbackEnabled = Settings.System.getInt(
+ context.getContentResolver(),
+ Settings.System.HAPTIC_FEEDBACK_ENABLED, 1) == 1;
+ if (hapticFeedbackEnabled) {
+ Vibrator v = (Vibrator) context.getSystemService(
+ Context.VIBRATOR_SERVICE);
+ final long noResultsVibrateDurationMs = 50;
+ v.vibrate(noResultsVibrateDurationMs);
+ }
+ }
+ }
+
+ private String getAccessibleStatusText(int activeMatchOrdinal, int numberOfMatches) {
+ Context context = getContext();
+ return (numberOfMatches > 0)
+ ? context.getResources().getString(
+ R.string.accessible_find_in_page_count,
+ activeMatchOrdinal,
+ numberOfMatches)
+ : context.getResources().getString(R.string.accessible_find_in_page_no_results);
+ }
+
+ private void announceStatusForAccessibility(final String announcementText) {
+ // Don't announce if the user has already activated a result by pressing Enter/Search
+ // or clicking on the Next/Previous buttons.
+ if (mAccessibilityDidActivateResult) return;
+
+ // Delay the announcement briefly, and if any additional announcements come in,
+ // have them preempt the previous queued one. That makes for a better user experience
+ // than speaking instantly as you're typing and constantly interrupting itself.
+
+ if (mAccessibleAnnouncementRunnable != null) {
+ mHandler.removeCallbacks(mAccessibleAnnouncementRunnable);
+ }
+
+ mAccessibleAnnouncementRunnable = new Runnable() {
+ @Override
+ public void run() {
+ mFindQuery.announceForAccessibility(announcementText);
+ }
+ };
+ mHandler.postDelayed(mAccessibleAnnouncementRunnable,
+ ACCESSIBLE_ANNOUNCEMENT_DELAY_MILLIS);
+ }
+
+ /** The find toolbar's container must provide access to its TabModel. */
+ public void setTabModelSelector(TabModelSelector modelSelector) {
+ mTabModelSelector = modelSelector;
+ updateVisualsForTabModel(modelSelector != null && modelSelector.isIncognitoSelected());
+ }
+
+ /**
+ * Handles updating any visual elements of the find toolbar based on changes to the tab model.
+ * @param isIncognito Whether the current tab model is incognito or not.
+ */
+ protected void updateVisualsForTabModel(boolean isIncognito) {
+ }
+
+ /**
+ * Sets a custom ActionMode.Callback instance to the FindQuery. This lets us
+ * get notified when the user tries to do copy, paste, etc. on the FindQuery.
+ * @param callback The ActionMode.Callback instance to be notified when selection ActionMode
+ * is triggered.
+ */
+ public void setActionModeCallbackForTextEdit(ActionMode.Callback callback) {
+ mFindQuery.setCustomSelectionActionModeCallback(callback);
+ }
+
+ /**
+ * Sets the observer to be notified of changes to the find toolbar.
+ */
+ protected void setObserver(FindToolbarObserver observer) {
+ mObserver = observer;
+ }
+
+ /**
+ * Checks to see if a ContentViewCore is available to hook into.
+ */
+ protected boolean isViewAvailable() {
+ Tab currentTab = mTabModelSelector.getCurrentTab();
+ return currentTab != null && currentTab.getContentViewCore() != null;
+ }
+
+ /**
+ * Initializes the find toolbar. Should be called just after the find toolbar is shown.
+ * If the toolbar is already showing, this just focuses the toolbar.
+ */
+ public void activate() {
+ if (!isViewAvailable()) return;
+ if (mActive) {
+ requestQueryFocus();
+ return;
+ }
+
+ mTabModelSelector.addObserver(mTabModelSelectorObserver);
+ for (TabModel model : mTabModelSelector.getModels()) {
+ model.addObserver(mTabModelObserver);
+ }
+ mCurrentTab = mTabModelSelector.getCurrentTab();
+ mCurrentTab.addObserver(mTabObserver);
+ mFindInPageBridge = new FindInPageBridge(mCurrentTab.getWebContents());
+ mCurrentTab.getChromeWebContentsDelegateAndroid().setFindResultListener(this);
+ mCurrentTab.getChromeWebContentsDelegateAndroid().setFindMatchRectsListener(this);
+ initializeFindText();
+ mFindQuery.requestFocus();
+ // The keyboard doesn't show itself automatically.
+ showKeyboard();
+ // Always show the bar to make the FindToolbar more distinct from the Omnibox.
+ setResultsBarVisibility(true);
+ mActive = true;
+ updateVisualsForTabModel(mTabModelSelector.isIncognitoSelected());
+
+ // Let everyone know that we've just updated.
+ if (mObserver != null) mObserver.onFindToolbarShown();
+ }
+
+ /** Call this just before closing the find toolbar. */
+ public void deactivate() {
+ if (!mActive) return;
+
+ if (mObserver != null) mObserver.onFindToolbarHidden();
+
+ setResultsBarVisibility(false);
+
+ mTabModelSelector.removeObserver(mTabModelSelectorObserver);
+ for (TabModel model : mTabModelSelector.getModels()) {
+ model.removeObserver(mTabModelObserver);
+ }
+
+ mCurrentTab.getChromeWebContentsDelegateAndroid().setFindResultListener(null);
+ mCurrentTab.getChromeWebContentsDelegateAndroid().setFindMatchRectsListener(null);
+ mCurrentTab.removeObserver(mTabObserver);
+
+ UiUtils.hideKeyboard(mFindQuery);
+ if (mFindQuery.getText().length() > 0) {
+ clearResults();
+ mFindInPageBridge.stopFinding();
+ }
+
+ mFindInPageBridge.destroy();
+ mActive = false;
+ }
+
+ /**
+ * Requests focus for the query input field and shows the keyboard.
+ */
+ public void requestQueryFocus() {
+ mFindQuery.requestFocus();
+ showKeyboard();
+ }
+
+ /** Called by the tablet-specific implementation when the hide animation is about to begin. */
+ protected void onHideAnimationStart() {
+ // We do this because hiding the bar after the animation ends doesn't look good.
+ setResultsBarVisibility(false);
+ }
+
+ @VisibleForTesting
+ public FindResultBar getFindResultBar() {
+ return mResultBar;
+ }
+
+ /**
+ * Returns whether an animation to show/hide the FindToolbar is currently running.
+ */
+ @VisibleForTesting
+ public boolean isAnimating() {
+ return false;
+ }
+
+ /**
+ * Restores the last text searched in this tab, or the global last search.
+ */
+ private void initializeFindText() {
+ mSettingFindTextProgrammatically = true;
+ String findText = null;
+ if (mSettingFindTextProgrammatically) {
+ findText = mFindInPageBridge.getPreviousFindText();
+ if (findText.isEmpty() && !mCurrentTab.isIncognito()) {
+ findText = mLastUserSearch;
+ }
+ mSearchKeyShouldTriggerSearch = true;
+ } else {
+ mSearchKeyShouldTriggerSearch = false;
+ }
+ mFindQuery.setText(findText);
+ mSettingFindTextProgrammatically = false;
+ }
+
+ /** Clears the result displays (except in-page match highlighting). */
+ protected void clearResults() {
+ setStatus("", false);
+ if (mResultBar != null) {
+ mResultBar.clearMatchRects();
+ }
+ }
+
+ private void setResultsBarVisibility(boolean visibility) {
+ if (visibility && mResultBar == null && mCurrentTab != null
+ && mCurrentTab.getContentViewCore() != null) {
+ mResultBar = new FindResultBar(getContext(), mCurrentTab, mFindInPageBridge);
+ } else if (!visibility) {
+ if (mResultBar != null) {
+ mResultBar.dismiss();
+ mResultBar = null;
+ }
+ }
+ }
+
+ private void setStatus(String text, boolean failed) {
+ mFindStatus.setText(text);
+ mFindStatus.setContentDescription(null);
+ boolean incognito = mTabModelSelector != null && mTabModelSelector.isIncognitoSelected();
+ mFindStatus.setTextColor(getStatusColor(failed, incognito));
+ }
+
+ /**
+ * @param failed Whether or not the find query had any matching results.
+ * @param incognito Whether or not the current tab is incognito.
+ * @return The color of the status text.
+ */
+ protected int getStatusColor(boolean failed, boolean incognito) {
+ int colorResourceId = failed ? R.color.find_in_page_failed_results_status_color
+ : R.color.find_in_page_results_status_color;
+ return getContext().getResources().getColor(colorResourceId);
+ }
+
+ protected void setPrevNextEnabled(boolean enable) {
+ mFindPrevButton.setEnabled(enable);
+ mFindNextButton.setEnabled(enable);
+ }
+
+ private void showKeyboard() {
+ if (!mFindQuery.hasWindowFocus()) {
+ // HACK: showKeyboard() is normally called from activate() which is
+ // triggered by an options menu item. Unfortunately, because the
+ // options menu is still focused at this point, that means our
+ // window doesn't actually have focus when this first gets called,
+ // and hence it isn't the target of the Input Method, and in
+ // practice that means the soft keyboard never shows up (whatever
+ // flags you pass). So as a workaround we postpone asking for the
+ // keyboard to be shown until just after the window gets refocused.
+ // See onWindowFocusChanged(boolean hasFocus).
+ mShowKeyboardOnceWindowIsFocused = true;
+ return;
+ }
+ UiUtils.showKeyboard(mFindQuery);
+ }
+}

Powered by Google App Engine
This is Rietveld 408576698