• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2012 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 
17 package com.android.systemui.statusbar.policy;
18 
19 import android.animation.ObjectAnimator;
20 import android.content.Context;
21 import android.content.res.TypedArray;
22 import android.graphics.Canvas;
23 import android.os.SystemClock;
24 import android.util.AttributeSet;
25 import android.util.Slog;
26 import android.view.MotionEvent;
27 import android.view.View;
28 
29 import com.android.systemui.R;
30 
31 public class DeadZone extends View {
32     public static final String TAG = "DeadZone";
33 
34     public static final boolean DEBUG = false;
35     public static final int HORIZONTAL = 0;
36     public static final int VERTICAL = 1;
37 
38     private static final boolean CHATTY = true; // print to logcat when we eat a click
39 
40     private boolean mShouldFlash;
41     private float mFlashFrac = 0f;
42 
43     private int mSizeMax;
44     private int mSizeMin;
45     // Upon activity elsewhere in the UI, the dead zone will hold steady for
46     // mHold ms, then move back over the course of mDecay ms
47     private int mHold, mDecay;
48     private boolean mVertical;
49     private long mLastPokeTime;
50 
51     private final Runnable mDebugFlash = new Runnable() {
52         @Override
53         public void run() {
54             ObjectAnimator.ofFloat(DeadZone.this, "flash", 1f, 0f).setDuration(150).start();
55         }
56     };
57 
DeadZone(Context context, AttributeSet attrs)58     public DeadZone(Context context, AttributeSet attrs) {
59         this(context, attrs, 0);
60     }
61 
DeadZone(Context context, AttributeSet attrs, int defStyle)62     public DeadZone(Context context, AttributeSet attrs, int defStyle) {
63         super(context, attrs);
64 
65         TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.DeadZone,
66                 defStyle, 0);
67 
68         mHold = a.getInteger(R.styleable.DeadZone_holdTime, 0);
69         mDecay = a.getInteger(R.styleable.DeadZone_decayTime, 0);
70 
71         mSizeMin = a.getDimensionPixelSize(R.styleable.DeadZone_minSize, 0);
72         mSizeMax = a.getDimensionPixelSize(R.styleable.DeadZone_maxSize, 0);
73 
74         int index = a.getInt(R.styleable.DeadZone_orientation, -1);
75         mVertical = (index == VERTICAL);
76 
77         if (DEBUG)
78             Slog.v(TAG, this + " size=[" + mSizeMin + "-" + mSizeMax + "] hold=" + mHold
79                     + (mVertical ? " vertical" : " horizontal"));
80 
81         setFlashOnTouchCapture(context.getResources().getBoolean(R.bool.config_dead_zone_flash));
82     }
83 
lerp(float a, float b, float f)84     static float lerp(float a, float b, float f) {
85         return (b - a) * f + a;
86     }
87 
getSize(long now)88     private float getSize(long now) {
89         if (mSizeMax == 0)
90             return 0;
91         long dt = (now - mLastPokeTime);
92         if (dt > mHold + mDecay)
93             return mSizeMin;
94         if (dt < mHold)
95             return mSizeMax;
96         return (int) lerp(mSizeMax, mSizeMin, (float) (dt - mHold) / mDecay);
97     }
98 
setFlashOnTouchCapture(boolean dbg)99     public void setFlashOnTouchCapture(boolean dbg) {
100         mShouldFlash = dbg;
101         mFlashFrac = 0f;
102         postInvalidate();
103     }
104 
105     // I made you a touch event...
106     @Override
onTouchEvent(MotionEvent event)107     public boolean onTouchEvent(MotionEvent event) {
108         if (DEBUG) {
109             Slog.v(TAG, this + " onTouch: " + MotionEvent.actionToString(event.getAction()));
110         }
111 
112         final int action = event.getAction();
113         if (action == MotionEvent.ACTION_OUTSIDE) {
114             poke(event);
115         } else if (action == MotionEvent.ACTION_DOWN) {
116             if (DEBUG) {
117                 Slog.v(TAG, this + " ACTION_DOWN: " + event.getX() + "," + event.getY());
118             }
119             int size = (int) getSize(event.getEventTime());
120             if ((mVertical && event.getX() < size) || event.getY() < size) {
121                 if (CHATTY) {
122                     Slog.v(TAG, "consuming errant click: (" + event.getX() + "," + event.getY() + ")");
123                 }
124                 if (mShouldFlash) {
125                     post(mDebugFlash);
126                     postInvalidate();
127                 }
128                 return true; // ...but I eated it
129             }
130         }
131         return false;
132     }
133 
poke(MotionEvent event)134     public void poke(MotionEvent event) {
135         mLastPokeTime = event.getEventTime();
136         if (DEBUG)
137             Slog.v(TAG, "poked! size=" + getSize(mLastPokeTime));
138         if (mShouldFlash) postInvalidate();
139     }
140 
setFlash(float f)141     public void setFlash(float f) {
142         mFlashFrac = f;
143         postInvalidate();
144     }
145 
getFlash()146     public float getFlash() {
147         return mFlashFrac;
148     }
149 
150     @Override
onDraw(Canvas can)151     public void onDraw(Canvas can) {
152         if (!mShouldFlash || mFlashFrac <= 0f) {
153             return;
154         }
155 
156         final int size = (int) getSize(SystemClock.uptimeMillis());
157         can.clipRect(0, 0, mVertical ? size : can.getWidth(), mVertical ? can.getHeight() : size);
158         final float frac = DEBUG ? (mFlashFrac - 0.5f) + 0.5f : mFlashFrac;
159         can.drawARGB((int) (frac * 0xFF), 0xDD, 0xEE, 0xAA);
160 
161         if (DEBUG && size > mSizeMin)
162             // crazy aggressive redrawing here, for debugging only
163             postInvalidateDelayed(100);
164     }
165 }
166