Compare commits

...

7 Commits

Author SHA1 Message Date
ca3d807e7f Use non-secure display for Android >= 12
Since Android 12, secure displays could not be created with shell
permissions anymore.

Refs commit 1fdde490fd
Fixes #2129 <https://github.com/Genymobile/scrcpy/issues/2129>
2021-02-19 17:26:40 +01:00
dce0867737 Enable NDEBUG via Meson built-in option 2021-02-17 09:54:03 +01:00
5c4c28c973 Handle im-related events from input_manager.c 2021-02-17 09:54:03 +01:00
98628f25b5 Inline window events handling
Now that all screen-related events are handled from screen.c, there is
no need for a separate method for window events.
2021-02-17 09:54:03 +01:00
e1dbe4f71c Handle screen-related events from screen.c 2021-02-17 09:54:03 +01:00
b1734ab737 Reference video buffer from screen
This paves the way to handle EVENT_NEW_FRAME from screen.c, by allowing
to call screen_update_frame() without an explicit video_buffer instance.
2021-02-17 09:54:03 +01:00
44aa7f2c88 Improve error handling in screen initialization
After the struct screen is initialized, the window and the renderer are
necessarily valid, so there is no need o check in screen_destroy().
2021-02-17 09:54:03 +01:00
8 changed files with 130 additions and 126 deletions

View File

@ -99,9 +99,6 @@ foreach f : check_functions
endif endif
endforeach endforeach
# expose the build type
conf.set('NDEBUG', get_option('buildtype') != 'debug')
# the version, updated on release # the version, updated on release
conf.set_quoted('SCRCPY_VERSION', meson.project_version()) conf.set_quoted('SCRCPY_VERSION', meson.project_version())

View File

