Compare commits
12 Commits
threadwait
...
logical_si
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4e12a20064 | ||
|
|
fc77f85b6e | ||
|
|
d30593e1d5 | ||
|
|
9e78b765da | ||
|
|
271de0954a | ||
|
|
54ccccd883 | ||
|
|
bea1c11f8e | ||
|
|
94e1696869 | ||
|
|
a346bb80f4 | ||
|
|
d421741a83 | ||
|
|
64d5edce92 | ||
|
|
4150eedcdf |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -2,3 +2,4 @@ build/
|
||||
/dist/
|
||||
.idea/
|
||||
.gradle/
|
||||
/x/
|
||||
|
||||
@@ -23,7 +23,7 @@ fps_counter_init(struct fps_counter *counter) {
|
||||
}
|
||||
|
||||
counter->thread = NULL;
|
||||
SDL_AtomicSet(&counter->started, 0);
|
||||
atomic_init(&counter->started, 0);
|
||||
// no need to initialize the other fields, they are unused until started
|
||||
|
||||
return true;
|
||||
@@ -35,6 +35,16 @@ fps_counter_destroy(struct fps_counter *counter) {
|
||||
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
|
||||
static void
|
||||
display_fps(struct fps_counter *counter) {
|
||||
@@ -70,10 +80,10 @@ run_fps_counter(void *data) {
|
||||
|
||||
mutex_lock(counter->mutex);
|
||||
while (!counter->interrupted) {
|
||||
while (!counter->interrupted && !SDL_AtomicGet(&counter->started)) {
|
||||
while (!counter->interrupted && !is_started(counter)) {
|
||||
cond_wait(counter->state_cond, counter->mutex);
|
||||
}
|
||||
while (!counter->interrupted && SDL_AtomicGet(&counter->started)) {
|
||||
while (!counter->interrupted && is_started(counter)) {
|
||||
uint32_t now = SDL_GetTicks();
|
||||
check_interval_expired(counter, now);
|
||||
|
||||
@@ -96,7 +106,7 @@ fps_counter_start(struct fps_counter *counter) {
|
||||
counter->nr_skipped = 0;
|
||||
mutex_unlock(counter->mutex);
|
||||
|
||||
SDL_AtomicSet(&counter->started, 1);
|
||||
set_started(counter, true);
|
||||
cond_signal(counter->state_cond);
|
||||
|
||||
// counter->thread is always accessed from the same thread, no need to lock
|
||||
@@ -114,13 +124,13 @@ fps_counter_start(struct fps_counter *counter) {
|
||||
|
||||
void
|
||||
fps_counter_stop(struct fps_counter *counter) {
|
||||
SDL_AtomicSet(&counter->started, 0);
|
||||
set_started(counter, false);
|
||||
cond_signal(counter->state_cond);
|
||||
}
|
||||
|
||||
bool
|
||||
fps_counter_is_started(struct fps_counter *counter) {
|
||||
return SDL_AtomicGet(&counter->started);
|
||||
return is_started(counter);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -145,7 +155,7 @@ fps_counter_join(struct fps_counter *counter) {
|
||||
|
||||
void
|
||||
fps_counter_add_rendered_frame(struct fps_counter *counter) {
|
||||
if (!SDL_AtomicGet(&counter->started)) {
|
||||
if (!is_started(counter)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -158,7 +168,7 @@ fps_counter_add_rendered_frame(struct fps_counter *counter) {
|
||||
|
||||
void
|
||||
fps_counter_add_skipped_frame(struct fps_counter *counter) {
|
||||
if (!SDL_AtomicGet(&counter->started)) {
|
||||
if (!is_started(counter)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
#ifndef FPSCOUNTER_H
|
||||
#define FPSCOUNTER_H
|
||||
|
||||
#include <stdatomic.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <SDL2/SDL_atomic.h>
|
||||
#include <SDL2/SDL_mutex.h>
|
||||
#include <SDL2/SDL_thread.h>
|
||||
|
||||
@@ -16,7 +16,7 @@ struct fps_counter {
|
||||
|
||||
// atomic so that we can check without locking the mutex
|
||||
// if the FPS counter is disabled, we don't want to lock unnecessarily
|
||||
SDL_atomic_t started;
|
||||
atomic_bool started;
|
||||
|
||||
// the following fields are protected by the mutex
|
||||
bool interrupted;
|
||||
|
||||
@@ -7,33 +7,6 @@
|
||||
#include "util/lock.h"
|
||||
#include "util/log.h"
|
||||
|
||||
// Convert window coordinates (as provided by SDL_GetMouseState() to renderer
|
||||
// coordinates (as provided in SDL mouse events)
|
||||
//
|
||||
// See my question:
|
||||
// <https://stackoverflow.com/questions/49111054/how-to-get-mouse-position-on-mouse-wheel-event>
|
||||
static void
|
||||
convert_to_renderer_coordinates(SDL_Renderer *renderer, int *x, int *y) {
|
||||
SDL_Rect viewport;
|
||||
float scale_x, scale_y;
|
||||
SDL_RenderGetViewport(renderer, &viewport);
|
||||
SDL_RenderGetScale(renderer, &scale_x, &scale_y);
|
||||
*x = (int) (*x / scale_x) - viewport.x;
|
||||
*y = (int) (*y / scale_y) - viewport.y;
|
||||
}
|
||||
|
||||
static struct point
|
||||
get_mouse_point(struct screen *screen) {
|
||||
int x;
|
||||
int y;
|
||||
SDL_GetMouseState(&x, &y);
|
||||
convert_to_renderer_coordinates(screen->renderer, &x, &y);
|
||||
return (struct point) {
|
||||
.x = x,
|
||||
.y = y,
|
||||
};
|
||||
}
|
||||
|
||||
static const int ACTION_DOWN = 1;
|
||||
static const int ACTION_UP = 1 << 1;
|
||||
|
||||
@@ -427,8 +400,8 @@ convert_mouse_motion(const SDL_MouseMotionEvent *from, struct screen *screen,
|
||||
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->frame_size;
|
||||
to->inject_touch_event.position.point.x = from->x;
|
||||
to->inject_touch_event.position.point.y = from->y;
|
||||
to->inject_touch_event.position.point =
|
||||
screen_convert_to_frame_coords(screen, from->x, from->y);
|
||||
to->inject_touch_event.pressure = 1.f;
|
||||
to->inject_touch_event.buttons = convert_mouse_buttons(from->state);
|
||||
|
||||
@@ -464,12 +437,14 @@ convert_touch(const SDL_TouchFingerEvent *from, struct screen *screen,
|
||||
}
|
||||
|
||||
struct size frame_size = screen->frame_size;
|
||||
// SDL touch event coordinates are normalized in the range [0; 1]
|
||||
float x = from->x * frame_size.width;
|
||||
float y = from->y * frame_size.height;
|
||||
|
||||
to->inject_touch_event.pointer_id = from->fingerId;
|
||||
to->inject_touch_event.position.screen_size = frame_size;
|
||||
// SDL touch event coordinates are normalized in the range [0; 1]
|
||||
to->inject_touch_event.position.point.x = from->x * frame_size.width;
|
||||
to->inject_touch_event.position.point.y = from->y * frame_size.height;
|
||||
to->inject_touch_event.position.point =
|
||||
screen_convert_to_frame_coords(screen, x, y);
|
||||
to->inject_touch_event.pressure = from->pressure;
|
||||
to->inject_touch_event.buttons = 0;
|
||||
return true;
|
||||
@@ -504,8 +479,8 @@ convert_mouse_button(const SDL_MouseButtonEvent *from, struct screen *screen,
|
||||
|
||||
to->inject_touch_event.pointer_id = POINTER_ID_MOUSE;
|
||||
to->inject_touch_event.position.screen_size = screen->frame_size;
|
||||
to->inject_touch_event.position.point.x = from->x;
|
||||
to->inject_touch_event.position.point.y = from->y;
|
||||
to->inject_touch_event.position.point =
|
||||
screen_convert_to_frame_coords(screen, from->x, from->y);
|
||||
to->inject_touch_event.pressure = 1.f;
|
||||
to->inject_touch_event.buttons =
|
||||
convert_mouse_buttons(SDL_BUTTON(from->button));
|
||||
@@ -557,9 +532,15 @@ input_manager_process_mouse_button(struct input_manager *im,
|
||||
static bool
|
||||
convert_mouse_wheel(const SDL_MouseWheelEvent *from, struct screen *screen,
|
||||
struct control_msg *to) {
|
||||
|
||||
// mouse_x and mouse_y are expressed in pixels relatice to the window
|
||||
int mouse_x;
|
||||
int mouse_y;
|
||||
SDL_GetMouseState(&mouse_x, &mouse_y);
|
||||
|
||||
struct position position = {
|
||||
.screen_size = screen->frame_size,
|
||||
.point = get_mouse_point(screen),
|
||||
.point = screen_convert_to_frame_coords(screen, mouse_x, mouse_y),
|
||||
};
|
||||
|
||||
to->type = CONTROL_MSG_TYPE_INJECT_SCROLL_EVENT;
|
||||
|
||||
@@ -149,6 +149,32 @@ get_initial_optimal_size(struct size frame_size, uint16_t req_width,
|
||||
return window_size;
|
||||
}
|
||||
|
||||
static void
|
||||
update_frame_rect(struct screen *screen) {
|
||||
int ww;
|
||||
int wh;
|
||||
SDL_GL_GetDrawableSize(screen->window, &ww, &wh);
|
||||
|
||||
// 32 bits because we need to multiply two 16 bits values
|
||||
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;
|
||||
@@ -206,13 +232,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);
|
||||
@@ -258,12 +277,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);
|
||||
|
||||
@@ -309,6 +322,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);
|
||||
|
||||
@@ -316,10 +330,16 @@ screen_update_frame(struct screen *screen, struct video_buffer *vb) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
screen_window_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);
|
||||
}
|
||||
|
||||
@@ -391,7 +411,7 @@ screen_handle_window_event(struct screen *screen,
|
||||
// window is maximized or fullscreen is enabled.
|
||||
screen->windowed_window_size = get_window_size(screen->window);
|
||||
}
|
||||
screen_render(screen);
|
||||
screen_window_resized(screen);
|
||||
break;
|
||||
case SDL_WINDOWEVENT_MAXIMIZED:
|
||||
// The backup size must be non-nul.
|
||||
@@ -412,3 +432,11 @@ screen_handle_window_event(struct screen *screen,
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
struct point
|
||||
screen_convert_to_frame_coords(struct screen *screen, float x, float y) {
|
||||
struct point out;
|
||||
out.x = (x - screen->rect.x) * screen->frame_size.width / screen->rect.w;
|
||||
out.y = (y - screen->rect.y) * screen->frame_size.height / screen->rect.h;
|
||||
return out;
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ struct screen {
|
||||
// Since we receive the event SIZE_CHANGED before MAXIMIZED, we must be
|
||||
// able to revert the size to its non-maximized value.
|
||||
struct size windowed_window_size_backup;
|
||||
struct SDL_Rect rect;
|
||||
bool has_frame;
|
||||
bool fullscreen;
|
||||
bool maximized;
|
||||
@@ -44,6 +45,12 @@ struct screen {
|
||||
.width = 0, \
|
||||
.height = 0, \
|
||||
}, \
|
||||
.rect = { \
|
||||
.x = 0, \
|
||||
.y = 0, \
|
||||
.w = 0, \
|
||||
.h = 0, \
|
||||
}, \
|
||||
.has_frame = false, \
|
||||
.fullscreen = false, \
|
||||
.maximized = false, \
|
||||
@@ -74,6 +81,10 @@ screen_destroy(struct screen *screen);
|
||||
bool
|
||||
screen_update_frame(struct screen *screen, struct video_buffer *vb);
|
||||
|
||||
// update content after window resizing
|
||||
void
|
||||
screen_window_resized(struct screen *screen);
|
||||
|
||||
// render the texture to the renderer
|
||||
void
|
||||
screen_render(struct screen *screen);
|
||||
@@ -94,4 +105,9 @@ screen_resize_to_pixel_perfect(struct screen *screen);
|
||||
void
|
||||
screen_handle_window_event(struct screen *screen, const SDL_WindowEvent *event);
|
||||
|
||||
// convert point from window coordinates to frame coordinates
|
||||
// x and y are expressed in pixels (float to allow partial pixels)
|
||||
struct point
|
||||
screen_convert_to_frame_coords(struct screen *screen, float x, float y);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
#include <inttypes.h>
|
||||
#include <libgen.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <SDL2/SDL_thread.h>
|
||||
#include <SDL2/SDL_timer.h>
|
||||
#include <SDL2/SDL_platform.h>
|
||||
@@ -319,14 +318,12 @@ connect_to_server(uint16_t port, uint32_t attempts, uint32_t delay) {
|
||||
}
|
||||
|
||||
static void
|
||||
close_socket(socket_t *socket) {
|
||||
assert(*socket != INVALID_SOCKET);
|
||||
net_shutdown(*socket, SHUT_RDWR);
|
||||
if (!net_close(*socket)) {
|
||||
close_socket(socket_t socket) {
|
||||
assert(socket != INVALID_SOCKET);
|
||||
net_shutdown(socket, SHUT_RDWR);
|
||||
if (!net_close(socket)) {
|
||||
LOGW("Could not close socket");
|
||||
return;
|
||||
}
|
||||
*socket = INVALID_SOCKET;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -338,10 +335,14 @@ static int
|
||||
run_wait_server(void *data) {
|
||||
struct server *server = data;
|
||||
cmd_simple_wait(server->process, NULL); // ignore exit code
|
||||
|
||||
// wake up any net_select_interruptible()
|
||||
close(server->pipe_intr[1]);
|
||||
|
||||
// no need for synchronization, server_socket is initialized before this
|
||||
// thread was created
|
||||
if (server->server_socket != INVALID_SOCKET
|
||||
&& !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");
|
||||
return 0;
|
||||
}
|
||||
@@ -366,36 +367,38 @@ server_start(struct server *server, const char *serial,
|
||||
goto error1;
|
||||
}
|
||||
|
||||
bool ok = net_pipe(server->pipe_intr);
|
||||
if (!ok) {
|
||||
perror("pipe");
|
||||
goto error2;
|
||||
}
|
||||
|
||||
// server will connect to our server socket
|
||||
server->process = execute_server(server, params);
|
||||
if (server->process == PROCESS_NONE) {
|
||||
goto error3;
|
||||
goto error2;
|
||||
}
|
||||
|
||||
// If the server process dies before connecting to the server socket, then
|
||||
// the client will be stuck forever on accept(). To avoid the problem, we
|
||||
// must be able to wake up the accept() call when the server dies. To keep
|
||||
// things simple and multiplatform, just spawn a new thread waiting for the
|
||||
// server process and calling shutdown()/close() on the server socket if
|
||||
// necessary to wake up any accept() blocking call.
|
||||
server->wait_server_thread =
|
||||
SDL_CreateThread(run_wait_server, "wait-server", server);
|
||||
if (!server->wait_server_thread) {
|
||||
cmd_terminate(server->process);
|
||||
cmd_simple_wait(server->process, NULL); // ignore exit code
|
||||
goto error3;
|
||||
goto error2;
|
||||
}
|
||||
|
||||
server->tunnel_enabled = true;
|
||||
|
||||
return true;
|
||||
|
||||
error3:
|
||||
close(server->pipe_intr[0]);
|
||||
close(server->pipe_intr[1]);
|
||||
error2:
|
||||
if (!server->tunnel_forward) {
|
||||
close_socket(&server->server_socket);
|
||||
bool was_closed =
|
||||
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);
|
||||
error1:
|
||||
@@ -406,34 +409,23 @@ error1:
|
||||
bool
|
||||
server_connect_to(struct server *server) {
|
||||
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);
|
||||
if (server->video_socket == INVALID_SOCKET) {
|
||||
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);
|
||||
if (server->control_socket == INVALID_SOCKET) {
|
||||
// the video_socket will be cleaned up on destroy
|
||||
return false;
|
||||
}
|
||||
|
||||
close(server->pipe_intr[0]);
|
||||
|
||||
// we don't need the server socket anymore
|
||||
close_socket(&server->server_socket);
|
||||
if (!atomic_flag_test_and_set(&server->server_socket_closed)) {
|
||||
// close it from here
|
||||
close_socket(server->server_socket);
|
||||
// otherwise, it is closed by run_wait_server()
|
||||
}
|
||||
} else {
|
||||
uint32_t attempts = 100;
|
||||
uint32_t delay = 100; // ms
|
||||
@@ -460,14 +452,15 @@ server_connect_to(struct server *server) {
|
||||
|
||||
void
|
||||
server_stop(struct server *server) {
|
||||
if (server->server_socket != INVALID_SOCKET) {
|
||||
close_socket(&server->server_socket);
|
||||
if (server->server_socket != INVALID_SOCKET
|
||||
&& !atomic_flag_test_and_set(&server->server_socket_closed)) {
|
||||
close_socket(server->server_socket);
|
||||
}
|
||||
if (server->video_socket != INVALID_SOCKET) {
|
||||
close_socket(&server->video_socket);
|
||||
close_socket(server->video_socket);
|
||||
}
|
||||
if (server->control_socket != INVALID_SOCKET) {
|
||||
close_socket(&server->control_socket);
|
||||
close_socket(server->control_socket);
|
||||
}
|
||||
|
||||
assert(server->process != PROCESS_NONE);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#ifndef SERVER_H
|
||||
#define SERVER_H
|
||||
|
||||
#include <stdatomic.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <SDL2/SDL_thread.h>
|
||||
@@ -14,7 +15,7 @@ struct server {
|
||||
char *serial;
|
||||
process_t process;
|
||||
SDL_Thread *wait_server_thread;
|
||||
int pipe_intr[2]; // to wake up blocking accept() on process exit
|
||||
atomic_flag server_socket_closed;
|
||||
socket_t server_socket; // only used if !tunnel_forward
|
||||
socket_t video_socket;
|
||||
socket_t control_socket;
|
||||
@@ -27,6 +28,8 @@ struct server {
|
||||
#define SERVER_INITIALIZER { \
|
||||
.serial = NULL, \
|
||||
.process = PROCESS_NONE, \
|
||||
.wait_server_thread = NULL, \
|
||||
.server_socket_closed = ATOMIC_FLAG_INIT, \
|
||||
.server_socket = INVALID_SOCKET, \
|
||||
.video_socket = INVALID_SOCKET, \
|
||||
.control_socket = INVALID_SOCKET, \
|
||||
|
||||
@@ -1,22 +1,16 @@
|
||||
#include "net.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <SDL2/SDL_platform.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "common.h"
|
||||
#include "log.h"
|
||||
|
||||
#ifdef __WINDOWS__
|
||||
# include <io.h>
|
||||
# include <winsock2.h>
|
||||
typedef int socklen_t;
|
||||
#else
|
||||
# include <sys/select.h>
|
||||
# include <sys/socket.h>
|
||||
# include <sys/types.h>
|
||||
# include <sys/socket.h>
|
||||
# include <netinet/in.h>
|
||||
# include <arpa/inet.h>
|
||||
# include <unistd.h>
|
||||
@@ -151,38 +145,3 @@ net_close(socket_t socket) {
|
||||
return !close(socket);
|
||||
#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,12 +54,4 @@ net_shutdown(socket_t socket, int how);
|
||||
bool
|
||||
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
|
||||
|
||||
@@ -7,7 +7,7 @@ buildscript {
|
||||
jcenter()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:3.4.2'
|
||||
classpath 'com.android.tools.build:gradle:3.6.2'
|
||||
|
||||
// NOTE: Do not place your application dependencies here; they belong
|
||||
// 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
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-5.5.1-all.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.3-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
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\""
|
||||
fi
|
||||
|
||||
# For Cygwin, switch paths to Windows format before running java
|
||||
if $cygwin ; then
|
||||
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
|
||||
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||
JAVACMD=`cygpath --unix "$JAVACMD"`
|
||||
@@ -154,19 +154,19 @@ if $cygwin ; then
|
||||
else
|
||||
eval `echo args$i`="\"$arg\""
|
||||
fi
|
||||
i=$((i+1))
|
||||
i=`expr $i + 1`
|
||||
done
|
||||
case $i in
|
||||
(0) set -- ;;
|
||||
(1) set -- "$args0" ;;
|
||||
(2) set -- "$args0" "$args1" ;;
|
||||
(3) set -- "$args0" "$args1" "$args2" ;;
|
||||
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
||||
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
||||
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
||||
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
||||
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
||||
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
||||
0) set -- ;;
|
||||
1) set -- "$args0" ;;
|
||||
2) set -- "$args0" "$args1" ;;
|
||||
3) set -- "$args0" "$args1" "$args2" ;;
|
||||
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
||||
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
||||
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
||||
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
||||
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
||||
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
@@ -175,14 +175,9 @@ save () {
|
||||
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
||||
echo " "
|
||||
}
|
||||
APP_ARGS=$(save "$@")
|
||||
APP_ARGS=`save "$@"`
|
||||
|
||||
# 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"
|
||||
|
||||
# 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" "$@"
|
||||
|
||||
3
gradlew.bat
vendored
3
gradlew.bat
vendored
@@ -29,6 +29,9 @@ if "%DIRNAME%" == "" set DIRNAME=.
|
||||
set APP_BASE_NAME=%~n0
|
||||
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.
|
||||
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
||||
|
||||
|
||||
@@ -163,9 +163,11 @@ public final class Device {
|
||||
}
|
||||
|
||||
public void setClipboardText(String text) {
|
||||
serviceManager.getClipboardManager().setText(text);
|
||||
boolean ok = serviceManager.getClipboardManager().setText(text);
|
||||
if (ok) {
|
||||
Ln.i("Device clipboard set");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mode one of the {@code SCREEN_POWER_MODE_*} constants
|
||||
@@ -176,9 +178,11 @@ public final class Device {
|
||||
Ln.e("Could not get built-in display");
|
||||
return;
|
||||
}
|
||||
SurfaceControl.setDisplayPowerMode(d, mode);
|
||||
boolean ok = SurfaceControl.setDisplayPowerMode(d, mode);
|
||||
if (ok) {
|
||||
Ln.i("Device screen turned " + (mode == Device.POWER_MODE_OFF ? "off" : "on"));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable auto-rotation (if enabled), set the screen rotation and re-enable auto-rotation (if it was enabled).
|
||||
|
||||
@@ -74,13 +74,15 @@ public class ClipboardManager {
|
||||
}
|
||||
}
|
||||
|
||||
public void setText(CharSequence text) {
|
||||
public boolean setText(CharSequence text) {
|
||||
try {
|
||||
Method method = getSetPrimaryClipMethod();
|
||||
ClipData clipData = ClipData.newPlainText(null, text);
|
||||
setPrimaryClip(method, manager, clipData);
|
||||
return true;
|
||||
} catch (InvocationTargetException | IllegalAccessException | NoSuchMethodException e) {
|
||||
Ln.e("Could not invoke method", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -121,12 +121,14 @@ public final class SurfaceControl {
|
||||
return setDisplayPowerModeMethod;
|
||||
}
|
||||
|
||||
public static void setDisplayPowerMode(IBinder displayToken, int mode) {
|
||||
public static boolean setDisplayPowerMode(IBinder displayToken, int mode) {
|
||||
try {
|
||||
Method method = getSetDisplayPowerModeMethod();
|
||||
method.invoke(null, displayToken, mode);
|
||||
return true;
|
||||
} catch (InvocationTargetException | IllegalAccessException | NoSuchMethodException e) {
|
||||
Ln.e("Could not invoke method", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user