OK/Select on IR Remotes causing Exception

I am receiving this exception when pressing the OK/DPAD_CENTER button.
This is happening on two separate systems, on running Android 4.4 and the other Android 9.0.
Attempted to send a key down event when no keys are in keysPressed. This state can occur if the key event being sent doesn't properly set its modifier flags. This was the event: RawKeyDownEvent#065c6(logicalKey: LogicalKeyboardKey#70077(keyId: "0x100070077", keyLabel: "", debugName: "Select"), physicalKey: PhysicalKeyboardKey#700e4(usbHidUsage: "0x000700e4", debugName: "Control Right")) and its data: RawKeyEventDataAndroid(keyLabel:  flags: 8, codePoint: 0, keyCode: 23, scanCode: 97, metaState: 0, modifiers down: {})
'package:flutter/src/services/raw_keyboard.dart':
Failed assertion: line 601 pos 12: '<optimized out>'

This happens on stable through to master
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel master, 1.22.0-10.0.pre.82, on Linux, locale en_AU.UTF-8)
[✓] Android toolchain - develop for Android devices (Android SDK version 29.0.3)
[✓] Chrome - develop for the web
[✓] Android Studio (version 4.0)
[✓] Connected device (3 available)
• No issues found!
Very simple test app
import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData(
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({
    Key key,
  }) : super(key: key);

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Container(
        color: Colors.green,
        child: Row(
          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
          mainAxisSize: MainAxisSize.max,
          crossAxisAlignment: CrossAxisAlignment.center,
          children: [

            MaterialButton(
              child: Text('click me'),
              onPressed: () => print('Pressed'),
            ),
            MaterialButton(
              child: Text('click me'),
              onPressed: () => print('Pressed'),
            ),
            MaterialButton(
              child: Text('click me'),
              onPressed: () => print('Pressed'),
            ),
            MaterialButton(
              child: Text('click me'),
              onPressed: () => print('Pressed'),
            ),
          ],
        ));
  }
}

Hi @clarkap
Can you please provide your flutter doctor -v, your flutter run --verbose?
Thank you

[✓] Flutter (Channel master, 1.22.0-10.0.pre.82, on Linux, locale en_AU.UTF-8)
• Flutter version 1.22.0-10.0.pre.82 at /home/andyc/Applications/flutter/flutter
• Framework revision 9248fda410 (3 days ago), 2020-09-03 16:08:01 -0700
• Engine revision 3f05b521b9
• Dart version 2.10.0 (build 2.10.0-86.0.dev)
[✓] Android toolchain - develop for Android devices (Android SDK version 29.0.3)
• Android SDK at /home/andyc/Android/Sdk
• Platform android-29, build-tools 29.0.3
• Java binary at: /snap/android-studio/91/android-studio/jre/bin/java
• Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b3-6222593)
• All Android licenses accepted.
[✓] Chrome - develop for the web
• Chrome at google-chrome
[✓] Android Studio (version 4.0)
• Android Studio at /snap/android-studio/91/android-studio
• Flutter plugin version 46.0.2
• Dart plugin version 193.7361
• Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b3-6222593)
[✓] Connected device (3 available)
• XS (mobile)      • <IP_ADDRESS>:5555 • android-arm    • Android 4.4.2 (API 19)
• Web Server (web) • web-server          • web-javascript • Flutter Tools
• Chrome (web)     • chrome              • web-javascript • Google Chrome 84.0.4147.135
• No issues found!

