Skip to content

Commit 7941617

Browse files
author
ntwigg
committed
First draft of DeepLinkBridge.m
1 parent bf86b37 commit 7941617

File tree

14 files changed

+534
-0
lines changed

14 files changed

+534
-0
lines changed

.gitattributes

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
* text=auto eol=lf
22
*.MF text eol=crlf
33
*.jar binary
4+
*.dylib binary

CLAUDE.md

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
# CLAUDE.md
2+
3+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4+
5+
## Build Commands
6+
7+
This is a Gradle-based Java/Kotlin project focused on SWT (Standard Widget Toolkit) utilities. Standard gradle tasks.
8+
9+
### macOS-specific Requirements
10+
- On macOS, SWT tests require the `-XstartOnFirstThread` JVM argument (automatically configured in build.gradle).
11+
12+
## Project Architecture
13+
### Multi-Module Structure
14+
DurianSwt is organized as a multi-module Gradle project with platform-specific implementations:
15+
16+
- **durian-swt.os**: Platform detection utilities (OS, Arch, SwtPlatform) - no SWT dependencies
17+
- **durian-swt**: Main module with core SWT utilities and builders
18+
- **platform-specific modules**: (durian-swt.cocoa.macosx.aarch64, durian-swt.cocoa.macosx.x86_64, durian-swt.gtk.linux.x86_64, durian-swt.win32.win32.x86_64)
19+
20+
## Native Components
21+
22+
### macOS Deep Link Support (`natives/mac-deep-link/`)
23+
24+
Contains Objective-C code for handling deep links via a custom `diffplug://` protocol on macOS without breaking SWT:
25+
26+
- **DeepLinkBridge.m**: JNI bridge that intercepts URL open events from macOS
27+
- **compile-one.sh**: Compiles the native library for a specific architecture (x86_64 or arm64)
28+
- **clean-and-build.sh**: Builds for both architectures and deploys to appropriate module resources
29+
30+
To rebuild native libraries:
31+
```bash
32+
cd natives/mac-deep-link
33+
./clean-and-build.sh # Builds for both architectures
34+
# Or compile for specific architecture:
35+
./compile-one.sh arm64 # Apple Silicon
36+
./compile-one.sh x86_64 # Intel
37+
```
38+
39+
The resulting `DeepLinkBridge.dylib` files are placed in the platform-specific modules under `src/main/resources/durian-swt-natives/`.

