|
| 1 | +# scijava-desktop |
| 2 | + |
1 | 3 | [](https://github.com/scijava/scijava-desktop/actions/workflows/build.yml) |
2 | 4 |
|
3 | | -This component provides supporting code for SciJava applications |
4 | | -to manage their integration with the system native desktop: |
| 5 | +Unified desktop integration for SciJava applications. |
5 | 6 |
|
6 | | -* SciJava Platform plugins for macOS and Windows |
7 | | -* A links subsystem to handle URI-based links via plugins |
| 7 | +## Features |
8 | 8 |
|
9 | | -The scijava-desktop component requires Java 11 as a minimum, due |
10 | | -to its use of java.awt.Desktop features not present in Java 8. |
| 9 | +The scijava-desktop component provides three kinds of desktop integration: |
11 | 10 |
|
12 | | -## Features |
| 11 | +1. **URI Link Scheme Registration & Handling** |
| 12 | + - Register custom URI schemes (e.g., `myapp://`) with the operating system |
| 13 | + - Handle URI clicks from web browsers and other applications |
| 14 | + - Automatic scheme registration on application startup |
| 15 | + |
| 16 | +2. **Desktop Icon Generation** |
| 17 | + - Linux: `.desktop` file creation in application menus |
| 18 | + - Windows: Start Menu shortcuts (planned) |
| 19 | + - macOS: Application bundle support |
| 20 | + |
| 21 | +3. **File Extension Registration** (planned) |
| 22 | + - Associate file types with your application |
| 23 | + - Platform-specific MIME type handling |
| 24 | + |
| 25 | +## Platform Support |
| 26 | + |
| 27 | +- **Linux**: Full support for URI schemes and desktop icons via `.desktop` files |
| 28 | +- **Windows**: URI scheme registration via Windows Registry (desktop icons planned) |
| 29 | +- **macOS**: Read-only support (configuration via Info.plist at build time) |
| 30 | + |
| 31 | +## Requirements |
| 32 | + |
| 33 | +- Java 11 or later (due to use of `java.awt.Desktop` features) |
| 34 | +- Platform-specific tools: |
| 35 | + - Linux: `xdg-utils` (for `xdg-mime` and `update-desktop-database`) |
| 36 | + - Windows: `reg` command (built-in) |
| 37 | + - macOS: No runtime dependencies |
| 38 | + |
| 39 | +## Quick Start |
13 | 40 |
|
14 | | -- **Link handling**: Register custom handlers for URI schemes through the `LinkHandler` plugin interface |
15 | | -- **CLI integration**: Automatic handling of URI arguments passed on the command line via `ConsoleArgument` |
16 | | -- **OS integration**: Automatic registration of URI schemes with the operating system (Windows supported, macOS/Linux planned) |
| 41 | +### 1. Add Dependency |
17 | 42 |
|
18 | | -## Usage |
| 43 | +```xml |
| 44 | +<dependency> |
| 45 | + <groupId>org.scijava</groupId> |
| 46 | + <artifactId>scijava-desktop</artifactId> |
| 47 | + <version><!-- latest version --></version> |
| 48 | +</dependency> |
| 49 | +``` |
| 50 | + |
| 51 | +### 2. Configure System Properties |
19 | 52 |
|
20 | | -### Creating a Link Handler |
| 53 | +Set these properties when launching your application: |
21 | 54 |
|
22 | | -Implement the `LinkHandler` interface to handle custom URI schemes: |
| 55 | +```bash |
| 56 | +java -Dscijava.app.executable="/path/to/myapp" \ |
| 57 | + -Dscijava.app.name="My Application" \ |
| 58 | + -Dscijava.app.icon="/path/to/icon.png" \ |
| 59 | + -jar myapp.jar |
| 60 | +``` |
| 61 | + |
| 62 | +### 3. Create a LinkHandler Plugin |
23 | 63 |
|
24 | 64 | ```java |
| 65 | +package com.example; |
| 66 | + |
| 67 | +import org.scijava.desktop.links.AbstractLinkHandler; |
| 68 | +import org.scijava.desktop.links.LinkHandler; |
| 69 | +import org.scijava.plugin.Plugin; |
| 70 | + |
| 71 | +import java.net.URI; |
| 72 | +import java.util.Arrays; |
| 73 | +import java.util.List; |
| 74 | + |
25 | 75 | @Plugin(type = LinkHandler.class) |
26 | | -public class MyLinkHandler extends AbstractLinkHandler { |
| 76 | +public class MyAppLinkHandler extends AbstractLinkHandler { |
27 | 77 |
|
28 | 78 | @Override |
29 | | - public boolean supports(URI uri) { |
| 79 | + public boolean supports(final URI uri) { |
30 | 80 | return "myapp".equals(uri.getScheme()); |
31 | 81 | } |
32 | 82 |
|
33 | 83 | @Override |
34 | | - public void handle(URI uri) { |
35 | | - // Handle the URI |
| 84 | + public void handle(final URI uri) { |
| 85 | + // Handle the URI (e.g., open a file, navigate to a view) |
36 | 86 | System.out.println("Handling: " + uri); |
37 | 87 | } |
38 | 88 |
|
39 | 89 | @Override |
40 | 90 | public List<String> getSchemes() { |
41 | | - // Return schemes to register with the OS |
| 91 | + // Schemes to register with the OS |
42 | 92 | return Arrays.asList("myapp"); |
43 | 93 | } |
44 | 94 | } |
45 | 95 | ``` |
46 | 96 |
|
47 | | -### OS Registration |
| 97 | +### 4. Launch and Test |
48 | 98 |
|
49 | | -On Windows, URI schemes returned by `LinkHandler.getSchemes()` are automatically registered |
50 | | -in the Windows Registry when the `LinkService` initializes. This allows users to click |
51 | | -links like `myapp://action` in web browsers or other applications, which will launch your |
52 | | -Java application with the URI as a command-line argument. |
| 99 | +1. Start your application |
| 100 | +2. The `myapp://` scheme is automatically registered with your OS |
| 101 | +3. Click a `myapp://action?param=value` link in your browser |
| 102 | +4. Your application launches and handles the URI |
53 | 103 |
|
54 | | -The registration uses `HKEY_CURRENT_USER` and requires no administrator privileges. |
| 104 | +## Architecture |
55 | 105 |
|
56 | | -See [doc/WINDOWS.md](doc/WINDOWS.md) for details. |
| 106 | +### Link Handling System |
57 | 107 |
|
58 | | -## Architecture |
| 108 | +- **LinkService**: Service for routing URIs to appropriate handlers |
| 109 | +- **LinkHandler**: Plugin interface for implementing URI handlers |
| 110 | +- **LinkArgument**: Console argument plugin for command-line URI handling |
| 111 | +- **SchemeInstaller**: Platform-specific OS registration |
| 112 | + |
| 113 | +### Platform Integration |
| 114 | + |
| 115 | +- **Platform Plugins**: LinuxPlatform, WindowsPlatform, MacOSPlatform |
| 116 | +- **DesktopIntegrationProvider**: Interface for querying/toggling desktop features |
| 117 | +- **OptionsDesktop**: User-facing options plugin (Edit > Options > Desktop...) |
| 118 | + |
| 119 | +### State Management |
| 120 | + |
| 121 | +Desktop integration state is queried directly from the OS (not saved to preferences): |
| 122 | +- On load: Query OS for current registration state |
| 123 | +- On save: Apply changes directly to OS (e.g. registry, .desktop files) |
| 124 | +- Keeps UI in sync with actual OS state |
| 125 | + |
| 126 | +## System Properties |
| 127 | + |
| 128 | +| Property | Description | Platforms | Required | |
| 129 | +|----------------------------|--------------------------------|-----------|-----------------------------------------------------------| |
| 130 | +| `scijava.app.executable` | Path to application executable | All | Yes (for URI schemes) | |
| 131 | +| `scijava.app.name` | Application name | All | No (default: "SciJava") | |
| 132 | +| `scijava.app.icon` | Icon path | All | No | |
| 133 | +| `scijava.app.directory` | Application directory | All | No | |
| 134 | +| `scijava.app.desktop-file` | Override .desktop file path | Linux | No (default: `~/.local/share/applications/<app>.desktop`) | |
| 135 | + |
| 136 | +## User Interface |
| 137 | + |
| 138 | +Users can manage desktop integration via **Edit > Options > Desktop...** in your application: |
| 139 | + |
| 140 | +- **Enable web links**: Register/unregister URI schemes |
| 141 | +- **Add desktop icon**: Install/remove application launcher |
| 142 | + |
| 143 | +The UI automatically grays out features that are not available on the current platform. |
| 144 | + |
| 145 | +## Documentation |
| 146 | + |
| 147 | +- [doc/WINDOWS.md](doc/WINDOWS.md) - Windows Registry-based URI scheme registration |
| 148 | + |
| 149 | +## Examples |
| 150 | + |
| 151 | +### Parse URI Components |
| 152 | + |
| 153 | +```java |
| 154 | +import org.scijava.desktop.links.Links; |
| 155 | + |
| 156 | +URI uri = new URI("myapp://view/document?id=123&mode=edit"); |
| 157 | + |
| 158 | +String operation = Links.operation(uri); // "view" |
| 159 | +List<String> pathFragments = Links.pathFragments(uri); // ["view", "document"] |
| 160 | +Map<String, String> query = Links.query(uri); // {"id": "123", "mode": "edit"} |
| 161 | +``` |
| 162 | + |
| 163 | +### Multiple Schemes |
| 164 | + |
| 165 | +```java |
| 166 | +@Plugin(type = LinkHandler.class) |
| 167 | +public class MultiSchemeLinkHandler extends AbstractLinkHandler { |
| 168 | + |
| 169 | + @Override |
| 170 | + public boolean supports(final URI uri) { |
| 171 | + String scheme = uri.getScheme(); |
| 172 | + return "myapp".equals(scheme) || "myapp-dev".equals(scheme); |
| 173 | + } |
| 174 | + |
| 175 | + @Override |
| 176 | + public void handle(final URI uri) { |
| 177 | + if ("myapp-dev".equals(uri.getScheme())) { |
| 178 | + // Handle development scheme |
| 179 | + } else { |
| 180 | + // Handle production scheme |
| 181 | + } |
| 182 | + } |
| 183 | + |
| 184 | + @Override |
| 185 | + public List<String> getSchemes() { |
| 186 | + return Arrays.asList("myapp", "myapp-dev"); |
| 187 | + } |
| 188 | +} |
| 189 | +``` |
| 190 | + |
| 191 | +## Platform-Specific Details |
| 192 | + |
| 193 | +### Linux |
| 194 | + |
| 195 | +URI schemes are registered by: |
| 196 | +1. Creating a `.desktop` file in `~/.local/share/applications/` |
| 197 | +2. Adding `x-scheme-handler/<scheme>` to the MimeType field |
| 198 | +3. Registering with `xdg-mime default <app>.desktop x-scheme-handler/<scheme>` |
| 199 | +4. Updating the desktop database with `update-desktop-database` |
| 200 | + |
| 201 | +Desktop icons are created by installing the `.desktop` file with appropriate fields (Name, Exec, Icon, Categories). |
| 202 | + |
| 203 | +### macOS |
| 204 | + |
| 205 | +URI schemes are declared in the application's `Info.plist` file within the `.app` bundle. This is configured at build time (bundle is code-signed and immutable), so runtime registration is not supported. |
59 | 206 |
|
60 | | -- `LinkService` - Service for routing URIs to appropriate handlers |
61 | | -- `LinkHandler` - Plugin interface for implementing custom URI handlers |
62 | | -- `LinkArgument` - Console argument plugin that recognizes URIs on the command line |
63 | | -- `SchemeInstaller` - Interface for OS-specific URI scheme registration |
64 | | -- `WindowsSchemeInstaller` - Windows implementation using registry commands |
| 207 | +The MacOSPlatform correctly reports read-only status for all desktop integration features. |
65 | 208 |
|
66 | | -The launcher should set the `scijava.app.executable` system property to enable URI scheme registration. |
| 209 | +### Windows |
| 210 | + |
| 211 | +URI schemes are registered in the Windows Registry under `HKEY_CURRENT_USER\Software\Classes\<scheme>`. No administrator privileges are required. |
| 212 | + |
| 213 | +The registry structure: |
| 214 | +``` |
| 215 | +HKCU\Software\Classes\myapp |
| 216 | + (Default) = "URL:myapp" |
| 217 | + URL Protocol = "" |
| 218 | + shell\open\command\ |
| 219 | + (Default) = "C:\Path\To\App.exe" "%1" |
| 220 | +``` |
| 221 | + |
| 222 | +## Known Issues |
| 223 | + |
| 224 | +### Hardcoded Elements (Needs Fixes) |
| 225 | + |
| 226 | +1. **Hardcoded "fiji" scheme**: WindowsPlatform:86,102 and LinuxPlatform:112,129 hardcode the "fiji" scheme instead of querying LinkHandler plugins. |
| 227 | + - Impact: Only works for Fiji application |
| 228 | + - Fix: See NEXT.md Work Item #1 |
| 229 | + |
| 230 | +2. **Hardcoded OS checks**: DefaultLinkService:119-132 directly checks OS name instead of using PlatformService. |
| 231 | + - Impact: Violates plugin architecture |
| 232 | + - Fix: See NEXT.md Work Items #2 and #3 |
| 233 | + |
| 234 | +### Missing Features |
| 235 | + |
| 236 | +- File extension registration |
| 237 | +- Windows desktop icon (Start Menu shortcut) |
| 238 | +- First launch dialog for opt-in |
| 239 | + |
| 240 | +See [NEXT.md](NEXT.md) for details on planned improvements. |
| 241 | + |
| 242 | +## Manual Testing |
| 243 | + |
| 244 | +**Windows**: |
| 245 | +```bash |
| 246 | +# Check registry after running your app |
| 247 | +regedit |
| 248 | +# Navigate to HKCU\Software\Classes\myapp |
| 249 | +``` |
| 250 | + |
| 251 | +**Linux**: |
| 252 | +```bash |
| 253 | +# Check .desktop file |
| 254 | +cat ~/.local/share/applications/myapp.desktop |
| 255 | + |
| 256 | +# Check MIME associations |
| 257 | +xdg-mime query default x-scheme-handler/myapp |
| 258 | +``` |
| 259 | + |
| 260 | +**Test URI handling**: |
| 261 | +```bash |
| 262 | +# Linux/macOS |
| 263 | +xdg-open "myapp://test" |
| 264 | + |
| 265 | +# Windows |
| 266 | +start "myapp://test" |
| 267 | +``` |
0 commit comments