[  +72 ms] executing: [/home/andyc/Applications/flutter/flutter/] git -c log.showSignature=false log -n 1 --pretty=format:%H
[  +20 ms] Exit code 0 from: git -c log.showSignature=false log -n 1 --pretty=format:%H
[        ] 9248fda41005ce0af2e522fabd0e9fedf2b3c863
[        ] executing: [/home/andyc/Applications/flutter/flutter/] git tag --points-at HEAD
[   +7 ms] Exit code 0 from: git tag --points-at HEAD
[        ] executing: [/home/andyc/Applications/flutter/flutter/] git describe --match ..* --first-parent --long --tags
[  +16 ms] Exit code 0 from: git describe --match ..* --first-parent --long --tags
[        ] 1.22.0-9.0.pre-82-g9248fda410
[   +5 ms] executing: [/home/andyc/Applications/flutter/flutter/] git rev-parse --abbrev-ref --symbolic @{u}
[   +3 ms] Exit code 0 from: git rev-parse --abbrev-ref --symbolic @{u}
[        ] origin/master
[        ] executing: [/home/andyc/Applications/flutter/flutter/] git ls-remote --get-url origin
[   +2 ms] Exit code 0 from: git ls-remote --get-url origin
[        ] https://github.com/flutter/flutter.git
[  +23 ms] executing: [/home/andyc/Applications/flutter/flutter/] git rev-parse --abbrev-ref HEAD
[   +3 ms] Exit code 0 from: git rev-parse --abbrev-ref HEAD
[        ] master
[  +25 ms] Artifact Instance of 'AndroidMavenArtifacts' is not required, skipping update.
[        ] Artifact Instance of 'AndroidGenSnapshotArtifacts' is not required, skipping update.
[        ] Artifact Instance of 'AndroidInternalBuildArtifacts' is not required, skipping update.
[        ] Artifact Instance of 'IOSEngineArtifacts' is not required, skipping update.
[        ] Artifact Instance of 'FlutterWebSdk' is not required, skipping update.
[   +1 ms] Artifact Instance of 'WindowsEngineArtifacts' is not required, skipping update.
[        ] Artifact Instance of 'MacOSEngineArtifacts' is not required, skipping update.
[        ] Artifact Instance of 'LinuxEngineArtifacts' is not required, skipping update.
[        ] Artifact Instance of 'LinuxFuchsiaSDKArtifacts' is not required, skipping update.
[        ] Artifact Instance of 'MacOSFuchsiaSDKArtifacts' is not required, skipping update.
[        ] Artifact Instance of 'FlutterRunnerSDKArtifacts' is not required, skipping update.
[        ] Artifact Instance of 'FlutterRunnerDebugSymbols' is not required, skipping update.
[   +8 ms] executing: /home/andyc/Android/Sdk/platform-tools/adb devices -l
[  +22 ms] List of devices attached
<IP_ADDRESS>:5555    device product:stvm8b model:XS device:stvm8b transport_id:3
[   +9 ms] /home/andyc/Android/Sdk/platform-tools/adb -s <IP_ADDRESS>:5555 shell getprop
[ +155 ms] Artifact Instance of 'AndroidMavenArtifacts' is not required, skipping update.
[  +10 ms] Artifact Instance of 'AndroidInternalBuildArtifacts' is not required, skipping update.
[        ] Artifact Instance of 'IOSEngineArtifacts' is not required, skipping update.
[  +10 ms] Downloading Web SDK...
[+3918 ms] Downloading Web SDK... (completed in 3.9s)
[        ] executing: unzip -o -q /home/andyc/Applications/flutter/flutter/bin/cache/downloads/storage.googleapis.com/flutter_infra/flutter/3f05b521b939b4a9c33481b6f58a840babefa775/flutter-web-sdk-linux-x64.zip -d
/home/andyc/Applications/flutter/flutter/bin/cache/flutter_web_sdk
[ +473 ms] Exit code 0 from: unzip -o -q /home/andyc/Applications/flutter/flutter/bin/cache/downloads/storage.googleapis.com/flutter_infra/flutter/3f05b521b939b4a9c33481b6f58a840babefa775/flutter-web-sdk-linux-x64.zip -d
/home/andyc/Applications/flutter/flutter/bin/cache/flutter_web_sdk
[ +171 ms] Artifact Instance of 'WindowsEngineArtifacts' is not required, skipping update.
[        ] Artifact Instance of 'MacOSEngineArtifacts' is not required, skipping update.
[        ] Artifact Instance of 'LinuxEngineArtifacts' is not required, skipping update.
[        ] Artifact Instance of 'LinuxFuchsiaSDKArtifacts' is not required, skipping update.
[        ] Artifact Instance of 'MacOSFuchsiaSDKArtifacts' is not required, skipping update.
[        ] Artifact Instance of 'FlutterRunnerSDKArtifacts' is not required, skipping update.
[        ] Artifact Instance of 'FlutterRunnerDebugSymbols' is not required, skipping update.
[ +115 ms] Generating /home/andyc/Workspaces/tv_launcher/android/app/src/main/java/io/flutter/plugins/GeneratedPluginRegistrant.java
[  +11 ms] ro.hardware = amlogic
[        ] ro.build.characteristics = tablet
[  +22 ms] Starting incremental build...
[   +1 ms] Initializing file store
[   +7 ms] Skipping target: gen_localizations
[   +5 ms] complete
[   +2 ms] Launching lib/main.dart on XS in debug mode...
[   +3 ms] /home/andyc/Applications/flutter/flutter/bin/cache/dart-sdk/bin/dart --disable-dart-dev /home/andyc/Applications/flutter/flutter/bin/cache/artifacts/engine/linux-x64/frontend_server.dart.snapshot --sdk-root
/home/andyc/Applications/flutter/flutter/bin/cache/artifacts/engine/common/flutter_patched_sdk/ --incremental --target=flutter --debugger-module-names --experimental-emit-debug-metadata -Ddart.developer.causal_async_stacks=true
--output-dill /tmp/flutter_tools.FUMYPZ/flutter_tool.NYTSIM/app.dill --packages .packages -Ddart.vm.profile=false -Ddart.vm.product=false
--bytecode-options=source-positions,local-var-info,debugger-stops,instance-field-initializers,keep-unreachable-code,avoid-closure-call-instructions --enable-asserts --track-widget-creation --filesystem-scheme org-dartlang-root
--initialize-from-dill build/cache.dill.track.dill
[   +6 ms] executing: /home/andyc/Android/Sdk/build-tools/29.0.3/aapt dump xmltree /home/andyc/Workspaces/tv_launcher/build/app/outputs/flutter-apk/app.apk AndroidManifest.xml
[   +6 ms] Exit code 0 from: /home/andyc/Android/Sdk/build-tools/29.0.3/aapt dump xmltree /home/andyc/Workspaces/tv_launcher/build/app/outputs/flutter-apk/app.apk AndroidManifest.xml
[        ] N: android=http://schemas.android.com/apk/res/android
E: manifest (line=2)
A: android:versionCode(0x0101021b)=(type 0x10)0x1
A: android:versionName(0x0101021c)="1.0.0" (Raw: "1.0.0")
A: android:compileSdkVersion(0x01010572)=(type 0x10)0x1c
A: android:compileSdkVersionCodename(0x01010573)="9" (Raw: "9")
A: package="com.swiftmedia.tvlauncher" (Raw: "com.swiftmedia.tvlauncher")
A: platformBuildVersionCode=(type 0x10)0x1c
A: platformBuildVersionName=(type 0x10)0x9
E: uses-sdk (line=7)
A: android:minSdkVersion(0x0101020c)=(type 0x10)0x10
A: android:targetSdkVersion(0x01010270)=(type 0x10)0x1c
E: uses-permission (line=14)
A: android:name(0x01010003)="android.permission.INTERNET" (Raw: "android.permission.INTERNET")
E: application (line=22)
A: android:label(0x01010001)="tvlauncher" (Raw: "tvlauncher")
A: android:icon(0x01010002)=@0x7f080000
A: android:name(0x01010003)="io.flutter.app.FlutterApplication" (Raw: "io.flutter.app.FlutterApplication")
A: android:debuggable(0x0101000f)=(type 0x12)0xffffffff
A: android:appComponentFactory(0x0101057a)="androidx.core.app.CoreComponentFactory" (Raw: "androidx.core.app.CoreComponentFactory")
E: activity (line=28)
A: android:theme(0x01010000)=@0x7f0a0000
A: android:name(0x01010003)="com.swiftmedia.tvlauncher.MainActivity" (Raw: "com.swiftmedia.tvlauncher.MainActivity")
A: android:launchMode(0x0101001d)=(type 0x10)0x1
A: android:configChanges(0x0101001f)=(type 0x11)0x40003fb4
A: android:windowSoftInputMode(0x0101022b)=(type 0x11)0x10
A: android:hardwareAccelerated(0x010102d3)=(type 0x12)0xffffffff
E: meta-data (line=42)
A: android:name(0x01010003)="io.flutter.embedding.android.NormalTheme" (Raw: "io.flutter.embedding.android.NormalTheme")
A: android:resource(0x01010025)=@0x7f0a0001
E: meta-data (line=52)
A: android:name(0x01010003)="io.flutter.embedding.android.SplashScreenDrawable" (Raw: "io.flutter.embedding.android.SplashScreenDrawable")
A: android:resource(0x01010025)=@0x7f040000
E: intent-filter (line=56)
E: action (line=57)
A: android:name(0x01010003)="android.intent.action.MAIN" (Raw: "android.intent.action.MAIN")
E: category (line=59)
A: android:name(0x01010003)="android.intent.category.LAUNCHER" (Raw: "android.intent.category.LAUNCHER")
E: meta-data (line=66)
A: android:name(0x01010003)="flutterEmbedding" (Raw: "flutterEmbedding")
A: android:value(0x01010024)=(type 0x10)0x2
[   +9 ms] <- compile package:tvlauncher/main.dart
[  +10 ms] executing: /home/andyc/Android/Sdk/platform-tools/adb version
[   +5 ms] Android Debug Bridge version 1.0.41
Version 30.0.3-6597393
Installed as /home/andyc/Android/Sdk/platform-tools/adb
[   +1 ms] executing: /home/andyc/Android/Sdk/platform-tools/adb start-server
[   +5 ms] Building APK
[  +11 ms] Running Gradle task 'assembleDebug'...
[        ] gradle.properties already sets android.enableR8
[   +1 ms] Using gradle from /home/andyc/Workspaces/tv_launcher/android/gradlew.
[        ] /home/andyc/Workspaces/tv_launcher/android/gradlew mode: 33277 rwxrwxr-x.
[   +3 ms] executing: /snap/android-studio/91/android-studio/jre/bin/java -version
[  +40 ms] Exit code 0 from: /snap/android-studio/91/android-studio/jre/bin/java -version
[        ] openjdk version "1.8.0_242-release"
OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b3-6222593)
OpenJDK 64-Bit Server VM (build 25.242-b3-6222593, mixed mode)
[   +2 ms] executing: [/home/andyc/Workspaces/tv_launcher/android/] /home/andyc/Workspaces/tv_launcher/android/gradlew -Pverbose=true -Ptarget-platform=android-arm -Ptarget=/home/andyc/Workspaces/tv_launcher/lib/main.dart
-Ptrack-widget-creation=true -Pfilesystem-scheme=org-dartlang-root assembleDebug
[ +347 ms] Starting a Gradle Daemon (subsequent builds will be faster)
[+5990 ms] > Task :app:compileFlutterBuildDebug
[        ] [  +76 ms] executing: [/home/andyc/Applications/flutter/flutter/] git -c log.showSignature=false log -n 1 --pretty=format:%H
[        ] [  +19 ms] Exit code 0 from: git -c log.showSignature=false log -n 1 --pretty=format:%H
[        ] [        ] 9248fda41005ce0af2e522fabd0e9fedf2b3c863
[        ] [        ] executing: [/home/andyc/Applications/flutter/flutter/] git tag --points-at HEAD
[        ] [   +8 ms] Exit code 0 from: git tag --points-at HEAD
[        ] [   +1 ms] executing: [/home/andyc/Applications/flutter/flutter/] git describe --match ..* --first-parent --long --tags
[        ] [  +17 ms] Exit code 0 from: git describe --match ..* --first-parent --long --tags
[        ] [        ] 1.22.0-9.0.pre-82-g9248fda410
[        ] [   +7 ms] executing: [/home/andyc/Applications/flutter/flutter/] git rev-parse --abbrev-ref --symbolic @{u}
[        ] [   +3 ms] Exit code 0 from: git rev-parse --abbrev-ref --symbolic @{u}
[        ] [        ] origin/master
[        ] [        ] executing: [/home/andyc/Applications/flutter/flutter/] git ls-remote --get-url origin
[        ] [   +2 ms] Exit code 0 from: git ls-remote --get-url origin
[        ] [        ] https://github.com/flutter/flutter.git
[        ] [  +28 ms] executing: [/home/andyc/Applications/flutter/flutter/] git rev-parse --abbrev-ref HEAD
[        ] [   +3 ms] Exit code 0 from: git rev-parse --abbrev-ref HEAD
[        ] [        ] master
[        ] [  +32 ms] Artifact Instance of 'AndroidMavenArtifacts' is not required, skipping update.
[        ] [        ] Artifact Instance of 'AndroidGenSnapshotArtifacts' is not required, skipping update.
[        ] [        ] Artifact Instance of 'AndroidInternalBuildArtifacts' is not required, skipping update.
[        ] [        ] Artifact Instance of 'IOSEngineArtifacts' is not required, skipping update.
[        ] [        ] Artifact Instance of 'FlutterWebSdk' is not required, skipping update.
[        ] [   +1 ms] Artifact Instance of 'WindowsEngineArtifacts' is not required, skipping update.
[        ] [        ] Artifact Instance of 'MacOSEngineArtifacts' is not required, skipping update.
[        ] [        ] Artifact Instance of 'LinuxEngineArtifacts' is not required, skipping update.
[        ] [        ] Artifact Instance of 'LinuxFuchsiaSDKArtifacts' is not required, skipping update.
[        ] [        ] Artifact Instance of 'MacOSFuchsiaSDKArtifacts' is not required, skipping update.
[        ] [        ] Artifact Instance of 'FlutterRunnerSDKArtifacts' is not required, skipping update.
[        ] [        ] Artifact Instance of 'FlutterRunnerDebugSymbols' is not required, skipping update.
[        ] [   +5 ms] Artifact Instance of 'MaterialFonts' is not required, skipping update.
[        ] [        ] Artifact Instance of 'GradleWrapper' is not required, skipping update.
[        ] [        ] Artifact Instance of 'AndroidMavenArtifacts' is not required, skipping update.
[        ] [        ] Artifact Instance of 'AndroidGenSnapshotArtifacts' is not required, skipping update.
[        ] [        ] Artifact Instance of 'AndroidInternalBuildArtifacts' is not required, skipping update.
[        ] [        ] Artifact Instance of 'IOSEngineArtifacts' is not required, skipping update.
[        ] [        ] Artifact Instance of 'FlutterWebSdk' is not required, skipping update.
[        ] [        ] Artifact Instance of 'FlutterSdk' is not required, skipping update.
[        ] [        ] Artifact Instance of 'WindowsEngineArtifacts' is not required, skipping update.
[        ] [        ] Artifact Instance of 'MacOSEngineArtifacts' is not required, skipping update.
[        ] [        ] Artifact Instance of 'LinuxEngineArtifacts' is not required, skipping update.
[        ] [        ] Artifact Instance of 'LinuxFuchsiaSDKArtifacts' is not required, skipping update.
[        ] [        ] Artifact Instance of 'MacOSFuchsiaSDKArtifacts' is not required, skipping update.
[        ] [        ] Artifact Instance of 'FlutterRunnerSDKArtifacts' is not required, skipping update.
[        ] [        ] Artifact Instance of 'FlutterRunnerDebugSymbols' is not required, skipping update.
[        ] [        ] Artifact Instance of 'IosUsbArtifacts' is not required, skipping update.
[        ] [        ] Artifact Instance of 'IosUsbArtifacts' is not required, skipping update.
[        ] [        ] Artifact Instance of 'IosUsbArtifacts' is not required, skipping update.
[        ] [        ] Artifact Instance of 'IosUsbArtifacts' is not required, skipping update.
[        ] [        ] Artifact Instance of 'IosUsbArtifacts' is not required, skipping update.
[        ] [        ] Artifact Instance of 'FontSubsetArtifacts' is not required, skipping update.
[        ] [  +47 ms] Initializing file store
[        ] [   +6 ms] Done initializing file store
[        ] [  +19 ms] Skipping target: gen_localizations
[        ] [ +461 ms] kernel_snapshot: Starting due to {InvalidatedReason.inputChanged}
[        ] [  +15 ms] /home/andyc/Applications/flutter/flutter/bin/cache/dart-sdk/bin/dart --disable-dart-dev /home/andyc/Applications/flutter/flutter/bin/cache/artifacts/engine/linux-x64/frontend_server.dart.snapshot --sdk-root
/home/andyc/Applications/flutter/flutter/bin/cache/artifacts/engine/common/flutter_patched_sdk/ --target=flutter -Ddart.developer.causal_async_stacks=true -Ddart.vm.profile=false -Ddart.vm.product=false
--bytecode-options=source-positions,local-var-info,debugger-stops,instance-field-initializers,keep-unreachable-code,avoid-closure-call-instructions --enable-asserts --track-widget-creation --no-link-platform --packages
/home/andyc/Workspaces/tv_launcher/.packages --output-dill /home/andyc/Workspaces/tv_launcher/.dart_tool/flutter_build/426b7d87e351d73ba923fdfd544302b0/app.dill --depfile
/home/andyc/Workspaces/tv_launcher/.dart_tool/flutter_build/426b7d87e351d73ba923fdfd544302b0/kernel_snapshot.d package:tvlauncher/main.dart
[+3594 ms] [+4666 ms] kernel_snapshot: Complete
[ +600 ms] [ +537 ms] debug_android_application: Starting due to {InvalidatedReason.inputChanged}
[  +99 ms] [  +97 ms] debug_android_application: Complete
[ +300 ms] [ +278 ms] Persisting file store
[        ] [   +3 ms] Done persisting file store
[        ] [   +3 ms] build succeeded.
[        ] [   +6 ms] "flutter assemble" took 6,161ms.
[        ] [   +2 ms] ensureAnalyticsSent: 0ms
[        ] [        ] Running shutdown hooks
[        ] [        ] Shutdown hooks complete
[        ] [        ] exiting with code 0
[  +99 ms] > Task :app:packLibsflutterBuildDebug UP-TO-DATE
[        ] > Task :app:preBuild UP-TO-DATE
[        ] > Task :app:preDebugBuild UP-TO-DATE
[        ] > Task :app:checkDebugManifest UP-TO-DATE
[        ] > Task :app:generateDebugBuildConfig UP-TO-DATE
[        ] > Task :app:compileDebugAidl NO-SOURCE
[        ] > Task :app:compileDebugRenderscript NO-SOURCE
[        ] > Task :app:cleanMergeDebugAssets
[        ] > Task :app:mergeDebugShaders UP-TO-DATE
[        ] > Task :app:compileDebugShaders UP-TO-DATE
[        ] > Task :app:generateDebugAssets UP-TO-DATE
[        ] > Task :app:mergeDebugAssets
[ +198 ms] > Task :app:copyFlutterAssetsDebug
[        ] > Task :app:mainApkListPersistenceDebug UP-TO-DATE
[        ] > Task :app:generateDebugResValues UP-TO-DATE
[        ] > Task :app:generateDebugResources UP-TO-DATE
[        ] > Task :app:mergeDebugResources UP-TO-DATE
[        ] > Task :app:createDebugCompatibleScreenManifests UP-TO-DATE
[        ] > Task :app:processDebugManifest UP-TO-DATE
[        ] > Task :app:processDebugResources UP-TO-DATE
[ +199 ms] > Task :app:compileDebugKotlin UP-TO-DATE
[        ] > Task :app:javaPreCompileDebug UP-TO-DATE
[        ] > Task :app:compileDebugJavaWithJavac UP-TO-DATE
[        ] > Task :app:compileDebugSources UP-TO-DATE
[        ] > Task :app:processDebugJavaRes NO-SOURCE
[        ] > Task :app:mergeDebugJavaResource UP-TO-DATE
[        ] > Task :app:checkDebugDuplicateClasses UP-TO-DATE
[        ] > Task :app:desugarDebugFileDependencies UP-TO-DATE
[  +99 ms] > Task :app:mergeExtDexDebug UP-TO-DATE
[        ] > Task :app:transformClassesWithDexBuilderForDebug UP-TO-DATE
[        ] > Task :app:mergeDexDebug UP-TO-DATE
[        ] > Task :app:validateSigningDebug UP-TO-DATE
[        ] > Task :app:signingConfigWriterDebug UP-TO-DATE
[        ] > Task :app:mergeDebugJniLibFolders UP-TO-DATE
[        ] > Task :app:mergeDebugNativeLibs UP-TO-DATE
[        ] > Task :app:stripDebugDebugSymbols UP-TO-DATE
[        ] Compatible side by side NDK version was not found.
[+1099 ms] > Task :app:packageDebug
[  +76 ms] > Task :app:assembleDebug
[        ] BUILD SUCCESSFUL in 12s
[        ] 31 actionable tasks: 6 executed, 25 up-to-date
[ +324 ms] Running Gradle task 'assembleDebug'... (completed in 13.1s)
[  +29 ms] calculateSha: LocalDirectory: '/home/andyc/Workspaces/tv_launcher/build/app/outputs/flutter-apk'/app.apk
[  +41 ms] calculateSha: reading file took 40us
[ +461 ms] calculateSha: computing sha took 461us
[   +2 ms] ✓ Built build/app/outputs/flutter-apk/app-debug.apk.
[   +1 ms] executing: /home/andyc/Android/Sdk/build-tools/29.0.3/aapt dump xmltree /home/andyc/Workspaces/tv_launcher/build/app/outputs/flutter-apk/app.apk AndroidManifest.xml
[   +5 ms] Exit code 0 from: /home/andyc/Android/Sdk/build-tools/29.0.3/aapt dump xmltree /home/andyc/Workspaces/tv_launcher/build/app/outputs/flutter-apk/app.apk AndroidManifest.xml
[        ] N: android=http://schemas.android.com/apk/res/android
E: manifest (line=2)
A: android:versionCode(0x0101021b)=(type 0x10)0x1
A: android:versionName(0x0101021c)="1.0.0" (Raw: "1.0.0")
A: android:compileSdkVersion(0x01010572)=(type 0x10)0x1c
A: android:compileSdkVersionCodename(0x01010573)="9" (Raw: "9")
A: package="com.swiftmedia.tvlauncher" (Raw: "com.swiftmedia.tvlauncher")
A: platformBuildVersionCode=(type 0x10)0x1c
A: platformBuildVersionName=(type 0x10)0x9
E: uses-sdk (line=7)
A: android:minSdkVersion(0x0101020c)=(type 0x10)0x10
A: android:targetSdkVersion(0x01010270)=(type 0x10)0x1c
E: uses-permission (line=14)
A: android:name(0x01010003)="android.permission.INTERNET" (Raw: "android.permission.INTERNET")
E: application (line=22)
A: android:label(0x01010001)="tvlauncher" (Raw: "tvlauncher")
A: android:icon(0x01010002)=@0x7f080000
A: android:name(0x01010003)="io.flutter.app.FlutterApplication" (Raw: "io.flutter.app.FlutterApplication")
A: android:debuggable(0x0101000f)=(type 0x12)0xffffffff
A: android:appComponentFactory(0x0101057a)="androidx.core.app.CoreComponentFactory" (Raw: "androidx.core.app.CoreComponentFactory")
E: activity (line=28)
A: android:theme(0x01010000)=@0x7f0a0000
A: android:name(0x01010003)="com.swiftmedia.tvlauncher.MainActivity" (Raw: "com.swiftmedia.tvlauncher.MainActivity")
A: android:launchMode(0x0101001d)=(type 0x10)0x1
A: android:configChanges(0x0101001f)=(type 0x11)0x40003fb4
A: android:windowSoftInputMode(0x0101022b)=(type 0x11)0x10
A: android:hardwareAccelerated(0x010102d3)=(type 0x12)0xffffffff
E: meta-data (line=42)
A: android:name(0x01010003)="io.flutter.embedding.android.NormalTheme" (Raw: "io.flutter.embedding.android.NormalTheme")
A: android:resource(0x01010025)=@0x7f0a0001
E: meta-data (line=52)
A: android:name(0x01010003)="io.flutter.embedding.android.SplashScreenDrawable" (Raw: "io.flutter.embedding.android.SplashScreenDrawable")
A: android:resource(0x01010025)=@0x7f040000
E: intent-filter (line=56)
E: action (line=57)
A: android:name(0x01010003)="android.intent.action.MAIN" (Raw: "android.intent.action.MAIN")
E: category (line=59)
A: android:name(0x01010003)="android.intent.category.LAUNCHER" (Raw: "android.intent.category.LAUNCHER")
E: meta-data (line=66)
A: android:name(0x01010003)="flutterEmbedding" (Raw: "flutterEmbedding")
A: android:value(0x01010024)=(type 0x10)0x2
[        ] Stopping app 'app.apk' on XS.
[        ] executing: /home/andyc/Android/Sdk/platform-tools/adb -s <IP_ADDRESS>:5555 shell am force-stop com.swiftmedia.tvlauncher
[ +991 ms] executing: /home/andyc/Android/Sdk/platform-tools/adb -s <IP_ADDRESS>:5555 shell pm list packages com.swiftmedia.tvlauncher
[ +962 ms] package:/data/app/com.swiftmedia.tvlauncher-1.apk=com.swiftmedia.tvlauncher
[   +2 ms] Installing APK.
[   +2 ms] executing: /home/andyc/Android/Sdk/platform-tools/adb version
[   +4 ms] Android Debug Bridge version 1.0.41
Version 30.0.3-6597393
Installed as /home/andyc/Android/Sdk/platform-tools/adb
[        ] executing: /home/andyc/Android/Sdk/platform-tools/adb start-server
[   +3 ms] Installing build/app/outputs/flutter-apk/app.apk...
[        ] executing: /home/andyc/Android/Sdk/platform-tools/adb -s <IP_ADDRESS>:5555 install -t -r /home/andyc/Workspaces/tv_launcher/build/app/outputs/flutter-apk/app.apk
[+34548 ms] Performing Push Install
/home/andyc/Workspaces/tv_launcher/build/app/outputs/flutter-apk/app.apk: 1 file pushed, 0 skipped. 3.0 MB/s (49756697 bytes in 16.017s)
pkg: /data/local/tmp/app.apk
Success
[        ] Installing build/app/outputs/flutter-apk/app.apk... (completed in 34.5s)
[   +4 ms] executing: /home/andyc/Android/Sdk/platform-tools/adb -s <IP_ADDRESS>:5555 shell echo -n 2ecc6a9d957b1899079aa9d59bc8fff109a8f850 > /data/local/tmp/sky.com.swiftmedia.tvlauncher.sha1
[  +17 ms] XS startApp
[   +1 ms] executing: /home/andyc/Android/Sdk/platform-tools/adb -s <IP_ADDRESS>:5555 shell am start -a android.intent.action.RUN -f 0x20000000 --ez enable-background-compilation true --ez enable-dart-profiling true --ez
enable-checked-mode true --ez verify-entry-points true com.swiftmedia.tvlauncher/com.swiftmedia.tvlauncher.MainActivity
[+1250 ms] Starting: Intent { act=android.intent.action.RUN flg=0x20000000 cmp=com.swiftmedia.tvlauncher/.MainActivity (has extras) }
[        ] Waiting for observatory port to be available...
[+3591 ms] Observatory URL on device: http://<IP_ADDRESS>:55562/EaaVtqrjAPQ=/
[   +1 ms] executing: /home/andyc/Android/Sdk/platform-tools/adb -s <IP_ADDRESS>:5555 forward tcp:0 tcp:55562
[   +8 ms] 38077
[        ] Forwarded host port 38077 to device port 55562 for Observatory
[   +7 ms] Caching compiled dill
[  +49 ms] Connecting to service protocol: http://<IP_ADDRESS>:38077/EaaVtqrjAPQ=/
[        ] DDS is currently disabled due to https://github.com/flutter/flutter/issues/62507
[+1034 ms] Successfully connected to service protocol: http://<IP_ADDRESS>:38077/EaaVtqrjAPQ=/
[        ] Waiting for XS to report its views...
[  +10 ms] Waiting for XS to report its views... (completed in 9ms)
[  +59 ms] DevFS: Creating new filesystem on the device (null)
[ +501 ms] DevFS: Created new filesystem on the device (file:///data/data/com.swiftmedia.tvlauncher/cache/tv_launcherTRUUPH/tv_launcher/)
[   +5 ms] Updating assets
[  +44 ms] Syncing files to device XS...
[   +1 ms] Scanning asset files
[   +1 ms] <- reset
[        ] Compiling dart to kernel with 0 updated files
[        ] <- recompile package:tvlauncher/main.dart 01aac069-3748-44bc-9719-bb9cc58f4bab
[        ] <- 01aac069-3748-44bc-9719-bb9cc58f4bab
[  +58 ms] Updating files
[ +525 ms] DevFS: Sync finished
[        ] Syncing files to device XS... (completed in 588ms)
[        ] Synced 1.7MB.
[        ] <- accept
[   +8 ms] Connected to _flutterView/0x68ffb518.
[   +1 ms] Flutter run key commands.
[   +1 ms] r Hot reload. 🔥🔥🔥
[        ] R Hot restart.
[        ] h Repeat this help message.
[        ] d Detach (terminate "flutter run" but leave application running).
[        ] c Clear the screen
[        ] q Quit (terminate the application on the device).
[        ] An Observatory debugger and profiler on XS is available at: http://<IP_ADDRESS>:38077/EaaVtqrjAPQ=/
[+9118 ms] I/flutter ( 4498): ══╡ EXCEPTION CAUGHT BY SERVICES LIBRARY ╞══════════════════════════════════════════════════════════
[        ] I/flutter ( 4498): The following assertion was thrown during a platform message callback:
[        ] I/flutter ( 4498): Attempted to send a key down event when no keys are in keysPressed. This state can occur if the key
[        ] I/flutter ( 4498): event being sent doesn't properly set its modifier flags. This was the event:
[        ] I/flutter ( 4498): RawKeyDownEvent#8eca7(logicalKey: LogicalKeyboardKey#70077(keyId: "0x100070077", keyLabel: "",
[        ] I/flutter ( 4498): debugName: "Select"), physicalKey: PhysicalKeyboardKey#700e4(usbHidUsage: "0x000700e4", debugName:
[        ] I/flutter ( 4498): "Control Right")) and its data: RawKeyEventDataAndroid(keyLabel:  flags: 8, codePoint: 0, keyCode:
[        ] I/flutter ( 4498): 23, scanCode: 97, metaState: 0, modifiers down: {})
[        ] I/flutter ( 4498): 'package:flutter/src/services/raw_keyboard.dart':
[        ] I/flutter ( 4498): Failed assertion: line 601 pos 12: ''
[        ] I/flutter ( 4498): Either the assertion indicates an error in the framework itself, or we should provide substantially
[        ] I/flutter ( 4498): more information in this error message to help you determine and fix the underlying cause.
[        ] I/flutter ( 4498): In either case, please report this assertion by filing a bug on GitHub:
[        ] I/flutter ( 4498):   https://github.com/flutter/flutter/issues/new?template=BUG.md
[        ] I/flutter ( 4498): When the exception was thrown, this was the stack:
[        ] I/flutter ( 4498): #2      RawKeyboard._handleKeyEvent (package:flutter/src/services/raw_keyboard.dart:601:12)
[        ] I/flutter ( 4498): #3      BasicMessageChannel.setMessageHandler. (package:flutter/src/services/platform_channel.dart:74:49)
[        ] I/flutter ( 4498): #4      _DefaultBinaryMessenger.handlePlatformMessage (package:flutter/src/services/binding.dart:283:33)
[        ] I/flutter ( 4498): #5      _invoke3. (dart:ui/hooks.dart:280:15)
[        ] I/flutter ( 4498): #9      _invoke3 (dart:ui/hooks.dart:279:10)
[        ] I/flutter ( 4498): #10     _dispatchPlatformMessage (dart:ui/hooks.dart:154:5)
[        ] I/flutter ( 4498): (elided 5 frames from class _AssertionError and dart:async)
[   +3 ms] I/flutter ( 4498): ════════════════════════════════════════════════════════════════════════════════════════════════════

