diff options
author | Dianne Hackborn <hackbod@google.com> | 2009-08-17 15:15:18 -0700 |
---|---|---|
committer | Dianne Hackborn <hackbod@google.com> | 2009-08-17 21:23:05 -0700 |
commit | 8df8b2b405c60cacf7a66c4e2ca078dd3d7ec7bd (patch) | |
tree | 302a410dcd7af7bbf61f435cd96dd8b7384def2e /core | |
parent | 948ee251276e1ce7f5c5517b24bf88a75e99f160 (diff) | |
download | frameworks_base-8df8b2b405c60cacf7a66c4e2ca078dd3d7ec7bd.zip frameworks_base-8df8b2b405c60cacf7a66c4e2ca078dd3d7ec7bd.tar.gz frameworks_base-8df8b2b405c60cacf7a66c4e2ca078dd3d7ec7bd.tar.bz2 |
Allow wallpapers to get touch events.
Diffstat (limited to 'core')
-rw-r--r-- | core/java/android/service/wallpaper/WallpaperService.java | 82 | ||||
-rw-r--r-- | core/java/android/view/IWindow.aidl | 4 | ||||
-rw-r--r-- | core/java/android/view/MotionEvent.java | 38 | ||||
-rw-r--r-- | core/java/android/view/SurfaceView.java | 6 | ||||
-rw-r--r-- | core/java/android/view/ViewRoot.java | 41 | ||||
-rw-r--r-- | core/java/com/android/internal/os/HandlerCaller.java | 8 | ||||
-rw-r--r-- | core/java/com/android/internal/service/wallpaper/ImageWallpaper.java | 8 | ||||
-rw-r--r-- | core/java/com/android/internal/view/BaseIWindow.java | 36 |
8 files changed, 184 insertions, 39 deletions
diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java index 0a3ffff..80a154b 100644 --- a/core/java/android/service/wallpaper/WallpaperService.java +++ b/core/java/android/service/wallpaper/WallpaperService.java @@ -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); @@ -185,6 +212,22 @@ public abstract class WallpaperService extends Service { } /** + * 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. */ @@ -208,6 +251,16 @@ public abstract class WallpaperService extends Service { } /** + * 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 * call to {@link WallpaperManager#setWallpaperOffsets(IBinder, float, float) @@ -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); } diff --git a/core/java/android/view/IWindow.aidl b/core/java/android/view/IWindow.aidl index ec2036e..ebc5f7b 100644 --- a/core/java/android/view/IWindow.aidl +++ b/core/java/android/view/IWindow.aidl @@ -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(); diff --git a/core/java/android/view/MotionEvent.java b/core/java/android/view/MotionEvent.java index e8bfa6a..b2f0c60 100644 --- a/core/java/android/view/MotionEvent.java +++ b/core/java/android/view/MotionEvent.java @@ -552,6 +552,44 @@ public final class MotionEvent implements Parcelable { } /** + * 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. */ diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java index 3b64945..ea879ed9 100644 --- a/core/java/android/view/SurfaceView.java +++ b/core/java/android/view/SurfaceView.java @@ -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 { diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java index 4623bb5..3b78060 100644 --- a/core/java/android/view/ViewRoot.java +++ b/core/java/android/view/ViewRoot.java @@ -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); } diff --git a/core/java/com/android/internal/os/HandlerCaller.java b/core/java/com/android/internal/os/HandlerCaller.java index e4c473d..5825024 100644 --- a/core/java/com/android/internal/os/HandlerCaller.java +++ b/core/java/com/android/internal/os/HandlerCaller.java @@ -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); } diff --git a/core/java/com/android/internal/service/wallpaper/ImageWallpaper.java b/core/java/com/android/internal/service/wallpaper/ImageWallpaper.java index 7147ac0..3f2979f 100644 --- a/core/java/com/android/internal/service/wallpaper/ImageWallpaper.java +++ b/core/java/com/android/internal/service/wallpaper/ImageWallpaper.java @@ -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 @@ -83,6 +85,12 @@ public class ImageWallpaper extends WallpaperService { } @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) { mXOffset = xOffset; diff --git a/core/java/com/android/internal/view/BaseIWindow.java b/core/java/com/android/internal/view/BaseIWindow.java index a030db7..f4f6297 100644 --- a/core/java/com/android/internal/view/BaseIWindow.java +++ b/core/java/com/android/internal/view/BaseIWindow.java @@ -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) { } |