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

Reply via email to