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

Commit d7f5a51b authored by Victoria Lease's avatar Victoria Lease Committed by Android (Google) Code Review
Browse files

Merge "IME support for trackball and generic motion events" into jb-mr1-dev

parents e11dc0dd b38070ca
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -10217,6 +10217,7 @@ package android.inputmethodservice {
    method public final android.os.IBinder onBind(android.content.Intent);
    method public abstract android.inputmethodservice.AbstractInputMethodService.AbstractInputMethodImpl onCreateInputMethodInterface();
    method public abstract android.inputmethodservice.AbstractInputMethodService.AbstractInputMethodSessionImpl onCreateInputMethodSessionInterface();
    method public boolean onGenericMotionEvent(android.view.MotionEvent);
    method public boolean onTrackballEvent(android.view.MotionEvent);
  }
@@ -10229,6 +10230,7 @@ package android.inputmethodservice {
  public abstract class AbstractInputMethodService.AbstractInputMethodSessionImpl implements android.view.inputmethod.InputMethodSession {
    ctor public AbstractInputMethodService.AbstractInputMethodSessionImpl();
    method public void dispatchGenericMotionEvent(int, android.view.MotionEvent, android.view.inputmethod.InputMethodSession.EventCallback);
    method public void dispatchKeyEvent(int, android.view.KeyEvent, android.view.inputmethod.InputMethodSession.EventCallback);
    method public void dispatchTrackballEvent(int, android.view.MotionEvent, android.view.inputmethod.InputMethodSession.EventCallback);
    method public boolean isEnabled();
@@ -26697,6 +26699,7 @@ package android.view.inputmethod {
  public abstract interface InputMethodSession {
    method public abstract void appPrivateCommand(java.lang.String, android.os.Bundle);
    method public abstract void dispatchGenericMotionEvent(int, android.view.MotionEvent, android.view.inputmethod.InputMethodSession.EventCallback);
    method public abstract void dispatchKeyEvent(int, android.view.KeyEvent, android.view.inputmethod.InputMethodSession.EventCallback);
    method public abstract void dispatchTrackballEvent(int, android.view.MotionEvent, android.view.inputmethod.InputMethodSession.EventCallback);
    method public abstract void displayCompletions(android.view.inputmethod.CompletionInfo[]);
+89 −17
Original line number Diff line number Diff line
@@ -66,15 +66,54 @@ public class Input {
                }
            } else if (command.equals("tap")) {
                if (args.length == 3) {
                    sendTap(Float.parseFloat(args[1]), Float.parseFloat(args[2]));
                    sendTap(InputDevice.SOURCE_TOUCHSCREEN, Float.parseFloat(args[1]), Float.parseFloat(args[2]));
                    return;
                }
            } else if (command.equals("swipe")) {
                if (args.length == 5) {
                    sendSwipe(Float.parseFloat(args[1]), Float.parseFloat(args[2]),
                    sendSwipe(InputDevice.SOURCE_TOUCHSCREEN, Float.parseFloat(args[1]), Float.parseFloat(args[2]),
                            Float.parseFloat(args[3]), Float.parseFloat(args[4]));
                    return;
                }
            } else if (command.equals("touchscreen") || command.equals("touchpad")) {
                // determine input source
                int inputSource = InputDevice.SOURCE_TOUCHSCREEN;
                if (command.equals("touchpad")) {
                    inputSource = InputDevice.SOURCE_TOUCHPAD;
                }
                // determine subcommand
                if (args.length > 1) {
                    String subcommand = args[1];
                    if (subcommand.equals("tap")) {
                        if (args.length == 4) {
                            sendTap(inputSource, Float.parseFloat(args[2]),
                                    Float.parseFloat(args[3]));
                            return;
                        }
                    } else if (subcommand.equals("swipe")) {
                        if (args.length == 6) {
                            sendSwipe(inputSource, Float.parseFloat(args[2]),
                                    Float.parseFloat(args[3]), Float.parseFloat(args[4]),
                                    Float.parseFloat(args[5]));
                            return;
                        }
                    }
                }
            } else if (command.equals("trackball")) {
                // determine subcommand
                if (args.length > 1) {
                    String subcommand = args[1];
                    if (subcommand.equals("press")) {
                        sendTap(InputDevice.SOURCE_TRACKBALL, 0.0f, 0.0f);
                        return;
                    } else if (subcommand.equals("roll")) {
                        if (args.length == 4) {
                            sendMove(InputDevice.SOURCE_TRACKBALL, Float.parseFloat(args[2]),
                                    Float.parseFloat(args[3]));
                            return;
                        }
                    }
                }
            } else {
                System.err.println("Error: Unknown command: " + command);
                showUsage();
@@ -127,33 +166,64 @@ public class Input {
                KeyCharacterMap.VIRTUAL_KEYBOARD, 0, 0, InputDevice.SOURCE_KEYBOARD));
    }

    private void sendTap(float x, float y) {
    private void sendTap(int inputSource, float x, float y) {
        long now = SystemClock.uptimeMillis();
        injectPointerEvent(MotionEvent.obtain(now, now, MotionEvent.ACTION_DOWN, x, y, 0));
        injectPointerEvent(MotionEvent.obtain(now, now, MotionEvent.ACTION_UP, x, y, 0));
        injectMotionEvent(inputSource, MotionEvent.ACTION_DOWN, now, x, y, 1.0f);
        injectMotionEvent(inputSource, MotionEvent.ACTION_UP, now, x, y, 0.0f);
    }

    private void sendSwipe(float x1, float y1, float x2, float y2) {
    private void sendSwipe(int inputSource, float x1, float y1, float x2, float y2) {
        final int NUM_STEPS = 11;
        long now = SystemClock.uptimeMillis();
        injectPointerEvent(MotionEvent.obtain(now, now, MotionEvent.ACTION_DOWN, x1, y1, 0));
        injectMotionEvent(inputSource, MotionEvent.ACTION_DOWN, now, x1, y1, 1.0f);
        for (int i = 1; i < NUM_STEPS; i++) {
            float alpha = (float) i / NUM_STEPS;
            injectPointerEvent(MotionEvent.obtain(now, now, MotionEvent.ACTION_MOVE,
                    lerp(x1, x2, alpha), lerp(y1, y2, alpha), 0));
            injectMotionEvent(inputSource, MotionEvent.ACTION_MOVE, now, lerp(x1, x2, alpha),
                    lerp(y1, y2, alpha), 1.0f);
        }
        injectMotionEvent(inputSource, MotionEvent.ACTION_UP, now, x1, y1, 0.0f);
    }
        injectPointerEvent(MotionEvent.obtain(now, now, MotionEvent.ACTION_UP, x2, y2, 0));

    /**
     * Sends a simple zero-pressure move event.
     *
     * @param inputSource the InputDevice.SOURCE_* sending the input event
     * @param dx change in x coordinate due to move
     * @param dy change in y coordinate due to move
     */
    private void sendMove(int inputSource, float dx, float dy) {
        long now = SystemClock.uptimeMillis();
        injectMotionEvent(inputSource, MotionEvent.ACTION_MOVE, now, dx, dy, 0.0f);
    }

    private void injectKeyEvent(KeyEvent event) {
        Log.i(TAG, "InjectKeyEvent: " + event);
        Log.i(TAG, "injectKeyEvent: " + event);
        InputManager.getInstance().injectInputEvent(event,
                InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH);
    }

    private void injectPointerEvent(MotionEvent event) {
        event.setSource(InputDevice.SOURCE_TOUCHSCREEN);
        Log.i("Input", "InjectPointerEvent: " + event);
    /**
     * Builds a MotionEvent and injects it into the event stream.
     *
     * @param inputSource the InputDevice.SOURCE_* sending the input event
     * @param action the MotionEvent.ACTION_* for the event
     * @param when the value of SystemClock.uptimeMillis() at which the event happened
     * @param x x coordinate of event
     * @param y y coordinate of event
     * @param pressure pressure of event
     */
    private void injectMotionEvent(int inputSource, int action, long when, float x, float y, float pressure) {
        final float DEFAULT_SIZE = 1.0f;
        final int DEFAULT_META_STATE = 0;
        final float DEFAULT_PRECISION_X = 1.0f;
        final float DEFAULT_PRECISION_Y = 1.0f;
        final int DEFAULT_DEVICE_ID = 0;
        final int DEFAULT_EDGE_FLAGS = 0;
        MotionEvent event = MotionEvent.obtain(when, when, action, x, y, pressure, DEFAULT_SIZE,
                DEFAULT_META_STATE, DEFAULT_PRECISION_X, DEFAULT_PRECISION_Y, DEFAULT_DEVICE_ID,
                DEFAULT_EDGE_FLAGS);
        event.setSource(inputSource);
        Log.i("Input", "injectMotionEvent: " + event);
        InputManager.getInstance().injectInputEvent(event,
                InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH);
    }
@@ -166,7 +236,9 @@ public class Input {
        System.err.println("usage: input ...");
        System.err.println("       input text <string>");
        System.err.println("       input keyevent <key code number or name>");
        System.err.println("       input tap <x> <y>");
        System.err.println("       input swipe <x1> <y1> <x2> <y2>");
        System.err.println("       input [touchscreen|touchpad] tap <x> <y>");
        System.err.println("       input [touchscreen|touchpad] swipe <x1> <y1> <x2> <y2>");
        System.err.println("       input trackball press");
        System.err.println("       input trackball roll <dx> <dy>");
    }
}
+29 −0
Original line number Diff line number Diff line
@@ -149,6 +149,17 @@ public abstract class AbstractInputMethodService extends Service
                callback.finishedEvent(seq, handled);
            }
        }

        /**
         * Take care of dispatching incoming generic motion events to the appropriate
         * callbacks on the service, and tell the client when this is done.
         */
        public void dispatchGenericMotionEvent(int seq, MotionEvent event, EventCallback callback) {
            boolean handled = onGenericMotionEvent(event);
            if (callback != null) {
                callback.finishedEvent(seq, handled);
            }
        }
    }
    
    /**
@@ -189,7 +200,25 @@ public abstract class AbstractInputMethodService extends Service
        return new IInputMethodWrapper(this, mInputMethod);
    }
    
    /**
     * Implement this to handle trackball events on your input method.
     *
     * @param event The motion event being received.
     * @return True if the event was handled in this function, false otherwise.
     * @see View#onTrackballEvent
     */
    public boolean onTrackballEvent(MotionEvent event) {
        return false;
    }

    /**
     * Implement this to handle generic motion events on your input method.
     *
     * @param event The motion event being received.
     * @return True if the event was handled in this function, false otherwise.
     * @see View#onGenericMotionEvent
     */
    public boolean onGenericMotionEvent(MotionEvent event) {
        return false;
    }
}
+16 −0
Original line number Diff line number Diff line
@@ -43,6 +43,7 @@ class IInputMethodSessionWrapper extends IInputMethodSession.Stub
    private static final int DO_UPDATE_EXTRACTED_TEXT = 67;
    private static final int DO_DISPATCH_KEY_EVENT = 70;
    private static final int DO_DISPATCH_TRACKBALL_EVENT = 80;
    private static final int DO_DISPATCH_GENERIC_MOTION_EVENT = 85;
    private static final int DO_UPDATE_SELECTION = 90;
    private static final int DO_UPDATE_CURSOR = 95;
    private static final int DO_APP_PRIVATE_COMMAND = 100;
@@ -109,6 +110,15 @@ class IInputMethodSessionWrapper extends IInputMethodSession.Stub
                args.recycle();
                return;
            }
            case DO_DISPATCH_GENERIC_MOTION_EVENT: {
                SomeArgs args = (SomeArgs)msg.obj;
                mInputMethodSession.dispatchGenericMotionEvent(msg.arg1,
                        (MotionEvent)args.arg1,
                        new InputMethodEventCallbackWrapper(
                                (IInputMethodCallback)args.arg2));
                args.recycle();
                return;
            }
            case DO_UPDATE_SELECTION: {
                SomeArgs args = (SomeArgs)msg.obj;
                mInputMethodSession.updateSelection(args.argi1, args.argi2,
@@ -167,6 +177,12 @@ class IInputMethodSessionWrapper extends IInputMethodSession.Stub
                event, callback));
    }

    public void dispatchGenericMotionEvent(int seq, MotionEvent event,
            IInputMethodCallback callback) {
        mCaller.executeOrSendMessage(mCaller.obtainMessageIOO(DO_DISPATCH_GENERIC_MOTION_EVENT, seq,
                event, callback));
    }

    public void updateSelection(int oldSelStart, int oldSelEnd,
            int newSelStart, int newSelEnd, int candidatesStart, int candidatesEnd) {
        mCaller.executeOrSendMessage(mCaller.obtainMessageIIIIII(DO_UPDATE_SELECTION,
+23 −2
Original line number Diff line number Diff line
@@ -1773,7 +1773,7 @@ public class InputMethodService extends AbstractInputMethodService {
     * Override this to intercept special key multiple events before they are
     * processed by the
     * application.  If you return true, the application will not itself
     * process the event.  If you return true, the normal application processing
     * process the event.  If you return false, the normal application processing
     * will occur as if the IME had not seen the event at all.
     * 
     * <p>The default implementation always returns false, except when
@@ -1788,7 +1788,7 @@ public class InputMethodService extends AbstractInputMethodService {
    /**
     * Override this to intercept key up events before they are processed by the
     * application.  If you return true, the application will not itself
     * process the event.  If you return true, the normal application processing
     * process the event.  If you return false, the normal application processing
     * will occur as if the IME had not seen the event at all.
     * 
     * <p>The default implementation intercepts {@link KeyEvent#KEYCODE_BACK
@@ -1806,8 +1806,29 @@ public class InputMethodService extends AbstractInputMethodService {
        return doMovementKey(keyCode, event, MOVEMENT_UP);
    }

    /**
     * Override this to intercept trackball motion events before they are
     * processed by the application.
     * If you return true, the application will not itself process the event.
     * If you return false, the normal application processing will occur as if
     * the IME had not seen the event at all.
     */
    @Override
    public boolean onTrackballEvent(MotionEvent event) {
        if (DEBUG) Log.v(TAG, "onTrackballEvent: " + event);
        return false;
    }

    /**
     * Override this to intercept generic motion events before they are
     * processed by the application.
     * If you return true, the application will not itself process the event.
     * If you return false, the normal application processing will occur as if
     * the IME had not seen the event at all.
     */
    @Override
    public boolean onGenericMotionEvent(MotionEvent event) {
        if (DEBUG) Log.v(TAG, "onGenericMotionEvent(): event " + event);
        return false;
    }

Loading