For some reason I'm not able to create an emulator with Directional Pad on Android Studio 4.0. So this will need additional triage.

To clarify,
The button works fine from the emulator dpad.  It is from a real set top ir
remote that it fails.
Works fine from Android apps though.
I hope this clarifies things for you.
Sent from my Nexus 5
On Mon, 7 Sep 2020, 4:38 pm Pedro Massango<EMAIL_ADDRESS>wrote:

For some reason I'm not able to create an emulator with Directional Pad on
Android Studio 4.0. So this will need additional triage.
[image: Screen Shot 2020-09-07 at 09 34 29]
https://user-images.githubusercontent.com/67424416/92366692-66277a00-f0ed-11ea-8280-9cb8cd6c57c4.png
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/flutter/flutter/issues/65233#issuecomment-688165921,
or unsubscribe
https://github.com/notifications/unsubscribe-auth/ABOB4WEXBA3URGYP73MQYL3SESL2BANCNFSM4QXN4HFQ
.

Thanks for making it clear

CC @jason-simmons

cc @gspencergoog

I don't have access to an actual Android TV to try this on, unfortunately.
@clarkap would you be willing to add some code to your Flutter repo so I can see what the key information being sent is?
If you could add the following just before the call to _synchronizeModifiers in flutter/packages/flutter/lib/src/services/raw_keyboard.dart, and then rebuild your app and post what the log prints when you press the OK/Select button, that would give me a lot more to go on.
    print('Message received: $message');
    print('RawKeyEvent: $event');
    print('RawKeyEventData: ${event.data}');
    print('pressedKeys: $_keysPressed');

