Loading core/java/android/view/selectiontoolbar/SelectionToolbarManager.java +23 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ import android.annotation.NonNull; import android.annotation.SystemService; import android.content.Context; import android.os.RemoteException; import android.provider.DeviceConfig; import java.util.Objects; Loading @@ -40,6 +41,11 @@ public final class SelectionToolbarManager { */ public static final String LOG_TAG = "SelectionToolbar"; /** * Whether system selection toolbar is enabled. */ private static final String REMOTE_SELECTION_TOOLBAR_ENABLED = "remote_selection_toolbar_enabled"; @NonNull private final Context mContext; Loading Loading @@ -86,4 +92,21 @@ public final class SelectionToolbarManager { throw e.rethrowFromSystemServer(); } } private boolean isRemoteSelectionToolbarEnabled() { return DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_SELECTION_TOOLBAR, REMOTE_SELECTION_TOOLBAR_ENABLED, false); } /** * Returns {@code true} if remote render selection toolbar enabled, otherwise * returns {@code false}. */ public static boolean isRemoteSelectionToolbarEnabled(Context context) { SelectionToolbarManager manager = context.getSystemService(SelectionToolbarManager.class); if (manager != null) { return manager.isRemoteSelectionToolbarEnabled(); } return false; } } core/java/com/android/internal/policy/DecorView.java +1 −1 Original line number Diff line number Diff line Loading @@ -121,7 +121,7 @@ import com.android.internal.view.menu.MenuHelper; import com.android.internal.widget.ActionBarContextView; import com.android.internal.widget.BackgroundFallback; import com.android.internal.widget.DecorCaptionView; import com.android.internal.widget.FloatingToolbar; import com.android.internal.widget.floatingtoolbar.FloatingToolbar; import java.util.List; import java.util.function.Consumer; Loading core/java/com/android/internal/view/FloatingActionMode.java +1 −1 Original line number Diff line number Diff line Loading @@ -33,7 +33,7 @@ import android.widget.PopupWindow; import com.android.internal.R; import com.android.internal.view.menu.MenuBuilder; import com.android.internal.widget.FloatingToolbar; import com.android.internal.widget.floatingtoolbar.FloatingToolbar; import java.util.Arrays; import java.util.Objects; Loading core/java/com/android/internal/widget/FloatingToolbar.java→core/java/com/android/internal/widget/floatingtoolbar/FloatingToolbar.java +5 −25 Original line number Diff line number Diff line Loading @@ -14,7 +14,7 @@ * limitations under the License. */ package com.android.internal.widget; package com.android.internal.widget.floatingtoolbar; import android.annotation.Nullable; import android.graphics.Rect; Loading Loading @@ -50,14 +50,10 @@ public final class FloatingToolbar { private final FloatingToolbarPopup mPopup; private final Rect mContentRect = new Rect(); private final Rect mPreviousContentRect = new Rect(); private Menu mMenu; private MenuItem.OnMenuItemClickListener mMenuItemClickListener = NO_OP_MENUITEM_CLICK_LISTENER; private int mSuggestedWidth; private boolean mWidthChanged = true; private final OnLayoutChangeListener mOrientationChangeHandler = new OnLayoutChangeListener() { private final Rect mNewRect = new Rect(); Loading @@ -71,7 +67,7 @@ public final class FloatingToolbar { mNewRect.set(newLeft, newRight, newTop, newBottom); mOldRect.set(oldLeft, oldRight, oldTop, oldBottom); if (mPopup.isShowing() && !mNewRect.equals(mOldRect)) { mWidthChanged = true; mPopup.setWidthChanged(true); updateLayout(); } } Loading Loading @@ -114,7 +110,7 @@ public final class FloatingToolbar { // TODO(b/65172902): Pass context in constructor when DecorView (and other callers) // supports multi-display. mWindow = Objects.requireNonNull(window); mPopup = new FloatingToolbarPopup(window.getContext(), window.getDecorView()); mPopup = FloatingToolbarPopup.createInstance(window.getContext(), window.getDecorView()); } /** Loading Loading @@ -159,11 +155,7 @@ public final class FloatingToolbar { * toolbar. */ public FloatingToolbar setSuggestedWidth(int suggestedWidth) { // Check if there's been a substantial width spec change. int difference = Math.abs(suggestedWidth - mSuggestedWidth); mWidthChanged = difference > (mSuggestedWidth * 0.2); mSuggestedWidth = suggestedWidth; mPopup.setSuggestedWidth(suggestedWidth); return this; } Loading Loading @@ -232,19 +224,7 @@ public final class FloatingToolbar { private void doShow() { List<MenuItem> menuItems = getVisibleAndEnabledMenuItems(mMenu); menuItems.sort(mMenuItemComparator); if (mPopup.isLayoutRequired(menuItems) || mWidthChanged) { mPopup.dismiss(); mPopup.layoutMenuItems(menuItems, mMenuItemClickListener, mSuggestedWidth); } else { mPopup.updateMenuItems(menuItems, mMenuItemClickListener); } if (!mPopup.isShowing()) { mPopup.show(mContentRect); } else if (!mPreviousContentRect.equals(mContentRect)) { mPopup.updateCoordinates(mContentRect); } mWidthChanged = false; mPreviousContentRect.set(mContentRect); mPopup.show(menuItems, mMenuItemClickListener, mContentRect); } /** Loading core/java/com/android/internal/widget/floatingtoolbar/FloatingToolbarPopup.java 0 → 100644 +100 −0 Original line number Diff line number Diff line /* * Copyright (C) 2021 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.internal.widget.floatingtoolbar; import android.content.Context; import android.graphics.Rect; import android.view.MenuItem; import android.view.View; import android.view.selectiontoolbar.SelectionToolbarManager; import android.widget.PopupWindow; import java.util.List; /** * A popup window used by the {@link FloatingToolbar} to render menu items. * */ public interface FloatingToolbarPopup { /** * Sets the suggested dp width of this floating toolbar. * The actual width will be about this size but there are no guarantees that it will be exactly * the suggested width. */ void setSuggestedWidth(int suggestedWidth); /** * Sets if the floating toolbar width changed. */ void setWidthChanged(boolean widthChanged); /** * Shows this popup at the specified coordinates. * The specified coordinates may be adjusted to make sure the popup is entirely on-screen. */ void show(List<MenuItem> menuItems, MenuItem.OnMenuItemClickListener menuItemClickListener, Rect contentRect); /** * Gets rid of this popup. If the popup isn't currently showing, this will be a no-op. */ void dismiss(); /** * Hides this popup. This is a no-op if this popup is not showing. * Use {@link #isHidden()} to distinguish between a hidden and a dismissed popup. */ void hide(); /** * Returns {@code true} if this popup is currently showing. {@code false} otherwise. */ boolean isShowing(); /** * Returns {@code true} if this popup is currently hidden. {@code false} otherwise. */ boolean isHidden(); /** * Makes this toolbar "outside touchable" and sets the onDismissListener. * * @param outsideTouchable if true, the popup will be made "outside touchable" and * "non focusable". The reverse will happen if false. * @param onDismiss * * @return true if the "outsideTouchable" setting was modified. Otherwise returns false * * @see PopupWindow#setOutsideTouchable(boolean) * @see PopupWindow#setFocusable(boolean) * @see PopupWindow.OnDismissListener */ boolean setOutsideTouchable(boolean outsideTouchable, PopupWindow.OnDismissListener onDismiss); /** * Returns {@link RemoteFloatingToolbarPopup} implementation if the system selection toolbar * enabled, otherwise returns {@link LocalFloatingToolbarPopup} implementation. */ static FloatingToolbarPopup createInstance(Context context, View parent) { boolean enabled = SelectionToolbarManager.isRemoteSelectionToolbarEnabled(context); return enabled ? new RemoteFloatingToolbarPopup(context, parent) : new LocalFloatingToolbarPopup(context, parent); } } Loading
core/java/android/view/selectiontoolbar/SelectionToolbarManager.java +23 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ import android.annotation.NonNull; import android.annotation.SystemService; import android.content.Context; import android.os.RemoteException; import android.provider.DeviceConfig; import java.util.Objects; Loading @@ -40,6 +41,11 @@ public final class SelectionToolbarManager { */ public static final String LOG_TAG = "SelectionToolbar"; /** * Whether system selection toolbar is enabled. */ private static final String REMOTE_SELECTION_TOOLBAR_ENABLED = "remote_selection_toolbar_enabled"; @NonNull private final Context mContext; Loading Loading @@ -86,4 +92,21 @@ public final class SelectionToolbarManager { throw e.rethrowFromSystemServer(); } } private boolean isRemoteSelectionToolbarEnabled() { return DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_SELECTION_TOOLBAR, REMOTE_SELECTION_TOOLBAR_ENABLED, false); } /** * Returns {@code true} if remote render selection toolbar enabled, otherwise * returns {@code false}. */ public static boolean isRemoteSelectionToolbarEnabled(Context context) { SelectionToolbarManager manager = context.getSystemService(SelectionToolbarManager.class); if (manager != null) { return manager.isRemoteSelectionToolbarEnabled(); } return false; } }
core/java/com/android/internal/policy/DecorView.java +1 −1 Original line number Diff line number Diff line Loading @@ -121,7 +121,7 @@ import com.android.internal.view.menu.MenuHelper; import com.android.internal.widget.ActionBarContextView; import com.android.internal.widget.BackgroundFallback; import com.android.internal.widget.DecorCaptionView; import com.android.internal.widget.FloatingToolbar; import com.android.internal.widget.floatingtoolbar.FloatingToolbar; import java.util.List; import java.util.function.Consumer; Loading
core/java/com/android/internal/view/FloatingActionMode.java +1 −1 Original line number Diff line number Diff line Loading @@ -33,7 +33,7 @@ import android.widget.PopupWindow; import com.android.internal.R; import com.android.internal.view.menu.MenuBuilder; import com.android.internal.widget.FloatingToolbar; import com.android.internal.widget.floatingtoolbar.FloatingToolbar; import java.util.Arrays; import java.util.Objects; Loading
core/java/com/android/internal/widget/FloatingToolbar.java→core/java/com/android/internal/widget/floatingtoolbar/FloatingToolbar.java +5 −25 Original line number Diff line number Diff line Loading @@ -14,7 +14,7 @@ * limitations under the License. */ package com.android.internal.widget; package com.android.internal.widget.floatingtoolbar; import android.annotation.Nullable; import android.graphics.Rect; Loading Loading @@ -50,14 +50,10 @@ public final class FloatingToolbar { private final FloatingToolbarPopup mPopup; private final Rect mContentRect = new Rect(); private final Rect mPreviousContentRect = new Rect(); private Menu mMenu; private MenuItem.OnMenuItemClickListener mMenuItemClickListener = NO_OP_MENUITEM_CLICK_LISTENER; private int mSuggestedWidth; private boolean mWidthChanged = true; private final OnLayoutChangeListener mOrientationChangeHandler = new OnLayoutChangeListener() { private final Rect mNewRect = new Rect(); Loading @@ -71,7 +67,7 @@ public final class FloatingToolbar { mNewRect.set(newLeft, newRight, newTop, newBottom); mOldRect.set(oldLeft, oldRight, oldTop, oldBottom); if (mPopup.isShowing() && !mNewRect.equals(mOldRect)) { mWidthChanged = true; mPopup.setWidthChanged(true); updateLayout(); } } Loading Loading @@ -114,7 +110,7 @@ public final class FloatingToolbar { // TODO(b/65172902): Pass context in constructor when DecorView (and other callers) // supports multi-display. mWindow = Objects.requireNonNull(window); mPopup = new FloatingToolbarPopup(window.getContext(), window.getDecorView()); mPopup = FloatingToolbarPopup.createInstance(window.getContext(), window.getDecorView()); } /** Loading Loading @@ -159,11 +155,7 @@ public final class FloatingToolbar { * toolbar. */ public FloatingToolbar setSuggestedWidth(int suggestedWidth) { // Check if there's been a substantial width spec change. int difference = Math.abs(suggestedWidth - mSuggestedWidth); mWidthChanged = difference > (mSuggestedWidth * 0.2); mSuggestedWidth = suggestedWidth; mPopup.setSuggestedWidth(suggestedWidth); return this; } Loading Loading @@ -232,19 +224,7 @@ public final class FloatingToolbar { private void doShow() { List<MenuItem> menuItems = getVisibleAndEnabledMenuItems(mMenu); menuItems.sort(mMenuItemComparator); if (mPopup.isLayoutRequired(menuItems) || mWidthChanged) { mPopup.dismiss(); mPopup.layoutMenuItems(menuItems, mMenuItemClickListener, mSuggestedWidth); } else { mPopup.updateMenuItems(menuItems, mMenuItemClickListener); } if (!mPopup.isShowing()) { mPopup.show(mContentRect); } else if (!mPreviousContentRect.equals(mContentRect)) { mPopup.updateCoordinates(mContentRect); } mWidthChanged = false; mPreviousContentRect.set(mContentRect); mPopup.show(menuItems, mMenuItemClickListener, mContentRect); } /** Loading
core/java/com/android/internal/widget/floatingtoolbar/FloatingToolbarPopup.java 0 → 100644 +100 −0 Original line number Diff line number Diff line /* * Copyright (C) 2021 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.internal.widget.floatingtoolbar; import android.content.Context; import android.graphics.Rect; import android.view.MenuItem; import android.view.View; import android.view.selectiontoolbar.SelectionToolbarManager; import android.widget.PopupWindow; import java.util.List; /** * A popup window used by the {@link FloatingToolbar} to render menu items. * */ public interface FloatingToolbarPopup { /** * Sets the suggested dp width of this floating toolbar. * The actual width will be about this size but there are no guarantees that it will be exactly * the suggested width. */ void setSuggestedWidth(int suggestedWidth); /** * Sets if the floating toolbar width changed. */ void setWidthChanged(boolean widthChanged); /** * Shows this popup at the specified coordinates. * The specified coordinates may be adjusted to make sure the popup is entirely on-screen. */ void show(List<MenuItem> menuItems, MenuItem.OnMenuItemClickListener menuItemClickListener, Rect contentRect); /** * Gets rid of this popup. If the popup isn't currently showing, this will be a no-op. */ void dismiss(); /** * Hides this popup. This is a no-op if this popup is not showing. * Use {@link #isHidden()} to distinguish between a hidden and a dismissed popup. */ void hide(); /** * Returns {@code true} if this popup is currently showing. {@code false} otherwise. */ boolean isShowing(); /** * Returns {@code true} if this popup is currently hidden. {@code false} otherwise. */ boolean isHidden(); /** * Makes this toolbar "outside touchable" and sets the onDismissListener. * * @param outsideTouchable if true, the popup will be made "outside touchable" and * "non focusable". The reverse will happen if false. * @param onDismiss * * @return true if the "outsideTouchable" setting was modified. Otherwise returns false * * @see PopupWindow#setOutsideTouchable(boolean) * @see PopupWindow#setFocusable(boolean) * @see PopupWindow.OnDismissListener */ boolean setOutsideTouchable(boolean outsideTouchable, PopupWindow.OnDismissListener onDismiss); /** * Returns {@link RemoteFloatingToolbarPopup} implementation if the system selection toolbar * enabled, otherwise returns {@link LocalFloatingToolbarPopup} implementation. */ static FloatingToolbarPopup createInstance(Context context, View parent) { boolean enabled = SelectionToolbarManager.isRemoteSelectionToolbarEnabled(context); return enabled ? new RemoteFloatingToolbarPopup(context, parent) : new LocalFloatingToolbarPopup(context, parent); } }