From 3e1cebed3c1e3e4529b0305bd65cc52bed4033da Mon Sep 17 00:00:00 2001
From: danprice142 <[EMAIL REDACTED]>
Date: Fri, 24 Oct 2025 18:34:44 +0100
Subject: [PATCH] Add protocol activation URI support for WinRT (#14309)
---
include/SDL_system.h | 16 ++++++++++++++
src/core/winrt/SDL_winrtapp_direct3d.cpp | 28 ++++++++++++++++++++++++
2 files changed, 44 insertions(+)
diff --git a/include/SDL_system.h b/include/SDL_system.h
index 7d11a5bf50253..fb0135a84a282 100644
--- a/include/SDL_system.h
+++ b/include/SDL_system.h
@@ -572,6 +572,22 @@ extern DECLSPEC const char * SDLCALL SDL_WinRTGetFSPathUTF8(SDL_WinRT_Path pathT
*/
extern DECLSPEC SDL_WinRT_DeviceFamily SDLCALL SDL_WinRTGetDeviceFamily();
+/**
+ * Get the protocol activation URI if the app was launched via protocol activation.
+ *
+ * When a UWP/WinRT app is launched via a custom URI scheme (e.g., myapp://action?param=value),
+ * this function retrieves the full activation URI string.
+ *
+ * The URI is only available once per activation - after the first successful call,
+ * subsequent calls will return NULL. This ensures the URI is processed only once.
+ *
+ * \returns the protocol activation URI as a UTF-8 string that must be freed with SDL_free(),
+ * or NULL if the app was not activated via protocol or the URI was already retrieved.
+ *
+ * \since This function is available since SDL 2.33.0.
+ */
+extern DECLSPEC char * SDLCALL SDL_WinRTGetProtocolActivationURI(void);
+
#endif /* __WINRT__ */
/**
diff --git a/src/core/winrt/SDL_winrtapp_direct3d.cpp b/src/core/winrt/SDL_winrtapp_direct3d.cpp
index 04c655dda94f7..cd9118f2e4241 100644
--- a/src/core/winrt/SDL_winrtapp_direct3d.cpp
+++ b/src/core/winrt/SDL_winrtapp_direct3d.cpp
@@ -43,6 +43,7 @@ extern "C" {
#include "SDL_hints.h"
#include "SDL_main.h"
#include "SDL_stdinc.h"
+#include "SDL_system.h"
#include "SDL_render.h"
#include "../../video/SDL_sysvideo.h"
#include "../../events/SDL_events_c.h"
@@ -80,6 +81,9 @@ extern "C" void D3D11_Trim(SDL_Renderer *);
// SDL_CreateWindow().
SDL_WinRTApp ^ SDL_WinRTGlobalApp = nullptr;
+// Protocol activation URI storage
+static Platform::String^ WINRT_ProtocolActivationURI = nullptr;
+
ref class SDLApplicationSource sealed : Windows::ApplicationModel::Core::IFrameworkViewSource
{
public:
@@ -107,6 +111,22 @@ int SDL_WinRTInitNonXAMLApp(int (*mainFunction)(int, char **))
return 0;
}
+extern "C" char* SDL_WinRTGetProtocolActivationURI(void)
+{
+ if (WINRT_ProtocolActivationURI == nullptr)
+ return nullptr;
+ Platform::String^ uriStr = WINRT_ProtocolActivationURI;
+ const wchar_t* uriWide = uriStr->Data();
+ int uriLen = WideCharToMultiByte(CP_UTF8, 0, uriWide, -1, nullptr, 0, nullptr, nullptr);
+ char* uriUtf8 = (char*)SDL_malloc(uriLen);
+ if (uriUtf8)
+ WideCharToMultiByte(CP_UTF8, 0, uriWide, -1, uriUtf8, uriLen, nullptr, nullptr);
+
+ // Clear after first successful read (only return it once)
+ WINRT_ProtocolActivationURI = nullptr;
+ return uriUtf8;
+}
+
static void WINRT_ProcessWindowSizeChange() // TODO: Pass an SDL_Window-identifying thing into WINRT_ProcessWindowSizeChange()
{
CoreWindow ^ coreWindow = CoreWindow::GetForCurrentThread();
@@ -589,6 +609,14 @@ void SDL_WinRTApp::OnWindowClosed(CoreWindow ^ sender, CoreWindowEventArgs ^ arg
void SDL_WinRTApp::OnAppActivated(CoreApplicationView ^ applicationView, IActivatedEventArgs ^ args)
{
+ if (args->Kind == Windows::ApplicationModel::Activation::ActivationKind::Protocol)
+ {
+ auto protocolArgs = dynamic_cast<Windows::ApplicationModel::Activation::ProtocolActivatedEventArgs^>(args);
+ if (protocolArgs && protocolArgs->Uri)
+ {
+ WINRT_ProtocolActivationURI = protocolArgs->Uri->AbsoluteUri;
+ }
+ }
CoreWindow::GetForCurrentThread()->Activate();
}