Not A Problem,
I/flutter (10676): Message received: {keymap: android, productId: 1, flags:
8, vendorId: 1, source: 769, type: keydown, deviceId: 3, scanCode: 97,
keyCode: 23, plainCodePoint: 0, metaState: 0, codePoint: 0, repeatCount: 0}
I/flutter (10676): RawKeyEvent: RawKeyDownEvent#051d3(logicalKey:
LogicalKeyboardKey#70077(keyId: "0x100070077", keyLabel: null, debugName:
"Select"), physicalKey: PhysicalKeyboardKey#700e4(usbHidUsage:
"0x000700e4", debugName: "Control Right"))
I/flutter (10676): RawKeyEventData: RawKeyEventDataAndroid(keyLabel: null
flags: 8, codePoint: 0, keyCode: 23, scanCode: 97, metaState: 0, modifiers
down: {})
I/flutter (10676): pressedKeys: {PhysicalKeyboardKey#700e4(usbHidUsage:
"0x000700e4", debugName: "Control Right"): LogicalKeyboardKey#70077(keyId:
"0x100070077", keyLabel: null, debugName: "Select")}
I/flutter (10676): Message received: {keymap: android, productId: 1, flags:
8, vendorId: 1, source: 769, type: keyup, deviceId: 3, scanCode: 97,
keyCode: 23, plainCodePoint: 0, metaState: 0, codePoint: 0, repeatCount: 0}
══╡ EXCEPTION CAUGHT BY SERVICES LIBRARY
╞══════════════════════════════════════════════════════════
The following assertion was thrown during a platform message callback:
'package:flutter/src/widgets/shortcuts.dart': Failed assertion: line 77 pos
16: 'keys.isNotEmpty':
is not true.
On Wed, 16 Sep 2020 at 08:30, Greg Spencer<EMAIL_ADDRESS>wrote:

I don't have access to an actual Android TV to try this on, unfortunately.
@clarkap https://github.com/clarkap would you be willing to add some
code to your Flutter repo so I can see what the key information being sent
is?
If you could add the following just before the call to
_synchronizeModifiers
https://cs.opensource.google/flutter/flutter/+/master:packages/flutter/lib/src/services/raw_keyboard.dart;l=618
in flutter/packages/flutter/lib/src/services/raw_keyboard.dart, and then
rebuild your app and post what the log prints when you press the OK/Select
button, that would give me a lot more to go on.
print('Message received: $message');
print('RawKeyEvent: $event');
print('RawKeyEventData: ${event.data}');
print('pressedKeys: $_keysPressed');

—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/flutter/flutter/issues/65233#issuecomment-693099690,
or unsubscribe
https://github.com/notifications/unsubscribe-auth/ABOB4WDSEP5GVY4H4FVD2TTSGABKNANCNFSM4QXN4HFQ
.

As Adam Savage would say: "Well, there's your problem!"
Although it's not your problem, it's Flutter's: we're translating the physical scan code for the remote as if it were a keyboard, and it's not, so the scan code is mapping to a "Control Right" even though it's not a control key. And the reason the assertion is firing is because although the physical key purports to be a control key, the corresponding metaState bit is not set.

And I'm not quite sure what to do here: the physical key mapping only makes sense when the input is a keyboard, but we use the physical key scancode to make sure that we match the appropriate key down with the right key up.  Perhaps we need to just not synchronize the modifiers if the source isn't a keyboard.

Do we need a separate set of mappings for IR remotes maybe? Or in general for lots of classes of devices? How does Android know what key this "really" is?

Android looks at the .kl keyboard layout files installed on the device for the peripheral, and they're different for different peripherals. These are not accessible to the app on a non-rooted device, as far as I know.
I think the right fix here is to have a way to tell if something is not a keyboard (which we should be able to do with platform APIs), and just skip the modifier key synchronization if it isn't a keyboard. Other devices don't use modifier key masks anyhow, so synchronization doesn't make sense.

Is there any fix to thsi problem?
I have to make IR Remote in my app supported.
It is so sad ....

Is there any way to fix this problem, or should I abandon Flutter for my TV appliacation and go to Kotlin?

`// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:io';
import 'package:flutter/foundation.dart';
import 'binding.dart';
import 'hardware_keyboard.dart';
import 'keyboard_key.dart';
import 'raw_keyboard_android.dart';
import 'raw_keyboard_fuchsia.dart';
import 'raw_keyboard_ios.dart';
import 'raw_keyboard_linux.dart';
import 'raw_keyboard_macos.dart';
import 'raw_keyboard_web.dart';
import 'raw_keyboard_windows.dart';
import 'system_channels.dart';
/// An enum describing the side of the keyboard that a key is on, to allow
/// discrimination between which key is pressed (e.g. the left or right SHIFT
/// key).
///
/// See also:
///
///  * [RawKeyEventData.isModifierPressed], which accepts this enum as an
///    argument.
enum KeyboardSide {
/// Matches if either the left, right or both versions of the key are pressed.
any,
/// Matches the left version of the key.
left,
/// Matches the right version of the key.
right,
/// Matches the left and right version of the key pressed simultaneously.
all,
}
/// An enum describing the type of modifier key that is being pressed.
///
/// See also:
///
///  * [RawKeyEventData.isModifierPressed], which accepts this enum as an
///    argument.
enum ModifierKey {
/// The CTRL modifier key.
///
/// Typically, there are two of these.
controlModifier,
/// The SHIFT modifier key.
///
/// Typically, there are two of these.
shiftModifier,
/// The ALT modifier key.
///
/// Typically, there are two of these.
altModifier,
/// The META modifier key.
///
/// Typically, there are two of these. This is, for example, the Windows key
/// on Windows (⊞), the Command (⌘) key on macOS and iOS, and the Search (🔍)
/// key on Android.
metaModifier,
/// The CAPS LOCK modifier key.
///
/// Typically, there is one of these. Only shown as "pressed" when the caps
/// lock is on, so on a key up when the mode is turned on, on each key press
/// when it's enabled, and on a key down when it is turned off.
capsLockModifier,
/// The NUM LOCK modifier key.
///
/// Typically, there is one of these. Only shown as "pressed" when the num
/// lock is on, so on a key up when the mode is turned on, on each key press
/// when it's enabled, and on a key down when it is turned off.
numLockModifier,
/// The SCROLL LOCK modifier key.
///
/// Typically, there is one of these.  Only shown as "pressed" when the scroll
/// lock is on, so on a key up when the mode is turned on, on each key press
/// when it's enabled, and on a key down when it is turned off.
scrollLockModifier,
/// The FUNCTION (Fn) modifier key.
///
/// Typically, there is one of these.
functionModifier,
/// The SYMBOL modifier key.
///
/// Typically, there is one of these.
symbolModifier,
}
/// Base class for platform-specific key event data.
///
/// This base class exists to have a common type to use for each of the
/// target platform's key event data structures.
///
/// See also:
///
///  * [RawKeyEventDataAndroid], a specialization for Android.
///  * [RawKeyEventDataFuchsia], a specialization for Fuchsia.
///  * [RawKeyDownEvent] and [RawKeyUpEvent], the classes that hold the
///    reference to [RawKeyEventData] subclasses.
///  * [RawKeyboard], which uses these interfaces to expose key data.
@immutable
abstract class RawKeyEventData with Diagnosticable {
/// Abstract const constructor. This constructor enables subclasses to provide
/// const constructors so that they can be used in const expressions.
const RawKeyEventData();
/// Returns true if the given [ModifierKey] was pressed at the time of this
/// event.
///
/// If [side] is specified, then this restricts its check to the specified
/// side of the keyboard. Defaults to checking for the key being down on
/// either side of the keyboard. If there is only one instance of the key on
/// the keyboard, then [side] is ignored.
bool isModifierPressed(ModifierKey key,
{KeyboardSide side = KeyboardSide.any});
/// Returns a [KeyboardSide] enum value that describes which side or sides of
/// the given keyboard modifier key were pressed at the time of this event.
///
/// If the modifier key wasn't pressed at the time of this event, returns
/// null. If the given key only appears in one place on the keyboard, returns
/// [KeyboardSide.all] if pressed. If the given platform does not specify
/// the side, return [KeyboardSide.any].
KeyboardSide? getModifierSide(ModifierKey key);
/// Returns true if a CTRL modifier key was pressed at the time of this event,
/// regardless of which side of the keyboard it is on.
///
/// Use [isModifierPressed] if you need to know which control key was pressed.
bool get isControlPressed => isModifierPressed(ModifierKey.controlModifier);
/// Returns true if a SHIFT modifier key was pressed at the time of this
/// event, regardless of which side of the keyboard it is on.
///
/// Use [isModifierPressed] if you need to know which shift key was pressed.
bool get isShiftPressed => isModifierPressed(ModifierKey.shiftModifier);
/// Returns true if a ALT modifier key was pressed at the time of this event,
/// regardless of which side of the keyboard it is on.
///
/// Use [isModifierPressed] if you need to know which alt key was pressed.
bool get isAltPressed => isModifierPressed(ModifierKey.altModifier);
/// Returns true if a META modifier key was pressed at the time of this event,
/// regardless of which side of the keyboard it is on.
///
/// Use [isModifierPressed] if you need to know which meta key was pressed.
bool get isMetaPressed => isModifierPressed(ModifierKey.metaModifier);
/// Returns a map of modifier keys that were pressed at the time of this
/// event, and the keyboard side or sides that the key was on.
Map<ModifierKey, KeyboardSide> get modifiersPressed {
final Map<ModifierKey, KeyboardSide> result = <ModifierKey, KeyboardSide>{};
for (final ModifierKey key in ModifierKey.values) {
if (isModifierPressed(key)) {
final KeyboardSide? side = getModifierSide(key);
if (side != null) {
result[key] = side;
}
assert(() {
if (side == null) {
debugPrint(
'Raw key data is returning inconsistent information for '
'pressed modifiers. isModifierPressed returns true for $key '
'being pressed, but when getModifierSide is called, it says '
'that no modifiers are pressed.',
);
if (this is RawKeyEventDataAndroid) {
debugPrint(
'Android raw key metaState: ${(this as RawKeyEventDataAndroid).metaState}');
}
}
return true;
}());
}
}
return result;
}
/// Returns an object representing the physical location of this key on a
/// QWERTY keyboard.
///
/// {@macro flutter.services.RawKeyEvent.physicalKey}
///
/// See also:
///
///  * [logicalKey] for the non-location-specific key generated by this event.
///  * [RawKeyEvent.physicalKey], where this value is available on the event.
PhysicalKeyboardKey get physicalKey;
/// Returns an object representing the logical key that was pressed.
///
/// {@macro flutter.services.RawKeyEvent.logicalKey}
///
/// See also:
///
///  * [physicalKey] for the location-specific key generated by this event.
///  * [RawKeyEvent.logicalKey], where this value is available on the event.
LogicalKeyboardKey get logicalKey;
/// Returns the Unicode string representing the label on this key.
///
/// This value is an empty string if there's no key label data for a key.
///
/// {@template flutter.services.RawKeyEventData.keyLabel}
/// Do not use the [keyLabel] to compose a text string: it will be missing
/// special processing for Unicode strings for combining characters and other
/// special characters, and the effects of modifiers.
///
/// If you are looking for the character produced by a key event, use
/// [RawKeyEvent.character] instead.
///
/// If you are composing text strings, use the [TextField] or
/// [CupertinoTextField] widgets, since those automatically handle many of the
/// complexities of managing keyboard input, like showing a soft keyboard or
/// interacting with an input method editor (IME).
/// {@endtemplate}
String get keyLabel;
/// Whether a key down event, and likewise its accompanying key up event,
/// should be dispatched.
///
/// Certain events on some platforms should not be dispatched to listeners
/// according to Flutter's event model. For example, on macOS, Fn keys are
/// skipped to be consistent with other platform. On Win32, events dispatched
/// for IME (VK_PROCESSKEY) are also skipped.
///
/// This method will be called upon every down events. By default, this method
/// always return true. Subclasses should override this method to define the
/// filtering rule for the platform. If this method returns false for an event
/// message, the event will not be dispatched to listeners, but respond with
/// "handled: true" immediately. Moreover, the following up event with the
/// same physical key will also be skipped.
bool shouldDispatchEvent() {
return true;
}
}
/// Defines the interface for raw key events.
///
/// Raw key events pass through as much information as possible from the
/// underlying platform's key events, which allows them to provide a high level
/// of fidelity but a low level of portability.
///
/// The event also provides an abstraction for the [physicalKey] and the
/// [logicalKey], describing the physical location of the key, and the logical
/// meaning of the key, respectively. These are more portable representations of
/// the key events, and should produce the same results regardless of platform.
///
/// See also:
///
///  * [LogicalKeyboardKey], an object that describes the logical meaning of a
///    key.
///  * [PhysicalKeyboardKey], an object that describes the physical location of
///    a key.
///  * [RawKeyDownEvent], a specialization for events representing the user
///    pressing a key.
///  * [RawKeyUpEvent], a specialization for events representing the user
///    releasing a key.
///  * [RawKeyboard], which uses this interface to expose key data.
///  * [RawKeyboardListener], a widget that listens for raw key events.
@immutable
abstract class RawKeyEvent with Diagnosticable {
/// Abstract const constructor. This constructor enables subclasses to provide
/// const constructors so that they can be used in const expressions.
const RawKeyEvent({
required this.data,
this.character,
this.repeat = false,
});
/// Creates a concrete [RawKeyEvent] class from a message in the form received
/// on the [SystemChannels.keyEvent] channel.
///
/// [RawKeyEvent.repeat] will be derived from the current keyboard state,
/// instead of using the message information.
factory RawKeyEvent.fromMessage(Map<String, Object?> message) {
String? character;
RawKeyEventData _dataFromWeb() {
final String? key = message['key'] as String?;
if (key != null && key.isNotEmpty && key.length == 1) {
character = key;
}
return RawKeyEventDataWeb(
code: message['code'] as String? ?? '',
key: key ?? '',
location: message['location'] as int? ?? 0,
metaState: message['metaState'] as int? ?? 0,
keyCode: message['keyCode'] as int? ?? 0,
);
}
final RawKeyEventData data;
if (kIsWeb) {
  data = _dataFromWeb();
} else {
  final String keymap = message['keymap']! as String;
  switch (keymap) {
    case 'android':
      data = RawKeyEventDataAndroid(
        flags: message['flags'] as int? ?? 0,
        codePoint: message['codePoint'] as int? ?? 0,
        keyCode: message['keyCode'] as int? ?? 0,
        plainCodePoint: message['plainCodePoint'] as int? ?? 0,
        scanCode: message['scanCode'] as int? ?? 0,
        metaState: message['metaState'] as int? ?? 0,
        eventSource: message['source'] as int? ?? 0,
        vendorId: message['vendorId'] as int? ?? 0,
        productId: message['productId'] as int? ?? 0,
        deviceId: message['deviceId'] as int? ?? 0,
        repeatCount: message['repeatCount'] as int? ?? 0,
      );
      if (message.containsKey('character')) {
        character = message['character'] as String?;
      }
      break;
    case 'fuchsia':
      final int codePoint = message['codePoint'] as int? ?? 0;
      data = RawKeyEventDataFuchsia(
        hidUsage: message['hidUsage'] as int? ?? 0,
        codePoint: codePoint,
        modifiers: message['modifiers'] as int? ?? 0,
      );
      if (codePoint != 0) {
        character = String.fromCharCode(codePoint);
      }
      break;
    case 'macos':
      data = RawKeyEventDataMacOs(
        characters: message['characters'] as String? ?? '',
        charactersIgnoringModifiers:
            message['charactersIgnoringModifiers'] as String? ?? '',
        keyCode: message['keyCode'] as int? ?? 0,
        modifiers: message['modifiers'] as int? ?? 0,
      );
      character = message['characters'] as String?;
      break;
    case 'ios':
      data = RawKeyEventDataIos(
        characters: message['characters'] as String? ?? '',
        charactersIgnoringModifiers:
            message['charactersIgnoringModifiers'] as String? ?? '',
        keyCode: message['keyCode'] as int? ?? 0,
        modifiers: message['modifiers'] as int? ?? 0,
      );
      break;
    case 'linux':
      final int unicodeScalarValues =
          message['unicodeScalarValues'] as int? ?? 0;
      data = RawKeyEventDataLinux(
        keyHelper: KeyHelper(message['toolkit'] as String? ?? ''),
        unicodeScalarValues: unicodeScalarValues,
        keyCode: message['keyCode'] as int? ?? 0,
        scanCode: message['scanCode'] as int? ?? 0,
        modifiers: message['modifiers'] as int? ?? 0,
        isDown: message['type'] == 'keydown',
      );
      if (unicodeScalarValues != 0) {
        character = String.fromCharCode(unicodeScalarValues);
      }
      break;
    case 'windows':
      final int characterCodePoint =
          message['characterCodePoint'] as int? ?? 0;
      data = RawKeyEventDataWindows(
        keyCode: message['keyCode'] as int? ?? 0,
        scanCode: message['scanCode'] as int? ?? 0,
        characterCodePoint: characterCodePoint,
        modifiers: message['modifiers'] as int? ?? 0,
      );
      if (characterCodePoint != 0) {
        character = String.fromCharCode(characterCodePoint);
      }
      break;
    case 'web':
      data = _dataFromWeb();
      break;
    default:

      /// This exception would only be hit on platforms that haven't yet
      /// implemented raw key events, but will only be triggered if the
      /// engine for those platforms sends raw key event messages in the
      /// first place.
      throw FlutterError('Unknown keymap for key events: $keymap');
  }
}
final bool repeat =
    RawKeyboard.instance.physicalKeysPressed.contains(data.physicalKey);
final String type = message['type']! as String;
switch (type) {
  case 'keydown':
    return RawKeyDownEvent(
        data: data, character: character, repeat: repeat);
  case 'keyup':
    return RawKeyUpEvent(data: data);
  default:
    throw FlutterError('Unknown key event type: $type');
}

}
/// Returns true if the given [KeyboardKey] is pressed.
bool isKeyPressed(LogicalKeyboardKey key) =>
RawKeyboard.instance.keysPressed.contains(key);
/// Returns true if a CTRL modifier key is pressed, regardless of which side
/// of the keyboard it is on.
///
/// Use [isKeyPressed] if you need to know which control key was pressed.
bool get isControlPressed {
return isKeyPressed(LogicalKeyboardKey.controlLeft) ||
isKeyPressed(LogicalKeyboardKey.controlRight);
}
/// Returns true if a SHIFT modifier key is pressed, regardless of which side
/// of the keyboard it is on.
///
/// Use [isKeyPressed] if you need to know which shift key was pressed.
bool get isShiftPressed {
return isKeyPressed(LogicalKeyboardKey.shiftLeft) ||
isKeyPressed(LogicalKeyboardKey.shiftRight);
}
/// Returns true if a ALT modifier key is pressed, regardless of which side
/// of the keyboard it is on.
///
/// Note that the ALTGR key that appears on some keyboards is considered to be
/// the same as [LogicalKeyboardKey.altRight] on some platforms (notably
/// Android). On platforms that can distinguish between altRight and
/// altGr, a press of altGr will not return true here, and will need to be
/// tested for separately.
///
/// Use [isKeyPressed] if you need to know which alt key was pressed.
bool get isAltPressed {
return isKeyPressed(LogicalKeyboardKey.altLeft) ||
isKeyPressed(LogicalKeyboardKey.altRight);
}
/// Returns true if a META modifier key is pressed, regardless of which side
/// of the keyboard it is on.
///
/// Use [isKeyPressed] if you need to know which meta key was pressed.
bool get isMetaPressed {
return isKeyPressed(LogicalKeyboardKey.metaLeft) ||
isKeyPressed(LogicalKeyboardKey.metaRight);
}
/// Returns an object representing the physical location of this key.
///
/// {@template flutter.services.RawKeyEvent.physicalKey}
/// The [PhysicalKeyboardKey] ignores the key map, modifier keys (like SHIFT),
/// and the label on the key. It describes the location of the key as if it
/// were on a QWERTY keyboard regardless of the keyboard mapping in effect.
///
/// [PhysicalKeyboardKey]s are used to describe and test for keys in a
/// particular location.
///
/// For instance, if you wanted to make a game where the key to the right of
/// the CAPS LOCK key made the player move left, you would be comparing the
/// result of this physicalKey with [PhysicalKeyboardKey.keyA], since that
/// is the key next to the CAPS LOCK key on a QWERTY keyboard. This would
/// return the same thing even on a French keyboard where the key next to the
/// CAPS LOCK produces a "Q" when pressed.
///
/// If you want to make your app respond to a key with a particular character
/// on it regardless of location of the key, use [RawKeyEvent.logicalKey] instead.
/// {@endtemplate}
///
/// See also:
///
///  * [logicalKey] for the non-location specific key generated by this event.
///  * [character] for the character generated by this keypress (if any).
PhysicalKeyboardKey get physicalKey => data.physicalKey;
/// Returns an object representing the logical key that was pressed.
///
/// {@template flutter.services.RawKeyEvent.logicalKey}
/// This method takes into account the key map and modifier keys (like SHIFT)
/// to determine which logical key to return.
///
/// If you are looking for the character produced by a key event, use
/// [RawKeyEvent.character] instead.
///
/// If you are collecting text strings, use the [TextField] or
/// [CupertinoTextField] widgets, since those automatically handle many of the
/// complexities of managing keyboard input, like showing a soft keyboard or
/// interacting with an input method editor (IME).
/// {@endtemplate}
LogicalKeyboardKey get logicalKey => data.logicalKey;
/// Returns the Unicode character (grapheme cluster) completed by this
/// keystroke, if any.
///
/// This will only return a character if this keystroke, combined with any
/// preceding keystroke(s), generated a character, and only on a "key down"
/// event. It will return null if no character has been generated by the
/// keystroke (e.g. a "dead" or "combining" key), or if the corresponding key
/// is a key without a visual representation, such as a modifier key or a
/// control key.
///
/// This can return multiple Unicode code points, since some characters (more
/// accurately referred to as grapheme clusters) are made up of more than one
/// code point.
///
/// The character doesn't take into account edits by an input method editor
/// (IME), or manage the visibility of the soft keyboard on touch devices. For
/// composing text, use the [TextField] or [CupertinoTextField] widgets, since
/// those automatically handle many of the complexities of managing keyboard
/// input.
final String? character;
/// Whether this is a repeated down event.
///
/// When a key is held down, the systems usually fire a down event and then
/// a series of repeated down events. The [repeat] is false for the
/// first event and true for the following events.
///
/// The [repeat] attribute is always false for [RawKeyUpEvent]s.
final bool repeat;
/// Platform-specific information about the key event.
final RawKeyEventData data;
@override
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties);
properties
.add(DiagnosticsProperty('logicalKey', logicalKey));
properties.add(
DiagnosticsProperty('physicalKey', physicalKey));
if (this is RawKeyDownEvent)
properties.add(DiagnosticsProperty('repeat', repeat));
}
}
/// The user has pressed a key on the keyboard.
///
/// See also:
///
///  * [RawKeyboard], which uses this interface to expose key data.
class RawKeyDownEvent extends RawKeyEvent {
/// Creates a key event that represents the user pressing a key.
const RawKeyDownEvent({
required RawKeyEventData data,
String? character,
bool repeat = false,
}) : super(data: data, character: character, repeat: repeat);
}
/// The user has released a key on the keyboard.
///
/// See also:
///
///  * [RawKeyboard], which uses this interface to expose key data.
class RawKeyUpEvent extends RawKeyEvent {
/// Creates a key event that represents the user releasing a key.
const RawKeyUpEvent({
required RawKeyEventData data,
String? character,
}) : super(data: data, character: character, repeat: false);
}
/// A callback type used by [RawKeyboard.keyEventHandler] to send key events to
/// a handler that can determine if the key has been handled or not.
///
/// The handler should return true if the key has been handled, and false if the
/// key was not handled.  It must not return null.
typedef RawKeyEventHandler = bool Function(RawKeyEvent event);
/// An interface for listening to raw key events.
///
/// Raw key events pass through as much information as possible from the
/// underlying platform's key events, which makes them provide a high level of
/// fidelity but a low level of portability.
///
/// A [RawKeyboard] is useful for listening to raw key events and hardware
/// buttons that are represented as keys. Typically used by games and other apps
/// that use keyboards for purposes other than text entry.
///
/// These key events are typically only key events generated by a hardware
/// keyboard, and not those from software keyboards or input method editors.
///
/// See also:
///
///  * [RawKeyDownEvent] and [RawKeyUpEvent], the classes used to describe
///    specific raw key events.
///  * [RawKeyboardListener], a widget that listens for raw key events.
///  * [SystemChannels.keyEvent], the low-level channel used for receiving
///    events from the system.
class RawKeyboard {
RawKeyboard._();
/// The shared instance of [RawKeyboard].
static final RawKeyboard instance = RawKeyboard._();
final List<ValueChanged> _listeners =
<ValueChanged>[];
/// Register a listener that is called every time the user presses or releases
/// a hardware keyboard key.
///
/// Since the listeners have no way to indicate what they did with the event,
/// listeners are assumed to not handle the key event. These events will also
/// be distributed to other listeners, and to the [keyEventHandler].
///
/// Most applications prefer to use the focus system (see [Focus] and
/// [FocusManager]) to receive key events to the focused control instead of
/// this kind of passive listener.
///
/// Listeners can be removed with [removeListener].
void addListener(ValueChanged listener) {
_listeners.add(listener);
}
/// Stop calling the given listener every time the user presses or releases a
/// hardware keyboard key.
///
/// Listeners can be added with [addListener].
void removeListener(ValueChanged listener) {
_listeners.remove(listener);
}
/// A handler for raw hardware keyboard events that will stop propagation if
/// the handler returns true.
///
/// This property is only a wrapper over [KeyEventManager.keyMessageHandler],
/// and is kept only for backward compatibility. New code should use
/// [KeyEventManager.keyMessageHandler] to set custom global key event
/// handler. Setting [keyEventHandler] will cause
/// [KeyEventManager.keyMessageHandler] to be set with a converted handler.
/// If [KeyEventManager.keyMessageHandler] is set by [FocusManager] (the most
/// common situation), then the exact value of [keyEventHandler] is a dummy
/// callback and must not be invoked.
RawKeyEventHandler? get keyEventHandler {
if (ServicesBinding.instance.keyEventManager.keyMessageHandler !=
_cachedKeyMessageHandler) {
_cachedKeyMessageHandler =
ServicesBinding.instance.keyEventManager.keyMessageHandler;
_cachedKeyEventHandler = _cachedKeyMessageHandler == null
? null
: (RawKeyEvent event) {
assert(
false,
'The RawKeyboard.instance.keyEventHandler assigned by Flutter is a dummy '
'callback kept for compatibility and should not be directly called. Use '
'ServicesBinding.instance!.keyMessageHandler instead.');
return true;
};
}
return _cachedKeyEventHandler;
}
RawKeyEventHandler? _cachedKeyEventHandler;
KeyMessageHandler? _cachedKeyMessageHandler;
set keyEventHandler(RawKeyEventHandler? handler) {
_cachedKeyEventHandler = handler;
_cachedKeyMessageHandler = handler == null
? null
: (KeyMessage message) {
if (message.rawEvent != null) return handler(message.rawEvent!);
return false;
};
ServicesBinding.instance.keyEventManager.keyMessageHandler =
_cachedKeyMessageHandler;
}
/// Process a new [RawKeyEvent] by recording the state changes and
/// dispatching to listeners.
bool handleRawKeyEvent(RawKeyEvent event) {
bool shouldDispatch = true;
if (event is RawKeyDownEvent) {
if (event.data.shouldDispatchEvent()) {
_keysPressed[event.physicalKey] = event.logicalKey;
} else {
shouldDispatch = false;
_hiddenKeysPressed.add(event.physicalKey);
}
} else if (event is RawKeyUpEvent) {
if (!_hiddenKeysPressed.contains(event.physicalKey)) {
// Use the physical key in the key up event to find the physical key from
// the corresponding key down event and remove it, even if the logical
// keys don't match.
_keysPressed.remove(event.physicalKey);
} else {
_hiddenKeysPressed.remove(event.physicalKey);
shouldDispatch = false;
}
}
if (!shouldDispatch) {
return true;
}
// Make sure that the modifiers reflect reality, in case a modifier key was
// pressed/released while the app didn't have focus.
// _synchronizeModifiers(event);
// assert(
//   event is! RawKeyDownEvent || _keysPressed.isNotEmpty,
//   'Attempted to send a key down event when no keys are in keysPressed. '
//   "This state can occur if the key event being sent doesn't properly "
//   'set its modifier flags. This was the event: $event and its data: '
//   '${event.data}',
// );
// Send the event to passive listeners.
for (final ValueChanged listener
in List<ValueChanged>.of(_listeners)) {
try {
if (_listeners.contains(listener)) {
listener(event);
}
} catch (exception, stack) {
InformationCollector? collector;
assert(() {
collector = () => [
DiagnosticsProperty('Event', event),
];
return true;
}());
FlutterError.reportError(FlutterErrorDetails(
exception: exception,
stack: stack,
library: 'services library',
context: ErrorDescription('while processing a raw key listener'),
informationCollector: collector,
));
}
}
return false;

}
static final Map<_ModifierSidePair, Set>
_modifierKeyMap = <_ModifierSidePair, Set>{
const _ModifierSidePair(ModifierKey.altModifier, KeyboardSide.left):
{PhysicalKeyboardKey.altLeft},
const _ModifierSidePair(ModifierKey.altModifier, KeyboardSide.right):
{PhysicalKeyboardKey.altRight},
const _ModifierSidePair(ModifierKey.altModifier, KeyboardSide.all):
{
PhysicalKeyboardKey.altLeft,
PhysicalKeyboardKey.altRight
},
const _ModifierSidePair(ModifierKey.altModifier, KeyboardSide.any):
{PhysicalKeyboardKey.altLeft},
const _ModifierSidePair(ModifierKey.shiftModifier, KeyboardSide.left):
{PhysicalKeyboardKey.shiftLeft},
const _ModifierSidePair(ModifierKey.shiftModifier, KeyboardSide.right):
{PhysicalKeyboardKey.shiftRight},
const _ModifierSidePair(ModifierKey.shiftModifier, KeyboardSide.all):
{
PhysicalKeyboardKey.shiftLeft,
PhysicalKeyboardKey.shiftRight
},
const _ModifierSidePair(ModifierKey.shiftModifier, KeyboardSide.any):
{PhysicalKeyboardKey.shiftLeft},
const _ModifierSidePair(ModifierKey.controlModifier, KeyboardSide.left):
{PhysicalKeyboardKey.controlLeft},
const _ModifierSidePair(ModifierKey.controlModifier, KeyboardSide.right):
{PhysicalKeyboardKey.controlRight},
const _ModifierSidePair(ModifierKey.controlModifier, KeyboardSide.all):
{
PhysicalKeyboardKey.controlLeft,
PhysicalKeyboardKey.controlRight
},
const _ModifierSidePair(ModifierKey.controlModifier, KeyboardSide.any):
{PhysicalKeyboardKey.controlLeft},
const _ModifierSidePair(ModifierKey.metaModifier, KeyboardSide.left):
{PhysicalKeyboardKey.metaLeft},
const _ModifierSidePair(ModifierKey.metaModifier, KeyboardSide.right):
{PhysicalKeyboardKey.metaRight},
const _ModifierSidePair(ModifierKey.metaModifier, KeyboardSide.all):
{
PhysicalKeyboardKey.metaLeft,
PhysicalKeyboardKey.metaRight
},
const _ModifierSidePair(ModifierKey.metaModifier, KeyboardSide.any):
{PhysicalKeyboardKey.metaLeft},
const _ModifierSidePair(ModifierKey.capsLockModifier, KeyboardSide.all):
{PhysicalKeyboardKey.capsLock},
const _ModifierSidePair(ModifierKey.numLockModifier, KeyboardSide.all):
{PhysicalKeyboardKey.numLock},
const _ModifierSidePair(ModifierKey.scrollLockModifier, KeyboardSide.all):
{PhysicalKeyboardKey.scrollLock},
const _ModifierSidePair(ModifierKey.functionModifier, KeyboardSide.all):
{PhysicalKeyboardKey.fn},
// The symbolModifier doesn't have a key representation on any of the
// platforms, so don't map it here.
};
// The map of all modifier keys except Fn, since that is treated differently
// on some platforms.
static final Map<PhysicalKeyboardKey, LogicalKeyboardKey>
_allModifiersExceptFn = <PhysicalKeyboardKey, LogicalKeyboardKey>{
PhysicalKeyboardKey.altLeft: LogicalKeyboardKey.altLeft,
PhysicalKeyboardKey.altRight: LogicalKeyboardKey.altRight,
PhysicalKeyboardKey.shiftLeft: LogicalKeyboardKey.shiftLeft,
PhysicalKeyboardKey.shiftRight: LogicalKeyboardKey.shiftRight,
PhysicalKeyboardKey.controlLeft: LogicalKeyboardKey.controlLeft,
PhysicalKeyboardKey.controlRight: LogicalKeyboardKey.controlRight,
PhysicalKeyboardKey.metaLeft: LogicalKeyboardKey.metaLeft,
PhysicalKeyboardKey.metaRight: LogicalKeyboardKey.metaRight,
PhysicalKeyboardKey.capsLock: LogicalKeyboardKey.capsLock,
PhysicalKeyboardKey.numLock: LogicalKeyboardKey.numLock,
PhysicalKeyboardKey.scrollLock: LogicalKeyboardKey.scrollLock,
};
// The map of all modifier keys that are represented in modifier key bit
// masks on all platforms, so that they can be cleared out of pressedKeys when
// synchronizing.
static final Map<PhysicalKeyboardKey, LogicalKeyboardKey> _allModifiers =
<PhysicalKeyboardKey, LogicalKeyboardKey>{
PhysicalKeyboardKey.fn: LogicalKeyboardKey.fn,
..._allModifiersExceptFn,
};
void _synchronizeModifiers(RawKeyEvent event) {
// Compare modifier states to the ground truth as specified by
// [RawKeyEvent.data.modifiersPressed] and update unsynchronized ones.
//
// This function will update the state of modifier keys in _keysPressed so
// that they match the ones given by [RawKeyEvent.data.modifiersPressed].
// For a modifiersPressed result of anything but [KeyboardSide.any], the
// states in _keysPressed will be updated to exactly match the result,
// i.e. exactly one of "no down", "left down", "right down" or "both down".
//
// If modifiersPressed returns [KeyboardSide.any], the states in
// _keysPressed will be updated to a rough match, i.e. "either side down"
// or "no down". If _keysPressed has no modifier down, a
// [KeyboardSide.any] will synchronize by forcing the left modifier down. If
// _keysPressed has any modifier down, a [KeyboardSide.any] will not cause
// a state change.
final Map<ModifierKey, KeyboardSide?> modifiersPressed =
    event.data.modifiersPressed;
final Map<PhysicalKeyboardKey, LogicalKeyboardKey> modifierKeys =
    <PhysicalKeyboardKey, LogicalKeyboardKey>{};
// Physical keys that whose modifiers are pressed at any side.
final Set<PhysicalKeyboardKey> anySideKeys = <PhysicalKeyboardKey>{};
final Set<PhysicalKeyboardKey> keysPressedAfterEvent =
    <PhysicalKeyboardKey>{
  ..._keysPressed.keys,
  if (event is RawKeyDownEvent) event.physicalKey,
};
ModifierKey? thisKeyModifier;
for (final ModifierKey key in ModifierKey.values) {
  final Set<PhysicalKeyboardKey>? thisModifierKeys =
      _modifierKeyMap[_ModifierSidePair(key, KeyboardSide.all)];
  if (thisModifierKeys == null) continue;
  if (thisModifierKeys.contains(event.physicalKey)) {
    thisKeyModifier = key;
  }
  if (modifiersPressed[key] == KeyboardSide.any) {
    anySideKeys.addAll(thisModifierKeys);
    if (thisModifierKeys.any(keysPressedAfterEvent.contains)) {
      continue;
    }
  }
  final Set<PhysicalKeyboardKey>? mappedKeys = modifiersPressed[key] == null
      ? <PhysicalKeyboardKey>{}
      : _modifierKeyMap[_ModifierSidePair(key, modifiersPressed[key])];
  assert(() {
    if (mappedKeys == null) {
      debugPrint(
        'Platform key support for ${Platform.operatingSystem} is '
        'producing unsupported modifier combinations for '
        'modifier $key on side ${modifiersPressed[key]}.',
      );
      if (event.data is RawKeyEventDataAndroid) {
        debugPrint(
            'Android raw key metaState: ${(event.data as RawKeyEventDataAndroid).metaState}');
      }
    }
    return true;
  }());
  if (mappedKeys == null) {
    continue;
  }
  for (final PhysicalKeyboardKey physicalModifier in mappedKeys) {
    modifierKeys[physicalModifier] = _allModifiers[physicalModifier]!;
  }
}
_allModifiersExceptFn.keys
    .where((PhysicalKeyboardKey key) => !anySideKeys.contains(key))
    .forEach(_keysPressed.remove);
if (event.data is! RawKeyEventDataFuchsia &&
    event.data is! RawKeyEventDataMacOs) {
  // On Fuchsia and macOS, the Fn key is not considered a modifier key.
  _keysPressed.remove(PhysicalKeyboardKey.fn);
}
_keysPressed.addAll(modifierKeys);
// In rare cases, the event presses a modifier key but the key does not
// exist in the modifier list. Enforce the pressing state.
if (event is RawKeyDownEvent &&
    thisKeyModifier != null &&
    !_keysPressed.containsKey(event.physicalKey)) {
  // So far this inconsistancy is only found on Linux GTK for AltRight in a
  // rare case. (See https://github.com/flutter/flutter/issues/93278 .) In
  // other cases, this inconsistancy will be caught by an assertion later.
  if (event.data is RawKeyEventDataLinux &&
      event.physicalKey == PhysicalKeyboardKey.altRight) {
    final LogicalKeyboardKey? logicalKey =
        _allModifiersExceptFn[event.physicalKey];
    if (logicalKey != null) {
      _keysPressed[event.physicalKey] = logicalKey;
    }
  }
}

}
final Map<PhysicalKeyboardKey, LogicalKeyboardKey> _keysPressed =
<PhysicalKeyboardKey, LogicalKeyboardKey>{};
final Set _hiddenKeysPressed = {};
/// Returns the set of keys currently pressed.
Set get keysPressed => _keysPressed.values.toSet();
/// Returns the set of physical keys currently pressed.
Set get physicalKeysPressed => _keysPressed.keys.toSet();
/// Returns the logical key that corresponds to the given pressed physical key.
///
/// Returns null if the physical key is not currently pressed.
LogicalKeyboardKey? lookUpLayout(PhysicalKeyboardKey physicalKey) =>
_keysPressed[physicalKey];
/// Clears the list of keys returned from [keysPressed].
///
/// This is used by the testing framework to make sure tests are hermetic.
@visibleForTesting
void clearKeysPressed() => _keysPressed.clear();
}
@immutable
class _ModifierSidePair {
const _ModifierSidePair(this.modifier, this.side);
final ModifierKey modifier;
final KeyboardSide? side;
@override
bool operator ==(Object other) {
if (other.runtimeType != runtimeType) return false;
return other is _ModifierSidePair &&
other.modifier == modifier &&
other.side == side;
}
@override
int get hashCode => Object.hash(modifier, side);
}
`

