From 77cd5d9aef6774e3509789a1069aec1db5c6b5d4 Mon Sep 17 00:00:00 2001 From: Romain Vimont Date: Fri, 11 Jul 2025 09:42:03 +0200 Subject: [PATCH] Migrate from SDL2 to SDL3 Refs --- app/meson.build | 3 +- app/src/audio_player.c | 87 ++++++++++++++----- app/src/audio_player.h | 8 +- app/src/compat.h | 24 +----- app/src/display.c | 140 +++++++++++++++++++++---------- app/src/display.h | 3 +- app/src/events.c | 28 ++----- app/src/events.h | 4 +- app/src/icon.c | 66 ++++++++------- app/src/icon.h | 2 +- app/src/input_events.h | 158 +++++++++++++++++------------------ app/src/input_manager.c | 134 ++++++++++++++--------------- app/src/input_manager.h | 4 +- app/src/main.c | 5 +- app/src/mouse_capture.c | 39 ++++----- app/src/mouse_capture.h | 2 +- app/src/opengl.c | 18 ++-- app/src/opengl.h | 5 +- app/src/receiver.c | 3 +- app/src/scrcpy.c | 48 +++++------ app/src/screen.c | 107 +++++++++++++----------- app/src/screen.h | 2 +- app/src/shortcut_mod.h | 28 +++---- app/src/uhid/gamepad_uhid.c | 8 +- app/src/uhid/keyboard_uhid.c | 4 +- app/src/usb/scrcpy_otg.c | 12 +-- app/src/usb/screen_otg.c | 85 +++++++++---------- app/src/usb/screen_otg.h | 2 +- app/src/util/log.c | 12 +-- app/src/util/log.h | 2 +- app/src/util/thread.c | 80 ++++-------------- app/src/util/thread.h | 8 +- app/src/util/window.c | 33 ++++++++ app/src/util/window.h | 13 +++ app/src/version.c | 13 +-- 35 files changed, 632 insertions(+), 558 deletions(-) create mode 100644 app/src/util/window.c create mode 100644 app/src/util/window.h diff --git a/app/meson.build b/app/meson.build index f7df69eb..d7eb5384 100644 --- a/app/meson.build +++ b/app/meson.build @@ -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 diff --git a/app/src/audio_player.c b/app/src/audio_player.c index 9413c2ea..e1a4134e 100644 --- a/app/src/audio_player.c +++ b/app/src/audio_player.c @@ -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->audioreg.sample_size == 0); - uint32_t out_samples = len / ap->audioreg.sample_size; + 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; + } - sc_audio_regulator_pull(&ap->audioreg, stream, out_samples); + assert(len % ap->audioreg.sample_size == 0); + uint32_t out_samples = len / ap->audioreg.sample_size; + + 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 diff --git a/app/src/audio_player.h b/app/src/audio_player.h index 5a66d43b..786200bb 100644 --- a/app/src/audio_player.h +++ b/app/src/audio_player.h @@ -3,7 +3,7 @@ #include "common.h" -#include +#include #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; }; diff --git a/app/src/compat.h b/app/src/compat.h index 296d1a9f..a7ba289b 100644 --- a/app/src/compat.h +++ b/app/src/compat.h @@ -6,7 +6,7 @@ #include #include #include -#include +#include #ifndef _WIN32 # define PRIu64_ PRIu64 @@ -61,28 +61,6 @@ # define SCRCPY_LAVC_HAS_CODECPAR_CODEC_SIDEDATA #endif -#if SDL_VERSION_ATLEAST(2, 0, 6) -// -# define SCRCPY_SDL_HAS_HINT_TOUCH_MOUSE_EVENTS -#endif - -#if SDL_VERSION_ATLEAST(2, 0, 8) -// -# 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 diff --git a/app/src/display.c b/app/src/display.c index a1369ae8..fce540f4 100644 --- a/app/src/display.c +++ b/app/src/display.c @@ -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, - enum AVColorRange color_range) { +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; } diff --git a/app/src/display.h b/app/src/display.h index cc9107f5..8d2a1bd3 100644 --- a/app/src/display.h +++ b/app/src/display.h @@ -6,7 +6,7 @@ #include #include #include -#include +#include #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 diff --git a/app/src/events.c b/app/src/events.c index b4322d1b..ca7e4008 100644 --- a/app/src/events.c +++ b/app/src/events.c @@ -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); - LOGW("Could not post runnable to main thread: %s", SDL_GetError()); - } + 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 diff --git a/app/src/events.h b/app/src/events.h index 2e7318e5..8667bc57 100644 --- a/app/src/events.h +++ b/app/src/events.h @@ -5,10 +5,10 @@ #include #include -#include +#include 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, diff --git a/app/src/icon.c b/app/src/icon.c index 797afc75..ac80ecb3 100644 --- a/app/src/icon.c +++ b/app/src/icon.c @@ -10,7 +10,7 @@ #include #include #include -#include +#include #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); } diff --git a/app/src/icon.h b/app/src/icon.h index 6bcf46d2..21fbc548 100644 --- a/app/src/icon.h +++ b/app/src/icon.h @@ -3,7 +3,7 @@ #include "common.h" -#include +#include SDL_Surface * scrcpy_icon_load(void); diff --git a/app/src/input_events.h b/app/src/input_events.h index 0c022acc..87ea6634 100644 --- a/app/src/input_events.h +++ b/app/src/input_events.h @@ -6,7 +6,7 @@ #include #include #include -#include +#include #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; diff --git a/app/src/input_manager.c b/app/src/input_manager.c index f7a787d1..caba5fab 100644 --- a/app/src/input_manager.c +++ b/app/src/input_manager.c @@ -3,7 +3,7 @@ #include #include #include -#include +#include #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; } diff --git a/app/src/input_manager.h b/app/src/input_manager.h index af4cbc69..6f4af8f7 100644 --- a/app/src/input_manager.h +++ b/app/src/input_manager.h @@ -5,8 +5,8 @@ #include #include -#include -#include +#include +#include #include "controller.h" #include "file_pusher.h" diff --git a/app/src/main.c b/app/src/main.c index 968b1934..a3d323d2 100644 --- a/app/src/main.c +++ b/app/src/main.c @@ -5,8 +5,9 @@ #ifdef HAVE_V4L2 # include #endif -#define SDL_MAIN_HANDLED // avoid link error on Linux Windows Subsystem -#include +#define SDL_FUNCTION_POINTER_IS_VOID_POINTER +#include +#include #include "cli.h" #include "options.h" diff --git a/app/src/mouse_capture.c b/app/src/mouse_capture.c index 25345faa..5ea7a3ca 100644 --- a/app/src/mouse_capture.c +++ b/app/src/mouse_capture.c @@ -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) { - sc_mouse_capture_set_active(mc, false); - return true; - } - break; - case SDL_KEYDOWN: { - SDL_Keycode key = event->key.keysym.sym; + case SDL_EVENT_WINDOW_FOCUS_LOST: + sc_mouse_capture_set_active(mc, false); + return true; + 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 diff --git a/app/src/mouse_capture.h b/app/src/mouse_capture.h index f352cc13..65770f8a 100644 --- a/app/src/mouse_capture.h +++ b/app/src/mouse_capture.h @@ -5,7 +5,7 @@ #include -#include +#include struct sc_mouse_capture { SDL_Window *window; diff --git a/app/src/opengl.c b/app/src/opengl.c index 0cb83ed7..91e8d01d 100644 --- a/app/src/opengl.c +++ b/app/src/opengl.c @@ -3,21 +3,29 @@ #include #include #include -#include +#include 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); diff --git a/app/src/opengl.h b/app/src/opengl.h index 81163704..8db4e5d4 100644 --- a/app/src/opengl.h +++ b/app/src/opengl.h @@ -4,7 +4,7 @@ #include "common.h" #include -#include +#include 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); diff --git a/app/src/receiver.c b/app/src/receiver.c index 2ccb8a8b..ef9e9f00 100644 --- a/app/src/receiver.c +++ b/app/src/receiver.c @@ -2,7 +2,8 @@ #include #include -#include +#include +#include #include "device_msg.h" #include "events.h" diff --git a/app/src/scrcpy.c b/app/src/scrcpy.c index a4c8c340..0d293605 100644 --- a/app/src/scrcpy.c +++ b/app/src/scrcpy.c @@ -6,7 +6,7 @@ #include #include #include -#include +#include #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. // - 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; } diff --git a/app/src/screen.c b/app/src/screen.c index fc4a22ff..a4f14b50 100644 --- a/app/src/screen.c +++ b/app/src/screen.c @@ -2,12 +2,13 @@ #include #include -#include +#include #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) { // // // -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); + } else if (screen->has_video_window) { + sc_screen_render(screen, true); + } + return true; + case SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED: + if (screen->has_video_window) { + sc_screen_render(screen, true); + } + return true; + case SDL_EVENT_WINDOW_MAXIMIZED: + screen->maximized = true; + return true; + case SDL_EVENT_WINDOW_MINIMIZED: + screen->minimized = true; + 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). 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: - sc_screen_render(screen, true); - break; - case SDL_WINDOWEVENT_SIZE_CHANGED: - sc_screen_render(screen, true); - break; - case SDL_WINDOWEVENT_MAXIMIZED: - screen->maximized = true; - break; - case SDL_WINDOWEVENT_MINIMIZED: - screen->minimized = true; - break; - case SDL_WINDOWEVENT_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; - } - screen->maximized = false; - screen->minimized = false; - apply_pending_resize(screen); - sc_screen_render(screen, true); - break; + screen->maximized = false; + screen->minimized = false; + if (screen->has_video_window) { + apply_pending_resize(screen); + sc_screen_render(screen, true); } 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; diff --git a/app/src/screen.h b/app/src/screen.h index 89a25cda..0b992292 100644 --- a/app/src/screen.h +++ b/app/src/screen.h @@ -5,7 +5,7 @@ #include #include -#include +#include #include #include #include diff --git a/app/src/shortcut_mod.h b/app/src/shortcut_mod.h index f6c13f03..c53b0ff9 100644 --- a/app/src/shortcut_mod.h +++ b/app/src/shortcut_mod.h @@ -6,11 +6,11 @@ #include #include #include -#include +#include #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 diff --git a/app/src/uhid/gamepad_uhid.c b/app/src/uhid/gamepad_uhid.c index c64feb18..b4fef59e 100644 --- a/app/src/uhid/gamepad_uhid.c +++ b/app/src/uhid/gamepad_uhid.c @@ -3,7 +3,7 @@ #include #include #include -#include +#include #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); diff --git a/app/src/uhid/keyboard_uhid.c b/app/src/uhid/keyboard_uhid.c index 70082990..d8337df0 100644 --- a/app/src/uhid/keyboard_uhid.c +++ b/app/src/uhid/keyboard_uhid.c @@ -2,8 +2,8 @@ #include #include -#include -#include +#include +#include #include "util/log.h" #include "util/thread.h" diff --git a/app/src/usb/scrcpy_otg.c b/app/src/usb/scrcpy_otg.c index 1a9cc46e..ef0c1c5c 100644 --- a/app/src/usb/scrcpy_otg.c +++ b/app/src/usb/scrcpy_otg.c @@ -3,7 +3,7 @@ #include #include #include -#include +#include #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 } diff --git a/app/src/usb/screen_otg.c b/app/src/usb/screen_otg.c index bed48eb6..3f77e2c1 100644 --- a/app/src/usb/screen_otg.c +++ b/app/src/usb/screen_otg.c @@ -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: - sc_screen_otg_render(screen); - break; - } - return; - case SDL_KEYDOWN: + case SDL_EVENT_WINDOW_EXPOSED: + sc_screen_otg_render(screen); + break; + 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; } diff --git a/app/src/usb/screen_otg.h b/app/src/usb/screen_otg.h index 08b76ae7..32d9da96 100644 --- a/app/src/usb/screen_otg.h +++ b/app/src/usb/screen_otg.h @@ -5,7 +5,7 @@ #include #include -#include +#include #include "mouse_capture.h" #include "usb/gamepad_aoa.h" diff --git a/app/src/util/log.c b/app/src/util/log.c index 9114a258..c583b8fb 100644 --- a/app/src/util/log.c +++ b/app/src/util/log.c @@ -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); } diff --git a/app/src/util/log.h b/app/src/util/log.h index 0d79c9a4..02606cb4 100644 --- a/app/src/util/log.h +++ b/app/src/util/log.h @@ -3,7 +3,7 @@ #include "common.h" -#include +#include #include "options.h" diff --git a/app/src/util/thread.c b/app/src/util/thread.c index 2a5253f7..dce189bd 100644 --- a/app/src/util/thread.c +++ b/app/src/util/thread.c @@ -4,7 +4,7 @@ #include #include #include -#include +#include #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); } diff --git a/app/src/util/thread.h b/app/src/util/thread.h index 3d544046..13734bdc 100644 --- a/app/src/util/thread.h +++ b/app/src/util/thread.h @@ -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; diff --git a/app/src/util/window.c b/app/src/util/window.c new file mode 100644 index 00000000..ae1c0ac1 --- /dev/null +++ b/app/src/util/window.c @@ -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; +} diff --git a/app/src/util/window.h b/app/src/util/window.h new file mode 100644 index 00000000..c6f349e5 --- /dev/null +++ b/app/src/util/window.h @@ -0,0 +1,13 @@ +#ifndef SC_WINDOW_H +#define SC_WINDOW_H + +#include "common.h" + +#include +#include + +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 diff --git a/app/src/version.c b/app/src/version.c index f8610714..9a22a7e9 100644 --- a/app/src/version.c +++ b/app/src/version.c @@ -10,17 +10,20 @@ #ifdef HAVE_USB # include #endif -#include +#include 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",