build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ subprojects { subProject ->
6969
}
7070
dependencies {
7171
api project(':durian-swt')
72+
implementation "com.diffplug.durian:durian-core:$VER_DURIAN"
7273
}
7374
configurations.all {
7475
resolutionStrategy.eachDependency { DependencyResolveDetails details ->
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
/*
2+
* Copyright (C) 2025 DiffPlug
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.diffplug.common.swt.widgets;
17+
18+
import com.diffplug.common.base.Preconditions;
19+
import java.util.ArrayList;
20+
import java.util.List;
21+
import java.util.concurrent.atomic.AtomicReference;
22+
import java.util.function.Consumer;
23+
import org.jetbrains.annotations.Nullable;
24+
25+
public class MacDeepLink {
26+
private static volatile @Nullable Consumer<String> urlHandler;
27+
private static final AtomicReference<@Nullable List<String>> backlogUrls = new AtomicReference<>();
28+
29+
static {
30+
// Load the native library - try multiple strategies
31+
String libPath = System.getProperty("durian-swt.library.path");
32+
if (libPath != null) {
33+
System.load(libPath + "/durian-swt-natives/DeepLinkBridge.dylib");
34+
} else {
35+
throw new IllegalArgumentException("You need to set 'durian-swt.library.path'");
36+
}
37+
}
38+
39+
public static void setURLHandler(Consumer<String> handler) {
40+
Preconditions.checkArgument(urlHandler == null, "URL handler can only be set once");
41+
urlHandler = handler;
42+
}
43+
44+
public static void applicationStartBeforeSwt() {
45+
Preconditions.checkArgument(urlHandler != null, "Call `setURLHandler()` first");
46+
backlogUrls.set(new ArrayList<>());
47+
nativeBeforeSwt();
48+
}
49+
50+
public static void applicationStartAfterSwt() {
51+
Preconditions.checkArgument(backlogUrls.get() != null, "Call `applicationStartBeforeSwt()` first.");
52+
nativeAfterSwt();
53+
var accumulatedBacklog = backlogUrls.getAndSet(null);
54+
accumulatedBacklog.forEach(urlHandler);
55+
}
56+
57+
// Native method declarations - implemented in DeepLinkBridge.m
58+
private static native void nativeBeforeSwt();
59+
60+
private static native void nativeAfterSwt();
61+
62+
/**
63+
* Called from native code when a URL is received.
64+
* This method is invoked on various threads by the native code.
65+
*
66+
* @param url The URL string received from the operating system
67+
*/
68+
public static void deliverURL(String url) {
69+
var backlog = backlogUrls.get();
70+
if (backlog != null) {
71+
backlog.add(url);
72+
} else {
73+
urlHandler.accept(url);
74+
}
75+
}
76+
}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
/*
2+
* Copyright (C) 2025 DiffPlug
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.diffplug.common.swt.widgets;
17+
18+
import com.diffplug.common.base.Preconditions;
19+
import java.util.ArrayList;
20+
import java.util.List;
21+
import java.util.concurrent.atomic.AtomicReference;
22+
import java.util.function.Consumer;
23+
import org.jetbrains.annotations.Nullable;
24+
25+
public class MacDeepLink {
26+
private static volatile @Nullable Consumer<String> urlHandler;
27+
private static final AtomicReference<@Nullable List<String>> backlogUrls = new AtomicReference<>();
28+
29+
static {
30+
// Load the native library - try multiple strategies
31+
String libPath = System.getProperty("durian-swt.library.path");
32+
if (libPath != null) {
33+
System.load(libPath + "/durian-swt-natives/DeepLinkBridge.dylib");
34+
} else {
35+
throw new IllegalArgumentException("You need to set 'durian-swt.library.path'");
36+
}
37+
}
38+
39+
public static void setURLHandler(Consumer<String> handler) {
40+
Preconditions.checkArgument(urlHandler == null, "URL handler can only be set once");
41+
urlHandler = handler;
42+
}
43+
44+
public static void applicationStartBeforeSwt() {
45+
Preconditions.checkArgument(urlHandler != null, "Call `setURLHandler()` first");
46+
backlogUrls.set(new ArrayList<>());
47+
nativeBeforeSwt();
48+
}
49+
50+
public static void applicationStartAfterSwt() {
51+
Preconditions.checkArgument(backlogUrls.get() != null, "Call `applicationStartBeforeSwt()` first.");
52+
nativeAfterSwt();
53+
var accumulatedBacklog = backlogUrls.getAndSet(null);
54+
accumulatedBacklog.forEach(urlHandler);
55+
}
56+
57+
// Native method declarations - implemented in DeepLinkBridge.m
58+
private static native void nativeBeforeSwt();
59+
60+
private static native void nativeAfterSwt();
61+
62+
/**
63+
* Called from native code when a URL is received.
64+
* This method is invoked on various threads by the native code.
65+
*
66+
* @param url The URL string received from the operating system
67+
*/
68+
public static void deliverURL(String url) {
69+
var backlog = backlogUrls.get();
70+
if (backlog != null) {
71+
backlog.add(url);
72+
} else {
73+
urlHandler.accept(url);
74+
}
75+
}
76+
}

durian-swt.gtk.linux.x86/src/main/resources/durian-swt-natives/placeholder

Whitespace-only changes.

durian-swt.gtk.linux.x86_64/src/main/resources/durian-swt-natives/placeholder

Whitespace-only changes.

durian-swt.win32.win32.x86/src/main/resources/durian-swt-natives/placeholder

Whitespace-only changes.

0 commit comments

Comments
 (0)