/** Clears the selection. */ void clearSelection() { ContentViewCore baseContentView = getBaseContentView(); if (baseContentView != null) { baseContentView.clearSelection(); } resetAllStates(); }
/** * Injects a <script> tag into the current web site that pulls in the ChromeVox script for * accessibility support. Only injects if accessibility is turned on by {@link * AccessibilityManager#isEnabled()}, accessibility script injection is turned on, and javascript * is enabled on this page. * * @see AccessibilityManager#isEnabled() */ public void injectAccessibilityScriptIntoPage() { if (!accessibilityIsAvailable()) return; int axsParameterValue = getAxsUrlParameterValue(); if (axsParameterValue == ACCESSIBILITY_SCRIPT_INJECTION_UNDEFINED) { try { Field field = Settings.Secure.class.getField("ACCESSIBILITY_SCRIPT_INJECTION"); field.setAccessible(true); String ACCESSIBILITY_SCRIPT_INJECTION = (String) field.get(null); boolean onDeviceScriptInjectionEnabled = (Settings.Secure.getInt( mContentViewCore.getContext().getContentResolver(), ACCESSIBILITY_SCRIPT_INJECTION, 0) == 1); String js = getScreenReaderInjectingJs(); if (onDeviceScriptInjectionEnabled && js != null && mContentViewCore.isAlive()) { addOrRemoveAccessibilityApisIfNecessary(); mContentViewCore.evaluateJavaScript(js, null); mInjectedScriptEnabled = true; mScriptInjected = true; } } catch (NoSuchFieldException ex) { } catch (IllegalArgumentException ex) { } catch (IllegalAccessException ex) { } } }
@CalledByNative private void showAutofillPopup( float x, float y, float width, float height, boolean isRtl, AutofillSuggestion[] suggestions) { if (mContentViewCore == null) return; if (mAutofillPopup == null) { mAutofillPopup = new AutofillPopup( mContentViewCore.getContext(), mContentViewCore.getViewAndroidDelegate(), new AutofillPopup.AutofillPopupDelegate() { @Override public void dismissed() {} @Override public void suggestionSelected(int listIndex) { nativeSuggestionSelected(mNativeXWalkAutofillClient, listIndex); } }); } mAutofillPopup.setAnchorRect(x, y, width, height); mAutofillPopup.filterAndShow(suggestions, isRtl); }
/** * Initializes the rendering surface parameters of {@code contentViewCore}. Note that this does * not size the actual {@link ContentViewCore}. * * @param contentViewCore The {@link ContentViewCore} to initialize. */ private void initializeContentViewCore(ContentViewCore contentViewCore) { contentViewCore.setCurrentMotionEventOffsets(0.f, 0.f); contentViewCore.setTopControlsHeight( getTopControlsHeightPixels(), contentViewCore.doTopControlsShrinkBlinkSize()); contentViewCore.onPhysicalBackingSizeChanged( mCompositorView.getWidth(), mCompositorView.getHeight()); contentViewCore.onOverdrawBottomHeightChanged(mCompositorView.getOverdrawBottomHeight()); }
/** * Expands the current selection by the specified amounts. * * @param selectionStartAdjust The start offset adjustment of the selection to use to highlight * the search term. * @param selectionEndAdjust The end offset adjustment of the selection to use to highlight the * search term. */ void adjustSelection(int selectionStartAdjust, int selectionEndAdjust) { // TODO(donnd): add code to verify that the selection is still valid before changing it. // crbug.com/508354 if (selectionStartAdjust == 0 && selectionEndAdjust == 0) return; ContentViewCore basePageContentView = getBaseContentView(); if (basePageContentView != null && basePageContentView.getWebContents() != null) { mDidExpandSelection = true; basePageContentView .getWebContents() .adjustSelectionByCharacterOffset(selectionStartAdjust, selectionEndAdjust); } }
protected void removeAccessibilityApis() { if (mTextToSpeech != null) { mContentViewCore.removeJavascriptInterface(ALIAS_ACCESSIBILITY_JS_INTERFACE); mTextToSpeech.stop(); mTextToSpeech.shutdownInternal(); mTextToSpeech = null; } if (mVibrator != null) { mContentViewCore.removeJavascriptInterface(ALIAS_ACCESSIBILITY_JS_INTERFACE_2); mVibrator.cancel(); mVibrator = null; } }
protected void addAccessibilityApis() { Context context = mContentViewCore.getContext(); if (context != null) { // Enabled, we should try to add if we have to. if (mTextToSpeech == null) { mTextToSpeech = new TextToSpeechWrapper(mContentViewCore.getContainerView(), context); mContentViewCore.addJavascriptInterface(mTextToSpeech, ALIAS_ACCESSIBILITY_JS_INTERFACE); } if (mVibrator == null) { mVibrator = new VibratorWrapper(context); mContentViewCore.addJavascriptInterface(mVibrator, ALIAS_ACCESSIBILITY_JS_INTERFACE_2); } } }
/** * Sets whether or not the script is enabled. If the script is disabled, we also stop any we * output that is occurring. * * @param enabled Whether or not to enable the script. */ public void setScriptEnabled(boolean enabled) { if (!accessibilityIsAvailable() || mInjectedScriptEnabled == enabled) return; mInjectedScriptEnabled = enabled; if (mContentViewCore.isAlive()) { String js = String.format(TOGGLE_CHROME_VOX_JAVASCRIPT, Boolean.toString(mInjectedScriptEnabled)); mContentViewCore.evaluateJavaScript(js, null); if (!mInjectedScriptEnabled) { // Stop any TTS/Vibration right now. onPageLostFocus(); } } }
@Override public void setUp() throws Exception { super.setUp(); launchContentShellWithUrl(DATA_URL); assertTrue("Page failed to load", waitForActiveShellToBeDoneLoading()); mContentViewCore = getContentViewCore(); mWebContents = getWebContents(); mInputMethodManagerWrapper = new TestInputMethodManagerWrapper(mContentViewCore); getImeAdapter().setInputMethodManagerWrapper(mInputMethodManagerWrapper); assertEquals(0, mInputMethodManagerWrapper.getShowSoftInputCounter()); mContentViewCore.setAdapterInputConnectionFactory(new TestAdapterInputConnectionFactory()); mCallbackContainer = new TestCallbackHelperContainer(mContentViewCore); // TODO(aurimas) remove this wait once crbug.com/179511 is fixed. assertWaitForPageScaleFactorMatch(2); assertTrue(DOMUtils.waitForNonZeroNodeBounds(mWebContents, "input_text")); DOMUtils.clickNode(this, mContentViewCore, "input_text"); assertWaitForKeyboardStatus(true); mConnection = (TestAdapterInputConnection) getAdapterInputConnection(); mImeAdapter = getImeAdapter(); waitAndVerifyEditableCallback(mConnection.mImeUpdateQueue, 0, "", 0, 0, -1, -1); assertEquals(1, mInputMethodManagerWrapper.getShowSoftInputCounter()); assertEquals(0, mInputMethodManagerWrapper.getEditorInfo().initialSelStart); assertEquals(0, mInputMethodManagerWrapper.getEditorInfo().initialSelEnd); }
@VisibleForTesting boolean isValidSelection(String selection, ContentViewCore baseContentView) { if (selection.length() > MAX_SELECTION_LENGTH || !doesContainAWord(selection)) { return false; } return baseContentView != null && !baseContentView.isFocusedNodeEditable(); }
private AccessibilityManager getAccessibilityManager() { if (mAccessibilityManager == null) { mAccessibilityManager = (AccessibilityManager) mContentViewCore.getContext().getSystemService(Context.ACCESSIBILITY_SERVICE); } return mAccessibilityManager; }
private int getAxsUrlParameterValue() { if (mContentViewCore.getUrl() == null) return ACCESSIBILITY_SCRIPT_INJECTION_UNDEFINED; try { List<NameValuePair> params = URLEncodedUtils.parse(new URI(mContentViewCore.getUrl()), null); for (NameValuePair param : params) { if ("axs".equals(param.getName())) { return Integer.parseInt(param.getValue()); } } } catch (URISyntaxException ex) { } catch (NumberFormatException ex) { } catch (IllegalArgumentException ex) { } return ACCESSIBILITY_SCRIPT_INJECTION_UNDEFINED; }
/** Checks whether or not touch to explore is enabled on the system. */ public boolean accessibilityIsAvailable() { if (!getAccessibilityManager().isEnabled() || mContentViewCore.getContentSettings() == null || !mContentViewCore.getContentSettings().getJavaScriptEnabled()) { return false; } try { // Check that there is actually a service running that requires injecting this script. List<AccessibilityServiceInfo> services = getAccessibilityManager() .getEnabledAccessibilityServiceList( FEEDBACK_BRAILLE | AccessibilityServiceInfo.FEEDBACK_SPOKEN); return services.size() > 0; } catch (NullPointerException e) { // getEnabledAccessibilityServiceList() can throw an NPE due to a bad // AccessibilityService. return false; } }
@SmallTest @Feature({"TextInput"}) public void testTextHandlesPreservedWithDpadNavigation() throws Throwable { DOMUtils.longPressNode(this, mContentViewCore, "plain_text"); assertWaitForSelectActionBarStatus(true); assertTrue(mContentViewCore.hasSelection()); ThreadUtils.runOnUiThreadBlocking( new Runnable() { @Override public void run() { final KeyEvent downKeyEvent = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_DOWN); mImeAdapter.dispatchKeyEvent(downKeyEvent); } }); assertWaitForSelectActionBarStatus(true); assertTrue(mContentViewCore.hasSelection()); }
/** * Starts evaluation of a given JavaScript code on a given contentViewCore. * * @param contentViewCore A ContentViewCore instance to be used. * @param code A JavaScript code to be evaluated. */ public void evaluateJavaScript(ContentViewCore contentViewCore, String code) { JavaScriptCallback callback = new JavaScriptCallback() { @Override public void handleJavaScriptResult(String jsonResult) { notifyCalled(jsonResult); } }; contentViewCore.evaluateJavaScript(code, callback); mJsonResult = null; }
@SmallTest @Feature({"TextInput"}) public void testKeyboardNotDismissedAfterCopySelection() throws Exception { commitText(mConnection, "Sample Text", 1); waitAndVerifyEditableCallback(mConnection.mImeUpdateQueue, 1, "Sample Text", 11, 11, -1, -1); DOMUtils.clickNode(this, mContentViewCore, "input_text"); assertWaitForKeyboardStatus(true); DOMUtils.longPressNode(this, mContentViewCore, "input_text"); selectAll(mImeAdapter); copy(mImeAdapter); assertWaitForKeyboardStatus(true); assertEquals(11, Selection.getSelectionEnd(mContentViewCore.getEditableForTest())); }
/** * Handles a notification that a selection event took place. * * @param eventType The type of event that took place. * @param posXPix The x coordinate of the selection start handle. * @param posYPix The y coordinate of the selection start handle. */ void handleSelectionEvent(int eventType, float posXPix, float posYPix) { boolean shouldHandleSelection = false; switch (eventType) { case SelectionEventType.SELECTION_HANDLES_SHOWN: mWasTapGestureDetected = false; mSelectionType = SelectionType.LONG_PRESS; shouldHandleSelection = true; // Since we're showing pins, we don't care if the previous tap was invalid anymore. unscheduleInvalidTapNotification(); break; case SelectionEventType.SELECTION_HANDLES_CLEARED: mHandler.handleSelectionDismissal(); resetAllStates(); break; case SelectionEventType.SELECTION_HANDLE_DRAG_STOPPED: shouldHandleSelection = mShouldHandleSelectionModification; break; case SelectionEventType.SELECTION_ESTABLISHED: mIsSelectionEstablished = true; break; case SelectionEventType.SELECTION_DISSOLVED: mIsSelectionEstablished = false; break; default: } if (shouldHandleSelection) { ContentViewCore baseContentView = getBaseContentView(); if (baseContentView != null) { String selection = baseContentView.getSelectedText(); if (selection != null) { mX = posXPix; mY = posYPix; mSelectedText = selection; handleSelection(selection, SelectionType.LONG_PRESS); } } } }
/** * Tests that the showing select popup does not get closed because an unrelated ContentView gets * destroyed. @LargeTest @Feature({"Browser"}) BUG 172967 */ @DisabledTest public void testPopupNotClosedByOtherContentView() throws InterruptedException, Exception, Throwable { // Load the test page. launchChromeShellWithUrl(SELECT_URL); assertTrue("Page failed to load", waitForActiveShellToBeDoneLoading()); final ContentViewCore viewCore = getActivity().getActiveContentViewCore(); // Once clicked, the popup should show up. DOMUtils.clickNode(this, viewCore, "select"); assertTrue( "The select popup did not show up on click.", CriteriaHelper.pollForCriteria(new PopupShowingCriteria())); // Now create and destroy a different ContentView. ThreadUtils.runOnUiThreadBlocking( new Runnable() { @Override public void run() { long nativeWebContents = ContentViewUtil.createNativeWebContents(false); WindowAndroid windowAndroid = new ActivityWindowAndroid(getActivity()); ContentViewCore contentViewCore = new ContentViewCore(getActivity()); ContentView cv = ContentView.newInstance(getActivity(), contentViewCore); contentViewCore.initialize(cv, cv, nativeWebContents, windowAndroid); contentViewCore.destroy(); } }); // Process some more events to give a chance to the dialog to hide if it were to. getInstrumentation().waitForIdleSync(); // The popup should still be shown. assertNotNull( "The select popup got hidden by destroying of unrelated ContentViewCore.", viewCore.getSelectPopupForTest()); }
public TestCallbackHelperContainer(final ContentViewCore contentViewCore) { mTestContentViewClient = new TestContentViewClient(); contentViewCore.setContentViewClient(mTestContentViewClient); // TODO(yfriedman): Change callers to be executed on the UI thread. Unfortunately this is // super convenient as the caller is nearly always on the test thread which is fine to block // and it's cumbersome to keep bouncing to the UI thread. ThreadUtils.runOnUiThreadBlocking( new Runnable() { @Override public void run() { mTestWebContentsObserver = new TestWebContentsObserver(contentViewCore); } }); }
private void setContentViewMotionEventOffsets(MotionEvent e, boolean canClear) { // TODO(dtrainor): Factor this out to LayoutDriver. if (e == null || mTabVisible == null) return; ContentViewCore contentViewCore = mTabVisible.getContentViewCore(); if (contentViewCore == null) return; int actionMasked = e.getActionMasked(); if (SPenSupport.isSPenSupported(getContext())) { actionMasked = SPenSupport.convertSPenEventAction(actionMasked); } if (actionMasked == MotionEvent.ACTION_DOWN || actionMasked == MotionEvent.ACTION_HOVER_ENTER) { if (mLayoutManager != null) mLayoutManager.getViewportPixel(mCacheViewport); contentViewCore.setCurrentMotionEventOffsets(-mCacheViewport.left, -mCacheViewport.top); } else if (canClear && (actionMasked == MotionEvent.ACTION_UP || actionMasked == MotionEvent.ACTION_CANCEL || actionMasked == MotionEvent.ACTION_HOVER_EXIT)) { contentViewCore.setCurrentMotionEventOffsets(0.f, 0.f); } }
@SmallTest @Feature({"TextInput", "Main"}) public void testDpadKeyCodesWhileSwipingText() throws Throwable { DOMUtils.focusNode(mWebContents, "textarea"); assertWaitForKeyboardStatus(true); mConnection = (TestAdapterInputConnection) getAdapterInputConnection(); waitAndVerifyEditableCallback(mConnection.mImeUpdateQueue, 0, "", 0, 0, -1, -1); // DPAD_CENTER should cause keyboard to appear expectUpdateStateCall(mConnection); KeyEvent event = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_CENTER); mContentViewCore.dispatchKeyEvent(event); assertUpdateStateCall(mConnection, 1000); }
/** * Starts showing a context menu for {@code view} based on {@code params}. * * @param contentViewCore The {@link ContentViewCore} to show the menu to. * @param params The {@link ContextMenuParams} that indicate what menu items to show. */ @CalledByNative private void showContextMenu(ContentViewCore contentViewCore, ContextMenuParams params) { final View view = contentViewCore.getContainerView(); if (!shouldShowMenu(params) || view == null || view.getVisibility() != View.VISIBLE || view.getParent() == null) { return; } mCurrentContextMenuParams = params; view.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS); view.setOnCreateContextMenuListener(this); view.showContextMenu(); }
@SmallTest @Feature({"TextInput"}) public void testPastePopupShowOnLongPress() throws Throwable { commitText(mConnection, "hello", 1); waitAndVerifyEditableCallback(mConnection.mImeUpdateQueue, 1, "hello", 5, 5, -1, -1); selectAll(mImeAdapter); waitAndVerifyEditableCallback(mConnection.mImeUpdateQueue, 2, "hello", 0, 5, -1, -1); cut(mImeAdapter); waitAndVerifyEditableCallback(mConnection.mImeUpdateQueue, 0, "", 0, 0, -1, -1); DOMUtils.longPressNode(this, mContentViewCore, "input_text"); final PastePopupMenu pastePopup = mContentViewCore.getPastePopupForTest(); assertTrue( CriteriaHelper.pollForCriteria( new Criteria() { @Override public boolean isSatisfied() { return pastePopup.isShowing(); } })); }
private static boolean isGamepadAPIActive(ChromeActivity activity) { ContentViewCore cvc = activity.getCurrentContentViewCore(); return (cvc != null) ? cvc.isGamepadAPIActive() : false; }
@Override public boolean isSatisfied() { ContentViewCore contentViewCore = getActivity().getActiveContentViewCore(); return contentViewCore.getSelectPopupForTest() != null; }
private AdapterInputConnection getAdapterInputConnection() { return mContentViewCore.getInputConnectionForTest(); }
private ImeAdapter getImeAdapter() { return mContentViewCore.getImeAdapterForTest(); }
/** * This should be called from the Activity's onKeyDown() to handle keyboard shortcuts. * * <p>Note: onKeyDown() is called after the active view or web page has had a chance to handle the * key event. So the keys handled here *can* be overridden by any view or web page. * * @param event The KeyEvent to handle. * @param activity The ChromeActivity in which the key was pressed. * @param isCurrentTabVisible Whether page-related actions are valid, e.g. reload, zoom in. This * should be false when in the tab switcher. * @param tabSwitchingEnabled Whether shortcuts that switch between tabs are enabled (e.g. * Ctrl+Tab, Ctrl+3). * @return Whether the key event was handled. */ public static boolean onKeyDown( KeyEvent event, ChromeActivity activity, boolean isCurrentTabVisible, boolean tabSwitchingEnabled) { int keyCode = event.getKeyCode(); if (event.getRepeatCount() != 0 || KeyEvent.isModifierKey(keyCode)) return false; if (KeyEvent.isGamepadButton(keyCode)) { if (isGamepadAPIActive(activity)) return false; } else if (!event.isCtrlPressed() && !event.isAltPressed() && keyCode != KeyEvent.KEYCODE_F3 && keyCode != KeyEvent.KEYCODE_F5 && keyCode != KeyEvent.KEYCODE_F10 && keyCode != KeyEvent.KEYCODE_FORWARD) { return false; } TabModel curModel = activity.getCurrentTabModel(); int count = curModel.getCount(); int metaState = getMetaState(event); int keyCodeAndMeta = keyCode | metaState; switch (keyCodeAndMeta) { case CTRL | SHIFT | KeyEvent.KEYCODE_T: activity.onMenuOrKeyboardAction(R.id.open_recently_closed_tab, false); return true; case CTRL | KeyEvent.KEYCODE_T: activity.onMenuOrKeyboardAction( curModel.isIncognito() ? R.id.new_incognito_tab_menu_id : R.id.new_tab_menu_id, false); return true; case CTRL | KeyEvent.KEYCODE_N: activity.onMenuOrKeyboardAction(R.id.new_tab_menu_id, false); return true; case CTRL | SHIFT | KeyEvent.KEYCODE_N: activity.onMenuOrKeyboardAction(R.id.new_incognito_tab_menu_id, false); return true; // Alt+E represents a special character ´ (latin code: ´) in Android. // If an EditText or ContentView has focus, Alt+E will be swallowed by // the default dispatchKeyEvent and cannot open the menu. case ALT | KeyEvent.KEYCODE_E: case ALT | KeyEvent.KEYCODE_F: case KeyEvent.KEYCODE_F10: case KeyEvent.KEYCODE_BUTTON_Y: activity.onMenuOrKeyboardAction(R.id.show_menu, false); return true; } if (isCurrentTabVisible) { if (tabSwitchingEnabled && (metaState == CTRL || metaState == ALT)) { int numCode = keyCode - KeyEvent.KEYCODE_0; if (numCode > 0 && numCode <= Math.min(count, 8)) { // Ctrl+1 to Ctrl+8: select tab by index TabModelUtils.setIndex(curModel, numCode - 1); return true; } else if (numCode == 9 && count != 0) { // Ctrl+9: select last tab TabModelUtils.setIndex(curModel, count - 1); return true; } } switch (keyCodeAndMeta) { case CTRL | KeyEvent.KEYCODE_TAB: case CTRL | KeyEvent.KEYCODE_PAGE_DOWN: case KeyEvent.KEYCODE_BUTTON_R1: if (tabSwitchingEnabled && count > 1) { TabModelUtils.setIndex(curModel, (curModel.index() + 1) % count); } return true; case CTRL | SHIFT | KeyEvent.KEYCODE_TAB: case CTRL | KeyEvent.KEYCODE_PAGE_UP: case KeyEvent.KEYCODE_BUTTON_L1: if (tabSwitchingEnabled && count > 1) { TabModelUtils.setIndex(curModel, (curModel.index() + count - 1) % count); } return true; case CTRL | KeyEvent.KEYCODE_W: case CTRL | KeyEvent.KEYCODE_F4: case KeyEvent.KEYCODE_BUTTON_B: TabModelUtils.closeCurrentTab(curModel); return true; case CTRL | KeyEvent.KEYCODE_F: case CTRL | KeyEvent.KEYCODE_G: case CTRL | SHIFT | KeyEvent.KEYCODE_G: case KeyEvent.KEYCODE_F3: case SHIFT | KeyEvent.KEYCODE_F3: activity.onMenuOrKeyboardAction(R.id.find_in_page_id, false); return true; case CTRL | KeyEvent.KEYCODE_L: case ALT | KeyEvent.KEYCODE_D: case KeyEvent.KEYCODE_BUTTON_X: activity.onMenuOrKeyboardAction(R.id.focus_url_bar, false); return true; case CTRL | SHIFT | KeyEvent.KEYCODE_B: activity.onMenuOrKeyboardAction(R.id.all_bookmarks_menu_id, false); return true; case KeyEvent.KEYCODE_BOOKMARK: case CTRL | KeyEvent.KEYCODE_D: activity.onMenuOrKeyboardAction(R.id.bookmark_this_page_id, false); return true; case CTRL | KeyEvent.KEYCODE_H: activity.onMenuOrKeyboardAction(R.id.open_history_menu_id, false); return true; case CTRL | KeyEvent.KEYCODE_P: activity.onMenuOrKeyboardAction(R.id.print_id, false); return true; case CTRL | KeyEvent.KEYCODE_PLUS: case CTRL | KeyEvent.KEYCODE_EQUALS: case CTRL | SHIFT | KeyEvent.KEYCODE_PLUS: case CTRL | SHIFT | KeyEvent.KEYCODE_EQUALS: case KeyEvent.KEYCODE_ZOOM_IN: ContentViewCore cvc = activity.getCurrentContentViewCore(); if (cvc != null) cvc.zoomIn(); return true; case CTRL | KeyEvent.KEYCODE_MINUS: case KeyEvent.KEYCODE_ZOOM_OUT: cvc = activity.getCurrentContentViewCore(); if (cvc != null) cvc.zoomOut(); return true; case CTRL | KeyEvent.KEYCODE_0: cvc = activity.getCurrentContentViewCore(); if (cvc != null) cvc.zoomReset(); return true; case SHIFT | CTRL | KeyEvent.KEYCODE_R: case CTRL | KeyEvent.KEYCODE_R: case SHIFT | KeyEvent.KEYCODE_F5: case KeyEvent.KEYCODE_F5: Tab tab = activity.getActivityTab(); if (tab != null) { if ((keyCodeAndMeta & SHIFT) == SHIFT) { tab.reloadIgnoringCache(); } else { tab.reload(); } if (activity.getToolbarManager() != null && tab.getWebContents() != null && tab.getWebContents().focusLocationBarByDefault()) { activity.getToolbarManager().revertLocationBarChanges(); } else { tab.requestFocus(); } } return true; case ALT | KeyEvent.KEYCODE_DPAD_LEFT: tab = activity.getActivityTab(); if (tab != null && tab.canGoBack()) tab.goBack(); return true; case ALT | KeyEvent.KEYCODE_DPAD_RIGHT: case KeyEvent.KEYCODE_FORWARD: case KeyEvent.KEYCODE_BUTTON_START: tab = activity.getActivityTab(); if (tab != null && tab.canGoForward()) tab.goForward(); return true; case CTRL | SHIFT | KeyEvent.KEYCODE_SLASH: // i.e. Ctrl+? activity.onMenuOrKeyboardAction(R.id.help_id, false); return true; } } return false; }
@Override public void onContentViewCoreAdded(ContentViewCore content) { // TODO(dtrainor): Look into rolling this into onContentChanged(). initializeContentViewCore(content); setSizeOfUnattachedView(content.getContainerView()); }
private void updateContentOverlayVisibility(boolean show) { if (mView == null) return; sCachedCVCList.clear(); if (mLayoutManager != null) { mLayoutManager.getActiveLayout().getAllContentViewCores(sCachedCVCList); } if (show) { if (mView.getParent() != this) { // Make sure the view isn't a child of something else before we attempt to add it. if (mView.getParent() != null && mView.getParent() instanceof ViewGroup) { ((ViewGroup) mView.getParent()).removeView(mView); } for (int i = 0; i < sCachedCVCList.size(); i++) { ContentViewCore content = sCachedCVCList.get(i); assert content.isAlive(); content.getContainerView().setVisibility(View.VISIBLE); if (mFullscreenManager != null) { mFullscreenManager.updateContentViewViewportSize(content); } } FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); if (mView.getLayoutParams() instanceof MarginLayoutParams) { MarginLayoutParams existingLayoutParams = (MarginLayoutParams) mView.getLayoutParams(); layoutParams.leftMargin = existingLayoutParams.leftMargin; layoutParams.rightMargin = existingLayoutParams.rightMargin; layoutParams.topMargin = existingLayoutParams.topMargin; layoutParams.bottomMargin = existingLayoutParams.bottomMargin; } addView(mView, layoutParams); setFocusable(false); setFocusableInTouchMode(false); // Claim focus for the new view unless the user is currently using the URL bar. if (mUrlBar == null || !mUrlBar.hasFocus()) mView.requestFocus(); } } else { if (mView.getParent() == this) { setFocusable(true); setFocusableInTouchMode(true); for (int i = 0; i < sCachedCVCList.size(); i++) { ContentViewCore content = sCachedCVCList.get(i); if (content.isAlive()) content.getContainerView().setVisibility(View.INVISIBLE); } if (hasFocus()) { InputMethodManager manager = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE); if (manager.isActive(this)) { manager.hideSoftInputFromWindow(getWindowToken(), 0, null); } } removeView(mView); } } sCachedCVCList.clear(); }