Looks like this is happening with other remotes as well.

As a Workaround for those systems, I did this inside this file
<path-to-sdk>/pacakges/flutter/lib/src/services/hardware_keyboard.dart:
Edit the function handleRawKeyMessage:

Future<Map<String, dynamic>> handleRawKeyMessage(dynamic message) async {
    if (_transitMode == null) {
      _transitMode = KeyDataTransitMode.rawKeyData;
      // Convert raw events using a listener so that conversion only occurs if
      // the raw event should be dispatched.
      _rawKeyboard.addListener(_convertRawEventAndStore);
    }

+    try {
+      if (message["scanCode"] == 97) {
+        message["scanCode"] = 28;
+        message["keyCode"] = 66;
+      }
+    } catch (x) {
+      print(x);
+    }

  final RawKeyEvent rawEvent = RawKeyEvent.fromMessage(message as Map<String, dynamic>);
...

This will send select key without errors.
To send the enter key Use message["scanCode"] = 353; and message["keyCode"] = 23;
And add to the function _assertEventIsRegular:
void _assertEventIsRegular(KeyEvent event) {
    assert(() {
      const String common = 'If this occurs in real application, please report this '
        'bug to Flutter. If this occurs in unit tests, please ensure that '
        "simulated events follow Flutter's event model as documented in "
        '`HardwareKeyboard`. This was the event: ';
+     if (event.physicalKey == PhysicalKeyboardKey.controlRight) {
+       return true;
+     }

      if (event is KeyDownEvent) {
...

This is just a Workaround and is not meant to be committed to the source branch.
Feel free to improve on it. Or if you have an official fix.

Is this going to be merged into flutter soon? I'm not a huge fan of patching the SDK code. Happy to put together a PR if it helps?

Currently I have code to intercept the ok button in the Android Activity.
This then simulates the correct keypress before handing the event down to
the Flutter View.
It's clunky and a real fix such as the above would be welcome.
I can look over any patch if you want before submitting for PR.
On Thu, 12 Jan 2023 at 09:43, RtypeStudios @.***> wrote:

Is this going to be merged into flutter soon? I'm not a huge fan of
patching the SDK code. Happy to put together a PR if it helps?
—
Reply to this email directly, view it on GitHub
https://github.com/flutter/flutter/issues/65233#issuecomment-1379704261,
or unsubscribe
https://github.com/notifications/unsubscribe-auth/ABOB4WDHGLOSEVOIZPNBW5LWR5OTHANCNFSM4QXN4HFQ
.
You are receiving this because you were mentioned.Message ID:
@.***>

@clarkap Do you have an example of this? I'd much rather that than modifying the flutter SDK to get this working.

This works for me but YMMV.
`class MainActivity: FlutterActivity() {
lateinit var inputConnection: BaseInputConnection

override fun onResume() {
    super.onResume()

    val flutterView = findViewById<FlutterView>( FLUTTER_VIEW_ID )

    inputConnection = BaseInputConnection( flutterView , false )

}

override fun dispatchKeyEvent(event: KeyEvent?): Boolean {
    if ( event == null ) return true

    if ( event.keyCode != KeyEvent.KEYCODE_DPAD_CENTER ) {
        return super.dispatchKeyEvent(event)
    }

    if ( event.deviceId != 3 ){
        return super.dispatchKeyEvent(event)
    }

    if ( event.action == KeyEvent.ACTION_DOWN ) {
        inputConnection.sendKeyEvent(
            KeyEvent(
                event.downTime,
                event.eventTime,
                KeyEvent.ACTION_DOWN,
                KeyEvent.KEYCODE_DPAD_CENTER,
                event.repeatCount,
                event.metaState,
                event.modifiers,
                23
            )
        )
    } else {
        inputConnection.sendKeyEvent(
            KeyEvent(
                event.downTime,
                event.eventTime,
                KeyEvent.ACTION_UP,
                KeyEvent.KEYCODE_DPAD_CENTER,
                event.repeatCount,
                event.metaState,
                event.modifiers,
                23
            )
        )
    }

    return true
}

companion object{
    private const val TAG = "MainActivity"
}

}`

Thanks, will give that a go and report back.

cc: @mariamhas


TraceLog fails with RuntimeError: null function or function signature mismatch

I found that LoadingVox example doesn't work, it kabooms on the TraceLog function call:
TraceLog(TraceLogLevel.LOG_WARNING, $"[{voxFileNames[i]}] File loaded in {t1 - t0} ms");

INFO: RLGL: Default OpenGL state initialized successfully
dotnet.js:14 INFO: TEXTURE: [ID 11] Texture loaded successfully (128x128 | GRAY_ALPHA | 1 mipmaps)
dotnet.js:14 INFO: FONT: Default font loaded successfully (224 glyphs)
dotnet.js:14 INFO: FILEIO: [resources/models/vox/chr_knight.vox] File loaded successfully
dotnet.js:14 INFO: MODEL: [resources/models/vox/chr_knight.vox] VOX data loaded successfully : 2920 vertices/1 meshes
dotnet.js:14 INFO: VAO: [ID 12] Mesh uploaded successfully to VRAM (GPU)
dotnet.js:5 RuntimeError: null function or function signature mismatch

            ^^^ HERE is kaboom if you are blind or drunk

I suspect that the DllImport in Raylib-cs isn't correct. It does this:
public static extern void TraceLog(TraceLogLevel logLevel, sbyte* text);

because the TraceLog in raylib is a variadic function:
void TraceLog(int logType, const char *text, ...)

https://github.com/raysan5/raylib/blob/dbdfad7ace061931da701070c5c7fbe772c57725/src/utils.c#L107
And these two will never be good friends. 🤔
Anyway this random internet guy found that __arglist does the trick:
https://www.c-sharpcorner.com/UploadFile/b942f9/calling-unmanaged-functions-which-take-a-variable-number-of-arguments-from-C-Sharp/
What the fawk is __arglist, the totally secret C# thing?!

I've just try the original desktop examples and damn, it works. So maybe wasm is a bit too sensitive about the types.

And I also checked if there were some changes in TraceLog and nope, nothing happened for like 3 years already:
https://github.com/raysan5/raylib/commit/343fef4aa4532e21bd74ed84e0339756eb5ab897
So it's very likely all about the variadic.

Added workaround exists because the good ol' System.Console can be used to print something.

I think the issue also applies to TextFormat which is also missing the vardiac arguments as I couldn't get them to work correctly. Though that function can be removed if needed as it is not used much in the examples.
It might also impact custom logging though that uses a callback along with some logging utils to do the text formatting.

Though that only applies to custom logging if the other issue with callbacks is fixed.


Can't paste image from clipboard into demo

From what I understand, we should be able to paste images directly into the editor and it'll work like a drag-and-drop.
On Tutanota, pasting images doesn't do anything, despite the drag-and-drop behavior being to add attachments.

Related to https://github.com/tutao/tutanota/issues/5083

While investigating this, I wanted to see a demo where I can review the implementation of this, however even in Demo.html in the repository, pasting images doesn't perform anything either.

is this just a documentation issue
the code has a pasteImage event and a insertImage function which supports a base64 string as source
pasteImage is not mentioned and insertImage says the string must be a path - but the code supports a base64 string as source
so ... if you want to paste an image from the clipboard...
let editor = new Squire(node);
editor
   .addEventListener('pasteImage', function(e) {

      let payload = [...e.detail.clipboardData.items];
      payload = payload.filter(i => /image/.test(i.type));
      if (!payload.length || payload.length === 0) return false;

      let reader = new FileReader();

      // use squire's insertImage on data load
      reader.onload = e => this.insertImage(e.target.result);

      // read image as Base64
      reader.readAsDataURL(payload[0].getAsFile());
   });

Hey hey! I can confirm this works for the demo and I was able to apply it to Tutanota as well.
Turns out part of this was my fault, I was reading the version of Squire used in Tutanota, and then tested what I knew from that against the demo site which is using an entirely different version. :facepalm:
Thank you for making me aware of the pasteImage event and how to handle it.
Would you care to submit a PR to add this listener to the demo? I think this would offer a lot of value for future readers. If you'd prefer, I'd be happy to cover it, though.
Meanwhile, I've already submitted a PR to Tutanota, visible here:

https://github.com/tutao/tutanota/pull/5275

hey happy for you to raise the pr - I don't actually use this package, but do like the look of it and will maybe do something in future
I stumbled upon it while looking at snappymail, looked at it and made myself a demo - it's didn't paste images - so wound up here - probably like you
cheers


Make available with npm

I've tried this the other day and had trouble with gsap and npm. Another reason to why I want to switch to Velocity.js instead of the heavy gsap.

Here is some potential blockers
https://github.com/Hendrixer/ngFx/issues/105
https://github.com/Hendrixer/ngFx/issues/107


dependency conflict between the versions of i18next and next-i18next

Environment
NodeJS
Version
0.14.4
Describe the problem
dependency conflict between the versions of i18next and next-i18next
Logs
2024-01-26T10_36_29_100Z-eresolve-report.txt
Context
No response
Please tick the boxes

[X] I confirm that I attached the proper logs
[X] I've read the docs
[X] I've checked for duplicate issues
[X] I've tried to debug myself

after fixing the version manually

"i18next": "^23.4.6",
"react-i18next": "^13.2.1",

I get Type error: Property 'placeholder' is missing in ./src/components/Manage/User/Invite/create-invite.modal.tsx

<DateTimePicker
        placeholder=""
        popoverProps={{ withinPortal: true }}

after this fix I get Type error: Property 'reportNamespaces' does not exist on type 'i18n'. this I'm not able to fix

./src/pages/manage/about.tsx:53:13
Type error: Property 'reportNamespaces' does not exist on type 'i18n'.

  51 |   let items: InformationTableItem[] = [];
  52 |
> 53 |   if (i18n?.reportNamespaces) {
     |             ^
  54 |     const usedI18nNamespaces = i18n.reportNamespaces.getUsedNamespaces();
  55 |     const initOptions = i18n.options as ExtendedInitOptions;

When using the from source installation, we expect that you manage dependencies and breaking changes yourself.
We are unable to provide support for each system and dependency version due to the amount of requests that we get daily.
I'd strongly suggest you to use one of the recommended installation methods, like https://homarr.dev/docs/getting-started/installation#-docker-compose .
The drawbacks are also documented here: https://homarr.dev/docs/getting-started/installation#not-recommended-from-source .
Thank you for your understanding.

Thanks for the information this would be helpful, I'll have a look


Extract JS to be packaged separately

Is your feature request related to a problem? Please describe.
Integrating a JS test suite with Webpacker and Rails is complicated, keep running into roadblock with my attempts.
Describe the solution you'd like
I would like to move the JavaScript application to a separate repo for inclusion as a package, so that it can also be packaged as:

An SPA for inclusion in other websites
A mobile app
A desktop app in an Electron container

Additional context
Follows from considerations in #14: https://github.com/thombruce/helvellyn/issues/14#issuecomment-611124553

While we're talking about extraction...
I have previously considered moving Authentication into a separate engine. And we do also now have an issue to address separate scopes for admin and public JSON retireval: #13
So, would we be thinking something like:

Helvellyn::Auth
Helvellyn::PublicAPI
Helvellyn::AdminAPI

...and...

HelvellynApp

Something like that?
Separation of Auth does raise the question of... does it take its JS views with it? Answer... probably not. Probably: it is more like Helvellyn::AuthAPI and only contains the backend code required to function.
And JS packages need not be aware of the API engines, because they will stub responses (although setup with VCR for actual live data would be nice eventually too).
So, we're talking two broad scopes, Backend and Frontend, separated and each maybe comprised of several engines or packages:
Backend

Helvellyn::AuthAPI
Helvellyn::PublicAPI
Helvellyn::AdminAPI

Frontend

HelvellynAuth
HelvellynAdmin

(No equivalent for "PublicAPI" as the app is headless / it only serves JSON)
Just things to consider.


FFmpeg download problem in continuous integration

Seems that ffmpeg linux binaries are failing to download due to a timeout

https://github.com/k-box/k-box/issues/432

Seems that it is related to timeout issues, #9 increases the timeout and enable cache support


Guidelines on implementing plugins?

Need to port https://www.npmjs.com/package/babel-plugin-import
A simple regex replacer might suffice but I'd like to learn the recommended way to implement plugins for swc.

Currently plugin system is not ready yet.
I'm considering
A. Embed plugins in swc binary
This make deploying plugins easier, and makes
(codes will live in a module like contrib-xxx)

I personally want to go with A, as with it I can update plugins when types of ast node is changed.

Currently plugin system is not ready yet.
I'm considering
1. Embed plugins in swc binary
This make deploying plugins easier, and allow me maintaining plugins on swc update.
(codes will live in a module like contrib-xxx)
Also, this option allows me to update plugins when types of ast node is changed.
2. dll / so based
Seems ideal option, but dependency hell might occur.
3. Custom binary built by user with additional transform
It means building a rust library / command line app which depends on swc. If you pick binary, deploying would not be that hard.
See: https://github.com/izelnakri/mber-rust
4. IPC-based plugin
protobuf work in this way, and it allows writing plugin in any language.
5. js plugin interface
I though this is the best, but context switching and serializing native object is really slow.
6. DSL
There's some languages written in rust.
See: https://github.com/gluon-lang/gluon

Which option do you prefer?

Closing in favor of #471.

Javascript based plugin is almost done, and there's a basic example of using plugin.
See https://github.com/swc-project/node-swc/blob/d51369e43e590fa66ddc2db6ca39976cdd185ac9/tests/transform/plugin.js

@cyjake See https://swc-project.github.io/docs/usage-plugin

Awesome! I'll try implementing babel-plugin-import this week

Hey @cyjake !
Are there any news about the plugin? :-)

@cyjake I documented about it at https://docs.rs/swc/0.65.0/swc/#cutomizing
I wrote document for someone building a custom node binding, but plugin api will be almost identical.

If anyone is still looking for one, here is my implementation. swc-plugin-transform-import.


Migrate all pipelines off Ubuntu 18.04 by 4/1/2023

The Ubuntu 18.04 image will be fully unsupported on 4/1/2023 (actions/runner-images#5583).  Any pipelines still using Ubuntu 18.04 should be upgraded to Ubuntu 20.04 or 22.04 before this date.
You can view the pipelines still running in pool azsdk-pool-mms-ubuntu-1804-general here:
https://dev.azure.com/azure-sdk/internal/_settings/agentqueues?queueId=120&view=jobs
I found the following repos still using Ubuntu 18.04.  Search for "18.04" or "1804".
https://github.com/Azure/azure-rest-api-specs-pipeline
https://github.com/azure/azure-sdk-for-c
https://github.com/azure/azure-sdk-for-cpp
https://github.com/Azure/azure-sdk-for-python
Related work:

https://github.com/Azure/azure-sdk-tools/issues/3407#issuecomment-1454165893
https://github.com/Azure/azure-sdk-tools/issues/5494

Page to check which builds are still using the Ubuntu 18 pool:
https://dev.azure.com/azure-sdk/_settings/agentpools?poolId=19&view=jobs

PR:

https://devdiv.visualstudio.com/DevDiv/_git/openapi-alps/pullrequest/455967

Related issue, possible blocker:

https://github.com/Azure/azure-sdk-for-net/issues/31839

There is also relevant email thread about it:

RE: Error of "No usable version of the libssl was found" when running autorest.csharp V2 in swagger pipeline

Search query:
https://github.com/search?q=org%3AAzure+(path%3A*.y*ml+OR+path%3A*.json)+MMSUbuntu18&type=code

Additional searches that may catch a few more cases:
Name of our DevOps Pool
https://github.com/search?q=org%3AAzure+(path%3A*.y*ml+OR+path%3A*.json)+azsdk-pool-mms-ubuntu-1804-general&type=code
Name of GitHub Actions Image (needs to be filtered to repos we own)
https://github.com/search?q=org%3AAzure+(path%3A*.y*ml+OR+path%3A*.json)+ubuntu-18.04&type=code

All the queries merged into one:
org:Azure (path:*.y*ml OR path:*.json) MMSUbuntu18 OR ubuntu18 OR azsdk-pool-mms-ubuntu-1804-general OR ubuntu-18.04
https://github.com/search?q=org%3AAzure+(path%3A*.y*ml+OR+path%3A*.json)+MMSUbuntu18+OR+ubuntu18+OR+azsdk-pool-mms-ubuntu-1804-general+OR+ubuntu-18.04&type=code

I am not submitting any PR against https://github.com/Azure/embedded-wireless-framework/ because:

It doesn't appear to use the Ubuntu 18 pool
All occurrences of azsdk-pool-mms-ubuntu-1804 in the repository are either in docs or examples dirs.

For https://github.com/Azure/azure-uamqp-python I made a direct commit, a no PR was necessary:
https://github.com/Azure/azure-uamqp-python/commit/bf1118c156bcf863250ef87f26bc29159d7f1674

I am not submitting any PR against https://github.com/Azure/iotedgedev
The search query returned only this:
pool:
  name: Azure-IoT-EdgeExperience-1ES-Hosted-Linux
  demands:
    - ImageOverride -equals MMSUbuntu18.04TLS

which is unrelated to our pools or images.

Status update as of 4/21/2023 PDT 6:30 PM. I did all the necessary updates.
Once this PR is merged:

https://github.com/Azure/azure-sdk-for-c/pull/2549

and search index updated to current main, then:

this query

We should no longer see any use of the  azsdk-pool-mms-ubuntu-1804-general pool

I got a notification of following failure for https://github.com/Azure/azure-uamqp-python:

Attempting fix by following commit:

https://github.com/Azure/azure-uamqp-python/commit/bf004b01db65e18b26d194d55335578369179d70

There have been no new builds scheduled since April 24:
https://dev.azure.com/azure-sdk/_settings/agentpools?poolId=19&view=jobs
Closing this issue as resolved.


Add biicode support to jsonxx

Hi Hong Jiang,
I am David from biicode, a small start-up that’s developing a C and C++ dependency manager; just like Maven and Maven Central for Java. The tool consists of two parts: the client installed in the user's machine and the cloud, populated with the most popular and demanded libs and frameworks. Some of our users had been requesting for a while already jsonxx so I decided to upload it and give it full support, and it works like a charm.
My idea is to make a merge request to your main repository to integrate biicode support. I have also included two files, biicode.conf and a CMakelist.txt, which allows your library to work with biicode and affect only when you want to use biicode, otherwise they are ignored, so you can use Jsonxx with biicode or without it without any problem.
I have fixed your Test too.
I tried to make the small changes it required as crystal clear as possible but feel free to request further more detail.
Now, let me show you how to use jsonxx with biicode.
Just clone your repository with the biicode.conf file and go into it. then, run the following commands:
$ git clone https://github.com/davidsanfal/Jsonxx.git
$ cd Jsonxx
$ bii init -L
$ bii build # Build the executables if it exists
$ bii test # build and run the test

test 1
    Start 1: hjiang_jsonxx_jsonxx_test

1: Test command: ~/jsonxx/bin/hjiang_jsonxx_jsonxx_test
1: Test timeout computed to be: 9.99988e+06
1: All tests ok.
1/1 Test #1: hjiang_jsonxx_jsonxx_test .........   Passed    0.00 sec

100% tests passed, 0 tests failed out of 1

Total Test time (real) =   0.00 sec

That's all, biicode will have compiled your code into the bin folder.
I have published this library on biicode, in david/jsonxx and I added a badge in your readme with the link to it just in case anyone want to use it with biicode.
We would love you to sign up in biicode so that you could maintain and keep your library up-to-date in biicode yourself. Our users would like to have their code dependent on the latest stable version of your code and there's no one better than you to keep it alike, beside that would allow any of our users to reuse your lib in any kind of project with just one #include.
Plus we have a smooth workflow with GitHub and Travis CI.
Looking forward to your reply.
Best regards.

Thanks for the message. But the very purpose of this project was to create a minimal dependency-free JSON parser, so I'd rather not add dependency management.


Text is weird

How do i fix this?

It keeps happening on the console thing too

input 'lang en-US' and restart


Feature: add --lockfile flag to allow users to customize lock file name

Usecase
When a project needs to have multiple lock files for different users, it is convenient to be able to rename the lockfile.
API Suggestion
uv lock --lockfile my_uv_lock_file.lock

Context
pdm has this feature.

Can you share more details about "different users"?

I should have said "different resolution". For example, one user wants to use "highest", and another wants to use "lowest-direct".

I agree that the feature would be very useful in different situations. In addition to the case that @jensqin mentioned, I personally use the --lockfile option from pdm to have different locks based on different sources. Right now with uv that might be translated as different lockfiles based on different sets of --index-url and --extra-index-url

Another use case is to support conflicting dependencies if/when #6981 is implemented.


Filter.OddMapCollectFlow test fails on Windows

Description:
Filter.OddMapCollectFlow test fails on Windows with the following error:
test/filter.cc(98): error: Expected equality of these values:
  *res.begin()
    Which is: 6
  18
test/filter.cc(99): error: Expected equality of these values:
  *++res.begin()
    Which is: 18
  6

Steps to reproduce:
Run the test on Windows.

I guess that the hashes for values are calculated in different ways
unordered_map::insert(const_iterator hint, T value)
where hint - just suggestion of the position, anyways the function can accept it or just calculate the hash and choose another position


Python: Update google-api-core pin to '>= 1.14.0, < 2.0.0dev'.

Needed to fix python-test, e.g.:  https://circleci.com/gh/googleapis/gapic-generator/31223

I have no clue how to diagnose / fix the failing gapic-generator-bazel-test CI job.


feat: backpropagate constants in ACIR during optimization

Description
Problem*
Resolves
Summary*
This is a mildy bruteforce-y optimisation method where we just literally attempt to execute the circuit backwards. Any witnesses which we can determine from this can just be written into the circuit directly.
A lot of the complexity here comes from the fact that memory opcodes, etc. require witnesses to be unassigned at the point at which the opcode is encountered so we need to "forget" certain witnesses so that we don't optimise them away.
Draft as I'm just pushing this up to track effects.
Additional Context
Documentation*
Check one:

[x] No documentation needed.
[ ] Documentation included in this PR.
[ ] [Exceptional Case] Documentation to be submitted in a separate PR.

PR Checklist*

[x] I have tested the changes locally.
[x] I have formatted the changes with Prettier and/or cargo fmt on default settings.

This is currently deleting constant brillig programs


[Enhancement] Don't delete files in trashcan after 30 days

Hi. I'd like to have an option to not deleting the files in trashcan after 30 days.

This is not possible as the Gallery is not in charge of the trash can, but the media store (android media management).