From 57582498ba33a46b76edba9cc06ae59f368b3379 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jaakko=20Kera=CC=88nen?= jaakko.keranen@iki.fi
Date: Thu, 27 Apr 2023 21:45:56 +0300
Subject: [PATCH 1/1] iOS: Fixed opening URLs via external apps when app is not
running
The URL is launchOptions was never checked by anyone.
sdl2.26-macos-ios.diff | 226 +++++++++++++++++++++++++++++++++++++++++
src/app.c | 10 +-
src/ios.m | 28 ++++-
3 files changed, 260 insertions(+), 4 deletions(-)
create mode 100644 sdl2.26-macos-ios.diff
diff --git a/sdl2.26-macos-ios.diff b/sdl2.26-macos-ios.diff
new file mode 100644
index 00000000..3adcf1c2
--- /dev/null
+++ b/sdl2.26-macos-ios.diff
@@ -0,0 +1,226 @@
+diff --git a/src/events/SDL_mouse.c b/src/events/SDL_mouse.c
+index 994b6a6db..b332e1332 100644
+--- a/src/events/SDL_mouse.c
++++ b/src/events/SDL_mouse.c
+@@ -887,8 +887,8 @@ SDL_SendMouseWheel(SDL_Window * window, SDL_MouseID mouseID, float x, float y, S
event.type = SDL_MOUSEWHEEL;
event.wheel.windowID = mouse->focus ? mouse->focus->id : 0;
event.wheel.which = mouseID;
+- event.wheel.x = integral_x;
+- event.wheel.y = integral_y;
++ event.wheel.x = x; //integral_x;
++ event.wheel.y = y; //integral_y;
event.wheel.preciseX = x;
event.wheel.preciseY = y;
event.wheel.direction = (Uint32)direction;
+diff --git a/src/video/android/SDL_androidevents.c b/src/video/android/SDL_androidevents.c
+index 3424a8254..08ae827dc 100644
+--- a/src/video/android/SDL_androidevents.c
++++ b/src/video/android/SDL_androidevents.c
+@@ -176,10 +176,12 @@ Android_PumpEvents_Blocking(_THIS)
}
}
++ /* Doesn't actually seem to work ??
if ( aaudio_DetectBrokenPlayState() ) {
aaudio_PauseDevices();
aaudio_ResumeDevices();
}
++ */
+diff --git a/src/video/cocoa/SDL_cocoamouse.m b/src/video/cocoa/SDL_cocoamouse.m
+index da5ffac69..49ab6fe14 100644
+--- a/src/video/cocoa/SDL_cocoamouse.m
++++ b/src/video/cocoa/SDL_cocoamouse.m
+@@ -519,11 +519,22 @@ + (NSCursor *)invisibleCursor
return;
}
++ SDL_MouseID mouseID = mouse->mouseID;
++ CGFloat x = -[event scrollingDeltaX];
++ CGFloat y = [event scrollingDeltaY];
++ SDL_MouseWheelDirection direction = SDL_MOUSEWHEEL_NORMAL;
++
mouseID = mouse->mouseID;
x = -[event deltaX];
y = [event deltaY];
direction = SDL_MOUSEWHEEL_NORMAL;
++ /* HACK: Make a distinction between precise and imprecise scrolling.
++ Trackpad seems to be mouseID 0. */
++ if (![event hasPreciseScrollingDeltas]) {
++ mouseID = 1;
++ }
++
if ([event isDirectionInvertedFromDevice] == YES) {
direction = SDL_MOUSEWHEEL_FLIPPED;
}
+diff --git a/src/video/cocoa/SDL_cocoawindow.h b/src/video/cocoa/SDL_cocoawindow.h
+index 18f7d8587..1329a90ab 100644
+--- a/src/video/cocoa/SDL_cocoawindow.h
++++ b/src/video/cocoa/SDL_cocoawindow.h
+@@ -115,6 +115,8 @@ typedef enum
++-(void) syncMouseButtonAndKeyboardModifierState;
++
+diff --git a/src/video/cocoa/SDL_cocoawindow.m b/src/video/cocoa/SDL_cocoawindow.m
+index c73827656..786f288a2 100644
+--- a/src/video/cocoa/SDL_cocoawindow.m
++++ b/src/video/cocoa/SDL_cocoawindow.m
+@@ -1273,6 +1273,25 @@ - (void)otherMouseDown:(NSEvent *)theEvent
[self mouseDown:theEvent];
++- (void)syncMouseButtonAndKeyboardModifierState {
++ SDL_Mouse *mouse = SDL_GetMouse();
++ if (mouse) {
++ for (int i = 0; i < mouse->num_sources; i++) {
++ if (mouse->sources[i].mouseID == mouse->mouseID) {
++ mouse->sources[i].buttonstate = 0;
++ }
++ }
++ }
++ SDL_SendKeyboardKey(SDL_RELEASED, SDL_SCANCODE_LGUI);
++ SDL_SendKeyboardKey(SDL_RELEASED, SDL_SCANCODE_RGUI);
++ SDL_SendKeyboardKey(SDL_RELEASED, SDL_SCANCODE_LSHIFT);
++ SDL_SendKeyboardKey(SDL_RELEASED, SDL_SCANCODE_RSHIFT);
++ SDL_SendKeyboardKey(SDL_RELEASED, SDL_SCANCODE_LCTRL);
++ SDL_SendKeyboardKey(SDL_RELEASED, SDL_SCANCODE_RCTRL);
++ SDL_SendKeyboardKey(SDL_RELEASED, SDL_SCANCODE_LALT);
++ SDL_SendKeyboardKey(SDL_RELEASED, SDL_SCANCODE_RALT);
++}
++
SDL_Mouse *mouse = SDL_GetMouse();
+diff --git a/src/video/uikit/SDL_uikitappdelegate.h b/src/video/uikit/SDL_uikitappdelegate.h
+index ee2b5b6a8..8a7f81f62 100644
+--- a/src/video/uikit/SDL_uikitappdelegate.h
++++ b/src/video/uikit/SDL_uikitappdelegate.h
+@@ -34,6 +34,7 @@
++- (NSString *)getLaunchOptionsURL;
+diff --git a/src/video/uikit/SDL_uikitappdelegate.m b/src/video/uikit/SDL_uikitappdelegate.m
+index 3186cc6e8..dfa6c9307 100644
+--- a/src/video/uikit/SDL_uikitappdelegate.m
++++ b/src/video/uikit/SDL_uikitappdelegate.m
+@@ -25,6 +25,7 @@
++#include "SDL_timer.h"
+@@ -181,6 +182,8 @@ - (NSUInteger)supportedInterfaceOrientations;
++static NSString *launchOptionsURL;
++
+@@ -364,6 +367,11 @@ + (NSString *)getAppDelegateClassName
return @"SDLUIKitDelegate";
++- (NSString *)getLaunchOptionsURL
++{
++ return launchOptionsURL;
++}
++
UIWindow *window = launchWindow;
+@@ -387,7 +395,7 @@ - (void)postFinishLaunch
/* Hide the launch screen the next time the run loop is run. SDL apps will
* have a chance to load resources while the launch screen is still up. */
+- [self performSelector:@selector(hideLaunchScreen) withObject:nil afterDelay:0.0];
++ //[self performSelector:@selector(hideLaunchScreen) withObject:nil afterDelay:0.0];
/* run the user's application, passing argc and argv */
SDL_iPhoneSetEventPump(SDL_TRUE);
+@@ -421,6 +429,12 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(
/* tvOS only uses a plain launch image. */
++
++ NSURL *url = [launchOptions objectForKey:UIApplicationLaunchOptionsURLKey];
++ if (url != nil) {
++ launchOptionsURL = [url absoluteString];
++ }
++
screenname = [bundle objectForInfoDictionaryKey:@"UILaunchStoryboardName"];
if (screenname) {
+@@ -428,7 +442,7 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(
/* The launch storyboard is actually a nib in some older versions of
* Xcode. We'll try to load it as a storyboard first, as it's more
* modern. */
+- UIStoryboard *storyboard = [UIStoryboard storyboardWithName:screenname bundle:bundle];
++ UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"LaunchScreen" bundle:bundle];
__auto_type storyboardVc = [storyboard instantiateInitialViewController];
vc = [[SDLLaunchStoryboardViewController alloc] initWithStoryboardViewController:storyboardVc];
}
+diff --git a/src/video/uikit/SDL_uikitviewcontroller.h b/src/video/uikit/SDL_uikitviewcontroller.h
+index 2e64a5279..256be3073 100644
+--- a/src/video/uikit/SDL_uikitviewcontroller.h
++++ b/src/video/uikit/SDL_uikitviewcontroller.h
+@@ -58,10 +58,13 @@
++- (void)setStatusStyle:(UIStatusBarStyle)style;
++- (UIStatusBarStyle)preferredStatusBarStyle;
++@property (nonatomic, assign) UIStatusBarStyle statusBarStyle;
+diff --git a/src/video/uikit/SDL_uikitviewcontroller.m b/src/video/uikit/SDL_uikitviewcontroller.m
+index ee7ee83b0..f3cda52c8 100644
+--- a/src/video/uikit/SDL_uikitviewcontroller.m
++++ b/src/video/uikit/SDL_uikitviewcontroller.m
+@@ -101,6 +101,7 @@ - (instancetype)initWithSDLWindow:(SDL_Window *)_window
++ self.statusBarStyle = UIStatusBarStyleDefault;
SDL_AddHintCallback(SDL_HINT_IOS_HIDE_HOME_INDICATOR,
SDL_HideHomeIndicatorHintChanged,
(__bridge void *) self);
+@@ -219,6 +220,17 @@ - (BOOL)prefersHomeIndicatorAutoHidden
return hidden;
++- (void)setStatusStyle:(UIStatusBarStyle)style
++{
++ self.statusBarStyle = style;
++ [self setNeedsStatusBarAppearanceUpdate];
++}
++
++- (UIStatusBarStyle)preferredStatusBarStyle
++{
++ return self.statusBarStyle;
++}
++
if (self.homeIndicatorHidden >= 0) {
diff --git a/src/app.c b/src/app.c
index 811ae403..7dae4b2f 100644
--- a/src/app.c
+++ b/src/app.c
@@ -1856,12 +1856,15 @@ void processEvents_App(enum iAppEventMode eventMode) {
break;
}
case SDL_DROPFILE: {
if (!d->window) {
if (isDesktop_Platform() && !d->window) {
/* Need to open an empty window now. */
handleNonWindowRelatedCommand_App_(d, "window.new url:");
iAssert(d->window);
iAssert(d->window != NULL);
}
iBool wasUsed = iFalse;
if (d->window) {
wasUsed = processEvent_Window(as_Window(d->window), &ev);
}
iBool wasUsed = processEvent_Window(as_Window(d->window), &ev);
if (!wasUsed) {
if (startsWithCase_CStr(ev.drop.file, "gemini:") ||
startsWithCase_CStr(ev.drop.file, "gopher:") ||
@@ -1874,6 +1877,7 @@ void processEvents_App(enum iAppEventMode eventMode) {
"~open newtab:1 url:%s", makeFileUrl_CStr(ev.drop.file));
}
}
SDL_free(ev.drop.file);
break;
}
default: {
diff --git a/src/ios.m b/src/ios.m
index 3140ecb7..690aadbc 100644
--- a/src/ios.m
+++ b/src/ios.m
@@ -583,6 +583,20 @@ static void callVoidMethod(id target, NSString *selectorName) {
}
}
+static NSString *callStringMethod(id target, NSString *selectorName) {
NSInvocation *call = [NSInvocation invocationWithMethodSignature:
[NSMethodSignature signatureWithObjCTypes:"@@:"]];
[call setSelector:sel];
[call invokeWithTarget:target];
NSString *retVal;
[call getReturnValue:&retVal];
return retVal;
+}
static void callVoidMethodWithIntArgument(id target, NSString *selectorName, int argValue) {
SEL sel = NSSelectorFromString(selectorName);
if ([target respondsToSelector:sel]) {
@@ -615,9 +629,21 @@ iBool processEvent_iOS(const SDL_Event *ev) {
}
else if (ev->type == SDL_USEREVENT && ev->user.code == command_UserEventCode) {
const char *cmd = command_UserEvent(ev);
//NSLog(@"%s", cmd);
if (equal_Command(cmd, "window.unfreeze")) {
id<UIApplicationDelegate> dlg = [UIApplication sharedApplication].delegate;
callVoidMethod([UIApplication sharedApplication].delegate, @"hideLaunchScreen");
callVoidMethod(dlg, @"hideLaunchScreen");
/* When the application is launching, it is too early to post a SDL_DROPFILE
event. The customized SDL application delegate saves the launch URL, so
we can use it now to */
static iBool didCheckLaunchURL = iFalse;
if (!didCheckLaunchURL) {
didCheckLaunchURL = iTrue;
NSString *launchURL = callStringMethod(dlg, @"getLaunchOptionsURL");
if (launchURL) {
postCommandf_App("open newtab:1 url:%s", [launchURL UTF8String]);
}
}
}
else if (equal_Command(cmd, "ostheme")) {
if (arg_Command(cmd)) {
--
2.25.1
text/plain
This content has been proxied by September (ba2dc).