Commit Graph

26 Commits

Author SHA1 Message Date
Romain Vimont
599108bf90 Simplify capture invalidation
Remove the unnecessary requestInvalidate() indirection. Use a single
invalidate() method instead.
2026-01-10 11:53:22 +01:00
Romain Vimont
f90dc216d1 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 <https://github.com/Genymobile/scrcpy/issues/5605>
PR #5614 <https://github.com/Genymobile/scrcpy/pull/5614>
2024-12-07 20:09:14 +01:00
Romain Vimont
97fa77c76c 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 d19396718e,
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 <https://github.com/Genymobile/scrcpy/issues/5545>
Fixes #5605 <https://github.com/Genymobile/scrcpy/issues/5605>
Fixes #5616 <https://github.com/Genymobile/scrcpy/issues/5616>
Refs #4598 <https://github.com/Genymobile/scrcpy/issues/4598>
Refs #5137 <https://github.com/Genymobile/scrcpy/issues/5137>
Refs #5370 <https://github.com/Genymobile/scrcpy/pull/5370>
PR #5614 <https://github.com/Genymobile/scrcpy/pull/5614>
2024-12-07 20:08:49 +01:00
Romain Vimont
adb674a5c8 Add --angle
Add an option to rotate the video content by a custom angle.

Fixes #4135 <https://github.com/Genymobile/scrcpy/issues/4135>
Fixes #4345 <https://github.com/Genymobile/scrcpy/issues/4345>
Refs #4658 <https://github.com/Genymobile/scrcpy/pull/4658>
PR #5455 <https://github.com/Genymobile/scrcpy/pull/5455>
2024-11-19 21:31:04 +01:00
Romain Vimont
45382e3f01 Add --capture-orientation
Deprecate --lock-video-orientation in favor of a more general option
--capture-orientation, which supports all possible orientations
(0, 90, 180, 270, flip0, flip90, flip180, flip270), and a "locked" flag
via a '@' prefix.

All the old "locked video orientations" are supported:
 - --lock-video-orientation      ->  --capture-orientation=@
 - --lock-video-orientation=0    ->  --capture-orientation=@0
 - --lock-video-orientation=90   ->  --capture-orientation=@90
 - --lock-video-orientation=180  ->  --capture-orientation=@180
 - --lock-video-orientation=270  ->  --capture-orientation=@270

In addition, --capture-orientation can rotate/flip the display without
locking, so that it follows the physical device rotation.

For example:

    scrcpy --capture-orientation=flip90

always flips and rotates the capture by 90° clockwise.

The arguments are consistent with --display-orientation and
--record-orientation and --orientation (which provide separate
client-side orientation settings).

Refs #4011 <https://github.com/Genymobile/scrcpy/issues/4011>
PR #5455 <https://github.com/Genymobile/scrcpy/pull/5455>
2024-11-19 21:31:04 +01:00
Romain Vimont
d72686c867 Extract display size monitor
Detecting display size changes is not straightforward:
 - from a DisplayListener, "display changed" events are received, but
   this does not imply that the size has changed (it must be checked);
 - on Android 14 (see e26bdb07a2),
   "display changed" events are not received on some versions, so as a
   fallback, a RotationWatcher and a DisplayFoldListener are registered,
   but unregistered as soon as a "display changed" event is actually
   received, which means that the problem is fixed.

Extract a "display size monitor" to share the code between screen
capture and virtual display capture.

PR #5455 <https://github.com/Genymobile/scrcpy/pull/5455>
2024-11-19 21:31:04 +01:00
Romain Vimont
06385ce83b Reimplement lock orientation using transforms
Reimplement the --lock-video-orientation feature using affine
transforms.

Fixes #4011 <https://github.com/Genymobile/scrcpy/issues/4011>
PR #5455 <https://github.com/Genymobile/scrcpy/pull/5455>
2024-11-19 21:31:04 +01:00
Romain Vimont
9fb0a3dac1 Reimplement crop using transforms
Reimplement the --crop feature using affine transforms.

