PasswordEntryKeyboardView.java revision 0b31970cac04259a6e20dfc6d6e42cd9532528e3
1/*
2 * Copyright (C) 2010 Google Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 * use this file except in compliance with the License. You may obtain a copy of
6 * 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, WITHOUT
12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 * License for the specific language governing permissions and limitations under
14 * the License.
15 */
16
17package com.android.internal.widget;
18
19import android.content.Context;
20import android.inputmethodservice.Keyboard;
21import android.inputmethodservice.KeyboardView;
22import android.util.AttributeSet;
23import android.view.LayoutInflater;
24import android.view.MotionEvent;
25import android.widget.PopupWindow;
26import com.android.internal.R;
27
28public class PasswordEntryKeyboardView extends KeyboardView {
29
30    public static final int KEYCODE_OPTIONS = -100;
31    static final int KEYCODE_SHIFT_LONGPRESS = -101;
32    static final int KEYCODE_VOICE = -102;
33    static final int KEYCODE_F1 = -103;
34    static final int KEYCODE_NEXT_LANGUAGE = -104;
35
36    private boolean mExtensionVisible;
37    private PasswordEntryKeyboardView mExtension;
38    private PopupWindow mExtensionPopup;
39    private boolean mFirstEvent;
40
41    public PasswordEntryKeyboardView(Context context, AttributeSet attrs) {
42        super(context, attrs);
43    }
44
45    public PasswordEntryKeyboardView(Context context, AttributeSet attrs, int defStyle) {
46        super(context, attrs, defStyle);
47    }
48
49    @Override
50    public boolean onTouchEvent(MotionEvent me) {
51        if (((PasswordEntryKeyboard) getKeyboard()).getExtension() == 0) {
52            return super.onTouchEvent(me);
53        }
54        if (me.getY() < 0) {
55            if (mExtensionVisible) {
56                int action = me.getAction();
57                if (mFirstEvent) action = MotionEvent.ACTION_DOWN;
58                mFirstEvent = false;
59                MotionEvent translated = MotionEvent.obtain(me.getEventTime(), me.getEventTime(),
60                        action,
61                        me.getX(), me.getY() + mExtension.getHeight(), me.getMetaState());
62                boolean result = mExtension.onTouchEvent(translated);
63                translated.recycle();
64                if (me.getAction() == MotionEvent.ACTION_UP
65                        || me.getAction() == MotionEvent.ACTION_CANCEL) {
66                    closeExtension();
67                }
68                return result;
69            } else {
70                if (openExtension()) {
71                    MotionEvent cancel = MotionEvent.obtain(me.getDownTime(), me.getEventTime(),
72                            MotionEvent.ACTION_CANCEL, me.getX() - 100, me.getY() - 100, 0);
73                    super.onTouchEvent(cancel);
74                    cancel.recycle();
75                    if (mExtension.getHeight() > 0) {
76                        MotionEvent translated = MotionEvent.obtain(me.getEventTime(),
77                                me.getEventTime(),
78                                MotionEvent.ACTION_DOWN,
79                                me.getX(), me.getY() + mExtension.getHeight(),
80                                me.getMetaState());
81                        mExtension.onTouchEvent(translated);
82                        translated.recycle();
83                    } else {
84                        mFirstEvent = true;
85                    }
86                }
87                return true;
88            }
89        } else if (mExtensionVisible) {
90            closeExtension();
91            // Send a down event into the main keyboard first
92            MotionEvent down = MotionEvent.obtain(me.getEventTime(), me.getEventTime(),
93                    MotionEvent.ACTION_DOWN, me.getX(), me.getY(), me.getMetaState());
94            super.onTouchEvent(down);
95            down.recycle();
96            // Send the actual event
97            return super.onTouchEvent(me);
98        } else {
99            return super.onTouchEvent(me);
100        }
101    }
102
103    private boolean openExtension() {
104        if (((PasswordEntryKeyboard) getKeyboard()).getExtension() == 0) return false;
105        makePopupWindow();
106        mExtensionVisible = true;
107        return true;
108    }
109
110    private void makePopupWindow() {
111        if (mExtensionPopup == null) {
112            int[] windowLocation = new int[2];
113            mExtensionPopup = new PopupWindow(getContext());
114            mExtensionPopup.setBackgroundDrawable(null);
115            LayoutInflater li = (LayoutInflater) getContext().getSystemService(
116                    Context.LAYOUT_INFLATER_SERVICE);
117            mExtension = (PasswordEntryKeyboardView) li.inflate(
118                    R.layout.password_keyboard_input, null);
119            mExtension.setOnKeyboardActionListener(getOnKeyboardActionListener());
120            mExtension.setPopupParent(this);
121            mExtension.setPopupOffset(0, -windowLocation[1]);
122            Keyboard keyboard;
123            mExtension.setKeyboard(keyboard = new PasswordEntryKeyboard(getContext(),
124                    ((PasswordEntryKeyboard) getKeyboard()).getExtension()));
125            mExtensionPopup.setContentView(mExtension);
126            mExtensionPopup.setWidth(getWidth());
127            mExtensionPopup.setHeight(keyboard.getHeight());
128            getLocationInWindow(windowLocation);
129            // TODO: Fix the "- 30".
130            mExtension.setPopupOffset(0, -windowLocation[1] - 30);
131            mExtensionPopup.showAtLocation(this, 0, 0, -keyboard.getHeight()
132                    + windowLocation[1]);
133        } else {
134            mExtension.setVisibility(VISIBLE);
135        }
136    }
137
138    @Override
139    public void closing() {
140        super.closing();
141        if (mExtensionPopup != null && mExtensionPopup.isShowing()) {
142            mExtensionPopup.dismiss();
143            mExtensionPopup = null;
144        }
145    }
146
147    private void closeExtension() {
148        mExtension.setVisibility(INVISIBLE);
149        mExtension.closing();
150        mExtensionVisible = false;
151    }
152}
153