Merge "More native input dispatch work." into gingerbread

This commit is contained in:
Chris Tate
2010-07-07 17:43:12 -07:00
committed by Android (Google) Code Review
23 changed files with 892 additions and 6092 deletions

View File

@ -216,20 +216,7 @@ public abstract class WallpaperService extends Service {
@Override
public void handleTouch(MotionEvent event, Runnable finishedCallback) {
try {
synchronized (mLock) {
if (event.getAction() == MotionEvent.ACTION_MOVE) {
if (mPendingMove != null) {
mCaller.removeMessages(MSG_TOUCH_EVENT, mPendingMove);
mPendingMove.recycle();
}
mPendingMove = event;
} else {
mPendingMove = null;
}
Message msg = mCaller.obtainMessageO(MSG_TOUCH_EVENT,
event);
mCaller.sendMessage(msg);
}
dispatchPointer(event);
} finally {
finishedCallback.run();
}
@ -237,26 +224,6 @@ public abstract class WallpaperService extends Service {
};
final BaseIWindow mWindow = new BaseIWindow() {
@Override
public boolean onDispatchPointer(MotionEvent event, long eventTime,
boolean callWhenDone) {
synchronized (mLock) {
if (event.getAction() == MotionEvent.ACTION_MOVE) {
if (mPendingMove != null) {
mCaller.removeMessages(MSG_TOUCH_EVENT, mPendingMove);
mPendingMove.recycle();
}
mPendingMove = event;
} else {
mPendingMove = null;
}
Message msg = mCaller.obtainMessageO(MSG_TOUCH_EVENT,
event);
mCaller.sendMessage(msg);
}
return false;
}
@Override
public void resized(int w, int h, Rect coveredInsets,
Rect visibleInsets, boolean reportDraw, Configuration newConfig) {
@ -466,6 +433,22 @@ public abstract class WallpaperService extends Service {
*/
public void onSurfaceDestroyed(SurfaceHolder holder) {
}
private void dispatchPointer(MotionEvent event) {
synchronized (mLock) {
if (event.getAction() == MotionEvent.ACTION_MOVE) {
if (mPendingMove != null) {
mCaller.removeMessages(MSG_TOUCH_EVENT, mPendingMove);
mPendingMove.recycle();
}
mPendingMove = event;
} else {
mPendingMove = null;
}
Message msg = mCaller.obtainMessageO(MSG_TOUCH_EVENT, event);
mCaller.sendMessage(msg);
}
}
void updateSurface(boolean forceRelayout, boolean forceReport) {
if (mDestroyed) {
@ -523,10 +506,8 @@ public abstract class WallpaperService extends Service {
mInputChannel);
mCreated = true;
if (WindowManagerPolicy.ENABLE_NATIVE_INPUT_DISPATCH) {
InputQueue.registerInputChannel(mInputChannel, mInputHandler,
Looper.myQueue());
}
InputQueue.registerInputChannel(mInputChannel, mInputHandler,
Looper.myQueue());
}
mSurfaceHolder.mSurfaceLock.lock();
@ -770,10 +751,8 @@ public abstract class WallpaperService extends Service {
if (DEBUG) Log.v(TAG, "Removing window and destroying surface "
+ mSurfaceHolder.getSurface() + " of: " + this);
if (WindowManagerPolicy.ENABLE_NATIVE_INPUT_DISPATCH) {
if (mInputChannel != null) {
InputQueue.unregisterInputChannel(mInputChannel);
}
if (mInputChannel != null) {
InputQueue.unregisterInputChannel(mInputChannel);
}
mSession.remove(mWindow);
@ -782,13 +761,11 @@ public abstract class WallpaperService extends Service {
mSurfaceHolder.mSurface.release();
mCreated = false;
if (WindowManagerPolicy.ENABLE_NATIVE_INPUT_DISPATCH) {
// Dispose the input channel after removing the window so the Window Manager
// doesn't interpret the input channel being closed as an abnormal termination.
if (mInputChannel != null) {
mInputChannel.dispose();
mInputChannel = null;
}
// Dispose the input channel after removing the window so the Window Manager
// doesn't interpret the input channel being closed as an abnormal termination.
if (mInputChannel != null) {
mInputChannel.dispose();
mInputChannel = null;
}
}
}
@ -841,7 +818,7 @@ public abstract class WallpaperService extends Service {
public void dispatchPointer(MotionEvent event) {
if (mEngine != null) {
mEngine.mWindow.onDispatchPointer(event, event.getEventTime(), false);
mEngine.dispatchPointer(event);
}
}

View File

@ -46,9 +46,6 @@ oneway interface IWindow {
void resized(int w, int h, in Rect coveredInsets, in Rect visibleInsets,
boolean reportDraw, in Configuration newConfig);
void dispatchKey(in KeyEvent event);
void dispatchPointer(in MotionEvent event, long eventTime, boolean callWhenDone);
void dispatchTrackball(in MotionEvent event, long eventTime, boolean callWhenDone);
void dispatchAppVisibility(boolean visible);
void dispatchGetNewSurface();

View File

@ -109,10 +109,6 @@ interface IWindowSession {
void getDisplayFrame(IWindow window, out Rect outDisplayFrame);
void finishDrawing(IWindow window);
void finishKey(IWindow window);
MotionEvent getPendingPointerMove(IWindow window);
MotionEvent getPendingTrackballMove(IWindow window);
void setInTouchMode(boolean showFocus);
boolean getInTouchMode();

View File

@ -1,201 +0,0 @@
/*
* Copyright (C) 2008 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 android.view;
/**
* @hide
* This really belongs in services.jar; WindowManagerPolicy should go there too.
*/
public class RawInputEvent {
// Event class as defined by EventHub.
public static final int CLASS_KEYBOARD = 0x00000001;
public static final int CLASS_ALPHAKEY = 0x00000002;
public static final int CLASS_TOUCHSCREEN = 0x00000004;
public static final int CLASS_TRACKBALL = 0x00000008;
public static final int CLASS_TOUCHSCREEN_MT = 0x00000010;
public static final int CLASS_DPAD = 0x00000020;
// More special classes for QueuedEvent below.
public static final int CLASS_CONFIGURATION_CHANGED = 0x10000000;
// Event types.
public static final int EV_SYN = 0x00;
public static final int EV_KEY = 0x01;
public static final int EV_REL = 0x02;
public static final int EV_ABS = 0x03;
public static final int EV_MSC = 0x04;
public static final int EV_SW = 0x05;
public static final int EV_LED = 0x11;
public static final int EV_SND = 0x12;
public static final int EV_REP = 0x14;
public static final int EV_FF = 0x15;
public static final int EV_PWR = 0x16;
public static final int EV_FF_STATUS = 0x17;
// Platform-specific event types.
public static final int EV_DEVICE_ADDED = 0x10000000;
public static final int EV_DEVICE_REMOVED = 0x20000000;
// Special key (EV_KEY) scan codes for pointer buttons.
public static final int BTN_FIRST = 0x100;
public static final int BTN_MISC = 0x100;
public static final int BTN_0 = 0x100;
public static final int BTN_1 = 0x101;
public static final int BTN_2 = 0x102;
public static final int BTN_3 = 0x103;
public static final int BTN_4 = 0x104;
public static final int BTN_5 = 0x105;
public static final int BTN_6 = 0x106;
public static final int BTN_7 = 0x107;
public static final int BTN_8 = 0x108;
public static final int BTN_9 = 0x109;
public static final int BTN_MOUSE = 0x110;
public static final int BTN_LEFT = 0x110;
public static final int BTN_RIGHT = 0x111;
public static final int BTN_MIDDLE = 0x112;
public static final int BTN_SIDE = 0x113;
public static final int BTN_EXTRA = 0x114;
public static final int BTN_FORWARD = 0x115;
public static final int BTN_BACK = 0x116;
public static final int BTN_TASK = 0x117;
public static final int BTN_JOYSTICK = 0x120;
public static final int BTN_TRIGGER = 0x120;
public static final int BTN_THUMB = 0x121;
public static final int BTN_THUMB2 = 0x122;
public static final int BTN_TOP = 0x123;
public static final int BTN_TOP2 = 0x124;
public static final int BTN_PINKIE = 0x125;
public static final int BTN_BASE = 0x126;
public static final int BTN_BASE2 = 0x127;
public static final int BTN_BASE3 = 0x128;
public static final int BTN_BASE4 = 0x129;
public static final int BTN_BASE5 = 0x12a;
public static final int BTN_BASE6 = 0x12b;
public static final int BTN_DEAD = 0x12f;
public static final int BTN_GAMEPAD = 0x130;
public static final int BTN_A = 0x130;
public static final int BTN_B = 0x131;
public static final int BTN_C = 0x132;
public static final int BTN_X = 0x133;
public static final int BTN_Y = 0x134;
public static final int BTN_Z = 0x135;
public static final int BTN_TL = 0x136;
public static final int BTN_TR = 0x137;
public static final int BTN_TL2 = 0x138;
public static final int BTN_TR2 = 0x139;
public static final int BTN_SELECT = 0x13a;
public static final int BTN_START = 0x13b;
public static final int BTN_MODE = 0x13c;
public static final int BTN_THUMBL = 0x13d;
public static final int BTN_THUMBR = 0x13e;
public static final int BTN_DIGI = 0x140;
public static final int BTN_TOOL_PEN = 0x140;
public static final int BTN_TOOL_RUBBER = 0x141;
public static final int BTN_TOOL_BRUSH = 0x142;
public static final int BTN_TOOL_PENCIL = 0x143;
public static final int BTN_TOOL_AIRBRUSH = 0x144;
public static final int BTN_TOOL_FINGER = 0x145;
public static final int BTN_TOOL_MOUSE = 0x146;
public static final int BTN_TOOL_LENS = 0x147;
public static final int BTN_TOUCH = 0x14a;
public static final int BTN_STYLUS = 0x14b;
public static final int BTN_STYLUS2 = 0x14c;
public static final int BTN_TOOL_DOUBLETAP = 0x14d;
public static final int BTN_TOOL_TRIPLETAP = 0x14e;
public static final int BTN_WHEEL = 0x150;
public static final int BTN_GEAR_DOWN = 0x150;
public static final int BTN_GEAR_UP = 0x151;
public static final int BTN_LAST = 0x15f;
// Relative axes (EV_REL) scan codes.
public static final int REL_X = 0x00;
public static final int REL_Y = 0x01;
public static final int REL_Z = 0x02;
public static final int REL_RX = 0x03;
public static final int REL_RY = 0x04;
public static final int REL_RZ = 0x05;
public static final int REL_HWHEEL = 0x06;
public static final int REL_DIAL = 0x07;
public static final int REL_WHEEL = 0x08;
public static final int REL_MISC = 0x09;
public static final int REL_MAX = 0x0f;
// Absolute axes (EV_ABS) scan codes.
public static final int ABS_X = 0x00;
public static final int ABS_Y = 0x01;
public static final int ABS_Z = 0x02;
public static final int ABS_RX = 0x03;
public static final int ABS_RY = 0x04;
public static final int ABS_RZ = 0x05;
public static final int ABS_THROTTLE = 0x06;
public static final int ABS_RUDDER = 0x07;
public static final int ABS_WHEEL = 0x08;
public static final int ABS_GAS = 0x09;
public static final int ABS_BRAKE = 0x0a;
public static final int ABS_HAT0X = 0x10;
public static final int ABS_HAT0Y = 0x11;
public static final int ABS_HAT1X = 0x12;
public static final int ABS_HAT1Y = 0x13;
public static final int ABS_HAT2X = 0x14;
public static final int ABS_HAT2Y = 0x15;
public static final int ABS_HAT3X = 0x16;
public static final int ABS_HAT3Y = 0x17;
public static final int ABS_PRESSURE = 0x18;
public static final int ABS_DISTANCE = 0x19;
public static final int ABS_TILT_X = 0x1a;
public static final int ABS_TILT_Y = 0x1b;
public static final int ABS_TOOL_WIDTH = 0x1c;
public static final int ABS_VOLUME = 0x20;
public static final int ABS_MISC = 0x28;
public static final int ABS_MT_TOUCH_MAJOR = 0x30;
public static final int ABS_MT_TOUCH_MINOR = 0x31;
public static final int ABS_MT_WIDTH_MAJOR = 0x32;
public static final int ABS_MT_WIDTH_MINOR = 0x33;
public static final int ABS_MT_ORIENTATION = 0x34;
public static final int ABS_MT_POSITION_X = 0x35;
public static final int ABS_MT_POSITION_Y = 0x36;
public static final int ABS_MT_TOOL_TYPE = 0x37;
public static final int ABS_MT_BLOB_ID = 0x38;
public static final int ABS_MAX = 0x3f;
// Switch events
public static final int SW_LID = 0x00;
public static final int SYN_REPORT = 0;
public static final int SYN_CONFIG = 1;
public static final int SYN_MT_REPORT = 2;
public int deviceId;
public int type;
public int scancode;
public int keycode;
public int flags;
public int value;
public long when;
}

View File

@ -625,41 +625,6 @@ public class SurfaceView extends View {
}
}
public void dispatchKey(KeyEvent event) {
SurfaceView surfaceView = mSurfaceView.get();
if (surfaceView != null) {
//Log.w("SurfaceView", "Unexpected key event in surface: " + event);
if (surfaceView.mSession != null && surfaceView.mSurface != null) {
try {
surfaceView.mSession.finishKey(surfaceView.mWindow);
} catch (RemoteException ex) {
}
}
}
}
public void dispatchPointer(MotionEvent event, long eventTime,
boolean callWhenDone) {
Log.w("SurfaceView", "Unexpected pointer event in surface: " + event);
//if (mSession != null && mSurface != null) {
// try {
// //mSession.finishKey(mWindow);
// } catch (RemoteException ex) {
// }
//}
}
public void dispatchTrackball(MotionEvent event, long eventTime,
boolean callWhenDone) {
Log.w("SurfaceView", "Unexpected trackball event in surface: " + event);
//if (mSession != null && mSurface != null) {
// try {
// //mSession.finishKey(mWindow);
// } catch (RemoteException ex) {
// }
//}
}
public void dispatchAppVisibility(boolean visible) {
// The point of SurfaceView is to let the app control the surface.
}
@ -686,7 +651,6 @@ public class SurfaceView extends View {
private SurfaceHolder mSurfaceHolder = new SurfaceHolder() {
private static final String LOG_TAG = "SurfaceHolder";
private int mSaveCount;
public boolean isCreating() {
return mIsCreating;

View File

@ -556,18 +556,16 @@ public final class ViewRoot extends Handler implements ViewParent,
"Unable to add window -- unknown error code " + res);
}
if (WindowManagerPolicy.ENABLE_NATIVE_INPUT_DISPATCH) {
if (view instanceof RootViewSurfaceTaker) {
mInputQueueCallback =
((RootViewSurfaceTaker)view).willYouTakeTheInputQueue();
}
if (mInputQueueCallback != null) {
mInputQueue = new InputQueue(mInputChannel);
mInputQueueCallback.onInputQueueCreated(mInputQueue);
} else {
InputQueue.registerInputChannel(mInputChannel, mInputHandler,
Looper.myQueue());
}
if (view instanceof RootViewSurfaceTaker) {
mInputQueueCallback =
((RootViewSurfaceTaker)view).willYouTakeTheInputQueue();
}
if (mInputQueueCallback != null) {
mInputQueue = new InputQueue(mInputChannel);
mInputQueueCallback.onInputQueueCreated(mInputQueue);
} else {
InputQueue.registerInputChannel(mInputChannel, mInputHandler,
Looper.myQueue());
}
view.assignParent(this);
@ -1745,16 +1743,12 @@ public final class ViewRoot extends Handler implements ViewParent,
}
mSurface.release();
if (WindowManagerPolicy.ENABLE_NATIVE_INPUT_DISPATCH) {
if (mInputChannel != null) {
if (mInputQueueCallback != null) {
mInputQueueCallback.onInputQueueDestroyed(mInputQueue);
mInputQueueCallback = null;
} else {
InputQueue.unregisterInputChannel(mInputChannel);
}
mInputChannel.dispose();
mInputChannel = null;
if (mInputChannel != null) {
if (mInputQueueCallback != null) {
mInputQueueCallback.onInputQueueDestroyed(mInputQueue);
mInputQueueCallback = null;
} else {
InputQueue.unregisterInputChannel(mInputChannel);
}
}
@ -1763,13 +1757,11 @@ public final class ViewRoot extends Handler implements ViewParent,
} catch (RemoteException e) {
}
if (WindowManagerPolicy.ENABLE_NATIVE_INPUT_DISPATCH) {
// Dispose the input channel after removing the window so the Window Manager
// doesn't interpret the input channel being closed as an abnormal termination.
if (mInputChannel != null) {
mInputChannel.dispose();
mInputChannel = null;
}
// Dispose the input channel after removing the window so the Window Manager
// doesn't interpret the input channel being closed as an abnormal termination.
if (mInputChannel != null) {
mInputChannel.dispose();
mInputChannel = null;
}
}
@ -1869,105 +1861,22 @@ public final class ViewRoot extends Handler implements ViewParent,
deliverKeyEvent((KeyEvent)msg.obj, true);
break;
case DISPATCH_POINTER: {
MotionEvent event = (MotionEvent)msg.obj;
boolean callWhenDone = msg.arg1 != 0;
if (event == null) {
long timeBeforeGettingEvents;
if (MEASURE_LATENCY) {
timeBeforeGettingEvents = System.nanoTime();
}
event = getPendingPointerMotionEvent();
if (MEASURE_LATENCY && event != null) {
lt.sample("9 Client got events ", System.nanoTime() - event.getEventTimeNano());
lt.sample("8 Client getting events ", timeBeforeGettingEvents - event.getEventTimeNano());
}
callWhenDone = false;
}
if (event != null && mTranslator != null) {
mTranslator.translateEventInScreenToAppWindow(event);
}
MotionEvent event = (MotionEvent) msg.obj;
try {
boolean handled;
if (mView != null && mAdded && event != null) {
// enter touch mode on the down
boolean isDown = event.getAction() == MotionEvent.ACTION_DOWN;
if (isDown) {
ensureTouchMode(true);
}
if(Config.LOGV) {
captureMotionLog("captureDispatchPointer", event);
}
if (mCurScrollY != 0) {
event.offsetLocation(0, mCurScrollY);
}
if (MEASURE_LATENCY) {
lt.sample("A Dispatching TouchEvents", System.nanoTime() - event.getEventTimeNano());
}
handled = mView.dispatchTouchEvent(event);
if (MEASURE_LATENCY) {
lt.sample("B Dispatched TouchEvents ", System.nanoTime() - event.getEventTimeNano());
}
if (!handled && isDown) {
int edgeSlop = mViewConfiguration.getScaledEdgeSlop();
final int edgeFlags = event.getEdgeFlags();
int direction = View.FOCUS_UP;
int x = (int)event.getX();
int y = (int)event.getY();
final int[] deltas = new int[2];
if ((edgeFlags & MotionEvent.EDGE_TOP) != 0) {
direction = View.FOCUS_DOWN;
if ((edgeFlags & MotionEvent.EDGE_LEFT) != 0) {
deltas[0] = edgeSlop;
x += edgeSlop;
} else if ((edgeFlags & MotionEvent.EDGE_RIGHT) != 0) {
deltas[0] = -edgeSlop;
x -= edgeSlop;
}
} else if ((edgeFlags & MotionEvent.EDGE_BOTTOM) != 0) {
direction = View.FOCUS_UP;
if ((edgeFlags & MotionEvent.EDGE_LEFT) != 0) {
deltas[0] = edgeSlop;
x += edgeSlop;
} else if ((edgeFlags & MotionEvent.EDGE_RIGHT) != 0) {
deltas[0] = -edgeSlop;
x -= edgeSlop;
}
} else if ((edgeFlags & MotionEvent.EDGE_LEFT) != 0) {
direction = View.FOCUS_RIGHT;
} else if ((edgeFlags & MotionEvent.EDGE_RIGHT) != 0) {
direction = View.FOCUS_LEFT;
}
if (edgeFlags != 0 && mView instanceof ViewGroup) {
View nearest = FocusFinder.getInstance().findNearestTouchable(
((ViewGroup) mView), x, y, direction, deltas);
if (nearest != null) {
event.offsetLocation(deltas[0], deltas[1]);
event.setEdgeFlags(0);
mView.dispatchTouchEvent(event);
}
}
}
}
deliverPointerEvent(event);
} finally {
if (callWhenDone) {
finishMotionEvent();
}
recycleMotionEvent(event);
event.recycle();
if (LOCAL_LOGV || WATCH_POINTER) Log.i(TAG, "Done dispatching!");
// Let the exception fall through -- the looper will catch
// it and take care of the bad app for us.
}
} break;
case DISPATCH_TRACKBALL:
deliverTrackballEvent((MotionEvent)msg.obj, msg.arg1 != 0);
break;
case DISPATCH_TRACKBALL: {
MotionEvent event = (MotionEvent) msg.obj;
try {
deliverTrackballEvent(event);
} finally {
event.recycle();
}
} break;
case DISPATCH_APP_VISIBILITY:
handleAppVisibility(msg.arg1 != 0);
break;
@ -2101,61 +2010,12 @@ public final class ViewRoot extends Handler implements ViewParent,
}
private void finishKeyEvent(KeyEvent event) {
if (WindowManagerPolicy.ENABLE_NATIVE_INPUT_DISPATCH) {
if (mFinishedCallback != null) {
mFinishedCallback.run();
mFinishedCallback = null;
}
} else {
try {
sWindowSession.finishKey(mWindow);
} catch (RemoteException e) {
}
if (mFinishedCallback != null) {
mFinishedCallback.run();
mFinishedCallback = null;
}
}
private void finishMotionEvent() {
if (WindowManagerPolicy.ENABLE_NATIVE_INPUT_DISPATCH) {
throw new IllegalStateException("Should not be reachable with native input dispatch.");
}
try {
sWindowSession.finishKey(mWindow);
} catch (RemoteException e) {
}
}
private void recycleMotionEvent(MotionEvent event) {
if (event != null) {
event.recycle();
}
}
private MotionEvent getPendingPointerMotionEvent() {
if (WindowManagerPolicy.ENABLE_NATIVE_INPUT_DISPATCH) {
throw new IllegalStateException("Should not be reachable with native input dispatch.");
}
try {
return sWindowSession.getPendingPointerMove(mWindow);
} catch (RemoteException e) {
return null;
}
}
private MotionEvent getPendingTrackballMotionEvent() {
if (WindowManagerPolicy.ENABLE_NATIVE_INPUT_DISPATCH) {
throw new IllegalStateException("Should not be reachable with native input dispatch.");
}
try {
return sWindowSession.getPendingTrackballMove(mWindow);
} catch (RemoteException e) {
return null;
}
}
/**
* Something in the current window tells us we need to change the touch mode. For
* example, we are not in touch mode, and the user touches the screen.
@ -2277,42 +2137,95 @@ public final class ViewRoot extends Handler implements ViewParent,
return false;
}
private void deliverTrackballEvent(MotionEvent event, boolean callWhenDone) {
if (event == null) {
event = getPendingTrackballMotionEvent();
callWhenDone = false;
private void deliverPointerEvent(MotionEvent event) {
if (mTranslator != null) {
mTranslator.translateEventInScreenToAppWindow(event);
}
boolean handled;
if (mView != null && mAdded) {
// enter touch mode on the down
boolean isDown = event.getAction() == MotionEvent.ACTION_DOWN;
if (isDown) {
ensureTouchMode(true);
}
if(Config.LOGV) {
captureMotionLog("captureDispatchPointer", event);
}
if (mCurScrollY != 0) {
event.offsetLocation(0, mCurScrollY);
}
if (MEASURE_LATENCY) {
lt.sample("A Dispatching TouchEvents", System.nanoTime() - event.getEventTimeNano());
}
handled = mView.dispatchTouchEvent(event);
if (MEASURE_LATENCY) {
lt.sample("B Dispatched TouchEvents ", System.nanoTime() - event.getEventTimeNano());
}
if (!handled && isDown) {
int edgeSlop = mViewConfiguration.getScaledEdgeSlop();
final int edgeFlags = event.getEdgeFlags();
int direction = View.FOCUS_UP;
int x = (int)event.getX();
int y = (int)event.getY();
final int[] deltas = new int[2];
if ((edgeFlags & MotionEvent.EDGE_TOP) != 0) {
direction = View.FOCUS_DOWN;
if ((edgeFlags & MotionEvent.EDGE_LEFT) != 0) {
deltas[0] = edgeSlop;
x += edgeSlop;
} else if ((edgeFlags & MotionEvent.EDGE_RIGHT) != 0) {
deltas[0] = -edgeSlop;
x -= edgeSlop;
}
} else if ((edgeFlags & MotionEvent.EDGE_BOTTOM) != 0) {
direction = View.FOCUS_UP;
if ((edgeFlags & MotionEvent.EDGE_LEFT) != 0) {
deltas[0] = edgeSlop;
x += edgeSlop;
} else if ((edgeFlags & MotionEvent.EDGE_RIGHT) != 0) {
deltas[0] = -edgeSlop;
x -= edgeSlop;
}
} else if ((edgeFlags & MotionEvent.EDGE_LEFT) != 0) {
direction = View.FOCUS_RIGHT;
} else if ((edgeFlags & MotionEvent.EDGE_RIGHT) != 0) {
direction = View.FOCUS_LEFT;
}
if (edgeFlags != 0 && mView instanceof ViewGroup) {
View nearest = FocusFinder.getInstance().findNearestTouchable(
((ViewGroup) mView), x, y, direction, deltas);
if (nearest != null) {
event.offsetLocation(deltas[0], deltas[1]);
event.setEdgeFlags(0);
mView.dispatchTouchEvent(event);
}
}
}
}
}
private void deliverTrackballEvent(MotionEvent event) {
if (DEBUG_TRACKBALL) Log.v(TAG, "Motion event:" + event);
boolean handled = false;
try {
if (event == null) {
handled = true;
} else if (mView != null && mAdded) {
handled = mView.dispatchTrackballEvent(event);
if (!handled) {
// we could do something here, like changing the focus
// or something?
}
}
} finally {
if (mView != null && mAdded) {
handled = mView.dispatchTrackballEvent(event);
if (handled) {
if (callWhenDone) {
finishMotionEvent();
}
recycleMotionEvent(event);
// If we reach this, we delivered a trackball event to mView and
// mView consumed it. Because we will not translate the trackball
// event into a key event, touch mode will not exit, so we exit
// touch mode here.
ensureTouchMode(false);
//noinspection ReturnInsideFinallyBlock
return;
}
// Let the exception fall through -- the looper will catch
// it and take care of the bad app for us.
// Otherwise we could do something here, like changing the focus
// or something?
}
final TrackballAxis x = mTrackballAxisX;
@ -2327,95 +2240,86 @@ public final class ViewRoot extends Handler implements ViewParent,
mLastTrackballTime = curTime;
}
try {
final int action = event.getAction();
final int metastate = event.getMetaState();
switch (action) {
case MotionEvent.ACTION_DOWN:
x.reset(2);
y.reset(2);
deliverKeyEvent(new KeyEvent(curTime, curTime,
KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_CENTER,
0, metastate), false);
break;
case MotionEvent.ACTION_UP:
x.reset(2);
y.reset(2);
deliverKeyEvent(new KeyEvent(curTime, curTime,
KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DPAD_CENTER,
0, metastate), false);
break;
}
final int action = event.getAction();
final int metastate = event.getMetaState();
switch (action) {
case MotionEvent.ACTION_DOWN:
x.reset(2);
y.reset(2);
deliverKeyEvent(new KeyEvent(curTime, curTime,
KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_CENTER,
0, metastate), false);
break;
case MotionEvent.ACTION_UP:
x.reset(2);
y.reset(2);
deliverKeyEvent(new KeyEvent(curTime, curTime,
KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DPAD_CENTER,
0, metastate), false);
break;
}
if (DEBUG_TRACKBALL) Log.v(TAG, "TB X=" + x.position + " step="
+ x.step + " dir=" + x.dir + " acc=" + x.acceleration
+ " move=" + event.getX()
+ " / Y=" + y.position + " step="
+ y.step + " dir=" + y.dir + " acc=" + y.acceleration
+ " move=" + event.getY());
final float xOff = x.collect(event.getX(), event.getEventTime(), "X");
final float yOff = y.collect(event.getY(), event.getEventTime(), "Y");
if (DEBUG_TRACKBALL) Log.v(TAG, "TB X=" + x.position + " step="
+ x.step + " dir=" + x.dir + " acc=" + x.acceleration
+ " move=" + event.getX()
+ " / Y=" + y.position + " step="
+ y.step + " dir=" + y.dir + " acc=" + y.acceleration
+ " move=" + event.getY());
final float xOff = x.collect(event.getX(), event.getEventTime(), "X");
final float yOff = y.collect(event.getY(), event.getEventTime(), "Y");
// Generate DPAD events based on the trackball movement.
// We pick the axis that has moved the most as the direction of
// the DPAD. When we generate DPAD events for one axis, then the
// other axis is reset -- we don't want to perform DPAD jumps due
// to slight movements in the trackball when making major movements
// along the other axis.
int keycode = 0;
int movement = 0;
float accel = 1;
if (xOff > yOff) {
movement = x.generate((2/event.getXPrecision()));
if (movement != 0) {
keycode = movement > 0 ? KeyEvent.KEYCODE_DPAD_RIGHT
: KeyEvent.KEYCODE_DPAD_LEFT;
accel = x.acceleration;
y.reset(2);
}
} else if (yOff > 0) {
movement = y.generate((2/event.getYPrecision()));
if (movement != 0) {
keycode = movement > 0 ? KeyEvent.KEYCODE_DPAD_DOWN
: KeyEvent.KEYCODE_DPAD_UP;
accel = y.acceleration;
x.reset(2);
}
// Generate DPAD events based on the trackball movement.
// We pick the axis that has moved the most as the direction of
// the DPAD. When we generate DPAD events for one axis, then the
// other axis is reset -- we don't want to perform DPAD jumps due
// to slight movements in the trackball when making major movements
// along the other axis.
int keycode = 0;
int movement = 0;
float accel = 1;
if (xOff > yOff) {
movement = x.generate((2/event.getXPrecision()));
if (movement != 0) {
keycode = movement > 0 ? KeyEvent.KEYCODE_DPAD_RIGHT
: KeyEvent.KEYCODE_DPAD_LEFT;
accel = x.acceleration;
y.reset(2);
}
} else if (yOff > 0) {
movement = y.generate((2/event.getYPrecision()));
if (movement != 0) {
keycode = movement > 0 ? KeyEvent.KEYCODE_DPAD_DOWN
: KeyEvent.KEYCODE_DPAD_UP;
accel = y.acceleration;
x.reset(2);
}
}
if (keycode != 0) {
if (movement < 0) movement = -movement;
int accelMovement = (int)(movement * accel);
if (DEBUG_TRACKBALL) Log.v(TAG, "Move: movement=" + movement
+ " accelMovement=" + accelMovement
+ " accel=" + accel);
if (accelMovement > movement) {
if (DEBUG_TRACKBALL) Log.v("foo", "Delivering fake DPAD: "
+ keycode);
movement--;
deliverKeyEvent(new KeyEvent(curTime, curTime,
KeyEvent.ACTION_MULTIPLE, keycode,
accelMovement-movement, metastate), false);
}
while (movement > 0) {
if (DEBUG_TRACKBALL) Log.v("foo", "Delivering fake DPAD: "
+ keycode);
movement--;
curTime = SystemClock.uptimeMillis();
deliverKeyEvent(new KeyEvent(curTime, curTime,
KeyEvent.ACTION_DOWN, keycode, 0, event.getMetaState()), false);
deliverKeyEvent(new KeyEvent(curTime, curTime,
KeyEvent.ACTION_UP, keycode, 0, metastate), false);
}
mLastTrackballTime = curTime;
if (keycode != 0) {
if (movement < 0) movement = -movement;
int accelMovement = (int)(movement * accel);
if (DEBUG_TRACKBALL) Log.v(TAG, "Move: movement=" + movement
+ " accelMovement=" + accelMovement
+ " accel=" + accel);
if (accelMovement > movement) {
if (DEBUG_TRACKBALL) Log.v("foo", "Delivering fake DPAD: "
+ keycode);
movement--;
deliverKeyEvent(new KeyEvent(curTime, curTime,
KeyEvent.ACTION_MULTIPLE, keycode,
accelMovement-movement, metastate), false);
}
} finally {
if (callWhenDone) {
finishMotionEvent();
recycleMotionEvent(event);
while (movement > 0) {
if (DEBUG_TRACKBALL) Log.v("foo", "Delivering fake DPAD: "
+ keycode);
movement--;
curTime = SystemClock.uptimeMillis();
deliverKeyEvent(new KeyEvent(curTime, curTime,
KeyEvent.ACTION_DOWN, keycode, 0, event.getMetaState()), false);
deliverKeyEvent(new KeyEvent(curTime, curTime,
KeyEvent.ACTION_UP, keycode, 0, metastate), false);
}
// Let the exception fall through -- the looper will catch
// it and take care of the bad app for us.
mLastTrackballTime = curTime;
}
}
@ -2862,45 +2766,20 @@ public final class ViewRoot extends Handler implements ViewParent,
private final InputHandler mInputHandler = new InputHandler() {
public void handleKey(KeyEvent event, Runnable finishedCallback) {
mFinishedCallback = finishedCallback;
if (event.getAction() == KeyEvent.ACTION_DOWN) {
//noinspection ConstantConditions
if (false && event.getKeyCode() == KeyEvent.KEYCODE_CAMERA) {
if (Config.LOGD) Log.d("keydisp",
"===================================================");
if (Config.LOGD) Log.d("keydisp", "Focused view Hierarchy is:");
debug();
if (Config.LOGD) Log.d("keydisp",
"===================================================");
}
}
Message msg = obtainMessage(DISPATCH_KEY);
msg.obj = event;
if (LOCAL_LOGV) Log.v(
"ViewRoot", "sending key " + event + " to " + mView);
sendMessageAtTime(msg, event.getEventTime());
dispatchKey(event);
}
public void handleTouch(MotionEvent event, Runnable finishedCallback) {
finishedCallback.run();
Message msg = obtainMessage(DISPATCH_POINTER);
msg.obj = event;
msg.arg1 = 0;
sendMessageAtTime(msg, event.getEventTime());
dispatchPointer(event);
}
public void handleTrackball(MotionEvent event, Runnable finishedCallback) {
finishedCallback.run();
Message msg = obtainMessage(DISPATCH_TRACKBALL);
msg.obj = event;
msg.arg1 = 0;
sendMessageAtTime(msg, event.getEventTime());
dispatchTrackball(event);
}
};
@ -2927,22 +2806,18 @@ public final class ViewRoot extends Handler implements ViewParent,
sendMessageAtTime(msg, event.getEventTime());
}
public void dispatchPointer(MotionEvent event, long eventTime,
boolean callWhenDone) {
public void dispatchPointer(MotionEvent event) {
Message msg = obtainMessage(DISPATCH_POINTER);
msg.obj = event;
msg.arg1 = callWhenDone ? 1 : 0;
sendMessageAtTime(msg, eventTime);
sendMessageAtTime(msg, event.getEventTime());
}
public void dispatchTrackball(MotionEvent event, long eventTime,
boolean callWhenDone) {
public void dispatchTrackball(MotionEvent event) {
Message msg = obtainMessage(DISPATCH_TRACKBALL);
msg.obj = event;
msg.arg1 = callWhenDone ? 1 : 0;
sendMessageAtTime(msg, eventTime);
sendMessageAtTime(msg, event.getEventTime());
}
public void dispatchAppVisibility(boolean visible) {
Message msg = obtainMessage(DISPATCH_APP_VISIBILITY);
msg.arg1 = visible ? 1 : 0;
@ -3073,56 +2948,11 @@ public final class ViewRoot extends Handler implements ViewParent,
}
}
class EventCompletion extends Handler {
final IWindow mWindow;
final KeyEvent mKeyEvent;
final boolean mIsPointer;
final MotionEvent mMotionEvent;
EventCompletion(Looper looper, IWindow window, KeyEvent key,
boolean isPointer, MotionEvent motion) {
super(looper);
mWindow = window;
mKeyEvent = key;
mIsPointer = isPointer;
mMotionEvent = motion;
sendEmptyMessage(0);
}
@Override
public void handleMessage(Message msg) {
if (mKeyEvent != null) {
finishKeyEvent(mKeyEvent);
} else if (mIsPointer) {
boolean didFinish;
MotionEvent event = mMotionEvent;
if (event == null) {
event = getPendingPointerMotionEvent();
didFinish = true;
} else {
didFinish = event.getAction() == MotionEvent.ACTION_OUTSIDE;
}
if (!didFinish) {
finishMotionEvent();
}
} else {
MotionEvent event = mMotionEvent;
if (event == null) {
event = getPendingTrackballMotionEvent();
} else {
finishMotionEvent();
}
}
}
}
static class W extends IWindow.Stub {
private final WeakReference<ViewRoot> mViewRoot;
private final Looper mMainLooper;
public W(ViewRoot viewRoot, Context context) {
mViewRoot = new WeakReference<ViewRoot>(viewRoot);
mMainLooper = context.getMainLooper();
}
public void resized(int w, int h, Rect coveredInsets,
@ -3134,40 +2964,6 @@ public final class ViewRoot extends Handler implements ViewParent,
}
}
public void dispatchKey(KeyEvent event) {
final ViewRoot viewRoot = mViewRoot.get();
if (viewRoot != null) {
viewRoot.dispatchKey(event);
} else {
Log.w("ViewRoot.W", "Key event " + event + " but no ViewRoot available!");
viewRoot.new EventCompletion(mMainLooper, this, event, false, null);
}
}
public void dispatchPointer(MotionEvent event, long eventTime,
boolean callWhenDone) {
final ViewRoot viewRoot = mViewRoot.get();
if (viewRoot != null) {
if (MEASURE_LATENCY) {
// Note: eventTime is in milliseconds
ViewRoot.lt.sample("* ViewRoot b4 dispatchPtr", System.nanoTime() - eventTime * 1000000);
}
viewRoot.dispatchPointer(event, eventTime, callWhenDone);
} else {
viewRoot.new EventCompletion(mMainLooper, this, null, true, event);
}
}
public void dispatchTrackball(MotionEvent event, long eventTime,
boolean callWhenDone) {
final ViewRoot viewRoot = mViewRoot.get();
if (viewRoot != null) {
viewRoot.dispatchTrackball(event, eventTime, callWhenDone);
} else {
viewRoot.new EventCompletion(mMainLooper, this, null, false, event);
}
}
public void dispatchAppVisibility(boolean visible) {
final ViewRoot viewRoot = mViewRoot.get();
if (viewRoot != null) {

View File

@ -78,12 +78,6 @@ public interface WindowManagerPolicy {
public final static int FLAG_BRIGHT_HERE = 0x20000000;
public final static boolean WATCH_POINTER = false;
/**
* Temporary flag added during the transition to the new native input dispatcher.
* This will be removed when the old input dispatch code is deleted.
*/
public final static boolean ENABLE_NATIVE_INPUT_DISPATCH = true;
// flags for interceptKeyTq
/**
@ -555,23 +549,26 @@ public interface WindowManagerPolicy {
public Animation createForceHideEnterAnimation();
/**
* Called from the key queue thread before a key is dispatched to the
* input thread.
* Called from the input reader thread before a key is enqueued.
*
* <p>There are some actions that need to be handled here because they
* affect the power state of the device, for example, the power keys.
* Generally, it's best to keep as little as possible in the queue thread
* because it's the most fragile.
* @param whenNanos The event time in uptime nanoseconds.
* @param keyCode The key code.
* @param down True if the key is down.
* @param policyFlags The policy flags associated with the key.
* @param isScreenOn True if the screen is already on
*
* @param event the raw input event as read from the driver
* @param screenIsOn true if the screen is already on
* @return The bitwise or of the {@link #ACTION_PASS_TO_USER},
* {@link #ACTION_POKE_USER_ACTIVITY} and {@link #ACTION_GO_TO_SLEEP} flags.
*/
public int interceptKeyTq(RawInputEvent event, boolean screenIsOn);
public int interceptKeyBeforeQueueing(long whenNanos, int keyCode, boolean down, int policyFlags,
boolean isScreenOn);
/**
* Called from the input thread before a key is dispatched to a window.
* Called from the input dispatcher thread before a key is dispatched to a window.
*
* <p>Allows you to define
* behavior for keys that can not be overridden by applications or redirect
@ -583,16 +580,17 @@ public interface WindowManagerPolicy {
*
* @param win The window that currently has focus. This is where the key
* event will normally go.
* @param code Key code.
* @param metaKeys bit mask of meta keys that are held.
* @param down Is this a key press (true) or release (false)?
* @param action The key event action.
* @param flags The key event flags.
* @param keyCode The key code.
* @param metaState bit mask of meta keys that are held.
* @param repeatCount Number of times a key down has repeated.
* @param flags event's flags.
* @param policyFlags The policy flags associated with the key.
* @return Returns true if the policy consumed the event and it should
* not be further dispatched.
*/
public boolean interceptKeyTi(WindowState win, int code,
int metaKeys, boolean down, int repeatCount, int flags);
public boolean interceptKeyBeforeDispatching(WindowState win, int action, int flags,
int keyCode, int metaState, int repeatCount, int policyFlags);
/**
* Called when layout of the windows is about to start.
@ -701,84 +699,14 @@ public interface WindowManagerPolicy {
* Return whether the screen is currently on.
*/
public boolean isScreenOn();
/**
* Perform any initial processing of a low-level input event before the
* window manager handles special keys and generates a high-level event
* that is dispatched to the application.
*
* @param event The input event that has occurred.
*
* @return Return true if you have consumed the event and do not want
* further processing to occur; return false for normal processing.
* Tell the policy that the lid switch has changed state.
* @param whenNanos The time when the change occurred in uptime nanoseconds.
* @param lidOpen True if the lid is now open.
*/
public boolean preprocessInputEventTq(RawInputEvent event);
public void notifyLidSwitchChanged(long whenNanos, boolean lidOpen);
/**
* Determine whether a given key code is used to cause an app switch
* to occur (most often the HOME key, also often ENDCALL). If you return
* true, then the system will go into a special key processing state
* where it drops any pending events that it cans and adjusts timeouts to
* try to get to this key as quickly as possible.
*
* <p>Note that this function is called from the low-level input queue
* thread, with either/or the window or input lock held; be very careful
* about what you do here. You absolutely should never acquire a lock
* that you would ever hold elsewhere while calling out into the window
* manager or view hierarchy.
*
* @param keycode The key that should be checked for performing an
* app switch before delivering to the application.
*
* @return Return true if this is an app switch key and special processing
* should happen; return false for normal processing.
*/
public boolean isAppSwitchKeyTqTiLwLi(int keycode);
/**
* Determine whether a given key code is used for movement within a UI,
* and does not generally cause actions to be performed (normally the DPAD
* movement keys, NOT the DPAD center press key). This is called
* when {@link #isAppSwitchKeyTiLi} returns true to remove any pending events
* in the key queue that are not needed to switch applications.
*
* <p>Note that this function is called from the low-level input queue
* thread; be very careful about what you do here.
*
* @param keycode The key that is waiting to be delivered to the
* application.
*
* @return Return true if this is a purely navigation key and can be
* dropped without negative consequences; return false to keep it.
*/
public boolean isMovementKeyTi(int keycode);
/**
* Given the current state of the world, should this relative movement
* wake up the device?
*
* @param device The device the movement came from.
* @param classes The input classes associated with the device.
* @param event The input event that occurred.
* @return
*/
public boolean isWakeRelMovementTq(int device, int classes,
RawInputEvent event);
/**
* Given the current state of the world, should this absolute movement
* wake up the device?
*
* @param device The device the movement came from.
* @param classes The input classes associated with the device.
* @param event The input event that occurred.
* @return
*/
public boolean isWakeAbsMovementTq(int device, int classes,
RawInputEvent event);
/**
* Tell the policy if anyone is requesting that keyguard not come on.
*
@ -851,18 +779,6 @@ public interface WindowManagerPolicy {
*/
public void enableScreenAfterBoot();
/**
* Returns true if the user's cheek has been pressed against the phone. This is
* determined by comparing the event's size attribute with a threshold value.
* For example for a motion event like down or up or move, if the size exceeds
* the threshold, it is considered as cheek press.
* @param ev the motion event generated when the cheek is pressed
* against the phone
* @return Returns true if the user's cheek has been pressed against the phone
* screen resulting in an invalid motion event
*/
public boolean isCheekPressedAgainstScreen(MotionEvent ev);
/**
* Called every time the window manager is dispatching a pointer event.
*/
@ -875,13 +791,6 @@ public interface WindowManagerPolicy {
*/
public boolean performHapticFeedbackLw(WindowState win, int effectId, boolean always);
/**
* A special function that is called from the very low-level input queue
* to provide feedback to the user. Currently only called for virtual
* keys.
*/
public void keyFeedbackFromInput(KeyEvent event);
/**
* Called when we have stopped keeping the screen on because a window
* requesting this is no longer visible.