Fixes #4162 <https://github.com/Genymobile/scrcpy/issues/4162>
PR #5455 <https://github.com/Genymobile/scrcpy/pull/5455>
2024-11-19 21:31:04 +01:00
Romain Vimont
e226950cfa Make PositionMapper use affine transforms
This will allow applying transformations performed by video filters.

PR #5455 <https://github.com/Genymobile/scrcpy/pull/5455>
2024-11-19 21:31:04 +01:00
Romain Vimont
019ce5eea4 Temporarily ignore lock video orientation and crop
Get rid of old code implementing --lock-video-orientation and --crop
features on the device side.

They will be reimplemented differently.

Refs #4011 <https://github.com/Genymobile/scrcpy/issues/4011>
Refs #4162 <https://github.com/Genymobile/scrcpy/issues/4162>
PR #5455 <https://github.com/Genymobile/scrcpy/pull/5455>
2024-11-19 21:31:04 +01:00
Romain Vimont
bd9d93194b Pass Options instance directly
Many constructors take a lot of parameters copied from Options. For
simplicity, just pass the Options instance.
2024-11-15 20:16:04 +01:00
Romain Vimont
104195fc3b Add shortcut to reset video capture/encoding
Reset video capture/encoding on MOD+Shift+r.

Like on device rotation, this starts a new encoding session which
produces a video stream starting by a key frame.

PR #5432 <https://github.com/Genymobile/scrcpy/pull/5432>
2024-11-03 19:31:02 +01:00
Romain Vimont
69b836930a Handle capture reset via listener
When the capture source becomes "invalid" (because the display size
changes for example), a reset request is performed to restart the
encoder.

The reset state was stored in SurfaceCapture. The capture implementation
set the flag, and the encoder consumed it.

However, this mechanism did not allow a reset request to _interrupt_ the
encoder, which may be waiting on a blocking call (until a new frame is
produced).

To be able to interrupt the encoder, a reset request must not only set a
flag, but run a callback provided by the encoder. For that purpose,
introduce the CaptureListener interface, which is notified by the
SurfaceCapture implementation whenever the capture is invalidated.

For now, the listener implementation just set a flag as before, so the
behavior is unchanged. It lays the groundwork for the next commits.

PR #5432 <https://github.com/Genymobile/scrcpy/pull/5432>
2024-11-03 19:26:55 +01:00
Romain Vimont
3ac4b64461 Register rotation watcher for non-main displays
While moving code, commit 874eaec487 added
a condition `if (displayId == 0)` to register a rotation watcher,
without good reasons.

This condition was kept when the rotation watcher was moved to a
fallback in e26bdb07a2.

Note: use `git show -b` to show this commit ignoring whitespace changes.

Refs #5428 <https://github.com/Genymobile/scrcpy/issues/5428>
2024-11-02 18:49:08 +01:00
Romain Vimont
e26bdb07a2 Listen to display changed events
Replace RotationWatcher and DisplayFoldListener by a single
DisplayListener, which is notified whenever the display size or dpi
changes.

However, the DisplayListener mechanism is broken in the first versions
of Android 14 (it is fixed in android-14.0.0_r29 by commit [1]), so
continue to use the old mechanism specifically for Android 14 (where
DisplayListener may be broken), until we receive the first
"display changed" event (which proves that it works).

[1]: <5653c6b587%5E%21/>

Fixes #161 <https://github.com/Genymobile/scrcpy/issues/161>
Fixes #1918 <https://github.com/Genymobile/scrcpy/issues/1918>
Fixes #4152 <https://github.com/Genymobile/scrcpy/issues/4152>
Fixes #5362 comment <https://github.com/Genymobile/scrcpy/issues/5362#issuecomment-2416219316>
Refs #4469 <https://github.com/Genymobile/scrcpy/pull/4469>
PR #5415 <https://github.com/Genymobile/scrcpy/pull/5415>

