1f451ed2012df7eb080de045a93a494aecd2775b4Tadashi G. Takaoka/* 2f451ed2012df7eb080de045a93a494aecd2775b4Tadashi G. Takaoka * Copyright (C) 2011 The Android Open Source Project 3f451ed2012df7eb080de045a93a494aecd2775b4Tadashi G. Takaoka * 48aa9963a895f9dd5bb1bc92ab2e4f461e058f87aTadashi G. Takaoka * Licensed under the Apache License, Version 2.0 (the "License"); 58aa9963a895f9dd5bb1bc92ab2e4f461e058f87aTadashi G. Takaoka * you may not use this file except in compliance with the License. 68aa9963a895f9dd5bb1bc92ab2e4f461e058f87aTadashi G. Takaoka * You may obtain a copy of the License at 7f451ed2012df7eb080de045a93a494aecd2775b4Tadashi G. Takaoka * 88aa9963a895f9dd5bb1bc92ab2e4f461e058f87aTadashi G. Takaoka * http://www.apache.org/licenses/LICENSE-2.0 9f451ed2012df7eb080de045a93a494aecd2775b4Tadashi G. Takaoka * 10f451ed2012df7eb080de045a93a494aecd2775b4Tadashi G. Takaoka * Unless required by applicable law or agreed to in writing, software 118aa9963a895f9dd5bb1bc92ab2e4f461e058f87aTadashi G. Takaoka * distributed under the License is distributed on an "AS IS" BASIS, 128aa9963a895f9dd5bb1bc92ab2e4f461e058f87aTadashi G. Takaoka * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 138aa9963a895f9dd5bb1bc92ab2e4f461e058f87aTadashi G. Takaoka * See the License for the specific language governing permissions and 148aa9963a895f9dd5bb1bc92ab2e4f461e058f87aTadashi G. Takaoka * limitations under the License. 15f451ed2012df7eb080de045a93a494aecd2775b4Tadashi G. Takaoka */ 16f451ed2012df7eb080de045a93a494aecd2775b4Tadashi G. Takaoka 17f451ed2012df7eb080de045a93a494aecd2775b4Tadashi G. Takaokapackage com.android.inputmethod.latin; 18f451ed2012df7eb080de045a93a494aecd2775b4Tadashi G. Takaoka 19f451ed2012df7eb080de045a93a494aecd2775b4Tadashi G. Takaokaimport android.content.Context; 20f451ed2012df7eb080de045a93a494aecd2775b4Tadashi G. Takaokaimport android.graphics.Rect; 21f451ed2012df7eb080de045a93a494aecd2775b4Tadashi G. Takaokaimport android.util.AttributeSet; 22f451ed2012df7eb080de045a93a494aecd2775b4Tadashi G. Takaokaimport android.view.MotionEvent; 23f451ed2012df7eb080de045a93a494aecd2775b4Tadashi G. Takaokaimport android.view.View; 24f451ed2012df7eb080de045a93a494aecd2775b4Tadashi G. Takaokaimport android.widget.LinearLayout; 25f451ed2012df7eb080de045a93a494aecd2775b4Tadashi G. Takaoka 26a28a05e971cc242b338331a3b78276fa95188d19Tadashi G. Takaokapublic final class InputView extends LinearLayout { 2752d220e71b2840b35d143afd248fe33e2cfebe91Tadashi G. Takaoka private View mSuggestionStripView; 28f451ed2012df7eb080de045a93a494aecd2775b4Tadashi G. Takaoka private View mKeyboardView; 29f451ed2012df7eb080de045a93a494aecd2775b4Tadashi G. Takaoka private int mKeyboardTopPadding; 30f451ed2012df7eb080de045a93a494aecd2775b4Tadashi G. Takaoka 31f451ed2012df7eb080de045a93a494aecd2775b4Tadashi G. Takaoka private boolean mIsForwardingEvent; 32f451ed2012df7eb080de045a93a494aecd2775b4Tadashi G. Takaoka private final Rect mInputViewRect = new Rect(); 33f451ed2012df7eb080de045a93a494aecd2775b4Tadashi G. Takaoka private final Rect mEventForwardingRect = new Rect(); 34f451ed2012df7eb080de045a93a494aecd2775b4Tadashi G. Takaoka private final Rect mEventReceivingRect = new Rect(); 35f451ed2012df7eb080de045a93a494aecd2775b4Tadashi G. Takaoka 3688f840d2a2a3b30cd65f10d9bc38902d8423da93Tadashi G. Takaoka public InputView(final Context context, final AttributeSet attrs) { 37f451ed2012df7eb080de045a93a494aecd2775b4Tadashi G. Takaoka super(context, attrs, 0); 38f451ed2012df7eb080de045a93a494aecd2775b4Tadashi G. Takaoka } 39f451ed2012df7eb080de045a93a494aecd2775b4Tadashi G. Takaoka 4088f840d2a2a3b30cd65f10d9bc38902d8423da93Tadashi G. Takaoka public void setKeyboardGeometry(final int keyboardTopPadding) { 41f451ed2012df7eb080de045a93a494aecd2775b4Tadashi G. Takaoka mKeyboardTopPadding = keyboardTopPadding; 42f451ed2012df7eb080de045a93a494aecd2775b4Tadashi G. Takaoka } 43f451ed2012df7eb080de045a93a494aecd2775b4Tadashi G. Takaoka 44f451ed2012df7eb080de045a93a494aecd2775b4Tadashi G. Takaoka @Override 45f451ed2012df7eb080de045a93a494aecd2775b4Tadashi G. Takaoka protected void onFinishInflate() { 4652d220e71b2840b35d143afd248fe33e2cfebe91Tadashi G. Takaoka mSuggestionStripView = findViewById(R.id.suggestion_strip_view); 47f451ed2012df7eb080de045a93a494aecd2775b4Tadashi G. Takaoka mKeyboardView = findViewById(R.id.keyboard_view); 48f451ed2012df7eb080de045a93a494aecd2775b4Tadashi G. Takaoka } 49f451ed2012df7eb080de045a93a494aecd2775b4Tadashi G. Takaoka 50f451ed2012df7eb080de045a93a494aecd2775b4Tadashi G. Takaoka @Override 5188f840d2a2a3b30cd65f10d9bc38902d8423da93Tadashi G. Takaoka public boolean dispatchTouchEvent(final MotionEvent me) { 5288f840d2a2a3b30cd65f10d9bc38902d8423da93Tadashi G. Takaoka if (mSuggestionStripView.getVisibility() != VISIBLE 5388f840d2a2a3b30cd65f10d9bc38902d8423da93Tadashi G. Takaoka || mKeyboardView.getVisibility() != VISIBLE) { 5488f840d2a2a3b30cd65f10d9bc38902d8423da93Tadashi G. Takaoka return super.dispatchTouchEvent(me); 55f451ed2012df7eb080de045a93a494aecd2775b4Tadashi G. Takaoka } 56f451ed2012df7eb080de045a93a494aecd2775b4Tadashi G. Takaoka 5788f840d2a2a3b30cd65f10d9bc38902d8423da93Tadashi G. Takaoka // The touch events that hit the top padding of keyboard should be forwarded to 5888f840d2a2a3b30cd65f10d9bc38902d8423da93Tadashi G. Takaoka // {@link SuggestionStripView}. 59f451ed2012df7eb080de045a93a494aecd2775b4Tadashi G. Takaoka final Rect rect = mInputViewRect; 60f451ed2012df7eb080de045a93a494aecd2775b4Tadashi G. Takaoka this.getGlobalVisibleRect(rect); 61f451ed2012df7eb080de045a93a494aecd2775b4Tadashi G. Takaoka final int x = (int)me.getX() + rect.left; 62f451ed2012df7eb080de045a93a494aecd2775b4Tadashi G. Takaoka final int y = (int)me.getY() + rect.top; 63f451ed2012df7eb080de045a93a494aecd2775b4Tadashi G. Takaoka 64f451ed2012df7eb080de045a93a494aecd2775b4Tadashi G. Takaoka final Rect forwardingRect = mEventForwardingRect; 65f451ed2012df7eb080de045a93a494aecd2775b4Tadashi G. Takaoka mKeyboardView.getGlobalVisibleRect(forwardingRect); 66f451ed2012df7eb080de045a93a494aecd2775b4Tadashi G. Takaoka if (!mIsForwardingEvent && !forwardingRect.contains(x, y)) { 6788f840d2a2a3b30cd65f10d9bc38902d8423da93Tadashi G. Takaoka return super.dispatchTouchEvent(me); 68f451ed2012df7eb080de045a93a494aecd2775b4Tadashi G. Takaoka } 69f451ed2012df7eb080de045a93a494aecd2775b4Tadashi G. Takaoka 70f451ed2012df7eb080de045a93a494aecd2775b4Tadashi G. Takaoka final int forwardingLimitY = forwardingRect.top + mKeyboardTopPadding; 71f451ed2012df7eb080de045a93a494aecd2775b4Tadashi G. Takaoka boolean sendToTarget = false; 72f451ed2012df7eb080de045a93a494aecd2775b4Tadashi G. Takaoka 73f451ed2012df7eb080de045a93a494aecd2775b4Tadashi G. Takaoka switch (me.getAction()) { 74f451ed2012df7eb080de045a93a494aecd2775b4Tadashi G. Takaoka case MotionEvent.ACTION_DOWN: 75f451ed2012df7eb080de045a93a494aecd2775b4Tadashi G. Takaoka if (y < forwardingLimitY) { 76f451ed2012df7eb080de045a93a494aecd2775b4Tadashi G. Takaoka // This down event and further move and up events should be forwarded to the target. 77f451ed2012df7eb080de045a93a494aecd2775b4Tadashi G. Takaoka mIsForwardingEvent = true; 78f451ed2012df7eb080de045a93a494aecd2775b4Tadashi G. Takaoka sendToTarget = true; 79f451ed2012df7eb080de045a93a494aecd2775b4Tadashi G. Takaoka } 80f451ed2012df7eb080de045a93a494aecd2775b4Tadashi G. Takaoka break; 81f451ed2012df7eb080de045a93a494aecd2775b4Tadashi G. Takaoka case MotionEvent.ACTION_MOVE: 82f451ed2012df7eb080de045a93a494aecd2775b4Tadashi G. Takaoka sendToTarget = mIsForwardingEvent; 83f451ed2012df7eb080de045a93a494aecd2775b4Tadashi G. Takaoka break; 84f451ed2012df7eb080de045a93a494aecd2775b4Tadashi G. Takaoka case MotionEvent.ACTION_UP: 85f451ed2012df7eb080de045a93a494aecd2775b4Tadashi G. Takaoka case MotionEvent.ACTION_CANCEL: 86f451ed2012df7eb080de045a93a494aecd2775b4Tadashi G. Takaoka sendToTarget = mIsForwardingEvent; 87f451ed2012df7eb080de045a93a494aecd2775b4Tadashi G. Takaoka mIsForwardingEvent = false; 88f451ed2012df7eb080de045a93a494aecd2775b4Tadashi G. Takaoka break; 89f451ed2012df7eb080de045a93a494aecd2775b4Tadashi G. Takaoka } 90f451ed2012df7eb080de045a93a494aecd2775b4Tadashi G. Takaoka 91f451ed2012df7eb080de045a93a494aecd2775b4Tadashi G. Takaoka if (!sendToTarget) { 9288f840d2a2a3b30cd65f10d9bc38902d8423da93Tadashi G. Takaoka return super.dispatchTouchEvent(me); 93f451ed2012df7eb080de045a93a494aecd2775b4Tadashi G. Takaoka } 94f451ed2012df7eb080de045a93a494aecd2775b4Tadashi G. Takaoka 95f451ed2012df7eb080de045a93a494aecd2775b4Tadashi G. Takaoka final Rect receivingRect = mEventReceivingRect; 9652d220e71b2840b35d143afd248fe33e2cfebe91Tadashi G. Takaoka mSuggestionStripView.getGlobalVisibleRect(receivingRect); 97f451ed2012df7eb080de045a93a494aecd2775b4Tadashi G. Takaoka final int translatedX = x - receivingRect.left; 98f451ed2012df7eb080de045a93a494aecd2775b4Tadashi G. Takaoka final int translatedY; 99f451ed2012df7eb080de045a93a494aecd2775b4Tadashi G. Takaoka if (y < forwardingLimitY) { 100f451ed2012df7eb080de045a93a494aecd2775b4Tadashi G. Takaoka // The forwarded event should have coordinates that are inside of the target. 101f451ed2012df7eb080de045a93a494aecd2775b4Tadashi G. Takaoka translatedY = Math.min(y - receivingRect.top, receivingRect.height() - 1); 102f451ed2012df7eb080de045a93a494aecd2775b4Tadashi G. Takaoka } else { 103f451ed2012df7eb080de045a93a494aecd2775b4Tadashi G. Takaoka translatedY = y - receivingRect.top; 104f451ed2012df7eb080de045a93a494aecd2775b4Tadashi G. Takaoka } 105f451ed2012df7eb080de045a93a494aecd2775b4Tadashi G. Takaoka me.setLocation(translatedX, translatedY); 10652d220e71b2840b35d143afd248fe33e2cfebe91Tadashi G. Takaoka mSuggestionStripView.dispatchTouchEvent(me); 107f451ed2012df7eb080de045a93a494aecd2775b4Tadashi G. Takaoka return true; 108f451ed2012df7eb080de045a93a494aecd2775b4Tadashi G. Takaoka } 109f451ed2012df7eb080de045a93a494aecd2775b4Tadashi G. Takaoka} 110