Compare commits
5 Commits
client_rot
...
threadwait
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
73d098872c | ||
|
|
943d264b35 | ||
|
|
32dc192883 | ||
|
|
7732f1097b | ||
|
|
429153abfb |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -2,4 +2,3 @@ build/
|
|||||||
/dist/
|
/dist/
|
||||||
.idea/
|
.idea/
|
||||||
.gradle/
|
.gradle/
|
||||||
/x/
|
|
||||||
|
|||||||
@@ -491,8 +491,6 @@ Also see [issue #14].
|
|||||||
| Action | Shortcut | Shortcut (macOS)
|
| Action | Shortcut | Shortcut (macOS)
|
||||||
| -------------------------------------- |:----------------------------- |:-----------------------------
|
| -------------------------------------- |:----------------------------- |:-----------------------------
|
||||||
| Switch fullscreen mode | `Ctrl`+`f` | `Cmd`+`f`
|
| Switch fullscreen mode | `Ctrl`+`f` | `Cmd`+`f`
|
||||||
| Rotate window left | `Ctrl`+`←` _(left)_ | `Cmd`+`←` _(left)_
|
|
||||||
| Rotate window right | `Ctrl`+`→` _(right)_ | `Cmd`+`→` _(right)_
|
|
||||||
| Resize window to 1:1 (pixel-perfect) | `Ctrl`+`g` | `Cmd`+`g`
|
| Resize window to 1:1 (pixel-perfect) | `Ctrl`+`g` | `Cmd`+`g`
|
||||||
| Resize window to remove black borders | `Ctrl`+`x` \| _Double-click¹_ | `Cmd`+`x` \| _Double-click¹_
|
| Resize window to remove black borders | `Ctrl`+`x` \| _Double-click¹_ | `Cmd`+`x` \| _Double-click¹_
|
||||||
| Click on `HOME` | `Ctrl`+`h` \| _Middle-click_ | `Ctrl`+`h` \| _Middle-click_
|
| Click on `HOME` | `Ctrl`+`h` \| _Middle-click_ | `Ctrl`+`h` \| _Middle-click_
|
||||||
|
|||||||
@@ -166,14 +166,6 @@ Default is 0 (automatic).\n
|
|||||||
.B Ctrl+f
|
.B Ctrl+f
|
||||||
switch fullscreen mode
|
switch fullscreen mode
|
||||||
|
|
||||||
.TP
|
|
||||||
.B Ctrl+Left
|
|
||||||
rotate window left
|
|
||||||
|
|
||||||
.TP
|
|
||||||
.B Ctrl+Right
|
|
||||||
rotate window right
|
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.B Ctrl+g
|
.B Ctrl+g
|
||||||
resize window to 1:1 (pixel\-perfect)
|
resize window to 1:1 (pixel\-perfect)
|
||||||
|
|||||||
@@ -145,12 +145,6 @@ scrcpy_print_usage(const char *arg0) {
|
|||||||
" " CTRL_OR_CMD "+f\n"
|
" " CTRL_OR_CMD "+f\n"
|
||||||
" switch fullscreen mode\n"
|
" switch fullscreen mode\n"
|
||||||
"\n"
|
"\n"
|
||||||
" " CTRL_OR_CMD "+Left\n"
|
|
||||||
" rotate window left\n"
|
|
||||||
"\n"
|
|
||||||
" " CTRL_OR_CMD "+Right\n"
|
|
||||||
" rotate window right\n"
|
|
||||||
"\n"
|
|
||||||
" " CTRL_OR_CMD "+g\n"
|
" " CTRL_OR_CMD "+g\n"
|
||||||
" resize window to 1:1 (pixel-perfect)\n"
|
" resize window to 1:1 (pixel-perfect)\n"
|
||||||
"\n"
|
"\n"
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ fps_counter_init(struct fps_counter *counter) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
counter->thread = NULL;
|
counter->thread = NULL;
|
||||||
atomic_init(&counter->started, 0);
|
SDL_AtomicSet(&counter->started, 0);
|
||||||
// no need to initialize the other fields, they are unused until started
|
// no need to initialize the other fields, they are unused until started
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -35,16 +35,6 @@ fps_counter_destroy(struct fps_counter *counter) {
|
|||||||
SDL_DestroyMutex(counter->mutex);
|
SDL_DestroyMutex(counter->mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool
|
|
||||||
is_started(struct fps_counter *counter) {
|
|
||||||
return atomic_load_explicit(&counter->started, memory_order_acquire);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void
|
|
||||||
set_started(struct fps_counter *counter, bool started) {
|
|
||||||
atomic_store_explicit(&counter->started, started, memory_order_release);
|
|
||||||
}
|
|
||||||
|
|
||||||
// must be called with mutex locked
|
// must be called with mutex locked
|
||||||
static void
|
static void
|
||||||
display_fps(struct fps_counter *counter) {
|
display_fps(struct fps_counter *counter) {
|
||||||
@@ -80,10 +70,10 @@ run_fps_counter(void *data) {
|
|||||||
|
|
||||||
mutex_lock(counter->mutex);
|
mutex_lock(counter->mutex);
|
||||||
while (!counter->interrupted) {
|
while (!counter->interrupted) {
|
||||||
while (!counter->interrupted && !is_started(counter)) {
|
while (!counter->interrupted && !SDL_AtomicGet(&counter->started)) {
|
||||||
cond_wait(counter->state_cond, counter->mutex);
|
cond_wait(counter->state_cond, counter->mutex);
|
||||||
}
|
}
|
||||||
while (!counter->interrupted && is_started(counter)) {
|
while (!counter->interrupted && SDL_AtomicGet(&counter->started)) {
|
||||||
uint32_t now = SDL_GetTicks();
|
uint32_t now = SDL_GetTicks();
|
||||||
check_interval_expired(counter, now);
|
check_interval_expired(counter, now);
|
||||||
|
|
||||||
@@ -106,7 +96,7 @@ fps_counter_start(struct fps_counter *counter) {
|
|||||||
counter->nr_skipped = 0;
|
counter->nr_skipped = 0;
|
||||||
mutex_unlock(counter->mutex);
|
mutex_unlock(counter->mutex);
|
||||||
|
|
||||||
set_started(counter, true);
|
SDL_AtomicSet(&counter->started, 1);
|
||||||
cond_signal(counter->state_cond);
|
cond_signal(counter->state_cond);
|
||||||
|
|
||||||
// counter->thread is always accessed from the same thread, no need to lock
|
// counter->thread is always accessed from the same thread, no need to lock
|
||||||
@@ -124,13 +114,13 @@ fps_counter_start(struct fps_counter *counter) {
|
|||||||
|
|
||||||
void
|
void
|
||||||
fps_counter_stop(struct fps_counter *counter) {
|
fps_counter_stop(struct fps_counter *counter) {
|
||||||
set_started(counter, false);
|
SDL_AtomicSet(&counter->started, 0);
|
||||||
cond_signal(counter->state_cond);
|
cond_signal(counter->state_cond);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
fps_counter_is_started(struct fps_counter *counter) {
|
fps_counter_is_started(struct fps_counter *counter) {
|
||||||
return is_started(counter);
|
return SDL_AtomicGet(&counter->started);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -155,7 +145,7 @@ fps_counter_join(struct fps_counter *counter) {
|
|||||||
|
|
||||||
void
|
void
|
||||||
fps_counter_add_rendered_frame(struct fps_counter *counter) {
|
fps_counter_add_rendered_frame(struct fps_counter *counter) {
|
||||||
if (!is_started(counter)) {
|
if (!SDL_AtomicGet(&counter->started)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -168,7 +158,7 @@ fps_counter_add_rendered_frame(struct fps_counter *counter) {
|
|||||||
|
|
||||||
void
|
void
|
||||||
fps_counter_add_skipped_frame(struct fps_counter *counter) {
|
fps_counter_add_skipped_frame(struct fps_counter *counter) {
|
||||||
if (!is_started(counter)) {
|
if (!SDL_AtomicGet(&counter->started)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
#ifndef FPSCOUNTER_H
|
#ifndef FPSCOUNTER_H
|
||||||
#define FPSCOUNTER_H
|
#define FPSCOUNTER_H
|
||||||
|
|
||||||
#include <stdatomic.h>
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <SDL2/SDL_atomic.h>
|
||||||
#include <SDL2/SDL_mutex.h>
|
#include <SDL2/SDL_mutex.h>
|
||||||
#include <SDL2/SDL_thread.h>
|
#include <SDL2/SDL_thread.h>
|
||||||
|
|
||||||
@@ -16,7 +16,7 @@ struct fps_counter {
|
|||||||
|
|
||||||
// atomic so that we can check without locking the mutex
|
// atomic so that we can check without locking the mutex
|
||||||
// if the FPS counter is disabled, we don't want to lock unnecessarily
|
// if the FPS counter is disabled, we don't want to lock unnecessarily
|
||||||
atomic_bool started;
|
SDL_atomic_t started;
|
||||||
|
|
||||||
// the following fields are protected by the mutex
|
// the following fields are protected by the mutex
|
||||||
bool interrupted;
|
bool interrupted;
|
||||||
|
|||||||
@@ -221,18 +221,6 @@ rotate_device(struct controller *controller) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
rotate_client_left(struct screen *screen) {
|
|
||||||
unsigned new_rotation = (screen->rotation + 3) % 4;
|
|
||||||
screen_set_rotation(screen, new_rotation);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
rotate_client_right(struct screen *screen) {
|
|
||||||
unsigned new_rotation = (screen->rotation + 1) % 4;
|
|
||||||
screen_set_rotation(screen, new_rotation);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
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) {
|
||||||
@@ -363,16 +351,6 @@ input_manager_process_key(struct input_manager *im,
|
|||||||
action_volume_up(controller, action);
|
action_volume_up(controller, action);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
case SDLK_LEFT:
|
|
||||||
if (cmd && !shift && down) {
|
|
||||||
rotate_client_left(im->screen);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
case SDLK_RIGHT:
|
|
||||||
if (cmd && !shift && down) {
|
|
||||||
rotate_client_right(im->screen);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
case SDLK_c:
|
case SDLK_c:
|
||||||
if (control && cmd && !shift && !repeat && down) {
|
if (control && cmd && !shift && !repeat && down) {
|
||||||
request_device_clipboard(controller);
|
request_device_clipboard(controller);
|
||||||
|
|||||||
132
app/src/screen.c
132
app/src/screen.c
@@ -15,19 +15,6 @@
|
|||||||
|
|
||||||
#define DISPLAY_MARGINS 96
|
#define DISPLAY_MARGINS 96
|
||||||
|
|
||||||
static inline struct size
|
|
||||||
get_rotated_size(struct size size, int rotation) {
|
|
||||||
struct size rotated_size;
|
|
||||||
if (rotation & 1) {
|
|
||||||
rotated_size.width = size.height;
|
|
||||||
rotated_size.height = size.width;
|
|
||||||
} else {
|
|
||||||
rotated_size.width = size.width;
|
|
||||||
rotated_size.height = size.height;
|
|
||||||
}
|
|
||||||
return rotated_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
// get the window size in a struct size
|
// get the window size in a struct size
|
||||||
static struct size
|
static struct size
|
||||||
get_window_size(SDL_Window *window) {
|
get_window_size(SDL_Window *window) {
|
||||||
@@ -93,8 +80,8 @@ get_preferred_display_bounds(struct size *bounds) {
|
|||||||
// - it keeps the aspect ratio
|
// - it keeps the aspect ratio
|
||||||
// - it scales down to make it fit in the display_size
|
// - it scales down to make it fit in the display_size
|
||||||
static struct size
|
static struct size
|
||||||
get_optimal_size(struct size current_size, struct size content_size) {
|
get_optimal_size(struct size current_size, struct size frame_size) {
|
||||||
if (content_size.width == 0 || content_size.height == 0) {
|
if (frame_size.width == 0 || frame_size.height == 0) {
|
||||||
// avoid division by 0
|
// avoid division by 0
|
||||||
return current_size;
|
return current_size;
|
||||||
}
|
}
|
||||||
@@ -113,14 +100,14 @@ get_optimal_size(struct size current_size, struct size content_size) {
|
|||||||
h = MIN(current_size.height, display_size.height);
|
h = MIN(current_size.height, display_size.height);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool keep_width = content_size.width * h > content_size.height * w;
|
bool keep_width = frame_size.width * h > frame_size.height * w;
|
||||||
if (keep_width) {
|
if (keep_width) {
|
||||||
// remove black borders on top and bottom
|
// remove black borders on top and bottom
|
||||||
h = content_size.height * w / content_size.width;
|
h = frame_size.height * w / frame_size.width;
|
||||||
} else {
|
} else {
|
||||||
// remove black borders on left and right (or none at all if it already
|
// remove black borders on left and right (or none at all if it already
|
||||||
// fits)
|
// fits)
|
||||||
w = content_size.width * h / content_size.height;
|
w = frame_size.width * h / frame_size.height;
|
||||||
}
|
}
|
||||||
|
|
||||||
// w and h must fit into 16 bits
|
// w and h must fit into 16 bits
|
||||||
@@ -130,33 +117,33 @@ get_optimal_size(struct size current_size, struct size content_size) {
|
|||||||
|
|
||||||
// same as get_optimal_size(), but read the current size from the window
|
// same as get_optimal_size(), but read the current size from the window
|
||||||
static inline struct size
|
static inline struct size
|
||||||
get_optimal_window_size(const struct screen *screen, struct size content_size) {
|
get_optimal_window_size(const struct screen *screen, struct size frame_size) {
|
||||||
struct size windowed_size = get_windowed_window_size(screen);
|
struct size windowed_size = get_windowed_window_size(screen);
|
||||||
return get_optimal_size(windowed_size, content_size);
|
return get_optimal_size(windowed_size, frame_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
// initially, there is no current size, so use the frame size as current size
|
// initially, there is no current size, so use the frame size as current size
|
||||||
// req_width and req_height, if not 0, are the sizes requested by the user
|
// req_width and req_height, if not 0, are the sizes requested by the user
|
||||||
static inline struct size
|
static inline struct size
|
||||||
get_initial_optimal_size(struct size content_size, uint16_t req_width,
|
get_initial_optimal_size(struct size frame_size, uint16_t req_width,
|
||||||
uint16_t req_height) {
|
uint16_t req_height) {
|
||||||
struct size window_size;
|
struct size window_size;
|
||||||
if (!req_width && !req_height) {
|
if (!req_width && !req_height) {
|
||||||
window_size = get_optimal_size(content_size, content_size);
|
window_size = get_optimal_size(frame_size, frame_size);
|
||||||
} else {
|
} else {
|
||||||
if (req_width) {
|
if (req_width) {
|
||||||
window_size.width = req_width;
|
window_size.width = req_width;
|
||||||
} else {
|
} else {
|
||||||
// compute from the requested height
|
// compute from the requested height
|
||||||
window_size.width = (uint32_t) req_height * content_size.width
|
window_size.width = (uint32_t) req_height * frame_size.width
|
||||||
/ content_size.height;
|
/ frame_size.height;
|
||||||
}
|
}
|
||||||
if (req_height) {
|
if (req_height) {
|
||||||
window_size.height = req_height;
|
window_size.height = req_height;
|
||||||
} else {
|
} else {
|
||||||
// compute from the requested width
|
// compute from the requested width
|
||||||
window_size.height = (uint32_t) req_width * content_size.height
|
window_size.height = (uint32_t) req_width * frame_size.height
|
||||||
/ content_size.width;
|
/ frame_size.width;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return window_size;
|
return window_size;
|
||||||
@@ -180,11 +167,9 @@ screen_init_rendering(struct screen *screen, const char *window_title,
|
|||||||
int16_t window_x, int16_t window_y, uint16_t window_width,
|
int16_t window_x, int16_t window_y, uint16_t window_width,
|
||||||
uint16_t window_height, bool window_borderless) {
|
uint16_t window_height, bool window_borderless) {
|
||||||
screen->frame_size = frame_size;
|
screen->frame_size = frame_size;
|
||||||
struct size content_size =
|
|
||||||
get_rotated_size(frame_size, screen->rotation);
|
|
||||||
|
|
||||||
struct size window_size =
|
struct size window_size =
|
||||||
get_initial_optimal_size(content_size, window_width, window_height);
|
get_initial_optimal_size(frame_size, window_width, window_height);
|
||||||
uint32_t window_flags = SDL_WINDOW_HIDDEN | SDL_WINDOW_RESIZABLE;
|
uint32_t window_flags = SDL_WINDOW_HIDDEN | SDL_WINDOW_RESIZABLE;
|
||||||
#ifdef HIDPI_SUPPORT
|
#ifdef HIDPI_SUPPORT
|
||||||
window_flags |= SDL_WINDOW_ALLOW_HIGHDPI;
|
window_flags |= SDL_WINDOW_ALLOW_HIGHDPI;
|
||||||
@@ -221,8 +206,8 @@ screen_init_rendering(struct screen *screen, const char *window_title,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SDL_RenderSetLogicalSize(screen->renderer, content_size.width,
|
if (SDL_RenderSetLogicalSize(screen->renderer, frame_size.width,
|
||||||
content_size.height)) {
|
frame_size.height)) {
|
||||||
LOGE("Could not set renderer logical size: %s", SDL_GetError());
|
LOGE("Could not set renderer logical size: %s", SDL_GetError());
|
||||||
screen_destroy(screen);
|
screen_destroy(screen);
|
||||||
return false;
|
return false;
|
||||||
@@ -268,51 +253,13 @@ screen_destroy(struct screen *screen) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
screen_set_rotation(struct screen *screen, unsigned rotation) {
|
|
||||||
assert(rotation < 4);
|
|
||||||
if (rotation == screen->rotation) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct size old_content_size =
|
|
||||||
get_rotated_size(screen->frame_size, screen->rotation);
|
|
||||||
struct size new_content_size =
|
|
||||||
get_rotated_size(screen->frame_size, rotation);
|
|
||||||
|
|
||||||
if (SDL_RenderSetLogicalSize(screen->renderer,
|
|
||||||
new_content_size.width,
|
|
||||||
new_content_size.height)) {
|
|
||||||
LOGE("Could not set renderer logical size: %s", SDL_GetError());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct size windowed_size = get_windowed_window_size(screen);
|
|
||||||
struct size target_size = {
|
|
||||||
.width = (uint32_t) windowed_size.width * new_content_size.width
|
|
||||||
/ old_content_size.width,
|
|
||||||
.height = (uint32_t) windowed_size.height * new_content_size.height
|
|
||||||
/ old_content_size.height,
|
|
||||||
};
|
|
||||||
target_size = get_optimal_size(target_size, new_content_size);
|
|
||||||
set_window_size(screen, target_size);
|
|
||||||
|
|
||||||
screen->rotation = rotation;
|
|
||||||
LOGI("Client rotation set to %u", rotation);
|
|
||||||
|
|
||||||
screen_render(screen);
|
|
||||||
}
|
|
||||||
|
|
||||||
// recreate the texture and resize the window if the frame size has changed
|
// recreate the texture and resize the window if the frame size has changed
|
||||||
static bool
|
static bool
|
||||||
prepare_for_frame(struct screen *screen, struct size new_frame_size) {
|
prepare_for_frame(struct screen *screen, struct size new_frame_size) {
|
||||||
if (screen->frame_size.width != new_frame_size.width
|
if (screen->frame_size.width != new_frame_size.width
|
||||||
|| screen->frame_size.height != new_frame_size.height) {
|
|| screen->frame_size.height != new_frame_size.height) {
|
||||||
struct size new_content_size =
|
if (SDL_RenderSetLogicalSize(screen->renderer, new_frame_size.width,
|
||||||
get_rotated_size(new_frame_size, screen->rotation);
|
new_frame_size.height)) {
|
||||||
if (SDL_RenderSetLogicalSize(screen->renderer,
|
|
||||||
new_content_size.width,
|
|
||||||
new_content_size.height)) {
|
|
||||||
LOGE("Could not set renderer logical size: %s", SDL_GetError());
|
LOGE("Could not set renderer logical size: %s", SDL_GetError());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -320,16 +267,14 @@ prepare_for_frame(struct screen *screen, struct size new_frame_size) {
|
|||||||
// frame dimension changed, destroy texture
|
// frame dimension changed, destroy texture
|
||||||
SDL_DestroyTexture(screen->texture);
|
SDL_DestroyTexture(screen->texture);
|
||||||
|
|
||||||
struct size content_size =
|
|
||||||
get_rotated_size(screen->frame_size, screen->rotation);
|
|
||||||
struct size windowed_size = get_windowed_window_size(screen);
|
struct size windowed_size = get_windowed_window_size(screen);
|
||||||
struct size target_size = {
|
struct size target_size = {
|
||||||
(uint32_t) windowed_size.width * new_content_size.width
|
(uint32_t) windowed_size.width * new_frame_size.width
|
||||||
/ content_size.width,
|
/ screen->frame_size.width,
|
||||||
(uint32_t) windowed_size.height * new_content_size.height
|
(uint32_t) windowed_size.height * new_frame_size.height
|
||||||
/ content_size.height,
|
/ screen->frame_size.height,
|
||||||
};
|
};
|
||||||
target_size = get_optimal_size(target_size, new_content_size);
|
target_size = get_optimal_size(target_size, new_frame_size);
|
||||||
set_window_size(screen, target_size);
|
set_window_size(screen, target_size);
|
||||||
|
|
||||||
screen->frame_size = new_frame_size;
|
screen->frame_size = new_frame_size;
|
||||||
@@ -374,27 +319,7 @@ screen_update_frame(struct screen *screen, struct video_buffer *vb) {
|
|||||||
void
|
void
|
||||||
screen_render(struct screen *screen) {
|
screen_render(struct screen *screen) {
|
||||||
SDL_RenderClear(screen->renderer);
|
SDL_RenderClear(screen->renderer);
|
||||||
if (screen->rotation == 0) {
|
SDL_RenderCopy(screen->renderer, screen->texture, NULL, NULL);
|
||||||
SDL_RenderCopy(screen->renderer, screen->texture, NULL, NULL);
|
|
||||||
} else {
|
|
||||||
double angle = 90 * screen->rotation;
|
|
||||||
|
|
||||||
SDL_Rect *dstrect = NULL;
|
|
||||||
SDL_Rect rect;
|
|
||||||
if (screen->rotation & 1) {
|
|
||||||
struct size size =
|
|
||||||
get_rotated_size(screen->frame_size, screen->rotation);
|
|
||||||
rect.x = (size.width - size.height) / 2;
|
|
||||||
rect.y = (size.height - size.width) / 2;
|
|
||||||
rect.w = size.height;
|
|
||||||
rect.h = size.width;
|
|
||||||
dstrect = ▭
|
|
||||||
}
|
|
||||||
|
|
||||||
// rotation in RenderCopyEx() is clockwise
|
|
||||||
SDL_RenderCopyEx(screen->renderer, screen->texture, NULL, dstrect,
|
|
||||||
angle, NULL, 0);
|
|
||||||
}
|
|
||||||
SDL_RenderPresent(screen->renderer);
|
SDL_RenderPresent(screen->renderer);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -424,10 +349,8 @@ screen_resize_to_fit(struct screen *screen) {
|
|||||||
screen->maximized = false;
|
screen->maximized = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct size content_size =
|
|
||||||
get_rotated_size(screen->frame_size, screen->rotation);
|
|
||||||
struct size optimal_size =
|
struct size optimal_size =
|
||||||
get_optimal_window_size(screen, content_size);
|
get_optimal_window_size(screen, screen->frame_size);
|
||||||
SDL_SetWindowSize(screen->window, optimal_size.width, optimal_size.height);
|
SDL_SetWindowSize(screen->window, optimal_size.width, optimal_size.height);
|
||||||
LOGD("Resized to optimal size");
|
LOGD("Resized to optimal size");
|
||||||
}
|
}
|
||||||
@@ -443,9 +366,8 @@ screen_resize_to_pixel_perfect(struct screen *screen) {
|
|||||||
screen->maximized = false;
|
screen->maximized = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct size content_size =
|
SDL_SetWindowSize(screen->window, screen->frame_size.width,
|
||||||
get_rotated_size(screen->frame_size, screen->rotation);
|
screen->frame_size.height);
|
||||||
SDL_SetWindowSize(screen->window, content_size.width, content_size.height);
|
|
||||||
LOGD("Resized to pixel-perfect");
|
LOGD("Resized to pixel-perfect");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,8 +22,6 @@ struct screen {
|
|||||||
// Since we receive the event SIZE_CHANGED before MAXIMIZED, we must be
|
// Since we receive the event SIZE_CHANGED before MAXIMIZED, we must be
|
||||||
// able to revert the size to its non-maximized value.
|
// able to revert the size to its non-maximized value.
|
||||||
struct size windowed_window_size_backup;
|
struct size windowed_window_size_backup;
|
||||||
// client rotation: 0, 1, 2 or 3 (x90 degrees clockwise)
|
|
||||||
unsigned rotation;
|
|
||||||
bool has_frame;
|
bool has_frame;
|
||||||
bool fullscreen;
|
bool fullscreen;
|
||||||
bool maximized;
|
bool maximized;
|
||||||
@@ -46,7 +44,6 @@ struct screen {
|
|||||||
.width = 0, \
|
.width = 0, \
|
||||||
.height = 0, \
|
.height = 0, \
|
||||||
}, \
|
}, \
|
||||||
.rotation = 0, \
|
|
||||||
.has_frame = false, \
|
.has_frame = false, \
|
||||||
.fullscreen = false, \
|
.fullscreen = false, \
|
||||||
.maximized = false, \
|
.maximized = false, \
|
||||||
@@ -93,10 +90,6 @@ screen_resize_to_fit(struct screen *screen);
|
|||||||
void
|
void
|
||||||
screen_resize_to_pixel_perfect(struct screen *screen);
|
screen_resize_to_pixel_perfect(struct screen *screen);
|
||||||
|
|
||||||
// change the client rotation (0, 1, 2 or 3, x90 degrees clockwise)
|
|
||||||
void
|
|
||||||
screen_set_rotation(struct screen *screen, unsigned rotation);
|
|
||||||
|
|
||||||
// react to window events
|
// react to window events
|
||||||
void
|
void
|
||||||
screen_handle_window_event(struct screen *screen, const SDL_WindowEvent *event);
|
screen_handle_window_event(struct screen *screen, const SDL_WindowEvent *event);
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <libgen.h>
|
#include <libgen.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
#include <SDL2/SDL_thread.h>
|
#include <SDL2/SDL_thread.h>
|
||||||
#include <SDL2/SDL_timer.h>
|
#include <SDL2/SDL_timer.h>
|
||||||
#include <SDL2/SDL_platform.h>
|
#include <SDL2/SDL_platform.h>
|
||||||
@@ -318,12 +319,14 @@ connect_to_server(uint16_t port, uint32_t attempts, uint32_t delay) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
close_socket(socket_t socket) {
|
close_socket(socket_t *socket) {
|
||||||
assert(socket != INVALID_SOCKET);
|
assert(*socket != INVALID_SOCKET);
|
||||||
net_shutdown(socket, SHUT_RDWR);
|
net_shutdown(*socket, SHUT_RDWR);
|
||||||
if (!net_close(socket)) {
|
if (!net_close(*socket)) {
|
||||||
LOGW("Could not close socket");
|
LOGW("Could not close socket");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
*socket = INVALID_SOCKET;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -335,14 +338,10 @@ static int
|
|||||||
run_wait_server(void *data) {
|
run_wait_server(void *data) {
|
||||||
struct server *server = data;
|
struct server *server = data;
|
||||||
cmd_simple_wait(server->process, NULL); // ignore exit code
|
cmd_simple_wait(server->process, NULL); // ignore exit code
|
||||||
// no need for synchronization, server_socket is initialized before this
|
|
||||||
// thread was created
|
// wake up any net_select_interruptible()
|
||||||
if (server->server_socket != INVALID_SOCKET
|
close(server->pipe_intr[1]);
|
||||||
&& !atomic_flag_test_and_set(&server->server_socket_closed)) {
|
|
||||||
// On Linux, accept() is unblocked by shutdown(), but on Windows, it is
|
|
||||||
// unblocked by closesocket(). Therefore, call both (close_socket()).
|
|
||||||
close_socket(server->server_socket);
|
|
||||||
}
|
|
||||||
LOGD("Server terminated");
|
LOGD("Server terminated");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -367,38 +366,36 @@ server_start(struct server *server, const char *serial,
|
|||||||
goto error1;
|
goto error1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// server will connect to our server socket
|
bool ok = net_pipe(server->pipe_intr);
|
||||||
server->process = execute_server(server, params);
|
if (!ok) {
|
||||||
if (server->process == PROCESS_NONE) {
|
perror("pipe");
|
||||||
goto error2;
|
goto error2;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the server process dies before connecting to the server socket, then
|
// server will connect to our server socket
|
||||||
// the client will be stuck forever on accept(). To avoid the problem, we
|
server->process = execute_server(server, params);
|
||||||
// must be able to wake up the accept() call when the server dies. To keep
|
if (server->process == PROCESS_NONE) {
|
||||||
// things simple and multiplatform, just spawn a new thread waiting for the
|
goto error3;
|
||||||
// server process and calling shutdown()/close() on the server socket if
|
}
|
||||||
// necessary to wake up any accept() blocking call.
|
|
||||||
server->wait_server_thread =
|
server->wait_server_thread =
|
||||||
SDL_CreateThread(run_wait_server, "wait-server", server);
|
SDL_CreateThread(run_wait_server, "wait-server", server);
|
||||||
if (!server->wait_server_thread) {
|
if (!server->wait_server_thread) {
|
||||||
cmd_terminate(server->process);
|
cmd_terminate(server->process);
|
||||||
cmd_simple_wait(server->process, NULL); // ignore exit code
|
cmd_simple_wait(server->process, NULL); // ignore exit code
|
||||||
goto error2;
|
goto error3;
|
||||||
}
|
}
|
||||||
|
|
||||||
server->tunnel_enabled = true;
|
server->tunnel_enabled = true;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
error3:
|
||||||
|
close(server->pipe_intr[0]);
|
||||||
|
close(server->pipe_intr[1]);
|
||||||
error2:
|
error2:
|
||||||
if (!server->tunnel_forward) {
|
if (!server->tunnel_forward) {
|
||||||
bool was_closed =
|
close_socket(&server->server_socket);
|
||||||
atomic_flag_test_and_set(&server->server_socket_closed);
|
|
||||||
// the thread is not started, the flag could not be already set
|
|
||||||
assert(!was_closed);
|
|
||||||
(void) was_closed;
|
|
||||||
close_socket(server->server_socket);
|
|
||||||
}
|
}
|
||||||
disable_tunnel(server);
|
disable_tunnel(server);
|
||||||
error1:
|
error1:
|
||||||
@@ -409,23 +406,34 @@ error1:
|
|||||||
bool
|
bool
|
||||||
server_connect_to(struct server *server) {
|
server_connect_to(struct server *server) {
|
||||||
if (!server->tunnel_forward) {
|
if (!server->tunnel_forward) {
|
||||||
|
bool acceptable = net_select_interruptible(server->server_socket,
|
||||||
|
server->pipe_intr[0]);
|
||||||
|
if (!acceptable) {
|
||||||
|
// the process died, accept() would never succeed
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
server->video_socket = net_accept(server->server_socket);
|
server->video_socket = net_accept(server->server_socket);
|
||||||
if (server->video_socket == INVALID_SOCKET) {
|
if (server->video_socket == INVALID_SOCKET) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
acceptable = net_select_interruptible(server->server_socket,
|
||||||
|
server->pipe_intr[0]);
|
||||||
|
if (!acceptable) {
|
||||||
|
// the process died, accept() would never succeed
|
||||||
|
return false;
|
||||||
|
}
|
||||||
server->control_socket = net_accept(server->server_socket);
|
server->control_socket = net_accept(server->server_socket);
|
||||||
if (server->control_socket == INVALID_SOCKET) {
|
if (server->control_socket == INVALID_SOCKET) {
|
||||||
// the video_socket will be cleaned up on destroy
|
// the video_socket will be cleaned up on destroy
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
close(server->pipe_intr[0]);
|
||||||
|
|
||||||
// we don't need the server socket anymore
|
// we don't need the server socket anymore
|
||||||
if (!atomic_flag_test_and_set(&server->server_socket_closed)) {
|
close_socket(&server->server_socket);
|
||||||
// close it from here
|
|
||||||
close_socket(server->server_socket);
|
|
||||||
// otherwise, it is closed by run_wait_server()
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
uint32_t attempts = 100;
|
uint32_t attempts = 100;
|
||||||
uint32_t delay = 100; // ms
|
uint32_t delay = 100; // ms
|
||||||
@@ -452,15 +460,14 @@ server_connect_to(struct server *server) {
|
|||||||
|
|
||||||
void
|
void
|
||||||
server_stop(struct server *server) {
|
server_stop(struct server *server) {
|
||||||
if (server->server_socket != INVALID_SOCKET
|
if (server->server_socket != INVALID_SOCKET) {
|
||||||
&& !atomic_flag_test_and_set(&server->server_socket_closed)) {
|
close_socket(&server->server_socket);
|
||||||
close_socket(server->server_socket);
|
|
||||||
}
|
}
|
||||||
if (server->video_socket != INVALID_SOCKET) {
|
if (server->video_socket != INVALID_SOCKET) {
|
||||||
close_socket(server->video_socket);
|
close_socket(&server->video_socket);
|
||||||
}
|
}
|
||||||
if (server->control_socket != INVALID_SOCKET) {
|
if (server->control_socket != INVALID_SOCKET) {
|
||||||
close_socket(server->control_socket);
|
close_socket(&server->control_socket);
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(server->process != PROCESS_NONE);
|
assert(server->process != PROCESS_NONE);
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
#ifndef SERVER_H
|
#ifndef SERVER_H
|
||||||
#define SERVER_H
|
#define SERVER_H
|
||||||
|
|
||||||
#include <stdatomic.h>
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <SDL2/SDL_thread.h>
|
#include <SDL2/SDL_thread.h>
|
||||||
@@ -15,7 +14,7 @@ struct server {
|
|||||||
char *serial;
|
char *serial;
|
||||||
process_t process;
|
process_t process;
|
||||||
SDL_Thread *wait_server_thread;
|
SDL_Thread *wait_server_thread;
|
||||||
atomic_flag server_socket_closed;
|
int pipe_intr[2]; // to wake up blocking accept() on process exit
|
||||||
socket_t server_socket; // only used if !tunnel_forward
|
socket_t server_socket; // only used if !tunnel_forward
|
||||||
socket_t video_socket;
|
socket_t video_socket;
|
||||||
socket_t control_socket;
|
socket_t control_socket;
|
||||||
@@ -28,8 +27,6 @@ struct server {
|
|||||||
#define SERVER_INITIALIZER { \
|
#define SERVER_INITIALIZER { \
|
||||||
.serial = NULL, \
|
.serial = NULL, \
|
||||||
.process = PROCESS_NONE, \
|
.process = PROCESS_NONE, \
|
||||||
.wait_server_thread = NULL, \
|
|
||||||
.server_socket_closed = ATOMIC_FLAG_INIT, \
|
|
||||||
.server_socket = INVALID_SOCKET, \
|
.server_socket = INVALID_SOCKET, \
|
||||||
.video_socket = INVALID_SOCKET, \
|
.video_socket = INVALID_SOCKET, \
|
||||||
.control_socket = INVALID_SOCKET, \
|
.control_socket = INVALID_SOCKET, \
|
||||||
|
|||||||
@@ -1,16 +1,22 @@
|
|||||||
#include "net.h"
|
#include "net.h"
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <errno.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <SDL2/SDL_platform.h>
|
#include <SDL2/SDL_platform.h>
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
#include "common.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
|
||||||
#ifdef __WINDOWS__
|
#ifdef __WINDOWS__
|
||||||
|
# include <io.h>
|
||||||
|
# include <winsock2.h>
|
||||||
typedef int socklen_t;
|
typedef int socklen_t;
|
||||||
#else
|
#else
|
||||||
# include <sys/types.h>
|
# include <sys/select.h>
|
||||||
# include <sys/socket.h>
|
# include <sys/socket.h>
|
||||||
|
# include <sys/types.h>
|
||||||
# include <netinet/in.h>
|
# include <netinet/in.h>
|
||||||
# include <arpa/inet.h>
|
# include <arpa/inet.h>
|
||||||
# include <unistd.h>
|
# include <unistd.h>
|
||||||
@@ -145,3 +151,38 @@ net_close(socket_t socket) {
|
|||||||
return !close(socket);
|
return !close(socket);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
net_select_interruptible(int fd, int fd_intr) {
|
||||||
|
fd_set rfds;
|
||||||
|
|
||||||
|
FD_ZERO(&rfds);
|
||||||
|
FD_SET(fd, &rfds);
|
||||||
|
FD_SET(fd_intr, &rfds);
|
||||||
|
|
||||||
|
int nfds = MAX(fd, fd_intr) + 1;
|
||||||
|
|
||||||
|
// use select() because it's available on supported platforms
|
||||||
|
int r = select(nfds, &rfds, NULL, NULL, NULL);
|
||||||
|
if (r == -1) {
|
||||||
|
// failure
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
assert(r > 0);
|
||||||
|
if (FD_ISSET(fd_intr, &rfds)) {
|
||||||
|
// interrupted is set
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(FD_ISSET(fd, &rfds));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
net_pipe(int fds[static 2]) {
|
||||||
|
#ifdef __WINDOWS__
|
||||||
|
return !_pipe(fds, 4096, 0);
|
||||||
|
#else
|
||||||
|
return !pipe(fds);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|||||||
@@ -54,4 +54,12 @@ net_shutdown(socket_t socket, int how);
|
|||||||
bool
|
bool
|
||||||
net_close(socket_t socket);
|
net_close(socket_t socket);
|
||||||
|
|
||||||
|
// wait for fd or fd_intr to be readable
|
||||||
|
// return true if fd is readable and fd_intr is not
|
||||||
|
bool
|
||||||
|
net_select_interruptible(int fd, int fd_intr);
|
||||||
|
|
||||||
|
bool
|
||||||
|
net_pipe(int fd[static 2]);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ buildscript {
|
|||||||
jcenter()
|
jcenter()
|
||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.android.tools.build:gradle:3.6.2'
|
classpath 'com.android.tools.build:gradle:3.4.2'
|
||||||
|
|
||||||
// NOTE: Do not place your application dependencies here; they belong
|
// NOTE: Do not place your application dependencies here; they belong
|
||||||
// in the individual module build.gradle files
|
// in the individual module build.gradle files
|
||||||
|
|||||||
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Binary file not shown.
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@@ -1,5 +1,5 @@
|
|||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.3-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-5.5.1-all.zip
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
|
|||||||
33
gradlew
vendored
33
gradlew
vendored
@@ -125,8 +125,8 @@ if $darwin; then
|
|||||||
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# For Cygwin or MSYS, switch paths to Windows format before running java
|
# For Cygwin, switch paths to Windows format before running java
|
||||||
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
|
if $cygwin ; then
|
||||||
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||||
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||||
JAVACMD=`cygpath --unix "$JAVACMD"`
|
JAVACMD=`cygpath --unix "$JAVACMD"`
|
||||||
@@ -154,19 +154,19 @@ if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
|
|||||||
else
|
else
|
||||||
eval `echo args$i`="\"$arg\""
|
eval `echo args$i`="\"$arg\""
|
||||||
fi
|
fi
|
||||||
i=`expr $i + 1`
|
i=$((i+1))
|
||||||
done
|
done
|
||||||
case $i in
|
case $i in
|
||||||
0) set -- ;;
|
(0) set -- ;;
|
||||||
1) set -- "$args0" ;;
|
(1) set -- "$args0" ;;
|
||||||
2) set -- "$args0" "$args1" ;;
|
(2) set -- "$args0" "$args1" ;;
|
||||||
3) set -- "$args0" "$args1" "$args2" ;;
|
(3) set -- "$args0" "$args1" "$args2" ;;
|
||||||
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
||||||
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
||||||
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
||||||
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
||||||
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
||||||
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
||||||
esac
|
esac
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -175,9 +175,14 @@ save () {
|
|||||||
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
||||||
echo " "
|
echo " "
|
||||||
}
|
}
|
||||||
APP_ARGS=`save "$@"`
|
APP_ARGS=$(save "$@")
|
||||||
|
|
||||||
# Collect all arguments for the java command, following the shell quoting and substitution rules
|
# Collect all arguments for the java command, following the shell quoting and substitution rules
|
||||||
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
|
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
|
||||||
|
|
||||||
|
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
|
||||||
|
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
|
||||||
|
cd "$(dirname "$0")"
|
||||||
|
fi
|
||||||
|
|
||||||
exec "$JAVACMD" "$@"
|
exec "$JAVACMD" "$@"
|
||||||
|
|||||||
3
gradlew.bat
vendored
3
gradlew.bat
vendored
@@ -29,9 +29,6 @@ if "%DIRNAME%" == "" set DIRNAME=.
|
|||||||
set APP_BASE_NAME=%~n0
|
set APP_BASE_NAME=%~n0
|
||||||
set APP_HOME=%DIRNAME%
|
set APP_HOME=%DIRNAME%
|
||||||
|
|
||||||
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
|
|
||||||
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
|
|
||||||
|
|
||||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
||||||
|
|
||||||
|
|||||||
@@ -163,10 +163,8 @@ public final class Device {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void setClipboardText(String text) {
|
public void setClipboardText(String text) {
|
||||||
boolean ok = serviceManager.getClipboardManager().setText(text);
|
serviceManager.getClipboardManager().setText(text);
|
||||||
if (ok) {
|
Ln.i("Device clipboard set");
|
||||||
Ln.i("Device clipboard set");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -178,10 +176,8 @@ public final class Device {
|
|||||||
Ln.e("Could not get built-in display");
|
Ln.e("Could not get built-in display");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
boolean ok = SurfaceControl.setDisplayPowerMode(d, mode);
|
SurfaceControl.setDisplayPowerMode(d, mode);
|
||||||
if (ok) {
|
Ln.i("Device screen turned " + (mode == Device.POWER_MODE_OFF ? "off" : "on"));
|
||||||
Ln.i("Device screen turned " + (mode == Device.POWER_MODE_OFF ? "off" : "on"));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -74,15 +74,13 @@ public class ClipboardManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean setText(CharSequence text) {
|
public void setText(CharSequence text) {
|
||||||
try {
|
try {
|
||||||
Method method = getSetPrimaryClipMethod();
|
Method method = getSetPrimaryClipMethod();
|
||||||
ClipData clipData = ClipData.newPlainText(null, text);
|
ClipData clipData = ClipData.newPlainText(null, text);
|
||||||
setPrimaryClip(method, manager, clipData);
|
setPrimaryClip(method, manager, clipData);
|
||||||
return true;
|
|
||||||
} catch (InvocationTargetException | IllegalAccessException | NoSuchMethodException e) {
|
} catch (InvocationTargetException | IllegalAccessException | NoSuchMethodException e) {
|
||||||
Ln.e("Could not invoke method", e);
|
Ln.e("Could not invoke method", e);
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -121,14 +121,12 @@ public final class SurfaceControl {
|
|||||||
return setDisplayPowerModeMethod;
|
return setDisplayPowerModeMethod;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean setDisplayPowerMode(IBinder displayToken, int mode) {
|
public static void setDisplayPowerMode(IBinder displayToken, int mode) {
|
||||||
try {
|
try {
|
||||||
Method method = getSetDisplayPowerModeMethod();
|
Method method = getSetDisplayPowerModeMethod();
|
||||||
method.invoke(null, displayToken, mode);
|
method.invoke(null, displayToken, mode);
|
||||||
return true;
|
|
||||||
} catch (InvocationTargetException | IllegalAccessException | NoSuchMethodException e) {
|
} catch (InvocationTargetException | IllegalAccessException | NoSuchMethodException e) {
|
||||||
Ln.e("Could not invoke method", e);
|
Ln.e("Could not invoke method", e);
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user