1 /*
2  * Copyright (C) 2021 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.android.launcher3.util;
17 
18 import android.content.Context;
19 import android.graphics.Canvas;
20 import android.os.SystemClock;
21 import android.view.MotionEvent;
22 import android.widget.EdgeEffect;
23 
24 import com.android.launcher3.BuildConfig;
25 import com.android.launcher3.Utilities;
26 import com.android.systemui.plugins.shared.LauncherOverlayManager.LauncherOverlayTouchProxy;
27 
28 /**
29  * Extension of {@link EdgeEffect} which shows the Launcher overlay
30  */
31 public class OverlayEdgeEffect extends EdgeEffectCompat {
32 
33     protected float mDistance;
34     protected final LauncherOverlayTouchProxy mOverlay;
35     protected boolean mIsScrolling;
36     protected final boolean mIsRtl;
37 
OverlayEdgeEffect(Context context, LauncherOverlayTouchProxy overlay)38     public OverlayEdgeEffect(Context context, LauncherOverlayTouchProxy overlay) {
39         super(context);
40         mOverlay = overlay;
41         mIsRtl = Utilities.isRtl(context.getResources());
42     }
43 
44     @Override
getDistance()45     public float getDistance() {
46         return mDistance;
47     }
48 
onPullDistance(float deltaDistance, float displacement)49     public float onPullDistance(float deltaDistance, float displacement) {
50         // Fallback implementation, will never actually get called
51         if (BuildConfig.IS_DEBUG_DEVICE) {
52             throw new RuntimeException("Wrong method called");
53         }
54         MotionEvent mv = MotionEvent.obtain(SystemClock.uptimeMillis(), SystemClock.uptimeMillis(),
55                 MotionEvent.ACTION_MOVE, displacement, 0, 0);
56         try {
57             return onPullDistance(deltaDistance, displacement, mv);
58         } finally {
59             mv.recycle();
60         }
61     }
62 
63     @Override
onPullDistance(float deltaDistance, float displacement, MotionEvent ev)64     public float onPullDistance(float deltaDistance, float displacement, MotionEvent ev) {
65         mDistance = Math.max(0f, deltaDistance + mDistance);
66         if (!mIsScrolling) {
67             int originalAction = ev.getAction();
68             ev.setAction(MotionEvent.ACTION_DOWN);
69             mOverlay.onOverlayMotionEvent(ev, 0);
70             ev.setAction(originalAction);
71             mIsScrolling = true;
72         }
73         mOverlay.onOverlayMotionEvent(ev, mDistance);
74         return mDistance > 0 ? deltaDistance : 0;
75     }
76 
77     @Override
onAbsorb(int velocity)78     public void onAbsorb(int velocity) { }
79 
80     @Override
isFinished()81     public boolean isFinished() {
82         return mDistance <= 0;
83     }
84 
85     @Override
onRelease()86     public void onRelease() {
87         // Fallback implementation, will never actually get called
88         if (BuildConfig.IS_DEBUG_DEVICE) {
89             throw new RuntimeException("Wrong method called");
90         }
91         MotionEvent mv = MotionEvent.obtain(SystemClock.uptimeMillis(), SystemClock.uptimeMillis(),
92                 MotionEvent.ACTION_UP, mDistance, 0, 0);
93         onRelease(mv);
94         mv.recycle();
95     }
96 
97     @Override
onFlingVelocity(int velocity)98     public void onFlingVelocity(int velocity) {
99         mOverlay.onFlingVelocity(velocity);
100     }
101 
102     @Override
onRelease(MotionEvent ev)103     public void onRelease(MotionEvent ev) {
104         if (mIsScrolling) {
105             int originalAction = ev.getAction();
106             ev.setAction(MotionEvent.ACTION_UP);
107             mOverlay.onOverlayMotionEvent(ev, mDistance);
108             ev.setAction(originalAction);
109 
110             mDistance = 0;
111             mIsScrolling = false;
112         }
113     }
114 
115     @Override
draw(Canvas canvas)116     public boolean draw(Canvas canvas) {
117         return false;
118     }
119 
finish()120     public void finish() {
121         mDistance = 0;
122     }
123 }
124