Browse Source

Added property types: pointer, string, number, float

Sam Lantinga 1 year ago
parent
commit
0907f345cb

+ 161 - 10
include/SDL3/SDL_properties.h

@@ -39,6 +39,18 @@ extern "C" {
  */
 typedef Uint32 SDL_PropertiesID;
 
+/**
+ * SDL property type
+ */
+typedef enum
+{
+    SDL_PROPERTY_TYPE_INVALID,
+    SDL_PROPERTY_TYPE_POINTER,
+    SDL_PROPERTY_TYPE_STRING,
+    SDL_PROPERTY_TYPE_NUMBER,
+    SDL_PROPERTY_TYPE_FLOAT,
+} SDL_PropertyType;
+
 /**
  * Get the global SDL properties
  *
@@ -105,6 +117,28 @@ extern DECLSPEC int SDLCALL SDL_LockProperties(SDL_PropertiesID props);
  */
 extern DECLSPEC void SDLCALL SDL_UnlockProperties(SDL_PropertiesID props);
 
+/**
+ * Set a property on a set of properties with a cleanup function that is
+ * called when the property is deleted
+ *
+ * \param props the properties to modify
+ * \param name the name of the property to modify
+ * \param value the new value of the property, or NULL to delete the property
+ * \param cleanup the function to call when this property is deleted, or NULL
+ *                if no cleanup is necessary
+ * \param userdata a pointer that is passed to the cleanup function
+ * \returns 0 on success or a negative error code on failure; call
+ *          SDL_GetError() for more information.
+ *
+ * \threadsafety It is safe to call this function from any thread.
+ *
+ * \since This function is available since SDL 3.0.0.
+ *
+ * \sa SDL_GetProperty
+ * \sa SDL_SetProperty
+ */
+extern DECLSPEC int SDLCALL SDL_SetPropertyWithCleanup(SDL_PropertiesID props, const char *name, void *value, void (SDLCALL *cleanup)(void *userdata, void *value), void *userdata);
+
 /**
  * Set a property on a set of properties
  *
@@ -124,15 +158,11 @@ extern DECLSPEC void SDLCALL SDL_UnlockProperties(SDL_PropertiesID props);
 extern DECLSPEC int SDLCALL SDL_SetProperty(SDL_PropertiesID props, const char *name, void *value);
 
 /**
- * Set a property on a set of properties with a cleanup function that is
- * called when the property is deleted
+ * Set a string property on a set of properties
  *
  * \param props the properties to modify
  * \param name the name of the property to modify
  * \param value the new value of the property, or NULL to delete the property
- * \param cleanup the function to call when this property is deleted, or NULL
- *                if no cleanup is necessary
- * \param userdata a pointer that is passed to the cleanup function
  * \returns 0 on success or a negative error code on failure; call
  *          SDL_GetError() for more information.
  *
@@ -140,10 +170,56 @@ extern DECLSPEC int SDLCALL SDL_SetProperty(SDL_PropertiesID props, const char *
  *
  * \since This function is available since SDL 3.0.0.
  *
- * \sa SDL_GetProperty
- * \sa SDL_SetProperty
+ * \sa SDL_GetStringProperty
  */
-extern DECLSPEC int SDLCALL SDL_SetPropertyWithCleanup(SDL_PropertiesID props, const char *name, void *value, void (SDLCALL *cleanup)(void *userdata, void *value), void *userdata);
+extern DECLSPEC int SDLCALL SDL_SetStringProperty(SDL_PropertiesID props, const char *name, const char *value);
+
+/**
+ * Set an integer property on a set of properties
+ *
+ * \param props the properties to modify
+ * \param name the name of the property to modify
+ * \param value the new value of the property
+ * \returns 0 on success or a negative error code on failure; call
+ *          SDL_GetError() for more information.
+ *
+ * \threadsafety It is safe to call this function from any thread.
+ *
+ * \since This function is available since SDL 3.0.0.
+ *
+ * \sa SDL_GetNumberProperty
+ */
+extern DECLSPEC int SDLCALL SDL_SetNumberProperty(SDL_PropertiesID props, const char *name, Sint64 value);
+
+/**
+ * Set a floating point property on a set of properties
+ *
+ * \param props the properties to modify
+ * \param name the name of the property to modify
+ * \param value the new value of the property
+ * \returns 0 on success or a negative error code on failure; call
+ *          SDL_GetError() for more information.
+ *
+ * \threadsafety It is safe to call this function from any thread.
+ *
+ * \since This function is available since SDL 3.0.0.
+ *
+ * \sa SDL_GetFloatProperty
+ */
+extern DECLSPEC int SDLCALL SDL_SetFloatProperty(SDL_PropertiesID props, const char *name, float value);
+
+/**
+ * Get the type of a property on a set of properties
+ *
+ * \param props the properties to query
+ * \param name the name of the property to query
+ * \returns the type of the property, or SDL_PROPERTY_TYPE_INVALID if it is not set.
+ *
+ * \threadsafety It is safe to call this function from any thread.
+ *
+ * \since This function is available since SDL 3.0.0.
+ */
+extern DECLSPEC SDL_PropertyType SDLCALL SDL_GetPropertyType(SDL_PropertiesID props, const char *name);
 
 /**
  * Get a property on a set of properties
@@ -155,7 +231,8 @@ extern DECLSPEC int SDLCALL SDL_SetPropertyWithCleanup(SDL_PropertiesID props, c
  *
  * \param props the properties to query
  * \param name the name of the property to query
- * \returns the value of the property, or NULL if it is not set.
+ * \param default_value the default value of the property
+ * \returns the value of the property, or `default_value` if it is not set or not a pointer property.
  *
  * \threadsafety It is safe to call this function from any thread, although
  *               the data returned is not protected and could potentially be
@@ -165,9 +242,65 @@ extern DECLSPEC int SDLCALL SDL_SetPropertyWithCleanup(SDL_PropertiesID props, c
  *
  * \since This function is available since SDL 3.0.0.
  *
+ * \sa SDL_GetPropertyType
  * \sa SDL_SetProperty
  */
-extern DECLSPEC void *SDLCALL SDL_GetProperty(SDL_PropertiesID props, const char *name);
+extern DECLSPEC void *SDLCALL SDL_GetProperty(SDL_PropertiesID props, const char *name, void *default_value);
+
+/**
+ * Get a string property on a set of properties
+ *
+ * \param props the properties to query
+ * \param name the name of the property to query
+ * \param default_value the default value of the property
+ * \returns the value of the property, or `default_value` if it is not set or not a string property.
+ *
+ * \threadsafety It is safe to call this function from any thread.
+ *
+ * \since This function is available since SDL 3.0.0.
+ *
+ * \sa SDL_GetPropertyType
+ * \sa SDL_SetStringProperty
+ */
+extern DECLSPEC const char *SDLCALL SDL_GetStringProperty(SDL_PropertiesID props, const char *name, const char *default_value);
+
+/**
+ * Get a number property on a set of properties
+ *
+ * You can use SDL_GetPropertyType() to query whether the property exists and is a number property.
+ *
+ * \param props the properties to query
+ * \param name the name of the property to query
+ * \param default_value the default value of the property
+ * \returns the value of the property, or `default_value` if it is not set or not a number property.
+ *
+ * \threadsafety It is safe to call this function from any thread.
+ *
+ * \since This function is available since SDL 3.0.0.
+ *
+ * \sa SDL_GetPropertyType
+ * \sa SDL_SetNumberProperty
+ */
+extern DECLSPEC Sint64 SDLCALL SDL_GetNumberProperty(SDL_PropertiesID props, const char *name, Sint64 default_value);
+
+/**
+ * Get a floating point property on a set of properties
+ *
+ * You can use SDL_GetPropertyType() to query whether the property exists and is a floating point property.
+ *
+ * \param props the properties to query
+ * \param name the name of the property to query
+ * \param default_value the default value of the property
+ * \returns the value of the property, or `default_value` if it is not set or not a float property.
+ *
+ * \threadsafety It is safe to call this function from any thread.
+ *
+ * \since This function is available since SDL 3.0.0.
+ *
+ * \sa SDL_GetPropertyType
+ * \sa SDL_SetFloatProperty
+ */
+extern DECLSPEC float SDLCALL SDL_GetFloatProperty(SDL_PropertiesID props, const char *name, float default_value);
 
 /**
  * Clear a property on a set of properties
@@ -185,6 +318,24 @@ extern DECLSPEC void *SDLCALL SDL_GetProperty(SDL_PropertiesID props, const char
  */
 extern DECLSPEC int SDLCALL SDL_ClearProperty(SDL_PropertiesID props, const char *name);
 
+typedef void (SDLCALL *SDL_EnumeratePropertiesCallback)(void *userdata, SDL_PropertiesID props, const char *name);
+/**
+ * Enumerate the properties on a set of properties
+ *
+ * The callback function is called for each property on the set of properties. The properties are locked during enumeration.
+ *
+ * \param props the properties to query
+ * \param callback the function to call for each property
+ * \param userdata a pointer that is passed to `callback`
+ * \returns 0 on success or a negative error code on failure; call
+ *          SDL_GetError() for more information.
+ *
+ * \threadsafety It is safe to call this function from any thread.
+ *
+ * \since This function is available since SDL 3.0.0.
+ */
+extern DECLSPEC int SDLCALL SDL_EnumerateProperties(SDL_PropertiesID props, SDL_EnumeratePropertiesCallback callback, void *userdata);
+
 /**
  * Destroy a set of properties
  *

+ 19 - 19
include/SDL3/SDL_render.h

@@ -311,10 +311,10 @@ extern DECLSPEC int SDLCALL SDL_GetRendererInfo(SDL_Renderer *renderer, SDL_Rend
  *
  * The following properties are provided by SDL:
  * ```
- * "SDL.renderer.d3d9.device" - the IDirect3DDevice9 associated with the renderer
- * "SDL.renderer.d3d11.device" - the ID3D11Device associated with the renderer
- * "SDL.renderer.d3d12.device" - the ID3D12Device associated with the renderer
- * "SDL.renderer.d3d12.command_queue" - the ID3D12CommandQueue associated with the renderer
+ * "SDL.renderer.d3d9.device" (pointer) - the IDirect3DDevice9 associated with the renderer
+ * "SDL.renderer.d3d11.device" (pointer) - the ID3D11Device associated with the renderer
+ * "SDL.renderer.d3d12.device" (pointer) - the ID3D12Device associated with the renderer
+ * "SDL.renderer.d3d12.command_queue" (pointer) - the ID3D12CommandQueue associated with the renderer
  * ```
  *
  * \param renderer the rendering context
@@ -424,33 +424,33 @@ extern DECLSPEC SDL_Texture *SDLCALL SDL_CreateTextureFromSurface(SDL_Renderer *
  *
  * With the direct3d11 renderer:
  * ```
- * "SDL.texture.d3d11.texture" - the ID3D11Texture2D associated with the texture
- * "SDL.texture.d3d11.texture_u" - the ID3D11Texture2D associated with the U plane of a YUV texture
- * "SDL.texture.d3d11.texture_v" - the ID3D11Texture2D associated with the V plane of a YUV texture
+ * "SDL.texture.d3d11.texture" (pointer) - the ID3D11Texture2D associated with the texture
+ * "SDL.texture.d3d11.texture_u" (pointer) - the ID3D11Texture2D associated with the U plane of a YUV texture
+ * "SDL.texture.d3d11.texture_v" (pointer) - the ID3D11Texture2D associated with the V plane of a YUV texture
  * ```
  *
  * With the direct3d12 renderer:
  * ```
- * "SDL.texture.d3d12.texture" - the ID3D12Resource associated with the texture
- * "SDL.texture.d3d12.texture_u" - the ID3D12Resource associated with the U plane of a YUV texture
- * "SDL.texture.d3d12.texture_v" - the ID3D12Resource associated with the V plane of a YUV texture
+ * "SDL.texture.d3d12.texture" (pointer) - the ID3D12Resource associated with the texture
+ * "SDL.texture.d3d12.texture_u" (pointer) - the ID3D12Resource associated with the U plane of a YUV texture
+ * "SDL.texture.d3d12.texture_v" (pointer) - the ID3D12Resource associated with the V plane of a YUV texture
  * ```
  *
  * With the opengl renderer:
  * ```
- * "SDL.texture.opengl.texture" - the GLuint texture associated with the texture
- * "SDL.texture.opengl.texture_u" - the GLuint texture associated with the U plane of a YUV texture
- * "SDL.texture.opengl.texture_v" - the GLuint texture associated with the V plane of a YUV texture
- * "SDL.texture.opengl.tex_w" - the 16.16 fixed point texture coordinate width of the texture
- * "SDL.texture.opengl.tex_h" - the 16.16 fixed point texture coordinate height of the texture
+ * "SDL.texture.opengl.texture" (number) - the GLuint texture associated with the texture
+ * "SDL.texture.opengl.texture_u" (number) - the GLuint texture associated with the U plane of a YUV texture
+ * "SDL.texture.opengl.texture_v" (number) - the GLuint texture associated with the V plane of a YUV texture
+ * "SDL.texture.opengl.tex_w" (float) - the texture coordinate width of the texture (0.0 - 1.0)
+ * "SDL.texture.opengl.tex_h" (float) - the texture coordinate height of the texture (0.0 - 1.0)
  * ```
  *
  * With the opengles2 renderer:
  * ```
- * "SDL.texture.opengles2.texture" - the GLuint texture associated with the texture
- * "SDL.texture.opengles2.texture_uv" - the GLuint texture associated with the UV plane of an NV12 texture
- * "SDL.texture.opengles2.texture_u" - the GLuint texture associated with the U plane of a YUV texture
- * "SDL.texture.opengles2.texture_v" - the GLuint texture associated with the V plane of a YUV texture
+ * "SDL.texture.opengles2.texture" (number) - the GLuint texture associated with the texture
+ * "SDL.texture.opengles2.texture_uv" (number) - the GLuint texture associated with the UV plane of an NV12 texture
+ * "SDL.texture.opengles2.texture_u" (number) - the GLuint texture associated with the U plane of a YUV texture
+ * "SDL.texture.opengles2.texture_v" (number) - the GLuint texture associated with the V plane of a YUV texture
  * ```
  *
  * \param texture the texture to query

+ 27 - 27
include/SDL3/SDL_video.h

@@ -938,58 +938,58 @@ extern DECLSPEC SDL_Window *SDLCALL SDL_GetWindowParent(SDL_Window *window);
  *
  * On Android:
  * ```
- * "SDL.window.android.window" - the ANativeWindow associated with the window
- * "SDL.window.android.surface" - the EGLSurface associated with the window
+ * "SDL.window.android.window" (pointer) - the ANativeWindow associated with the window
+ * "SDL.window.android.surface" (pointer) - the EGLSurface associated with the window
  * ```
  *
  * On iOS:
  * ```
- * "SDL.window.uikit.window" - the (__unsafe_unretained) UIWindow associated with the window
- * "SDL.window.uikit.metal_view_tag" - the NSInteger tag assocated with metal views on the window
+ * "SDL.window.uikit.window" (pointer) - the (__unsafe_unretained) UIWindow associated with the window
+ * "SDL.window.uikit.metal_view_tag" (number) - the NSInteger tag assocated with metal views on the window
  * ```
  *
  * On KMS/DRM:
  * ```
- * "SDL.window.kmsdrm.dev_index" - the device index associated with the window (e.g. the X in /dev/dri/cardX)
- * "SDL.window.kmsdrm.drm_fd" - the DRM FD associated with the window
- * "SDL.window.kmsdrm.gbm_dev" - the GBM device associated with the window
+ * "SDL.window.kmsdrm.dev_index" (number) - the device index associated with the window (e.g. the X in /dev/dri/cardX)
+ * "SDL.window.kmsdrm.drm_fd" (number) - the DRM FD associated with the window
+ * "SDL.window.kmsdrm.gbm_dev" (pointer) - the GBM device associated with the window
  * ```
  *
  * On macOS:
  * ```
- * "SDL.window.cocoa.window" - the (__unsafe_unretained) NSWindow associated with the window
- * "SDL.window.cocoa.metal_view_tag" - the NSInteger tag assocated with metal views on the window
+ * "SDL.window.cocoa.window" (pointer) - the (__unsafe_unretained) NSWindow associated with the window
+ * "SDL.window.cocoa.metal_view_tag" (number) - the NSInteger tag assocated with metal views on the window
  * ```
  *
  * On Vivante:
  * ```
- * "SDL.window.vivante.display" - the EGLNativeDisplayType associated with the window
- * "SDL.window.vivante.window" - the EGLNativeWindowType associated with the window
- * "SDL.window.vivante.surface" - the EGLSurface associated with the window
+ * "SDL.window.vivante.display" (pointer) - the EGLNativeDisplayType associated with the window
+ * "SDL.window.vivante.window" (pointer) - the EGLNativeWindowType associated with the window
+ * "SDL.window.vivante.surface" (pointer) - the EGLSurface associated with the window
  * ```
  *
  * On UWP:
  * ```
- * "SDL.window.winrt.window" - the IInspectable CoreWindow associated with the window
+ * "SDL.window.winrt.window" (pointer) - the IInspectable CoreWindow associated with the window
  * ```
  *
  * On Windows:
  * ```
- * "SDL.window.win32.hwnd" - the HWND associated with the window
- * "SDL.window.win32.hdc" - the HDC associated with the window
- * "SDL.window.win32.instance" - the HINSTANCE associated with the window
+ * "SDL.window.win32.hwnd" (pointer) - the HWND associated with the window
+ * "SDL.window.win32.hdc" (pointer) - the HDC associated with the window
+ * "SDL.window.win32.instance" (pointer) - the HINSTANCE associated with the window
  * ```
  *
  * On Wayland:
  * ```
- * "SDL.window.wayland.registry" - the wl_registry associated with the window
- * "SDL.window.wayland.display" - the wl_display associated with the window
- * "SDL.window.wayland.surface" - the wl_surface associated with the window
- * "SDL.window.wayland.egl_window" - the wl_egl_window associated with the window
- * "SDL.window.wayland.xdg_surface" - the xdg_surface associated with the window
- * "SDL.window.wayland.xdg_toplevel" - the xdg_toplevel role associated with the window
- * "SDL.window.wayland.xdg_popup" - the xdg_popup role associated with the window
- * "SDL.window.wayland.xdg_positioner" - the xdg_positioner associated with the window, in popup mode
+ * "SDL.window.wayland.registry" (pointer) - the wl_registry associated with the window
+ * "SDL.window.wayland.display" (pointer) - the wl_display associated with the window
+ * "SDL.window.wayland.surface" (pointer) - the wl_surface associated with the window
+ * "SDL.window.wayland.egl_window" (pointer) - the wl_egl_window associated with the window
+ * "SDL.window.wayland.xdg_surface" (pointer) - the xdg_surface associated with the window
+ * "SDL.window.wayland.xdg_toplevel" (pointer) - the xdg_toplevel role associated with the window
+ * "SDL.window.wayland.xdg_popup" (pointer) - the xdg_popup role associated with the window
+ * "SDL.window.wayland.xdg_positioner" (pointer) - the xdg_positioner associated with the window, in popup mode
  * ```
  *
  * Note: The xdg_* window objects do not internally persist across window show/hide calls.
@@ -997,9 +997,9 @@ extern DECLSPEC SDL_Window *SDLCALL SDL_GetWindowParent(SDL_Window *window);
  *
  * On X11:
  * ```
- * "SDL.window.x11.display" - the X11 Display associated with the window
- * "SDL.window.x11.screen" - the screen number associated with the window
- * "SDL.window.x11.window" - the X11 Window associated with the window
+ * "SDL.window.x11.display" (pointer) - the X11 Display associated with the window
+ * "SDL.window.x11.screen" (number) - the screen number associated with the window
+ * "SDL.window.x11.window" (number) - the X11 Window associated with the window
  * ```
  *
  * \param window the window to query

+ 317 - 28
src/SDL_properties.c

@@ -25,7 +25,15 @@
 
 typedef struct
 {
-    void *value;
+    SDL_PropertyType type;
+
+    union {
+        void *pointer_value;
+        char *string_value;
+        Sint64 number_value;
+        float float_value;
+    } value;
+
     void (SDLCALL *cleanup)(void *userdata, void *value);
     void *userdata;
 } SDL_Property;
@@ -45,8 +53,19 @@ static SDL_PropertiesID SDL_global_properties;
 static void SDL_FreeProperty(const void *key, const void *value, void *data)
 {
     SDL_Property *property = (SDL_Property *)value;
-    if (property->cleanup) {
-        property->cleanup(property->userdata, property->value);
+    if (property) {
+        switch (property->type) {
+        case SDL_PROPERTY_TYPE_POINTER:
+            if (property->cleanup) {
+                property->cleanup(property->userdata, property->value.pointer_value);
+            }
+            break;
+        case SDL_PROPERTY_TYPE_STRING:
+            SDL_free(property->value.string_value);
+            break;
+        default:
+            break;
+        }
     }
     SDL_free((void *)key);
     SDL_free((void *)value);
@@ -196,21 +215,17 @@ void SDL_UnlockProperties(SDL_PropertiesID props)
     SDL_UnlockMutex(properties->lock);
 }
 
-int SDL_SetProperty(SDL_PropertiesID props, const char *name, void *value)
-{
-    return SDL_SetPropertyWithCleanup(props, name, value, NULL, NULL);
-}
-
-int SDL_SetPropertyWithCleanup(SDL_PropertiesID props, const char *name, void *value, void (SDLCALL *cleanup)(void *userdata, void *value), void *userdata)
+static int SDL_PrivateSetProperty(SDL_PropertiesID props, const char *name, SDL_Property *property)
 {
     SDL_Properties *properties = NULL;
-    SDL_Property *property = NULL;
     int result = 0;
 
     if (!props) {
+        SDL_FreeProperty(NULL, property, NULL);
         return SDL_InvalidParamError("props");
     }
     if (!name || !*name) {
+        SDL_FreeProperty(NULL, property, NULL);
         return SDL_InvalidParamError("name");
     }
 
@@ -219,20 +234,10 @@ int SDL_SetPropertyWithCleanup(SDL_PropertiesID props, const char *name, void *v
     SDL_UnlockRWLock(SDL_properties_lock);
 
     if (!properties) {
+        SDL_FreeProperty(NULL, property, NULL);
         return SDL_InvalidParamError("props");
     }
 
-    if (value) {
-        property = (SDL_Property *)SDL_malloc(sizeof(*property));
-        if (!property) {
-            return SDL_OutOfMemory();
-        }
-
-        property->value = value;
-        property->cleanup = cleanup;
-        property->userdata = userdata;
-    }
-
     SDL_LockMutex(properties->lock);
     {
         SDL_RemoveFromHashTable(properties->props, name);
@@ -249,18 +254,135 @@ int SDL_SetPropertyWithCleanup(SDL_PropertiesID props, const char *name, void *v
     return result;
 }
 
-void *SDL_GetProperty(SDL_PropertiesID props, const char *name)
+int SDL_SetPropertyWithCleanup(SDL_PropertiesID props, const char *name, void *value, void (SDLCALL *cleanup)(void *userdata, void *value), void *userdata)
+{
+    SDL_Property *property;
+
+    if (!value) {
+        return SDL_ClearProperty(props, name);
+    }
+
+    property = (SDL_Property *)SDL_calloc(1, sizeof(*property));
+    if (!property) {
+        return SDL_OutOfMemory();
+    }
+    property->type = SDL_PROPERTY_TYPE_POINTER;
+    property->value.pointer_value = value;
+    property->cleanup = cleanup;
+    property->userdata = userdata;
+    return SDL_PrivateSetProperty(props, name, property);
+}
+
+int SDL_SetProperty(SDL_PropertiesID props, const char *name, void *value)
+{
+    SDL_Property *property;
+
+    if (!value) {
+        return SDL_ClearProperty(props, name);
+    }
+
+    property = (SDL_Property *)SDL_calloc(1, sizeof(*property));
+    if (!property) {
+        return SDL_OutOfMemory();
+    }
+    property->type = SDL_PROPERTY_TYPE_POINTER;
+    property->value.pointer_value = value;
+    return SDL_PrivateSetProperty(props, name, property);
+}
+
+
+int SDL_SetStringProperty(SDL_PropertiesID props, const char *name, const char *value)
+{
+    SDL_Property *property;
+
+    if (!value) {
+        return SDL_ClearProperty(props, name);
+    }
+
+    property = (SDL_Property *)SDL_calloc(1, sizeof(*property));
+    if (!property) {
+        return SDL_OutOfMemory();
+    }
+    property->type = SDL_PROPERTY_TYPE_STRING;
+    property->value.string_value = SDL_strdup(value);
+    if (!property->value.string_value) {
+        SDL_free(property);
+        return SDL_OutOfMemory();
+    }
+    return SDL_PrivateSetProperty(props, name, property);
+}
+
+int SDL_SetNumberProperty(SDL_PropertiesID props, const char *name, Sint64 value)
+{
+    SDL_Property *property = (SDL_Property *)SDL_calloc(1, sizeof(*property));
+    if (!property) {
+        return SDL_OutOfMemory();
+    }
+    property->type = SDL_PROPERTY_TYPE_NUMBER;
+    property->value.number_value = value;
+    return SDL_PrivateSetProperty(props, name, property);
+}
+
+int SDL_SetFloatProperty(SDL_PropertiesID props, const char *name, float value)
+{
+    SDL_Property *property = (SDL_Property *)SDL_calloc(1, sizeof(*property));
+    if (!property) {
+        return SDL_OutOfMemory();
+    }
+    property->type = SDL_PROPERTY_TYPE_FLOAT;
+    property->value.float_value = value;
+    return SDL_PrivateSetProperty(props, name, property);
+}
+
+SDL_PropertyType SDL_GetPropertyType(SDL_PropertiesID props, const char *name)
+{
+    SDL_Properties *properties = NULL;
+    SDL_PropertyType type = SDL_PROPERTY_TYPE_INVALID;
+
+    if (!props) {
+        SDL_InvalidParamError("props");
+        return SDL_PROPERTY_TYPE_INVALID;
+    }
+    if (!name || !*name) {
+        SDL_InvalidParamError("name");
+        return SDL_PROPERTY_TYPE_INVALID;
+    }
+
+    SDL_LockRWLockForReading(SDL_properties_lock);
+    SDL_FindInHashTable(SDL_properties, (const void *)(uintptr_t)props, (const void **)&properties);
+    SDL_UnlockRWLock(SDL_properties_lock);
+
+    if (!properties) {
+        SDL_InvalidParamError("props");
+        return SDL_PROPERTY_TYPE_INVALID;
+    }
+
+    SDL_LockMutex(properties->lock);
+    {
+        SDL_Property *property = NULL;
+        if (SDL_FindInHashTable(properties->props, name, (const void **)&property)) {
+            type = property->type;
+        } else {
+            SDL_SetError("Couldn't find property named %s", name);
+        }
+    }
+    SDL_UnlockMutex(properties->lock);
+
+    return type;
+}
+
+void *SDL_GetProperty(SDL_PropertiesID props, const char *name, void *default_value)
 {
     SDL_Properties *properties = NULL;
-    void *value = NULL;
+    void *value = default_value;
 
     if (!props) {
         SDL_InvalidParamError("props");
-        return NULL;
+        return value;
     }
     if (!name || !*name) {
         SDL_InvalidParamError("name");
-        return NULL;
+        return value;
     }
 
     SDL_LockRWLockForReading(SDL_properties_lock);
@@ -269,7 +391,7 @@ void *SDL_GetProperty(SDL_PropertiesID props, const char *name)
 
     if (!properties) {
         SDL_InvalidParamError("props");
-        return NULL;
+        return value;
     }
 
     /* Note that taking the lock here only guarantees that we won't read the
@@ -280,7 +402,140 @@ void *SDL_GetProperty(SDL_PropertiesID props, const char *name)
     {
         SDL_Property *property = NULL;
         if (SDL_FindInHashTable(properties->props, name, (const void **)&property)) {
-            value = property->value;
+            if (property->type == SDL_PROPERTY_TYPE_POINTER) {
+                value = property->value.pointer_value;
+            } else {
+                SDL_SetError("Property %s isn't a pointer value", name);
+            }
+        } else {
+            SDL_SetError("Couldn't find property named %s", name);
+        }
+    }
+    SDL_UnlockMutex(properties->lock);
+
+    return value;
+}
+
+const char *SDL_GetStringProperty(SDL_PropertiesID props, const char *name, const char *default_value)
+{
+    SDL_Properties *properties = NULL;
+    const char *value = default_value;
+
+    if (!props) {
+        SDL_InvalidParamError("props");
+        return value;
+    }
+    if (!name || !*name) {
+        SDL_InvalidParamError("name");
+        return value;
+    }
+
+    SDL_LockRWLockForReading(SDL_properties_lock);
+    SDL_FindInHashTable(SDL_properties, (const void *)(uintptr_t)props, (const void **)&properties);
+    SDL_UnlockRWLock(SDL_properties_lock);
+
+    if (!properties) {
+        SDL_InvalidParamError("props");
+        return value;
+    }
+
+    /* Note that taking the lock here only guarantees that we won't read the
+     * hashtable while it's being modified. The value itself can easily be
+     * freed from another thread after it is returned here.
+     *
+     * FIXME: Should we SDL_strdup() the return value to avoid this?
+     */
+    SDL_LockMutex(properties->lock);
+    {
+        SDL_Property *property = NULL;
+        if (SDL_FindInHashTable(properties->props, name, (const void **)&property)) {
+            if (property->type == SDL_PROPERTY_TYPE_STRING) {
+                value = property->value.string_value;
+            } else {
+                SDL_SetError("Property %s isn't a string value", name);
+            }
+        } else {
+            SDL_SetError("Couldn't find property named %s", name);
+        }
+    }
+    SDL_UnlockMutex(properties->lock);
+
+    return value;
+}
+
+Sint64 SDL_GetNumberProperty(SDL_PropertiesID props, const char *name, Sint64 default_value)
+{
+    SDL_Properties *properties = NULL;
+    Sint64 value = default_value;
+
+    if (!props) {
+        SDL_InvalidParamError("props");
+        return value;
+    }
+    if (!name || !*name) {
+        SDL_InvalidParamError("name");
+        return value;
+    }
+
+    SDL_LockRWLockForReading(SDL_properties_lock);
+    SDL_FindInHashTable(SDL_properties, (const void *)(uintptr_t)props, (const void **)&properties);
+    SDL_UnlockRWLock(SDL_properties_lock);
+
+    if (!properties) {
+        SDL_InvalidParamError("props");
+        return value;
+    }
+
+    SDL_LockMutex(properties->lock);
+    {
+        SDL_Property *property = NULL;
+        if (SDL_FindInHashTable(properties->props, name, (const void **)&property)) {
+            if (property->type == SDL_PROPERTY_TYPE_NUMBER) {
+                value = property->value.number_value;
+            } else {
+                SDL_SetError("Property %s isn't a string value", name);
+            }
+        } else {
+            SDL_SetError("Couldn't find property named %s", name);
+        }
+    }
+    SDL_UnlockMutex(properties->lock);
+
+    return value;
+}
+
+float SDL_GetFloatProperty(SDL_PropertiesID props, const char *name, float default_value)
+{
+    SDL_Properties *properties = NULL;
+    float value = default_value;
+
+    if (!props) {
+        SDL_InvalidParamError("props");
+        return value;
+    }
+    if (!name || !*name) {
+        SDL_InvalidParamError("name");
+        return value;
+    }
+
+    SDL_LockRWLockForReading(SDL_properties_lock);
+    SDL_FindInHashTable(SDL_properties, (const void *)(uintptr_t)props, (const void **)&properties);
+    SDL_UnlockRWLock(SDL_properties_lock);
+
+    if (!properties) {
+        SDL_InvalidParamError("props");
+        return value;
+    }
+
+    SDL_LockMutex(properties->lock);
+    {
+        SDL_Property *property = NULL;
+        if (SDL_FindInHashTable(properties->props, name, (const void **)&property)) {
+            if (property->type == SDL_PROPERTY_TYPE_FLOAT) {
+                value = property->value.float_value;
+            } else {
+                SDL_SetError("Property %s isn't a float value", name);
+            }
         } else {
             SDL_SetError("Couldn't find property named %s", name);
         }
@@ -292,7 +547,41 @@ void *SDL_GetProperty(SDL_PropertiesID props, const char *name)
 
 int SDL_ClearProperty(SDL_PropertiesID props, const char *name)
 {
-    return SDL_SetProperty(props, name, NULL);
+    return SDL_PrivateSetProperty(props, name, NULL);
+}
+
+int SDL_EnumerateProperties(SDL_PropertiesID props, SDL_EnumeratePropertiesCallback callback, void *userdata)
+{
+    SDL_Properties *properties = NULL;
+
+    if (!props) {
+        return SDL_InvalidParamError("props");
+    }
+    if (!callback) {
+        return SDL_InvalidParamError("callback");
+    }
+
+    SDL_LockRWLockForReading(SDL_properties_lock);
+    SDL_FindInHashTable(SDL_properties, (const void *)(uintptr_t)props, (const void **)&properties);
+    SDL_UnlockRWLock(SDL_properties_lock);
+
+    if (!properties) {
+        return SDL_InvalidParamError("props");
+    }
+
+    SDL_LockMutex(properties->lock);
+    {
+        void *iter;
+        const void *key, *value;
+
+        iter = NULL;
+        while (SDL_IterateHashTable(properties->props, &key, &value, &iter)) {
+            callback(userdata, props, (const char *)key);
+        }
+    }
+    SDL_UnlockMutex(properties->lock);
+
+    return 0;
 }
 
 void SDL_DestroyProperties(SDL_PropertiesID props)

+ 3 - 3
src/core/linux/SDL_fcitx.c

@@ -428,9 +428,9 @@ void SDL_Fcitx_UpdateTextRect(const SDL_Rect *rect)
 #ifdef SDL_VIDEO_DRIVER_X11
     {
         SDL_PropertiesID props = SDL_GetWindowProperties(focused_win);
-        Display *x_disp = (Display *)SDL_GetProperty(props, "SDL.window.x11.display");
-        int x_screen = (int)(intptr_t)SDL_GetProperty(props, "SDL.window.x11.screen");
-        Window x_win = (Window)SDL_GetProperty(props, "SDL.window.x11.window");
+        Display *x_disp = (Display *)SDL_GetProperty(props, "SDL.window.x11.display", NULL);
+        int x_screen = SDL_GetNumberProperty(props, "SDL.window.x11.screen", 0);
+        Window x_win = SDL_GetNumberProperty(props, "SDL.window.x11.window", 0);
         Window unused;
         if (x_disp && x_win) {
             X11_XTranslateCoordinates(x_disp, x_win, RootWindow(x_disp, x_screen), 0, 0, &x, &y, &unused);

+ 3 - 3
src/core/linux/SDL_ibus.c

@@ -705,9 +705,9 @@ void SDL_IBus_UpdateTextRect(const SDL_Rect *rect)
 #ifdef SDL_VIDEO_DRIVER_X11
     {
         SDL_PropertiesID props = SDL_GetWindowProperties(focused_win);
-        Display *x_disp = (Display *)SDL_GetProperty(props, "SDL.window.x11.display");
-        int x_screen = (int)(intptr_t)SDL_GetProperty(props, "SDL.window.x11.screen");
-        Window x_win = (Window)SDL_GetProperty(props, "SDL.window.x11.window");
+        Display *x_disp = (Display *)SDL_GetProperty(props, "SDL.window.x11.display", NULL);
+        int x_screen = SDL_GetNumberProperty(props, "SDL.window.x11.screen", 0);
+        Window x_win = SDL_GetNumberProperty(props, "SDL.window.x11.window", 0);
         Window unused;
 
         if (x_disp && x_win) {

+ 8 - 0
src/dynapi/SDL_dynapi.sym

@@ -956,6 +956,14 @@ SDL3_0.0.0 {
     SDL_GetPenName;
     SDL_GetPenCapabilities;
     SDL_GetPenType;
+    SDL_SetStringProperty;
+    SDL_SetNumberProperty;
+    SDL_SetFloatProperty;
+    SDL_GetPropertyType;
+    SDL_GetStringProperty;
+    SDL_GetNumberProperty;
+    SDL_GetFloatProperty;
+    SDL_EnumerateProperties;
     # extra symbols go here (don't modify this line)
   local: *;
 };

+ 8 - 0
src/dynapi/SDL_dynapi_overrides.h

@@ -981,3 +981,11 @@
 #define SDL_GetPenName SDL_GetPenName_REAL
 #define SDL_GetPenCapabilities SDL_GetPenCapabilities_REAL
 #define SDL_GetPenType SDL_GetPenType_REAL
+#define SDL_SetStringProperty SDL_SetStringProperty_REAL
+#define SDL_SetNumberProperty SDL_SetNumberProperty_REAL
+#define SDL_SetFloatProperty SDL_SetFloatProperty_REAL
+#define SDL_GetPropertyType SDL_GetPropertyType_REAL
+#define SDL_GetStringProperty SDL_GetStringProperty_REAL
+#define SDL_GetNumberProperty SDL_GetNumberProperty_REAL
+#define SDL_GetFloatProperty SDL_GetFloatProperty_REAL
+#define SDL_EnumerateProperties SDL_EnumerateProperties_REAL

+ 9 - 1
src/dynapi/SDL_dynapi_procs.h

@@ -961,7 +961,7 @@ SDL_DYNAPI_PROC(SDL_PropertiesID,SDL_CreateProperties,(void),(),return)
 SDL_DYNAPI_PROC(int,SDL_LockProperties,(SDL_PropertiesID a),(a),return)
 SDL_DYNAPI_PROC(void,SDL_UnlockProperties,(SDL_PropertiesID a),(a),)
 SDL_DYNAPI_PROC(int,SDL_SetProperty,(SDL_PropertiesID a, const char *b, void *c),(a,b,c),return)
-SDL_DYNAPI_PROC(void*,SDL_GetProperty,(SDL_PropertiesID a, const char *b),(a,b),return)
+SDL_DYNAPI_PROC(void*,SDL_GetProperty,(SDL_PropertiesID a, const char *b, void *c),(a,b,c),return)
 SDL_DYNAPI_PROC(void,SDL_DestroyProperties,(SDL_PropertiesID a),(a),)
 SDL_DYNAPI_PROC(SDL_PropertiesID,SDL_GetAudioStreamProperties,(SDL_AudioStream *a),(a),return)
 SDL_DYNAPI_PROC(SDL_PropertiesID,SDL_GetGamepadProperties,(SDL_Gamepad *a),(a),return)
@@ -1006,3 +1006,11 @@ SDL_DYNAPI_PROC(SDL_bool,SDL_PenConnected,(SDL_PenID a),(a),return)
 SDL_DYNAPI_PROC(const char*,SDL_GetPenName,(SDL_PenID a),(a),return)
 SDL_DYNAPI_PROC(Uint32,SDL_GetPenCapabilities,(SDL_PenID a, SDL_PenCapabilityInfo *b),(a,b),return)
 SDL_DYNAPI_PROC(SDL_PenSubtype,SDL_GetPenType,(SDL_PenID a),(a),return)
+SDL_DYNAPI_PROC(int,SDL_SetStringProperty,(SDL_PropertiesID a, const char *b, const char *c),(a,b,c),return)
+SDL_DYNAPI_PROC(int,SDL_SetNumberProperty,(SDL_PropertiesID a, const char *b, Sint64 c),(a,b,c),return)
+SDL_DYNAPI_PROC(int,SDL_SetFloatProperty,(SDL_PropertiesID a, const char *b, float c),(a,b,c),return)
+SDL_DYNAPI_PROC(SDL_PropertyType,SDL_GetPropertyType,(SDL_PropertiesID a, const char *b),(a,b),return)
+SDL_DYNAPI_PROC(const char*,SDL_GetStringProperty,(SDL_PropertiesID a, const char *b, const char *c),(a,b,c),return)
+SDL_DYNAPI_PROC(Sint64,SDL_GetNumberProperty,(SDL_PropertiesID a, const char *b, Sint64 c),(a,b,c),return)
+SDL_DYNAPI_PROC(float,SDL_GetFloatProperty,(SDL_PropertiesID a, const char *b, float c),(a,b,c),return)
+SDL_DYNAPI_PROC(int,SDL_EnumerateProperties,(SDL_PropertiesID a, SDL_EnumeratePropertiesCallback b, void *c),(a,b,c),return)

+ 1 - 1
src/render/SDL_render.c

@@ -994,7 +994,7 @@ SDL_Renderer *SDL_CreateSoftwareRenderer(SDL_Surface *surface)
 
 SDL_Renderer *SDL_GetRenderer(SDL_Window *window)
 {
-    return (SDL_Renderer *)SDL_GetProperty(SDL_GetWindowProperties(window), SDL_WINDOWRENDERDATA);
+    return (SDL_Renderer *)SDL_GetProperty(SDL_GetWindowProperties(window), SDL_WINDOWRENDERDATA, NULL);
 }
 
 SDL_Window *SDL_GetRenderWindow(SDL_Renderer *renderer)

+ 1 - 1
src/render/direct3d/SDL_render_d3d.c

@@ -1602,7 +1602,7 @@ SDL_Renderer *D3D_CreateRenderer(SDL_Window *window, Uint32 flags)
     }
 
     SDL_zero(pparams);
-    pparams.hDeviceWindow = (HWND)SDL_GetProperty(SDL_GetWindowProperties(window), "SDL.window.win32.hwnd");
+    pparams.hDeviceWindow = (HWND)SDL_GetProperty(SDL_GetWindowProperties(window), "SDL.window.win32.hwnd", NULL);
     pparams.BackBufferWidth = w;
     pparams.BackBufferHeight = h;
     pparams.BackBufferCount = 1;

+ 1 - 1
src/render/direct3d11/SDL_render_d3d11.c

@@ -825,7 +825,7 @@ static HRESULT D3D11_CreateSwapChain(SDL_Renderer *renderer, int w, int h)
 #endif
     } else {
 #if defined(__WIN32__) || defined(__WINGDK__)
-        HWND hwnd = (HWND)SDL_GetProperty(SDL_GetWindowProperties(renderer->window), "SDL.window.win32.hwnd");
+        HWND hwnd = (HWND)SDL_GetProperty(SDL_GetWindowProperties(renderer->window), "SDL.window.win32.hwnd", NULL);
 
         result = IDXGIFactory2_CreateSwapChainForHwnd(data->dxgiFactory,
                                                       (IUnknown *)data->d3dDevice,

+ 1 - 1
src/render/direct3d11/SDL_render_winrt.cpp

@@ -44,7 +44,7 @@ using namespace Windows::Graphics::Display;
 extern "C" void *
 D3D11_GetCoreWindowFromSDLRenderer(SDL_Renderer *renderer)
 {
-    IInspectable *window = (IInspectable *)SDL_GetProperty(SDL_GetWindowProperties(renderer->window), "SDL.window.winrt.window");
+    IInspectable *window = (IInspectable *)SDL_GetProperty(SDL_GetWindowProperties(renderer->window), "SDL.window.winrt.window", NULL);
     ABI::Windows::UI::Core::ICoreWindow *coreWindow = NULL;
     if (!window || FAILED(window->QueryInterface(&coreWindow))) {
         return NULL;

+ 1 - 1
src/render/direct3d12/SDL_render_d3d12.c

@@ -1178,7 +1178,7 @@ static HRESULT D3D12_CreateSwapChain(SDL_Renderer *renderer, int w, int h)
     swapChainDesc.Flags = DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT | /* To support SetMaximumFrameLatency */
                           DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING;                  /* To support presenting with allow tearing on */
 
-    HWND hwnd = (HWND)SDL_GetProperty(SDL_GetWindowProperties(renderer->window), "SDL.window.win32.hwnd");
+    HWND hwnd = (HWND)SDL_GetProperty(SDL_GetWindowProperties(renderer->window), "SDL.window.win32.hwnd", NULL);
 
     result = D3D_CALL(data->dxgiFactory, CreateSwapChainForHwnd,
                       (IUnknown *)data->commandQueue,

+ 6 - 6
src/render/metal/SDL_render_metal.m

@@ -1626,9 +1626,9 @@ static int METAL_SetVSync(SDL_Renderer *renderer, const int vsync)
 static SDL_MetalView GetWindowView(SDL_Window *window)
 {
 #ifdef SDL_VIDEO_DRIVER_COCOA
-    NSWindow *nswindow = (__bridge NSWindow *)SDL_GetProperty(SDL_GetWindowProperties(window), "SDL.window.cocoa.window");
-    NSInteger tag = (NSInteger)SDL_GetProperty(SDL_GetWindowProperties(window), "SDL.window.cocoa.metal_view_tag");
-    if (nswindow) {
+    NSWindow *nswindow = (__bridge NSWindow *)SDL_GetProperty(SDL_GetWindowProperties(window), "SDL.window.cocoa.window", NULL);
+    NSInteger tag = (NSInteger)SDL_GetNumberProperty(SDL_GetWindowProperties(window), "SDL.window.cocoa.metal_view_tag", 0);
+    if (nswindow && tag) {
         NSView *view = nswindow.contentView;
         if (view.subviews.count > 0) {
             view = view.subviews[0];
@@ -1640,9 +1640,9 @@ static SDL_MetalView GetWindowView(SDL_Window *window)
 #endif
 
 #ifdef SDL_VIDEO_DRIVER_UIKIT
-    UIWindow *uiwindow = (__bridge UIWindow *)SDL_GetProperty(SDL_GetWindowProperties(window), "SDL.window.uikit.window");
-    NSInteger tag = (NSInteger)SDL_GetProperty(SDL_GetWindowProperties(window), "SDL.window.uikit.metal_view_tag");
-    if (uiwindow) {
+    UIWindow *uiwindow = (__bridge UIWindow *)SDL_GetProperty(SDL_GetWindowProperties(window), "SDL.window.uikit.window", NULL);
+    NSInteger tag = (NSInteger)SDL_GetNumberProperty(SDL_GetWindowProperties(window), "SDL.window.uikit.metal_view_tag", 0);
+    if (uiwindow && tag) {
         UIView *view = uiwindow.rootViewController.view;
         if (view.tag == tag) {
             return (SDL_MetalView)CFBridgingRetain(view);

+ 5 - 5
src/render/opengl/SDL_render_gl.c

@@ -519,9 +519,9 @@ static int GL_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture)
         data->texh = (GLfloat)texture->h / texture_h;
     }
     SDL_PropertiesID props = SDL_GetTextureProperties(texture);
-    SDL_SetProperty(props, "SDL.texture.opengl.texture", (void *)(uintptr_t)data->texture);
-    SDL_SetProperty(props, "SDL.texture.opengl.tex_w", (void *)(uintptr_t)(Uint32)(data->texw * 65536));
-    SDL_SetProperty(props, "SDL.texture.opengl.tex_h", (void *)(uintptr_t)(Uint32)(data->texh * 65536));
+    SDL_SetNumberProperty(props, "SDL.texture.opengl.texture", data->texture);
+    SDL_SetFloatProperty(props, "SDL.texture.opengl.tex_w", data->texw);
+    SDL_SetFloatProperty(props, "SDL.texture.opengl.tex_h", data->texh);
 
     data->format = format;
     data->formattype = type;
@@ -594,7 +594,7 @@ static int GL_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture)
                                     GL_CLAMP_TO_EDGE);
         renderdata->glTexImage2D(textype, 0, internalFormat, (texture_w + 1) / 2,
                                  (texture_h + 1) / 2, 0, format, type, NULL);
-        SDL_SetProperty(props, "SDL.texture.opengl.texture_u", (void *)(uintptr_t)data->utexture);
+        SDL_SetNumberProperty(props, "SDL.texture.opengl.texture_u", data->utexture);
 
         renderdata->glBindTexture(textype, data->vtexture);
         renderdata->glTexParameteri(textype, GL_TEXTURE_MIN_FILTER,
@@ -607,7 +607,7 @@ static int GL_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture)
                                     GL_CLAMP_TO_EDGE);
         renderdata->glTexImage2D(textype, 0, internalFormat, (texture_w + 1) / 2,
                                  (texture_h + 1) / 2, 0, format, type, NULL);
-        SDL_SetProperty(props, "SDL.texture.opengl.texture_v", (void *)(uintptr_t)data->vtexture);
+        SDL_SetNumberProperty(props, "SDL.texture.opengl.texture_v", data->vtexture);
     }
 
     if (texture->format == SDL_PIXELFORMAT_NV12 ||

+ 4 - 4
src/render/opengles2/SDL_render_gles2.c

@@ -1499,7 +1499,7 @@ static int GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture)
         renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
         renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
         renderdata->glTexImage2D(data->texture_type, 0, format, (texture->w + 1) / 2, (texture->h + 1) / 2, 0, format, type, NULL);
-        SDL_SetProperty(SDL_GetTextureProperties(texture), "SDL.texture.opengles2.texture_v", (void *)(uintptr_t)data->texture_v);
+        SDL_SetNumberProperty(SDL_GetTextureProperties(texture), "SDL.texture.opengles2.texture_v", data->texture_v);
 
         renderdata->glGenTextures(1, &data->texture_u);
         if (GL_CheckError("glGenTexures()", renderer) < 0) {
@@ -1515,7 +1515,7 @@ static int GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture)
         if (GL_CheckError("glTexImage2D()", renderer) < 0) {
             return -1;
         }
-        SDL_SetProperty(SDL_GetTextureProperties(texture), "SDL.texture.opengles2.texture_u", (void *)(uintptr_t)data->texture_u);
+        SDL_SetNumberProperty(SDL_GetTextureProperties(texture), "SDL.texture.opengles2.texture_u", data->texture_u);
 
     } else if (data->nv12) {
         renderdata->glGenTextures(1, &data->texture_u);
@@ -1532,7 +1532,7 @@ static int GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture)
         if (GL_CheckError("glTexImage2D()", renderer) < 0) {
             return -1;
         }
-        SDL_SetProperty(SDL_GetTextureProperties(texture), "SDL.texture.opengles2.texture_uv", (void *)(uintptr_t)data->texture_u);
+        SDL_SetNumberProperty(SDL_GetTextureProperties(texture), "SDL.texture.opengles2.texture_uv", data->texture_u);
     }
 #endif
 
@@ -1553,7 +1553,7 @@ static int GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture)
             return -1;
         }
     }
-    SDL_SetProperty(SDL_GetTextureProperties(texture), "SDL.texture.opengles2.texture", (void *)(uintptr_t)data->texture);
+    SDL_SetNumberProperty(SDL_GetTextureProperties(texture), "SDL.texture.opengles2.texture", data->texture);
 
     if (texture->access == SDL_TEXTUREACCESS_TARGET) {
         data->fbo = GLES2_GetFBO(renderer->driverdata, texture->w, texture->h);

+ 3 - 3
src/video/SDL_video.c

@@ -226,7 +226,7 @@ static int SDL_CreateWindowTexture(SDL_VideoDevice *_this, SDL_Window *window, U
 {
     SDL_RendererInfo info;
     SDL_PropertiesID props = SDL_GetWindowProperties(window);
-    SDL_WindowTextureData *data = (SDL_WindowTextureData *)SDL_GetProperty(props, SDL_WINDOWTEXTUREDATA);
+    SDL_WindowTextureData *data = (SDL_WindowTextureData *)SDL_GetProperty(props, SDL_WINDOWTEXTUREDATA, NULL);
     const SDL_bool transparent = (window->flags & SDL_WINDOW_TRANSPARENT) ? SDL_TRUE : SDL_FALSE;
     int i;
     int w, h;
@@ -349,7 +349,7 @@ static int SDL_UpdateWindowTexture(SDL_VideoDevice *unused, SDL_Window *window,
 
     SDL_GetWindowSizeInPixels(window, &w, &h);
 
-    data = SDL_GetProperty(SDL_GetWindowProperties(window), SDL_WINDOWTEXTUREDATA);
+    data = SDL_GetProperty(SDL_GetWindowProperties(window), SDL_WINDOWTEXTUREDATA, NULL);
     if (!data || !data->texture) {
         return SDL_SetError("No window texture data");
     }
@@ -381,7 +381,7 @@ int SDL_SetWindowTextureVSync(SDL_Window *window, int vsync)
 {
     SDL_WindowTextureData *data;
 
-    data = SDL_GetProperty(SDL_GetWindowProperties(window), SDL_WINDOWTEXTUREDATA);
+    data = SDL_GetProperty(SDL_GetWindowProperties(window), SDL_WINDOWTEXTUREDATA, NULL);
     if (!data) {
         return -1;
     }

+ 1 - 1
src/video/cocoa/SDL_cocoawindow.m

@@ -1864,7 +1864,7 @@ static int SetupWindowData(SDL_VideoDevice *_this, SDL_Window *window, NSWindow
 
         SDL_PropertiesID props = SDL_GetWindowProperties(window);
         SDL_SetProperty(props, "SDL.window.cocoa.window", (__bridge void *)data.nswindow);
-        SDL_SetProperty(props, "SDL.window.cocoa.metal_view_tag", SDL_METALVIEW_TAG);
+        SDL_SetNumberProperty(props, "SDL.window.cocoa.metal_view_tag", SDL_METALVIEW_TAG);
 
         /* All done! */
         window->driverdata = (SDL_WindowData *)CFBridgingRetain(data);

+ 1 - 1
src/video/dummy/SDL_nullframebuffer.c

@@ -60,7 +60,7 @@ int SDL_DUMMY_UpdateWindowFramebuffer(SDL_VideoDevice *_this, SDL_Window *window
     static int frame_number;
     SDL_Surface *surface;
 
-    surface = (SDL_Surface *)SDL_GetProperty(SDL_GetWindowProperties(window), DUMMY_SURFACE);
+    surface = (SDL_Surface *)SDL_GetProperty(SDL_GetWindowProperties(window), DUMMY_SURFACE, NULL);
     if (!surface) {
         return SDL_SetError("Couldn't find dummy surface for window");
     }

+ 2 - 2
src/video/kmsdrm/SDL_kmsdrmvideo.c

@@ -1467,8 +1467,8 @@ int KMSDRM_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window)
     window->driverdata = windata;
 
     SDL_PropertiesID props = SDL_GetWindowProperties(window);
-    SDL_SetProperty(props, "SDL.window.kmsdrm.dev_index", (void *)(intptr_t)viddata->devindex);
-    SDL_SetProperty(props, "SDL.window.kmsdrm.drm_fd", (void *)(intptr_t)viddata->drm_fd);
+    SDL_SetNumberProperty(props, "SDL.window.kmsdrm.dev_index", viddata->devindex);
+    SDL_SetNumberProperty(props, "SDL.window.kmsdrm.drm_fd", viddata->drm_fd);
     SDL_SetProperty(props, "SDL.window.kmsdrm.gbm_dev", viddata->gbm_dev);
 
     if (!is_vulkan && !vulkan_mode) { /* NON-Vulkan block. */

+ 1 - 1
src/video/n3ds/SDL_n3dsframebuffer.c

@@ -72,7 +72,7 @@ int SDL_N3DS_UpdateWindowFramebuffer(SDL_VideoDevice *_this, SDL_Window *window,
     u32 *framebuffer;
     u32 bufsize;
 
-    surface = (SDL_Surface *)SDL_GetProperty(SDL_GetWindowProperties(window), N3DS_SURFACE);
+    surface = (SDL_Surface *)SDL_GetProperty(SDL_GetWindowProperties(window), N3DS_SURFACE, NULL);
     if (!surface) {
         return SDL_SetError("%s: Unable to get the window surface.", __func__);
     }

+ 1 - 1
src/video/offscreen/SDL_offscreenframebuffer.c

@@ -61,7 +61,7 @@ int SDL_OFFSCREEN_UpdateWindowFramebuffer(SDL_VideoDevice *_this, SDL_Window *wi
     static int frame_number;
     SDL_Surface *surface;
 
-    surface = (SDL_Surface *)SDL_GetProperty(SDL_GetWindowProperties(window), OFFSCREEN_SURFACE);
+    surface = (SDL_Surface *)SDL_GetProperty(SDL_GetWindowProperties(window), OFFSCREEN_SURFACE, NULL);
     if (!surface) {
         return SDL_SetError("Couldn't find offscreen surface for window");
     }

+ 1 - 1
src/video/uikit/SDL_uikitwindow.m

@@ -155,7 +155,7 @@ static int SetupWindowData(SDL_VideoDevice *_this, SDL_Window *window, UIWindow
 
     SDL_PropertiesID props = SDL_GetWindowProperties(window);
     SDL_SetProperty(props, "SDL.window.uikit.window", (__bridge void *)data.uiwindow);
-    SDL_SetProperty(props, "SDL.window.uikit.metal_view_tag", SDL_METALVIEW_TAG);
+    SDL_SetNumberProperty(props, "SDL.window.uikit.metal_view_tag", SDL_METALVIEW_TAG);
 
     return 0;
 }

+ 2 - 2
src/video/x11/SDL_x11window.c

@@ -386,8 +386,8 @@ static int SetupWindowData(SDL_VideoDevice *_this, SDL_Window *window, Window w,
     SDL_PropertiesID props = SDL_GetWindowProperties(window);
     int screen = (displaydata ? displaydata->screen : 0);
     SDL_SetProperty(props, "SDL.window.x11.display", data->videodata->display);
-    SDL_SetProperty(props, "SDL.window.x11.screen", (void *)(intptr_t)screen);
-    SDL_SetProperty(props, "SDL.window.x11.window", (void *)(uintptr_t)data->xwindow);
+    SDL_SetNumberProperty(props, "SDL.window.x11.screen", screen);
+    SDL_SetNumberProperty(props, "SDL.window.x11.window", data->xwindow);
 
     return 0;
 }

+ 128 - 6
test/testautomation_properties.c

@@ -11,12 +11,28 @@
 /**
  * Test basic functionality
  */
+static void SDLCALL count_properties(void *userdata, SDL_PropertiesID props, const char *name)
+{
+    int *count = (int *)userdata;
+    ++(*count);
+}
+static void SDLCALL count_foo_properties(void *userdata, SDL_PropertiesID props, const char *name)
+{
+    int *count = (int *)userdata;
+    if (SDL_strcmp(name, "foo") == 0) {
+        ++(*count);
+    }
+}
 static int properties_testBasic(void *arg)
 {
     SDL_PropertiesID props;
     char key[2], expected_value[2];
+    SDL_PropertyType type;
     void *value;
-    int i, result;
+    const char *value_string;
+    Sint64 value_number;
+    float value_float;
+    int i, result, count;
 
     props = SDL_CreateProperties();
     SDLTest_AssertPass("Call to SDL_CreateProperties()");
@@ -30,24 +46,130 @@ static int properties_testBasic(void *arg)
         SDLTest_AssertPass("Call to SDL_SetProperty()");
         SDLTest_AssertCheck(result == 0,
             "Verify property value was set, got: %d", result);
-        value = SDL_GetProperty(props, key);
+        value = SDL_GetProperty(props, key, NULL);
         SDLTest_AssertPass("Call to SDL_GetProperty()");
         SDLTest_AssertCheck(value && SDL_strcmp((const char *)value, expected_value) == 0,
             "Verify property value was set, got %s, expected %s", value ? (const char *)value : "NULL", expected_value);
     }
 
+    count = 0;
+    SDL_EnumerateProperties(props, count_properties, &count);
+    SDLTest_AssertCheck(count == 10,
+            "Verify property count, expected 10, got: %d", count);
+
     for (i = 0; i < 10; ++i) {
         SDL_snprintf(key, SDL_arraysize(key), "%c", 'a' + i);
         result = SDL_SetProperty(props, key, NULL);
         SDLTest_AssertPass("Call to SDL_SetProperty(NULL)");
         SDLTest_AssertCheck(result == 0,
             "Verify property value was set, got: %d", result);
-        value = SDL_GetProperty(props, key);
+        value = SDL_GetProperty(props, key, NULL);
         SDLTest_AssertPass("Call to SDL_GetProperty()");
         SDLTest_AssertCheck(value == NULL,
             "Verify property value was set, got %s, expected NULL", (const char *)value);
     }
 
+    count = 0;
+    SDL_EnumerateProperties(props, count_properties, &count);
+    SDLTest_AssertCheck(count == 0,
+            "Verify property count, expected 0, got: %d", count);
+
+    /* Check default values */
+    value = SDL_GetProperty(props, "foo", (void *)0xabcd);
+    SDLTest_AssertCheck(value == (void *)0xabcd,
+            "Verify property, expected 0xabcd, got: %p", value);
+    value_string = SDL_GetStringProperty(props, "foo", "abcd");
+    SDLTest_AssertCheck(value_string && SDL_strcmp(value_string, "abcd") == 0,
+            "Verify string property, expected \"abcd\", got: %s", value_string);
+    value_number = SDL_GetNumberProperty(props, "foo", 1234);
+    SDLTest_AssertCheck(value_number == 1234,
+            "Verify number property, expected 1234, got: %" SDL_PRIu64 "", value_number);
+    value_float = SDL_GetFloatProperty(props, "foo", 1234.0f);
+    SDLTest_AssertCheck(value_float == 1234.0f,
+            "Verify float property, expected 1234, got: %f", value_float);
+
+    /* Check data value */
+    SDLTest_AssertPass("Call to SDL_SetProperty(\"foo\", 0x01)");
+    SDL_SetProperty(props, "foo", (void *)0x01);
+    type = SDL_GetPropertyType(props, "foo");
+    SDLTest_AssertCheck(type == SDL_PROPERTY_TYPE_POINTER,
+            "Verify property type, expected %d, got: %d", SDL_PROPERTY_TYPE_POINTER, type);
+    value = SDL_GetProperty(props, "foo", NULL);
+    SDLTest_AssertCheck(value == (void *)0x01,
+            "Verify property, expected 0x01, got: %p", value);
+    value_string = SDL_GetStringProperty(props, "foo", NULL);
+    SDLTest_AssertCheck(value_string == NULL,
+            "Verify string property, expected NULL, got: %s", value_string);
+    value_number = SDL_GetNumberProperty(props, "foo", 0);
+    SDLTest_AssertCheck(value_number == 0,
+            "Verify number property, expected 0, got: %" SDL_PRIu64 "", value_number);
+    value_float = SDL_GetFloatProperty(props, "foo", 0.0f);
+    SDLTest_AssertCheck(value_float == 0.0f,
+            "Verify float property, expected 0, got: %f", value_float);
+
+    /* Check string value */
+    SDLTest_AssertPass("Call to SDL_SetStringProperty(\"foo\", \"bar\")");
+    SDL_SetStringProperty(props, "foo", "bar");
+    type = SDL_GetPropertyType(props, "foo");
+    SDLTest_AssertCheck(type == SDL_PROPERTY_TYPE_STRING,
+            "Verify property type, expected %d, got: %d", SDL_PROPERTY_TYPE_STRING, type);
+    value = SDL_GetProperty(props, "foo", NULL);
+    SDLTest_AssertCheck(value == NULL,
+            "Verify property, expected NULL, got: %p", value);
+    value_string = SDL_GetStringProperty(props, "foo", NULL);
+    SDLTest_AssertCheck(value_string != NULL && SDL_strcmp(value_string, "bar") == 0,
+            "Verify string property, expected \"bar\", got: %s", value_string);
+    value_number = SDL_GetNumberProperty(props, "foo", 0);
+    SDLTest_AssertCheck(value_number == 0,
+            "Verify number property, expected 0, got: %" SDL_PRIu64 "", value_number);
+    value_float = SDL_GetFloatProperty(props, "foo", 0.0f);
+    SDLTest_AssertCheck(value_float == 0.0f,
+            "Verify float property, expected 0, got: %f", value_float);
+
+    /* Check number value */
+    SDLTest_AssertPass("Call to SDL_SetNumberProperty(\"foo\", 1)");
+    SDL_SetNumberProperty(props, "foo", 1);
+    type = SDL_GetPropertyType(props, "foo");
+    SDLTest_AssertCheck(type == SDL_PROPERTY_TYPE_NUMBER,
+            "Verify property type, expected %d, got: %d", SDL_PROPERTY_TYPE_NUMBER, type);
+    value = SDL_GetProperty(props, "foo", NULL);
+    SDLTest_AssertCheck(value == NULL,
+            "Verify property, expected NULL, got: %p", value);
+    value_string = SDL_GetStringProperty(props, "foo", NULL);
+    SDLTest_AssertCheck(value_string == NULL,
+            "Verify string property, expected NULL, got: %s", value_string);
+    value_number = SDL_GetNumberProperty(props, "foo", 0);
+    SDLTest_AssertCheck(value_number == 1,
+            "Verify number property, expected 1, got: %" SDL_PRIu64 "", value_number);
+    value_float = SDL_GetFloatProperty(props, "foo", 0.0f);
+    SDLTest_AssertCheck(value_float == 0.0f,
+            "Verify float property, expected 0, got: %f", value_float);
+
+    /* Check float value */
+    SDLTest_AssertPass("Call to SDL_SetNumberProperty(\"foo\", 1)");
+    SDL_SetFloatProperty(props, "foo", 1.0f);
+    type = SDL_GetPropertyType(props, "foo");
+    SDLTest_AssertCheck(type == SDL_PROPERTY_TYPE_FLOAT,
+            "Verify property type, expected %d, got: %d", SDL_PROPERTY_TYPE_FLOAT, type);
+    value = SDL_GetProperty(props, "foo", NULL);
+    SDLTest_AssertCheck(value == NULL,
+            "Verify property, expected NULL, got: %p", value);
+    value_string = SDL_GetStringProperty(props, "foo", NULL);
+    SDLTest_AssertCheck(value_string == NULL,
+            "Verify string property, expected NULL, got: %s", value_string);
+    value_number = SDL_GetNumberProperty(props, "foo", 0);
+    SDLTest_AssertCheck(value_number == 0,
+            "Verify number property, expected 0, got: %" SDL_PRIu64 "", value_number);
+    value_float = SDL_GetFloatProperty(props, "foo", 0.0f);
+    SDLTest_AssertCheck(value_float == 1.0f,
+            "Verify string property, expected 1, got: %f", value_float);
+
+    /* Make sure we have exactly one property named foo */
+    count = 0;
+    SDL_EnumerateProperties(props, count_foo_properties, &count);
+    SDLTest_AssertCheck(count == 1,
+            "Verify foo property count, expected 1, got: %d", count);
+
     SDL_DestroyProperties(props);
 
     return TEST_COMPLETED;
@@ -130,7 +252,7 @@ static int properties_testLocking(void *arg)
         {
             SDL_Delay(10);
             SDL_LockProperties(data.props);
-            value = SDL_GetProperty(data.props, "a");
+            value = SDL_GetProperty(data.props, "a", NULL);
             SDL_UnlockProperties(data.props);
 
             if (!value || SDL_strcmp((const char *)value, "thread_loop") == 0) {
@@ -144,7 +266,7 @@ static int properties_testLocking(void *arg)
         SDL_LockProperties(data.props);
         SDL_SetProperty(data.props, "a", "main");
         SDL_Delay(100);
-        value = SDL_GetProperty(data.props, "a");
+        value = SDL_GetProperty(data.props, "a", NULL);
         SDLTest_AssertCheck(value && SDL_strcmp((const char *)value, "main") == 0,
             "After 100ms sleep, property is %s, expected 'main'", value ? (const char *)value : "NULL");
         SDL_UnlockProperties(data.props);
@@ -152,7 +274,7 @@ static int properties_testLocking(void *arg)
         data.done = SDL_TRUE;
         SDL_WaitThread(thread, NULL);
 
-        value = SDL_GetProperty(data.props, "a");
+        value = SDL_GetProperty(data.props, "a", NULL);
         SDLTest_AssertCheck(value && SDL_strcmp((const char *)value, "thread_done") == 0,
             "After thread complete, property is %s, expected 'thread_done'", value ? (const char *)value : "NULL");
     }

+ 9 - 10
test/testautomation_video.c

@@ -1492,7 +1492,7 @@ static int video_getSetWindowData(void *arg)
     }
 
     /* Get non-existent data */
-    result = (char *)SDL_GetProperty(SDL_GetWindowProperties(window), name);
+    result = (char *)SDL_GetProperty(SDL_GetWindowProperties(window), name, NULL);
     SDLTest_AssertPass("Call to SDL_GetWindowData(..,%s)", name);
     SDLTest_AssertCheck(result == NULL, "Validate that result is NULL");
     SDLTest_AssertCheck(SDL_strcmp(referenceName, name) == 0, "Validate that name was not changed, expected: %s, got: %s", referenceName, name);
@@ -1505,8 +1505,7 @@ static int video_getSetWindowData(void *arg)
 
     /* Get data (twice) */
     for (iteration = 1; iteration <= 2; iteration++) {
-        result = (char *)SDL_GetProperty(SDL_GetWindowProperties(window),
-                                          name);
+        result = (char *)SDL_GetProperty(SDL_GetWindowProperties(window), name, NULL);
         SDLTest_AssertPass("Call to SDL_GetWindowData(..,%s) [iteration %d]", name, iteration);
         SDLTest_AssertCheck(SDL_strcmp(referenceUserdata, result) == 0, "Validate that correct result was returned; expected: %s, got: %s", referenceUserdata, result);
         SDLTest_AssertCheck(SDL_strcmp(referenceName, name) == 0, "Validate that name was not changed, expected: %s, got: %s", referenceName, name);
@@ -1521,7 +1520,7 @@ static int video_getSetWindowData(void *arg)
     }
 
     /* Get data again */
-    result = (char *)SDL_GetProperty(SDL_GetWindowProperties(window), name);
+    result = (char *)SDL_GetProperty(SDL_GetWindowProperties(window), name, NULL);
     SDLTest_AssertPass("Call to SDL_GetWindowData(..,%s) [again]", name);
     SDLTest_AssertCheck(SDL_strcmp(referenceUserdata, result) == 0, "Validate that correct result was returned; expected: %s, got: %s", referenceUserdata, result);
     SDLTest_AssertCheck(SDL_strcmp(referenceName, name) == 0, "Validate that name was not changed, expected: %s, got: %s", referenceName, name);
@@ -1541,7 +1540,7 @@ static int video_getSetWindowData(void *arg)
     SDLTest_AssertCheck(SDL_strcmp(referenceUserdata2, userdata2) == 0, "Validate that userdata2 was not changed, expected: %s, got: %s", referenceUserdata2, userdata2);
 
     /* Get new data */
-    result = (char *)SDL_GetProperty(SDL_GetWindowProperties(window), name);
+    result = (char *)SDL_GetProperty(SDL_GetWindowProperties(window), name, NULL);
     SDLTest_AssertPass("Call to SDL_GetWindowData(..,%s)", name);
     SDLTest_AssertCheck(SDL_strcmp(referenceUserdata2, result) == 0, "Validate that correct result was returned; expected: %s, got: %s", referenceUserdata2, result);
     SDLTest_AssertCheck(SDL_strcmp(referenceName, name) == 0, "Validate that name was not changed, expected: %s, got: %s", referenceName, name);
@@ -1561,13 +1560,13 @@ static int video_getSetWindowData(void *arg)
     SDLTest_AssertCheck(SDL_strcmp(referenceUserdata2, userdata2) == 0, "Validate that userdata2 was not changed, expected: %s, got: %s", referenceUserdata2, userdata2);
 
     /* Get non-existent data */
-    result = (char *)SDL_GetProperty(SDL_GetWindowProperties(window), name);
+    result = (char *)SDL_GetProperty(SDL_GetWindowProperties(window), name, NULL);
     SDLTest_AssertPass("Call to SDL_GetWindowData(..,%s)", name);
     SDLTest_AssertCheck(result == NULL, "Validate that result is NULL");
     SDLTest_AssertCheck(SDL_strcmp(referenceName, name) == 0, "Validate that name was not changed, expected: %s, got: %s", referenceName, name);
 
     /* Get non-existent data new name */
-    result = (char *)SDL_GetProperty(SDL_GetWindowProperties(window), name2);
+    result = (char *)SDL_GetProperty(SDL_GetWindowProperties(window), name2, NULL);
     SDLTest_AssertPass("Call to SDL_GetWindowData(..,%s)", name2);
     SDLTest_AssertCheck(result == NULL, "Validate that result is NULL");
     SDLTest_AssertCheck(SDL_strcmp(referenceName2, name2) == 0, "Validate that name2 was not changed, expected: %s, got: %s", referenceName2, name2);
@@ -1579,7 +1578,7 @@ static int video_getSetWindowData(void *arg)
     SDLTest_AssertCheck(SDL_strcmp(referenceUserdata, userdata) == 0, "Validate that userdata was not changed, expected: %s, got: %s", referenceUserdata, userdata);
 
     /* Get data (again) */
-    result = (char *)SDL_GetProperty(SDL_GetWindowProperties(window), name);
+    result = (char *)SDL_GetProperty(SDL_GetWindowProperties(window), name, NULL);
     SDLTest_AssertPass("Call to SDL_GetWindowData(..,%s) [again, after clear]", name);
     SDLTest_AssertCheck(SDL_strcmp(referenceUserdata, result) == 0, "Validate that correct result was returned; expected: %s, got: %s", referenceUserdata, result);
     SDLTest_AssertCheck(SDL_strcmp(referenceName, name) == 0, "Validate that name was not changed, expected: %s, got: %s", referenceName, name);
@@ -1605,13 +1604,13 @@ static int video_getSetWindowData(void *arg)
     checkInvalidParameterError();
 
     /* Get data with NULL name */
-    result = (char *)SDL_GetProperty(SDL_GetWindowProperties(window), NULL);
+    result = (char *)SDL_GetProperty(SDL_GetWindowProperties(window), NULL, NULL);
     SDLTest_AssertPass("Call to SDL_GetWindowData(name=NULL)");
     SDLTest_AssertCheck(result == NULL, "Validate that result is NULL");
     checkInvalidParameterError();
 
     /* Get data with empty name */
-    result = (char *)SDL_GetProperty(SDL_GetWindowProperties(window), "");
+    result = (char *)SDL_GetProperty(SDL_GetWindowProperties(window), "", NULL);
     SDLTest_AssertPass("Call to SDL_GetWindowData(name='')");
     SDLTest_AssertCheck(result == NULL, "Validate that result is NULL");
     checkInvalidParameterError();

+ 3 - 3
test/testffmpeg.c

@@ -145,7 +145,7 @@ static SDL_bool CreateWindowAndRenderer(Uint32 window_flags, const char *driver)
 #endif
 
 #ifdef __WIN32__
-    d3d11_device = (ID3D11Device *)SDL_GetProperty(SDL_GetRendererProperties(renderer), "SDL.renderer.d3d11.device");
+    d3d11_device = (ID3D11Device *)SDL_GetProperty(SDL_GetRendererProperties(renderer), "SDL.renderer.d3d11.device", NULL);
     if (d3d11_device) {
         ID3D11Device_AddRef(d3d11_device);
         ID3D11Device_GetImmediateContext(d3d11_device, &d3d11_context);
@@ -457,7 +457,7 @@ static SDL_bool GetTextureForMemoryFrame(AVFrame *frame, SDL_Texture **texture)
     case SDL_PIXELFORMAT_UNKNOWN:
     {
         SDL_PropertiesID props = SDL_GetTextureProperties(*texture);
-        struct SwsContextContainer *sws_container = (struct SwsContextContainer *)SDL_GetProperty(props, SWS_CONTEXT_CONTAINER_PROPERTY);
+        struct SwsContextContainer *sws_container = (struct SwsContextContainer *)SDL_GetProperty(props, SWS_CONTEXT_CONTAINER_PROPERTY, NULL);
         if (!sws_container) {
             sws_container = (struct SwsContextContainer *)SDL_calloc(1, sizeof(*sws_container));
             if (!sws_container) {
@@ -625,7 +625,7 @@ static SDL_bool GetTextureForD3D11Frame(AVFrame *frame, SDL_Texture **texture)
         }
     }
 
-    ID3D11Resource *dx11_resource = SDL_GetProperty(SDL_GetTextureProperties(*texture), "SDL.texture.d3d11.texture");
+    ID3D11Resource *dx11_resource = SDL_GetProperty(SDL_GetTextureProperties(*texture), "SDL.texture.d3d11.texture", NULL);
     if (!dx11_resource) {
         SDL_SetError("Couldn't get texture ID3D11Resource interface");
         return SDL_FALSE;