am 8df8b2b4: Allow wallpapers to get touch events.
Merge commit '8df8b2b405c60cacf7a66c4e2ca078dd3d7ec7bd' * commit '8df8b2b405c60cacf7a66c4e2ca078dd3d7ec7bd': Allow wallpapers to get touch events.
This commit is contained in:
@@ -30,6 +30,7 @@ import android.os.RemoteException;
|
||||
import android.util.Log;
|
||||
import android.view.Gravity;
|
||||
import android.view.IWindowSession;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.SurfaceHolder;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
@@ -59,6 +60,7 @@ public abstract class WallpaperService extends Service {
|
||||
private static final int MSG_VISIBILITY_CHANGED = 10010;
|
||||
private static final int MSG_WALLPAPER_OFFSETS = 10020;
|
||||
private static final int MSG_WINDOW_RESIZED = 10030;
|
||||
private static final int MSG_TOUCH_EVENT = 10040;
|
||||
|
||||
/**
|
||||
* The actual implementation of a wallpaper. A wallpaper service may
|
||||
@@ -87,6 +89,8 @@ public abstract class WallpaperService extends Service {
|
||||
int mType;
|
||||
int mCurWidth;
|
||||
int mCurHeight;
|
||||
int mWindowFlags = WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
|
||||
int mCurWindowFlags = mWindowFlags;
|
||||
boolean mDestroyReportNeeded;
|
||||
final Rect mVisibleInsets = new Rect();
|
||||
final Rect mWinFrame = new Rect();
|
||||
@@ -100,6 +104,7 @@ public abstract class WallpaperService extends Service {
|
||||
boolean mOffsetMessageEnqueued;
|
||||
float mPendingXOffset;
|
||||
float mPendingYOffset;
|
||||
MotionEvent mPendingMove;
|
||||
|
||||
final BaseSurfaceHolder mSurfaceHolder = new BaseSurfaceHolder() {
|
||||
|
||||
@@ -131,6 +136,27 @@ 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) {
|
||||
Message msg = mCaller.obtainMessageI(MSG_WINDOW_RESIZED,
|
||||
@@ -138,6 +164,7 @@ public abstract class WallpaperService extends Service {
|
||||
mCaller.sendMessage(msg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispatchAppVisibility(boolean visible) {
|
||||
Message msg = mCaller.obtainMessageI(MSG_VISIBILITY_CHANGED,
|
||||
visible ? 1 : 0);
|
||||
@@ -184,6 +211,22 @@ public abstract class WallpaperService extends Service {
|
||||
return mIWallpaperEngine.mReqHeight;
|
||||
}
|
||||
|
||||
/**
|
||||
* Control whether this wallpaper will receive raw touch events
|
||||
* from the window manager as the user interacts with the window
|
||||
* that is currently displaying the wallpaper. By default they
|
||||
* are turned off. If enabled, the events will be received in
|
||||
* {@link #onTouchEvent(MotionEvent)}.
|
||||
*/
|
||||
public void setTouchEventsEnabled(boolean enabled) {
|
||||
mWindowFlags = enabled
|
||||
? (mWindowFlags&~WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE)
|
||||
: (mWindowFlags|WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);
|
||||
if (mCreated) {
|
||||
updateSurface(false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called once to initialize the engine. After returning, the
|
||||
* engine's surface will be created by the framework.
|
||||
@@ -207,6 +250,16 @@ public abstract class WallpaperService extends Service {
|
||||
public void onVisibilityChanged(boolean visible) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Called as the user performs touch-screen interaction with the
|
||||
* window that is currently showing this wallpaper. Note that the
|
||||
* events you receive here are driven by the actual application the
|
||||
* user is interacting with, so if it is slow you will get viewer
|
||||
* move events.
|
||||
*/
|
||||
public void onTouchEvent(MotionEvent event) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to inform you of the wallpaper's offsets changing
|
||||
* within its contain, corresponding to the container's
|
||||
@@ -248,7 +301,9 @@ public abstract class WallpaperService extends Service {
|
||||
final boolean formatChanged = mFormat != mSurfaceHolder.getRequestedFormat();
|
||||
boolean sizeChanged = mWidth != myWidth || mHeight != myHeight;
|
||||
final boolean typeChanged = mType != mSurfaceHolder.getRequestedType();
|
||||
if (force || creating || formatChanged || sizeChanged || typeChanged) {
|
||||
final boolean flagsChanged = mCurWindowFlags != mWindowFlags;
|
||||
if (force || creating || formatChanged || sizeChanged || typeChanged
|
||||
|| flagsChanged) {
|
||||
|
||||
if (DEBUG) Log.i(TAG, "Changes: creating=" + creating
|
||||
+ " format=" + formatChanged + " size=" + sizeChanged);
|
||||
@@ -259,20 +314,19 @@ public abstract class WallpaperService extends Service {
|
||||
mFormat = mSurfaceHolder.getRequestedFormat();
|
||||
mType = mSurfaceHolder.getRequestedType();
|
||||
|
||||
// Scaling/Translate window's layout here because mLayout is not used elsewhere.
|
||||
|
||||
// Places the window relative
|
||||
mLayout.x = 0;
|
||||
mLayout.y = 0;
|
||||
mLayout.width = myWidth;
|
||||
mLayout.height = myHeight;
|
||||
|
||||
mLayout.format = mFormat;
|
||||
mLayout.flags |=WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
|
||||
| WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
|
||||
| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
|
||||
| WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
|
||||
;
|
||||
|
||||
mCurWindowFlags = mWindowFlags;
|
||||
mLayout.flags = mWindowFlags
|
||||
| WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
|
||||
| WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
|
||||
| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
|
||||
;
|
||||
|
||||
mLayout.memoryType = mType;
|
||||
mLayout.token = mWindowToken;
|
||||
@@ -478,6 +532,16 @@ public abstract class WallpaperService extends Service {
|
||||
}
|
||||
}
|
||||
} break;
|
||||
case MSG_TOUCH_EVENT: {
|
||||
MotionEvent ev = (MotionEvent)message.obj;
|
||||
synchronized (mEngine.mLock) {
|
||||
if (mEngine.mPendingMove == ev) {
|
||||
mEngine.mPendingMove = null;
|
||||
}
|
||||
}
|
||||
mEngine.onTouchEvent(ev);
|
||||
ev.recycle();
|
||||
} break;
|
||||
default :
|
||||
Log.w(TAG, "Unknown message type " + message.what);
|
||||
}
|
||||
|
||||
@@ -46,8 +46,8 @@ oneway interface IWindow {
|
||||
void resized(int w, int h, in Rect coveredInsets, in Rect visibleInsets,
|
||||
boolean reportDraw);
|
||||
void dispatchKey(in KeyEvent event);
|
||||
void dispatchPointer(in MotionEvent event, long eventTime);
|
||||
void dispatchTrackball(in MotionEvent event, long eventTime);
|
||||
void dispatchPointer(in MotionEvent event, long eventTime, boolean callWhenDone);
|
||||
void dispatchTrackball(in MotionEvent event, long eventTime, boolean callWhenDone);
|
||||
void dispatchAppVisibility(boolean visible);
|
||||
void dispatchGetNewSurface();
|
||||
|
||||
|
||||
@@ -551,6 +551,44 @@ public final class MotionEvent implements Parcelable {
|
||||
return ev;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new MotionEvent, copying from an existing one, but not including
|
||||
* any historical point information.
|
||||
*/
|
||||
static public MotionEvent obtainNoHistory(MotionEvent o) {
|
||||
MotionEvent ev = obtain();
|
||||
ev.mDeviceId = o.mDeviceId;
|
||||
ev.mEdgeFlags = o.mEdgeFlags;
|
||||
ev.mDownTime = o.mDownTime;
|
||||
ev.mEventTimeNano = o.mEventTimeNano;
|
||||
ev.mAction = o.mAction;
|
||||
ev.mNumPointers = o.mNumPointers;
|
||||
ev.mRawX = o.mRawX;
|
||||
ev.mRawY = o.mRawY;
|
||||
ev.mMetaState = o.mMetaState;
|
||||
ev.mXPrecision = o.mXPrecision;
|
||||
ev.mYPrecision = o.mYPrecision;
|
||||
|
||||
ev.mNumSamples = 1;
|
||||
ev.mTimeSamples[0] = o.mTimeSamples[0];
|
||||
|
||||
final int NP = (ev.mNumPointers=o.mNumPointers);
|
||||
if (ev.mPointerIdentifiers.length >= NP) {
|
||||
System.arraycopy(o.mPointerIdentifiers, 0, ev.mPointerIdentifiers, 0, NP);
|
||||
} else {
|
||||
ev.mPointerIdentifiers = (int[])o.mPointerIdentifiers.clone();
|
||||
}
|
||||
|
||||
final int ND = NP * NUM_SAMPLE_DATA;
|
||||
if (ev.mDataSamples.length >= ND) {
|
||||
System.arraycopy(o.mDataSamples, 0, ev.mDataSamples, 0, ND);
|
||||
} else {
|
||||
ev.mDataSamples = (float[])o.mDataSamples.clone();
|
||||
}
|
||||
|
||||
return ev;
|
||||
}
|
||||
|
||||
/**
|
||||
* Recycle the MotionEvent, to be re-used by a later caller. After calling
|
||||
* this function you must not ever touch the event again.
|
||||
|
||||
@@ -481,7 +481,8 @@ public class SurfaceView extends View {
|
||||
}
|
||||
}
|
||||
|
||||
public void dispatchPointer(MotionEvent event, long eventTime) {
|
||||
public void dispatchPointer(MotionEvent event, long eventTime,
|
||||
boolean callWhenDone) {
|
||||
Log.w("SurfaceView", "Unexpected pointer event in surface: " + event);
|
||||
//if (mSession != null && mSurface != null) {
|
||||
// try {
|
||||
@@ -491,7 +492,8 @@ public class SurfaceView extends View {
|
||||
//}
|
||||
}
|
||||
|
||||
public void dispatchTrackball(MotionEvent event, long eventTime) {
|
||||
public void dispatchTrackball(MotionEvent event, long eventTime,
|
||||
boolean callWhenDone) {
|
||||
Log.w("SurfaceView", "Unexpected trackball event in surface: " + event);
|
||||
//if (mSession != null && mSurface != null) {
|
||||
// try {
|
||||
|
||||
@@ -1637,8 +1637,8 @@ public final class ViewRoot extends Handler implements ViewParent,
|
||||
break;
|
||||
case DISPATCH_POINTER: {
|
||||
MotionEvent event = (MotionEvent)msg.obj;
|
||||
|
||||
boolean didFinish;
|
||||
boolean callWhenDone = msg.arg1 != 0;
|
||||
|
||||
if (event == null) {
|
||||
try {
|
||||
long timeBeforeGettingEvents;
|
||||
@@ -1654,9 +1654,7 @@ public final class ViewRoot extends Handler implements ViewParent,
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
}
|
||||
didFinish = true;
|
||||
} else {
|
||||
didFinish = event.getAction() == MotionEvent.ACTION_OUTSIDE;
|
||||
callWhenDone = false;
|
||||
}
|
||||
if (event != null && mTranslator != null) {
|
||||
mTranslator.translateEventInScreenToAppWindow(event);
|
||||
@@ -1728,7 +1726,7 @@ public final class ViewRoot extends Handler implements ViewParent,
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
if (!didFinish) {
|
||||
if (callWhenDone) {
|
||||
try {
|
||||
sWindowSession.finishKey(mWindow);
|
||||
} catch (RemoteException e) {
|
||||
@@ -1743,7 +1741,7 @@ public final class ViewRoot extends Handler implements ViewParent,
|
||||
}
|
||||
} break;
|
||||
case DISPATCH_TRACKBALL:
|
||||
deliverTrackballEvent((MotionEvent)msg.obj);
|
||||
deliverTrackballEvent((MotionEvent)msg.obj, msg.arg1 != 0);
|
||||
break;
|
||||
case DISPATCH_APP_VISIBILITY:
|
||||
handleAppVisibility(msg.arg1 != 0);
|
||||
@@ -1985,16 +1983,13 @@ public final class ViewRoot extends Handler implements ViewParent,
|
||||
}
|
||||
|
||||
|
||||
private void deliverTrackballEvent(MotionEvent event) {
|
||||
boolean didFinish;
|
||||
private void deliverTrackballEvent(MotionEvent event, boolean callWhenDone) {
|
||||
if (event == null) {
|
||||
try {
|
||||
event = sWindowSession.getPendingTrackballMove(mWindow);
|
||||
} catch (RemoteException e) {
|
||||
}
|
||||
didFinish = true;
|
||||
} else {
|
||||
didFinish = false;
|
||||
callWhenDone = false;
|
||||
}
|
||||
|
||||
if (DEBUG_TRACKBALL) Log.v(TAG, "Motion event:" + event);
|
||||
@@ -2012,7 +2007,7 @@ public final class ViewRoot extends Handler implements ViewParent,
|
||||
}
|
||||
} finally {
|
||||
if (handled) {
|
||||
if (!didFinish) {
|
||||
if (callWhenDone) {
|
||||
try {
|
||||
sWindowSession.finishKey(mWindow);
|
||||
} catch (RemoteException e) {
|
||||
@@ -2128,7 +2123,7 @@ public final class ViewRoot extends Handler implements ViewParent,
|
||||
mLastTrackballTime = curTime;
|
||||
}
|
||||
} finally {
|
||||
if (!didFinish) {
|
||||
if (callWhenDone) {
|
||||
try {
|
||||
sWindowSession.finishKey(mWindow);
|
||||
} catch (RemoteException e) {
|
||||
@@ -2591,15 +2586,19 @@ public final class ViewRoot extends Handler implements ViewParent,
|
||||
sendMessageAtTime(msg, event.getEventTime());
|
||||
}
|
||||
|
||||
public void dispatchPointer(MotionEvent event, long eventTime) {
|
||||
public void dispatchPointer(MotionEvent event, long eventTime,
|
||||
boolean callWhenDone) {
|
||||
Message msg = obtainMessage(DISPATCH_POINTER);
|
||||
msg.obj = event;
|
||||
msg.arg1 = callWhenDone ? 1 : 0;
|
||||
sendMessageAtTime(msg, eventTime);
|
||||
}
|
||||
|
||||
public void dispatchTrackball(MotionEvent event, long eventTime) {
|
||||
public void dispatchTrackball(MotionEvent event, long eventTime,
|
||||
boolean callWhenDone) {
|
||||
Message msg = obtainMessage(DISPATCH_TRACKBALL);
|
||||
msg.obj = event;
|
||||
msg.arg1 = callWhenDone ? 1 : 0;
|
||||
sendMessageAtTime(msg, eventTime);
|
||||
}
|
||||
|
||||
@@ -2772,23 +2771,25 @@ public final class ViewRoot extends Handler implements ViewParent,
|
||||
}
|
||||
}
|
||||
|
||||
public void dispatchPointer(MotionEvent event, long eventTime) {
|
||||
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);
|
||||
viewRoot.dispatchPointer(event, eventTime, callWhenDone);
|
||||
} else {
|
||||
new EventCompletion(mMainLooper, this, null, true, event);
|
||||
}
|
||||
}
|
||||
|
||||
public void dispatchTrackball(MotionEvent event, long eventTime) {
|
||||
public void dispatchTrackball(MotionEvent event, long eventTime,
|
||||
boolean callWhenDone) {
|
||||
final ViewRoot viewRoot = mViewRoot.get();
|
||||
if (viewRoot != null) {
|
||||
viewRoot.dispatchTrackball(event, eventTime);
|
||||
viewRoot.dispatchTrackball(event, eventTime, callWhenDone);
|
||||
} else {
|
||||
new EventCompletion(mMainLooper, this, null, false, event);
|
||||
}
|
||||
|
||||
@@ -97,6 +97,14 @@ public class HandlerCaller {
|
||||
return mH.hasMessages(what);
|
||||
}
|
||||
|
||||
public void removeMessages(int what) {
|
||||
mH.removeMessages(what);
|
||||
}
|
||||
|
||||
public void removeMessages(int what, Object obj) {
|
||||
mH.removeMessages(what, obj);
|
||||
}
|
||||
|
||||
public void sendMessage(Message msg) {
|
||||
mH.sendMessage(msg);
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import android.graphics.Rect;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.service.wallpaper.WallpaperService;
|
||||
import android.util.Log;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.SurfaceHolder;
|
||||
import android.content.Context;
|
||||
import android.content.IntentFilter;
|
||||
@@ -75,6 +76,7 @@ public class ImageWallpaper extends WallpaperService {
|
||||
super.onCreate(surfaceHolder);
|
||||
updateWallpaper();
|
||||
surfaceHolder.setSizeFromLayout();
|
||||
//setTouchEventsEnabled(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -82,6 +84,12 @@ public class ImageWallpaper extends WallpaperService {
|
||||
drawFrame();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTouchEvent(MotionEvent event) {
|
||||
super.onTouchEvent(event);
|
||||
Log.i("foo", "Touch event: " + event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onOffsetsChanged(float xOffset, float yOffset,
|
||||
int xPixels, int yPixels) {
|
||||
|
||||
@@ -32,23 +32,47 @@ public class BaseIWindow extends IWindow.Stub {
|
||||
}
|
||||
}
|
||||
|
||||
public void dispatchPointer(MotionEvent event, long eventTime) {
|
||||
public boolean onDispatchPointer(MotionEvent event, long eventTime,
|
||||
boolean callWhenDone) {
|
||||
event.recycle();
|
||||
return false;
|
||||
}
|
||||
|
||||
public void dispatchPointer(MotionEvent event, long eventTime,
|
||||
boolean callWhenDone) {
|
||||
try {
|
||||
if (event == null) {
|
||||
event = mSession.getPendingPointerMove(this);
|
||||
} else if (event.getAction() != MotionEvent.ACTION_OUTSIDE) {
|
||||
mSession.finishKey(this);
|
||||
onDispatchPointer(event, eventTime, false);
|
||||
} else if (callWhenDone) {
|
||||
if (!onDispatchPointer(event, eventTime, true)) {
|
||||
mSession.finishKey(this);
|
||||
}
|
||||
} else {
|
||||
onDispatchPointer(event, eventTime, false);
|
||||
}
|
||||
} catch (RemoteException ex) {
|
||||
}
|
||||
}
|
||||
|
||||
public void dispatchTrackball(MotionEvent event, long eventTime) {
|
||||
public boolean onDispatchTrackball(MotionEvent event, long eventTime,
|
||||
boolean callWhenDone) {
|
||||
event.recycle();
|
||||
return false;
|
||||
}
|
||||
|
||||
public void dispatchTrackball(MotionEvent event, long eventTime,
|
||||
boolean callWhenDone) {
|
||||
try {
|
||||
if (event == null) {
|
||||
event = mSession.getPendingTrackballMove(this);
|
||||
} else if (event.getAction() != MotionEvent.ACTION_OUTSIDE) {
|
||||
mSession.finishKey(this);
|
||||
onDispatchTrackball(event, eventTime, false);
|
||||
} else if (callWhenDone) {
|
||||
if (!onDispatchTrackball(event, eventTime, true)) {
|
||||
mSession.finishKey(this);
|
||||
}
|
||||
} else {
|
||||
onDispatchTrackball(event, eventTime, false);
|
||||
}
|
||||
} catch (RemoteException ex) {
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user