@ -286,7 +286,7 @@ rotate_client_right(struct screen *screen) {
screen_set_rotation(screen, new_rotation); screen_set_rotation(screen, new_rotation);
} }
void static void
input_manager_process_text_input(struct input_manager *im, input_manager_process_text_input(struct input_manager *im,
const SDL_TextInputEvent *event) { const SDL_TextInputEvent *event) {
if (is_shortcut_mod(im, SDL_GetModState())) { if (is_shortcut_mod(im, SDL_GetModState())) {
@ -366,7 +366,7 @@ convert_input_key(const SDL_KeyboardEvent *from, struct control_msg *to,
return true; return true;
} }
void static void
input_manager_process_key(struct input_manager *im, input_manager_process_key(struct input_manager *im,
const SDL_KeyboardEvent *event) { const SDL_KeyboardEvent *event) {
// control: indicates the state of the command-line option --no-control // control: indicates the state of the command-line option --no-control
@ -551,7 +551,7 @@ convert_mouse_motion(const SDL_MouseMotionEvent *from, struct screen *screen,
return true; return true;
} }
void static void
input_manager_process_mouse_motion(struct input_manager *im, input_manager_process_mouse_motion(struct input_manager *im,
const SDL_MouseMotionEvent *event) { const SDL_MouseMotionEvent *event) {
if (!event->state) { if (!event->state) {
@ -605,7 +605,7 @@ convert_touch(const SDL_TouchFingerEvent *from, struct screen *screen,
return true; return true;
} }
void static void
input_manager_process_touch(struct input_manager *im, input_manager_process_touch(struct input_manager *im,
const SDL_TouchFingerEvent *event) { const SDL_TouchFingerEvent *event) {
struct control_msg msg; struct control_msg msg;
@ -637,7 +637,7 @@ convert_mouse_button(const SDL_MouseButtonEvent *from, struct screen *screen,
return true; return true;
} }
void static void
input_manager_process_mouse_button(struct input_manager *im, input_manager_process_mouse_button(struct input_manager *im,
const SDL_MouseButtonEvent *event) { const SDL_MouseButtonEvent *event) {
bool control = im->control; bool control = im->control;
@ -736,7 +736,7 @@ convert_mouse_wheel(const SDL_MouseWheelEvent *from, struct screen *screen,
return true; return true;
} }
void static void
input_manager_process_mouse_wheel(struct input_manager *im, input_manager_process_mouse_wheel(struct input_manager *im,
const SDL_MouseWheelEvent *event) { const SDL_MouseWheelEvent *event) {
struct control_msg msg; struct control_msg msg;
@ -746,3 +746,46 @@ input_manager_process_mouse_wheel(struct input_manager *im,
} }
} }
} }
bool
input_manager_handle_event(struct input_manager *im, SDL_Event *event) {
switch (event->type) {
case SDL_TEXTINPUT:
if (!im->control) {
return true;
}
input_manager_process_text_input(im, &event->text);
return true;
case SDL_KEYDOWN:
case SDL_KEYUP:
// some key events do not interact with the device, so process the
// event even if control is disabled
input_manager_process_key(im, &event->key);
return true;
case SDL_MOUSEMOTION:
if (!im->control) {
break;
}
input_manager_process_mouse_motion(im, &event->motion);
return true;
case SDL_MOUSEWHEEL:
if (!im->control) {
break;
}
input_manager_process_mouse_wheel(im, &event->wheel);
return true;
case SDL_MOUSEBUTTONDOWN:
case SDL_MOUSEBUTTONUP:
// some mouse events do not interact with the device, so process
// the event even if control is disabled
input_manager_process_mouse_button(im, &event->button);
return true;
case SDL_FINGERMOTION:
case SDL_FINGERDOWN:
case SDL_FINGERUP:
input_manager_process_touch(im, &event->tfinger);
return true;
}
return false;
}

View File

@ -40,28 +40,7 @@ void
input_manager_init(struct input_manager *im, input_manager_init(struct input_manager *im,
const struct scrcpy_options *options); const struct scrcpy_options *options);
void bool
input_manager_process_text_input(struct input_manager *im, input_manager_handle_event(struct input_manager *im, SDL_Event *event);
const SDL_TextInputEvent *event);
void
input_manager_process_key(struct input_manager *im,
const SDL_KeyboardEvent *event);
void
input_manager_process_mouse_motion(struct input_manager *im,
const SDL_MouseMotionEvent *event);
void
input_manager_process_touch(struct input_manager *im,
const SDL_TouchFingerEvent *event);
void
input_manager_process_mouse_button(struct input_manager *im,
const SDL_MouseButtonEvent *event);
void
input_manager_process_mouse_wheel(struct input_manager *im,
const SDL_MouseWheelEvent *event);
#endif #endif

View File

@ -30,7 +30,7 @@
#include "util/net.h" #include "util/net.h"
static struct server server; static struct server server;
static struct screen screen = SCREEN_INITIALIZER; static struct screen screen;
static struct fps_counter fps_counter; static struct fps_counter fps_counter;
static struct video_buffer video_buffer; static struct video_buffer video_buffer;
static struct stream stream; static struct stream stream;
@ -173,56 +173,6 @@ handle_event(SDL_Event *event, const struct scrcpy_options *options) {
case SDL_QUIT: case SDL_QUIT:
LOGD("User requested to quit"); LOGD("User requested to quit");
return EVENT_RESULT_STOPPED_BY_USER; return EVENT_RESULT_STOPPED_BY_USER;
case EVENT_NEW_FRAME:
if (!screen.has_frame) {
screen.has_frame = true;
// this is the very first frame, show the window
screen_show_window(&screen);
}
if (!screen_update_frame(&screen, &video_buffer)) {
return EVENT_RESULT_CONTINUE;
}
break;
case SDL_WINDOWEVENT:
if (screen.has_frame) {
screen_handle_window_event(&screen, &event->window);
}
break;
case SDL_TEXTINPUT:
if (!options->control) {
break;
}
input_manager_process_text_input(&input_manager, &event->text);
break;
case SDL_KEYDOWN:
case SDL_KEYUP:
// some key events do not interact with the device, so process the
// event even if control is disabled
input_manager_process_key(&input_manager, &event->key);
break;
case SDL_MOUSEMOTION:
if (!options->control) {
break;
}
input_manager_process_mouse_motion(&input_manager, &event->motion);
break;
case SDL_MOUSEWHEEL:
if (!options->control) {
break;
}
input_manager_process_mouse_wheel(&input_manager, &event->wheel);
break;
case SDL_MOUSEBUTTONDOWN:
case SDL_MOUSEBUTTONUP:
// some mouse events do not interact with the device, so process
// the event even if control is disabled
input_manager_process_mouse_button(&input_manager, &event->button);
break;
case SDL_FINGERMOTION:
case SDL_FINGERDOWN:
case SDL_FINGERUP:
input_manager_process_touch(&input_manager, &event->tfinger);
break;
case SDL_DROPFILE: { case SDL_DROPFILE: {
if (!options->control) { if (!options->control) {
break; break;
@ -244,6 +194,16 @@ handle_event(SDL_Event *event, const struct scrcpy_options *options) {
break; break;
} }
} }
bool consumed = screen_handle_event(&screen, event);
if (consumed) {
goto end;
}
consumed = input_manager_handle_event(&input_manager, event);
(void) consumed;
end:
return EVENT_RESULT_CONTINUE; return EVENT_RESULT_CONTINUE;
} }
@ -429,6 +389,8 @@ scrcpy(const struct scrcpy_options *options) {
const char *window_title = const char *window_title =
options->window_title ? options->window_title : device_name; options->window_title ? options->window_title : device_name;
screen_init(&screen, &video_buffer);
if (!screen_init_rendering(&screen, window_title, frame_size, if (!screen_init_rendering(&screen, window_title, frame_size,
options->always_on_top, options->window_x, options->always_on_top, options->window_x,
options->window_y, options->window_width, options->window_y, options->window_width,

View File

@ -4,6 +4,7 @@
#include <string.h> #include <string.h>
#include <SDL2/SDL.h> #include <SDL2/SDL.h>
#include "events.h"
#include "icon.xpm" #include "icon.xpm"
#include "scrcpy.h" #include "scrcpy.h"
#include "tiny_xpm.h" #include "tiny_xpm.h"
@ -191,8 +192,9 @@ screen_update_content_rect(struct screen *screen) {
} }
void void
screen_init(struct screen *screen) { screen_init(struct screen *screen, struct video_buffer *vb) {
*screen = (struct screen) SCREEN_INITIALIZER; *screen = (struct screen) SCREEN_INITIALIZER;
screen->vb = vb;
} }
static inline SDL_Texture * static inline SDL_Texture *
@ -270,7 +272,7 @@ screen_init_rendering(struct screen *screen, const char *window_title,
SDL_RENDERER_ACCELERATED); SDL_RENDERER_ACCELERATED);
if (!screen->renderer) { if (!screen->renderer) {
LOGC("Could not create renderer: %s", SDL_GetError()); LOGC("Could not create renderer: %s", SDL_GetError());
screen_destroy(screen); SDL_DestroyWindow(screen->window);
return false; return false;
} }
@ -318,6 +320,8 @@ screen_init_rendering(struct screen *screen, const char *window_title,
screen->texture = create_texture(screen); screen->texture = create_texture(screen);
if (!screen->texture) { if (!screen->texture) {
LOGC("Could not create texture: %s", SDL_GetError()); LOGC("Could not create texture: %s", SDL_GetError());
SDL_DestroyRenderer(screen->renderer);
SDL_DestroyWindow(screen->window);
screen_destroy(screen); screen_destroy(screen);
return false; return false;
} }
@ -342,12 +346,8 @@ screen_destroy(struct screen *screen) {
if (screen->texture) { if (screen->texture) {
SDL_DestroyTexture(screen->texture); SDL_DestroyTexture(screen->texture);
} }
if (screen->renderer) { SDL_DestroyRenderer(screen->renderer);
SDL_DestroyRenderer(screen->renderer); SDL_DestroyWindow(screen->window);
}
if (screen->window) {
SDL_DestroyWindow(screen->window);
}
} }
static void static void
@ -450,9 +450,9 @@ update_texture(struct screen *screen, const AVFrame *frame) {
} }
} }
bool static bool
screen_update_frame(struct screen *screen, struct video_buffer *vb) { screen_update_frame(struct screen *screen) {
const AVFrame *frame = video_buffer_take_rendering_frame(vb); const AVFrame *frame = video_buffer_take_rendering_frame(screen->vb);
struct size new_frame_size = {frame->width, frame->height}; struct size new_frame_size = {frame->width, frame->height};
if (!prepare_for_frame(screen, new_frame_size)) { if (!prepare_for_frame(screen, new_frame_size)) {
return false; return false;
@ -544,31 +544,52 @@ screen_resize_to_pixel_perfect(struct screen *screen) {
content_size.height); content_size.height);
} }
void bool
screen_handle_window_event(struct screen *screen, screen_handle_event(struct screen *screen, SDL_Event *event) {
const SDL_WindowEvent *event) { switch (event->type) {
switch (event->event) { case EVENT_NEW_FRAME:
case SDL_WINDOWEVENT_EXPOSED: if (!screen->has_frame) {
screen_render(screen, true); screen->has_frame = true;
break; // this is the very first frame, show the window
case SDL_WINDOWEVENT_SIZE_CHANGED: screen_show_window(screen);
screen_render(screen, true);
break;
case SDL_WINDOWEVENT_MAXIMIZED:
screen->maximized = true;
break;
case SDL_WINDOWEVENT_RESTORED:
if (screen->fullscreen) {
// On Windows, in maximized+fullscreen, disabling fullscreen
// mode unexpectedly triggers the "restored" then "maximized"
// events, leaving the window in a weird state (maximized
// according to the events, but not maximized visually).
break;
} }
screen->maximized = false; bool ok = screen_update_frame(screen);
apply_pending_resize(screen); if (!ok) {
break; LOGW("Frame update failed\n");
}
return true;
case SDL_WINDOWEVENT:
if (!screen->has_frame) {
// Do nothing
return true;
}
switch (event->window.event) {
case SDL_WINDOWEVENT_EXPOSED:
screen_render(screen, true);
break;
case SDL_WINDOWEVENT_SIZE_CHANGED:
screen_render(screen, true);
break;
case SDL_WINDOWEVENT_MAXIMIZED:
screen->maximized = true;
break;
case SDL_WINDOWEVENT_RESTORED:
if (screen->fullscreen) {
// On Windows, in maximized+fullscreen, disabling
// fullscreen mode unexpectedly triggers the "restored"
// then "maximized" events, leaving the window in a
// weird state (maximized according to the events, but
// not maximized visually).
break;
}
screen->maximized = false;
apply_pending_resize(screen);
break;
}
return true;
} }
return false;
} }
struct point struct point

View File

@ -13,6 +13,7 @@
struct video_buffer; struct video_buffer;
struct screen { struct screen {
struct video_buffer *vb;
SDL_Window *window; SDL_Window *window;
SDL_Renderer *renderer; SDL_Renderer *renderer;
SDL_Texture *texture; SDL_Texture *texture;
@ -37,6 +38,7 @@ struct screen {
}; };
#define SCREEN_INITIALIZER { \ #define SCREEN_INITIALIZER { \
.vb = NULL, \
.window = NULL, \ .window = NULL, \
.renderer = NULL, \ .renderer = NULL, \
.texture = NULL, \ .texture = NULL, \
@ -70,7 +72,7 @@ struct screen {
// initialize default values // initialize default values
void void
screen_init(struct screen *screen); screen_init(struct screen *screen, struct video_buffer *vb);
// initialize screen, create window, renderer and texture (window is hidden) // initialize screen, create window, renderer and texture (window is hidden)
// window_x and window_y accept SC_WINDOW_POSITION_UNDEFINED // window_x and window_y accept SC_WINDOW_POSITION_UNDEFINED
@ -89,10 +91,6 @@ screen_show_window(struct screen *screen);
void void
screen_destroy(struct screen *screen); screen_destroy(struct screen *screen);
// resize if necessary and write the rendered frame into the texture
bool
screen_update_frame(struct screen *screen, struct video_buffer *vb);
// render the texture to the renderer // render the texture to the renderer
// //
// Set the update_content_rect flag if the window or content size may have // Set the update_content_rect flag if the window or content size may have
@ -116,9 +114,9 @@ screen_resize_to_pixel_perfect(struct screen *screen);
void void
screen_set_rotation(struct screen *screen, unsigned rotation); screen_set_rotation(struct screen *screen, unsigned rotation);
// react to window events // react to SDL events
void bool
screen_handle_window_event(struct screen *screen, const SDL_WindowEvent *event); screen_handle_event(struct screen *screen, SDL_Event *event);
// convert point from window coordinates to frame coordinates // convert point from window coordinates to frame coordinates
// x and y are expressed in pixels // x and y are expressed in pixels

View File

@ -4,6 +4,7 @@ project('scrcpy', 'c',
default_options: [ default_options: [
'c_std=c11', 'c_std=c11',
'warning_level=2', 'warning_level=2',
'b_ndebug=if-release',
]) ])
if get_option('compile_app') if get_option('compile_app')

View File

@ -7,6 +7,7 @@ import android.media.MediaCodec;
import android.media.MediaCodecInfo; import android.media.MediaCodecInfo;
import android.media.MediaCodecList; import android.media.MediaCodecList;
import android.media.MediaFormat; import android.media.MediaFormat;
import android.os.Build;
import android.os.IBinder; import android.os.IBinder;
import android.view.Surface; import android.view.Surface;
@ -225,7 +226,9 @@ public class ScreenEncoder implements Device.RotationListener {
} }
private static IBinder createDisplay() { private static IBinder createDisplay() {
return SurfaceControl.createDisplay("scrcpy", true); // Since Android 12, secure displays could not be created with shell permissions anymore
boolean secure = Build.VERSION.SDK_INT <= Build.VERSION_CODES.R;
return SurfaceControl.createDisplay("scrcpy", secure);
} }
private static void configure(MediaCodec codec, MediaFormat format) { private static void configure(MediaCodec codec, MediaFormat format) {