Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f451ed20 authored by Tadashi G. Takaoka's avatar Tadashi G. Takaoka
Browse files

Forward touch events above the keyboard to the suggestions strip

The gutter area between the suggestions strip and the top-row keys
looks like a part of the suggestions strip, and the touch events
landing on the area should be forwarded to the suggestions strip.

Bug: 5246673
Change-Id: I92af763be0feed21aa36ceffb5d575abe554f19e
parent e4ff4d6b
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -18,7 +18,7 @@
*/
-->

<LinearLayout
<com.android.inputmethod.latin.InputView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
    android:orientation="vertical"
@@ -61,4 +61,4 @@
        android:layout_alignParentBottom="true"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
</LinearLayout>
</com.android.inputmethod.latin.InputView>
+4 −2
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@ import android.view.inputmethod.EditorInfo;
import com.android.inputmethod.accessibility.AccessibleKeyboardViewProxy;
import com.android.inputmethod.keyboard.internal.ModifierKeyState;
import com.android.inputmethod.keyboard.internal.ShiftKeyState;
import com.android.inputmethod.latin.InputView;
import com.android.inputmethod.latin.LatinIME;
import com.android.inputmethod.latin.LatinImeLogger;
import com.android.inputmethod.latin.LocaleUtils;
@@ -62,7 +63,7 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
    private SubtypeSwitcher mSubtypeSwitcher;
    private SharedPreferences mPrefs;

    private View mCurrentInputView;
    private InputView mCurrentInputView;
    private LatinKeyboardView mKeyboardView;
    private LatinIME mInputMethodService;
    private String mPackageName;
@@ -230,6 +231,7 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
    private void setKeyboard(final Keyboard keyboard) {
        final Keyboard oldKeyboard = mKeyboardView.getKeyboard();
        mKeyboardView.setKeyboard(keyboard);
        mCurrentInputView.setKeyboardGeometry(keyboard.mTopPadding);
        mCurrentId = keyboard.mId;
        mSwitchState = getSwitchState(mCurrentId);
        updateShiftLockState(keyboard);
@@ -762,7 +764,7 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
        for (int i = 0; i < Utils.GCUtils.GC_TRY_LOOP_MAX && tryGC; ++i) {
            try {
                setContextThemeWrapper(mInputMethodService, newThemeIndex);
                mCurrentInputView = LayoutInflater.from(mThemeContext).inflate(
                mCurrentInputView = (InputView)LayoutInflater.from(mThemeContext).inflate(
                        R.layout.input_view, null);
                tryGC = false;
            } catch (OutOfMemoryError e) {
+112 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2011 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.inputmethod.latin;

import android.content.Context;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.LinearLayout;

public class InputView extends LinearLayout {
    private View mSuggestionsContainer;
    private View mKeyboardView;
    private int mKeyboardTopPadding;

    private boolean mIsForwardingEvent;
    private final Rect mInputViewRect = new Rect();
    private final Rect mEventForwardingRect = new Rect();
    private final Rect mEventReceivingRect = new Rect();

    public InputView(Context context, AttributeSet attrs) {
        super(context, attrs, 0);
    }

    public void setKeyboardGeometry(int keyboardTopPadding) {
        mKeyboardTopPadding = keyboardTopPadding;
    }

    @Override
    protected void onFinishInflate() {
        mSuggestionsContainer = findViewById(R.id.suggestions_container);
        mKeyboardView = findViewById(R.id.keyboard_view);
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent me) {
        if (mSuggestionsContainer.getVisibility() == VISIBLE
                && mKeyboardView.getVisibility() == VISIBLE
                && forwardTouchEvent(me)) {
            return true;
        }
        return super.dispatchTouchEvent(me);
    }

    // The touch events that hit the top padding of keyboard should be forwarded to SuggestionsView.
    private boolean forwardTouchEvent(MotionEvent me) {
        final Rect rect = mInputViewRect;
        this.getGlobalVisibleRect(rect);
        final int x = (int)me.getX() + rect.left;
        final int y = (int)me.getY() + rect.top;

        final Rect forwardingRect = mEventForwardingRect;
        mKeyboardView.getGlobalVisibleRect(forwardingRect);
        if (!mIsForwardingEvent && !forwardingRect.contains(x, y)) {
            return false;
        }

        final int forwardingLimitY = forwardingRect.top + mKeyboardTopPadding;
        boolean sendToTarget = false;

        switch (me.getAction()) {
        case MotionEvent.ACTION_DOWN:
            if (y < forwardingLimitY) {
                // This down event and further move and up events should be forwarded to the target.
                mIsForwardingEvent = true;
                sendToTarget = true;
            }
            break;
        case MotionEvent.ACTION_MOVE:
            sendToTarget = mIsForwardingEvent;
            break;
        case MotionEvent.ACTION_UP:
        case MotionEvent.ACTION_CANCEL:
            sendToTarget = mIsForwardingEvent;
            mIsForwardingEvent = false;
            break;
        }

        if (!sendToTarget) {
            return false;
        }

        final Rect receivingRect = mEventReceivingRect;
        mSuggestionsContainer.getGlobalVisibleRect(receivingRect);
        final int translatedX = x - receivingRect.left;
        final int translatedY;
        if (y < forwardingLimitY) {
            // The forwarded event should have coordinates that are inside of the target.
            translatedY = Math.min(y - receivingRect.top, receivingRect.height() - 1);
        } else {
            translatedY = y - receivingRect.top;
        }
        me.setLocation(translatedX, translatedY);
        mSuggestionsContainer.dispatchTouchEvent(me);
        return true;
    }
}