Compare commits
6
Commits
locked
...
negativepos
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a12b459746 | ||
|
|
a0af402d96 | ||
|
|
600df37753 | ||
|
|
902b99174d | ||
|
|
cd69eb4a4f | ||
|
|
ae2d094362 |
@@ -282,6 +282,15 @@ meson x -Dserver_debugger=true
|
|||||||
meson configure x -Dserver_debugger=true
|
meson configure x -Dserver_debugger=true
|
||||||
```
|
```
|
||||||
|
|
||||||
|
If your device runs Android 8 or below, set the `server_debugger_method` to
|
||||||
|
`old` in addition:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
meson x -Dserver_debugger=true -Dserver_debugger_method=old
|
||||||
|
# or, if x is already configured
|
||||||
|
meson configure x -Dserver_debugger=true -Dserver_debugger_method=old
|
||||||
|
```
|
||||||
|
|
||||||
Then recompile.
|
Then recompile.
|
||||||
|
|
||||||
When you start scrcpy, it will start a debugger on port 5005 on the device.
|
When you start scrcpy, it will start a debugger on port 5005 on the device.
|
||||||
|
|||||||
@@ -261,6 +261,16 @@ scrcpy -s 192.168.0.1:5555 # short version
|
|||||||
|
|
||||||
You can start several instances of _scrcpy_ for several devices.
|
You can start several instances of _scrcpy_ for several devices.
|
||||||
|
|
||||||
|
#### Autostart on device connection
|
||||||
|
|
||||||
|
You could use [AutoAdb]:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
autoadb scrcpy -s '{}'
|
||||||
|
```
|
||||||
|
|
||||||
|
[AutoAdb]: https://github.com/rom1v/usbaudio
|
||||||
|
|
||||||
#### SSH tunnel
|
#### SSH tunnel
|
||||||
|
|
||||||
To connect to a remote device, it is possible to connect a local `adb` client to
|
To connect to a remote device, it is possible to connect a local `adb` client to
|
||||||
|
|||||||
@@ -124,6 +124,9 @@ conf.set('WINDOWS_NOCONSOLE', get_option('windows_noconsole'))
|
|||||||
# run a server debugger and wait for a client to be attached
|
# run a server debugger and wait for a client to be attached
|
||||||
conf.set('SERVER_DEBUGGER', get_option('server_debugger'))
|
conf.set('SERVER_DEBUGGER', get_option('server_debugger'))
|
||||||
|
|
||||||
|
# select the debugger method ('old' for Android < 9, 'new' for Android >= 9)
|
||||||
|
conf.set('SERVER_DEBUGGER_METHOD_NEW', get_option('server_debugger_method') == 'new')
|
||||||
|
|
||||||
configure_file(configuration: conf, output: 'config.h')
|
configure_file(configuration: conf, output: 'config.h')
|
||||||
|
|
||||||
src_dir = include_directories('src')
|
src_dir = include_directories('src')
|
||||||
|
|||||||
+2
-2
@@ -131,13 +131,13 @@ Set a custom window title.
|
|||||||
.BI "\-\-window\-x " value
|
.BI "\-\-window\-x " value
|
||||||
Set the initial window horizontal position.
|
Set the initial window horizontal position.
|
||||||
|
|
||||||
Default is -1 (automatic).\n
|
Default is "auto".\n
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.BI "\-\-window\-y " value
|
.BI "\-\-window\-y " value
|
||||||
Set the initial window vertical position.
|
Set the initial window vertical position.
|
||||||
|
|
||||||
Default is -1 (automatic).\n
|
Default is "auto".\n
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.BI "\-\-window\-width " value
|
.BI "\-\-window\-width " value
|
||||||
|
|||||||
+12
-3
@@ -1,5 +1,6 @@
|
|||||||
#include "cli.h"
|
#include "cli.h"
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
@@ -116,11 +117,11 @@ scrcpy_print_usage(const char *arg0) {
|
|||||||
"\n"
|
"\n"
|
||||||
" --window-x value\n"
|
" --window-x value\n"
|
||||||
" Set the initial window horizontal position.\n"
|
" Set the initial window horizontal position.\n"
|
||||||
" Default is -1 (automatic).\n"
|
" Default is \"auto\".\n"
|
||||||
"\n"
|
"\n"
|
||||||
" --window-y value\n"
|
" --window-y value\n"
|
||||||
" Set the initial window vertical position.\n"
|
" Set the initial window vertical position.\n"
|
||||||
" Default is -1 (automatic).\n"
|
" Default is \"auto\".\n"
|
||||||
"\n"
|
"\n"
|
||||||
" --window-width value\n"
|
" --window-width value\n"
|
||||||
" Set the initial window width.\n"
|
" Set the initial window width.\n"
|
||||||
@@ -302,8 +303,16 @@ parse_lock_video_orientation(const char *s, int8_t *lock_video_orientation) {
|
|||||||
|
|
||||||
static bool
|
static bool
|
||||||
parse_window_position(const char *s, int16_t *position) {
|
parse_window_position(const char *s, int16_t *position) {
|
||||||
|
// special value for "auto"
|
||||||
|
static_assert(WINDOW_POSITION_UNDEFINED == -0x8000);
|
||||||
|
|
||||||
|
if (!strcmp(s, "auto")) {
|
||||||
|
*position = WINDOW_POSITION_UNDEFINED;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
long value;
|
long value;
|
||||||
bool ok = parse_integer_arg(s, &value, false, -1, 0x7FFF,
|
bool ok = parse_integer_arg(s, &value, false, -0x7FFF, 0x7FFF,
|
||||||
"window position");
|
"window position");
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -94,6 +94,23 @@ convert_keycode(SDL_Keycode from, enum android_keycode *to, uint16_t mod,
|
|||||||
MAP(SDLK_UP, AKEYCODE_DPAD_UP);
|
MAP(SDLK_UP, AKEYCODE_DPAD_UP);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!(mod & (KMOD_NUM | KMOD_SHIFT))) {
|
||||||
|
// Handle Numpad events when Num Lock is disabled
|
||||||
|
// If SHIFT is pressed, a text event will be sent instead
|
||||||
|
switch(from) {
|
||||||
|
MAP(SDLK_KP_0, AKEYCODE_INSERT);
|
||||||
|
MAP(SDLK_KP_1, AKEYCODE_MOVE_END);
|
||||||
|
MAP(SDLK_KP_2, AKEYCODE_DPAD_DOWN);
|
||||||
|
MAP(SDLK_KP_3, AKEYCODE_PAGE_DOWN);
|
||||||
|
MAP(SDLK_KP_4, AKEYCODE_DPAD_LEFT);
|
||||||
|
MAP(SDLK_KP_6, AKEYCODE_DPAD_RIGHT);
|
||||||
|
MAP(SDLK_KP_7, AKEYCODE_MOVE_HOME);
|
||||||
|
MAP(SDLK_KP_8, AKEYCODE_DPAD_UP);
|
||||||
|
MAP(SDLK_KP_9, AKEYCODE_PAGE_UP);
|
||||||
|
MAP(SDLK_KP_PERIOD, AKEYCODE_FORWARD_DEL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (prefer_text) {
|
if (prefer_text) {
|
||||||
// do not forward alpha and space key events
|
// do not forward alpha and space key events
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
+4
-4
@@ -21,8 +21,8 @@ struct scrcpy_options {
|
|||||||
uint32_t bit_rate;
|
uint32_t bit_rate;
|
||||||
uint16_t max_fps;
|
uint16_t max_fps;
|
||||||
int8_t lock_video_orientation;
|
int8_t lock_video_orientation;
|
||||||
int16_t window_x;
|
int16_t window_x; // WINDOW_POSITION_UNDEFINED for "auto"
|
||||||
int16_t window_y;
|
int16_t window_y; // WINDOW_POSITION_UNDEFINED for "auto"
|
||||||
uint16_t window_width;
|
uint16_t window_width;
|
||||||
uint16_t window_height;
|
uint16_t window_height;
|
||||||
bool show_touches;
|
bool show_touches;
|
||||||
@@ -51,8 +51,8 @@ struct scrcpy_options {
|
|||||||
.bit_rate = DEFAULT_BIT_RATE, \
|
.bit_rate = DEFAULT_BIT_RATE, \
|
||||||
.max_fps = 0, \
|
.max_fps = 0, \
|
||||||
.lock_video_orientation = DEFAULT_LOCK_VIDEO_ORIENTATION, \
|
.lock_video_orientation = DEFAULT_LOCK_VIDEO_ORIENTATION, \
|
||||||
.window_x = -1, \
|
.window_x = WINDOW_POSITION_UNDEFINED, \
|
||||||
.window_y = -1, \
|
.window_y = WINDOW_POSITION_UNDEFINED, \
|
||||||
.window_width = 0, \
|
.window_width = 0, \
|
||||||
.window_height = 0, \
|
.window_height = 0, \
|
||||||
.show_touches = false, \
|
.show_touches = false, \
|
||||||
|
|||||||
+4
-2
@@ -186,8 +186,10 @@ screen_init_rendering(struct screen *screen, const char *window_title,
|
|||||||
window_flags |= SDL_WINDOW_BORDERLESS;
|
window_flags |= SDL_WINDOW_BORDERLESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
int x = window_x != -1 ? window_x : (int) SDL_WINDOWPOS_UNDEFINED;
|
int x = window_x != WINDOW_POSITION_UNDEFINED
|
||||||
int y = window_y != -1 ? window_y : (int) SDL_WINDOWPOS_UNDEFINED;
|
? window_x : (int) SDL_WINDOWPOS_UNDEFINED;
|
||||||
|
int y = window_y != WINDOW_POSITION_UNDEFINED
|
||||||
|
? window_y : (int) SDL_WINDOWPOS_UNDEFINED;
|
||||||
screen->window = SDL_CreateWindow(window_title, x, y,
|
screen->window = SDL_CreateWindow(window_title, x, y,
|
||||||
window_size.width, window_size.height,
|
window_size.width, window_size.height,
|
||||||
window_flags);
|
window_flags);
|
||||||
|
|||||||
@@ -8,6 +8,8 @@
|
|||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
|
||||||
|
#define WINDOW_POSITION_UNDEFINED (-0x8000)
|
||||||
|
|
||||||
struct video_buffer;
|
struct video_buffer;
|
||||||
|
|
||||||
struct screen {
|
struct screen {
|
||||||
@@ -53,6 +55,7 @@ void
|
|||||||
screen_init(struct screen *screen);
|
screen_init(struct screen *screen);
|
||||||
|
|
||||||
// initialize screen, create window, renderer and texture (window is hidden)
|
// initialize screen, create window, renderer and texture (window is hidden)
|
||||||
|
// window_x and window_y accept WINDOW_POSITION_UNDEFINED
|
||||||
bool
|
bool
|
||||||
screen_init_rendering(struct screen *screen, const char *window_title,
|
screen_init_rendering(struct screen *screen, const char *window_title,
|
||||||
struct size frame_size, bool always_on_top,
|
struct size frame_size, bool always_on_top,
|
||||||
|
|||||||
@@ -244,7 +244,13 @@ execute_server(struct server *server, const struct server_params *params) {
|
|||||||
"app_process",
|
"app_process",
|
||||||
#ifdef SERVER_DEBUGGER
|
#ifdef SERVER_DEBUGGER
|
||||||
# define SERVER_DEBUGGER_PORT "5005"
|
# define SERVER_DEBUGGER_PORT "5005"
|
||||||
|
# ifdef SERVER_DEBUGGER_METHOD_NEW
|
||||||
|
/* Android 9 and above */
|
||||||
|
"-XjdwpProvider:internal -XjdwpOptions:transport=dt_socket,suspend=y,server=y,address="
|
||||||
|
# else
|
||||||
|
/* Android 8 and below */
|
||||||
"-agentlib:jdwp=transport=dt_socket,suspend=y,server=y,address="
|
"-agentlib:jdwp=transport=dt_socket,suspend=y,server=y,address="
|
||||||
|
# endif
|
||||||
SERVER_DEBUGGER_PORT,
|
SERVER_DEBUGGER_PORT,
|
||||||
#endif
|
#endif
|
||||||
"/", // unused
|
"/", // unused
|
||||||
|
|||||||
@@ -6,3 +6,4 @@ option('prebuilt_server', type: 'string', description: 'Path of the prebuilt ser
|
|||||||
option('portable', type: 'boolean', value: false, description: 'Use scrcpy-server from the same directory as the scrcpy executable')
|
option('portable', type: 'boolean', value: false, description: 'Use scrcpy-server from the same directory as the scrcpy executable')
|
||||||
option('hidpi_support', type: 'boolean', value: true, description: 'Enable High DPI support')
|
option('hidpi_support', type: 'boolean', value: true, description: 'Enable High DPI support')
|
||||||
option('server_debugger', type: 'boolean', value: false, description: 'Run a server debugger and wait for a client to be attached')
|
option('server_debugger', type: 'boolean', value: false, description: 'Run a server debugger and wait for a client to be attached')
|
||||||
|
option('server_debugger_method', type: 'combo', choices: ['old', 'new'], value: 'new', description: 'Select the debugger method (Android < 9: "old", Android >= 9: "new")')
|
||||||
|
|||||||
@@ -22,14 +22,12 @@ public final class Device {
|
|||||||
|
|
||||||
private final ServiceManager serviceManager = new ServiceManager();
|
private final ServiceManager serviceManager = new ServiceManager();
|
||||||
|
|
||||||
private final int lockedVideoOrientation;
|
|
||||||
private ScreenInfo screenInfo;
|
private ScreenInfo screenInfo;
|
||||||
private RotationListener rotationListener;
|
private RotationListener rotationListener;
|
||||||
|
|
||||||
public Device(Options options) {
|
public Device(Options options) {
|
||||||
lockedVideoOrientation = options.getLockedVideoOrientation();
|
|
||||||
DisplayInfo displayInfo = serviceManager.getDisplayManager().getDisplayInfo();
|
DisplayInfo displayInfo = serviceManager.getDisplayManager().getDisplayInfo();
|
||||||
screenInfo = ScreenInfo.computeScreenInfo(displayInfo, options.getCrop(), options.getMaxSize());
|
screenInfo = ScreenInfo.computeScreenInfo(displayInfo, options.getCrop(), options.getMaxSize(), options.getLockedVideoOrientation());
|
||||||
registerRotationWatcher(new IRotationWatcher.Stub() {
|
registerRotationWatcher(new IRotationWatcher.Stub() {
|
||||||
@Override
|
@Override
|
||||||
public void onRotationChanged(int rotation) throws RemoteException {
|
public void onRotationChanged(int rotation) throws RemoteException {
|
||||||
@@ -49,55 +47,28 @@ public final class Device {
|
|||||||
return screenInfo;
|
return screenInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the rotation to apply to the device rotation to get the requested locked video orientation
|
|
||||||
*
|
|
||||||
* @param deviceRotation the device rotation
|
|
||||||
* @return the rotation offset
|
|
||||||
*/
|
|
||||||
public int getVideoRotation(int deviceRotation) {
|
|
||||||
if (lockedVideoOrientation == -1) {
|
|
||||||
// no offset
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return (deviceRotation + 4 - lockedVideoOrientation) % 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the rotation to apply to the requested locked video orientation to get the device rotation
|
|
||||||
*
|
|
||||||
* @param deviceRotation the device rotation
|
|
||||||
* @return the (reverse) rotation offset
|
|
||||||
*/
|
|
||||||
private int getReverseVideoRotation(int deviceRotation) {
|
|
||||||
if (lockedVideoOrientation == -1) {
|
|
||||||
// no offset
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return (lockedVideoOrientation + 4 - deviceRotation) % 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Point getPhysicalPoint(Position position) {
|
public Point getPhysicalPoint(Position position) {
|
||||||
// it hides the field on purpose, to read it with a lock
|
// it hides the field on purpose, to read it with a lock
|
||||||
@SuppressWarnings("checkstyle:HiddenField")
|
@SuppressWarnings("checkstyle:HiddenField")
|
||||||
ScreenInfo screenInfo = getScreenInfo(); // read with synchronization
|
ScreenInfo screenInfo = getScreenInfo(); // read with synchronization
|
||||||
Size videoSize = screenInfo.getVideoSize();
|
|
||||||
|
|
||||||
int deviceRotation = screenInfo.getDeviceRotation();
|
// ignore the locked video orientation, the events will apply in coordinates considered in the physical device orientation
|
||||||
int reverseVideoRotation = getReverseVideoRotation(deviceRotation);
|
Size unlockedVideoSize = screenInfo.getUnlockedVideoSize();
|
||||||
|
|
||||||
|
int reverseVideoRotation = screenInfo.getReverseVideoRotation();
|
||||||
// reverse the video rotation to apply the events
|
// reverse the video rotation to apply the events
|
||||||
Position devicePosition = position.rotate(reverseVideoRotation);
|
Position devicePosition = position.rotate(reverseVideoRotation);
|
||||||
|
|
||||||
Size clientVideoSize = devicePosition.getScreenSize();
|
Size clientVideoSize = devicePosition.getScreenSize();
|
||||||
if (!videoSize.equals(clientVideoSize)) {
|
if (!unlockedVideoSize.equals(clientVideoSize)) {
|
||||||
// The client sends a click relative to a video with wrong dimensions,
|
// The client sends a click relative to a video with wrong dimensions,
|
||||||
// the device may have been rotated since the event was generated, so ignore the event
|
// the device may have been rotated since the event was generated, so ignore the event
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
Rect contentRect = screenInfo.getContentRect();
|
Rect contentRect = screenInfo.getContentRect();
|
||||||
Point point = devicePosition.getPoint();
|
Point point = devicePosition.getPoint();
|
||||||
int convertedX = contentRect.left + point.getX() * contentRect.width() / videoSize.getWidth();
|
int convertedX = contentRect.left + point.getX() * contentRect.width() / unlockedVideoSize.getWidth();
|
||||||
int convertedY = contentRect.top + point.getY() * contentRect.height() / videoSize.getHeight();
|
int convertedY = contentRect.top + point.getY() * contentRect.height() / unlockedVideoSize.getHeight();
|
||||||
return new Point(convertedX, convertedY);
|
return new Point(convertedX, convertedY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -66,12 +66,15 @@ public class ScreenEncoder implements Device.RotationListener {
|
|||||||
IBinder display = createDisplay();
|
IBinder display = createDisplay();
|
||||||
ScreenInfo screenInfo = device.getScreenInfo();
|
ScreenInfo screenInfo = device.getScreenInfo();
|
||||||
Rect contentRect = screenInfo.getContentRect();
|
Rect contentRect = screenInfo.getContentRect();
|
||||||
|
// include the locked video orientation
|
||||||
Rect videoRect = screenInfo.getVideoSize().toRect();
|
Rect videoRect = screenInfo.getVideoSize().toRect();
|
||||||
int videoRotation = device.getVideoRotation(screenInfo.getDeviceRotation());
|
// does not include the locked video orientation
|
||||||
setSize(format, videoRotation, videoRect.width(), videoRect.height());
|
Rect unlockedVideoRect = screenInfo.getUnlockedVideoSize().toRect();
|
||||||
|
int videoRotation = screenInfo.getVideoRotation();
|
||||||
|
setSize(format, videoRect.width(), videoRect.height());
|
||||||
configure(codec, format);
|
configure(codec, format);
|
||||||
Surface surface = codec.createInputSurface();
|
Surface surface = codec.createInputSurface();
|
||||||
setDisplaySurface(display, surface, videoRotation, contentRect, videoRect);
|
setDisplaySurface(display, surface, videoRotation, contentRect, unlockedVideoRect);
|
||||||
codec.start();
|
codec.start();
|
||||||
try {
|
try {
|
||||||
alive = encode(codec, fd);
|
alive = encode(codec, fd);
|
||||||
@@ -170,14 +173,9 @@ public class ScreenEncoder implements Device.RotationListener {
|
|||||||
codec.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
|
codec.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void setSize(MediaFormat format, int orientation, int width, int height) {
|
private static void setSize(MediaFormat format, int width, int height) {
|
||||||
if (orientation % 2 == 0) {
|
format.setInteger(MediaFormat.KEY_WIDTH, width);
|
||||||
format.setInteger(MediaFormat.KEY_WIDTH, width);
|
format.setInteger(MediaFormat.KEY_HEIGHT, height);
|
||||||
format.setInteger(MediaFormat.KEY_HEIGHT, height);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
format.setInteger(MediaFormat.KEY_WIDTH, height);
|
|
||||||
format.setInteger(MediaFormat.KEY_HEIGHT, width);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void setDisplaySurface(IBinder display, Surface surface, int orientation, Rect deviceRect, Rect displayRect) {
|
private static void setDisplaySurface(IBinder display, Surface surface, int orientation, Rect deviceRect, Rect displayRect) {
|
||||||
|
|||||||
@@ -9,27 +9,53 @@ public final class ScreenInfo {
|
|||||||
private final Rect contentRect; // device size, possibly cropped
|
private final Rect contentRect; // device size, possibly cropped
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Video size, possibly smaller than the device size, already taking the device rotation and crop into account
|
* Video size, possibly smaller than the device size, already taking the device rotation and crop into account.
|
||||||
|
* <p>
|
||||||
|
* However, it does not include the locked video orientation.
|
||||||
*/
|
*/
|
||||||
private final Size videoSize;
|
private final Size unlockedVideoSize;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Device rotation, related to the natural device orientation (0, 1, 2 or 3)
|
* Device rotation, related to the natural device orientation (0, 1, 2 or 3)
|
||||||
*/
|
*/
|
||||||
private final int deviceRotation;
|
private final int deviceRotation;
|
||||||
|
|
||||||
public ScreenInfo(Rect contentRect, Size videoSize, int deviceRotation) {
|
/**
|
||||||
|
* The locked video orientation (-1: disabled, 0: normal, 1: 90° CCW, 2: 180°, 3: 90° CW)
|
||||||
|
*/
|
||||||
|
private final int lockedVideoOrientation;
|
||||||
|
|
||||||
|
public ScreenInfo(Rect contentRect, Size unlockedVideoSize, int deviceRotation, int lockedVideoOrientation) {
|
||||||
this.contentRect = contentRect;
|
this.contentRect = contentRect;
|
||||||
this.videoSize = videoSize;
|
this.unlockedVideoSize = unlockedVideoSize;
|
||||||
this.deviceRotation = deviceRotation;
|
this.deviceRotation = deviceRotation;
|
||||||
|
this.lockedVideoOrientation = lockedVideoOrientation;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Rect getContentRect() {
|
public Rect getContentRect() {
|
||||||
return contentRect;
|
return contentRect;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the video size as if locked video orientation was not set.
|
||||||
|
*
|
||||||
|
* @return the unlocked video size
|
||||||
|
*/
|
||||||
|
public Size getUnlockedVideoSize() {
|
||||||
|
return unlockedVideoSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the actual video size if locked video orientation is set.
|
||||||
|
*
|
||||||
|
* @return the actual video size
|
||||||
|
*/
|
||||||
public Size getVideoSize() {
|
public Size getVideoSize() {
|
||||||
return videoSize;
|
if (getVideoRotation() % 2 == 0) {
|
||||||
|
return unlockedVideoSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
return unlockedVideoSize.rotate();
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getDeviceRotation() {
|
public int getDeviceRotation() {
|
||||||
@@ -43,18 +69,18 @@ public final class ScreenInfo {
|
|||||||
// true if changed between portrait and landscape
|
// true if changed between portrait and landscape
|
||||||
boolean orientationChanged = (deviceRotation + newDeviceRotation) % 2 != 0;
|
boolean orientationChanged = (deviceRotation + newDeviceRotation) % 2 != 0;
|
||||||
Rect newContentRect;
|
Rect newContentRect;
|
||||||
Size newVideoSize;
|
Size newUnlockedVideoSize;
|
||||||
if (orientationChanged) {
|
if (orientationChanged) {
|
||||||
newContentRect = flipRect(contentRect);
|
newContentRect = flipRect(contentRect);
|
||||||
newVideoSize = videoSize.rotate();
|
newUnlockedVideoSize = unlockedVideoSize.rotate();
|
||||||
} else {
|
} else {
|
||||||
newContentRect = contentRect;
|
newContentRect = contentRect;
|
||||||
newVideoSize = videoSize;
|
newUnlockedVideoSize = unlockedVideoSize;
|
||||||
}
|
}
|
||||||
return new ScreenInfo(newContentRect, newVideoSize, newDeviceRotation);
|
return new ScreenInfo(newContentRect, newUnlockedVideoSize, newDeviceRotation, lockedVideoOrientation);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ScreenInfo computeScreenInfo(DisplayInfo displayInfo, Rect crop, int maxSize) {
|
public static ScreenInfo computeScreenInfo(DisplayInfo displayInfo, Rect crop, int maxSize, int lockedVideoOrientation) {
|
||||||
int rotation = displayInfo.getRotation();
|
int rotation = displayInfo.getRotation();
|
||||||
Size deviceSize = displayInfo.getSize();
|
Size deviceSize = displayInfo.getSize();
|
||||||
Rect contentRect = new Rect(0, 0, deviceSize.getWidth(), deviceSize.getHeight());
|
Rect contentRect = new Rect(0, 0, deviceSize.getWidth(), deviceSize.getHeight());
|
||||||
@@ -71,7 +97,7 @@ public final class ScreenInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Size videoSize = computeVideoSize(contentRect.width(), contentRect.height(), maxSize);
|
Size videoSize = computeVideoSize(contentRect.width(), contentRect.height(), maxSize);
|
||||||
return new ScreenInfo(contentRect, videoSize, rotation);
|
return new ScreenInfo(contentRect, videoSize, rotation, lockedVideoOrientation);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String formatCrop(Rect rect) {
|
private static String formatCrop(Rect rect) {
|
||||||
@@ -109,4 +135,30 @@ public final class ScreenInfo {
|
|||||||
private static Rect flipRect(Rect crop) {
|
private static Rect flipRect(Rect crop) {
|
||||||
return new Rect(crop.top, crop.left, crop.bottom, crop.right);
|
return new Rect(crop.top, crop.left, crop.bottom, crop.right);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the rotation to apply to the device rotation to get the requested locked video orientation
|
||||||
|
*
|
||||||
|
* @return the rotation offset
|
||||||
|
*/
|
||||||
|
public int getVideoRotation() {
|
||||||
|
if (lockedVideoOrientation == -1) {
|
||||||
|
// no offset
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return (deviceRotation + 4 - lockedVideoOrientation) % 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the rotation to apply to the requested locked video orientation to get the device rotation
|
||||||
|
*
|
||||||
|
* @return the (reverse) rotation offset
|
||||||
|
*/
|
||||||
|
public int getReverseVideoRotation() {
|
||||||
|
if (lockedVideoOrientation == -1) {
|
||||||
|
// no offset
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return (lockedVideoOrientation + 4 - deviceRotation) % 4;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ public final class Server {
|
|||||||
String clientVersion = args[0];
|
String clientVersion = args[0];
|
||||||
if (!clientVersion.equals(BuildConfig.VERSION_NAME)) {
|
if (!clientVersion.equals(BuildConfig.VERSION_NAME)) {
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
"The server version (" + clientVersion + ") does not match the client " + "(" + BuildConfig.VERSION_NAME + ")");
|
"The server version (" + BuildConfig.VERSION_NAME + ") does not match the client " + "(" + clientVersion + ")");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (args.length != 9) {
|
if (args.length != 9) {
|
||||||
|
|||||||
Reference in New Issue
Block a user