aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2013-02-28 13:31:29 +0100
committerSven Gothel <[email protected]>2013-02-28 13:31:29 +0100
commit3a4892c43be4a9dabba73d42175c2cfa39bd6d8d (patch)
tree8780bb35234f6d16c89efc34c94409816f54464a
parent1f9bff1aab54c399438c735581508ac85c6a29b3 (diff)
Fix Bug 677: NEWT/Android: Add support for Android's KeyEvent.KEYCODE_BACK
Original author: Eric Brayet <[email protected]> Revised by: Sven Gothel <[email protected]> I took the freedom to cleanup the three original patches from https://github.com/Pooouf/jogl.git branch 'bug_677': - 7449d4726633d524a3bb79efffd04cfd0ca25e58 (removed by followup patch!) - 68c739a4f03e46deecdbb71c125b4586aec08d63 (removes previous patch!) - c2813dfc325a1482d18b6fc304e4e483f5633964 Further more I was able to reduce the 'extra' code while utilizing - Window's isKeyboardVisible() and using keyboardVisibilityChanged(false) to update the hidden keyboard state. - Moving the key-handling code to the containing WindowDriver class avoiding passing a reference to the inner view. - Using AndroidNewtEventFactory for NEWT KeyEvent creation +++ - Handle KeyEvent.KEYCODE_BACK w/ jogamp.newt.driver.android.WindowDriver.MSurfaceView.onKeyPreIme(..): if( soft keyboard is up ) [1] Update keyboard visibility state and return NEWT KeyEvent.VK_KEYBOARD_INVISIBLE; else [2] call WindowImpl.windowDestroyNotify(true) [3] then cont. processing, i.e. return false; - Turns out respecting WindowClosingMode might be - too complicated - interfere w/ Android UI behavior - AndroidNewtEventFactory - createKeyEvent - static - adding boolean param 'inclSysKeys', if true, KEYCODE_BACK and KEYCODE_HOME are mapped - Unit tests: GearsES2 + MovieCubeActivity0 shows keyboard if pressure > 0.6f - pressure on Android shall be between [0..1], however we have to figure out badly calibrated touchpads/Android device where we could experience pressure > 2.0f ! - TODO: API documentation of pressure [0..1]
-rw-r--r--src/newt/classes/com/jogamp/newt/event/KeyEvent.java5
-rw-r--r--src/newt/classes/com/jogamp/newt/event/NEWTEvent.java2
-rw-r--r--src/newt/classes/jogamp/newt/driver/android/WindowDriver.java39
-rw-r--r--src/newt/classes/jogamp/newt/driver/android/event/AndroidNewtEventFactory.java88
-rw-r--r--src/newt/classes/jogamp/newt/driver/android/event/AndroidNewtEventTranslator.java2
-rw-r--r--src/test/com/jogamp/opengl/test/android/MovieCubeActivity0.java2
-rw-r--r--src/test/com/jogamp/opengl/test/android/NEWTGearsES2Activity.java8
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/GearsES2.java4
8 files changed, 105 insertions, 45 deletions
diff --git a/src/newt/classes/com/jogamp/newt/event/KeyEvent.java b/src/newt/classes/com/jogamp/newt/event/KeyEvent.java
index f626fec38..5117ffe29 100644
--- a/src/newt/classes/com/jogamp/newt/event/KeyEvent.java
+++ b/src/newt/classes/com/jogamp/newt/event/KeyEvent.java
@@ -872,6 +872,11 @@ public class KeyEvent extends InputEvent
public static final short VK_BEGIN = (short) 0xFF58;
/**
+ * Constant for Keyboard became invisible, e.g. Android's soft keyboard Back button hit while keyboard is visible.
+ */
+ public static final short VK_KEYBOARD_INVISIBLE = (short) 0xDEAD;
+
+ /**
* This value is used to indicate that the keyCode is unknown.
* KEY_TYPED events do not have a keyCode value; this value
* is used instead.
diff --git a/src/newt/classes/com/jogamp/newt/event/NEWTEvent.java b/src/newt/classes/com/jogamp/newt/event/NEWTEvent.java
index 6f4561ce6..17210cef8 100644
--- a/src/newt/classes/com/jogamp/newt/event/NEWTEvent.java
+++ b/src/newt/classes/com/jogamp/newt/event/NEWTEvent.java
@@ -107,7 +107,7 @@ public class NEWTEvent extends java.util.EventObject {
return sb.append("NEWTEvent[source:").append(getSource().getClass().getName()).append(", when:").append(getWhen()).append(" d ").append((System.currentTimeMillis()-getWhen())).append("ms]");
}
- static String toHexString(short hex) {
+ public static String toHexString(short hex) {
return "0x" + Integer.toHexString( (int)hex & 0x0000FFFF );
}
}
diff --git a/src/newt/classes/jogamp/newt/driver/android/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/android/WindowDriver.java
index a85febca0..c5371ae9c 100644
--- a/src/newt/classes/jogamp/newt/driver/android/WindowDriver.java
+++ b/src/newt/classes/jogamp/newt/driver/android/WindowDriver.java
@@ -30,6 +30,7 @@ package jogamp.newt.driver.android;
import jogamp.common.os.android.StaticContext;
import jogamp.newt.WindowImpl;
+import jogamp.newt.driver.android.event.AndroidNewtEventFactory;
import jogamp.newt.driver.android.event.AndroidNewtEventTranslator;
import javax.media.nativewindow.Capabilities;
@@ -65,6 +66,8 @@ import android.view.SurfaceHolder.Callback2;
import android.view.ViewGroup;
import android.view.inputmethod.InputMethodManager;
import android.view.SurfaceView;
+import android.view.KeyEvent;
+
public class WindowDriver extends jogamp.newt.WindowImpl implements Callback2 {
static {
@@ -573,10 +576,8 @@ public class WindowDriver extends jogamp.newt.WindowImpl implements Callback2 {
@Override
public final void surfaceDestroyed(SurfaceHolder holder) {
Log.d(MD.TAG, "surfaceDestroyed - on thread "+Thread.currentThread().getName());
- if(WindowImpl.DEBUG_IMPLEMENTATION) {
- Thread.dumpStack();
- }
windowDestroyNotify(true); // actually too late .. however ..
+ Thread.dumpStack();
}
@Override
@@ -585,6 +586,27 @@ public class WindowDriver extends jogamp.newt.WindowImpl implements Callback2 {
windowRepaint(0, 0, getWidth(), getHeight());
}
+ protected boolean handleKeyCodeBack(KeyEvent.DispatcherState state, android.view.KeyEvent event) {
+ if (event.getAction() == KeyEvent.ACTION_DOWN && event.getRepeatCount() == 0) {
+ state.startTracking(event, this);
+ } else if (event.getAction() == KeyEvent.ACTION_UP && !event.isCanceled() && state.isTracking(event)) {
+ if( isKeyboardVisible() ) {
+ keyboardVisibilityChanged(false);
+ enqueueAKey2NKeyUpDown(event);
+ } else {
+ Log.d(MD.TAG, "handleKeyCodeBack : "+event);
+ windowDestroyNotify(true);
+ }
+ }
+ return false; // cont. processing
+ }
+ private void enqueueAKey2NKeyUpDown(android.view.KeyEvent aEvent) {
+ final com.jogamp.newt.event.KeyEvent eDown = AndroidNewtEventFactory.createKeyEvent(aEvent, com.jogamp.newt.event.KeyEvent.EVENT_KEY_PRESSED, this, true);
+ final com.jogamp.newt.event.KeyEvent eUp = AndroidNewtEventFactory.createKeyEvent(aEvent, com.jogamp.newt.event.KeyEvent.EVENT_KEY_RELEASED, this, true);
+ enqueueEvent(false, eDown);
+ enqueueEvent(false, eUp);
+ }
+
private boolean added2StaticViewGroup;
private MSurfaceView androidView;
private int nativeFormat; // chosen current native PixelFormat (suitable for EGL)
@@ -600,6 +622,17 @@ public class WindowDriver extends jogamp.newt.WindowImpl implements Callback2 {
setBackgroundDrawable(null);
// setBackgroundColor(Color.TRANSPARENT);
}
+
+ @Override
+ public boolean onKeyPreIme(int keyCode, KeyEvent event) {
+ if ( event.getKeyCode() == KeyEvent.KEYCODE_BACK ) {
+ final KeyEvent.DispatcherState state = getKeyDispatcherState();
+ if (state != null) {
+ return handleKeyCodeBack(state, event);
+ }
+ }
+ return false; // cont. processing
+ }
}
//----------------------------------------------------------------------
// Internals only
diff --git a/src/newt/classes/jogamp/newt/driver/android/event/AndroidNewtEventFactory.java b/src/newt/classes/jogamp/newt/driver/android/event/AndroidNewtEventFactory.java
index 4f19e9c4d..a9c642d8c 100644
--- a/src/newt/classes/jogamp/newt/driver/android/event/AndroidNewtEventFactory.java
+++ b/src/newt/classes/jogamp/newt/driver/android/event/AndroidNewtEventFactory.java
@@ -31,6 +31,7 @@ package jogamp.newt.driver.android.event;
import com.jogamp.common.os.AndroidVersion;
import com.jogamp.newt.Window;
import com.jogamp.newt.event.InputEvent;
+import com.jogamp.newt.event.NEWTEvent;
public class AndroidNewtEventFactory {
@@ -86,7 +87,7 @@ public class AndroidNewtEventFactory {
return (short)0;
}
- private static final short aKeyCode2NewtKeyCode(int androidKeyCode) {
+ private static final short aKeyCode2NewtKeyCode(int androidKeyCode, boolean inclSysKeys) {
if(android.view.KeyEvent.KEYCODE_0 <= androidKeyCode && androidKeyCode <= android.view.KeyEvent.KEYCODE_9) {
return (short) ( com.jogamp.newt.event.KeyEvent.VK_0 + ( androidKeyCode - android.view.KeyEvent.KEYCODE_0 ) );
}
@@ -122,11 +123,19 @@ public class AndroidNewtEventFactory {
// case android.view.KeyEvent.KEYCODE_MUTE: ??
case android.view.KeyEvent.KEYCODE_PAGE_UP: return com.jogamp.newt.event.KeyEvent.VK_PAGE_UP;
case android.view.KeyEvent.KEYCODE_PAGE_DOWN: return com.jogamp.newt.event.KeyEvent.VK_PAGE_DOWN;
- // case android.view.KeyEvent.KEYCODE_HOME: return com.jogamp.newt.event.KeyEvent.VK_HOME;
- // case android.view.KeyEvent.KEYCODE_BACK: return com.jogamp.newt.event.KeyEvent.VK_BACK_SPACE;
case android.view.KeyEvent.KEYCODE_ESCAPE: return com.jogamp.newt.event.KeyEvent.VK_ESCAPE;
case android.view.KeyEvent.KEYCODE_CTRL_LEFT: return com.jogamp.newt.event.KeyEvent.VK_CONTROL;
case android.view.KeyEvent.KEYCODE_CTRL_RIGHT: return com.jogamp.newt.event.KeyEvent.VK_CONTROL; // ??
+ case android.view.KeyEvent.KEYCODE_BACK:
+ if( inclSysKeys ) {
+ return com.jogamp.newt.event.KeyEvent.VK_KEYBOARD_INVISIBLE;
+ }
+ break;
+ case android.view.KeyEvent.KEYCODE_HOME:
+ if( inclSysKeys ) {
+ return com.jogamp.newt.event.KeyEvent.VK_HOME;
+ }
+ break;
}
return (short)0;
}
@@ -140,19 +149,7 @@ public class AndroidNewtEventFactory {
return newtMods;
}
- private final NewtGestureListener gestureListener;
- private final android.view.GestureDetector gestureDetector;
- private final float touchSlop;
-
- public AndroidNewtEventFactory(android.content.Context context, android.os.Handler handler) {
- gestureListener = new NewtGestureListener();
- gestureDetector = new android.view.GestureDetector(context, gestureListener, handler, false /* ignoreMultitouch */);
- gestureDetector.setIsLongpressEnabled(false); // favor scroll event!
- final android.view.ViewConfiguration configuration = android.view.ViewConfiguration.get(context);
- touchSlop = configuration.getScaledTouchSlop();
- }
-
- public com.jogamp.newt.event.WindowEvent createWindowEvent(android.view.accessibility.AccessibilityEvent event, com.jogamp.newt.Window newtSource) {
+ public static com.jogamp.newt.event.WindowEvent createWindowEvent(android.view.accessibility.AccessibilityEvent event, com.jogamp.newt.Window newtSource) {
final int aType = event.getEventType();
final short nType = aAccessibilityEventType2Newt(aType);
@@ -163,25 +160,54 @@ public class AndroidNewtEventFactory {
}
- public com.jogamp.newt.event.KeyEvent createKeyEvent(int keyCode, android.view.KeyEvent event, com.jogamp.newt.Window newtSource) {
- final short type = aKeyEventType2NewtEventType(event.getAction());
- if(Window.DEBUG_MOUSE_EVENT) {
- System.err.println("createKeyEvent: type 0x"+Integer.toHexString(type)+", keyCode 0x"+Integer.toHexString(keyCode)+", "+event);
+ public static com.jogamp.newt.event.KeyEvent createKeyEvent(android.view.KeyEvent aEvent, com.jogamp.newt.Window newtSource, boolean inclSysKeys) {
+ final com.jogamp.newt.event.KeyEvent res;
+ final short newtType = aKeyEventType2NewtEventType(aEvent.getAction());
+ if( (short)0 != newtType) {
+ final short newtKeyCode = aKeyCode2NewtKeyCode(aEvent.getKeyCode(), inclSysKeys);
+ res = createKeyEventImpl(aEvent, newtType, newtKeyCode, newtSource);
+ } else {
+ res = null;
}
- if( (short)0 != type) {
- final short newtKeyCode = aKeyCode2NewtKeyCode(keyCode);
- if( (short)0 != newtKeyCode ) {
- final Object src = (null==newtSource)?null:(Object)newtSource;
- final long unixTime = System.currentTimeMillis() + ( event.getEventTime() - android.os.SystemClock.uptimeMillis() );
- final int newtMods = aKeyModifiers2Newt(event.getMetaState());
-
- return new com.jogamp.newt.event.KeyEvent(
- type, src, unixTime, newtMods, newtKeyCode, newtKeyCode, (char) event.getUnicodeChar());
- }
+ if(Window.DEBUG_KEY_EVENT) {
+ System.err.println("createKeyEvent0: "+aEvent+" -> "+res);
}
- return null;
+ return res;
}
+ public static com.jogamp.newt.event.KeyEvent createKeyEvent(android.view.KeyEvent aEvent, short newtType, com.jogamp.newt.Window newtSource, boolean inclSysKeys) {
+ final short newtKeyCode = aKeyCode2NewtKeyCode(aEvent.getKeyCode(), inclSysKeys);
+ final com.jogamp.newt.event.KeyEvent res = createKeyEventImpl(aEvent, newtType, newtKeyCode, newtSource);
+ if(Window.DEBUG_KEY_EVENT) {
+ System.err.println("createKeyEvent1: newtType "+NEWTEvent.toHexString(newtType)+", "+aEvent+" -> "+res);
+ }
+ return res;
+ }
+
+ private static com.jogamp.newt.event.KeyEvent createKeyEventImpl(android.view.KeyEvent aEvent, short newtType, short newtKeyCode, com.jogamp.newt.Window newtSource) {
+ if( (short)0 != newtType && (short)0 != newtKeyCode ) {
+ final Object src = null==newtSource ? null : newtSource;
+ final long unixTime = System.currentTimeMillis() + ( aEvent.getEventTime() - android.os.SystemClock.uptimeMillis() );
+ final int newtMods = aKeyModifiers2Newt(aEvent.getMetaState());
+
+ return new com.jogamp.newt.event.KeyEvent(
+ newtType, src, unixTime, newtMods, newtKeyCode, newtKeyCode, (char) aEvent.getUnicodeChar());
+ }
+ return null;
+ }
+
+ private final NewtGestureListener gestureListener;
+ private final android.view.GestureDetector gestureDetector;
+ private final float touchSlop;
+
+ public AndroidNewtEventFactory(android.content.Context context, android.os.Handler handler) {
+ gestureListener = new NewtGestureListener();
+ gestureDetector = new android.view.GestureDetector(context, gestureListener, handler, false /* ignoreMultitouch */);
+ gestureDetector.setIsLongpressEnabled(false); // favor scroll event!
+ final android.view.ViewConfiguration configuration = android.view.ViewConfiguration.get(context);
+ touchSlop = configuration.getScaledTouchSlop();
+ }
+
private int gestureScrollPointerDown = 0;
public com.jogamp.newt.event.MouseEvent[] createMouseEvents(boolean isOnTouchEvent,
diff --git a/src/newt/classes/jogamp/newt/driver/android/event/AndroidNewtEventTranslator.java b/src/newt/classes/jogamp/newt/driver/android/event/AndroidNewtEventTranslator.java
index 2d972f752..93735863e 100644
--- a/src/newt/classes/jogamp/newt/driver/android/event/AndroidNewtEventTranslator.java
+++ b/src/newt/classes/jogamp/newt/driver/android/event/AndroidNewtEventTranslator.java
@@ -38,7 +38,7 @@ public class AndroidNewtEventTranslator implements View.OnKeyListener, View.OnTo
@Override
public boolean onKey(View v, int keyCode, android.view.KeyEvent event) {
- final com.jogamp.newt.event.KeyEvent newtEvent = factory.createKeyEvent(keyCode, event, newtWindow);
+ final com.jogamp.newt.event.KeyEvent newtEvent = AndroidNewtEventFactory.createKeyEvent(event, newtWindow, false /* no system keys */);
if(null != newtEvent) {
newtWindow.enqueueEvent(false, newtEvent);
return true;
diff --git a/src/test/com/jogamp/opengl/test/android/MovieCubeActivity0.java b/src/test/com/jogamp/opengl/test/android/MovieCubeActivity0.java
index a30262ee3..0c65b6d53 100644
--- a/src/test/com/jogamp/opengl/test/android/MovieCubeActivity0.java
+++ b/src/test/com/jogamp/opengl/test/android/MovieCubeActivity0.java
@@ -54,7 +54,7 @@ public class MovieCubeActivity0 extends NewtBaseActivity {
MouseAdapter showKeyboardMouseListener = new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
- if(e.getPressure()>2f) {
+ if(e.getPressure()>0.6f) {
((com.jogamp.newt.Window) e.getSource()).setKeyboardVisible(true);
}
}
diff --git a/src/test/com/jogamp/opengl/test/android/NEWTGearsES2Activity.java b/src/test/com/jogamp/opengl/test/android/NEWTGearsES2Activity.java
index e782ac75f..931ffdbb2 100644
--- a/src/test/com/jogamp/opengl/test/android/NEWTGearsES2Activity.java
+++ b/src/test/com/jogamp/opengl/test/android/NEWTGearsES2Activity.java
@@ -66,14 +66,6 @@ public class NEWTGearsES2Activity extends NewtBaseActivity {
GLWindow glWindow = GLWindow.create(caps);
glWindow.setFullscreen(true);
setContentView(getWindow(), glWindow);
- glWindow.addMouseListener(new MouseAdapter() {
- @Override
- public void mousePressed(MouseEvent e) {
- if(e.getPressure()>2f) { // show Keyboard
- ((com.jogamp.newt.Window) e.getSource()).setKeyboardVisible(true);
- }
- }
- });
GearsES2 demo = new GearsES2(-1);
// demo.enableAndroidTrace(true);
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/GearsES2.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/GearsES2.java
index 74377a5f8..14c6a0cda 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/GearsES2.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/GearsES2.java
@@ -366,6 +366,10 @@ public class GearsES2 implements GLEventListener {
public void mousePressed(MouseEvent e) {
prevMouseX = e.getX();
prevMouseY = e.getY();
+ Object src = e.getSource();
+ if(e.getPressure()>0.6f && src instanceof Window) { // show Keyboard
+ ((Window) src).setKeyboardVisible(true);
+ }
}
public void mouseReleased(MouseEvent e) {