Final fixes for Android O pointer capture

This commit is contained in:
Cameron Gutman 2017-06-08 18:17:34 -07:00
parent 5d6094df97
commit f6a0990432
4 changed files with 40 additions and 25 deletions

View File

@ -170,20 +170,6 @@ public class Game extends Activity implements SurfaceHolder.Callback,
streamView = (StreamView) findViewById(R.id.surfaceView); streamView = (StreamView) findViewById(R.id.surfaceView);
streamView.setOnGenericMotionListener(this); streamView.setOnGenericMotionListener(this);
streamView.setOnTouchListener(this); streamView.setOnTouchListener(this);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
streamView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
inputCaptureProvider.enableCapture();
}
});
streamView.setOnCapturedPointerListener(new View.OnCapturedPointerListener() {
@Override
public boolean onCapturedPointer(View view, MotionEvent motionEvent) {
return handleMotionEvent(motionEvent);
}
});
}
// Warn the user if they're on a metered connection // Warn the user if they're on a metered connection
checkDataConnection(); checkDataConnection();
@ -273,6 +259,18 @@ public class Game extends Activity implements SurfaceHolder.Callback,
inputCaptureProvider = InputCaptureManager.getInputCaptureProvider(this, this); inputCaptureProvider = InputCaptureManager.getInputCaptureProvider(this, this);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
// The view must be focusable for pointer capture to work.
streamView.setFocusable(true);
streamView.setDefaultFocusHighlightEnabled(false);
streamView.setOnCapturedPointerListener(new View.OnCapturedPointerListener() {
@Override
public boolean onCapturedPointer(View view, MotionEvent motionEvent) {
return handleMotionEvent(motionEvent);
}
});
}
if (prefConfig.onscreenController) { if (prefConfig.onscreenController) {
// create virtual onscreen controller // create virtual onscreen controller
virtualController = new VirtualController(conn, virtualController = new VirtualController(conn,
@ -291,6 +289,20 @@ public class Game extends Activity implements SurfaceHolder.Callback,
streamView.getHolder().addCallback(this); streamView.getHolder().addCallback(this);
} }
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
// Capture is lost when focus is lost, so it must be requested again
// when focus is regained.
if (inputCaptureProvider.isCapturingEnabled() && hasFocus) {
// Recapture the pointer if focus was regained
streamView.requestPointerCapture();
}
}
}
private void prepareDisplayForRendering() { private void prepareDisplayForRendering() {
Display display = getWindowManager().getDefaultDisplay(); Display display = getWindowManager().getDefaultDisplay();
WindowManager.LayoutParams windowLayoutParams = getWindow().getAttributes(); WindowManager.LayoutParams windowLayoutParams = getWindow().getAttributes();
@ -699,7 +711,7 @@ public class Game extends Activity implements SurfaceHolder.Callback,
int changedButtons = event.getButtonState() ^ lastButtonState; int changedButtons = event.getButtonState() ^ lastButtonState;
// Ignore mouse input if we're not capturing from our input source // Ignore mouse input if we're not capturing from our input source
if (!inputCaptureProvider.isCapturing()) { if (!inputCaptureProvider.isCapturingActive()) {
return false; return false;
} }

View File

@ -32,7 +32,7 @@ public class AndroidNativePointerCaptureProvider extends InputCaptureProvider {
} }
@Override @Override
public boolean isCapturing() { public boolean isCapturingActive() {
return targetView.hasPointerCapture(); return targetView.hasPointerCapture();
} }

View File

@ -9,22 +9,21 @@ import com.limelight.binding.input.evdev.EvdevListener;
public class InputCaptureManager { public class InputCaptureManager {
public static InputCaptureProvider getInputCaptureProvider(Activity activity, EvdevListener rootListener) { public static InputCaptureProvider getInputCaptureProvider(Activity activity, EvdevListener rootListener) {
// Shield capture is preferred because it can capture when the cursor is over if (AndroidNativePointerCaptureProvider.isCaptureProviderSupported()) {
// the system UI. Android N native capture can only capture over views owned
// by the application.
if (ShieldCaptureProvider.isCaptureProviderSupported()) {
LimeLog.info("Using NVIDIA mouse capture extension");
return new ShieldCaptureProvider(activity);
}
else if (AndroidNativePointerCaptureProvider.isCaptureProviderSupported()) {
LimeLog.info("Using Android O+ native mouse capture"); LimeLog.info("Using Android O+ native mouse capture");
return new AndroidNativePointerCaptureProvider(activity.findViewById(R.id.surfaceView)); return new AndroidNativePointerCaptureProvider(activity.findViewById(R.id.surfaceView));
} }
else if (ShieldCaptureProvider.isCaptureProviderSupported()) {
LimeLog.info("Using NVIDIA mouse capture extension");
return new ShieldCaptureProvider(activity);
}
else if (EvdevCaptureProvider.isCaptureProviderSupported()) { else if (EvdevCaptureProvider.isCaptureProviderSupported()) {
LimeLog.info("Using Evdev mouse capture"); LimeLog.info("Using Evdev mouse capture");
return new EvdevCaptureProvider(activity, rootListener); return new EvdevCaptureProvider(activity, rootListener);
} }
else if (AndroidPointerIconCaptureProvider.isCaptureProviderSupported()) { else if (AndroidPointerIconCaptureProvider.isCaptureProviderSupported()) {
// Android N's native capture can't capture over system UI elements
// so we want to only use it if there's no other option.
LimeLog.info("Using Android N+ pointer hiding"); LimeLog.info("Using Android N+ pointer hiding");
return new AndroidPointerIconCaptureProvider(activity); return new AndroidPointerIconCaptureProvider(activity);
} }

View File

@ -14,7 +14,11 @@ public abstract class InputCaptureProvider {
public void destroy() {} public void destroy() {}
public boolean isCapturing() { public boolean isCapturingEnabled() {
return isCapturing;
}
public boolean isCapturingActive() {
return isCapturing; return isCapturing;
} }