From ceb9bd3342865c0f2c490eee9b56efc6f40437e1 Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Sun, 28 Sep 2014 12:27:21 -0700 Subject: [PATCH 1/9] Change bitstream restrictions to match default values --- .../limelight/binding/video/MediaCodecDecoderRenderer.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/com/limelight/binding/video/MediaCodecDecoderRenderer.java b/src/com/limelight/binding/video/MediaCodecDecoderRenderer.java index e8a5007c..cb4002e6 100644 --- a/src/com/limelight/binding/video/MediaCodecDecoderRenderer.java +++ b/src/com/limelight/binding/video/MediaCodecDecoderRenderer.java @@ -436,9 +436,9 @@ public class MediaCodecDecoderRenderer implements VideoDecoderRenderer { LimeLog.info("Adding bitstream restrictions"); sps.vuiParams.bitstreamRestriction = new VUIParameters.BitstreamRestriction(); - sps.vuiParams.bitstreamRestriction.motion_vectors_over_pic_boundaries_flag = false; - sps.vuiParams.bitstreamRestriction.max_bytes_per_pic_denom = 0; - sps.vuiParams.bitstreamRestriction.max_bits_per_mb_denom = 0; + sps.vuiParams.bitstreamRestriction.motion_vectors_over_pic_boundaries_flag = true; + sps.vuiParams.bitstreamRestriction.max_bytes_per_pic_denom = 2; + sps.vuiParams.bitstreamRestriction.max_bits_per_mb_denom = 1; sps.vuiParams.bitstreamRestriction.log2_max_mv_length_horizontal = 16; sps.vuiParams.bitstreamRestriction.log2_max_mv_length_vertical = 16; sps.vuiParams.bitstreamRestriction.num_reorder_frames = 0; From cafdc21bf2f00044ab5963e23a1e64e7271224b5 Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Sun, 28 Sep 2014 14:17:31 -0700 Subject: [PATCH 2/9] Prefer Samsung's OMX.SEC.AVC.Decoder if it's in the list of decoders --- .../video/MediaCodecDecoderRenderer.java | 42 ++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/src/com/limelight/binding/video/MediaCodecDecoderRenderer.java b/src/com/limelight/binding/video/MediaCodecDecoderRenderer.java index cb4002e6..2a96821c 100644 --- a/src/com/limelight/binding/video/MediaCodecDecoderRenderer.java +++ b/src/com/limelight/binding/video/MediaCodecDecoderRenderer.java @@ -44,11 +44,20 @@ public class MediaCodecDecoderRenderer implements VideoDecoderRenderer { private int numPpsIn; private int numIframeIn; + public static final List preferredDecoders; + public static final List blacklistedDecoderPrefixes; public static final List spsFixupBitstreamFixupDecoderPrefixes; public static final List spsFixupNumRefFixupDecoderPrefixes; public static final List whitelistedAdaptiveResolutionPrefixes; + static { + preferredDecoders = new LinkedList(); + + // This is the most reliable of Samsung's decoders + preferredDecoders.add("OMX.SEC.AVC.Decoder"); + } + static { blacklistedDecoderPrefixes = new LinkedList(); @@ -158,6 +167,31 @@ public class MediaCodecDecoderRenderer implements VideoDecoderRenderer { return str; } + private static MediaCodecInfo findPreferredDecoder() { + // This is a different algorithm than the other findXXXDecoder functions, + // because we want to evaluate the decoders in our list's order + // rather than MediaCodecList's order + + for (String preferredDecoder : preferredDecoders) { + for (int i = 0; i < MediaCodecList.getCodecCount(); i++) { + MediaCodecInfo codecInfo = MediaCodecList.getCodecInfoAt(i); + + // Skip encoders + if (codecInfo.isEncoder()) { + continue; + } + + // Check for preferred decoders + if (preferredDecoder.equalsIgnoreCase(codecInfo.getName())) { + LimeLog.info("Preferred decoder choice is "+codecInfo.getName()); + return codecInfo; + } + } + } + + return null; + } + private static MediaCodecInfo findFirstDecoder() { for (int i = 0; i < MediaCodecList.getCodecCount(); i++) { MediaCodecInfo codecInfo = MediaCodecList.getCodecInfoAt(i); @@ -186,7 +220,13 @@ public class MediaCodecDecoderRenderer implements VideoDecoderRenderer { } public static MediaCodecInfo findProbableSafeDecoder() { - // First look for decoders we know are safe + // First look for a preferred decoder by name + MediaCodecInfo info = findPreferredDecoder(); + if (info != null) { + return info; + } + + // Now look for decoders we know are safe try { // If this function completes, it will determine if the decoder is safe return findKnownSafeDecoder(); From d3438f49380639a787766cdcace8ea57b37bc5cd Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Sun, 28 Sep 2014 16:27:11 -0700 Subject: [PATCH 3/9] Update common jar --- libs/limelight-common.jar | Bin 418126 -> 418136 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/libs/limelight-common.jar b/libs/limelight-common.jar index 78eb0bd489e45d4b0885c2a9b5f9f06f257aaa52..4cfafd60d8b25ffab78f8455023f9b7df4d4972f 100644 GIT binary patch delta 7468 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 Xzmve`$M|5nb|RZBo2CmJ0|Ns9XOR?W delta 7661 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 Date: Sun, 28 Sep 2014 16:30:37 -0700 Subject: [PATCH 4/9] Merge version update --- AndroidManifest.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 7383b6ee..3b5530ef 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -1,8 +1,8 @@  + android:versionCode="35" + android:versionName="2.5.5.1" > Date: Wed, 1 Oct 2014 20:24:40 -0700 Subject: [PATCH 5/9] Add axis scaling support --- libs/limelight-common.jar | Bin 418136 -> 418537 bytes .../binding/input/ControllerHandler.java | 25 ++++++++++++++++-- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/libs/limelight-common.jar b/libs/limelight-common.jar index 4cfafd60d8b25ffab78f8455023f9b7df4d4972f..0348acc13d669b6fa12132b3e7c66957bb28fe05 100644 GIT binary patch delta 1949 zcmca{Nb==TN!|c&W)=|!4h{~6yNetfdAIU1Dugm0p658-Ae7OyKJ0a{aJY!Qw-Zz0 z!4Dly2f}_|5Ll(Tb*t{eEFqzeH7aS--494j-_SC3LdK?mm)Q??o09g zA+1Jp{r)rjpZrgF>;CG^oZ7ADcFeq4UH5$6cgyd2^ZtH59`AC+-QIGg--5$8A0;WQ z*Uzf7HP2_^I-RC$=&W8w+vGP)KmUcRp1UWS*(h`P z;)Mhg)quMt5emD7y1bd*dbKGj2dXY!GC8oZWru_BhhVcSO@`~9O*fG~^tvHWLwK^2 z^MnZp3xzEb&oSOQe<4M5Zi+^%mL(Z#VqF@XUtAOpPh23%sm(2Ri(Fl>V|&5ZdEfW(`ntDC)(!4&e+mq60$R)^mNmP>jo2A z-S1lHO*nhqxbJ7DNcvVc7Hf?lTT2O1;ggXI+gz>O-g9q>zQld&#id6*VL=gZn6`Sk z9Ds{mf~YJo24eiy*j~WIQx#Ps#?3g9{;!c6MDNGD%Eup&giW;ou#l| ztf=wwDntECN}>S;rORS8nflTfbA{HKER3HsTl@23+vRD!O0%-{U+-i(eL_If{qqdF z#TE;vZ&|WylK!gAOr<|m-Ys4r&iqi+nOpzt+03O1+V4|;UGdb`xX;bhd1+0U&`aZA zGRKzeSd^f&cyaT`3oGg!-d?JAZPxoWDQs>D>(x8QCVPaxoaOM6SUqowrFSf3+iPw?Tsjf`_x%Uy#on;K+VmjrL9N&y zt`Dol&OEYDIJlm1f8N1-hW(ib*&F#IH}LN`-t_mtUa>Qu>Q6WEGs|y$!0_RAbb-k=f3LE zRFhecJ->ez;+m7>y5_Nn_Tt{)H51DGHU?cQ?h?IxP&3R={Z>=<=`*hxm&^>A|2=)x zcH2*OD(QFEr)-zsTy5^bUzPt`>>cag*yqjnrfHwAS5&XR=h%POy8i#gX(h)JGGy|W z1susd^T%>Z$k8?DlvH^?Fa2Ed$7Y9}R*|e*tjXn$I$?(!^|c|AeUQ6%A+P`O6fl?M}eCw130#oc=%ne{KB8vB8#IXmfbdSEU&mz zt+ny0Tjr#97t8@#!z3*|eAv6X3!E z(`{qeY?-oCAR_$9jPlc0xUvaMKN7KKi!=KD3G+j52&4TGh6-1;Vj?IzDxEao2oqng0QDpjmkX@|tY*I`sdqHwB zOtzD!*T=J&GBHk>zAc{3jOp`~>F?s%OqkwGovxC==D@Tpe|lO1n=RAo-swvd*c_NY zI` Ay8r+H delta 1526 zcmaEPRPx3lN!|c&W)=|!4h{|m!)BXC-mSch3ZawN8VF3z@06ZC!Ie>9`pOtKp8Ba% z-v-@w6KOl2lq~Je!d}4Cx@Adba57ikzFW&CH2h&@J6e{LSdjVpl$!)=;!>w`KL4IN zRdN2kY_iOFuAkll@vC3%Zq=D0Vij!o*!KL*#l_$D?2h{P>vzAoOUZ1%LncQuHm1rh z_jw#)-urFgFLW)XX8~Yn{&pEs9am3s`E4TVPEUSC4V%x>M z*Jfe7XH{qCPkP?6&O5KKI0k|wd|tdoO<^jrp}*IWk$(wUn@sE zF&E+u?ugbFYSlcF;bUl3wXyonmE6$mSyqb+k7i}2`EKStx6XLWBefp2RWD0K&)4XB zF?xA#@sbSj5P6nulkc}kRqE-rT`roxnxa`bpNB_83*CKr-fr59y!%?7CF}ETC%&-j zRhn6x;V^f~r~Q1tja2H(*T^2ecKR0gMz6qG-y#W3Nq$q%&cy@jAO?)KX`5TPvFnQ{^tkGYyKGiSXSR}&shKJarA@pHFFrw|F+fON#yT-EPK8Fy6pR%k82It7QUYTMbxO4H>>eyv9Z`M;~@Sci?VEmW{1=- zW?%O>eXCqw?%|DpR%`qb*uQ;);f~CWzRD3dQvb9n{= zcg>zBUSGrP-=c3PIs4b#Cr^C(H=VpG_jL00>Mav{*sHh9?BW0J;d#v2R!i;iL%FH< z*Z&pR8Xj29E3KcLeEG&29y0~*z+wS){jBg`Qw_pgCwn^?sp;t5ny_I<4r5~B!=^)z zF7a}AcZ&;&P1o<)9(t>+y0VwY=J>lq+N$^U9Wva z@5aAffA)3V^uCqK|CFP?oOzoNXb`Ai_PaY=MDmbj%IE@9nG@+bTsSlm&}IEHrr3S zvP~D8p5Vd8!iCU1Juil>km*I_^oKEQ2~12e(-%gu$xpYBVPl=19?NFKbRiBRGCzim zYx=oZHe04!Nz)7C*bJxJ#jzPOy~qG@l9>AQK(xVh)_67prvD`%j?(mVWsH2&U;3~K zOfQdTlVakj010bP-xtqj!Q@^!y)lwaayoA{qxf`<1U4oGy^aX3A7BX}WtNn;BEmJfCWOHB=&71x`kK4&(i>9dpAv{W8AvoYwUXO?89=j9ir26(fwF)%PN1TX|JNXjxW IXu5#709EIuqW}N^ diff --git a/src/com/limelight/binding/input/ControllerHandler.java b/src/com/limelight/binding/input/ControllerHandler.java index 26d47a18..471ff411 100644 --- a/src/com/limelight/binding/input/ControllerHandler.java +++ b/src/com/limelight/binding/input/ControllerHandler.java @@ -47,6 +47,9 @@ public class ControllerHandler { public ControllerHandler(NvConnection conn) { this.conn = conn; + + // We want limelight-common to scale the axis values to match Xinput values + ControllerPacket.enableAxisScaling = true; } private ControllerMapping createMappingForDevice(InputDevice dev) { @@ -135,6 +138,15 @@ public class ControllerHandler { InputDevice.MotionRange lsYRange = dev.getMotionRange(mapping.leftStickYAxis); if (lsXRange != null && lsYRange != null) { mapping.leftStickDeadzoneRadius = Math.max(lsXRange.getFlat(), lsYRange.getFlat()); + + // If there isn't a (reasonable) deadzone at all, use 20% + if (mapping.leftStickDeadzoneRadius < 0.02f) { + mapping.leftStickDeadzoneRadius = 0.20f; + } + // Check that the deadzone is 10% at minimum + else if (mapping.leftStickDeadzoneRadius < 0.10f) { + mapping.leftStickDeadzoneRadius = 0.10f; + } } } @@ -143,6 +155,15 @@ public class ControllerHandler { InputDevice.MotionRange rsYRange = dev.getMotionRange(mapping.rightStickYAxis); if (rsXRange != null && rsYRange != null) { mapping.rightStickDeadzoneRadius = Math.max(rsXRange.getFlat(), rsYRange.getFlat()); + + // If there isn't a (reasonable) deadzone at all, use 20% + if (mapping.rightStickDeadzoneRadius < 0.02f) { + mapping.rightStickDeadzoneRadius = 0.20f; + } + // Check that the deadzone is 10% at minimum + else if (mapping.rightStickDeadzoneRadius < 0.10f) { + mapping.rightStickDeadzoneRadius = 0.10f; + } } } @@ -242,7 +263,7 @@ public class ControllerHandler { // Scale the input based on the distance from the deadzone inputVector.getNormalized(normalizedInputVector); normalizedInputVector.scalarMultiply((inputVector.getMagnitude() - deadzoneRadius) / (1.0f - deadzoneRadius)); - + // Bound the X value to -1.0 to 1.0 if (normalizedInputVector.getX() > 1.0f) { normalizedInputVector.setX(1.0f); @@ -284,7 +305,7 @@ public class ControllerHandler { event.getAxisValue(mapping.rightStickYAxis), mapping.rightStickDeadzoneRadius); rightStickX = (short)(rightStickVector.getX() * 0x7FFE); - rightStickY = (short)(-rightStickVector.getY() * 0x7FFE); + rightStickY = (short)(-rightStickVector.getY() * 0x7FFE); } // Handle controllers with analog triggers From a726ba8ea79a34680b6f467457310df763792d4f Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Fri, 3 Oct 2014 22:18:36 -0700 Subject: [PATCH 6/9] Add an ungrab key combo (Ctrl+Shift+Z). Ignore repeat key down events. Fix some mishandling of input events that could cause crashes. --- src/com/limelight/Game.java | 214 ++++++++++++++---- .../binding/input/evdev/EvdevWatcher.java | 40 +++- 2 files changed, 210 insertions(+), 44 deletions(-) diff --git a/src/com/limelight/Game.java b/src/com/limelight/Game.java index 4ba30d7a..15e82d51 100644 --- a/src/com/limelight/Game.java +++ b/src/com/limelight/Game.java @@ -69,6 +69,11 @@ public class Game extends Activity implements SurfaceHolder.Callback, private boolean toastsDisabled; private EvdevWatcher evdevWatcher; + private int modifierFlags = 0; + private boolean grabbedInput = true; + private boolean grabComboDown = false; + private static final int MODIFIER_CTRL = 0x1; + private static final int MODIFIER_SHIFT = 0x2; private ConfigurableDecoderRenderer decoderRenderer; @@ -315,6 +320,80 @@ public class Game extends Activity implements SurfaceHolder.Callback, wifiLock.release(); } + private Runnable toggleGrab = new Runnable() { + @Override + public void run() { + + if (evdevWatcher != null) { + if (grabbedInput) { + evdevWatcher.ungrabAll(); + } + else { + evdevWatcher.regrabAll(); + } + } + + grabbedInput = !grabbedInput; + } + }; + + // Returns true if the key stroke was consumed + private boolean handleMagicKeyCombos(short translatedKey, boolean down) { + int modifierMask = 0; + + // Mask off the high byte + translatedKey &= 0xff; + + if (translatedKey == KeyboardTranslator.VK_CONTROL) { + modifierMask = MODIFIER_CTRL; + } + else if (translatedKey == KeyboardTranslator.VK_SHIFT) { + modifierMask = MODIFIER_SHIFT; + } + + if (down) { + this.modifierFlags |= modifierMask; + } + else { + this.modifierFlags &= ~modifierMask; + } + + // Check if Ctrl+Shift+Z is pressed + if (translatedKey == KeyboardTranslator.VK_Z && + (modifierFlags & (MODIFIER_CTRL|MODIFIER_SHIFT)) == (MODIFIER_CTRL|MODIFIER_SHIFT)) + { + if (down) { + // Now that we've pressed the magic combo + // we'll wait for one of the keys to come up + grabComboDown = true; + } + else { + // Toggle the grab if Z comes up + Handler h = getWindow().getDecorView().getHandler(); + if (h != null) { + h.postDelayed(toggleGrab, 250); + } + + grabComboDown = false; + } + + return true; + } + // Toggle the grab if control or shift comes up + else if (grabComboDown) { + Handler h = getWindow().getDecorView().getHandler(); + if (h != null) { + h.postDelayed(toggleGrab, 250); + } + + grabComboDown = false; + return true; + } + + // Not a special combo + return false; + } + private static byte getModifierState(KeyEvent event) { byte modifier = 0; if (event.isShiftPressed()) { @@ -350,6 +429,21 @@ public class Game extends Activity implements SurfaceHolder.Callback, return super.onKeyDown(keyCode, event); } + // Let this method take duplicate key down events + if (handleMagicKeyCombos(translated, true)) { + return true; + } + + // Eat repeat down events + if (event.getRepeatCount() > 0) { + return true; + } + + // Pass through keyboard input if we're not grabbing + if (!grabbedInput) { + return super.onKeyDown(keyCode, event); + } + keybTranslator.sendKeyDown(translated, getModifierState(event)); } @@ -388,6 +482,15 @@ public class Game extends Activity implements SurfaceHolder.Callback, return super.onKeyUp(keyCode, event); } + if (handleMagicKeyCombos(translated, false)) { + return true; + } + + // Pass through keyboard input if we're not grabbing + if (!grabbedInput) { + return super.onKeyUp(keyCode, event); + } + keybTranslator.sendKeyUp(translated, getModifierState(event)); } @@ -404,25 +507,35 @@ public class Game extends Activity implements SurfaceHolder.Callback, return null; } } - - @Override - public boolean onTouchEvent(MotionEvent event) { - if ((event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0) + + // Returns true if the event was consumed + private boolean handleMotionEvent(MotionEvent event) { + // Pass through keyboard input if we're not grabbing + if (!grabbedInput) { + return false; + } + + if ((event.getSource() & InputDevice.SOURCE_CLASS_JOYSTICK) != 0) { + if (controllerHandler.handleMotionEvent(event)) { + return true; + } + } + else if ((event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0) { // This case is for touch-based input devices if (event.getSource() == InputDevice.SOURCE_TOUCHSCREEN || - event.getSource() == InputDevice.SOURCE_STYLUS) + event.getSource() == InputDevice.SOURCE_STYLUS) { int actionIndex = event.getActionIndex(); - + int eventX = (int)event.getX(actionIndex); int eventY = (int)event.getY(actionIndex); - + TouchContext context = getTouchContext(actionIndex); if (context == null) { - return super.onTouchEvent(event); + return false; } - + switch (event.getActionMasked()) { case MotionEvent.ACTION_POINTER_DOWN: @@ -444,15 +557,24 @@ public class Game extends Activity implements SurfaceHolder.Callback, touchContextMap[i].touchMoveEvent(eventX, eventY); } break; + case MotionEvent.ACTION_HOVER_MOVE: + // Send a mouse move update (if neccessary) + updateMousePosition((int)event.getX(), (int)event.getY()); + break; + case MotionEvent.ACTION_SCROLL: + // Send the vertical scroll packet + byte vScrollClicks = (byte) event.getAxisValue(MotionEvent.AXIS_VSCROLL); + conn.sendMouseScroll(vScrollClicks); + break; default: - return super.onTouchEvent(event); + return false; } } // This case is for mice else if (event.getSource() == InputDevice.SOURCE_MOUSE) { int changedButtons = event.getButtonState() ^ lastButtonState; - + if ((changedButtons & MotionEvent.BUTTON_PRIMARY) != 0) { if ((event.getButtonState() & MotionEvent.BUTTON_PRIMARY) != 0) { conn.sendMouseButtonDown(MouseButtonPacket.BUTTON_LEFT); @@ -461,7 +583,7 @@ public class Game extends Activity implements SurfaceHolder.Callback, conn.sendMouseButtonUp(MouseButtonPacket.BUTTON_LEFT); } } - + if ((changedButtons & MotionEvent.BUTTON_SECONDARY) != 0) { if ((event.getButtonState() & MotionEvent.BUTTON_SECONDARY) != 0) { conn.sendMouseButtonDown(MouseButtonPacket.BUTTON_RIGHT); @@ -470,7 +592,7 @@ public class Game extends Activity implements SurfaceHolder.Callback, conn.sendMouseButtonUp(MouseButtonPacket.BUTTON_RIGHT); } } - + if ((changedButtons & MotionEvent.BUTTON_TERTIARY) != 0) { if ((event.getButtonState() & MotionEvent.BUTTON_TERTIARY) != 0) { conn.sendMouseButtonDown(MouseButtonPacket.BUTTON_MIDDLE); @@ -479,47 +601,41 @@ public class Game extends Activity implements SurfaceHolder.Callback, conn.sendMouseButtonUp(MouseButtonPacket.BUTTON_MIDDLE); } } - + updateMousePosition((int)event.getX(), (int)event.getY()); - + lastButtonState = event.getButtonState(); } else { - return super.onTouchEvent(event); + // Unknown source + return false; } + // Handled a known source return true; } + + // Unknown class + return false; + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + if (!handleMotionEvent(event)) { + return super.onTouchEvent(event); + } - return super.onTouchEvent(event); + return true; } @Override public boolean onGenericMotionEvent(MotionEvent event) { - if ((event.getSource() & InputDevice.SOURCE_CLASS_JOYSTICK) != 0) { - if (controllerHandler.handleMotionEvent(event)) { - return true; - } - } - else if ((event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0) - { - switch (event.getActionMasked()) - { - case MotionEvent.ACTION_HOVER_MOVE: - // Send a mouse move update (if neccessary) - updateMousePosition((int)event.getX(), (int)event.getY()); - break; - case MotionEvent.ACTION_SCROLL: - // Send the vertical scroll packet - byte vScrollClicks = (byte) event.getAxisValue(MotionEvent.AXIS_VSCROLL); - conn.sendMouseScroll(vScrollClicks); - break; - } - return true; + if (!handleMotionEvent(event)) { + return super.onGenericMotionEvent(event); } - return super.onGenericMotionEvent(event); + return true; } private void updateMousePosition(int eventX, int eventY) { @@ -547,15 +663,13 @@ public class Game extends Activity implements SurfaceHolder.Callback, @Override public boolean onGenericMotion(View v, MotionEvent event) { - // Send it to the activity's motion event handler - return onGenericMotionEvent(event); + return handleMotionEvent(event); } @SuppressLint("ClickableViewAccessibility") @Override public boolean onTouch(View v, MotionEvent event) { - // Send it to the activity's touch event handler - return onTouchEvent(event); + return handleMotionEvent(event); } @Override @@ -706,4 +820,20 @@ public class Game extends Activity implements SurfaceHolder.Callback, public void mouseScroll(byte amount) { conn.sendMouseScroll(amount); } + + public void keyboardEvent(boolean buttonDown, short keyCode) { + short keyMap = keybTranslator.translate(keyCode); + if (keyMap != 0) { + if (handleMagicKeyCombos(keyMap, buttonDown)) { + return; + } + + if (buttonDown) { + keybTranslator.sendKeyDown(keyMap, (byte) 0); + } + else { + keybTranslator.sendKeyUp(keyMap, (byte) 0); + } + } + } } diff --git a/src/com/limelight/binding/input/evdev/EvdevWatcher.java b/src/com/limelight/binding/input/evdev/EvdevWatcher.java index 806901ec..67a5050c 100644 --- a/src/com/limelight/binding/input/evdev/EvdevWatcher.java +++ b/src/com/limelight/binding/input/evdev/EvdevWatcher.java @@ -2,6 +2,7 @@ package com.limelight.binding.input.evdev; import java.io.File; import java.util.HashMap; +import java.util.Map; import com.limelight.LimeLog; @@ -14,6 +15,7 @@ public class EvdevWatcher { private HashMap handlers = new HashMap(); private boolean shutdown = false; private boolean init = false; + private boolean ungrabbed = false; private EvdevListener listener; private Thread startThread; @@ -42,7 +44,11 @@ public class EvdevWatcher { } EvdevHandler handler = new EvdevHandler(PATH + "/" + fileName, listener); - handler.start(); + + // If we're ungrabbed now, don't start the handler + if (!ungrabbed) { + handler.start(); + } handlers.put(fileName, handler); } @@ -78,6 +84,31 @@ public class EvdevWatcher { return files; } + public void ungrabAll() { + synchronized (handlers) { + // Note that we're ungrabbed for now + ungrabbed = true; + + // Stop all handlers + for (EvdevHandler handler : handlers.values()) { + handler.stop(); + } + } + } + + public void regrabAll() { + synchronized (handlers) { + // We're regrabbing everything now + ungrabbed = false; + + for (Map.Entry entry : handlers.entrySet()) { + // We need to recreate each entry since we can't reuse a stopped one + entry.setValue(new EvdevHandler(PATH + "/" + entry.getKey(), listener)); + entry.getValue().start(); + } + } + } + public void start() { startThread = new Thread() { @Override @@ -119,10 +150,15 @@ public class EvdevWatcher { // Stop the observer observer.stopWatching(); - synchronized (handlers) { + synchronized (handlers) { // Stop creating new handlers shutdown = true; + // If we've already ungrabbed, there's nothing else to do + if (ungrabbed) { + return; + } + // Stop all handlers for (EvdevHandler handler : handlers.values()) { handler.stop(); From 67e22fca6bba2ea9381bf31508faddbd31646718 Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Fri, 3 Oct 2014 22:49:36 -0700 Subject: [PATCH 7/9] Improve re-hiding of the system UI by using a proper system UI visibility listener --- src/com/limelight/Game.java | 50 +++++++++++++++++++++++++------------ 1 file changed, 34 insertions(+), 16 deletions(-) diff --git a/src/com/limelight/Game.java b/src/com/limelight/Game.java index 15e82d51..e0e42345 100644 --- a/src/com/limelight/Game.java +++ b/src/com/limelight/Game.java @@ -35,6 +35,7 @@ import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.View; import android.view.View.OnGenericMotionListener; +import android.view.View.OnSystemUiVisibilityChangeListener; import android.view.View.OnTouchListener; import android.view.ViewGroup; import android.view.Window; @@ -43,7 +44,8 @@ import android.widget.Toast; public class Game extends Activity implements SurfaceHolder.Callback, - OnGenericMotionListener, OnTouchListener, NvConnectionListener, EvdevListener + OnGenericMotionListener, OnTouchListener, NvConnectionListener, EvdevListener, + OnSystemUiVisibilityChangeListener { private int lastMouseX = Integer.MIN_VALUE; private int lastMouseY = Integer.MIN_VALUE; @@ -138,6 +140,9 @@ public class Game extends Activity implements SurfaceHolder.Callback, getWindow().addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN); } + // Listen for UI visibility events + getWindow().getDecorView().setOnSystemUiVisibilityChangeListener(this); + // Change volume button behavior setVolumeControlStream(AudioManager.STREAM_MUSIC); @@ -275,11 +280,11 @@ public class Game extends Activity implements SurfaceHolder.Callback, } }; - private void hideSystemUi() { + private void hideSystemUi(int delay) { Handler h = getWindow().getDecorView().getHandler(); if (h != null) { h.removeCallbacks(hideSystemUi); - h.postDelayed(hideSystemUi, 1000); + h.postDelayed(hideSystemUi, delay); } } @@ -453,16 +458,6 @@ public class Game extends Activity implements SurfaceHolder.Callback, @Override public boolean onKeyUp(int keyCode, KeyEvent event) { - // Pressing a volume button drops the immersive flag so the UI shows up again and doesn't - // go away. I'm not sure if that's a bug or a feature, but we're working around it here - if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN || keyCode == KeyEvent.KEYCODE_VOLUME_UP) { - Handler h = getWindow().getDecorView().getHandler(); - if (h != null) { - h.removeCallbacks(hideSystemUi); - h.postDelayed(hideSystemUi, 2000); - } - } - InputDevice dev = event.getDevice(); if (dev == null) { return super.onKeyUp(keyCode, event); @@ -705,8 +700,8 @@ public class Game extends Activity implements SurfaceHolder.Callback, if (!displayedFailureDialog) { displayedFailureDialog = true; - Dialog.displayDialog(this, "Connection Error", "Starting "+stage.getName()+" failed", true); stopConnection(); + Dialog.displayDialog(this, "Connection Error", "Starting "+stage.getName()+" failed", true); } } @@ -716,8 +711,8 @@ public class Game extends Activity implements SurfaceHolder.Callback, displayedFailureDialog = true; e.printStackTrace(); - Dialog.displayDialog(this, "Connection Terminated", "The connection failed unexpectedly", true); stopConnection(); + Dialog.displayDialog(this, "Connection Terminated", "The connection failed unexpectedly", true); } } @@ -731,7 +726,7 @@ public class Game extends Activity implements SurfaceHolder.Callback, connecting = false; connected = true; - hideSystemUi(); + hideSystemUi(1000); } @Override @@ -836,4 +831,27 @@ public class Game extends Activity implements SurfaceHolder.Callback, } } } + + @Override + public void onSystemUiVisibilityChange(int visibility) { + // Don't do anything if we're not connected + if (!connected) { + return; + } + + // This flag is set for all devices + if ((visibility & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0) { + hideSystemUi(2000); + } + // This flag is only set on 4.4+ + else if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT && + (visibility & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0) { + hideSystemUi(2000); + } + // This flag is only set before 4.4+ + else if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.KITKAT && + (visibility & View.SYSTEM_UI_FLAG_LOW_PROFILE) == 0) { + hideSystemUi(2000); + } + } } From 645ea683ee4a51f61819488ec5a90dbe136e9f2b Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Fri, 3 Oct 2014 22:52:48 -0700 Subject: [PATCH 8/9] Increase the minimum deadzone to 12% because I'm paranoid --- .../limelight/binding/input/ControllerHandler.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/com/limelight/binding/input/ControllerHandler.java b/src/com/limelight/binding/input/ControllerHandler.java index 471ff411..a84ed130 100644 --- a/src/com/limelight/binding/input/ControllerHandler.java +++ b/src/com/limelight/binding/input/ControllerHandler.java @@ -143,9 +143,9 @@ public class ControllerHandler { if (mapping.leftStickDeadzoneRadius < 0.02f) { mapping.leftStickDeadzoneRadius = 0.20f; } - // Check that the deadzone is 10% at minimum - else if (mapping.leftStickDeadzoneRadius < 0.10f) { - mapping.leftStickDeadzoneRadius = 0.10f; + // Check that the deadzone is 12% at minimum + else if (mapping.leftStickDeadzoneRadius < 0.12f) { + mapping.leftStickDeadzoneRadius = 0.12f; } } } @@ -160,9 +160,9 @@ public class ControllerHandler { if (mapping.rightStickDeadzoneRadius < 0.02f) { mapping.rightStickDeadzoneRadius = 0.20f; } - // Check that the deadzone is 10% at minimum - else if (mapping.rightStickDeadzoneRadius < 0.10f) { - mapping.rightStickDeadzoneRadius = 0.10f; + // Check that the deadzone is 12% at minimum + else if (mapping.rightStickDeadzoneRadius < 0.12f) { + mapping.rightStickDeadzoneRadius = 0.12f; } } } From f56b7ff79ea2f252d9e83eec598e29abe23db177 Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Fri, 3 Oct 2014 22:56:30 -0700 Subject: [PATCH 9/9] Bump to 2.5.6 --- AndroidManifest.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 3b5530ef..d7056e70 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -2,7 +2,7 @@ + android:versionName="2.5.6" >