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

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

Clip touch event at SoftInputWindow to handle the event from Inset

Bug: 3238092
Change-Id: I92d98bed75957c8db149e1ad87defe24d44f4d53
parent 57ffc002
Loading
Loading
Loading
Loading
+57 −0
Original line number Diff line number Diff line
@@ -19,11 +19,16 @@ package android.inputmethodservice;
import android.app.Dialog;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.graphics.Rect;
import android.os.IBinder;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;

import java.lang.Math;

/**
 * A SoftInputWindow is a Dialog that is intended to be used for a top-level input
 * method window.  It will be displayed along the edge of the screen, moving
@@ -32,6 +37,7 @@ import android.view.WindowManager;
 */
class SoftInputWindow extends Dialog {
    final KeyEvent.DispatcherState mDispatcherState;
    private final Rect mBounds = new Rect();
    
    public void setToken(IBinder token) {
        WindowManager.LayoutParams lp = getWindow().getAttributes();
@@ -64,6 +70,13 @@ class SoftInputWindow extends Dialog {
        mDispatcherState.reset();
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        getWindow().getDecorView().getHitRect(mBounds);
        final MotionEvent event = clipMotionEvent(ev, mBounds);
        return super.dispatchTouchEvent(event);
    }

    /**
     * Get the size of the DockWindow.
     * 
@@ -150,4 +163,48 @@ class SoftInputWindow extends Dialog {
                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
                WindowManager.LayoutParams.FLAG_DIM_BEHIND);
    }

    private static MotionEvent clipMotionEvent(MotionEvent me, Rect bounds) {
        final int pointerCount = me.getPointerCount();
        boolean shouldClip = false;
        for (int pointerIndex = 0; pointerIndex < pointerCount; pointerIndex++) {
            final int x = (int)me.getX(pointerIndex);
            final int y = (int)me.getY(pointerIndex);
            if (!bounds.contains(x, y)) {
                shouldClip = true;
                break;
            }
        }
        if (!shouldClip)
            return me;

        if (pointerCount == 1) {
            final int x = (int)me.getX();
            final int y = (int)me.getY();
            me.setLocation(
                    Math.max(bounds.left, Math.min(x, bounds.right - 1)),
                    Math.max(bounds.top, Math.min(y, bounds.bottom - 1)));
            return me;
        }

        final int[] pointerIds = new int[pointerCount];
        final MotionEvent.PointerCoords[] pointerCoords =
            new MotionEvent.PointerCoords[pointerCount];
        for (int pointerIndex = 0; pointerIndex < pointerCount; pointerIndex++) {
            pointerIds[pointerIndex] = me.getPointerId(pointerIndex);
            final MotionEvent.PointerCoords coords = new MotionEvent.PointerCoords();
            me.getPointerCoords(pointerIndex, coords);
            pointerCoords[pointerIndex] = coords;
            final int x = (int)coords.x;
            final int y = (int)coords.y;
            if (!bounds.contains(x, y)) {
                coords.x = Math.max(bounds.left, Math.min(x, bounds.right - 1));
                coords.y = Math.max(bounds.top, Math.min(y, bounds.bottom - 1));
            }
        }
        return MotionEvent.obtain(
                me.getDownTime(), me.getEventTime(), me.getAction(), pointerCount, pointerIds,
                pointerCoords, me.getMetaState(), me.getXPrecision(), me.getYPrecision(),
                me.getDeviceId(), me.getEdgeFlags(), me.getSource(), me.getFlags());
    }
}