Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
30714aba34 | ||
|
|
a973757fd1 | ||
|
|
deea29f52a | ||
|
|
5fa46ad0c7 | ||
|
|
334964c380 | ||
|
|
f7d4b6d0db | ||
|
|
e8a565f9ea | ||
|
|
3c1ed5d86c | ||
|
|
0ba74fbd9a | ||
|
|
29e5af76d4 |
@@ -3,10 +3,11 @@
|
||||
#include <assert.h>
|
||||
#include <getopt.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "recorder.h"
|
||||
#include "scrcpy.h"
|
||||
#include "util/log.h"
|
||||
#include "util/str_util.h"
|
||||
|
||||
@@ -382,10 +383,10 @@ parse_rotation(const char *s, uint8_t *rotation) {
|
||||
static bool
|
||||
parse_window_position(const char *s, int16_t *position) {
|
||||
// special value for "auto"
|
||||
static_assert(WINDOW_POSITION_UNDEFINED == -0x8000, "unexpected value");
|
||||
static_assert(SC_WINDOW_POSITION_UNDEFINED == -0x8000, "unexpected value");
|
||||
|
||||
if (!strcmp(s, "auto")) {
|
||||
*position = WINDOW_POSITION_UNDEFINED;
|
||||
*position = SC_WINDOW_POSITION_UNDEFINED;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -414,7 +415,7 @@ parse_window_dimension(const char *s, uint16_t *dimension) {
|
||||
}
|
||||
|
||||
static bool
|
||||
parse_port_range(const char *s, struct port_range *port_range) {
|
||||
parse_port_range(const char *s, struct sc_port_range *port_range) {
|
||||
long values[2];
|
||||
size_t count = parse_integers_arg(s, 2, values, 0, 0xFFFF, "port");
|
||||
if (!count) {
|
||||
@@ -480,20 +481,20 @@ parse_log_level(const char *s, enum sc_log_level *log_level) {
|
||||
}
|
||||
|
||||
static bool
|
||||
parse_record_format(const char *optarg, enum recorder_format *format) {
|
||||
parse_record_format(const char *optarg, enum sc_record_format *format) {
|
||||
if (!strcmp(optarg, "mp4")) {
|
||||
*format = RECORDER_FORMAT_MP4;
|
||||
*format = SC_RECORD_FORMAT_MP4;
|
||||
return true;
|
||||
}
|
||||
if (!strcmp(optarg, "mkv")) {
|
||||
*format = RECORDER_FORMAT_MKV;
|
||||
*format = SC_RECORD_FORMAT_MKV;
|
||||
return true;
|
||||
}
|
||||
LOGE("Unsupported format: %s (expected mp4 or mkv)", optarg);
|
||||
return false;
|
||||
}
|
||||
|
||||
static enum recorder_format
|
||||
static enum sc_record_format
|
||||
guess_record_format(const char *filename) {
|
||||
size_t len = strlen(filename);
|
||||
if (len < 4) {
|
||||
@@ -501,10 +502,10 @@ guess_record_format(const char *filename) {
|
||||
}
|
||||
const char *ext = &filename[len - 4];
|
||||
if (!strcmp(ext, ".mp4")) {
|
||||
return RECORDER_FORMAT_MP4;
|
||||
return SC_RECORD_FORMAT_MP4;
|
||||
}
|
||||
if (!strcmp(ext, ".mkv")) {
|
||||
return RECORDER_FORMAT_MKV;
|
||||
return SC_RECORD_FORMAT_MKV;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -434,7 +434,7 @@ convert_mouse_motion(const SDL_MouseMotionEvent *from, struct screen *screen,
|
||||
to->inject_touch_event.pointer_id = POINTER_ID_MOUSE;
|
||||
to->inject_touch_event.position.screen_size = screen->frame_size;
|
||||
to->inject_touch_event.position.point =
|
||||
screen_convert_to_frame_coords(screen, from->x, from->y);
|
||||
screen_convert_window_to_frame_coords(screen, from->x, from->y);
|
||||
to->inject_touch_event.pressure = 1.f;
|
||||
to->inject_touch_event.buttons = convert_mouse_buttons(from->state);
|
||||
|
||||
@@ -472,15 +472,15 @@ convert_touch(const SDL_TouchFingerEvent *from, struct screen *screen,
|
||||
to->inject_touch_event.pointer_id = from->fingerId;
|
||||
to->inject_touch_event.position.screen_size = screen->frame_size;
|
||||
|
||||
int ww;
|
||||
int wh;
|
||||
SDL_GL_GetDrawableSize(screen->window, &ww, &wh);
|
||||
int dw;
|
||||
int dh;
|
||||
SDL_GL_GetDrawableSize(screen->window, &dw, &dh);
|
||||
|
||||
// SDL touch event coordinates are normalized in the range [0; 1]
|
||||
int32_t x = from->x * ww;
|
||||
int32_t y = from->y * wh;
|
||||
int32_t x = from->x * dw;
|
||||
int32_t y = from->y * dh;
|
||||
to->inject_touch_event.position.point =
|
||||
screen_convert_to_frame_coords(screen, x, y);
|
||||
screen_convert_drawable_to_frame_coords(screen, x, y);
|
||||
|
||||
to->inject_touch_event.pressure = from->pressure;
|
||||
to->inject_touch_event.buttons = 0;
|
||||
@@ -510,8 +510,9 @@ convert_mouse_button(const SDL_MouseButtonEvent *from, struct screen *screen,
|
||||
to->inject_touch_event.pointer_id = POINTER_ID_MOUSE;
|
||||
to->inject_touch_event.position.screen_size = screen->frame_size;
|
||||
to->inject_touch_event.position.point =
|
||||
screen_convert_to_frame_coords(screen, from->x, from->y);
|
||||
to->inject_touch_event.pressure = 1.f;
|
||||
screen_convert_window_to_frame_coords(screen, from->x, from->y);
|
||||
to->inject_touch_event.pressure =
|
||||
from->type == SDL_MOUSEBUTTONDOWN ? 1.f : 0.f;
|
||||
to->inject_touch_event.buttons =
|
||||
convert_mouse_buttons(SDL_BUTTON(from->button));
|
||||
|
||||
@@ -575,7 +576,8 @@ convert_mouse_wheel(const SDL_MouseWheelEvent *from, struct screen *screen,
|
||||
|
||||
struct position position = {
|
||||
.screen_size = screen->frame_size,
|
||||
.point = screen_convert_to_frame_coords(screen, mouse_x, mouse_y),
|
||||
.point = screen_convert_window_to_frame_coords(screen,
|
||||
mouse_x, mouse_y),
|
||||
};
|
||||
|
||||
to->type = CONTROL_MSG_TYPE_INJECT_SCROLL_EVENT;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "scrcpy.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdbool.h>
|
||||
#include <unistd.h>
|
||||
#include <libavformat/avformat.h>
|
||||
|
||||
@@ -63,7 +63,7 @@ recorder_queue_clear(struct recorder_queue *queue) {
|
||||
bool
|
||||
recorder_init(struct recorder *recorder,
|
||||
const char *filename,
|
||||
enum recorder_format format,
|
||||
enum sc_record_format format,
|
||||
struct size declared_frame_size) {
|
||||
recorder->filename = SDL_strdup(filename);
|
||||
if (!recorder->filename) {
|
||||
@@ -105,10 +105,10 @@ recorder_destroy(struct recorder *recorder) {
|
||||
}
|
||||
|
||||
static const char *
|
||||
recorder_get_format_name(enum recorder_format format) {
|
||||
recorder_get_format_name(enum sc_record_format format) {
|
||||
switch (format) {
|
||||
case RECORDER_FORMAT_MP4: return "mp4";
|
||||
case RECORDER_FORMAT_MKV: return "matroska";
|
||||
case SC_RECORD_FORMAT_MP4: return "mp4";
|
||||
case SC_RECORD_FORMAT_MKV: return "matroska";
|
||||
default: return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,14 +8,9 @@
|
||||
|
||||
#include "config.h"
|
||||
#include "common.h"
|
||||
#include "scrcpy.h"
|
||||
#include "util/queue.h"
|
||||
|
||||
enum recorder_format {
|
||||
RECORDER_FORMAT_AUTO,
|
||||
RECORDER_FORMAT_MP4,
|
||||
RECORDER_FORMAT_MKV,
|
||||
};
|
||||
|
||||
struct record_packet {
|
||||
AVPacket packet;
|
||||
struct record_packet *next;
|
||||
@@ -25,7 +20,7 @@ struct recorder_queue QUEUE(struct record_packet);
|
||||
|
||||
struct recorder {
|
||||
char *filename;
|
||||
enum recorder_format format;
|
||||
enum sc_record_format format;
|
||||
AVFormatContext *ctx;
|
||||
struct size declared_frame_size;
|
||||
bool header_written;
|
||||
@@ -46,7 +41,7 @@ struct recorder {
|
||||
|
||||
bool
|
||||
recorder_init(struct recorder *recorder, const char *filename,
|
||||
enum recorder_format format, struct size declared_frame_size);
|
||||
enum sc_record_format format, struct size declared_frame_size);
|
||||
|
||||
void
|
||||
recorder_destroy(struct recorder *recorder);
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
#include <SDL2/SDL.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
// not needed here, but winsock2.h must never be included AFTER windows.h
|
||||
# include <winsock2.h>
|
||||
# include <windows.h>
|
||||
#endif
|
||||
|
||||
|
||||
@@ -2,13 +2,30 @@
|
||||
#define SCRCPY_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "common.h"
|
||||
#include "input_manager.h"
|
||||
#include "recorder.h"
|
||||
#include "util/log.h"
|
||||
|
||||
enum sc_log_level {
|
||||
SC_LOG_LEVEL_DEBUG,
|
||||
SC_LOG_LEVEL_INFO,
|
||||
SC_LOG_LEVEL_WARN,
|
||||
SC_LOG_LEVEL_ERROR,
|
||||
};
|
||||
|
||||
enum sc_record_format {
|
||||
SC_RECORD_FORMAT_AUTO,
|
||||
SC_RECORD_FORMAT_MP4,
|
||||
SC_RECORD_FORMAT_MKV,
|
||||
};
|
||||
|
||||
struct sc_port_range {
|
||||
uint16_t first;
|
||||
uint16_t last;
|
||||
};
|
||||
|
||||
#define SC_WINDOW_POSITION_UNDEFINED (-0x8000)
|
||||
|
||||
struct scrcpy_options {
|
||||
const char *serial;
|
||||
@@ -19,15 +36,15 @@ struct scrcpy_options {
|
||||
const char *render_driver;
|
||||
const char *codec_options;
|
||||
enum sc_log_level log_level;
|
||||
enum recorder_format record_format;
|
||||
struct port_range port_range;
|
||||
enum sc_record_format record_format;
|
||||
struct sc_port_range port_range;
|
||||
uint16_t max_size;
|
||||
uint32_t bit_rate;
|
||||
uint16_t max_fps;
|
||||
int8_t lock_video_orientation;
|
||||
uint8_t rotation;
|
||||
int16_t window_x; // WINDOW_POSITION_UNDEFINED for "auto"
|
||||
int16_t window_y; // WINDOW_POSITION_UNDEFINED for "auto"
|
||||
int16_t window_x; // SC_WINDOW_POSITION_UNDEFINED for "auto"
|
||||
int16_t window_y; // SC_WINDOW_POSITION_UNDEFINED for "auto"
|
||||
uint16_t window_width;
|
||||
uint16_t window_height;
|
||||
uint16_t display_id;
|
||||
@@ -55,7 +72,7 @@ struct scrcpy_options {
|
||||
.render_driver = NULL, \
|
||||
.codec_options = NULL, \
|
||||
.log_level = SC_LOG_LEVEL_INFO, \
|
||||
.record_format = RECORDER_FORMAT_AUTO, \
|
||||
.record_format = SC_RECORD_FORMAT_AUTO, \
|
||||
.port_range = { \
|
||||
.first = DEFAULT_LOCAL_PORT_RANGE_FIRST, \
|
||||
.last = DEFAULT_LOCAL_PORT_RANGE_LAST, \
|
||||
@@ -65,8 +82,8 @@ struct scrcpy_options {
|
||||
.max_fps = 0, \
|
||||
.lock_video_orientation = DEFAULT_LOCK_VIDEO_ORIENTATION, \
|
||||
.rotation = 0, \
|
||||
.window_x = WINDOW_POSITION_UNDEFINED, \
|
||||
.window_y = WINDOW_POSITION_UNDEFINED, \
|
||||
.window_x = SC_WINDOW_POSITION_UNDEFINED, \
|
||||
.window_y = SC_WINDOW_POSITION_UNDEFINED, \
|
||||
.window_width = 0, \
|
||||
.window_height = 0, \
|
||||
.display_id = 0, \
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "common.h"
|
||||
#include "compat.h"
|
||||
#include "icon.xpm"
|
||||
#include "scrcpy.h"
|
||||
#include "tiny_xpm.h"
|
||||
#include "video_buffer.h"
|
||||
#include "util/lock.h"
|
||||
@@ -257,9 +258,9 @@ screen_init_rendering(struct screen *screen, const char *window_title,
|
||||
window_flags |= SDL_WINDOW_BORDERLESS;
|
||||
}
|
||||
|
||||
int x = window_x != WINDOW_POSITION_UNDEFINED
|
||||
int x = window_x != SC_WINDOW_POSITION_UNDEFINED
|
||||
? window_x : (int) SDL_WINDOWPOS_UNDEFINED;
|
||||
int y = window_y != WINDOW_POSITION_UNDEFINED
|
||||
int y = window_y != SC_WINDOW_POSITION_UNDEFINED
|
||||
? window_y : (int) SDL_WINDOWPOS_UNDEFINED;
|
||||
screen->window = SDL_CreateWindow(window_title, x, y,
|
||||
window_size.width, window_size.height,
|
||||
@@ -579,14 +580,14 @@ screen_handle_window_event(struct screen *screen,
|
||||
}
|
||||
|
||||
struct point
|
||||
screen_convert_to_frame_coords(struct screen *screen, int32_t x, int32_t y) {
|
||||
screen_convert_drawable_to_frame_coords(struct screen *screen,
|
||||
int32_t x, int32_t y) {
|
||||
unsigned rotation = screen->rotation;
|
||||
assert(rotation < 4);
|
||||
|
||||
int32_t w = screen->content_size.width;
|
||||
int32_t h = screen->content_size.height;
|
||||
|
||||
screen_hidpi_scale_coords(screen, &x, &y);
|
||||
|
||||
x = (int64_t) (x - screen->rect.x) * w / screen->rect.w;
|
||||
y = (int64_t) (y - screen->rect.y) * h / screen->rect.h;
|
||||
@@ -615,6 +616,13 @@ screen_convert_to_frame_coords(struct screen *screen, int32_t x, int32_t y) {
|
||||
return result;
|
||||
}
|
||||
|
||||
struct point
|
||||
screen_convert_window_to_frame_coords(struct screen *screen,
|
||||
int32_t x, int32_t y) {
|
||||
screen_hidpi_scale_coords(screen, &x, &y);
|
||||
return screen_convert_drawable_to_frame_coords(screen, x, y);
|
||||
}
|
||||
|
||||
void
|
||||
screen_hidpi_scale_coords(struct screen *screen, int32_t *x, int32_t *y) {
|
||||
// take the HiDPI scaling (dw/ww and dh/wh) into account
|
||||
|
||||
@@ -9,8 +9,6 @@
|
||||
#include "common.h"
|
||||
#include "opengl.h"
|
||||
|
||||
#define WINDOW_POSITION_UNDEFINED (-0x8000)
|
||||
|
||||
struct video_buffer;
|
||||
|
||||
struct screen {
|
||||
@@ -76,7 +74,7 @@ void
|
||||
screen_init(struct screen *screen);
|
||||
|
||||
// initialize screen, create window, renderer and texture (window is hidden)
|
||||
// window_x and window_y accept WINDOW_POSITION_UNDEFINED
|
||||
// window_x and window_y accept SC_WINDOW_POSITION_UNDEFINED
|
||||
bool
|
||||
screen_init_rendering(struct screen *screen, const char *window_title,
|
||||
struct size frame_size, bool always_on_top,
|
||||
@@ -126,7 +124,14 @@ screen_handle_window_event(struct screen *screen, const SDL_WindowEvent *event);
|
||||
// convert point from window coordinates to frame coordinates
|
||||
// x and y are expressed in pixels
|
||||
struct point
|
||||
screen_convert_to_frame_coords(struct screen *screen, int32_t x, int32_t y);
|
||||
screen_convert_window_to_frame_coords(struct screen *screen,
|
||||
int32_t x, int32_t y);
|
||||
|
||||
// convert point from drawable coordinates to frame coordinates
|
||||
// x and y are expressed in pixels
|
||||
struct point
|
||||
screen_convert_drawable_to_frame_coords(struct screen *screen,
|
||||
int32_t x, int32_t y);
|
||||
|
||||
// Convert coordinates from window to drawable.
|
||||
// Events are expressed in window coordinates, but content is expressed in
|
||||
|
||||
@@ -143,7 +143,7 @@ listen_on_port(uint16_t port) {
|
||||
|
||||
static bool
|
||||
enable_tunnel_reverse_any_port(struct server *server,
|
||||
struct port_range port_range) {
|
||||
struct sc_port_range port_range) {
|
||||
uint16_t port = port_range.first;
|
||||
for (;;) {
|
||||
if (!enable_tunnel_reverse(server->serial, port)) {
|
||||
@@ -189,7 +189,7 @@ enable_tunnel_reverse_any_port(struct server *server,
|
||||
|
||||
static bool
|
||||
enable_tunnel_forward_any_port(struct server *server,
|
||||
struct port_range port_range) {
|
||||
struct sc_port_range port_range) {
|
||||
server->tunnel_forward = true;
|
||||
uint16_t port = port_range.first;
|
||||
for (;;) {
|
||||
@@ -217,7 +217,7 @@ enable_tunnel_forward_any_port(struct server *server,
|
||||
}
|
||||
|
||||
static bool
|
||||
enable_tunnel_any_port(struct server *server, struct port_range port_range,
|
||||
enable_tunnel_any_port(struct server *server, struct sc_port_range port_range,
|
||||
bool force_adb_forward) {
|
||||
if (!force_adb_forward) {
|
||||
// Attempt to use "adb reverse"
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "config.h"
|
||||
#include "command.h"
|
||||
#include "common.h"
|
||||
#include "scrcpy.h"
|
||||
#include "util/log.h"
|
||||
#include "util/net.h"
|
||||
|
||||
@@ -20,7 +21,7 @@ struct server {
|
||||
socket_t server_socket; // only used if !tunnel_forward
|
||||
socket_t video_socket;
|
||||
socket_t control_socket;
|
||||
struct port_range port_range;
|
||||
struct sc_port_range port_range;
|
||||
uint16_t local_port; // selected from port_range
|
||||
bool tunnel_enabled;
|
||||
bool tunnel_forward; // use "adb forward" instead of "adb reverse"
|
||||
@@ -47,7 +48,7 @@ struct server_params {
|
||||
enum sc_log_level log_level;
|
||||
const char *crop;
|
||||
const char *codec_options;
|
||||
struct port_range port_range;
|
||||
struct sc_port_range port_range;
|
||||
uint16_t max_size;
|
||||
uint32_t bit_rate;
|
||||
uint16_t max_fps;
|
||||
|
||||
@@ -3,13 +3,6 @@
|
||||
|
||||
#include <SDL2/SDL_log.h>
|
||||
|
||||
enum sc_log_level {
|
||||
SC_LOG_LEVEL_DEBUG,
|
||||
SC_LOG_LEVEL_INFO,
|
||||
SC_LOG_LEVEL_WARN,
|
||||
SC_LOG_LEVEL_ERROR,
|
||||
};
|
||||
|
||||
#define LOGV(...) SDL_LogVerbose(SDL_LOG_CATEGORY_APPLICATION, __VA_ARGS__)
|
||||
#define LOGD(...) SDL_LogDebug(SDL_LOG_CATEGORY_APPLICATION, __VA_ARGS__)
|
||||
#define LOGI(...) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, __VA_ARGS__)
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "cli.h"
|
||||
#include "common.h"
|
||||
@@ -73,7 +74,6 @@ static void test_options(void) {
|
||||
|
||||
const struct scrcpy_options *opts = &args.opts;
|
||||
assert(opts->always_on_top);
|
||||
fprintf(stderr, "%d\n", (int) opts->bit_rate);
|
||||
assert(opts->bit_rate == 5000000);
|
||||
assert(!strcmp(opts->crop, "100:200:300:400"));
|
||||
assert(opts->fullscreen);
|
||||
@@ -84,7 +84,7 @@ static void test_options(void) {
|
||||
assert(opts->port_range.last == 1236);
|
||||
assert(!strcmp(opts->push_target, "/sdcard/Movies"));
|
||||
assert(!strcmp(opts->record_filename, "file"));
|
||||
assert(opts->record_format == RECORDER_FORMAT_MKV);
|
||||
assert(opts->record_format == SC_RECORD_FORMAT_MKV);
|
||||
assert(opts->render_expired_frames);
|
||||
assert(!strcmp(opts->serial, "0123456789abcdef"));
|
||||
assert(opts->show_touches);
|
||||
@@ -119,7 +119,7 @@ static void test_options2(void) {
|
||||
assert(!opts->control);
|
||||
assert(!opts->display);
|
||||
assert(!strcmp(opts->record_filename, "file.mp4"));
|
||||
assert(opts->record_format == RECORDER_FORMAT_MP4);
|
||||
assert(opts->record_format == SC_RECORD_FORMAT_MP4);
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
|
||||
@@ -19,18 +19,19 @@ public final class CleanUp {
|
||||
// not instantiable
|
||||
}
|
||||
|
||||
public static void configure(boolean disableShowTouches, int restoreStayOn) throws IOException {
|
||||
boolean needProcess = disableShowTouches || restoreStayOn != -1;
|
||||
public static void configure(boolean disableShowTouches, int restoreStayOn, boolean restoreNormalPowerMode) throws IOException {
|
||||
boolean needProcess = disableShowTouches || restoreStayOn != -1 || restoreNormalPowerMode;
|
||||
if (needProcess) {
|
||||
startProcess(disableShowTouches, restoreStayOn);
|
||||
startProcess(disableShowTouches, restoreStayOn, restoreNormalPowerMode);
|
||||
} else {
|
||||
// There is no additional clean up to do when scrcpy dies
|
||||
unlinkSelf();
|
||||
}
|
||||
}
|
||||
|
||||
private static void startProcess(boolean disableShowTouches, int restoreStayOn) throws IOException {
|
||||
String[] cmd = {"app_process", "/", CleanUp.class.getName(), String.valueOf(disableShowTouches), String.valueOf(restoreStayOn)};
|
||||
private static void startProcess(boolean disableShowTouches, int restoreStayOn, boolean restoreNormalPowerMode) throws IOException {
|
||||
String[] cmd = {"app_process", "/", CleanUp.class.getName(), String.valueOf(disableShowTouches), String.valueOf(
|
||||
restoreStayOn), String.valueOf(restoreNormalPowerMode)};
|
||||
|
||||
ProcessBuilder builder = new ProcessBuilder(cmd);
|
||||
builder.environment().put("CLASSPATH", SERVER_PATH);
|
||||
@@ -59,6 +60,7 @@ public final class CleanUp {
|
||||
|
||||
boolean disableShowTouches = Boolean.parseBoolean(args[0]);
|
||||
int restoreStayOn = Integer.parseInt(args[1]);
|
||||
boolean restoreNormalPowerMode = Boolean.parseBoolean(args[2]);
|
||||
|
||||
if (disableShowTouches || restoreStayOn != -1) {
|
||||
ServiceManager serviceManager = new ServiceManager();
|
||||
@@ -73,5 +75,10 @@ public final class CleanUp {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (restoreNormalPowerMode) {
|
||||
Ln.i("Restoring normal power mode");
|
||||
Device.setScreenPowerMode(Device.POWER_MODE_NORMAL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -116,7 +116,7 @@ public class Controller {
|
||||
case ControlMessage.TYPE_SET_SCREEN_POWER_MODE:
|
||||
if (device.supportsInputEvents()) {
|
||||
int mode = msg.getAction();
|
||||
boolean setPowerModeOk = device.setScreenPowerMode(mode);
|
||||
boolean setPowerModeOk = Device.setScreenPowerMode(mode);
|
||||
if (setPowerModeOk) {
|
||||
Ln.i("Device screen turned " + (mode == Device.POWER_MODE_OFF ? "off" : "on"));
|
||||
}
|
||||
@@ -166,7 +166,7 @@ public class Controller {
|
||||
|
||||
Point point = device.getPhysicalPoint(position);
|
||||
if (point == null) {
|
||||
// ignore event
|
||||
Ln.w("Ignore touch event, it was generated for a different device size");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.genymobile.scrcpy;
|
||||
|
||||
import com.genymobile.scrcpy.wrappers.ClipboardManager;
|
||||
import com.genymobile.scrcpy.wrappers.ContentProvider;
|
||||
import com.genymobile.scrcpy.wrappers.InputManager;
|
||||
import com.genymobile.scrcpy.wrappers.ServiceManager;
|
||||
@@ -80,23 +81,28 @@ public final class Device {
|
||||
|
||||
if (options.getControl()) {
|
||||
// If control is enabled, synchronize Android clipboard to the computer automatically
|
||||
serviceManager.getClipboardManager().addPrimaryClipChangedListener(new IOnPrimaryClipChangedListener.Stub() {
|
||||
@Override
|
||||
public void dispatchPrimaryClipChanged() {
|
||||
if (isSettingClipboard.get()) {
|
||||
// This is a notification for the change we are currently applying, ignore it
|
||||
return;
|
||||
}
|
||||
synchronized (Device.this) {
|
||||
if (clipboardListener != null) {
|
||||
String text = getClipboardText();
|
||||
if (text != null) {
|
||||
clipboardListener.onClipboardTextChanged(text);
|
||||
ClipboardManager clipboardManager = serviceManager.getClipboardManager();
|
||||
if (clipboardManager != null) {
|
||||
clipboardManager.addPrimaryClipChangedListener(new IOnPrimaryClipChangedListener.Stub() {
|
||||
@Override
|
||||
public void dispatchPrimaryClipChanged() {
|
||||
if (isSettingClipboard.get()) {
|
||||
// This is a notification for the change we are currently applying, ignore it
|
||||
return;
|
||||
}
|
||||
synchronized (Device.this) {
|
||||
if (clipboardListener != null) {
|
||||
String text = getClipboardText();
|
||||
if (text != null) {
|
||||
clipboardListener.onClipboardTextChanged(text);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
} else {
|
||||
Ln.w("No clipboard manager, copy-paste between device and computer will not work");
|
||||
}
|
||||
}
|
||||
|
||||
if ((displayInfoFlags & DisplayInfo.FLAG_SUPPORTS_PROTECTED_BUFFERS) == 0) {
|
||||
@@ -199,7 +205,11 @@ public final class Device {
|
||||
}
|
||||
|
||||
public String getClipboardText() {
|
||||
CharSequence s = serviceManager.getClipboardManager().getText();
|
||||
ClipboardManager clipboardManager = serviceManager.getClipboardManager();
|
||||
if (clipboardManager == null) {
|
||||
return null;
|
||||
}
|
||||
CharSequence s = clipboardManager.getText();
|
||||
if (s == null) {
|
||||
return null;
|
||||
}
|
||||
@@ -207,16 +217,20 @@ public final class Device {
|
||||
}
|
||||
|
||||
public boolean setClipboardText(String text) {
|
||||
ClipboardManager clipboardManager = serviceManager.getClipboardManager();
|
||||
if (clipboardManager == null) {
|
||||
return false;
|
||||
}
|
||||
isSettingClipboard.set(true);
|
||||
boolean ok = serviceManager.getClipboardManager().setText(text);
|
||||
boolean ok = clipboardManager.setText(text);
|
||||
isSettingClipboard.set(false);
|
||||
return ok;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mode one of the {@code SCREEN_POWER_MODE_*} constants
|
||||
* @param mode one of the {@code POWER_MODE_*} constants
|
||||
*/
|
||||
public boolean setScreenPowerMode(int mode) {
|
||||
public static boolean setScreenPowerMode(int mode) {
|
||||
IBinder d = SurfaceControl.getBuiltInDisplay();
|
||||
if (d == null) {
|
||||
Ln.e("Could not get built-in display");
|
||||
|
||||
@@ -49,7 +49,7 @@ public final class Server {
|
||||
}
|
||||
}
|
||||
|
||||
CleanUp.configure(mustDisableShowTouchesOnCleanUp, restoreStayOn);
|
||||
CleanUp.configure(mustDisableShowTouchesOnCleanUp, restoreStayOn, true);
|
||||
|
||||
boolean tunnelForward = options.isTunnelForward();
|
||||
|
||||
|
||||
@@ -77,7 +77,14 @@ public final class ServiceManager {
|
||||
|
||||
public ClipboardManager getClipboardManager() {
|
||||
if (clipboardManager == null) {
|
||||
clipboardManager = new ClipboardManager(getService("clipboard", "android.content.IClipboard"));
|
||||
IInterface clipboard = getService("clipboard", "android.content.IClipboard");
|
||||
if (clipboard == null) {
|
||||
// Some devices have no clipboard manager
|
||||
// <https://github.com/Genymobile/scrcpy/issues/1440>
|
||||
// <https://github.com/Genymobile/scrcpy/issues/1556>
|
||||
return null;
|
||||
}
|
||||
clipboardManager = new ClipboardManager(clipboard);
|
||||
}
|
||||
return clipboardManager;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user