Skip to content

Commit da567b9

Browse files
committed
[Cocoa] Use NSBezelStyleFlexiblePush for buttons with custom font size
NSRoundedBezelStyle (the default rounded push button style on macOS) has a fixed height optimised for the system default font size of 13 pt. When a larger custom font is set on a push or toggle button, the text overflows the fixed rendering bounds and is visually clipped. Apple provides NSBezelStyleFlexiblePush (previously known as the now- deprecated NSRegularSquareBezelStyle) specifically for this situation: it allows the button cell to grow vertically and adapt its appearance to whatever content height is required. The fix has two parts: 1. setFont() – when the internal Cocoa font hook fires, check whether a custom font has been explicitly set on the widget (Control.font != null). If so, immediately switch the bezel style to NSBezelStyleFlexiblePush so that a subsequent computeSize() / layout pass sees the correct style and the cell reports the right preferred height. When the custom font is cleared (setFont(null)), the style is restored to NSRoundedBezelStyle. 2. setBounds() – the existing height-threshold guard that switches bezel styles during layout is extended with "|| font != null" so that a layout pass following a font change never inadvertently reverts the button back to NSRoundedBezelStyle. Both guards apply only to PUSH and TOGGLE buttons without the FLAT or WRAP style bits, mirroring the existing bezel-style selection logic. The constant NSBezelStyleFlexiblePush is added to OS.java (value 2, sourced from NSButtonCell.h in the macOS 15.4 SDK) in alphabetical order alongside the other NSBezelStyle constants, making the intention explicit and avoiding reliance on the deprecated NSRegularSquareBezelStyle alias. A regression test is added to Test_org_eclipse_swt_widgets_Button that verifies a push button reports a greater preferred height after its font size is increased to 50 pt. This ensures that layout managers allocate sufficient space and the button text is not clipped. Fixes #3085
1 parent d820f7e commit da567b9

File tree

3 files changed

+42
-3
lines changed

3 files changed

+42
-3
lines changed

bundles/org.eclipse.swt/Eclipse SWT PI/cocoa/org/eclipse/swt/internal/cocoa/OS.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2179,6 +2179,7 @@ public static Selector getSelector (long value) {
21792179
public static final int NSBackspaceCharacter = 8;
21802180
public static final int NSBevelLineJoinStyle = 2;
21812181
public static final int NSBezelBorder = 2;
2182+
public static final int NSBezelStyleFlexiblePush = 2;
21822183
public static final int NSBoldFontMask = 2;
21832184
public static final int NSBorderlessWindowMask = 0;
21842185
public static final int NSBottomTabsBezelBorder = 2;

bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/widgets/Button.java

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -829,8 +829,11 @@ void setBounds (int x, int y, int width, int height, boolean move, boolean resiz
829829
}
830830

831831
NSButton button = (NSButton)view;
832-
if (height > heightThreshold) {
833-
button.setBezelStyle(OS.NSRegularSquareBezelStyle);
832+
// Use NSBezelStyleFlexiblePush when a custom font is set or when the height
833+
// exceeds the standard button height. NSRoundedBezelStyle assumes the macOS
834+
// default font size (13pt) and clips text at larger sizes.
835+
if (height > heightThreshold || font != null) {
836+
button.setBezelStyle(OS.NSBezelStyleFlexiblePush);
834837
} else {
835838
button.setBezelStyle(OS.NSRoundedBezelStyle);
836839
}
@@ -845,10 +848,15 @@ void setBounds (int x, int y, int width, int height, boolean move, boolean resiz
845848
}
846849

847850
@Override
848-
void setFont (NSFont font) {
851+
void setFont (NSFont nsFont) {
849852
if (text != null) {
850853
((NSButton)view).setAttributedTitle(createString());
851854
}
855+
if ((style & (SWT.PUSH | SWT.TOGGLE)) != 0 && (style & (SWT.FLAT | SWT.WRAP)) == 0) {
856+
// Use NSBezelStyleFlexiblePush when a custom font is set. NSRoundedBezelStyle
857+
// assumes the macOS default font size (13pt) and clips text at larger sizes.
858+
((NSButton)view).setBezelStyle(font != null ? OS.NSBezelStyleFlexiblePush : OS.NSRoundedBezelStyle);
859+
}
852860
}
853861

854862
@Override

tests/org.eclipse.swt.tests/JUnit Tests/org/eclipse/swt/tests/junit/Test_org_eclipse_swt_widgets_Button.java

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,11 @@
2828
import org.eclipse.swt.events.SelectionEvent;
2929
import org.eclipse.swt.events.SelectionListener;
3030
import org.eclipse.swt.graphics.Color;
31+
import org.eclipse.swt.graphics.Font;
32+
import org.eclipse.swt.graphics.FontData;
3133
import org.eclipse.swt.graphics.Image;
3234
import org.eclipse.swt.graphics.ImageGcDrawer;
35+
import org.eclipse.swt.graphics.Point;
3336
import org.eclipse.swt.layout.FillLayout;
3437
import org.eclipse.swt.layout.GridLayout;
3538
import org.eclipse.swt.widgets.Button;
@@ -584,6 +587,33 @@ public void test_consistency_DragDetect () {
584587
consistencyEvent(5, 5, 15, 15, ConsistencyUtility.MOUSE_DRAG);
585588
}
586589

590+
/**
591+
* Test that a push button reports a greater preferred height after its font
592+
* size is increased. A button whose font grows larger must compute a
593+
* proportionally taller preferred size so that layout managers allocate
594+
* sufficient space and the text is not clipped.
595+
*
596+
* @see <a href="https://github.com/eclipse-platform/eclipse.platform.swt/issues/3085">issue #3085</a>
597+
*/
598+
@Test
599+
public void test_computeSize_largerWithLargeCustomFont() {
600+
button.setText("OK");
601+
602+
Point defaultSize = button.computeSize(SWT.DEFAULT, SWT.DEFAULT);
603+
604+
FontData[] fontData = button.getFont().getFontData();
605+
Font largeFont = new Font(button.getDisplay(), fontData[0].getName(), 50, fontData[0].getStyle());
606+
try {
607+
button.setFont(largeFont);
608+
SwtTestUtil.processEvents();
609+
Point largeSize = button.computeSize(SWT.DEFAULT, SWT.DEFAULT);
610+
assertTrue(largeSize.y > defaultSize.y,
611+
"Button with 50 pt font should be taller than button with default font");
612+
} finally {
613+
largeFont.dispose();
614+
}
615+
}
616+
587617
/** Test for Bug 381668 - NPE when disposing radio buttons right before they should gain focus */
588618
@Disabled(value = "Test works fine locally but fails to get correct focus on automated builds.")
589619
@Test

0 commit comments

Comments
 (0)