Skip to content

Commit 365628f

Browse files
better
Signed-off-by: Cédrik Fuoco <[email protected]>
1 parent 64b8d87 commit 365628f

File tree

2 files changed

+52
-44
lines changed

2 files changed

+52
-44
lines changed

src/bin/nsapps/rvlinklauncher/Info.plist

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
<string>RVLinkLauncher.icns</string>
2121
<key>LSApplicationCategoryType</key>
2222
<string>public.app-category.utilities</string>
23+
<key>LSMultipleInstancesProhibited</key>
24+
<true/>
2325
<key>CFBundleShortVersionString</key>
2426
<string>${RV_MAJOR_VERSION}.${RV_MINOR_VERSION}.${RV_REVISION_NUMBER}</string>
2527
<key>CFBundleSupportedPlatforms</key>

src/bin/nsapps/rvlinklauncher/RVLinkLauncher.mm

Lines changed: 50 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,13 @@
99
@interface RVLinkURLHandler : NSObject {
1010
BOOL urlProcessed;
1111
NSAlert *currentAlert;
12+
NSString *latestRVLinkURL;
1213
}
1314
- (void)handleGetURLEvent:(NSAppleEventDescriptor *)event withReplyEvent:(NSAppleEventDescriptor *)replyEvent;
1415
- (void)processRVLinkURL:(NSString *)rvlinkURL;
1516
- (BOOL)hasProcessedURL;
1617
- (NSMutableArray<NSURL *> *)findRVAppsUsingMDFind;
1718
- (NSMutableArray<NSURL *> *)findRVAppsUsingWorkspace:(NSString *)rvlinkURL;
18-
+ (BOOL)terminateOtherInstancesIfNeeded;
1919
@end
2020

2121
@implementation RVLinkURLHandler
@@ -24,6 +24,7 @@ - (instancetype)init {
2424
if (self) {
2525
urlProcessed = NO;
2626
currentAlert = nil;
27+
latestRVLinkURL = nil;
2728
}
2829
return self;
2930
}
@@ -32,51 +33,42 @@ - (BOOL)hasProcessedURL {
3233
return urlProcessed;
3334
}
3435

