mirror of
https://github.com/Genymobile/scrcpy.git
synced 2026-02-24 15:24:28 +01:00
Compare commits
23 Commits
hover
...
bindings_s
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9989668226 | ||
|
|
6baea57987 | ||
|
|
86b8286217 | ||
|
|
51fee79bf5 | ||
|
|
6808288823 | ||
|
|
0bce4d7f56 | ||
|
|
6d98766cd5 | ||
|
|
487a6b9cf4 | ||
|
|
b50f9eb41d | ||
|
|
46041e0cc0 | ||
|
|
b419eef55e | ||
|
|
a4f8c02502 | ||
|
|
a8871bfad7 | ||
|
|
89df38f641 | ||
|
|
c95e6964c5 | ||
|
|
343f715323 | ||
|
|
f13f00021f | ||
|
|
48c2c03093 | ||
|
|
1e3deabd6c | ||
|
|
576e7552a2 | ||
|
|
c27ab46efb | ||
|
|
b5849db32f | ||
|
|
206809a99a |
@@ -2,7 +2,7 @@
|
||||
source for the project. Do not download releases from random websites, even if
|
||||
their name contains `scrcpy`.**
|
||||
|
||||
# scrcpy (v2.4)
|
||||
# scrcpy (v2.5)
|
||||
|
||||
<img src="app/data/icon.svg" width="128" height="128" alt="scrcpy" align="right" />
|
||||
|
||||
|
||||
@@ -4,10 +4,10 @@ DEPS_DIR=$(dirname ${BASH_SOURCE[0]})
|
||||
cd "$DEPS_DIR"
|
||||
. common
|
||||
|
||||
VERSION=34.0.5
|
||||
VERSION=35.0.0
|
||||
FILENAME=platform-tools_r$VERSION-windows.zip
|
||||
PROJECT_DIR=platform-tools-$VERSION
|
||||
SHA256SUM=3f8320152704377de150418a3c4c9d07d16d80a6c0d0d8f7289c22c499e33571
|
||||
SHA256SUM=7ab78a8f8b305ae4d0de647d99c43599744de61a0838d3a47bda0cdffefee87e
|
||||
|
||||
cd "$SOURCES_DIR"
|
||||
|
||||
|
||||
@@ -4,10 +4,10 @@ DEPS_DIR=$(dirname ${BASH_SOURCE[0]})
|
||||
cd "$DEPS_DIR"
|
||||
. common
|
||||
|
||||
VERSION=6.1.1
|
||||
VERSION=7.0.1
|
||||
FILENAME=ffmpeg-$VERSION.tar.xz
|
||||
PROJECT_DIR=ffmpeg-$VERSION
|
||||
SHA256SUM=8684f4b00f94b85461884c3719382f1261f0d9eb3d59640a1f4ac0873616f968
|
||||
SHA256SUM=bce9eeb0f17ef8982390b1f37711a61b4290dc8c2a0c1a37b5857e85bfb0e4ff
|
||||
|
||||
cd "$SOURCES_DIR"
|
||||
|
||||
@@ -17,7 +17,6 @@ then
|
||||
else
|
||||
get_file "https://ffmpeg.org/releases/$FILENAME" "$FILENAME" "$SHA256SUM"
|
||||
tar xf "$FILENAME" # First level directory is "$PROJECT_DIR"
|
||||
patch -d "$PROJECT_DIR" -p1 < "$PATCHES_DIR"/ffmpeg-6.1-fix-build.patch
|
||||
fi
|
||||
|
||||
mkdir -p "$BUILD_DIR/$PROJECT_DIR"
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
From 03c80197afb324da38c9b70254231e3fdcfa68fc Mon Sep 17 00:00:00 2001
|
||||
From: Romain Vimont <rom@rom1v.com>
|
||||
Date: Sun, 12 Nov 2023 17:58:50 +0100
|
||||
Subject: [PATCH] Fix FFmpeg 6.1 build
|
||||
|
||||
Build failed on tag n6.1 With --enable-decoder=av1 but without
|
||||
--enable-muxer=av1.
|
||||
---
|
||||
libavcodec/Makefile | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/libavcodec/Makefile b/libavcodec/Makefile
|
||||
index 580a8d6b54..aff19b670c 100644
|
||||
--- a/libavcodec/Makefile
|
||||
+++ b/libavcodec/Makefile
|
||||
@@ -249,7 +249,7 @@ OBJS-$(CONFIG_ATRAC3PAL_DECODER) += atrac3plusdec.o atrac3plus.o \
|
||||
OBJS-$(CONFIG_ATRAC9_DECODER) += atrac9dec.o
|
||||
OBJS-$(CONFIG_AURA_DECODER) += cyuv.o
|
||||
OBJS-$(CONFIG_AURA2_DECODER) += aura.o
|
||||
-OBJS-$(CONFIG_AV1_DECODER) += av1dec.o
|
||||
+OBJS-$(CONFIG_AV1_DECODER) += av1dec.o av1_parse.o
|
||||
OBJS-$(CONFIG_AV1_CUVID_DECODER) += cuviddec.o
|
||||
OBJS-$(CONFIG_AV1_MEDIACODEC_DECODER) += mediacodecdec.o
|
||||
OBJS-$(CONFIG_AV1_MEDIACODEC_ENCODER) += mediacodecenc.o
|
||||
--
|
||||
2.42.0
|
||||
|
||||
@@ -4,10 +4,10 @@ DEPS_DIR=$(dirname ${BASH_SOURCE[0]})
|
||||
cd "$DEPS_DIR"
|
||||
. common
|
||||
|
||||
VERSION=2.28.5
|
||||
VERSION=2.30.4
|
||||
FILENAME=SDL-$VERSION.tar.gz
|
||||
PROJECT_DIR=SDL-release-$VERSION
|
||||
SHA256SUM=9f0556e4a24ef5b267010038ad9e9948b62f236d5bcc4b22179f95ef62d84023
|
||||
SHA256SUM=dcc2c8c9c3e9e1a7c8d61d9522f1cba4e9b740feb560dcb15234030984610ee2
|
||||
|
||||
cd "$SOURCES_DIR"
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ BEGIN
|
||||
VALUE "LegalCopyright", "Romain Vimont, Genymobile"
|
||||
VALUE "OriginalFilename", "scrcpy.exe"
|
||||
VALUE "ProductName", "scrcpy"
|
||||
VALUE "ProductVersion", "2.4"
|
||||
VALUE "ProductVersion", "2.5"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
|
||||
10
app/scrcpy.1
10
app/scrcpy.1
@@ -258,10 +258,14 @@ LAlt, LSuper or RSuper toggle the capture mode, to give control of the mouse bac
|
||||
Also see \fB\-\-keyboard\fR.
|
||||
|
||||
.TP
|
||||
.BI "\-\-mouse\-bind " xxxx
|
||||
.BI "\-\-mouse\-bind " xxxx[:xxxx]
|
||||
Configure bindings of secondary clicks.
|
||||
|
||||
The argument must be exactly 4 characters, one for each secondary click (in order: right click, middle click, 4th click, 5th click).
|
||||
The argument must be one or two sequences (separated by ':') of exactly 4 characters, one for each secondary click (in order: right click, middle click, 4th click, 5th click).
|
||||
|
||||
The first sequence defines the primary bindings, used when a mouse button is pressed alone. The second sequence defines the secondary bindings, used when a mouse button is pressed while the Shift key is held.
|
||||
|
||||
If the second sequence of bindings is omitted, then it is the same as the first one.
|
||||
|
||||
Each character must be one of the following:
|
||||
|
||||
@@ -272,7 +276,7 @@ Each character must be one of the following:
|
||||
- 's': trigger shortcut APP_SWITCH
|
||||
- 'n': trigger shortcut "expand notification panel"
|
||||
|
||||
Default is 'bhsn' for SDK mouse, and '++++' for AOA and UHID.
|
||||
Default is 'bhsn:++++' for SDK mouse, and '++++:bhsn' for AOA and UHID.
|
||||
|
||||
|
||||
.TP
|
||||
|
||||
119
app/src/cli.c
119
app/src/cli.c
@@ -493,11 +493,17 @@ static const struct sc_option options[] = {
|
||||
{
|
||||
.longopt_id = OPT_MOUSE_BIND,
|
||||
.longopt = "mouse-bind",
|
||||
.argdesc = "xxxx",
|
||||
.argdesc = "xxxx[:xxxx]",
|
||||
.text = "Configure bindings of secondary clicks.\n"
|
||||
"The argument must be exactly 4 characters, one for each "
|
||||
"secondary click (in order: right click, middle click, 4th "
|
||||
"click, 5th click).\n"
|
||||
"The argument must be one or two sequences (separated by ':') "
|
||||
"of exactly 4 characters, one for each secondary click (in "
|
||||
"order: right click, middle click, 4th click, 5th click).\n"
|
||||
"The first sequence defines the primary bindings, used when a "
|
||||
"mouse button is pressed alone. The second sequence defines "
|
||||
"the secondary bindings, used when a mouse button is pressed "
|
||||
"while the Shift key is held.\n"
|
||||
"If the second sequence of bindings is omitted, then it is the "
|
||||
"same as the first one.\n"
|
||||
"Each character must be one of the following:\n"
|
||||
" '+': forward the click to the device\n"
|
||||
" '-': ignore the click\n"
|
||||
@@ -505,7 +511,8 @@ static const struct sc_option options[] = {
|
||||
" 'h': trigger shortcut HOME\n"
|
||||
" 's': trigger shortcut APP_SWITCH\n"
|
||||
" 'n': trigger shortcut \"expand notification panel\"\n"
|
||||
"Default is 'bhsn' for SDK mouse, and '++++' for AOA and UHID.",
|
||||
"Default is 'bhsn:++++' for SDK mouse, and '++++:bhsn' for AOA "
|
||||
"and UHID.",
|
||||
},
|
||||
{
|
||||
.shortopt = 'n',
|
||||
@@ -2095,24 +2102,46 @@ parse_mouse_binding(char c, enum sc_mouse_binding *b) {
|
||||
}
|
||||
|
||||
static bool
|
||||
parse_mouse_bindings(const char *s, struct sc_mouse_bindings *mb) {
|
||||
if (strlen(s) != 4) {
|
||||
LOGE("Invalid mouse bindings: '%s' (expected exactly 4 characters from "
|
||||
"{'+', '-', 'b', 'h', 's', 'n'})", s);
|
||||
parse_mouse_binding_set(const char *s, struct sc_mouse_binding_set *mbs) {
|
||||
assert(strlen(s) >= 4);
|
||||
|
||||
if (!parse_mouse_binding(s[0], &mbs->right_click)) {
|
||||
return false;
|
||||
}
|
||||
if (!parse_mouse_binding(s[1], &mbs->middle_click)) {
|
||||
return false;
|
||||
}
|
||||
if (!parse_mouse_binding(s[2], &mbs->click4)) {
|
||||
return false;
|
||||
}
|
||||
if (!parse_mouse_binding(s[3], &mbs->click5)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!parse_mouse_binding(s[0], &mb->right_click)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
parse_mouse_bindings(const char *s, struct sc_mouse_bindings *mb) {
|
||||
size_t len = strlen(s);
|
||||
// either "xxxx" or "xxxx:xxxx"
|
||||
if (len != 4 && (len != 9 || s[4] != ':')) {
|
||||
LOGE("Invalid mouse bindings: '%s' (expected 'xxxx' or 'xxxx:xxxx', "
|
||||
"with each 'x' being in {'+', '-', 'b', 'h', 's', 'n'})", s);
|
||||
return false;
|
||||
}
|
||||
if (!parse_mouse_binding(s[1], &mb->middle_click)) {
|
||||
|
||||
if (!parse_mouse_binding_set(s, &mb->pri)) {
|
||||
return false;
|
||||
}
|
||||
if (!parse_mouse_binding(s[2], &mb->click4)) {
|
||||
return false;
|
||||
}
|
||||
if (!parse_mouse_binding(s[3], &mb->click5)) {
|
||||
return false;
|
||||
|
||||
if (len == 9) {
|
||||
if (!parse_mouse_binding_set(s + 5, &mb->sec)) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
// use the same bindings for Shift+click
|
||||
mb->sec = mb->pri;
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -2408,10 +2437,18 @@ parse_args_with_getopt(struct scrcpy_cli_args *args, int argc, char *argv[],
|
||||
LOGW("--forward-all-clicks is deprecated, "
|
||||
"use --mouse-bind=++++ instead.");
|
||||
opts->mouse_bindings = (struct sc_mouse_bindings) {
|
||||
.right_click = SC_MOUSE_BINDING_CLICK,
|
||||
.middle_click = SC_MOUSE_BINDING_CLICK,
|
||||
.click4 = SC_MOUSE_BINDING_CLICK,
|
||||
.click5 = SC_MOUSE_BINDING_CLICK,
|
||||
.pri = {
|
||||
.right_click = SC_MOUSE_BINDING_CLICK,
|
||||
.middle_click = SC_MOUSE_BINDING_CLICK,
|
||||
.click4 = SC_MOUSE_BINDING_CLICK,
|
||||
.click5 = SC_MOUSE_BINDING_CLICK,
|
||||
},
|
||||
.sec = {
|
||||
.right_click = SC_MOUSE_BINDING_CLICK,
|
||||
.middle_click = SC_MOUSE_BINDING_CLICK,
|
||||
.click4 = SC_MOUSE_BINDING_CLICK,
|
||||
.click5 = SC_MOUSE_BINDING_CLICK,
|
||||
},
|
||||
};
|
||||
break;
|
||||
case OPT_LEGACY_PASTE:
|
||||
@@ -2701,26 +2738,36 @@ parse_args_with_getopt(struct scrcpy_cli_args *args, int argc, char *argv[],
|
||||
}
|
||||
|
||||
// If mouse bindings are not explictly set, configure default bindings
|
||||
if (opts->mouse_bindings.right_click == SC_MOUSE_BINDING_AUTO) {
|
||||
assert(opts->mouse_bindings.middle_click == SC_MOUSE_BINDING_AUTO);
|
||||
assert(opts->mouse_bindings.click4 == SC_MOUSE_BINDING_AUTO);
|
||||
assert(opts->mouse_bindings.click5 == SC_MOUSE_BINDING_AUTO);
|
||||
if (opts->mouse_bindings.pri.right_click == SC_MOUSE_BINDING_AUTO) {
|
||||
assert(opts->mouse_bindings.pri.middle_click == SC_MOUSE_BINDING_AUTO);
|
||||
assert(opts->mouse_bindings.pri.click4 == SC_MOUSE_BINDING_AUTO);
|
||||
assert(opts->mouse_bindings.pri.click5 == SC_MOUSE_BINDING_AUTO);
|
||||
assert(opts->mouse_bindings.sec.right_click == SC_MOUSE_BINDING_AUTO);
|
||||
assert(opts->mouse_bindings.sec.middle_click == SC_MOUSE_BINDING_AUTO);
|
||||
assert(opts->mouse_bindings.sec.click4 == SC_MOUSE_BINDING_AUTO);
|
||||
assert(opts->mouse_bindings.sec.click5 == SC_MOUSE_BINDING_AUTO);
|
||||
|
||||
static struct sc_mouse_binding_set default_shortcuts = {
|
||||
.right_click = SC_MOUSE_BINDING_BACK,
|
||||
.middle_click = SC_MOUSE_BINDING_HOME,
|
||||
.click4 = SC_MOUSE_BINDING_APP_SWITCH,
|
||||
.click5 = SC_MOUSE_BINDING_EXPAND_NOTIFICATION_PANEL,
|
||||
};
|
||||
|
||||
static struct sc_mouse_binding_set forward = {
|
||||
.right_click = SC_MOUSE_BINDING_CLICK,
|
||||
.middle_click = SC_MOUSE_BINDING_CLICK,
|
||||
.click4 = SC_MOUSE_BINDING_CLICK,
|
||||
.click5 = SC_MOUSE_BINDING_CLICK,
|
||||
};
|
||||
|
||||
// By default, forward all clicks only for UHID and AOA
|
||||
if (opts->mouse_input_mode == SC_MOUSE_INPUT_MODE_SDK) {
|
||||
opts->mouse_bindings = (struct sc_mouse_bindings) {
|
||||
.right_click = SC_MOUSE_BINDING_BACK,
|
||||
.middle_click = SC_MOUSE_BINDING_HOME,
|
||||
.click4 = SC_MOUSE_BINDING_APP_SWITCH,
|
||||
.click5 = SC_MOUSE_BINDING_EXPAND_NOTIFICATION_PANEL,
|
||||
};
|
||||
opts->mouse_bindings.pri = default_shortcuts;
|
||||
opts->mouse_bindings.sec = forward;
|
||||
} else {
|
||||
opts->mouse_bindings = (struct sc_mouse_bindings) {
|
||||
.right_click = SC_MOUSE_BINDING_CLICK,
|
||||
.middle_click = SC_MOUSE_BINDING_CLICK,
|
||||
.click4 = SC_MOUSE_BINDING_CLICK,
|
||||
.click5 = SC_MOUSE_BINDING_CLICK,
|
||||
};
|
||||
opts->mouse_bindings.pri = forward;
|
||||
opts->mouse_bindings.sec = default_shortcuts;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -64,13 +64,11 @@ static const char *const copy_key_labels[] = {
|
||||
static inline const char *
|
||||
get_well_known_pointer_id_name(uint64_t pointer_id) {
|
||||
switch (pointer_id) {
|
||||
case POINTER_ID_MOUSE:
|
||||
case SC_POINTER_ID_MOUSE:
|
||||
return "mouse";
|
||||
case POINTER_ID_GENERIC_FINGER:
|
||||
case SC_POINTER_ID_GENERIC_FINGER:
|
||||
return "finger";
|
||||
case POINTER_ID_VIRTUAL_MOUSE:
|
||||
return "vmouse";
|
||||
case POINTER_ID_VIRTUAL_FINGER:
|
||||
case SC_POINTER_ID_VIRTUAL_FINGER:
|
||||
return "vfinger";
|
||||
default:
|
||||
return NULL;
|
||||
|
||||
@@ -18,12 +18,11 @@
|
||||
// type: 1 byte; sequence: 8 bytes; paste flag: 1 byte; length: 4 bytes
|
||||
#define SC_CONTROL_MSG_CLIPBOARD_TEXT_MAX_LENGTH (SC_CONTROL_MSG_MAX_SIZE - 14)
|
||||
|
||||
#define POINTER_ID_MOUSE UINT64_C(-1)
|
||||
#define POINTER_ID_GENERIC_FINGER UINT64_C(-2)
|
||||
#define SC_POINTER_ID_MOUSE UINT64_C(-1)
|
||||
#define SC_POINTER_ID_GENERIC_FINGER UINT64_C(-2)
|
||||
|
||||
// Used for injecting an additional virtual pointer for pinch-to-zoom
|
||||
#define POINTER_ID_VIRTUAL_MOUSE UINT64_C(-3)
|
||||
#define POINTER_ID_VIRTUAL_FINGER UINT64_C(-4)
|
||||
#define SC_POINTER_ID_VIRTUAL_FINGER UINT64_C(-3)
|
||||
|
||||
enum sc_control_msg_type {
|
||||
SC_CONTROL_MSG_TYPE_INJECT_KEYCODE,
|
||||
|
||||
@@ -7,12 +7,13 @@
|
||||
#define SC_CONTROL_MSG_QUEUE_MAX 64
|
||||
|
||||
static void
|
||||
sc_controller_receiver_on_error(struct sc_receiver *receiver, void *userdata) {
|
||||
sc_controller_receiver_on_ended(struct sc_receiver *receiver, bool error,
|
||||
void *userdata) {
|
||||
(void) receiver;
|
||||
|
||||
struct sc_controller *controller = userdata;
|
||||
// Forward the event to the controller listener
|
||||
controller->cbs->on_error(controller, controller->cbs_userdata);
|
||||
controller->cbs->on_ended(controller, error, controller->cbs_userdata);
|
||||
}
|
||||
|
||||
bool
|
||||
@@ -27,7 +28,7 @@ sc_controller_init(struct sc_controller *controller, sc_socket control_socket,
|
||||
}
|
||||
|
||||
static const struct sc_receiver_callbacks receiver_cbs = {
|
||||
.on_error = sc_controller_receiver_on_error,
|
||||
.on_ended = sc_controller_receiver_on_ended,
|
||||
};
|
||||
|
||||
ok = sc_receiver_init(&controller->receiver, control_socket, &receiver_cbs,
|
||||
@@ -55,7 +56,7 @@ sc_controller_init(struct sc_controller *controller, sc_socket control_socket,
|
||||
controller->control_socket = control_socket;
|
||||
controller->stopped = false;
|
||||
|
||||
assert(cbs && cbs->on_error);
|
||||
assert(cbs && cbs->on_ended);
|
||||
controller->cbs = cbs;
|
||||
controller->cbs_userdata = cbs_userdata;
|
||||
|
||||
@@ -110,21 +111,30 @@ sc_controller_push_msg(struct sc_controller *controller,
|
||||
|
||||
static bool
|
||||
process_msg(struct sc_controller *controller,
|
||||
const struct sc_control_msg *msg) {
|
||||
const struct sc_control_msg *msg, bool *eos) {
|
||||
static uint8_t serialized_msg[SC_CONTROL_MSG_MAX_SIZE];
|
||||
size_t length = sc_control_msg_serialize(msg, serialized_msg);
|
||||
if (!length) {
|
||||
*eos = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
ssize_t w =
|
||||
net_send_all(controller->control_socket, serialized_msg, length);
|
||||
return (size_t) w == length;
|
||||
if ((size_t) w != length) {
|
||||
*eos = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int
|
||||
run_controller(void *data) {
|
||||
struct sc_controller *controller = data;
|
||||
|
||||
bool error = false;
|
||||
|
||||
for (;;) {
|
||||
sc_mutex_lock(&controller->mutex);
|
||||
while (!controller->stopped
|
||||
@@ -134,6 +144,7 @@ run_controller(void *data) {
|
||||
if (controller->stopped) {
|
||||
// stop immediately, do not process further msgs
|
||||
sc_mutex_unlock(&controller->mutex);
|
||||
LOGD("Controller stopped");
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -141,20 +152,21 @@ run_controller(void *data) {
|
||||
struct sc_control_msg msg = sc_vecdeque_pop(&controller->queue);
|
||||
sc_mutex_unlock(&controller->mutex);
|
||||
|
||||
bool ok = process_msg(controller, &msg);
|
||||
bool eos;
|
||||
bool ok = process_msg(controller, &msg, &eos);
|
||||
sc_control_msg_destroy(&msg);
|
||||
if (!ok) {
|
||||
LOGD("Could not write msg to socket");
|
||||
goto error;
|
||||
if (eos) {
|
||||
LOGD("Controller stopped (socket closed)");
|
||||
} // else error already logged
|
||||
error = !eos;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
controller->cbs->on_ended(controller, error, controller->cbs_userdata);
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
controller->cbs->on_error(controller, controller->cbs_userdata);
|
||||
|
||||
return 1; // ignored
|
||||
}
|
||||
|
||||
bool
|
||||
|
||||
@@ -28,7 +28,8 @@ struct sc_controller {
|
||||
};
|
||||
|
||||
struct sc_controller_callbacks {
|
||||
void (*on_error)(struct sc_controller *controller, void *userdata);
|
||||
void (*on_ended)(struct sc_controller *controller, bool error,
|
||||
void *userdata);
|
||||
};
|
||||
|
||||
bool
|
||||
|
||||
@@ -278,7 +278,6 @@ run_demuxer(void *data) {
|
||||
finally_close_sinks:
|
||||
sc_packet_source_sinks_close(&demuxer->packet_source);
|
||||
finally_free_context:
|
||||
// This also calls avcodec_close() internally
|
||||
avcodec_free_context(&codec_ctx);
|
||||
end:
|
||||
demuxer->cbs->on_ended(demuxer, status, demuxer->cbs_userdata);
|
||||
|
||||
@@ -43,6 +43,10 @@ sc_display_init(struct sc_display *display, SDL_Window *window,
|
||||
|
||||
display->mipmaps = false;
|
||||
|
||||
#ifdef SC_DISPLAY_FORCE_OPENGL_CORE_PROFILE
|
||||
display->gl_context = NULL;
|
||||
#endif
|
||||
|
||||
// starts with "opengl"
|
||||
bool use_opengl = renderer_name && !strncmp(renderer_name, "opengl", 6);
|
||||
if (use_opengl) {
|
||||
|
||||
@@ -117,21 +117,21 @@ decode_image(const char *path) {
|
||||
AVFrame *frame = av_frame_alloc();
|
||||
if (!frame) {
|
||||
LOG_OOM();
|
||||
goto close_codec;
|
||||
goto free_codec_ctx;
|
||||
}
|
||||
|
||||
AVPacket *packet = av_packet_alloc();
|
||||
if (!packet) {
|
||||
LOG_OOM();
|
||||
av_frame_free(&frame);
|
||||
goto close_codec;
|
||||
goto free_codec_ctx;
|
||||
}
|
||||
|
||||
if (av_read_frame(ctx, packet) < 0) {
|
||||
LOGE("Could not read frame");
|
||||
av_packet_free(&packet);
|
||||
av_frame_free(&frame);
|
||||
goto close_codec;
|
||||
goto free_codec_ctx;
|
||||
}
|
||||
|
||||
int ret;
|
||||
@@ -139,22 +139,20 @@ decode_image(const char *path) {
|
||||
LOGE("Could not send icon packet: %d", ret);
|
||||
av_packet_free(&packet);
|
||||
av_frame_free(&frame);
|
||||
goto close_codec;
|
||||
goto free_codec_ctx;
|
||||
}
|
||||
|
||||
if ((ret = avcodec_receive_frame(codec_ctx, frame)) != 0) {
|
||||
LOGE("Could not receive icon frame: %d", ret);
|
||||
av_packet_free(&packet);
|
||||
av_frame_free(&frame);
|
||||
goto close_codec;
|
||||
goto free_codec_ctx;
|
||||
}
|
||||
|
||||
av_packet_free(&packet);
|
||||
|
||||
result = frame;
|
||||
|
||||
close_codec:
|
||||
avcodec_close(codec_ctx);
|
||||
free_codec_ctx:
|
||||
avcodec_free_context(&codec_ctx);
|
||||
close_input:
|
||||
|
||||
@@ -437,25 +437,11 @@ sc_mouse_button_from_sdl(uint8_t button) {
|
||||
}
|
||||
|
||||
static inline uint8_t
|
||||
sc_mouse_buttons_state_from_sdl(uint32_t buttons_state,
|
||||
const struct sc_mouse_bindings *mb) {
|
||||
sc_mouse_buttons_state_from_sdl(uint32_t buttons_state) {
|
||||
assert(buttons_state < 0x100); // fits in uint8_t
|
||||
|
||||
uint8_t mask = SC_MOUSE_BUTTON_LEFT;
|
||||
if (!mb || mb->right_click == SC_MOUSE_BINDING_CLICK) {
|
||||
mask |= SC_MOUSE_BUTTON_RIGHT;
|
||||
}
|
||||
if (!mb || mb->middle_click == SC_MOUSE_BINDING_CLICK) {
|
||||
mask |= SC_MOUSE_BUTTON_MIDDLE;
|
||||
}
|
||||
if (!mb || mb->click4 == SC_MOUSE_BINDING_CLICK) {
|
||||
mask |= SC_MOUSE_BUTTON_X1;
|
||||
}
|
||||
if (!mb || mb->click5 == SC_MOUSE_BINDING_CLICK) {
|
||||
mask |= SC_MOUSE_BUTTON_X2;
|
||||
}
|
||||
|
||||
return buttons_state & mask;
|
||||
// SC_MOUSE_BUTTON_* constants are initialized from SDL_BUTTON(index)
|
||||
return buttons_state;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -52,14 +52,6 @@ is_shortcut_key(struct sc_input_manager *im, SDL_Keycode keycode) {
|
||||
|| (im->sdl_shortcut_mods & KMOD_RGUI && keycode == SDLK_RGUI);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
mouse_bindings_has_secondary_click(const struct sc_mouse_bindings *mb) {
|
||||
return mb->right_click == SC_MOUSE_BINDING_CLICK
|
||||
|| mb->middle_click == SC_MOUSE_BINDING_CLICK
|
||||
|| mb->click4 == SC_MOUSE_BINDING_CLICK
|
||||
|| mb->click5 == SC_MOUSE_BINDING_CLICK;
|
||||
}
|
||||
|
||||
void
|
||||
sc_input_manager_init(struct sc_input_manager *im,
|
||||
const struct sc_input_manager_params *params) {
|
||||
@@ -76,8 +68,6 @@ sc_input_manager_init(struct sc_input_manager *im,
|
||||
im->mp = params->mp;
|
||||
|
||||
im->mouse_bindings = params->mouse_bindings;
|
||||
im->has_secondary_click =
|
||||
mouse_bindings_has_secondary_click(&im->mouse_bindings);
|
||||
im->legacy_paste = params->legacy_paste;
|
||||
im->clipboard_autosync = params->clipboard_autosync;
|
||||
|
||||
@@ -87,6 +77,8 @@ sc_input_manager_init(struct sc_input_manager *im,
|
||||
im->vfinger_invert_x = false;
|
||||
im->vfinger_invert_y = false;
|
||||
|
||||
im->mouse_buttons_state = 0;
|
||||
|
||||
im->last_keycode = SDLK_UNKNOWN;
|
||||
im->last_mod = 0;
|
||||
im->key_repeat = 0;
|
||||
@@ -375,9 +367,7 @@ simulate_virtual_finger(struct sc_input_manager *im,
|
||||
msg.inject_touch_event.action = action;
|
||||
msg.inject_touch_event.position.screen_size = im->screen->frame_size;
|
||||
msg.inject_touch_event.position.point = point;
|
||||
msg.inject_touch_event.pointer_id =
|
||||
im->has_secondary_click ? POINTER_ID_VIRTUAL_MOUSE
|
||||
: POINTER_ID_VIRTUAL_FINGER;
|
||||
msg.inject_touch_event.pointer_id = SC_POINTER_ID_VIRTUAL_FINGER;
|
||||
msg.inject_touch_event.pressure = up ? 0.0f : 1.0f;
|
||||
msg.inject_touch_event.action_button = 0;
|
||||
msg.inject_touch_event.buttons = 0;
|
||||
@@ -662,12 +652,11 @@ sc_input_manager_process_mouse_motion(struct sc_input_manager *im,
|
||||
|
||||
struct sc_mouse_motion_event evt = {
|
||||
.position = sc_input_manager_get_position(im, event->x, event->y),
|
||||
.pointer_id = im->has_secondary_click ? POINTER_ID_MOUSE
|
||||
: POINTER_ID_GENERIC_FINGER,
|
||||
.pointer_id = im->vfinger_down ? SC_POINTER_ID_GENERIC_FINGER
|
||||
: SC_POINTER_ID_MOUSE,
|
||||
.xrel = event->xrel,
|
||||
.yrel = event->yrel,
|
||||
.buttons_state =
|
||||
sc_mouse_buttons_state_from_sdl(event->state, &im->mouse_bindings),
|
||||
.buttons_state = im->mouse_buttons_state,
|
||||
};
|
||||
|
||||
assert(im->mp->ops->process_mouse_motion);
|
||||
@@ -719,7 +708,7 @@ sc_input_manager_process_touch(struct sc_input_manager *im,
|
||||
}
|
||||
|
||||
static enum sc_mouse_binding
|
||||
sc_input_manager_get_binding(const struct sc_mouse_bindings *bindings,
|
||||
sc_input_manager_get_binding(const struct sc_mouse_binding_set *bindings,
|
||||
uint8_t sdl_button) {
|
||||
switch (sdl_button) {
|
||||
case SDL_BUTTON_LEFT:
|
||||
@@ -748,11 +737,25 @@ sc_input_manager_process_mouse_button(struct sc_input_manager *im,
|
||||
bool control = im->controller;
|
||||
bool paused = im->screen->paused;
|
||||
bool down = event->type == SDL_MOUSEBUTTONDOWN;
|
||||
|
||||
enum sc_mouse_button button = sc_mouse_button_from_sdl(event->button);
|
||||
if (!down) {
|
||||
// Mark the button as released
|
||||
im->mouse_buttons_state &= ~button;
|
||||
}
|
||||
|
||||
SDL_Keymod keymod = SDL_GetModState();
|
||||
bool ctrl_pressed = keymod & KMOD_CTRL;
|
||||
bool shift_pressed = keymod & KMOD_SHIFT;
|
||||
|
||||
if (control && !paused) {
|
||||
enum sc_action action = down ? SC_ACTION_DOWN : SC_ACTION_UP;
|
||||
|
||||
struct sc_mouse_binding_set *bindings = !shift_pressed
|
||||
? &im->mouse_bindings.pri
|
||||
: &im->mouse_bindings.sec;
|
||||
enum sc_mouse_binding binding =
|
||||
sc_input_manager_get_binding(&im->mouse_bindings, event->button);
|
||||
sc_input_manager_get_binding(bindings, event->button);
|
||||
assert(binding != SC_MOUSE_BINDING_AUTO);
|
||||
switch (binding) {
|
||||
case SC_MOUSE_BINDING_DISABLED:
|
||||
@@ -811,16 +814,23 @@ sc_input_manager_process_mouse_button(struct sc_input_manager *im,
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t sdl_buttons_state = SDL_GetMouseState(NULL, NULL);
|
||||
if (down) {
|
||||
// Mark the button as pressed
|
||||
im->mouse_buttons_state |= button;
|
||||
}
|
||||
|
||||
bool change_vfinger = event->button == SDL_BUTTON_LEFT &&
|
||||
((down && !im->vfinger_down && (ctrl_pressed ^ shift_pressed)) ||
|
||||
(!down && im->vfinger_down));
|
||||
bool use_finger = im->vfinger_down || change_vfinger;
|
||||
|
||||
struct sc_mouse_click_event evt = {
|
||||
.position = sc_input_manager_get_position(im, event->x, event->y),
|
||||
.action = sc_action_from_sdl_mousebutton_type(event->type),
|
||||
.button = sc_mouse_button_from_sdl(event->button),
|
||||
.pointer_id = im->has_secondary_click ? POINTER_ID_MOUSE
|
||||
: POINTER_ID_GENERIC_FINGER,
|
||||
.buttons_state = sc_mouse_buttons_state_from_sdl(sdl_buttons_state,
|
||||
&im->mouse_bindings),
|
||||
.pointer_id = use_finger ? SC_POINTER_ID_GENERIC_FINGER
|
||||
: SC_POINTER_ID_MOUSE,
|
||||
.buttons_state = im->mouse_buttons_state,
|
||||
};
|
||||
|
||||
assert(im->mp->ops->process_mouse_click);
|
||||
@@ -846,14 +856,7 @@ sc_input_manager_process_mouse_button(struct sc_input_manager *im,
|
||||
// can be used instead of Ctrl. The "virtual finger" has a position
|
||||
// inverted with respect to the vertical axis of symmetry in the middle of
|
||||
// the screen.
|
||||
const SDL_Keymod keymod = SDL_GetModState();
|
||||
const bool ctrl_pressed = keymod & KMOD_CTRL;
|
||||
const bool shift_pressed = keymod & KMOD_SHIFT;
|
||||
if (event->button == SDL_BUTTON_LEFT &&
|
||||
((down && !im->vfinger_down &&
|
||||
((ctrl_pressed && !shift_pressed) ||
|
||||
(!ctrl_pressed && shift_pressed))) ||
|
||||
(!down && im->vfinger_down))) {
|
||||
if (change_vfinger) {
|
||||
struct sc_point mouse =
|
||||
sc_screen_convert_window_to_frame_coords(im->screen, event->x,
|
||||
event->y);
|
||||
@@ -886,6 +889,7 @@ sc_input_manager_process_mouse_wheel(struct sc_input_manager *im,
|
||||
int mouse_x;
|
||||
int mouse_y;
|
||||
uint32_t buttons = SDL_GetMouseState(&mouse_x, &mouse_y);
|
||||
(void) buttons; // Actual buttons are tracked manually to ignore shortcuts
|
||||
|
||||
struct sc_mouse_scroll_event evt = {
|
||||
.position = sc_input_manager_get_position(im, mouse_x, mouse_y),
|
||||
@@ -896,8 +900,7 @@ sc_input_manager_process_mouse_wheel(struct sc_input_manager *im,
|
||||
.hscroll = CLAMP(event->x, -1, 1),
|
||||
.vscroll = CLAMP(event->y, -1, 1),
|
||||
#endif
|
||||
.buttons_state = sc_mouse_buttons_state_from_sdl(buttons,
|
||||
&im->mouse_bindings),
|
||||
.buttons_state = im->mouse_buttons_state,
|
||||
};
|
||||
|
||||
im->mp->ops->process_mouse_scroll(im->mp, &evt);
|
||||
|
||||
@@ -23,7 +23,6 @@ struct sc_input_manager {
|
||||
struct sc_mouse_processor *mp;
|
||||
|
||||
struct sc_mouse_bindings mouse_bindings;
|
||||
bool has_secondary_click;
|
||||
bool legacy_paste;
|
||||
bool clipboard_autosync;
|
||||
|
||||
@@ -33,6 +32,8 @@ struct sc_input_manager {
|
||||
bool vfinger_invert_x;
|
||||
bool vfinger_invert_y;
|
||||
|
||||
uint8_t mouse_buttons_state; // OR of enum sc_mouse_button values
|
||||
|
||||
// Tracks the number of identical consecutive shortcut key down events.
|
||||
// Not to be confused with event->repeat, which counts the number of
|
||||
// system-generated repeated key presses.
|
||||
|
||||
@@ -24,10 +24,18 @@ const struct scrcpy_options scrcpy_options_default = {
|
||||
.keyboard_input_mode = SC_KEYBOARD_INPUT_MODE_AUTO,
|
||||
.mouse_input_mode = SC_MOUSE_INPUT_MODE_AUTO,
|
||||
.mouse_bindings = {
|
||||
.right_click = SC_MOUSE_BINDING_AUTO,
|
||||
.middle_click = SC_MOUSE_BINDING_AUTO,
|
||||
.click4 = SC_MOUSE_BINDING_AUTO,
|
||||
.click5 = SC_MOUSE_BINDING_AUTO,
|
||||
.pri = {
|
||||
.right_click = SC_MOUSE_BINDING_AUTO,
|
||||
.middle_click = SC_MOUSE_BINDING_AUTO,
|
||||
.click4 = SC_MOUSE_BINDING_AUTO,
|
||||
.click5 = SC_MOUSE_BINDING_AUTO,
|
||||
},
|
||||
.sec = {
|
||||
.right_click = SC_MOUSE_BINDING_AUTO,
|
||||
.middle_click = SC_MOUSE_BINDING_AUTO,
|
||||
.click4 = SC_MOUSE_BINDING_AUTO,
|
||||
.click5 = SC_MOUSE_BINDING_AUTO,
|
||||
},
|
||||
},
|
||||
.camera_facing = SC_CAMERA_FACING_ANY,
|
||||
.port_range = {
|
||||
|
||||
@@ -165,13 +165,18 @@ enum sc_mouse_binding {
|
||||
SC_MOUSE_BINDING_EXPAND_NOTIFICATION_PANEL,
|
||||
};
|
||||
|
||||
struct sc_mouse_bindings {
|
||||
struct sc_mouse_binding_set {
|
||||
enum sc_mouse_binding right_click;
|
||||
enum sc_mouse_binding middle_click;
|
||||
enum sc_mouse_binding click4;
|
||||
enum sc_mouse_binding click5;
|
||||
};
|
||||
|
||||
struct sc_mouse_bindings {
|
||||
struct sc_mouse_binding_set pri;
|
||||
struct sc_mouse_binding_set sec; // When Shift is pressed
|
||||
};
|
||||
|
||||
enum sc_key_inject_mode {
|
||||
// Inject special keys, letters and space as key events.
|
||||
// Inject numbers and punctuation as text events.
|
||||
|
||||
@@ -21,7 +21,7 @@ sc_receiver_init(struct sc_receiver *receiver, sc_socket control_socket,
|
||||
receiver->acksync = NULL;
|
||||
receiver->uhid_devices = NULL;
|
||||
|
||||
assert(cbs && cbs->on_error);
|
||||
assert(cbs && cbs->on_ended);
|
||||
receiver->cbs = cbs;
|
||||
receiver->cbs_userdata = cbs_userdata;
|
||||
|
||||
@@ -134,12 +134,15 @@ run_receiver(void *data) {
|
||||
static uint8_t buf[DEVICE_MSG_MAX_SIZE];
|
||||
size_t head = 0;
|
||||
|
||||
bool error = false;
|
||||
|
||||
for (;;) {
|
||||
assert(head < DEVICE_MSG_MAX_SIZE);
|
||||
ssize_t r = net_recv(receiver->control_socket, buf + head,
|
||||
DEVICE_MSG_MAX_SIZE - head);
|
||||
if (r <= 0) {
|
||||
LOGD("Receiver stopped");
|
||||
// device disconnected: keep error=false
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -147,6 +150,7 @@ run_receiver(void *data) {
|
||||
ssize_t consumed = process_msgs(receiver, buf, head);
|
||||
if (consumed == -1) {
|
||||
// an error occurred
|
||||
error = true;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -157,7 +161,7 @@ run_receiver(void *data) {
|
||||
}
|
||||
}
|
||||
|
||||
receiver->cbs->on_error(receiver, receiver->cbs_userdata);
|
||||
receiver->cbs->on_ended(receiver, error, receiver->cbs_userdata);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ struct sc_receiver {
|
||||
};
|
||||
|
||||
struct sc_receiver_callbacks {
|
||||
void (*on_error)(struct sc_receiver *receiver, void *userdata);
|
||||
void (*on_ended)(struct sc_receiver *receiver, bool error, void *userdata);
|
||||
};
|
||||
|
||||
bool
|
||||
|
||||
@@ -269,13 +269,18 @@ sc_audio_demuxer_on_ended(struct sc_demuxer *demuxer,
|
||||
}
|
||||
|
||||
static void
|
||||
sc_controller_on_error(struct sc_controller *controller, void *userdata) {
|
||||
sc_controller_on_ended(struct sc_controller *controller, bool error,
|
||||
void *userdata) {
|
||||
// Note: this function may be called twice, once from the controller thread
|
||||
// and once from the receiver thread
|
||||
(void) controller;
|
||||
(void) userdata;
|
||||
|
||||
PUSH_EVENT(SC_EVENT_CONTROLLER_ERROR);
|
||||
if (error) {
|
||||
PUSH_EVENT(SC_EVENT_CONTROLLER_ERROR);
|
||||
} else {
|
||||
PUSH_EVENT(SC_EVENT_DEVICE_DISCONNECTED);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -567,7 +572,7 @@ scrcpy(struct scrcpy_options *options) {
|
||||
|
||||
if (options->control) {
|
||||
static const struct sc_controller_callbacks controller_cbs = {
|
||||
.on_error = sc_controller_on_error,
|
||||
.on_ended = sc_controller_on_ended,
|
||||
};
|
||||
|
||||
if (!sc_controller_init(&s->controller, s->server.control_socket,
|
||||
@@ -730,23 +735,20 @@ scrcpy(struct scrcpy_options *options) {
|
||||
.start_fps_counter = options->start_fps_counter,
|
||||
};
|
||||
|
||||
struct sc_frame_source *src;
|
||||
if (options->video_playback) {
|
||||
src = &s->video_decoder.frame_source;
|
||||
if (options->display_buffer) {
|
||||
sc_delay_buffer_init(&s->display_buffer,
|
||||
options->display_buffer, true);
|
||||
sc_frame_source_add_sink(src, &s->display_buffer.frame_sink);
|
||||
src = &s->display_buffer.frame_source;
|
||||
}
|
||||
}
|
||||
|
||||
if (!sc_screen_init(&s->screen, &screen_params)) {
|
||||
goto end;
|
||||
}
|
||||
screen_initialized = true;
|
||||
|
||||
if (options->video_playback) {
|
||||
struct sc_frame_source *src = &s->video_decoder.frame_source;
|
||||
if (options->display_buffer) {
|
||||
sc_delay_buffer_init(&s->display_buffer,
|
||||
options->display_buffer, true);
|
||||
sc_frame_source_add_sink(src, &s->display_buffer.frame_sink);
|
||||
src = &s->display_buffer.frame_source;
|
||||
}
|
||||
|
||||
sc_frame_source_add_sink(src, &s->screen.frame_sink);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -169,7 +169,7 @@ sc_screen_otg_process_mouse_motion(struct sc_screen_otg *screen,
|
||||
// .position not used for HID events
|
||||
.xrel = event->xrel,
|
||||
.yrel = event->yrel,
|
||||
.buttons_state = sc_mouse_buttons_state_from_sdl(event->state, NULL),
|
||||
.buttons_state = sc_mouse_buttons_state_from_sdl(event->state),
|
||||
};
|
||||
|
||||
assert(mp->ops->process_mouse_motion);
|
||||
@@ -188,8 +188,7 @@ sc_screen_otg_process_mouse_button(struct sc_screen_otg *screen,
|
||||
// .position not used for HID events
|
||||
.action = sc_action_from_sdl_mousebutton_type(event->type),
|
||||
.button = sc_mouse_button_from_sdl(event->button),
|
||||
.buttons_state =
|
||||
sc_mouse_buttons_state_from_sdl(sdl_buttons_state, NULL),
|
||||
.buttons_state = sc_mouse_buttons_state_from_sdl(sdl_buttons_state),
|
||||
};
|
||||
|
||||
assert(mp->ops->process_mouse_click);
|
||||
@@ -208,8 +207,7 @@ sc_screen_otg_process_mouse_wheel(struct sc_screen_otg *screen,
|
||||
// .position not used for HID events
|
||||
.hscroll = event->x,
|
||||
.vscroll = event->y,
|
||||
.buttons_state =
|
||||
sc_mouse_buttons_state_from_sdl(sdl_buttons_state, NULL),
|
||||
.buttons_state = sc_mouse_buttons_state_from_sdl(sdl_buttons_state),
|
||||
};
|
||||
|
||||
assert(mp->ops->process_mouse_scroll);
|
||||
|
||||
@@ -240,7 +240,7 @@ sc_v4l2_sink_open(struct sc_v4l2_sink *vs, const AVCodecContext *ctx) {
|
||||
vs->frame = av_frame_alloc();
|
||||
if (!vs->frame) {
|
||||
LOG_OOM();
|
||||
goto error_avcodec_close;
|
||||
goto error_avcodec_free_context;
|
||||
}
|
||||
|
||||
vs->packet = av_packet_alloc();
|
||||
@@ -268,8 +268,6 @@ error_av_packet_free:
|
||||
av_packet_free(&vs->packet);
|
||||
error_av_frame_free:
|
||||
av_frame_free(&vs->frame);
|
||||
error_avcodec_close:
|
||||
avcodec_close(vs->encoder_ctx);
|
||||
error_avcodec_free_context:
|
||||
avcodec_free_context(&vs->encoder_ctx);
|
||||
error_avio_close:
|
||||
@@ -297,7 +295,6 @@ sc_v4l2_sink_close(struct sc_v4l2_sink *vs) {
|
||||
|
||||
av_packet_free(&vs->packet);
|
||||
av_frame_free(&vs->frame);
|
||||
avcodec_close(vs->encoder_ctx);
|
||||
avcodec_free_context(&vs->encoder_ctx);
|
||||
avio_close(vs->format_ctx->pb);
|
||||
avformat_free_context(vs->format_ctx);
|
||||
|
||||
@@ -42,7 +42,7 @@ scrcpy --no-window
|
||||
# interrupt with Ctrl+C
|
||||
```
|
||||
|
||||
Without video, the audio latency is typically not criticial, so it might be
|
||||
Without video, the audio latency is typically not critical, so it might be
|
||||
interesting to add [buffering](#buffering) to minimize glitches:
|
||||
|
||||
```
|
||||
|
||||
@@ -94,7 +94,7 @@ This is the preferred method (and the way the release is built).
|
||||
From _Debian_, install _mingw_:
|
||||
|
||||
```bash
|
||||
sudo apt install mingw-w64 mingw-w64-tools
|
||||
sudo apt install mingw-w64 mingw-w64-tools libz-mingw-w64-dev
|
||||
```
|
||||
|
||||
You also need the JDK to build the server:
|
||||
@@ -233,10 +233,10 @@ install` must be run as root)._
|
||||
|
||||
#### Option 2: Use prebuilt server
|
||||
|
||||
- [`scrcpy-server-v2.4`][direct-scrcpy-server]
|
||||
<sub>SHA-256: `93c272b7438605c055e127f7444064ed78fa9ca49f81156777fd201e79ce7ba3`</sub>
|
||||
- [`scrcpy-server-v2.5`][direct-scrcpy-server]
|
||||
<sub>SHA-256: `1488b1105d6aff534873a26bf610cd2aea06ee867dd7a4d9c6bb2c091396eb15`</sub>
|
||||
|
||||
[direct-scrcpy-server]: https://github.com/Genymobile/scrcpy/releases/download/v2.4/scrcpy-server-v2.4
|
||||
[direct-scrcpy-server]: https://github.com/Genymobile/scrcpy/releases/download/v2.5/scrcpy-server-v2.5
|
||||
|
||||
Download the prebuilt server somewhere, and specify its path during the Meson
|
||||
configuration:
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
Scrcpy is packaged in several distributions and package managers:
|
||||
|
||||
- Debian/Ubuntu: `apt install scrcpy`
|
||||
- Debian/Ubuntu: ~~`apt install scrcpy`~~ _(obsolete version)_
|
||||
- Arch Linux: `pacman -S scrcpy`
|
||||
- Fedora: `dnf copr enable zeno/scrcpy && dnf install scrcpy`
|
||||
- Gentoo: `emerge scrcpy`
|
||||
|
||||
52
doc/mouse.md
52
doc/mouse.md
@@ -80,21 +80,37 @@ process like the _adb daemon_).
|
||||
|
||||
## Mouse bindings
|
||||
|
||||
By default, with SDK mouse, right-click triggers BACK (or POWER on) and
|
||||
middle-click triggers HOME. In addition, the 4th click triggers APP_SWITCH and
|
||||
the 5th click expands the notification panel.
|
||||
By default, with SDK mouse:
|
||||
- right-click triggers BACK (or POWER on)
|
||||
- middle-click triggers HOME
|
||||
- the 4th click triggers APP_SWITCH
|
||||
- the 5th click expands the notification panel
|
||||
|
||||
In AOA and UHID mouse modes, all clicks are forwarded by default.
|
||||
The secondary clicks may be forwarded to the device instead by pressing the
|
||||
<kbd>Shift</kbd> key (e.g. <kbd>Shift</kbd>+right-click injects a right click to
|
||||
the device).
|
||||
|
||||
The shortcuts can be configured using `--mouse-bind=xxxx` for any mouse mode.
|
||||
The argument must be exactly 4 characters, one for each secondary click:
|
||||
In AOA and UHID mouse modes, the default bindings are reversed: all clicks are
|
||||
forwarded by default, and pressing <kbd>Shift</kbd> gives access to the
|
||||
shortcuts (since the cursor is handled on the device side, it makes more sense
|
||||
to forward all mouse buttons by default in these modes).
|
||||
|
||||
The shortcuts can be configured using `--mouse-bind=xxxx:xxxx` for any mouse
|
||||
mode. The argument must be one or two sequences (separated by `:`) of exactly 4
|
||||
characters, one for each secondary click:
|
||||
|
||||
```
|
||||
--mouse-bind=xxxx
|
||||
.---- Shift + right click
|
||||
SECONDARY |.--- Shift + middle click
|
||||
BINDINGS ||.-- Shift + 4th click
|
||||
|||.- Shift + 5th click
|
||||
||||
|
||||
vvvv
|
||||
--mouse-bind=xxxx:xxxx
|
||||
^^^^
|
||||
||||
|
||||
||| `- 5th click
|
||||
|| `-- 4th click
|
||||
PRIMARY ||| `- 5th click
|
||||
BINDINGS || `-- 4th click
|
||||
| `--- middle click
|
||||
`---- right click
|
||||
```
|
||||
@@ -111,8 +127,18 @@ Each character must be one of the following:
|
||||
For example:
|
||||
|
||||
```bash
|
||||
scrcpy --mouse-bind=bhsn # the default mode with SDK mouse
|
||||
scrcpy --mouse-bind=++++ # forward all clicks (default for AOA/UHID)
|
||||
scrcpy --mouse-bind=++bh # forward right and middle clicks,
|
||||
# use 4th and 5th for BACK and HOME
|
||||
scrcpy --mouse-bind=bhsn:++++ # the default mode for SDK mouse
|
||||
scrcpy --mouse-bind=++++:bhsn # the default mode for AOA and UHID
|
||||
scrcpy --mouse-bind=++bh:++sn # forward right and middle clicks,
|
||||
# use 4th and 5th for BACK and HOME,
|
||||
# use Shift+4th and Shift+5th for APP_SWITCH
|
||||
# and expand notification panel
|
||||
```
|
||||
|
||||
The second sequence of bindings may be omitted. In that case, it is the same as
|
||||
the first one:
|
||||
|
||||
```bash
|
||||
scrcpy --mouse-bind=bhsn
|
||||
scrcpy --mouse-bind=bhsn:bhsn # equivalent
|
||||
```
|
||||
|
||||
@@ -4,24 +4,18 @@
|
||||
|
||||
Download the [latest release]:
|
||||
|
||||
- [`scrcpy-win64-v2.4.zip`][direct-win64] (64-bit)
|
||||
<sub>SHA-256: `9dc56f21bfa455352ec0c58b40feaf2fb02d67372910a4235e298ece286ff3a9`</sub>
|
||||
- [`scrcpy-win32-v2.4.zip`][direct-win32] (32-bit)
|
||||
<sub>SHA-256: `cf92acc45eef37c6ee2db819f92e420ced3bc50f1348dd57f7d6ca1fc80f6116`</sub>
|
||||
- [`scrcpy-win64-v2.5.zip`][direct-win64] (64-bit)
|
||||
<sub>SHA-256: `345cf04a66a9144281dce72ca4e82adfd2c3092463196e586051df4c69e1507b`</sub>
|
||||
- [`scrcpy-win32-v2.5.zip`][direct-win32] (32-bit)
|
||||
<sub>SHA-256: `d56312a92471565fa4f3a6b94e8eb07717c4c90f2c0f05b03ba444e1001806ec`</sub>
|
||||
|
||||
[latest release]: https://github.com/Genymobile/scrcpy/releases/latest
|
||||
[direct-win64]: https://github.com/Genymobile/scrcpy/releases/download/v2.4/scrcpy-win64-v2.4.zip
|
||||
[direct-win32]: https://github.com/Genymobile/scrcpy/releases/download/v2.4/scrcpy-win32-v2.4.zip
|
||||
[direct-win64]: https://github.com/Genymobile/scrcpy/releases/download/v2.5/scrcpy-win64-v2.5.zip
|
||||
[direct-win32]: https://github.com/Genymobile/scrcpy/releases/download/v2.5/scrcpy-win32-v2.5.zip
|
||||
|
||||
and extract it.
|
||||
|
||||
Alternatively, you could install it from packages manager, like [Winget]:
|
||||
|
||||
```bash
|
||||
winget install scrcpy
|
||||
```
|
||||
|
||||
or [Chocolatey]:
|
||||
Alternatively, you could install it from packages manager, like [Chocolatey]:
|
||||
|
||||
```bash
|
||||
choco install scrcpy
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
set -e
|
||||
|
||||
BUILDDIR=build-auto
|
||||
PREBUILT_SERVER_URL=https://github.com/Genymobile/scrcpy/releases/download/v2.4/scrcpy-server-v2.4
|
||||
PREBUILT_SERVER_SHA256=93c272b7438605c055e127f7444064ed78fa9ca49f81156777fd201e79ce7ba3
|
||||
PREBUILT_SERVER_URL=https://github.com/Genymobile/scrcpy/releases/download/v2.5/scrcpy-server-v2.5
|
||||
PREBUILT_SERVER_SHA256=1488b1105d6aff534873a26bf610cd2aea06ee867dd7a4d9c6bb2c091396eb15
|
||||
|
||||
echo "[scrcpy] Downloading prebuilt server..."
|
||||
wget "$PREBUILT_SERVER_URL" -O scrcpy-server
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
project('scrcpy', 'c',
|
||||
version: '2.4',
|
||||
version: '2.5',
|
||||
meson_version: '>= 0.48',
|
||||
default_options: [
|
||||
'c_std=c11',
|
||||
|
||||
@@ -7,8 +7,8 @@ android {
|
||||
applicationId "com.genymobile.scrcpy"
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 34
|
||||
versionCode 20400
|
||||
versionName "2.4"
|
||||
versionCode 20500
|
||||
versionName "2.5"
|
||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
buildTypes {
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
set -e
|
||||
|
||||
SCRCPY_DEBUG=false
|
||||
SCRCPY_VERSION_NAME=2.4
|
||||
SCRCPY_VERSION_NAME=2.5
|
||||
|
||||
PLATFORM=${ANDROID_PLATFORM:-34}
|
||||
BUILD_TOOLS=${ANDROID_BUILD_TOOLS:-34.0.0}
|
||||
|
||||
@@ -22,7 +22,6 @@ public class Controller implements AsyncProcessor {
|
||||
|
||||
// control_msg.h values of the pointerId field in inject_touch_event message
|
||||
private static final int POINTER_ID_MOUSE = -1;
|
||||
private static final int POINTER_ID_VIRTUAL_MOUSE = -3;
|
||||
|
||||
private static final ScheduledExecutorService EXECUTOR = Executors.newSingleThreadScheduledExecutor();
|
||||
|
||||
@@ -273,8 +272,8 @@ public class Controller implements AsyncProcessor {
|
||||
pointer.setPressure(pressure);
|
||||
|
||||
int source;
|
||||
if (pointerId == POINTER_ID_MOUSE || pointerId == POINTER_ID_VIRTUAL_MOUSE) {
|
||||
// real mouse event (forced by the client when --forward-on-click)
|
||||
if (pointerId == POINTER_ID_MOUSE) {
|
||||
// real mouse event
|
||||
pointerProperties[pointerIndex].toolType = MotionEvent.TOOL_TYPE_MOUSE;
|
||||
source = InputDevice.SOURCE_MOUSE;
|
||||
pointer.setUp(buttons == 0);
|
||||
|
||||
@@ -63,9 +63,11 @@ public final class Workarounds {
|
||||
// - <https://github.com/Genymobile/scrcpy/issues/940>
|
||||
// - <https://github.com/Genymobile/scrcpy/issues/994>
|
||||
mustFillAppInfo = true;
|
||||
} else if (Build.BRAND.equalsIgnoreCase("honor")) {
|
||||
} else if (Build.BRAND.equalsIgnoreCase("honor") || Build.MANUFACTURER.equalsIgnoreCase("skyworth")) {
|
||||
// More workarounds must be applied for Honor devices:
|
||||
// - <https://github.com/Genymobile/scrcpy/issues/4015>
|
||||
// and Skyworth devices:
|
||||
// - <https://github.com/Genymobile/scrcpy/issues/4922>
|
||||
//
|
||||
// The system context must not be set for all devices, because it would cause other problems:
|
||||
// - <https://github.com/Genymobile/scrcpy/issues/4015#issuecomment-1595382142>
|
||||
|
||||
Reference in New Issue
Block a user