mirror of
https://github.com/moonlight-stream/moonlight-android.git
synced 2025-07-18 18:42:46 +00:00
Fix for broken keyboard d-pad and Shift+Space behavior on Samsung devices
This commit is contained in:
parent
381509b3a6
commit
989d6fc169
@ -70,7 +70,7 @@ import android.widget.Toast;
|
||||
|
||||
public class Game extends Activity implements SurfaceHolder.Callback,
|
||||
OnGenericMotionListener, OnTouchListener, NvConnectionListener, EvdevListener,
|
||||
OnSystemUiVisibilityChangeListener, GameGestures
|
||||
OnSystemUiVisibilityChangeListener, GameGestures, StreamView.InputCallbacks
|
||||
{
|
||||
private int lastMouseX = Integer.MIN_VALUE;
|
||||
private int lastMouseY = Integer.MIN_VALUE;
|
||||
@ -189,6 +189,7 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
||||
streamView = findViewById(R.id.surfaceView);
|
||||
streamView.setOnGenericMotionListener(this);
|
||||
streamView.setOnTouchListener(this);
|
||||
streamView.setInputCallbacks(this);
|
||||
|
||||
inputCaptureProvider = InputCaptureManager.getInputCaptureProvider(this, this);
|
||||
|
||||
@ -788,9 +789,14 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
||||
|
||||
@Override
|
||||
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
||||
return handleKeyDown(event) || super.onKeyDown(keyCode, event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handleKeyDown(KeyEvent event) {
|
||||
// Pass-through virtual navigation keys
|
||||
if ((event.getFlags() & KeyEvent.FLAG_VIRTUAL_HARD_KEY) != 0) {
|
||||
return super.onKeyDown(keyCode, event);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Handle a synthetic back button event that some Android OS versions
|
||||
@ -802,11 +808,7 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
||||
|
||||
boolean handled = false;
|
||||
|
||||
boolean detectedGamepad = event.getDevice() != null && ((event.getDevice().getSources() & InputDevice.SOURCE_JOYSTICK) == InputDevice.SOURCE_JOYSTICK ||
|
||||
(event.getDevice().getSources() & InputDevice.SOURCE_GAMEPAD) == InputDevice.SOURCE_GAMEPAD);
|
||||
if (detectedGamepad || (event.getDevice() == null ||
|
||||
event.getDevice().getKeyboardType() != InputDevice.KEYBOARD_TYPE_ALPHABETIC
|
||||
)) {
|
||||
if (ControllerHandler.isGameControllerDevice(event.getDevice())) {
|
||||
// Always try the controller handler first, unless it's an alphanumeric keyboard device.
|
||||
// Otherwise, controller handler will eat keyboard d-pad events.
|
||||
handled = controllerHandler.handleButtonDown(event);
|
||||
@ -816,17 +818,17 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
||||
// Try the keyboard handler
|
||||
short translated = KeyboardTranslator.translate(event.getKeyCode());
|
||||
if (translated == 0) {
|
||||
return super.onKeyDown(keyCode, event);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Let this method take duplicate key down events
|
||||
if (handleSpecialKeys(keyCode, true)) {
|
||||
if (handleSpecialKeys(event.getKeyCode(), true)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Pass through keyboard input if we're not grabbing
|
||||
if (!grabbedInput) {
|
||||
return super.onKeyDown(keyCode, event);
|
||||
return false;
|
||||
}
|
||||
|
||||
conn.sendKeyboardInput(translated, KeyboardPacket.KEY_DOWN, getModifierState(event));
|
||||
@ -837,9 +839,14 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
||||
|
||||
@Override
|
||||
public boolean onKeyUp(int keyCode, KeyEvent event) {
|
||||
return handleKeyUp(event) || super.onKeyUp(keyCode, event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handleKeyUp(KeyEvent event) {
|
||||
// Pass-through virtual navigation keys
|
||||
if ((event.getFlags() & KeyEvent.FLAG_VIRTUAL_HARD_KEY) != 0) {
|
||||
return super.onKeyUp(keyCode, event);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Handle a synthetic back button event that some Android OS versions
|
||||
@ -850,11 +857,7 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
||||
}
|
||||
|
||||
boolean handled = false;
|
||||
boolean detectedGamepad = event.getDevice() != null && ((event.getDevice().getSources() & InputDevice.SOURCE_JOYSTICK) == InputDevice.SOURCE_JOYSTICK ||
|
||||
(event.getDevice().getSources() & InputDevice.SOURCE_GAMEPAD) == InputDevice.SOURCE_GAMEPAD);
|
||||
if (detectedGamepad || (event.getDevice() == null ||
|
||||
event.getDevice().getKeyboardType() != InputDevice.KEYBOARD_TYPE_ALPHABETIC
|
||||
)) {
|
||||
if (ControllerHandler.isGameControllerDevice(event.getDevice())) {
|
||||
// Always try the controller handler first, unless it's an alphanumeric keyboard device.
|
||||
// Otherwise, controller handler will eat keyboard d-pad events.
|
||||
handled = controllerHandler.handleButtonUp(event);
|
||||
@ -864,16 +867,16 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
||||
// Try the keyboard handler
|
||||
short translated = KeyboardTranslator.translate(event.getKeyCode());
|
||||
if (translated == 0) {
|
||||
return super.onKeyUp(keyCode, event);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (handleSpecialKeys(keyCode, false)) {
|
||||
if (handleSpecialKeys(event.getKeyCode(), false)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Pass through keyboard input if we're not grabbing
|
||||
if (!grabbedInput) {
|
||||
return super.onKeyUp(keyCode, event);
|
||||
return false;
|
||||
}
|
||||
|
||||
conn.sendKeyboardInput(translated, KeyboardPacket.KEY_UP, getModifierState(event));
|
||||
|
@ -149,6 +149,30 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
|
||||
onInputDeviceAdded(deviceId);
|
||||
}
|
||||
|
||||
private static boolean hasJoystickAxes(InputDevice device) {
|
||||
return (device.getSources() & InputDevice.SOURCE_JOYSTICK) == InputDevice.SOURCE_JOYSTICK &&
|
||||
getMotionRangeForJoystickAxis(device, MotionEvent.AXIS_X) != null &&
|
||||
getMotionRangeForJoystickAxis(device, MotionEvent.AXIS_Y) != null;
|
||||
}
|
||||
|
||||
private static boolean hasGamepadButtons(InputDevice device) {
|
||||
return (device.getSources() & InputDevice.SOURCE_GAMEPAD) == InputDevice.SOURCE_GAMEPAD;
|
||||
}
|
||||
|
||||
public static boolean isGameControllerDevice(InputDevice device) {
|
||||
if (device == null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (hasJoystickAxes(device) || hasGamepadButtons(device)) {
|
||||
// Has real joystick axes or gamepad buttons
|
||||
return true;
|
||||
}
|
||||
|
||||
// Otherwise, we'll try anything that claims to be a non-alphabetic keyboard
|
||||
return device.getKeyboardType() != InputDevice.KEYBOARD_TYPE_ALPHABETIC;
|
||||
}
|
||||
|
||||
public static short getAttachedControllerMask(Context context) {
|
||||
int count = 0;
|
||||
short mask = 0;
|
||||
@ -161,9 +185,7 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((dev.getSources() & InputDevice.SOURCE_JOYSTICK) != 0 &&
|
||||
getMotionRangeForJoystickAxis(dev, MotionEvent.AXIS_X) != null &&
|
||||
getMotionRangeForJoystickAxis(dev, MotionEvent.AXIS_Y) != null) {
|
||||
if (hasJoystickAxes(dev)) {
|
||||
LimeLog.info("Counting InputDevice: "+dev.getName());
|
||||
mask |= 1 << count++;
|
||||
}
|
||||
|
@ -3,15 +3,21 @@ package com.limelight.ui;
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.SurfaceView;
|
||||
|
||||
public class StreamView extends SurfaceView {
|
||||
private double desiredAspectRatio;
|
||||
private InputCallbacks inputCallbacks;
|
||||
|
||||
public void setDesiredAspectRatio(double aspectRatio) {
|
||||
this.desiredAspectRatio = aspectRatio;
|
||||
}
|
||||
|
||||
public void setInputCallbacks(InputCallbacks callbacks) {
|
||||
this.inputCallbacks = callbacks;
|
||||
}
|
||||
|
||||
public StreamView(Context context) {
|
||||
super(context);
|
||||
}
|
||||
@ -52,4 +58,30 @@ public class StreamView extends SurfaceView {
|
||||
|
||||
setMeasuredDimension(measuredWidth, measuredHeight);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onKeyPreIme(int keyCode, KeyEvent event) {
|
||||
// This callbacks allows us to override dumb IME behavior like when
|
||||
// Samsung's default keyboard consumes Shift+Space. We'll process
|
||||
// the input event directly if any modifier keys are down.
|
||||
if (inputCallbacks != null && event.getModifiers() != 0) {
|
||||
if (event.getAction() == KeyEvent.ACTION_DOWN) {
|
||||
if (inputCallbacks.handleKeyDown(event)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (event.getAction() == KeyEvent.ACTION_UP) {
|
||||
if (inputCallbacks.handleKeyUp(event)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return super.onKeyPreIme(keyCode, event);
|
||||
}
|
||||
|
||||
public interface InputCallbacks {
|
||||
boolean handleKeyUp(KeyEvent event);
|
||||
boolean handleKeyDown(KeyEvent event);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user