mirror of
https://github.com/Genymobile/scrcpy
synced 2025-08-22 01:47:37 +00:00
Compare commits
6 Commits
98d30288f7
...
f01231dff8
Author | SHA1 | Date | |
---|---|---|---|
|
f01231dff8 | ||
|
5b18ce0d2e | ||
|
4841fdd1ef | ||
|
fc75319bb2 | ||
|
7c8bdccbdc | ||
|
9787fe5d26 |
@ -2,7 +2,7 @@
|
||||
source for the project. Do not download releases from random websites, even if
|
||||
their name contains `scrcpy`.**
|
||||
|
||||
# scrcpy (v3.3)
|
||||
# scrcpy (v3.3.1)
|
||||
|
||||
<img src="app/data/icon.svg" width="128" height="128" alt="scrcpy" align="right" />
|
||||
|
||||
|
@ -13,7 +13,7 @@ BEGIN
|
||||
VALUE "LegalCopyright", "Romain Vimont, Genymobile"
|
||||
VALUE "OriginalFilename", "scrcpy.exe"
|
||||
VALUE "ProductName", "scrcpy"
|
||||
VALUE "ProductVersion", "3.3"
|
||||
VALUE "ProductVersion", "3.3.1"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
|
@ -127,10 +127,14 @@ sc_control_msg_serialize(const struct sc_control_msg *msg, uint8_t *buf) {
|
||||
return 32;
|
||||
case SC_CONTROL_MSG_TYPE_INJECT_SCROLL_EVENT:
|
||||
write_position(&buf[1], &msg->inject_scroll_event.position);
|
||||
int16_t hscroll =
|
||||
sc_float_to_i16fp(msg->inject_scroll_event.hscroll);
|
||||
int16_t vscroll =
|
||||
sc_float_to_i16fp(msg->inject_scroll_event.vscroll);
|
||||
// Accept values in the range [-16, 16].
|
||||
// Normalize to [-1, 1] in order to use sc_float_to_i16fp().
|
||||
float hscroll_norm = msg->inject_scroll_event.hscroll / 16;
|
||||
hscroll_norm = CLAMP(hscroll_norm, -1, 1);
|
||||
float vscroll_norm = msg->inject_scroll_event.vscroll / 16;
|
||||
vscroll_norm = CLAMP(vscroll_norm, -1, 1);
|
||||
int16_t hscroll = sc_float_to_i16fp(hscroll_norm);
|
||||
int16_t vscroll = sc_float_to_i16fp(vscroll_norm);
|
||||
sc_write16be(&buf[13], (uint16_t) hscroll);
|
||||
sc_write16be(&buf[15], (uint16_t) vscroll);
|
||||
sc_write32be(&buf[17], msg->inject_scroll_event.buttons);
|
||||
|
@ -3,8 +3,8 @@
|
||||
#include <stdint.h>
|
||||
|
||||
// 1 byte for buttons + padding, 1 byte for X position, 1 byte for Y position,
|
||||
// 1 byte for wheel motion
|
||||
#define SC_HID_MOUSE_INPUT_SIZE 4
|
||||
// 1 byte for wheel motion, 1 byte for hozizontal scrolling
|
||||
#define SC_HID_MOUSE_INPUT_SIZE 5
|
||||
|
||||
/**
|
||||
* Mouse descriptor from the specification:
|
||||
@ -75,6 +75,21 @@ static const uint8_t SC_HID_MOUSE_REPORT_DESC[] = {
|
||||
// Input (Data, Variable, Relative): 3 position bytes (X, Y, Wheel)
|
||||
0x81, 0x06,
|
||||
|
||||
// Usage Page (Consumer Page)
|
||||
0x05, 0x0C,
|
||||
// Usage(AC Pan)
|
||||
0x0A, 0x38, 0x02,
|
||||
// Logical Minimum (-127)
|
||||
0x15, 0x81,
|
||||
// Logical Maximum (127)
|
||||
0x25, 0x7F,
|
||||
// Report Size (8)
|
||||
0x75, 0x08,
|
||||
// Report Count (1)
|
||||
0x95, 0x01,
|
||||
// Input (Data, Variable, Relative): 1 byte (AC Pan)
|
||||
0x81, 0x06,
|
||||
|
||||
// End Collection
|
||||
0xC0,
|
||||
|
||||
@ -160,7 +175,8 @@ sc_hid_mouse_generate_input_from_motion(struct sc_hid_input *hid_input,
|
||||
data[0] = sc_hid_buttons_from_buttons_state(event->buttons_state);
|
||||
data[1] = CLAMP(event->xrel, -127, 127);
|
||||
data[2] = CLAMP(event->yrel, -127, 127);
|
||||
data[3] = 0; // wheel coordinates only used for scrolling
|
||||
data[3] = 0; // no vertical scrolling
|
||||
data[4] = 0; // no horizontal scrolling
|
||||
}
|
||||
|
||||
void
|
||||
@ -172,22 +188,27 @@ sc_hid_mouse_generate_input_from_click(struct sc_hid_input *hid_input,
|
||||
data[0] = sc_hid_buttons_from_buttons_state(event->buttons_state);
|
||||
data[1] = 0; // no x motion
|
||||
data[2] = 0; // no y motion
|
||||
data[3] = 0; // wheel coordinates only used for scrolling
|
||||
data[3] = 0; // no vertical scrolling
|
||||
data[4] = 0; // no horizontal scrolling
|
||||
}
|
||||
|
||||
void
|
||||
bool
|
||||
sc_hid_mouse_generate_input_from_scroll(struct sc_hid_input *hid_input,
|
||||
const struct sc_mouse_scroll_event *event) {
|
||||
if (!event->vscroll_int && !event->hscroll_int) {
|
||||
// Need a full integral value for HID
|
||||
return false;
|
||||
}
|
||||
|
||||
sc_hid_mouse_input_init(hid_input);
|
||||
|
||||
uint8_t *data = hid_input->data;
|
||||
data[0] = 0; // buttons state irrelevant (and unknown)
|
||||
data[1] = 0; // no x motion
|
||||
data[2] = 0; // no y motion
|
||||
// In practice, vscroll is always -1, 0 or 1, but in theory other values
|
||||
// are possible
|
||||
data[3] = CLAMP(event->vscroll, -127, 127);
|
||||
// Horizontal scrolling ignored
|
||||
data[3] = CLAMP(event->vscroll_int, -127, 127);
|
||||
data[4] = CLAMP(event->hscroll_int, -127, 127);
|
||||
return true;
|
||||
}
|
||||
|
||||
void sc_hid_mouse_generate_open(struct sc_hid_open *hid_open) {
|
||||
|
@ -22,7 +22,7 @@ void
|
||||
sc_hid_mouse_generate_input_from_click(struct sc_hid_input *hid_input,
|
||||
const struct sc_mouse_click_event *event);
|
||||
|
||||
void
|
||||
bool
|
||||
sc_hid_mouse_generate_input_from_scroll(struct sc_hid_input *hid_input,
|
||||
const struct sc_mouse_scroll_event *event);
|
||||
|
||||
|
@ -393,6 +393,8 @@ struct sc_mouse_scroll_event {
|
||||
struct sc_position position;
|
||||
float hscroll;
|
||||
float vscroll;
|
||||
int32_t hscroll_int;
|
||||
int32_t vscroll_int;
|
||||
uint8_t buttons_state; // bitwise-OR of sc_mouse_button values
|
||||
};
|
||||
|
||||
|
@ -897,12 +897,14 @@ sc_input_manager_process_mouse_wheel(struct sc_input_manager *im,
|
||||
struct sc_mouse_scroll_event evt = {
|
||||
.position = sc_input_manager_get_position(im, mouse_x, mouse_y),
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 18)
|
||||
.hscroll = CLAMP(event->preciseX, -1.0f, 1.0f),
|
||||
.vscroll = CLAMP(event->preciseY, -1.0f, 1.0f),
|
||||
.hscroll = event->preciseX,
|
||||
.vscroll = event->preciseY,
|
||||
#else
|
||||
.hscroll = CLAMP(event->x, -1, 1),
|
||||
.vscroll = CLAMP(event->y, -1, 1),
|
||||
.hscroll = event->x,
|
||||
.vscroll = event->y,
|
||||
#endif
|
||||
.hscroll_int = event->x,
|
||||
.vscroll_int = event->y,
|
||||
.buttons_state = im->mouse_buttons_state,
|
||||
};
|
||||
|
||||
|
@ -55,7 +55,9 @@ sc_mouse_processor_process_mouse_scroll(struct sc_mouse_processor *mp,
|
||||
struct sc_mouse_uhid *mouse = DOWNCAST(mp);
|
||||
|
||||
struct sc_hid_input hid_input;
|
||||
sc_hid_mouse_generate_input_from_scroll(&hid_input, event);
|
||||
if (!sc_hid_mouse_generate_input_from_scroll(&hid_input, event)) {
|
||||
return;
|
||||
}
|
||||
|
||||
sc_mouse_uhid_send_input(mouse, &hid_input, "mouse scroll");
|
||||
}
|
||||
|
@ -42,7 +42,9 @@ sc_mouse_processor_process_mouse_scroll(struct sc_mouse_processor *mp,
|
||||
struct sc_mouse_aoa *mouse = DOWNCAST(mp);
|
||||
|
||||
struct sc_hid_input hid_input;
|
||||
sc_hid_mouse_generate_input_from_scroll(&hid_input, event);
|
||||
if (!sc_hid_mouse_generate_input_from_scroll(&hid_input, event)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!sc_aoa_push_input(mouse->aoa, &hid_input)) {
|
||||
LOGW("Could not push AOA HID input (mouse scroll)");
|
||||
|
@ -164,8 +164,15 @@ sc_screen_otg_process_mouse_wheel(struct sc_screen_otg *screen,
|
||||
|
||||
struct sc_mouse_scroll_event evt = {
|
||||
// .position not used for HID events
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 18)
|
||||
.hscroll = event->preciseX,
|
||||
.vscroll = event->preciseY,
|
||||
#else
|
||||
.hscroll = event->x,
|
||||
.vscroll = event->y,
|
||||
#endif
|
||||
.hscroll_int = event->x,
|
||||
.vscroll_int = event->y,
|
||||
.buttons_state = sc_mouse_buttons_state_from_sdl(sdl_buttons_state),
|
||||
};
|
||||
|
||||
|
@ -127,8 +127,8 @@ static void test_serialize_inject_scroll_event(void) {
|
||||
.height = 1920,
|
||||
},
|
||||
},
|
||||
.hscroll = 1,
|
||||
.vscroll = -1,
|
||||
.hscroll = 16,
|
||||
.vscroll = -16,
|
||||
.buttons = 1,
|
||||
},
|
||||
};
|
||||
@ -141,8 +141,8 @@ static void test_serialize_inject_scroll_event(void) {
|
||||
SC_CONTROL_MSG_TYPE_INJECT_SCROLL_EVENT,
|
||||
0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x04, 0x02, // 260 1026
|
||||
0x04, 0x38, 0x07, 0x80, // 1080 1920
|
||||
0x7F, 0xFF, // 1 (float encoded as i16)
|
||||
0x80, 0x00, // -1 (float encoded as i16)
|
||||
0x7F, 0xFF, // 16 (float encoded as i16 in the range [-16, 16])
|
||||
0x80, 0x00, // -16 (float encoded as i16 in the range [-16, 16])
|
||||
0x00, 0x00, 0x00, 0x01, // 1
|
||||
};
|
||||
assert(!memcmp(buf, expected, sizeof(expected)));
|
||||
|
@ -233,10 +233,10 @@ install` must be run as root)._
|
||||
|
||||
#### Option 2: Use prebuilt server
|
||||
|
||||
- [`scrcpy-server-v3.3`][direct-scrcpy-server]
|
||||
<sub>SHA-256: `351cb2edc7e4c2c75f09a7933fdabcf137be52e2602df154f24ec02db46e9e51`</sub>
|
||||
- [`scrcpy-server-v3.3.1`][direct-scrcpy-server]
|
||||
<sub>SHA-256: `a0f70b20aa4998fbf658c94118cd6c8dab6abbb0647a3bdab344d70bc1ebcbb8`</sub>
|
||||
|
||||
[direct-scrcpy-server]: https://github.com/Genymobile/scrcpy/releases/download/v3.3/scrcpy-server-v3.3
|
||||
[direct-scrcpy-server]: https://github.com/Genymobile/scrcpy/releases/download/v3.3.1/scrcpy-server-v3.3.1
|
||||
|
||||
Download the prebuilt server somewhere, and specify its path during the Meson
|
||||
configuration:
|
||||
|
@ -6,11 +6,11 @@
|
||||
|
||||
Download a static build of the [latest release]:
|
||||
|
||||
- [`scrcpy-linux-x86_64-v3.3.tar.gz`][direct-linux-x86_64] (x86_64)
|
||||
<sub>SHA-256: `a0abf37003c3c47a53c1b2a12420296a2b0ee323cf3610fd6fbf9d9bab9d99f3`</sub>
|
||||
- [`scrcpy-linux-x86_64-v3.3.1.tar.gz`][direct-linux-x86_64] (x86_64)
|
||||
<sub>SHA-256: `bbfe54c6b178adafeaffbbfbbc1548a74486553170c63e63bdd41863ad123422`</sub>
|
||||
|
||||
[latest release]: https://github.com/Genymobile/scrcpy/releases/latest
|
||||
[direct-linux-x86_64]: https://github.com/Genymobile/scrcpy/releases/download/v3.3/scrcpy-linux-x86_64-v3.3.tar.gz
|
||||
[direct-linux-x86_64]: https://github.com/Genymobile/scrcpy/releases/download/v3.3.1/scrcpy-linux-x86_64-v3.3.1.tar.gz
|
||||
|
||||
and extract it.
|
||||
|
||||
|
12
doc/macos.md
12
doc/macos.md
@ -6,15 +6,15 @@
|
||||
|
||||
Download a static build of the [latest release]:
|
||||
|
||||
- [`scrcpy-macos-aarch64-v3.3.tar.gz`][direct-macos-aarch64] (aarch64)
|
||||
<sub>SHA-256: `7a4cdaeb8ba74593edda278c000ddedc8d70a51263a80b16a6345475d42ac21e`</sub>
|
||||
- [`scrcpy-macos-aarch64-v3.3.1.tar.gz`][direct-macos-aarch64] (aarch64)
|
||||
<sub>SHA-256: `907b925900ebd8499c1e47acc9689a95bd3a6f9930eb1d7bdfbca8375ae4f139`</sub>
|
||||
|
||||
- [`scrcpy-macos-x86_64-v3.3.tar.gz`][direct-macos-x86_64] (x86_64)
|
||||
<sub>SHA-256: `bb3c13aac166b92539371883a8781aa861a7cd18e3e6077e570ab7a1f562f774`</sub>
|
||||
- [`scrcpy-macos-x86_64-v3.3.1.tar.gz`][direct-macos-x86_64] (x86_64)
|
||||
<sub>SHA-256: `69772491dad718eea82fc65c8e89febff7d41c4ce6faff02f4789a588d10fd7d`</sub>
|
||||
|
||||
[latest release]: https://github.com/Genymobile/scrcpy/releases/latest
|
||||
[direct-macos-aarch64]: https://github.com/Genymobile/scrcpy/releases/download/v3.3/scrcpy-macos-aarch64-v3.3.tar.gz
|
||||
[direct-macos-x86_64]: https://github.com/Genymobile/scrcpy/releases/download/v3.3/scrcpy-macos-x86_64-v3.3.tar.gz
|
||||
[direct-macos-aarch64]: https://github.com/Genymobile/scrcpy/releases/download/v3.3.1/scrcpy-macos-aarch64-v3.3.1.tar.gz
|
||||
[direct-macos-x86_64]: https://github.com/Genymobile/scrcpy/releases/download/v3.3.1/scrcpy-macos-x86_64-v3.3.1.tar.gz
|
||||
|
||||
and extract it.
|
||||
|
||||
|
@ -6,14 +6,14 @@
|
||||
|
||||
Download the [latest release]:
|
||||
|
||||
- [`scrcpy-win64-v3.3.zip`][direct-win64] (64-bit)
|
||||
<sub>SHA-256: `a120cb4be7cde2891af38e83d2008173a0b6b6b5e344b2dfe668d0f892999933`</sub>
|
||||
- [`scrcpy-win32-v3.3.zip`][direct-win32] (32-bit)
|
||||
<sub>SHA-256: `e409ab83f8c57bd6ac741d652635cab7699fcf3d384e233833872f117b993ca6`</sub>
|
||||
- [`scrcpy-win64-v3.3.1.zip`][direct-win64] (64-bit)
|
||||
<sub>SHA-256: `4fcad494772a3ae5de9a133149f8856d2fc429b41795f7cf7c754e0c1bb6fbc0`</sub>
|
||||
- [`scrcpy-win32-v3.3.1.zip`][direct-win32] (32-bit)
|
||||
<sub>SHA-256: `ccdf1b4f5d19dfe760446a107e55b0a010a00e097d46533a161499c9333a20a6`</sub>
|
||||
|
||||
[latest release]: https://github.com/Genymobile/scrcpy/releases/latest
|
||||
[direct-win64]: https://github.com/Genymobile/scrcpy/releases/download/v3.3/scrcpy-win64-v3.3.zip
|
||||
[direct-win32]: https://github.com/Genymobile/scrcpy/releases/download/v3.3/scrcpy-win32-v3.3.zip
|
||||
[direct-win64]: https://github.com/Genymobile/scrcpy/releases/download/v3.3.1/scrcpy-win64-v3.3.1.zip
|
||||
[direct-win32]: https://github.com/Genymobile/scrcpy/releases/download/v3.3.1/scrcpy-win32-v3.3.1.zip
|
||||
|
||||
and extract it.
|
||||
|
||||
|
@ -2,8 +2,8 @@
|
||||
set -e
|
||||
|
||||
BUILDDIR=build-auto
|
||||
PREBUILT_SERVER_URL=https://github.com/Genymobile/scrcpy/releases/download/v3.3/scrcpy-server-v3.3
|
||||
PREBUILT_SERVER_SHA256=351cb2edc7e4c2c75f09a7933fdabcf137be52e2602df154f24ec02db46e9e51
|
||||
PREBUILT_SERVER_URL=https://github.com/Genymobile/scrcpy/releases/download/v3.3.1/scrcpy-server-v3.3.1
|
||||
PREBUILT_SERVER_SHA256=a0f70b20aa4998fbf658c94118cd6c8dab6abbb0647a3bdab344d70bc1ebcbb8
|
||||
|
||||
echo "[scrcpy] Downloading prebuilt server..."
|
||||
wget "$PREBUILT_SERVER_URL" -O scrcpy-server
|
||||
|
@ -1,5 +1,5 @@
|
||||
project('scrcpy', 'c',
|
||||
version: '3.3',
|
||||
version: '3.3.1',
|
||||
meson_version: '>= 0.49',
|
||||
default_options: [
|
||||
'c_std=c11',
|
||||
|
@ -7,8 +7,8 @@ android {
|
||||
applicationId "com.genymobile.scrcpy"
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 35
|
||||
versionCode 30300
|
||||
versionName "3.3"
|
||||
versionCode 30301
|
||||
versionName "3.3.1"
|
||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
buildTypes {
|
||||
|
@ -12,7 +12,7 @@
|
||||
set -e
|
||||
|
||||
SCRCPY_DEBUG=false
|
||||
SCRCPY_VERSION_NAME=3.3
|
||||
SCRCPY_VERSION_NAME=3.3.1
|
||||
|
||||
PLATFORM=${ANDROID_PLATFORM:-35}
|
||||
BUILD_TOOLS=${ANDROID_BUILD_TOOLS:-35.0.0}
|
||||
|
@ -112,8 +112,9 @@ public class ControlMessageReader {
|
||||
|
||||
private ControlMessage parseInjectScrollEvent() throws IOException {
|
||||
Position position = parsePosition();
|
||||
float hScroll = Binary.i16FixedPointToFloat(dis.readShort());
|
||||
float vScroll = Binary.i16FixedPointToFloat(dis.readShort());
|
||||
// Binary.i16FixedPointToFloat() decodes values assuming the full range is [-1, 1], but the actual range is [-16, 16].
|
||||
float hScroll = Binary.i16FixedPointToFloat(dis.readShort()) * 16;
|
||||
float vScroll = Binary.i16FixedPointToFloat(dis.readShort()) * 16;
|
||||
int buttons = dis.readInt();
|
||||
return ControlMessage.createInjectScrollEvent(position, hScroll, vScroll, buttons);
|
||||
}
|
||||
|
@ -125,7 +125,7 @@ public class ControlMessageReaderTest {
|
||||
dos.writeShort(1080);
|
||||
dos.writeShort(1920);
|
||||
dos.writeShort(0); // 0.0f encoded as i16
|
||||
dos.writeShort(0x8000); // -1.0f encoded as i16
|
||||
dos.writeShort(0x8000); // -16.0f encoded as i16 (the range is [-16, 16])
|
||||
dos.writeInt(1);
|
||||
byte[] packet = bos.toByteArray();
|
||||
|
||||
@ -139,7 +139,7 @@ public class ControlMessageReaderTest {
|
||||
Assert.assertEquals(1080, event.getPosition().getScreenSize().getWidth());
|
||||
Assert.assertEquals(1920, event.getPosition().getScreenSize().getHeight());
|
||||
Assert.assertEquals(0f, event.getHScroll(), 0f);
|
||||
Assert.assertEquals(-1f, event.getVScroll(), 0f);
|
||||
Assert.assertEquals(-16f, event.getVScroll(), 0f);
|
||||
Assert.assertEquals(1, event.getButtons());
|
||||
|
||||
Assert.assertEquals(-1, bis.read()); // EOS
|
||||
|
Loading…
x
Reference in New Issue
Block a user