diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/cocoa/library/os_custom.c b/bundles/org.eclipse.swt/Eclipse SWT PI/cocoa/library/os_custom.c index 99f8bae271..27bc21a5d3 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT PI/cocoa/library/os_custom.c +++ b/bundles/org.eclipse.swt/Eclipse SWT PI/cocoa/library/os_custom.c @@ -15,6 +15,8 @@ #include "swt.h" #include "os_structs.h" #include "os_stats.h" +#include +#include #define OS_NATIVE(func) Java_org_eclipse_swt_internal_cocoa_OS_##func @@ -150,3 +152,26 @@ JNIEXPORT jlong JNICALL OS_NATIVE(beginSheetModalForWindow) } #endif +#ifndef NO_getMachOSDKVersion +JNIEXPORT jint JNICALL OS_NATIVE(getMachOSDKVersion) + (JNIEnv *env, jclass that) +{ + jint rc = 0; + OS_NATIVE_ENTER(env, that, getMachOSDKVersion_FUNC); + const struct mach_header_64 *header = (const struct mach_header_64 *)_NSGetMachExecuteHeader(); + const uint8_t *ptr = (const uint8_t *)header + sizeof(struct mach_header_64); + for (uint32_t i = 0; i < header->ncmds; i++) { + const struct load_command *lc = (const struct load_command *)ptr; + if (lc->cmd == LC_BUILD_VERSION) { + const struct build_version_command *bv = (const struct build_version_command *)ptr; + uint32_t sdk = bv->sdk; + rc = (jint)(((sdk >> 16) & 0xff) << 16) | (((sdk >> 8) & 0xff) << 8) | (sdk & 0xff); + break; + } + ptr += lc->cmdsize; + } + OS_NATIVE_EXIT(env, that, getMachOSDKVersion_FUNC); + return rc; +} +#endif + diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/cocoa/library/os_stats.h b/bundles/org.eclipse.swt/Eclipse SWT PI/cocoa/library/os_stats.h index be2c525007..c5d0e1e858 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT PI/cocoa/library/os_stats.h +++ b/bundles/org.eclipse.swt/Eclipse SWT PI/cocoa/library/os_stats.h @@ -369,6 +369,7 @@ typedef enum { class_1getMethodImplementation_FUNC, class_1getName_FUNC, class_1getSuperclass_FUNC, + getMachOSDKVersion_FUNC, getpid_FUNC, instrumentObjcMessageSends_FUNC, isFlipped_1CALLBACK_FUNC, diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/cocoa/org/eclipse/swt/internal/cocoa/CALayer.java b/bundles/org.eclipse.swt/Eclipse SWT PI/cocoa/org/eclipse/swt/internal/cocoa/CALayer.java index d2767f63a7..5344aad367 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT PI/cocoa/org/eclipse/swt/internal/cocoa/CALayer.java +++ b/bundles/org.eclipse.swt/Eclipse SWT PI/cocoa/org/eclipse/swt/internal/cocoa/CALayer.java @@ -27,6 +27,18 @@ public CALayer(id id) { super(id); } +public void setBorderColor(long /*CGColorRef*/ color) { + OS.objc_msgSend(this.id, OS.sel_setBorderColor_, color); +} + +public void setBorderWidth(double width) { + OS.objc_msgSend(this.id, OS.sel_setBorderWidth_, width); +} + +public void setCornerRadius(double cornerRadius) { + OS.objc_msgSend(this.id, OS.sel_setCornerRadius_, cornerRadius); +} + public void setHidden(boolean hidden) { OS.objc_msgSend(this.id, OS.sel_setHidden_, hidden); } diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/cocoa/org/eclipse/swt/internal/cocoa/NSColor.java b/bundles/org.eclipse.swt/Eclipse SWT PI/cocoa/org/eclipse/swt/internal/cocoa/NSColor.java index b74b633bad..e9df7a7735 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT PI/cocoa/org/eclipse/swt/internal/cocoa/NSColor.java +++ b/bundles/org.eclipse.swt/Eclipse SWT PI/cocoa/org/eclipse/swt/internal/cocoa/NSColor.java @@ -27,6 +27,10 @@ public NSColor(id id) { super(id); } +public long /*CGColorRef*/ CGColor() { + return OS.objc_msgSend(this.id, OS.sel_CGColor); +} + public double alphaComponent() { return OS.objc_msgSend_fpret(this.id, OS.sel_alphaComponent); } @@ -151,6 +155,11 @@ public static NSColor selectedTextColor() { return result != 0 ? new NSColor(result) : null; } +public static NSColor separatorColor() { + long result = OS.objc_msgSend(OS.class_NSColor, OS.sel_separatorColor); + return result != 0 ? new NSColor(result) : null; +} + public void set() { OS.objc_msgSend(this.id, OS.sel_set); } diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/cocoa/org/eclipse/swt/internal/cocoa/NSView.java b/bundles/org.eclipse.swt/Eclipse SWT PI/cocoa/org/eclipse/swt/internal/cocoa/NSView.java index 02a5319e7f..b9f6c8c011 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT PI/cocoa/org/eclipse/swt/internal/cocoa/NSView.java +++ b/bundles/org.eclipse.swt/Eclipse SWT PI/cocoa/org/eclipse/swt/internal/cocoa/NSView.java @@ -276,6 +276,10 @@ public void setToolTip(NSString toolTip) { OS.objc_msgSend(this.id, OS.sel_setToolTip_, toolTip != null ? toolTip.id : 0); } +public void setWantsLayer(boolean wantsLayer) { + OS.objc_msgSend(this.id, OS.sel_setWantsLayer_, wantsLayer); +} + public void setWantsRestingTouches(boolean wantsRestingTouches) { OS.objc_msgSend(this.id, OS.sel_setWantsRestingTouches_, wantsRestingTouches); } 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 cd24777ad6..0bb3610e37 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 @@ -38,6 +38,18 @@ public static int VERSION (int major, int minor, int bugfix) { return (major << 16) + (minor << 8) + bugfix; } + public static int VERSION_MAJOR (int version) { + return (version >>> 16) & 0xFF; + } + + public static int VERSION_MINOR (int version) { + return (version >>> 8) & 0xFF; + } + + public static int VERSION_BUGFIX (int version) { + return version & 0xFF; + } + public static final boolean IS_X86_64 = System.getProperty("os.arch").equals("x86_64"); //$NON-NLS-1$ /* @@ -336,6 +348,15 @@ public static boolean isSystemDarkAppearance() { public static final native int getpid(); +/** + * Returns the SDK version from LC_BUILD_VERSION in the main executable's + * Mach-O header, encoded as {@code (major << 16) + (minor << 8) + bugfix}. + * Returns 0 if LC_BUILD_VERSION is not found. + * @method flags=no_gen + */ +public static final native int getMachOSDKVersion(); +public static final int MACH_O_SDK_VERSION = getMachOSDKVersion(); + public static final native void call(long proc, long id, long sel); /** QuickDraw calls */ @@ -823,6 +844,7 @@ public static void registerSelector (Long value, Selector selector) { public static Selector getSelector (long value) { return SELECTORS.get(value); } +public static final long sel_CGColor = Selector.sel_CGColor.value; public static final long sel_CGEvent = Selector.sel_CGEvent.value; public static final long sel_DOMDocument = Selector.sel_DOMDocument.value; public static final long sel_IBeamCursor = Selector.sel_IBeamCursor.value; @@ -1653,6 +1675,7 @@ public static Selector getSelector (long value) { public static final long sel_sendAction_to_from_ = Selector.sel_sendAction_to_from_.value; public static final long sel_sendEvent_ = Selector.sel_sendEvent_.value; public static final long sel_sender = Selector.sel_sender.value; +public static final long sel_separatorColor = Selector.sel_separatorColor.value; public static final long sel_separatorItem = Selector.sel_separatorItem.value; public static final long sel_set = Selector.sel_set.value; public static final long sel_setAcceptsMouseMovedEvents_ = Selector.sel_setAcceptsMouseMovedEvents_.value; @@ -1695,6 +1718,7 @@ public static Selector getSelector (long value) { public static final long sel_setBecomesKeyOnlyIfNeeded_ = Selector.sel_setBecomesKeyOnlyIfNeeded_.value; public static final long sel_setBezelStyle_ = Selector.sel_setBezelStyle_.value; public static final long sel_setBezeled_ = Selector.sel_setBezeled_.value; +public static final long sel_setBorderColor_ = Selector.sel_setBorderColor_.value; public static final long sel_setBorderType_ = Selector.sel_setBorderType_.value; public static final long sel_setBorderWidth_ = Selector.sel_setBorderWidth_.value; public static final long sel_setBordered_ = Selector.sel_setBordered_.value; @@ -1719,6 +1743,7 @@ public static Selector getSelector (long value) { public static final long sel_setContentView_ = Selector.sel_setContentView_.value; public static final long sel_setContentViewMargins_ = Selector.sel_setContentViewMargins_.value; public static final long sel_setControlSize_ = Selector.sel_setControlSize_.value; +public static final long sel_setCornerRadius_ = Selector.sel_setCornerRadius_.value; public static final long sel_setCookie_ = Selector.sel_setCookie_.value; public static final long sel_setCopiesOnScroll_ = Selector.sel_setCopiesOnScroll_.value; public static final long sel_setCurrentContext_ = Selector.sel_setCurrentContext_.value; @@ -1915,6 +1940,7 @@ public static Selector getSelector (long value) { public static final long sel_setVerticalScroller_ = Selector.sel_setVerticalScroller_.value; public static final long sel_setView_ = Selector.sel_setView_.value; public static final long sel_setVisible_ = Selector.sel_setVisible_.value; +public static final long sel_setWantsLayer_ = Selector.sel_setWantsLayer_.value; public static final long sel_setWantsRestingTouches_ = Selector.sel_setWantsRestingTouches_.value; public static final long sel_setWidth_ = Selector.sel_setWidth_.value; public static final long sel_setWidthTracksTextView_ = Selector.sel_setWidthTracksTextView_.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..5d43256c9b 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 @@ -89,6 +89,7 @@ public enum Selector { /** This section is auto generated */ + , sel_CGColor("CGColor") , sel_CGEvent("CGEvent") , sel_DOMDocument("DOMDocument") , sel_IBeamCursor("IBeamCursor") @@ -919,6 +920,7 @@ public enum Selector { , sel_sendAction_to_from_("sendAction:to:from:") , sel_sendEvent_("sendEvent:") , sel_sender("sender") + , sel_separatorColor("separatorColor") , sel_separatorItem("separatorItem") , sel_set("set") , sel_setAcceptsMouseMovedEvents_("setAcceptsMouseMovedEvents:") @@ -961,6 +963,7 @@ public enum Selector { , sel_setBecomesKeyOnlyIfNeeded_("setBecomesKeyOnlyIfNeeded:") , sel_setBezelStyle_("setBezelStyle:") , sel_setBezeled_("setBezeled:") + , sel_setBorderColor_("setBorderColor:") , sel_setBorderType_("setBorderType:") , sel_setBorderWidth_("setBorderWidth:") , sel_setBordered_("setBordered:") @@ -985,6 +988,7 @@ public enum Selector { , sel_setContentView_("setContentView:") , sel_setContentViewMargins_("setContentViewMargins:") , sel_setControlSize_("setControlSize:") + , sel_setCornerRadius_("setCornerRadius:") , sel_setCookie_("setCookie:") , sel_setCopiesOnScroll_("setCopiesOnScroll:") , sel_setCurrentContext_("setCurrentContext:") @@ -1181,6 +1185,7 @@ public enum Selector { , sel_setVerticalScroller_("setVerticalScroller:") , sel_setView_("setView:") , sel_setVisible_("setVisible:") + , sel_setWantsLayer_("setWantsLayer:") , sel_setWantsRestingTouches_("setWantsRestingTouches:") , sel_setWidth_("setWidth:") , sel_setWidthTracksTextView_("setWidthTracksTextView:") diff --git a/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/widgets/Combo.java b/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/widgets/Combo.java index 0597becb23..630870b8f7 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/widgets/Combo.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/widgets/Combo.java @@ -510,6 +510,12 @@ void createHandle () { if (cell != null) { cell.setUsesSingleLineMode(true); } + if (OS.VERSION_MAJOR(OS.MACH_O_SDK_VERSION) == 26) { + // macOS 26 (Tahoe) Liquid Glass requires a visible border on all combo boxes, + // so we draw one via the layer. + widget.setBordered(false); + configureLayerBorder(widget); + } view = widget; } } diff --git a/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/widgets/Control.java b/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/widgets/Control.java index 1e423a6a52..a7ab8653a1 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/widgets/Control.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/widgets/Control.java @@ -3631,6 +3631,19 @@ void setBackgroundImage (NSImage image) { void setBackgroundColor (NSColor nsColor) { } +void configureLayerBorder(NSView nsView) { + nsView.setWantsLayer(true); + CALayer layer = nsView.layer(); + if (layer != null) { + NSColor separatorColor = NSColor.separatorColor(); + if (separatorColor != null) { + layer.setBorderColor(separatorColor.CGColor()); + } + layer.setBorderWidth(1.0); + layer.setCornerRadius(4.0); + } +} + /** * Sets the receiver's size and location in points to the rectangular * area specified by the arguments. The x and diff --git a/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/widgets/Text.java b/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/widgets/Text.java index ee965adccc..f48a3e0d16 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/widgets/Text.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/widgets/Text.java @@ -515,9 +515,16 @@ void createHandle () { widget.init (); widget.setSelectable (true); widget.setEditable((style & SWT.READ_ONLY) == 0); - if ((style & SWT.BORDER) == 0) { - widget.setFocusRingType (OS.NSFocusRingTypeNone); - widget.setBordered (false); + if (OS.VERSION_MAJOR(OS.MACH_O_SDK_VERSION) == 26) { + // macOS 26 (Tahoe) Liquid Glass requires a visible border on all text fields + // regardless of SWT.BORDER style, so we draw one via the layer. + widget.setBordered(false); + configureLayerBorder(widget); + } else { + if ((style & SWT.BORDER) == 0) { + widget.setFocusRingType (OS.NSFocusRingTypeNone); + widget.setBordered (false); + } } /* * Bug in Cocoa: On OSX 10.10, setting the alignment on the search field