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.
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -420,6 +420,13 @@ public abstract class WallpaperService extends Service {
|
||||
public void onSurfaceChanged(SurfaceHolder holder, int format, int width, int height) {
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
@@ -118,6 +118,23 @@ public interface SurfaceHolder {
|
||||
public void surfaceDestroyed(SurfaceHolder holder);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user