diff --git a/README.md b/README.md
index d875fd9989..4ef28ab203 100644
--- a/README.md
+++ b/README.md
@@ -440,8 +440,12 @@ scrcpy -S
Or by pressing MOD+o at any time.
-To turn it back on, press MOD+Shift+o (or
-`POWER`, MOD+p).
+To turn it back on, press MOD+Shift+o.
+
+On Android, the `POWER` button always turns the screen on. For convenience, if
+`POWER` is sent via scrcpy (via right-click or Ctrl+p), it
+will force to turn the screen off after a small delay (on a best effort basis).
+The physical `POWER` button will still cause the screen to be turned on.
It can be useful to also prevent the device to sleep:
diff --git a/server/src/main/java/com/genymobile/scrcpy/Controller.java b/server/src/main/java/com/genymobile/scrcpy/Controller.java
index f32e5ec04e..2ad26a9506 100644
--- a/server/src/main/java/com/genymobile/scrcpy/Controller.java
+++ b/server/src/main/java/com/genymobile/scrcpy/Controller.java
@@ -8,11 +8,16 @@
import android.view.MotionEvent;
import java.io.IOException;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
public class Controller {
private static final int DEVICE_ID_VIRTUAL = -1;
+ private static final ScheduledExecutorService EXECUTOR = Executors.newSingleThreadScheduledExecutor();
+
private final Device device;
private final DesktopConnection connection;
private final DeviceMessageSender sender;
@@ -24,6 +29,8 @@ public class Controller {
private final MotionEvent.PointerProperties[] pointerProperties = new MotionEvent.PointerProperties[PointersState.MAX_POINTERS];
private final MotionEvent.PointerCoords[] pointerCoords = new MotionEvent.PointerCoords[PointersState.MAX_POINTERS];
+ private boolean keepPowerModeOff;
+
public Controller(Device device, DesktopConnection connection) {
this.device = device;
this.connection = connection;
@@ -117,6 +124,7 @@ private void handleEvent() throws IOException {
int mode = msg.getAction();
boolean setPowerModeOk = Device.setScreenPowerMode(mode);
if (setPowerModeOk) {
+ keepPowerModeOff = mode == Device.POWER_MODE_OFF;
Ln.i("Device screen turned " + (mode == Device.POWER_MODE_OFF ? "off" : "on"));
}
}
@@ -130,6 +138,9 @@ private void handleEvent() throws IOException {
}
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);
}
@@ -223,8 +234,24 @@ private boolean injectScroll(Position position, int hScroll, int vScroll) {
return device.injectEvent(event);
}
+ /**
+ * Schedule a call to set power mode to off after a small delay.
+ */
+ private static void schedulePowerModeOff() {
+ EXECUTOR.schedule(new Runnable() {
+ @Override
+ public void run() {
+ Ln.i("Forcing screen off");
+ Device.setScreenPowerMode(Device.POWER_MODE_OFF);
+ }
+ }, 200, TimeUnit.MILLISECONDS);
+ }
+
private boolean pressBackOrTurnScreenOn() {
int keycode = device.isScreenOn() ? KeyEvent.KEYCODE_BACK : KeyEvent.KEYCODE_WAKEUP;
+ if (keepPowerModeOff && keycode == KeyEvent.KEYCODE_WAKEUP) {
+ schedulePowerModeOff();
+ }
return device.injectKeycode(keycode);
}