Skip to content

Commit f7bc0bd

Browse files
committed
Merge branch 'dev' into release
2 parents e69f6f7 + 8a3c6a3 commit f7bc0bd

File tree

22 files changed

+333
-92
lines changed

22 files changed

+333
-92
lines changed

README.md

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -243,20 +243,23 @@ To run without installing:
243243

244244
## Shortcuts
245245

246-
| Action | Shortcut |
247-
| ------------------------------------- | -------------:|
248-
| switch fullscreen mode | `Ctrl`+`f` |
249-
| resize window to 1:1 (pixel-perfect) | `Ctrl`+`g` |
250-
| resize window to remove black borders | `Ctrl`+`x` |
251-
| click on `HOME` | `Ctrl`+`h` |
252-
| click on `BACK` | `Ctrl`+`b` |
253-
| click on `APP_SWITCH` | `Ctrl`+`m` |
254-
| click on `VOLUME_UP` | `Ctrl`+`+` |
255-
| click on `VOLUME_DOWN` | `Ctrl`+`-` |
256-
| click on `POWER` | `Ctrl`+`p` |
257-
| turn screen on | _Right-click_ |
258-
| paste computer clipboard to device | `Ctrl`+`v` |
259-
| enable/disable FPS counter (on stdout) | `Ctrl`+`i` |
246+
| Action | Shortcut |
247+
| -------------------------------------- |:---------------------------- |
248+
| switch fullscreen mode | `Ctrl`+`f` |
249+
| resize window to 1:1 (pixel-perfect) | `Ctrl`+`g` |
250+
| resize window to remove black borders | `Ctrl`+`x` \| _Double-click¹_ |
251+
| click on `HOME` | `Ctrl`+`h` \| _Middle-click_ |
252+
| click on `BACK` | `Ctrl`+`b` \| _Right-click²_ |
253+
| click on `APP_SWITCH` | `Ctrl`+`m` |
254+
| click on `VOLUME_UP` | `Ctrl`+`+` |
255+
| click on `VOLUME_DOWN` | `Ctrl`+`-` |
256+
| click on `POWER` | `Ctrl`+`p` |
257+
| turn screen on | _Right-click¹_ |
258+
| paste computer clipboard to device | `Ctrl`+`v` |
259+
| enable/disable FPS counter (on stdout) | `Ctrl`+`i` |
260+
261+
_¹Double-click on black borders to remove them._
262+
_²Right-click turns the screen on if it was off, presses BACK otherwise._
260263

261264

262265
## Why _scrcpy_?

app/src/command.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,13 @@ process_t adb_forward(const char *serial, uint16_t local_port, const char *devic
4545
return adb_execute(serial, adb_cmd, ARRAY_LEN(adb_cmd));
4646
}
4747

48+
process_t adb_forward_remove(const char *serial, uint16_t local_port) {
49+
char local[4 + 5 + 1]; // tcp:PORT
50+
sprintf(local, "tcp:%" PRIu16, local_port);
51+
const char *const adb_cmd[] = {"forward", "--remove", local};
52+
return adb_execute(serial, adb_cmd, ARRAY_LEN(adb_cmd));
53+
}
54+
4855
process_t adb_reverse(const char *serial, const char *device_socket_name, uint16_t local_port) {
4956
char local[4 + 5 + 1]; // tcp:PORT
5057
char remote[108 + 14 + 1]; // localabstract:NAME

app/src/command.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ SDL_bool cmd_simple_wait(process_t pid, exit_code_t *exit_code);
3939

4040
process_t adb_execute(const char *serial, const char *const adb_cmd[], int len);
4141
process_t adb_forward(const char *serial, uint16_t local_port, const char *device_socket_name);
42+
process_t adb_forward_remove(const char *serial, uint16_t local_port);
4243
process_t adb_reverse(const char *serial, const char *device_socket_name, uint16_t local_port);
4344
process_t adb_reverse_remove(const char *serial, const char *device_socket_name);
4445
process_t adb_push(const char *serial, const char *local, const char *remote);

app/src/controlevent.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,9 @@ int control_event_serialize(const struct control_event *event, unsigned char *bu
3939
// injecting a text takes time, so limit the text length
4040
len = TEXT_MAX_LENGTH;
4141
}
42-
buf[1] = (Uint8) len;
43-
memcpy(&buf[2], event->text_event.text, len);
44-
return 2 + len;
42+
write16(&buf[1], (Uint16) len);
43+
memcpy(&buf[3], event->text_event.text, len);
44+
return 3 + len;
4545
}
4646
case CONTROL_EVENT_TYPE_MOUSE:
4747
buf[1] = event->mouse_event.action;

app/src/controlevent.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@
99
#include "common.h"
1010