35-
+ (BOOL)terminateOtherInstancesIfNeeded {
36-
NSString *bundleID = [[NSBundle mainBundle] bundleIdentifier];
37-
NSArray<NSRunningApplication *> *runningInstances =
38-
[NSRunningApplication runningApplicationsWithBundleIdentifier:bundleID];
39-
40-
int currentPID = [[NSProcessInfo processInfo] processIdentifier];
41-
42-
// Terminate any other running instances to prevent multiple dialogs
43-
for (NSRunningApplication *app in runningInstances) {
44-
int instancePID = [app processIdentifier];
45-
46-
if (instancePID != currentPID) {
47-
// Use forceTerminate because the other instance may be blocked in a modal dialog
48-
[app forceTerminate];
49-
[NSThread sleepForTimeInterval:0.3];
50-
}
36+
- (void)dealloc {
37+
if (latestRVLinkURL != nil) {
38+
[latestRVLinkURL release];
39+
latestRVLinkURL = nil;
5140
}
52-
53-
return NO;
41+
[super dealloc];
5442
}
5543

5644
- (void)handleGetURLEvent:(NSAppleEventDescriptor *)event withReplyEvent:(NSAppleEventDescriptor *)replyEvent
5745
{
5846
NSLog(@"*** RVLinkLauncher Apple Event handler called! ***");
59-
60-
// If we're showing a dialog, close it so we can show a new one with the new URL
61-
if (currentAlert != nil) {
62-
[[NSApplication sharedApplication] stopModal];
63-
[[currentAlert window] close];
64-
urlProcessed = NO;
65-
currentAlert = nil;
66-
}
67-
47+
6848
@try {
6949
NSAppleEventDescriptor *directObjectDescriptor = [event paramDescriptorForKeyword:keyDirectObject];
7050
if (directObjectDescriptor != nil) {
7151
NSString *url = [directObjectDescriptor stringValue];
7252
if (url != nil && [url hasPrefix:@"rvlink://"]) {
7353
NSLog(@"RVLinkLauncher received URL: %@", url);
74-
[self processRVLinkURL:url];
54+
55+
// Track the most recent rvlink URL
56+
if (latestRVLinkURL != nil) {
57+
[latestRVLinkURL release];
58+
latestRVLinkURL = nil;
59+
}
60+
latestRVLinkURL = [url copy];
61+
62+
if (currentAlert != nil) {
63+
// Update the existing dialog in place and bring it to the front
64+
[currentAlert setInformativeText:[NSString stringWithFormat:@"Opening: %@", latestRVLinkURL]];
65+
[[currentAlert window] makeKeyAndOrderFront:nil];
66+
} else {
67+
// No dialog is currently shown – process normally
68+
[self processRVLinkURL:latestRVLinkURL];
69+
}
70+
7571
urlProcessed = YES;
76-
// Exit app after processing URL
77-
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
78-
[[NSApplication sharedApplication] terminate:nil];
79-
});
8072
} else {
8173
NSLog(@"RVLinkLauncher received invalid or non-rvlink URL: %@", url);
8274
}
@@ -153,6 +145,16 @@ - (void)handleGetURLEvent:(NSAppleEventDescriptor *)event withReplyEvent:(NSAppl
153145

154146
- (void)processRVLinkURL:(NSString *)rvlinkURL
155147
{
148+
// Remember the URL we are currently processing so that if new URLs arrive
149+
// while a chooser dialog is visible, we can still open the most recent one.
150+
if (rvlinkURL != nil) {
151+
if (latestRVLinkURL != nil) {
152+
[latestRVLinkURL release];
153+
latestRVLinkURL = nil;
154+
}
155+
latestRVLinkURL = [rvlinkURL copy];
156+
}
157+
156158
// Find all RV apps using both discovery methods
157159
NSLog(@"Discovering RV applications using multiple methods...");
158160

@@ -204,7 +206,7 @@ - (void)processRVLinkURL:(NSString *)rvlinkURL
204206
NSString *displayName = [[NSFileManager defaultManager] displayNameAtPath:[selectedAppURL path]];
205207
NSLog(@"Only one RV application found, launching directly: %@", displayName);
206208

207-
NSURL *targetURL = [NSURL URLWithString:rvlinkURL];
209+
NSURL *targetURL = [NSURL URLWithString:latestRVLinkURL];
208210
if (targetURL != nil) {
209211
NSWorkspaceOpenConfiguration *config = [NSWorkspaceOpenConfiguration configuration];
210212
[[NSWorkspace sharedWorkspace] openURLs:@[targetURL]
@@ -215,19 +217,19 @@ - (void)processRVLinkURL:(NSString *)rvlinkURL
215217
NSLog(@"Failed to launch app: %@", [selectedAppURL path]);
216218
NSLog(@"Error: %@", [err localizedDescription]);
217219
} else {
218-
NSLog(@"Successfully opened URL: %@ with app: %@", rvlinkURL, [selectedAppURL path]);
220+
NSLog(@"Successfully opened URL: %@ with app: %@", latestRVLinkURL, [selectedAppURL path]);
219221
}
220222
}];
221223
} else {
222-
NSLog(@"Invalid rvlink URL: %@", rvlinkURL);
224+
NSLog(@"Invalid rvlink URL: %@", latestRVLinkURL);
223225
}
224226
return;
225227
}
226228

227229
// Present chooser UI for multiple apps
228230
currentAlert = [[NSAlert alloc] init];
229231
[currentAlert setMessageText:@"Choose RV Application"];
230-
[currentAlert setInformativeText:[NSString stringWithFormat:@"Opening: %@", rvlinkURL]];
232+
[currentAlert setInformativeText:[NSString stringWithFormat:@"Opening: %@", latestRVLinkURL]];
231233
[currentAlert addButtonWithTitle:@"Open"];
232234
[currentAlert addButtonWithTitle:@"Cancel"];
233235

@@ -271,7 +273,7 @@ - (void)processRVLinkURL:(NSString *)rvlinkURL
271273

272274
if (result == NSAlertFirstButtonReturn) {
273275
NSURL *selectedAppURL = [[popup selectedItem] representedObject];
274-
NSURL *targetURL = [NSURL URLWithString:rvlinkURL];
276+
NSURL *targetURL = [NSURL URLWithString:latestRVLinkURL];
275277
if (targetURL != nil) {
276278
NSWorkspaceOpenConfiguration *config = [NSWorkspaceOpenConfiguration configuration];
277279
[[NSWorkspace sharedWorkspace] openURLs:@[targetURL]
@@ -325,9 +327,6 @@ int main(int argc, const char * argv[])
325327
CFRelease(currentHandler);
326328
}
327329

328-
// Terminate any other running instances to prevent multiple dialogs
329-
[RVLinkURLHandler terminateOtherInstancesIfNeeded];
330-
331330
// Check for command line URL
332331
NSString *rvlinkURL = nil;
333332
for (int i = 1; i < argc; i++) {
@@ -338,10 +337,17 @@ int main(int argc, const char * argv[])
338337
}
339338
}
340339

341-
// If a URL was provided via command line, process it immediately and exit
340+
// If a URL was provided via command line, forward it to LaunchServices and exit.
341+
// This avoids creating a second launcher instance with its own UI when the
342+
// binary is invoked directly from the terminal.
342343
if (rvlinkURL != nil) {
343-
NSLog(@"Processing rvlink URL from command line: %@", rvlinkURL);
344-
[urlHandler processRVLinkURL:rvlinkURL];
344+
NSLog(@"Forwarding rvlink URL from command line to LaunchServices: %@", rvlinkURL);
345+
NSURL *url = [NSURL URLWithString:rvlinkURL];
346+
if (url != nil) {
347+
[[NSWorkspace sharedWorkspace] openURL:url];
348+
} else {
349+
NSLog(@"Invalid rvlink URL from command line: %@", rvlinkURL);
350+
}
345351
return 0;
346352
}
347353

0 commit comments

Comments
 (0)