[Cocoa] Use NSBezelStyleFlexiblePush for buttons with custom font size#3210
Conversation
eaab3d8 to
da567b9
Compare
Test Results 170 files 170 suites 27m 12s ⏱️ Results for commit 7e05b65. ♻️ This comment has been updated with latest results. |
da567b9 to
53e410d
Compare
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 eclipse-platform#3085
53e410d to
7e05b65
Compare
|
In macOS 14, the previously existing constant Maybe this should be two commits: one simply renaming the constant in OS.java (and of course its uses), and then one adding the real fixes and the test: the |
Yes, this applies to basically all NSBezelStyle constants. I planned to update them all at once. You are right that it probably makes sense to rename them before processing this PR. Edit: Constant replacement is now done by this PR: |
|
checked out and tested locally. It works fine and looks much better than my version. |
|
Time for you @xpomul to get Claude AI or the foundation sponsered Copilot licence which also allow to use Claude (Opus) to also generate much better patches. ;-) As Eclipse committer can you request the free Copilot license in your profile. I highly recommned using the command line version of Copilot with Claude Opal as model (/model to trigger selection) or Claude directly. |
Issue
When a custom font with a size larger than the macOS default of 13 pt is set on a push or toggle button, the button text is visually clipped. macOS internally assumes the default font size when drawing a button with
NSRoundedBezelStyleand does not expand the rendered pill shape to accommodate taller text. This is reported in issue #3085.Root cause
NSRoundedBezelStyle(value 1) is the standard rounded push button bezel on macOS. Its rendered height is fixed and optimised for the 13 pt system font. When SWT sets a larger custom font on anNSButtonthat still usesNSRoundedBezelStyle, the native rendering engine clips the text to the fixed bezel height.Solution
Apple explicitly provides
NSBezelStyleFlexiblePushfor exactly this situation. According to the documentation, this style allows the button to adapt its height to the content, making it the correct choice whenever text larger than the default font size is displayed.The constant is defined in
NSButtonCell.hof the macOS 15.4 SDK as:Note that
NSBezelStyleFlexiblePushhas the same integer value (2) as the long-deprecatedNSRegularSquareBezelStyleconstant that SWT already uses insetBounds()for oversized buttons. This PR introducesNSBezelStyleFlexiblePushas a properly-named constant inOS.javaand uses it consistently.The fix has two parts in
Button.java:setFont()— when a custom font is set (Control.font != null), immediately switch the bezel style toNSBezelStyleFlexiblePush. When the custom font is cleared, restoreNSRoundedBezelStyle. This ensures the correct style is active before any layout pass queriescomputeSize().setBounds()— extend the existing height-threshold condition with|| font != nullso that a subsequent layout pass never reverts the bezel style back toNSRoundedBezelStylefor buttons that carry a custom font.Both guards apply only to
PUSHandTOGGLEbuttons withoutFLATorWRAP, matching the scope of the existing bezel-style selection logic.Test
A regression test
test_computeSize_largerWithLargeCustomFontis added toTest_org_eclipse_swt_widgets_Button. It verifies that a push button reports a strictly greater preferred height after its font is changed to 50 pt, ensuring layout managers allocate sufficient space and the button text is not clipped.Visual validation
The following snippet can be used to visually verify the fix. It shows a reference button with the default font alongside a button whose font size can be changed interactively via a combo box:
Alternative proposal
PR #3086 by @xpomul addresses the same issue with a different approach: it overrides
cellSizeForBounds()to manually add a fixed pixel offset (FONT_SIZE_HEIGHT_ADJUST = 8) to the cell height when a custom font larger than 16 pt is detected.This proposal is preferable for the following reasons:
NSBezelStyleFlexiblePushis the mechanism Apple specifically designed and documents for buttons that need to accommodate non-default font sizes. Manual height arithmetic works around a symptom rather than using the intended solution.setFont(),computeSize()immediately returns the right preferred size. PR [Mac] Buttons with font sizes>23pt are not correctly rendered #3085 #3086 patchescellSizeForBounds(), which is only called in certain layout paths and may not be reached in all scenarios.NSBezelStyleFlexiblePush, macOS itself computes and renders the correct button dimensions. There is no risk of the manual offset drifting out of sync with what the native layer actually draws.