flutter icon indicating copy to clipboard operation
flutter copied to clipboard

Animation Duration is broken on Linux

Open synchronisator opened this issue 2 years ago • 14 comments

Steps to Reproduce

Create a new Flutter project. Replace the _MyHomePageState with the following code:

class _MyHomePageState extends State<MyHomePage> with SingleTickerProviderStateMixin{

  late AnimationController _playPauseController;
  bool _playing = false;

  @override
  void initState() {
    _playPauseController = AnimationController(
        vsync: this, duration: const Duration(seconds: 20));
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
            child: SizedBox(
              height: 30,
              child: FloatingActionButton(
                elevation: 2,
                onPressed: () {
                  if (_playing) {
                    _playPauseController.reverse();
                  } else {
                    _playPauseController.forward();
                  }
                  _playing = !_playing;
                },
                child: AnimatedIcon(
                  progress: _playPauseController,
                  icon: AnimatedIcons.play_pause,
                  size: 15,
                ),
              ),
            ),
      ),
    );
  }
}

Expected results: The Duration of 20 Seconds should be used for the animations on all plattforms.

Actual results: The Animationduration is correct on Android and in web. On Linux it is more a 2 second Duration.

The whole main.dart:

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        // This is the theme of your application.
        //
        // Try running your application with "flutter run". You'll see the
        // application has a blue toolbar. Then, without quitting the app, try
        // changing the primarySwatch below to Colors.green and then invoke
        // "hot reload" (press "r" in the console where you ran "flutter run",
        // or simply save your changes to "hot reload" in a Flutter IDE).
        // Notice that the counter didn't reset back to zero; the application
        // is not restarted.
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});

  // This widget is the home page of your application. It is stateful, meaning
  // that it has a State object (defined below) that contains fields that affect
  // how it looks.

  // This class is the configuration for the state. It holds the values (in this
  // case the title) provided by the parent (in this case the App widget) and
  // used by the build method of the State. Fields in a Widget subclass are
  // always marked "final".

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> with SingleTickerProviderStateMixin{

  late AnimationController _playPauseController;
  bool _playing = false;

  @override
  void initState() {
    _playPauseController = AnimationController(
        vsync: this, duration: const Duration(seconds: 20));
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
            child: SizedBox(
              height: 30,
              child: FloatingActionButton(
                elevation: 2,
                onPressed: () {
                  if (_playing) {
                    _playPauseController.reverse();
                  } else {
                    _playPauseController.forward();
                  }
                  _playing = !_playing;
                },
                child: AnimatedIcon(
                  progress: _playPauseController,
                  icon: AnimatedIcons.play_pause,
                  size: 15,
                ),
              ),
            ),
      ),
    );
  }
}

Direct compare between web (real 20 seconds) and Linux.

https://user-images.githubusercontent.com/10772789/205653316-6ef7bc31-45c2-4cca-8bb3-90b386df1db5.mp4

synchronisator avatar Dec 05 '22 12:12 synchronisator

Issue is unreproducible on my end (Arch Linux 6.0.10-arch2-1). Both works the same as it supposed to (20 seconds duration).

brainwo avatar Dec 05 '22 13:12 brainwo

My System is a Linux Mint 20 MATE 64-bit

synchronisator avatar Dec 05 '22 14:12 synchronisator

I can't repro it (Ubuntu 22.10). I tested on Flutter 3.0.5, 3.3.9 and master.

bleroux avatar Dec 06 '22 08:12 bleroux

@synchronisator Could you try re-creating a new project and reproducing it on there with the code sample you provided?

exaby73 avatar Dec 06 '22 08:12 exaby73

Absolutly. I recreated this issue in 3 different projects. One from scratch as i discribed in the description.

And my system looks good, i have not enabled any accessibility feature or something like that.

 ➜ flutter doctor   
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, 3.3.9, on Linux Mint 20 5.4.0-135-generic, locale de_DE.UTF-8)
[✓] Android toolchain - develop for Android devices (Android SDK version 30.0.3)
[✓] Chrome - develop for the web
[✓] Linux toolchain - develop for Linux desktop
[✓] Android Studio (version 2021.2)
[✓] IntelliJ IDEA Community Edition (version 2020.3)
[✓] IntelliJ IDEA Community Edition (version 2022.1)
[✓] VS Code (version 1.73.1)
[✓] Connected device (2 available)
[✓] HTTP Host Availability

• No issues found!

synchronisator avatar Dec 06 '22 08:12 synchronisator

Ok, i found a step: I ran into animation_controller.dart:584

    if (SemanticsBinding.instance.disableAnimations) {
      switch (animationBehavior) {
        case AnimationBehavior.normal:
          // Since the framework cannot handle zero duration animations, we run it at 5% of the normal
          // duration to limit most animations to a single frame.
          // Ideally, the framework would be able to handle zero duration animations, however, the common
          // pattern of an eternally repeating animation might cause an endless loop if it weren't delayed
          // for at least one frame.
          scale = 0.05;
          break;
        case AnimationBehavior.preserve:
          break;
      }
    }

so SemanticsBinding.instance.disableAnimations seams to be set. But i didnt set this...

synchronisator avatar Dec 06 '22 09:12 synchronisator

I can prevent this to happen if i set animationBehavior: AnimationBehavior.preserve but thats only a workaround. Where does this option came from, how is it set? I did not set something manually in this fresh and new project. My flutter-setting-files like ~/.flutter, ~/.flutter_settings or ~/.flutter_tool_state dont have anything set that looks like this... Where is flutter searching for this value in my system?

synchronisator avatar Dec 06 '22 09:12 synchronisator

You might have reduced animations set on the OS level. Could you check this? I am not familiar with the MATE desktop environment but maybe a quick Google search might help you

