From dc2ee1bfb50b7bec0cf3215e3d298b246dc71101 Mon Sep 17 00:00:00 2001 From: Michael Kolb Date: Mon, 14 Feb 2011 14:34:40 -0800 Subject: fix shortcut handling Bugs: 3400078 3270434 3368141 3381411 Fixed controller to check for menu & ctrl keys for shortcuts Changed focus handling in url bar Keyboard focus transitions are not 100% working yet, but it's possible to navigate to all the elements Change-Id: I514d85a37dae2589e3ce1ecb18c7fc0bf4e715f3 --- src/com/android/browser/BaseUi.java | 2 + src/com/android/browser/BrowserActivity.java | 1 - src/com/android/browser/Controller.java | 29 ++++++---- src/com/android/browser/PhoneUi.java | 6 ++ src/com/android/browser/TabBar.java | 9 +++ src/com/android/browser/TitleBarXLarge.java | 56 ++++++++++++++++--- src/com/android/browser/UI.java | 2 + src/com/android/browser/UiController.java | 2 + src/com/android/browser/UrlInputView.java | 82 ++++++++++++++-------------- src/com/android/browser/XLargeUi.java | 44 +++++++++------ 10 files changed, 155 insertions(+), 78 deletions(-) (limited to 'src/com/android/browser') diff --git a/src/com/android/browser/BaseUi.java b/src/com/android/browser/BaseUi.java index 025482b4..9bce3cdb 100644 --- a/src/com/android/browser/BaseUi.java +++ b/src/com/android/browser/BaseUi.java @@ -163,6 +163,8 @@ public abstract class BaseUi implements UI, WebViewFactory { public void onConfigurationChanged(Configuration config) { } + public abstract void editUrl(boolean clearInput); + // key handling @Override diff --git a/src/com/android/browser/BrowserActivity.java b/src/com/android/browser/BrowserActivity.java index ddd5aabd..8c38e597 100644 --- a/src/com/android/browser/BrowserActivity.java +++ b/src/com/android/browser/BrowserActivity.java @@ -276,5 +276,4 @@ public class BrowserActivity extends Activity { mController.onActivityResult(requestCode, resultCode, intent); } - } diff --git a/src/com/android/browser/Controller.java b/src/com/android/browser/Controller.java index 80da85f8..6393ac81 100644 --- a/src/com/android/browser/Controller.java +++ b/src/com/android/browser/Controller.java @@ -1026,9 +1026,7 @@ public class Controller // callback from phone title bar public void editUrl() { if (mOptionsMenuOpen) mActivity.closeOptionsMenu(); - String url = (getCurrentTopWebView() == null) ? null : getCurrentTopWebView().getUrl(); - startSearch(mSettings.getHomePage().equals(url) ? null : url, true, - null, false); + mUi.editUrl(false); } public void startVoiceSearch() { @@ -2412,6 +2410,12 @@ public class Controller startSearch(result, false, bundle, false); } + @Override + public void startSearch(String url) { + startSearch(mSettings.getHomePage().equals(url) ? null : url, true, + null, false); + } + private void startSearch(String initialQuery, boolean selectInitialQuery, Bundle appSearchData, boolean globalSearch) { if (appSearchData == null) { @@ -2445,14 +2449,13 @@ public class Controller // Even if MENU is already held down, we need to call to super to open // the IME on long press. - if (!noModifiers && KeyEvent.KEYCODE_MENU == keyCode) { + if (!noModifiers + && ((KeyEvent.KEYCODE_MENU == keyCode) + || (KeyEvent.KEYCODE_CTRL_LEFT == keyCode) + || (KeyEvent.KEYCODE_CTRL_RIGHT == keyCode))) { mMenuIsDown = true; return false; } - // The default key mode is DEFAULT_KEYS_SEARCH_LOCAL. As the MENU is - // still down, we don't want to trigger the search. Pretend to consume - // the key and do nothing. - if (mMenuIsDown) return true; WebView webView = getCurrentTopWebView(); if (webView == null) return false; @@ -2525,10 +2528,12 @@ public class Controller // case KeyEvent.KEYCODE_O: // in Chrome: open file // case KeyEvent.KEYCODE_P: // in Chrome: print page // case KeyEvent.KEYCODE_Q: // unused -// case KeyEvent.KEYCODE_R: +// case KeyEvent.KEYCODE_R: // case KeyEvent.KEYCODE_S: // in Chrome: saves page case KeyEvent.KEYCODE_T: - if (ctrl) { + // we can't use the ctrl/shift flags, they check for + // exclusive use of a modifier + if (event.isCtrlPressed()) { if (event.isShiftPressed()) { openIncognitoTab(); } else { @@ -2544,8 +2549,8 @@ public class Controller // case KeyEvent.KEYCODE_Y: // unused // case KeyEvent.KEYCODE_Z: // unused } - // if we get here, it is a regular key and webview is not null - return mUi.dispatchKey(keyCode, event); + // it is a regular key and webview is not null + return mUi.dispatchKey(keyCode, event); } boolean onKeyUp(int keyCode, KeyEvent event) { diff --git a/src/com/android/browser/PhoneUi.java b/src/com/android/browser/PhoneUi.java index a7b78344..f1939e43 100644 --- a/src/com/android/browser/PhoneUi.java +++ b/src/com/android/browser/PhoneUi.java @@ -98,6 +98,12 @@ public class PhoneUi extends BaseUi { hideTitleBar(); } + @Override + public void editUrl(boolean clearInput) { + String url = getActiveTab().getUrl(); + mUiController.startSearch(url); + } + @Override public boolean onBackKey() { if (mActiveTabsPage != null) { diff --git a/src/com/android/browser/TabBar.java b/src/com/android/browser/TabBar.java index c00e1f51..990d68ff 100644 --- a/src/com/android/browser/TabBar.java +++ b/src/com/android/browser/TabBar.java @@ -85,6 +85,7 @@ public class TabBar extends LinearLayout private final Paint mActiveShaderPaint = new Paint(); private final Paint mInactiveShaderPaint = new Paint(); + private final Paint mFocusPaint = new Paint(); private final Matrix mActiveMatrix = new Matrix(); private final Matrix mInactiveMatrix = new Matrix(); @@ -131,6 +132,9 @@ public class TabBar extends LinearLayout mInactiveShaderPaint.setStyle(Paint.Style.FILL); mInactiveShaderPaint.setAntiAlias(true); + mFocusPaint.setStyle(Paint.Style.STROKE); + mFocusPaint.setAntiAlias(true); + mFocusPaint.setColor(res.getColor(R.color.tabFocusHighlight)); } void setUseQuickControls(boolean useQuickControls) { @@ -399,6 +403,8 @@ public class TabBar extends LinearLayout lp.width = selected ? mTabWidthSelected : mTabWidthUnselected; lp.height = LayoutParams.MATCH_PARENT; setLayoutParams(lp); + setFocusable(!selected); + postInvalidate(); } void setDisplayTitle(String title) { @@ -479,6 +485,9 @@ public class TabBar extends LinearLayout matrix.setTranslate(-left, 0.0f); (mSelected ? mActiveShader : mInactiveShader).setLocalMatrix(matrix); canvas.drawPath(clipPath, paint); + if (isFocused()) { + canvas.drawPath(clipPath, mFocusPaint); + } } private void setTabPath(Path path, int l, int t, int r, int b) { diff --git a/src/com/android/browser/TitleBarXLarge.java b/src/com/android/browser/TitleBarXLarge.java index 2aa5bb91..3931526a 100644 --- a/src/com/android/browser/TitleBarXLarge.java +++ b/src/com/android/browser/TitleBarXLarge.java @@ -26,6 +26,8 @@ import android.graphics.drawable.Drawable; import android.text.Editable; import android.text.TextUtils; import android.text.TextWatcher; +import android.util.Log; +import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; @@ -137,7 +139,7 @@ public class TitleBarXLarge extends TitleBarBase mUrlInput.setOnFocusChangeListener(this); mUrlInput.setSelectAllOnFocus(true); mUrlInput.addTextChangedListener(this); - setEditMode(false); + setFocusState(false); } void updateNavigationState(Tab tab) { @@ -190,9 +192,22 @@ public class TitleBarXLarge extends TitleBarBase @Override public void onFocusChange(View view, boolean hasFocus) { - setEditMode(hasFocus); - mUrlContainer.setBackgroundDrawable(hasFocus - ? mFocusDrawable : mUnfocusDrawable); + // if losing focus and not in touch mode, leave as is + if (hasFocus || view.isInTouchMode() || mUrlInput.needsUpdate()) { + setFocusState(hasFocus); + mUrlContainer.setBackgroundDrawable(hasFocus + ? mFocusDrawable : mUnfocusDrawable); + } + if (hasFocus) { + mUrlInput.forceIme(); + if (mInVoiceMode) { + mUrlInput.forceFilter(); + } + } else if (!mUrlInput.needsUpdate()) { + mUrlInput.dismissDropDown(); + mUrlInput.hideIME(); + } + mUrlInput.clearNeedsUpdate(); } public void setCurrentUrlIsBookmark(boolean isBookmark) { @@ -203,7 +218,7 @@ public class TitleBarXLarge extends TitleBarBase * called from the Ui when the user wants to edit * @param clearInput clear the input field */ - void onEditUrl(boolean clearInput) { + void startEditingUrl(boolean clearInput) { // editing takes preference of progress mContainer.setVisibility(View.VISIBLE); if (mUseQuickControls) { @@ -267,8 +282,8 @@ public class TitleBarXLarge extends TitleBarBase } } - private void setEditMode(boolean edit) { - if (edit) { + private void setFocusState(boolean focus) { + if (focus) { mUrlInput.setDropDownWidth(mUrlContainer.getWidth()); mUrlInput.setDropDownHorizontalOffset(-mUrlInput.getLeft()); mSearchButton.setVisibility(View.GONE); @@ -390,4 +405,31 @@ public class TitleBarXLarge extends TitleBarBase mUrlInput.setIncognitoMode(incognito); } + @Override + public View focusSearch(View focused, int dir) { + if (FOCUS_DOWN == dir && hasFocus()) { + return getCurrentWebView(); + } + return super.focusSearch(focused, dir); + } + + @Override + public boolean dispatchKeyEventPreIme(KeyEvent evt) { + if (evt.getKeyCode() == KeyEvent.KEYCODE_BACK) { + // catch back key in order to do slightly more cleanup than usual + mUrlInput.clearFocus(); + return true; + } + return super.dispatchKeyEventPreIme(evt); + } + + private WebView getCurrentWebView() { + Tab t = mUi.getActiveTab(); + if (t != null) { + return t.getWebView(); + } else { + return null; + } + } + } diff --git a/src/com/android/browser/UI.java b/src/com/android/browser/UI.java index 8de2b19a..34dcaeed 100644 --- a/src/com/android/browser/UI.java +++ b/src/com/android/browser/UI.java @@ -118,6 +118,8 @@ public interface UI { void showMaxTabsWarning(); + void editUrl(boolean clearInput); + boolean dispatchKey(int code, KeyEvent event); } diff --git a/src/com/android/browser/UiController.java b/src/com/android/browser/UiController.java index a16b44b7..6075d364 100644 --- a/src/com/android/browser/UiController.java +++ b/src/com/android/browser/UiController.java @@ -53,6 +53,8 @@ public interface UiController extends BookmarksHistoryCallbacks { void bookmarksOrHistoryPicker(boolean openHistory); + void startSearch(String url); + void startVoiceSearch(); void showVoiceSearchResults(String title); diff --git a/src/com/android/browser/UrlInputView.java b/src/com/android/browser/UrlInputView.java index 1f15b327..2ec21111 100644 --- a/src/com/android/browser/UrlInputView.java +++ b/src/com/android/browser/UrlInputView.java @@ -29,7 +29,6 @@ import android.util.AttributeSet; import android.util.Patterns; import android.view.KeyEvent; import android.view.View; -import android.view.View.OnFocusChangeListener; import android.view.inputmethod.InputMethodManager; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; @@ -44,7 +43,7 @@ import java.util.List; * handling suggestions */ public class UrlInputView extends AutoCompleteTextView - implements OnFocusChangeListener, OnEditorActionListener, + implements OnEditorActionListener, CompletionListener, OnItemClickListener { @@ -55,12 +54,11 @@ public class UrlInputView extends AutoCompleteTextView private UrlInputListener mListener; private InputMethodManager mInputManager; private SuggestionsAdapter mAdapter; - private OnFocusChangeListener mWrappedFocusListener; private View mContainer; private boolean mLandscape; - private boolean mInVoiceMode; private boolean mIncognitoMode; private int mVOffset; + private boolean mNeedsUpdate; public UrlInputView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); @@ -80,7 +78,6 @@ public class UrlInputView extends AutoCompleteTextView private void init(Context ctx) { mInputManager = (InputMethodManager) ctx.getSystemService(Context.INPUT_METHOD_SERVICE); setOnEditorActionListener(this); - super.setOnFocusChangeListener(this); mAdapter = new SuggestionsAdapter(ctx, this); setAdapter(mAdapter); setSelectAllOnFocus(true); @@ -88,6 +85,21 @@ public class UrlInputView extends AutoCompleteTextView setThreshold(1); setOnItemClickListener(this); mVOffset = 0; + mNeedsUpdate = false; + } + + /** + * check if focus change requires a title bar update + */ + boolean needsUpdate() { + return mNeedsUpdate; + } + + /** + * clear the focus change needs title bar update flag + */ + void clearNeedsUpdate() { + mNeedsUpdate = false; } void setController(UiController controller) { @@ -107,9 +119,12 @@ public class UrlInputView extends AutoCompleteTextView mContainer = container; } + public void setUrlInputListener(UrlInputListener listener) { + mListener = listener; + } + void setVoiceResults(List voiceResults) { mAdapter.setVoiceResults(voiceResults); - mInVoiceMode = (voiceResults != null); } @Override @@ -147,44 +162,29 @@ public class UrlInputView extends AutoCompleteTextView setDropDownVerticalOffset(mVOffset); } - @Override - public void setOnFocusChangeListener(OnFocusChangeListener focusListener) { - mWrappedFocusListener = focusListener; - } - @Override public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { finishInput(getText().toString(), null, TYPED); return true; } - @Override - public void onFocusChange(View v, boolean hasFocus) { - if (mWrappedFocusListener != null) { - mWrappedFocusListener.onFocusChange(v, hasFocus); - } - if (hasFocus) { - forceIme(); - if (mInVoiceMode) { - performFiltering(getText().toString(), 0); - showDropDown(); - } - } else { - finishInput(null, null, null); - } + void forceFilter() { + performFiltering(getText().toString(), 0); + showDropDown(); } - public void setUrlInputListener(UrlInputListener listener) { - mListener = listener; - } - - public void forceIme() { + void forceIme() { mInputManager.focusIn(this); mInputManager.showSoftInput(this, 0); } + void hideIME() { + mInputManager.hideSoftInputFromWindow(getWindowToken(), 0); + } + private void finishInput(String url, String extra, String source) { - this.dismissDropDown(); + mNeedsUpdate = true; + dismissDropDown(); mInputManager.hideSoftInputFromWindow(getWindowToken(), 0); if (TextUtils.isEmpty(url)) { mListener.onDismiss(); @@ -229,17 +229,6 @@ public class UrlInputView extends AutoCompleteTextView ? VOICE : SUGGESTED); } - @Override - public boolean onKeyPreIme(int keyCode, KeyEvent evt) { - if ((evt.getAction() == KeyEvent.ACTION_DOWN) - && (keyCode == KeyEvent.KEYCODE_BACK)) { - // catch back key in order to do slightly more cleanup than usual - clearFocus(); - return true; - } - return super.onKeyPreIme(keyCode, evt); - } - @Override public void onItemClick( AdapterView parent, View view, int position, long id) { @@ -263,4 +252,13 @@ public class UrlInputView extends AutoCompleteTextView mAdapter.setIncognitoMode(mIncognitoMode); } + @Override + public boolean onKeyDown(int keyCode, KeyEvent evt) { + if (keyCode == KeyEvent.KEYCODE_ESCAPE && !isInTouchMode()) { + finishInput(null, null, null); + return true; + } + return super.onKeyDown(keyCode, evt); + } + } diff --git a/src/com/android/browser/XLargeUi.java b/src/com/android/browser/XLargeUi.java index 88df015a..f361e57b 100644 --- a/src/com/android/browser/XLargeUi.java +++ b/src/com/android/browser/XLargeUi.java @@ -260,18 +260,19 @@ public class XLargeUi extends BaseUi implements ScrollListener { return 0; } - void editUrl(boolean clearInput) { + @Override + public void editUrl(boolean clearInput) { if (mUiController.isInCustomActionMode()) { mUiController.endActionMode(); } showTitleBar(); - mTitleBar.onEditUrl(clearInput); + mTitleBar.startEditingUrl(clearInput); } void showTitleBarAndEdit() { mTitleBar.setShowProgressOnly(false); showTitleBar(); - mTitleBar.onEditUrl(false); + mTitleBar.startEditingUrl(false); } void stopEditingUrl() { @@ -387,21 +388,32 @@ public class XLargeUi extends BaseUi implements ScrollListener { @Override public boolean dispatchKey(int code, KeyEvent event) { WebView web = getActiveTab().getWebView(); - switch (code) { - case KeyEvent.KEYCODE_TAB: - case KeyEvent.KEYCODE_DPAD_UP: - case KeyEvent.KEYCODE_DPAD_LEFT: - if ((web != null) && web.hasFocus()) { - editUrl(true); - return true; - } - } - boolean ctrl = event.hasModifiers(KeyEvent.META_CTRL_ON); - if (!ctrl && event.isPrintingKey() && !mTitleBar.isEditingUrl()) { - editUrl(true); - return mContentView.dispatchKeyEvent(event); + if (event.getAction() == KeyEvent.ACTION_DOWN) { + + switch (code) { + case KeyEvent.KEYCODE_TAB: + case KeyEvent.KEYCODE_DPAD_UP: + case KeyEvent.KEYCODE_DPAD_LEFT: + if ((web != null) && web.hasFocus() && !mTitleBar.hasFocus()) { + editUrl(false); + return true; + } + } + boolean ctrl = event.hasModifiers(KeyEvent.META_CTRL_ON); + if (!ctrl && isTypingKey(event) && !mTitleBar.isEditingUrl()) { + editUrl(true); + return mContentView.dispatchKeyEvent(event); + } } return false; } + private boolean isTypingKey(KeyEvent evt) { + return evt.getUnicodeChar() > 0; + } + + TabBar getTabBar() { + return mTabBar; + } + } -- cgit v1.2.3