diff options
author | Dianne Hackborn <hackbod@google.com> | 2010-07-13 18:55:52 -0700 |
---|---|---|
committer | Android Git Automerger <android-git-automerger@android.com> | 2010-07-13 18:55:52 -0700 |
commit | f8d9379bd834573feca085284970cf686993c330 (patch) | |
tree | d603a4c197ba91ab2103a04d244e3f1004bef9e3 /core/java | |
parent | 89ee578b7053d27a50922f82feb94bf6054b330c (diff) | |
parent | d76b67c340d1564abf8d14d976fdaf83bf2b3320 (diff) | |
download | frameworks_base-f8d9379bd834573feca085284970cf686993c330.zip frameworks_base-f8d9379bd834573feca085284970cf686993c330.tar.gz frameworks_base-f8d9379bd834573feca085284970cf686993c330.tar.bz2 |
am d76b67c3: IME events are now dispatched to native applications.
Merge commit 'd76b67c340d1564abf8d14d976fdaf83bf2b3320' into gingerbread-plus-aosp
* commit 'd76b67c340d1564abf8d14d976fdaf83bf2b3320':
IME events are now dispatched to native applications.
Diffstat (limited to 'core/java')
-rw-r--r-- | core/java/android/app/NativeActivity.java | 101 | ||||
-rw-r--r-- | core/java/android/service/wallpaper/WallpaperService.java | 47 | ||||
-rw-r--r-- | core/java/android/view/SurfaceHolder.java | 17 | ||||
-rw-r--r-- | core/java/android/view/SurfaceView.java | 37 | ||||
-rw-r--r-- | core/java/android/view/ViewRoot.java | 14 | ||||
-rw-r--r-- | core/java/android/view/Window.java | 2 | ||||
-rw-r--r-- | core/java/com/android/internal/view/RootViewSurfaceTaker.java | 2 |
7 files changed, 183 insertions, 37 deletions
diff --git a/core/java/android/app/NativeActivity.java b/core/java/android/app/NativeActivity.java index d72dda7..ccc9ae3 100644 --- a/core/java/android/app/NativeActivity.java +++ b/core/java/android/app/NativeActivity.java @@ -2,6 +2,7 @@ package android.app; import dalvik.system.PathClassLoader; +import android.content.Context; import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; @@ -11,12 +12,16 @@ import android.os.Bundle; import android.os.Environment; import android.os.Looper; import android.os.MessageQueue; +import android.util.AttributeSet; import android.view.InputChannel; import android.view.InputQueue; import android.view.KeyEvent; import android.view.Surface; import android.view.SurfaceHolder; import android.view.View; +import android.view.WindowManager; +import android.view.ViewTreeObserver.OnGlobalLayoutListener; +import android.view.inputmethod.InputMethodManager; import java.io.File; @@ -24,15 +29,26 @@ import java.io.File; * Convenience for implementing an activity that will be implemented * purely in native code. That is, a game (or game-like thing). */ -public class NativeActivity extends Activity implements SurfaceHolder.Callback, - InputQueue.Callback { +public class NativeActivity extends Activity implements SurfaceHolder.Callback2, + InputQueue.Callback, OnGlobalLayoutListener { public static final String META_DATA_LIB_NAME = "android.app.lib_name"; + private NativeContentView mNativeContentView; + private InputMethodManager mIMM; + private int mNativeHandle; private InputQueue mCurInputQueue; private SurfaceHolder mCurSurfaceHolder; + final int[] mLocation = new int[2]; + int mLastContentX; + int mLastContentY; + int mLastContentWidth; + int mLastContentHeight; + + private boolean mDispatchingUnhandledKey; + private boolean mDestroyed; private native int loadNativeCode(String path, MessageQueue queue, @@ -49,18 +65,44 @@ public class NativeActivity extends Activity implements SurfaceHolder.Callback, private native void onSurfaceCreatedNative(int handle, Surface surface); private native void onSurfaceChangedNative(int handle, Surface surface, int format, int width, int height); + private native void onSurfaceRedrawNeededNative(int handle, Surface surface); private native void onSurfaceDestroyedNative(int handle); private native void onInputChannelCreatedNative(int handle, InputChannel channel); private native void onInputChannelDestroyedNative(int handle, InputChannel channel); + private native void onContentRectChangedNative(int handle, int x, int y, int w, int h); + private native void dispatchKeyEventNative(int handle, KeyEvent event); + + static class NativeContentView extends View { + NativeActivity mActivity; + + public NativeContentView(Context context) { + super(context); + } + + public NativeContentView(Context context, AttributeSet attrs) { + super(context, attrs); + } + } @Override protected void onCreate(Bundle savedInstanceState) { String libname = "main"; ActivityInfo ai; + mIMM = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE); + getWindow().takeSurface(this); getWindow().takeInputQueue(this); getWindow().setFormat(PixelFormat.RGB_565); + getWindow().setSoftInputMode( + WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED + | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE); + + mNativeContentView = new NativeContentView(this); + mNativeContentView.mActivity = this; + setContentView(mNativeContentView); + mNativeContentView.requestFocus(); + mNativeContentView.getViewTreeObserver().addOnGlobalLayoutListener(this); try { ai = getPackageManager().getActivityInfo( @@ -165,6 +207,18 @@ public class NativeActivity extends Activity implements SurfaceHolder.Callback, } } + @Override + public boolean dispatchKeyEvent(KeyEvent event) { + if (mDispatchingUnhandledKey) { + return super.dispatchKeyEvent(event); + } else { + // Key events from the IME do not go through the input channel; + // we need to intercept them here to hand to the application. + dispatchKeyEventNative(mNativeHandle, event); + return true; + } + } + public void surfaceCreated(SurfaceHolder holder) { if (!mDestroyed) { mCurSurfaceHolder = holder; @@ -179,6 +233,13 @@ public class NativeActivity extends Activity implements SurfaceHolder.Callback, } } + public void surfaceRedrawNeeded(SurfaceHolder holder) { + if (!mDestroyed) { + mCurSurfaceHolder = holder; + onSurfaceRedrawNeededNative(mNativeHandle, holder.getSurface()); + } + } + public void surfaceDestroyed(SurfaceHolder holder) { mCurSurfaceHolder = null; if (!mDestroyed) { @@ -200,10 +261,32 @@ public class NativeActivity extends Activity implements SurfaceHolder.Callback, } } + public void onGlobalLayout() { + mNativeContentView.getLocationInWindow(mLocation); + int w = mNativeContentView.getWidth(); + int h = mNativeContentView.getHeight(); + if (mLocation[0] != mLastContentX || mLocation[1] != mLastContentY + || w != mLastContentWidth || h != mLastContentHeight) { + mLastContentX = mLocation[0]; + mLastContentY = mLocation[1]; + mLastContentWidth = w; + mLastContentHeight = h; + if (!mDestroyed) { + onContentRectChangedNative(mNativeHandle, mLastContentX, + mLastContentY, mLastContentWidth, mLastContentHeight); + } + } + } + void dispatchUnhandledKeyEvent(KeyEvent event) { - View decor = getWindow().getDecorView(); - if (decor != null) { - decor.dispatchKeyEvent(event); + try { + mDispatchingUnhandledKey = true; + View decor = getWindow().getDecorView(); + if (decor != null) { + decor.dispatchKeyEvent(event); + } + } finally { + mDispatchingUnhandledKey = false; } } @@ -214,4 +297,12 @@ public class NativeActivity extends Activity implements SurfaceHolder.Callback, void setWindowFormat(int format) { getWindow().setFormat(format); } + + void showIme(int mode) { + mIMM.showSoftInput(mNativeContentView, mode); + } + + void hideIme(int mode) { + mIMM.hideSoftInputFromWindow(mNativeContentView.getWindowToken(), mode); + } } diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java index 6f12f19..2d120e8 100644 --- a/core/java/android/service/wallpaper/WallpaperService.java +++ b/core/java/android/service/wallpaper/WallpaperService.java @@ -336,7 +336,7 @@ public abstract class WallpaperService extends Service { ? (mWindowFlags&~WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE) : (mWindowFlags|WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE); if (mCreated) { - updateSurface(false, false); + updateSurface(false, false, false); } } @@ -421,6 +421,13 @@ public abstract class WallpaperService extends Service { } /** + * Convenience for {@link SurfaceHolder.Callback#surfaceRedrawNeeded + * SurfaceHolder.Callback.surfaceRedrawNeeded()}. + */ + public void onSurfaceRedrawNeeded(SurfaceHolder holder) { + } + + /** * Convenience for {@link SurfaceHolder.Callback#surfaceCreated * SurfaceHolder.Callback.surfaceCreated()}. */ @@ -450,7 +457,7 @@ public abstract class WallpaperService extends Service { } } - void updateSurface(boolean forceRelayout, boolean forceReport) { + void updateSurface(boolean forceRelayout, boolean forceReport, boolean redrawNeeded) { if (mDestroyed) { Log.w(TAG, "Ignoring updateSurface: destroyed"); } @@ -467,7 +474,7 @@ public abstract class WallpaperService extends Service { final boolean typeChanged = mType != mSurfaceHolder.getRequestedType(); final boolean flagsChanged = mCurWindowFlags != mWindowFlags; if (forceRelayout || creating || surfaceCreating || formatChanged || sizeChanged - || typeChanged || flagsChanged) { + || typeChanged || flagsChanged || redrawNeeded) { if (DEBUG) Log.v(TAG, "Changes: creating=" + creating + " format=" + formatChanged + " size=" + sizeChanged); @@ -555,6 +562,10 @@ public abstract class WallpaperService extends Service { } } } + + redrawNeeded |= creating + || (relayoutResult&WindowManagerImpl.RELAYOUT_FIRST_TIME) != 0; + if (forceReport || creating || surfaceCreating || formatChanged || sizeChanged) { if (DEBUG) { @@ -578,10 +589,24 @@ public abstract class WallpaperService extends Service { } } } + + if (redrawNeeded) { + onSurfaceRedrawNeeded(mSurfaceHolder); + SurfaceHolder.Callback callbacks[] = mSurfaceHolder.getCallbacks(); + if (callbacks != null) { + for (SurfaceHolder.Callback c : callbacks) { + if (c instanceof SurfaceHolder.Callback2) { + ((SurfaceHolder.Callback2)c).surfaceRedrawNeeded( + mSurfaceHolder); + } + } + } + } + } finally { mIsCreating = false; mSurfaceCreated = true; - if (creating || (relayoutResult&WindowManagerImpl.RELAYOUT_FIRST_TIME) != 0) { + if (redrawNeeded) { mSession.finishDrawing(mWindow); } } @@ -618,7 +643,7 @@ public abstract class WallpaperService extends Service { onCreate(mSurfaceHolder); mInitializing = false; - updateSurface(false, false); + updateSurface(false, false, false); } void doDesiredSizeChanged(int desiredWidth, int desiredHeight) { @@ -647,7 +672,7 @@ public abstract class WallpaperService extends Service { // If becoming visible, in preview mode the surface // may have been destroyed so now we need to make // sure it is re-created. - updateSurface(false, false); + updateSurface(false, false, false); } onVisibilityChanged(visible); } @@ -852,7 +877,7 @@ public abstract class WallpaperService extends Service { return; } case MSG_UPDATE_SURFACE: - mEngine.updateSurface(true, false); + mEngine.updateSurface(true, false, false); break; case MSG_VISIBILITY_CHANGED: if (DEBUG) Log.v(TAG, "Visibility change in " + mEngine @@ -868,14 +893,8 @@ public abstract class WallpaperService extends Service { } break; case MSG_WINDOW_RESIZED: { final boolean reportDraw = message.arg1 != 0; - mEngine.updateSurface(true, false); + mEngine.updateSurface(true, false, reportDraw); mEngine.doOffsetsChanged(); - if (reportDraw) { - try { - mEngine.mSession.finishDrawing(mEngine.mWindow); - } catch (RemoteException e) { - } - } } break; case MSG_TOUCH_EVENT: { MotionEvent ev = (MotionEvent)message.obj; diff --git a/core/java/android/view/SurfaceHolder.java b/core/java/android/view/SurfaceHolder.java index 34e4638..0d38f7b 100644 --- a/core/java/android/view/SurfaceHolder.java +++ b/core/java/android/view/SurfaceHolder.java @@ -119,6 +119,23 @@ public interface SurfaceHolder { } /** + * Additional callbacks that can be received for {@link Callback}. + */ + public interface Callback2 extends Callback { + /** + * Called when the application needs to redraw the content of its + * surface, after it is resized or for some other reason. By not + * returning here until the redraw is complete, you can ensure that + * the user will not see your surface in a bad state (at its new + * size before it has been correctly drawn that way). This will + * typically be preceeded by a call to {@link #surfaceChanged}. + * + * @param holder The SurfaceHolder whose surface has changed. + */ + public void surfaceRedrawNeeded(SurfaceHolder holder); + } + + /** * Add a Callback interface for this holder. There can several Callback * interfaces associated to a holder. * diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java index e4d1ae1..c469bcc 100644 --- a/core/java/android/view/SurfaceView.java +++ b/core/java/android/view/SurfaceView.java @@ -123,7 +123,7 @@ public class SurfaceView extends View { handleGetNewSurface(); } break; case UPDATE_WINDOW_MSG: { - updateWindow(false); + updateWindow(false, false); } break; } } @@ -132,7 +132,7 @@ public class SurfaceView extends View { final ViewTreeObserver.OnScrollChangedListener mScrollChangedListener = new ViewTreeObserver.OnScrollChangedListener() { public void onScrollChanged() { - updateWindow(false); + updateWindow(false, false); } }; @@ -210,7 +210,7 @@ public class SurfaceView extends View { super.onWindowVisibilityChanged(visibility); mWindowVisibility = visibility == VISIBLE; mRequestedVisible = mWindowVisibility && mViewVisibility; - updateWindow(false); + updateWindow(false, false); } @Override @@ -218,7 +218,7 @@ public class SurfaceView extends View { super.setVisibility(visibility); mViewVisibility = visibility == VISIBLE; mRequestedVisible = mWindowVisibility && mViewVisibility; - updateWindow(false); + updateWindow(false, false); } /** @@ -232,7 +232,7 @@ public class SurfaceView extends View { */ protected void showSurface() { if (mSession != null) { - updateWindow(true); + updateWindow(true, false); } } @@ -265,7 +265,7 @@ public class SurfaceView extends View { protected void onDetachedFromWindow() { getViewTreeObserver().removeOnScrollChangedListener(mScrollChangedListener); mRequestedVisible = false; - updateWindow(false); + updateWindow(false, false); mHaveFrame = false; if (mWindow != null) { try { @@ -290,7 +290,7 @@ public class SurfaceView extends View { @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); - updateWindow(false); + updateWindow(false, false); } @Override @@ -343,7 +343,7 @@ public class SurfaceView extends View { } // reposition ourselves where the surface is mHaveFrame = true; - updateWindow(false); + updateWindow(false, false); super.dispatchDraw(canvas); } @@ -397,7 +397,7 @@ public class SurfaceView extends View { mWindowType = type; } - private void updateWindow(boolean force) { + private void updateWindow(boolean force, boolean redrawNeeded) { if (!mHaveFrame) { return; } @@ -425,7 +425,7 @@ public class SurfaceView extends View { final boolean typeChanged = mType != mRequestedType; if (force || creating || formatChanged || sizeChanged || visibleChanged || typeChanged || mLeft != mLocation[0] || mTop != mLocation[1] - || mUpdateWindowNeeded || mReportDrawNeeded) { + || mUpdateWindowNeeded || mReportDrawNeeded || redrawNeeded) { if (localLOGV) Log.i(TAG, "Changes: creating=" + creating + " format=" + formatChanged + " size=" + sizeChanged @@ -524,6 +524,8 @@ public class SurfaceView extends View { } try { + redrawNeeded |= creating | reportDrawNeeded; + if (visible) { mDestroyReportNeeded = true; @@ -541,8 +543,13 @@ public class SurfaceView extends View { } if (creating || formatChanged || sizeChanged || visibleChanged || realSizeChanged) { + } + if (redrawNeeded) { for (SurfaceHolder.Callback c : callbacks) { - c.surfaceChanged(mSurfaceHolder, mFormat, myWidth, myHeight); + if (c instanceof SurfaceHolder.Callback2) { + ((SurfaceHolder.Callback2)c).surfaceRedrawNeeded( + mSurfaceHolder); + } } } } else { @@ -550,7 +557,7 @@ public class SurfaceView extends View { } } finally { mIsCreating = false; - if (creating || reportDrawNeeded) { + if (redrawNeeded) { mSession.finishDrawing(mWindow); } } @@ -580,7 +587,7 @@ public class SurfaceView extends View { void handleGetNewSurface() { mNewSurfaceNeeded = true; - updateWindow(false); + updateWindow(false, false); } /** @@ -696,7 +703,7 @@ public class SurfaceView extends View { mRequestedFormat = format; if (mWindow != null) { - updateWindow(false); + updateWindow(false, false); } } @@ -713,7 +720,7 @@ public class SurfaceView extends View { case SURFACE_TYPE_PUSH_BUFFERS: mRequestedType = type; if (mWindow != null) { - updateWindow(false); + updateWindow(false, false); } break; } diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java index fb45971..260bf7bc 100644 --- a/core/java/android/view/ViewRoot.java +++ b/core/java/android/view/ViewRoot.java @@ -137,7 +137,7 @@ public final class ViewRoot extends Handler implements ViewParent, int mViewVisibility; boolean mAppVisible = true; - SurfaceHolder.Callback mSurfaceHolderCallback; + SurfaceHolder.Callback2 mSurfaceHolderCallback; BaseSurfaceHolder mSurfaceHolder; boolean mIsCreating; boolean mDrawingAllowed; @@ -1263,6 +1263,18 @@ public final class ViewRoot extends Handler implements ViewParent, Log.v("ViewRoot", "FINISHED DRAWING: " + mWindowAttributes.getTitle()); } mReportNextDraw = false; + if (mSurfaceHolder != null && mSurface.isValid()) { + mSurfaceHolderCallback.surfaceRedrawNeeded(mSurfaceHolder); + SurfaceHolder.Callback callbacks[] = mSurfaceHolder.getCallbacks(); + if (callbacks != null) { + for (SurfaceHolder.Callback c : callbacks) { + if (c instanceof SurfaceHolder.Callback2) { + ((SurfaceHolder.Callback2)c).surfaceRedrawNeeded( + mSurfaceHolder); + } + } + } + } try { sWindowSession.finishDrawing(mWindow); } catch (RemoteException e) { diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java index f40734b..11c09c1 100644 --- a/core/java/android/view/Window.java +++ b/core/java/android/view/Window.java @@ -478,7 +478,7 @@ public abstract class Window { * to operate (such as for receiving input events). The given SurfaceHolder * callback will be used to tell you about state changes to the surface. */ - public abstract void takeSurface(SurfaceHolder.Callback callback); + public abstract void takeSurface(SurfaceHolder.Callback2 callback); /** * Take ownership of this window's InputQueue. The window will no diff --git a/core/java/com/android/internal/view/RootViewSurfaceTaker.java b/core/java/com/android/internal/view/RootViewSurfaceTaker.java index 7ff8d4c..9c1b558 100644 --- a/core/java/com/android/internal/view/RootViewSurfaceTaker.java +++ b/core/java/com/android/internal/view/RootViewSurfaceTaker.java @@ -5,7 +5,7 @@ import android.view.SurfaceHolder; /** hahahah */ public interface RootViewSurfaceTaker { - SurfaceHolder.Callback willYouTakeTheSurface(); + SurfaceHolder.Callback2 willYouTakeTheSurface(); void setSurfaceType(int type); void setSurfaceFormat(int format); void setSurfaceKeepScreenOn(boolean keepOn); |