1 /* 2 * Copyright (C) 2011 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 17 package com.android.inputmethod.latin; 18 19 import android.content.Context; 20 import android.graphics.Rect; 21 import android.util.AttributeSet; 22 import android.view.MotionEvent; 23 import android.view.View; 24 import android.widget.LinearLayout; 25 26 public final class InputView extends LinearLayout { 27 private View mSuggestionStripContainer; 28 private View mKeyboardView; 29 private int mKeyboardTopPadding; 30 31 private boolean mIsForwardingEvent; 32 private final Rect mInputViewRect = new Rect(); 33 private final Rect mEventForwardingRect = new Rect(); 34 private final Rect mEventReceivingRect = new Rect(); 35 36 public InputView(Context context, AttributeSet attrs) { 37 super(context, attrs, 0); 38 } 39 40 public void setKeyboardGeometry(int keyboardTopPadding) { 41 mKeyboardTopPadding = keyboardTopPadding; 42 } 43 44 @Override 45 protected void onFinishInflate() { 46 mSuggestionStripContainer = findViewById(R.id.suggestions_container); 47 mKeyboardView = findViewById(R.id.keyboard_view); 48 } 49 50 @Override 51 public boolean dispatchTouchEvent(MotionEvent me) { 52 if (mSuggestionStripContainer.getVisibility() == VISIBLE 53 && mKeyboardView.getVisibility() == VISIBLE 54 && forwardTouchEvent(me)) { 55 return true; 56 } 57 return super.dispatchTouchEvent(me); 58 } 59 60 // The touch events that hit the top padding of keyboard should be forwarded to 61 // {@link SuggestionStripView}. 62 private boolean forwardTouchEvent(MotionEvent me) { 63 final Rect rect = mInputViewRect; 64 this.getGlobalVisibleRect(rect); 65 final int x = (int)me.getX() + rect.left; 66 final int y = (int)me.getY() + rect.top; 67 68 final Rect forwardingRect = mEventForwardingRect; 69 mKeyboardView.getGlobalVisibleRect(forwardingRect); 70 if (!mIsForwardingEvent && !forwardingRect.contains(x, y)) { 71 return false; 72 } 73 74 final int forwardingLimitY = forwardingRect.top + mKeyboardTopPadding; 75 boolean sendToTarget = false; 76 77 switch (me.getAction()) { 78 case MotionEvent.ACTION_DOWN: 79 if (y < forwardingLimitY) { 80 // This down event and further move and up events should be forwarded to the target. 81 mIsForwardingEvent = true; 82 sendToTarget = true; 83 } 84 break; 85 case MotionEvent.ACTION_MOVE: 86 sendToTarget = mIsForwardingEvent; 87 break; 88 case MotionEvent.ACTION_UP: 89 case MotionEvent.ACTION_CANCEL: 90 sendToTarget = mIsForwardingEvent; 91 mIsForwardingEvent = false; 92 break; 93 } 94 95 if (!sendToTarget) { 96 return false; 97 } 98 99 final Rect receivingRect = mEventReceivingRect; 100 mSuggestionStripContainer.getGlobalVisibleRect(receivingRect); 101 final int translatedX = x - receivingRect.left; 102 final int translatedY; 103 if (y < forwardingLimitY) { 104 // The forwarded event should have coordinates that are inside of the target. 105 translatedY = Math.min(y - receivingRect.top, receivingRect.height() - 1); 106 } else { 107 translatedY = y - receivingRect.top; 108 } 109 me.setLocation(translatedX, translatedY); 110 mSuggestionStripContainer.dispatchTouchEvent(me); 111 return true; 112 } 113 } 114