Skip to content

Commit

Permalink
Expose sync mode for injecting events
Browse files Browse the repository at this point in the history
Expose the inject input event mode so that it is possible to wait for
the events to be "finished". This will be necessary to read the
clipboard content only after the COPY or CUT key event is handled.

PR #2834 <#2834>
  • Loading branch information
rom1v committed Nov 29, 2021
1 parent dc19ae3 commit bfcb9d0
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 21 deletions.
16 changes: 8 additions & 8 deletions server/src/main/java/com/genymobile/scrcpy/Controller.java
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ private void initPointers() {
public void control() throws IOException {
// on start, power on the device
if (!Device.isScreenOn()) {
device.pressReleaseKeycode(KeyEvent.KEYCODE_POWER);
device.pressReleaseKeycode(KeyEvent.KEYCODE_POWER, Device.INJECT_MODE_ASYNC);

// dirty hack
// After POWER is injected, the device is powered on asynchronously.
Expand Down Expand Up @@ -144,7 +144,7 @@ private boolean injectKeycode(int action, int keycode, int repeat, int metaState
if (keepPowerModeOff && action == KeyEvent.ACTION_UP && (keycode == KeyEvent.KEYCODE_POWER || keycode == KeyEvent.KEYCODE_WAKEUP)) {
schedulePowerModeOff();
}
return device.injectKeyEvent(action, keycode, repeat, metaState);
return device.injectKeyEvent(action, keycode, repeat, metaState, Device.INJECT_MODE_ASYNC);
}

private boolean injectChar(char c) {
Expand All @@ -155,7 +155,7 @@ private boolean injectChar(char c) {
return false;
}
for (KeyEvent event : events) {
if (!device.injectEvent(event)) {
if (!device.injectEvent(event, Device.INJECT_MODE_ASYNC)) {
return false;
}
}
Expand Down Expand Up @@ -219,7 +219,7 @@ private boolean injectTouch(int action, long pointerId, Position position, float
MotionEvent event = MotionEvent
.obtain(lastTouchDown, now, action, pointerCount, pointerProperties, pointerCoords, 0, buttons, 1f, 1f, DEFAULT_DEVICE_ID, 0, source,
0);
return device.injectEvent(event);
return device.injectEvent(event, Device.INJECT_MODE_ASYNC);
}

private boolean injectScroll(Position position, int hScroll, int vScroll) {
Expand All @@ -242,7 +242,7 @@ private boolean injectScroll(Position position, int hScroll, int vScroll) {
MotionEvent event = MotionEvent
.obtain(lastTouchDown, now, MotionEvent.ACTION_SCROLL, 1, pointerProperties, pointerCoords, 0, 0, 1f, 1f, DEFAULT_DEVICE_ID, 0,
InputDevice.SOURCE_MOUSE, 0);
return device.injectEvent(event);
return device.injectEvent(event, Device.INJECT_MODE_ASYNC);
}

/**
Expand All @@ -260,7 +260,7 @@ public void run() {

private boolean pressBackOrTurnScreenOn(int action) {
if (Device.isScreenOn()) {
return device.injectKeyEvent(action, KeyEvent.KEYCODE_BACK, 0, 0);
return device.injectKeyEvent(action, KeyEvent.KEYCODE_BACK, 0, 0, Device.INJECT_MODE_ASYNC);
}

// Screen is off
Expand All @@ -273,7 +273,7 @@ private boolean pressBackOrTurnScreenOn(int action) {
if (keepPowerModeOff) {
schedulePowerModeOff();
}
return device.pressReleaseKeycode(KeyEvent.KEYCODE_POWER);
return device.pressReleaseKeycode(KeyEvent.KEYCODE_POWER, Device.INJECT_MODE_ASYNC);
}

private boolean setClipboard(String text, boolean paste, long sequence) {
Expand All @@ -284,7 +284,7 @@ private boolean setClipboard(String text, boolean paste, long sequence) {

// On Android >= 7, also press the PASTE key if requested
if (paste && Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && device.supportsInputEvents()) {
device.pressReleaseKeycode(KeyEvent.KEYCODE_PASTE);
device.pressReleaseKeycode(KeyEvent.KEYCODE_PASTE, Device.INJECT_MODE_ASYNC);
}

if (sequence != ControlMessage.SEQUENCE_INVALID) {
Expand Down
31 changes: 18 additions & 13 deletions server/src/main/java/com/genymobile/scrcpy/Device.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ public final class Device {
public static final int POWER_MODE_OFF = SurfaceControl.POWER_MODE_OFF;
public static final int POWER_MODE_NORMAL = SurfaceControl.POWER_MODE_NORMAL;

public static final int INJECT_MODE_ASYNC = InputManager.INJECT_INPUT_EVENT_MODE_ASYNC;
public static final int INJECT_MODE_WAIT_FOR_RESULT = InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_RESULT;
public static final int INJECT_MODE_WAIT_FOR_FINISH = InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH;

public static final int LOCK_VIDEO_ORIENTATION_UNLOCKED = -1;
public static final int LOCK_VIDEO_ORIENTATION_INITIAL = -2;

Expand Down Expand Up @@ -164,7 +168,7 @@ public boolean supportsInputEvents() {
return supportsInputEvents;
}

public static boolean injectEvent(InputEvent inputEvent, int displayId) {
public static boolean injectEvent(InputEvent inputEvent, int displayId, int injectMode) {
if (!supportsInputEvents(displayId)) {
throw new AssertionError("Could not inject input event if !supportsInputEvents()");
}
Expand All @@ -173,30 +177,31 @@ public static boolean injectEvent(InputEvent inputEvent, int displayId) {
return false;
}

return SERVICE_MANAGER.getInputManager().injectInputEvent(inputEvent, InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);
return SERVICE_MANAGER.getInputManager().injectInputEvent(inputEvent, injectMode);
}

public boolean injectEvent(InputEvent event) {
return injectEvent(event, displayId);
public boolean injectEvent(InputEvent event, int injectMode) {
return injectEvent(event, displayId, injectMode);
}

public static boolean injectKeyEvent(int action, int keyCode, int repeat, int metaState, int displayId) {
public static boolean injectKeyEvent(int action, int keyCode, int repeat, int metaState, int displayId, int injectMode) {
long now = SystemClock.uptimeMillis();
KeyEvent event = new KeyEvent(now, now, action, keyCode, repeat, metaState, KeyCharacterMap.VIRTUAL_KEYBOARD, 0, 0,
InputDevice.SOURCE_KEYBOARD);
return injectEvent(event, displayId);
return injectEvent(event, displayId, injectMode);
}

public boolean injectKeyEvent(int action, int keyCode, int repeat, int metaState) {
return injectKeyEvent(action, keyCode, repeat, metaState, displayId);
public boolean injectKeyEvent(int action, int keyCode, int repeat, int metaState, int injectMode) {
return injectKeyEvent(action, keyCode, repeat, metaState, displayId, injectMode);
}

public static boolean pressReleaseKeycode(int keyCode, int displayId) {
return injectKeyEvent(KeyEvent.ACTION_DOWN, keyCode, 0, 0, displayId) && injectKeyEvent(KeyEvent.ACTION_UP, keyCode, 0, 0, displayId);
public static boolean pressReleaseKeycode(int keyCode, int displayId, int injectMode) {
return injectKeyEvent(KeyEvent.ACTION_DOWN, keyCode, 0, 0, displayId, injectMode)
&& injectKeyEvent(KeyEvent.ACTION_UP, keyCode, 0, 0, displayId, injectMode);
}

public boolean pressReleaseKeycode(int keyCode) {
return pressReleaseKeycode(keyCode, displayId);
public boolean pressReleaseKeycode(int keyCode, int injectMode) {
return pressReleaseKeycode(keyCode, displayId, injectMode);
}

public static boolean isScreenOn() {
Expand Down Expand Up @@ -272,7 +277,7 @@ public static boolean powerOffScreen(int displayId) {
if (!isScreenOn()) {
return true;
}
return pressReleaseKeycode(KeyEvent.KEYCODE_POWER, displayId);
return pressReleaseKeycode(KeyEvent.KEYCODE_POWER, displayId, Device.INJECT_MODE_ASYNC);
}

/**
Expand Down

0 comments on commit bfcb9d0

Please sign in to comment.