summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorClara Bayarri <clarabayarri@google.com>2015-03-02 19:42:48 +0000
committerClara Bayarri <clarabayarri@google.com>2015-03-13 10:51:51 +0000
commit4423d91de5300d3fd318bf5bc2d4d7e5bb856abf (patch)
treef62a9d12f773379d306278c6cb003f545df8138c
parent993d128477bf7c9a55a015bd9dc5e4fafddf9a14 (diff)
downloadframeworks_base-4423d91de5300d3fd318bf5bc2d4d7e5bb856abf.zip
frameworks_base-4423d91de5300d3fd318bf5bc2d4d7e5bb856abf.tar.gz
frameworks_base-4423d91de5300d3fd318bf5bc2d4d7e5bb856abf.tar.bz2
Add a type parameter to startActionMode() calls.
This requires adding a new method to View and Window.Callback to pass down the type as a parameter. For compatibility purposes, the new method implementations keep the type and call the old method, in case clients have subclassed it. Change-Id: If5d857f131e33be8cc6a8814f2e9c4e85ad2da25
-rw-r--r--api/current.txt8
-rw-r--r--api/system-current.txt8
-rw-r--r--core/java/android/app/Activity.java44
-rw-r--r--core/java/android/app/Dialog.java25
-rw-r--r--core/java/android/app/SearchDialog.java6
-rw-r--r--core/java/android/service/dreams/DreamService.java7
-rw-r--r--core/java/android/view/PhoneWindow.java177
-rw-r--r--core/java/android/view/View.java23
-rw-r--r--core/java/android/view/ViewGroup.java117
-rw-r--r--core/java/android/view/ViewParent.java23
-rw-r--r--core/java/android/view/ViewRootImpl.java6
-rw-r--r--core/java/android/view/Window.java17
-rw-r--r--core/java/android/view/WindowCallbackWrapper.java5
-rw-r--r--core/java/com/android/internal/app/WindowDecorActionBar.java40
-rw-r--r--core/java/com/android/internal/view/StandaloneActionMode.java7
-rw-r--r--core/java/com/android/internal/widget/ActionBarContainer.java9
-rw-r--r--tools/layoutlib/bridge/src/android/view/WindowCallback.java5
17 files changed, 395 insertions, 132 deletions
diff --git a/api/current.txt b/api/current.txt
index 16eb4e9..5f36806 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -3450,6 +3450,7 @@ package android.app {
method public void onWindowAttributesChanged(android.view.WindowManager.LayoutParams);
method public void onWindowFocusChanged(boolean);
method public android.view.ActionMode onWindowStartingActionMode(android.view.ActionMode.Callback);
+ method public android.view.ActionMode onWindowStartingActionMode(android.view.ActionMode.Callback, int);
method public void openContextMenu(android.view.View);
method public void openOptionsMenu();
method public void overridePendingTransition(int, int);
@@ -3496,6 +3497,7 @@ package android.app {
method public final deprecated void showDialog(int);
method public final deprecated boolean showDialog(int, android.os.Bundle);
method public android.view.ActionMode startActionMode(android.view.ActionMode.Callback);
+ method public android.view.ActionMode startActionMode(android.view.ActionMode.Callback, int);
method public void startActivityForResult(android.content.Intent, int);
method public void startActivityForResult(android.content.Intent, int, android.os.Bundle);
method public void startActivityFromChild(android.app.Activity, android.content.Intent, int);
@@ -4073,6 +4075,7 @@ package android.app {
method public void onWindowAttributesChanged(android.view.WindowManager.LayoutParams);
method public void onWindowFocusChanged(boolean);
method public android.view.ActionMode onWindowStartingActionMode(android.view.ActionMode.Callback);
+ method public android.view.ActionMode onWindowStartingActionMode(android.view.ActionMode.Callback, int);
method public void openContextMenu(android.view.View);
method public void openOptionsMenu();
method public void registerForContextMenu(android.view.View);
@@ -27541,6 +27544,7 @@ package android.service.dreams {
method public void onWindowAttributesChanged(android.view.WindowManager.LayoutParams);
method public void onWindowFocusChanged(boolean);
method public android.view.ActionMode onWindowStartingActionMode(android.view.ActionMode.Callback);
+ method public android.view.ActionMode onWindowStartingActionMode(android.view.ActionMode.Callback, int);
method public void setContentView(int);
method public void setContentView(android.view.View);
method public void setContentView(android.view.View, android.view.ViewGroup.LayoutParams);
@@ -34470,6 +34474,7 @@ package android.view {
method public void setZ(float);
method public boolean showContextMenu();
method public android.view.ActionMode startActionMode(android.view.ActionMode.Callback);
+ method public android.view.ActionMode startActionMode(android.view.ActionMode.Callback, int);
method public void startAnimation(android.view.animation.Animation);
method public final boolean startDrag(android.content.ClipData, android.view.View.DragShadowBuilder, java.lang.Object, int);
method public boolean startNestedScroll(int);
@@ -34925,6 +34930,7 @@ package android.view {
method public boolean shouldDelayChildPressedState();
method public boolean showContextMenuForChild(android.view.View);
method public android.view.ActionMode startActionModeForChild(android.view.View, android.view.ActionMode.Callback);
+ method public android.view.ActionMode startActionModeForChild(android.view.View, android.view.ActionMode.Callback, int);
method public void startLayoutAnimation();
method public void startViewTransition(android.view.View);
method public void updateViewLayout(android.view.View, android.view.ViewGroup.LayoutParams);
@@ -35045,6 +35051,7 @@ package android.view {
method public abstract void requestTransparentRegion(android.view.View);
method public abstract boolean showContextMenuForChild(android.view.View);
method public abstract android.view.ActionMode startActionModeForChild(android.view.View, android.view.ActionMode.Callback);
+ method public abstract android.view.ActionMode startActionModeForChild(android.view.View, android.view.ActionMode.Callback, int);
}
public class ViewPropertyAnimator {
@@ -35333,6 +35340,7 @@ package android.view {
method public abstract void onWindowAttributesChanged(android.view.WindowManager.LayoutParams);
method public abstract void onWindowFocusChanged(boolean);
method public abstract android.view.ActionMode onWindowStartingActionMode(android.view.ActionMode.Callback);
+ method public abstract android.view.ActionMode onWindowStartingActionMode(android.view.ActionMode.Callback, int);
}
public final class WindowAnimationFrameStats extends android.view.FrameStats implements android.os.Parcelable {
diff --git a/api/system-current.txt b/api/system-current.txt
index 1707897..2cb56ea 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -3533,6 +3533,7 @@ package android.app {
method public void onWindowAttributesChanged(android.view.WindowManager.LayoutParams);
method public void onWindowFocusChanged(boolean);
method public android.view.ActionMode onWindowStartingActionMode(android.view.ActionMode.Callback);
+ method public android.view.ActionMode onWindowStartingActionMode(android.view.ActionMode.Callback, int);
method public void openContextMenu(android.view.View);
method public void openOptionsMenu();
method public void overridePendingTransition(int, int);
@@ -3579,6 +3580,7 @@ package android.app {
method public final deprecated void showDialog(int);
method public final deprecated boolean showDialog(int, android.os.Bundle);
method public android.view.ActionMode startActionMode(android.view.ActionMode.Callback);
+ method public android.view.ActionMode startActionMode(android.view.ActionMode.Callback, int);
method public void startActivityForResult(android.content.Intent, int);
method public void startActivityForResult(android.content.Intent, int, android.os.Bundle);
method public void startActivityFromChild(android.app.Activity, android.content.Intent, int);
@@ -4163,6 +4165,7 @@ package android.app {
method public void onWindowAttributesChanged(android.view.WindowManager.LayoutParams);
method public void onWindowFocusChanged(boolean);
method public android.view.ActionMode onWindowStartingActionMode(android.view.ActionMode.Callback);
+ method public android.view.ActionMode onWindowStartingActionMode(android.view.ActionMode.Callback, int);
method public void openContextMenu(android.view.View);
method public void openOptionsMenu();
method public void registerForContextMenu(android.view.View);
@@ -29147,6 +29150,7 @@ package android.service.dreams {
method public void onWindowAttributesChanged(android.view.WindowManager.LayoutParams);
method public void onWindowFocusChanged(boolean);
method public android.view.ActionMode onWindowStartingActionMode(android.view.ActionMode.Callback);
+ method public android.view.ActionMode onWindowStartingActionMode(android.view.ActionMode.Callback, int);
method public void setContentView(int);
method public void setContentView(android.view.View);
method public void setContentView(android.view.View, android.view.ViewGroup.LayoutParams);
@@ -36638,6 +36642,7 @@ package android.view {
method public void setZ(float);
method public boolean showContextMenu();
method public android.view.ActionMode startActionMode(android.view.ActionMode.Callback);
+ method public android.view.ActionMode startActionMode(android.view.ActionMode.Callback, int);
method public void startAnimation(android.view.animation.Animation);
method public final boolean startDrag(android.content.ClipData, android.view.View.DragShadowBuilder, java.lang.Object, int);
method public boolean startNestedScroll(int);
@@ -37093,6 +37098,7 @@ package android.view {
method public boolean shouldDelayChildPressedState();
method public boolean showContextMenuForChild(android.view.View);
method public android.view.ActionMode startActionModeForChild(android.view.View, android.view.ActionMode.Callback);
+ method public android.view.ActionMode startActionModeForChild(android.view.View, android.view.ActionMode.Callback, int);
method public void startLayoutAnimation();
method public void startViewTransition(android.view.View);
method public void updateViewLayout(android.view.View, android.view.ViewGroup.LayoutParams);
@@ -37213,6 +37219,7 @@ package android.view {
method public abstract void requestTransparentRegion(android.view.View);
method public abstract boolean showContextMenuForChild(android.view.View);
method public abstract android.view.ActionMode startActionModeForChild(android.view.View, android.view.ActionMode.Callback);
+ method public abstract android.view.ActionMode startActionModeForChild(android.view.View, android.view.ActionMode.Callback, int);
}
public class ViewPropertyAnimator {
@@ -37502,6 +37509,7 @@ package android.view {
method public abstract void onWindowAttributesChanged(android.view.WindowManager.LayoutParams);
method public abstract void onWindowFocusChanged(boolean);
method public abstract android.view.ActionMode onWindowStartingActionMode(android.view.ActionMode.Callback);
+ method public abstract android.view.ActionMode onWindowStartingActionMode(android.view.ActionMode.Callback, int);
}
public final class WindowAnimationFrameStats extends android.view.FrameStats implements android.os.Parcelable {
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 9f8befe..fdbf197 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -787,6 +787,7 @@ public class Activity extends ContextThemeWrapper
private boolean mChangeCanvasToTranslucent;
private boolean mTitleReady = false;
+ private int mActionModeTypeStarting = ActionMode.TYPE_PRIMARY;
private int mDefaultKeyMode = DEFAULT_KEYS_DISABLE;
private SpannableStringBuilder mDefaultKeySsb = null;
@@ -5681,10 +5682,10 @@ public class Activity extends ContextThemeWrapper
}
/**
- * Start an action mode.
+ * Start an action mode of the default type {@link ActionMode#TYPE_PRIMARY}.
*
- * @param callback Callback that will manage lifecycle events for this context mode
- * @return The ContextMode that was started, or null if it was canceled
+ * @param callback Callback that will manage lifecycle events for this action mode
+ * @return The ActionMode that was started, or null if it was canceled
*
* @see ActionMode
*/
@@ -5694,6 +5695,20 @@ public class Activity extends ContextThemeWrapper
}
/**
+ * Start an action mode of the given type.
+ *
+ * @param callback Callback that will manage lifecycle events for this action mode
+ * @param type One of {@link ActionMode#TYPE_PRIMARY} or {@link ActionMode#TYPE_FLOATING}.
+ * @return The ActionMode that was started, or null if it was canceled
+ *
+ * @see ActionMode
+ */
+ @Nullable
+ public ActionMode startActionMode(ActionMode.Callback callback, int type) {
+ return mWindow.getDecorView().startActionMode(callback, type);
+ }
+
+ /**
* Give the Activity a chance to control the UI for an action mode requested
* by the system.
*
@@ -5707,14 +5722,31 @@ public class Activity extends ContextThemeWrapper
@Nullable
@Override
public ActionMode onWindowStartingActionMode(ActionMode.Callback callback) {
- initWindowDecorActionBar();
- if (mActionBar != null) {
- return mActionBar.startActionMode(callback);
+ // Only Primary ActionModes are represented in the ActionBar.
+ if (mActionModeTypeStarting == ActionMode.TYPE_PRIMARY) {
+ initWindowDecorActionBar();
+ if (mActionBar != null) {
+ return mActionBar.startActionMode(callback);
+ }
}
return null;
}
/**
+ * {@inheritDoc}
+ */
+ @Nullable
+ @Override
+ public ActionMode onWindowStartingActionMode(ActionMode.Callback callback, int type) {
+ try {
+ mActionModeTypeStarting = type;
+ return onWindowStartingActionMode(callback);
+ } finally {
+ mActionModeTypeStarting = ActionMode.TYPE_PRIMARY;
+ }
+ }
+
+ /**
* Notifies the Activity that an action mode has been started.
* Activity subclasses overriding this method should call the superclass implementation.
*
diff --git a/core/java/android/app/Dialog.java b/core/java/android/app/Dialog.java
index 8e64b34..9defcbe 100644
--- a/core/java/android/app/Dialog.java
+++ b/core/java/android/app/Dialog.java
@@ -121,6 +121,8 @@ public class Dialog implements DialogInterface, Window.Callback,
private ActionMode mActionMode;
+ private int mActionModeTypeStarting = ActionMode.TYPE_PRIMARY;
+
private final Runnable mDismissAction = new Runnable() {
public void run() {
dismissDialog();
@@ -973,13 +975,13 @@ public class Dialog implements DialogInterface, Window.Callback,
public boolean onContextItemSelected(MenuItem item) {
return false;
}
-
+
/**
* @see Activity#onContextMenuClosed(Menu)
*/
public void onContextMenuClosed(Menu menu) {
}
-
+
/**
* This hook is called when the user signals the desire to start a search.
*/
@@ -998,8 +1000,12 @@ public class Dialog implements DialogInterface, Window.Callback,
}
}
+ /**
+ * {@inheritDoc}
+ */
+ @Override
public ActionMode onWindowStartingActionMode(ActionMode.Callback callback) {
- if (mActionBar != null) {
+ if (mActionBar != null && mActionModeTypeStarting == ActionMode.TYPE_PRIMARY) {
return mActionBar.startActionMode(callback);
}
return null;
@@ -1007,6 +1013,19 @@ public class Dialog implements DialogInterface, Window.Callback,
/**
* {@inheritDoc}
+ */
+ @Override
+ public ActionMode onWindowStartingActionMode(ActionMode.Callback callback, int type) {
+ try {
+ mActionModeTypeStarting = type;
+ return onWindowStartingActionMode(callback);
+ } finally {
+ mActionModeTypeStarting = ActionMode.TYPE_PRIMARY;
+ }
+ }
+
+ /**
+ * {@inheritDoc}
*
* Note that if you override this method you should always call through
* to the superclass implementation by calling super.onActionModeStarted(mode).
diff --git a/core/java/android/app/SearchDialog.java b/core/java/android/app/SearchDialog.java
index af1810b..c719a0e 100644
--- a/core/java/android/app/SearchDialog.java
+++ b/core/java/android/app/SearchDialog.java
@@ -639,6 +639,12 @@ public class SearchDialog extends Dialog {
public ActionMode startActionModeForChild(View child, ActionMode.Callback callback) {
return null;
}
+
+ @Override
+ public ActionMode startActionModeForChild(
+ View child, ActionMode.Callback callback, int type) {
+ return null;
+ }
}
private boolean isEmpty(AutoCompleteTextView actv) {
diff --git a/core/java/android/service/dreams/DreamService.java b/core/java/android/service/dreams/DreamService.java
index df4d7e0..822bfcc 100644
--- a/core/java/android/service/dreams/DreamService.java
+++ b/core/java/android/service/dreams/DreamService.java
@@ -344,6 +344,13 @@ public class DreamService extends Service implements Window.Callback {
/** {@inheritDoc} */
@Override
+ public ActionMode onWindowStartingActionMode(
+ android.view.ActionMode.Callback callback, int type) {
+ return null;
+ }
+
+ /** {@inheritDoc} */
+ @Override
public void onActionModeStarted(ActionMode mode) {
}
diff --git a/core/java/android/view/PhoneWindow.java b/core/java/android/view/PhoneWindow.java
index d4b14f6..e43dfef 100644
--- a/core/java/android/view/PhoneWindow.java
+++ b/core/java/android/view/PhoneWindow.java
@@ -28,7 +28,6 @@ import android.app.SearchManager;
import android.os.UserHandle;
import com.android.internal.R;
-import com.android.internal.view.ActionModeWrapper;
import com.android.internal.view.RootViewSurfaceTaker;
import com.android.internal.view.StandaloneActionMode;
import com.android.internal.view.menu.ContextMenuBuilder;
@@ -76,7 +75,6 @@ import android.util.EventLog;
import android.util.Log;
import android.util.SparseArray;
import android.util.TypedValue;
-import android.view.ActionMode.Callback;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
import android.view.animation.Animation;
@@ -2676,44 +2674,47 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
}
@Override
+ public ActionMode startActionModeForChild(
+ View child, ActionMode.Callback callback, int type) {
+ // originalView can be used here to be sure that we don't obscure
+ // relevant content with the context mode UI.
+ return startActionMode(callback, type);
+ }
+
+ @Override
public ActionMode startActionMode(ActionMode.Callback callback) {
+ return startActionMode(callback, ActionMode.TYPE_PRIMARY);
+ }
+
+ @Override
+ public ActionMode startActionMode(ActionMode.Callback callback, int type) {
if (mActionMode != null) {
mActionMode.finish();
mActionMode = null;
}
-
ActionMode.Callback wrappedCallback = new ActionModeCallbackWrapper(callback);
- ActionModeWrapper mode = null;
- ActionMode callbackMode = null;
+ ActionMode mode = null;
if (getCallback() != null && !isDestroyed()) {
try {
- callbackMode =
- getCallback().onWindowStartingActionMode(wrappedCallback);
- if (callbackMode != null && callbackMode instanceof ActionModeWrapper) {
- // If we get an ActionModeWrapper back, we handle its lifecycle.
- mode = (ActionModeWrapper) callbackMode;
- callbackMode = null;
- }
+ mode = getCallback().onWindowStartingActionMode(wrappedCallback, type);
} catch (AbstractMethodError ame) {
// Older apps might not implement this callback method.
}
}
- if (callbackMode != null) {
- mActionMode = callbackMode;
+ if (mode != null) {
+ mActionMode = mode;
} else {
- if (mode == null) {
- mode = new ActionModeWrapper(
- mContext, wrappedCallback, new StandaloneActionModeProvider());
- }
- if (mActionModeView != null) {
- mActionModeView.killMode();
- }
- if (callback.onCreateActionMode(mode, mode.getMenu())) {
- mode.lockType();
- mActionMode = mode.getWrappedActionMode();
- mActionMode.invalidate();
- } else {
- mActionMode = null;
+ if (type == ActionMode.TYPE_PRIMARY) {
+ if (mActionModeView != null) {
+ mActionModeView.killMode();
+ }
+ mode = createStandaloneActionMode(wrappedCallback);
+ if (mode != null && callback.onCreateActionMode(mode, mode.getMenu())) {
+ mActionMode = mode;
+ mActionMode.invalidate();
+ } else {
+ mActionMode = null;
+ }
}
}
if (mActionMode != null && getCallback() != null && !isDestroyed()) {
@@ -3209,80 +3210,70 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
updateColorViewTranslations();
}
- /**
- * Encapsulates the view creation for {@link StandaloneActionMode}.
- */
- private class StandaloneActionModeProvider
- implements ActionModeWrapper.ActionModeProvider {
+ private ActionMode createStandaloneActionMode(ActionMode.Callback callback) {
+ if (mActionModeView == null) {
+ if (isFloating()) {
+ // Use the action bar theme.
+ final TypedValue outValue = new TypedValue();
+ final Theme baseTheme = mContext.getTheme();
+ baseTheme.resolveAttribute(R.attr.actionBarTheme, outValue, true);
- @Override
- public ActionMode createActionMode(android.view.ActionMode.Callback callback,
- MenuBuilder menuBuilder) {
- if (mActionModeView == null) {
- if (isFloating()) {
- // Use the action bar theme.
- final TypedValue outValue = new TypedValue();
- final Theme baseTheme = mContext.getTheme();
- baseTheme.resolveAttribute(R.attr.actionBarTheme, outValue, true);
-
- final Context actionBarContext;
- if (outValue.resourceId != 0) {
- final Theme actionBarTheme = mContext.getResources().newTheme();
- actionBarTheme.setTo(baseTheme);
- actionBarTheme.applyStyle(outValue.resourceId, true);
-
- actionBarContext = new ContextThemeWrapper(mContext, 0);
- actionBarContext.getTheme().setTo(actionBarTheme);
- } else {
- actionBarContext = mContext;
- }
+ final Context actionBarContext;
+ if (outValue.resourceId != 0) {
+ final Theme actionBarTheme = mContext.getResources().newTheme();
+ actionBarTheme.setTo(baseTheme);
+ actionBarTheme.applyStyle(outValue.resourceId, true);
- mActionModeView = new ActionBarContextView(actionBarContext);
- mActionModePopup = new PopupWindow(actionBarContext, null,
- R.attr.actionModePopupWindowStyle);
- mActionModePopup.setWindowLayoutType(
- WindowManager.LayoutParams.TYPE_APPLICATION);
- mActionModePopup.setContentView(mActionModeView);
- mActionModePopup.setWidth(MATCH_PARENT);
-
- actionBarContext.getTheme().resolveAttribute(
- R.attr.actionBarSize, outValue, true);
- final int height = TypedValue.complexToDimensionPixelSize(outValue.data,
- actionBarContext.getResources().getDisplayMetrics());
- mActionModeView.setContentHeight(height);
- mActionModePopup.setHeight(WRAP_CONTENT);
- mShowActionModePopup = new Runnable() {
- public void run() {
- mActionModePopup.showAtLocation(
- mActionModeView.getApplicationWindowToken(),
- Gravity.TOP | Gravity.FILL_HORIZONTAL, 0, 0);
- }
- };
+ actionBarContext = new ContextThemeWrapper(mContext, 0);
+ actionBarContext.getTheme().setTo(actionBarTheme);
} else {
- ViewStub stub = (ViewStub) findViewById(
- R.id.action_mode_bar_stub);
- if (stub != null) {
- mActionModeView = (ActionBarContextView) stub.inflate();
+ actionBarContext = mContext;
+ }
+
+ mActionModeView = new ActionBarContextView(actionBarContext);
+ mActionModePopup = new PopupWindow(actionBarContext, null,
+ R.attr.actionModePopupWindowStyle);
+ mActionModePopup.setWindowLayoutType(
+ WindowManager.LayoutParams.TYPE_APPLICATION);
+ mActionModePopup.setContentView(mActionModeView);
+ mActionModePopup.setWidth(MATCH_PARENT);
+
+ actionBarContext.getTheme().resolveAttribute(
+ R.attr.actionBarSize, outValue, true);
+ final int height = TypedValue.complexToDimensionPixelSize(outValue.data,
+ actionBarContext.getResources().getDisplayMetrics());
+ mActionModeView.setContentHeight(height);
+ mActionModePopup.setHeight(WRAP_CONTENT);
+ mShowActionModePopup = new Runnable() {
+ public void run() {
+ mActionModePopup.showAtLocation(
+ mActionModeView.getApplicationWindowToken(),
+ Gravity.TOP | Gravity.FILL_HORIZONTAL, 0, 0);
}
+ };
+ } else {
+ ViewStub stub = (ViewStub) findViewById(
+ R.id.action_mode_bar_stub);
+ if (stub != null) {
+ mActionModeView = (ActionBarContextView) stub.inflate();
}
}
- if (mActionModeView != null) {
- ActionMode mode = new StandaloneActionMode(
- mActionModeView.getContext(), mActionModeView,
- callback, mActionModePopup == null, menuBuilder);
- mActionModeView.killMode();
- mActionModeView.initForMode(mode);
- mActionModeView.setVisibility(View.VISIBLE);
- if (mActionModePopup != null) {
- post(mShowActionModePopup);
- }
- mActionModeView.sendAccessibilityEvent(
- AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
- return mode;
+ }
+ if (mActionModeView != null) {
+ ActionMode mode = new StandaloneActionMode(
+ mActionModeView.getContext(), mActionModeView,
+ callback, mActionModePopup == null);
+ mActionModeView.killMode();
+ mActionModeView.initForMode(mode);
+ mActionModeView.setVisibility(View.VISIBLE);
+ if (mActionModePopup != null) {
+ post(mShowActionModePopup);
}
- return null;
+ mActionModeView.sendAccessibilityEvent(
+ AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
+ return mode;
}
-
+ return null;
}
/**
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 4f2d4a6..57dc015 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -4844,17 +4844,36 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
}
/**
- * Start an action mode.
+ * Start an action mode with the default type {@link ActionMode#TYPE_PRIMARY}.
*
* @param callback Callback that will control the lifecycle of the action mode
* @return The new action mode if it is started, null otherwise
*
* @see ActionMode
+ * @see #startActionMode(android.view.ActionMode.Callback, int)
*/
public ActionMode startActionMode(ActionMode.Callback callback) {
+ return startActionMode(callback, ActionMode.TYPE_PRIMARY);
+ }
+
+ /**
+ * Start an action mode with the given type.
+ *
+ * @param callback Callback that will control the lifecycle of the action mode
+ * @param type One of {@link ActionMode#TYPE_PRIMARY} or {@link ActionMode#TYPE_FLOATING}.
+ * @return The new action mode if it is started, null otherwise
+ *
+ * @see ActionMode
+ */
+ public ActionMode startActionMode(ActionMode.Callback callback, int type) {
ViewParent parent = getParent();
if (parent == null) return null;
- return parent.startActionModeForChild(this, callback);
+ try {
+ return parent.startActionModeForChild(this, callback, type);
+ } catch (AbstractMethodError ame) {
+ // Older implementations of custom views might not implement this.
+ return parent.startActionModeForChild(this, callback);
+ }
}
/**
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index dfe9f0e..87f3e94 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -369,6 +369,26 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
static final int FLAG_TOUCHSCREEN_BLOCKS_FOCUS = 0x4000000;
/**
+ * When true, indicates that a call to startActionModeForChild was made with the type parameter
+ * and should not be ignored. This helps in backwards compatibility with the existing method
+ * without a type.
+ *
+ * @see #startActionModeForChild(View, android.view.ActionMode.Callback)
+ * @see #startActionModeForChild(View, android.view.ActionMode.Callback, int)
+ */
+ private static final int FLAG_START_ACTION_MODE_FOR_CHILD_IS_TYPED = 0x8000000;
+
+ /**
+ * When true, indicates that a call to startActionModeForChild was made without the type
+ * parameter. This helps in backwards compatibility with the existing method
+ * without a type.
+ *
+ * @see #startActionModeForChild(View, android.view.ActionMode.Callback)
+ * @see #startActionModeForChild(View, android.view.ActionMode.Callback, int)
+ */
+ private static final int FLAG_START_ACTION_MODE_FOR_CHILD_IS_NOT_TYPED = 0x10000000;
+
+ /**
* Indicates which types of drawing caches are to be kept in memory.
* This field should be made private, so it is hidden from the SDK.
* {@hide}
@@ -479,6 +499,60 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
*/
private int mNestedScrollAxes;
+ /**
+ * Empty ActionMode used as a sentinel in recursive entries to startActionModeForChild.
+ *
+ * @see #startActionModeForChild(View, android.view.ActionMode.Callback)
+ * @see #startActionModeForChild(View, android.view.ActionMode.Callback, int)
+ */
+ private static final ActionMode SENTINEL_ACTION_MODE = new ActionMode() {
+ @Override
+ public void setTitle(CharSequence title) {}
+
+ @Override
+ public void setTitle(int resId) {}
+
+ @Override
+ public void setSubtitle(CharSequence subtitle) {}
+
+ @Override
+ public void setSubtitle(int resId) {}
+
+ @Override
+ public void setCustomView(View view) {}
+
+ @Override
+ public void invalidate() {}
+
+ @Override
+ public void finish() {}
+
+ @Override
+ public Menu getMenu() {
+ return null;
+ }
+
+ @Override
+ public CharSequence getTitle() {
+ return null;
+ }
+
+ @Override
+ public CharSequence getSubtitle() {
+ return null;
+ }
+
+ @Override
+ public View getCustomView() {
+ return null;
+ }
+
+ @Override
+ public MenuInflater getMenuInflater() {
+ return null;
+ }
+ };
+
public ViewGroup(Context context) {
this(context, null);
}
@@ -694,8 +768,49 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
/**
* {@inheritDoc}
*/
+ @Override
public ActionMode startActionModeForChild(View originalView, ActionMode.Callback callback) {
- return mParent != null ? mParent.startActionModeForChild(originalView, callback) : null;
+ if ((mGroupFlags & FLAG_START_ACTION_MODE_FOR_CHILD_IS_TYPED) == 0) {
+ // This is the original call.
+ try {
+ mGroupFlags |= FLAG_START_ACTION_MODE_FOR_CHILD_IS_NOT_TYPED;
+ return startActionModeForChild(originalView, callback, ActionMode.TYPE_PRIMARY);
+ } finally {
+ mGroupFlags &= ~FLAG_START_ACTION_MODE_FOR_CHILD_IS_NOT_TYPED;
+ }
+ } else {
+ // We are being called from the new method with type.
+ return SENTINEL_ACTION_MODE;
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public ActionMode startActionModeForChild(
+ View originalView, ActionMode.Callback callback, int type) {
+ if ((mGroupFlags & FLAG_START_ACTION_MODE_FOR_CHILD_IS_NOT_TYPED) == 0) {
+ ActionMode mode;
+ try {
+ mGroupFlags |= FLAG_START_ACTION_MODE_FOR_CHILD_IS_TYPED;
+ mode = startActionModeForChild(originalView, callback);
+ } finally {
+ mGroupFlags &= ~FLAG_START_ACTION_MODE_FOR_CHILD_IS_TYPED;
+ }
+ if (mode != SENTINEL_ACTION_MODE) {
+ return mode;
+ }
+ }
+ if (mParent != null) {
+ try {
+ return mParent.startActionModeForChild(originalView, callback, type);
+ } catch (AbstractMethodError ame) {
+ // Custom view parents might not implement this method.
+ return mParent.startActionModeForChild(originalView, callback);
+ }
+ }
+ return null;
}
/**
diff --git a/core/java/android/view/ViewParent.java b/core/java/android/view/ViewParent.java
index 035871d..15b86d1 100644
--- a/core/java/android/view/ViewParent.java
+++ b/core/java/android/view/ViewParent.java
@@ -190,7 +190,8 @@ public interface ViewParent {
public void createContextMenu(ContextMenu menu);
/**
- * Start an action mode for the specified view.
+ * Start an action mode for the specified view with the default type
+ * {@link ActionMode#TYPE_PRIMARY}.
*
* <p>In most cases, a subclass does not need to override this. However, if the
* subclass is added directly to the window manager (for example,
@@ -200,17 +201,35 @@ public interface ViewParent {
* @param originalView The source view where the action mode was first invoked
* @param callback The callback that will handle lifecycle events for the action mode
* @return The new action mode if it was started, null otherwise
+ *
+ * @see #startActionModeForChild(View, android.view.ActionMode.Callback, int)
*/
public ActionMode startActionModeForChild(View originalView, ActionMode.Callback callback);
/**
+ * Start an action mode of a specific type for the specified view.
+ *
+ * <p>In most cases, a subclass does not need to override this. However, if the
+ * subclass is added directly to the window manager (for example,
+ * {@link ViewManager#addView(View, android.view.ViewGroup.LayoutParams)})
+ * then it should override this and start the action mode.</p>
+ *
+ * @param originalView The source view where the action mode was first invoked
+ * @param callback The callback that will handle lifecycle events for the action mode
+ * @param type One of {@link ActionMode#TYPE_PRIMARY} or {@link ActionMode#TYPE_FLOATING}.
+ * @return The new action mode if it was started, null otherwise
+ */
+ public ActionMode startActionModeForChild(
+ View originalView, ActionMode.Callback callback, int type);
+
+ /**
* This method is called on the parent when a child's drawable state
* has changed.
*
* @param child The child whose drawable state has changed.
*/
public void childDrawableStateChanged(View child);
-
+
/**
* Called when a child does not want this parent and its ancestors to
* intercept touch events with
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index f970e88..1473806 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -6227,6 +6227,12 @@ public final class ViewRootImpl implements ViewParent,
}
@Override
+ public ActionMode startActionModeForChild(
+ View originalView, ActionMode.Callback callback, int type) {
+ return null;
+ }
+
+ @Override
public void createContextMenu(ContextMenu menu) {
}
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index 744f665..f36fd5a 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -416,7 +416,9 @@ public abstract class Window {
* Called when an action mode is being started for this window. Gives the
* callback an opportunity to handle the action mode in its own unique and
* beautiful way. If this method returns null the system can choose a way
- * to present the mode or choose not to start the mode at all.
+ * to present the mode or choose not to start the mode at all. This is equivalent
+ * to {@link #onWindowStartingActionMode(android.view.ActionMode.Callback, int)}
+ * with type {@link ActionMode#TYPE_PRIMARY}.
*
* @param callback Callback to control the lifecycle of this action mode
* @return The ActionMode that was started, or null if the system should present it
@@ -425,6 +427,19 @@ public abstract class Window {
public ActionMode onWindowStartingActionMode(ActionMode.Callback callback);
/**
+ * Called when an action mode is being started for this window. Gives the
+ * callback an opportunity to handle the action mode in its own unique and
+ * beautiful way. If this method returns null the system can choose a way
+ * to present the mode or choose not to start the mode at all.
+ *
+ * @param callback Callback to control the lifecycle of this action mode
+ * @param type One of {@link ActionMode#TYPE_PRIMARY} or {@link ActionMode#TYPE_FLOATING}.
+ * @return The ActionMode that was started, or null if the system should present it
+ */
+ @Nullable
+ public ActionMode onWindowStartingActionMode(ActionMode.Callback callback, int type);
+
+ /**
* Called when an action mode has been started. The appropriate mode callback
* method will have already been invoked.
*
diff --git a/core/java/android/view/WindowCallbackWrapper.java b/core/java/android/view/WindowCallbackWrapper.java
index 35a6a76..979ee95 100644
--- a/core/java/android/view/WindowCallbackWrapper.java
+++ b/core/java/android/view/WindowCallbackWrapper.java
@@ -132,6 +132,11 @@ public class WindowCallbackWrapper implements Window.Callback {
}
@Override
+ public ActionMode onWindowStartingActionMode(ActionMode.Callback callback, int type) {
+ return mWrapped.onWindowStartingActionMode(callback, type);
+ }
+
+ @Override
public void onActionModeStarted(ActionMode mode) {
mWrapped.onActionModeStarted(mode);
}
diff --git a/core/java/com/android/internal/app/WindowDecorActionBar.java b/core/java/com/android/internal/app/WindowDecorActionBar.java
index 70a0b6b..2bf02f1 100644
--- a/core/java/com/android/internal/app/WindowDecorActionBar.java
+++ b/core/java/com/android/internal/app/WindowDecorActionBar.java
@@ -493,21 +493,15 @@ public class WindowDecorActionBar extends ActionBar implements
}
public ActionMode startActionMode(ActionMode.Callback callback) {
- return new ActionModeWrapper(mContext, callback, new ActionModeProviderImpl());
- }
-
- private class ActionModeProviderImpl implements ActionModeWrapper.ActionModeProvider {
-
- @Override
- public ActionMode createActionMode(Callback callback, MenuBuilder menuBuilder) {
- if (mActionMode != null) {
- mActionMode.finish();
- }
+ if (mActionMode != null) {
+ mActionMode.finish();
+ }
- mOverlayLayout.setHideOnContentScrollEnabled(false);
- mContextView.killMode();
- ActionModeImpl mode = new ActionModeImpl(
- mContextView.getContext(), callback, menuBuilder);
+ mOverlayLayout.setHideOnContentScrollEnabled(false);
+ mContextView.killMode();
+ ActionModeImpl mode = new ActionModeImpl(mContextView.getContext(), callback);
+ if (mode.dispatchOnCreate()) {
+ mode.invalidate();
mContextView.initForMode(mode);
animateToMode(true);
if (mSplitView != null && mContextDisplayMode == CONTEXT_DISPLAY_SPLIT) {
@@ -523,6 +517,7 @@ public class WindowDecorActionBar extends ActionBar implements
mActionMode = mode;
return mode;
}
+ return null;
}
private void configureTab(Tab tab, int position) {
@@ -951,13 +946,11 @@ public class WindowDecorActionBar extends ActionBar implements
private WeakReference<View> mCustomView;
public ActionModeImpl(
- Context context, ActionMode.Callback callback, MenuBuilder menuBuilder) {
+ Context context, ActionMode.Callback callback) {
mActionModeContext = context;
mCallback = callback;
- mMenu = menuBuilder == null
- ? new MenuBuilder(context)
- .setDefaultShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM)
- : menuBuilder;
+ mMenu = new MenuBuilder(context)
+ .setDefaultShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
mMenu.setCallback(this);
}
@@ -1019,6 +1012,15 @@ public class WindowDecorActionBar extends ActionBar implements
}
}
+ public boolean dispatchOnCreate() {
+ mMenu.stopDispatchingItemsChanged();
+ try {
+ return mCallback.onCreateActionMode(this, mMenu);
+ } finally {
+ mMenu.startDispatchingItemsChanged();
+ }
+ }
+
@Override
public void setCustomView(View view) {
mContextView.setCustomView(view);
diff --git a/core/java/com/android/internal/view/StandaloneActionMode.java b/core/java/com/android/internal/view/StandaloneActionMode.java
index 2812b77..e6d911c 100644
--- a/core/java/com/android/internal/view/StandaloneActionMode.java
+++ b/core/java/com/android/internal/view/StandaloneActionMode.java
@@ -20,7 +20,6 @@ import com.android.internal.view.menu.MenuPopupHelper;
import com.android.internal.view.menu.SubMenuBuilder;
import com.android.internal.widget.ActionBarContextView;
-import android.annotation.Nullable;
import android.content.Context;
import android.view.ActionMode;
import android.view.Menu;
@@ -42,14 +41,12 @@ public class StandaloneActionMode extends ActionMode implements MenuBuilder.Call
private MenuBuilder mMenu;
public StandaloneActionMode(Context context, ActionBarContextView view,
- ActionMode.Callback callback, boolean isFocusable, @Nullable MenuBuilder menuBuilder) {
+ ActionMode.Callback callback, boolean isFocusable) {
mContext = context;
mContextView = view;
mCallback = callback;
- mMenu = (menuBuilder != null)
- ? menuBuilder
- : new MenuBuilder(view.getContext()).setDefaultShowAsAction(
+ mMenu = new MenuBuilder(view.getContext()).setDefaultShowAsAction(
MenuItem.SHOW_AS_ACTION_IF_ROOM);
mMenu.setCallback(this);
mFocusable = isFocusable;
diff --git a/core/java/com/android/internal/widget/ActionBarContainer.java b/core/java/com/android/internal/widget/ActionBarContainer.java
index eaf0bbc..a5efa82 100644
--- a/core/java/com/android/internal/widget/ActionBarContainer.java
+++ b/core/java/com/android/internal/widget/ActionBarContainer.java
@@ -256,6 +256,15 @@ public class ActionBarContainer extends FrameLayout {
return null;
}
+ @Override
+ public ActionMode startActionModeForChild(
+ View child, ActionMode.Callback callback, int type) {
+ if (type != ActionMode.TYPE_PRIMARY) {
+ return super.startActionModeForChild(child, callback, type);
+ }
+ return null;
+ }
+
private static boolean isCollapsed(View view) {
return view == null || view.getVisibility() == GONE || view.getMeasuredHeight() == 0;
}
diff --git a/tools/layoutlib/bridge/src/android/view/WindowCallback.java b/tools/layoutlib/bridge/src/android/view/WindowCallback.java
index 78242a8..823b247 100644
--- a/tools/layoutlib/bridge/src/android/view/WindowCallback.java
+++ b/tools/layoutlib/bridge/src/android/view/WindowCallback.java
@@ -120,6 +120,11 @@ public class WindowCallback implements Window.Callback {
}
@Override
+ public ActionMode onWindowStartingActionMode(Callback callback, int type) {
+ return null;
+ }
+
+ @Override
public void onActionModeStarted(ActionMode mode) {
}