summaryrefslogtreecommitdiffstats
path: root/src/com/android/browser/KeyTracker.java
blob: 344e4f85f9fffd0e8d6aeaa4e324727dd61987b6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
/*
 * Copyright (C) 2006 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.browser;

import android.view.KeyEvent;
import android.view.ViewConfiguration;

class KeyTracker {

    public enum Stage {
        DOWN,           //!< the key has just been pressed
        SHORT_REPEAT,   //!< repeated key, but duration is under the long-press threshold
        LONG_REPEAT,    //!< repeated key, but duration is over the long-press threshold
        UP              //!< the key is being released
    }
    
    public enum State {
        KEEP_TRACKING,  //!< return this to continue to track the key
        DONE_TRACKING,  //!< return this if you handled the key, but need not track it anymore
        NOT_TRACKING    //!< return this if you will not handle this key
    }
    
    public interface OnKeyTracker {

        /** Called whenever there is a key event [down, short/long repeat, up]
            @param keyCode  The current keyCode (see KeyEvent class)
            @param msg      The message associated with the keyCode
            @maram stage    The state the key press is in [down, short/long repeat, up]
            @param duration The number of milliseconds since this key was initially pressed
            @return your state after seeing the key. If you return DONE_TRACKING or NOT_TRACKING,
                    you will not be called again for the lifetime of this key event.
        */
        public State onKeyTracker(int keyCode, KeyEvent event, Stage stage, int duration);
    }
    
    public KeyTracker(OnKeyTracker tracker) {
        mTracker = tracker;
    }
    
    public boolean doKeyDown(int keyCode, KeyEvent event) {
        long now = System.currentTimeMillis();
        Stage stage = null;

        // check if its a new/different key
        if (mKeyCode != keyCode || event.getRepeatCount() == 0) {
            mKeyCode = keyCode;
            mStartMS = now;
            stage = Stage.DOWN;
        }
        else if (mState == State.KEEP_TRACKING) {
            stage = (now - mStartMS) >= LONG_PRESS_DURATION_MS ? Stage.LONG_REPEAT : Stage.SHORT_REPEAT;
        }

        if (stage != null) {
            mEvent = event;        
            callTracker(stage, now);
        }

        return mState != State.NOT_TRACKING;
    }
    
    public boolean doKeyUp(int keyCode, KeyEvent event) {
        boolean handled = false;

        if (mState == State.KEEP_TRACKING && mKeyCode == keyCode) {
            mEvent = event;
            callTracker(Stage.UP, System.currentTimeMillis());
            handled = mState != State.NOT_TRACKING;
        }
        mKeyCode = NOT_A_KEYCODE;
        return handled;
    }
    
    private void callTracker(Stage stage, long now) {
        mState = mTracker.onKeyTracker(mKeyCode, mEvent, stage, (int)(now - mStartMS));
    }
    
    private void dump() {
        System.out.println(" key=" + mKeyCode + " dur=" + (System.currentTimeMillis() - mStartMS) +
                            " state=" + mState);
    }

    private int             mKeyCode = NOT_A_KEYCODE;
    private KeyEvent        mEvent;
    private long            mStartMS;
    private State           mState;
    private OnKeyTracker    mTracker;

    private static final int LONG_PRESS_DURATION_MS = 
            ViewConfiguration.getLongPressTimeout();
    private static final int NOT_A_KEYCODE = -123456;
}