On Thu, 28 May 2026 14:55:34 GMT, Michael Strauß <[email protected]> wrote:
>> Several JavaFX controls use animations to convey state changes, some of >> which are controllable by developers (for example: `TitledPane.animated` or >> `Chart.animated`). However, none of those controls respect the >> `reducedMotion` preference that was introduced with >> [JDK-8341514](https://bugs.openjdk.org/browse/JDK-8341514). >> >> This enhancement changes the behavior of the following control skins to take >> the `Scene.Preferences.reducedMotion` preference into account when >> determining whether to animate a state change: >> >> * `TableRowSkinBase` >> * `TitledPaneSkin` >> * `TabPaneSkin` >> * `PaginationSkin` >> * Charts >> >> --------- >> - [x] I confirm that I make this contribution in accordance with the >> [OpenJDK Interim AI Policy](https://openjdk.org/legal/ai). > > Michael Strauß has updated the pull request incrementally with one additional > commit since the last revision: > > stale animation hardening The question whether `reducedMotion` should override `animated` or if it should be the other way around is indeed a very good question. I've thought quite a bit about this, and in general I agree with your idea that ideally there would be a "default value" that would depend on platform or scene preferences. There's a little bit of precedence for this with `Scene.Preferences`, where all properties are "null-coalescing". This means that if set to `null`, the property will instead take on its default value. Since this isn't supported by the Property API, it requires a bit of trickery, where for example `Scene.Preferences.reducedMotion` is defined as: ObjectProperty<Boolean> reducedMotionProperty(); boolean isReducedMotion(); void setReducedMotion(Boolean); This API allows users to assign `null` to a boolean property, but never see `null` when its value is read. This trick isn't possible with `animated`, which is defined as: BooleanProperty animatedProperty(); boolean getAnimated(); void setAnimated(boolean); // can't set null We could try to invent another ad-hoc mechanism to support a default value, for example by having an internal flag in the property implementation that tracks whether any code ever attempted to set or bind its value; and if so, treat the property as user-set. However, I don't think that this particular idea is good, because it's too magical and it's irreversible: set the value once, and you can never go back to the default behavior. I've also entertained the idea of adding another `setAnimated(Boolean)` overload, but that doesn't feel right. Maybe something like `clearAnimated()` could work, which would clear the user-set value and reset the property back to its default value. But that would be yet another ad-hoc invention, and it would also not be reflected in the Property API. If we can't change the API of `animated`, and if we also don't want to have magical property behavior, there's the obvious question: should `reducedMotion` just override `animated`? Let's explore both scenarios: 1. `reducedMotion` overrides `animated`: In this case, users can change animations application-wide, regardless of what the application author specified for each individual control. If the author _insists_ that users can't disable animations, there's the option of setting `Scene.Preferences.setReducedMotion(false)`, such that it overrides the platform default. I would call this "everyone can have their cake". 2. `animated` overrides `reducedMotion`: This is much trickier: application authors can have legitimate reasons to enable animations on some, but not on all controls. But simply by setting the `animated` property, the value of `reducedMotion` is ignored. This can't be easily circumvented, even if the author wants to support a reduced-motion user experience. In this scenario, someone must lose: either the author can't set the `animated` property, or users can't toggle a reduced-motion experience. > On a desktop, however, the new behavior does not seem right. If the chart is > animated via property, the animation must run. I'd interpret it differently: `Chart.setAnimated(true)` doesn't necessarily mean that the animation must be forced to run, no matter what. For me, another interpretation makes more sense: that the author intended for the animation to run, but not if the user clearly expressed that they don't want animations. Mind you: the author still has full control to ignore the users's wish by just setting `Scene.Preferences.setReducedMotion(false)`. > Furthermore, perhaps there should be another platform preference property > like low power which will disable animations when active. For example, this > property will kick in when the battery drops below 10% or whatever. Even if we had this, I'd still think that `reducedMotion` should affect all animations, if not explicitly disabled by the application author. ------------- PR Comment: https://git.openjdk.org/jfx/pull/2177#issuecomment-4607253770
