diff --git a/app/src/main.c b/app/src/main.c index e0008e93..4d4cf5ca 100644 --- a/app/src/main.c +++ b/app/src/main.c @@ -28,6 +28,7 @@ struct args { uint16_t max_size; uint32_t bit_rate; bool always_on_top; + bool turn_screen_off; }; static void usage(const char *arg0) { @@ -82,6 +83,9 @@ static void usage(const char *arg0) { " The device serial number. Mandatory only if several devices\n" " are connected to adb.\n" "\n" + " -S, --turn-screen-off\n" + " Turn the device screen off immediately.\n" + "\n" " -t, --show-touches\n" " Enable \"show touches\" on start, disable on quit.\n" " It only shows physical touches (not clicks from scrcpy).\n" @@ -299,11 +303,12 @@ parse_args(struct args *args, int argc, char *argv[]) { {"record-format", required_argument, NULL, 'f'}, {"serial", required_argument, NULL, 's'}, {"show-touches", no_argument, NULL, 't'}, + {"turn-screen-off", no_argument, NULL, 'S'}, {"version", no_argument, NULL, 'v'}, {NULL, 0, NULL, 0 }, }; int c; - while ((c = getopt_long(argc, argv, "b:c:fF:hm:nNp:r:s:tTv", long_options, + while ((c = getopt_long(argc, argv, "b:c:fF:hm:nNp:r:s:StTv", long_options, NULL)) != -1) { switch (c) { case 'b': @@ -347,6 +352,9 @@ parse_args(struct args *args, int argc, char *argv[]) { case 's': args->serial = optarg; break; + case 'S': + args->turn_screen_off = true; + break; case 't': args->show_touches = true; break; @@ -417,6 +425,7 @@ main(int argc, char *argv[]) { .always_on_top = false, .no_control = false, .no_display = false, + .turn_screen_off = false, }; if (!parse_args(&args, argc, argv)) { return 1; @@ -457,6 +466,7 @@ main(int argc, char *argv[]) { .always_on_top = args.always_on_top, .control = !args.no_control, .display = !args.no_display, + .turn_screen_off = args.turn_screen_off, }; int res = scrcpy(&options) ? 0 : 1; diff --git a/app/src/scrcpy.c b/app/src/scrcpy.c index e85577a4..0e24fc7c 100644 --- a/app/src/scrcpy.c +++ b/app/src/scrcpy.c @@ -375,6 +375,16 @@ scrcpy(const struct scrcpy_options *options) { goto end; } + if (options->turn_screen_off) { + struct control_msg msg; + msg.type = CONTROL_MSG_TYPE_SET_SCREEN_POWER_MODE; + msg.set_screen_power_mode.mode = SCREEN_POWER_MODE_OFF; + + if (!controller_push_msg(&controller, &msg)) { + LOGW("Cannot request 'set screen power mode'"); + } + } + if (options->fullscreen) { screen_switch_fullscreen(&screen); } diff --git a/app/src/scrcpy.h b/app/src/scrcpy.h index 52bd14cc..4cbadcad 100644 --- a/app/src/scrcpy.h +++ b/app/src/scrcpy.h @@ -18,6 +18,7 @@ struct scrcpy_options { bool always_on_top; bool control; bool display; + bool turn_screen_off; }; bool diff --git a/server/src/main/java/com/genymobile/scrcpy/Controller.java b/server/src/main/java/com/genymobile/scrcpy/Controller.java index a43ee5ba..263fc2fc 100644 --- a/server/src/main/java/com/genymobile/scrcpy/Controller.java +++ b/server/src/main/java/com/genymobile/scrcpy/Controller.java @@ -53,9 +53,21 @@ public class Controller { coords.setAxisValue(MotionEvent.AXIS_VSCROLL, vScroll); } + @SuppressWarnings("checkstyle:MagicNumber") public void control() throws IOException { // on start, power on the device - powerOn(); + if (!device.isScreenOn()) { + injectKeycode(KeyEvent.KEYCODE_POWER); + + // dirty hack + // After POWER is injected, the device is powered on asynchronously. + // To turn the device screen off while mirroring, the client will send a message that + // would be handled before the device is actually powered on, so its effect would + // be "canceled" once the device is turned back on. + // Adding this delay prevents to handle the message before the device is actually + // powered on. + SystemClock.sleep(500); + } while (true) { handleEvent(); @@ -182,10 +194,6 @@ public class Controller { return device.injectInputEvent(event, InputManager.INJECT_INPUT_EVENT_MODE_ASYNC); } - private boolean powerOn() { - return device.isScreenOn() || injectKeycode(KeyEvent.KEYCODE_POWER); - } - private boolean pressBackOrTurnScreenOn() { int keycode = device.isScreenOn() ? KeyEvent.KEYCODE_BACK : KeyEvent.KEYCODE_POWER; return injectKeycode(keycode);