Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d795ea77 authored by Tracy Zhou's avatar Tracy Zhou
Browse files

[Trackpad] Do not reverse lockscreen trackpad gestures when reverse scrolling is on

- Two-finger swipe up to unlock
- Two-finger swipe down to pull down notifications
- Two-finger swipe up to go back to lockscreen

Fixes: 301966798
Test: above
Change-Id: I5092f075b5530f6380d72f9a74b07979ccbcd245
parent 32a0d2ff
Loading
Loading
Loading
Loading
+67 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 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.systemui.keyguard.domain.interactor

import android.content.Context
import android.database.ContentObserver
import android.os.Handler
import android.os.UserHandle
import android.provider.Settings
import android.provider.Settings.SettingNotFoundException
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Main
import javax.inject.Inject

@SysUISingleton
class NaturalScrollingSettingObserver
@Inject
constructor(
    @Main private val handler: Handler,
    private val context: Context,
) {
    var isNaturalScrollingEnabled = true
        get() {
            if (!isInitialized) {
                isInitialized = true
                update()
            }
            return field
        }

    private var isInitialized = false

    private val contentObserver = object : ContentObserver(handler) {
        override fun onChange(selfChange: Boolean) {
            update()
        }
    }

    init {
        context.contentResolver.registerContentObserver(
                Settings.System.getUriFor(Settings.System.TOUCHPAD_NATURAL_SCROLLING), false,
                contentObserver)
    }

    private fun update() {
        isNaturalScrollingEnabled = try {
            Settings.System.getIntForUser(context.contentResolver,
                    Settings.System.TOUCHPAD_NATURAL_SCROLLING, UserHandle.USER_CURRENT) == 1
        } catch (e: SettingNotFoundException) {
            true
        }
    }
}
+18 −7
Original line number Diff line number Diff line
@@ -134,6 +134,7 @@ import com.android.systemui.keyguard.domain.interactor.KeyguardBottomAreaInterac
import com.android.systemui.keyguard.domain.interactor.KeyguardFaceAuthInteractor;
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor;
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor;
import com.android.systemui.keyguard.domain.interactor.NaturalScrollingSettingObserver;
import com.android.systemui.keyguard.shared.KeyguardShadeMigrationNssl;
import com.android.systemui.keyguard.shared.model.TransitionState;
import com.android.systemui.keyguard.shared.model.TransitionStep;
@@ -355,6 +356,7 @@ public final class NotificationPanelViewController implements ShadeSurface, Dump
    private final NotificationGutsManager mGutsManager;
    private final AlternateBouncerInteractor mAlternateBouncerInteractor;
    private final QuickSettingsController mQsController;
    private final NaturalScrollingSettingObserver mNaturalScrollingSettingObserver;
    private final TouchHandler mTouchHandler = new TouchHandler();

    private long mDownTime;
@@ -407,6 +409,7 @@ public final class NotificationPanelViewController implements ShadeSurface, Dump
    private float mOverStretchAmount;
    private float mDownX;
    private float mDownY;
    private boolean mIsTrackpadReverseScroll;
    private int mDisplayTopInset = 0; // in pixels
    private int mDisplayRightInset = 0; // in pixels
    private int mDisplayLeftInset = 0; // in pixels