Co-authored-by: Simon Chan <1330321+yume-chan@users.noreply.github.com>
2024-10-31 20:12:23 +01:00
Romain Vimont
d19396718e Inject display-related events to virtual display
Mouse and touch events must be sent to the virtual display id (used for
mirroring), other events (like key events) must be sent to the original
display id.

Fixes #4598 <https://github.com/Genymobile/scrcpy/issues/4598>
Fixes #5137 <https://github.com/Genymobile/scrcpy/issues/5137>
PR #5370 <https://github.com/Genymobile/scrcpy/pull/5370>

Co-authored-by: nightmare <mengyanshou@gmail.com>
2024-10-28 18:13:55 +01:00
Romain Vimont
7024d38199 Send PositionMapper to Controller directly
When a new capture starts, send a new PositionMapper to the Controller
without using the global Device as an intermediate.

Now all Device methods are static.

PR #5370 <https://github.com/Genymobile/scrcpy/pull/5370>
2024-10-28 18:13:55 +01:00
Romain Vimont
f1368d9a8f Introduce PositionMapper
Extract the function that converts coordinates from video space to
display space into a separate component.

It only requires the specific data it uses and does not need a full
ScreenInfo object (although it can be created from a ScreenInfo
instance).

PR #5370 <https://github.com/Genymobile/scrcpy/pull/5370>
2024-10-28 18:13:55 +01:00
Romain Vimont
b60e174780 Add capture prepare() step
Add a function called before each capture starts (before getSize() is
called).

This allows to compute the ScreenInfo instance once exactly when needed.

PR #5370 <https://github.com/Genymobile/scrcpy/pull/5370>
2024-10-28 18:13:55 +01:00
Romain Vimont
5851b62580 Simplify virtual display video size
Do not use an unnecessary intermediate Rect object.

PR #5370 <https://github.com/Genymobile/scrcpy/pull/5370>
2024-10-28 18:13:55 +01:00
Romain Vimont
12d5ca4d5e Move local variables in ScreenCapture
Do not initialize variables when they are not used.

PR #5370 <https://github.com/Genymobile/scrcpy/pull/5370>
2024-10-28 18:13:55 +01:00
Romain Vimont
5f0480c039 Ignore first displayFoldChanged event
An event is posted on registration to signal the initial state.

This had no impact when the listener was registered from Device (before
it was moved to ScreenCapture), because this first initial event was
already triggered when ScreenCapture started listening.

But now, it causes the first encoding to be reset immediately. To avoid
that, ignore the first event.

Refs <https://android.googlesource.com/platform/frameworks/base.git/+/refs/tags/android-15.0.0_r3/services/core/java/com/android/server/policy/DisplayFoldController.java#138>
PR #5370 <https://github.com/Genymobile/scrcpy/pull/5370>
2024-10-28 18:13:55 +01:00
Romain Vimont
874eaec487 Move screen-related features out of Device.java
Move the code related to screen size and rotation/fold to ScreenCapture.

For now, keep the ScreenInfo instance in the Device class to communicate
with the Controller, but it will be removed by further commits.

PR #5370 <https://github.com/Genymobile/scrcpy/pull/5370>
2024-10-28 18:13:55 +01:00
Romain Vimont
3acffaae57 Use explicit constants for Android versions
Who remembers code names? This avoids to check the mapping every time.
2024-10-20 13:15:22 +02:00
Romain Vimont
f69ac40534 Reorganize server imports
Moving classes into subpackages changed the expected imports order.

Reorganize them all at once automatically to avoid spurious changes in
future commits.
2024-09-20 08:43:42 +02:00
Romain Vimont
e84db2914d Reorganize server packages
There are now a lot of classes in the server, reorganize them into
subpackages.
2024-07-11 22:38:00 +02:00