From d8d4eb036cf1ba3b07526cfcffa7b043451ac139 Mon Sep 17 00:00:00 2001 From: wchen342 Date: Wed, 20 Sep 2023 00:44:15 +0300 Subject: [PATCH] [Android] Add method to extend touch area without changing View appearances --- android/brave_java_sources.gni | 2 + .../brave_news/CardBuilderFeedCard.java | 2 + .../BraveStatsBottomSheetDialogFragment.java | 37 ++++--- .../firstrun/WelcomeOnboardingActivity.java | 11 ++ .../chrome/browser/ntp/BraveNtpAdapter.java | 5 + .../BraveLocationBarQRDialogFragment.java | 4 + .../BraveRewardsOnboardingFragment.java | 3 + .../browser/rewards/BraveRewardsPanel.java | 45 ++++++-- .../rewards/onboarding/RewardsOnboarding.java | 15 +-- .../settings/BraveNewsPreferencesV2.java | 8 ++ .../BrowsingModeBottomToolbarCoordinator.java | 2 + .../toolbar/top/BraveToolbarLayoutImpl.java | 6 ++ .../chrome/browser/util/BraveTouchUtils.java | 100 ++++++++++++++++++ .../chrome/browser/util/README.chromium | 4 + .../browser/util/TouchDelegateComposite.java | 80 ++++++++++++++ script/brave_license_helper.py | 2 + 16 files changed, 299 insertions(+), 27 deletions(-) create mode 100644 android/java/org/chromium/chrome/browser/util/BraveTouchUtils.java create mode 100644 android/java/org/chromium/chrome/browser/util/README.chromium create mode 100644 android/java/org/chromium/chrome/browser/util/TouchDelegateComposite.java diff --git a/android/brave_java_sources.gni b/android/brave_java_sources.gni index 26546a0013b..c2a48752e9a 100644 --- a/android/brave_java_sources.gni +++ b/android/brave_java_sources.gni @@ -442,11 +442,13 @@ brave_java_sources = [ "../../brave/android/java/org/chromium/chrome/browser/util/BraveDbUtil.java", "../../brave/android/java/org/chromium/chrome/browser/util/BraveDynamicColors.java", "../../brave/android/java/org/chromium/chrome/browser/util/BraveReferrer.java", + "../../brave/android/java/org/chromium/chrome/browser/util/BraveTouchUtils.java", "../../brave/android/java/org/chromium/chrome/browser/util/ConfigurationUtils.java", "../../brave/android/java/org/chromium/chrome/browser/util/ImageUtils.java", "../../brave/android/java/org/chromium/chrome/browser/util/LiveDataUtil.java", "../../brave/android/java/org/chromium/chrome/browser/util/PackageUtils.java", "../../brave/android/java/org/chromium/chrome/browser/util/TabUtils.java", + "../../brave/android/java/org/chromium/chrome/browser/util/TouchDelegateComposite.java", "../../brave/android/java/org/chromium/chrome/browser/util/Triple.java", "../../brave/android/java/org/chromium/chrome/browser/vpn/BraveVpnNativeWorker.java", "../../brave/android/java/org/chromium/chrome/browser/vpn/BraveVpnObserver.java", diff --git a/android/java/org/chromium/chrome/browser/brave_news/CardBuilderFeedCard.java b/android/java/org/chromium/chrome/browser/brave_news/CardBuilderFeedCard.java index 2849326efc1..d06be636946 100644 --- a/android/java/org/chromium/chrome/browser/brave_news/CardBuilderFeedCard.java +++ b/android/java/org/chromium/chrome/browser/brave_news/CardBuilderFeedCard.java @@ -73,6 +73,7 @@ import org.chromium.chrome.browser.local_database.DisplayAdsTable; import org.chromium.chrome.browser.preferences.SharedPreferencesManager; import org.chromium.chrome.browser.rate.BraveRateDialogFragment; import org.chromium.chrome.browser.tab.Tab; +import org.chromium.chrome.browser.util.BraveTouchUtils; import org.chromium.chrome.browser.util.ConfigurationUtils; import org.chromium.chrome.browser.util.TabUtils; import org.chromium.url.mojom.Url; @@ -374,6 +375,7 @@ public class CardBuilderFeedCard { int displayHeight = mActivity.getResources().getDisplayMetrics().heightPixels; TableRow rowTop = new TableRow(mActivity); TextView topText = new TextView(mActivity); + BraveTouchUtils.ensureMinTouchTarget(topText); TableRow row1 = new TableRow(mActivity); TableRow row2 = new TableRow(mActivity); diff --git a/android/java/org/chromium/chrome/browser/brave_stats/BraveStatsBottomSheetDialogFragment.java b/android/java/org/chromium/chrome/browser/brave_stats/BraveStatsBottomSheetDialogFragment.java index 6ebf7349142..4145825a9a5 100644 --- a/android/java/org/chromium/chrome/browser/brave_stats/BraveStatsBottomSheetDialogFragment.java +++ b/android/java/org/chromium/chrome/browser/brave_stats/BraveStatsBottomSheetDialogFragment.java @@ -38,6 +38,7 @@ import org.chromium.chrome.R; import org.chromium.chrome.browser.local_database.DatabaseHelper; import org.chromium.chrome.browser.night_mode.GlobalNightModeStateProviderHolder; import org.chromium.chrome.browser.notifications.BravePermissionUtils; +import org.chromium.chrome.browser.util.BraveTouchUtils; import org.chromium.ui.base.DeviceFormFactor; import org.chromium.ui.permissions.PermissionConstants; @@ -68,8 +69,11 @@ public class BraveStatsBottomSheetDialogFragment extends BottomSheetDialogFragme private LinearLayout websitesLayout; private LinearLayout trackersLayout; - private RadioButton monthRadioButton; - private RadioButton monthsRadioButton; + private RadioButton mWeekRadioButton; + private RadioButton mMonthRadioButton; + private RadioButton mMonthsRadioButton; + private RadioButton mTrackersRadioButton; + private RadioButton mWebsitesRadioButton; private View statsNotificationView; private int selectedType = WEBSITES; @@ -128,8 +132,11 @@ public class BraveStatsBottomSheetDialogFragment extends BottomSheetDialogFragme } }); - monthRadioButton = view.findViewById(R.id.month_radio); - monthsRadioButton = view.findViewById(R.id.months_radio); + mWeekRadioButton = view.findViewById(R.id.week_radio); + mMonthRadioButton = view.findViewById(R.id.month_radio); + mMonthsRadioButton = view.findViewById(R.id.months_radio); + mTrackersRadioButton = view.findViewById(R.id.trackers_radio); + mWebsitesRadioButton = view.findViewById(R.id.websites_radio); LinearLayout layout = view.findViewById(R.id.brave_stats_layout); adsTrackersCountText = layout.findViewById(R.id.ads_trackers_count_text); @@ -143,6 +150,12 @@ public class BraveStatsBottomSheetDialogFragment extends BottomSheetDialogFragme braveStatsSubSectionText = layout.findViewById(R.id.brave_stats_sub_section_text); statsNotificationView = view.findViewById(R.id.brave_stats_notification_permission); + BraveTouchUtils.ensureMinTouchTarget(mWeekRadioButton); + BraveTouchUtils.ensureMinTouchTarget(mMonthRadioButton); + BraveTouchUtils.ensureMinTouchTarget(mMonthsRadioButton); + BraveTouchUtils.ensureMinTouchTarget(mTrackersRadioButton); + BraveTouchUtils.ensureMinTouchTarget(mWebsitesRadioButton); + RadioGroup statTypeRadioGroup = layout.findViewById(R.id.stat_type_radio_group); statTypeRadioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() { @Override @@ -297,20 +310,20 @@ public class BraveStatsBottomSheetDialogFragment extends BottomSheetDialogFragme // Check for month option if (adsTrackersCountToCheckForMonth > 0) { - monthRadioButton.setEnabled(true); - monthRadioButton.setAlpha(1.0f); + mMonthRadioButton.setEnabled(true); + mMonthRadioButton.setAlpha(1.0f); } else { - monthRadioButton.setEnabled(false); - monthRadioButton.setAlpha(0.2f); + mMonthRadioButton.setEnabled(false); + mMonthRadioButton.setAlpha(0.2f); } // Check for 3 month option if (adsTrackersCountToCheckFor3Month > 0) { - monthsRadioButton.setEnabled(true); - monthsRadioButton.setAlpha(1.0f); + mMonthsRadioButton.setEnabled(true); + mMonthsRadioButton.setAlpha(1.0f); } else { - monthsRadioButton.setEnabled(false); - monthsRadioButton.setAlpha(0.2f); + mMonthsRadioButton.setEnabled(false); + mMonthsRadioButton.setAlpha(0.2f); } showWebsitesTrackers(); } diff --git a/android/java/org/chromium/chrome/browser/firstrun/WelcomeOnboardingActivity.java b/android/java/org/chromium/chrome/browser/firstrun/WelcomeOnboardingActivity.java index c4897fb0d4b..1bffa1ffae9 100644 --- a/android/java/org/chromium/chrome/browser/firstrun/WelcomeOnboardingActivity.java +++ b/android/java/org/chromium/chrome/browser/firstrun/WelcomeOnboardingActivity.java @@ -51,6 +51,7 @@ import org.chromium.chrome.browser.preferences.SharedPreferencesManager; import org.chromium.chrome.browser.privacy.settings.PrivacyPreferencesManagerImpl; import org.chromium.chrome.browser.set_default_browser.BraveSetDefaultBrowserUtils; import org.chromium.chrome.browser.util.BraveConstants; +import org.chromium.chrome.browser.util.BraveTouchUtils; import org.chromium.chrome.browser.util.PackageUtils; import org.chromium.ui.base.DeviceFormFactor; @@ -185,6 +186,16 @@ public class WelcomeOnboardingActivity extends FirstRunActivityBase { bottomLeafParams.topMargin = margin; mVLeafAlignBottom.setLayoutParams(bottomLeafParams); } + + if (mBtnPositive != null) { + BraveTouchUtils.ensureMinTouchTarget(mBtnPositive); + } + if (mCheckboxCrash != null) { + BraveTouchUtils.ensureMinTouchTarget(mCheckboxCrash); + } + if (mCheckboxP3a != null) { + BraveTouchUtils.ensureMinTouchTarget(mCheckboxP3a); + } } private void onClickViews() { diff --git a/android/java/org/chromium/chrome/browser/ntp/BraveNtpAdapter.java b/android/java/org/chromium/chrome/browser/ntp/BraveNtpAdapter.java index ec10f47956b..09cde60f44e 100644 --- a/android/java/org/chromium/chrome/browser/ntp/BraveNtpAdapter.java +++ b/android/java/org/chromium/chrome/browser/ntp/BraveNtpAdapter.java @@ -53,6 +53,7 @@ import org.chromium.chrome.browser.preferences.SharedPreferencesManager; import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.settings.BackgroundImagesPreferences; import org.chromium.chrome.browser.util.BraveConstants; +import org.chromium.chrome.browser.util.BraveTouchUtils; import org.chromium.chrome.browser.util.TabUtils; import org.chromium.components.user_prefs.UserPrefs; @@ -605,6 +606,7 @@ public class BraveNtpAdapter extends RecyclerView.Adapter { showRewardsTour(); }); + mCountrySpinner = mPopupView.findViewById(R.id.country_spinner); + BraveTouchUtils.ensureMinTouchTarget(mCountrySpinner); + String termsOfServiceText = String.format( mPopupView.getContext().getString(R.string.brave_rewards_onboarding_tos_text), mPopupView.getContext().getString(R.string.terms_of_service), @@ -186,13 +191,11 @@ public class RewardsOnboarding implements BraveRewardsObserver { } String[] countryArray = countryList.toArray(new String[countryList.size()]); - Spinner countrySpinner; - countrySpinner = mPopupView.findViewById(R.id.country_spinner); CountrySelectionSpinnerAdapter countrySelectionSpinnerAdapter = new CountrySelectionSpinnerAdapter(mActivity, countryList); - countrySpinner.setAdapter(countrySelectionSpinnerAdapter); - countrySpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { + mCountrySpinner.setAdapter(countrySelectionSpinnerAdapter); + mCountrySpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { @Override public void onItemSelected(AdapterView parent, View view, int pos, long id) { mContinueButton.setEnabled(pos != 0); @@ -210,9 +213,9 @@ public class RewardsOnboarding implements BraveRewardsObserver { mAnchorView.getContext())) { requestNotificationPermission(); } - if (countrySpinner != null) { + if (mCountrySpinner != null) { mBraveRewardsNativeWorker.CreateRewardsWallet( - sortedCountryMap.get(countrySpinner.getSelectedItem().toString())); + sortedCountryMap.get(mCountrySpinner.getSelectedItem().toString())); shouldShowContinueProgress(true); mContinueButton.setText(""); } diff --git a/android/java/org/chromium/chrome/browser/settings/BraveNewsPreferencesV2.java b/android/java/org/chromium/chrome/browser/settings/BraveNewsPreferencesV2.java index e1e812543be..ac7d74ad81d 100644 --- a/android/java/org/chromium/chrome/browser/settings/BraveNewsPreferencesV2.java +++ b/android/java/org/chromium/chrome/browser/settings/BraveNewsPreferencesV2.java @@ -40,6 +40,7 @@ import org.chromium.chrome.browser.night_mode.GlobalNightModeStateProviderHolder import org.chromium.chrome.browser.preferences.BravePrefServiceBridge; import org.chromium.chrome.browser.preferences.SharedPreferencesManager; import org.chromium.chrome.browser.util.BraveConstants; +import org.chromium.chrome.browser.util.BraveTouchUtils; import org.chromium.components.browser_ui.settings.FragmentSettingsLauncher; import org.chromium.components.browser_ui.settings.SettingsLauncher; import org.chromium.mojo.bindings.ConnectionErrorHandler; @@ -106,6 +107,13 @@ public class BraveNewsPreferencesV2 extends BravePreferenceFragment mLayoutChannels = (View) view.findViewById(R.id.layout_channels); mLayoutFollowing = (View) view.findViewById(R.id.layout_following); + BraveTouchUtils.ensureMinTouchTarget(mBtnTurnOnNews); + BraveTouchUtils.ensureMinTouchTarget(mLayoutChannels); + BraveTouchUtils.ensureMinTouchTarget(mLayoutFollowing); + BraveTouchUtils.ensureMinTouchTarget(mLayoutPopularSources); + BraveTouchUtils.ensureMinTouchTarget(mLayoutSuggestions); + BraveTouchUtils.ensureMinTouchTarget(mTvSearch); + setData(); onClickViews(); } diff --git a/android/java/org/chromium/chrome/browser/toolbar/bottom/BrowsingModeBottomToolbarCoordinator.java b/android/java/org/chromium/chrome/browser/toolbar/bottom/BrowsingModeBottomToolbarCoordinator.java index 5fb85ebe67e..8e0d6d98efd 100644 --- a/android/java/org/chromium/chrome/browser/toolbar/bottom/BrowsingModeBottomToolbarCoordinator.java +++ b/android/java/org/chromium/chrome/browser/toolbar/bottom/BrowsingModeBottomToolbarCoordinator.java @@ -30,6 +30,7 @@ import org.chromium.chrome.browser.toolbar.menu_button.BraveMenuButtonCoordinato import org.chromium.chrome.browser.toolbar.menu_button.MenuButton; import org.chromium.chrome.browser.toolbar.menu_button.MenuButtonState; import org.chromium.chrome.browser.ui.appmenu.AppMenuButtonHelper; +import org.chromium.chrome.browser.util.BraveTouchUtils; import org.chromium.ui.modelutil.PropertyModelChangeProcessor; /** @@ -98,6 +99,7 @@ public class BrowsingModeBottomToolbarCoordinator { mSearchAccelerator = mToolbarRoot.findViewById(R.id.search_accelerator); mSearchAccelerator.setOnClickListener(searchAcceleratorListener); + BraveTouchUtils.ensureMinTouchTarget(mSearchAccelerator); // TODO(amaralp): Make this adhere to MVC framework. mTabSwitcherButtonView = mToolbarRoot.findViewById(R.id.bottom_tab_switcher_button); diff --git a/android/java/org/chromium/chrome/browser/toolbar/top/BraveToolbarLayoutImpl.java b/android/java/org/chromium/chrome/browser/toolbar/top/BraveToolbarLayoutImpl.java index 6b2a266f201..b07eaad375c 100644 --- a/android/java/org/chromium/chrome/browser/toolbar/top/BraveToolbarLayoutImpl.java +++ b/android/java/org/chromium/chrome/browser/toolbar/top/BraveToolbarLayoutImpl.java @@ -126,6 +126,7 @@ import org.chromium.chrome.browser.toolbar.menu_button.MenuButtonCoordinator; import org.chromium.chrome.browser.toolbar.top.NavigationPopup.HistoryDelegate; import org.chromium.chrome.browser.toolbar.top.ToolbarTablet.OfflineDownloader; import org.chromium.chrome.browser.util.BraveConstants; +import org.chromium.chrome.browser.util.BraveTouchUtils; import org.chromium.chrome.browser.util.ConfigurationUtils; import org.chromium.chrome.browser.util.PackageUtils; import org.chromium.chrome.browser.widget.quickactionsearchandbookmark.promo.SearchWidgetPromoPanel; @@ -288,18 +289,21 @@ public abstract class BraveToolbarLayoutImpl extends ToolbarLayout mBraveShieldsButton.setClickable(true); mBraveShieldsButton.setOnClickListener(this); mBraveShieldsButton.setOnLongClickListener(this); + BraveTouchUtils.ensureMinTouchTarget(mBraveShieldsButton); } if (mBraveRewardsButton != null) { mBraveRewardsButton.setClickable(true); mBraveRewardsButton.setOnClickListener(this); mBraveRewardsButton.setOnLongClickListener(this); + BraveTouchUtils.ensureMinTouchTarget(mBraveRewardsButton); } if (mBraveWalletButton != null) { mBraveWalletButton.setClickable(true); mBraveWalletButton.setOnClickListener(this); mBraveWalletButton.setOnLongClickListener(this); + BraveTouchUtils.ensureMinTouchTarget(mBraveWalletButton); } mBraveShieldsHandler = new BraveShieldsHandler(getContext()); @@ -1102,6 +1106,7 @@ public abstract class BraveToolbarLayoutImpl extends ToolbarLayout R.id.brave_rewards_onboarding_modal_tos_pp_text); tosAndPpText.setMovementMethod(LinkMovementMethod.getInstance()); tosAndPpText.setText(tosTextSS); + BraveTouchUtils.ensureMinTouchTarget(tosAndPpText); TextView takeQuickTourButton = braveRewardsOnboardingModalView.findViewById(R.id.take_quick_tour_button); @@ -1113,6 +1118,7 @@ public abstract class BraveToolbarLayoutImpl extends ToolbarLayout dialog.dismiss(); } })); + BraveTouchUtils.ensureMinTouchTarget(takeQuickTourButton); TextView btnBraveRewards = braveRewardsOnboardingModalView.findViewById(R.id.start_using_brave_rewards_text); btnBraveRewards.setOnClickListener((new View.OnClickListener() { diff --git a/android/java/org/chromium/chrome/browser/util/BraveTouchUtils.java b/android/java/org/chromium/chrome/browser/util/BraveTouchUtils.java new file mode 100644 index 00000000000..52d17eb99ed --- /dev/null +++ b/android/java/org/chromium/chrome/browser/util/BraveTouchUtils.java @@ -0,0 +1,100 @@ +/* Copyright (c) 2023 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at https://mozilla.org/MPL/2.0/. */ + +package org.chromium.chrome.browser.util; + +import android.graphics.Rect; +import android.util.DisplayMetrics; +import android.view.TouchDelegate; +import android.view.View; +import android.view.ViewTreeObserver.OnGlobalLayoutListener; + +public class BraveTouchUtils { + public static final int MIN_TOUCH_TARGET = 48; + + /** + * Ensures that the touchable area of [view] equal MIN_TOUCH_TARGET. + */ + public static void ensureMinTouchTarget(View view) { + ensureMinTouchTarget(view, MIN_TOUCH_TARGET); + } + + /** + * Ensures that the touchable area of [view] equal [minTarget] by expanding the touch area + * of a view beyond its actual view bounds. + * + * This function was taken from Trackr Android App (https://github.com/android/trackr) + * and adapted to Java. minTarget is in dp instead of px. + * + * 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. + */ + public static void ensureMinTouchTarget(View view, int minTarget) { + View parent = (View) view.getParent(); + if (parent != null) { + parent.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() { + @Override + public void onGlobalLayout() { + if (view.isShown()) { + final Rect bounds = new Rect(); + view.getHitRect(bounds); + + DisplayMetrics metrics = + view.getContext().getResources().getDisplayMetrics(); + int height = (int) Math.round(bounds.height() / metrics.density); + int width = (int) Math.round(bounds.width() / metrics.density); + + int extraSpaceStart = 0; + int extraSpaceEnd = 0; + if (height < minTarget) { + extraSpaceStart = (int) Math.floor((minTarget - height) / 2f); + extraSpaceEnd = minTarget - height - extraSpaceStart; + extraSpaceStart = (int) Math.ceil(extraSpaceStart * metrics.density); + extraSpaceEnd = (int) Math.ceil(extraSpaceEnd * metrics.density); + bounds.top -= extraSpaceStart; + bounds.bottom += extraSpaceEnd; + } + + if (width < minTarget) { + extraSpaceStart = (int) Math.floor((minTarget - width) / 2f); + extraSpaceEnd = minTarget - width - extraSpaceStart; + extraSpaceStart = (int) Math.ceil(extraSpaceStart * metrics.density); + extraSpaceEnd = (int) Math.ceil(extraSpaceEnd * metrics.density); + bounds.left -= extraSpaceStart; + bounds.right += extraSpaceEnd; + } + + ensureTouchDelegateComposite(parent, view); + ((TouchDelegateComposite) parent.getTouchDelegate()) + .addDelegate(bounds, view); + } + } + }); + } + } + + private static void ensureTouchDelegateComposite(View parent, View view) { + TouchDelegate parentTouchDelegate = parent.getTouchDelegate(); + if (parentTouchDelegate == null) { + parent.setTouchDelegate(new TouchDelegateComposite(new Rect(), view)); + } else if (!(parentTouchDelegate instanceof TouchDelegateComposite)) { + TouchDelegateComposite touchDelegateComposite = + new TouchDelegateComposite(new Rect(), view); + touchDelegateComposite.addDelegate(parentTouchDelegate); + parent.setTouchDelegate(touchDelegateComposite); + } + } +} diff --git a/android/java/org/chromium/chrome/browser/util/README.chromium b/android/java/org/chromium/chrome/browser/util/README.chromium new file mode 100644 index 00000000000..b1290a1c0d0 --- /dev/null +++ b/android/java/org/chromium/chrome/browser/util/README.chromium @@ -0,0 +1,4 @@ +Name: Trackr Android App +URL: https://github.com/android/trackr/ +License: Apache-2.0 +License File: /brave/common/licenses/Apache-2.0 diff --git a/android/java/org/chromium/chrome/browser/util/TouchDelegateComposite.java b/android/java/org/chromium/chrome/browser/util/TouchDelegateComposite.java new file mode 100644 index 00000000000..f227d1c44d0 --- /dev/null +++ b/android/java/org/chromium/chrome/browser/util/TouchDelegateComposite.java @@ -0,0 +1,80 @@ +/* Copyright (c) 2023 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at https://mozilla.org/MPL/2.0/. */ + +package org.chromium.chrome.browser.util; + +import android.graphics.Rect; +import android.graphics.Region; +import android.os.Build; +import android.util.ArrayMap; +import android.util.Pair; +import android.view.MotionEvent; +import android.view.TouchDelegate; +import android.view.View; +import android.view.accessibility.AccessibilityNodeInfo.TouchDelegateInfo; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +/** + * A class holding multiple TouchDelegates to ensure touch events are dispatched correctly from + * parent to all children. + */ +public class TouchDelegateComposite extends TouchDelegate { + private List>> mDelegates = new ArrayList<>(4); + + public TouchDelegateComposite(Rect bounds, View view) { + super(bounds, view); + } + + /** + * Add a pre-existing TouchDelegate. Cannot get bounds and view from existing delegate. + */ + public void addDelegate(TouchDelegate delegate) { + mDelegates.add(new Pair<>(null, new Pair<>(new Rect(), delegate))); + } + + /** + * Add a delegate by bounds and view. + */ + public void addDelegate(Rect bounds, View view) { + boolean dup = false; + mDelegates = mDelegates.stream() + .filter(e -> e.first == null || e.first.getId() != view.getId()) + .collect(Collectors.toList()); + + mDelegates.add(new Pair<>(view, new Pair<>(bounds, new TouchDelegate(bounds, view)))); + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + boolean handled = false; + float x = event.getX(); + float y = event.getY(); + for (Pair> delegate : mDelegates) { + event.setLocation(x, y); + handled = delegate.second.second.onTouchEvent(event) || handled; + } + return handled; + } + + @Override + public TouchDelegateInfo getTouchDelegateInfo() { + final ArrayMap targetMap = new ArrayMap<>(); + for (Pair> delegate : mDelegates) { + if (delegate.first == null) continue; + Rect bounds = delegate.second.first; + if (bounds == null) { + bounds = new Rect(); + } + targetMap.put(new Region(bounds), delegate.first); + } + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + return new TouchDelegateInfo(targetMap); + } + return null; + } +} diff --git a/script/brave_license_helper.py b/script/brave_license_helper.py index e20a9a0b429..9eb7108b23c 100644 --- a/script/brave_license_helper.py +++ b/script/brave_license_helper.py @@ -170,6 +170,8 @@ def AddBraveCredits(root, prune_paths, special_cases, prune_dirs, os.path.join('brave', 'browser', 'brave_vpn', 'win', 'brave_vpn_wireguard_service'), os.path.join('brave', 'components', 'filecoin'), + os.path.join('brave', 'android', 'java', 'org', 'chromium', 'chrome', + 'browser', 'util'), ] # Add all Android libraries since they're not directly contained