From: uazo Date: Sun, 7 Jan 2024 15:46:46 +0000 Subject: Customize selection popup Adds options related to the handling of pop-up selections: Opens tabs in foreground, Move web search to the top of items, Web search in tab group and Enable smart text selection License: GPL-2.0-or-later - https://spdx.org/licenses/GPL-2.0-or-later.html --- .../browser/ChromeActionModeHandler.java | 4 +- .../chrome/browser/ChromeTabbedActivity.java | 15 +- ...ActivityTabWebContentsDelegateAndroid.java | 10 +- .../compositor/layouts/LayoutManagerImpl.java | 8 ++ .../tab/TabContextMenuItemDelegate.java | 7 +- .../chrome/browser/ui/RootUiCoordinator.java | 8 +- .../Customize-selection-popup.grdp | 34 +++++ .../res/xml/accessibility_preferences.xml | 24 ++++ .../selection/SelectActionMenuHelper.java | 129 ++++++++++++------ .../selection/SmartSelectionClient.java | 4 + 10 files changed, 192 insertions(+), 51 deletions(-) create mode 100644 chrome/browser/ui/android/strings/cromite_android_chrome_strings_grd/Customize-selection-popup.grdp diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeActionModeHandler.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeActionModeHandler.java --- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeActionModeHandler.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeActionModeHandler.java @@ -166,9 +166,7 @@ public class ChromeActionModeHandler { | ActionModeCallbackHelper.MENU_ITEM_SHARE; // Disable options that expose additional Chrome functionality prior to the FRE being // completed (i.e. creation of a new tab). - if (FirstRunStatus.getFirstRunFlowComplete() && mShowWebSearch) { - allowedActionModes |= ActionModeCallbackHelper.MENU_ITEM_WEB_SEARCH; - } + allowedActionModes |= ActionModeCallbackHelper.MENU_ITEM_WEB_SEARCH; mHelper.setAllowedMenuItems(allowedActionModes); mHelper.onCreateActionMode(mode, menu); diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java --- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java @@ -803,10 +803,17 @@ public class ChromeTabbedActivity extends ChromeActivity { @TabLaunchType int type, @TabCreationState int creationState, boolean markedForSelection) { - if (type == TabLaunchType.FROM_LONGPRESS_BACKGROUND - || type == TabLaunchType.FROM_LONGPRESS_BACKGROUND_IN_GROUP - || (type == TabLaunchType.FROM_RECENT_TABS - && !DeviceClassManager.enableAnimations())) { + boolean selectionPopupTabsForeground = + ContextUtils.getAppSharedPreferences().getBoolean( + "selection_popup_tabs_foreground", false); + boolean showToast = type == TabLaunchType.FROM_RECENT_TABS + && !DeviceClassManager.enableAnimations(); + if (!showToast && !selectionPopupTabsForeground) { + showToast = !DeviceClassManager.enableAnimations() && + (type == TabLaunchType.FROM_LONGPRESS_BACKGROUND + || type == TabLaunchType.FROM_LONGPRESS_BACKGROUND_IN_GROUP); + } + if (showToast) { Toast.makeText( ChromeTabbedActivity.this, R.string.open_in_new_tab_toast, diff --git a/chrome/android/java/src/org/chromium/chrome/browser/app/tab_activity_glue/ActivityTabWebContentsDelegateAndroid.java b/chrome/android/java/src/org/chromium/chrome/browser/app/tab_activity_glue/ActivityTabWebContentsDelegateAndroid.java --- a/chrome/android/java/src/org/chromium/chrome/browser/app/tab_activity_glue/ActivityTabWebContentsDelegateAndroid.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/app/tab_activity_glue/ActivityTabWebContentsDelegateAndroid.java @@ -202,6 +202,14 @@ public class ActivityTabWebContentsDelegateAndroid extends TabWebContentsDelegat // Skip opening a new Tab if it doesn't make sense. if (mTab.isClosing()) return false; + int tabLaunchType = TabLaunchType.FROM_LONGPRESS_FOREGROUND; + boolean selectionPopupTabsForeground = + ContextUtils.getAppSharedPreferences().getBoolean( + "selection_popup_tabs_foreground", false); + if (selectionPopupTabsForeground) { + tabLaunchType = TabLaunchType.FROM_LONGPRESS_BACKGROUND_IN_GROUP; + } + boolean openingPopup = PopupCreator.arePopupsEnabled(mActivity) && (disposition == WindowOpenDisposition.NEW_POPUP); @@ -225,7 +233,7 @@ public class ActivityTabWebContentsDelegateAndroid extends TabWebContentsDelegat tabCreator.createTabWithWebContents( mTab, webContents, - TabLaunchType.FROM_LONGPRESS_FOREGROUND, + tabLaunchType, url, !openingPopup && !willReparentTab); if (tab == null) return false; diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerImpl.java --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerImpl.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerImpl.java @@ -18,6 +18,7 @@ import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; import org.chromium.base.Callback; +import org.chromium.base.ContextUtils; import org.chromium.base.ObserverList; import org.chromium.base.TraceEvent; import org.chromium.base.supplier.ObservableSupplier; @@ -246,6 +247,13 @@ public class LayoutManagerImpl != TabLaunchType .FROM_COLLABORATION_BACKGROUND_IN_GROUP) || (!getTabModelSelector().isIncognitoSelected() && incognito); + boolean selectionPopupTabsForeground = + ContextUtils.getAppSharedPreferences().getBoolean( + "selection_popup_tabs_foreground", false); + if (selectionPopupTabsForeground) { + willBeSelected = launchType != TabLaunchType.FROM_RESTORE_TABS_UI + || (!getTabModelSelector().isIncognitoSelected() && incognito); + } float lastTapX = LocalizationUtils.isLayoutRtl() ? mHost.getWidth() * mPxToDp : 0.f; float lastTapY = 0.f; if (launchType != TabLaunchType.FROM_CHROME_UI) { diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabContextMenuItemDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabContextMenuItemDelegate.java --- a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabContextMenuItemDelegate.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabContextMenuItemDelegate.java @@ -372,8 +372,13 @@ public class TabContextMenuItemDelegate implements ContextMenuItemDelegate { public void onOpenImageInNewTab(GURL url, Referrer referrer) { LoadUrlParams loadUrlParams = new LoadUrlParams(url.getSpec()); loadUrlParams.setReferrer(referrer); + @TabLaunchType int type = TabLaunchType.FROM_LONGPRESS_BACKGROUND; + if (ContextUtils.getAppSharedPreferences().getBoolean( + "selection_popup_tabs_foreground", false)) { + type = TabLaunchType.FROM_LONGPRESS_BACKGROUND_IN_GROUP; + } mTabModelSelector.openNewTab( - loadUrlParams, TabLaunchType.FROM_LONGPRESS_BACKGROUND, mTab, isIncognito()); + loadUrlParams, type, mTab, isIncognito()); } /** diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ui/RootUiCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/ui/RootUiCoordinator.java --- a/chrome/android/java/src/org/chromium/chrome/browser/ui/RootUiCoordinator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ui/RootUiCoordinator.java @@ -29,6 +29,7 @@ import androidx.core.view.WindowInsetsCompat; import org.chromium.base.BuildInfo; import org.chromium.base.Callback; import org.chromium.base.CallbackController; +import org.chromium.base.ContextUtils; import org.chromium.base.TraceEvent; import org.chromium.base.lifetime.Destroyable; import org.chromium.base.metrics.RecordUserAction; @@ -795,11 +796,16 @@ public class RootUiCoordinator TrackerFactory.getTrackerForProfile(tab.getProfile()) .notifyEvent(EventConstants.WEB_SEARCH_PERFORMED); + boolean selection_popup_web_search_to_group = + ContextUtils.getAppSharedPreferences().getBoolean( + "selection_popup_web_search_to_group", false); + mTabModelSelectorSupplier .get() .openNewTab( generateUrlParamsForSearch(tab, query), - TabLaunchType.FROM_LONGPRESS_FOREGROUND, + selection_popup_web_search_to_group ? TabLaunchType.FROM_LONGPRESS_BACKGROUND_IN_GROUP + : TabLaunchType.FROM_LONGPRESS_FOREGROUND, tab, tab.isIncognito()); }, diff --git a/chrome/browser/ui/android/strings/cromite_android_chrome_strings_grd/Customize-selection-popup.grdp b/chrome/browser/ui/android/strings/cromite_android_chrome_strings_grd/Customize-selection-popup.grdp new file mode 100644 --- /dev/null +++ b/chrome/browser/ui/android/strings/cromite_android_chrome_strings_grd/Customize-selection-popup.grdp @@ -0,0 +1,34 @@ + + + + Customize selection popup + + + + Opens tabs in foreground + + + Immediately brings new open tabs to the foreground + + + + Move web search to the top of items + + + Web search as first choice + + + + Web search in tab group + + + Opens the search in a tab in the current group, if deactivated opens a new group + + + + Enable smart text selection + + + Smart Text selection automatically augments the selected boundaries and classifies the selected text based on the context by sending selection together with its surrounding text + + diff --git a/components/browser_ui/accessibility/android/java/res/xml/accessibility_preferences.xml b/components/browser_ui/accessibility/android/java/res/xml/accessibility_preferences.xml --- a/components/browser_ui/accessibility/android/java/res/xml/accessibility_preferences.xml +++ b/components/browser_ui/accessibility/android/java/res/xml/accessibility_preferences.xml @@ -79,4 +79,28 @@ found in the LICENSE file. android:key="disable_toolbar_swipeup" android:title="@string/disable_toolbar_swipe_up" /> + + + + + + + + + + diff --git a/content/public/android/java/src/org/chromium/content/browser/selection/SelectActionMenuHelper.java b/content/public/android/java/src/org/chromium/content/browser/selection/SelectActionMenuHelper.java --- a/content/public/android/java/src/org/chromium/content/browser/selection/SelectActionMenuHelper.java +++ b/content/public/android/java/src/org/chromium/content/browser/selection/SelectActionMenuHelper.java @@ -27,6 +27,7 @@ import androidx.core.content.ContextCompat; import org.chromium.base.ApiCompatibilityUtils; import org.chromium.base.ContextUtils; import org.chromium.base.Log; +import org.chromium.base.ContextUtils; import org.chromium.base.PackageManagerUtils; import org.chromium.base.StrictModeContext; import org.chromium.build.annotations.NullMarked; @@ -54,38 +55,84 @@ import java.util.TreeSet; public class SelectActionMenuHelper { private static final String TAG = "SelectActionMenu"; // 20 char limit. - @Retention(RetentionPolicy.SOURCE) - @IntDef({ - GroupItemOrder.ASSIST_ITEMS, - GroupItemOrder.DEFAULT_ITEMS, - GroupItemOrder.SECONDARY_ASSIST_ITEMS, - GroupItemOrder.TEXT_PROCESSING_ITEMS - }) - public @interface GroupItemOrder { - int ASSIST_ITEMS = 1; - int DEFAULT_ITEMS = 2; - int SECONDARY_ASSIST_ITEMS = 3; - int TEXT_PROCESSING_ITEMS = 4; + private static class GroupItemOrderChromium { + static int CHROMIUM_ASSIST_ITEMS = 1; + static int CHROMIUM_DEFAULT_ITEMS = 2; + static int CHROMIUM_SECONDARY_ASSIST_ITEMS = 3; + static int CHROMIUM_TEXT_PROCESSING_ITEMS = 4; + + static int CROMITE_DEFAULT_ITEMS = 1; + static int CROMITE_ASSIST_ITEMS = 2; + static int CROMITE_SECONDARY_ASSIST_ITEMS = 3; + static int CROMITE_TEXT_PROCESSING_ITEMS = 4; + + private static int GetValue(int a, int b) { + return !ContextUtils.getAppSharedPreferences().getBoolean( + "enable_accessibility", false) + ? a : b; + } + + public static int ASSIST_ITEMS() { + return GetValue(CHROMIUM_ASSIST_ITEMS, CROMITE_ASSIST_ITEMS); + } + + public static int DEFAULT_ITEMS() { + return GetValue(CHROMIUM_DEFAULT_ITEMS, CROMITE_DEFAULT_ITEMS); + } + + public static int SECONDARY_ASSIST_ITEMS() { + return GetValue(CHROMIUM_SECONDARY_ASSIST_ITEMS, CROMITE_SECONDARY_ASSIST_ITEMS); + } + + public static int TEXT_PROCESSING_ITEMS() { + return GetValue(CHROMIUM_TEXT_PROCESSING_ITEMS, CROMITE_TEXT_PROCESSING_ITEMS); + } } - @Retention(RetentionPolicy.SOURCE) - @IntDef({ - DefaultItemOrder.CUT, - DefaultItemOrder.COPY, - DefaultItemOrder.PASTE, - DefaultItemOrder.PASTE_AS_PLAIN_TEXT, - DefaultItemOrder.SHARE, - DefaultItemOrder.SELECT_ALL, - DefaultItemOrder.WEB_SEARCH - }) - public @interface DefaultItemOrder { - int CUT = 1; - int COPY = 2; - int PASTE = 3; - int PASTE_AS_PLAIN_TEXT = 4; - int SHARE = 5; - int SELECT_ALL = 6; - int WEB_SEARCH = 7; + private static class DefaultItemOrderChromium { + static int CHROMIUM_CUT = 1; + static int CHROMIUM_COPY = 2; + static int CHROMIUM_PASTE = 3; + static int CHROMIUM_SHARE = 4; + static int CHROMIUM_SELECT_ALL = 5; + static int CHROMIUM_PASTE_AS_PLAIN_TEXT = 6; + static int CHROMIUM_WEB_SEARCH = 7; + + static int CROMITE_WEB_SEARCH = 1; + static int CROMITE_CUT = 2; + static int CROMITE_COPY = 3; + static int CROMITE_PASTE = 4; + static int CROMITE_SHARE = 5; + static int CROMITE_SELECT_ALL = 6; + static int CROMITE_PASTE_AS_PLAIN_TEXT = 7; + + private static int GetValue(int a, int b) { + return !ContextUtils.getAppSharedPreferences().getBoolean( + "selection_popup_web_search_to_top", false) + ? a : b; + } + + public static int CUT() { + return GetValue(CHROMIUM_CUT, CROMITE_CUT); + } + public static int COPY() { + return GetValue(CHROMIUM_COPY, CROMITE_COPY); + } + public static int PASTE() { + return GetValue(CHROMIUM_PASTE, CROMITE_PASTE); + } + public static int SHARE() { + return GetValue(CHROMIUM_SHARE, CROMITE_SHARE); + } + public static int SELECT_ALL() { + return GetValue(CHROMIUM_SELECT_ALL, CROMITE_SELECT_ALL); + } + public static int PASTE_AS_PLAIN_TEXT() { + return GetValue(CHROMIUM_PASTE_AS_PLAIN_TEXT, CROMITE_PASTE_AS_PLAIN_TEXT); + } + public static int WEB_SEARCH() { + return GetValue(CHROMIUM_WEB_SEARCH, CROMITE_WEB_SEARCH); + } } @Retention(RetentionPolicy.SOURCE) @@ -196,7 +243,7 @@ public class SelectActionMenuHelper { } SelectionMenuGroup primaryAssistGroup = new SelectionMenuGroup( - R.id.select_action_menu_assist_items, GroupItemOrder.ASSIST_ITEMS); + R.id.select_action_menu_assist_items, GroupItemOrderChromium.ASSIST_ITEMS()); View.OnClickListener clickListener = null; if (classificationResult.onClickListener != null) { clickListener = classificationResult.onClickListener; @@ -223,7 +270,7 @@ public class SelectActionMenuHelper { String selectedText) { SelectionMenuGroup defaultGroup = new SelectionMenuGroup( - R.id.select_action_menu_default_items, GroupItemOrder.DEFAULT_ITEMS); + R.id.select_action_menu_default_items, GroupItemOrderChromium.DEFAULT_ITEMS()); List menuItemBuilders = new ArrayList<>(); menuItemBuilders.add(cut(delegate.canCut())); menuItemBuilders.add(copy(delegate.canCopy())); @@ -251,7 +298,7 @@ public class SelectActionMenuHelper { // menu items if there is selected text. @IdRes int groupId = selectedText.isEmpty() ? Menu.NONE : android.R.id.textAssist; SelectionMenuGroup secondaryAssistItems = - new SelectionMenuGroup(groupId, GroupItemOrder.SECONDARY_ASSIST_ITEMS); + new SelectionMenuGroup(groupId, GroupItemOrderChromium.SECONDARY_ASSIST_ITEMS()); if (selectedText.isEmpty() && selectionActionMenuDelegate != null) { List additionalMenuItems = @@ -313,7 +360,7 @@ public class SelectActionMenuHelper { SelectionMenuGroup textProcessingItems = new SelectionMenuGroup( R.id.select_action_menu_text_processing_items, - GroupItemOrder.TEXT_PROCESSING_ITEMS); + GroupItemOrderChromium.TEXT_PROCESSING_ITEMS()); if (isSelectionPassword || intentHandler == null) { addAdditionalTextProcessingItems(textProcessingItems, selectionActionMenuDelegate); return textProcessingItems; @@ -415,7 +462,7 @@ public class SelectActionMenuHelper { .setId(R.id.select_action_menu_cut) .setIconAttr(android.R.attr.actionModeCutDrawable) .setAlphabeticShortcut(ItemKeyShortcuts.CUT) - .setOrderInCategory(DefaultItemOrder.CUT) + .setOrderInCategory(DefaultItemOrderChromium.CUT()) .setShowAsActionFlags( MenuItem.SHOW_AS_ACTION_ALWAYS | MenuItem.SHOW_AS_ACTION_WITH_TEXT) .setIsEnabled(isEnabled) @@ -427,7 +474,7 @@ public class SelectActionMenuHelper { .setId(R.id.select_action_menu_copy) .setIconAttr(android.R.attr.actionModeCopyDrawable) .setAlphabeticShortcut(ItemKeyShortcuts.COPY) - .setOrderInCategory(DefaultItemOrder.COPY) + .setOrderInCategory(DefaultItemOrderChromium.COPY()) .setShowAsActionFlags( MenuItem.SHOW_AS_ACTION_ALWAYS | MenuItem.SHOW_AS_ACTION_WITH_TEXT) .setIsEnabled(isEnabled) @@ -439,7 +486,7 @@ public class SelectActionMenuHelper { .setId(R.id.select_action_menu_paste) .setIconAttr(android.R.attr.actionModePasteDrawable) .setAlphabeticShortcut(ItemKeyShortcuts.PASTE) - .setOrderInCategory(DefaultItemOrder.PASTE) + .setOrderInCategory(DefaultItemOrderChromium.PASTE()) .setShowAsActionFlags( MenuItem.SHOW_AS_ACTION_ALWAYS | MenuItem.SHOW_AS_ACTION_WITH_TEXT) .setIsEnabled(isEnabled) @@ -453,7 +500,7 @@ public class SelectActionMenuHelper { return new SelectionMenuItem.Builder(context.getString(R.string.actionbar_share)) .setId(R.id.select_action_menu_share) .setIconAttr(android.R.attr.actionModeShareDrawable) - .setOrderInCategory(DefaultItemOrder.SHARE) + .setOrderInCategory(DefaultItemOrderChromium.SHARE()) .setShowAsActionFlags( MenuItem.SHOW_AS_ACTION_ALWAYS | MenuItem.SHOW_AS_ACTION_WITH_TEXT) .setIsEnabled(isEnabled) @@ -465,7 +512,7 @@ public class SelectActionMenuHelper { .setId(R.id.select_action_menu_select_all) .setIconAttr(android.R.attr.actionModeSelectAllDrawable) .setAlphabeticShortcut(ItemKeyShortcuts.SELECT_ALL) - .setOrderInCategory(DefaultItemOrder.SELECT_ALL) + .setOrderInCategory(DefaultItemOrderChromium.SELECT_ALL()) .setShowAsActionFlags( MenuItem.SHOW_AS_ACTION_ALWAYS | MenuItem.SHOW_AS_ACTION_WITH_TEXT) .setIsEnabled(isEnabled) @@ -477,7 +524,7 @@ public class SelectActionMenuHelper { SelectionMenuItem.Builder builder = new SelectionMenuItem.Builder(android.R.string.paste_as_plain_text) .setId(R.id.select_action_menu_paste_as_plain_text) - .setOrderInCategory(DefaultItemOrder.PASTE_AS_PLAIN_TEXT) + .setOrderInCategory(DefaultItemOrderChromium.PASTE_AS_PLAIN_TEXT()) .setShowAsActionFlags( MenuItem.SHOW_AS_ACTION_ALWAYS | MenuItem.SHOW_AS_ACTION_WITH_TEXT) .setIsEnabled(isEnabled); @@ -497,7 +544,7 @@ public class SelectActionMenuHelper { return new SelectionMenuItem.Builder(context.getString(R.string.actionbar_web_search)) .setId(R.id.select_action_menu_web_search) .setIconAttr(android.R.attr.actionModeWebSearchDrawable) - .setOrderInCategory(DefaultItemOrder.WEB_SEARCH) + .setOrderInCategory(DefaultItemOrderChromium.WEB_SEARCH()) .setShowAsActionFlags( MenuItem.SHOW_AS_ACTION_ALWAYS | MenuItem.SHOW_AS_ACTION_WITH_TEXT) .setIsEnabled(isEnabled) diff --git a/content/public/android/java/src/org/chromium/content/browser/selection/SmartSelectionClient.java b/content/public/android/java/src/org/chromium/content/browser/selection/SmartSelectionClient.java --- a/content/public/android/java/src/org/chromium/content/browser/selection/SmartSelectionClient.java +++ b/content/public/android/java/src/org/chromium/content/browser/selection/SmartSelectionClient.java @@ -18,6 +18,7 @@ import org.jni_zero.CalledByNative; import org.jni_zero.JNINamespace; import org.jni_zero.NativeMethods; +import org.chromium.base.ContextUtils; import org.chromium.base.ObserverList; import org.chromium.base.UserData; import org.chromium.build.annotations.Initializer; @@ -84,6 +85,9 @@ public class SmartSelectionClient implements SelectionClient, UserData { return null; } + if (!ContextUtils.getAppSharedPreferences().getBoolean( + "selection_popup_smart_text", false)) return null; + SmartSelectionClient client = assumeNonNull( webContents.getOrSetUserData( --