Compare commits

..

3 Commits

Author SHA1 Message Date
Romain Vimont
7b169610c6 Add a script to build the server without gradle
Gradle versions may sometimes cause problems. This script offers an
alternative.
2019-10-29 23:06:52 +01:00
Romain Vimont
f9938dbf88 Inject button state for touch/mouse events
The buttons state was forwarded, but ignored by the server.
2019-10-25 11:04:04 +02:00
Romain Vimont
f6c8460ebb Rename window size functions for clarity
Now, get_window_size() returns the current window size (fullscreen or
not), while get_windowed_window_size() always returned the windowed size
(the size when fullscreen is disabled).
2019-10-20 16:08:16 +02:00
8 changed files with 107 additions and 93 deletions

View File

@@ -176,30 +176,19 @@ 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, const SDL_Rect *rect,
struct size frame_size, struct control_msg *to) {
convert_mouse_button(const SDL_MouseButtonEvent *from, struct size screen_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 = frame_size;
to->inject_touch_event.position.point.x = x;
to->inject_touch_event.position.point.y = y;
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.pressure = 1.f;
to->inject_touch_event.buttons =
convert_mouse_buttons(SDL_BUTTON(from->button));
@@ -208,18 +197,14 @@ convert_mouse_button(const SDL_MouseButtonEvent *from, const SDL_Rect *rect,
}
bool
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);
convert_mouse_motion(const SDL_MouseMotionEvent *from, struct size screen_size,
struct control_msg *to) {
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 = frame_size;
to->inject_touch_event.position.point.x = x;
to->inject_touch_event.position.point.y = y;
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.pressure = 1.f;
to->inject_touch_event.buttons = convert_mouse_buttons(from->state);
@@ -260,7 +245,6 @@ 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;

View File

@@ -21,14 +21,14 @@ bool
convert_input_key(const SDL_KeyboardEvent *from, struct control_msg *to);
bool
convert_mouse_button(const SDL_MouseButtonEvent *from, const SDL_Rect *rect,
struct size frame_size, struct control_msg *to);
convert_mouse_button(const SDL_MouseButtonEvent *from, struct size screen_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, const SDL_Rect *rect,
struct size frame_size, struct control_msg *to);
convert_mouse_motion(const SDL_MouseMotionEvent *from, struct size screen_size,
struct control_msg *to);
bool
convert_touch(const SDL_TouchFingerEvent *from, struct size screen_size,

View File

@@ -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->rect, input_manager->screen->frame_size, &msg)) {
if (convert_mouse_motion(event, 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->rect, input_manager->screen->frame_size, &msg)) {
if (convert_mouse_button(event, input_manager->screen->frame_size, &msg)) {
if (!controller_push_msg(input_manager->controller, &msg)) {
LOGW("Could not request 'inject mouse button event'");
}

View File

@@ -145,10 +145,8 @@ handle_event(SDL_Event *event, bool control) {
case SDL_WINDOWEVENT:
switch (event->window.event) {
case SDL_WINDOWEVENT_EXPOSED:
screen_render(&screen);
break;
case SDL_WINDOWEVENT_SIZE_CHANGED:
screen_resized(&screen);
screen_render(&screen);
break;
}
break;

View File

@@ -16,7 +16,7 @@
// get the window size in a struct size
static struct size
get_native_window_size(SDL_Window *window) {
get_window_size(SDL_Window *window) {
int width;
int height;
SDL_GetWindowSize(window, &width, &height);
@@ -29,11 +29,11 @@ get_native_window_size(SDL_Window *window) {
// get the windowed window size
static struct size
get_window_size(const struct screen *screen) {
get_windowed_window_size(const struct screen *screen) {
if (screen->fullscreen) {
return screen->windowed_window_size;
}
return get_native_window_size(screen->window);
return get_window_size(screen->window);
}
// set the window size to be applied when fullscreen is disabled
@@ -112,8 +112,8 @@ get_optimal_size(struct size current_size, struct size frame_size) {
// same as get_optimal_size(), but read the current size from the window
static inline struct size
get_optimal_window_size(const struct screen *screen, struct size frame_size) {
struct size current_size = get_window_size(screen);
return get_optimal_size(current_size, frame_size);
struct size windowed_size = get_windowed_window_size(screen);
return get_optimal_size(windowed_size, frame_size);
}
// initially, there is no current size, so use the frame size as current size
@@ -122,32 +122,6 @@ 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;
@@ -196,6 +170,13 @@ 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);
@@ -239,14 +220,20 @@ 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);
struct size current_size = get_window_size(screen);
struct size windowed_size = get_windowed_window_size(screen);
struct size target_size = {
(uint32_t) current_size.width * new_frame_size.width
(uint32_t) windowed_size.width * new_frame_size.width
/ screen->frame_size.width,
(uint32_t) current_size.height * new_frame_size.height
(uint32_t) windowed_size.height * new_frame_size.height
/ screen->frame_size.height,
};
target_size = get_optimal_size(target_size, new_frame_size);
@@ -284,7 +271,6 @@ 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);
@@ -292,16 +278,10 @@ 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, &screen->rect);
SDL_RenderCopy(screen->renderer, screen->texture, NULL, NULL);
SDL_RenderPresent(screen->renderer);
}
@@ -309,7 +289,7 @@ void
screen_switch_fullscreen(struct screen *screen) {
if (!screen->fullscreen) {
// going to fullscreen, store the current windowed window size
screen->windowed_window_size = get_native_window_size(screen->window);
screen->windowed_window_size = get_window_size(screen->window);
}
uint32_t new_mode = screen->fullscreen ? 0 : SDL_WINDOW_FULLSCREEN_DESKTOP;
if (SDL_SetWindowFullscreen(screen->window, new_mode)) {

View File

@@ -17,7 +17,6 @@ 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;
@@ -35,15 +34,9 @@ struct screen {
.width = 0, \
.height = 0, \
}, \
.rect = { \
.x = 0, \
.y = 0, \
.w = 0, \
.h = 0, \
}, \
.has_frame = false, \
.fullscreen = false, \
.no_window = false, \
.has_frame = false, \
.fullscreen = false, \
.no_window = false, \
}
// initialize default values
@@ -67,9 +60,6 @@ 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);

62
server/build_without_gradle.sh Executable file
View File

@@ -0,0 +1,62 @@
#!/bin/bash
#
# This script generates the scrcpy binary "manually" (without gradle).
#
# Adapt Android platform and build tools versions (via ANDROID_PLATFORM and
# ANDROID_BUILD_TOOLS environment variables).
#
# Then execute:
#
# BUILD_DIR=my_build_dir ./build_without_gradle.sh
set -e
PLATFORM=${ANDROID_PLATFORM:-29}
BUILD_TOOLS=${ANDROID_BUILD_TOOLS:-29.0.2}
BUILD_DIR="$(realpath ${BUILD_DIR:-build_manual})"
CLASSES_DIR="$BUILD_DIR/classes"
SERVER_DIR=$(dirname "$0")
SERVER_BINARY=scrcpy-server.jar
echo "Platform: android-$PLATFORM"
echo "Build-tools: $BUILD_TOOLS"
echo "Build dir: $BUILD_DIR"
rm -rf "$CLASSES_DIR" "$BUILD_DIR/$SERVER_BINARY" classes.dex
mkdir -p "$CLASSES_DIR/com/genymobile/scrcpy"
<< EOF cat > "$CLASSES_DIR/com/genymobile/scrcpy/BuildConfig.java"
package com.genymobile.scrcpy;
public final class BuildConfig {
public static final boolean DEBUG = false;
}
EOF
echo "Generating java from aidl..."
cd "$SERVER_DIR/src/main/aidl"
"$ANDROID_HOME/build-tools/$BUILD_TOOLS/aidl" -o "$CLASSES_DIR" \
android/view/IRotationWatcher.aidl
echo "Compiling java sources..."
cd ../java
javac -bootclasspath "$ANDROID_HOME/platforms/android-$PLATFORM/android.jar" \
-cp "$CLASSES_DIR" -d "$CLASSES_DIR" -source 1.8 -target 1.8 \
com/genymobile/scrcpy/*.java \
com/genymobile/scrcpy/wrappers/*.java
echo "Dexing..."
cd "$CLASSES_DIR"
"$ANDROID_HOME/build-tools/$BUILD_TOOLS/dx" --dex \
--output "$BUILD_DIR/classes.dex" \
android/view/*.class \
com/genymobile/scrcpy/*.class \
com/genymobile/scrcpy/wrappers/*.class
echo "Archiving..."
cd "$BUILD_DIR"
jar cvf "$SERVER_BINARY" classes.dex
rm -rf classes.dex classes
echo "Server generated in $BUILD_DIR/scrcpy-server.jar"

View File

@@ -82,7 +82,7 @@ public class Controller {
injectText(msg.getText());
break;
case ControlMessage.TYPE_INJECT_TOUCH_EVENT:
injectTouch(msg.getAction(), msg.getPointerId(), msg.getPosition(), msg.getPressure(), 0);
injectTouch(msg.getAction(), msg.getPointerId(), msg.getPosition(), msg.getPressure(), msg.getButtons());
break;
case ControlMessage.TYPE_INJECT_SCROLL_EVENT:
injectScroll(msg.getPosition(), msg.getHScroll(), msg.getVScroll());
@@ -177,7 +177,7 @@ public class Controller {
}
MotionEvent event = MotionEvent.obtain(lastTouchDown, now, action, pointerCount, pointerProperties,
pointerCoords, 0, 0, 1f, 1f, 0, 0, InputDevice.SOURCE_TOUCHSCREEN, 0);
pointerCoords, 0, buttons, 1f, 1f, 0, 0, InputDevice.SOURCE_TOUCHSCREEN, 0);
return injectEvent(event);
}