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