Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3b6495aefc | ||
|
|
72ff957e9a | ||
|
|
db8c1ce8e1 | ||
|
|
4aeb78ece2 | ||
|
|
396e4bd925 | ||
|
|
7f2f5950f2 |
@@ -401,6 +401,7 @@ sc_adb_list_devices(struct sc_intr *intr, unsigned flags,
|
|||||||
#define BUFSIZE 65536
|
#define BUFSIZE 65536
|
||||||
char *buf = malloc(BUFSIZE);
|
char *buf = malloc(BUFSIZE);
|
||||||
if (!buf) {
|
if (!buf) {
|
||||||
|
LOG_OOM();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -434,7 +435,6 @@ sc_adb_list_devices(struct sc_intr *intr, unsigned flags,
|
|||||||
"Please report an issue.");
|
"Please report an issue.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
#undef BUFSIZE
|
|
||||||
|
|
||||||
// It is parsed as a NUL-terminated string
|
// It is parsed as a NUL-terminated string
|
||||||
buf[r] = '\0';
|
buf[r] = '\0';
|
||||||
@@ -713,95 +713,3 @@ sc_adb_get_device_ip(struct sc_intr *intr, const char *serial, unsigned flags) {
|
|||||||
|
|
||||||
return sc_adb_parse_device_ip(buf);
|
return sc_adb_parse_device_ip(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
char *
|
|
||||||
sc_adb_get_installed_apk_path(struct sc_intr *intr, const char *serial,
|
|
||||||
unsigned flags) {
|
|
||||||
assert(serial);
|
|
||||||
const char *const argv[] =
|
|
||||||
SC_ADB_COMMAND("-s", serial, "shell", "pm", "list", "package", "-f",
|
|
||||||
SC_ANDROID_PACKAGE);
|
|
||||||
|
|
||||||
sc_pipe pout;
|
|
||||||
sc_pid pid = sc_adb_execute_p(argv, flags, &pout);
|
|
||||||
if (pid == SC_PROCESS_NONE) {
|
|
||||||
LOGD("Could not execute \"pm list packages\"");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// "pm list packages -f <package>" output should contain only one line, so
|
|
||||||
// the output should be short
|
|
||||||
char buf[1024];
|
|
||||||
ssize_t r = sc_pipe_read_all_intr(intr, pid, pout, buf, sizeof(buf) - 1);
|
|
||||||
sc_pipe_close(pout);
|
|
||||||
|
|
||||||
bool ok = process_check_success_intr(intr, pid, "pm list packages", flags);
|
|
||||||
if (!ok) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (r == -1) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
assert((size_t) r < sizeof(buf));
|
|
||||||
if (r == sizeof(buf) - 1) {
|
|
||||||
// The implementation assumes that the output of "pm list packages"
|
|
||||||
// fits in the buffer in a single pass
|
|
||||||
LOGW("Result of \"pm list package\" does not fit in 1Kb. "
|
|
||||||
"Please report an issue.");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// It is parsed as a NUL-terminated string
|
|
||||||
buf[r] = '\0';
|
|
||||||
|
|
||||||
return sc_adb_parse_installed_apk_path(buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
char *
|
|
||||||
sc_adb_get_installed_apk_version(struct sc_intr *intr, const char *serial,
|
|
||||||
unsigned flags) {
|
|
||||||
assert(serial);
|
|
||||||
const char *const argv[] =
|
|
||||||
SC_ADB_COMMAND("-s", serial, "shell", "dumpsys", "package",
|
|
||||||
SC_ANDROID_PACKAGE);
|
|
||||||
|
|
||||||
sc_pipe pout;
|
|
||||||
sc_pid pid = sc_adb_execute_p(argv, flags, &pout);
|
|
||||||
if (pid == SC_PROCESS_NONE) {
|
|
||||||
LOGD("Could not execute \"dumpsys package\"");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// "dumpsys package" output can be huge (e.g. 16k), but versionName is at
|
|
||||||
// the beginning, typically in the first 1024 bytes (64k should be enough
|
|
||||||
// for the whole output anyway)
|
|
||||||
#define BUFSIZE 65536
|
|
||||||
char *buf = malloc(BUFSIZE);
|
|
||||||
if (!buf) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
ssize_t r = sc_pipe_read_all_intr(intr, pid, pout, buf, BUFSIZE - 1);
|
|
||||||
sc_pipe_close(pout);
|
|
||||||
|
|
||||||
bool ok = process_check_success_intr(intr, pid, "dumpsys package", flags);
|
|
||||||
if (!ok) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (r == -1) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
assert((size_t) r < BUFSIZE);
|
|
||||||
#undef BUFSIZE
|
|
||||||
// if r == sizeof(buf), then the output is truncated, but we don't care,
|
|
||||||
// versionName is at the beginning in practice, and is unlikely to be
|
|
||||||
// truncated at 64k
|
|
||||||
|
|
||||||
// It is parsed as a NUL-terminated string
|
|
||||||
buf[r] = '\0';
|
|
||||||
|
|
||||||
return sc_adb_parse_installed_apk_version(buf);
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -15,8 +15,6 @@
|
|||||||
|
|
||||||
#define SC_ADB_SILENT (SC_ADB_NO_STDOUT | SC_ADB_NO_STDERR | SC_ADB_NO_LOGERR)
|
#define SC_ADB_SILENT (SC_ADB_NO_STDOUT | SC_ADB_NO_STDERR | SC_ADB_NO_LOGERR)
|
||||||
|
|
||||||
#define SC_ANDROID_PACKAGE "com.genymobile.scrcpy"
|
|
||||||
|
|
||||||
const char *
|
const char *
|
||||||
sc_adb_get_executable(void);
|
sc_adb_get_executable(void);
|
||||||
|
|
||||||
@@ -116,18 +114,4 @@ sc_adb_getprop(struct sc_intr *intr, const char *serial, const char *prop,
|
|||||||
char *
|
char *
|
||||||
sc_adb_get_device_ip(struct sc_intr *intr, const char *serial, unsigned flags);
|
sc_adb_get_device_ip(struct sc_intr *intr, const char *serial, unsigned flags);
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the path of the installed APK for com.genymobile.scrcpy (if any)
|
|
||||||
*/
|
|
||||||
char *
|
|
||||||
sc_adb_get_installed_apk_path(struct sc_intr *intr, const char *serial,
|
|
||||||
unsigned flags);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the version of the installed APK for com.genymobile.scrcpy (if any)
|
|
||||||
*/
|
|
||||||
char *
|
|
||||||
sc_adb_get_installed_apk_version(struct sc_intr *intr, const char *serial,
|
|
||||||
unsigned flags);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -225,62 +225,3 @@ sc_adb_parse_device_ip(char *str) {
|
|||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *
|
|
||||||
sc_adb_parse_installed_apk_path(char *str) {
|
|
||||||
// str is expected to look like:
|
|
||||||
// "package:/data/app/.../base.apk=com.genymobile.scrcpy"
|
|
||||||
// ^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
// We want to extract the path (which may contain '=', even in practice)
|
|
||||||
|
|
||||||
if (strncmp(str, "package:", 8)) {
|
|
||||||
// Does not start with "package:"
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *s = str + 8;
|
|
||||||
size_t len = strcspn(s, " \r\n");
|
|
||||||
s[len] = '\0';
|
|
||||||
|
|
||||||
char *p = strrchr(s, '=');
|
|
||||||
if (!p) {
|
|
||||||
// No '=' found
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Truncate at the last '='
|
|
||||||
*p = '\0';
|
|
||||||
|
|
||||||
return strdup(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
char *
|
|
||||||
sc_adb_parse_installed_apk_version(const char *str) {
|
|
||||||
// str is the (beginning of the) output of `dumpsys package`
|
|
||||||
// We want to extract the version string from a line starting with 4 spaces
|
|
||||||
// then `versionName=` then the version string.
|
|
||||||
|
|
||||||
#define VERSION_NAME_PREFIX "\n versionName="
|
|
||||||
char *s = strstr(str, VERSION_NAME_PREFIX);
|
|
||||||
if (!s) {
|
|
||||||
// Not found
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
s+= sizeof(VERSION_NAME_PREFIX) - 1;
|
|
||||||
|
|
||||||
size_t len = strspn(s, "0123456789.");
|
|
||||||
if (!len) {
|
|
||||||
LOGW("Unexpected version name with no value");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *version = malloc(len + 1);
|
|
||||||
if (!version) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(version, s, len);
|
|
||||||
version[len] = '\0';
|
|
||||||
return version;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -27,24 +27,4 @@ sc_adb_parse_devices(char *str, struct sc_vec_adb_devices *out_vec);
|
|||||||
char *
|
char *
|
||||||
sc_adb_parse_device_ip(char *str);
|
sc_adb_parse_device_ip(char *str);
|
||||||
|
|
||||||
/**
|
|
||||||
* Parse the package path from the output of
|
|
||||||
* `adb shell pm list packages -f <package>`
|
|
||||||
*
|
|
||||||
* The parameter must be a NUL-terminated string.
|
|
||||||
*
|
|
||||||
* Warning: this function modifies the buffer for optimization purposes.
|
|
||||||
*/
|
|
||||||
char *
|
|
||||||
sc_adb_parse_installed_apk_path(char *str);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parse the package version from the output of
|
|
||||||
* `adb shell dumpsys package <package>`
|
|
||||||
*
|
|
||||||
* The parameter must be a NUL-terminated string.
|
|
||||||
*/
|
|
||||||
char *
|
|
||||||
sc_adb_parse_installed_apk_version(const char *str);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -115,12 +115,15 @@ sc_control_msg_serialize(const struct sc_control_msg *msg, unsigned char *buf) {
|
|||||||
return 28;
|
return 28;
|
||||||
case SC_CONTROL_MSG_TYPE_INJECT_SCROLL_EVENT:
|
case SC_CONTROL_MSG_TYPE_INJECT_SCROLL_EVENT:
|
||||||
write_position(&buf[1], &msg->inject_scroll_event.position);
|
write_position(&buf[1], &msg->inject_scroll_event.position);
|
||||||
sc_write32be(&buf[13],
|
// map [-1, 1] to [0, 1], then to uint16
|
||||||
(uint32_t) msg->inject_scroll_event.hscroll);
|
uint16_t hscroll =
|
||||||
sc_write32be(&buf[17],
|
to_fixed_point_16((msg->inject_scroll_event.hscroll + 1) / 2);
|
||||||
(uint32_t) msg->inject_scroll_event.vscroll);
|
uint16_t vscroll =
|
||||||
sc_write32be(&buf[21], msg->inject_scroll_event.buttons);
|
to_fixed_point_16((msg->inject_scroll_event.vscroll + 1) / 2);
|
||||||
return 25;
|
sc_write16be(&buf[13], hscroll);
|
||||||
|
sc_write16be(&buf[15], vscroll);
|
||||||
|
sc_write32be(&buf[17], msg->inject_scroll_event.buttons);
|
||||||
|
return 21;
|
||||||
case SC_CONTROL_MSG_TYPE_BACK_OR_SCREEN_ON:
|
case SC_CONTROL_MSG_TYPE_BACK_OR_SCREEN_ON:
|
||||||
buf[1] = msg->inject_keycode.action;
|
buf[1] = msg->inject_keycode.action;
|
||||||
return 2;
|
return 2;
|
||||||
@@ -191,8 +194,8 @@ sc_control_msg_log(const struct sc_control_msg *msg) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SC_CONTROL_MSG_TYPE_INJECT_SCROLL_EVENT:
|
case SC_CONTROL_MSG_TYPE_INJECT_SCROLL_EVENT:
|
||||||
LOG_CMSG("scroll position=%" PRIi32 ",%" PRIi32 " hscroll=%" PRIi32
|
LOG_CMSG("scroll position=%" PRIi32 ",%" PRIi32 " hscroll=%g"
|
||||||
" vscroll=%" PRIi32 " buttons=%06lx",
|
" vscroll=%g buttons=%06lx",
|
||||||
msg->inject_scroll_event.position.point.x,
|
msg->inject_scroll_event.position.point.x,
|
||||||
msg->inject_scroll_event.position.point.y,
|
msg->inject_scroll_event.position.point.y,
|
||||||
msg->inject_scroll_event.hscroll,
|
msg->inject_scroll_event.hscroll,
|
||||||
|
|||||||
@@ -68,8 +68,8 @@ struct sc_control_msg {
|
|||||||
} inject_touch_event;
|
} inject_touch_event;
|
||||||
struct {
|
struct {
|
||||||
struct sc_position position;
|
struct sc_position position;
|
||||||
int32_t hscroll;
|
float hscroll;
|
||||||
int32_t vscroll;
|
float vscroll;
|
||||||
enum android_motionevent_buttons buttons;
|
enum android_motionevent_buttons buttons;
|
||||||
} inject_scroll_event;
|
} inject_scroll_event;
|
||||||
struct {
|
struct {
|
||||||
|
|||||||
@@ -37,8 +37,8 @@ sc_demuxer_recv_packet(struct sc_demuxer *demuxer, AVPacket *packet) {
|
|||||||
// CK...... ........ ........ ........ ........ ........ ........ ........
|
// CK...... ........ ........ ........ ........ ........ ........ ........
|
||||||
// ^^<------------------------------------------------------------------->
|
// ^^<------------------------------------------------------------------->
|
||||||
// || PTS
|
// || PTS
|
||||||
// | `- config packet
|
// | `- key frame
|
||||||
// `-- key frame
|
// `-- config packet
|
||||||
|
|
||||||
uint8_t header[SC_PACKET_HEADER_SIZE];
|
uint8_t header[SC_PACKET_HEADER_SIZE];
|
||||||
ssize_t r = net_recv_all(demuxer->socket, header, SC_PACKET_HEADER_SIZE);
|
ssize_t r = net_recv_all(demuxer->socket, header, SC_PACKET_HEADER_SIZE);
|
||||||
|
|||||||
@@ -358,8 +358,8 @@ struct sc_mouse_click_event {
|
|||||||
|
|
||||||
struct sc_mouse_scroll_event {
|
struct sc_mouse_scroll_event {
|
||||||
struct sc_position position;
|
struct sc_position position;
|
||||||
int32_t hscroll;
|
float hscroll;
|
||||||
int32_t vscroll;
|
float vscroll;
|
||||||
uint8_t buttons_state; // bitwise-OR of sc_mouse_button values
|
uint8_t buttons_state; // bitwise-OR of sc_mouse_button values
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -747,8 +747,13 @@ sc_input_manager_process_mouse_wheel(struct sc_input_manager *im,
|
|||||||
.point = sc_screen_convert_window_to_frame_coords(im->screen,
|
.point = sc_screen_convert_window_to_frame_coords(im->screen,
|
||||||
mouse_x, mouse_y),
|
mouse_x, mouse_y),
|
||||||
},
|
},
|
||||||
.hscroll = event->x,
|
#if SDL_VERSION_ATLEAST(2, 0, 18)
|
||||||
.vscroll = event->y,
|
.hscroll = CLAMP(event->preciseX, -1.0f, 1.0f),
|
||||||
|
.vscroll = CLAMP(event->preciseY, -1.0f, 1.0f),
|
||||||
|
#else
|
||||||
|
.hscroll = CLAMP(event->x, -1, 1),
|
||||||
|
.vscroll = CLAMP(event->y, -1, 1),
|
||||||
|
#endif
|
||||||
.buttons_state =
|
.buttons_state =
|
||||||
sc_mouse_buttons_state_from_sdl(buttons, im->forward_all_clicks),
|
sc_mouse_buttons_state_from_sdl(buttons, im->forward_all_clicks),
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -160,8 +160,6 @@ execute_server(struct sc_server *server,
|
|||||||
const char *serial = server->serial;
|
const char *serial = server->serial;
|
||||||
assert(serial);
|
assert(serial);
|
||||||
|
|
||||||
fprintf(stderr, "=== [%s]\n", sc_adb_get_installed_apk_version(&server->intr, serial, 0));
|
|
||||||
|
|
||||||
const char *cmd[128];
|
const char *cmd[128];
|
||||||
unsigned count = 0;
|
unsigned count = 0;
|
||||||
cmd[count++] = sc_adb_get_executable();
|
cmd[count++] = sc_adb_get_executable();
|
||||||
|
|||||||
@@ -23,6 +23,11 @@ read_string(libusb_device_handle *handle, uint8_t desc_index) {
|
|||||||
|
|
||||||
// When non-negative, 'result' contains the number of bytes written
|
// When non-negative, 'result' contains the number of bytes written
|
||||||
char *s = malloc(result + 1);
|
char *s = malloc(result + 1);
|
||||||
|
if (!s) {
|
||||||
|
LOG_OOM();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
memcpy(s, buffer, result);
|
memcpy(s, buffer, result);
|
||||||
s[result] = '\0';
|
s[result] = '\0';
|
||||||
return s;
|
return s;
|
||||||
|
|||||||
@@ -241,54 +241,6 @@ static void test_get_ip_truncated(void) {
|
|||||||
assert(!ip);
|
assert(!ip);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_apk_path(void) {
|
|
||||||
char str[] = "package:/data/app/~~71mguyc6p-kNjQdNaNkToA==/com.genymobile."
|
|
||||||
"scrcpy-l6fiqqUSU7Ok7QLg-rIyJA==/base.apk=com.genymobile."
|
|
||||||
"scrcpy\n";
|
|
||||||
|
|
||||||
const char *expected = "/data/app/~~71mguyc6p-kNjQdNaNkToA==/com.genymobile"
|
|
||||||
".scrcpy-l6fiqqUSU7Ok7QLg-rIyJA==/base.apk";
|
|
||||||
char *path = sc_adb_parse_installed_apk_path(str);
|
|
||||||
assert(!strcmp(path, expected));
|
|
||||||
free(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void test_apk_path_invalid(void) {
|
|
||||||
// Does not start with "package:"
|
|
||||||
char str[] = "garbage:/data/app/~~71mguyc6p-kNjQdNaNkToA==/com.genymobile."
|
|
||||||
"scrcpy-l6fiqqUSU7Ok7QLg-rIyJA==/base.apk=com.genymobile."
|
|
||||||
"scrcpy\n";
|
|
||||||
|
|
||||||
char *path = sc_adb_parse_installed_apk_path(str);
|
|
||||||
assert(!path);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void test_apk_version(void) {
|
|
||||||
char str[] =
|
|
||||||
"Key Set Manager:\n"
|
|
||||||
" [com.genymobile.scrcpy]\n"
|
|
||||||
" Signing KeySets: 128\n"
|
|
||||||
"\n"
|
|
||||||
"Packages:\n"
|
|
||||||
" Package [com.genymobile.scrcpy] (89abcdef):\n"
|
|
||||||
" userId=12345\n"
|
|
||||||
" pkg=Package{012345 com.genymobile.scrcpy}\n"
|
|
||||||
" codePath=/data/app/~~abcdef==/com.genymobile.scrcpy-012345==\n"
|
|
||||||
" resourcePath=/data/app/~~abcdef==/com.genymobile.scrcpy-013245==\n"
|
|
||||||
" primaryCpuAbi=null\n"
|
|
||||||
" secondaryCpuAbi=null\n"
|
|
||||||
" versionCode=12400 minSdk=21 targetSdk=31\n"
|
|
||||||
" versionName=1.24\n"
|
|
||||||
" splits=[base]\n"
|
|
||||||
" apkSigningVersion=2\n"
|
|
||||||
" applicationInfo=ApplicationInfo{012345 com.genymobile.scrcpy}\n";
|
|
||||||
|
|
||||||
const char *expected = "1.24";
|
|
||||||
char *version = sc_adb_parse_installed_apk_version(str);
|
|
||||||
assert(!strcmp(version, expected));
|
|
||||||
free(version);
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
(void) argc;
|
(void) argc;
|
||||||
(void) argv;
|
(void) argv;
|
||||||
@@ -311,9 +263,5 @@ int main(int argc, char *argv[]) {
|
|||||||
test_get_ip_no_wlan_without_eol();
|
test_get_ip_no_wlan_without_eol();
|
||||||
test_get_ip_truncated();
|
test_get_ip_truncated();
|
||||||
|
|
||||||
test_apk_path();
|
|
||||||
test_apk_path_invalid();
|
|
||||||
test_apk_version();
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ android {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
|
||||||
testImplementation 'junit:junit:4.13.1'
|
testImplementation 'junit:junit:4.13.1'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -33,8 +33,8 @@ public final class ControlMessage {
|
|||||||
private long pointerId;
|
private long pointerId;
|
||||||
private float pressure;
|
private float pressure;
|
||||||
private Position position;
|
private Position position;
|
||||||
private int hScroll;
|
private float hScroll;
|
||||||
private int vScroll;
|
private float vScroll;
|
||||||
private int copyKey;
|
private int copyKey;
|
||||||
private boolean paste;
|
private boolean paste;
|
||||||
private int repeat;
|
private int repeat;
|
||||||
@@ -71,7 +71,7 @@ public final class ControlMessage {
|
|||||||
return msg;
|
return msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ControlMessage createInjectScrollEvent(Position position, int hScroll, int vScroll, int buttons) {
|
public static ControlMessage createInjectScrollEvent(Position position, float hScroll, float vScroll, int buttons) {
|
||||||
ControlMessage msg = new ControlMessage();
|
ControlMessage msg = new ControlMessage();
|
||||||
msg.type = TYPE_INJECT_SCROLL_EVENT;
|
msg.type = TYPE_INJECT_SCROLL_EVENT;
|
||||||
msg.position = position;
|
msg.position = position;
|
||||||
@@ -156,11 +156,11 @@ public final class ControlMessage {
|
|||||||
return position;
|
return position;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getHScroll() {
|
public float getHScroll() {
|
||||||
return hScroll;
|
return hScroll;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getVScroll() {
|
public float getVScroll() {
|
||||||
return vScroll;
|
return vScroll;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ public class ControlMessageReader {
|
|||||||
|
|
||||||
static final int INJECT_KEYCODE_PAYLOAD_LENGTH = 13;
|
static final int INJECT_KEYCODE_PAYLOAD_LENGTH = 13;
|
||||||
static final int INJECT_TOUCH_EVENT_PAYLOAD_LENGTH = 27;
|
static final int INJECT_TOUCH_EVENT_PAYLOAD_LENGTH = 27;
|
||||||
static final int INJECT_SCROLL_EVENT_PAYLOAD_LENGTH = 24;
|
static final int INJECT_SCROLL_EVENT_PAYLOAD_LENGTH = 20;
|
||||||
static final int BACK_OR_SCREEN_ON_LENGTH = 1;
|
static final int BACK_OR_SCREEN_ON_LENGTH = 1;
|
||||||
static final int SET_SCREEN_POWER_MODE_PAYLOAD_LENGTH = 1;
|
static final int SET_SCREEN_POWER_MODE_PAYLOAD_LENGTH = 1;
|
||||||
static final int GET_CLIPBOARD_LENGTH = 1;
|
static final int GET_CLIPBOARD_LENGTH = 1;
|
||||||
@@ -139,10 +139,7 @@ public class ControlMessageReader {
|
|||||||
int action = toUnsigned(buffer.get());
|
int action = toUnsigned(buffer.get());
|
||||||
long pointerId = buffer.getLong();
|
long pointerId = buffer.getLong();
|
||||||
Position position = readPosition(buffer);
|
Position position = readPosition(buffer);
|
||||||
// 16 bits fixed-point
|
float pressure = fixedPointToFloat(buffer.getShort());
|
||||||
int pressureInt = toUnsigned(buffer.getShort());
|
|
||||||
// convert it to a float between 0 and 1 (0x1p16f is 2^16 as float)
|
|
||||||
float pressure = pressureInt == 0xffff ? 1f : (pressureInt / 0x1p16f);
|
|
||||||
int buttons = buffer.getInt();
|
int buttons = buffer.getInt();
|
||||||
return ControlMessage.createInjectTouchEvent(action, pointerId, position, pressure, buttons);
|
return ControlMessage.createInjectTouchEvent(action, pointerId, position, pressure, buttons);
|
||||||
}
|
}
|
||||||
@@ -152,8 +149,9 @@ public class ControlMessageReader {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
Position position = readPosition(buffer);
|
Position position = readPosition(buffer);
|
||||||
int hScroll = buffer.getInt();
|
// map from [0; 1] to [-1; 1]
|
||||||
int vScroll = buffer.getInt();
|
float hScroll = fixedPointToFloat(buffer.getShort());
|
||||||
|
float vScroll = fixedPointToFloat(buffer.getShort());
|
||||||
int buttons = buffer.getInt();
|
int buttons = buffer.getInt();
|
||||||
return ControlMessage.createInjectScrollEvent(position, hScroll, vScroll, buttons);
|
return ControlMessage.createInjectScrollEvent(position, hScroll, vScroll, buttons);
|
||||||
}
|
}
|
||||||
@@ -210,4 +208,10 @@ public class ControlMessageReader {
|
|||||||
private static int toUnsigned(byte value) {
|
private static int toUnsigned(byte value) {
|
||||||
return value & 0xff;
|
return value & 0xff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static float fixedPointToFloat(short value) {
|
||||||
|
int unsignedShort = toUnsigned(value);
|
||||||
|
// convert 16 bits fixed-point to a float between 0 and 1 (0x1p16f is 2^16 as float)
|
||||||
|
return unsignedShort == 0xffff ? 1f : (unsignedShort / 0x1p16f);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -223,7 +223,7 @@ public class Controller {
|
|||||||
return device.injectEvent(event, Device.INJECT_MODE_ASYNC);
|
return device.injectEvent(event, Device.INJECT_MODE_ASYNC);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean injectScroll(Position position, int hScroll, int vScroll, int buttons) {
|
private boolean injectScroll(Position position, float hScroll, float vScroll, int buttons) {
|
||||||
long now = SystemClock.uptimeMillis();
|
long now = SystemClock.uptimeMillis();
|
||||||
Point point = device.getPhysicalPoint(position);
|
Point point = device.getPhysicalPoint(position);
|
||||||
if (point == null) {
|
if (point == null) {
|
||||||
|
|||||||
@@ -126,8 +126,8 @@ public class ControlMessageReaderTest {
|
|||||||
dos.writeInt(1026);
|
dos.writeInt(1026);
|
||||||
dos.writeShort(1080);
|
dos.writeShort(1080);
|
||||||
dos.writeShort(1920);
|
dos.writeShort(1920);
|
||||||
dos.writeInt(1);
|
dos.writeShort(0x8000);
|
||||||
dos.writeInt(-1);
|
dos.writeShort(0);
|
||||||
dos.writeInt(1);
|
dos.writeInt(1);
|
||||||
|
|
||||||
byte[] packet = bos.toByteArray();
|
byte[] packet = bos.toByteArray();
|
||||||
@@ -143,8 +143,8 @@ public class ControlMessageReaderTest {
|
|||||||
Assert.assertEquals(1026, event.getPosition().getPoint().getY());
|
Assert.assertEquals(1026, event.getPosition().getPoint().getY());
|
||||||
Assert.assertEquals(1080, event.getPosition().getScreenSize().getWidth());
|
Assert.assertEquals(1080, event.getPosition().getScreenSize().getWidth());
|
||||||
Assert.assertEquals(1920, event.getPosition().getScreenSize().getHeight());
|
Assert.assertEquals(1920, event.getPosition().getScreenSize().getHeight());
|
||||||
Assert.assertEquals(1, event.getHScroll());
|
Assert.assertEquals(0f, event.getHScroll(), 0f);
|
||||||
Assert.assertEquals(-1, event.getVScroll());
|
Assert.assertEquals(-1f, event.getVScroll(), 0f);
|
||||||
Assert.assertEquals(1, event.getButtons());
|
Assert.assertEquals(1, event.getButtons());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user