2
0
Эх сурвалжийг харах

Sdl2 Add support for launchOnExit URI for WinRT

Implements extraction and launching of a 'launchOnExit' URI parameter from protocol activation in SDL_WinRTApp. The URI is stored and launched on app exit, suspension, or window close, enabling return-to-caller scenarios for protocol-activated apps.
danprice142 1 өдөр өмнө
parent
commit
639c7a1e52

+ 66 - 0
src/core/winrt/SDL_winrtapp_direct3d.cpp

@@ -20,6 +20,8 @@
 */
 */
 #include "../../SDL_internal.h"
 #include "../../SDL_internal.h"
 
 
+/* Standard C++11 includes: */
+#include <string>
 /* Windows includes */
 /* Windows includes */
 #include "ppltasks.h"
 #include "ppltasks.h"
 using namespace concurrency;
 using namespace concurrency;
@@ -84,6 +86,57 @@ SDL_WinRTApp ^ SDL_WinRTGlobalApp = nullptr;
 // Protocol activation URI storage
 // Protocol activation URI storage
 static Platform::String^ WINRT_ProtocolActivationURI = nullptr;
 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
 ref class SDLApplicationSource sealed : Windows::ApplicationModel::Core::IFrameworkViewSource
 {
 {
   public:
   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)
 void SDL_WinRTApp::Initialize(CoreApplicationView ^ applicationView)
 {
 {
     applicationView->Activated +=
     applicationView->Activated +=
@@ -605,6 +664,7 @@ void SDL_WinRTApp::OnWindowClosed(CoreWindow ^ sender, CoreWindowEventArgs ^ arg
     SDL_Log("%s\n", __FUNCTION__);
     SDL_Log("%s\n", __FUNCTION__);
 #endif
 #endif
     m_windowClosed = true;
     m_windowClosed = true;
+    WINRT_LaunchExitUriIfSet();
 }
 }
 
 
 void SDL_WinRTApp::OnAppActivated(CoreApplicationView ^ applicationView, IActivatedEventArgs ^ args)
 void SDL_WinRTApp::OnAppActivated(CoreApplicationView ^ applicationView, IActivatedEventArgs ^ args)
@@ -615,6 +675,8 @@ void SDL_WinRTApp::OnAppActivated(CoreApplicationView ^ applicationView, IActiva
         if (protocolArgs && protocolArgs->Uri)
         if (protocolArgs && protocolArgs->Uri)
         {
         {
             WINRT_ProtocolActivationURI = protocolArgs->Uri->AbsoluteUri;
             WINRT_ProtocolActivationURI = protocolArgs->Uri->AbsoluteUri;
+            // Extract and store launchOnExit URI before main URI gets cleared
+            WINRT_ExtractLaunchOnExitURI(WINRT_ProtocolActivationURI);
         }
         }
     }
     }
     CoreWindow::GetForCurrentThread()->Activate();
     CoreWindow::GetForCurrentThread()->Activate();
@@ -622,6 +684,9 @@ void SDL_WinRTApp::OnAppActivated(CoreApplicationView ^ applicationView, IActiva
 
 
 void SDL_WinRTApp::OnSuspending(Platform::Object ^ sender, SuspendingEventArgs ^ args)
 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
     // Save app state asynchronously after requesting a deferral. Holding a deferral
     // indicates that the application is busy performing suspending operations. Be
     // indicates that the application is busy performing suspending operations. Be
     // aware that a deferral may not be held indefinitely. After about five seconds,
     // 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)
 void SDL_WinRTApp::OnExiting(Platform::Object ^ sender, Platform::Object ^ args)
 {
 {
     SDL_SendAppEvent(SDL_APP_TERMINATING);
     SDL_SendAppEvent(SDL_APP_TERMINATING);
+    WINRT_LaunchExitUriIfSet();
 }
 }
 
 
 static void WINRT_LogPointerEvent(const char *header, Windows::UI::Core::PointerEventArgs ^ args, Windows::Foundation::Point transformedPoint)
 static void WINRT_LogPointerEvent(const char *header, Windows::UI::Core::PointerEventArgs ^ args, Windows::Foundation::Point transformedPoint)

+ 1 - 0
src/core/winrt/SDL_winrtapp_direct3d.h

@@ -26,6 +26,7 @@ ref class SDL_WinRTApp sealed : public Windows::ApplicationModel::Core::IFramewo
 {
 {
   public:
   public:
     SDL_WinRTApp();
     SDL_WinRTApp();
+    virtual ~SDL_WinRTApp();
 
 
     // IFrameworkView Methods.
     // IFrameworkView Methods.
     virtual void Initialize(Windows::ApplicationModel::Core::CoreApplicationView ^ applicationView);
     virtual void Initialize(Windows::ApplicationModel::Core::CoreApplicationView ^ applicationView);