Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package sdl2-compat for openSUSE:Factory checked in at 2025-05-06 16:38:32 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/sdl2-compat (Old) and /work/SRC/openSUSE:Factory/.sdl2-compat.new.30101 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "sdl2-compat" Tue May 6 16:38:32 2025 rev:3 rq:1274285 version:2.32.56 Changes: -------- --- /work/SRC/openSUSE:Factory/sdl2-compat/sdl2-compat.changes 2025-04-03 18:40:41.105892422 +0200 +++ /work/SRC/openSUSE:Factory/.sdl2-compat.new.30101/sdl2-compat.changes 2025-05-06 16:38:57.925991175 +0200 @@ -1,0 +2,16 @@ +Mon May 5 03:28:40 UTC 2025 - Jan Engelhardt <[email protected]> + +- Update to release 2.32.56 + * Fixed rendering in Mesen2 + * Fixed brightness in ioquake3 + * Fixed a hang at launch in the xemu emulator + * Fixed crackling and sped up audio in OpenRCT2 + * Fixed fullscreen window positioning on Wayland with multiple + displays + * Key events are now sent for dead keys on X11 + * Fixed mouse wheel integer scrolling values + * Fixed a double-free when working with RLE surfaces + * Fixed a memory leak in SDL_LockTextureToSurface() + * Fixed sending SDL3 controller events to SDL2 applications + +------------------------------------------------------------------- Old: ---- sdl2-compat-2.32.54.tar.gz sdl2-compat-2.32.54.tar.gz.sig New: ---- sdl2-compat-2.32.56.tar.gz sdl2-compat-2.32.56.tar.gz.sig sdl2-compat.keyring ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ sdl2-compat.spec ++++++ --- /var/tmp/diff_new_pack.APGM3t/_old 2025-05-06 16:38:58.470013911 +0200 +++ /var/tmp/diff_new_pack.APGM3t/_new 2025-05-06 16:38:58.470013911 +0200 @@ -19,7 +19,7 @@ %define lname libSDL2-2_0-0 %global _lto_cflags %_lto_cflags -ffat-lto-objects Name: sdl2-compat -Version: 2.32.54 +Version: 2.32.56 Release: 0 Summary: SDL-2.0 Compatibility Layer for Simple DirectMedia Layer 3.0 License: MIT @@ -27,12 +27,13 @@ URL: https://github.com/libsdl-org/sdl2-compat Source: https://github.com/libsdl-org/sdl2-compat/releases/download/release-%version/sdl2-compat-%version.tar.gz Source2: https://github.com/libsdl-org/sdl2-compat/releases/download/release-%version/sdl2-compat-%version.tar.gz.sig +Source3: %name.keyring Source8: baselibs.conf Source9: %name-rpmlintrc Patch1: sdl2-symvers.patch BuildRequires: cmake BuildRequires: pkg-config -BuildRequires: pkgconfig(sdl3) >= 3.2.4 +BuildRequires: pkgconfig(sdl3) >= 3.2.12 %description This is the "Simple DirectMedia Layer" library built from sdl2-compat. @@ -57,6 +58,9 @@ Requires: %lname = %version Conflicts: SDL2-devel Provides: SDL2-devel = %version-%release +# You should not add pkgconfig(x11) to sdl-devel; as far as SDL is concerned, it is optional. +# (Think outputting to Wayland, KMSDRM, or null.) +# https://github.com/libsdl-org/sdl2-compat/issues/405 %description devel This package contains files needed for development with the SDL2 ++++++ _scmsync.obsinfo ++++++ --- /var/tmp/diff_new_pack.APGM3t/_old 2025-05-06 16:38:58.498015081 +0200 +++ /var/tmp/diff_new_pack.APGM3t/_new 2025-05-06 16:38:58.502015249 +0200 @@ -1,5 +1,5 @@ -mtime: 1743528239 -commit: 473d16ecce1c284fca7b8bde21c2e48bd8d44f9c8e589ac949ada57de10ebc8c +mtime: 1746416410 +commit: 3805f776203e84495c424321b91d8972ce6e147010f966f3f7d8b8f18876785a url: https://src.opensuse.org/jengelh/sdl2-compat revision: master ++++++ sdl2-compat-2.32.54.tar.gz -> sdl2-compat-2.32.56.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sdl2-compat-2.32.54/.git-hash new/sdl2-compat-2.32.56/.git-hash --- old/sdl2-compat-2.32.54/.git-hash 2025-03-31 23:01:37.000000000 +0200 +++ new/sdl2-compat-2.32.56/.git-hash 2025-05-04 20:04:32.000000000 +0200 @@ -1 +1 @@ -005c6b27eb323ec3fc4c1a36da2c049d9acaded9 +1321b6c2857022a016280ecc8ed890d1d64c5213 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sdl2-compat-2.32.54/CMakeLists.txt new/sdl2-compat-2.32.56/CMakeLists.txt --- old/sdl2-compat-2.32.54/CMakeLists.txt 2025-03-31 22:56:41.000000000 +0200 +++ new/sdl2-compat-2.32.56/CMakeLists.txt 2025-05-04 20:01:15.000000000 +0200 @@ -3,7 +3,7 @@ # cmake -DSDL3_INCLUDE_DIRS=/opt/SDL3/include [other stuff ....] cmake_minimum_required(VERSION 3.0...3.28) -project(sdl2_compat VERSION 2.32.54 LANGUAGES C) +project(sdl2_compat VERSION 2.32.56 LANGUAGES C) if(POLICY CMP0074) # CMP0074: find_package() uses <PackageName>_ROOT variables. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sdl2-compat-2.32.54/REVISION.txt new/sdl2-compat-2.32.56/REVISION.txt --- old/sdl2-compat-2.32.54/REVISION.txt 2025-03-31 23:01:37.000000000 +0200 +++ new/sdl2-compat-2.32.56/REVISION.txt 2025-05-04 20:04:32.000000000 +0200 @@ -1 +1 @@ -release-2.32.54-0-g005c6b2 +release-2.32.56-0-g1321b6c diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sdl2-compat-2.32.54/include/SDL2/SDL_cpuinfo.h new/sdl2-compat-2.32.56/include/SDL2/SDL_cpuinfo.h --- old/sdl2-compat-2.32.54/include/SDL2/SDL_cpuinfo.h 2025-01-01 17:27:42.000000000 +0100 +++ new/sdl2-compat-2.32.56/include/SDL2/SDL_cpuinfo.h 2025-04-03 19:25:40.000000000 +0200 @@ -115,7 +115,8 @@ #include <lasxintrin.h> #define __LASX__ #endif -#if defined(HAVE_IMMINTRIN_H) && !defined(SDL_DISABLE_IMMINTRIN_H) +#if defined(HAVE_IMMINTRIN_H) && !defined(SDL_DISABLE_IMMINTRIN_H) && \ + (defined(__x86_64__) || defined(_M_X64) || defined(__i386__) || defined(_M_IX86)) #include <immintrin.h> #else #if defined(__MMX__) && !defined(SDL_DISABLE_MMINTRIN_H) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sdl2-compat-2.32.54/include/SDL2/SDL_revision.h new/sdl2-compat-2.32.56/include/SDL2/SDL_revision.h --- old/sdl2-compat-2.32.54/include/SDL2/SDL_revision.h 2025-03-31 23:01:37.000000000 +0200 +++ new/sdl2-compat-2.32.56/include/SDL2/SDL_revision.h 2025-05-04 20:04:32.000000000 +0200 @@ -1,6 +1,6 @@ #ifdef SDL_VENDOR_INFO -#define SDL_REVISION "release-2.32.54-0-g005c6b2 (" SDL_VENDOR_INFO ")" +#define SDL_REVISION "release-2.32.56-0-g1321b6c (" SDL_VENDOR_INFO ")" #else -#define SDL_REVISION "release-2.32.54-0-g005c6b2" +#define SDL_REVISION "release-2.32.56-0-g1321b6c" #endif #define SDL_REVISION_NUMBER 0 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sdl2-compat-2.32.54/include/SDL2/SDL_stdinc.h new/sdl2-compat-2.32.56/include/SDL2/SDL_stdinc.h --- old/sdl2-compat-2.32.54/include/SDL2/SDL_stdinc.h 2025-01-01 17:27:42.000000000 +0100 +++ new/sdl2-compat-2.32.56/include/SDL2/SDL_stdinc.h 2025-05-04 20:04:32.000000000 +0200 @@ -750,8 +750,12 @@ size_t wcslcat(wchar_t *dst, const wchar_t *src, size_t size); #endif +#ifndef _WIN32 /* strdup is not ANSI but POSIX, and its prototype might be hidden... */ +/* not for windows: might conflict with string.h where strdup may have + * dllimport attribute: https://github.com/libsdl-org/SDL/issues/12948 */ char *strdup(const char *str); +#endif /* Starting LLVM 16, the analyser errors out if these functions do not have their prototype defined (clang-diagnostic-implicit-function-declaration) */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sdl2-compat-2.32.54/include/SDL2/SDL_surface.h new/sdl2-compat-2.32.56/include/SDL2/SDL_surface.h --- old/sdl2-compat-2.32.54/include/SDL2/SDL_surface.h 2025-01-15 22:45:20.000000000 +0100 +++ new/sdl2-compat-2.32.56/include/SDL2/SDL_surface.h 2025-04-23 16:39:20.000000000 +0200 @@ -808,8 +808,8 @@ * * This assumes that the source and destination rectangles are the same size. * If either `srcrect` or `dstrect` are NULL, the entire surface (`src` or - * `dst`) is copied. The final blit rectangles are saved in `srcrect` and - * `dstrect` after all clipping is performed. + * `dst`) is copied. The final blit rectangle is saved in `dstrect` after all + * clipping is performed. * * The blit function should not be called on a locked surface. * diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sdl2-compat-2.32.54/include/SDL2/SDL_version.h new/sdl2-compat-2.32.56/include/SDL2/SDL_version.h --- old/sdl2-compat-2.32.54/include/SDL2/SDL_version.h 2025-03-31 22:56:41.000000000 +0200 +++ new/sdl2-compat-2.32.56/include/SDL2/SDL_version.h 2025-05-04 20:01:15.000000000 +0200 @@ -58,7 +58,7 @@ */ #define SDL_MAJOR_VERSION 2 #define SDL_MINOR_VERSION 32 -#define SDL_PATCHLEVEL 54 +#define SDL_PATCHLEVEL 56 /** * Macro to determine SDL version program was compiled against. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sdl2-compat-2.32.54/src/Makefile.darwin new/sdl2-compat-2.32.56/src/Makefile.darwin --- old/sdl2-compat-2.32.54/src/Makefile.darwin 2025-03-31 22:56:41.000000000 +0200 +++ new/sdl2-compat-2.32.56/src/Makefile.darwin 2025-05-04 20:01:15.000000000 +0200 @@ -20,7 +20,7 @@ LDFLAGS = -dynamiclib -Wl,-undefined,error -Wl,-single_module #LDFLAGS+= -Wl,-headerpad_max_install_names LDFLAGS+= -Wl,-install_name,"/usr/local/lib/$(DYLIB)" -LDFLAGS+= -Wl,-compatibility_version,3201.0 -Wl,-current_version,3201.54 +LDFLAGS+= -Wl,-compatibility_version,3201.0 -Wl,-current_version,3201.56 LDLIBS = -Wl,-framework,AppKit # this is needed for x86_64 - cross-gcc might not add it. #LDLIBS += -Wl,-lbundle1.o diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sdl2-compat-2.32.54/src/Makefile.linux new/sdl2-compat-2.32.56/src/Makefile.linux --- old/sdl2-compat-2.32.54/src/Makefile.linux 2025-03-31 22:56:41.000000000 +0200 +++ new/sdl2-compat-2.32.56/src/Makefile.linux 2025-05-04 20:01:15.000000000 +0200 @@ -14,7 +14,7 @@ LDFLAGS+= -Wl,--no-undefined LDLIBS = -ldl -SHLIB = libSDL2-2.0.so.0.3200.54 +SHLIB = libSDL2-2.0.so.0.3200.56 OBJ = sdl2_compat.o dynapi/SDL_dynapi.o diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sdl2-compat-2.32.54/src/sdl2_compat.c new/sdl2-compat-2.32.56/src/sdl2_compat.c --- old/sdl2-compat-2.32.54/src/sdl2_compat.c 2025-03-31 23:01:37.000000000 +0200 +++ new/sdl2-compat-2.32.56/src/sdl2_compat.c 2025-05-04 20:01:15.000000000 +0200 @@ -58,7 +58,7 @@ * The number might increment past 90 if there are a ton of releases. */ #define SDL2_COMPAT_VERSION_MINOR 32 -#define SDL2_COMPAT_VERSION_PATCH 54 +#define SDL2_COMPAT_VERSION_PATCH 56 #ifndef SDL2COMPAT_REVISION #define SDL2COMPAT_REVISION "SDL-2." STRINGIFY(SDL2_COMPAT_VERSION_MINOR) "." STRINGIFY(SDL2_COMPAT_VERSION_PATCH) "-no-vcs" @@ -111,6 +111,13 @@ #define SDL2COMPAT_MAXPATH 1024 #endif +#if defined(SDL_PLATFORM_UNIX) && !defined(SDL_PLATFORM_ANDROID) +/* We don't know whether SDL3 was really compiled with X11 support on this + * platform, but probably it was */ +#define SDL2COMPAT_HAVE_X11 +#else +#undef SDL2COMPAT_HAVE_X11 +#endif /* SDL2 function prototypes: */ #include "sdl2_protos.h" @@ -431,7 +438,7 @@ #endif #ifndef SDL3_REQUIRED_VER -#define SDL3_REQUIRED_VER SDL_VERSIONNUM(3,2,10) +#define SDL3_REQUIRED_VER SDL_VERSIONNUM(3,2,12) #endif #ifndef DIRSEP @@ -481,12 +488,9 @@ { "hl.exe", SDL_HINT_MOUSE_EMULATE_WARP_WITH_RELATIVE, "0" }, #endif - /* Moonlight supports high DPI properly under Wayland. - It also reads fractional values in wheel events. */ + /* Moonlight supports high DPI properly under Wayland */ { "moonlight", SDL_HINT_VIDEO_WAYLAND_SCALE_TO_DISPLAY, "0" }, { "moonlight-qt", SDL_HINT_VIDEO_WAYLAND_SCALE_TO_DISPLAY, "0" }, - { "moonlight", "SDL_MOUSE_INTEGER_MODE", "1" }, - { "moonlight-qt", "SDL_MOUSE_INTEGER_MODE", "1" }, /* Pragtical code editor supports high DPI properly under Wayland */ { "pragtical", SDL_HINT_VIDEO_WAYLAND_SCALE_TO_DISPLAY, "0" }, @@ -498,18 +502,29 @@ { "tauon/__main__.py", SDL_HINT_VIDEO_WAYLAND_SCALE_TO_DISPLAY, "0" }, { "tauon/__main__.py", SDL_HINT_VIDEO_WAYLAND_ALLOW_LIBDECOR, "0" }, +#ifdef SDL2COMPAT_HAVE_X11 /* Stylus Labs Write does its own X11 input handling */ { "Write", "SDL_VIDEO_X11_XINPUT2", "0" }, - /* PPSSPP reads fractional values in wheel events */ - { "PPSSPP", "SDL_MOUSE_INTEGER_MODE", "1" }, - { "PPSSPPSDL", "SDL_MOUSE_INTEGER_MODE", "1" }, - - /* Lite-XL reads fractional values in wheel events */ - { "lite-xl", "SDL_MOUSE_INTEGER_MODE", "1" }, - /* The UE5 editor has input issues and broken toast notification positioning on Wayland */ { "UnrealEditor", SDL_HINT_VIDEO_DRIVER, "x11" }, + + /* Darkest Dungeon assumes X11 and crashes otherwise + * https://github.com/libsdl-org/SDL/issues/12751 */ + { "darkest.bin.x86", SDL_HINT_VIDEO_DRIVER, "x11" }, + { "darkest.bin.x86_64", SDL_HINT_VIDEO_DRIVER, "x11" }, + + /* World of Goo 2 assumes X11 and crashes otherwise + * https://github.com/libsdl-org/SDL/issues/12752 */ + { "WorldOfGoo2", SDL_HINT_VIDEO_DRIVER, "x11" }, + + /* Infinity Engine Enhanced Edition assumes X11 and crashes otherwise + * https://github.com/libsdl-org/SDL/issues/12753 */ + { "BaldursGate", SDL_HINT_VIDEO_DRIVER, "x11" }, + { "BaldursGateII", SDL_HINT_VIDEO_DRIVER, "x11" }, + { "IcewindDale", SDL_HINT_VIDEO_DRIVER, "x11" }, + { "Torment64", SDL_HINT_VIDEO_DRIVER, "x11" }, +#endif }; #ifdef __linux__ @@ -606,6 +621,16 @@ return exename; } +SDL_DECLSPEC const char * SDLCALL +SDL_GetPlatform(void) +{ +#ifdef SDL_PLATFORM_MACOS + return "Mac OS X"; +#else + return SDL3_GetPlatform(); +#endif +} + static struct { const char *old_hint; const char *new_hint; @@ -1319,9 +1344,8 @@ SDL3_SetHint("SDL_VIDEO_SYNC_WINDOW_OPERATIONS", "1"); SDL3_SetHint("SDL_VIDEO_X11_EXTERNAL_WINDOW_INPUT", "0"); - /* Emulate both integer mouse coordinates and integer mouse wheel deltas for maximum compatibility. - Apps that use preciseX/Y for smooth scrolling can be quirked to get fractional wheel deltas. */ - SDL3_SetHint("SDL_MOUSE_INTEGER_MODE", "3"); + /* Emulate integer mouse coordinates */ + SDL3_SetHint("SDL_MOUSE_INTEGER_MODE", "1"); // Pretend Wayland doesn't have fractional scaling by default. // This is more compatible with applications that have only been tested under X11 without high DPI support. @@ -2312,8 +2336,8 @@ wheel->y = (Sint32)(event3->wheel.x * 120); } else { SDL2_MouseWheelEvent *wheel = &event2->wheel; - wheel->x = (Sint32)event3->wheel.x; - wheel->y = (Sint32)event3->wheel.y; + wheel->x = event3->wheel.integer_x; + wheel->y = event3->wheel.integer_y; wheel->preciseX = event3->wheel.x; wheel->preciseY = event3->wheel.y; wheel->mouseX = (Sint32)event3->wheel.mouse_x; @@ -4020,14 +4044,16 @@ SDL_DECLSPEC int SDLCALL SDL_SetWindowGammaRamp(SDL_Window *window, const Uint16 *r, const Uint16 *g, const Uint16 *b) { - Uint16 *gamma; - if (!window) { SDL3_SetError("Invalid window"); return -1; } - gamma = (Uint16 *)SDL3_GetPointerProperty(SDL3_GetWindowProperties(window), PROP_WINDOW_GAMMA_RAMP, NULL); + SDL3_Unsupported(); + return -1; + +#if 0 /* Leaving this code here in case we need it for a compatibility quirk */ + Uint16 *gamma = (Uint16 *)SDL3_GetPointerProperty(SDL3_GetWindowProperties(window), PROP_WINDOW_GAMMA_RAMP, NULL); if (!gamma) { if (SDL_GetWindowGammaRamp(window, NULL, NULL, NULL) < 0) { return -1; @@ -4045,6 +4071,7 @@ SDL_memcpy(&gamma[2*256], b, 256*sizeof(Uint16)); } return 0; +#endif } static void SDLCALL CleanupFreeableProperty(void *userdata, void *value) @@ -5431,27 +5458,26 @@ int x = 0; int y = 0; Uint8 r = 0, g = 0, b = 0, alpha = 0; - Uint8 *pixel = NULL; Uint32 pixel_value = 0, mask_value = 0; SDL_Color key; for (y = 0; y < shape->h; y++) { for (x = 0; x < shape->w; x++) { + const Uint8 *shape_pixels = (Uint8 *)(shape->pixels) + (y * shape->pitch) + (x * shape->format->BytesPerPixel); alpha = 0; pixel_value = 0; - pixel = (Uint8 *)(shape->pixels) + (y * shape->pitch) + (x * shape->format->BytesPerPixel); switch (shape->format->BytesPerPixel) { case 1: - pixel_value = *pixel; + pixel_value = *shape_pixels; break; case 2: - pixel_value = *(Uint16 *)pixel; + pixel_value = *(Uint16 *)shape_pixels; break; case 3: - pixel_value = *(Uint32 *)pixel & (~shape->format->Amask); + pixel_value = *(Uint32 *)shape_pixels & (~shape->format->Amask); break; case 4: - pixel_value = *(Uint32 *)pixel; + pixel_value = *(Uint32 *)shape_pixels; break; } SDL_GetRGBA(pixel_value, shape->format, &r, &g, &b, &alpha); @@ -6246,6 +6272,10 @@ srcfrect.w = (float)srcrect->w; srcfrect.h = (float)srcrect->h; psrcfrect = &srcfrect; + + if (srcrect->w == 0 || srcrect->h == 0) { + return 0; + } } if (dstrect) { dstfrect.x = (float)dstrect->x; @@ -6270,6 +6300,10 @@ srcfrect.w = (float)srcrect->w; srcfrect.h = (float)srcrect->h; psrcfrect = &srcfrect; + + if (srcrect->w == 0 || srcrect->h == 0) { + return 0; + } } retval = SDL3_RenderTexture(renderer, texture, psrcfrect, dstrect) ? 0 : -1; return retval < 0 ? retval : FlushRendererIfNotBatching(renderer); @@ -6294,6 +6328,10 @@ srcfrect.w = (float)srcrect->w; srcfrect.h = (float)srcrect->h; psrcfrect = &srcfrect; + + if (srcrect->w == 0 || srcrect->h == 0) { + return 0; + } } if (dstrect) { @@ -6329,6 +6367,10 @@ srcfrect.w = (float)srcrect->w; srcfrect.h = (float)srcrect->h; psrcfrect = &srcfrect; + + if (srcrect->w == 0 || srcrect->h == 0) { + return 0; + } } retval = SDL3_RenderTextureRotated(renderer, texture, psrcfrect, dstrect, angle, center, flip) ? 0 : -1; @@ -8180,6 +8222,14 @@ out->h = in->h; out->refresh_rate = (int) SDL3_lroundf(in->refresh_rate); out->driverdata = in->internal; + + /* Make sure the returned refresh rate and format are something valid */ + if (!out->refresh_rate) { + out->refresh_rate = 60; + } + if (!out->format) { + out->format = SDL_PIXELFORMAT_XRGB8888; + } } } @@ -8403,21 +8453,43 @@ } #define PROP_WINDOW_FULLSCREEN_MODE "sdl2-compat.window.fullscreen-mode" +#define PROP_WINDOW_FULLSCREEN_RESIZE_W "sdl2-compat.window.fullscreen_resize_w" +#define PROP_WINDOW_FULLSCREEN_RESIZE_H "sdl2-compat.window.fullscreen_resize_h" +#define PROP_WINDOW_FULLSCREEN_DISPLAY "sdl2-compat.window.preferred_fullscreen_display" static int ApplyFullscreenMode(SDL_Window *window) { /* Always try to enter fullscreen on the current display */ - const SDL_DisplayID displayID = SDL3_GetDisplayForWindow(window); - SDL2_DisplayMode *property = (SDL2_DisplayMode *)SDL3_GetPointerProperty(SDL3_GetWindowProperties(window), PROP_WINDOW_FULLSCREEN_MODE, NULL); + SDL_DisplayID displayID = SDL3_GetDisplayForWindow(window); + const SDL_PropertiesID window_props = SDL3_GetWindowProperties(window); + SDL2_DisplayMode *property = (SDL2_DisplayMode *)SDL3_GetPointerProperty(window_props, PROP_WINDOW_FULLSCREEN_MODE, NULL); SDL_DisplayMode mode; + /* Calling SDL3_GetDisplayForWindow supplies the display where the window currently is, but not necessarily + * the display on which the window should become fullscreen, particularly in cases where the backend can't + * actually reposition the window. This must only be queried *after* calling SDL3_GetDisplayForWindow(). + */ + displayID = SDL3_GetNumberProperty(window_props, PROP_WINDOW_FULLSCREEN_DISPLAY, displayID); + SDL3_zero(mode); if (property) { mode.w = property->w; mode.h = property->h; mode.refresh_rate = (float)property->refresh_rate; } else { - SDL3_GetWindowSize(window, &mode.w, &mode.h); + int count = 0; + int w, h; + SDL3_free(SDL3_GetFullscreenDisplayModes(displayID, &count)); + + /* If the video driver has no fullscreen modes, transition to fullscreen desktop mode */ + if (count == 0) { + return 0; + } + + /* If no mode was explicitly set, the window dimensions will determine it. */ + SDL3_GetWindowSize(window, &w, &h); + mode.w = (int)SDL3_GetNumberProperty(window_props, PROP_WINDOW_FULLSCREEN_RESIZE_W, w); + mode.h = (int)SDL3_GetNumberProperty(window_props, PROP_WINDOW_FULLSCREEN_RESIZE_H, h); } /* The SDL2 refresh rate is rounded off, and SDL3 checks that the mode parameters match exactly, so try to find the closest matching SDL3 mode. */ @@ -8426,6 +8498,15 @@ if (mode.displayID && SDL3_SetWindowFullscreenMode(window, &mode)) { return 0; } + else if (property) { + const SDL_DisplayMode *desktop = SDL3_GetDesktopDisplayMode(displayID); + + /* It's possible that this was an attempted transition to the desktop display mode on a driver without modesetting support */ + if (desktop && desktop->w == property->w && desktop->h == property->h) { + return 0; + } + } + return -1; } @@ -8466,11 +8547,6 @@ if (SDL_GetDesktopDisplayMode(display, mode) < 0) { return -1; } - - /* When returning the desktop mode, make sure the refresh is some nonzero value. */ - if (mode->refresh_rate == 0) { - mode->refresh_rate = 60; - } } else { if (!SDL_GetClosestDisplayMode(display, mode, mode)) { SDL_zerop(mode); @@ -8504,14 +8580,6 @@ } DisplayMode_3to2(ret3, closest); - - /* Make sure the returned refresh rate and format are something valid */ - if (!closest->refresh_rate) { - closest->refresh_rate = mode->refresh_rate ? mode->refresh_rate : 60; - } - if (!closest->format) { - closest->format = SDL_PIXELFORMAT_XRGB8888; - } return closest; } @@ -8800,6 +8868,12 @@ Uint32 flags3 = (Uint32) SDL3_GetWindowFlags(window); Uint32 flags = (flags3 & ~(SDL2_WINDOW_SHOWN | SDL2_WINDOW_FULLSCREEN | SDL2_WINDOW_FULLSCREEN_DESKTOP | SDL2_WINDOW_SKIP_TASKBAR | SDL2_WINDOW_ALWAYS_ON_TOP)); + /* If we get no flags back from SDL3, check if the window is actually valid */ + if (flags3 == 0 && SDL3_GetWindowID(window) == 0) { + /* SDL2 always returns 0 for an invalid window */ + return 0; + } + if ((flags3 & SDL2_WINDOW_HIDDEN) == 0) { flags |= SDL2_WINDOW_SHOWN; } @@ -9067,6 +9141,7 @@ { int ret = 0; bool fullscreen = false; + SDL_WindowFlags old_flags = SDL_GetWindowFlags(window); if (flags == SDL2_WINDOW_FULLSCREEN_DESKTOP) { fullscreen = true; @@ -9078,6 +9153,20 @@ if (ret == 0) { ret = SDL3_SetWindowFullscreen(window, fullscreen) ? 0 : -1; + if (!ret && !fullscreen && (old_flags & SDL2_WINDOW_FULLSCREEN)) { + /* SDL2 applied size changes while in fullscreen to the non-fullscreen size as well. */ + int w, h; + SDL_PropertiesID props = SDL3_GetWindowProperties(window); + w = SDL3_GetNumberProperty(props, PROP_WINDOW_FULLSCREEN_RESIZE_W, 0); + h = SDL3_GetNumberProperty(props, PROP_WINDOW_FULLSCREEN_RESIZE_H, 0); + + if (w && h) { + SDL_SetWindowSize(window, w, h); + } + + SDL3_ClearProperty(props, PROP_WINDOW_FULLSCREEN_RESIZE_W); + SDL3_ClearProperty(props, PROP_WINDOW_FULLSCREEN_RESIZE_H); + } } return ret; } @@ -9098,10 +9187,22 @@ SDL_DECLSPEC void SDLCALL SDL_SetWindowSize(SDL_Window *window, int w, int h) { + SDL_WindowFlags flags = SDL_GetWindowFlags(window); + SDL_PropertiesID props = SDL3_GetWindowProperties(window); - SDL3_SetNumberProperty(props, PROP_WINDOW_EXPECTED_WIDTH, w); - SDL3_SetNumberProperty(props, PROP_WINDOW_EXPECTED_HEIGHT, h); - SDL3_SetWindowSize(window, w, h); + if (!(flags & SDL2_WINDOW_FULLSCREEN)) { + SDL3_SetNumberProperty(props, PROP_WINDOW_EXPECTED_WIDTH, w); + SDL3_SetNumberProperty(props, PROP_WINDOW_EXPECTED_HEIGHT, h); + SDL3_SetWindowSize(window, w, h); + } else { + /* SDL2 can change the video mode of exclusive fullscreen windows by setting the size. */ + SDL3_SetNumberProperty(props, PROP_WINDOW_FULLSCREEN_RESIZE_W, w); + SDL3_SetNumberProperty(props, PROP_WINDOW_FULLSCREEN_RESIZE_H, h); + + if ((flags & SDL2_WINDOW_FULLSCREEN_DESKTOP) != SDL2_WINDOW_FULLSCREEN_DESKTOP) { + ApplyFullscreenMode(window); + } + } } SDL_DECLSPEC void SDLCALL @@ -9805,25 +9906,25 @@ } SDL_DECLSPEC void SDLCALL -SDL_GetRGB(Uint32 pixel, const SDL2_PixelFormat *format2, Uint8 * r, Uint8 * g, Uint8 * b) +SDL_GetRGB(Uint32 pixelvalue, const SDL2_PixelFormat *format2, Uint8 *r, Uint8 *g, Uint8 *b) { const SDL_PixelFormatDetails *format = GetPixelFormatDetails(format2); if (!format) { *r = *g = *b = 0; return; } - SDL3_GetRGB(pixel, format, format2->palette, r, g, b); + SDL3_GetRGB(pixelvalue, format, format2->palette, r, g, b); } SDL_DECLSPEC void SDLCALL -SDL_GetRGBA(Uint32 pixel, const SDL2_PixelFormat *format2, Uint8 * r, Uint8 * g, Uint8 * b, Uint8 *a) +SDL_GetRGBA(Uint32 pixelvalue, const SDL2_PixelFormat *format2, Uint8 *r, Uint8 *g, Uint8 *b, Uint8 *a) { const SDL_PixelFormatDetails *format = GetPixelFormatDetails(format2); if (!format) { *r = *g = *b = *a = 0; return; } - SDL3_GetRGBA(pixel, format, format2->palette, r, g, b, a); + SDL3_GetRGBA(pixelvalue, format, format2->palette, r, g, b, a); } SDL_DECLSPEC SDL_Renderer * SDLCALL @@ -9857,8 +9958,7 @@ if (!SDL3_LockSurface(surface3)) { return -1; } - surface->pixels = surface3->pixels; - surface->pitch = surface3->pitch; + SynchronizeSurface3to2(surface3, surface); } /* Increment the surface lock count, for recursive locks */ @@ -9880,8 +9980,7 @@ SDL3_UnlockSurface(surface3); - surface->pixels = surface3->pixels; - surface->pitch = surface3->pitch; + SynchronizeSurface3to2(surface3, surface); } SDL_DECLSPEC int SDLCALL @@ -9968,7 +10067,8 @@ return SDL3_GetSurfaceBlendMode(Surface2to3(surface), blendMode) ? 0 : -1; } -static void SDLCALL CleanupWindowSurface(void *userdata, void *value) +/* Cleanup callback for SDL2 surfaces that are retained by an SDL3 object */ +static void SDLCALL CleanupRetainedSurface2(void *userdata, void *value) { SDL2_Surface *surface = (SDL2_Surface *)value; surface->flags &= ~SDL_DONTFREE; @@ -10003,7 +10103,7 @@ if (surface2) { surface2->flags |= SDL_DONTFREE; - SDL3_SetPointerPropertyWithCleanup(SDL3_GetWindowProperties(window), PROP_SURFACE2, surface2, CleanupWindowSurface, NULL); + SDL3_SetPointerPropertyWithCleanup(SDL3_GetWindowProperties(window), PROP_SURFACE2, surface2, CleanupRetainedSurface2, NULL); } } } @@ -10018,7 +10118,15 @@ if (!SDL3_LockTextureToSurface(texture, rect, &surface3)) { return -1; } - *surface = Surface3to2(surface3); + *surface = CreateSurface2from3(surface3); + if (!*surface) { + SDL_UnlockTexture(texture); + return -1; + } + + /* This surface is freed by SDL_UnlockTexture() or SDL_DestroyTexture(), not by SDL_FreeSurface() */ + (*surface)->flags |= SDL_DONTFREE; + SDL3_SetPointerPropertyWithCleanup(SDL3_GetSurfaceProperties(surface3), PROP_SURFACE2, *surface, CleanupRetainedSurface2, NULL); return 0; } @@ -10084,7 +10192,7 @@ } #endif /* SDL_PLATFORM_WINDOWS */ -#if defined(SDL_PLATFORM_UNIX) && !defined(SDL_PLATFORM_ANDROID) +#ifdef SDL2COMPAT_HAVE_X11 static bool SDLCALL SDL2COMPAT_X11EventHook(void *userdata, XEvent *xevent) { SDL2_Event event; @@ -10100,7 +10208,7 @@ SDL_PushEvent(&event); return true; } -#endif /* SDL_PLATFORM_UNIX */ +#endif /* SDL2COMPAT_HAVE_X11 */ /* SDL3 split this into getter/setter functions. */ SDL_DECLSPEC Uint8 SDLCALL @@ -10112,7 +10220,7 @@ #ifdef SDL_PLATFORM_WINDOWS SDL3_SetWindowsMessageHook(SDL3to2_WindowsMessageHook, NULL); #endif -#if defined(SDL_PLATFORM_UNIX) && !defined(SDL_PLATFORM_ANDROID) +#ifdef SDL2COMPAT_HAVE_X11 SDL3_SetX11EventHook(SDL2COMPAT_X11EventHook, NULL); #endif } @@ -10124,7 +10232,7 @@ SDL_SetWindowsMessageHook(NULL, NULL); } #endif -#if defined(SDL_PLATFORM_UNIX) && !defined(SDL_PLATFORM_ANDROID) +#ifdef SDL2COMPAT_HAVE_X11 SDL3_SetX11EventHook(NULL, NULL); #endif } @@ -11471,7 +11579,12 @@ } if (src_channels < dst_channels) { - cvt->len_mult = ((cvt->len_mult * dst_channels) + (src_channels - 1)) / src_channels; + const double mult = ((double)dst_channels / (double)src_channels); + cvt->len_mult *= (int)SDL_ceil(mult); + cvt->len_ratio *= mult; + } else { + const double divisor = ((double)src_channels / (double)dst_channels); + cvt->len_ratio /= divisor; } if (src_rate < dst_rate) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sdl2-compat-2.32.54/src/sdl3_include_wrapper.h new/sdl2-compat-2.32.56/src/sdl3_include_wrapper.h --- old/sdl2-compat-2.32.54/src/sdl3_include_wrapper.h 2025-03-07 20:47:00.000000000 +0100 +++ new/sdl2-compat-2.32.56/src/sdl3_include_wrapper.h 2025-04-27 21:37:50.000000000 +0200 @@ -1270,6 +1270,21 @@ #define SDL_RenderTexture9GridTiled IGNORE_THIS_VERSION_OF_SDL_RenderTexture9GridTiled #define SDL_SetDefaultTextureScaleMode IGNORE_THIS_VERSION_OF_SDL_SetDefaultTextureScaleMode #define SDL_GetDefaultTextureScaleMode IGNORE_THIS_VERSION_OF_SDL_GetDefaultTextureScaleMode +#define SDL_CreateGPURenderState IGNORE_THIS_VERSION_OF_SDL_CreateGPURenderState +#define SDL_SetGPURenderStateFragmentUniforms IGNORE_THIS_VERSION_OF_SDL_SetGPURenderStateFragmentUniforms +#define SDL_SetRenderGPUState IGNORE_THIS_VERSION_OF_SDL_SetRenderGPUState +#define SDL_DestroyGPURenderState IGNORE_THIS_VERSION_OF_SDL_DestroyGPURenderState +#define SDL_SetWindowProgressState IGNORE_THIS_VERSION_OF_SDL_SetWindowProgressState +#define SDL_SetWindowProgressValue IGNORE_THIS_VERSION_OF_SDL_SetWindowProgressValue +#define SDL_GetWindowProgressState IGNORE_THIS_VERSION_OF_SDL_GetWindowProgressState +#define SDL_GetWindowProgressValue IGNORE_THIS_VERSION_OF_SDL_GetWindowProgressValue +#define SDL_SetRenderTextureAddressMode IGNORE_THIS_VERSION_OF_SDL_SetRenderTextureAddressMode +#define SDL_GetRenderTextureAddressMode IGNORE_THIS_VERSION_OF_SDL_GetRenderTextureAddressMode +#define SDL_GetGPUDeviceProperties IGNORE_THIS_VERSION_OF_SDL_GetGPUDeviceProperties +#define SDL_CreateGPURenderer IGNORE_THIS_VERSION_OF_SDL_CreateGPURenderer +#define SDL_PutAudioStreamPlanarData IGNORE_THIS_VERSION_OF_SDL_PutAudioStreamPlanarData +#define SDL_SetAudioIterationCallbacks IGNORE_THIS_VERSION_OF_SDL_SetAudioIterationCallbacks +#define SDL_GetEventDescription IGNORE_THIS_VERSION_OF_SDL_GetEventDescription #define SDL_FUNCTION_POINTER_IS_VOID_POINTER 1 @@ -6244,6 +6259,66 @@ #undef SDL_GetDefaultTextureScaleMode #endif +#ifdef SDL_CreateGPURenderState +#undef SDL_CreateGPURenderState +#endif + +#ifdef SDL_SetGPURenderStateFragmentUniforms +#undef SDL_SetGPURenderStateFragmentUniforms +#endif + +#ifdef SDL_SetRenderGPUState +#undef SDL_SetRenderGPUState +#endif + +#ifdef SDL_DestroyGPURenderState +#undef SDL_DestroyGPURenderState +#endif + +#ifdef SDL_SetWindowProgressState +#undef SDL_SetWindowProgressState +#endif + +#ifdef SDL_SetWindowProgressValue +#undef SDL_SetWindowProgressValue +#endif + +#ifdef SDL_GetWindowProgressState +#undef SDL_GetWindowProgressState +#endif + +#ifdef SDL_GetWindowProgressValue +#undef SDL_GetWindowProgressValue +#endif + +#ifdef SDL_SetRenderTextureAddressMode +#undef SDL_SetRenderTextureAddressMode +#endif + +#ifdef SDL_GetRenderTextureAddressMode +#undef SDL_GetRenderTextureAddressMode +#endif + +#ifdef SDL_GetGPUDeviceProperties +#undef SDL_GetGPUDeviceProperties +#endif + +#ifdef SDL_CreateGPURenderer +#undef SDL_CreateGPURenderer +#endif + +#ifdef SDL_PutAudioStreamPlanarData +#undef SDL_PutAudioStreamPlanarData +#endif + +#ifdef SDL_SetAudioIterationCallbacks +#undef SDL_SetAudioIterationCallbacks +#endif + +#ifdef SDL_GetEventDescription +#undef SDL_GetEventDescription +#endif + #undef SDL_ThreadID /* see at top. */ /* dump the macro CreateThread versions, too. */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sdl2-compat-2.32.54/src/sdl3_syms.h new/sdl2-compat-2.32.56/src/sdl3_syms.h --- old/sdl2-compat-2.32.54/src/sdl3_syms.h 2025-03-29 02:51:05.000000000 +0100 +++ new/sdl2-compat-2.32.56/src/sdl3_syms.h 2025-04-29 06:47:37.000000000 +0200 @@ -344,7 +344,7 @@ SDL3_SYM(const SDL_PixelFormatDetails *,GetPixelFormatDetails,(SDL_PixelFormat a),(a),return) SDL3_SYM(SDL_PixelFormat,GetPixelFormatForMasks,(int a, Uint32 b, Uint32 c, Uint32 d, Uint32 e),(a,b,c,d,e),return) SDL3_SYM(const char*,GetPixelFormatName,(SDL_PixelFormat a),(a),return) -SDL3_SYM_PASSTHROUGH(const char*,GetPlatform,(void),(),return) +SDL3_SYM(const char*,GetPlatform,(void),(),return) SDL3_SYM(void*,GetPointerProperty,(SDL_PropertiesID a, const char *b, void *c),(a,b,c),return) SDL3_SYM_PASSTHROUGH(SDL_PowerState,GetPowerInfo,(int *a, int *b),(a,b),return) SDL3_SYM_PASSTHROUGH(char*,GetPrefPath,(const char *a, const char *b),(a,b),return) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sdl2-compat-2.32.54/src/version.rc new/sdl2-compat-2.32.56/src/version.rc --- old/sdl2-compat-2.32.54/src/version.rc 2025-03-31 22:56:41.000000000 +0200 +++ new/sdl2-compat-2.32.56/src/version.rc 2025-05-04 20:01:15.000000000 +0200 @@ -3,8 +3,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US VS_VERSION_INFO VERSIONINFO - FILEVERSION 2,32,54,0 - PRODUCTVERSION 2,32,54,0 + FILEVERSION 2,32,56,0 + PRODUCTVERSION 2,32,56,0 FILEFLAGSMASK 0x3fL FILEFLAGS 0x0L FILEOS 0x40004L @@ -17,12 +17,12 @@ BEGIN VALUE "CompanyName", "\0" VALUE "FileDescription", "SDL\0" - VALUE "FileVersion", "2, 32, 54, 0\0" + VALUE "FileVersion", "2, 32, 56, 0\0" VALUE "InternalName", "SDL\0" VALUE "LegalCopyright", "Copyright (C) 2025 Sam Lantinga\0" VALUE "OriginalFilename", "SDL2.dll\0" VALUE "ProductName", "Simple DirectMedia Layer 2.0 wrapper\0" - VALUE "ProductVersion", "2, 32, 54, 0\0" + VALUE "ProductVersion", "2, 32, 56, 0\0" END END BLOCK "VarFileInfo" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sdl2-compat-2.32.54/test/testautomation_hints.c new/sdl2-compat-2.32.56/test/testautomation_hints.c --- old/sdl2-compat-2.32.54/test/testautomation_hints.c 2025-03-23 23:35:10.000000000 +0100 +++ new/sdl2-compat-2.32.56/test/testautomation_hints.c 2025-04-01 00:55:40.000000000 +0200 @@ -182,6 +182,17 @@ "testValue = %s, expected \"original\"", testValue); +#if 0 /* Disabled in SDL2-COMPAT. */ + SDLTest_AssertPass("Call to SDL_SetHint(\"\", \"data\")"); + result = SDL_SetHint("", "data"); + SDLTest_AssertCheck(result, "SDL_SetHint(\"\", \"data\") should return true"); + testValue = SDL_GetHint(""); + SDLTest_AssertCheck( + testValue && SDL_strcmp(testValue, "data") == 0, + "testValue = %s, expected \"data\"", + testValue); +#endif + SDLTest_AssertPass("Call to SDL_SetHintWithPriority(\"temp\", SDL_HINT_OVERRIDE)"); result = SDL_SetHintWithPriority(testHint, "temp", SDL_HINT_OVERRIDE); SDLTest_AssertCheck(result, "SDL_SetHintWithPriority(\"%s\", \"temp\", SDL_HINT_OVERRIDE) should return true", testHint); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sdl2-compat-2.32.54/test/testautomation_video.c new/sdl2-compat-2.32.56/test/testautomation_video.c --- old/sdl2-compat-2.32.54/test/testautomation_video.c 2025-03-17 02:14:40.000000000 +0100 +++ new/sdl2-compat-2.32.56/test/testautomation_video.c 2025-04-01 00:55:40.000000000 +0200 @@ -2024,14 +2024,14 @@ } /* Get display bounds */ - result = SDL_GetDisplayUsableBounds(0 % displayNum, &display0); + result = SDL_GetDisplayUsableBounds(0 % displayNum, &display0); /* SDL2-COMPAT change -- was SDL_GetDisplayBounds() */ SDLTest_AssertPass("SDL_GetDisplayBounds()"); SDLTest_AssertCheck(result == 0, "Verify return value; expected: 0, got: %d", result); if (result != 0) { return TEST_ABORTED; } - result = SDL_GetDisplayUsableBounds(1 % displayNum, &display1); + result = SDL_GetDisplayUsableBounds(1 % displayNum, &display1); /* SDL2-COMPAT change -- was SDL_GetDisplayBounds() */ SDLTest_AssertPass("SDL_GetDisplayBounds()"); SDLTest_AssertCheck(result == 0, "Verify return value; expected: 0, got: %d", result); if (result != 0) { @@ -2045,7 +2045,8 @@ int expectedX = 0, expectedY = 0; int currentDisplay; int expectedDisplay; - SDL_Rect expectedDisplayRect, expectedFullscreenRect; + SDL_Rect expectedFullscreenRect; /* Added for SDL2-COMPAT -- see below */ + SDL_Rect expectedDisplayRect; SDL_bool video_driver_is_wayland = SDL_strcmp(SDL_GetCurrentVideoDriver(), "wayland") == 0; /* xVariation is the display we start on */ @@ -2108,7 +2109,7 @@ SDL_GetWindowSize(window, ¤tW, ¤tH); SDL_GetWindowPosition(window, ¤tX, ¤tY); - /* Get the expected fullscreen rect. + /* SDL2-COMPAT addition: Get the expected fullscreen rect. * This needs to be queried after window creation and positioning as some drivers can alter the * usable bounds based on the window scaling mode. */ @@ -2121,6 +2122,7 @@ } else { SDLTest_Log("Skipping display index validation: Wayland driver does not support window positioning"); } + /* The following four checks changed from expectedDisplayRect to expectedFullscreenRect for SDL2-COMPAT: */ SDLTest_AssertCheck(currentW == expectedFullscreenRect.w, "Validate width (current: %d, expected: %d)", currentW, expectedFullscreenRect.w); SDLTest_AssertCheck(currentH == expectedFullscreenRect.h, "Validate height (current: %d, expected: %d)", currentH, expectedFullscreenRect.h); if (!video_driver_is_wayland) { ++++++ sdl2-compat.keyring ++++++ pub 1024D/A7763BE6 2001-01-05 uid Sam Lantinga <[email protected]> sub 1024g/06F8768C 2001-01-05 -----BEGIN PGP PUBLIC KEY BLOCK----- Version: GnuPG v2.0.19 (GNU/Linux) mQGiBDpWOb0RBADQwd3d9mzt6KzqlsgXf9mikBuMbpKzYs1SBKYpdzUs9sRY0CnH vCQTrL5sI57yKLnqEl6SbIiE75ZwrSWwvUDFFTh35Jew5nPZwv64en2kw2y4qrnJ kBZCHDSU4KgfUZtoJ25Tmeru5MLNbXxCOoMszO5L5OchwMrGMtmFLRA/bwCgy5Th d1/vJo+bej9tbgv++SJ05o0D/3MPK7EBoxWkQ0I+ScqOsvSMRQXWc/hXy4lyIp8e xJByBApkv0LiiT3KlPpq/K2gTlDlCZ/JTt6Rv8Ug0g47R3a0aoz9kfc15UjHdiap UOfF9MWmmbw59Lyx6+y2e0/C5xWzNOR1G4G5y4RZL/GXrp67xz/0fEhI85R+eASq AEfSBAC5ZxwnBwyl+h+PXeJYKrPQjSUlgtSAkKp7PNBywwlue1LcSb7j4cc+cmgH QMVuM883LPE59btNzFTAZjlzzIMiaXf5h9EkDARTGQ1wFiO3V5vIbVLh4kAoNfpT egy7bYn3UrlbKg3V2DbCdEXm1zQufZzK7T0yenA5Ps8xXX7mNrQhU2FtIExhbnRp bmdhIDxzbG91a2VuQGxpYnNkbC5vcmc+iF8EExECABcFAjpWOb0FCwcKAwQDFQMC AxYCAQIXgAASCRAwpZN3p3Y75gdlR1BHAAEB31EAnjxYj6c496zRYru3fzUiPgl9 JjFZAKCOkxoODf9qHbcdmFi1Mq0dTMP3OLkBDQQ6VjnDEAQA++MHQHlE0CPyEEX8 urvzDmsnX9/lGpZeZ1/ECm4QT/04QVdRJReaz1/8ha/JJ3J/jw+Ti3aHxvyLsXR/ dH61wKnqbQ+3UFI0di6Z+a2idPLkUeqnAFWUSLsjSzmYPeTE76Tw9BsBMcfmyYWe jPZRNz4zNCNR21PNdSRSCq9/3NMAAwYD/1j+HquGLdhhd4jpKZtepybOxArNpZWE t7DruzN6OdiwognWNrgx59iW2EJeCYgGuI1+3Ega0EjQ9ybPCmfR6SdE0ro2CmYR JsYoJaHn0l6IArmF0E97jstIVVy3nNI729CFEPIvOHM8+0Hdd6gpNSQtbEFItt5l XBwc8gr/AtqXiE4EGBECAAYFAjpWOcMAEgkQMKWTd6d2O+YHZUdQRwABAcZlAJ9z Xumd1FC6YnvEST9eUQbeitjFhQCfYSvy7PxXgSfXedKsZmHWdka01zY= =62+H -----END PGP PUBLIC KEY BLOCK-----