@@ -775,7 +778,8 @@ public final class NotificationPanelViewController implements ShadeSurface, Dump
            KeyguardFaceAuthInteractor keyguardFaceAuthInteractor,
            SplitShadeStateController splitShadeStateController,
            PowerInteractor powerInteractor,
            KeyguardClockPositionAlgorithm keyguardClockPositionAlgorithm) {
            KeyguardClockPositionAlgorithm keyguardClockPositionAlgorithm,
            NaturalScrollingSettingObserver naturalScrollingSettingObserver) {
        keyguardStateController.addCallback(new KeyguardStateController.Callback() {
            @Override
            public void onKeyguardFadingAwayChanged() {
@@ -804,6 +808,7 @@ public final class NotificationPanelViewController implements ShadeSurface, Dump
        mPowerInteractor = powerInteractor;
        mKeyguardViewConfigurator = keyguardViewConfigurator;
        mClockPositionAlgorithm = keyguardClockPositionAlgorithm;
        mNaturalScrollingSettingObserver = naturalScrollingSettingObserver;
        mView.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() {
            @Override
            public void onViewAttachedToWindow(View v) {
@@ -3682,7 +3687,7 @@ public final class NotificationPanelViewController implements ShadeSurface, Dump
     */
    private boolean isDirectionUpwards(float x, float y) {
        float xDiff = x - mInitialExpandX;
        float yDiff = y - mInitialExpandY;
        float yDiff = (mIsTrackpadReverseScroll ? -1 : 1) * (y - mInitialExpandY);
        if (yDiff >= 0) {
            return false;
        }
@@ -3719,7 +3724,7 @@ public final class NotificationPanelViewController implements ShadeSurface, Dump
                || (!isFullyExpanded() && !isFullyCollapsed())
                || event.getActionMasked() == MotionEvent.ACTION_CANCEL || forceCancel) {
            mVelocityTracker.computeCurrentVelocity(1000);
            float vel = mVelocityTracker.getYVelocity();
            float vel = (mIsTrackpadReverseScroll ? -1 : 1) * mVelocityTracker.getYVelocity();
            float vectorVel = (float) Math.hypot(
                    mVelocityTracker.getXVelocity(), mVelocityTracker.getYVelocity());

@@ -3758,8 +3763,9 @@ public final class NotificationPanelViewController implements ShadeSurface, Dump
                mLockscreenGestureLogger.write(MetricsEvent.ACTION_LS_UNLOCK, heightDp, velocityDp);
                mLockscreenGestureLogger.log(LockscreenUiEvent.LOCKSCREEN_UNLOCK);
            }
            float dy = (mIsTrackpadReverseScroll ? -1 : 1) * (y - mInitialExpandY);
            @Classifier.InteractionType int interactionType = vel == 0 ? GENERIC
                    : y - mInitialExpandY > 0 ? QUICK_SETTINGS
                    : dy > 0 ? QUICK_SETTINGS
                            : (mKeyguardStateController.canDismissLockScreen()
                                    ? UNLOCK : BOUNCER_UNLOCK);

@@ -3786,7 +3792,7 @@ public final class NotificationPanelViewController implements ShadeSurface, Dump

    private float getCurrentExpandVelocity() {
        mVelocityTracker.computeCurrentVelocity(1000);
        return mVelocityTracker.getYVelocity();
        return (mIsTrackpadReverseScroll ? -1 : 1) * mVelocityTracker.getYVelocity();
    }

    private void endClosing() {
@@ -4827,6 +4833,10 @@ public final class NotificationPanelViewController implements ShadeSurface, Dump
                                + " mAnimatingOnDown: true, mClosing: true");
                        return true;
                    }

                    mIsTrackpadReverseScroll =
                            !mNaturalScrollingSettingObserver.isNaturalScrollingEnabled()
                                    && isTrackpadScroll(mTrackpadGestureFeaturesEnabled, event);
                    if (!isTracking() || isFullyCollapsed()) {
                        mInitialExpandY = y;
                        mInitialExpandX = x;
@@ -4869,7 +4879,7 @@ public final class NotificationPanelViewController implements ShadeSurface, Dump
                    }
                    break;
                case MotionEvent.ACTION_MOVE:
                    final float h = y - mInitialExpandY;
                    final float h = (mIsTrackpadReverseScroll ? -1 : 1) * (y - mInitialExpandY);
                    addMovement(event);
                    final boolean openShadeWithoutHun =
                            mPanelClosedOnDown && !mCollapsedAndHeadsUpOnDown;
@@ -5133,7 +5143,7 @@ public final class NotificationPanelViewController implements ShadeSurface, Dump
                    if (!isFullyCollapsed()) {
                        maybeVibrateOnOpening(true /* openingWithTouch */);
                    }
                    float h = y - mInitialExpandY;
                    float h = (mIsTrackpadReverseScroll ? -1 : 1) * (y - mInitialExpandY);

                    // If the panel was collapsed when touching, we only need to check for the
                    // y-component of the gesture, as we have no conflicting horizontal gesture.
@@ -5182,6 +5192,7 @@ public final class NotificationPanelViewController implements ShadeSurface, Dump
                            mQsController.cancelJankMonitoring();
                        }
                    }
                    mIsTrackpadReverseScroll = false;
                    break;
            }
            return !mGestureWaitForTouchSlop || isTracking();
+16 −5
Original line number Diff line number Diff line
@@ -21,7 +21,9 @@ import com.android.systemui.classifier.FalsingCollector
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dump.DumpManager
import com.android.systemui.keyguard.WakefulnessLifecycle
import com.android.systemui.keyguard.domain.interactor.NaturalScrollingSettingObserver
import com.android.systemui.media.controls.ui.MediaHierarchyManager
import com.android.systemui.navigationbar.gestural.Utilities.isTrackpadScroll
import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.plugins.ActivityStarter.OnDismissAction
import com.android.systemui.plugins.FalsingManager
@@ -78,7 +80,8 @@ constructor(
    private val shadeRepository: ShadeRepository,
    private val shadeInteractor: ShadeInteractor,
    private val powerInteractor: PowerInteractor,
    private val splitShadeStateController: SplitShadeStateController
    private val splitShadeStateController: SplitShadeStateController,
    private val naturalScrollingSettingObserver: NaturalScrollingSettingObserver,
) : Dumpable {
    private var pulseHeight: Float = 0f

@@ -157,7 +160,8 @@ constructor(
    var mUdfpsKeyguardViewControllerLegacy: UdfpsKeyguardViewControllerLegacy? = null

    /** The touch helper responsible for the drag down animation. */
    val touchHelper = DragDownHelper(falsingManager, falsingCollector, this, context)
    val touchHelper = DragDownHelper(falsingManager, falsingCollector, this,
            naturalScrollingSettingObserver, context)

    private val splitShadeOverScroller: SplitShadeLockScreenOverScroller by lazy {
        splitShadeOverScrollerFactory.create({ qS }, { nsslController })
@@ -751,6 +755,7 @@ class DragDownHelper(
    private val falsingManager: FalsingManager,
    private val falsingCollector: FalsingCollector,
    private val dragDownCallback: LockscreenShadeTransitionController,
    private val naturalScrollingSettingObserver: NaturalScrollingSettingObserver,
    context: Context
) : Gefingerpoken {

@@ -765,6 +770,7 @@ class DragDownHelper(
    private var draggedFarEnough = false
    private var startingChild: ExpandableView? = null
    private var lastHeight = 0f
    private var isTrackpadReverseScroll = false
    var isDraggingDown = false
        private set

@@ -802,9 +808,11 @@ class DragDownHelper(
                startingChild = null
                initialTouchY = y
                initialTouchX = x
                isTrackpadReverseScroll = !naturalScrollingSettingObserver.isNaturalScrollingEnabled
                        && isTrackpadScroll(true, event)
            }
            MotionEvent.ACTION_MOVE -> {
                val h = y - initialTouchY
                val h = (if (isTrackpadReverseScroll) -1 else 1) * (y - initialTouchY)
                // Adjust the touch slop if another gesture may be being performed.
                val touchSlop =
                    if (event.classification == MotionEvent.CLASSIFICATION_AMBIGUOUS_GESTURE) {
@@ -834,7 +842,7 @@ class DragDownHelper(
        val y = event.y
        when (event.actionMasked) {
            MotionEvent.ACTION_MOVE -> {
                lastHeight = y - initialTouchY
                lastHeight = (if (isTrackpadReverseScroll) -1 else 1) * (y - initialTouchY)
                captureStartingChild(initialTouchX, initialTouchY)
                dragDownCallback.dragDownAmount = lastHeight + dragDownAmountOnStart
                if (startingChild != null) {
@@ -859,12 +867,14 @@ class DragDownHelper(
                        !isFalseTouch &&
                        dragDownCallback.canDragDown()
                ) {
                    dragDownCallback.onDraggedDown(startingChild, (y - initialTouchY).toInt())
                    val dragDown = (if (isTrackpadReverseScroll) -1 else 1) * (y - initialTouchY)
                    dragDownCallback.onDraggedDown(startingChild, dragDown.toInt())
                    if (startingChild != null) {
                        expandCallback.setUserLockedChild(startingChild, false)
                        startingChild = null
                    }
                    isDraggingDown = false
                    isTrackpadReverseScroll = false
                } else {
                    stopDragging()
                    return false
@@ -943,6 +953,7 @@ class DragDownHelper(
            startingChild = null
        }
        isDraggingDown = false
        isTrackpadReverseScroll = false
        dragDownCallback.onDragDownReset()
    }

+5 −1
Original line number Diff line number Diff line
@@ -100,6 +100,7 @@ import com.android.systemui.keyguard.domain.interactor.KeyguardFaceAuthInteracto
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor;
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractorFactory;
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor;
import com.android.systemui.keyguard.domain.interactor.NaturalScrollingSettingObserver;
import com.android.systemui.keyguard.shared.KeyguardShadeMigrationNssl;
import com.android.systemui.keyguard.ui.viewmodel.DreamingToLockscreenTransitionViewModel;
import com.android.systemui.keyguard.ui.viewmodel.GoneToDreamingLockscreenHostedTransitionViewModel;
@@ -334,6 +335,7 @@ public class NotificationPanelViewControllerBaseTest extends SysuiTestCase {
    @Mock private CastController mCastController;
    @Mock private SharedNotificationContainerInteractor mSharedNotificationContainerInteractor;
    @Mock private KeyguardClockPositionAlgorithm mKeyguardClockPositionAlgorithm;
    @Mock private NaturalScrollingSettingObserver mNaturalScrollingSettingObserver;

    protected final int mMaxUdfpsBurnInOffsetY = 5;
    protected FakeFeatureFlagsClassic mFeatureFlags = new FakeFeatureFlagsClassic();
@@ -498,6 +500,7 @@ public class NotificationPanelViewControllerBaseTest extends SysuiTestCase {
        when(mScreenOffAnimationController.shouldAnimateClockChange()).thenReturn(true);
        when(mQs.getView()).thenReturn(mView);
        when(mQSFragment.getView()).thenReturn(mView);
        when(mNaturalScrollingSettingObserver.isNaturalScrollingEnabled()).thenReturn(true);
        doAnswer(invocation -> {
            mFragmentListener = invocation.getArgument(1);
            return null;
@@ -708,7 +711,8 @@ public class NotificationPanelViewControllerBaseTest extends SysuiTestCase {
                mKeyguardFaceAuthInteractor,
                new ResourcesSplitShadeStateController(),
                mPowerInteractor,
                mKeyguardClockPositionAlgorithm);
                mKeyguardClockPositionAlgorithm,
                mNaturalScrollingSettingObserver);
        mNotificationPanelViewController.initDependencies(
                mCentralSurfaces,
                null,
+5 −1
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ import androidx.test.filters.SmallTest
import com.android.systemui.ExpandHelper
import com.android.systemui.SysuiTestCase
import com.android.systemui.classifier.FalsingCollector
import com.android.systemui.keyguard.domain.interactor.NaturalScrollingSettingObserver
import com.android.systemui.plugins.FalsingManager
import com.android.systemui.statusbar.notification.row.ExpandableView
import com.android.systemui.util.mockito.mock
@@ -48,16 +49,19 @@ class DragDownHelperTest : SysuiTestCase() {
    private val dragDownloadCallback: LockscreenShadeTransitionController = mock()
    private val expandableView: ExpandableView = mock()
    private val expandCallback: ExpandHelper.Callback = mock()
    private val naturalScrollingSettingObserver: NaturalScrollingSettingObserver = mock()

    @Before
    fun setUp() {
        whenever(expandableView.collapsedHeight).thenReturn(collapsedHeight)
        whenever(naturalScrollingSettingObserver.isNaturalScrollingEnabled).thenReturn(true)

        dragDownHelper = DragDownHelper(
                falsingManager,
                falsingCollector,
                dragDownloadCallback,
                mContext
                naturalScrollingSettingObserver,
                mContext,
        ).also {
            it.expandCallback = expandCallback
        }
Loading