mirror of
https://github.com/Genymobile/scrcpy.git
synced 2025-08-11 02:28:57 +00:00
Migrate from SDL2 to SDL3
Refs <https://wiki.libsdl.org/SDL3/README-migration>
This commit is contained in:
parent
d7e0d36fe6
commit
77cd5d9aef
35 changed files with 632 additions and 558 deletions
|
@ -63,6 +63,7 @@ src = [
|
|||
'src/util/thread.c',
|
||||
'src/util/tick.c',
|
||||
'src/util/timeout.c',
|
||||
'src/util/window.c',
|
||||
]
|
||||
|
||||
conf = configuration_data()
|
||||
|
@ -117,7 +118,7 @@ dependencies = [
|
|||
dependency('libavcodec', version: '>= 57.37', static: static),
|
||||
dependency('libavutil', static: static),
|
||||
dependency('libswresample', static: static),
|
||||
dependency('sdl2', version: '>= 2.0.5', static: static),
|
||||
dependency('sdl3', version: '>= 3.2.0', static: static),
|
||||
]
|
||||
|
||||
if v4l2_support
|
||||
|
|
|
@ -1,23 +1,40 @@
|
|||
#include "audio_player.h"
|
||||
|
||||
#include "util/log.h"
|
||||
#include "SDL3/SDL_hints.h"
|
||||
|
||||
/** Downcast frame_sink to sc_audio_player */
|
||||
#define DOWNCAST(SINK) container_of(SINK, struct sc_audio_player, frame_sink)
|
||||
|
||||
#define SC_SDL_SAMPLE_FMT AUDIO_F32
|
||||
#define SC_SDL_SAMPLE_FMT SDL_AUDIO_F32LE
|
||||
|
||||
static void SDLCALL
|
||||
sc_audio_player_sdl_callback(void *userdata, uint8_t *stream, int len_int) {
|
||||
sc_audio_player_stream_callback(void *userdata, SDL_AudioStream *stream,
|
||||
int additional_amount, int total_amount) {
|
||||
(void) total_amount;
|
||||
|
||||
struct sc_audio_player *ap = userdata;
|
||||
|
||||
assert(len_int > 0);
|
||||
size_t len = len_int;
|
||||
if (additional_amount > 0) {
|
||||
size_t len = additional_amount;
|
||||
|
||||
assert(len <= ap->aout_buffer_size);
|
||||
if (len > ap->aout_buffer_size) {
|
||||
// Just in case for release builds
|
||||
LOGE("Unexpected SDL audio behavior: too much data requested");
|
||||
len = ap->aout_buffer_size;
|
||||
}
|
||||
|
||||
assert(len % ap->audioreg.sample_size == 0);
|
||||
uint32_t out_samples = len / ap->audioreg.sample_size;
|
||||
|
||||
sc_audio_regulator_pull(&ap->audioreg, stream, out_samples);
|
||||
sc_audio_regulator_pull(&ap->audioreg, ap->aout_buffer, out_samples);
|
||||
bool ok = SDL_PutAudioStreamData(stream, ap->aout_buffer, len);
|
||||
SDL_stack_free(data);
|
||||
if (!ok) {
|
||||
LOGW("Audio stream error: %s", SDL_GetError());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
|
@ -61,23 +78,42 @@ sc_audio_player_frame_sink_open(struct sc_frame_sink *sink,
|
|||
/ SC_TICK_FREQ;
|
||||
assert(aout_samples <= 0xFFFF);
|
||||
|
||||
SDL_AudioSpec desired = {
|
||||
.freq = ctx->sample_rate,
|
||||
.format = SC_SDL_SAMPLE_FMT,
|
||||
.channels = nb_channels,
|
||||
.samples = aout_samples,
|
||||
.callback = sc_audio_player_sdl_callback,
|
||||
.userdata = ap,
|
||||
};
|
||||
SDL_AudioSpec obtained;
|
||||
|
||||
ap->device = SDL_OpenAudioDevice(NULL, 0, &desired, &obtained, 0);
|
||||
if (!ap->device) {
|
||||
LOGE("Could not open audio device: %s", SDL_GetError());
|
||||
char str[5 + 1]; // max 65535
|
||||
int r = snprintf(str, sizeof(str), "%" PRIu16, (uint16_t) aout_samples);
|
||||
assert(r >= 0 && (size_t) r < sizeof(str));
|
||||
(void) r;
|
||||
if (!SDL_SetHint(SDL_HINT_AUDIO_DEVICE_SAMPLE_FRAMES, str)) {
|
||||
LOGE("Could not set audio output buffer");
|
||||
sc_audio_regulator_destroy(&ap->audioreg);
|
||||
return false;
|
||||
}
|
||||
|
||||
ap->aout_buffer_size = aout_samples * sample_size;
|
||||
ap->aout_buffer = malloc(ap->aout_buffer_size);
|
||||
if (!ap->aout_buffer) {
|
||||
sc_audio_regulator_destroy(&ap->audioreg);
|
||||
return false;
|
||||
}
|
||||
|
||||
SDL_AudioSpec spec = {
|
||||
.freq = ctx->sample_rate,
|
||||
.format = SC_SDL_SAMPLE_FMT,
|
||||
.channels = nb_channels,
|
||||
};
|
||||
|
||||
ap->stream = SDL_OpenAudioDeviceStream(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK,
|
||||
&spec,
|
||||
sc_audio_player_stream_callback, ap);
|
||||
if (!ap->stream) {
|
||||
LOGE("Could not open audio device: %s", SDL_GetError());
|
||||
free(ap->aout_buffer);
|
||||
sc_audio_regulator_destroy(&ap->audioreg);
|
||||
return false;
|
||||
}
|
||||
|
||||
ap->device = SDL_GetAudioStreamDevice(ap->stream);
|
||||
assert(ap->device);
|
||||
|
||||
// The thread calling open() is the thread calling push(), which fills the
|
||||
// audio buffer consumed by the SDL audio thread.
|
||||
ok = sc_thread_set_priority(SC_THREAD_PRIORITY_TIME_CRITICAL);
|
||||
|
@ -86,7 +122,7 @@ sc_audio_player_frame_sink_open(struct sc_frame_sink *sink,
|
|||
(void) ok; // We don't care if it worked, at least we tried
|
||||
}
|
||||
|
||||
SDL_PauseAudioDevice(ap->device, 0);
|
||||
SDL_ResumeAudioDevice(ap->device);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -95,11 +131,16 @@ static void
|
|||
sc_audio_player_frame_sink_close(struct sc_frame_sink *sink) {
|
||||
struct sc_audio_player *ap = DOWNCAST(sink);
|
||||
|
||||
assert(ap->stream);
|
||||
assert(ap->device);
|
||||
SDL_PauseAudioDevice(ap->device, 1);
|
||||
SDL_CloseAudioDevice(ap->device);
|
||||
SDL_PauseAudioDevice(ap->device);
|
||||
|
||||
// ap->device is owned by ap->stream
|
||||
SDL_DestroyAudioStream(ap->stream);
|
||||
|
||||
sc_audio_regulator_destroy(&ap->audioreg);
|
||||
|
||||
free(ap->aout_buffer);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
#include "common.h"
|
||||
|
||||
#include <SDL2/SDL_audio.h>
|
||||
#include <SDL3/SDL_audio.h>
|
||||
|
||||
#include "audio_regulator.h"
|
||||
#include "trait/frame_sink.h"
|
||||
|
@ -22,7 +22,11 @@ struct sc_audio_player {
|
|||
// SDL audio output buffer size
|
||||
sc_tick output_buffer_duration;
|
||||
|
||||
SDL_AudioDeviceID device;
|
||||
uint8_t *aout_buffer;
|
||||
size_t aout_buffer_size;
|
||||
|
||||
SDL_AudioStream *stream;
|
||||
SDL_AudioDeviceID device; // owned by the audio stream
|
||||
struct sc_audio_regulator audioreg;
|
||||
};
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
#include <libavcodec/version.h>
|
||||
#include <libavformat/version.h>
|
||||
#include <libavutil/version.h>
|
||||
#include <SDL2/SDL_version.h>
|
||||
#include <SDL3/SDL_version.h>
|
||||
|
||||
#ifndef _WIN32
|
||||
# define PRIu64_ PRIu64
|
||||
|
@ -61,28 +61,6 @@
|
|||
# define SCRCPY_LAVC_HAS_CODECPAR_CODEC_SIDEDATA
|
||||
#endif
|
||||
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 6)
|
||||
// <https://github.com/libsdl-org/SDL/commit/d7a318de563125e5bb465b1000d6bc9576fbc6fc>
|
||||
# define SCRCPY_SDL_HAS_HINT_TOUCH_MOUSE_EVENTS
|
||||
#endif
|
||||
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 8)
|
||||
// <https://hg.libsdl.org/SDL/rev/dfde5d3f9781>
|
||||
# define SCRCPY_SDL_HAS_HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR
|
||||
#endif
|
||||
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 16)
|
||||
# define SCRCPY_SDL_HAS_THREAD_PRIORITY_TIME_CRITICAL
|
||||
#endif
|
||||
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 18)
|
||||
# define SCRCPY_SDL_HAS_HINT_APP_NAME
|
||||
#endif
|
||||
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 14)
|
||||
# define SCRCPY_SDL_HAS_HINT_AUDIO_DEVICE_APP_NAME
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_STRDUP
|
||||
char *strdup(const char *s);
|
||||
#endif
|
||||
|
|
|
@ -12,8 +12,11 @@ sc_display_init_novideo_icon(struct sc_display *display,
|
|||
SDL_Surface *icon_novideo) {
|
||||
assert(icon_novideo);
|
||||
|
||||
if (SDL_RenderSetLogicalSize(display->renderer,
|
||||
icon_novideo->w, icon_novideo->h)) {
|
||||
bool ok = SDL_SetRenderLogicalPresentation(display->renderer,
|
||||
icon_novideo->w,
|
||||
icon_novideo->h,
|
||||
SDL_LOGICAL_PRESENTATION_LETTERBOX);
|
||||
if (!ok) {
|
||||
LOGW("Could not set renderer logical size: %s", SDL_GetError());
|
||||
// don't fail
|
||||
}
|
||||
|
@ -31,16 +34,13 @@ sc_display_init_novideo_icon(struct sc_display *display,
|
|||
bool
|
||||
sc_display_init(struct sc_display *display, SDL_Window *window,
|
||||
SDL_Surface *icon_novideo, bool mipmaps) {
|
||||
display->renderer =
|
||||
SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
|
||||
display->renderer = SDL_CreateRenderer(window, NULL);
|
||||
if (!display->renderer) {
|
||||
LOGE("Could not create renderer: %s", SDL_GetError());
|
||||
return false;
|
||||
}
|
||||
|
||||
SDL_RendererInfo renderer_info;
|
||||
int r = SDL_GetRendererInfo(display->renderer, &renderer_info);
|
||||
const char *renderer_name = r ? NULL : renderer_info.name;
|
||||
const char *renderer_name = SDL_GetRendererName(display->renderer);
|
||||
LOGI("Renderer: %s", renderer_name ? renderer_name : "(unknown)");
|
||||
|
||||
display->mipmaps = false;
|
||||
|
@ -100,7 +100,7 @@ sc_display_init(struct sc_display *display, SDL_Window *window,
|
|||
bool ok = sc_display_init_novideo_icon(display, icon_novideo);
|
||||
if (!ok) {
|
||||
#ifdef SC_DISPLAY_FORCE_OPENGL_CORE_PROFILE
|
||||
SDL_GL_DeleteContext(display->gl_context);
|
||||
SDL_GL_DestroyContext(display->gl_context);
|
||||
#endif
|
||||
SDL_DestroyRenderer(display->renderer);
|
||||
return false;
|
||||
|
@ -116,7 +116,7 @@ sc_display_destroy(struct sc_display *display) {
|
|||
av_frame_free(&display->pending.frame);
|
||||
}
|
||||
#ifdef SC_DISPLAY_FORCE_OPENGL_CORE_PROFILE
|
||||
SDL_GL_DeleteContext(display->gl_context);
|
||||
SDL_GL_DestroyContext(display->gl_context);
|
||||
#endif
|
||||
if (display->texture) {
|
||||
SDL_DestroyTexture(display->texture);
|
||||
|
@ -124,20 +124,25 @@ sc_display_destroy(struct sc_display *display) {
|
|||
SDL_DestroyRenderer(display->renderer);
|
||||
}
|
||||
|
||||
static SDL_YUV_CONVERSION_MODE
|
||||
sc_display_to_sdl_color_mode(enum AVColorSpace color_space,
|
||||
static enum SDL_Colorspace
|
||||
sc_display_to_sdl_color_space(enum AVColorSpace color_space,
|
||||
enum AVColorRange color_range) {
|
||||
bool full_range = color_range == AVCOL_RANGE_JPEG;
|
||||
|
||||
switch (color_space) {
|
||||
case AVCOL_SPC_BT709:
|
||||
return SDL_YUV_CONVERSION_BT709;
|
||||
return full_range ? SDL_COLORSPACE_BT709_FULL
|
||||
: SDL_COLORSPACE_BT709_LIMITED;
|
||||
case AVCOL_SPC_BT470BG:
|
||||
case AVCOL_SPC_SMPTE170M:
|
||||
return SDL_YUV_CONVERSION_BT601;
|
||||
return full_range ? SDL_COLORSPACE_BT601_FULL
|
||||
: SDL_COLORSPACE_BT601_LIMITED;
|
||||
case AVCOL_SPC_BT2020_NCL:
|
||||
case AVCOL_SPC_BT2020_CL:
|
||||
return full_range ? SDL_COLORSPACE_BT2020_FULL
|
||||
: SDL_COLORSPACE_BT2020_LIMITED;
|
||||
default:
|
||||
if (color_range == AVCOL_RANGE_JPEG) {
|
||||
return SDL_YUV_CONVERSION_JPEG;
|
||||
}
|
||||
return SDL_YUV_CONVERSION_AUTOMATIC;
|
||||
return SDL_COLORSPACE_JPEG;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -145,10 +150,36 @@ static SDL_Texture *
|
|||
sc_display_create_texture(struct sc_display *display,
|
||||
struct sc_size size, enum AVColorSpace color_space,
|
||||
enum AVColorRange color_range) {
|
||||
SDL_PropertiesID props = SDL_CreateProperties();
|
||||
if (!props) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
enum SDL_Colorspace sdl_color_space =
|
||||
sc_display_to_sdl_color_space(color_space, color_range);
|
||||
|
||||
bool ok =
|
||||
SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_FORMAT_NUMBER,
|
||||
SDL_PIXELFORMAT_YV12);
|
||||
ok &= SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_ACCESS_NUMBER,
|
||||
SDL_TEXTUREACCESS_STREAMING);
|
||||
ok &= SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_WIDTH_NUMBER,
|
||||
size.width);
|
||||
ok &= SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_HEIGHT_NUMBER,
|
||||
size.height);
|
||||
ok &= SDL_SetNumberProperty(props,
|
||||
SDL_PROP_TEXTURE_CREATE_COLORSPACE_NUMBER,
|
||||
sdl_color_space);
|
||||
|
||||
if (!ok) {
|
||||
LOGE("Could not set texture properties");
|
||||
SDL_DestroyProperties(props);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SDL_Renderer *renderer = display->renderer;
|
||||
SDL_Texture *texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_YV12,
|
||||
SDL_TEXTUREACCESS_STREAMING,
|
||||
size.width, size.height);
|
||||
SDL_Texture *texture = SDL_CreateTextureWithProperties(renderer, props);
|
||||
SDL_DestroyProperties(props);
|
||||
if (!texture) {
|
||||
LOGD("Could not create texture: %s", SDL_GetError());
|
||||
return NULL;
|
||||
|
@ -157,21 +188,35 @@ sc_display_create_texture(struct sc_display *display,
|
|||
if (display->mipmaps) {
|
||||
struct sc_opengl *gl = &display->gl;
|
||||
|
||||
SDL_GL_BindTexture(texture, NULL, NULL);
|
||||
SDL_PropertiesID props = SDL_GetTextureProperties(texture);
|
||||
if (!props) {
|
||||
LOGE("Could not get texture properties: %s", SDL_GetError());
|
||||
SDL_DestroyTexture(texture);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int64_t texture_id =
|
||||
SDL_GetNumberProperty(props,
|
||||
SDL_PROP_TEXTURE_OPENGL_TEXTURE_NUMBER, 0);
|
||||
SDL_DestroyProperties(props);
|
||||
if (!texture_id) {
|
||||
LOGE("Could not get texture id: %s", SDL_GetError());
|
||||
SDL_DestroyTexture(texture);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
assert(!(texture_id & ~0xFFFFFFFF)); // fits in uint32_t
|
||||
display->texture_id = texture_id;
|
||||
gl->BindTexture(GL_TEXTURE_2D, display->texture_id);
|
||||
|
||||
// Enable trilinear filtering for downscaling
|
||||
gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
|
||||
GL_LINEAR_MIPMAP_LINEAR);
|
||||
gl->TexParameterf(GL_TEXTURE_2D, GL_TEXTURE_LOD_BIAS, -1.f);
|
||||
|
||||
SDL_GL_UnbindTexture(texture);
|
||||
gl->BindTexture(GL_TEXTURE_2D, 0);
|
||||
}
|
||||
|
||||
// Configure YUV color range conversion
|
||||
SDL_YUV_CONVERSION_MODE sdl_color_mode =
|
||||
sc_display_to_sdl_color_mode(color_space, color_range);
|
||||
SDL_SetYUVConversionMode(sdl_color_mode);
|
||||
|
||||
return texture;
|
||||
}
|
||||
|
||||
|
@ -275,19 +320,22 @@ sc_display_prepare_texture(struct sc_display *display, struct sc_size size,
|
|||
static bool
|
||||
sc_display_update_texture_internal(struct sc_display *display,
|
||||
const AVFrame *frame) {
|
||||
int ret = SDL_UpdateYUVTexture(display->texture, NULL,
|
||||
bool ok = SDL_UpdateYUVTexture(display->texture, NULL,
|
||||
frame->data[0], frame->linesize[0],
|
||||
frame->data[1], frame->linesize[1],
|
||||
frame->data[2], frame->linesize[2]);
|
||||
if (ret) {
|
||||
if (!ok) {
|
||||
LOGD("Could not update texture: %s", SDL_GetError());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (display->mipmaps) {
|
||||
SDL_GL_BindTexture(display->texture, NULL, NULL);
|
||||
assert(display->texture_id);
|
||||
struct sc_opengl *gl = &display->gl;
|
||||
|
||||
gl->BindTexture(GL_TEXTURE_2D, display->texture_id);
|
||||
display->gl.GenerateMipmap(GL_TEXTURE_2D);
|
||||
SDL_GL_UnbindTexture(display->texture);
|
||||
gl->BindTexture(GL_TEXTURE_2D, 0);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -325,8 +373,10 @@ sc_display_render(struct sc_display *display, const SDL_Rect *geometry,
|
|||
SDL_Texture *texture = display->texture;
|
||||
|
||||
if (orientation == SC_ORIENTATION_0) {
|
||||
int ret = SDL_RenderCopy(renderer, texture, NULL, geometry);
|
||||
if (ret) {
|
||||
SDL_FRect frect;
|
||||
SDL_RectToFRect(geometry, &frect);
|
||||
bool ok = SDL_RenderTexture(renderer, texture, NULL, &frect);
|
||||
if (!ok) {
|
||||
LOGE("Could not render texture: %s", SDL_GetError());
|
||||
return SC_DISPLAY_RESULT_ERROR;
|
||||
}
|
||||
|
@ -334,24 +384,22 @@ sc_display_render(struct sc_display *display, const SDL_Rect *geometry,
|
|||
unsigned cw_rotation = sc_orientation_get_rotation(orientation);
|
||||
double angle = 90 * cw_rotation;
|
||||
|
||||
const SDL_Rect *dstrect = NULL;
|
||||
SDL_Rect rect;
|
||||
SDL_FRect frect;
|
||||
if (sc_orientation_is_swap(orientation)) {
|
||||
rect.x = geometry->x + (geometry->w - geometry->h) / 2;
|
||||
rect.y = geometry->y + (geometry->h - geometry->w) / 2;
|
||||
rect.w = geometry->h;
|
||||
rect.h = geometry->w;
|
||||
dstrect = ▭
|
||||
frect.x = geometry->x + (geometry->w - geometry->h) / 2.f;
|
||||
frect.y = geometry->y + (geometry->h - geometry->w) / 2.f;
|
||||
frect.w = geometry->h;
|
||||
frect.h = geometry->w;
|
||||
} else {
|
||||
dstrect = geometry;
|
||||
SDL_RectToFRect(geometry, &frect);
|
||||
}
|
||||
|
||||
SDL_RendererFlip flip = sc_orientation_is_mirror(orientation)
|
||||
SDL_FlipMode flip = sc_orientation_is_mirror(orientation)
|
||||
? SDL_FLIP_HORIZONTAL : 0;
|
||||
|
||||
int ret = SDL_RenderCopyEx(renderer, texture, NULL, dstrect, angle,
|
||||
NULL, flip);
|
||||
if (ret) {
|
||||
bool ok = SDL_RenderTextureRotated(renderer, texture, NULL, &frect,
|
||||
angle, NULL, flip);
|
||||
if (!ok) {
|
||||
LOGE("Could not render texture: %s", SDL_GetError());
|
||||
return SC_DISPLAY_RESULT_ERROR;
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <libavutil/frame.h>
|
||||
#include <SDL2/SDL.h>
|
||||
#include <SDL3/SDL.h>
|
||||
|
||||
#include "coords.h"
|
||||
#include "opengl.h"
|
||||
|
@ -26,6 +26,7 @@ struct sc_display {
|
|||
#endif
|
||||
|
||||
bool mipmaps;
|
||||
uint32_t texture_id; // only set if mipmaps is enabled
|
||||
|
||||
struct {
|
||||
#define SC_DISPLAY_PENDING_FLAG_TEXTURE 1
|
||||
|
|
|
@ -9,11 +9,8 @@ bool
|
|||
sc_push_event_impl(uint32_t type, const char *name) {
|
||||
SDL_Event event;
|
||||
event.type = type;
|
||||
int ret = SDL_PushEvent(&event);
|
||||
// ret < 0: error (queue full)
|
||||
// ret == 0: event was filtered
|
||||
// ret == 1: success
|
||||
if (ret != 1) {
|
||||
bool ok = SDL_PushEvent(&event);
|
||||
if (!ok) {
|
||||
LOGE("Could not post %s event: %s", name, SDL_GetError());
|
||||
return false;
|
||||
}
|
||||
|
@ -30,34 +27,25 @@ sc_post_to_main_thread(sc_runnable_fn run, void *userdata) {
|
|||
.data2 = userdata,
|
||||
},
|
||||
};
|
||||
int ret = SDL_PushEvent(&event);
|
||||
// ret < 0: error (queue full)
|
||||
// ret == 0: event was filtered
|
||||
// ret == 1: success
|
||||
if (ret != 1) {
|
||||
if (ret == 0) {
|
||||
// if ret == 0, this is expected on exit, log in debug mode
|
||||
LOGD("Could not post runnable to main thread (filtered)");
|
||||
} else {
|
||||
assert(ret < 0);
|
||||
bool ok = SDL_PushEvent(&event);
|
||||
if (!ok) {
|
||||
LOGW("Could not post runnable to main thread: %s", SDL_GetError());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int SDLCALL
|
||||
static bool SDLCALL
|
||||
task_event_filter(void *userdata, SDL_Event *event) {
|
||||
(void) userdata;
|
||||
|
||||
if (event->type == SC_EVENT_RUN_ON_MAIN_THREAD) {
|
||||
// Reject this event type from now on
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -5,10 +5,10 @@
|
|||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <SDL2/SDL_events.h>
|
||||
#include <SDL3/SDL_events.h>
|
||||
|
||||
enum {
|
||||
SC_EVENT_NEW_FRAME = SDL_USEREVENT,
|
||||
SC_EVENT_NEW_FRAME = SDL_EVENT_USER,
|
||||
SC_EVENT_RUN_ON_MAIN_THREAD,
|
||||
SC_EVENT_DEVICE_DISCONNECTED,
|
||||
SC_EVENT_SERVER_CONNECTION_FAILED,
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
#include <libavutil/avutil.h>
|
||||
#include <libavutil/pixdesc.h>
|
||||
#include <libavutil/pixfmt.h>
|
||||
#include <SDL2/SDL.h>
|
||||
#include <SDL3/SDL.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "util/env.h"
|
||||
|
@ -156,13 +156,7 @@ free_ctx:
|
|||
return result;
|
||||
}
|
||||
|
||||
#if !SDL_VERSION_ATLEAST(2, 0, 10)
|
||||
// SDL_PixelFormatEnum has been introduced in SDL 2.0.10. Use int for older SDL
|
||||
// versions.
|
||||
typedef int SDL_PixelFormatEnum;
|
||||
#endif
|
||||
|
||||
static SDL_PixelFormatEnum
|
||||
static SDL_PixelFormat
|
||||
to_sdl_pixel_format(enum AVPixelFormat fmt) {
|
||||
switch (fmt) {
|
||||
case AV_PIX_FMT_RGB24: return SDL_PIXELFORMAT_RGB24;
|
||||
|
@ -172,13 +166,11 @@ to_sdl_pixel_format(enum AVPixelFormat fmt) {
|
|||
case AV_PIX_FMT_ABGR: return SDL_PIXELFORMAT_ABGR32;
|
||||
case AV_PIX_FMT_BGRA: return SDL_PIXELFORMAT_BGRA32;
|
||||
case AV_PIX_FMT_RGB565BE: return SDL_PIXELFORMAT_RGB565;
|
||||
case AV_PIX_FMT_RGB555BE: return SDL_PIXELFORMAT_RGB555;
|
||||
case AV_PIX_FMT_RGB555BE: return SDL_PIXELFORMAT_XRGB1555;
|
||||
case AV_PIX_FMT_BGR565BE: return SDL_PIXELFORMAT_BGR565;
|
||||
case AV_PIX_FMT_BGR555BE: return SDL_PIXELFORMAT_BGR555;
|
||||
case AV_PIX_FMT_RGB444BE: return SDL_PIXELFORMAT_RGB444;
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 12)
|
||||
case AV_PIX_FMT_BGR444BE: return SDL_PIXELFORMAT_BGR444;
|
||||
#endif
|
||||
case AV_PIX_FMT_BGR555BE: return SDL_PIXELFORMAT_XBGR1555;
|
||||
case AV_PIX_FMT_RGB444BE: return SDL_PIXELFORMAT_XRGB4444;
|
||||
case AV_PIX_FMT_BGR444BE: return SDL_PIXELFORMAT_XBGR4444;
|
||||
case AV_PIX_FMT_PAL8: return SDL_PIXELFORMAT_INDEX8;
|
||||
default: return SDL_PIXELFORMAT_UNKNOWN;
|
||||
}
|
||||
|
@ -203,20 +195,16 @@ load_from_path(const char *path) {
|
|||
goto error;
|
||||
}
|
||||
|
||||
SDL_PixelFormatEnum format = to_sdl_pixel_format(frame->format);
|
||||
SDL_PixelFormat format = to_sdl_pixel_format(frame->format);
|
||||
if (format == SDL_PIXELFORMAT_UNKNOWN) {
|
||||
LOGE("Unsupported icon pixel format: %s (%d)", desc->name,
|
||||
frame->format);
|
||||
goto error;
|
||||
}
|
||||
|
||||
int bits_per_pixel = av_get_bits_per_pixel(desc);
|
||||
SDL_Surface *surface =
|
||||
SDL_CreateRGBSurfaceWithFormatFrom(frame->data[0],
|
||||
frame->width, frame->height,
|
||||
bits_per_pixel,
|
||||
frame->linesize[0],
|
||||
format);
|
||||
SDL_CreateSurfaceFrom(frame->width, frame->height, format,
|
||||
frame->data[0], frame->linesize[0]);
|
||||
|
||||
if (!surface) {
|
||||
LOGE("Could not create icon surface");
|
||||
|
@ -248,17 +236,35 @@ load_from_path(const char *path) {
|
|||
#endif
|
||||
}
|
||||
|
||||
SDL_Palette *palette = surface->format->palette;
|
||||
assert(palette);
|
||||
int ret = SDL_SetPaletteColors(palette, colors, 0, 256);
|
||||
if (ret) {
|
||||
SDL_Palette *palette = SDL_CreateSurfacePalette(surface);
|
||||
if (!palette) {
|
||||
LOGE("Could not create palette");
|
||||
SDL_DestroySurface(surface);
|
||||
goto error;
|
||||
}
|
||||
|
||||
bool ok = SDL_SetPaletteColors(palette, colors, 0, 256);
|
||||
if (!ok) {
|
||||
LOGE("Could not set palette colors");
|
||||
SDL_FreeSurface(surface);
|
||||
SDL_DestroySurface(surface);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
surface->userdata = frame; // frame owns the data
|
||||
SDL_PropertiesID props = SDL_GetSurfaceProperties(surface);
|
||||
if (!props) {
|
||||
LOGE("Could not get surface properties: %s", SDL_GetError());
|
||||
SDL_DestroySurface(surface);
|
||||
goto error;
|
||||
}
|
||||
|
||||
// frame owns the data
|
||||
bool ok = SDL_SetPointerProperty(props, "sc_frame", frame);
|
||||
if (!ok) {
|
||||
LOGE("Could not get surface properties: %s", SDL_GetError());
|
||||
SDL_DestroySurface(surface);
|
||||
goto error;
|
||||
}
|
||||
|
||||
return surface;
|
||||
|
||||
|
@ -281,8 +287,10 @@ scrcpy_icon_load(void) {
|
|||
|
||||
void
|
||||
scrcpy_icon_destroy(SDL_Surface *icon) {
|
||||
AVFrame *frame = icon->userdata;
|
||||
SDL_PropertiesID props = SDL_GetSurfaceProperties(icon);
|
||||
assert(props);
|
||||
AVFrame *frame = SDL_GetPointerProperty(props, "sc_frame", NULL);
|
||||
assert(frame);
|
||||
av_frame_free(&frame);
|
||||
SDL_FreeSurface(icon);
|
||||
SDL_DestroySurface(icon);
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
#include "common.h"
|
||||
|
||||
#include <SDL2/SDL_surface.h>
|
||||
#include <SDL3/SDL_surface.h>
|
||||
|
||||
SDL_Surface *
|
||||
scrcpy_icon_load(void);
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
#include <assert.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <SDL2/SDL_events.h>
|
||||
#include <SDL3/SDL_events.h>
|
||||
|
||||
#include "coords.h"
|
||||
|
||||
|
@ -43,17 +43,17 @@
|
|||
*/
|
||||
|
||||
enum sc_mod {
|
||||
SC_MOD_LSHIFT = KMOD_LSHIFT,
|
||||
SC_MOD_RSHIFT = KMOD_RSHIFT,
|
||||
SC_MOD_LCTRL = KMOD_LCTRL,
|
||||
SC_MOD_RCTRL = KMOD_RCTRL,
|
||||
SC_MOD_LALT = KMOD_LALT,
|
||||
SC_MOD_RALT = KMOD_RALT,
|
||||
SC_MOD_LGUI = KMOD_LGUI,
|
||||
SC_MOD_RGUI = KMOD_RGUI,
|
||||
SC_MOD_LSHIFT = SDL_KMOD_LSHIFT,
|
||||
SC_MOD_RSHIFT = SDL_KMOD_RSHIFT,
|
||||
SC_MOD_LCTRL = SDL_KMOD_LCTRL,
|
||||
SC_MOD_RCTRL = SDL_KMOD_RCTRL,
|
||||
SC_MOD_LALT = SDL_KMOD_LALT,
|
||||
SC_MOD_RALT = SDL_KMOD_RALT,
|
||||
SC_MOD_LGUI = SDL_KMOD_LGUI,
|
||||
SC_MOD_RGUI = SDL_KMOD_RGUI,
|
||||
|
||||
SC_MOD_NUM = KMOD_NUM,
|
||||
SC_MOD_CAPS = KMOD_CAPS,
|
||||
SC_MOD_NUM = SDL_KMOD_NUM,
|
||||
SC_MOD_CAPS = SDL_KMOD_CAPS,
|
||||
};
|
||||
|
||||
enum sc_action {
|
||||
|
@ -70,12 +70,12 @@ enum sc_keycode {
|
|||
SC_KEYCODE_TAB = SDLK_TAB,
|
||||
SC_KEYCODE_SPACE = SDLK_SPACE,
|
||||
SC_KEYCODE_EXCLAIM = SDLK_EXCLAIM,
|
||||
SC_KEYCODE_QUOTEDBL = SDLK_QUOTEDBL,
|
||||
SC_KEYCODE_QUOTEDBL = SDLK_DBLAPOSTROPHE,
|
||||
SC_KEYCODE_HASH = SDLK_HASH,
|
||||
SC_KEYCODE_PERCENT = SDLK_PERCENT,
|
||||
SC_KEYCODE_DOLLAR = SDLK_DOLLAR,
|
||||
SC_KEYCODE_AMPERSAND = SDLK_AMPERSAND,
|
||||
SC_KEYCODE_QUOTE = SDLK_QUOTE,
|
||||
SC_KEYCODE_QUOTE = SDLK_APOSTROPHE,
|
||||
SC_KEYCODE_LEFTPAREN = SDLK_LEFTPAREN,
|
||||
SC_KEYCODE_RIGHTPAREN = SDLK_RIGHTPAREN,
|
||||
SC_KEYCODE_ASTERISK = SDLK_ASTERISK,
|
||||
|
@ -107,33 +107,33 @@ enum sc_keycode {
|
|||
SC_KEYCODE_RIGHTBRACKET = SDLK_RIGHTBRACKET,
|
||||
SC_KEYCODE_CARET = SDLK_CARET,
|
||||
SC_KEYCODE_UNDERSCORE = SDLK_UNDERSCORE,
|
||||
SC_KEYCODE_BACKQUOTE = SDLK_BACKQUOTE,
|
||||
SC_KEYCODE_a = SDLK_a,
|
||||
SC_KEYCODE_b = SDLK_b,
|
||||
SC_KEYCODE_c = SDLK_c,
|
||||
SC_KEYCODE_d = SDLK_d,
|
||||
SC_KEYCODE_e = SDLK_e,
|
||||
SC_KEYCODE_f = SDLK_f,
|
||||
SC_KEYCODE_g = SDLK_g,
|
||||
SC_KEYCODE_h = SDLK_h,
|
||||
SC_KEYCODE_i = SDLK_i,
|
||||
SC_KEYCODE_j = SDLK_j,
|
||||
SC_KEYCODE_k = SDLK_k,
|
||||
SC_KEYCODE_l = SDLK_l,
|
||||
SC_KEYCODE_m = SDLK_m,
|
||||
SC_KEYCODE_n = SDLK_n,
|
||||
SC_KEYCODE_o = SDLK_o,
|
||||
SC_KEYCODE_p = SDLK_p,
|
||||
SC_KEYCODE_q = SDLK_q,
|
||||
SC_KEYCODE_r = SDLK_r,
|
||||
SC_KEYCODE_s = SDLK_s,
|
||||
SC_KEYCODE_t = SDLK_t,
|
||||
SC_KEYCODE_u = SDLK_u,
|
||||
SC_KEYCODE_v = SDLK_v,
|
||||
SC_KEYCODE_w = SDLK_w,
|
||||
SC_KEYCODE_x = SDLK_x,
|
||||
SC_KEYCODE_y = SDLK_y,
|
||||
SC_KEYCODE_z = SDLK_z,
|
||||
SC_KEYCODE_BACKQUOTE = SDLK_GRAVE,
|
||||
SC_KEYCODE_a = SDLK_A,
|
||||
SC_KEYCODE_b = SDLK_B,
|
||||
SC_KEYCODE_c = SDLK_C,
|
||||
SC_KEYCODE_d = SDLK_D,
|
||||
SC_KEYCODE_e = SDLK_E,
|
||||
SC_KEYCODE_f = SDLK_F,
|
||||
SC_KEYCODE_g = SDLK_G,
|
||||
SC_KEYCODE_h = SDLK_H,
|
||||
SC_KEYCODE_i = SDLK_I,
|
||||
SC_KEYCODE_j = SDLK_J,
|
||||
SC_KEYCODE_k = SDLK_K,
|
||||
SC_KEYCODE_l = SDLK_L,
|
||||
SC_KEYCODE_m = SDLK_M,
|
||||
SC_KEYCODE_n = SDLK_N,
|
||||
SC_KEYCODE_o = SDLK_O,
|
||||
SC_KEYCODE_p = SDLK_P,
|
||||
SC_KEYCODE_q = SDLK_Q,
|
||||
SC_KEYCODE_r = SDLK_R,
|
||||
SC_KEYCODE_s = SDLK_S,
|
||||
SC_KEYCODE_t = SDLK_T,
|
||||
SC_KEYCODE_u = SDLK_U,
|
||||
SC_KEYCODE_v = SDLK_V,
|
||||
SC_KEYCODE_w = SDLK_W,
|
||||
SC_KEYCODE_x = SDLK_X,
|
||||
SC_KEYCODE_y = SDLK_Y,
|
||||
SC_KEYCODE_z = SDLK_Z,
|
||||
|
||||
SC_KEYCODE_CAPSLOCK = SDLK_CAPSLOCK,
|
||||
|
||||
|
@ -315,11 +315,11 @@ enum sc_scancode {
|
|||
// to avoid unnecessary conversions (and confusion).
|
||||
enum sc_mouse_button {
|
||||
SC_MOUSE_BUTTON_UNKNOWN = 0,
|
||||
SC_MOUSE_BUTTON_LEFT = SDL_BUTTON(SDL_BUTTON_LEFT),
|
||||
SC_MOUSE_BUTTON_RIGHT = SDL_BUTTON(SDL_BUTTON_RIGHT),
|
||||
SC_MOUSE_BUTTON_MIDDLE = SDL_BUTTON(SDL_BUTTON_MIDDLE),
|
||||
SC_MOUSE_BUTTON_X1 = SDL_BUTTON(SDL_BUTTON_X1),
|
||||
SC_MOUSE_BUTTON_X2 = SDL_BUTTON(SDL_BUTTON_X2),
|
||||
SC_MOUSE_BUTTON_LEFT = SDL_BUTTON_MASK(SDL_BUTTON_LEFT),
|
||||
SC_MOUSE_BUTTON_RIGHT = SDL_BUTTON_MASK(SDL_BUTTON_RIGHT),
|
||||
SC_MOUSE_BUTTON_MIDDLE = SDL_BUTTON_MASK(SDL_BUTTON_MIDDLE),
|
||||
SC_MOUSE_BUTTON_X1 = SDL_BUTTON_MASK(SDL_BUTTON_X1),
|
||||
SC_MOUSE_BUTTON_X2 = SDL_BUTTON_MASK(SDL_BUTTON_X2),
|
||||
};
|
||||
|
||||
// Use the naming from SDL3 for gamepad axis and buttons:
|
||||
|
@ -327,31 +327,31 @@ enum sc_mouse_button {
|
|||
|
||||
enum sc_gamepad_axis {
|
||||
SC_GAMEPAD_AXIS_UNKNOWN = -1,
|
||||
SC_GAMEPAD_AXIS_LEFTX = SDL_CONTROLLER_AXIS_LEFTX,
|
||||
SC_GAMEPAD_AXIS_LEFTY = SDL_CONTROLLER_AXIS_LEFTY,
|
||||
SC_GAMEPAD_AXIS_RIGHTX = SDL_CONTROLLER_AXIS_RIGHTX,
|
||||
SC_GAMEPAD_AXIS_RIGHTY = SDL_CONTROLLER_AXIS_RIGHTY,
|
||||
SC_GAMEPAD_AXIS_LEFT_TRIGGER = SDL_CONTROLLER_AXIS_TRIGGERLEFT,
|
||||
SC_GAMEPAD_AXIS_RIGHT_TRIGGER = SDL_CONTROLLER_AXIS_TRIGGERRIGHT,
|
||||
SC_GAMEPAD_AXIS_LEFTX = SDL_GAMEPAD_AXIS_LEFTX,
|
||||
SC_GAMEPAD_AXIS_LEFTY = SDL_GAMEPAD_AXIS_LEFTY,
|
||||
SC_GAMEPAD_AXIS_RIGHTX = SDL_GAMEPAD_AXIS_RIGHTX,
|
||||
SC_GAMEPAD_AXIS_RIGHTY = SDL_GAMEPAD_AXIS_RIGHTY,
|
||||
SC_GAMEPAD_AXIS_LEFT_TRIGGER = SDL_GAMEPAD_AXIS_LEFT_TRIGGER,
|
||||
SC_GAMEPAD_AXIS_RIGHT_TRIGGER = SDL_GAMEPAD_AXIS_RIGHT_TRIGGER,
|
||||
};
|
||||
|
||||
enum sc_gamepad_button {
|
||||
SC_GAMEPAD_BUTTON_UNKNOWN = -1,
|
||||
SC_GAMEPAD_BUTTON_SOUTH = SDL_CONTROLLER_BUTTON_A,
|
||||
SC_GAMEPAD_BUTTON_EAST = SDL_CONTROLLER_BUTTON_B,
|
||||
SC_GAMEPAD_BUTTON_WEST = SDL_CONTROLLER_BUTTON_X,
|
||||
SC_GAMEPAD_BUTTON_NORTH = SDL_CONTROLLER_BUTTON_Y,
|
||||
SC_GAMEPAD_BUTTON_BACK = SDL_CONTROLLER_BUTTON_BACK,
|
||||
SC_GAMEPAD_BUTTON_GUIDE = SDL_CONTROLLER_BUTTON_GUIDE,
|
||||
SC_GAMEPAD_BUTTON_START = SDL_CONTROLLER_BUTTON_START,
|
||||
SC_GAMEPAD_BUTTON_LEFT_STICK = SDL_CONTROLLER_BUTTON_LEFTSTICK,
|
||||
SC_GAMEPAD_BUTTON_RIGHT_STICK = SDL_CONTROLLER_BUTTON_RIGHTSTICK,
|
||||
SC_GAMEPAD_BUTTON_LEFT_SHOULDER = SDL_CONTROLLER_BUTTON_LEFTSHOULDER,
|
||||
SC_GAMEPAD_BUTTON_RIGHT_SHOULDER = SDL_CONTROLLER_BUTTON_RIGHTSHOULDER,
|
||||
SC_GAMEPAD_BUTTON_DPAD_UP = SDL_CONTROLLER_BUTTON_DPAD_UP,
|
||||
SC_GAMEPAD_BUTTON_DPAD_DOWN = SDL_CONTROLLER_BUTTON_DPAD_DOWN,
|
||||
SC_GAMEPAD_BUTTON_DPAD_LEFT = SDL_CONTROLLER_BUTTON_DPAD_LEFT,
|
||||
SC_GAMEPAD_BUTTON_DPAD_RIGHT = SDL_CONTROLLER_BUTTON_DPAD_RIGHT,
|
||||
SC_GAMEPAD_BUTTON_SOUTH = SDL_GAMEPAD_BUTTON_SOUTH,
|
||||
SC_GAMEPAD_BUTTON_EAST = SDL_GAMEPAD_BUTTON_EAST,
|
||||
SC_GAMEPAD_BUTTON_WEST = SDL_GAMEPAD_BUTTON_WEST,
|
||||
SC_GAMEPAD_BUTTON_NORTH = SDL_GAMEPAD_BUTTON_NORTH,
|
||||
SC_GAMEPAD_BUTTON_BACK = SDL_GAMEPAD_BUTTON_BACK,
|
||||
SC_GAMEPAD_BUTTON_GUIDE = SDL_GAMEPAD_BUTTON_GUIDE,
|
||||
SC_GAMEPAD_BUTTON_START = SDL_GAMEPAD_BUTTON_START,
|
||||
SC_GAMEPAD_BUTTON_LEFT_STICK = SDL_GAMEPAD_BUTTON_LEFT_STICK,
|
||||
SC_GAMEPAD_BUTTON_RIGHT_STICK = SDL_GAMEPAD_BUTTON_RIGHT_STICK,
|
||||
SC_GAMEPAD_BUTTON_LEFT_SHOULDER = SDL_GAMEPAD_BUTTON_LEFT_SHOULDER,
|
||||
SC_GAMEPAD_BUTTON_RIGHT_SHOULDER = SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER,
|
||||
SC_GAMEPAD_BUTTON_DPAD_UP = SDL_GAMEPAD_BUTTON_DPAD_UP,
|
||||
SC_GAMEPAD_BUTTON_DPAD_DOWN = SDL_GAMEPAD_BUTTON_DPAD_DOWN,
|
||||
SC_GAMEPAD_BUTTON_DPAD_LEFT = SDL_GAMEPAD_BUTTON_DPAD_LEFT,
|
||||
SC_GAMEPAD_BUTTON_DPAD_RIGHT = SDL_GAMEPAD_BUTTON_DPAD_RIGHT,
|
||||
};
|
||||
|
||||
static_assert(sizeof(enum sc_mod) >= sizeof(SDL_Keymod),
|
||||
|
@ -449,8 +449,8 @@ sc_scancode_from_sdl(SDL_Scancode scancode) {
|
|||
|
||||
static inline enum sc_action
|
||||
sc_action_from_sdl_keyboard_type(uint32_t type) {
|
||||
assert(type == SDL_KEYDOWN || type == SDL_KEYUP);
|
||||
if (type == SDL_KEYDOWN) {
|
||||
assert(type == SDL_EVENT_KEY_DOWN || type == SDL_EVENT_KEY_UP);
|
||||
if (type == SDL_EVENT_KEY_DOWN) {
|
||||
return SC_ACTION_DOWN;
|
||||
}
|
||||
return SC_ACTION_UP;
|
||||
|
@ -458,8 +458,8 @@ sc_action_from_sdl_keyboard_type(uint32_t type) {
|
|||
|
||||
static inline enum sc_action
|
||||
sc_action_from_sdl_mousebutton_type(uint32_t type) {
|
||||
assert(type == SDL_MOUSEBUTTONDOWN || type == SDL_MOUSEBUTTONUP);
|
||||
if (type == SDL_MOUSEBUTTONDOWN) {
|
||||
assert(type == SDL_EVENT_MOUSE_BUTTON_DOWN || type == SDL_EVENT_MOUSE_BUTTON_UP);
|
||||
if (type == SDL_EVENT_MOUSE_BUTTON_DOWN) {
|
||||
return SC_ACTION_DOWN;
|
||||
}
|
||||
return SC_ACTION_UP;
|
||||
|
@ -467,12 +467,12 @@ sc_action_from_sdl_mousebutton_type(uint32_t type) {
|
|||
|
||||
static inline enum sc_touch_action
|
||||
sc_touch_action_from_sdl(uint32_t type) {
|
||||
assert(type == SDL_FINGERMOTION || type == SDL_FINGERDOWN ||
|
||||
type == SDL_FINGERUP);
|
||||
if (type == SDL_FINGERMOTION) {
|
||||
assert(type == SDL_EVENT_FINGER_MOTION || type == SDL_EVENT_FINGER_DOWN ||
|
||||
type == SDL_EVENT_FINGER_UP);
|
||||
if (type == SDL_EVENT_FINGER_MOTION) {
|
||||
return SC_TOUCH_ACTION_MOVE;
|
||||
}
|
||||
if (type == SDL_FINGERDOWN) {
|
||||
if (type == SDL_EVENT_FINGER_DOWN) {
|
||||
return SC_TOUCH_ACTION_DOWN;
|
||||
}
|
||||
return SC_TOUCH_ACTION_UP;
|
||||
|
@ -482,7 +482,7 @@ static inline enum sc_mouse_button
|
|||
sc_mouse_button_from_sdl(uint8_t button) {
|
||||
if (button >= SDL_BUTTON_LEFT && button <= SDL_BUTTON_X2) {
|
||||
// SC_MOUSE_BUTTON_* constants are initialized from SDL_BUTTON(index)
|
||||
return SDL_BUTTON(button);
|
||||
return SDL_BUTTON_MASK(button);
|
||||
}
|
||||
|
||||
return SC_MOUSE_BUTTON_UNKNOWN;
|
||||
|
@ -498,7 +498,7 @@ sc_mouse_buttons_state_from_sdl(uint32_t buttons_state) {
|
|||
|
||||
static inline enum sc_gamepad_axis
|
||||
sc_gamepad_axis_from_sdl(uint8_t axis) {
|
||||
if (axis <= SDL_CONTROLLER_AXIS_TRIGGERRIGHT) {
|
||||
if (axis <= SDL_GAMEPAD_AXIS_RIGHT_TRIGGER) {
|
||||
// SC_GAMEPAD_AXIS_* constants are initialized from
|
||||
// SDL_CONTROLLER_AXIS_*
|
||||
return axis;
|
||||
|
@ -508,7 +508,7 @@ sc_gamepad_axis_from_sdl(uint8_t axis) {
|
|||
|
||||
static inline enum sc_gamepad_button
|
||||
sc_gamepad_button_from_sdl(uint8_t button) {
|
||||
if (button <= SDL_CONTROLLER_BUTTON_DPAD_RIGHT) {
|
||||
if (button <= SDL_GAMEPAD_BUTTON_DPAD_RIGHT) {
|
||||
// SC_GAMEPAD_BUTTON_* constants are initialized from
|
||||
// SDL_CONTROLLER_BUTTON_*
|
||||
return button;
|
||||
|
@ -518,8 +518,8 @@ sc_gamepad_button_from_sdl(uint8_t button) {
|
|||
|
||||
static inline enum sc_action
|
||||
sc_action_from_sdl_controllerbutton_type(uint32_t type) {
|
||||
assert(type == SDL_CONTROLLERBUTTONDOWN || type == SDL_CONTROLLERBUTTONUP);
|
||||
if (type == SDL_CONTROLLERBUTTONDOWN) {
|
||||
assert(type == SDL_EVENT_GAMEPAD_BUTTON_DOWN || type == SDL_EVENT_GAMEPAD_BUTTON_UP);
|
||||
if (type == SDL_EVENT_GAMEPAD_BUTTON_DOWN) {
|
||||
return SC_ACTION_DOWN;
|
||||
}
|
||||
return SC_ACTION_UP;
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <SDL2/SDL.h>
|
||||
#include <SDL3/SDL.h>
|
||||
|
||||
#include "android/input.h"
|
||||
#include "android/keycodes.h"
|
||||
|
@ -374,11 +374,11 @@ sc_input_manager_process_key(struct sc_input_manager *im,
|
|||
bool paused = im->screen->paused;
|
||||
bool video = im->screen->video;
|
||||
|
||||
SDL_Keycode sdl_keycode = event->keysym.sym;
|
||||
uint16_t mod = event->keysym.mod;
|
||||
bool down = event->type == SDL_KEYDOWN;
|
||||
bool ctrl = event->keysym.mod & KMOD_CTRL;
|
||||
bool shift = event->keysym.mod & KMOD_SHIFT;
|
||||
SDL_Keycode sdl_keycode = event->key;
|
||||
uint16_t mod = event->mod;
|
||||
bool down = event->type == SDL_EVENT_KEY_DOWN;
|
||||
bool ctrl = event->mod & SDL_KMOD_CTRL;
|
||||
bool shift = event->mod & SDL_KMOD_SHIFT;
|
||||
bool repeat = event->repeat;
|
||||
|
||||
// Either the modifier includes a shortcut modifier, or the key
|
||||
|
@ -402,39 +402,39 @@ sc_input_manager_process_key(struct sc_input_manager *im,
|
|||
if (is_shortcut) {
|
||||
enum sc_action action = down ? SC_ACTION_DOWN : SC_ACTION_UP;
|
||||
switch (sdl_keycode) {
|
||||
case SDLK_h:
|
||||
case SDLK_H:
|
||||
if (im->kp && !shift && !repeat && !paused) {
|
||||
action_home(im, action);
|
||||
}
|
||||
return;
|
||||
case SDLK_b: // fall-through
|
||||
case SDLK_B: // fall-through
|
||||
case SDLK_BACKSPACE:
|
||||
if (im->kp && !shift && !repeat && !paused) {
|
||||
action_back(im, action);
|
||||
}
|
||||
return;
|
||||
case SDLK_s:
|
||||
case SDLK_S:
|
||||
if (im->kp && !shift && !repeat && !paused) {
|
||||
action_app_switch(im, action);
|
||||
}
|
||||
return;
|
||||
case SDLK_m:
|
||||
case SDLK_M:
|
||||
if (im->kp && !shift && !repeat && !paused) {
|
||||
action_menu(im, action);
|
||||
}
|
||||
return;
|
||||
case SDLK_p:
|
||||
case SDLK_P:
|
||||
if (im->kp && !shift && !repeat && !paused) {
|
||||
action_power(im, action);
|
||||
}
|
||||
return;
|
||||
case SDLK_o:
|
||||
case SDLK_O:
|
||||
if (control && !repeat && down && !paused) {
|
||||
bool on = shift;
|
||||
set_display_power(im, on);
|
||||
}
|
||||
return;
|
||||
case SDLK_z:
|
||||
case SDLK_Z:
|
||||
if (video && down && !repeat) {
|
||||
sc_screen_set_paused(im->screen, !shift);
|
||||
}
|
||||
|
@ -483,17 +483,17 @@ sc_input_manager_process_key(struct sc_input_manager *im,
|
|||
}
|
||||
}
|
||||
return;
|
||||
case SDLK_c:
|
||||
case SDLK_C:
|
||||
if (im->kp && !shift && !repeat && down && !paused) {
|
||||
get_device_clipboard(im, SC_COPY_KEY_COPY);
|
||||
}
|
||||
return;
|
||||
case SDLK_x:
|
||||
case SDLK_X:
|
||||
if (im->kp && !shift && !repeat && down && !paused) {
|
||||
get_device_clipboard(im, SC_COPY_KEY_CUT);
|
||||
}
|
||||
return;
|
||||
case SDLK_v:
|
||||
case SDLK_V:
|
||||
if (im->kp && !repeat && down && !paused) {
|
||||
if (shift || im->legacy_paste) {
|
||||
// inject the text as input events
|
||||
|
@ -505,27 +505,27 @@ sc_input_manager_process_key(struct sc_input_manager *im,
|
|||
}
|
||||
}
|
||||
return;
|
||||
case SDLK_f:
|
||||
case SDLK_F:
|
||||
if (video && !shift && !repeat && down) {
|
||||
sc_screen_toggle_fullscreen(im->screen);
|
||||
}
|
||||
return;
|
||||
case SDLK_w:
|
||||
case SDLK_W:
|
||||
if (video && !shift && !repeat && down) {
|
||||
sc_screen_resize_to_fit(im->screen);
|
||||
}
|
||||
return;
|
||||
case SDLK_g:
|
||||
case SDLK_G:
|
||||
if (video && !shift && !repeat && down) {
|
||||
sc_screen_resize_to_pixel_perfect(im->screen);
|
||||
}
|
||||
return;
|
||||
case SDLK_i:
|
||||
case SDLK_I:
|
||||
if (video && !shift && !repeat && down) {
|
||||
switch_fps_counter_state(im);
|
||||
}
|
||||
return;
|
||||
case SDLK_n:
|
||||
case SDLK_N:
|
||||
if (control && !repeat && down && !paused) {
|
||||
if (shift) {
|
||||
collapse_panels(im);
|
||||
|
@ -536,7 +536,7 @@ sc_input_manager_process_key(struct sc_input_manager *im,
|
|||
}
|
||||
}
|
||||
return;
|
||||
case SDLK_r:
|
||||
case SDLK_R:
|
||||
if (control && !repeat && down && !paused) {
|
||||
if (shift) {
|
||||
reset_video(im);
|
||||
|
@ -545,7 +545,7 @@ sc_input_manager_process_key(struct sc_input_manager *im,
|
|||
}
|
||||
}
|
||||
return;
|
||||
case SDLK_k:
|
||||
case SDLK_K:
|
||||
if (control && !shift && !repeat && down && !paused
|
||||
&& im->kp && im->kp->hid) {
|
||||
// Only if the current keyboard is hid
|
||||
|
@ -562,7 +562,7 @@ sc_input_manager_process_key(struct sc_input_manager *im,
|
|||
}
|
||||
|
||||
uint64_t ack_to_wait = SC_SEQUENCE_INVALID;
|
||||
bool is_ctrl_v = ctrl && !shift && sdl_keycode == SDLK_v && down && !repeat;
|
||||
bool is_ctrl_v = ctrl && !shift && sdl_keycode == SDLK_V && down && !repeat;
|
||||
if (im->clipboard_autosync && is_ctrl_v) {
|
||||
if (im->legacy_paste) {
|
||||
// inject the text as input events
|
||||
|
@ -595,7 +595,7 @@ sc_input_manager_process_key(struct sc_input_manager *im,
|
|||
return;
|
||||
}
|
||||
|
||||
enum sc_scancode scancode = sc_scancode_from_sdl(event->keysym.scancode);
|
||||
enum sc_scancode scancode = sc_scancode_from_sdl(event->scancode);
|
||||
if (scancode == SC_SCANCODE_UNKNOWN) {
|
||||
return;
|
||||
}
|
||||
|
@ -605,7 +605,7 @@ sc_input_manager_process_key(struct sc_input_manager *im,
|
|||
.keycode = keycode,
|
||||
.scancode = scancode,
|
||||
.repeat = event->repeat,
|
||||
.mods_state = sc_mods_state_from_sdl(event->keysym.mod),
|
||||
.mods_state = sc_mods_state_from_sdl(event->mod),
|
||||
};
|
||||
|
||||
assert(im->kp->ops->process_key);
|
||||
|
@ -674,7 +674,7 @@ sc_input_manager_process_touch(struct sc_input_manager *im,
|
|||
|
||||
int dw;
|
||||
int dh;
|
||||
SDL_GL_GetDrawableSize(im->screen->window, &dw, &dh);
|
||||
SDL_GetWindowSizeInPixels(im->screen->window, &dw, &dh);
|
||||
|
||||
// SDL touch event coordinates are normalized in the range [0; 1]
|
||||
int32_t x = event->x * dw;
|
||||
|
@ -687,7 +687,7 @@ sc_input_manager_process_touch(struct sc_input_manager *im,
|
|||
sc_screen_convert_drawable_to_frame_coords(im->screen, x, y),
|
||||
},
|
||||
.action = sc_touch_action_from_sdl(event->type),
|
||||
.pointer_id = event->fingerId,
|
||||
.pointer_id = event->fingerID,
|
||||
.pressure = event->pressure,
|
||||
};
|
||||
|
||||
|
@ -723,7 +723,7 @@ sc_input_manager_process_mouse_button(struct sc_input_manager *im,
|
|||
|
||||
bool control = im->controller;
|
||||
bool paused = im->screen->paused;
|
||||
bool down = event->type == SDL_MOUSEBUTTONDOWN;
|
||||
bool down = event->type == SDL_EVENT_MOUSE_BUTTON_DOWN;
|
||||
|
||||
enum sc_mouse_button button = sc_mouse_button_from_sdl(event->button);
|
||||
if (button == SC_MOUSE_BUTTON_UNKNOWN) {
|
||||
|
@ -736,8 +736,8 @@ sc_input_manager_process_mouse_button(struct sc_input_manager *im,
|
|||
}
|
||||
|
||||
SDL_Keymod keymod = SDL_GetModState();
|
||||
bool ctrl_pressed = keymod & KMOD_CTRL;
|
||||
bool shift_pressed = keymod & KMOD_SHIFT;
|
||||
bool ctrl_pressed = keymod & SDL_KMOD_CTRL;
|
||||
bool shift_pressed = keymod & SDL_KMOD_SHIFT;
|
||||
|
||||
if (control && !paused) {
|
||||
enum sc_action action = down ? SC_ACTION_DOWN : SC_ACTION_UP;
|
||||
|
@ -889,16 +889,16 @@ sc_input_manager_process_mouse_wheel(struct sc_input_manager *im,
|
|||
}
|
||||
|
||||
// mouse_x and mouse_y are expressed in pixels relative to the window
|
||||
int mouse_x;
|
||||
int mouse_y;
|
||||
float mouse_x;
|
||||
float mouse_y;
|
||||
uint32_t buttons = SDL_GetMouseState(&mouse_x, &mouse_y);
|
||||
(void) buttons; // Actual buttons are tracked manually to ignore shortcuts
|
||||
|
||||
struct sc_mouse_scroll_event evt = {
|
||||
.position = sc_input_manager_get_position(im, mouse_x, mouse_y),
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 18)
|
||||
.hscroll = event->preciseX,
|
||||
.vscroll = event->preciseY,
|
||||
.hscroll = event->x,
|
||||
.vscroll = event->y,
|
||||
#else
|
||||
.hscroll = event->x,
|
||||
.vscroll = event->y,
|
||||
|
@ -911,31 +911,31 @@ sc_input_manager_process_mouse_wheel(struct sc_input_manager *im,
|
|||
|
||||
static void
|
||||
sc_input_manager_process_gamepad_device(struct sc_input_manager *im,
|
||||
const SDL_ControllerDeviceEvent *event) {
|
||||
if (event->type == SDL_CONTROLLERDEVICEADDED) {
|
||||
SDL_GameController *gc = SDL_GameControllerOpen(event->which);
|
||||
const SDL_GamepadDeviceEvent *event) {
|
||||
if (event->type == SDL_EVENT_GAMEPAD_ADDED) {
|
||||
SDL_Gamepad *gc = SDL_OpenGamepad(event->which);
|
||||
if (!gc) {
|
||||
LOGW("Could not open game controller");
|
||||
return;
|
||||
}
|
||||
|
||||
SDL_Joystick *joystick = SDL_GameControllerGetJoystick(gc);
|
||||
SDL_Joystick *joystick = SDL_GetGamepadJoystick(gc);
|
||||
if (!joystick) {
|
||||
LOGW("Could not get controller joystick");
|
||||
SDL_GameControllerClose(gc);
|
||||
SDL_CloseGamepad(gc);
|
||||
return;
|
||||
}
|
||||
|
||||
struct sc_gamepad_device_event evt = {
|
||||
.gamepad_id = SDL_JoystickInstanceID(joystick),
|
||||
.gamepad_id = SDL_GetJoystickID(joystick),
|
||||
};
|
||||
im->gp->ops->process_gamepad_added(im->gp, &evt);
|
||||
} else if (event->type == SDL_CONTROLLERDEVICEREMOVED) {
|
||||
} else if (event->type == SDL_EVENT_GAMEPAD_REMOVED) {
|
||||
SDL_JoystickID id = event->which;
|
||||
|
||||
SDL_GameController *gc = SDL_GameControllerFromInstanceID(id);
|
||||
SDL_Gamepad *gc = SDL_GetGamepadFromID(id);
|
||||
if (gc) {
|
||||
SDL_GameControllerClose(gc);
|
||||
SDL_CloseGamepad(gc);
|
||||
} else {
|
||||
LOGW("Unknown gamepad device removed");
|
||||
}
|
||||
|
@ -952,7 +952,7 @@ sc_input_manager_process_gamepad_device(struct sc_input_manager *im,
|
|||
|
||||
static void
|
||||
sc_input_manager_process_gamepad_axis(struct sc_input_manager *im,
|
||||
const SDL_ControllerAxisEvent *event) {
|
||||
const SDL_GamepadAxisEvent *event) {
|
||||
enum sc_gamepad_axis axis = sc_gamepad_axis_from_sdl(event->axis);
|
||||
if (axis == SC_GAMEPAD_AXIS_UNKNOWN) {
|
||||
return;
|
||||
|
@ -968,7 +968,7 @@ sc_input_manager_process_gamepad_axis(struct sc_input_manager *im,
|
|||
|
||||
static void
|
||||
sc_input_manager_process_gamepad_button(struct sc_input_manager *im,
|
||||
const SDL_ControllerButtonEvent *event) {
|
||||
const SDL_GamepadButtonEvent *event) {
|
||||
enum sc_gamepad_button button = sc_gamepad_button_from_sdl(event->button);
|
||||
if (button == SC_GAMEPAD_BUTTON_UNKNOWN) {
|
||||
return;
|
||||
|
@ -991,8 +991,8 @@ is_apk(const char *file) {
|
|||
static void
|
||||
sc_input_manager_process_file(struct sc_input_manager *im,
|
||||
const SDL_DropEvent *event) {
|
||||
char *file = strdup(event->file);
|
||||
SDL_free(event->file);
|
||||
assert(event->type == SDL_EVENT_DROP_FILE);
|
||||
char *file = strdup(event->data);
|
||||
if (!file) {
|
||||
LOG_OOM();
|
||||
return;
|
||||
|
@ -1016,66 +1016,66 @@ sc_input_manager_handle_event(struct sc_input_manager *im,
|
|||
bool control = im->controller;
|
||||
bool paused = im->screen->paused;
|
||||
switch (event->type) {
|
||||
case SDL_TEXTINPUT:
|
||||
case SDL_EVENT_TEXT_INPUT:
|
||||
if (!im->kp || paused) {
|
||||
break;
|
||||
}
|
||||
sc_input_manager_process_text_input(im, &event->text);
|
||||
break;
|
||||
case SDL_KEYDOWN:
|
||||
case SDL_KEYUP:
|
||||
case SDL_EVENT_KEY_DOWN:
|
||||
case SDL_EVENT_KEY_UP:
|
||||
// some key events do not interact with the device, so process the
|
||||
// event even if control is disabled
|
||||
sc_input_manager_process_key(im, &event->key);
|
||||
break;
|
||||
case SDL_MOUSEMOTION:
|
||||
case SDL_EVENT_MOUSE_MOTION:
|
||||
if (!im->mp || paused) {
|
||||
break;
|
||||
}
|
||||
sc_input_manager_process_mouse_motion(im, &event->motion);
|
||||
break;
|
||||
case SDL_MOUSEWHEEL:
|
||||
case SDL_EVENT_MOUSE_WHEEL:
|
||||
if (!im->mp || paused) {
|
||||
break;
|
||||
}
|
||||
sc_input_manager_process_mouse_wheel(im, &event->wheel);
|
||||
break;
|
||||
case SDL_MOUSEBUTTONDOWN:
|
||||
case SDL_MOUSEBUTTONUP:
|
||||
case SDL_EVENT_MOUSE_BUTTON_DOWN:
|
||||
case SDL_EVENT_MOUSE_BUTTON_UP:
|
||||
// some mouse events do not interact with the device, so process
|
||||
// the event even if control is disabled
|
||||
sc_input_manager_process_mouse_button(im, &event->button);
|
||||
break;
|
||||
case SDL_FINGERMOTION:
|
||||
case SDL_FINGERDOWN:
|
||||
case SDL_FINGERUP:
|
||||
case SDL_EVENT_FINGER_MOTION:
|
||||
case SDL_EVENT_FINGER_DOWN:
|
||||
case SDL_EVENT_FINGER_UP:
|
||||
if (!im->mp || paused) {
|
||||
break;
|
||||
}
|
||||
sc_input_manager_process_touch(im, &event->tfinger);
|
||||
break;
|
||||
case SDL_CONTROLLERDEVICEADDED:
|
||||
case SDL_CONTROLLERDEVICEREMOVED:
|
||||
case SDL_EVENT_GAMEPAD_ADDED:
|
||||
case SDL_EVENT_GAMEPAD_REMOVED:
|
||||
// Handle device added or removed even if paused
|
||||
if (!im->gp) {
|
||||
break;
|
||||
}
|
||||
sc_input_manager_process_gamepad_device(im, &event->cdevice);
|
||||
sc_input_manager_process_gamepad_device(im, &event->gdevice);
|
||||
break;
|
||||
case SDL_CONTROLLERAXISMOTION:
|
||||
case SDL_EVENT_GAMEPAD_AXIS_MOTION:
|
||||
if (!im->gp || paused) {
|
||||
break;
|
||||
}
|
||||
sc_input_manager_process_gamepad_axis(im, &event->caxis);
|
||||
sc_input_manager_process_gamepad_axis(im, &event->gaxis);
|
||||
break;
|
||||
case SDL_CONTROLLERBUTTONDOWN:
|
||||
case SDL_CONTROLLERBUTTONUP:
|
||||
case SDL_EVENT_GAMEPAD_BUTTON_DOWN:
|
||||
case SDL_EVENT_GAMEPAD_BUTTON_UP:
|
||||
if (!im->gp || paused) {
|
||||
break;
|
||||
}
|
||||
sc_input_manager_process_gamepad_button(im, &event->cbutton);
|
||||
sc_input_manager_process_gamepad_button(im, &event->gbutton);
|
||||
break;
|
||||
case SDL_DROPFILE: {
|
||||
case SDL_EVENT_DROP_FILE: {
|
||||
if (!control) {
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -5,8 +5,8 @@
|
|||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <SDL2/SDL_events.h>
|
||||
#include <SDL2/SDL_keycode.h>
|
||||
#include <SDL3/SDL_events.h>
|
||||
#include <SDL3/SDL_keycode.h>
|
||||
|
||||
#include "controller.h"
|
||||
#include "file_pusher.h"
|
||||
|
|
|
@ -5,8 +5,9 @@
|
|||
#ifdef HAVE_V4L2
|
||||
# include <libavdevice/avdevice.h>
|
||||
#endif
|
||||
#define SDL_MAIN_HANDLED // avoid link error on Linux Windows Subsystem
|
||||
#include <SDL2/SDL.h>
|
||||
#define SDL_FUNCTION_POINTER_IS_VOID_POINTER
|
||||
#include <SDL3/SDL_stdinc.h>
|
||||
#include <SDL3/SDL.h>
|
||||
|
||||
#include "cli.h"
|
||||
#include "options.h"
|
||||
|
|
|
@ -20,14 +20,11 @@ bool
|
|||
sc_mouse_capture_handle_event(struct sc_mouse_capture *mc,
|
||||
const SDL_Event *event) {
|
||||
switch (event->type) {
|
||||
case SDL_WINDOWEVENT:
|
||||
if (event->window.event == SDL_WINDOWEVENT_FOCUS_LOST) {
|
||||
case SDL_EVENT_WINDOW_FOCUS_LOST:
|
||||
sc_mouse_capture_set_active(mc, false);
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case SDL_KEYDOWN: {
|
||||
SDL_Keycode key = event->key.keysym.sym;
|
||||
case SDL_EVENT_KEY_DOWN: {
|
||||
SDL_Keycode key = event->key.key;
|
||||
if (sc_mouse_capture_is_capture_key(mc, key)) {
|
||||
if (!mc->mouse_capture_key_pressed) {
|
||||
mc->mouse_capture_key_pressed = key;
|
||||
|
@ -41,8 +38,8 @@ sc_mouse_capture_handle_event(struct sc_mouse_capture *mc,
|
|||
}
|
||||
break;
|
||||
}
|
||||
case SDL_KEYUP: {
|
||||
SDL_Keycode key = event->key.keysym.sym;
|
||||
case SDL_EVENT_KEY_UP: {
|
||||
SDL_Keycode key = event->key.key;
|
||||
SDL_Keycode cap = mc->mouse_capture_key_pressed;
|
||||
mc->mouse_capture_key_pressed = 0;
|
||||
if (sc_mouse_capture_is_capture_key(mc, key)) {
|
||||
|
@ -56,24 +53,24 @@ sc_mouse_capture_handle_event(struct sc_mouse_capture *mc,
|
|||
}
|
||||
break;
|
||||
}
|
||||
case SDL_MOUSEWHEEL:
|
||||
case SDL_MOUSEMOTION:
|
||||
case SDL_MOUSEBUTTONDOWN:
|
||||
case SDL_EVENT_MOUSE_WHEEL:
|
||||
case SDL_EVENT_MOUSE_MOTION:
|
||||
case SDL_EVENT_MOUSE_BUTTON_DOWN:
|
||||
if (!sc_mouse_capture_is_active(mc)) {
|
||||
// The mouse will be captured on SDL_MOUSEBUTTONUP, so consume
|
||||
// the event
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case SDL_MOUSEBUTTONUP:
|
||||
case SDL_EVENT_MOUSE_BUTTON_UP:
|
||||
if (!sc_mouse_capture_is_active(mc)) {
|
||||
sc_mouse_capture_set_active(mc, true);
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case SDL_FINGERMOTION:
|
||||
case SDL_FINGERDOWN:
|
||||
case SDL_FINGERUP:
|
||||
case SDL_EVENT_FINGER_MOTION:
|
||||
case SDL_EVENT_FINGER_DOWN:
|
||||
case SDL_EVENT_FINGER_UP:
|
||||
// Touch events are not compatible with relative mode
|
||||
// (coordinates are not relative), so consume the event
|
||||
return true;
|
||||
|
@ -101,10 +98,9 @@ sc_mouse_capture_set_active(struct sc_mouse_capture *mc, bool capture) {
|
|||
SDL_WarpMouseInWindow(mc->window, w / 2, h / 2);
|
||||
}
|
||||
}
|
||||
#else
|
||||
(void) mc;
|
||||
#endif
|
||||
if (SDL_SetRelativeMouseMode(capture)) {
|
||||
bool ok = SDL_SetWindowRelativeMouseMode(mc->window, capture);
|
||||
if (!ok) {
|
||||
LOGE("Could not set relative mouse mode to %s: %s",
|
||||
capture ? "true" : "false", SDL_GetError());
|
||||
}
|
||||
|
@ -112,8 +108,7 @@ sc_mouse_capture_set_active(struct sc_mouse_capture *mc, bool capture) {
|
|||
|
||||
bool
|
||||
sc_mouse_capture_is_active(struct sc_mouse_capture *mc) {
|
||||
(void) mc;
|
||||
return SDL_GetRelativeMouseMode();
|
||||
return SDL_GetWindowRelativeMouseMode(mc->window);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <SDL2/SDL.h>
|
||||
#include <SDL3/SDL.h>
|
||||
|
||||
struct sc_mouse_capture {
|
||||
SDL_Window *window;
|
||||
|
|
|
@ -3,21 +3,29 @@
|
|||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <SDL2/SDL.h>
|
||||
#include <SDL3/SDL.h>
|
||||
|
||||
void
|
||||
sc_opengl_init(struct sc_opengl *gl) {
|
||||
gl->GetString = SDL_GL_GetProcAddress("glGetString");
|
||||
gl->GetString = (const GLubyte *(*)(GLenum))
|
||||
SDL_GL_GetProcAddress("glGetString");
|
||||
assert(gl->GetString);
|
||||
|
||||
gl->TexParameterf = SDL_GL_GetProcAddress("glTexParameterf");
|
||||
gl->BindTexture = (void (*)(GLenum, GLuint))
|
||||
SDL_GL_GetProcAddress("glBindTexture");
|
||||
assert(gl->BindTexture);
|
||||
|
||||
gl->TexParameterf = (void (*)(GLenum, GLenum, GLfloat))
|
||||
SDL_GL_GetProcAddress("glTexParameterf");
|
||||
assert(gl->TexParameterf);
|
||||
|
||||
gl->TexParameteri = SDL_GL_GetProcAddress("glTexParameteri");
|
||||
gl->TexParameteri = (void (*)(GLenum, GLenum, GLint))
|
||||
SDL_GL_GetProcAddress("glTexParameteri");
|
||||
assert(gl->TexParameteri);
|
||||
|
||||
// optional
|
||||
gl->GenerateMipmap = SDL_GL_GetProcAddress("glGenerateMipmap");
|
||||
gl->GenerateMipmap = (void (*)(GLenum))
|
||||
SDL_GL_GetProcAddress("glGenerateMipmap");
|
||||
|
||||
const char *version = (const char *) gl->GetString(GL_VERSION);
|
||||
assert(version);
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
#include "common.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <SDL2/SDL_opengl.h>
|
||||
#include <SDL3/SDL_opengl.h>
|
||||
|
||||
struct sc_opengl {
|
||||
const char *version;
|
||||
|
@ -15,6 +15,9 @@ struct sc_opengl {
|
|||
const GLubyte *
|
||||
(*GetString)(GLenum name);
|
||||
|
||||
void
|
||||
(*BindTexture)(GLenum target, GLuint texture);
|
||||
|
||||
void
|
||||
(*TexParameterf)(GLenum target, GLenum pname, GLfloat param);
|
||||
|
||||
|
|
|
@ -2,7 +2,8 @@
|
|||
|
||||
#include <assert.h>
|
||||
#include <inttypes.h>
|
||||
#include <SDL2/SDL_clipboard.h>
|
||||
#include <stdlib.h>
|
||||
#include <SDL3/SDL_clipboard.h>
|
||||
|
||||
#include "device_msg.h"
|
||||
#include "events.h"
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <SDL2/SDL.h>
|
||||
#include <SDL3/SDL.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
// not needed here, but winsock2.h must never be included AFTER windows.h
|
||||
|
@ -94,7 +94,7 @@ struct scrcpy {
|
|||
#ifdef _WIN32
|
||||
static BOOL WINAPI windows_ctrl_handler(DWORD ctrl_type) {
|
||||
if (ctrl_type == CTRL_C_EVENT) {
|
||||
sc_push_event(SDL_QUIT);
|
||||
sc_push_event(SDL_EVENT_QUIT);
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
|
@ -108,41 +108,26 @@ sdl_set_hints(const char *render_driver) {
|
|||
}
|
||||
|
||||
// App name used in various contexts (such as PulseAudio)
|
||||
#if defined(SCRCPY_SDL_HAS_HINT_APP_NAME)
|
||||
if (!SDL_SetHint(SDL_HINT_APP_NAME, "scrcpy")) {
|
||||
LOGW("Could not set app name");
|
||||
}
|
||||
#elif defined(SCRCPY_SDL_HAS_HINT_AUDIO_DEVICE_APP_NAME)
|
||||
if (!SDL_SetHint(SDL_HINT_AUDIO_DEVICE_APP_NAME, "scrcpy")) {
|
||||
LOGW("Could not set audio device app name");
|
||||
}
|
||||
#endif
|
||||
|
||||
// Linear filtering
|
||||
if (!SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "1")) {
|
||||
LOGW("Could not enable linear filtering");
|
||||
}
|
||||
|
||||
// Handle a click to gain focus as any other click
|
||||
if (!SDL_SetHint(SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH, "1")) {
|
||||
LOGW("Could not enable mouse focus clickthrough");
|
||||
}
|
||||
|
||||
#ifdef SCRCPY_SDL_HAS_HINT_TOUCH_MOUSE_EVENTS
|
||||
// Disable synthetic mouse events from touch events
|
||||
// Touch events with id SDL_TOUCH_MOUSEID are ignored anyway, but it is
|
||||
// better not to generate them in the first place.
|
||||
if (!SDL_SetHint(SDL_HINT_TOUCH_MOUSE_EVENTS, "0")) {
|
||||
LOGW("Could not disable synthetic mouse events");
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef SCRCPY_SDL_HAS_HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR
|
||||
// Disable compositor bypassing on X11
|
||||
if (!SDL_SetHint(SDL_HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR, "0")) {
|
||||
LOGW("Could not disable X11 compositor bypass");
|
||||
}
|
||||
#endif
|
||||
|
||||
// Do not minimize on focus loss
|
||||
if (!SDL_SetHint(SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS, "0")) {
|
||||
|
@ -198,7 +183,7 @@ event_loop(struct scrcpy *s, bool has_screen) {
|
|||
case SC_EVENT_TIME_LIMIT_REACHED:
|
||||
LOGI("Time limit reached");
|
||||
return SCRCPY_EXIT_SUCCESS;
|
||||
case SDL_QUIT:
|
||||
case SDL_EVENT_QUIT:
|
||||
LOGD("User requested to quit");
|
||||
return SCRCPY_EXIT_SUCCESS;
|
||||
case SC_EVENT_RUN_ON_MAIN_THREAD: {
|
||||
|
@ -238,7 +223,7 @@ await_for_server(bool *connected) {
|
|||
SDL_Event event;
|
||||
while (SDL_WaitEvent(&event)) {
|
||||
switch (event.type) {
|
||||
case SDL_QUIT:
|
||||
case SDL_EVENT_QUIT:
|
||||
if (connected) {
|
||||
*connected = false;
|
||||
}
|
||||
|
@ -366,12 +351,19 @@ static void
|
|||
init_sdl_gamepads(void) {
|
||||
// Trigger a SDL_CONTROLLERDEVICEADDED event for all gamepads already
|
||||
// connected
|
||||
int num_joysticks = SDL_NumJoysticks();
|
||||
for (int i = 0; i < num_joysticks; ++i) {
|
||||
if (SDL_IsGameController(i)) {
|
||||
int count;
|
||||
SDL_JoystickID *joysticks = SDL_GetJoysticks(&count);
|
||||
if (!joysticks) {
|
||||
LOGE("Could not list joysticks: %s", SDL_GetError());
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < count; ++i) {
|
||||
SDL_JoystickID joystick = joysticks[i];
|
||||
if (SDL_IsGamepad(joystick)) {
|
||||
SDL_Event event;
|
||||
event.cdevice.type = SDL_CONTROLLERDEVICEADDED;
|
||||
event.cdevice.which = i;
|
||||
event.gdevice.type = SDL_EVENT_GAMEPAD_ADDED;
|
||||
event.gdevice.which = i;
|
||||
SDL_PushEvent(&event);
|
||||
}
|
||||
}
|
||||
|
@ -387,7 +379,7 @@ scrcpy(struct scrcpy_options *options) {
|
|||
struct scrcpy *s = &scrcpy;
|
||||
|
||||
// Minimal SDL initialization
|
||||
if (SDL_Init(SDL_INIT_EVENTS)) {
|
||||
if (!SDL_Init(SDL_INIT_EVENTS)) {
|
||||
LOGE("Could not initialize SDL: %s", SDL_GetError());
|
||||
return SCRCPY_EXIT_FAILURE;
|
||||
}
|
||||
|
@ -513,7 +505,7 @@ scrcpy(struct scrcpy_options *options) {
|
|||
// --no-video-playback is passed so that clipboard synchronization
|
||||
// still works.
|
||||
// <https://github.com/Genymobile/scrcpy/issues/4418>
|
||||
if (SDL_Init(SDL_INIT_VIDEO)) {
|
||||
if (!SDL_Init(SDL_INIT_VIDEO)) {
|
||||
// If it fails, it is an error only if video playback is enabled
|
||||
if (options->video_playback) {
|
||||
LOGE("Could not initialize SDL video: %s", SDL_GetError());
|
||||
|
@ -525,14 +517,14 @@ scrcpy(struct scrcpy_options *options) {
|
|||
}
|
||||
|
||||
if (options->audio_playback) {
|
||||
if (SDL_Init(SDL_INIT_AUDIO)) {
|
||||
if (!SDL_Init(SDL_INIT_AUDIO)) {
|
||||
LOGE("Could not initialize SDL audio: %s", SDL_GetError());
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
if (options->gamepad_input_mode != SC_GAMEPAD_INPUT_MODE_DISABLED) {
|
||||
if (SDL_Init(SDL_INIT_GAMECONTROLLER)) {
|
||||
if (!SDL_Init(SDL_INIT_GAMEPAD)) {
|
||||
LOGE("Could not initialize SDL gamepad: %s", SDL_GetError());
|
||||
goto end;
|
||||
}
|
||||
|
|
|
@ -2,12 +2,13 @@
|
|||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <SDL2/SDL.h>
|
||||
#include <SDL3/SDL.h>
|
||||
|
||||
#include "events.h"
|
||||
#include "icon.h"
|
||||
#include "options.h"
|
||||
#include "util/log.h"
|
||||
#include "util/window.h"
|
||||
|
||||
#define DISPLAY_MARGINS 96
|
||||
|
||||
|
@ -64,7 +65,9 @@ set_window_size(struct sc_screen *screen, struct sc_size new_size) {
|
|||
static bool
|
||||
get_preferred_display_bounds(struct sc_size *bounds) {
|
||||
SDL_Rect rect;
|
||||
if (SDL_GetDisplayUsableBounds(0, &rect)) {
|
||||
SDL_DisplayID display = SDL_GetPrimaryDisplay();
|
||||
bool ok = SDL_GetDisplayUsableBounds(display, &rect);
|
||||
if (!ok) {
|
||||
LOGW("Could not get display usable bounds: %s", SDL_GetError());
|
||||
return false;
|
||||
}
|
||||
|
@ -168,7 +171,7 @@ sc_screen_update_content_rect(struct sc_screen *screen) {
|
|||
|
||||
int dw;
|
||||
int dh;
|
||||
SDL_GL_GetDrawableSize(screen->window, &dw, &dh);
|
||||
SDL_GetWindowSizeInPixels(screen->window, &dw, &dh);
|
||||
|
||||
struct sc_size content_size = screen->content_size;
|
||||
// The drawable size is the window size * the HiDPI scale
|
||||
|
@ -236,18 +239,18 @@ sc_screen_render_novideo(struct sc_screen *screen) {
|
|||
//
|
||||
// <https://bugzilla.libsdl.org/show_bug.cgi?id=2077>
|
||||
// <https://stackoverflow.com/a/40693139/1987178>
|
||||
static int
|
||||
static bool
|
||||
event_watcher(void *data, SDL_Event *event) {
|
||||
struct sc_screen *screen = data;
|
||||
assert(screen->video);
|
||||
|
||||
if (event->type == SDL_WINDOWEVENT
|
||||
&& event->window.event == SDL_WINDOWEVENT_RESIZED) {
|
||||
if (event->type == SDL_EVENT_WINDOW_EXPOSED) {
|
||||
// In practice, it seems to always be called from the same thread in
|
||||
// that specific case. Anyway, it's just a workaround.
|
||||
sc_screen_render(screen, true);
|
||||
}
|
||||
return 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -258,6 +261,7 @@ sc_screen_frame_sink_open(struct sc_frame_sink *sink,
|
|||
(void) ctx;
|
||||
|
||||
struct sc_screen *screen = DOWNCAST(sink);
|
||||
(void) screen;
|
||||
|
||||
if (ctx->width <= 0 || ctx->width > 0xFFFF
|
||||
|| ctx->height <= 0 || ctx->height > 0xFFFF) {
|
||||
|
@ -349,7 +353,7 @@ sc_screen_init(struct sc_screen *screen,
|
|||
}
|
||||
}
|
||||
|
||||
uint32_t window_flags = SDL_WINDOW_ALLOW_HIGHDPI;
|
||||
uint32_t window_flags = SDL_WINDOW_HIGH_PIXEL_DENSITY;
|
||||
if (params->always_on_top) {
|
||||
window_flags |= SDL_WINDOW_ALWAYS_ON_TOP;
|
||||
}
|
||||
|
@ -383,15 +387,24 @@ sc_screen_init(struct sc_screen *screen,
|
|||
}
|
||||
|
||||
// The window will be positioned and sized on first video frame
|
||||
screen->window = SDL_CreateWindow(title, x, y, width, height, window_flags);
|
||||
screen->window =
|
||||
sc_create_sdl_window(title, x, y, width, height, window_flags);
|
||||
if (!screen->window) {
|
||||
LOGE("Could not create window: %s", SDL_GetError());
|
||||
goto error_destroy_fps_counter;
|
||||
}
|
||||
|
||||
ok = SDL_StartTextInput(screen->window);
|
||||
if (!ok) {
|
||||
LOGE("Could not enable text input: %s", SDL_GetError());
|
||||
goto error_destroy_window;
|
||||
}
|
||||
|
||||
SDL_Surface *icon = scrcpy_icon_load();
|
||||
if (icon) {
|
||||
SDL_SetWindowIcon(screen->window, icon);
|
||||
if (!SDL_SetWindowIcon(screen->window, icon)) {
|
||||
LOGW("Could not set window icon: %s", SDL_GetError());
|
||||
}
|
||||
} else if (params->video) {
|
||||
// just a warning
|
||||
LOGW("Could not load icon");
|
||||
|
@ -712,8 +725,8 @@ void
|
|||
sc_screen_toggle_fullscreen(struct sc_screen *screen) {
|
||||
assert(screen->video);
|
||||
|
||||
uint32_t new_mode = screen->fullscreen ? 0 : SDL_WINDOW_FULLSCREEN_DESKTOP;
|
||||
if (SDL_SetWindowFullscreen(screen->window, new_mode)) {
|
||||
bool ok = SDL_SetWindowFullscreen(screen->window, !screen->fullscreen);
|
||||
if (!ok) {
|
||||
LOGW("Could not switch fullscreen mode: %s", SDL_GetError());
|
||||
return;
|
||||
}
|
||||
|
@ -774,6 +787,8 @@ sc_screen_resize_to_pixel_perfect(struct sc_screen *screen) {
|
|||
|
||||
bool
|
||||
sc_screen_handle_event(struct sc_screen *screen, const SDL_Event *event) {
|
||||
// !video implies !has_video_window
|
||||
assert(screen->video || !screen->has_video_window);
|
||||
switch (event->type) {
|
||||
case SC_EVENT_NEW_FRAME: {
|
||||
bool ok = sc_screen_update_frame(screen);
|
||||
|
@ -783,46 +798,38 @@ sc_screen_handle_event(struct sc_screen *screen, const SDL_Event *event) {
|
|||
}
|
||||
return true;
|
||||
}
|
||||
case SDL_WINDOWEVENT:
|
||||
if (!screen->video
|
||||
&& event->window.event == SDL_WINDOWEVENT_EXPOSED) {
|
||||
case SDL_EVENT_WINDOW_EXPOSED:
|
||||
if (!screen->video) {
|
||||
sc_screen_render_novideo(screen);
|
||||
return true;
|
||||
}
|
||||
|
||||
// !video implies !has_video_window
|
||||
assert(screen->video || !screen->has_video_window);
|
||||
if (!screen->has_video_window) {
|
||||
// Do nothing
|
||||
return true;
|
||||
}
|
||||
switch (event->window.event) {
|
||||
case SDL_WINDOWEVENT_EXPOSED:
|
||||
} else if (screen->has_video_window) {
|
||||
sc_screen_render(screen, true);
|
||||
break;
|
||||
case SDL_WINDOWEVENT_SIZE_CHANGED:
|
||||
}
|
||||
return true;
|
||||
case SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED:
|
||||
if (screen->has_video_window) {
|
||||
sc_screen_render(screen, true);
|
||||
break;
|
||||
case SDL_WINDOWEVENT_MAXIMIZED:
|
||||
}
|
||||
return true;
|
||||
case SDL_EVENT_WINDOW_MAXIMIZED:
|
||||
screen->maximized = true;
|
||||
break;
|
||||
case SDL_WINDOWEVENT_MINIMIZED:
|
||||
return true;
|
||||
case SDL_EVENT_WINDOW_MINIMIZED:
|
||||
screen->minimized = true;
|
||||
break;
|
||||
case SDL_WINDOWEVENT_RESTORED:
|
||||
return true;
|
||||
case SDL_EVENT_WINDOW_RESTORED:
|
||||
if (screen->fullscreen) {
|
||||
// On Windows, in maximized+fullscreen, disabling
|
||||
// fullscreen mode unexpectedly triggers the "restored"
|
||||
// then "maximized" events, leaving the window in a
|
||||
// weird state (maximized according to the events, but
|
||||
// not maximized visually).
|
||||
break;
|
||||
return true;
|
||||
}
|
||||
screen->maximized = false;
|
||||
screen->minimized = false;
|
||||
if (screen->has_video_window) {
|
||||
apply_pending_resize(screen);
|
||||
sc_screen_render(screen, true);
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -905,7 +912,7 @@ sc_screen_hidpi_scale_coords(struct sc_screen *screen, int32_t *x, int32_t *y) {
|
|||
// take the HiDPI scaling (dw/ww and dh/wh) into account
|
||||
int ww, wh, dw, dh;
|
||||
SDL_GetWindowSize(screen->window, &ww, &wh);
|
||||
SDL_GL_GetDrawableSize(screen->window, &dw, &dh);
|
||||
SDL_GetWindowSizeInPixels(screen->window, &dw, &dh);
|
||||
|
||||
// scale for HiDPI (64 bits for intermediate multiplications)
|
||||
*x = (int64_t) *x * dw / ww;
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <SDL2/SDL.h>
|
||||
#include <SDL3/SDL.h>
|
||||
#include <libavcodec/avcodec.h>
|
||||
#include <libavutil/frame.h>
|
||||
#include <libavutil/pixfmt.h>
|
||||
|
|
|
@ -6,11 +6,11 @@
|
|||
#include <assert.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <SDL2/SDL_keycode.h>
|
||||
#include <SDL3/SDL_keycode.h>
|
||||
|
||||
#include "options.h"
|
||||
|
||||
#define SC_SDL_SHORTCUT_MODS_MASK (KMOD_CTRL | KMOD_ALT | KMOD_GUI)
|
||||
#define SC_SDL_SHORTCUT_MODS_MASK (SDL_KMOD_CTRL | SDL_KMOD_ALT | SDL_KMOD_GUI)
|
||||
|
||||
// input: OR of enum sc_shortcut_mod
|
||||
// output: OR of SDL_Keymod
|
||||
|
@ -18,22 +18,22 @@ static inline uint16_t
|
|||
sc_shortcut_mods_to_sdl(uint8_t shortcut_mods) {
|
||||
uint16_t sdl_mod = 0;
|
||||
if (shortcut_mods & SC_SHORTCUT_MOD_LCTRL) {
|
||||
sdl_mod |= KMOD_LCTRL;
|
||||
sdl_mod |= SDL_KMOD_LCTRL;
|
||||
}
|
||||
if (shortcut_mods & SC_SHORTCUT_MOD_RCTRL) {
|
||||
sdl_mod |= KMOD_RCTRL;
|
||||
sdl_mod |= SDL_KMOD_RCTRL;
|
||||
}
|
||||
if (shortcut_mods & SC_SHORTCUT_MOD_LALT) {
|
||||
sdl_mod |= KMOD_LALT;
|
||||
sdl_mod |= SDL_KMOD_LALT;
|
||||
}
|
||||
if (shortcut_mods & SC_SHORTCUT_MOD_RALT) {
|
||||
sdl_mod |= KMOD_RALT;
|
||||
sdl_mod |= SDL_KMOD_RALT;
|
||||
}
|
||||
if (shortcut_mods & SC_SHORTCUT_MOD_LSUPER) {
|
||||
sdl_mod |= KMOD_LGUI;
|
||||
sdl_mod |= SDL_KMOD_LGUI;
|
||||
}
|
||||
if (shortcut_mods & SC_SHORTCUT_MOD_RSUPER) {
|
||||
sdl_mod |= KMOD_RGUI;
|
||||
sdl_mod |= SDL_KMOD_RGUI;
|
||||
}
|
||||
return sdl_mod;
|
||||
}
|
||||
|
@ -50,12 +50,12 @@ sc_shortcut_mods_is_shortcut_mod(uint16_t sdl_shortcut_mods, uint16_t sdl_mod) {
|
|||
static inline bool
|
||||
sc_shortcut_mods_is_shortcut_key(uint16_t sdl_shortcut_mods,
|
||||
SDL_Keycode keycode) {
|
||||
return (sdl_shortcut_mods & KMOD_LCTRL && keycode == SDLK_LCTRL)
|
||||
|| (sdl_shortcut_mods & KMOD_RCTRL && keycode == SDLK_RCTRL)
|
||||
|| (sdl_shortcut_mods & KMOD_LALT && keycode == SDLK_LALT)
|
||||
|| (sdl_shortcut_mods & KMOD_RALT && keycode == SDLK_RALT)
|
||||
|| (sdl_shortcut_mods & KMOD_LGUI && keycode == SDLK_LGUI)
|
||||
|| (sdl_shortcut_mods & KMOD_RGUI && keycode == SDLK_RGUI);
|
||||
return (sdl_shortcut_mods & SDL_KMOD_LCTRL && keycode == SDLK_LCTRL)
|
||||
|| (sdl_shortcut_mods & SDL_KMOD_RCTRL && keycode == SDLK_RCTRL)
|
||||
|| (sdl_shortcut_mods & SDL_KMOD_LALT && keycode == SDLK_LALT)
|
||||
|| (sdl_shortcut_mods & SDL_KMOD_RALT && keycode == SDLK_RALT)
|
||||
|| (sdl_shortcut_mods & SDL_KMOD_LGUI && keycode == SDLK_LGUI)
|
||||
|| (sdl_shortcut_mods & SDL_KMOD_RGUI && keycode == SDLK_RGUI);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
#include <assert.h>
|
||||
#include <inttypes.h>
|
||||
#include <string.h>
|
||||
#include <SDL2/SDL_gamecontroller.h>
|
||||
#include <SDL3/SDL_gamepad.h>
|
||||
|
||||
#include "hid/hid_gamepad.h"
|
||||
#include "input_events.h"
|
||||
|
@ -74,10 +74,10 @@ sc_gamepad_processor_process_gamepad_added(struct sc_gamepad_processor *gp,
|
|||
return;
|
||||
}
|
||||
|
||||
SDL_GameController* game_controller =
|
||||
SDL_GameControllerFromInstanceID(event->gamepad_id);
|
||||
SDL_Gamepad * game_controller =
|
||||
SDL_GetGamepadFromID(event->gamepad_id);
|
||||
assert(game_controller);
|
||||
const char *name = SDL_GameControllerName(game_controller);
|
||||
const char *name = SDL_GetGamepadName(game_controller);
|
||||
LOGI("Gamepad added: [%" PRIu32 "] %s", event->gamepad_id, name);
|
||||
|
||||
sc_gamepad_uhid_send_open(gamepad, &hid_open);
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <SDL2/SDL_keyboard.h>
|
||||
#include <SDL2/SDL_keycode.h>
|
||||
#include <SDL3/SDL_keyboard.h>
|
||||
#include <SDL3/SDL_keycode.h>
|
||||
|
||||
#include "util/log.h"
|
||||
#include "util/thread.h"
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
#include <assert.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <SDL2/SDL.h>
|
||||
#include <SDL3/SDL.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
# include "adb/adb.h"
|
||||
|
@ -45,7 +45,7 @@ event_loop(struct scrcpy_otg *s) {
|
|||
case SC_EVENT_AOA_OPEN_ERROR:
|
||||
LOGE("AOA open error");
|
||||
return SCRCPY_EXIT_FAILURE;
|
||||
case SDL_QUIT:
|
||||
case SDL_EVENT_QUIT:
|
||||
LOGD("User requested to quit");
|
||||
return SCRCPY_EXIT_SUCCESS;
|
||||
default:
|
||||
|
@ -63,22 +63,18 @@ scrcpy_otg(struct scrcpy_options *options) {
|
|||
|
||||
const char *serial = options->serial;
|
||||
|
||||
if (!SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "1")) {
|
||||
LOGW("Could not enable linear filtering");
|
||||
}
|
||||
|
||||
if (!SDL_SetHint(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, "1")) {
|
||||
LOGW("Could not allow joystick background events");
|
||||
}
|
||||
|
||||
// Minimal SDL initialization
|
||||
if (SDL_Init(SDL_INIT_EVENTS)) {
|
||||
if (!SDL_Init(SDL_INIT_EVENTS)) {
|
||||
LOGE("Could not initialize SDL: %s", SDL_GetError());
|
||||
return SCRCPY_EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (options->gamepad_input_mode != SC_GAMEPAD_INPUT_MODE_DISABLED) {
|
||||
if (SDL_Init(SDL_INIT_GAMECONTROLLER)) {
|
||||
if (!SDL_Init(SDL_INIT_GAMEPAD)) {
|
||||
LOGE("Could not initialize SDL controller: %s", SDL_GetError());
|
||||
// Not fatal, keyboard/mouse should still work
|
||||
}
|
||||
|
|
|
@ -7,12 +7,13 @@
|
|||
#include "options.h"
|
||||
#include "util/acksync.h"
|
||||
#include "util/log.h"
|
||||
#include "util/window.h"
|
||||
|
||||
static void
|
||||
sc_screen_otg_render(struct sc_screen_otg *screen) {
|
||||
SDL_RenderClear(screen->renderer);
|
||||
if (screen->texture) {
|
||||
SDL_RenderCopy(screen->renderer, screen->texture, NULL, NULL);
|
||||
SDL_RenderTexture(screen->renderer, screen->texture, NULL, NULL);
|
||||
}
|
||||
SDL_RenderPresent(screen->renderer);
|
||||
}
|
||||
|
@ -34,7 +35,7 @@ sc_screen_otg_init(struct sc_screen_otg *screen,
|
|||
int width = params->window_width ? params->window_width : 256;
|
||||
int height = params->window_height ? params->window_height : 256;
|
||||
|
||||
uint32_t window_flags = SDL_WINDOW_ALLOW_HIGHDPI;
|
||||
uint32_t window_flags = SDL_WINDOW_HIGH_PIXEL_DENSITY;
|
||||
if (params->always_on_top) {
|
||||
window_flags |= SDL_WINDOW_ALWAYS_ON_TOP;
|
||||
}
|
||||
|
@ -42,13 +43,14 @@ sc_screen_otg_init(struct sc_screen_otg *screen,
|
|||
window_flags |= SDL_WINDOW_BORDERLESS;
|
||||
}
|
||||
|
||||
screen->window = SDL_CreateWindow(title, x, y, width, height, window_flags);
|
||||
screen->window =
|
||||
sc_create_sdl_window(title, x, y, width, height, window_flags);
|
||||
if (!screen->window) {
|
||||
LOGE("Could not create window: %s", SDL_GetError());
|
||||
return false;
|
||||
}
|
||||
|
||||
screen->renderer = SDL_CreateRenderer(screen->window, -1, 0);
|
||||
screen->renderer = SDL_CreateRenderer(screen->window, NULL);
|
||||
if (!screen->renderer) {
|
||||
LOGE("Could not create renderer: %s", SDL_GetError());
|
||||
goto error_destroy_window;
|
||||
|
@ -59,7 +61,10 @@ sc_screen_otg_init(struct sc_screen_otg *screen,
|
|||
if (icon) {
|
||||
SDL_SetWindowIcon(screen->window, icon);
|
||||
|
||||
if (SDL_RenderSetLogicalSize(screen->renderer, icon->w, icon->h)) {
|
||||
bool ok =
|
||||
SDL_SetRenderLogicalPresentation(screen->renderer, icon->w, icon->h,
|
||||
SDL_LOGICAL_PRESENTATION_LETTERBOX);
|
||||
if (!ok) {
|
||||
LOGW("Could not set renderer logical size: %s", SDL_GetError());
|
||||
// don't fail
|
||||
}
|
||||
|
@ -108,10 +113,10 @@ sc_screen_otg_process_key(struct sc_screen_otg *screen,
|
|||
|
||||
struct sc_key_event evt = {
|
||||
.action = sc_action_from_sdl_keyboard_type(event->type),
|
||||
.keycode = sc_keycode_from_sdl(event->keysym.sym),
|
||||
.scancode = sc_scancode_from_sdl(event->keysym.scancode),
|
||||
.keycode = sc_keycode_from_sdl(event->key),
|
||||
.scancode = sc_scancode_from_sdl(event->scancode),
|
||||
.repeat = event->repeat,
|
||||
.mods_state = sc_mods_state_from_sdl(event->keysym.mod),
|
||||
.mods_state = sc_mods_state_from_sdl(event->mod),
|
||||
};
|
||||
|
||||
assert(kp->ops->process_key);
|
||||
|
@ -165,8 +170,8 @@ sc_screen_otg_process_mouse_wheel(struct sc_screen_otg *screen,
|
|||
struct sc_mouse_scroll_event evt = {
|
||||
// .position not used for HID events
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 18)
|
||||
.hscroll = event->preciseX,
|
||||
.vscroll = event->preciseY,
|
||||
.hscroll = event->x,
|
||||
.vscroll = event->y,
|
||||
#else
|
||||
.hscroll = event->x,
|
||||
.vscroll = event->y,
|
||||
|
@ -180,34 +185,34 @@ sc_screen_otg_process_mouse_wheel(struct sc_screen_otg *screen,
|
|||
|
||||
static void
|
||||
sc_screen_otg_process_gamepad_device(struct sc_screen_otg *screen,
|
||||
const SDL_ControllerDeviceEvent *event) {
|
||||
const SDL_GamepadDeviceEvent *event) {
|
||||
assert(screen->gamepad);
|
||||
struct sc_gamepad_processor *gp = &screen->gamepad->gamepad_processor;
|
||||
|
||||
if (event->type == SDL_CONTROLLERDEVICEADDED) {
|
||||
SDL_GameController *gc = SDL_GameControllerOpen(event->which);
|
||||
if (event->type == SDL_EVENT_GAMEPAD_ADDED) {
|
||||
SDL_Gamepad *gc = SDL_OpenGamepad(event->which);
|
||||
if (!gc) {
|
||||
LOGW("Could not open game controller");
|
||||
return;
|
||||
}
|
||||
|
||||
SDL_Joystick *joystick = SDL_GameControllerGetJoystick(gc);
|
||||
SDL_Joystick *joystick = SDL_GetGamepadJoystick(gc);
|
||||
if (!joystick) {
|
||||
LOGW("Could not get controller joystick");
|
||||
SDL_GameControllerClose(gc);
|
||||
SDL_CloseGamepad(gc);
|
||||
return;
|
||||
}
|
||||
|
||||
struct sc_gamepad_device_event evt = {
|
||||
.gamepad_id = SDL_JoystickInstanceID(joystick),
|
||||
.gamepad_id = SDL_GetJoystickID(joystick),
|
||||
};
|
||||
gp->ops->process_gamepad_added(gp, &evt);
|
||||
} else if (event->type == SDL_CONTROLLERDEVICEREMOVED) {
|
||||
} else if (event->type == SDL_EVENT_GAMEPAD_REMOVED) {
|
||||
SDL_JoystickID id = event->which;
|
||||
|
||||
SDL_GameController *gc = SDL_GameControllerFromInstanceID(id);
|
||||
SDL_Gamepad *gc = SDL_GetGamepadFromID(id);
|
||||
if (gc) {
|
||||
SDL_GameControllerClose(gc);
|
||||
SDL_CloseGamepad(gc);
|
||||
} else {
|
||||
LOGW("Unknown gamepad device removed");
|
||||
}
|
||||
|
@ -221,7 +226,7 @@ sc_screen_otg_process_gamepad_device(struct sc_screen_otg *screen,
|
|||
|
||||
static void
|
||||
sc_screen_otg_process_gamepad_axis(struct sc_screen_otg *screen,
|
||||
const SDL_ControllerAxisEvent *event) {
|
||||
const SDL_GamepadAxisEvent *event) {
|
||||
assert(screen->gamepad);
|
||||
struct sc_gamepad_processor *gp = &screen->gamepad->gamepad_processor;
|
||||
|
||||
|
@ -240,7 +245,7 @@ sc_screen_otg_process_gamepad_axis(struct sc_screen_otg *screen,
|
|||
|
||||
static void
|
||||
sc_screen_otg_process_gamepad_button(struct sc_screen_otg *screen,
|
||||
const SDL_ControllerButtonEvent *event) {
|
||||
const SDL_GamepadButtonEvent *event) {
|
||||
assert(screen->gamepad);
|
||||
struct sc_gamepad_processor *gp = &screen->gamepad->gamepad_processor;
|
||||
|
||||
|
@ -265,59 +270,55 @@ sc_screen_otg_handle_event(struct sc_screen_otg *screen, SDL_Event *event) {
|
|||
}
|
||||
|
||||
switch (event->type) {
|
||||
case SDL_WINDOWEVENT:
|
||||
switch (event->window.event) {
|
||||
case SDL_WINDOWEVENT_EXPOSED:
|
||||
case SDL_EVENT_WINDOW_EXPOSED:
|
||||
sc_screen_otg_render(screen);
|
||||
break;
|
||||
}
|
||||
return;
|
||||
case SDL_KEYDOWN:
|
||||
case SDL_EVENT_KEY_DOWN:
|
||||
if (screen->keyboard) {
|
||||
sc_screen_otg_process_key(screen, &event->key);
|
||||
}
|
||||
break;
|
||||
case SDL_KEYUP:
|
||||
case SDL_EVENT_KEY_UP:
|
||||
if (screen->keyboard) {
|
||||
sc_screen_otg_process_key(screen, &event->key);
|
||||
}
|
||||
break;
|
||||
case SDL_MOUSEMOTION:
|
||||
case SDL_EVENT_MOUSE_MOTION:
|
||||
if (screen->mouse) {
|
||||
sc_screen_otg_process_mouse_motion(screen, &event->motion);
|
||||
}
|
||||
break;
|
||||
case SDL_MOUSEBUTTONDOWN:
|
||||
case SDL_EVENT_MOUSE_BUTTON_DOWN:
|
||||
if (screen->mouse) {
|
||||
sc_screen_otg_process_mouse_button(screen, &event->button);
|
||||
}
|
||||
break;
|
||||
case SDL_MOUSEBUTTONUP:
|
||||
case SDL_EVENT_MOUSE_BUTTON_UP:
|
||||
if (screen->mouse) {
|
||||
sc_screen_otg_process_mouse_button(screen, &event->button);
|
||||
}
|
||||
break;
|
||||
case SDL_MOUSEWHEEL:
|
||||
case SDL_EVENT_MOUSE_WHEEL:
|
||||
if (screen->mouse) {
|
||||
sc_screen_otg_process_mouse_wheel(screen, &event->wheel);
|
||||
}
|
||||
break;
|
||||
case SDL_CONTROLLERDEVICEADDED:
|
||||
case SDL_CONTROLLERDEVICEREMOVED:
|
||||
case SDL_EVENT_GAMEPAD_ADDED:
|
||||
case SDL_EVENT_GAMEPAD_REMOVED:
|
||||
// Handle device added or removed even if paused
|
||||
if (screen->gamepad) {
|
||||
sc_screen_otg_process_gamepad_device(screen, &event->cdevice);
|
||||
sc_screen_otg_process_gamepad_device(screen, &event->gdevice);
|
||||
}
|
||||
break;
|
||||
case SDL_CONTROLLERAXISMOTION:
|
||||
case SDL_EVENT_GAMEPAD_AXIS_MOTION:
|
||||
if (screen->gamepad) {
|
||||
sc_screen_otg_process_gamepad_axis(screen, &event->caxis);
|
||||
sc_screen_otg_process_gamepad_axis(screen, &event->gaxis);
|
||||
}
|
||||
break;
|
||||
case SDL_CONTROLLERBUTTONDOWN:
|
||||
case SDL_CONTROLLERBUTTONUP:
|
||||
case SDL_EVENT_GAMEPAD_BUTTON_DOWN:
|
||||
case SDL_EVENT_GAMEPAD_BUTTON_UP:
|
||||
if (screen->gamepad) {
|
||||
sc_screen_otg_process_gamepad_button(screen, &event->cbutton);
|
||||
sc_screen_otg_process_gamepad_button(screen, &event->gbutton);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <SDL2/SDL.h>
|
||||
#include <SDL3/SDL.h>
|
||||
|
||||
#include "mouse_capture.h"
|
||||
#include "usb/gamepad_aoa.h"
|
||||
|
|
|
@ -50,13 +50,13 @@ log_level_sdl_to_sc(SDL_LogPriority priority) {
|
|||
void
|
||||
sc_set_log_level(enum sc_log_level level) {
|
||||
SDL_LogPriority sdl_log = log_level_sc_to_sdl(level);
|
||||
SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, sdl_log);
|
||||
SDL_LogSetPriority(SDL_LOG_CATEGORY_CUSTOM, sdl_log);
|
||||
SDL_SetLogPriority(SDL_LOG_CATEGORY_APPLICATION, sdl_log);
|
||||
SDL_SetLogPriority(SDL_LOG_CATEGORY_CUSTOM, sdl_log);
|
||||
}
|
||||
|
||||
enum sc_log_level
|
||||
sc_get_log_level(void) {
|
||||
SDL_LogPriority sdl_log = SDL_LogGetPriority(SDL_LOG_CATEGORY_APPLICATION);
|
||||
SDL_LogPriority sdl_log = SDL_GetLogPriority(SDL_LOG_CATEGORY_APPLICATION);
|
||||
return log_level_sdl_to_sc(sdl_log);
|
||||
}
|
||||
|
||||
|
@ -128,7 +128,7 @@ sc_av_log_callback(void *avcl, int level, const char *fmt, va_list vl) {
|
|||
free(local_fmt);
|
||||
}
|
||||
|
||||
static const char *const sc_sdl_log_priority_names[SDL_NUM_LOG_PRIORITIES] = {
|
||||
static const char *const sc_sdl_log_priority_names[SDL_LOG_PRIORITY_COUNT] = {
|
||||
[SDL_LOG_PRIORITY_VERBOSE] = "VERBOSE",
|
||||
[SDL_LOG_PRIORITY_DEBUG] = "DEBUG",
|
||||
[SDL_LOG_PRIORITY_INFO] = "INFO",
|
||||
|
@ -144,14 +144,14 @@ sc_sdl_log_print(void *userdata, int category, SDL_LogPriority priority,
|
|||
(void) category;
|
||||
|
||||
FILE *out = priority < SDL_LOG_PRIORITY_WARN ? stdout : stderr;
|
||||
assert(priority < SDL_NUM_LOG_PRIORITIES);
|
||||
assert(priority < SDL_LOG_PRIORITY_COUNT);
|
||||
const char *prio_name = sc_sdl_log_priority_names[priority];
|
||||
fprintf(out, "%s: %s\n", prio_name, message);
|
||||
}
|
||||
|
||||
void
|
||||
sc_log_configure(void) {
|
||||
SDL_LogSetOutputFunction(sc_sdl_log_print, NULL);
|
||||
SDL_SetLogOutputFunction(sc_sdl_log_print, NULL);
|
||||
// Redirect FFmpeg logs to SDL logs
|
||||
av_log_set_callback(sc_av_log_callback);
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
#include "common.h"
|
||||
|
||||
#include <SDL2/SDL_log.h>
|
||||
#include <SDL3/SDL_log.h>
|
||||
|
||||
#include "options.h"
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <SDL2/SDL_thread.h>
|
||||
#include <SDL3/SDL_mutex.h>
|
||||
|
||||
#include "util/log.h"
|
||||
|
||||
|
@ -31,11 +31,7 @@ static SDL_ThreadPriority
|
|||
to_sdl_thread_priority(enum sc_thread_priority priority) {
|
||||
switch (priority) {
|
||||
case SC_THREAD_PRIORITY_TIME_CRITICAL:
|
||||
#ifdef SCRCPY_SDL_HAS_THREAD_PRIORITY_TIME_CRITICAL
|
||||
return SDL_THREAD_PRIORITY_TIME_CRITICAL;
|
||||
#else
|
||||
// fall through
|
||||
#endif
|
||||
case SC_THREAD_PRIORITY_HIGH:
|
||||
return SDL_THREAD_PRIORITY_HIGH;
|
||||
case SC_THREAD_PRIORITY_NORMAL:
|
||||
|
@ -51,8 +47,8 @@ to_sdl_thread_priority(enum sc_thread_priority priority) {
|
|||
bool
|
||||
sc_thread_set_priority(enum sc_thread_priority priority) {
|
||||
SDL_ThreadPriority sdl_priority = to_sdl_thread_priority(priority);
|
||||
int r = SDL_SetThreadPriority(sdl_priority);
|
||||
if (r) {
|
||||
bool ok = SDL_SetCurrentThreadPriority(sdl_priority);
|
||||
if (!ok) {
|
||||
LOGD("Could not set thread priority: %s", SDL_GetError());
|
||||
return false;
|
||||
}
|
||||
|
@ -67,7 +63,7 @@ sc_thread_join(sc_thread *thread, int *status) {
|
|||
|
||||
bool
|
||||
sc_mutex_init(sc_mutex *mutex) {
|
||||
SDL_mutex *sdl_mutex = SDL_CreateMutex();
|
||||
SDL_Mutex *sdl_mutex = SDL_CreateMutex();
|
||||
if (!sdl_mutex) {
|
||||
LOG_OOM();
|
||||
return false;
|
||||
|
@ -89,40 +85,25 @@ void
|
|||
sc_mutex_lock(sc_mutex *mutex) {
|
||||
// SDL mutexes are recursive, but we don't want to use recursive mutexes
|
||||
assert(!sc_mutex_held(mutex));
|
||||
int r = SDL_LockMutex(mutex->mutex);
|
||||
SDL_LockMutex(mutex->mutex);
|
||||
#ifndef NDEBUG
|
||||
if (r) {
|
||||
LOGE("Could not lock mutex: %s", SDL_GetError());
|
||||
abort();
|
||||
}
|
||||
|
||||
atomic_store_explicit(&mutex->locker, sc_thread_get_id(),
|
||||
memory_order_relaxed);
|
||||
#else
|
||||
(void) r;
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
sc_mutex_unlock(sc_mutex *mutex) {
|
||||
#ifndef NDEBUG
|
||||
assert(sc_mutex_held(mutex));
|
||||
#ifndef NDEBUG
|
||||
atomic_store_explicit(&mutex->locker, 0, memory_order_relaxed);
|
||||
#endif
|
||||
int r = SDL_UnlockMutex(mutex->mutex);
|
||||
#ifndef NDEBUG
|
||||
if (r) {
|
||||
LOGE("Could not lock mutex: %s", SDL_GetError());
|
||||
abort();
|
||||
}
|
||||
#else
|
||||
(void) r;
|
||||
#endif
|
||||
SDL_UnlockMutex(mutex->mutex);
|
||||
}
|
||||
|
||||
sc_thread_id
|
||||
sc_thread_get_id(void) {
|
||||
return SDL_ThreadID();
|
||||
return SDL_GetCurrentThreadID();
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
|
@ -136,7 +117,7 @@ sc_mutex_held(struct sc_mutex *mutex) {
|
|||
|
||||
bool
|
||||
sc_cond_init(sc_cond *cond) {
|
||||
SDL_cond *sdl_cond = SDL_CreateCond();
|
||||
SDL_Condition *sdl_cond = SDL_CreateCondition();
|
||||
if (!sdl_cond) {
|
||||
LOG_OOM();
|
||||
return false;
|
||||
|
@ -148,22 +129,15 @@ sc_cond_init(sc_cond *cond) {
|
|||
|
||||
void
|
||||
sc_cond_destroy(sc_cond *cond) {
|
||||
SDL_DestroyCond(cond->cond);
|
||||
SDL_DestroyCondition(cond->cond);
|
||||
}
|
||||
|
||||
void
|
||||
sc_cond_wait(sc_cond *cond, sc_mutex *mutex) {
|
||||
int r = SDL_CondWait(cond->cond, mutex->mutex);
|
||||
SDL_WaitCondition(cond->cond, mutex->mutex);
|
||||
#ifndef NDEBUG
|
||||
if (r) {
|
||||
LOGE("Could not wait on condition: %s", SDL_GetError());
|
||||
abort();
|
||||
}
|
||||
|
||||
atomic_store_explicit(&mutex->locker, sc_thread_get_id(),
|
||||
memory_order_relaxed);
|
||||
#else
|
||||
(void) r;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -177,44 +151,22 @@ sc_cond_timedwait(sc_cond *cond, sc_mutex *mutex, sc_tick deadline) {
|
|||
// Round up to the next millisecond to guarantee that the deadline is
|
||||
// reached when returning due to timeout
|
||||
uint32_t ms = SC_TICK_TO_MS(deadline - now + SC_TICK_FROM_MS(1) - 1);
|
||||
int r = SDL_CondWaitTimeout(cond->cond, mutex->mutex, ms);
|
||||
bool signaled = SDL_WaitConditionTimeout(cond->cond, mutex->mutex, ms);
|
||||
#ifndef NDEBUG
|
||||
if (r < 0) {
|
||||
LOGE("Could not wait on condition with timeout: %s", SDL_GetError());
|
||||
abort();
|
||||
}
|
||||
|
||||
atomic_store_explicit(&mutex->locker, sc_thread_get_id(),
|
||||
memory_order_relaxed);
|
||||
#endif
|
||||
assert(r == 0 || r == SDL_MUTEX_TIMEDOUT);
|
||||
// The deadline is reached on timeout
|
||||
assert(r != SDL_MUTEX_TIMEDOUT || sc_tick_now() >= deadline);
|
||||
return r == 0;
|
||||
assert(signaled || sc_tick_now() >= deadline);
|
||||
return signaled;
|
||||
}
|
||||
|
||||
void
|
||||
sc_cond_signal(sc_cond *cond) {
|
||||
int r = SDL_CondSignal(cond->cond);
|
||||
#ifndef NDEBUG
|
||||
if (r) {
|
||||
LOGE("Could not signal a condition: %s", SDL_GetError());
|
||||
abort();
|
||||
}
|
||||
#else
|
||||
(void) r;
|
||||
#endif
|
||||
SDL_SignalCondition(cond->cond);
|
||||
}
|
||||
|
||||
void
|
||||
sc_cond_broadcast(sc_cond *cond) {
|
||||
int r = SDL_CondBroadcast(cond->cond);
|
||||
#ifndef NDEBUG
|
||||
if (r) {
|
||||
LOGE("Could not broadcast a condition: %s", SDL_GetError());
|
||||
abort();
|
||||
}
|
||||
#else
|
||||
(void) r;
|
||||
#endif
|
||||
SDL_BroadcastCondition(cond->cond);
|
||||
}
|
||||
|
|
|
@ -10,8 +10,8 @@
|
|||
|
||||
/* Forward declarations */
|
||||
typedef struct SDL_Thread SDL_Thread;
|
||||
typedef struct SDL_mutex SDL_mutex;
|
||||
typedef struct SDL_cond SDL_cond;
|
||||
typedef struct SDL_Mutex SDL_Mutex;
|
||||
typedef struct SDL_Condition SDL_Condition;
|
||||
|
||||
typedef int sc_thread_fn(void *);
|
||||
typedef unsigned sc_thread_id;
|
||||
|
@ -29,14 +29,14 @@ enum sc_thread_priority {
|
|||
};
|
||||
|
||||
typedef struct sc_mutex {
|
||||
SDL_mutex *mutex;
|
||||
SDL_Mutex *mutex;
|
||||
#ifndef NDEBUG
|
||||
sc_atomic_thread_id locker;
|
||||
#endif
|
||||
} sc_mutex;
|
||||
|
||||
typedef struct sc_cond {
|
||||
SDL_cond *cond;
|
||||
SDL_Condition *cond;
|
||||
} sc_cond;
|
||||
|
||||
extern sc_thread_id SC_MAIN_THREAD_ID;
|
||||
|
|
33
app/src/util/window.c
Normal file
33
app/src/util/window.c
Normal file
|
@ -0,0 +1,33 @@
|
|||
#include "window.h"
|
||||
|
||||
SDL_Window *
|
||||
sc_create_sdl_window(const char *title, int64_t x, int64_t y, int64_t width,
|
||||
int64_t height, int64_t flags) {
|
||||
SDL_Window *window = NULL;
|
||||
|
||||
SDL_PropertiesID props = SDL_CreateProperties();
|
||||
if (!props) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool ok =
|
||||
SDL_SetStringProperty(props, SDL_PROP_WINDOW_CREATE_TITLE_STRING,
|
||||
title);
|
||||
ok &= SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_X_NUMBER, x);
|
||||
ok &= SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_Y_NUMBER, y);
|
||||
ok &= SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_WIDTH_NUMBER,
|
||||
width);
|
||||
ok &= SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_HEIGHT_NUMBER,
|
||||
height);
|
||||
ok &= SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_FLAGS_NUMBER,
|
||||
flags);
|
||||
|
||||
if (!ok) {
|
||||
SDL_DestroyProperties(props);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
window = SDL_CreateWindowWithProperties(props);
|
||||
SDL_DestroyProperties(props);
|
||||
return window;
|
||||
}
|
13
app/src/util/window.h
Normal file
13
app/src/util/window.h
Normal file
|
@ -0,0 +1,13 @@
|
|||
#ifndef SC_WINDOW_H
|
||||
#define SC_WINDOW_H
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <SDL3/SDL_video.h>
|
||||
|
||||
SDL_Window *
|
||||
sc_create_sdl_window(const char *title, int64_t x, int64_t y, int64_t width,
|
||||
int64_t height, int64_t flags);
|
||||
|
||||
#endif
|
|
@ -10,17 +10,20 @@
|
|||
#ifdef HAVE_USB
|
||||
# include <libusb-1.0/libusb.h>
|
||||
#endif
|
||||
#include <SDL2/SDL_version.h>
|
||||
#include <SDL3/SDL_version.h>
|
||||
|
||||
void
|
||||
scrcpy_print_version(void) {
|
||||
printf("\nDependencies (compiled / linked):\n");
|
||||
|
||||
SDL_version sdl;
|
||||
SDL_GetVersion(&sdl);
|
||||
int sdl = SDL_GetVersion();
|
||||
printf(" - SDL: %u.%u.%u / %u.%u.%u\n",
|
||||
SDL_MAJOR_VERSION, SDL_MINOR_VERSION, SDL_PATCHLEVEL,
|
||||
(unsigned) sdl.major, (unsigned) sdl.minor, (unsigned) sdl.patch);
|
||||
SDL_MAJOR_VERSION,
|
||||
SDL_MINOR_VERSION,
|
||||
SDL_MICRO_VERSION,
|
||||
SDL_VERSIONNUM_MAJOR(sdl),
|
||||
SDL_VERSIONNUM_MINOR(sdl),
|
||||
SDL_VERSIONNUM_MICRO(sdl));
|
||||
|
||||
unsigned avcodec = avcodec_version();
|
||||
printf(" - libavcodec: %u.%u.%u / %u.%u.%u\n",
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue