Skip to content

[JEWEL-993] Add MacOS Scrollbar Detection to Standalone#3407

Open
DanielSouzaBertoldi wants to merge 1 commit intoJetBrains:masterfrom
DanielSouzaBertoldi:dsb/JEWEL-993
Open

[JEWEL-993] Add MacOS Scrollbar Detection to Standalone#3407
DanielSouzaBertoldi wants to merge 1 commit intoJetBrains:masterfrom
DanielSouzaBertoldi:dsb/JEWEL-993

Conversation

@DanielSouzaBertoldi
Copy link
Collaborator

Context

After #3372 was merged, we finally have access to JNA in the :int-ui-standalone module. This means we can safely fetch data directly from MacOS settings and use it in our components 🥳

This PR basically just changes ScrollbarStyle.Companion.macOsLight() and ScrollbarStyle.Companion.macOsDark() to fetch the user's current option from the new StandaloneScrollbarHelper class instead of hardcoding an option.

I also added a minor bonus: now you can change the configurations of all scrollbars in our Scrollbar showcase, changing from "manual" mode to "system", check the screenshots below!

Changes

  • Now that both StandalonePlatformCursorController and StandaloneScrollbarHelper use JNA to fetch style information, I opted to just move all JNA code from :decorated-window over to :int-ui-standalone, since the code we had there was more robust and :decorated-window depends on :int-ui-standalone anyway.
  • Added new methods to Jewel's Foundation class so that we can add observers via JNA.
  • Updated Scrollbars showcase code to add an option for scrollbars to follow the behavior/visibility of the system.
  • Added a new icon called "Terminal"

Screenshots

Before After
Screen.Recording.2026-02-04.at.15.04.24.mov
Screen.Recording.2026-02-04.at.14.55.50.mov

Scrollbars Showcase

Standalone Bridge
Screen.Recording.2026-02-04.at.14.59.09.mov
Screen.Recording.2026-02-04.at.15.01.01.mov


operator fun invoke(id: ID?, selector: String?, vararg args: Any?): ID = invoke(id, createSelector(selector), *args)

fun allocateObjcClassPair(superCls: ID, name: String) =
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All code here was taken directly from com.intellij.ui.mac.foundation.Foundation.java class and converted to Kotlin.

However, I did not import 100% of the code there


private fun listenToTrackClickBehaviorChange() {
callMac {
// Copied from MacScrollBarUI
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately, as is the case with ScrollbarHelper from bridge, we can't directly use the code in MacScrollBarUI since all its classes are internal.

This means this code is duplicated. We have the same lines over in bridge, but such is the case with our structure. The only difference is that bridge uses IJP's version of Foundation.

Column {
Text("Configuration", style = JewelTheme.typography.h2TextStyle)

Spacer(Modifier.height(16.dp))
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can't set the vertical arrangement to spacedBy(16.dp) in our parent Column because that screws up the animation:

Screen.Recording.2026-02-04.at.15.21.51.mov

See? it kinda jumps at the end. That's because the parent Column has to get rid of the space that was reserved for the settings row after it's done animating :(

Copy link
Collaborator

@nebojsa-vuksic nebojsa-vuksic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are missing tests :)

@DanielSouzaBertoldi DanielSouzaBertoldi force-pushed the dsb/JEWEL-993 branch 2 times, most recently from 437d4e2 to 18b4a03 Compare February 6, 2026 14:16
@DanielSouzaBertoldi
Copy link
Collaborator Author

@nebojsa-vuksic just pushed the changes you asked + added tests. However, to avoid having to add the JNA dependency in the test module, I had to make a bunch of changes to the code which in turn made it a bit more complex:

  1. Created an interface that MacUtils implements, so that we can create a fake impl and use it in tests.
  2. With the use of callbacks, StandaloneScrollbarHelper doesnt inherits from JNA

Like, I think this is still pretty okay overall, but let me know if you disagree (in other words, if you think it's a bit overkill)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To avoid making StandaloneScrollbarHelper inherit from JNA and subsequently forcing us to add the JNA dependency in our int-ui-standalone-tests module, I had to move references to JNA's Callback here.

With the use of callbacks, we can make StandaloneScrollbarHelper refresh its state with whatever the callback returns. BUT! We have to do this "hacky" thing to keep the reference from being purged by GC 😭

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please feel free to suggest better names if you think of any! 🙏🏻

@DanielSouzaBertoldi DanielSouzaBertoldi force-pushed the dsb/JEWEL-993 branch 4 times, most recently from 8cc29a5 to 287d07f Compare February 6, 2026 16:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants