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,
|
public class Game extends Activity implements SurfaceHolder.Callback,
|
||||||
OnGenericMotionListener, OnTouchListener, NvConnectionListener, EvdevListener,
|
OnGenericMotionListener, OnTouchListener, NvConnectionListener, EvdevListener,
|
||||||
OnSystemUiVisibilityChangeListener, GameGestures
|
OnSystemUiVisibilityChangeListener, GameGestures, StreamView.InputCallbacks
|
||||||
{
|
{
|
||||||
private int lastMouseX = Integer.MIN_VALUE;
|
private int lastMouseX = Integer.MIN_VALUE;
|
||||||
private int lastMouseY = 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 = findViewById(R.id.surfaceView);
|
||||||
streamView.setOnGenericMotionListener(this);
|
streamView.setOnGenericMotionListener(this);
|
||||||
streamView.setOnTouchListener(this);
|
streamView.setOnTouchListener(this);
|
||||||
|
streamView.setInputCallbacks(this);
|
||||||
|
|
||||||
inputCaptureProvider = InputCaptureManager.getInputCaptureProvider(this, this);
|
inputCaptureProvider = InputCaptureManager.getInputCaptureProvider(this, this);
|
||||||
|
|
||||||
@ -788,9 +789,14 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
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
|
// Pass-through virtual navigation keys
|
||||||
if ((event.getFlags() & KeyEvent.FLAG_VIRTUAL_HARD_KEY) != 0) {
|
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
|
// 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 handled = false;
|
||||||
|
|
||||||
boolean detectedGamepad = event.getDevice() != null && ((event.getDevice().getSources() & InputDevice.SOURCE_JOYSTICK) == InputDevice.SOURCE_JOYSTICK ||
|
if (ControllerHandler.isGameControllerDevice(event.getDevice())) {
|
||||||
(event.getDevice().getSources() & InputDevice.SOURCE_GAMEPAD) == InputDevice.SOURCE_GAMEPAD);
|
|
||||||
if (detectedGamepad || (event.getDevice() == null ||
|
|
||||||
event.getDevice().getKeyboardType() != InputDevice.KEYBOARD_TYPE_ALPHABETIC
|
|
||||||
)) {
|
|
||||||
// Always try the controller handler first, unless it's an alphanumeric keyboard device.
|
// Always try the controller handler first, unless it's an alphanumeric keyboard device.
|
||||||
// Otherwise, controller handler will eat keyboard d-pad events.
|
// Otherwise, controller handler will eat keyboard d-pad events.
|
||||||
handled = controllerHandler.handleButtonDown(event);
|
handled = controllerHandler.handleButtonDown(event);
|
||||||
@ -816,17 +818,17 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
|||||||
// Try the keyboard handler
|
// Try the keyboard handler
|
||||||
short translated = KeyboardTranslator.translate(event.getKeyCode());
|
short translated = KeyboardTranslator.translate(event.getKeyCode());
|
||||||
if (translated == 0) {
|
if (translated == 0) {
|
||||||
return super.onKeyDown(keyCode, event);
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Let this method take duplicate key down events
|
// Let this method take duplicate key down events
|
||||||
if (handleSpecialKeys(keyCode, true)) {
|
if (handleSpecialKeys(event.getKeyCode(), true)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pass through keyboard input if we're not grabbing
|
// Pass through keyboard input if we're not grabbing
|
||||||
if (!grabbedInput) {
|
if (!grabbedInput) {
|
||||||
return super.onKeyDown(keyCode, event);
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
conn.sendKeyboardInput(translated, KeyboardPacket.KEY_DOWN, getModifierState(event));
|
conn.sendKeyboardInput(translated, KeyboardPacket.KEY_DOWN, getModifierState(event));
|
||||||
@ -837,9 +839,14 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onKeyUp(int keyCode, KeyEvent event) {
|
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
|
// Pass-through virtual navigation keys
|
||||||
if ((event.getFlags() & KeyEvent.FLAG_VIRTUAL_HARD_KEY) != 0) {
|
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
|
// 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 handled = false;
|
||||||
boolean detectedGamepad = event.getDevice() != null && ((event.getDevice().getSources() & InputDevice.SOURCE_JOYSTICK) == InputDevice.SOURCE_JOYSTICK ||
|
if (ControllerHandler.isGameControllerDevice(event.getDevice())) {
|
||||||
(event.getDevice().getSources() & InputDevice.SOURCE_GAMEPAD) == InputDevice.SOURCE_GAMEPAD);
|
|
||||||
if (detectedGamepad || (event.getDevice() == null ||
|
|
||||||
event.getDevice().getKeyboardType() != InputDevice.KEYBOARD_TYPE_ALPHABETIC
|
|
||||||
)) {
|
|
||||||
// Always try the controller handler first, unless it's an alphanumeric keyboard device.
|
// Always try the controller handler first, unless it's an alphanumeric keyboard device.
|
||||||
// Otherwise, controller handler will eat keyboard d-pad events.
|
// Otherwise, controller handler will eat keyboard d-pad events.
|
||||||
handled = controllerHandler.handleButtonUp(event);
|
handled = controllerHandler.handleButtonUp(event);
|
||||||
@ -864,16 +867,16 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
|||||||
// Try the keyboard handler
|
// Try the keyboard handler
|
||||||
short translated = KeyboardTranslator.translate(event.getKeyCode());
|
short translated = KeyboardTranslator.translate(event.getKeyCode());
|
||||||
if (translated == 0) {
|
if (translated == 0) {
|
||||||
return super.onKeyUp(keyCode, event);
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (handleSpecialKeys(keyCode, false)) {
|
if (handleSpecialKeys(event.getKeyCode(), false)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pass through keyboard input if we're not grabbing
|
// Pass through keyboard input if we're not grabbing
|
||||||
if (!grabbedInput) {
|
if (!grabbedInput) {
|
||||||
return super.onKeyUp(keyCode, event);
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
conn.sendKeyboardInput(translated, KeyboardPacket.KEY_UP, getModifierState(event));
|
conn.sendKeyboardInput(translated, KeyboardPacket.KEY_UP, getModifierState(event));
|
||||||
|
@ -149,6 +149,30 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
|
|||||||
onInputDeviceAdded(deviceId);
|
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) {
|
public static short getAttachedControllerMask(Context context) {
|
||||||
int count = 0;
|
int count = 0;
|
||||||
short mask = 0;
|
short mask = 0;
|
||||||
@ -161,9 +185,7 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((dev.getSources() & InputDevice.SOURCE_JOYSTICK) != 0 &&
|
if (hasJoystickAxes(dev)) {
|
||||||
getMotionRangeForJoystickAxis(dev, MotionEvent.AXIS_X) != null &&
|
|
||||||
getMotionRangeForJoystickAxis(dev, MotionEvent.AXIS_Y) != null) {
|
|
||||||
LimeLog.info("Counting InputDevice: "+dev.getName());
|
LimeLog.info("Counting InputDevice: "+dev.getName());
|
||||||
mask |= 1 << count++;
|
mask |= 1 << count++;
|
||||||
}
|
}
|
||||||
|
@ -3,15 +3,21 @@ package com.limelight.ui;
|
|||||||
import android.annotation.TargetApi;
|
import android.annotation.TargetApi;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
|
import android.view.KeyEvent;
|
||||||
import android.view.SurfaceView;
|
import android.view.SurfaceView;
|
||||||
|
|
||||||
public class StreamView extends SurfaceView {
|
public class StreamView extends SurfaceView {
|
||||||
private double desiredAspectRatio;
|
private double desiredAspectRatio;
|
||||||
|
private InputCallbacks inputCallbacks;
|
||||||
|
|
||||||
public void setDesiredAspectRatio(double aspectRatio) {
|
public void setDesiredAspectRatio(double aspectRatio) {
|
||||||
this.desiredAspectRatio = aspectRatio;
|
this.desiredAspectRatio = aspectRatio;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setInputCallbacks(InputCallbacks callbacks) {
|
||||||
|
this.inputCallbacks = callbacks;
|
||||||
|
}
|
||||||
|
|
||||||
public StreamView(Context context) {
|
public StreamView(Context context) {
|
||||||
super(context);
|
super(context);
|
||||||
}
|
}
|
||||||
@ -52,4 +58,30 @@ public class StreamView extends SurfaceView {
|
|||||||
|
|
||||||
setMeasuredDimension(measuredWidth, measuredHeight);
|
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