diff --git a/src/core/winrt/SDL_winrtapp_direct3d.cpp b/src/core/winrt/SDL_winrtapp_direct3d.cpp index cd9118f2e4..b251ccb9dc 100644 --- a/src/core/winrt/SDL_winrtapp_direct3d.cpp +++ b/src/core/winrt/SDL_winrtapp_direct3d.cpp @@ -20,6 +20,8 @@ */ #include "../../SDL_internal.h" +/* Standard C++11 includes: */ +#include /* Windows includes */ #include "ppltasks.h" using namespace concurrency; @@ -84,6 +86,57 @@ SDL_WinRTApp ^ SDL_WinRTGlobalApp = nullptr; // Protocol activation URI storage static Platform::String^ WINRT_ProtocolActivationURI = nullptr; +// Store launchOnExit URI separately since WINRT_ProtocolActivationURI gets cleared +static std::wstring WINRT_LaunchOnExitURI; + +// Helper function to extract and store launchOnExit from protocol URI +static void WINRT_ExtractLaunchOnExitURI(Platform::String^ fullUri) +{ + if (fullUri == nullptr) + return; + + std::wstring uri(fullUri->Data()); + + // Look for launchOnExit parameter in the URI + size_t launchPos = uri.find(L"launchOnExit="); + if (launchPos == std::wstring::npos) + return; + + // Extract the launchOnExit URI value + launchPos += 13; // Skip past "launchOnExit=" + size_t endPos = uri.find(L'&', launchPos); + if (endPos == std::wstring::npos) + endPos = uri.length(); + + std::wstring launchUri = uri.substr(launchPos, endPos - launchPos); + + // URL decode the URI (convert %3A to :, etc.) + WINRT_LaunchOnExitURI.clear(); + for (size_t i = 0; i < launchUri.length(); i++) { + if (launchUri[i] == L'%' && i + 2 < launchUri.length()) { + wchar_t hex[3] = { launchUri[i + 1], launchUri[i + 2], 0 }; + WINRT_LaunchOnExitURI += (wchar_t)wcstol(hex, nullptr, 16); + i += 2; + } else { + WINRT_LaunchOnExitURI += launchUri[i]; + } + } +} + +// Helper function to launch URI on exit if protocol activation included launchOnExit parameter +static void WINRT_LaunchExitUriIfSet() +{ + if (!WINRT_LaunchOnExitURI.empty()) { + try { + // Launch the URI + auto uri = ref new Windows::Foundation::Uri(ref new Platform::String(WINRT_LaunchOnExitURI.c_str())); + Windows::System::Launcher::LaunchUriAsync(uri); + } catch (...) { + // Silently ignore errors during termination + } + } +} + ref class SDLApplicationSource sealed : Windows::ApplicationModel::Core::IFrameworkViewSource { public: @@ -184,6 +237,12 @@ SDL_WinRTApp::SDL_WinRTApp() : m_windowClosed(false), { } +SDL_WinRTApp::~SDL_WinRTApp() +{ + // Launch exit URI if set (handles protocol activation returning to caller) + WINRT_LaunchExitUriIfSet(); +} + void SDL_WinRTApp::Initialize(CoreApplicationView ^ applicationView) { applicationView->Activated += @@ -605,6 +664,7 @@ void SDL_WinRTApp::OnWindowClosed(CoreWindow ^ sender, CoreWindowEventArgs ^ arg SDL_Log("%s\n", __FUNCTION__); #endif m_windowClosed = true; + WINRT_LaunchExitUriIfSet(); } void SDL_WinRTApp::OnAppActivated(CoreApplicationView ^ applicationView, IActivatedEventArgs ^ args) @@ -615,6 +675,8 @@ void SDL_WinRTApp::OnAppActivated(CoreApplicationView ^ applicationView, IActiva if (protocolArgs && protocolArgs->Uri) { WINRT_ProtocolActivationURI = protocolArgs->Uri->AbsoluteUri; + // Extract and store launchOnExit URI before main URI gets cleared + WINRT_ExtractLaunchOnExitURI(WINRT_ProtocolActivationURI); } } CoreWindow::GetForCurrentThread()->Activate(); @@ -622,6 +684,9 @@ void SDL_WinRTApp::OnAppActivated(CoreApplicationView ^ applicationView, IActiva void SDL_WinRTApp::OnSuspending(Platform::Object ^ sender, SuspendingEventArgs ^ args) { + // Launch exit URI if set before suspending + WINRT_LaunchExitUriIfSet(); + // Save app state asynchronously after requesting a deferral. Holding a deferral // indicates that the application is busy performing suspending operations. Be // aware that a deferral may not be held indefinitely. After about five seconds, @@ -675,6 +740,7 @@ void SDL_WinRTApp::OnResuming(Platform::Object ^ sender, Platform::Object ^ args void SDL_WinRTApp::OnExiting(Platform::Object ^ sender, Platform::Object ^ args) { SDL_SendAppEvent(SDL_APP_TERMINATING); + WINRT_LaunchExitUriIfSet(); } static void WINRT_LogPointerEvent(const char *header, Windows::UI::Core::PointerEventArgs ^ args, Windows::Foundation::Point transformedPoint) diff --git a/src/core/winrt/SDL_winrtapp_direct3d.h b/src/core/winrt/SDL_winrtapp_direct3d.h index c4bfd1d461..9d2eb76870 100644 --- a/src/core/winrt/SDL_winrtapp_direct3d.h +++ b/src/core/winrt/SDL_winrtapp_direct3d.h @@ -26,6 +26,7 @@ ref class SDL_WinRTApp sealed : public Windows::ApplicationModel::Core::IFramewo { public: SDL_WinRTApp(); + virtual ~SDL_WinRTApp(); // IFrameworkView Methods. virtual void Initialize(Windows::ApplicationModel::Core::CoreApplicationView ^ applicationView);