diff --git a/app/src/event_converter.c b/app/src/event_converter.c index 13abfab2..69ecf624 100644 --- a/app/src/event_converter.c +++ b/app/src/event_converter.c @@ -176,19 +176,30 @@ convert_mouse_action(SDL_EventType from, enum android_motionevent_action *to) { } } +static inline void +map_coords(int32_t *x, int32_t *y, const SDL_Rect *rect, + struct size frame_size) { + *x = (*x - rect->x) * frame_size.width / rect->w; + *y = (*y - rect->y) * frame_size.height / rect->h; +} + bool -convert_mouse_button(const SDL_MouseButtonEvent *from, struct size screen_size, - struct control_msg *to) { +convert_mouse_button(const SDL_MouseButtonEvent *from, const SDL_Rect *rect, + struct size frame_size, struct control_msg *to) { to->type = CONTROL_MSG_TYPE_INJECT_TOUCH_EVENT; if (!convert_mouse_action(from->type, &to->inject_touch_event.action)) { return false; } + int32_t x = from->x; + int32_t y = from->y; + map_coords(&x, &y, rect, frame_size); + to->inject_touch_event.pointer_id = POINTER_ID_MOUSE; - to->inject_touch_event.position.screen_size = screen_size; - to->inject_touch_event.position.point.x = from->x; - to->inject_touch_event.position.point.y = from->y; + to->inject_touch_event.position.screen_size = frame_size; + to->inject_touch_event.position.point.x = x; + to->inject_touch_event.position.point.y = y; to->inject_touch_event.pressure = 1.f; to->inject_touch_event.buttons = convert_mouse_buttons(SDL_BUTTON(from->button)); @@ -197,14 +208,18 @@ convert_mouse_button(const SDL_MouseButtonEvent *from, struct size screen_size, } bool -convert_mouse_motion(const SDL_MouseMotionEvent *from, struct size screen_size, - struct control_msg *to) { +convert_mouse_motion(const SDL_MouseMotionEvent *from, const SDL_Rect *rect, + struct size frame_size, struct control_msg *to) { + int32_t x = from->x; + int32_t y = from->y; + map_coords(&x, &y, rect, frame_size); + to->type = CONTROL_MSG_TYPE_INJECT_TOUCH_EVENT; to->inject_touch_event.action = AMOTION_EVENT_ACTION_MOVE; to->inject_touch_event.pointer_id = POINTER_ID_MOUSE; - to->inject_touch_event.position.screen_size = screen_size; - to->inject_touch_event.position.point.x = from->x; - to->inject_touch_event.position.point.y = from->y; + to->inject_touch_event.position.screen_size = frame_size; + to->inject_touch_event.position.point.x = x; + to->inject_touch_event.position.point.y = y; to->inject_touch_event.pressure = 1.f; to->inject_touch_event.buttons = convert_mouse_buttons(from->state); @@ -245,6 +260,7 @@ convert_mouse_wheel(const SDL_MouseWheelEvent *from, struct position position, struct control_msg *to) { to->type = CONTROL_MSG_TYPE_INJECT_SCROLL_EVENT; + // TODO map coords to->inject_scroll_event.position = position; int mul = from->direction == SDL_MOUSEWHEEL_NORMAL ? 1 : -1; diff --git a/app/src/event_converter.h b/app/src/event_converter.h index f6f136a3..4f9d8821 100644 --- a/app/src/event_converter.h +++ b/app/src/event_converter.h @@ -21,14 +21,14 @@ bool convert_input_key(const SDL_KeyboardEvent *from, struct control_msg *to); bool -convert_mouse_button(const SDL_MouseButtonEvent *from, struct size screen_size, - struct control_msg *to); +convert_mouse_button(const SDL_MouseButtonEvent *from, const SDL_Rect *rect, + struct size frame_size, struct control_msg *to); // the video size may be different from the real device size, so we need the // size to which the absolute position apply, to scale it accordingly bool -convert_mouse_motion(const SDL_MouseMotionEvent *from, struct size screen_size, - struct control_msg *to); +convert_mouse_motion(const SDL_MouseMotionEvent *from, const SDL_Rect *rect, + struct size frame_size, struct control_msg *to); bool convert_touch(const SDL_TouchFingerEvent *from, struct size screen_size, diff --git a/app/src/input_manager.c b/app/src/input_manager.c index db15da75..2dd9197b 100644 --- a/app/src/input_manager.c +++ b/app/src/input_manager.c @@ -394,7 +394,7 @@ input_manager_process_mouse_motion(struct input_manager *input_manager, return; } struct control_msg msg; - if (convert_mouse_motion(event, input_manager->screen->frame_size, &msg)) { + if (convert_mouse_motion(event, &input_manager->screen->rect, input_manager->screen->frame_size, &msg)) { if (!controller_push_msg(input_manager->controller, &msg)) { LOGW("Could not request 'inject mouse motion event'"); } @@ -453,7 +453,7 @@ input_manager_process_mouse_button(struct input_manager *input_manager, } struct control_msg msg; - if (convert_mouse_button(event, input_manager->screen->frame_size, &msg)) { + if (convert_mouse_button(event, &input_manager->screen->rect, input_manager->screen->frame_size, &msg)) { if (!controller_push_msg(input_manager->controller, &msg)) { LOGW("Could not request 'inject mouse button event'"); } diff --git a/app/src/scrcpy.c b/app/src/scrcpy.c index c219c9e5..831380f4 100644 --- a/app/src/scrcpy.c +++ b/app/src/scrcpy.c @@ -145,9 +145,11 @@ handle_event(SDL_Event *event, bool control) { case SDL_WINDOWEVENT: switch (event->window.event) { case SDL_WINDOWEVENT_EXPOSED: - case SDL_WINDOWEVENT_SIZE_CHANGED: screen_render(&screen); break; + case SDL_WINDOWEVENT_SIZE_CHANGED: + screen_resized(&screen); + break; } break; case SDL_TEXTINPUT: diff --git a/app/src/screen.c b/app/src/screen.c index e34bcf46..51bc00a0 100644 --- a/app/src/screen.c +++ b/app/src/screen.c @@ -122,6 +122,32 @@ get_initial_optimal_size(struct size frame_size) { return get_optimal_size(frame_size, frame_size); } +static void +update_frame_rect(struct screen *screen) { + struct size window_size = get_window_size(screen); + + // 32 bits because we need to multiply two 16 bits values + uint32_t ww = window_size.width; + uint32_t wh = window_size.height; + uint32_t fw = screen->frame_size.width; + uint32_t fh = screen->frame_size.height; + + SDL_Rect *rect = &screen->rect; + + bool keep_width = fw * wh > fh * ww; + if (keep_width) { + rect->x = 0; + rect->w = ww; + rect->h = ww * fh / fw; + rect->y = (wh - rect->h) / 2; + } else { + rect->y = 0; + rect->h = wh; + rect->w = wh * fw / fh; + rect->x = (ww - rect->w) / 2; + } +} + void screen_init(struct screen *screen) { *screen = (struct screen) SCREEN_INITIALIZER; @@ -170,13 +196,6 @@ screen_init_rendering(struct screen *screen, const char *window_title, return false; } - if (SDL_RenderSetLogicalSize(screen->renderer, frame_size.width, - frame_size.height)) { - LOGE("Could not set renderer logical size: %s", SDL_GetError()); - screen_destroy(screen); - return false; - } - SDL_Surface *icon = read_xpm(icon_xpm); if (icon) { SDL_SetWindowIcon(screen->window, icon); @@ -220,12 +239,6 @@ static bool prepare_for_frame(struct screen *screen, struct size new_frame_size) { if (screen->frame_size.width != new_frame_size.width || screen->frame_size.height != new_frame_size.height) { - if (SDL_RenderSetLogicalSize(screen->renderer, new_frame_size.width, - new_frame_size.height)) { - LOGE("Could not set renderer logical size: %s", SDL_GetError()); - return false; - } - // frame dimension changed, destroy texture SDL_DestroyTexture(screen->texture); @@ -271,6 +284,7 @@ screen_update_frame(struct screen *screen, struct video_buffer *vb) { mutex_unlock(vb->mutex); return false; } + update_frame_rect(screen); update_texture(screen, frame); mutex_unlock(vb->mutex); @@ -278,10 +292,16 @@ screen_update_frame(struct screen *screen, struct video_buffer *vb) { return true; } +void +screen_resized(struct screen *screen) { + update_frame_rect(screen); + screen_render(screen); +} + void screen_render(struct screen *screen) { SDL_RenderClear(screen->renderer); - SDL_RenderCopy(screen->renderer, screen->texture, NULL, NULL); + SDL_RenderCopy(screen->renderer, screen->texture, NULL, &screen->rect); SDL_RenderPresent(screen->renderer); } diff --git a/app/src/screen.h b/app/src/screen.h index bc189189..c1098d94 100644 --- a/app/src/screen.h +++ b/app/src/screen.h @@ -17,6 +17,7 @@ struct screen { struct size frame_size; //used only in fullscreen mode to know the windowed window size struct size windowed_window_size; + struct SDL_Rect rect; // frame location and size inside the window bool has_frame; bool fullscreen; bool no_window; @@ -34,9 +35,15 @@ struct screen { .width = 0, \ .height = 0, \ }, \ - .has_frame = false, \ - .fullscreen = false, \ - .no_window = false, \ + .rect = { \ + .x = 0, \ + .y = 0, \ + .w = 0, \ + .h = 0, \ + }, \ + .has_frame = false, \ + .fullscreen = false, \ + .no_window = false, \ } // initialize default values @@ -60,6 +67,9 @@ screen_destroy(struct screen *screen); bool screen_update_frame(struct screen *screen, struct video_buffer *vb); +void +screen_resized(struct screen *screen); + // render the texture to the renderer void screen_render(struct screen *screen);