186f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato/*
286f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato * Copyright (C) 2008 The Android Open Source Project
386f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato *
486f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato * Licensed under the Apache License, Version 2.0 (the "License");
586f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato * you may not use this file except in compliance with the License.
686f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato * You may obtain a copy of the License at
786f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato *
886f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato *      http://www.apache.org/licenses/LICENSE-2.0
986f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato *
1086f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato * Unless required by applicable law or agreed to in writing, software
1186f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato * distributed under the License is distributed on an "AS IS" BASIS,
1286f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1386f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato * See the License for the specific language governing permissions and
1486f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato * limitations under the License.
1586f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato */
1686f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato
17fd52b18d9bf3cd62c7a07058536e9f97db65beeaJoe Onoratopackage com.android.systemui.statusbar.policy;
1886f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato
19a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandlerimport android.animation.AnimatorSet;
20a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandlerimport android.animation.ObjectAnimator;
2186f9bd2fd054522e36f84776056cd07531ead9cfJoe Onoratoimport android.content.Context;
2286f9bd2fd054522e36f84776056cd07531ead9cfJoe Onoratoimport android.content.res.TypedArray;
2386f9bd2fd054522e36f84776056cd07531ead9cfJoe Onoratoimport android.graphics.drawable.Drawable;
24a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandlerimport android.graphics.Canvas;
25a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandlerimport android.graphics.RectF;
2686f9bd2fd054522e36f84776056cd07531ead9cfJoe Onoratoimport android.os.RemoteException;
2786f9bd2fd054522e36f84776056cd07531ead9cfJoe Onoratoimport android.os.SystemClock;
2886f9bd2fd054522e36f84776056cd07531ead9cfJoe Onoratoimport android.os.ServiceManager;
2986f9bd2fd054522e36f84776056cd07531ead9cfJoe Onoratoimport android.util.AttributeSet;
30aa051d66afa791872bfe362a94765dece07cd4c5Daniel Sandlerimport android.view.accessibility.AccessibilityEvent;
31804eb858348dbe2c8564aa930b6349a5571b5476Daniel Sandlerimport android.view.HapticFeedbackConstants;
3286f9bd2fd054522e36f84776056cd07531ead9cfJoe Onoratoimport android.view.IWindowManager;
33bbda99d2086d79ac70b403cad38a47c35af84adfJeff Brownimport android.view.InputDevice;
346b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brownimport android.view.KeyCharacterMap;
3586f9bd2fd054522e36f84776056cd07531ead9cfJoe Onoratoimport android.view.KeyEvent;
3686f9bd2fd054522e36f84776056cd07531ead9cfJoe Onoratoimport android.view.MotionEvent;
37aa051d66afa791872bfe362a94765dece07cd4c5Daniel Sandlerimport android.view.SoundEffectConstants;
38a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandlerimport android.view.View;
39804eb858348dbe2c8564aa930b6349a5571b5476Daniel Sandlerimport android.view.ViewConfiguration;
4086f9bd2fd054522e36f84776056cd07531ead9cfJoe Onoratoimport android.widget.ImageView;
4186f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato
4286f9bd2fd054522e36f84776056cd07531ead9cfJoe Onoratoimport com.android.systemui.R;
4386f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato
4486f9bd2fd054522e36f84776056cd07531ead9cfJoe Onoratopublic class KeyButtonView extends ImageView {
45fd52b18d9bf3cd62c7a07058536e9f97db65beeaJoe Onorato    private static final String TAG = "StatusBar.KeyButtonView";
46fd52b18d9bf3cd62c7a07058536e9f97db65beeaJoe Onorato
4796f4818ef41141649337d4dee09f837594e93d09Daniel Sandler    final float GLOW_MAX_SCALE_FACTOR = 1.8f;
48bceff71b9231643090d0dad6e3f1e1aac6fda1a2Justin Ho    final float BUTTON_QUIESCENT_ALPHA = 0.6f;
4996f4818ef41141649337d4dee09f837594e93d09Daniel Sandler
5086f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato    IWindowManager mWindowManager;
5186f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato    long mDownTime;
5286f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato    int mCode;
53aa051d66afa791872bfe362a94765dece07cd4c5Daniel Sandler    int mTouchSlop;
54a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler    Drawable mGlowBG;
55a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler    float mGlowAlpha = 0f, mGlowScale = 1f, mDrawingAlpha = 1f;
5644a4616bf780f131f8d78b46a075844800088860Daniel Sandler    boolean mSupportsLongpress = true;
57c638c1eb1bbed67d7d8f0d43f39137d766366f54Daniel Sandler    RectF mRect = new RectF(0f,0f,0f,0f);
58aa051d66afa791872bfe362a94765dece07cd4c5Daniel Sandler
59804eb858348dbe2c8564aa930b6349a5571b5476Daniel Sandler    Runnable mCheckLongPress = new Runnable() {
60804eb858348dbe2c8564aa930b6349a5571b5476Daniel Sandler        public void run() {
61804eb858348dbe2c8564aa930b6349a5571b5476Daniel Sandler            if (isPressed()) {
6244a4616bf780f131f8d78b46a075844800088860Daniel Sandler                // Slog.d("KeyButtonView", "longpressed: " + this);
63a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler                if (mCode != 0) {
6498392efb24d8aac36a4cfa85106812e17d5984f9Jeff Brown                    sendEvent(KeyEvent.ACTION_DOWN, KeyEvent.FLAG_LONG_PRESS);
65a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler                    sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
66a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler                } else {
67a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler                    // Just an old-fashioned ImageView
68a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler                    performLongClick();
69a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler                }
70804eb858348dbe2c8564aa930b6349a5571b5476Daniel Sandler            }
71804eb858348dbe2c8564aa930b6349a5571b5476Daniel Sandler        }
72804eb858348dbe2c8564aa930b6349a5571b5476Daniel Sandler    };
7386f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato
7486f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato    public KeyButtonView(Context context, AttributeSet attrs) {
7586f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato        this(context, attrs, 0);
7686f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato    }
7786f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato
7886f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato    public KeyButtonView(Context context, AttributeSet attrs, int defStyle) {
7986f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato        super(context, attrs);
8086f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato
8186f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.KeyButtonView,
8286f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato                defStyle, 0);
8386f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato
8486f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato        mCode = a.getInteger(R.styleable.KeyButtonView_keyCode, 0);
8544a4616bf780f131f8d78b46a075844800088860Daniel Sandler
8644a4616bf780f131f8d78b46a075844800088860Daniel Sandler        mSupportsLongpress = a.getBoolean(R.styleable.KeyButtonView_keyRepeat, true);
87a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler
88a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler        mGlowBG = a.getDrawable(R.styleable.KeyButtonView_glowBackground);
89a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler        if (mGlowBG != null) {
90bceff71b9231643090d0dad6e3f1e1aac6fda1a2Justin Ho            mDrawingAlpha = BUTTON_QUIESCENT_ALPHA;
9186f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato        }
9286f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato
9386f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato        a.recycle();
9486f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato
9586f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato        mWindowManager = IWindowManager.Stub.asInterface(
9686f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato                ServiceManager.getService(Context.WINDOW_SERVICE));
97641bad449ba3b971500843c6bf7bf6f08363d09eJoe Onorato
98641bad449ba3b971500843c6bf7bf6f08363d09eJoe Onorato        setClickable(true);
99aa051d66afa791872bfe362a94765dece07cd4c5Daniel Sandler        mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
10086f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato    }
10186f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato
102a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler    @Override
103a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler    protected void onDraw(Canvas canvas) {
104a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler        if (mGlowBG != null) {
105a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler            canvas.save();
106a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler            final int w = getWidth();
107a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler            final int h = getHeight();
108a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler            canvas.scale(mGlowScale, mGlowScale, w*0.5f, h*0.5f);
109a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler            mGlowBG.setBounds(0, 0, w, h);
110a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler            mGlowBG.setAlpha((int)(mGlowAlpha * 255));
111a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler            mGlowBG.draw(canvas);
112a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler            canvas.restore();
113c638c1eb1bbed67d7d8f0d43f39137d766366f54Daniel Sandler            mRect.right = w;
114c638c1eb1bbed67d7d8f0d43f39137d766366f54Daniel Sandler            mRect.bottom = h;
115c638c1eb1bbed67d7d8f0d43f39137d766366f54Daniel Sandler            canvas.saveLayerAlpha(mRect, (int)(mDrawingAlpha * 255), Canvas.ALL_SAVE_FLAG);
116a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler        }
117a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler        super.onDraw(canvas);
118a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler        if (mGlowBG != null) {
119a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler            canvas.restore();
120a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler        }
121a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler    }
122a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler
123a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler    public float getDrawingAlpha() {
124a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler        if (mGlowBG == null) return 0;
125a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler        return mDrawingAlpha;
126a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler    }
127a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler
128a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler    public void setDrawingAlpha(float x) {
129a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler        if (mGlowBG == null) return;
130a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler        mDrawingAlpha = x;
131a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler        invalidate();
132a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler    }
133a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler
134a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler    public float getGlowAlpha() {
135a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler        if (mGlowBG == null) return 0;
136a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler        return mGlowAlpha;
137a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler    }
138a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler
139a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler    public void setGlowAlpha(float x) {
140a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler        if (mGlowBG == null) return;
141a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler        mGlowAlpha = x;
142a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler        invalidate();
143a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler    }
144a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler
145a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler    public float getGlowScale() {
146a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler        if (mGlowBG == null) return 0;
147a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler        return mGlowScale;
148a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler    }
149a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler
150a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler    public void setGlowScale(float x) {
151a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler        if (mGlowBG == null) return;
152a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler        mGlowScale = x;
153a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler        final float w = getWidth();
154a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler        final float h = getHeight();
15596f4818ef41141649337d4dee09f837594e93d09Daniel Sandler        if (GLOW_MAX_SCALE_FACTOR <= 1.0f) {
15696f4818ef41141649337d4dee09f837594e93d09Daniel Sandler            // this only works if we know the glow will never leave our bounds
157a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler            invalidate();
158a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler        } else {
15996f4818ef41141649337d4dee09f837594e93d09Daniel Sandler            final float rx = (w * (GLOW_MAX_SCALE_FACTOR - 1.0f)) / 2.0f + 1.0f;
16096f4818ef41141649337d4dee09f837594e93d09Daniel Sandler            final float ry = (h * (GLOW_MAX_SCALE_FACTOR - 1.0f)) / 2.0f + 1.0f;
161a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler            com.android.systemui.SwipeHelper.invalidateGlobalRegion(
162a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler                    this,
1635298582717494098fcdf115d832c8e871340d0b5Daniel Sandler                    new RectF(getLeft() - rx,
1645298582717494098fcdf115d832c8e871340d0b5Daniel Sandler                              getTop() - ry,
1655298582717494098fcdf115d832c8e871340d0b5Daniel Sandler                              getRight() + rx,
1665298582717494098fcdf115d832c8e871340d0b5Daniel Sandler                              getBottom() + ry));
16796f4818ef41141649337d4dee09f837594e93d09Daniel Sandler
16896f4818ef41141649337d4dee09f837594e93d09Daniel Sandler            // also invalidate our immediate parent to help avoid situations where nearby glows
16996f4818ef41141649337d4dee09f837594e93d09Daniel Sandler            // interfere
17096f4818ef41141649337d4dee09f837594e93d09Daniel Sandler            ((View)getParent()).invalidate();
171a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler        }
172a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler    }
173a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler
174a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler    public void setPressed(boolean pressed) {
175a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler        if (mGlowBG != null) {
176a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler            if (pressed != isPressed()) {
177a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler                AnimatorSet as = new AnimatorSet();
178a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler                if (pressed) {
179bceff71b9231643090d0dad6e3f1e1aac6fda1a2Justin Ho                    if (mGlowScale < GLOW_MAX_SCALE_FACTOR)
180bceff71b9231643090d0dad6e3f1e1aac6fda1a2Justin Ho                        mGlowScale = GLOW_MAX_SCALE_FACTOR;
181bceff71b9231643090d0dad6e3f1e1aac6fda1a2Justin Ho                    if (mGlowAlpha < BUTTON_QUIESCENT_ALPHA)
182bceff71b9231643090d0dad6e3f1e1aac6fda1a2Justin Ho                        mGlowAlpha = BUTTON_QUIESCENT_ALPHA;
183a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler                    setDrawingAlpha(1f);
184a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler                    as.playTogether(
185a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler                        ObjectAnimator.ofFloat(this, "glowAlpha", 1f),
18696f4818ef41141649337d4dee09f837594e93d09Daniel Sandler                        ObjectAnimator.ofFloat(this, "glowScale", GLOW_MAX_SCALE_FACTOR)
187a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler                    );
188a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler                    as.setDuration(50);
189a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler                } else {
190a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler                    as.playTogether(
191a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler                        ObjectAnimator.ofFloat(this, "glowAlpha", 0f),
192a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler                        ObjectAnimator.ofFloat(this, "glowScale", 1f),
193bceff71b9231643090d0dad6e3f1e1aac6fda1a2Justin Ho                        ObjectAnimator.ofFloat(this, "drawingAlpha", BUTTON_QUIESCENT_ALPHA)
194a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler                    );
195a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler                    as.setDuration(500);
196a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler                }
197a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler                as.start();
198a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler            }
199a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler        }
200a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler        super.setPressed(pressed);
201a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler    }
202a375c94fca986d76d21f8cb9a3eb29f1ef88c4a8Daniel Sandler
20386f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato    public boolean onTouchEvent(MotionEvent ev) {
20486f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato        final int action = ev.getAction();
20586f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato        int x, y;
20686f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato
20786f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato        switch (action) {
20886f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato            case MotionEvent.ACTION_DOWN:
2097a1a2f0e9273afbde398d9804cfaa245f6adbf5dChristopher Tate                //Slog.d("KeyButtonView", "press");
21086f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato                mDownTime = SystemClock.uptimeMillis();
21144a4616bf780f131f8d78b46a075844800088860Daniel Sandler                setPressed(true);
21298392efb24d8aac36a4cfa85106812e17d5984f9Jeff Brown                if (mCode != 0) {
21398392efb24d8aac36a4cfa85106812e17d5984f9Jeff Brown                    sendEvent(KeyEvent.ACTION_DOWN, 0, mDownTime);
21498392efb24d8aac36a4cfa85106812e17d5984f9Jeff Brown                } else {
21598392efb24d8aac36a4cfa85106812e17d5984f9Jeff Brown                    // Provide the same haptic feedback that the system offers for virtual keys.
21698392efb24d8aac36a4cfa85106812e17d5984f9Jeff Brown                    performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY);
21798392efb24d8aac36a4cfa85106812e17d5984f9Jeff Brown                }
21844a4616bf780f131f8d78b46a075844800088860Daniel Sandler                if (mSupportsLongpress) {
21944a4616bf780f131f8d78b46a075844800088860Daniel Sandler                    removeCallbacks(mCheckLongPress);
22044a4616bf780f131f8d78b46a075844800088860Daniel Sandler                    postDelayed(mCheckLongPress, ViewConfiguration.getLongPressTimeout());
22144a4616bf780f131f8d78b46a075844800088860Daniel Sandler                }
22286f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato                break;
22386f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato            case MotionEvent.ACTION_MOVE:
22498392efb24d8aac36a4cfa85106812e17d5984f9Jeff Brown                x = (int)ev.getX();
22598392efb24d8aac36a4cfa85106812e17d5984f9Jeff Brown                y = (int)ev.getY();
22698392efb24d8aac36a4cfa85106812e17d5984f9Jeff Brown                setPressed(x >= -mTouchSlop
22798392efb24d8aac36a4cfa85106812e17d5984f9Jeff Brown                        && x < getWidth() + mTouchSlop
22898392efb24d8aac36a4cfa85106812e17d5984f9Jeff Brown                        && y >= -mTouchSlop
22998392efb24d8aac36a4cfa85106812e17d5984f9Jeff Brown                        && y < getHeight() + mTouchSlop);
23086f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato                break;
23186f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato            case MotionEvent.ACTION_CANCEL:
232804eb858348dbe2c8564aa930b6349a5571b5476Daniel Sandler                setPressed(false);
23398392efb24d8aac36a4cfa85106812e17d5984f9Jeff Brown                if (mCode != 0) {
23498392efb24d8aac36a4cfa85106812e17d5984f9Jeff Brown                    sendEvent(KeyEvent.ACTION_UP, KeyEvent.FLAG_CANCELED);
23598392efb24d8aac36a4cfa85106812e17d5984f9Jeff Brown                }
23698392efb24d8aac36a4cfa85106812e17d5984f9Jeff Brown                if (mSupportsLongpress) {
23798392efb24d8aac36a4cfa85106812e17d5984f9Jeff Brown                    removeCallbacks(mCheckLongPress);
238abb27777f4763d057d37a58936232f8e17f57de1Joe Onorato                }
239abb27777f4763d057d37a58936232f8e17f57de1Joe Onorato                break;
240abb27777f4763d057d37a58936232f8e17f57de1Joe Onorato            case MotionEvent.ACTION_UP:
241aa051d66afa791872bfe362a94765dece07cd4c5Daniel Sandler                final boolean doIt = isPressed();
242abb27777f4763d057d37a58936232f8e17f57de1Joe Onorato                setPressed(false);
24398392efb24d8aac36a4cfa85106812e17d5984f9Jeff Brown                if (mCode != 0) {
24498392efb24d8aac36a4cfa85106812e17d5984f9Jeff Brown                    if (doIt) {
24598392efb24d8aac36a4cfa85106812e17d5984f9Jeff Brown                        sendEvent(KeyEvent.ACTION_UP, 0);
24698392efb24d8aac36a4cfa85106812e17d5984f9Jeff Brown                        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
24798392efb24d8aac36a4cfa85106812e17d5984f9Jeff Brown                        playSoundEffect(SoundEffectConstants.CLICK);
2485ee1a3daf0fb274b2a5fdea797748b569495a621Patrick Dubroy                    } else {
24998392efb24d8aac36a4cfa85106812e17d5984f9Jeff Brown                        sendEvent(KeyEvent.ACTION_UP, KeyEvent.FLAG_CANCELED);
250aa051d66afa791872bfe362a94765dece07cd4c5Daniel Sandler                    }
25198392efb24d8aac36a4cfa85106812e17d5984f9Jeff Brown                } else {
25298392efb24d8aac36a4cfa85106812e17d5984f9Jeff Brown                    // no key code, just a regular ImageView
25398392efb24d8aac36a4cfa85106812e17d5984f9Jeff Brown                    if (doIt) {
25498392efb24d8aac36a4cfa85106812e17d5984f9Jeff Brown                        performClick();
25598392efb24d8aac36a4cfa85106812e17d5984f9Jeff Brown                    }
25698392efb24d8aac36a4cfa85106812e17d5984f9Jeff Brown                }
25798392efb24d8aac36a4cfa85106812e17d5984f9Jeff Brown                if (mSupportsLongpress) {
25898392efb24d8aac36a4cfa85106812e17d5984f9Jeff Brown                    removeCallbacks(mCheckLongPress);
25986f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato                }
26086f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato                break;
26186f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato        }
26286f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato
26386f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato        return true;
26486f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato    }
26586f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato
266bbda99d2086d79ac70b403cad38a47c35af84adfJeff Brown    void sendEvent(int action, int flags) {
267bbda99d2086d79ac70b403cad38a47c35af84adfJeff Brown        sendEvent(action, flags, SystemClock.uptimeMillis());
26886f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato    }
26986f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato
270bbda99d2086d79ac70b403cad38a47c35af84adfJeff Brown    void sendEvent(int action, int flags, long when) {
27198392efb24d8aac36a4cfa85106812e17d5984f9Jeff Brown        final int repeatCount = (flags & KeyEvent.FLAG_LONG_PRESS) != 0 ? 1 : 0;
27298392efb24d8aac36a4cfa85106812e17d5984f9Jeff Brown        final KeyEvent ev = new KeyEvent(mDownTime, when, action, mCode, repeatCount,
27398392efb24d8aac36a4cfa85106812e17d5984f9Jeff Brown                0, KeyCharacterMap.VIRTUAL_KEYBOARD, 0,
27498392efb24d8aac36a4cfa85106812e17d5984f9Jeff Brown                flags | KeyEvent.FLAG_FROM_SYSTEM | KeyEvent.FLAG_VIRTUAL_HARD_KEY,
27598392efb24d8aac36a4cfa85106812e17d5984f9Jeff Brown                InputDevice.SOURCE_KEYBOARD);
27686f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato        try {
277fd52b18d9bf3cd62c7a07058536e9f97db65beeaJoe Onorato            //Slog.d(TAG, "injecting event " + ev);
278bbda99d2086d79ac70b403cad38a47c35af84adfJeff Brown            mWindowManager.injectInputEventNoWait(ev);
27986f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato        } catch (RemoteException ex) {
28086f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato            // System process is dead
28186f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato        }
28286f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato    }
28386f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato}
28486f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato
28586f9bd2fd054522e36f84776056cd07531ead9cfJoe Onorato
286