implement focus keys capture and jni interaction. Some hackishness

required due to inconsistency in ordering of key events,
e.g. sometimes up not preceeded by down.
This commit is contained in:
eehouse 2010-02-27 18:05:54 +00:00
parent cb6b19f0aa
commit f0840f1e8d
3 changed files with 140 additions and 1 deletions

View file

@ -7,6 +7,7 @@ import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MenuInflater;
import android.view.KeyEvent;
import android.content.res.AssetManager;
import java.io.InputStream;
import android.os.Handler;
@ -288,6 +289,26 @@ public class BoardActivity extends Activity implements UtilCtxt {
super.onConfigurationChanged( newConfig );
}
@Override
public boolean onKeyDown( int keyCode, KeyEvent event )
{
XwJNI.XP_Key xpKey = keyCodeToXPKey( keyCode );
if ( XwJNI.XP_Key.XP_KEY_NONE != xpKey ) {
m_jniThread.handle( JNIThread.JNICmd.CMD_KEYDOWN, xpKey );
}
return super.onKeyDown( keyCode, event );
}
@Override
public boolean onKeyUp( int keyCode, KeyEvent event )
{
XwJNI.XP_Key xpKey = keyCodeToXPKey( keyCode );
if ( XwJNI.XP_Key.XP_KEY_NONE != xpKey ) {
m_jniThread.handle( JNIThread.JNICmd.CMD_KEYUP, xpKey );
}
return super.onKeyUp( keyCode, event );
}
protected void onDestroy()
{
byte[] state = XwJNI.game_saveToStream( m_jniGamePtr, null );
@ -394,6 +415,32 @@ public class BoardActivity extends Activity implements UtilCtxt {
return handled;
}
private XwJNI.XP_Key keyCodeToXPKey( int keyCode )
{
XwJNI.XP_Key xpKey = XwJNI.XP_Key.XP_KEY_NONE;
switch( keyCode ) {
case KeyEvent.KEYCODE_DPAD_CENTER:
xpKey = XwJNI.XP_Key.XP_RETURN_KEY;
break;
case KeyEvent.KEYCODE_DPAD_DOWN:
xpKey = XwJNI.XP_Key.XP_CURSOR_KEY_DOWN;
break;
case KeyEvent.KEYCODE_DPAD_LEFT:
xpKey = XwJNI.XP_Key.XP_CURSOR_KEY_LEFT;
break;
case KeyEvent.KEYCODE_DPAD_RIGHT:
xpKey = XwJNI.XP_Key.XP_CURSOR_KEY_RIGHT;
break;
case KeyEvent.KEYCODE_DPAD_UP:
xpKey = XwJNI.XP_Key.XP_CURSOR_KEY_UP;
break;
case KeyEvent.KEYCODE_SPACE:
xpKey = XwJNI.XP_Key.XP_RAISEFOCUS_KEY;
break;
}
return xpKey;
}
//////////////////////////////////////////
// XW_UtilCtxt interface implementation //
//////////////////////////////////////////

View file

@ -11,6 +11,7 @@ import android.os.Handler;
import android.os.Message;
import android.graphics.Paint;
import android.graphics.Rect;
import junit.framework.Assert;
import org.eehouse.android.xw4.R;
import org.eehouse.android.xw4.jni.CurGameInfo.DeviceRole;
@ -27,6 +28,8 @@ public class JNIThread extends Thread {
CMD_PEN_DOWN,
CMD_PEN_MOVE,
CMD_PEN_UP,
CMD_KEYDOWN,
CMD_KEYUP,
CMD_TIMER_FIRED,
CMD_COMMIT,
CMD_JUGGLE,
@ -57,6 +60,8 @@ public class JNIThread extends Thread {
private CurGameInfo m_gi;
private Handler m_handler;
private SyncedDraw m_drawer;
private static final int kMinDivWidth = 10;
private boolean m_keyDown = false;
LinkedBlockingQueue<QueueElem> m_queue;
@ -158,7 +163,7 @@ public class JNIThread extends Thread {
scoreHt + ((nCells-nToScroll) * cellSize),
nCells * cellSize, // width
trayHt, // height
4 );
kMinDivWidth );
XwJNI.board_invalAll( m_jniGamePtr );
}
@ -169,6 +174,61 @@ public class JNIThread extends Thread {
return null != nextElem && nextElem.m_cmd == cmd;
}
private boolean processKeyEvent( JNICmd cmd, XwJNI.XP_Key xpKey,
boolean[] barr )
{
boolean draw = false;
boolean handled = false;
boolean goingUp = JNICmd.CMD_KEYUP == cmd;
if ( m_keyDown && !goingUp ) {
// ignore duplicate downs for now
} else {
// sometimes ups come without prior downs. Fake a down in
// that case.
if ( goingUp && !m_keyDown ) {
draw = XwJNI.board_handleKey( m_jniGamePtr, xpKey, false, barr );
handled = barr[0];
}
if ( XwJNI.board_handleKey( m_jniGamePtr, xpKey, goingUp, barr ) ) {
handled = barr[0] || handled;
draw = true;
}
m_keyDown = !goingUp;
if ( goingUp && !handled ) {
int[] order = { DrawCtx.OBJ_SCORE,
DrawCtx.OBJ_BOARD,
DrawCtx.OBJ_TRAY };
int curType = XwJNI.board_getFocusOwner( m_jniGamePtr );
int cur = 0;
if ( DrawCtx.OBJ_NONE != curType ) {
for ( cur = 0; cur < order.length; ++cur ) {
if ( order[cur] == curType ) {
break;
}
}
}
cur += order.length;
switch( xpKey ) {
case XP_CURSOR_KEY_DOWN:
case XP_CURSOR_KEY_RIGHT:
++cur;
break;
case XP_CURSOR_KEY_UP:
case XP_CURSOR_KEY_LEFT:
--cur;
break;
}
cur %= order.length;
draw = XwJNI.board_focusChanged( m_jniGamePtr, order[cur] )
|| draw;
}
}
return draw;
}
public void run()
{
boolean[] barr = new boolean[1]; // scratch boolean
@ -246,6 +306,11 @@ public class JNIThread extends Thread {
((Integer)args[1]).intValue() );
break;
case CMD_KEYDOWN:
case CMD_KEYUP:
draw = processKeyEvent( elem.m_cmd, (XwJNI.XP_Key)args[0], barr );
break;
case CMD_COMMIT:
draw = XwJNI.board_commitTurn( m_jniGamePtr );
break;

View file

@ -112,6 +112,33 @@ public class XwJNI {
public static native String board_formatRemainingTiles( int gamePtr );
public static native boolean board_prefsChanged( int gamePtr,
CommonPrefs cp );
public static native int board_getFocusOwner( int gamePtr );
public static native boolean board_focusChanged( int gamePtr, int typ );
public enum XP_Key {
XP_KEY_NONE,
XP_CURSOR_KEY_DOWN,
XP_CURSOR_KEY_ALTDOWN,
XP_CURSOR_KEY_RIGHT,
XP_CURSOR_KEY_ALTRIGHT,
XP_CURSOR_KEY_UP,
XP_CURSOR_KEY_ALTUP,
XP_CURSOR_KEY_LEFT,
XP_CURSOR_KEY_ALTLEFT,
XP_CURSOR_KEY_DEL,
XP_RAISEFOCUS_KEY,
XP_RETURN_KEY,
XP_KEY_LAST
};
public static native boolean board_handleKey( int gamePtr, XP_Key key,
boolean up, boolean[] handled );
// public static native boolean board_handleKeyDown( XP_Key key,
// boolean[] handled );
// public static native boolean board_handleKeyRepeat( XP_Key key,
// boolean[] handled );
// Model
public static native String model_writeGameHistory( int gamePtr,
boolean gameOver );