From 345cd8daa82bfd954f391bd231c17debf9a9bd52 Mon Sep 17 00:00:00 2001 From: Heiko Klare Date: Tue, 14 Jul 2026 11:45:50 +0200 Subject: [PATCH] [Cocoa] Correct generation for urlForApplicationToOpen[URL|ContentType] NSWorkspace.URLForApplicationToOpenURL: and URLForApplicationToOpenContentType:, introduced as a replacement for deprecated file-association API, were hand-written directly in NSWorkspace.java without registering them for MacGenerator. Since UTType.typeWithFilenameExtension: (the other new API involved, UniformTypeIdentifiers framework, macOS 12+) is not declared in any bridgesupport file, MacGenerator had no way to reproduce these methods and silently dropped them on the next regeneration. - Declare the two NSWorkspace selectors and a minimal UTType class (one method) in AppKitFull.bridgesupport/.extras by hand, since neither API exists in the SDK version the bridgesupport files were generated from, and UTType's own framework has no dedicated bridgesupport file in this project. This makes both methods regenerable instead of being a permanent manual exception. - Rename the two NSWorkspace methods to the casing MacGenerator derives from the Objective-C selector, matching existing conventions elsewhere (e.g. NSURL.URLWithString). - Introduce a proper UTType wrapper class instead of passing its handle around as a raw long, consistent with how every other Cocoa object is represented in this codebase; NSWorkspace.URLForApplicationToOpenContentType now takes a typed UTType argument. - Update Program.findAppURLForExtension() to use the generated UTType.typeWithFilenameExtension() wrapper instead of manual objc_getClass/objc_msgSend calls. Follow-up to https://github.com/eclipse-platform/eclipse.platform.swt/pull/3187 --- .../internal/cocoa/AppKitFull.bridgesupport | 10 ++++++ .../cocoa/AppKitFull.bridgesupport.extras | 14 ++++++++ .../swt/internal/cocoa/NSWorkspace.java | 23 ++++++------- .../org/eclipse/swt/internal/cocoa/OS.java | 5 +-- .../eclipse/swt/internal/cocoa/Selector.java | 4 +-- .../eclipse/swt/internal/cocoa/UTType.java | 32 +++++++++++++++++++ .../org/eclipse/swt/program/Program.java | 15 ++++----- 7 files changed, 77 insertions(+), 26 deletions(-) create mode 100644 bundles/org.eclipse.swt/Eclipse SWT PI/cocoa/org/eclipse/swt/internal/cocoa/UTType.java diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/cocoa/org/eclipse/swt/internal/cocoa/AppKitFull.bridgesupport b/bundles/org.eclipse.swt/Eclipse SWT PI/cocoa/org/eclipse/swt/internal/cocoa/AppKitFull.bridgesupport index cc41662c1b..c9b09006ac 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT PI/cocoa/org/eclipse/swt/internal/cocoa/AppKitFull.bridgesupport +++ b/bundles/org.eclipse.swt/Eclipse SWT PI/cocoa/org/eclipse/swt/internal/cocoa/AppKitFull.bridgesupport @@ -32642,6 +32642,10 @@ + + + + @@ -32935,6 +32939,12 @@ + + + + + + diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/cocoa/org/eclipse/swt/internal/cocoa/AppKitFull.bridgesupport.extras b/bundles/org.eclipse.swt/Eclipse SWT PI/cocoa/org/eclipse/swt/internal/cocoa/AppKitFull.bridgesupport.extras index d1ca0ed5bf..f9adf872e0 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT PI/cocoa/org/eclipse/swt/internal/cocoa/AppKitFull.bridgesupport.extras +++ b/bundles/org.eclipse.swt/Eclipse SWT PI/cocoa/org/eclipse/swt/internal/cocoa/AppKitFull.bridgesupport.extras @@ -4154,6 +4154,14 @@ + + + + + + + + @@ -4192,6 +4200,12 @@ + + + + + + diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/cocoa/org/eclipse/swt/internal/cocoa/NSWorkspace.java b/bundles/org.eclipse.swt/Eclipse SWT PI/cocoa/org/eclipse/swt/internal/cocoa/NSWorkspace.java index 9bfa02eae8..16d5910854 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT PI/cocoa/org/eclipse/swt/internal/cocoa/NSWorkspace.java +++ b/bundles/org.eclipse.swt/Eclipse SWT PI/cocoa/org/eclipse/swt/internal/cocoa/NSWorkspace.java @@ -7,9 +7,6 @@ * https://www.eclipse.org/legal/epl-2.0/ * * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.swt.internal.cocoa; @@ -27,6 +24,16 @@ public NSWorkspace(id id) { super(id); } +public NSURL URLForApplicationToOpenURL(NSURL url) { + long result = OS.objc_msgSend(this.id, OS.sel_URLForApplicationToOpenURL_, url != null ? url.id : 0); + return result != 0 ? new NSURL(result) : null; +} + +public NSURL URLForApplicationToOpenContentType(UTType contentType) { + long result = OS.objc_msgSend(this.id, OS.sel_URLForApplicationToOpenContentType_, contentType != null ? contentType.id : 0); + return result != 0 ? new NSURL(result) : null; +} + public NSString fullPathForApplication(NSString appName) { long result = OS.objc_msgSend(this.id, OS.sel_fullPathForApplication_, appName != null ? appName.id : 0); return result != 0 ? new NSString(result) : null; @@ -45,16 +52,6 @@ public boolean openURL(NSURL url) { return OS.objc_msgSend_bool(this.id, OS.sel_openURL_, url != null ? url.id : 0); } -public NSURL urlForApplicationToOpenURL(NSURL url) { - long result = OS.objc_msgSend(this.id, OS.sel_URLForApplicationToOpenURL_, url != null ? url.id : 0); - return result != 0 ? new NSURL(result) : null; -} - -public NSURL urlForApplicationToOpenContentType(long contentType) { - long result = OS.objc_msgSend(this.id, OS.sel_URLForApplicationToOpenContentType_, contentType); - return result != 0 ? new NSURL(result) : null; -} - public boolean openURLs(NSArray urls, NSString bundleIdentifier, long options, NSAppleEventDescriptor descriptor, long identifiers) { return OS.objc_msgSend_bool(this.id, OS.sel_openURLs_withAppBundleIdentifier_options_additionalEventParamDescriptor_launchIdentifiers_, urls != null ? urls.id : 0, bundleIdentifier != null ? bundleIdentifier.id : 0, options, descriptor != null ? descriptor.id : 0, identifiers); } diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/cocoa/org/eclipse/swt/internal/cocoa/OS.java b/bundles/org.eclipse.swt/Eclipse SWT PI/cocoa/org/eclipse/swt/internal/cocoa/OS.java index 8c94dfd44e..bfe161cc67 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT PI/cocoa/org/eclipse/swt/internal/cocoa/OS.java +++ b/bundles/org.eclipse.swt/Eclipse SWT PI/cocoa/org/eclipse/swt/internal/cocoa/OS.java @@ -767,6 +767,7 @@ public static boolean isSystemDarkAppearance() { public static final long class_NSWorkspace = objc_getClass("NSWorkspace"); public static final long class_SFCertificatePanel = objc_getClass("SFCertificatePanel"); public static final long class_SFCertificateTrustPanel = objc_getClass("SFCertificateTrustPanel"); +public static final long class_UTType = objc_getClass("UTType"); public static final long class_WebDataSource = objc_getClass("WebDataSource"); public static final long class_WebFrame = objc_getClass("WebFrame"); public static final long class_WebFrameView = objc_getClass("WebFrameView"); @@ -830,9 +831,9 @@ public static Selector getSelector (long value) { public static final long sel_PMPrintSettings = Selector.sel_PMPrintSettings.value; public static final long sel_TIFFRepresentation = Selector.sel_TIFFRepresentation.value; public static final long sel_URL = Selector.sel_URL.value; -public static final long sel_URLFromPasteboard_ = Selector.sel_URLFromPasteboard_.value; -public static final long sel_URLForApplicationToOpenURL_ = Selector.sel_URLForApplicationToOpenURL_.value; public static final long sel_URLForApplicationToOpenContentType_ = Selector.sel_URLForApplicationToOpenContentType_.value; +public static final long sel_URLForApplicationToOpenURL_ = Selector.sel_URLForApplicationToOpenURL_.value; +public static final long sel_URLFromPasteboard_ = Selector.sel_URLFromPasteboard_.value; public static final long sel_URLWithString_ = Selector.sel_URLWithString_.value; public static final long sel_UTF8String = Selector.sel_UTF8String.value; public static final long sel_abortEditing = Selector.sel_abortEditing.value; diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/cocoa/org/eclipse/swt/internal/cocoa/Selector.java b/bundles/org.eclipse.swt/Eclipse SWT PI/cocoa/org/eclipse/swt/internal/cocoa/Selector.java index 589d736607..09e0ae8c00 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT PI/cocoa/org/eclipse/swt/internal/cocoa/Selector.java +++ b/bundles/org.eclipse.swt/Eclipse SWT PI/cocoa/org/eclipse/swt/internal/cocoa/Selector.java @@ -96,9 +96,9 @@ public enum Selector { , sel_PMPrintSettings("PMPrintSettings") , sel_TIFFRepresentation("TIFFRepresentation") , sel_URL("URL") - , sel_URLFromPasteboard_("URLFromPasteboard:") - , sel_URLForApplicationToOpenURL_("URLForApplicationToOpenURL:") , sel_URLForApplicationToOpenContentType_("URLForApplicationToOpenContentType:") + , sel_URLForApplicationToOpenURL_("URLForApplicationToOpenURL:") + , sel_URLFromPasteboard_("URLFromPasteboard:") , sel_URLWithString_("URLWithString:") , sel_UTF8String("UTF8String") , sel_abortEditing("abortEditing") diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/cocoa/org/eclipse/swt/internal/cocoa/UTType.java b/bundles/org.eclipse.swt/Eclipse SWT PI/cocoa/org/eclipse/swt/internal/cocoa/UTType.java new file mode 100644 index 0000000000..b836c18703 --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT PI/cocoa/org/eclipse/swt/internal/cocoa/UTType.java @@ -0,0 +1,32 @@ +/******************************************************************************* + * Copyright (c) 2026 IBM Corporation and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ +package org.eclipse.swt.internal.cocoa; + +public class UTType extends NSObject { + +public UTType() { + super(); +} + +public UTType(long id) { + super(id); +} + +public UTType(id id) { + super(id); +} + +public static UTType typeWithFilenameExtension(NSString filenameExtension) { + long result = OS.objc_msgSend(OS.class_UTType, OS.sel_typeWithFilenameExtension_, filenameExtension != null ? filenameExtension.id : 0); + return result != 0 ? new UTType(result) : null; +} + +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT Program/cocoa/org/eclipse/swt/program/Program.java b/bundles/org.eclipse.swt/Eclipse SWT Program/cocoa/org/eclipse/swt/program/Program.java index 465abcc118..786067fece 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT Program/cocoa/org/eclipse/swt/program/Program.java +++ b/bundles/org.eclipse.swt/Eclipse SWT Program/cocoa/org/eclipse/swt/program/Program.java @@ -153,20 +153,17 @@ private static NSURL findAppURLForExtension(NSString ext) { // On macOS 12.0+, use the content type-based API which works reliably // for all file types including third-party ones. if (OS.VERSION >= OS.VERSION(12, 0, 0)) { - long UTTypeClass = OS.objc_getClass("UTType"); - if (UTTypeClass != 0) { - long utType = OS.objc_msgSend(UTTypeClass, OS.sel_typeWithFilenameExtension_, ext.id); - if (utType != 0) { - NSURL appURL = workspace.urlForApplicationToOpenContentType(utType); - if (appURL != null) { - return appURL; - } + UTType utType = UTType.typeWithFilenameExtension(ext); + if (utType != null) { + NSURL appURL = workspace.URLForApplicationToOpenContentType(utType); + if (appURL != null) { + return appURL; } } } // Fallback: URL-based lookup (available since macOS 10.6, deprecated in macOS 12.0) NSURL fileURL = NSURL.fileURLWithPath(NSString.stringWith("/tmp/dummy." + ext.getString())); - return workspace.urlForApplicationToOpenURL(fileURL); + return workspace.URLForApplicationToOpenURL(fileURL); } static Program getProgram(NSBundle bundle) {