1111
#define CONTROL_EVENT_QUEUE_SIZE 64
12-
#define SERIALIZED_EVENT_MAX_SIZE 33
13-
#define TEXT_MAX_LENGTH 256
12+
#define TEXT_MAX_LENGTH 300
13+
#define SERIALIZED_EVENT_MAX_SIZE 3 + TEXT_MAX_LENGTH
1414

1515
enum control_event_type {
1616
CONTROL_EVENT_TYPE_KEYCODE,
@@ -20,7 +20,7 @@ enum control_event_type {
2020
CONTROL_EVENT_TYPE_COMMAND,
2121
};
2222

23-
#define CONTROL_EVENT_COMMAND_SCREEN_ON 0
23+
#define CONTROL_EVENT_COMMAND_BACK_OR_SCREEN_ON 0
2424

2525
struct control_event {
2626
enum control_event_type type;

app/src/inputmanager.c

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -78,10 +78,11 @@ static inline void action_volume_down(struct controller *controller) {
7878
send_keycode(controller, AKEYCODE_VOLUME_DOWN, "VOLUME_DOWN");
7979
}
8080

81-
static void turn_screen_on(struct controller *controller) {
81+
// turn the screen on if it was off, press BACK otherwise
82+
static void press_back_or_turn_screen_on(struct controller *controller) {
8283
struct control_event control_event;
8384
control_event.type = CONTROL_EVENT_TYPE_COMMAND;
84-
control_event.command_event.action = CONTROL_EVENT_COMMAND_SCREEN_ON;
85+
control_event.command_event.action = CONTROL_EVENT_COMMAND_BACK_OR_SCREEN_ON;
8586

8687
if (!controller_push_event(controller, &control_event)) {
8788
LOGW("Cannot turn screen on");
@@ -225,9 +226,25 @@ void input_manager_process_mouse_motion(struct input_manager *input_manager,
225226

226227
void input_manager_process_mouse_button(struct input_manager *input_manager,
227228
const SDL_MouseButtonEvent *event) {
228-
if (event->button == SDL_BUTTON_RIGHT && event->type == SDL_MOUSEBUTTONDOWN) {
229-
turn_screen_on(input_manager->controller);
230-
return;
229+
if (event->type == SDL_MOUSEBUTTONDOWN) {
230+
if (event->button == SDL_BUTTON_RIGHT) {
231+
press_back_or_turn_screen_on(input_manager->controller);
232+
return;
233+
}
234+
if (event->button == SDL_BUTTON_MIDDLE) {
235+
action_home(input_manager->controller);
236+
return;
237+
}
238+
// double-click on black borders resize to fit the device screen
239+
if (event->button == SDL_BUTTON_LEFT && event->clicks == 2) {
240+
SDL_bool outside_device_screen =
241+
event->x < 0 || event->x >= input_manager->screen->frame_size.width ||
242+
event->y < 0 || event->y >= input_manager->screen->frame_size.height;
243+
if (outside_device_screen) {
244+
screen_resize_to_fit(input_manager->screen);
245+
}
246+
return;
247+
}
231248
};
232249
struct control_event control_event;
233250
if (mouse_button_from_sdl_to_android(event, input_manager->screen->frame_size, &control_event)) {

app/src/main.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,14 +57,17 @@ static void usage(const char *arg0) {
5757
" resize window to 1:1 (pixel-perfect)\n"
5858
"\n"
5959
" Ctrl+x\n"
60+
" Double-click on black borders\n"
6061
" resize window to remove black borders\n"
6162
"\n"
6263
" Ctrl+h\n"
6364
" Home\n"
65+
" Middle-click\n"
6466
" click on HOME\n"
6567
"\n"
6668
" Ctrl+b\n"
6769
" Ctrl+Backspace\n"
70+
" Right-click (when screen is on)\n"
6871
" click on BACK\n"
6972
"\n"
7073
" Ctrl+m\n"
@@ -79,7 +82,7 @@ static void usage(const char *arg0) {
7982
" Ctrl+p\n"
8083
" click on POWER (turn screen on/off)\n"
8184
"\n"
82-
" Right-click\n"
85+
" Right-click (when screen is off)\n"
8386
" turn screen on\n"
8487
"\n"
8588
" Ctrl+v\n"

app/src/net.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,26 @@
1818
typedef struct in_addr IN_ADDR;
1919
#endif
2020

21+
socket_t net_connect(Uint32 addr, Uint16 port) {
22+
socket_t sock = socket(AF_INET, SOCK_STREAM, 0);
23+
if (sock == INVALID_SOCKET) {
24+
perror("socket");
25+
return INVALID_SOCKET;
26+
}
27+
28+
SOCKADDR_IN sin;
29+
sin.sin_family = AF_INET;
30+
sin.sin_addr.s_addr = htonl(addr);
31+
sin.sin_port = htons(port);
32+
33+
if (connect(sock, (SOCKADDR *) &sin, sizeof(sin)) == SOCKET_ERROR) {
34+
perror("connect");
35+
return INVALID_SOCKET;
36+
}
37+
38+
return sock;
39+
}
40+
2141
socket_t net_listen(Uint32 addr, Uint16 port, int backlog) {
2242
socket_t sock = socket(AF_INET, SOCK_STREAM, 0);
2343
if (sock == INVALID_SOCKET) {

app/src/net.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
SDL_bool net_init(void);
2222
void net_cleanup(void);
2323

24+
socket_t net_connect(Uint32 addr, Uint16 port);
2425
socket_t net_listen(Uint32 addr, Uint16 port, int backlog);
2526
socket_t net_accept(socket_t server_socket);
2627

app/src/scrcpy.c

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,29 @@ static struct input_manager input_manager = {
3535
.screen = &screen,
3636
};
3737

38+
#if defined(__APPLE__) || defined(__WINDOWS__)
39+
# define CONTINUOUS_RESIZING_WORKAROUND
40+
#endif
41+
42+
#ifdef CONTINUOUS_RESIZING_WORKAROUND
43+
// On Windows and MacOS, resizing blocks the event loop, so resizing events are
44+
// not triggered. As a workaround, handle them in an event handler.
45+
//
46+
// <https://bugzilla.libsdl.org/show_bug.cgi?id=2077>
47+
// <https://stackoverflow.com/a/40693139/1987178>
48+
static int event_watcher(void *data, SDL_Event *event) {
49+
if (event->type == SDL_WINDOWEVENT && event->window.event == SDL_WINDOWEVENT_RESIZED) {
50+
// called from another thread, not very safe, but it's a workaround!
51+
screen_render(&screen);
52+
}
53+
return 0;
54+
}
55+
#endif
56+
3857
static void event_loop(void) {
58+
#ifdef CONTINUOUS_RESIZING_WORKAROUND
59+
SDL_AddEventWatch(event_watcher, NULL);
60+
#endif
3961
SDL_Event event;
4062
while (SDL_WaitEvent(&event)) {
4163
switch (event.type) {
@@ -103,9 +125,9 @@ SDL_bool scrcpy(const char *serial, Uint16 local_port, Uint16 max_size, Uint32 b
103125
// managed by the event loop. This blocking call blocks the event loop, so
104126
// timeout the connection not to block indefinitely in case of SIGTERM.
105127
#define SERVER_CONNECT_TIMEOUT_MS 2000
106-
socket_t device_socket = server_connect_to(&server, serial, SERVER_CONNECT_TIMEOUT_MS);
128+
socket_t device_socket = server_connect_to(&server, SERVER_CONNECT_TIMEOUT_MS);
107129
if (device_socket == INVALID_SOCKET) {
108-
server_stop(&server, serial);
130+
server_stop(&server);
109131
ret = SDL_FALSE;
110132
goto finally_destroy_server;
111133
}
@@ -117,13 +139,13 @@ SDL_bool scrcpy(const char *serial, Uint16 local_port, Uint16 max_size, Uint32 b
117139
// therefore, we transmit the screen size before the video stream, to be able
118140
// to init the window immediately
119141
if (!device_read_info(device_socket, device_name, &frame_size)) {
120-
server_stop(&server, serial);
142+
server_stop(&server);
121143
ret = SDL_FALSE;
122144
goto finally_destroy_server;
123145
}
124146

125147
if (!frames_init(&frames)) {
126-
server_stop(&server, serial);
148+
server_stop(&server);
127149
ret = SDL_FALSE;
128150
goto finally_destroy_server;
129151
}
@@ -134,7 +156,7 @@ SDL_bool scrcpy(const char *serial, Uint16 local_port, Uint16 max_size, Uint32 b
134156
// start the decoder
135157
if (!decoder_start(&decoder)) {
136158
ret = SDL_FALSE;
137-
server_stop(&server, serial);
159+
server_stop(&server);
138160
goto finally_destroy_frames;
139161
}
140162

@@ -165,7 +187,7 @@ SDL_bool scrcpy(const char *serial, Uint16 local_port, Uint16 max_size, Uint32 b
165187
finally_stop_decoder:
166188
decoder_stop(&decoder);
167189
// stop the server before decoder_join() to wake up the decoder
168-
server_stop(&server, serial);
190+
server_stop(&server);
169191
decoder_join(&decoder);
170192
finally_destroy_frames:
171193
frames_destroy(&frames);

0 commit comments

Comments
 (0)