blob: 6eb88be48569cb0926530677f308f6220143c2c6 [file] [log] [blame]
Daniel Sandlere97a7762012-03-19 22:56:42 -04001/*
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
17package com.android.systemui.statusbar.policy;
18
Daniel Sandlerc26185b2012-08-29 15:49:53 -040019import android.animation.ObjectAnimator;
Daniel Sandlere97a7762012-03-19 22:56:42 -040020import android.content.Context;
Daniel Sandlerc26185b2012-08-29 15:49:53 -040021import android.content.res.TypedArray;
22import android.graphics.Canvas;
23import android.os.SystemClock;
Daniel Sandlere97a7762012-03-19 22:56:42 -040024import android.util.AttributeSet;
Daniel Sandlerc26185b2012-08-29 15:49:53 -040025import android.util.Slog;
Daniel Sandlere97a7762012-03-19 22:56:42 -040026import android.view.MotionEvent;
27import android.view.View;
28
29import com.android.systemui.R;
30
31public class DeadZone extends View {
Daniel Sandlerc26185b2012-08-29 15:49:53 -040032 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
Daniel Sandler25bb8ee2012-08-30 17:10:50 -040038 private static final boolean CHATTY = true; // print to logcat when we eat a click
39
Daniel Sandlerc26185b2012-08-29 15:49:53 -040040 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
Daniel Sandlere97a7762012-03-19 22:56:42 -040058 public DeadZone(Context context, AttributeSet attrs) {
59 this(context, attrs, 0);
60 }
61
62 public DeadZone(Context context, AttributeSet attrs, int defStyle) {
63 super(context, attrs);
Daniel Sandlerc26185b2012-08-29 15:49:53 -040064
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
Daniel Sandler25bb8ee2012-08-30 17:10:50 -040081 setFlashOnTouchCapture(context.getResources().getBoolean(R.bool.config_dead_zone_flash));
Daniel Sandlerc26185b2012-08-29 15:49:53 -040082 }
83
84 static float lerp(float a, float b, float f) {
85 return (b - a) * f + a;
86 }
87
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
99 public void setFlashOnTouchCapture(boolean dbg) {
100 mShouldFlash = dbg;
101 mFlashFrac = 0f;
102 postInvalidate();
Daniel Sandlere97a7762012-03-19 22:56:42 -0400103 }
104
Daniel Sandler25bb8ee2012-08-30 17:10:50 -0400105 // I made you a touch event...
Daniel Sandlere97a7762012-03-19 22:56:42 -0400106 @Override
Daniel Sandlerc26185b2012-08-29 15:49:53 -0400107 public boolean onTouchEvent(MotionEvent event) {
Daniel Sandler25bb8ee2012-08-30 17:10:50 -0400108 if (DEBUG) {
Daniel Sandlerc26185b2012-08-29 15:49:53 -0400109 Slog.v(TAG, this + " onTouch: " + MotionEvent.actionToString(event.getAction()));
Daniel Sandler25bb8ee2012-08-30 17:10:50 -0400110 }
Daniel Sandlerc26185b2012-08-29 15:49:53 -0400111
112 final int action = event.getAction();
113 if (action == MotionEvent.ACTION_OUTSIDE) {
114 poke(event);
115 } else if (action == MotionEvent.ACTION_DOWN) {
Daniel Sandler25bb8ee2012-08-30 17:10:50 -0400116 if (DEBUG) {
Daniel Sandlerc26185b2012-08-29 15:49:53 -0400117 Slog.v(TAG, this + " ACTION_DOWN: " + event.getX() + "," + event.getY());
Daniel Sandler25bb8ee2012-08-30 17:10:50 -0400118 }
Daniel Sandlerc26185b2012-08-29 15:49:53 -0400119 int size = (int) getSize(event.getEventTime());
120 if ((mVertical && event.getX() < size) || event.getY() < size) {
Daniel Sandler25bb8ee2012-08-30 17:10:50 -0400121 if (CHATTY) {
122 Slog.v(TAG, "consuming errant click: (" + event.getX() + "," + event.getY() + ")");
123 }
Daniel Sandlerc26185b2012-08-29 15:49:53 -0400124 if (mShouldFlash) {
125 post(mDebugFlash);
126 postInvalidate();
127 }
Daniel Sandler25bb8ee2012-08-30 17:10:50 -0400128 return true; // ...but I eated it
Daniel Sandlerc26185b2012-08-29 15:49:53 -0400129 }
130 }
131 return false;
132 }
133
134 public void poke(MotionEvent event) {
135 mLastPokeTime = event.getEventTime();
136 if (DEBUG)
137 Slog.v(TAG, "poked! size=" + getSize(mLastPokeTime));
Daniel Sandler4f6ec7f2013-01-17 16:02:36 -0500138 if (mShouldFlash) postInvalidate();
Daniel Sandlerc26185b2012-08-29 15:49:53 -0400139 }
140
141 public void setFlash(float f) {
142 mFlashFrac = f;
143 postInvalidate();
144 }
145
146 public float getFlash() {
147 return mFlashFrac;
148 }
149
150 @Override
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);
Daniel Sandlere97a7762012-03-19 22:56:42 -0400164 }
165}