From 97fa77c76c5502105a3d128a0be2477a04f4fd1b Mon Sep 17 00:00:00 2001 From: Romain Vimont Date: Wed, 4 Dec 2024 23:35:43 +0100 Subject: [PATCH 1/2] Inject main display events to the original display When mirroring a secondary display, touch and scroll events must be sent to the mirroring virtual display id (with coordinates relative to the virtual display size), rather than to the original display (with coordinates relative to the original display size). This behavior, introduced by d19396718ee0c0ba7fb578f595a6553c0458da59, was also applied for the main display for consistency. However, it causes some UI elements to become unclickable. To minimize inconveniences, restore the previous behavior when mirroring the main display: send all events to the original display id (0) with coordinates relative to the original display size. Fixes #5545 Fixes #5605 Fixes #5616 Refs #4598 Refs #5137 Refs #5370 PR #5614 --- .../com/genymobile/scrcpy/video/ScreenCapture.java | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/server/src/main/java/com/genymobile/scrcpy/video/ScreenCapture.java b/server/src/main/java/com/genymobile/scrcpy/video/ScreenCapture.java index 47425d090f..5d026a7322 100644 --- a/server/src/main/java/com/genymobile/scrcpy/video/ScreenCapture.java +++ b/server/src/main/java/com/genymobile/scrcpy/video/ScreenCapture.java @@ -129,10 +129,18 @@ public void start(Surface surface) throws IOException { try { virtualDisplay = ServiceManager.getDisplayManager() .createVirtualDisplay("scrcpy", inputSize.getWidth(), inputSize.getHeight(), displayId, surface); - virtualDisplayId = virtualDisplay.getDisplay().getDisplayId(); - // The positions are relative to the virtual display, not the original display (so use inputSize, not deviceSize!) - positionMapper = PositionMapper.create(videoSize, transform, inputSize); + + if (displayId == 0) { + // Main display: send all events to the original display, relative to the device size + Size deviceSize = displayInfo.getSize(); + positionMapper = PositionMapper.create(videoSize, transform, deviceSize); + virtualDisplayId = 0; + } else { + // The positions are relative to the virtual display, not the original display (so use inputSize, not deviceSize!) + positionMapper = PositionMapper.create(videoSize, transform, inputSize); + virtualDisplayId = virtualDisplay.getDisplay().getDisplayId(); + } Ln.d("Display: using DisplayManager API"); } catch (Exception displayManagerException) { try { From f90dc216d10ac062ab1a06e14e574acc5569d2c3 Mon Sep 17 00:00:00 2001 From: Romain Vimont Date: Wed, 4 Dec 2024 23:58:22 +0100 Subject: [PATCH 2/2] Refactor virtual display properties initialization Following the changes from the previous commit, the behavior is now identical when mirroring the main display or using the SurfaceControl API. Factorize the code to perform the initialization in a single location. Refs #5605 PR #5614 --- .../scrcpy/video/ScreenCapture.java | 30 ++++++++----------- 1 file changed, 12 insertions(+), 18 deletions(-) diff --git a/server/src/main/java/com/genymobile/scrcpy/video/ScreenCapture.java b/server/src/main/java/com/genymobile/scrcpy/video/ScreenCapture.java index 5d026a7322..5f4e1803f9 100644 --- a/server/src/main/java/com/genymobile/scrcpy/video/ScreenCapture.java +++ b/server/src/main/java/com/genymobile/scrcpy/video/ScreenCapture.java @@ -124,23 +124,9 @@ public void start(Surface surface) throws IOException { inputSize = videoSize; } - int virtualDisplayId; - PositionMapper positionMapper; try { virtualDisplay = ServiceManager.getDisplayManager() .createVirtualDisplay("scrcpy", inputSize.getWidth(), inputSize.getHeight(), displayId, surface); - - - if (displayId == 0) { - // Main display: send all events to the original display, relative to the device size - Size deviceSize = displayInfo.getSize(); - positionMapper = PositionMapper.create(videoSize, transform, deviceSize); - virtualDisplayId = 0; - } else { - // The positions are relative to the virtual display, not the original display (so use inputSize, not deviceSize!) - positionMapper = PositionMapper.create(videoSize, transform, inputSize); - virtualDisplayId = virtualDisplay.getDisplay().getDisplayId(); - } Ln.d("Display: using DisplayManager API"); } catch (Exception displayManagerException) { try { @@ -148,11 +134,7 @@ public void start(Surface surface) throws IOException { Size deviceSize = displayInfo.getSize(); int layerStack = displayInfo.getLayerStack(); - setDisplaySurface(display, surface, deviceSize.toRect(), inputSize.toRect(), layerStack); - virtualDisplayId = displayId; - - positionMapper = PositionMapper.create(videoSize, transform, deviceSize); Ln.d("Display: using SurfaceControl API"); } catch (Exception surfaceControlException) { Ln.e("Could not create display using DisplayManager", displayManagerException); @@ -162,6 +144,18 @@ public void start(Surface surface) throws IOException { } if (vdListener != null) { + int virtualDisplayId; + PositionMapper positionMapper; + if (virtualDisplay == null || displayId == 0) { + // Surface control or main display: send all events to the original display, relative to the device size + Size deviceSize = displayInfo.getSize(); + positionMapper = PositionMapper.create(videoSize, transform, deviceSize); + virtualDisplayId = displayId; + } else { + // The positions are relative to the virtual display, not the original display (so use inputSize, not deviceSize!) + positionMapper = PositionMapper.create(videoSize, transform, inputSize); + virtualDisplayId = virtualDisplay.getDisplay().getDisplayId(); + } vdListener.onNewVirtualDisplay(virtualDisplayId, positionMapper); } }