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

Side by Side 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 unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 package org.chromium.chrome.browser.widget.findinpage;
6
7 import android.annotation.SuppressLint;
8 import android.content.Context;
9 import android.graphics.Rect;
10 import android.os.Handler;
11 import android.os.Vibrator;
12 import android.provider.Settings;
13 import android.support.v4.view.accessibility.AccessibilityEventCompat;
14 import android.text.Editable;
15 import android.text.InputType;
16 import android.text.TextWatcher;
17 import android.util.AttributeSet;
18 import android.view.ActionMode;
19 import android.view.Gravity;
20 import android.view.KeyEvent;
21 import android.view.View;
22 import android.widget.LinearLayout;
23 import android.widget.TextView;
24
25 import com.google.android.apps.chrome.R;
26
27 import org.chromium.base.VisibleForTesting;
28 import org.chromium.chrome.browser.ChromeWebContentsDelegateAndroid;
29 import org.chromium.chrome.browser.EmptyTabObserver;
30 import org.chromium.chrome.browser.FindMatchRectsDetails;
31 import org.chromium.chrome.browser.FindNotificationDetails;
32 import org.chromium.chrome.browser.Tab;
33 import org.chromium.chrome.browser.TabObserver;
34 import org.chromium.chrome.browser.findinpage.FindInPageBridge;
35 import org.chromium.chrome.browser.tabmodel.EmptyTabModelObserver;
36 import org.chromium.chrome.browser.tabmodel.EmptyTabModelSelectorObserver;
37 import org.chromium.chrome.browser.tabmodel.TabModel;
38 import org.chromium.chrome.browser.tabmodel.TabModel.TabSelectionType;
39 import org.chromium.chrome.browser.tabmodel.TabModelObserver;
40 import org.chromium.chrome.browser.tabmodel.TabModelSelector;
41 import org.chromium.chrome.browser.tabmodel.TabModelSelectorObserver;
42 import org.chromium.chrome.browser.widget.TintedImageButton;
43 import org.chromium.chrome.browser.widget.VerticallyFixedEditText;
44 import org.chromium.ui.UiUtils;
45
46 /** A toolbar providing find in page functionality. */
47 public class FindToolbar extends LinearLayout
48 implements ChromeWebContentsDelegateAndroid.FindResultListener,
49 ChromeWebContentsDelegateAndroid.FindMatchRectsListener {
50 private static final long ACCESSIBLE_ANNOUNCEMENT_DELAY_MILLIS = 500;
51
52 // Toolbar UI
53 private TextView mFindStatus;
54 protected FindQuery mFindQuery;
55 protected TintedImageButton mCloseFindButton;
56 protected TintedImageButton mFindPrevButton;
57 protected TintedImageButton mFindNextButton;
58
59 private FindResultBar mResultBar = null;
60
61 protected TabModelSelector mTabModelSelector;
62 private final TabModelSelectorObserver mTabModelSelectorObserver;
63 private final TabModelObserver mTabModelObserver;
64 private Tab mCurrentTab;
65 private final TabObserver mTabObserver;
66 private FindInPageBridge mFindInPageBridge;
67 private FindToolbarObserver mObserver;
68
69 /** Most recently entered search text (globally, in non-incognito tabs). */
70 private String mLastUserSearch = "";
71
72 /** Whether toolbar text is being set automatically (not typed by user). */
73 private boolean mSettingFindTextProgrammatically = false;
74
75 /** Whether the search key should trigger a new search. */
76 private boolean mSearchKeyShouldTriggerSearch = false;
77
78 private boolean mActive = false;
79
80 private Handler mHandler = new Handler();
81 private Runnable mAccessibleAnnouncementRunnable;
82 private boolean mAccessibilityDidActivateResult;
83
84 /** Subclasses EditText in order to intercept BACK key presses. */
85 @SuppressLint("Instantiatable")
86 static class FindQuery extends VerticallyFixedEditText {
87 private FindToolbar mFindToolbar;
88
89 public FindQuery(Context context, AttributeSet attrs) {
90 super(context, attrs);
91 }
92
93 void setFindToolbar(FindToolbar findToolbar) {
94 mFindToolbar = findToolbar;
95 }
96
97 @Override
98 public boolean onKeyPreIme(int keyCode, KeyEvent event) {
99 if (keyCode == KeyEvent.KEYCODE_BACK) {
100 if (event.getAction() == KeyEvent.ACTION_DOWN
101 && event.getRepeatCount() == 0) {
102 // Tell the framework to start tracking this event.
103 getKeyDispatcherState().startTracking(event, this);
104 return true;
105 } else if (event.getAction() == KeyEvent.ACTION_UP) {
106 getKeyDispatcherState().handleUpEvent(event);
107 if (event.isTracking() && !event.isCanceled()) {
108 mFindToolbar.deactivate();
109 return true;
110 }
111 }
112 }
113 return super.onKeyPreIme(keyCode, event);
114 }
115
116 @Override
117 public boolean onKeyDown(int keyCode, KeyEvent event) {
118 if (keyCode == KeyEvent.KEYCODE_ENTER || keyCode == KeyEvent.KEYCODE _F3
119 || (keyCode == KeyEvent.KEYCODE_G && event.isCtrlPressed())) {
120 mFindToolbar.hideKeyboardAndStartFinding(!event.isShiftPressed() );
121 return true;
122 }
123 return super.onKeyDown(keyCode, event);
124 }
125 }
126
127 public FindToolbar(Context context, AttributeSet attrs) {
128 super(context, attrs);
129
130 mTabObserver = new EmptyTabObserver() {
131 @Override
132 public void onPageLoadStarted(Tab tab) {
133 deactivate();
134 }
135
136 @Override
137 public void onContentChanged(Tab tab) {
138 deactivate();
139 }
140
141 @Override
142 public void onClosingStateChanged(Tab tab, boolean closing) {
143 if (closing) deactivate();
144 }
145 };
146
147 mTabModelSelectorObserver = new EmptyTabModelSelectorObserver() {
148 @Override
149 public void onTabModelSelected(TabModel newModel, TabModel oldModel) {
150 deactivate();
151 updateVisualsForTabModel(newModel.isIncognito());
152 }
153 };
154
155 mTabModelObserver = new EmptyTabModelObserver() {
156 @Override
157 public void didSelectTab(Tab tab, TabSelectionType type, int lastId) {
158 deactivate();
159 }
160 };
161 }
162
163 @Override
164 public void onFinishInflate() {
165 setOrientation(HORIZONTAL);
166 setGravity(Gravity.CENTER_VERTICAL);
167
168 mFindQuery = (FindQuery) findViewById(R.id.find_query);
169 mFindQuery.setFindToolbar(this);
170 mFindQuery.setInputType(InputType.TYPE_TEXT_VARIATION_FILTER);
171 mFindQuery.setSelectAllOnFocus(true);
172 mFindQuery.setOnFocusChangeListener(new View.OnFocusChangeListener() {
173 @Override
174 public void onFocusChange(View v, boolean hasFocus) {
175 mAccessibilityDidActivateResult = false;
176 if (!hasFocus) {
177 if (mFindQuery.getText().length() > 0) {
178 mSearchKeyShouldTriggerSearch = true;
179 }
180 UiUtils.hideKeyboard(mFindQuery);
181 }
182 }
183 });
184 mFindQuery.addTextChangedListener(new TextWatcher() {
185 @Override
186 public void onTextChanged(CharSequence s, int start, int before, int count) {
187 mAccessibilityDidActivateResult = false;
188 setPrevNextEnabled(s.length() > 0);
189
190 if (mSettingFindTextProgrammatically) return;
191
192 // If we're called during onRestoreInstanceState() the current
193 // view won't have been set yet. TODO(husky): Find a better fix.
194 assert mCurrentTab != null;
195 assert mCurrentTab.getContentViewCore() != null;
196 if (mCurrentTab.getContentViewCore() == null) return;
197
198 if (s.length() > 0) {
199 // Don't clearResults() as that would cause flicker.
200 // Just wait until onFindResultReceived updates it.
201 mSearchKeyShouldTriggerSearch = false;
202 mFindInPageBridge.startFinding(s.toString(), true, false);
203 } else {
204 clearResults();
205 mFindInPageBridge.stopFinding();
206 }
207
208 if (!mCurrentTab.isIncognito()) {
209 mLastUserSearch = s.toString();
210 }
211 }
212
213 @Override
214 public void beforeTextChanged(CharSequence s,
215 int start, int count, int after) {
216 }
217
218 @Override
219 public void afterTextChanged(Editable s) {
220 }
221 });
222 mFindQuery.setOnEditorActionListener(new TextView.OnEditorActionListener () {
223 @Override
224 public boolean onEditorAction(TextView v, int actionId, KeyEvent eve nt) {
225 if (event != null && event.getAction() == KeyEvent.ACTION_UP) re turn false;
226
227 // Only trigger a new find if the text was set programmatically.
228 // Otherwise just revisit the current active match.
229 if (mSearchKeyShouldTriggerSearch) {
230 mSearchKeyShouldTriggerSearch = false;
231 hideKeyboardAndStartFinding(true);
232 } else {
233 UiUtils.hideKeyboard(mFindQuery);
234 mFindInPageBridge.activateFindInPageResultForAccessibility() ;
235 mAccessibilityDidActivateResult = true;
236 }
237 return true;
238 }
239 });
240
241 mFindStatus = (TextView) findViewById(R.id.find_status);
242
243 mFindPrevButton = (TintedImageButton) findViewById(R.id.find_prev_button );
244 mFindPrevButton.setOnClickListener(new OnClickListener() {
245 @Override
246 public void onClick(View v) {
247 hideKeyboardAndStartFinding(false);
248 }
249 });
250
251 mFindNextButton = (TintedImageButton) findViewById(R.id.find_next_button );
252 mFindNextButton.setOnClickListener(new OnClickListener() {
253 @Override
254 public void onClick(View v) {
255 hideKeyboardAndStartFinding(true);
256 }
257 });
258
259 setPrevNextEnabled(false);
260
261 mCloseFindButton = (TintedImageButton) findViewById(R.id.close_find_butt on);
262 mCloseFindButton.setOnClickListener(new OnClickListener() {
263 @Override
264 public void onClick(View v) {
265 deactivate();
266 }
267 });
268 }
269
270 // Overriden by subclasses.
271 protected void findResultSelected(Rect rect) {
272 }
273
274 private void hideKeyboardAndStartFinding(boolean forward) {
275 final String findQuery = mFindQuery.getText().toString();
276 if (findQuery.length() == 0) return;
277
278 UiUtils.hideKeyboard(mFindQuery);
279 mFindInPageBridge.startFinding(findQuery, forward, false);
280 mFindInPageBridge.activateFindInPageResultForAccessibility();
281 mAccessibilityDidActivateResult = true;
282 }
283
284 private boolean mShowKeyboardOnceWindowIsFocused = false;
285
286 @Override
287 public void onWindowFocusChanged(boolean hasFocus) {
288 super.onWindowFocusChanged(hasFocus);
289
290 if (mShowKeyboardOnceWindowIsFocused) {
291 mShowKeyboardOnceWindowIsFocused = false;
292 // See showKeyboard() for explanation.
293 // By this point we've already waited till the window regains focus
294 // from the options menu, but we still need to use postDelayed with
295 // a zero wait time to delay until all the side-effects are complete
296 // (e.g. becoming the target of the Input Method).
297 mHandler.postDelayed(new Runnable() {
298 @Override
299 public void run() {
300 showKeyboard();
301
302 // This is also a great time to set accessibility focus to t he query box -
303 // this also fails if we don't wait until the window regains focus.
304 // Sending a HOVER_ENTER event before the ACCESSIBILITY_FOCU SED event
305 // is a widely-used hack to force TalkBack to move accessibi lity focus
306 // to a view, which is discouraged in general but reasonable in this case.
307 mFindQuery.sendAccessibilityEvent(
308 AccessibilityEventCompat.TYPE_VIEW_HOVER_ENTER);
309 mFindQuery.sendAccessibilityEvent(
310 AccessibilityEventCompat.TYPE_VIEW_ACCESSIBILITY_FOC USED);
311 }
312 }, 0);
313 }
314 }
315
316 @Override
317 public void onFindMatchRects(FindMatchRectsDetails matchRects) {
318 if (mResultBar == null) return;
319 if (mFindQuery.getText().length() > 0) {
320 mResultBar.setMatchRects(matchRects.version, matchRects.rects, match Rects.activeRect);
321 } else {
322 // Since we don't issue a request for an empty string we never get a 'no rects' response
323 // in that case. This could cause us to display stale state if the u ser is deleting the
324 // search string. If the response for the last character comes in af ter we've issued a
325 // clearReslts in TextChangedListener that response will be accepted and we will end up
326 // showing stale results for an empty query.
327 // Sending an empty string message seems a bit wasteful, so instead we simply ignore all
328 // results that come in if the query is empty.
329 mResultBar.clearMatchRects();
330 }
331 }
332
333 @Override
334 public void onFindResult(FindNotificationDetails result) {
335 if (mResultBar != null) mResultBar.mWaitingForActivateAck = false;
336
337 if ((result.activeMatchOrdinal == -1 || result.numberOfMatches == 1)
338 && !result.finalUpdate) {
339 // Wait until activeMatchOrdinal has been determined (is no longer
340 // -1) before showing counts. Additionally, to reduce flicker,
341 // ignore short-lived interim notifications with numberOfMatches set
342 // to 1, which are sent as soon as something has been found (see bug
343 // 894389 and FindBarController::UpdateFindBarForCurrentResult).
344 // Instead wait until the scoping effort starts returning real
345 // match counts (or the search actually finishes with 1 result).
346 // This also protects against receiving bogus rendererSelectionRects
347 // at the start (see below for why we can't filter them out).
348 return;
349 }
350
351 if (result.finalUpdate) {
352 if (result.numberOfMatches > 0) {
353 // TODO(johnme): Don't wait till end of find, stream rects live!
354 mFindInPageBridge.requestFindMatchRects(
355 mResultBar != null ? mResultBar.mRectsVersion : -1);
356 } else {
357 clearResults();
358 }
359
360 findResultSelected(result.rendererSelectionRect);
361 }
362
363 // Even though we wait above until activeMatchOrdinal is no longer -1,
364 // it's possible for it to still be -1 (unknown) in the final find
365 // notification. This happens very rarely, e.g. if the m_activeMatch
366 // found by WebFrameImpl::find has been removed from the DOM by the time
367 // WebFrameImpl::scopeStringMatches tries to find the ordinal of the
368 // active match (while counting the matches), as in b/4147049. In such
369 // cases it looks less broken to show 0 instead of -1 (as desktop does).
370 Context context = getContext();
371 String text = context.getResources().getString(
372 R.string.find_in_page_count,
373 Math.max(result.activeMatchOrdinal, 0),
374 result.numberOfMatches);
375 setStatus(text, result.numberOfMatches == 0);
376
377 // The accessible version will be something like "Result 1 of 9".
378 String accessibleText = getAccessibleStatusText(
379 Math.max(result.activeMatchOrdinal, 0),
380 result.numberOfMatches);
381 mFindStatus.setContentDescription(accessibleText);
382 announceStatusForAccessibility(accessibleText);
383
384 // Vibrate when no results are found, unless you're just deleting chars.
385 if (result.numberOfMatches == 0 && result.finalUpdate
386 && !mFindInPageBridge.getPreviousFindText().startsWith(
387 mFindQuery.getText().toString())) {
388 final boolean hapticFeedbackEnabled = Settings.System.getInt(
389 context.getContentResolver(),
390 Settings.System.HAPTIC_FEEDBACK_ENABLED, 1) == 1;
391 if (hapticFeedbackEnabled) {
392 Vibrator v = (Vibrator) context.getSystemService(
393 Context.VIBRATOR_SERVICE);
394 final long noResultsVibrateDurationMs = 50;
395 v.vibrate(noResultsVibrateDurationMs);
396 }
397 }
398 }
399
400 private String getAccessibleStatusText(int activeMatchOrdinal, int numberOfM atches) {
401 Context context = getContext();
402 return (numberOfMatches > 0)
403 ? context.getResources().getString(
404 R.string.accessible_find_in_page_count,
405 activeMatchOrdinal,
406 numberOfMatches)
407 : context.getResources().getString(R.string.accessible_find_in_p age_no_results);
408 }
409
410 private void announceStatusForAccessibility(final String announcementText) {
411 // Don't announce if the user has already activated a result by pressing Enter/Search
412 // or clicking on the Next/Previous buttons.
413 if (mAccessibilityDidActivateResult) return;
414
415 // Delay the announcement briefly, and if any additional announcements c ome in,
416 // have them preempt the previous queued one. That makes for a better us er experience
417 // than speaking instantly as you're typing and constantly interrupting itself.
418
419 if (mAccessibleAnnouncementRunnable != null) {
420 mHandler.removeCallbacks(mAccessibleAnnouncementRunnable);
421 }
422
423 mAccessibleAnnouncementRunnable = new Runnable() {
424 @Override
425 public void run() {
426 mFindQuery.announceForAccessibility(announcementText);
427 }
428 };
429 mHandler.postDelayed(mAccessibleAnnouncementRunnable,
430 ACCESSIBLE_ANNOUNCEMENT_DELAY_MILLIS);
431 }
432
433 /** The find toolbar's container must provide access to its TabModel. */
434 public void setTabModelSelector(TabModelSelector modelSelector) {
435 mTabModelSelector = modelSelector;
436 updateVisualsForTabModel(modelSelector != null && modelSelector.isIncogn itoSelected());
437 }
438
439 /**
440 * Handles updating any visual elements of the find toolbar based on changes to the tab model.
441 * @param isIncognito Whether the current tab model is incognito or not.
442 */
443 protected void updateVisualsForTabModel(boolean isIncognito) {
444 }
445
446 /**
447 * Sets a custom ActionMode.Callback instance to the FindQuery. This lets u s
448 * get notified when the user tries to do copy, paste, etc. on the FindQuery .
449 * @param callback The ActionMode.Callback instance to be notified when sele ction ActionMode
450 * is triggered.
451 */
452 public void setActionModeCallbackForTextEdit(ActionMode.Callback callback) {
453 mFindQuery.setCustomSelectionActionModeCallback(callback);
454 }
455
456 /**
457 * Sets the observer to be notified of changes to the find toolbar.
458 */
459 protected void setObserver(FindToolbarObserver observer) {
460 mObserver = observer;
461 }
462
463 /**
464 * Checks to see if a ContentViewCore is available to hook into.
465 */
466 protected boolean isViewAvailable() {
467 Tab currentTab = mTabModelSelector.getCurrentTab();
468 return currentTab != null && currentTab.getContentViewCore() != null;
469 }
470
471 /**
472 * Initializes the find toolbar. Should be called just after the find toolba r is shown.
473 * If the toolbar is already showing, this just focuses the toolbar.
474 */
475 public void activate() {
476 if (!isViewAvailable()) return;
477 if (mActive) {
478 requestQueryFocus();
479 return;
480 }
481
482 mTabModelSelector.addObserver(mTabModelSelectorObserver);
483 for (TabModel model : mTabModelSelector.getModels()) {
484 model.addObserver(mTabModelObserver);
485 }
486 mCurrentTab = mTabModelSelector.getCurrentTab();
487 mCurrentTab.addObserver(mTabObserver);
488 mFindInPageBridge = new FindInPageBridge(mCurrentTab.getWebContents());
489 mCurrentTab.getChromeWebContentsDelegateAndroid().setFindResultListener( this);
490 mCurrentTab.getChromeWebContentsDelegateAndroid().setFindMatchRectsListe ner(this);
491 initializeFindText();
492 mFindQuery.requestFocus();
493 // The keyboard doesn't show itself automatically.
494 showKeyboard();
495 // Always show the bar to make the FindToolbar more distinct from the Om nibox.
496 setResultsBarVisibility(true);
497 mActive = true;
498 updateVisualsForTabModel(mTabModelSelector.isIncognitoSelected());
499
500 // Let everyone know that we've just updated.
501 if (mObserver != null) mObserver.onFindToolbarShown();
502 }
503
504 /** Call this just before closing the find toolbar. */
505 public void deactivate() {
506 if (!mActive) return;
507
508 if (mObserver != null) mObserver.onFindToolbarHidden();
509
510 setResultsBarVisibility(false);
511
512 mTabModelSelector.removeObserver(mTabModelSelectorObserver);
513 for (TabModel model : mTabModelSelector.getModels()) {
514 model.removeObserver(mTabModelObserver);
515 }
516
517 mCurrentTab.getChromeWebContentsDelegateAndroid().setFindResultListener( null);
518 mCurrentTab.getChromeWebContentsDelegateAndroid().setFindMatchRectsListe ner(null);
519 mCurrentTab.removeObserver(mTabObserver);
520
521 UiUtils.hideKeyboard(mFindQuery);
522 if (mFindQuery.getText().length() > 0) {
523 clearResults();
524 mFindInPageBridge.stopFinding();
525 }
526
527 mFindInPageBridge.destroy();
528 mActive = false;
529 }
530
531 /**
532 * Requests focus for the query input field and shows the keyboard.
533 */
534 public void requestQueryFocus() {
535 mFindQuery.requestFocus();
536 showKeyboard();
537 }
538
539 /** Called by the tablet-specific implementation when the hide animation is about to begin. */
540 protected void onHideAnimationStart() {
541 // We do this because hiding the bar after the animation ends doesn't lo ok good.
542 setResultsBarVisibility(false);
543 }
544
545 @VisibleForTesting
546 public FindResultBar getFindResultBar() {
547 return mResultBar;
548 }
549
550 /**
551 * Returns whether an animation to show/hide the FindToolbar is currently ru nning.
552 */
553 @VisibleForTesting
554 public boolean isAnimating() {
555 return false;
556 }
557
558 /**
559 * Restores the last text searched in this tab, or the global last search.
560 */
561 private void initializeFindText() {
562 mSettingFindTextProgrammatically = true;
563 String findText = null;
564 if (mSettingFindTextProgrammatically) {
565 findText = mFindInPageBridge.getPreviousFindText();
566 if (findText.isEmpty() && !mCurrentTab.isIncognito()) {
567 findText = mLastUserSearch;
568 }
569 mSearchKeyShouldTriggerSearch = true;
570 } else {
571 mSearchKeyShouldTriggerSearch = false;
572 }
573 mFindQuery.setText(findText);
574 mSettingFindTextProgrammatically = false;
575 }
576
577 /** Clears the result displays (except in-page match highlighting). */
578 protected void clearResults() {
579 setStatus("", false);
580 if (mResultBar != null) {
581 mResultBar.clearMatchRects();
582 }
583 }
584
585 private void setResultsBarVisibility(boolean visibility) {
586 if (visibility && mResultBar == null && mCurrentTab != null
587 && mCurrentTab.getContentViewCore() != null) {
588 mResultBar = new FindResultBar(getContext(), mCurrentTab, mFindInPag eBridge);
589 } else if (!visibility) {
590 if (mResultBar != null) {
591 mResultBar.dismiss();
592 mResultBar = null;
593 }
594 }
595 }
596
597 private void setStatus(String text, boolean failed) {
598 mFindStatus.setText(text);
599 mFindStatus.setContentDescription(null);
600 boolean incognito = mTabModelSelector != null && mTabModelSelector.isInc ognitoSelected();
601 mFindStatus.setTextColor(getStatusColor(failed, incognito));
602 }
603
604 /**
605 * @param failed Whether or not the find query had any matching results.
606 * @param incognito Whether or not the current tab is incognito.
607 * @return The color of the status text.
608 */
609 protected int getStatusColor(boolean failed, boolean incognito) {
610 int colorResourceId = failed ? R.color.find_in_page_failed_results_statu s_color
611 : R.color.find_in_page_results_status_color;
612 return getContext().getResources().getColor(colorResourceId);
613 }
614
615 protected void setPrevNextEnabled(boolean enable) {
616 mFindPrevButton.setEnabled(enable);
617 mFindNextButton.setEnabled(enable);
618 }
619
620 private void showKeyboard() {
621 if (!mFindQuery.hasWindowFocus()) {
622 // HACK: showKeyboard() is normally called from activate() which is
623 // triggered by an options menu item. Unfortunately, because the
624 // options menu is still focused at this point, that means our
625 // window doesn't actually have focus when this first gets called,
626 // and hence it isn't the target of the Input Method, and in
627 // practice that means the soft keyboard never shows up (whatever
628 // flags you pass). So as a workaround we postpone asking for the
629 // keyboard to be shown until just after the window gets refocused.
630 // See onWindowFocusChanged(boolean hasFocus).
631 mShowKeyboardOnceWindowIsFocused = true;
632 return;
633 }
634 UiUtils.showKeyboard(mFindQuery);
635 }
636 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698