exaby73 avatar Dec 06 '22 14:12 exaby73

All gsettings that have something to do with animations are looking good:

 ➜ gsettings list-recursively | grep anim                 
org.cinnamon.desktop.interface enable-animations true
org.mate.interface gtk-enable-animations true
org.mate.interface enable-animations true
org.gnome.desktop.interface enable-animations true
org.mate.panel enable-animations true

synchronisator avatar Dec 06 '22 14:12 synchronisator

If you see the documentation for SemanticsBinding.instance.disableAnimations, it quotes:

The platform is requesting that animations be disabled or simplified.

This doesn't appear to be a Flutter issue since this is not reproducible on Ubuntu (Gnome) or Manjaro (KDE Plasma) as I have tested it

exaby73 avatar Dec 07 '22 06:12 exaby73

From the engine code, Flutter get this information by reading org.gnome.desktop.interface enable-animations property.

See:

  • https://github.com/flutter/engine/blob/8d83b98c55b3d0839de0c4201f5a8d56dbf92d2f/shell/platform/linux/fl_settings_portal.cc#L41-L45

  • https://github.com/flutter/engine/blob/8d83b98c55b3d0839de0c4201f5a8d56dbf92d2f/shell/platform/linux/fl_settings_portal.cc#L199-L210

Maybe on Linux Mate this can be set on an application basis? There seems to be Mate specific properties that might be in play, see https://askubuntu.com/questions/1332844/disable-all-mate-animations-in-ubuntu-mate-20-04.

bleroux avatar Dec 07 '22 07:12 bleroux

@bleroux Thanks for your answer. All my available options are set to enable animations:

 ➜ gsettings list-recursively | grep -e reduced-resources -e enable-animations
org.cinnamon.desktop.interface enable-animations true
org.mate.Marco.general reduced-resources false
org.mate.interface gtk-enable-animations true
org.mate.interface enable-animations true
org.gnome.metacity reduced-resources false
org.gnome.desktop.interface enable-animations true
org.mate.panel enable-animations true

Is it possible to debug this platform code? I see that it should work, like all of you said, but it does not work here. Additionally to your code i found https://github.com/flutter/engine/blob/5ca80bdb6284ebec0158b8dbf4474e821ead25ca/shell/platform/linux/fl_gnome_settings.cc#L66-L68 but this should also point in the right direction, so animations should be enabled. I have no clue why this is happening. And its reproducable in IDE and compiled Linux App. So its no problem with some strange IDE-Settings...

synchronisator avatar Dec 10 '22 20:12 synchronisator

Is it possible to debug this platform code? I see that it should work, like all of you said, but it does not work here.

Yes it is possible, to do so you have to compile the engine: https://github.com/flutter/flutter/wiki/Setting-up-the-Engine-development-environment. It is not as straightforward as debugging a Dart app or the framework code.

@jpnurmi Can we have your insight on this issue? OP is using Linux Mint MATE and found that SemanticsBinding.instance.disableAnimations returns true while gsettings seems to be ok (see https://github.com/flutter/flutter/issues/116511#issuecomment-1345373256).

bleroux avatar Dec 12 '22 07:12 bleroux

Hi @synchronisator, which xdg-desktop-portal-* packages does your system have installed, and what is the value of enable-animations in the response of the following settings portal dbus call?

gdbus call --session --dest org.freedesktop.portal.Desktop --object-path /org/freedesktop/portal/desktop --method org.freedesktop.portal.Settings.Read org.gnome.desktop.interface enable-animations

jpnurmi avatar Dec 12 '22 08:12 jpnurmi

@jpnurmi Thanks for your answer. Your command looks like this:

 ➜ gdbus call --session --dest org.freedesktop.portal.Desktop --object-path /org/freedesktop/portal/desktop --method org.freedesktop.portal.Settings.Read org.gnome.desktop.interface enable-animations
(<<false>>,)

And thats the opposite of this:

 ➜ gsettings list-recursively | grep 'org.gnome.desktop.interface enable-animations' 
org.gnome.desktop.interface enable-animations true

I dont understand why this is happening.

synchronisator avatar Dec 13 '22 09:12 synchronisator

Out of curiosity, I installed both Mint 20 and 21 last night and I found out that it works correctly in Mint 21. I suspect this was fixed by https://github.com/flatpak/xdg-desktop-portal-gtk/pull/281.

jpnurmi@mint-20:~$ gsettings get org.gnome.desktop.interface enable-animations
true
jpnurmi@mint-20:~$ gdbus call --session --dest org.freedesktop.portal.Desktop --object-path /org/freedesktop/portal/desktop --method org.freedesktop.portal.Settings.Read org.gnome.desktop.interface enable-animations
(<<false>>,)
jpnurmi@mint-21:~$ gsettings get org.gnome.desktop.interface enable-animations
true
jpnurmi@mint-21:~$ gdbus call --session --dest org.freedesktop.portal.Desktop --object-path /org/freedesktop/portal/desktop --method org.freedesktop.portal.Settings.Read org.gnome.desktop.interface enable-animations
(<<true>>,)

jpnurmi avatar Dec 13 '22 09:12 jpnurmi

Oh Wow. Thank you very much. So i think this ticket can be closed. Thanks for not closing this issue too early. On my own i would have never found out the real problem behind this.

synchronisator avatar Dec 13 '22 09:12 synchronisator

Many thanks @jpnurmi for your thorough insight and @synchronisator for your constructive feedbacks.

bleroux avatar Dec 13 '22 09:12 bleroux

This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of flutter doctor -v and a minimal reproduction of the issue.

github-actions[bot] avatar Mar 05 '23 00:03 github-actions[bot]