JDK-8341667 : Add reducedMotion and reducedTransparency preferences
  • Type: CSR
  • Component: javafx
  • Sub-Component: graphics
  • Priority: P4
  • Status: Provisional
  • Resolution: Unresolved
  • Fix Versions: jfx24
  • Submitted: 2024-10-07
  • Updated: 2024-10-15
Related Reports
CSR :  
Description
Summary
-------

Add the `reducedMotion` and `reducedTransparency` platform preferences.

Problem
-------

Some users feel discomfort when user interfaces are animated or layered with transparency. Several operating systems have accessibility settings to reduce animations and transparency, which should be exposed to JavaFX applications as platform preferences.

Solution
--------

On Windows, these preferences correspond to "Transparency effects" and "Animation effects" in the system settings.

On macOS, these preferences correspond to "Reduce motion" and "Reduce transparency" in the system settings.

On Linux, the `reducedMotion` preference corresponds to `gtk-enable-animations`. The `reducedTransparency` preference has no corresponding GTK setting.

As an implementation detail, the existing API
```
Map<String, String> com.sun.glass.ui.Application.getPlatformKeyMappings()
```
is changed to
```
Map<String, PreferenceMapping<?>> com.sun.glass.ui.Application.getPlatformKeyMappings()
```
The `PreferenceMapping` record contains an optional mapping function that allows platform toolkits to map the platform-specific settings to platform-independent preferences. For example, the Windows toolkit maps `Windows.SPI.ClientAreaAnimation` (which is true when animations are enabled) to `reducedMotion` (which is false when animations are enabled).

Specification
-------------

```
--- a/modules/javafx.graphics/src/main/java/javafx/application/Platform.java
+++ b/modules/javafx.graphics/src/main/java/javafx/application/Platform.java
@@ -478,6 +478,7 @@
      *     <tbody>
      *         <tr><td>{@code Windows.SPI.HighContrast}</td><td>{@link Boolean}</td></tr>
      *         <tr><td>{@code Windows.SPI.HighContrastColorScheme}</td><td>{@link String}</td></tr>
+     *         <tr><td>{@code Windows.SPI.ClientAreaAnimation}</td><td>{@link Boolean}</td></tr>
      *         <tr><td>{@code Windows.SysColor.COLOR_3DFACE}</td><td>{@link Color}</td></tr>
      *         <tr><td>{@code Windows.SysColor.COLOR_BTNTEXT}</td><td>{@link Color}</td></tr>
      *         <tr><td>{@code Windows.SysColor.COLOR_GRAYTEXT}</td><td>{@link Color}</td></tr>
@@ -495,6 +496,7 @@
      *         <tr><td>{@code Windows.UIColor.AccentLight1}</td><td>{@link Color}</td></tr>
      *         <tr><td>{@code Windows.UIColor.AccentLight2}</td><td>{@link Color}</td></tr>
      *         <tr><td>{@code Windows.UIColor.AccentLight3}</td><td>{@link Color}</td></tr>
+     *         <tr><td>{@code Windows.UISettings.AdvancedEffectsEnabled}</td><td>{@link Boolean}</td></tr>
      *         <tr></tr>
      *     </tbody>
      * </table>
@@ -547,6 +549,8 @@
      *         <tr><td>{@code macOS.NSColor.systemRedColor}</td><td>{@link Color}</td></tr>
      *         <tr><td>{@code macOS.NSColor.systemTealColor}</td><td>{@link Color}</td></tr>
      *         <tr><td>{@code macOS.NSColor.systemYellowColor}</td><td>{@link Color}</td></tr>
+     *         <tr><td>{@code macOS.NSWorkspace.accessibilityDisplayShouldReduceMotion}</td><td>{@link Boolean}</td></tr>
+     *         <tr><td>{@code macOS.NSWorkspace.accessibilityDisplayShouldReduceTransparency}</td><td>{@link Boolean}</td></tr>
      *         <tr></tr>
      *     </tbody>
      * </table>
@@ -572,6 +576,7 @@
      *         <tr><td>{@code GTK.warning_color}</td><td>{@link Color}</td></tr>
      *         <tr><td>{@code GTK.error_color}</td><td>{@link Color}</td></tr>
      *         <tr><td>{@code GTK.success_color}</td><td>{@link Color}</td></tr>
+     *         <tr><td>{@code GTK.enable_animations}</td><td>{@link Boolean}</td></tr>
      *         <tr></tr>
      *     </tbody>
      * </table>
@@ -578,7 +583,36 @@
      *
      * @since 22
      */
-    public interface Preferences extends ObservableMap<String, Object> {
+    public sealed interface Preferences extends ObservableMap<String, Object>
+            permits com.sun.javafx.application.preferences.PlatformPreferences {
+
+        /**
+         * Specifies whether applications should minimize the amount of non-essential animations,
+         * reducing discomfort for users who experience motion sickness or vertigo.
+         * <p>
+         * If the platform does not report this preference, this property defaults to {@code false}.
+         *
+         * @return the {@code reducedMotion} property
+         * @defaultValue {@code false}
+         * @since 24
+         */
+        ReadOnlyBooleanProperty reducedMotionProperty();
+
+        boolean isReducedMotion();
+
+        /**
+         * Specifies whether applications should minimize the amount of transparent or translucent
+         * layer effects, which can help to increase contrast and readability for some users.
+         * <p>
+         * If the platform does not report this preference, this property defaults to {@code false}.
+         *
+         * @return the {@code reducedTransparency} property
+         * @defaultValue {@code false}
+         * @since 24
+         */
+        ReadOnlyBooleanProperty reducedTransparencyProperty();
+
+        boolean isReducedTransparency();
 
         /**
          * The platform color scheme, which specifies whether applications should prefer light text on
```
Comments
Looks good. I changed the risk from "minimal" to "low" since by sealing the interface, it breaks compatibility for an application that implemented the interface. This seems fine, and I can't imagine that any application would actually do this, since there is nothing useful they could do with their own implementation of Platform.Preferences. Now that it is sealed, further evolution should be "minimal" risk.
15-10-2024

Moving to Provisional.
07-10-2024