diff --git a/.vscode/settings.json b/.vscode/settings.json index 8f170fb8..8267437e 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,3 +1,6 @@ { "rust-analyzer.check.command": "clippy", + "rust-analyzer.linkedProjects": [ + "rust\\bindings\\dart_vdd\\rust\\Cargo.toml" + ], } diff --git a/rust/Cargo.lock b/rust/Cargo.lock index fa9e17ae..677518a4 100644 --- a/rust/Cargo.lock +++ b/rust/Cargo.lock @@ -26,6 +26,35 @@ dependencies = [ "memchr", ] +[[package]] +name = "allo-isolate" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f5a5fd28223e6f3cafb7d9cd685f51eafdd71d33ca1229f8316925d5957240" +dependencies = [ + "anyhow", + "atomic", + "backtrace", +] + +[[package]] +name = "android_log-sys" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ecc8056bf6ab9892dcd53216c83d1597487d7dacac16c8df6b877d127df9937" + +[[package]] +name = "android_logger" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c494134f746c14dc653a35a4ea5aca24ac368529da5370ecf41fe0341c35772f" +dependencies = [ + "android_log-sys", + "env_logger", + "log", + "once_cell", +] + [[package]] name = "anstream" version = "0.6.13" @@ -76,9 +105,15 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.81" +version = "1.0.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0952808a6c2afd1aa8947271f3a60f1a6763c7b912d210184c5149b5cf147247" +checksum = "f538837af36e6f6a9be0faa67f9a314f8119e4e4b5867c6ab40ed60360142519" + +[[package]] +name = "atomic" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c59bdb34bc650a32731b31bd8f0829cc15d24a708ee31559e0bb34f2bc320cba" [[package]] name = "autocfg" @@ -136,6 +171,18 @@ version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" +[[package]] +name = "build-target" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "832133bbabbbaa9fbdba793456a2827627a7d2b8fb96032fa1e7666d7895832b" + +[[package]] +name = "bumpalo" +version = "3.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" + [[package]] name = "bytemuck" version = "1.15.0" @@ -156,6 +203,12 @@ dependencies = [ "syn", ] +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + [[package]] name = "bytes" version = "1.6.0" @@ -164,9 +217,9 @@ checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" [[package]] name = "cc" -version = "1.0.90" +version = "1.0.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cd6604a82acf3039f1144f54b8eb34e91ffba622051189e71b781822d5ee1f5" +checksum = "2678b2e3449475e95b0aa6f9b506a28e61b3dc8996592b983695e8ebb58a8b41" [[package]] name = "cexpr" @@ -267,6 +320,54 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" +[[package]] +name = "console_error_panic_hook" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc" +dependencies = [ + "cfg-if", + "wasm-bindgen", +] + +[[package]] +name = "dart-sys-fork" +version = "4.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "933dafff26172b719bb9695dd3715a1e7792f62dcdc8a5d4c740db7e0fedee8b" +dependencies = [ + "cc", +] + +[[package]] +name = "dart-vdd" +version = "0.1.0" +dependencies = [ + "driver-ipc", + "flutter_rust_bridge", +] + +[[package]] +name = "dashmap" +version = "4.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e77a43b28d0668df09411cb0bc9a8c2adc40f9a048afe863e05fd43251e8e39c" +dependencies = [ + "cfg-if", + "num_cpus", +] + +[[package]] +name = "delegate-attr" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51aac4c99b2e6775164b412ea33ae8441b2fde2dbf05a20bc0052a63d08c475b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "deranged" version = "0.3.11" @@ -321,6 +422,16 @@ dependencies = [ "log", ] +[[package]] +name = "env_logger" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd405aab171cb85d6735e5c8d9db038c17d3ca007a4d2c25f337935c3d90580" +dependencies = [ + "log", + "regex", +] + [[package]] name = "equivalent" version = "1.0.1" @@ -347,6 +458,133 @@ dependencies = [ "once_cell", ] +[[package]] +name = "flutter_rust_bridge" +version = "2.0.0-dev.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d9ceb6f8db0bf711a55e20151c6699132bb5975f846ecac2c3bc7d23cc0845d" +dependencies = [ + "allo-isolate", + "android_logger", + "anyhow", + "build-target", + "bytemuck", + "byteorder", + "console_error_panic_hook", + "dart-sys-fork", + "delegate-attr", + "flutter_rust_bridge_macros", + "futures", + "js-sys", + "lazy_static", + "oslog", + "threadpool", + "tokio", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + +[[package]] +name = "flutter_rust_bridge_macros" +version = "2.0.0-dev.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e02edfe56f04af804d3145b17dfe7820d46a6753b214160f227dbdfa1073f7cb" +dependencies = [ + "hex", + "quote", + "syn", +] + +[[package]] +name = "futures" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" + +[[package]] +name = "futures-executor" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" + +[[package]] +name = "futures-macro" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "futures-sink" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" + +[[package]] +name = "futures-task" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" + +[[package]] +name = "futures-util" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + [[package]] name = "gimli" version = "0.28.1" @@ -383,6 +621,12 @@ version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + [[package]] name = "home" version = "0.5.9" @@ -435,6 +679,15 @@ version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57d8bde02bbf44a562cf068a8ff4a68842df387e302a03a4de4a57fcf82ec377" +[[package]] +name = "js-sys" +version = "0.3.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" +dependencies = [ + "wasm-bindgen", +] + [[package]] name = "lazy_format" version = "2.0.3" @@ -582,6 +835,17 @@ version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +[[package]] +name = "oslog" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8343ce955f18e7e68c0207dd0ea776ec453035685395ababd2ea651c569728b3" +dependencies = [ + "cc", + "dashmap", + "log", +] + [[package]] name = "owo-colors" version = "3.5.0" @@ -629,6 +893,12 @@ version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + [[package]] name = "portable-atomic" version = "1.6.0" @@ -733,9 +1003,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.35" +version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" dependencies = [ "proc-macro2", ] @@ -805,9 +1075,9 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.14" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" +checksum = "80af6f9131f277a45a3fba6ce8e2258037bb0477a67e610d3c1fe046ab31de47" [[package]] name = "ryu" @@ -885,6 +1155,15 @@ dependencies = [ "libc", ] +[[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] + [[package]] name = "smallvec" version = "1.13.2" @@ -903,15 +1182,15 @@ dependencies = [ [[package]] name = "strsim" -version = "0.11.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ee073c9e4cd00e28217186dbe12796d692868f432bf2e97ee73bed0c56dfa01" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "syn" -version = "2.0.57" +version = "2.0.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11a6ae1e52eb25aab8f3fb9fca13be982a373b8f1157ca14b897a825ba4a2d35" +checksum = "44cfb93f38070beee36b3fef7d4f5a16f27751d94b187b666a5cc5e9b0d30687" dependencies = [ "proc-macro2", "quote", @@ -954,11 +1233,20 @@ dependencies = [ "once_cell", ] +[[package]] +name = "threadpool" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa" +dependencies = [ + "num_cpus", +] + [[package]] name = "time" -version = "0.3.34" +version = "0.3.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8248b6521bb14bc45b4067159b9b6ad792e2d6d754d6c41fb50e29fefe38749" +checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" dependencies = [ "deranged", "itoa", @@ -979,9 +1267,9 @@ checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" -version = "0.2.17" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ba3a3ef41e6672a2f0f001392bb5dcd3ff0a9992d618ca761a11c3121547774" +checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" dependencies = [ "num-conv", "time-core", @@ -1197,6 +1485,72 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +[[package]] +name = "wasm-bindgen" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" + [[package]] name = "wdf-umdf" version = "0.1.0" @@ -1217,6 +1571,16 @@ dependencies = [ "winreg", ] +[[package]] +name = "web-sys" +version = "0.3.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + [[package]] name = "which" version = "4.4.2" diff --git a/rust/Cargo.toml b/rust/Cargo.toml index d8e7d13f..29211e93 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -1,14 +1,15 @@ [workspace] resolver = "2" members = [ - "virtual-display-driver", "wdf-umdf-sys", "wdf-umdf", "driver-ipc", "driver-logger", + "virtual-display-driver", "virtual-display-driver-cli", - "bindings/pyvdd", "vdd-user-session-service", + "bindings/pyvdd", + "bindings/dart_vdd/rust", ] [profile.release] diff --git a/rust/bindings/dart_vdd/.gitignore b/rust/bindings/dart_vdd/.gitignore new file mode 100644 index 00000000..3cceda55 --- /dev/null +++ b/rust/bindings/dart_vdd/.gitignore @@ -0,0 +1,7 @@ +# https://dart.dev/guides/libraries/private-files +# Created by `dart pub` +.dart_tool/ + +# Avoid committing pubspec.lock for library packages; see +# https://dart.dev/guides/libraries/private-files#pubspeclock. +pubspec.lock diff --git a/rust/bindings/dart_vdd/CHANGELOG.md b/rust/bindings/dart_vdd/CHANGELOG.md new file mode 100644 index 00000000..effe43c8 --- /dev/null +++ b/rust/bindings/dart_vdd/CHANGELOG.md @@ -0,0 +1,3 @@ +## 1.0.0 + +- Initial version. diff --git a/rust/bindings/dart_vdd/Makefile.toml b/rust/bindings/dart_vdd/Makefile.toml new file mode 100644 index 00000000..7b2b9a45 --- /dev/null +++ b/rust/bindings/dart_vdd/Makefile.toml @@ -0,0 +1,5 @@ +[tasks.generate] +install_crate = "flutter_rust_bridge_codegen@^2.0.0-dev.31" +script = ''' + flutter_rust_bridge_codegen generate + ''' diff --git a/rust/bindings/dart_vdd/README.md b/rust/bindings/dart_vdd/README.md new file mode 100644 index 00000000..8b55e735 --- /dev/null +++ b/rust/bindings/dart_vdd/README.md @@ -0,0 +1,39 @@ + + +TODO: Put a short description of the package here that helps potential users +know whether this package might be useful for them. + +## Features + +TODO: List what your package can do. Maybe include images, gifs, or videos. + +## Getting started + +TODO: List prerequisites and provide or point to information on how to +start using the package. + +## Usage + +TODO: Include short and useful examples for package users. Add longer examples +to `/example` folder. + +```dart +const like = 'sample'; +``` + +## Additional information + +TODO: Tell users more about the package: where to find more information, how to +contribute to the package, how to file issues, what response they can expect +from the package authors, and more. diff --git a/rust/bindings/dart_vdd/analysis_options.yaml b/rust/bindings/dart_vdd/analysis_options.yaml new file mode 100644 index 00000000..dee8927a --- /dev/null +++ b/rust/bindings/dart_vdd/analysis_options.yaml @@ -0,0 +1,30 @@ +# This file configures the static analysis results for your project (errors, +# warnings, and lints). +# +# This enables the 'recommended' set of lints from `package:lints`. +# This set helps identify many issues that may lead to problems when running +# or consuming Dart code, and enforces writing Dart using a single, idiomatic +# style and format. +# +# If you want a smaller set of lints you can change this to specify +# 'package:lints/core.yaml'. These are just the most critical lints +# (the recommended set includes the core lints). +# The core lints are also what is used by pub.dev for scoring packages. + +include: package:lints/recommended.yaml + +# Uncomment the following section to specify additional rules. + +# linter: +# rules: +# - camel_case_types + +# analyzer: +# exclude: +# - path/to/excluded/files/** + +# For more information about the core and recommended set of lints, see +# https://dart.dev/go/core-lints + +# For additional information about configuring this file, see +# https://dart.dev/guides/language/analysis-options diff --git a/rust/bindings/dart_vdd/build.dart b/rust/bindings/dart_vdd/build.dart new file mode 100644 index 00000000..ab96e132 --- /dev/null +++ b/rust/bindings/dart_vdd/build.dart @@ -0,0 +1,45 @@ +import 'dart:io'; + +import 'package:flutter_rust_bridge/src/cli/run_command.dart'; +import 'package:native_assets_cli/native_assets_cli.dart'; + +void main(List args) async { + final buildConfig = await BuildConfig.fromArgs(args); + final buildOutput = BuildOutput(); + + final rustCrateDir = buildConfig.packageRoot.resolve('rust'); + + final rustflags = Platform.environment['RUSTFLAGS']; + + await runCommand( + 'cargo', + [ + 'build', + '--release', + '--out-dir', + buildConfig.outDir.toFilePath(), + '-Z', + 'unstable-options', + ], + pwd: rustCrateDir.toFilePath(), + printCommandInStderr: true, + env: { + // Though runCommand auto pass environment variable to commands, + // we do this to explicitly show this important flag + if (rustflags != null) 'RUSTFLAGS': rustflags, + }, + ); + + buildOutput.dependencies.dependencies.addAll({ + rustCrateDir, + buildConfig.packageRoot.resolve('build.rs'), + }); + buildOutput.assets.add(Asset( + id: "package:dart_vdd/dart-vdd-lib.dart", + linkMode: LinkMode.dynamic, + target: Target.current, + path: AssetAbsolutePath(buildConfig.outDir.resolve('dart_vdd.dll')), + )); + + await buildOutput.writeToFile(outDir: buildConfig.outDir); +} diff --git a/rust/bindings/dart_vdd/example/dart_vdd_example.dart b/rust/bindings/dart_vdd/example/dart_vdd_example.dart new file mode 100644 index 00000000..dc612c98 --- /dev/null +++ b/rust/bindings/dart_vdd/example/dart_vdd_example.dart @@ -0,0 +1,42 @@ +import 'dart:io'; + +import 'package:dart_vdd/dart_vdd.dart'; +import 'package:dart_vdd/src/generated/frb_generated.dart'; +import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart'; + +/// Can be run from package root using `dart --enable-experiment=native-assets +/// run .\example\dart_vdd_example.dart` +void main() async { + await RustLib.init( + // There is currently no way to accurately resolve the shared library in + // every szenario + externalLibrary: ExternalLibrary.open("../../target/release/dart_vdd.dll"), + + // This works with `dart build` + // externalLibrary: ExternalLibrary.open("dart_vdd.dll"), + ); + + final driver = await VirtualDisplayDriver.newInstance(); + + print(driver.state); + + Future(() async { + await for (final monitors in await driver.stream) { + print('monitors: $monitors'); + } + }); + + driver.addMonitor(enabled: true, modes: [ + Mode(width: 1920, height: 1080, refreshRates: Uint32List.fromList([60])), + ]); + await driver.notify(); + await driver.persist(); + + await Future.delayed(Duration(seconds: 10)); + + driver.removeAllMonitors(); + await driver.notify(); + await driver.persist(); + + exit(0); +} diff --git a/rust/bindings/dart_vdd/flutter_rust_bridge.yaml b/rust/bindings/dart_vdd/flutter_rust_bridge.yaml new file mode 100644 index 00000000..9431113b --- /dev/null +++ b/rust/bindings/dart_vdd/flutter_rust_bridge.yaml @@ -0,0 +1,3 @@ +rust_input: rust/src/api.rs # Glob pattern +dart_output: lib/src/generated # Directory +web: false diff --git a/rust/bindings/dart_vdd/lib/dart_vdd.dart b/rust/bindings/dart_vdd/lib/dart_vdd.dart new file mode 100644 index 00000000..0ee5a6d7 --- /dev/null +++ b/rust/bindings/dart_vdd/lib/dart_vdd.dart @@ -0,0 +1,16 @@ +/// Support for doing something awesome. +/// +/// More dartdocs go here. +library; + +import 'package:dart_vdd/src/generated/frb_generated.dart'; +import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart'; + +export 'src/generated/api.dart'; + +Future initVdd() async { + await RustLib.init( + // This works with `dart build`, `flutter build`, `flutter run` + externalLibrary: ExternalLibrary.open("dart_vdd.dll"), + ); +} diff --git a/rust/bindings/dart_vdd/lib/src/generated/api.dart b/rust/bindings/dart_vdd/lib/src/generated/api.dart new file mode 100644 index 00000000..a5b56e76 --- /dev/null +++ b/rust/bindings/dart_vdd/lib/src/generated/api.dart @@ -0,0 +1,148 @@ +// This file is automatically generated, so please do not edit it. +// Generated by `flutter_rust_bridge`@ 2.0.0-dev.31. + +// ignore_for_file: invalid_use_of_internal_member, unused_import, unnecessary_import + +import 'frb_generated.dart'; +import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart'; +import 'package:freezed_annotation/freezed_annotation.dart' hide protected; +part 'api.freezed.dart'; + +// Rust type: RustOpaqueMoi> +@sealed +class VirtualDisplayDriver extends RustOpaque { + VirtualDisplayDriver.dcoDecode(List wire) + : super.dcoDecode(wire, _kStaticData); + + VirtualDisplayDriver.sseDecode(int ptr, int externalSizeOnNative) + : super.sseDecode(ptr, externalSizeOnNative, _kStaticData); + + static final _kStaticData = RustArcStaticData( + rustArcIncrementStrongCount: RustLib + .instance.api.rust_arc_increment_strong_count_VirtualDisplayDriver, + rustArcDecrementStrongCount: RustLib + .instance.api.rust_arc_decrement_strong_count_VirtualDisplayDriver, + rustArcDecrementStrongCountPtr: RustLib + .instance.api.rust_arc_decrement_strong_count_VirtualDisplayDriverPtr, + ); + + /// Add a new monitor to the driver. + void addMonitor( + {String? name, + required bool enabled, + required List modes, + dynamic hint}) => + RustLib.instance.api.virtualDisplayDriverAddMonitor( + that: this, name: name, enabled: enabled, modes: modes, hint: hint); + + /// Cancel any previously set up stream + Future cancelStream({dynamic hint}) => RustLib.instance.api + .virtualDisplayDriverCancelStream(that: this, hint: hint); + + // HINT: Make it `#[frb(sync)]` to let it become the default constructor of Dart class. + static Future newInstance( + {String? pipeName, dynamic hint}) => + RustLib.instance.api + .virtualDisplayDriverNew(pipeName: pipeName, hint: hint); + + /// Push in-memory changes to driver. + Future notify({dynamic hint}) => + RustLib.instance.api.virtualDisplayDriverNotify(that: this, hint: hint); + + /// Persist in-memory changes to user settings + Future persist({dynamic hint}) => + RustLib.instance.api.virtualDisplayDriverPersist(that: this, hint: hint); + + /// Remove all monitors from the driver. + void removeAllMonitors({dynamic hint}) => RustLib.instance.api + .virtualDisplayDriverRemoveAllMonitors(that: this, hint: hint); + + /// Remove monitors from the driver. + void removeMonitors({required List ids, dynamic hint}) => + RustLib.instance.api + .virtualDisplayDriverRemoveMonitors(that: this, ids: ids, hint: hint); + + /// Set the state of the monitor with the provided ID. + /// + /// Only the provided properties will be updated. + void setMonitor( + {required int id, + bool? enabled, + String? name, + List? modes, + dynamic hint}) => + RustLib.instance.api.virtualDisplayDriverSetMonitor( + that: this, + id: id, + enabled: enabled, + name: name, + modes: modes, + hint: hint); + + /// Set the state of the provided monitors. + /// + /// Each monitor with a matching ID will be updated to the provided state. + void setMonitors({required List monitors, dynamic hint}) => + RustLib.instance.api.virtualDisplayDriverSetMonitors( + that: this, monitors: monitors, hint: hint); + + /// Get the current state of the driver. + List get state => RustLib.instance.api.virtualDisplayDriverState( + that: this, + ); + + /// Stream of state changes. + /// + /// Updates whenever the state of the driver changes. It does not matter + /// from which process the change is requested. It will always reflect the + /// current state of the driver. + /// + /// If set again, it will cancel the old stream and set the new one + Future>> get stream => + RustLib.instance.api.virtualDisplayDriverStream( + that: this, + ); +} + +@freezed +sealed class IpcError with _$IpcError implements FrbException { + const IpcError._(); + + const factory IpcError.serDe( + String field0, + ) = IpcError_SerDe; + const factory IpcError.io( + String field0, + ) = IpcError_Io; + const factory IpcError.win( + String field0, + ) = IpcError_Win; + const factory IpcError.client( + String field0, + ) = IpcError_Client; + const factory IpcError.requestState() = IpcError_RequestState; + const factory IpcError.receive() = IpcError_Receive; + const factory IpcError.connectionFailed( + String field0, + ) = IpcError_ConnectionFailed; + const factory IpcError.sendFailed() = IpcError_SendFailed; +} + +@freezed +class Mode with _$Mode { + const factory Mode({ + required int width, + required int height, + required Uint32List refreshRates, + }) = _Mode; +} + +@freezed +class Monitor with _$Monitor { + const factory Monitor({ + required int id, + String? name, + required bool enabled, + required List modes, + }) = _Monitor; +} diff --git a/rust/bindings/dart_vdd/lib/src/generated/api.freezed.dart b/rust/bindings/dart_vdd/lib/src/generated/api.freezed.dart new file mode 100644 index 00000000..f2ed647c --- /dev/null +++ b/rust/bindings/dart_vdd/lib/src/generated/api.freezed.dart @@ -0,0 +1,1714 @@ +// coverage:ignore-file +// GENERATED CODE - DO NOT MODIFY BY HAND +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'api.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +T _$identity(T value) => value; + +final _privateConstructorUsedError = UnsupportedError( + 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models'); + +/// @nodoc +mixin _$IpcError { + @optionalTypeArgs + TResult when({ + required TResult Function(String field0) serDe, + required TResult Function(String field0) io, + required TResult Function(String field0) win, + required TResult Function(String field0) client, + required TResult Function() requestState, + required TResult Function() receive, + required TResult Function(String field0) connectionFailed, + required TResult Function() sendFailed, + }) => + throw _privateConstructorUsedError; + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(String field0)? serDe, + TResult? Function(String field0)? io, + TResult? Function(String field0)? win, + TResult? Function(String field0)? client, + TResult? Function()? requestState, + TResult? Function()? receive, + TResult? Function(String field0)? connectionFailed, + TResult? Function()? sendFailed, + }) => + throw _privateConstructorUsedError; + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(String field0)? serDe, + TResult Function(String field0)? io, + TResult Function(String field0)? win, + TResult Function(String field0)? client, + TResult Function()? requestState, + TResult Function()? receive, + TResult Function(String field0)? connectionFailed, + TResult Function()? sendFailed, + required TResult orElse(), + }) => + throw _privateConstructorUsedError; + @optionalTypeArgs + TResult map({ + required TResult Function(IpcError_SerDe value) serDe, + required TResult Function(IpcError_Io value) io, + required TResult Function(IpcError_Win value) win, + required TResult Function(IpcError_Client value) client, + required TResult Function(IpcError_RequestState value) requestState, + required TResult Function(IpcError_Receive value) receive, + required TResult Function(IpcError_ConnectionFailed value) connectionFailed, + required TResult Function(IpcError_SendFailed value) sendFailed, + }) => + throw _privateConstructorUsedError; + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(IpcError_SerDe value)? serDe, + TResult? Function(IpcError_Io value)? io, + TResult? Function(IpcError_Win value)? win, + TResult? Function(IpcError_Client value)? client, + TResult? Function(IpcError_RequestState value)? requestState, + TResult? Function(IpcError_Receive value)? receive, + TResult? Function(IpcError_ConnectionFailed value)? connectionFailed, + TResult? Function(IpcError_SendFailed value)? sendFailed, + }) => + throw _privateConstructorUsedError; + @optionalTypeArgs + TResult maybeMap({ + TResult Function(IpcError_SerDe value)? serDe, + TResult Function(IpcError_Io value)? io, + TResult Function(IpcError_Win value)? win, + TResult Function(IpcError_Client value)? client, + TResult Function(IpcError_RequestState value)? requestState, + TResult Function(IpcError_Receive value)? receive, + TResult Function(IpcError_ConnectionFailed value)? connectionFailed, + TResult Function(IpcError_SendFailed value)? sendFailed, + required TResult orElse(), + }) => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $IpcErrorCopyWith<$Res> { + factory $IpcErrorCopyWith(IpcError value, $Res Function(IpcError) then) = + _$IpcErrorCopyWithImpl<$Res, IpcError>; +} + +/// @nodoc +class _$IpcErrorCopyWithImpl<$Res, $Val extends IpcError> + implements $IpcErrorCopyWith<$Res> { + _$IpcErrorCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; +} + +/// @nodoc +abstract class _$$IpcError_SerDeImplCopyWith<$Res> { + factory _$$IpcError_SerDeImplCopyWith(_$IpcError_SerDeImpl value, + $Res Function(_$IpcError_SerDeImpl) then) = + __$$IpcError_SerDeImplCopyWithImpl<$Res>; + @useResult + $Res call({String field0}); +} + +/// @nodoc +class __$$IpcError_SerDeImplCopyWithImpl<$Res> + extends _$IpcErrorCopyWithImpl<$Res, _$IpcError_SerDeImpl> + implements _$$IpcError_SerDeImplCopyWith<$Res> { + __$$IpcError_SerDeImplCopyWithImpl( + _$IpcError_SerDeImpl _value, $Res Function(_$IpcError_SerDeImpl) _then) + : super(_value, _then); + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? field0 = null, + }) { + return _then(_$IpcError_SerDeImpl( + null == field0 + ? _value.field0 + : field0 // ignore: cast_nullable_to_non_nullable + as String, + )); + } +} + +/// @nodoc + +class _$IpcError_SerDeImpl extends IpcError_SerDe { + const _$IpcError_SerDeImpl(this.field0) : super._(); + + @override + final String field0; + + @override + String toString() { + return 'IpcError.serDe(field0: $field0)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$IpcError_SerDeImpl && + (identical(other.field0, field0) || other.field0 == field0)); + } + + @override + int get hashCode => Object.hash(runtimeType, field0); + + @JsonKey(ignore: true) + @override + @pragma('vm:prefer-inline') + _$$IpcError_SerDeImplCopyWith<_$IpcError_SerDeImpl> get copyWith => + __$$IpcError_SerDeImplCopyWithImpl<_$IpcError_SerDeImpl>( + this, _$identity); + + @override + @optionalTypeArgs + TResult when({ + required TResult Function(String field0) serDe, + required TResult Function(String field0) io, + required TResult Function(String field0) win, + required TResult Function(String field0) client, + required TResult Function() requestState, + required TResult Function() receive, + required TResult Function(String field0) connectionFailed, + required TResult Function() sendFailed, + }) { + return serDe(field0); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(String field0)? serDe, + TResult? Function(String field0)? io, + TResult? Function(String field0)? win, + TResult? Function(String field0)? client, + TResult? Function()? requestState, + TResult? Function()? receive, + TResult? Function(String field0)? connectionFailed, + TResult? Function()? sendFailed, + }) { + return serDe?.call(field0); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(String field0)? serDe, + TResult Function(String field0)? io, + TResult Function(String field0)? win, + TResult Function(String field0)? client, + TResult Function()? requestState, + TResult Function()? receive, + TResult Function(String field0)? connectionFailed, + TResult Function()? sendFailed, + required TResult orElse(), + }) { + if (serDe != null) { + return serDe(field0); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(IpcError_SerDe value) serDe, + required TResult Function(IpcError_Io value) io, + required TResult Function(IpcError_Win value) win, + required TResult Function(IpcError_Client value) client, + required TResult Function(IpcError_RequestState value) requestState, + required TResult Function(IpcError_Receive value) receive, + required TResult Function(IpcError_ConnectionFailed value) connectionFailed, + required TResult Function(IpcError_SendFailed value) sendFailed, + }) { + return serDe(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(IpcError_SerDe value)? serDe, + TResult? Function(IpcError_Io value)? io, + TResult? Function(IpcError_Win value)? win, + TResult? Function(IpcError_Client value)? client, + TResult? Function(IpcError_RequestState value)? requestState, + TResult? Function(IpcError_Receive value)? receive, + TResult? Function(IpcError_ConnectionFailed value)? connectionFailed, + TResult? Function(IpcError_SendFailed value)? sendFailed, + }) { + return serDe?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(IpcError_SerDe value)? serDe, + TResult Function(IpcError_Io value)? io, + TResult Function(IpcError_Win value)? win, + TResult Function(IpcError_Client value)? client, + TResult Function(IpcError_RequestState value)? requestState, + TResult Function(IpcError_Receive value)? receive, + TResult Function(IpcError_ConnectionFailed value)? connectionFailed, + TResult Function(IpcError_SendFailed value)? sendFailed, + required TResult orElse(), + }) { + if (serDe != null) { + return serDe(this); + } + return orElse(); + } +} + +abstract class IpcError_SerDe extends IpcError { + const factory IpcError_SerDe(final String field0) = _$IpcError_SerDeImpl; + const IpcError_SerDe._() : super._(); + + String get field0; + @JsonKey(ignore: true) + _$$IpcError_SerDeImplCopyWith<_$IpcError_SerDeImpl> get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class _$$IpcError_IoImplCopyWith<$Res> { + factory _$$IpcError_IoImplCopyWith( + _$IpcError_IoImpl value, $Res Function(_$IpcError_IoImpl) then) = + __$$IpcError_IoImplCopyWithImpl<$Res>; + @useResult + $Res call({String field0}); +} + +/// @nodoc +class __$$IpcError_IoImplCopyWithImpl<$Res> + extends _$IpcErrorCopyWithImpl<$Res, _$IpcError_IoImpl> + implements _$$IpcError_IoImplCopyWith<$Res> { + __$$IpcError_IoImplCopyWithImpl( + _$IpcError_IoImpl _value, $Res Function(_$IpcError_IoImpl) _then) + : super(_value, _then); + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? field0 = null, + }) { + return _then(_$IpcError_IoImpl( + null == field0 + ? _value.field0 + : field0 // ignore: cast_nullable_to_non_nullable + as String, + )); + } +} + +/// @nodoc + +class _$IpcError_IoImpl extends IpcError_Io { + const _$IpcError_IoImpl(this.field0) : super._(); + + @override + final String field0; + + @override + String toString() { + return 'IpcError.io(field0: $field0)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$IpcError_IoImpl && + (identical(other.field0, field0) || other.field0 == field0)); + } + + @override + int get hashCode => Object.hash(runtimeType, field0); + + @JsonKey(ignore: true) + @override + @pragma('vm:prefer-inline') + _$$IpcError_IoImplCopyWith<_$IpcError_IoImpl> get copyWith => + __$$IpcError_IoImplCopyWithImpl<_$IpcError_IoImpl>(this, _$identity); + + @override + @optionalTypeArgs + TResult when({ + required TResult Function(String field0) serDe, + required TResult Function(String field0) io, + required TResult Function(String field0) win, + required TResult Function(String field0) client, + required TResult Function() requestState, + required TResult Function() receive, + required TResult Function(String field0) connectionFailed, + required TResult Function() sendFailed, + }) { + return io(field0); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(String field0)? serDe, + TResult? Function(String field0)? io, + TResult? Function(String field0)? win, + TResult? Function(String field0)? client, + TResult? Function()? requestState, + TResult? Function()? receive, + TResult? Function(String field0)? connectionFailed, + TResult? Function()? sendFailed, + }) { + return io?.call(field0); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(String field0)? serDe, + TResult Function(String field0)? io, + TResult Function(String field0)? win, + TResult Function(String field0)? client, + TResult Function()? requestState, + TResult Function()? receive, + TResult Function(String field0)? connectionFailed, + TResult Function()? sendFailed, + required TResult orElse(), + }) { + if (io != null) { + return io(field0); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(IpcError_SerDe value) serDe, + required TResult Function(IpcError_Io value) io, + required TResult Function(IpcError_Win value) win, + required TResult Function(IpcError_Client value) client, + required TResult Function(IpcError_RequestState value) requestState, + required TResult Function(IpcError_Receive value) receive, + required TResult Function(IpcError_ConnectionFailed value) connectionFailed, + required TResult Function(IpcError_SendFailed value) sendFailed, + }) { + return io(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(IpcError_SerDe value)? serDe, + TResult? Function(IpcError_Io value)? io, + TResult? Function(IpcError_Win value)? win, + TResult? Function(IpcError_Client value)? client, + TResult? Function(IpcError_RequestState value)? requestState, + TResult? Function(IpcError_Receive value)? receive, + TResult? Function(IpcError_ConnectionFailed value)? connectionFailed, + TResult? Function(IpcError_SendFailed value)? sendFailed, + }) { + return io?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(IpcError_SerDe value)? serDe, + TResult Function(IpcError_Io value)? io, + TResult Function(IpcError_Win value)? win, + TResult Function(IpcError_Client value)? client, + TResult Function(IpcError_RequestState value)? requestState, + TResult Function(IpcError_Receive value)? receive, + TResult Function(IpcError_ConnectionFailed value)? connectionFailed, + TResult Function(IpcError_SendFailed value)? sendFailed, + required TResult orElse(), + }) { + if (io != null) { + return io(this); + } + return orElse(); + } +} + +abstract class IpcError_Io extends IpcError { + const factory IpcError_Io(final String field0) = _$IpcError_IoImpl; + const IpcError_Io._() : super._(); + + String get field0; + @JsonKey(ignore: true) + _$$IpcError_IoImplCopyWith<_$IpcError_IoImpl> get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class _$$IpcError_WinImplCopyWith<$Res> { + factory _$$IpcError_WinImplCopyWith( + _$IpcError_WinImpl value, $Res Function(_$IpcError_WinImpl) then) = + __$$IpcError_WinImplCopyWithImpl<$Res>; + @useResult + $Res call({String field0}); +} + +/// @nodoc +class __$$IpcError_WinImplCopyWithImpl<$Res> + extends _$IpcErrorCopyWithImpl<$Res, _$IpcError_WinImpl> + implements _$$IpcError_WinImplCopyWith<$Res> { + __$$IpcError_WinImplCopyWithImpl( + _$IpcError_WinImpl _value, $Res Function(_$IpcError_WinImpl) _then) + : super(_value, _then); + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? field0 = null, + }) { + return _then(_$IpcError_WinImpl( + null == field0 + ? _value.field0 + : field0 // ignore: cast_nullable_to_non_nullable + as String, + )); + } +} + +/// @nodoc + +class _$IpcError_WinImpl extends IpcError_Win { + const _$IpcError_WinImpl(this.field0) : super._(); + + @override + final String field0; + + @override + String toString() { + return 'IpcError.win(field0: $field0)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$IpcError_WinImpl && + (identical(other.field0, field0) || other.field0 == field0)); + } + + @override + int get hashCode => Object.hash(runtimeType, field0); + + @JsonKey(ignore: true) + @override + @pragma('vm:prefer-inline') + _$$IpcError_WinImplCopyWith<_$IpcError_WinImpl> get copyWith => + __$$IpcError_WinImplCopyWithImpl<_$IpcError_WinImpl>(this, _$identity); + + @override + @optionalTypeArgs + TResult when({ + required TResult Function(String field0) serDe, + required TResult Function(String field0) io, + required TResult Function(String field0) win, + required TResult Function(String field0) client, + required TResult Function() requestState, + required TResult Function() receive, + required TResult Function(String field0) connectionFailed, + required TResult Function() sendFailed, + }) { + return win(field0); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(String field0)? serDe, + TResult? Function(String field0)? io, + TResult? Function(String field0)? win, + TResult? Function(String field0)? client, + TResult? Function()? requestState, + TResult? Function()? receive, + TResult? Function(String field0)? connectionFailed, + TResult? Function()? sendFailed, + }) { + return win?.call(field0); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(String field0)? serDe, + TResult Function(String field0)? io, + TResult Function(String field0)? win, + TResult Function(String field0)? client, + TResult Function()? requestState, + TResult Function()? receive, + TResult Function(String field0)? connectionFailed, + TResult Function()? sendFailed, + required TResult orElse(), + }) { + if (win != null) { + return win(field0); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(IpcError_SerDe value) serDe, + required TResult Function(IpcError_Io value) io, + required TResult Function(IpcError_Win value) win, + required TResult Function(IpcError_Client value) client, + required TResult Function(IpcError_RequestState value) requestState, + required TResult Function(IpcError_Receive value) receive, + required TResult Function(IpcError_ConnectionFailed value) connectionFailed, + required TResult Function(IpcError_SendFailed value) sendFailed, + }) { + return win(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(IpcError_SerDe value)? serDe, + TResult? Function(IpcError_Io value)? io, + TResult? Function(IpcError_Win value)? win, + TResult? Function(IpcError_Client value)? client, + TResult? Function(IpcError_RequestState value)? requestState, + TResult? Function(IpcError_Receive value)? receive, + TResult? Function(IpcError_ConnectionFailed value)? connectionFailed, + TResult? Function(IpcError_SendFailed value)? sendFailed, + }) { + return win?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(IpcError_SerDe value)? serDe, + TResult Function(IpcError_Io value)? io, + TResult Function(IpcError_Win value)? win, + TResult Function(IpcError_Client value)? client, + TResult Function(IpcError_RequestState value)? requestState, + TResult Function(IpcError_Receive value)? receive, + TResult Function(IpcError_ConnectionFailed value)? connectionFailed, + TResult Function(IpcError_SendFailed value)? sendFailed, + required TResult orElse(), + }) { + if (win != null) { + return win(this); + } + return orElse(); + } +} + +abstract class IpcError_Win extends IpcError { + const factory IpcError_Win(final String field0) = _$IpcError_WinImpl; + const IpcError_Win._() : super._(); + + String get field0; + @JsonKey(ignore: true) + _$$IpcError_WinImplCopyWith<_$IpcError_WinImpl> get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class _$$IpcError_ClientImplCopyWith<$Res> { + factory _$$IpcError_ClientImplCopyWith(_$IpcError_ClientImpl value, + $Res Function(_$IpcError_ClientImpl) then) = + __$$IpcError_ClientImplCopyWithImpl<$Res>; + @useResult + $Res call({String field0}); +} + +/// @nodoc +class __$$IpcError_ClientImplCopyWithImpl<$Res> + extends _$IpcErrorCopyWithImpl<$Res, _$IpcError_ClientImpl> + implements _$$IpcError_ClientImplCopyWith<$Res> { + __$$IpcError_ClientImplCopyWithImpl( + _$IpcError_ClientImpl _value, $Res Function(_$IpcError_ClientImpl) _then) + : super(_value, _then); + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? field0 = null, + }) { + return _then(_$IpcError_ClientImpl( + null == field0 + ? _value.field0 + : field0 // ignore: cast_nullable_to_non_nullable + as String, + )); + } +} + +/// @nodoc + +class _$IpcError_ClientImpl extends IpcError_Client { + const _$IpcError_ClientImpl(this.field0) : super._(); + + @override + final String field0; + + @override + String toString() { + return 'IpcError.client(field0: $field0)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$IpcError_ClientImpl && + (identical(other.field0, field0) || other.field0 == field0)); + } + + @override + int get hashCode => Object.hash(runtimeType, field0); + + @JsonKey(ignore: true) + @override + @pragma('vm:prefer-inline') + _$$IpcError_ClientImplCopyWith<_$IpcError_ClientImpl> get copyWith => + __$$IpcError_ClientImplCopyWithImpl<_$IpcError_ClientImpl>( + this, _$identity); + + @override + @optionalTypeArgs + TResult when({ + required TResult Function(String field0) serDe, + required TResult Function(String field0) io, + required TResult Function(String field0) win, + required TResult Function(String field0) client, + required TResult Function() requestState, + required TResult Function() receive, + required TResult Function(String field0) connectionFailed, + required TResult Function() sendFailed, + }) { + return client(field0); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(String field0)? serDe, + TResult? Function(String field0)? io, + TResult? Function(String field0)? win, + TResult? Function(String field0)? client, + TResult? Function()? requestState, + TResult? Function()? receive, + TResult? Function(String field0)? connectionFailed, + TResult? Function()? sendFailed, + }) { + return client?.call(field0); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(String field0)? serDe, + TResult Function(String field0)? io, + TResult Function(String field0)? win, + TResult Function(String field0)? client, + TResult Function()? requestState, + TResult Function()? receive, + TResult Function(String field0)? connectionFailed, + TResult Function()? sendFailed, + required TResult orElse(), + }) { + if (client != null) { + return client(field0); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(IpcError_SerDe value) serDe, + required TResult Function(IpcError_Io value) io, + required TResult Function(IpcError_Win value) win, + required TResult Function(IpcError_Client value) client, + required TResult Function(IpcError_RequestState value) requestState, + required TResult Function(IpcError_Receive value) receive, + required TResult Function(IpcError_ConnectionFailed value) connectionFailed, + required TResult Function(IpcError_SendFailed value) sendFailed, + }) { + return client(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(IpcError_SerDe value)? serDe, + TResult? Function(IpcError_Io value)? io, + TResult? Function(IpcError_Win value)? win, + TResult? Function(IpcError_Client value)? client, + TResult? Function(IpcError_RequestState value)? requestState, + TResult? Function(IpcError_Receive value)? receive, + TResult? Function(IpcError_ConnectionFailed value)? connectionFailed, + TResult? Function(IpcError_SendFailed value)? sendFailed, + }) { + return client?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(IpcError_SerDe value)? serDe, + TResult Function(IpcError_Io value)? io, + TResult Function(IpcError_Win value)? win, + TResult Function(IpcError_Client value)? client, + TResult Function(IpcError_RequestState value)? requestState, + TResult Function(IpcError_Receive value)? receive, + TResult Function(IpcError_ConnectionFailed value)? connectionFailed, + TResult Function(IpcError_SendFailed value)? sendFailed, + required TResult orElse(), + }) { + if (client != null) { + return client(this); + } + return orElse(); + } +} + +abstract class IpcError_Client extends IpcError { + const factory IpcError_Client(final String field0) = _$IpcError_ClientImpl; + const IpcError_Client._() : super._(); + + String get field0; + @JsonKey(ignore: true) + _$$IpcError_ClientImplCopyWith<_$IpcError_ClientImpl> get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class _$$IpcError_RequestStateImplCopyWith<$Res> { + factory _$$IpcError_RequestStateImplCopyWith( + _$IpcError_RequestStateImpl value, + $Res Function(_$IpcError_RequestStateImpl) then) = + __$$IpcError_RequestStateImplCopyWithImpl<$Res>; +} + +/// @nodoc +class __$$IpcError_RequestStateImplCopyWithImpl<$Res> + extends _$IpcErrorCopyWithImpl<$Res, _$IpcError_RequestStateImpl> + implements _$$IpcError_RequestStateImplCopyWith<$Res> { + __$$IpcError_RequestStateImplCopyWithImpl(_$IpcError_RequestStateImpl _value, + $Res Function(_$IpcError_RequestStateImpl) _then) + : super(_value, _then); +} + +/// @nodoc + +class _$IpcError_RequestStateImpl extends IpcError_RequestState { + const _$IpcError_RequestStateImpl() : super._(); + + @override + String toString() { + return 'IpcError.requestState()'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$IpcError_RequestStateImpl); + } + + @override + int get hashCode => runtimeType.hashCode; + + @override + @optionalTypeArgs + TResult when({ + required TResult Function(String field0) serDe, + required TResult Function(String field0) io, + required TResult Function(String field0) win, + required TResult Function(String field0) client, + required TResult Function() requestState, + required TResult Function() receive, + required TResult Function(String field0) connectionFailed, + required TResult Function() sendFailed, + }) { + return requestState(); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(String field0)? serDe, + TResult? Function(String field0)? io, + TResult? Function(String field0)? win, + TResult? Function(String field0)? client, + TResult? Function()? requestState, + TResult? Function()? receive, + TResult? Function(String field0)? connectionFailed, + TResult? Function()? sendFailed, + }) { + return requestState?.call(); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(String field0)? serDe, + TResult Function(String field0)? io, + TResult Function(String field0)? win, + TResult Function(String field0)? client, + TResult Function()? requestState, + TResult Function()? receive, + TResult Function(String field0)? connectionFailed, + TResult Function()? sendFailed, + required TResult orElse(), + }) { + if (requestState != null) { + return requestState(); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(IpcError_SerDe value) serDe, + required TResult Function(IpcError_Io value) io, + required TResult Function(IpcError_Win value) win, + required TResult Function(IpcError_Client value) client, + required TResult Function(IpcError_RequestState value) requestState, + required TResult Function(IpcError_Receive value) receive, + required TResult Function(IpcError_ConnectionFailed value) connectionFailed, + required TResult Function(IpcError_SendFailed value) sendFailed, + }) { + return requestState(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(IpcError_SerDe value)? serDe, + TResult? Function(IpcError_Io value)? io, + TResult? Function(IpcError_Win value)? win, + TResult? Function(IpcError_Client value)? client, + TResult? Function(IpcError_RequestState value)? requestState, + TResult? Function(IpcError_Receive value)? receive, + TResult? Function(IpcError_ConnectionFailed value)? connectionFailed, + TResult? Function(IpcError_SendFailed value)? sendFailed, + }) { + return requestState?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(IpcError_SerDe value)? serDe, + TResult Function(IpcError_Io value)? io, + TResult Function(IpcError_Win value)? win, + TResult Function(IpcError_Client value)? client, + TResult Function(IpcError_RequestState value)? requestState, + TResult Function(IpcError_Receive value)? receive, + TResult Function(IpcError_ConnectionFailed value)? connectionFailed, + TResult Function(IpcError_SendFailed value)? sendFailed, + required TResult orElse(), + }) { + if (requestState != null) { + return requestState(this); + } + return orElse(); + } +} + +abstract class IpcError_RequestState extends IpcError { + const factory IpcError_RequestState() = _$IpcError_RequestStateImpl; + const IpcError_RequestState._() : super._(); +} + +/// @nodoc +abstract class _$$IpcError_ReceiveImplCopyWith<$Res> { + factory _$$IpcError_ReceiveImplCopyWith(_$IpcError_ReceiveImpl value, + $Res Function(_$IpcError_ReceiveImpl) then) = + __$$IpcError_ReceiveImplCopyWithImpl<$Res>; +} + +/// @nodoc +class __$$IpcError_ReceiveImplCopyWithImpl<$Res> + extends _$IpcErrorCopyWithImpl<$Res, _$IpcError_ReceiveImpl> + implements _$$IpcError_ReceiveImplCopyWith<$Res> { + __$$IpcError_ReceiveImplCopyWithImpl(_$IpcError_ReceiveImpl _value, + $Res Function(_$IpcError_ReceiveImpl) _then) + : super(_value, _then); +} + +/// @nodoc + +class _$IpcError_ReceiveImpl extends IpcError_Receive { + const _$IpcError_ReceiveImpl() : super._(); + + @override + String toString() { + return 'IpcError.receive()'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && other is _$IpcError_ReceiveImpl); + } + + @override + int get hashCode => runtimeType.hashCode; + + @override + @optionalTypeArgs + TResult when({ + required TResult Function(String field0) serDe, + required TResult Function(String field0) io, + required TResult Function(String field0) win, + required TResult Function(String field0) client, + required TResult Function() requestState, + required TResult Function() receive, + required TResult Function(String field0) connectionFailed, + required TResult Function() sendFailed, + }) { + return receive(); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(String field0)? serDe, + TResult? Function(String field0)? io, + TResult? Function(String field0)? win, + TResult? Function(String field0)? client, + TResult? Function()? requestState, + TResult? Function()? receive, + TResult? Function(String field0)? connectionFailed, + TResult? Function()? sendFailed, + }) { + return receive?.call(); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(String field0)? serDe, + TResult Function(String field0)? io, + TResult Function(String field0)? win, + TResult Function(String field0)? client, + TResult Function()? requestState, + TResult Function()? receive, + TResult Function(String field0)? connectionFailed, + TResult Function()? sendFailed, + required TResult orElse(), + }) { + if (receive != null) { + return receive(); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(IpcError_SerDe value) serDe, + required TResult Function(IpcError_Io value) io, + required TResult Function(IpcError_Win value) win, + required TResult Function(IpcError_Client value) client, + required TResult Function(IpcError_RequestState value) requestState, + required TResult Function(IpcError_Receive value) receive, + required TResult Function(IpcError_ConnectionFailed value) connectionFailed, + required TResult Function(IpcError_SendFailed value) sendFailed, + }) { + return receive(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(IpcError_SerDe value)? serDe, + TResult? Function(IpcError_Io value)? io, + TResult? Function(IpcError_Win value)? win, + TResult? Function(IpcError_Client value)? client, + TResult? Function(IpcError_RequestState value)? requestState, + TResult? Function(IpcError_Receive value)? receive, + TResult? Function(IpcError_ConnectionFailed value)? connectionFailed, + TResult? Function(IpcError_SendFailed value)? sendFailed, + }) { + return receive?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(IpcError_SerDe value)? serDe, + TResult Function(IpcError_Io value)? io, + TResult Function(IpcError_Win value)? win, + TResult Function(IpcError_Client value)? client, + TResult Function(IpcError_RequestState value)? requestState, + TResult Function(IpcError_Receive value)? receive, + TResult Function(IpcError_ConnectionFailed value)? connectionFailed, + TResult Function(IpcError_SendFailed value)? sendFailed, + required TResult orElse(), + }) { + if (receive != null) { + return receive(this); + } + return orElse(); + } +} + +abstract class IpcError_Receive extends IpcError { + const factory IpcError_Receive() = _$IpcError_ReceiveImpl; + const IpcError_Receive._() : super._(); +} + +/// @nodoc +abstract class _$$IpcError_ConnectionFailedImplCopyWith<$Res> { + factory _$$IpcError_ConnectionFailedImplCopyWith( + _$IpcError_ConnectionFailedImpl value, + $Res Function(_$IpcError_ConnectionFailedImpl) then) = + __$$IpcError_ConnectionFailedImplCopyWithImpl<$Res>; + @useResult + $Res call({String field0}); +} + +/// @nodoc +class __$$IpcError_ConnectionFailedImplCopyWithImpl<$Res> + extends _$IpcErrorCopyWithImpl<$Res, _$IpcError_ConnectionFailedImpl> + implements _$$IpcError_ConnectionFailedImplCopyWith<$Res> { + __$$IpcError_ConnectionFailedImplCopyWithImpl( + _$IpcError_ConnectionFailedImpl _value, + $Res Function(_$IpcError_ConnectionFailedImpl) _then) + : super(_value, _then); + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? field0 = null, + }) { + return _then(_$IpcError_ConnectionFailedImpl( + null == field0 + ? _value.field0 + : field0 // ignore: cast_nullable_to_non_nullable + as String, + )); + } +} + +/// @nodoc + +class _$IpcError_ConnectionFailedImpl extends IpcError_ConnectionFailed { + const _$IpcError_ConnectionFailedImpl(this.field0) : super._(); + + @override + final String field0; + + @override + String toString() { + return 'IpcError.connectionFailed(field0: $field0)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$IpcError_ConnectionFailedImpl && + (identical(other.field0, field0) || other.field0 == field0)); + } + + @override + int get hashCode => Object.hash(runtimeType, field0); + + @JsonKey(ignore: true) + @override + @pragma('vm:prefer-inline') + _$$IpcError_ConnectionFailedImplCopyWith<_$IpcError_ConnectionFailedImpl> + get copyWith => __$$IpcError_ConnectionFailedImplCopyWithImpl< + _$IpcError_ConnectionFailedImpl>(this, _$identity); + + @override + @optionalTypeArgs + TResult when({ + required TResult Function(String field0) serDe, + required TResult Function(String field0) io, + required TResult Function(String field0) win, + required TResult Function(String field0) client, + required TResult Function() requestState, + required TResult Function() receive, + required TResult Function(String field0) connectionFailed, + required TResult Function() sendFailed, + }) { + return connectionFailed(field0); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(String field0)? serDe, + TResult? Function(String field0)? io, + TResult? Function(String field0)? win, + TResult? Function(String field0)? client, + TResult? Function()? requestState, + TResult? Function()? receive, + TResult? Function(String field0)? connectionFailed, + TResult? Function()? sendFailed, + }) { + return connectionFailed?.call(field0); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(String field0)? serDe, + TResult Function(String field0)? io, + TResult Function(String field0)? win, + TResult Function(String field0)? client, + TResult Function()? requestState, + TResult Function()? receive, + TResult Function(String field0)? connectionFailed, + TResult Function()? sendFailed, + required TResult orElse(), + }) { + if (connectionFailed != null) { + return connectionFailed(field0); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(IpcError_SerDe value) serDe, + required TResult Function(IpcError_Io value) io, + required TResult Function(IpcError_Win value) win, + required TResult Function(IpcError_Client value) client, + required TResult Function(IpcError_RequestState value) requestState, + required TResult Function(IpcError_Receive value) receive, + required TResult Function(IpcError_ConnectionFailed value) connectionFailed, + required TResult Function(IpcError_SendFailed value) sendFailed, + }) { + return connectionFailed(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(IpcError_SerDe value)? serDe, + TResult? Function(IpcError_Io value)? io, + TResult? Function(IpcError_Win value)? win, + TResult? Function(IpcError_Client value)? client, + TResult? Function(IpcError_RequestState value)? requestState, + TResult? Function(IpcError_Receive value)? receive, + TResult? Function(IpcError_ConnectionFailed value)? connectionFailed, + TResult? Function(IpcError_SendFailed value)? sendFailed, + }) { + return connectionFailed?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(IpcError_SerDe value)? serDe, + TResult Function(IpcError_Io value)? io, + TResult Function(IpcError_Win value)? win, + TResult Function(IpcError_Client value)? client, + TResult Function(IpcError_RequestState value)? requestState, + TResult Function(IpcError_Receive value)? receive, + TResult Function(IpcError_ConnectionFailed value)? connectionFailed, + TResult Function(IpcError_SendFailed value)? sendFailed, + required TResult orElse(), + }) { + if (connectionFailed != null) { + return connectionFailed(this); + } + return orElse(); + } +} + +abstract class IpcError_ConnectionFailed extends IpcError { + const factory IpcError_ConnectionFailed(final String field0) = + _$IpcError_ConnectionFailedImpl; + const IpcError_ConnectionFailed._() : super._(); + + String get field0; + @JsonKey(ignore: true) + _$$IpcError_ConnectionFailedImplCopyWith<_$IpcError_ConnectionFailedImpl> + get copyWith => throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class _$$IpcError_SendFailedImplCopyWith<$Res> { + factory _$$IpcError_SendFailedImplCopyWith(_$IpcError_SendFailedImpl value, + $Res Function(_$IpcError_SendFailedImpl) then) = + __$$IpcError_SendFailedImplCopyWithImpl<$Res>; +} + +/// @nodoc +class __$$IpcError_SendFailedImplCopyWithImpl<$Res> + extends _$IpcErrorCopyWithImpl<$Res, _$IpcError_SendFailedImpl> + implements _$$IpcError_SendFailedImplCopyWith<$Res> { + __$$IpcError_SendFailedImplCopyWithImpl(_$IpcError_SendFailedImpl _value, + $Res Function(_$IpcError_SendFailedImpl) _then) + : super(_value, _then); +} + +/// @nodoc + +class _$IpcError_SendFailedImpl extends IpcError_SendFailed { + const _$IpcError_SendFailedImpl() : super._(); + + @override + String toString() { + return 'IpcError.sendFailed()'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$IpcError_SendFailedImpl); + } + + @override + int get hashCode => runtimeType.hashCode; + + @override + @optionalTypeArgs + TResult when({ + required TResult Function(String field0) serDe, + required TResult Function(String field0) io, + required TResult Function(String field0) win, + required TResult Function(String field0) client, + required TResult Function() requestState, + required TResult Function() receive, + required TResult Function(String field0) connectionFailed, + required TResult Function() sendFailed, + }) { + return sendFailed(); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(String field0)? serDe, + TResult? Function(String field0)? io, + TResult? Function(String field0)? win, + TResult? Function(String field0)? client, + TResult? Function()? requestState, + TResult? Function()? receive, + TResult? Function(String field0)? connectionFailed, + TResult? Function()? sendFailed, + }) { + return sendFailed?.call(); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(String field0)? serDe, + TResult Function(String field0)? io, + TResult Function(String field0)? win, + TResult Function(String field0)? client, + TResult Function()? requestState, + TResult Function()? receive, + TResult Function(String field0)? connectionFailed, + TResult Function()? sendFailed, + required TResult orElse(), + }) { + if (sendFailed != null) { + return sendFailed(); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(IpcError_SerDe value) serDe, + required TResult Function(IpcError_Io value) io, + required TResult Function(IpcError_Win value) win, + required TResult Function(IpcError_Client value) client, + required TResult Function(IpcError_RequestState value) requestState, + required TResult Function(IpcError_Receive value) receive, + required TResult Function(IpcError_ConnectionFailed value) connectionFailed, + required TResult Function(IpcError_SendFailed value) sendFailed, + }) { + return sendFailed(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(IpcError_SerDe value)? serDe, + TResult? Function(IpcError_Io value)? io, + TResult? Function(IpcError_Win value)? win, + TResult? Function(IpcError_Client value)? client, + TResult? Function(IpcError_RequestState value)? requestState, + TResult? Function(IpcError_Receive value)? receive, + TResult? Function(IpcError_ConnectionFailed value)? connectionFailed, + TResult? Function(IpcError_SendFailed value)? sendFailed, + }) { + return sendFailed?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(IpcError_SerDe value)? serDe, + TResult Function(IpcError_Io value)? io, + TResult Function(IpcError_Win value)? win, + TResult Function(IpcError_Client value)? client, + TResult Function(IpcError_RequestState value)? requestState, + TResult Function(IpcError_Receive value)? receive, + TResult Function(IpcError_ConnectionFailed value)? connectionFailed, + TResult Function(IpcError_SendFailed value)? sendFailed, + required TResult orElse(), + }) { + if (sendFailed != null) { + return sendFailed(this); + } + return orElse(); + } +} + +abstract class IpcError_SendFailed extends IpcError { + const factory IpcError_SendFailed() = _$IpcError_SendFailedImpl; + const IpcError_SendFailed._() : super._(); +} + +/// @nodoc +mixin _$Mode { + int get width => throw _privateConstructorUsedError; + int get height => throw _privateConstructorUsedError; + Uint32List get refreshRates => throw _privateConstructorUsedError; + + @JsonKey(ignore: true) + $ModeCopyWith get copyWith => throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $ModeCopyWith<$Res> { + factory $ModeCopyWith(Mode value, $Res Function(Mode) then) = + _$ModeCopyWithImpl<$Res, Mode>; + @useResult + $Res call({int width, int height, Uint32List refreshRates}); +} + +/// @nodoc +class _$ModeCopyWithImpl<$Res, $Val extends Mode> + implements $ModeCopyWith<$Res> { + _$ModeCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? width = null, + Object? height = null, + Object? refreshRates = null, + }) { + return _then(_value.copyWith( + width: null == width + ? _value.width + : width // ignore: cast_nullable_to_non_nullable + as int, + height: null == height + ? _value.height + : height // ignore: cast_nullable_to_non_nullable + as int, + refreshRates: null == refreshRates + ? _value.refreshRates + : refreshRates // ignore: cast_nullable_to_non_nullable + as Uint32List, + ) as $Val); + } +} + +/// @nodoc +abstract class _$$ModeImplCopyWith<$Res> implements $ModeCopyWith<$Res> { + factory _$$ModeImplCopyWith( + _$ModeImpl value, $Res Function(_$ModeImpl) then) = + __$$ModeImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({int width, int height, Uint32List refreshRates}); +} + +/// @nodoc +class __$$ModeImplCopyWithImpl<$Res> + extends _$ModeCopyWithImpl<$Res, _$ModeImpl> + implements _$$ModeImplCopyWith<$Res> { + __$$ModeImplCopyWithImpl(_$ModeImpl _value, $Res Function(_$ModeImpl) _then) + : super(_value, _then); + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? width = null, + Object? height = null, + Object? refreshRates = null, + }) { + return _then(_$ModeImpl( + width: null == width + ? _value.width + : width // ignore: cast_nullable_to_non_nullable + as int, + height: null == height + ? _value.height + : height // ignore: cast_nullable_to_non_nullable + as int, + refreshRates: null == refreshRates + ? _value.refreshRates + : refreshRates // ignore: cast_nullable_to_non_nullable + as Uint32List, + )); + } +} + +/// @nodoc + +class _$ModeImpl implements _Mode { + const _$ModeImpl( + {required this.width, required this.height, required this.refreshRates}); + + @override + final int width; + @override + final int height; + @override + final Uint32List refreshRates; + + @override + String toString() { + return 'Mode(width: $width, height: $height, refreshRates: $refreshRates)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$ModeImpl && + (identical(other.width, width) || other.width == width) && + (identical(other.height, height) || other.height == height) && + const DeepCollectionEquality() + .equals(other.refreshRates, refreshRates)); + } + + @override + int get hashCode => Object.hash(runtimeType, width, height, + const DeepCollectionEquality().hash(refreshRates)); + + @JsonKey(ignore: true) + @override + @pragma('vm:prefer-inline') + _$$ModeImplCopyWith<_$ModeImpl> get copyWith => + __$$ModeImplCopyWithImpl<_$ModeImpl>(this, _$identity); +} + +abstract class _Mode implements Mode { + const factory _Mode( + {required final int width, + required final int height, + required final Uint32List refreshRates}) = _$ModeImpl; + + @override + int get width; + @override + int get height; + @override + Uint32List get refreshRates; + @override + @JsonKey(ignore: true) + _$$ModeImplCopyWith<_$ModeImpl> get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +mixin _$Monitor { + int get id => throw _privateConstructorUsedError; + String? get name => throw _privateConstructorUsedError; + bool get enabled => throw _privateConstructorUsedError; + List get modes => throw _privateConstructorUsedError; + + @JsonKey(ignore: true) + $MonitorCopyWith get copyWith => throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $MonitorCopyWith<$Res> { + factory $MonitorCopyWith(Monitor value, $Res Function(Monitor) then) = + _$MonitorCopyWithImpl<$Res, Monitor>; + @useResult + $Res call({int id, String? name, bool enabled, List modes}); +} + +/// @nodoc +class _$MonitorCopyWithImpl<$Res, $Val extends Monitor> + implements $MonitorCopyWith<$Res> { + _$MonitorCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? id = null, + Object? name = freezed, + Object? enabled = null, + Object? modes = null, + }) { + return _then(_value.copyWith( + id: null == id + ? _value.id + : id // ignore: cast_nullable_to_non_nullable + as int, + name: freezed == name + ? _value.name + : name // ignore: cast_nullable_to_non_nullable + as String?, + enabled: null == enabled + ? _value.enabled + : enabled // ignore: cast_nullable_to_non_nullable + as bool, + modes: null == modes + ? _value.modes + : modes // ignore: cast_nullable_to_non_nullable + as List, + ) as $Val); + } +} + +/// @nodoc +abstract class _$$MonitorImplCopyWith<$Res> implements $MonitorCopyWith<$Res> { + factory _$$MonitorImplCopyWith( + _$MonitorImpl value, $Res Function(_$MonitorImpl) then) = + __$$MonitorImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({int id, String? name, bool enabled, List modes}); +} + +/// @nodoc +class __$$MonitorImplCopyWithImpl<$Res> + extends _$MonitorCopyWithImpl<$Res, _$MonitorImpl> + implements _$$MonitorImplCopyWith<$Res> { + __$$MonitorImplCopyWithImpl( + _$MonitorImpl _value, $Res Function(_$MonitorImpl) _then) + : super(_value, _then); + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? id = null, + Object? name = freezed, + Object? enabled = null, + Object? modes = null, + }) { + return _then(_$MonitorImpl( + id: null == id + ? _value.id + : id // ignore: cast_nullable_to_non_nullable + as int, + name: freezed == name + ? _value.name + : name // ignore: cast_nullable_to_non_nullable + as String?, + enabled: null == enabled + ? _value.enabled + : enabled // ignore: cast_nullable_to_non_nullable + as bool, + modes: null == modes + ? _value._modes + : modes // ignore: cast_nullable_to_non_nullable + as List, + )); + } +} + +/// @nodoc + +class _$MonitorImpl implements _Monitor { + const _$MonitorImpl( + {required this.id, + this.name, + required this.enabled, + required final List modes}) + : _modes = modes; + + @override + final int id; + @override + final String? name; + @override + final bool enabled; + final List _modes; + @override + List get modes { + if (_modes is EqualUnmodifiableListView) return _modes; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_modes); + } + + @override + String toString() { + return 'Monitor(id: $id, name: $name, enabled: $enabled, modes: $modes)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$MonitorImpl && + (identical(other.id, id) || other.id == id) && + (identical(other.name, name) || other.name == name) && + (identical(other.enabled, enabled) || other.enabled == enabled) && + const DeepCollectionEquality().equals(other._modes, _modes)); + } + + @override + int get hashCode => Object.hash(runtimeType, id, name, enabled, + const DeepCollectionEquality().hash(_modes)); + + @JsonKey(ignore: true) + @override + @pragma('vm:prefer-inline') + _$$MonitorImplCopyWith<_$MonitorImpl> get copyWith => + __$$MonitorImplCopyWithImpl<_$MonitorImpl>(this, _$identity); +} + +abstract class _Monitor implements Monitor { + const factory _Monitor( + {required final int id, + final String? name, + required final bool enabled, + required final List modes}) = _$MonitorImpl; + + @override + int get id; + @override + String? get name; + @override + bool get enabled; + @override + List get modes; + @override + @JsonKey(ignore: true) + _$$MonitorImplCopyWith<_$MonitorImpl> get copyWith => + throw _privateConstructorUsedError; +} diff --git a/rust/bindings/dart_vdd/lib/src/generated/frb_generated.dart b/rust/bindings/dart_vdd/lib/src/generated/frb_generated.dart new file mode 100644 index 00000000..72a1edbe --- /dev/null +++ b/rust/bindings/dart_vdd/lib/src/generated/frb_generated.dart @@ -0,0 +1,1081 @@ +// This file is automatically generated, so please do not edit it. +// Generated by `flutter_rust_bridge`@ 2.0.0-dev.31. + +// ignore_for_file: unused_import, unused_element, unnecessary_import, duplicate_ignore, invalid_use_of_internal_member, annotate_overrides, non_constant_identifier_names, curly_braces_in_flow_control_structures, prefer_const_literals_to_create_immutables, unused_field + +import 'api.dart'; +import 'dart:async'; +import 'dart:convert'; +import 'frb_generated.io.dart' if (dart.library.html) 'frb_generated.web.dart'; +import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart'; + +/// Main entrypoint of the Rust API +class RustLib extends BaseEntrypoint { + @internal + static final instance = RustLib._(); + + RustLib._(); + + /// Initialize flutter_rust_bridge + static Future init({ + RustLibApi? api, + BaseHandler? handler, + ExternalLibrary? externalLibrary, + }) async { + await instance.initImpl( + api: api, + handler: handler, + externalLibrary: externalLibrary, + ); + } + + /// Dispose flutter_rust_bridge + /// + /// The call to this function is optional, since flutter_rust_bridge (and everything else) + /// is automatically disposed when the app stops. + static void dispose() => instance.disposeImpl(); + + @override + ApiImplConstructor get apiImplConstructor => + RustLibApiImpl.new; + + @override + WireConstructor get wireConstructor => + RustLibWire.fromExternalLibrary; + + @override + Future executeRustInitializers() async {} + + @override + ExternalLibraryLoaderConfig get defaultExternalLibraryLoaderConfig => + kDefaultExternalLibraryLoaderConfig; + + @override + String get codegenVersion => '2.0.0-dev.31'; + + static const kDefaultExternalLibraryLoaderConfig = + ExternalLibraryLoaderConfig( + stem: 'dart-vdd', + ioDirectory: 'rust/target/release/', + webPrefix: 'pkg/', + ); +} + +abstract class RustLibApi extends BaseApi { + void virtualDisplayDriverAddMonitor( + {required VirtualDisplayDriver that, + String? name, + required bool enabled, + required List modes, + dynamic hint}); + + Future virtualDisplayDriverCancelStream( + {required VirtualDisplayDriver that, dynamic hint}); + + Future virtualDisplayDriverNew( + {String? pipeName, dynamic hint}); + + Future virtualDisplayDriverNotify( + {required VirtualDisplayDriver that, dynamic hint}); + + Future virtualDisplayDriverPersist( + {required VirtualDisplayDriver that, dynamic hint}); + + void virtualDisplayDriverRemoveAllMonitors( + {required VirtualDisplayDriver that, dynamic hint}); + + void virtualDisplayDriverRemoveMonitors( + {required VirtualDisplayDriver that, + required List ids, + dynamic hint}); + + void virtualDisplayDriverSetMonitor( + {required VirtualDisplayDriver that, + required int id, + bool? enabled, + String? name, + List? modes, + dynamic hint}); + + void virtualDisplayDriverSetMonitors( + {required VirtualDisplayDriver that, + required List monitors, + dynamic hint}); + + List virtualDisplayDriverState( + {required VirtualDisplayDriver that, dynamic hint}); + + Future>> virtualDisplayDriverStream( + {required VirtualDisplayDriver that, dynamic hint}); + + RustArcIncrementStrongCountFnType + get rust_arc_increment_strong_count_VirtualDisplayDriver; + + RustArcDecrementStrongCountFnType + get rust_arc_decrement_strong_count_VirtualDisplayDriver; + + CrossPlatformFinalizerArg + get rust_arc_decrement_strong_count_VirtualDisplayDriverPtr; +} + +class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { + RustLibApiImpl({ + required super.handler, + required super.wire, + required super.generalizedFrbRustBinding, + required super.portManager, + }); + + @override + void virtualDisplayDriverAddMonitor( + {required VirtualDisplayDriver that, + String? name, + required bool enabled, + required List modes, + dynamic hint}) { + return handler.executeSync(SyncTask( + callFfi: () { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedrust_asyncRwLockVirtualDisplayDriver( + that, serializer); + sse_encode_opt_String(name, serializer); + sse_encode_bool(enabled, serializer); + sse_encode_list_mode(modes, serializer); + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 7)!; + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_ipc_error, + ), + constMeta: kVirtualDisplayDriverAddMonitorConstMeta, + argValues: [that, name, enabled, modes], + apiImpl: this, + hint: hint, + )); + } + + TaskConstMeta get kVirtualDisplayDriverAddMonitorConstMeta => + const TaskConstMeta( + debugName: "VirtualDisplayDriver_add_monitor", + argNames: ["that", "name", "enabled", "modes"], + ); + + @override + Future virtualDisplayDriverCancelStream( + {required VirtualDisplayDriver that, dynamic hint}) { + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedrust_asyncRwLockVirtualDisplayDriver( + that, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 4, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: null, + ), + constMeta: kVirtualDisplayDriverCancelStreamConstMeta, + argValues: [that], + apiImpl: this, + hint: hint, + )); + } + + TaskConstMeta get kVirtualDisplayDriverCancelStreamConstMeta => + const TaskConstMeta( + debugName: "VirtualDisplayDriver_cancel_stream", + argNames: ["that"], + ); + + @override + Future virtualDisplayDriverNew( + {String? pipeName, dynamic hint}) { + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_opt_String(pipeName, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 1, port: port_); + }, + codec: SseCodec( + decodeSuccessData: + sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedrust_asyncRwLockVirtualDisplayDriver, + decodeErrorData: sse_decode_ipc_error, + ), + constMeta: kVirtualDisplayDriverNewConstMeta, + argValues: [pipeName], + apiImpl: this, + hint: hint, + )); + } + + TaskConstMeta get kVirtualDisplayDriverNewConstMeta => const TaskConstMeta( + debugName: "VirtualDisplayDriver_new", + argNames: ["pipeName"], + ); + + @override + Future virtualDisplayDriverNotify( + {required VirtualDisplayDriver that, dynamic hint}) { + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedrust_asyncRwLockVirtualDisplayDriver( + that, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 10, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_ipc_error, + ), + constMeta: kVirtualDisplayDriverNotifyConstMeta, + argValues: [that], + apiImpl: this, + hint: hint, + )); + } + + TaskConstMeta get kVirtualDisplayDriverNotifyConstMeta => const TaskConstMeta( + debugName: "VirtualDisplayDriver_notify", + argNames: ["that"], + ); + + @override + Future virtualDisplayDriverPersist( + {required VirtualDisplayDriver that, dynamic hint}) { + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedrust_asyncRwLockVirtualDisplayDriver( + that, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 11, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_ipc_error, + ), + constMeta: kVirtualDisplayDriverPersistConstMeta, + argValues: [that], + apiImpl: this, + hint: hint, + )); + } + + TaskConstMeta get kVirtualDisplayDriverPersistConstMeta => + const TaskConstMeta( + debugName: "VirtualDisplayDriver_persist", + argNames: ["that"], + ); + + @override + void virtualDisplayDriverRemoveAllMonitors( + {required VirtualDisplayDriver that, dynamic hint}) { + return handler.executeSync(SyncTask( + callFfi: () { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedrust_asyncRwLockVirtualDisplayDriver( + that, serializer); + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 9)!; + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: null, + ), + constMeta: kVirtualDisplayDriverRemoveAllMonitorsConstMeta, + argValues: [that], + apiImpl: this, + hint: hint, + )); + } + + TaskConstMeta get kVirtualDisplayDriverRemoveAllMonitorsConstMeta => + const TaskConstMeta( + debugName: "VirtualDisplayDriver_remove_all_monitors", + argNames: ["that"], + ); + + @override + void virtualDisplayDriverRemoveMonitors( + {required VirtualDisplayDriver that, + required List ids, + dynamic hint}) { + return handler.executeSync(SyncTask( + callFfi: () { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedrust_asyncRwLockVirtualDisplayDriver( + that, serializer); + sse_encode_list_prim_u_32_loose(ids, serializer); + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 8)!; + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: null, + ), + constMeta: kVirtualDisplayDriverRemoveMonitorsConstMeta, + argValues: [that, ids], + apiImpl: this, + hint: hint, + )); + } + + TaskConstMeta get kVirtualDisplayDriverRemoveMonitorsConstMeta => + const TaskConstMeta( + debugName: "VirtualDisplayDriver_remove_monitors", + argNames: ["that", "ids"], + ); + + @override + void virtualDisplayDriverSetMonitor( + {required VirtualDisplayDriver that, + required int id, + bool? enabled, + String? name, + List? modes, + dynamic hint}) { + return handler.executeSync(SyncTask( + callFfi: () { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedrust_asyncRwLockVirtualDisplayDriver( + that, serializer); + sse_encode_u_32(id, serializer); + sse_encode_opt_box_autoadd_bool(enabled, serializer); + sse_encode_opt_String(name, serializer); + sse_encode_opt_list_mode(modes, serializer); + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 6)!; + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: null, + ), + constMeta: kVirtualDisplayDriverSetMonitorConstMeta, + argValues: [that, id, enabled, name, modes], + apiImpl: this, + hint: hint, + )); + } + + TaskConstMeta get kVirtualDisplayDriverSetMonitorConstMeta => + const TaskConstMeta( + debugName: "VirtualDisplayDriver_set_monitor", + argNames: ["that", "id", "enabled", "name", "modes"], + ); + + @override + void virtualDisplayDriverSetMonitors( + {required VirtualDisplayDriver that, + required List monitors, + dynamic hint}) { + return handler.executeSync(SyncTask( + callFfi: () { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedrust_asyncRwLockVirtualDisplayDriver( + that, serializer); + sse_encode_list_monitor(monitors, serializer); + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 5)!; + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_ipc_error, + ), + constMeta: kVirtualDisplayDriverSetMonitorsConstMeta, + argValues: [that, monitors], + apiImpl: this, + hint: hint, + )); + } + + TaskConstMeta get kVirtualDisplayDriverSetMonitorsConstMeta => + const TaskConstMeta( + debugName: "VirtualDisplayDriver_set_monitors", + argNames: ["that", "monitors"], + ); + + @override + List virtualDisplayDriverState( + {required VirtualDisplayDriver that, dynamic hint}) { + return handler.executeSync(SyncTask( + callFfi: () { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedrust_asyncRwLockVirtualDisplayDriver( + that, serializer); + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 2)!; + }, + codec: SseCodec( + decodeSuccessData: sse_decode_list_monitor, + decodeErrorData: null, + ), + constMeta: kVirtualDisplayDriverStateConstMeta, + argValues: [that], + apiImpl: this, + hint: hint, + )); + } + + TaskConstMeta get kVirtualDisplayDriverStateConstMeta => const TaskConstMeta( + debugName: "VirtualDisplayDriver_state", + argNames: ["that"], + ); + + @override + Future>> virtualDisplayDriverStream( + {required VirtualDisplayDriver that, dynamic hint}) async { + final sink = RustStreamSink>(); + await handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedrust_asyncRwLockVirtualDisplayDriver( + that, serializer); + sse_encode_StreamSink_list_monitor_Sse(sink, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 3, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: null, + ), + constMeta: kVirtualDisplayDriverStreamConstMeta, + argValues: [that, sink], + apiImpl: this, + hint: hint, + )); + return sink.stream; + } + + TaskConstMeta get kVirtualDisplayDriverStreamConstMeta => const TaskConstMeta( + debugName: "VirtualDisplayDriver_stream", + argNames: ["that", "sink"], + ); + + RustArcIncrementStrongCountFnType + get rust_arc_increment_strong_count_VirtualDisplayDriver => wire + .rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedrust_asyncRwLockVirtualDisplayDriver; + + RustArcDecrementStrongCountFnType + get rust_arc_decrement_strong_count_VirtualDisplayDriver => wire + .rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedrust_asyncRwLockVirtualDisplayDriver; + + @protected + VirtualDisplayDriver + dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedrust_asyncRwLockVirtualDisplayDriver( + dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return VirtualDisplayDriver.dcoDecode(raw as List); + } + + @protected + VirtualDisplayDriver + dco_decode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedrust_asyncRwLockVirtualDisplayDriver( + dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return VirtualDisplayDriver.dcoDecode(raw as List); + } + + @protected + VirtualDisplayDriver + dco_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedrust_asyncRwLockVirtualDisplayDriver( + dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return VirtualDisplayDriver.dcoDecode(raw as List); + } + + @protected + VirtualDisplayDriver + dco_decode_RustOpaque_flutter_rust_bridgefor_generatedrust_asyncRwLockVirtualDisplayDriver( + dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return VirtualDisplayDriver.dcoDecode(raw as List); + } + + @protected + RustStreamSink> dco_decode_StreamSink_list_monitor_Sse( + dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + throw UnimplementedError(); + } + + @protected + String dco_decode_String(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return raw as String; + } + + @protected + bool dco_decode_bool(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return raw as bool; + } + + @protected + bool dco_decode_box_autoadd_bool(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return raw as bool; + } + + @protected + IpcError dco_decode_ipc_error(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + switch (raw[0]) { + case 0: + return IpcError_SerDe( + dco_decode_String(raw[1]), + ); + case 1: + return IpcError_Io( + dco_decode_String(raw[1]), + ); + case 2: + return IpcError_Win( + dco_decode_String(raw[1]), + ); + case 3: + return IpcError_Client( + dco_decode_String(raw[1]), + ); + case 4: + return IpcError_RequestState(); + case 5: + return IpcError_Receive(); + case 6: + return IpcError_ConnectionFailed( + dco_decode_String(raw[1]), + ); + case 7: + return IpcError_SendFailed(); + default: + throw Exception("unreachable"); + } + } + + @protected + List dco_decode_list_mode(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return (raw as List).map(dco_decode_mode).toList(); + } + + @protected + List dco_decode_list_monitor(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return (raw as List).map(dco_decode_monitor).toList(); + } + + @protected + List dco_decode_list_prim_u_32_loose(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return raw as List; + } + + @protected + Uint32List dco_decode_list_prim_u_32_strict(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return raw as Uint32List; + } + + @protected + Uint8List dco_decode_list_prim_u_8_strict(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return raw as Uint8List; + } + + @protected + Mode dco_decode_mode(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + final arr = raw as List; + if (arr.length != 3) + throw Exception('unexpected arr length: expect 3 but see ${arr.length}'); + return Mode( + width: dco_decode_u_32(arr[0]), + height: dco_decode_u_32(arr[1]), + refreshRates: dco_decode_list_prim_u_32_strict(arr[2]), + ); + } + + @protected + Monitor dco_decode_monitor(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + final arr = raw as List; + if (arr.length != 4) + throw Exception('unexpected arr length: expect 4 but see ${arr.length}'); + return Monitor( + id: dco_decode_u_32(arr[0]), + name: dco_decode_opt_String(arr[1]), + enabled: dco_decode_bool(arr[2]), + modes: dco_decode_list_mode(arr[3]), + ); + } + + @protected + String? dco_decode_opt_String(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return raw == null ? null : dco_decode_String(raw); + } + + @protected + bool? dco_decode_opt_box_autoadd_bool(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return raw == null ? null : dco_decode_box_autoadd_bool(raw); + } + + @protected + List? dco_decode_opt_list_mode(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return raw == null ? null : dco_decode_list_mode(raw); + } + + @protected + int dco_decode_u_32(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return raw as int; + } + + @protected + int dco_decode_u_8(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return raw as int; + } + + @protected + void dco_decode_unit(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return; + } + + @protected + int dco_decode_usize(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return dcoDecodeI64OrU64(raw); + } + + @protected + VirtualDisplayDriver + sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedrust_asyncRwLockVirtualDisplayDriver( + SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + return VirtualDisplayDriver.sseDecode( + sse_decode_usize(deserializer), sse_decode_i_32(deserializer)); + } + + @protected + VirtualDisplayDriver + sse_decode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedrust_asyncRwLockVirtualDisplayDriver( + SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + return VirtualDisplayDriver.sseDecode( + sse_decode_usize(deserializer), sse_decode_i_32(deserializer)); + } + + @protected + VirtualDisplayDriver + sse_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedrust_asyncRwLockVirtualDisplayDriver( + SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + return VirtualDisplayDriver.sseDecode( + sse_decode_usize(deserializer), sse_decode_i_32(deserializer)); + } + + @protected + VirtualDisplayDriver + sse_decode_RustOpaque_flutter_rust_bridgefor_generatedrust_asyncRwLockVirtualDisplayDriver( + SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + return VirtualDisplayDriver.sseDecode( + sse_decode_usize(deserializer), sse_decode_i_32(deserializer)); + } + + @protected + RustStreamSink> sse_decode_StreamSink_list_monitor_Sse( + SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + throw UnimplementedError('Unreachable ()'); + } + + @protected + String sse_decode_String(SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + var inner = sse_decode_list_prim_u_8_strict(deserializer); + return utf8.decoder.convert(inner); + } + + @protected + bool sse_decode_bool(SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + return deserializer.buffer.getUint8() != 0; + } + + @protected + bool sse_decode_box_autoadd_bool(SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + return (sse_decode_bool(deserializer)); + } + + @protected + IpcError sse_decode_ipc_error(SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + + var tag_ = sse_decode_i_32(deserializer); + switch (tag_) { + case 0: + var var_field0 = sse_decode_String(deserializer); + return IpcError_SerDe(var_field0); + case 1: + var var_field0 = sse_decode_String(deserializer); + return IpcError_Io(var_field0); + case 2: + var var_field0 = sse_decode_String(deserializer); + return IpcError_Win(var_field0); + case 3: + var var_field0 = sse_decode_String(deserializer); + return IpcError_Client(var_field0); + case 4: + return IpcError_RequestState(); + case 5: + return IpcError_Receive(); + case 6: + var var_field0 = sse_decode_String(deserializer); + return IpcError_ConnectionFailed(var_field0); + case 7: + return IpcError_SendFailed(); + default: + throw UnimplementedError(''); + } + } + + @protected + List sse_decode_list_mode(SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + + var len_ = sse_decode_i_32(deserializer); + var ans_ = []; + for (var idx_ = 0; idx_ < len_; ++idx_) { + ans_.add(sse_decode_mode(deserializer)); + } + return ans_; + } + + @protected + List sse_decode_list_monitor(SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + + var len_ = sse_decode_i_32(deserializer); + var ans_ = []; + for (var idx_ = 0; idx_ < len_; ++idx_) { + ans_.add(sse_decode_monitor(deserializer)); + } + return ans_; + } + + @protected + List sse_decode_list_prim_u_32_loose(SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + var len_ = sse_decode_i_32(deserializer); + return deserializer.buffer.getUint32List(len_); + } + + @protected + Uint32List sse_decode_list_prim_u_32_strict(SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + var len_ = sse_decode_i_32(deserializer); + return deserializer.buffer.getUint32List(len_); + } + + @protected + Uint8List sse_decode_list_prim_u_8_strict(SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + var len_ = sse_decode_i_32(deserializer); + return deserializer.buffer.getUint8List(len_); + } + + @protected + Mode sse_decode_mode(SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + var var_width = sse_decode_u_32(deserializer); + var var_height = sse_decode_u_32(deserializer); + var var_refreshRates = sse_decode_list_prim_u_32_strict(deserializer); + return Mode( + width: var_width, height: var_height, refreshRates: var_refreshRates); + } + + @protected + Monitor sse_decode_monitor(SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + var var_id = sse_decode_u_32(deserializer); + var var_name = sse_decode_opt_String(deserializer); + var var_enabled = sse_decode_bool(deserializer); + var var_modes = sse_decode_list_mode(deserializer); + return Monitor( + id: var_id, name: var_name, enabled: var_enabled, modes: var_modes); + } + + @protected + String? sse_decode_opt_String(SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + + if (sse_decode_bool(deserializer)) { + return (sse_decode_String(deserializer)); + } else { + return null; + } + } + + @protected + bool? sse_decode_opt_box_autoadd_bool(SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + + if (sse_decode_bool(deserializer)) { + return (sse_decode_box_autoadd_bool(deserializer)); + } else { + return null; + } + } + + @protected + List? sse_decode_opt_list_mode(SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + + if (sse_decode_bool(deserializer)) { + return (sse_decode_list_mode(deserializer)); + } else { + return null; + } + } + + @protected + int sse_decode_u_32(SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + return deserializer.buffer.getUint32(); + } + + @protected + int sse_decode_u_8(SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + return deserializer.buffer.getUint8(); + } + + @protected + void sse_decode_unit(SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + } + + @protected + int sse_decode_usize(SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + return deserializer.buffer.getUint64(); + } + + @protected + int sse_decode_i_32(SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + return deserializer.buffer.getInt32(); + } + + @protected + void + sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedrust_asyncRwLockVirtualDisplayDriver( + VirtualDisplayDriver self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_usize(self.sseEncode(move: true), serializer); + } + + @protected + void + sse_encode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedrust_asyncRwLockVirtualDisplayDriver( + VirtualDisplayDriver self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_usize(self.sseEncode(move: false), serializer); + } + + @protected + void + sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedrust_asyncRwLockVirtualDisplayDriver( + VirtualDisplayDriver self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_usize(self.sseEncode(move: false), serializer); + } + + @protected + void + sse_encode_RustOpaque_flutter_rust_bridgefor_generatedrust_asyncRwLockVirtualDisplayDriver( + VirtualDisplayDriver self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_usize(self.sseEncode(move: null), serializer); + } + + @protected + void sse_encode_StreamSink_list_monitor_Sse( + RustStreamSink> self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_String( + self.setupAndSerialize( + codec: SseCodec( + decodeSuccessData: sse_decode_list_monitor, + decodeErrorData: null)), + serializer); + } + + @protected + void sse_encode_String(String self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_list_prim_u_8_strict(utf8.encoder.convert(self), serializer); + } + + @protected + void sse_encode_bool(bool self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + serializer.buffer.putUint8(self ? 1 : 0); + } + + @protected + void sse_encode_box_autoadd_bool(bool self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_bool(self, serializer); + } + + @protected + void sse_encode_ipc_error(IpcError self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + switch (self) { + case IpcError_SerDe(field0: final field0): + sse_encode_i_32(0, serializer); + sse_encode_String(field0, serializer); + case IpcError_Io(field0: final field0): + sse_encode_i_32(1, serializer); + sse_encode_String(field0, serializer); + case IpcError_Win(field0: final field0): + sse_encode_i_32(2, serializer); + sse_encode_String(field0, serializer); + case IpcError_Client(field0: final field0): + sse_encode_i_32(3, serializer); + sse_encode_String(field0, serializer); + case IpcError_RequestState(): + sse_encode_i_32(4, serializer); + case IpcError_Receive(): + sse_encode_i_32(5, serializer); + case IpcError_ConnectionFailed(field0: final field0): + sse_encode_i_32(6, serializer); + sse_encode_String(field0, serializer); + case IpcError_SendFailed(): + sse_encode_i_32(7, serializer); + } + } + + @protected + void sse_encode_list_mode(List self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_i_32(self.length, serializer); + for (final item in self) { + sse_encode_mode(item, serializer); + } + } + + @protected + void sse_encode_list_monitor(List self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_i_32(self.length, serializer); + for (final item in self) { + sse_encode_monitor(item, serializer); + } + } + + @protected + void sse_encode_list_prim_u_32_loose( + List self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_i_32(self.length, serializer); + serializer.buffer + .putUint32List(self is Uint32List ? self : Uint32List.fromList(self)); + } + + @protected + void sse_encode_list_prim_u_32_strict( + Uint32List self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_i_32(self.length, serializer); + serializer.buffer.putUint32List(self); + } + + @protected + void sse_encode_list_prim_u_8_strict( + Uint8List self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_i_32(self.length, serializer); + serializer.buffer.putUint8List(self); + } + + @protected + void sse_encode_mode(Mode self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_u_32(self.width, serializer); + sse_encode_u_32(self.height, serializer); + sse_encode_list_prim_u_32_strict(self.refreshRates, serializer); + } + + @protected + void sse_encode_monitor(Monitor self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_u_32(self.id, serializer); + sse_encode_opt_String(self.name, serializer); + sse_encode_bool(self.enabled, serializer); + sse_encode_list_mode(self.modes, serializer); + } + + @protected + void sse_encode_opt_String(String? self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + + sse_encode_bool(self != null, serializer); + if (self != null) { + sse_encode_String(self, serializer); + } + } + + @protected + void sse_encode_opt_box_autoadd_bool(bool? self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + + sse_encode_bool(self != null, serializer); + if (self != null) { + sse_encode_box_autoadd_bool(self, serializer); + } + } + + @protected + void sse_encode_opt_list_mode(List? self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + + sse_encode_bool(self != null, serializer); + if (self != null) { + sse_encode_list_mode(self, serializer); + } + } + + @protected + void sse_encode_u_32(int self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + serializer.buffer.putUint32(self); + } + + @protected + void sse_encode_u_8(int self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + serializer.buffer.putUint8(self); + } + + @protected + void sse_encode_unit(void self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + } + + @protected + void sse_encode_usize(int self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + serializer.buffer.putUint64(self); + } + + @protected + void sse_encode_i_32(int self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + serializer.buffer.putInt32(self); + } +} diff --git a/rust/bindings/dart_vdd/lib/src/generated/frb_generated.io.dart b/rust/bindings/dart_vdd/lib/src/generated/frb_generated.io.dart new file mode 100644 index 00000000..87b97658 --- /dev/null +++ b/rust/bindings/dart_vdd/lib/src/generated/frb_generated.io.dart @@ -0,0 +1,314 @@ +// This file is automatically generated, so please do not edit it. +// Generated by `flutter_rust_bridge`@ 2.0.0-dev.31. + +// ignore_for_file: unused_import, unused_element, unnecessary_import, duplicate_ignore, invalid_use_of_internal_member, annotate_overrides, non_constant_identifier_names, curly_braces_in_flow_control_structures, prefer_const_literals_to_create_immutables, unused_field + +import 'api.dart'; +import 'dart:async'; +import 'dart:convert'; +import 'dart:ffi' as ffi; +import 'frb_generated.dart'; +import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated_io.dart'; + +abstract class RustLibApiImplPlatform extends BaseApiImpl { + RustLibApiImplPlatform({ + required super.handler, + required super.wire, + required super.generalizedFrbRustBinding, + required super.portManager, + }); + + CrossPlatformFinalizerArg + get rust_arc_decrement_strong_count_VirtualDisplayDriverPtr => wire + ._rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedrust_asyncRwLockVirtualDisplayDriverPtr; + + @protected + VirtualDisplayDriver + dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedrust_asyncRwLockVirtualDisplayDriver( + dynamic raw); + + @protected + VirtualDisplayDriver + dco_decode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedrust_asyncRwLockVirtualDisplayDriver( + dynamic raw); + + @protected + VirtualDisplayDriver + dco_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedrust_asyncRwLockVirtualDisplayDriver( + dynamic raw); + + @protected + VirtualDisplayDriver + dco_decode_RustOpaque_flutter_rust_bridgefor_generatedrust_asyncRwLockVirtualDisplayDriver( + dynamic raw); + + @protected + RustStreamSink> dco_decode_StreamSink_list_monitor_Sse( + dynamic raw); + + @protected + String dco_decode_String(dynamic raw); + + @protected + bool dco_decode_bool(dynamic raw); + + @protected + bool dco_decode_box_autoadd_bool(dynamic raw); + + @protected + IpcError dco_decode_ipc_error(dynamic raw); + + @protected + List dco_decode_list_mode(dynamic raw); + + @protected + List dco_decode_list_monitor(dynamic raw); + + @protected + List dco_decode_list_prim_u_32_loose(dynamic raw); + + @protected + Uint32List dco_decode_list_prim_u_32_strict(dynamic raw); + + @protected + Uint8List dco_decode_list_prim_u_8_strict(dynamic raw); + + @protected + Mode dco_decode_mode(dynamic raw); + + @protected + Monitor dco_decode_monitor(dynamic raw); + + @protected + String? dco_decode_opt_String(dynamic raw); + + @protected + bool? dco_decode_opt_box_autoadd_bool(dynamic raw); + + @protected + List? dco_decode_opt_list_mode(dynamic raw); + + @protected + int dco_decode_u_32(dynamic raw); + + @protected + int dco_decode_u_8(dynamic raw); + + @protected + void dco_decode_unit(dynamic raw); + + @protected + int dco_decode_usize(dynamic raw); + + @protected + VirtualDisplayDriver + sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedrust_asyncRwLockVirtualDisplayDriver( + SseDeserializer deserializer); + + @protected + VirtualDisplayDriver + sse_decode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedrust_asyncRwLockVirtualDisplayDriver( + SseDeserializer deserializer); + + @protected + VirtualDisplayDriver + sse_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedrust_asyncRwLockVirtualDisplayDriver( + SseDeserializer deserializer); + + @protected + VirtualDisplayDriver + sse_decode_RustOpaque_flutter_rust_bridgefor_generatedrust_asyncRwLockVirtualDisplayDriver( + SseDeserializer deserializer); + + @protected + RustStreamSink> sse_decode_StreamSink_list_monitor_Sse( + SseDeserializer deserializer); + + @protected + String sse_decode_String(SseDeserializer deserializer); + + @protected + bool sse_decode_bool(SseDeserializer deserializer); + + @protected + bool sse_decode_box_autoadd_bool(SseDeserializer deserializer); + + @protected + IpcError sse_decode_ipc_error(SseDeserializer deserializer); + + @protected + List sse_decode_list_mode(SseDeserializer deserializer); + + @protected + List sse_decode_list_monitor(SseDeserializer deserializer); + + @protected + List sse_decode_list_prim_u_32_loose(SseDeserializer deserializer); + + @protected + Uint32List sse_decode_list_prim_u_32_strict(SseDeserializer deserializer); + + @protected + Uint8List sse_decode_list_prim_u_8_strict(SseDeserializer deserializer); + + @protected + Mode sse_decode_mode(SseDeserializer deserializer); + + @protected + Monitor sse_decode_monitor(SseDeserializer deserializer); + + @protected + String? sse_decode_opt_String(SseDeserializer deserializer); + + @protected + bool? sse_decode_opt_box_autoadd_bool(SseDeserializer deserializer); + + @protected + List? sse_decode_opt_list_mode(SseDeserializer deserializer); + + @protected + int sse_decode_u_32(SseDeserializer deserializer); + + @protected + int sse_decode_u_8(SseDeserializer deserializer); + + @protected + void sse_decode_unit(SseDeserializer deserializer); + + @protected + int sse_decode_usize(SseDeserializer deserializer); + + @protected + int sse_decode_i_32(SseDeserializer deserializer); + + @protected + void + sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedrust_asyncRwLockVirtualDisplayDriver( + VirtualDisplayDriver self, SseSerializer serializer); + + @protected + void + sse_encode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedrust_asyncRwLockVirtualDisplayDriver( + VirtualDisplayDriver self, SseSerializer serializer); + + @protected + void + sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedrust_asyncRwLockVirtualDisplayDriver( + VirtualDisplayDriver self, SseSerializer serializer); + + @protected + void + sse_encode_RustOpaque_flutter_rust_bridgefor_generatedrust_asyncRwLockVirtualDisplayDriver( + VirtualDisplayDriver self, SseSerializer serializer); + + @protected + void sse_encode_StreamSink_list_monitor_Sse( + RustStreamSink> self, SseSerializer serializer); + + @protected + void sse_encode_String(String self, SseSerializer serializer); + + @protected + void sse_encode_bool(bool self, SseSerializer serializer); + + @protected + void sse_encode_box_autoadd_bool(bool self, SseSerializer serializer); + + @protected + void sse_encode_ipc_error(IpcError self, SseSerializer serializer); + + @protected + void sse_encode_list_mode(List self, SseSerializer serializer); + + @protected + void sse_encode_list_monitor(List self, SseSerializer serializer); + + @protected + void sse_encode_list_prim_u_32_loose( + List self, SseSerializer serializer); + + @protected + void sse_encode_list_prim_u_32_strict( + Uint32List self, SseSerializer serializer); + + @protected + void sse_encode_list_prim_u_8_strict( + Uint8List self, SseSerializer serializer); + + @protected + void sse_encode_mode(Mode self, SseSerializer serializer); + + @protected + void sse_encode_monitor(Monitor self, SseSerializer serializer); + + @protected + void sse_encode_opt_String(String? self, SseSerializer serializer); + + @protected + void sse_encode_opt_box_autoadd_bool(bool? self, SseSerializer serializer); + + @protected + void sse_encode_opt_list_mode(List? self, SseSerializer serializer); + + @protected + void sse_encode_u_32(int self, SseSerializer serializer); + + @protected + void sse_encode_u_8(int self, SseSerializer serializer); + + @protected + void sse_encode_unit(void self, SseSerializer serializer); + + @protected + void sse_encode_usize(int self, SseSerializer serializer); + + @protected + void sse_encode_i_32(int self, SseSerializer serializer); +} + +// Section: wire_class + +class RustLibWire implements BaseWire { + factory RustLibWire.fromExternalLibrary(ExternalLibrary lib) => + RustLibWire(lib.ffiDynamicLibrary); + + /// Holds the symbol lookup function. + final ffi.Pointer Function(String symbolName) + _lookup; + + /// The symbols are looked up in [dynamicLibrary]. + RustLibWire(ffi.DynamicLibrary dynamicLibrary) + : _lookup = dynamicLibrary.lookup; + + void + rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedrust_asyncRwLockVirtualDisplayDriver( + ffi.Pointer ptr, + ) { + return _rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedrust_asyncRwLockVirtualDisplayDriver( + ptr, + ); + } + + late final _rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedrust_asyncRwLockVirtualDisplayDriverPtr = + _lookup)>>( + 'frbgen_dart_vdd_rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedrust_asyncRwLockVirtualDisplayDriver'); + late final _rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedrust_asyncRwLockVirtualDisplayDriver = + _rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedrust_asyncRwLockVirtualDisplayDriverPtr + .asFunction)>(); + + void + rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedrust_asyncRwLockVirtualDisplayDriver( + ffi.Pointer ptr, + ) { + return _rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedrust_asyncRwLockVirtualDisplayDriver( + ptr, + ); + } + + late final _rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedrust_asyncRwLockVirtualDisplayDriverPtr = + _lookup)>>( + 'frbgen_dart_vdd_rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedrust_asyncRwLockVirtualDisplayDriver'); + late final _rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedrust_asyncRwLockVirtualDisplayDriver = + _rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedrust_asyncRwLockVirtualDisplayDriverPtr + .asFunction)>(); +} diff --git a/rust/bindings/dart_vdd/pubspec.yaml b/rust/bindings/dart_vdd/pubspec.yaml new file mode 100644 index 00000000..c305d1cb --- /dev/null +++ b/rust/bindings/dart_vdd/pubspec.yaml @@ -0,0 +1,20 @@ +name: dart_vdd +description: A starting point for Dart libraries or applications. +version: 1.0.0 +# repository: https://github.com/my_org/my_repo + +environment: + sdk: ^3.3.0 + +# Add regular dependencies here. +dependencies: + flutter_rust_bridge: 2.0.0-dev.31 + freezed_annotation: ^2.4.1 + native_assets_cli: ^0.4.2 + # path: ^1.8.0 + +dev_dependencies: + build_runner: ^2.4.8 + freezed: ^2.4.7 + lints: ^3.0.0 + test: ^1.24.0 diff --git a/rust/bindings/dart_vdd/rust/Cargo.toml b/rust/bindings/dart_vdd/rust/Cargo.toml new file mode 100644 index 00000000..25d70a6b --- /dev/null +++ b/rust/bindings/dart_vdd/rust/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "dart-vdd" +version = "0.1.0" +edition = "2021" + +[lib] +crate-type = ["cdylib"] + +[dependencies] +driver-ipc = { path = "../../../driver-ipc" } +flutter_rust_bridge = "=2.0.0-dev.31" + +[lints] +# May not work, because package might be compiled outside this workspace +workspace = true diff --git a/rust/bindings/dart_vdd/rust/src/api.rs b/rust/bindings/dart_vdd/rust/src/api.rs new file mode 100644 index 00000000..57f7f974 --- /dev/null +++ b/rust/bindings/dart_vdd/rust/src/api.rs @@ -0,0 +1,173 @@ +use driver_ipc::{DriverClient, EventCommand}; +pub use driver_ipc::{Mode, Monitor}; +use flutter_rust_bridge::frb; + +use crate::frb_generated::StreamSink; + +#[frb(mirror(Monitor), dart_metadata=("freezed"))] +pub struct _Monitor { + pub id: u32, + pub name: Option, + pub enabled: bool, + pub modes: Vec, +} + +#[frb(mirror(Mode), dart_metadata=("freezed"))] +pub struct _Mode { + pub width: u32, + pub height: u32, + pub refresh_rates: Vec, +} + +pub enum IpcError { + SerDe(String), + Io(String), + Win(String), + Client(String), + RequestState, + Receive, + ConnectionFailed(String), + SendFailed, +} + +impl From for IpcError { + fn from(e: driver_ipc::IpcError) -> Self { + match e { + driver_ipc::IpcError::SerDe(e) => IpcError::SerDe(e.to_string()), + driver_ipc::IpcError::Io(e) => IpcError::Io(e.to_string()), + driver_ipc::IpcError::Win(e) => IpcError::Win(e.to_string()), + driver_ipc::IpcError::Client(e) => IpcError::Client(e.to_string()), + driver_ipc::IpcError::RequestState => IpcError::RequestState, + driver_ipc::IpcError::Receive => IpcError::Receive, + driver_ipc::IpcError::ConnectionFailed(e) => IpcError::ConnectionFailed(e.to_string()), + driver_ipc::IpcError::SendFailed => IpcError::SendFailed, + } + } +} + +#[frb(opaque)] +pub struct VirtualDisplayDriver { + client: DriverClient, +} + +impl VirtualDisplayDriver { + pub async fn new(pipe_name: Option) -> Result { + let client = if let Some(name) = pipe_name { + DriverClient::new_with(&name).await? + } else { + DriverClient::new().await? + }; + + let vdd = VirtualDisplayDriver { client }; + + Ok(vdd) + } + + /// Get the current state of the driver. + #[frb(getter, sync)] + pub fn state(&self) -> Vec { + self.client.monitors().to_owned() + } + + /// Stream of state changes. + /// + /// Updates whenever the state of the driver changes. It does not matter + /// from which process the change is requested. It will always reflect the + /// current state of the driver. + /// + /// If set again, it will cancel the old stream and set the new one + #[frb(getter)] + pub async fn stream(&mut self, sink: StreamSink>) { + self.client + .set_event_receiver(move |command| { + if let EventCommand::Changed(data) = command { + if let Err(_e) = sink.add(data) { + // do something with err? hmm + } + } + }) + .await; + } + + /// Cancel any previously set up stream + pub async fn cancel_stream(&self) { + self.client.terminate_event_receiver().await; + } + + /// Set the state of the provided monitors. + /// + /// Each monitor with a matching ID will be updated to the provided state. + #[frb(sync)] + pub fn set_monitors(&mut self, monitors: Vec) -> Result<(), IpcError> { + self.client.set_monitors(&monitors)?; + Ok(()) + } + + /// Set the state of the monitor with the provided ID. + /// + /// Only the provided properties will be updated. + #[frb(sync)] + pub fn set_monitor( + &mut self, + id: u32, + enabled: Option, + name: Option, + modes: Option>, + ) { + self.client.find_monitor_mut(id, |monitor| { + if let Some(enabled) = enabled { + monitor.enabled = enabled; + } + + monitor.name = name; + + if let Some(modes) = modes { + monitor.modes = modes; + } + }); + } + + /// Add a new monitor to the driver. + #[frb(sync)] + pub fn add_monitor( + &mut self, + name: Option, + enabled: bool, + modes: Vec, + ) -> Result<(), IpcError> { + let monitor = Monitor { + id: self.client.new_id(None).unwrap(), + name, + enabled, + modes, + }; + + self.client.add(monitor)?; + + Ok(()) + } + + /// Remove monitors from the driver. + #[frb(sync)] + pub fn remove_monitors(&mut self, ids: Vec) { + self.client.remove(&ids); + } + + /// Remove all monitors from the driver. + #[frb(sync)] + pub fn remove_all_monitors(&mut self) { + self.client.remove_all(); + } + + /// Push in-memory changes to driver. + pub async fn notify(&mut self) -> Result<(), IpcError> { + self.client.notify().await?; + Ok(()) + } + + /// Persist in-memory changes to user settings + pub fn persist(&mut self) -> Result<(), IpcError> { + self.client.persist()?; + Ok(()) + } +} diff --git a/rust/bindings/dart_vdd/rust/src/frb_generated.io.rs b/rust/bindings/dart_vdd/rust/src/frb_generated.io.rs new file mode 100644 index 00000000..1004c45e --- /dev/null +++ b/rust/bindings/dart_vdd/rust/src/frb_generated.io.rs @@ -0,0 +1,28 @@ +// This file is automatically generated, so please do not edit it. +// Generated by `flutter_rust_bridge`@ 2.0.0-dev.31. + +// Section: imports + +use super::*; +use crate::api::*; +use flutter_rust_bridge::for_generated::byteorder::{NativeEndian, ReadBytesExt, WriteBytesExt}; +use flutter_rust_bridge::for_generated::transform_result_dco; +use flutter_rust_bridge::{Handler, IntoIntoDart}; + +// Section: boilerplate + +flutter_rust_bridge::frb_generated_boilerplate_io!(); + +#[no_mangle] +pub extern "C" fn frbgen_dart_vdd_rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedrust_asyncRwLockVirtualDisplayDriver( + ptr: *const std::ffi::c_void, +) { + MoiArc::>::increment_strong_count(ptr as _); +} + +#[no_mangle] +pub extern "C" fn frbgen_dart_vdd_rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedrust_asyncRwLockVirtualDisplayDriver( + ptr: *const std::ffi::c_void, +) { + MoiArc::>::decrement_strong_count(ptr as _); +} diff --git a/rust/bindings/dart_vdd/rust/src/frb_generated.rs b/rust/bindings/dart_vdd/rust/src/frb_generated.rs new file mode 100644 index 00000000..51678621 --- /dev/null +++ b/rust/bindings/dart_vdd/rust/src/frb_generated.rs @@ -0,0 +1,1039 @@ +// This file is automatically generated, so please do not edit it. +// Generated by `flutter_rust_bridge`@ 2.0.0-dev.31. + +#![allow( + non_camel_case_types, + unused, + non_snake_case, + clippy::needless_return, + clippy::redundant_closure_call, + clippy::redundant_closure, + clippy::useless_conversion, + clippy::unit_arg, + clippy::unused_unit, + clippy::double_parens, + clippy::let_and_return, + clippy::too_many_arguments, + clippy::match_single_binding +)] + +// Section: imports + +use crate::api::*; +use flutter_rust_bridge::for_generated::byteorder::{NativeEndian, ReadBytesExt, WriteBytesExt}; +use flutter_rust_bridge::for_generated::transform_result_dco; +use flutter_rust_bridge::{Handler, IntoIntoDart}; + +// Section: boilerplate + +flutter_rust_bridge::frb_generated_boilerplate!( + default_stream_sink_codec = SseCodec, + default_rust_opaque = RustOpaqueMoi, + default_rust_auto_opaque = RustAutoOpaqueMoi, +); +pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_VERSION: &str = "2.0.0-dev.31"; + +// Section: executor + +flutter_rust_bridge::frb_generated_default_handler!(); + +// Section: wire_funcs + +fn wire_VirtualDisplayDriver_add_monitor_impl( + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) -> flutter_rust_bridge::for_generated::WireSyncRust2DartSse { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_sync::( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "VirtualDisplayDriver_add_monitor", + port: None, + mode: flutter_rust_bridge::for_generated::FfiCallMode::Sync, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_that = , + >>::sse_decode(&mut deserializer); + let api_name = >::sse_decode(&mut deserializer); + let api_enabled = ::sse_decode(&mut deserializer); + let api_modes = >::sse_decode(&mut deserializer); + deserializer.end(); + transform_result_sse((move || { + let mut api_that = api_that.rust_auto_opaque_decode_ref_mut(); + crate::api::VirtualDisplayDriver::add_monitor( + &mut api_that, + api_name, + api_enabled, + api_modes, + ) + })()) + }, + ) +} +fn wire_VirtualDisplayDriver_cancel_stream_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "VirtualDisplayDriver_cancel_stream", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_that = , + >>::sse_decode(&mut deserializer); + deserializer.end(); + move |context| async move { + transform_result_sse( + (move || async move { + let api_that = api_that.rust_auto_opaque_decode_ref(); + Result::<_, ()>::Ok( + crate::api::VirtualDisplayDriver::cancel_stream(&api_that).await, + ) + })() + .await, + ) + } + }, + ) +} +fn wire_VirtualDisplayDriver_new_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "VirtualDisplayDriver_new", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_pipe_name = >::sse_decode(&mut deserializer); + deserializer.end(); + move |context| async move { + transform_result_sse((move || async move { + crate::api::VirtualDisplayDriver::new(api_pipe_name).await + })().await) + } + }, + ) +} +fn wire_VirtualDisplayDriver_notify_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "VirtualDisplayDriver_notify", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_that = , + >>::sse_decode(&mut deserializer); + deserializer.end(); + move |context| async move { + transform_result_sse( + (move || async move { + let mut api_that = api_that.rust_auto_opaque_decode_ref_mut(); + crate::api::VirtualDisplayDriver::notify(&mut api_that).await + })() + .await, + ) + } + }, + ) +} +fn wire_VirtualDisplayDriver_persist_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_normal::( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "VirtualDisplayDriver_persist", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_that = , + >>::sse_decode(&mut deserializer); + deserializer.end(); + move |context| { + transform_result_sse((move || { + let mut api_that = api_that.rust_auto_opaque_decode_ref_mut(); + crate::api::VirtualDisplayDriver::persist(&mut api_that) + })()) + } + }, + ) +} +fn wire_VirtualDisplayDriver_remove_all_monitors_impl( + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) -> flutter_rust_bridge::for_generated::WireSyncRust2DartSse { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_sync::( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "VirtualDisplayDriver_remove_all_monitors", + port: None, + mode: flutter_rust_bridge::for_generated::FfiCallMode::Sync, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_that = , + >>::sse_decode(&mut deserializer); + deserializer.end(); + transform_result_sse((move || { + let mut api_that = api_that.rust_auto_opaque_decode_ref_mut(); + Result::<_, ()>::Ok(crate::api::VirtualDisplayDriver::remove_all_monitors( + &mut api_that, + )) + })()) + }, + ) +} +fn wire_VirtualDisplayDriver_remove_monitors_impl( + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) -> flutter_rust_bridge::for_generated::WireSyncRust2DartSse { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_sync::( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "VirtualDisplayDriver_remove_monitors", + port: None, + mode: flutter_rust_bridge::for_generated::FfiCallMode::Sync, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_that = , + >>::sse_decode(&mut deserializer); + let api_ids = >::sse_decode(&mut deserializer); + deserializer.end(); + transform_result_sse((move || { + let mut api_that = api_that.rust_auto_opaque_decode_ref_mut(); + Result::<_, ()>::Ok(crate::api::VirtualDisplayDriver::remove_monitors( + &mut api_that, + api_ids, + )) + })()) + }, + ) +} +fn wire_VirtualDisplayDriver_set_monitor_impl( + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) -> flutter_rust_bridge::for_generated::WireSyncRust2DartSse { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_sync::( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "VirtualDisplayDriver_set_monitor", + port: None, + mode: flutter_rust_bridge::for_generated::FfiCallMode::Sync, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_that = , + >>::sse_decode(&mut deserializer); + let api_id = ::sse_decode(&mut deserializer); + let api_enabled = >::sse_decode(&mut deserializer); + let api_name = >::sse_decode(&mut deserializer); + let api_modes = >>::sse_decode(&mut deserializer); + deserializer.end(); + transform_result_sse((move || { + let mut api_that = api_that.rust_auto_opaque_decode_ref_mut(); + Result::<_, ()>::Ok(crate::api::VirtualDisplayDriver::set_monitor( + &mut api_that, + api_id, + api_enabled, + api_name, + api_modes, + )) + })()) + }, + ) +} +fn wire_VirtualDisplayDriver_set_monitors_impl( + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) -> flutter_rust_bridge::for_generated::WireSyncRust2DartSse { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_sync::( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "VirtualDisplayDriver_set_monitors", + port: None, + mode: flutter_rust_bridge::for_generated::FfiCallMode::Sync, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_that = , + >>::sse_decode(&mut deserializer); + let api_monitors = >::sse_decode(&mut deserializer); + deserializer.end(); + transform_result_sse((move || { + let mut api_that = api_that.rust_auto_opaque_decode_ref_mut(); + crate::api::VirtualDisplayDriver::set_monitors(&mut api_that, api_monitors) + })()) + }, + ) +} +fn wire_VirtualDisplayDriver_state_impl( + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) -> flutter_rust_bridge::for_generated::WireSyncRust2DartSse { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_sync::( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "VirtualDisplayDriver_state", + port: None, + mode: flutter_rust_bridge::for_generated::FfiCallMode::Sync, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_that = , + >>::sse_decode(&mut deserializer); + deserializer.end(); + transform_result_sse((move || { + let api_that = api_that.rust_auto_opaque_decode_ref(); + Result::<_, ()>::Ok(crate::api::VirtualDisplayDriver::state(&api_that)) + })()) + }, + ) +} +fn wire_VirtualDisplayDriver_stream_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "VirtualDisplayDriver_stream", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_that = , + >>::sse_decode(&mut deserializer); + let api_sink = , + flutter_rust_bridge::for_generated::SseCodec, + >>::sse_decode(&mut deserializer); + deserializer.end(); + move |context| async move { + transform_result_sse( + (move || async move { + let mut api_that = api_that.rust_auto_opaque_decode_ref_mut(); + Result::<_, ()>::Ok( + crate::api::VirtualDisplayDriver::stream(&mut api_that, api_sink).await, + ) + })() + .await, + ) + } + }, + ) +} + +// Section: static_checks + +#[allow(clippy::unnecessary_literal_unwrap)] +const _: fn() = || { + { + let Mode = None::.unwrap(); + let _: u32 = Mode.width; + let _: u32 = Mode.height; + let _: Vec = Mode.refresh_rates; + } + { + let Monitor = None::.unwrap(); + let _: u32 = Monitor.id; + let _: Option = Monitor.name; + let _: bool = Monitor.enabled; + let _: Vec = Monitor.modes; + } +}; + +// Section: related_funcs + +flutter_rust_bridge::frb_generated_moi_arc_impl_value!( + flutter_rust_bridge::for_generated::rust_async::RwLock +); + +// Section: dart2rust + +impl SseDecode for VirtualDisplayDriver { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + let mut inner = , + >>::sse_decode(deserializer); + return inner.rust_auto_opaque_decode_owned(); + } +} + +impl SseDecode + for RustOpaqueMoi> +{ + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + let mut inner = ::sse_decode(deserializer); + return decode_rust_opaque_moi(inner); + } +} + +impl SseDecode + for StreamSink, flutter_rust_bridge::for_generated::SseCodec> +{ + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + let mut inner = ::sse_decode(deserializer); + return StreamSink::deserialize(inner); + } +} + +impl SseDecode for String { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + let mut inner = >::sse_decode(deserializer); + return String::from_utf8(inner).unwrap(); + } +} + +impl SseDecode for bool { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + deserializer.cursor.read_u8().unwrap() != 0 + } +} + +impl SseDecode for crate::api::IpcError { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + let mut tag_ = ::sse_decode(deserializer); + match tag_ { + 0 => { + let mut var_field0 = ::sse_decode(deserializer); + return crate::api::IpcError::SerDe(var_field0); + } + 1 => { + let mut var_field0 = ::sse_decode(deserializer); + return crate::api::IpcError::Io(var_field0); + } + 2 => { + let mut var_field0 = ::sse_decode(deserializer); + return crate::api::IpcError::Win(var_field0); + } + 3 => { + let mut var_field0 = ::sse_decode(deserializer); + return crate::api::IpcError::Client(var_field0); + } + 4 => { + return crate::api::IpcError::RequestState; + } + 5 => { + return crate::api::IpcError::Receive; + } + 6 => { + let mut var_field0 = ::sse_decode(deserializer); + return crate::api::IpcError::ConnectionFailed(var_field0); + } + 7 => { + return crate::api::IpcError::SendFailed; + } + _ => { + unimplemented!(""); + } + } + } +} + +impl SseDecode for Vec { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + let mut len_ = ::sse_decode(deserializer); + let mut ans_ = vec![]; + for idx_ in 0..len_ { + ans_.push(::sse_decode(deserializer)); + } + return ans_; + } +} + +impl SseDecode for Vec { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + let mut len_ = ::sse_decode(deserializer); + let mut ans_ = vec![]; + for idx_ in 0..len_ { + ans_.push(::sse_decode(deserializer)); + } + return ans_; + } +} + +impl SseDecode for Vec { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + let mut len_ = ::sse_decode(deserializer); + let mut ans_ = vec![]; + for idx_ in 0..len_ { + ans_.push(::sse_decode(deserializer)); + } + return ans_; + } +} + +impl SseDecode for Vec { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + let mut len_ = ::sse_decode(deserializer); + let mut ans_ = vec![]; + for idx_ in 0..len_ { + ans_.push(::sse_decode(deserializer)); + } + return ans_; + } +} + +impl SseDecode for crate::api::Mode { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + let mut var_width = ::sse_decode(deserializer); + let mut var_height = ::sse_decode(deserializer); + let mut var_refreshRates = >::sse_decode(deserializer); + return crate::api::Mode { + width: var_width, + height: var_height, + refresh_rates: var_refreshRates, + }; + } +} + +impl SseDecode for crate::api::Monitor { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + let mut var_id = ::sse_decode(deserializer); + let mut var_name = >::sse_decode(deserializer); + let mut var_enabled = ::sse_decode(deserializer); + let mut var_modes = >::sse_decode(deserializer); + return crate::api::Monitor { + id: var_id, + name: var_name, + enabled: var_enabled, + modes: var_modes, + }; + } +} + +impl SseDecode for Option { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + if (::sse_decode(deserializer)) { + return Some(::sse_decode(deserializer)); + } else { + return None; + } + } +} + +impl SseDecode for Option { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + if (::sse_decode(deserializer)) { + return Some(::sse_decode(deserializer)); + } else { + return None; + } + } +} + +impl SseDecode for Option> { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + if (::sse_decode(deserializer)) { + return Some(>::sse_decode(deserializer)); + } else { + return None; + } + } +} + +impl SseDecode for u32 { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + deserializer.cursor.read_u32::().unwrap() + } +} + +impl SseDecode for u8 { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + deserializer.cursor.read_u8().unwrap() + } +} + +impl SseDecode for () { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self {} +} + +impl SseDecode for usize { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + deserializer.cursor.read_u64::().unwrap() as _ + } +} + +impl SseDecode for i32 { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + deserializer.cursor.read_i32::().unwrap() + } +} + +fn pde_ffi_dispatcher_primary_impl( + func_id: i32, + port: flutter_rust_bridge::for_generated::MessagePort, + ptr: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len: i32, + data_len: i32, +) { + // Codec=Pde (Serialization + dispatch), see doc to use other codecs + match func_id { + 4 => wire_VirtualDisplayDriver_cancel_stream_impl(port, ptr, rust_vec_len, data_len), + 1 => wire_VirtualDisplayDriver_new_impl(port, ptr, rust_vec_len, data_len), + 10 => wire_VirtualDisplayDriver_notify_impl(port, ptr, rust_vec_len, data_len), + 11 => wire_VirtualDisplayDriver_persist_impl(port, ptr, rust_vec_len, data_len), + 3 => wire_VirtualDisplayDriver_stream_impl(port, ptr, rust_vec_len, data_len), + _ => unreachable!(), + } +} + +fn pde_ffi_dispatcher_sync_impl( + func_id: i32, + ptr: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len: i32, + data_len: i32, +) -> flutter_rust_bridge::for_generated::WireSyncRust2DartSse { + // Codec=Pde (Serialization + dispatch), see doc to use other codecs + match func_id { + 7 => wire_VirtualDisplayDriver_add_monitor_impl(ptr, rust_vec_len, data_len), + 9 => wire_VirtualDisplayDriver_remove_all_monitors_impl(ptr, rust_vec_len, data_len), + 8 => wire_VirtualDisplayDriver_remove_monitors_impl(ptr, rust_vec_len, data_len), + 6 => wire_VirtualDisplayDriver_set_monitor_impl(ptr, rust_vec_len, data_len), + 5 => wire_VirtualDisplayDriver_set_monitors_impl(ptr, rust_vec_len, data_len), + 2 => wire_VirtualDisplayDriver_state_impl(ptr, rust_vec_len, data_len), + _ => unreachable!(), + } +} + +// Section: rust2dart + +// Codec=Dco (DartCObject based), see doc to use other codecs +impl flutter_rust_bridge::IntoDart for FrbWrapper { + fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { + flutter_rust_bridge::for_generated::rust_auto_opaque_encode::<_, MoiArc<_>>(self.0) + .into_dart() + } +} +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive + for FrbWrapper +{ +} + +impl flutter_rust_bridge::IntoIntoDart> for VirtualDisplayDriver { + fn into_into_dart(self) -> FrbWrapper { + self.into() + } +} + +// Codec=Dco (DartCObject based), see doc to use other codecs +impl flutter_rust_bridge::IntoDart for crate::api::IpcError { + fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { + match self { + crate::api::IpcError::SerDe(field0) => { + [0.into_dart(), field0.into_into_dart().into_dart()].into_dart() + } + crate::api::IpcError::Io(field0) => { + [1.into_dart(), field0.into_into_dart().into_dart()].into_dart() + } + crate::api::IpcError::Win(field0) => { + [2.into_dart(), field0.into_into_dart().into_dart()].into_dart() + } + crate::api::IpcError::Client(field0) => { + [3.into_dart(), field0.into_into_dart().into_dart()].into_dart() + } + crate::api::IpcError::RequestState => [4.into_dart()].into_dart(), + crate::api::IpcError::Receive => [5.into_dart()].into_dart(), + crate::api::IpcError::ConnectionFailed(field0) => { + [6.into_dart(), field0.into_into_dart().into_dart()].into_dart() + } + crate::api::IpcError::SendFailed => [7.into_dart()].into_dart(), + } + } +} +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::api::IpcError {} +impl flutter_rust_bridge::IntoIntoDart for crate::api::IpcError { + fn into_into_dart(self) -> crate::api::IpcError { + self + } +} +// Codec=Dco (DartCObject based), see doc to use other codecs +impl flutter_rust_bridge::IntoDart for FrbWrapper { + fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { + [ + self.0.width.into_into_dart().into_dart(), + self.0.height.into_into_dart().into_dart(), + self.0.refresh_rates.into_into_dart().into_dart(), + ] + .into_dart() + } +} +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for FrbWrapper {} +impl flutter_rust_bridge::IntoIntoDart> for crate::api::Mode { + fn into_into_dart(self) -> FrbWrapper { + self.into() + } +} +// Codec=Dco (DartCObject based), see doc to use other codecs +impl flutter_rust_bridge::IntoDart for FrbWrapper { + fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { + [ + self.0.id.into_into_dart().into_dart(), + self.0.name.into_into_dart().into_dart(), + self.0.enabled.into_into_dart().into_dart(), + self.0.modes.into_into_dart().into_dart(), + ] + .into_dart() + } +} +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive + for FrbWrapper +{ +} +impl flutter_rust_bridge::IntoIntoDart> for crate::api::Monitor { + fn into_into_dart(self) -> FrbWrapper { + self.into() + } +} + +impl SseEncode for VirtualDisplayDriver { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + >>::sse_encode(flutter_rust_bridge::for_generated::rust_auto_opaque_encode::<_, MoiArc<_>>(self), serializer); + } +} + +impl SseEncode + for RustOpaqueMoi> +{ + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + let (ptr, size) = self.sse_encode_raw(); + ::sse_encode(ptr, serializer); + ::sse_encode(size, serializer); + } +} + +impl SseEncode + for StreamSink, flutter_rust_bridge::for_generated::SseCodec> +{ + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + unimplemented!("") + } +} + +impl SseEncode for String { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + >::sse_encode(self.into_bytes(), serializer); + } +} + +impl SseEncode for bool { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + serializer.cursor.write_u8(self as _).unwrap(); + } +} + +impl SseEncode for crate::api::IpcError { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + match self { + crate::api::IpcError::SerDe(field0) => { + ::sse_encode(0, serializer); + ::sse_encode(field0, serializer); + } + crate::api::IpcError::Io(field0) => { + ::sse_encode(1, serializer); + ::sse_encode(field0, serializer); + } + crate::api::IpcError::Win(field0) => { + ::sse_encode(2, serializer); + ::sse_encode(field0, serializer); + } + crate::api::IpcError::Client(field0) => { + ::sse_encode(3, serializer); + ::sse_encode(field0, serializer); + } + crate::api::IpcError::RequestState => { + ::sse_encode(4, serializer); + } + crate::api::IpcError::Receive => { + ::sse_encode(5, serializer); + } + crate::api::IpcError::ConnectionFailed(field0) => { + ::sse_encode(6, serializer); + ::sse_encode(field0, serializer); + } + crate::api::IpcError::SendFailed => { + ::sse_encode(7, serializer); + } + } + } +} + +impl SseEncode for Vec { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + ::sse_encode(self.len() as _, serializer); + for item in self { + ::sse_encode(item, serializer); + } + } +} + +impl SseEncode for Vec { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + ::sse_encode(self.len() as _, serializer); + for item in self { + ::sse_encode(item, serializer); + } + } +} + +impl SseEncode for Vec { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + ::sse_encode(self.len() as _, serializer); + for item in self { + ::sse_encode(item, serializer); + } + } +} + +impl SseEncode for Vec { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + ::sse_encode(self.len() as _, serializer); + for item in self { + ::sse_encode(item, serializer); + } + } +} + +impl SseEncode for crate::api::Mode { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + ::sse_encode(self.width, serializer); + ::sse_encode(self.height, serializer); + >::sse_encode(self.refresh_rates, serializer); + } +} + +impl SseEncode for crate::api::Monitor { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + ::sse_encode(self.id, serializer); + >::sse_encode(self.name, serializer); + ::sse_encode(self.enabled, serializer); + >::sse_encode(self.modes, serializer); + } +} + +impl SseEncode for Option { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + ::sse_encode(self.is_some(), serializer); + if let Some(value) = self { + ::sse_encode(value, serializer); + } + } +} + +impl SseEncode for Option { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + ::sse_encode(self.is_some(), serializer); + if let Some(value) = self { + ::sse_encode(value, serializer); + } + } +} + +impl SseEncode for Option> { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + ::sse_encode(self.is_some(), serializer); + if let Some(value) = self { + >::sse_encode(value, serializer); + } + } +} + +impl SseEncode for u32 { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + serializer.cursor.write_u32::(self).unwrap(); + } +} + +impl SseEncode for u8 { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + serializer.cursor.write_u8(self).unwrap(); + } +} + +impl SseEncode for () { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) {} +} + +impl SseEncode for usize { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + serializer + .cursor + .write_u64::(self as _) + .unwrap(); + } +} + +impl SseEncode for i32 { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + serializer.cursor.write_i32::(self).unwrap(); + } +} + +#[cfg(not(target_family = "wasm"))] +#[path = "frb_generated.io.rs"] +mod io; +#[cfg(not(target_family = "wasm"))] +pub use io::*; diff --git a/rust/bindings/dart_vdd/rust/src/lib.rs b/rust/bindings/dart_vdd/rust/src/lib.rs new file mode 100644 index 00000000..93606027 --- /dev/null +++ b/rust/bindings/dart_vdd/rust/src/lib.rs @@ -0,0 +1,2 @@ +pub mod api; +mod frb_generated; /* AUTO INJECTED BY flutter_rust_bridge. This line may not be accurate, and you can change it according to your needs. */ diff --git a/rust/bindings/dart_vdd/test/dart_vdd_test.dart b/rust/bindings/dart_vdd/test/dart_vdd_test.dart new file mode 100644 index 00000000..d916be82 --- /dev/null +++ b/rust/bindings/dart_vdd/test/dart_vdd_test.dart @@ -0,0 +1,21 @@ +import 'package:dart_vdd/dart_vdd.dart'; +import 'package:dart_vdd/src/generated/frb_generated.dart'; +import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart'; +import 'package:test/test.dart'; + +/// Can be run from package root using `dart --enable-experiment=native-assets +/// test` +void main() { + setUpAll(() async { + await RustLib.init( + // There is currently no way to accurately resolve the shared library + externalLibrary: ExternalLibrary.open("../../target/release/dart_vdd.dll"), + ); + }); + + test('Test', () async { + final driver = await VirtualDisplayDriver.newInstance(); + + expect(() => driver.removeAllMonitors(), throwsException); + }); +} diff --git a/vdd_control/.gitignore b/vdd_control/.gitignore new file mode 100644 index 00000000..29a3a501 --- /dev/null +++ b/vdd_control/.gitignore @@ -0,0 +1,43 @@ +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.buildlog/ +.history +.svn/ +migrate_working_dir/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. +#.vscode/ + +# Flutter/Dart/Pub related +**/doc/api/ +**/ios/Flutter/.last_build_id +.dart_tool/ +.flutter-plugins +.flutter-plugins-dependencies +.pub-cache/ +.pub/ +/build/ + +# Symbolication related +app.*.symbols + +# Obfuscation related +app.*.map.json + +# Android Studio will place build artifacts here +/android/app/debug +/android/app/profile +/android/app/release diff --git a/vdd_control/.metadata b/vdd_control/.metadata new file mode 100644 index 00000000..ed37e53c --- /dev/null +++ b/vdd_control/.metadata @@ -0,0 +1,30 @@ +# This file tracks properties of this Flutter project. +# Used by Flutter tool to assess capabilities and perform upgrades etc. +# +# This file should be version controlled and should not be manually edited. + +version: + revision: "34b454f42dd6f8721dfe43fc7de5d215705b5e52" + channel: "main" + +project_type: app + +# Tracks metadata for the flutter migrate command +migration: + platforms: + - platform: root + create_revision: 34b454f42dd6f8721dfe43fc7de5d215705b5e52 + base_revision: 34b454f42dd6f8721dfe43fc7de5d215705b5e52 + - platform: windows + create_revision: 34b454f42dd6f8721dfe43fc7de5d215705b5e52 + base_revision: 34b454f42dd6f8721dfe43fc7de5d215705b5e52 + + # User provided section + + # List of Local paths (relative to this file) that should be + # ignored by the migrate tool. + # + # Files that are not part of the templates will be ignored by default. + unmanaged_files: + - 'lib/main.dart' + - 'ios/Runner.xcodeproj/project.pbxproj' diff --git a/vdd_control/README.md b/vdd_control/README.md new file mode 100644 index 00000000..26cb04f6 --- /dev/null +++ b/vdd_control/README.md @@ -0,0 +1,3 @@ +# vdd_control + +A new Flutter project. diff --git a/vdd_control/analysis_options.yaml b/vdd_control/analysis_options.yaml new file mode 100644 index 00000000..f9b30346 --- /dev/null +++ b/vdd_control/analysis_options.yaml @@ -0,0 +1 @@ +include: package:flutter_lints/flutter.yaml diff --git a/vdd_control/lib/main.dart b/vdd_control/lib/main.dart new file mode 100644 index 00000000..c2405476 --- /dev/null +++ b/vdd_control/lib/main.dart @@ -0,0 +1,38 @@ +import 'dart:typed_data'; + +import 'package:dart_vdd/dart_vdd.dart'; +import 'package:flutter/material.dart'; + +/// Requires flutter main channel currently, change with `flutter channel main` +void main() async { + await initVdd(); + + final driver = VirtualDisplayDriver(); + + Future(() async { + await for (final monitors in driver.stream) { + print('monitors: $monitors'); + } + }); + + driver.addMonitor(enabled: true, modes: [ + Mode(width: 1920, height: 1080, refreshRates: Uint32List.fromList([60])), + ]); + + runApp(const MainApp()); +} + +class MainApp extends StatelessWidget { + const MainApp({super.key}); + + @override + Widget build(BuildContext context) { + return const MaterialApp( + home: Scaffold( + body: Center( + child: Text('Hello World!'), + ), + ), + ); + } +} diff --git a/vdd_control/pubspec.lock b/vdd_control/pubspec.lock new file mode 100644 index 00000000..549e7900 --- /dev/null +++ b/vdd_control/pubspec.lock @@ -0,0 +1,316 @@ +# Generated by pub +# See https://dart.dev/tools/pub/glossary#lockfile +packages: + args: + dependency: transitive + description: + name: args + sha256: eef6c46b622e0494a36c5a12d10d77fb4e855501a91c1b9ef9339326e58f0596 + url: "https://pub.dev" + source: hosted + version: "2.4.2" + async: + dependency: transitive + description: + name: async + sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" + url: "https://pub.dev" + source: hosted + version: "2.11.0" + boolean_selector: + dependency: transitive + description: + name: boolean_selector + sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" + url: "https://pub.dev" + source: hosted + version: "2.1.1" + build_cli_annotations: + dependency: transitive + description: + name: build_cli_annotations + sha256: b59d2769769efd6c9ff6d4c4cede0be115a566afc591705c2040b707534b1172 + url: "https://pub.dev" + source: hosted + version: "2.1.0" + characters: + dependency: transitive + description: + name: characters + sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" + url: "https://pub.dev" + source: hosted + version: "1.3.0" + cli_config: + dependency: transitive + description: + name: cli_config + sha256: "65c7830649e1f8247660f1b783effb460255d6e2c1ac94eb823cf1f84e59b288" + url: "https://pub.dev" + source: hosted + version: "0.1.2" + clock: + dependency: transitive + description: + name: clock + sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf + url: "https://pub.dev" + source: hosted + version: "1.1.1" + collection: + dependency: transitive + description: + name: collection + sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a + url: "https://pub.dev" + source: hosted + version: "1.18.0" + crypto: + dependency: transitive + description: + name: crypto + sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab + url: "https://pub.dev" + source: hosted + version: "3.0.3" + dart_vdd: + dependency: "direct main" + description: + path: "../rust/bindings/dart_vdd" + relative: true + source: path + version: "1.0.0" + fake_async: + dependency: transitive + description: + name: fake_async + sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" + url: "https://pub.dev" + source: hosted + version: "1.3.1" + flutter: + dependency: "direct main" + description: flutter + source: sdk + version: "0.0.0" + flutter_lints: + dependency: "direct dev" + description: + name: flutter_lints + sha256: e2a421b7e59244faef694ba7b30562e489c2b489866e505074eb005cd7060db7 + url: "https://pub.dev" + source: hosted + version: "3.0.1" + flutter_rust_bridge: + dependency: transitive + description: + name: flutter_rust_bridge + sha256: e9a8716b1ad2fc81c434f3e4bf84b86c578578678c57e568b44aea7acf210102 + url: "https://pub.dev" + source: hosted + version: "2.0.0-dev.31" + flutter_test: + dependency: "direct dev" + description: flutter + source: sdk + version: "0.0.0" + freezed_annotation: + dependency: transitive + description: + name: freezed_annotation + sha256: c3fd9336eb55a38cc1bbd79ab17573113a8deccd0ecbbf926cca3c62803b5c2d + url: "https://pub.dev" + source: hosted + version: "2.4.1" + js: + dependency: transitive + description: + name: js + sha256: c1b2e9b5ea78c45e1a0788d29606ba27dc5f71f019f32ca5140f61ef071838cf + url: "https://pub.dev" + source: hosted + version: "0.7.1" + json_annotation: + dependency: transitive + description: + name: json_annotation + sha256: b10a7b2ff83d83c777edba3c6a0f97045ddadd56c944e1a23a3fdf43a1bf4467 + url: "https://pub.dev" + source: hosted + version: "4.8.1" + leak_tracker: + dependency: transitive + description: + name: leak_tracker + sha256: "7f0df31977cb2c0b88585095d168e689669a2cc9b97c309665e3386f3e9d341a" + url: "https://pub.dev" + source: hosted + version: "10.0.4" + leak_tracker_flutter_testing: + dependency: transitive + description: + name: leak_tracker_flutter_testing + sha256: "06e98f569d004c1315b991ded39924b21af84cf14cc94791b8aea337d25b57f8" + url: "https://pub.dev" + source: hosted + version: "3.0.3" + leak_tracker_testing: + dependency: transitive + description: + name: leak_tracker_testing + sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3" + url: "https://pub.dev" + source: hosted + version: "3.0.1" + lints: + dependency: transitive + description: + name: lints + sha256: cbf8d4b858bb0134ef3ef87841abdf8d63bfc255c266b7bf6b39daa1085c4290 + url: "https://pub.dev" + source: hosted + version: "3.0.0" + matcher: + dependency: transitive + description: + name: matcher + sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb + url: "https://pub.dev" + source: hosted + version: "0.12.16+1" + material_color_utilities: + dependency: transitive + description: + name: material_color_utilities + sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a" + url: "https://pub.dev" + source: hosted + version: "0.8.0" + meta: + dependency: transitive + description: + name: meta + sha256: "7687075e408b093f36e6bbf6c91878cc0d4cd10f409506f7bc996f68220b9136" + url: "https://pub.dev" + source: hosted + version: "1.12.0" + native_assets_cli: + dependency: transitive + description: + name: native_assets_cli + sha256: "4eb8a94601af0acd50f7e75e1ad15c0db0b046b89256ee994776b6a6d49139b7" + url: "https://pub.dev" + source: hosted + version: "0.4.2" + path: + dependency: transitive + description: + name: path + sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af" + url: "https://pub.dev" + source: hosted + version: "1.9.0" + pub_semver: + dependency: transitive + description: + name: pub_semver + sha256: "40d3ab1bbd474c4c2328c91e3a7df8c6dd629b79ece4c4bd04bee496a224fb0c" + url: "https://pub.dev" + source: hosted + version: "2.1.4" + sky_engine: + dependency: transitive + description: flutter + source: sdk + version: "0.0.99" + source_span: + dependency: transitive + description: + name: source_span + sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" + url: "https://pub.dev" + source: hosted + version: "1.10.0" + stack_trace: + dependency: transitive + description: + name: stack_trace + sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" + url: "https://pub.dev" + source: hosted + version: "1.11.1" + stream_channel: + dependency: transitive + description: + name: stream_channel + sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 + url: "https://pub.dev" + source: hosted + version: "2.1.2" + string_scanner: + dependency: transitive + description: + name: string_scanner + sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" + url: "https://pub.dev" + source: hosted + version: "1.2.0" + term_glyph: + dependency: transitive + description: + name: term_glyph + sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 + url: "https://pub.dev" + source: hosted + version: "1.2.1" + test_api: + dependency: transitive + description: + name: test_api + sha256: "9955ae474176f7ac8ee4e989dadfb411a58c30415bcfb648fa04b2b8a03afa7f" + url: "https://pub.dev" + source: hosted + version: "0.7.0" + typed_data: + dependency: transitive + description: + name: typed_data + sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c + url: "https://pub.dev" + source: hosted + version: "1.3.2" + vector_math: + dependency: transitive + description: + name: vector_math + sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" + url: "https://pub.dev" + source: hosted + version: "2.1.4" + vm_service: + dependency: transitive + description: + name: vm_service + sha256: e7d5ecd604e499358c5fe35ee828c0298a320d54455e791e9dcf73486bc8d9f0 + url: "https://pub.dev" + source: hosted + version: "14.1.0" + yaml: + dependency: transitive + description: + name: yaml + sha256: "75769501ea3489fca56601ff33454fe45507ea3bfb014161abc3b43ae25989d5" + url: "https://pub.dev" + source: hosted + version: "3.1.2" + yaml_edit: + dependency: transitive + description: + name: yaml_edit + sha256: c566f4f804215d84a7a2c377667f546c6033d5b34b4f9e60dfb09d17c4e97826 + url: "https://pub.dev" + source: hosted + version: "2.2.0" +sdks: + dart: ">=3.4.0-227.0.dev <4.0.0" + flutter: ">=3.18.0-18.0.pre.54" diff --git a/vdd_control/pubspec.yaml b/vdd_control/pubspec.yaml new file mode 100644 index 00000000..eb6e90ab --- /dev/null +++ b/vdd_control/pubspec.yaml @@ -0,0 +1,21 @@ +name: vdd_control +description: "A new Flutter project." +publish_to: "none" +version: 0.1.0 + +environment: + sdk: ">=3.4.0-227.0.dev <4.0.0" + +dependencies: + flutter: + sdk: flutter + dart_vdd: + path: ../rust/bindings/dart_vdd + +dev_dependencies: + flutter_test: + sdk: flutter + flutter_lints: ^3.0.0 + +flutter: + uses-material-design: true diff --git a/vdd_control/windows/.gitignore b/vdd_control/windows/.gitignore new file mode 100644 index 00000000..d492d0d9 --- /dev/null +++ b/vdd_control/windows/.gitignore @@ -0,0 +1,17 @@ +flutter/ephemeral/ + +# Visual Studio user-specific files. +*.suo +*.user +*.userosscache +*.sln.docstates + +# Visual Studio build-related files. +x64/ +x86/ + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ diff --git a/vdd_control/windows/CMakeLists.txt b/vdd_control/windows/CMakeLists.txt new file mode 100644 index 00000000..9bfef295 --- /dev/null +++ b/vdd_control/windows/CMakeLists.txt @@ -0,0 +1,108 @@ +# Project-level configuration. +cmake_minimum_required(VERSION 3.14) +project(vdd_control LANGUAGES CXX) + +# The name of the executable created for the application. Change this to change +# the on-disk name of your application. +set(BINARY_NAME "vdd_control") + +# Explicitly opt in to modern CMake behaviors to avoid warnings with recent +# versions of CMake. +cmake_policy(VERSION 3.14...3.25) + +# Define build configuration option. +get_property(IS_MULTICONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) +if(IS_MULTICONFIG) + set(CMAKE_CONFIGURATION_TYPES "Debug;Profile;Release" + CACHE STRING "" FORCE) +else() + if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + set(CMAKE_BUILD_TYPE "Debug" CACHE + STRING "Flutter build mode" FORCE) + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS + "Debug" "Profile" "Release") + endif() +endif() +# Define settings for the Profile build mode. +set(CMAKE_EXE_LINKER_FLAGS_PROFILE "${CMAKE_EXE_LINKER_FLAGS_RELEASE}") +set(CMAKE_SHARED_LINKER_FLAGS_PROFILE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE}") +set(CMAKE_C_FLAGS_PROFILE "${CMAKE_C_FLAGS_RELEASE}") +set(CMAKE_CXX_FLAGS_PROFILE "${CMAKE_CXX_FLAGS_RELEASE}") + +# Use Unicode for all projects. +add_definitions(-DUNICODE -D_UNICODE) + +# Compilation settings that should be applied to most targets. +# +# Be cautious about adding new options here, as plugins use this function by +# default. In most cases, you should add new options to specific targets instead +# of modifying this function. +function(APPLY_STANDARD_SETTINGS TARGET) + target_compile_features(${TARGET} PUBLIC cxx_std_17) + target_compile_options(${TARGET} PRIVATE /W4 /WX /wd"4100") + target_compile_options(${TARGET} PRIVATE /EHsc) + target_compile_definitions(${TARGET} PRIVATE "_HAS_EXCEPTIONS=0") + target_compile_definitions(${TARGET} PRIVATE "$<$:_DEBUG>") +endfunction() + +# Flutter library and tool build rules. +set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") +add_subdirectory(${FLUTTER_MANAGED_DIR}) + +# Application build; see runner/CMakeLists.txt. +add_subdirectory("runner") + + +# Generated plugin build rules, which manage building the plugins and adding +# them to the application. +include(flutter/generated_plugins.cmake) + + +# === Installation === +# Support files are copied into place next to the executable, so that it can +# run in place. This is done instead of making a separate bundle (as on Linux) +# so that building and running from within Visual Studio will work. +set(BUILD_BUNDLE_DIR "$") +# Make the "install" step default, as it's required to run. +set(CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD 1) +if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) +endif() + +set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") +set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}") + +install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) + +if(PLUGIN_BUNDLED_LIBRARIES) + install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endif() + +# Copy the native assets provided by the build.dart from all packages. +set(NATIVE_ASSETS_DIR "${PROJECT_BUILD_DIR}native_assets/windows/") +install(DIRECTORY "${NATIVE_ASSETS_DIR}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) + +# Fully re-copy the assets directory on each build to avoid having stale files +# from a previous install. +set(FLUTTER_ASSET_DIR_NAME "flutter_assets") +install(CODE " + file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") + " COMPONENT Runtime) +install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" + DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) + +# Install the AOT library on non-Debug builds only. +install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" + CONFIGURATIONS Profile;Release + COMPONENT Runtime) diff --git a/vdd_control/windows/flutter/CMakeLists.txt b/vdd_control/windows/flutter/CMakeLists.txt new file mode 100644 index 00000000..903f4899 --- /dev/null +++ b/vdd_control/windows/flutter/CMakeLists.txt @@ -0,0 +1,109 @@ +# This file controls Flutter-level build steps. It should not be edited. +cmake_minimum_required(VERSION 3.14) + +set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") + +# Configuration provided via flutter tool. +include(${EPHEMERAL_DIR}/generated_config.cmake) + +# TODO: Move the rest of this into files in ephemeral. See +# https://github.com/flutter/flutter/issues/57146. +set(WRAPPER_ROOT "${EPHEMERAL_DIR}/cpp_client_wrapper") + +# Set fallback configurations for older versions of the flutter tool. +if (NOT DEFINED FLUTTER_TARGET_PLATFORM) + set(FLUTTER_TARGET_PLATFORM "windows-x64") +endif() + +# === Flutter Library === +set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/flutter_windows.dll") + +# Published to parent scope for install step. +set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) +set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) +set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) +set(AOT_LIBRARY "${PROJECT_DIR}/build/windows/app.so" PARENT_SCOPE) + +list(APPEND FLUTTER_LIBRARY_HEADERS + "flutter_export.h" + "flutter_windows.h" + "flutter_messenger.h" + "flutter_plugin_registrar.h" + "flutter_texture_registrar.h" +) +list(TRANSFORM FLUTTER_LIBRARY_HEADERS PREPEND "${EPHEMERAL_DIR}/") +add_library(flutter INTERFACE) +target_include_directories(flutter INTERFACE + "${EPHEMERAL_DIR}" +) +target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}.lib") +add_dependencies(flutter flutter_assemble) + +# === Wrapper === +list(APPEND CPP_WRAPPER_SOURCES_CORE + "core_implementations.cc" + "standard_codec.cc" +) +list(TRANSFORM CPP_WRAPPER_SOURCES_CORE PREPEND "${WRAPPER_ROOT}/") +list(APPEND CPP_WRAPPER_SOURCES_PLUGIN + "plugin_registrar.cc" +) +list(TRANSFORM CPP_WRAPPER_SOURCES_PLUGIN PREPEND "${WRAPPER_ROOT}/") +list(APPEND CPP_WRAPPER_SOURCES_APP + "flutter_engine.cc" + "flutter_view_controller.cc" +) +list(TRANSFORM CPP_WRAPPER_SOURCES_APP PREPEND "${WRAPPER_ROOT}/") + +# Wrapper sources needed for a plugin. +add_library(flutter_wrapper_plugin STATIC + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_PLUGIN} +) +apply_standard_settings(flutter_wrapper_plugin) +set_target_properties(flutter_wrapper_plugin PROPERTIES + POSITION_INDEPENDENT_CODE ON) +set_target_properties(flutter_wrapper_plugin PROPERTIES + CXX_VISIBILITY_PRESET hidden) +target_link_libraries(flutter_wrapper_plugin PUBLIC flutter) +target_include_directories(flutter_wrapper_plugin PUBLIC + "${WRAPPER_ROOT}/include" +) +add_dependencies(flutter_wrapper_plugin flutter_assemble) + +# Wrapper sources needed for the runner. +add_library(flutter_wrapper_app STATIC + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_APP} +) +apply_standard_settings(flutter_wrapper_app) +target_link_libraries(flutter_wrapper_app PUBLIC flutter) +target_include_directories(flutter_wrapper_app PUBLIC + "${WRAPPER_ROOT}/include" +) +add_dependencies(flutter_wrapper_app flutter_assemble) + +# === Flutter tool backend === +# _phony_ is a non-existent file to force this command to run every time, +# since currently there's no way to get a full input/output list from the +# flutter tool. +set(PHONY_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/_phony_") +set_source_files_properties("${PHONY_OUTPUT}" PROPERTIES SYMBOLIC TRUE) +add_custom_command( + OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} + ${CPP_WRAPPER_SOURCES_CORE} ${CPP_WRAPPER_SOURCES_PLUGIN} + ${CPP_WRAPPER_SOURCES_APP} + ${PHONY_OUTPUT} + COMMAND ${CMAKE_COMMAND} -E env + ${FLUTTER_TOOL_ENVIRONMENT} + "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat" + ${FLUTTER_TARGET_PLATFORM} $ + VERBATIM +) +add_custom_target(flutter_assemble DEPENDS + "${FLUTTER_LIBRARY}" + ${FLUTTER_LIBRARY_HEADERS} + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_PLUGIN} + ${CPP_WRAPPER_SOURCES_APP} +) diff --git a/vdd_control/windows/flutter/generated_plugin_registrant.cc b/vdd_control/windows/flutter/generated_plugin_registrant.cc new file mode 100644 index 00000000..8b6d4680 --- /dev/null +++ b/vdd_control/windows/flutter/generated_plugin_registrant.cc @@ -0,0 +1,11 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#include "generated_plugin_registrant.h" + + +void RegisterPlugins(flutter::PluginRegistry* registry) { +} diff --git a/vdd_control/windows/flutter/generated_plugin_registrant.h b/vdd_control/windows/flutter/generated_plugin_registrant.h new file mode 100644 index 00000000..dc139d85 --- /dev/null +++ b/vdd_control/windows/flutter/generated_plugin_registrant.h @@ -0,0 +1,15 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#ifndef GENERATED_PLUGIN_REGISTRANT_ +#define GENERATED_PLUGIN_REGISTRANT_ + +#include + +// Registers Flutter plugins. +void RegisterPlugins(flutter::PluginRegistry* registry); + +#endif // GENERATED_PLUGIN_REGISTRANT_ diff --git a/vdd_control/windows/flutter/generated_plugins.cmake b/vdd_control/windows/flutter/generated_plugins.cmake new file mode 100644 index 00000000..b93c4c30 --- /dev/null +++ b/vdd_control/windows/flutter/generated_plugins.cmake @@ -0,0 +1,23 @@ +# +# Generated file, do not edit. +# + +list(APPEND FLUTTER_PLUGIN_LIST +) + +list(APPEND FLUTTER_FFI_PLUGIN_LIST +) + +set(PLUGIN_BUNDLED_LIBRARIES) + +foreach(plugin ${FLUTTER_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/windows plugins/${plugin}) + target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) + list(APPEND PLUGIN_BUNDLED_LIBRARIES $) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) +endforeach(plugin) + +foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/windows plugins/${ffi_plugin}) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) +endforeach(ffi_plugin) diff --git a/vdd_control/windows/runner/CMakeLists.txt b/vdd_control/windows/runner/CMakeLists.txt new file mode 100644 index 00000000..394917c0 --- /dev/null +++ b/vdd_control/windows/runner/CMakeLists.txt @@ -0,0 +1,40 @@ +cmake_minimum_required(VERSION 3.14) +project(runner LANGUAGES CXX) + +# Define the application target. To change its name, change BINARY_NAME in the +# top-level CMakeLists.txt, not the value here, or `flutter run` will no longer +# work. +# +# Any new source files that you add to the application should be added here. +add_executable(${BINARY_NAME} WIN32 + "flutter_window.cpp" + "main.cpp" + "utils.cpp" + "win32_window.cpp" + "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" + "Runner.rc" + "runner.exe.manifest" +) + +# Apply the standard set of build settings. This can be removed for applications +# that need different build settings. +apply_standard_settings(${BINARY_NAME}) + +# Add preprocessor definitions for the build version. +target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION=\"${FLUTTER_VERSION}\"") +target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MAJOR=${FLUTTER_VERSION_MAJOR}") +target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MINOR=${FLUTTER_VERSION_MINOR}") +target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_PATCH=${FLUTTER_VERSION_PATCH}") +target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_BUILD=${FLUTTER_VERSION_BUILD}") + +# Disable Windows macros that collide with C++ standard library functions. +target_compile_definitions(${BINARY_NAME} PRIVATE "NOMINMAX") + +# Add dependency libraries and include directories. Add any application-specific +# dependencies here. +target_link_libraries(${BINARY_NAME} PRIVATE flutter flutter_wrapper_app) +target_link_libraries(${BINARY_NAME} PRIVATE "dwmapi.lib") +target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}") + +# Run the Flutter tool portions of the build. This must not be removed. +add_dependencies(${BINARY_NAME} flutter_assemble) diff --git a/vdd_control/windows/runner/Runner.rc b/vdd_control/windows/runner/Runner.rc new file mode 100644 index 00000000..eafdbe7d --- /dev/null +++ b/vdd_control/windows/runner/Runner.rc @@ -0,0 +1,121 @@ +// Microsoft Visual C++ generated resource script. +// +#pragma code_page(65001) +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "winres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (United States) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""winres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_APP_ICON ICON "resources\\app_icon.ico" + + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +#if defined(FLUTTER_VERSION_MAJOR) && defined(FLUTTER_VERSION_MINOR) && defined(FLUTTER_VERSION_PATCH) && defined(FLUTTER_VERSION_BUILD) +#define VERSION_AS_NUMBER FLUTTER_VERSION_MAJOR,FLUTTER_VERSION_MINOR,FLUTTER_VERSION_PATCH,FLUTTER_VERSION_BUILD +#else +#define VERSION_AS_NUMBER 1,0,0,0 +#endif + +#if defined(FLUTTER_VERSION) +#define VERSION_AS_STRING FLUTTER_VERSION +#else +#define VERSION_AS_STRING "1.0.0" +#endif + +VS_VERSION_INFO VERSIONINFO + FILEVERSION VERSION_AS_NUMBER + PRODUCTVERSION VERSION_AS_NUMBER + FILEFLAGSMASK VS_FFI_FILEFLAGSMASK +#ifdef _DEBUG + FILEFLAGS VS_FF_DEBUG +#else + FILEFLAGS 0x0L +#endif + FILEOS VOS__WINDOWS32 + FILETYPE VFT_APP + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904e4" + BEGIN + VALUE "CompanyName", "com.example" "\0" + VALUE "FileDescription", "vdd_control" "\0" + VALUE "FileVersion", VERSION_AS_STRING "\0" + VALUE "InternalName", "vdd_control" "\0" + VALUE "LegalCopyright", "Copyright (C) 2024 com.example. All rights reserved." "\0" + VALUE "OriginalFilename", "vdd_control.exe" "\0" + VALUE "ProductName", "vdd_control" "\0" + VALUE "ProductVersion", VERSION_AS_STRING "\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1252 + END +END + +#endif // English (United States) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED diff --git a/vdd_control/windows/runner/flutter_window.cpp b/vdd_control/windows/runner/flutter_window.cpp new file mode 100644 index 00000000..955ee303 --- /dev/null +++ b/vdd_control/windows/runner/flutter_window.cpp @@ -0,0 +1,71 @@ +#include "flutter_window.h" + +#include + +#include "flutter/generated_plugin_registrant.h" + +FlutterWindow::FlutterWindow(const flutter::DartProject& project) + : project_(project) {} + +FlutterWindow::~FlutterWindow() {} + +bool FlutterWindow::OnCreate() { + if (!Win32Window::OnCreate()) { + return false; + } + + RECT frame = GetClientArea(); + + // The size here must match the window dimensions to avoid unnecessary surface + // creation / destruction in the startup path. + flutter_controller_ = std::make_unique( + frame.right - frame.left, frame.bottom - frame.top, project_); + // Ensure that basic setup of the controller was successful. + if (!flutter_controller_->engine() || !flutter_controller_->view()) { + return false; + } + RegisterPlugins(flutter_controller_->engine()); + SetChildContent(flutter_controller_->view()->GetNativeWindow()); + + flutter_controller_->engine()->SetNextFrameCallback([&]() { + this->Show(); + }); + + // Flutter can complete the first frame before the "show window" callback is + // registered. The following call ensures a frame is pending to ensure the + // window is shown. It is a no-op if the first frame hasn't completed yet. + flutter_controller_->ForceRedraw(); + + return true; +} + +void FlutterWindow::OnDestroy() { + if (flutter_controller_) { + flutter_controller_ = nullptr; + } + + Win32Window::OnDestroy(); +} + +LRESULT +FlutterWindow::MessageHandler(HWND hwnd, UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept { + // Give Flutter, including plugins, an opportunity to handle window messages. + if (flutter_controller_) { + std::optional result = + flutter_controller_->HandleTopLevelWindowProc(hwnd, message, wparam, + lparam); + if (result) { + return *result; + } + } + + switch (message) { + case WM_FONTCHANGE: + flutter_controller_->engine()->ReloadSystemFonts(); + break; + } + + return Win32Window::MessageHandler(hwnd, message, wparam, lparam); +} diff --git a/vdd_control/windows/runner/flutter_window.h b/vdd_control/windows/runner/flutter_window.h new file mode 100644 index 00000000..6da0652f --- /dev/null +++ b/vdd_control/windows/runner/flutter_window.h @@ -0,0 +1,33 @@ +#ifndef RUNNER_FLUTTER_WINDOW_H_ +#define RUNNER_FLUTTER_WINDOW_H_ + +#include +#include + +#include + +#include "win32_window.h" + +// A window that does nothing but host a Flutter view. +class FlutterWindow : public Win32Window { + public: + // Creates a new FlutterWindow hosting a Flutter view running |project|. + explicit FlutterWindow(const flutter::DartProject& project); + virtual ~FlutterWindow(); + + protected: + // Win32Window: + bool OnCreate() override; + void OnDestroy() override; + LRESULT MessageHandler(HWND window, UINT const message, WPARAM const wparam, + LPARAM const lparam) noexcept override; + + private: + // The project to run. + flutter::DartProject project_; + + // The Flutter instance hosted by this window. + std::unique_ptr flutter_controller_; +}; + +#endif // RUNNER_FLUTTER_WINDOW_H_ diff --git a/vdd_control/windows/runner/main.cpp b/vdd_control/windows/runner/main.cpp new file mode 100644 index 00000000..659f5aee --- /dev/null +++ b/vdd_control/windows/runner/main.cpp @@ -0,0 +1,43 @@ +#include +#include +#include + +#include "flutter_window.h" +#include "utils.h" + +int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev, + _In_ wchar_t *command_line, _In_ int show_command) { + // Attach to console when present (e.g., 'flutter run') or create a + // new console when running with a debugger. + if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::IsDebuggerPresent()) { + CreateAndAttachConsole(); + } + + // Initialize COM, so that it is available for use in the library and/or + // plugins. + ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); + + flutter::DartProject project(L"data"); + + std::vector command_line_arguments = + GetCommandLineArguments(); + + project.set_dart_entrypoint_arguments(std::move(command_line_arguments)); + + FlutterWindow window(project); + Win32Window::Point origin(10, 10); + Win32Window::Size size(1280, 720); + if (!window.Create(L"vdd_control", origin, size)) { + return EXIT_FAILURE; + } + window.SetQuitOnClose(true); + + ::MSG msg; + while (::GetMessage(&msg, nullptr, 0, 0)) { + ::TranslateMessage(&msg); + ::DispatchMessage(&msg); + } + + ::CoUninitialize(); + return EXIT_SUCCESS; +} diff --git a/vdd_control/windows/runner/resource.h b/vdd_control/windows/runner/resource.h new file mode 100644 index 00000000..66a65d1e --- /dev/null +++ b/vdd_control/windows/runner/resource.h @@ -0,0 +1,16 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by Runner.rc +// +#define IDI_APP_ICON 101 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 102 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/vdd_control/windows/runner/resources/app_icon.ico b/vdd_control/windows/runner/resources/app_icon.ico new file mode 100644 index 00000000..c04e20ca Binary files /dev/null and b/vdd_control/windows/runner/resources/app_icon.ico differ diff --git a/vdd_control/windows/runner/runner.exe.manifest b/vdd_control/windows/runner/runner.exe.manifest new file mode 100644 index 00000000..a42ea768 --- /dev/null +++ b/vdd_control/windows/runner/runner.exe.manifest @@ -0,0 +1,20 @@ + + + + + PerMonitorV2 + + + + + + + + + + + + + + + diff --git a/vdd_control/windows/runner/utils.cpp b/vdd_control/windows/runner/utils.cpp new file mode 100644 index 00000000..3a0b4651 --- /dev/null +++ b/vdd_control/windows/runner/utils.cpp @@ -0,0 +1,65 @@ +#include "utils.h" + +#include +#include +#include +#include + +#include + +void CreateAndAttachConsole() { + if (::AllocConsole()) { + FILE *unused; + if (freopen_s(&unused, "CONOUT$", "w", stdout)) { + _dup2(_fileno(stdout), 1); + } + if (freopen_s(&unused, "CONOUT$", "w", stderr)) { + _dup2(_fileno(stdout), 2); + } + std::ios::sync_with_stdio(); + FlutterDesktopResyncOutputStreams(); + } +} + +std::vector GetCommandLineArguments() { + // Convert the UTF-16 command line arguments to UTF-8 for the Engine to use. + int argc; + wchar_t** argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc); + if (argv == nullptr) { + return std::vector(); + } + + std::vector command_line_arguments; + + // Skip the first argument as it's the binary name. + for (int i = 1; i < argc; i++) { + command_line_arguments.push_back(Utf8FromUtf16(argv[i])); + } + + ::LocalFree(argv); + + return command_line_arguments; +} + +std::string Utf8FromUtf16(const wchar_t* utf16_string) { + if (utf16_string == nullptr) { + return std::string(); + } + unsigned int target_length = ::WideCharToMultiByte( + CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, + -1, nullptr, 0, nullptr, nullptr) + -1; // remove the trailing null character + int input_length = (int)wcslen(utf16_string); + std::string utf8_string; + if (target_length == 0 || target_length > utf8_string.max_size()) { + return utf8_string; + } + utf8_string.resize(target_length); + int converted_length = ::WideCharToMultiByte( + CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, + input_length, utf8_string.data(), target_length, nullptr, nullptr); + if (converted_length == 0) { + return std::string(); + } + return utf8_string; +} diff --git a/vdd_control/windows/runner/utils.h b/vdd_control/windows/runner/utils.h new file mode 100644 index 00000000..3879d547 --- /dev/null +++ b/vdd_control/windows/runner/utils.h @@ -0,0 +1,19 @@ +#ifndef RUNNER_UTILS_H_ +#define RUNNER_UTILS_H_ + +#include +#include + +// Creates a console for the process, and redirects stdout and stderr to +// it for both the runner and the Flutter library. +void CreateAndAttachConsole(); + +// Takes a null-terminated wchar_t* encoded in UTF-16 and returns a std::string +// encoded in UTF-8. Returns an empty std::string on failure. +std::string Utf8FromUtf16(const wchar_t* utf16_string); + +// Gets the command line arguments passed in as a std::vector, +// encoded in UTF-8. Returns an empty std::vector on failure. +std::vector GetCommandLineArguments(); + +#endif // RUNNER_UTILS_H_ diff --git a/vdd_control/windows/runner/win32_window.cpp b/vdd_control/windows/runner/win32_window.cpp new file mode 100644 index 00000000..60608d0f --- /dev/null +++ b/vdd_control/windows/runner/win32_window.cpp @@ -0,0 +1,288 @@ +#include "win32_window.h" + +#include +#include + +#include "resource.h" + +namespace { + +/// Window attribute that enables dark mode window decorations. +/// +/// Redefined in case the developer's machine has a Windows SDK older than +/// version 10.0.22000.0. +/// See: https://docs.microsoft.com/windows/win32/api/dwmapi/ne-dwmapi-dwmwindowattribute +#ifndef DWMWA_USE_IMMERSIVE_DARK_MODE +#define DWMWA_USE_IMMERSIVE_DARK_MODE 20 +#endif + +constexpr const wchar_t kWindowClassName[] = L"FLUTTER_RUNNER_WIN32_WINDOW"; + +/// Registry key for app theme preference. +/// +/// A value of 0 indicates apps should use dark mode. A non-zero or missing +/// value indicates apps should use light mode. +constexpr const wchar_t kGetPreferredBrightnessRegKey[] = + L"Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize"; +constexpr const wchar_t kGetPreferredBrightnessRegValue[] = L"AppsUseLightTheme"; + +// The number of Win32Window objects that currently exist. +static int g_active_window_count = 0; + +using EnableNonClientDpiScaling = BOOL __stdcall(HWND hwnd); + +// Scale helper to convert logical scaler values to physical using passed in +// scale factor +int Scale(int source, double scale_factor) { + return static_cast(source * scale_factor); +} + +// Dynamically loads the |EnableNonClientDpiScaling| from the User32 module. +// This API is only needed for PerMonitor V1 awareness mode. +void EnableFullDpiSupportIfAvailable(HWND hwnd) { + HMODULE user32_module = LoadLibraryA("User32.dll"); + if (!user32_module) { + return; + } + auto enable_non_client_dpi_scaling = + reinterpret_cast( + GetProcAddress(user32_module, "EnableNonClientDpiScaling")); + if (enable_non_client_dpi_scaling != nullptr) { + enable_non_client_dpi_scaling(hwnd); + } + FreeLibrary(user32_module); +} + +} // namespace + +// Manages the Win32Window's window class registration. +class WindowClassRegistrar { + public: + ~WindowClassRegistrar() = default; + + // Returns the singleton registrar instance. + static WindowClassRegistrar* GetInstance() { + if (!instance_) { + instance_ = new WindowClassRegistrar(); + } + return instance_; + } + + // Returns the name of the window class, registering the class if it hasn't + // previously been registered. + const wchar_t* GetWindowClass(); + + // Unregisters the window class. Should only be called if there are no + // instances of the window. + void UnregisterWindowClass(); + + private: + WindowClassRegistrar() = default; + + static WindowClassRegistrar* instance_; + + bool class_registered_ = false; +}; + +WindowClassRegistrar* WindowClassRegistrar::instance_ = nullptr; + +const wchar_t* WindowClassRegistrar::GetWindowClass() { + if (!class_registered_) { + WNDCLASS window_class{}; + window_class.hCursor = LoadCursor(nullptr, IDC_ARROW); + window_class.lpszClassName = kWindowClassName; + window_class.style = CS_HREDRAW | CS_VREDRAW; + window_class.cbClsExtra = 0; + window_class.cbWndExtra = 0; + window_class.hInstance = GetModuleHandle(nullptr); + window_class.hIcon = + LoadIcon(window_class.hInstance, MAKEINTRESOURCE(IDI_APP_ICON)); + window_class.hbrBackground = 0; + window_class.lpszMenuName = nullptr; + window_class.lpfnWndProc = Win32Window::WndProc; + RegisterClass(&window_class); + class_registered_ = true; + } + return kWindowClassName; +} + +void WindowClassRegistrar::UnregisterWindowClass() { + UnregisterClass(kWindowClassName, nullptr); + class_registered_ = false; +} + +Win32Window::Win32Window() { + ++g_active_window_count; +} + +Win32Window::~Win32Window() { + --g_active_window_count; + Destroy(); +} + +bool Win32Window::Create(const std::wstring& title, + const Point& origin, + const Size& size) { + Destroy(); + + const wchar_t* window_class = + WindowClassRegistrar::GetInstance()->GetWindowClass(); + + const POINT target_point = {static_cast(origin.x), + static_cast(origin.y)}; + HMONITOR monitor = MonitorFromPoint(target_point, MONITOR_DEFAULTTONEAREST); + UINT dpi = FlutterDesktopGetDpiForMonitor(monitor); + double scale_factor = dpi / 96.0; + + HWND window = CreateWindow( + window_class, title.c_str(), WS_OVERLAPPEDWINDOW, + Scale(origin.x, scale_factor), Scale(origin.y, scale_factor), + Scale(size.width, scale_factor), Scale(size.height, scale_factor), + nullptr, nullptr, GetModuleHandle(nullptr), this); + + if (!window) { + return false; + } + + UpdateTheme(window); + + return OnCreate(); +} + +bool Win32Window::Show() { + return ShowWindow(window_handle_, SW_SHOWNORMAL); +} + +// static +LRESULT CALLBACK Win32Window::WndProc(HWND const window, + UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept { + if (message == WM_NCCREATE) { + auto window_struct = reinterpret_cast(lparam); + SetWindowLongPtr(window, GWLP_USERDATA, + reinterpret_cast(window_struct->lpCreateParams)); + + auto that = static_cast(window_struct->lpCreateParams); + EnableFullDpiSupportIfAvailable(window); + that->window_handle_ = window; + } else if (Win32Window* that = GetThisFromHandle(window)) { + return that->MessageHandler(window, message, wparam, lparam); + } + + return DefWindowProc(window, message, wparam, lparam); +} + +LRESULT +Win32Window::MessageHandler(HWND hwnd, + UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept { + switch (message) { + case WM_DESTROY: + window_handle_ = nullptr; + Destroy(); + if (quit_on_close_) { + PostQuitMessage(0); + } + return 0; + + case WM_DPICHANGED: { + auto newRectSize = reinterpret_cast(lparam); + LONG newWidth = newRectSize->right - newRectSize->left; + LONG newHeight = newRectSize->bottom - newRectSize->top; + + SetWindowPos(hwnd, nullptr, newRectSize->left, newRectSize->top, newWidth, + newHeight, SWP_NOZORDER | SWP_NOACTIVATE); + + return 0; + } + case WM_SIZE: { + RECT rect = GetClientArea(); + if (child_content_ != nullptr) { + // Size and position the child window. + MoveWindow(child_content_, rect.left, rect.top, rect.right - rect.left, + rect.bottom - rect.top, TRUE); + } + return 0; + } + + case WM_ACTIVATE: + if (child_content_ != nullptr) { + SetFocus(child_content_); + } + return 0; + + case WM_DWMCOLORIZATIONCOLORCHANGED: + UpdateTheme(hwnd); + return 0; + } + + return DefWindowProc(window_handle_, message, wparam, lparam); +} + +void Win32Window::Destroy() { + OnDestroy(); + + if (window_handle_) { + DestroyWindow(window_handle_); + window_handle_ = nullptr; + } + if (g_active_window_count == 0) { + WindowClassRegistrar::GetInstance()->UnregisterWindowClass(); + } +} + +Win32Window* Win32Window::GetThisFromHandle(HWND const window) noexcept { + return reinterpret_cast( + GetWindowLongPtr(window, GWLP_USERDATA)); +} + +void Win32Window::SetChildContent(HWND content) { + child_content_ = content; + SetParent(content, window_handle_); + RECT frame = GetClientArea(); + + MoveWindow(content, frame.left, frame.top, frame.right - frame.left, + frame.bottom - frame.top, true); + + SetFocus(child_content_); +} + +RECT Win32Window::GetClientArea() { + RECT frame; + GetClientRect(window_handle_, &frame); + return frame; +} + +HWND Win32Window::GetHandle() { + return window_handle_; +} + +void Win32Window::SetQuitOnClose(bool quit_on_close) { + quit_on_close_ = quit_on_close; +} + +bool Win32Window::OnCreate() { + // No-op; provided for subclasses. + return true; +} + +void Win32Window::OnDestroy() { + // No-op; provided for subclasses. +} + +void Win32Window::UpdateTheme(HWND const window) { + DWORD light_mode; + DWORD light_mode_size = sizeof(light_mode); + LSTATUS result = RegGetValue(HKEY_CURRENT_USER, kGetPreferredBrightnessRegKey, + kGetPreferredBrightnessRegValue, + RRF_RT_REG_DWORD, nullptr, &light_mode, + &light_mode_size); + + if (result == ERROR_SUCCESS) { + BOOL enable_dark_mode = light_mode == 0; + DwmSetWindowAttribute(window, DWMWA_USE_IMMERSIVE_DARK_MODE, + &enable_dark_mode, sizeof(enable_dark_mode)); + } +} diff --git a/vdd_control/windows/runner/win32_window.h b/vdd_control/windows/runner/win32_window.h new file mode 100644 index 00000000..e901dde6 --- /dev/null +++ b/vdd_control/windows/runner/win32_window.h @@ -0,0 +1,102 @@ +#ifndef RUNNER_WIN32_WINDOW_H_ +#define RUNNER_WIN32_WINDOW_H_ + +#include + +#include +#include +#include + +// A class abstraction for a high DPI-aware Win32 Window. Intended to be +// inherited from by classes that wish to specialize with custom +// rendering and input handling +class Win32Window { + public: + struct Point { + unsigned int x; + unsigned int y; + Point(unsigned int x, unsigned int y) : x(x), y(y) {} + }; + + struct Size { + unsigned int width; + unsigned int height; + Size(unsigned int width, unsigned int height) + : width(width), height(height) {} + }; + + Win32Window(); + virtual ~Win32Window(); + + // Creates a win32 window with |title| that is positioned and sized using + // |origin| and |size|. New windows are created on the default monitor. Window + // sizes are specified to the OS in physical pixels, hence to ensure a + // consistent size this function will scale the inputted width and height as + // as appropriate for the default monitor. The window is invisible until + // |Show| is called. Returns true if the window was created successfully. + bool Create(const std::wstring& title, const Point& origin, const Size& size); + + // Show the current window. Returns true if the window was successfully shown. + bool Show(); + + // Release OS resources associated with window. + void Destroy(); + + // Inserts |content| into the window tree. + void SetChildContent(HWND content); + + // Returns the backing Window handle to enable clients to set icon and other + // window properties. Returns nullptr if the window has been destroyed. + HWND GetHandle(); + + // If true, closing this window will quit the application. + void SetQuitOnClose(bool quit_on_close); + + // Return a RECT representing the bounds of the current client area. + RECT GetClientArea(); + + protected: + // Processes and route salient window messages for mouse handling, + // size change and DPI. Delegates handling of these to member overloads that + // inheriting classes can handle. + virtual LRESULT MessageHandler(HWND window, + UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept; + + // Called when CreateAndShow is called, allowing subclass window-related + // setup. Subclasses should return false if setup fails. + virtual bool OnCreate(); + + // Called when Destroy is called. + virtual void OnDestroy(); + + private: + friend class WindowClassRegistrar; + + // OS callback called by message pump. Handles the WM_NCCREATE message which + // is passed when the non-client area is being created and enables automatic + // non-client DPI scaling so that the non-client area automatically + // responds to changes in DPI. All other messages are handled by + // MessageHandler. + static LRESULT CALLBACK WndProc(HWND const window, + UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept; + + // Retrieves a class instance pointer for |window| + static Win32Window* GetThisFromHandle(HWND const window) noexcept; + + // Update the window frame's theme to match the system theme. + static void UpdateTheme(HWND const window); + + bool quit_on_close_ = false; + + // window handle for top level window. + HWND window_handle_ = nullptr; + + // window handle for hosted content. + HWND child_content_ = nullptr; +}; + +#endif // RUNNER_WIN32_WINDOW_H_