diff --git a/docs/macos-signing.md b/docs/macos-signing.md index f4cec0db..30543e6d 100644 --- a/docs/macos-signing.md +++ b/docs/macos-signing.md @@ -157,7 +157,7 @@ Related: secrets are stored in the login keychain, so they work without `keychai ## Minimum macOS version -`MACOSX_DEPLOYMENT_TARGET` is **10.15** in every Xcode configuration, and `LSMinimumSystemVersion` follows it. That is also the highest minimum among the macOS plugins in use (`file_selector_macos` and `url_launcher_macos` need 10.15; `package_info_plus`, `device_info_plus` and the vendored `refresh_rate` need 10.14). Raising it needs no plugin change, lowering it is not possible. +`MACOSX_DEPLOYMENT_TARGET` is **10.15** in every Xcode configuration, and `LSMinimumSystemVersion` follows it. That is also the highest minimum among the macOS plugins in use (`file_selector_macos` and `url_launcher_macos` need 10.15; `package_info_plus`, `device_info_plus` and `refresh_rate` need 10.14). Raising it needs no plugin change, lowering it is not possible. Rendering above 60 Hz on a ProMotion display needs **macOS 14** or later (`refresh_rate`, see [motion and high refresh](motion-and-high-refresh.md)); on older versions the app runs at 60 Hz. diff --git a/docs/motion-and-high-refresh.md b/docs/motion-and-high-refresh.md index 6ac8cca4..6382c003 100644 --- a/docs/motion-and-high-refresh.md +++ b/docs/motion-and-high-refresh.md @@ -65,7 +65,7 @@ Root cause (engine): per `flutter/flutter#160952`, the engine "can render at 120 ### Practical implication for Querya (desktop) - **Windows:** usually follows DWM monitor Hz; **measure and verify**. -- **Linux:** **query-only** — `enable` / prefer-max are no-ops in `third_party/refresh_rate` Linux plugin. Overlay/`RefreshRate.info` report what GDK sees; actual frame pacing is compositor-dependent. Do not treat a 120/144 reading as “unlocked by Querya”. +- **Linux:** **query-only** — `enable` / prefer-max are no-ops in the `refresh_rate` Linux plugin. Overlay/`RefreshRate.info` report what GDK sees; actual frame pacing is compositor-dependent. Do not treat a 120/144 reading as “unlocked by Querya”. - **macOS:** unlock via `RefreshRate.enable()` when capped at 60 (ProMotion / high-Hz). - Use `refresh_rate` for **diagnostics** (debug overlay / benchmark) plus the macOS unlock in `main()`. - **Implementation:** `lib/core/motion/display_refresh_service.dart` calls `RefreshRate.enable()` in `main()`. Debug Hz badge: `flutter run --dart-define=QUERYA_REFRESH_OVERLAY=true`. diff --git a/lib/core/motion/display_refresh_service.dart b/lib/core/motion/display_refresh_service.dart index 870d9d2f..64d69f3a 100644 --- a/lib/core/motion/display_refresh_service.dart +++ b/lib/core/motion/display_refresh_service.dart @@ -1,3 +1,5 @@ +import 'dart:async'; + import 'package:flutter/foundation.dart'; import 'package:refresh_rate/refresh_rate.dart'; @@ -7,7 +9,8 @@ import 'package:refresh_rate/refresh_rate.dart'; /// - **macOS 14+:** ProMotion / high-Hz unlock /// - **Windows:** typically follows DWM (enable is effectively a no-op unlock) /// - **Linux:** **query-only** — enable is a no-op; [RefreshRate.info] / overlay -/// report GDK monitor refresh (compositor decides actual pacing) +/// report GDK monitor refresh (compositor decides actual pacing). An unknown +/// rate reads 0 Hz (it no longer falls back to 60) /// /// Debug overlay: `flutter run --dart-define=QUERYA_REFRESH_OVERLAY=true`. abstract final class DisplayRefreshService { @@ -17,7 +20,8 @@ abstract final class DisplayRefreshService { /// Unlock peak refresh where the platform supports it; log Hz in debug builds. static void initialize() { - RefreshRate.enable(); + // 2.x returns the result of the request; nothing here acts on it. + unawaited(RefreshRate.enable()); if (!kDebugMode) return; @@ -31,6 +35,7 @@ abstract final class DisplayRefreshService { } static void _logRefreshInfo() { + // The first reading can still be 0 Hz: 2.x fills `info` asynchronously. final info = RefreshRate.info; debugPrint( 'Display refresh: ${info.currentRate} Hz ' diff --git a/pubspec.yaml b/pubspec.yaml index 8eb429e8..d6119139 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -14,7 +14,7 @@ dependencies: sdk: flutter http: ^1.2.2 crypto: ^3.0.6 - refresh_rate: ^1.0.2 + refresh_rate: ^2.0.1 shadcn_flutter: ^0.0.52 bitsdojo_window: ^0.1.6 path: ^1.9.0 @@ -56,16 +56,14 @@ dependency_overrides: # Patched ToastLayer (fixes InheritedNotifier crash on resize / hot reload). shadcn_flutter: path: third_party/shadcn_flutter - # Linux -Werror: fix uninitialized rates[0] in refresh_rate 1.0.2. - refresh_rate: - path: third_party/refresh_rate flutter: uses-material-design: true config: - # The vendored refresh_rate plugin's Package.swift points its target at - # ../Classes, outside the package root, so Swift Package Manager (on by - # default since Flutter 3.47) cannot resolve it; macOS builds use CocoaPods. + # Swift Package Manager (on by default since Flutter 3.47) is off for every + # plugin: macOS builds use CocoaPods. The vendored refresh_rate plugin that + # needed this is gone (refresh_rate 2.x has a valid Package.swift); whether + # to turn it back on is its own change, to be tried on a Mac. enable-swift-package-manager: false assets: - assets/images/ diff --git a/third_party/refresh_rate/CHANGELOG.md b/third_party/refresh_rate/CHANGELOG.md deleted file mode 100644 index 6f9b880f..00000000 --- a/third_party/refresh_rate/CHANGELOG.md +++ /dev/null @@ -1,60 +0,0 @@ -# Changelog - -## 1.0.2 - -- Added Swift Package Manager support. - -## 1.0.1 - -### Web support -- Added web platform implementation using `requestAnimationFrame` interval - timing to detect the display's current refresh rate (same technique as TestUFO). -- Control methods are graceful no-ops (browsers own vsync scheduling). -- FPS overlay and benchmark sessions work unchanged on web. - -### Documentation -- Added comprehensive Dartdoc comments to all public APIs. - -### Platform fixes -- Restructured `Package.swift` into `ios/refresh_rate/` and `macos/refresh_rate/` - for correct Swift Package Manager module resolution. -- Resolved minor lint warnings from test suites. - -## 1.0.0 - -Initial stable release — unlock, query, overlay, and benchmark display refresh rates across all Flutter platforms. - -### Control - -- `RefreshRate.enable()` — one-line unlock of peak display refresh rate -- `RefreshRate.preferMax()` / `preferDefault()` — explicit rate preference -- `RefreshRate.matchContent(fps)` — sync display cadence to content frame rate (fixes 24 fps video judder) -- `RefreshRate.boost(duration)` — temporary max-rate spike for gesture-driven animations -- `RefreshRate.category(RateCategory)` — Android 15 semantic rate category -- `RefreshRate.setTouchBoost(bool)` — Android 15 touch-driven rate boost - -### Diagnostics - -- `RefreshRate.info` — synchronous cached `RefreshRateInfo` snapshot (current rate, max, min, supported rates, VRR, API level) -- `RefreshRate.onChanged` — stream fires on rate change, Low Power Mode toggle, or thermal state change -- `RefreshRate.isLowPowerMode` / `thermalState` / `isProMotionReady` - -### Debug overlay - -- `RefreshRate.showOverlay()` — full diagnostic HUD with live FPS, build/raster timings, frame budget -- `RefreshRate.showFPS()` / `showHz()` — individual overlay badges -- FPS colour is relative to the device's actual target rate, not a hard-coded 60 Hz baseline - -### Benchmark sessions - -- `RefreshRate.startSession(name)` returns `RefreshRateSession` -- `session.end()` returns `SessionReport` with verdict, bottleneck, avgFps, 1% low FPS, missed-frame %, and JSON export -- Sessions auto-exclude backgrounded periods, resume warmup, LPM changes, and thermal changes - -### Platform coverage - -- **Android 6+** (API 23): `SurfaceControl.Transaction.setFrameRate()` (API 34+), `preferredRefreshRate` + `preferredDisplayModeId` (API 30–33), legacy `preferredDisplayModeId` fallback (API 23–29) -- **iOS 15+**: `CADisplayLink.preferredFrameRateRange` with runtime `Info.plist` ProMotion validation -- **macOS 14+**: `CADisplayLink`-based control via `NSView.displayLink` -- **macOS < 14 / Windows / Linux**: query-only (reports real monitor refresh rate) -- All platform bridges use [pigeon](https://pub.dev/packages/pigeon) — fully typed, zero codec overhead diff --git a/third_party/refresh_rate/LICENSE b/third_party/refresh_rate/LICENSE deleted file mode 100644 index 5bdae8a2..00000000 --- a/third_party/refresh_rate/LICENSE +++ /dev/null @@ -1,24 +0,0 @@ -Copyright 2026 Qoder. All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -* Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. -* Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. -* Neither the name of Qoder nor the names of its contributors may be - used to endorse or promote products derived from this software without - specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/third_party/refresh_rate/README.md b/third_party/refresh_rate/README.md deleted file mode 100644 index 1d07f6a9..00000000 --- a/third_party/refresh_rate/README.md +++ /dev/null @@ -1,230 +0,0 @@ -# refresh_rate - -[![pub package](https://img.shields.io/pub/v/refresh_rate.svg)](https://pub.dev/packages/refresh_rate) -[![pub points](https://img.shields.io/pub/points/refresh_rate)](https://pub.dev/packages/refresh_rate/score) -[![likes](https://img.shields.io/pub/likes/refresh_rate)](https://pub.dev/packages/refresh_rate/score) -[![popularity](https://img.shields.io/pub/popularity/refresh_rate)](https://pub.dev/packages/refresh_rate/score) -[![License: BSD-3](https://img.shields.io/badge/License-BSD_3--Clause-blue.svg)](https://github.com/qoder-official/refresh_rate/blob/main/LICENSE) - -**Unlock your device's full refresh rate in one line of Flutter.** - -Your Flutter app runs at 60 Hz on a 120 Hz phone right now. The engine never tells the OS compositor it can handle more. `refresh_rate` fixes that — and gives you diagnostics, benchmarks, and a live overlay to prove it. - -```dart -void main() { - RefreshRate.enable(); // that's it — 120 Hz on a 120 Hz device - runApp(const MyApp()); -} -``` - -> **Why does this happen?** Flutter's engine never calls Android's `Surface.setFrameRate()` and the default iOS template is missing the `CADisableMinimumFrameDurationOnPhone` plist key. See [Flutter #160952](https://github.com/flutter/flutter/issues/160952). This package makes those calls for you. - -Built on [pigeon](https://pub.dev/packages/pigeon) — fully typed end-to-end, zero `MethodChannel` codec overhead. - ---- - -## Platform support - -| Platform | Unlock | Query | Overlay | Benchmark | -|:---------|:------:|:-----:|:-------:|:---------:| -| **Android** 6+ (API 23) | ✅ | ✅ | ✅ | ✅ | -| **iOS** 15+ (ProMotion) | ✅ \* | ✅ | ✅ | ✅ | -| **macOS** 14+ (Sonoma) | ✅ | ✅ | ✅ | ✅ | -| **macOS** < 14 | — | ✅ | ✅ | ✅ | -| **Windows** | — | ✅ | ✅ | ✅ | -| **Linux** | — | ✅ | ✅ | ✅ | - -\* iOS requires `Info.plist` key — see [iOS setup](#ios-setup). - ---- - -## Installation - -```yaml -dependencies: - refresh_rate: ^1.0.0 -``` - -### iOS setup - -Add to `ios/Runner/Info.plist` — required for > 60 Hz on iPhones with ProMotion: - -```xml -CADisableMinimumFrameDurationOnPhone - -``` - -Without this key, iOS caps your app at 60 Hz even on 120 Hz hardware. The plugin detects this at runtime and prints a console warning if missing. iPad Pro does **not** need this key. - ---- - -## Quick start - -```dart -import 'package:refresh_rate/refresh_rate.dart'; - -void main() { - WidgetsFlutterBinding.ensureInitialized(); - RefreshRate.enable(); // unlocks peak rate on every supported device - runApp(const MyApp()); -} -``` - -One call in `main()`. On a 120 Hz device your app now renders at 120 Hz. On a 60 Hz device nothing changes — the OS stays in control. - ---- - -## Diagnostics - -```dart -final info = RefreshRate.info; // synchronous cached snapshot - -print(info.currentRate); // 120.0 -print(info.maxRate); // 120.0 -print(info.supportedRates); // [60.0, 90.0, 120.0] -print(info.isVariableRefreshRate); // true (LTPO panel) -print(info.androidApiLevel); // 34 (Android only) -print(info.displayServer); // "wayland" (Linux only) - -print(RefreshRate.isLowPowerMode); // false -print(RefreshRate.thermalState); // ThermalState.nominal -print(RefreshRate.isProMotionReady); // true — plist key + hardware both present - -await RefreshRate.refresh(); // reload platform cache - -RefreshRate.onChanged.listen((info) { // rate, Low Power Mode, or thermal change - print('Now running at ${info.currentRate} Hz'); -}); -``` - ---- - -## Advanced control - -```dart -RefreshRate.preferMax(); // highest available rate -RefreshRate.preferDefault(); // return to OS default -RefreshRate.matchContent(24.0); // sync to 24 fps video (fixes judder) -RefreshRate.boost(const Duration(seconds: 2)); // temporary spike for gestures - -// Android 15+ -RefreshRate.category(RateCategory.high); // semantic rate category -RefreshRate.setTouchBoost(true); // OS-managed touch boost -``` - ---- - -## Debug overlay - -Drop a live performance HUD into any debug build: - -```dart -if (kDebugMode) RefreshRate.showOverlay(); -``` - -The overlay is **refresh-rate-aware**: FPS is colour-coded against the device's *actual* target Hz, not a hard-coded 60 Hz baseline. It also shows per-frame build/raster timings, frame budget, Low Power Mode, and thermal state. - -```dart -RefreshRate.showFPS(); // just the FPS counter -RefreshRate.showHz(); // just the Hz badge -RefreshRate.showOverlay(); // full diagnostic panel -RefreshRate.hideOverlay(); // dismiss -``` - ---- - -## Benchmark sessions - -Record a named performance window and get a structured report: - -```dart -final session = RefreshRate.startSession('home_scroll'); - -// ... user interacts ... - -final report = await session.end(); - -print(report.verdict); // Verdict.good / degraded / poor -print(report.likelyBottleneck); // Bottleneck.rasterBound / buildBound / none -print(report.avgFps); // 108.4 -print(report.onePercentLowFps); // 87.2 -print(report.missedFramePercent); // 3.2% - -final json = report.toJson(); // export for CI / QA dashboards -``` - -Sessions automatically exclude app backgrounding, resume warmup, Low Power Mode toggles, and thermal state changes — so numbers reflect real rendering performance. - ---- - -## How it works - -### Android - -| API Level | What the plugin calls | -|:---------:|:----------------------| -| **34+** | `SurfaceControl.Transaction.setFrameRate()` — direct SurfaceFlinger vote | -| **30–33** | `preferredRefreshRate` + `preferredDisplayModeId` — dual hint | -| **23–29** | `preferredDisplayModeId` with resolution-match guard — legacy fallback | - -Flutter never calls `Surface.setFrameRate()`. That single missing call is why 120 Hz phones render Flutter at 60 Hz. - -### iOS - -Sets `CADisplayLink.preferredFrameRateRange` with the device max. Validates the `CADisableMinimumFrameDurationOnPhone` plist key at runtime and warns loudly if missing. - -### macOS - -`NSView.displayLink` with `preferredFrameRateRange` on macOS 14+. Falls back to `NSScreen.maximumFramesPerSecond` / `CGDisplayCopyDisplayMode` for query. - -### Windows & Linux - -Query-only via `QueryDisplayConfig` (Win) and `gdk_monitor_get_refresh_rate` (Linux). Control depends on Flutter's desktop embedder evolution — tracked at [#93058](https://github.com/flutter/flutter/issues/93058) and [#183703](https://github.com/flutter/flutter/issues/183703). - ---- - -## API reference - -| Method | What it does | -|:-------|:-------------| -| `enable()` | Unlock peak rate — call once in `main()` | -| `disable()` | Stop overriding, return to OS default | -| `preferMax()` | Request highest available rate | -| `preferDefault()` | Clear rate override | -| `matchContent(fps)` | Sync display cadence to content frame rate | -| `boost(duration)` | Temporary max-rate spike | -| `category(cat)` | Android 15 semantic rate category | -| `setTouchBoost(bool)` | Android 15 touch-driven boost | -| `refresh()` | Reload platform info cache | -| `info` | Cached `RefreshRateInfo` snapshot | -| `isLowPowerMode` | Battery Saver / Low Power Mode active | -| `thermalState` | `ThermalState` enum | -| `isProMotionReady` | iOS plist key + ProMotion hardware | -| `onChanged` | `Stream` | -| `showFPS()` | Live FPS counter overlay | -| `showHz()` | Live Hz badge overlay | -| `showOverlay()` | Full diagnostic overlay | -| `hideOverlay()` | Dismiss overlay | -| `startSession(name)` | Start benchmark session | - ---- - -## Why this exists - -Flutter's engine (Impeller since 3.24) *can* render at 120 Hz. But it never *tells the OS*. On Android, `Surface.setFrameRate()` returns zero search results across the entire engine codebase. On iOS, the engine code is correct but the default template omits the plist key. - -This has been open since January 2023 ([#119268](https://github.com/flutter/flutter/issues/119268)), currently tracked at [#160952](https://github.com/flutter/flutter/issues/160952) (P2, unassigned). - -`refresh_rate` fixes this today on shipping apps, while collecting real-device evidence for an eventual engine-level fix. - ---- - -## License - -BSD 3-Clause © 2026 [Qoder](https://qoder.in) - ---- - -

- Made with care by Qoder · More packages -

diff --git a/third_party/refresh_rate/analysis_options.yaml b/third_party/refresh_rate/analysis_options.yaml deleted file mode 100644 index b0f3c0af..00000000 --- a/third_party/refresh_rate/analysis_options.yaml +++ /dev/null @@ -1,4 +0,0 @@ -include: package:flutter_lints/flutter.yaml -linter: - rules: - - public_member_api_docs diff --git a/third_party/refresh_rate/android/build.gradle b/third_party/refresh_rate/android/build.gradle deleted file mode 100644 index 484f253e..00000000 --- a/third_party/refresh_rate/android/build.gradle +++ /dev/null @@ -1,51 +0,0 @@ -group = "in.qoder.refresh_rate" -version = "1.0-SNAPSHOT" - -buildscript { - ext.kotlin_version = "1.9.22" - repositories { - google() - mavenCentral() - } - - dependencies { - classpath("com.android.tools.build:gradle:8.1.0") - classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version") - } -} - -allprojects { - repositories { - google() - mavenCentral() - } -} - -apply plugin: "com.android.library" -apply plugin: "kotlin-android" - -android { - namespace = "in.qoder.refresh_rate" - compileSdk = 35 - - compileOptions { - sourceCompatibility = JavaVersion.VERSION_1_8 - targetCompatibility = JavaVersion.VERSION_1_8 - } - - kotlinOptions { - jvmTarget = "1.8" - } - - sourceSets { - main.java.srcDirs += "src/main/kotlin" - } - - defaultConfig { - minSdk = 21 - } -} - -dependencies { - implementation("org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version") -} diff --git a/third_party/refresh_rate/android/settings.gradle b/third_party/refresh_rate/android/settings.gradle deleted file mode 100644 index f27361d7..00000000 --- a/third_party/refresh_rate/android/settings.gradle +++ /dev/null @@ -1 +0,0 @@ -rootProject.name = "refresh_rate" diff --git a/third_party/refresh_rate/android/src/main/AndroidManifest.xml b/third_party/refresh_rate/android/src/main/AndroidManifest.xml deleted file mode 100644 index 1e375ae6..00000000 --- a/third_party/refresh_rate/android/src/main/AndroidManifest.xml +++ /dev/null @@ -1,3 +0,0 @@ - - diff --git a/third_party/refresh_rate/android/src/main/kotlin/in/qoder/refresh_rate/RefreshRatePlugin.kt b/third_party/refresh_rate/android/src/main/kotlin/in/qoder/refresh_rate/RefreshRatePlugin.kt deleted file mode 100644 index 596430dd..00000000 --- a/third_party/refresh_rate/android/src/main/kotlin/in/qoder/refresh_rate/RefreshRatePlugin.kt +++ /dev/null @@ -1,248 +0,0 @@ -package `in`.qoder.refresh_rate - -import android.app.Activity -import android.content.Context -import android.hardware.display.DisplayManager -import android.os.Build -import android.os.PowerManager -import android.view.Display -import android.view.Surface -import android.view.View -import android.view.WindowManager -import io.flutter.embedding.engine.plugins.FlutterPlugin -import io.flutter.embedding.engine.plugins.activity.ActivityAware -import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding -import `in`.qoder.refresh_rate.generated.DisplayInfoMessage -import `in`.qoder.refresh_rate.generated.RefreshRateFlutterApi -import `in`.qoder.refresh_rate.generated.RefreshRateHostApi - -class RefreshRatePlugin : FlutterPlugin, ActivityAware, RefreshRateHostApi { - - private var activity: Activity? = null - private var context: Context? = null - private var flutterApi: RefreshRateFlutterApi? = null - private var displayListener: DisplayManager.DisplayListener? = null - - // ─── FlutterPlugin ────────────────────────────────────────── - - override fun onAttachedToEngine(binding: FlutterPlugin.FlutterPluginBinding) { - context = binding.applicationContext - RefreshRateHostApi.setUp(binding.binaryMessenger, this) - flutterApi = RefreshRateFlutterApi(binding.binaryMessenger) - registerDisplayListener() - } - - override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) { - RefreshRateHostApi.setUp(binding.binaryMessenger, null) - unregisterDisplayListener() - flutterApi = null - } - - // ─── ActivityAware ────────────────────────────────────────── - - override fun onAttachedToActivity(binding: ActivityPluginBinding) { activity = binding.activity } - override fun onDetachedFromActivityForConfigChanges() { activity = null } - override fun onReattachedToActivityForConfigChanges(binding: ActivityPluginBinding) { activity = binding.activity } - override fun onDetachedFromActivity() { activity = null } - - // ─── RefreshRateHostApi ───────────────────────────────────── - - override fun getDisplayInfo(): DisplayInfoMessage { - val display = getDisplay() - val currentRate = display?.refreshRate?.toDouble() ?: 60.0 - val modes = display?.supportedModes ?: emptyArray() - val supportedRates = modes.map { it.refreshRate.toDouble() }.distinct().sorted() - val maxRate = supportedRates.maxOrNull() ?: 60.0 - val minRate = supportedRates.minOrNull() ?: 60.0 - val isVRR = (maxRate - minRate > 30) && modes.size <= 4 - val pm = context?.getSystemService(Context.POWER_SERVICE) as? PowerManager - val thermalIndex: Long? = if (Build.VERSION.SDK_INT >= 29) { - when (pm?.currentThermalStatus) { - PowerManager.THERMAL_STATUS_NONE -> 0L - PowerManager.THERMAL_STATUS_LIGHT, PowerManager.THERMAL_STATUS_MODERATE -> 1L - PowerManager.THERMAL_STATUS_SEVERE -> 2L - PowerManager.THERMAL_STATUS_CRITICAL, - PowerManager.THERMAL_STATUS_EMERGENCY, - PowerManager.THERMAL_STATUS_SHUTDOWN -> 3L - else -> null - } - } else null - - // hasArrSupport() is API 36+ — fall back to VRR heuristic for now - val hasArr = isVRR - - return DisplayInfoMessage( - currentRate = currentRate, - maxRate = maxRate, - minRate = minRate, - supportedRates = supportedRates, - isVariableRefreshRate = isVRR, - engineTargetRate = currentRate, - androidApiLevel = Build.VERSION.SDK_INT.toLong(), - isLowPowerMode = pm?.isPowerSaveMode, - thermalStateIndex = thermalIndex, - hasAdaptiveRefreshRate = hasArr, - iosProMotionEnabled = null, - displayServer = null, - monitorCount = null, - ) - } - - override fun enable() = setDeviceDefault() - override fun disable() = resetToDefault() - override fun preferMax() = setDeviceDefault() - override fun preferDefault() = resetToDefault() - - override fun matchContent(fps: Double) { - if (Build.VERSION.SDK_INT >= 30) { - setSurfaceFrameRate(fps.toFloat(), Surface.FRAME_RATE_COMPATIBILITY_FIXED_SOURCE, forceAlways = true) - } else if (Build.VERSION.SDK_INT >= 23) { - setPreferredDisplayMode(fps.toFloat()) - } - } - - override fun boost(durationMs: Long) { - val display = getDisplay() ?: return - val maxRate = display.supportedModes.maxByOrNull { it.refreshRate }?.refreshRate ?: 60f - if (Build.VERSION.SDK_INT >= 35) { - try { activity?.window?.decorView?.setRequestedFrameRate(View.REQUESTED_FRAME_RATE_CATEGORY_HIGH.toFloat()) } catch (_: Exception) {} - } - setSurfaceFrameRate(maxRate, Surface.FRAME_RATE_COMPATIBILITY_DEFAULT, forceAlways = true) - android.os.Handler(android.os.Looper.getMainLooper()).postDelayed({ resetToDefault() }, durationMs) - } - - override fun setCategory(categoryIndex: Long) { - if (Build.VERSION.SDK_INT < 35) { - when (categoryIndex.toInt()) { - 3 -> setDeviceDefault() - 0, 1 -> resetToDefault() - else -> {} - } - return - } - try { - val categoryFloat = when (categoryIndex.toInt()) { - 0 -> 0f - 1 -> View.REQUESTED_FRAME_RATE_CATEGORY_LOW.toFloat() - 2 -> View.REQUESTED_FRAME_RATE_CATEGORY_NORMAL.toFloat() - 3 -> View.REQUESTED_FRAME_RATE_CATEGORY_HIGH.toFloat() - else -> View.REQUESTED_FRAME_RATE_CATEGORY_HIGH.toFloat() - } - activity?.window?.decorView?.setRequestedFrameRate(categoryFloat) - } catch (_: Exception) {} - } - - override fun setTouchBoost(enabled: Boolean) { - if (Build.VERSION.SDK_INT >= 35) { - try { activity?.window?.setFrameRateBoostOnTouchEnabled(enabled) } catch (_: Exception) {} - } - } - - override fun isSupported(): Boolean = Build.VERSION.SDK_INT >= 23 - - // ─── Private helpers ──────────────────────────────────────── - - private fun setDeviceDefault() { - val display = getDisplay() ?: return - val maxRate = display.supportedModes.maxByOrNull { it.refreshRate }?.refreshRate ?: 60f - if (Build.VERSION.SDK_INT >= 35) { - try { - val window = activity?.window - window?.decorView?.setRequestedFrameRate(View.REQUESTED_FRAME_RATE_CATEGORY_HIGH.toFloat()) - window?.setFrameRateBoostOnTouchEnabled(true) - } catch (_: Exception) {} - setSurfaceFrameRate(maxRate, Surface.FRAME_RATE_COMPATIBILITY_DEFAULT) - } else if (Build.VERSION.SDK_INT >= 30) { - setSurfaceFrameRate(maxRate, Surface.FRAME_RATE_COMPATIBILITY_DEFAULT) - } else if (Build.VERSION.SDK_INT >= 23) { - setPreferredDisplayMode(maxRate) - } - } - - private fun resetToDefault() { - if (Build.VERSION.SDK_INT >= 35) { - try { - val window = activity?.window - window?.decorView?.setRequestedFrameRate(0f) - window?.setFrameRateBoostOnTouchEnabled(false) - } catch (_: Exception) {} - setSurfaceFrameRate(0f, Surface.FRAME_RATE_COMPATIBILITY_DEFAULT) - } else if (Build.VERSION.SDK_INT >= 30) { - setSurfaceFrameRate(0f, Surface.FRAME_RATE_COMPATIBILITY_DEFAULT) - } else if (Build.VERSION.SDK_INT >= 23) { - try { - val params = activity?.window?.attributes ?: return - params.preferredDisplayModeId = 0 - activity?.window?.attributes = params - } catch (_: Exception) {} - } - } - - private fun setSurfaceFrameRate(frameRate: Float, compatibility: Int, forceAlways: Boolean = false): Boolean { - if (Build.VERSION.SDK_INT < 30) return false - return try { - val window = activity?.window ?: return false - val strategy = if (Build.VERSION.SDK_INT >= 31) { - if (forceAlways) Surface.CHANGE_FRAME_RATE_ALWAYS - else Surface.CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS - } else -1 - val params = window.attributes - params.preferredRefreshRate = frameRate - val display = getDisplay() - if (display != null && frameRate > 0) { - val targetMode = display.supportedModes - .filter { it.refreshRate >= frameRate - 1f } - .minByOrNull { Math.abs(it.refreshRate - frameRate) } - if (targetMode != null) params.preferredDisplayModeId = targetMode.modeId - } else if (frameRate == 0f) { - params.preferredDisplayModeId = 0 - params.preferredRefreshRate = 0f - } - window.attributes = params - true - } catch (e: Exception) { false } - } - - private fun setPreferredDisplayMode(targetRate: Float): Boolean { - if (Build.VERSION.SDK_INT < 23) return false - return try { - val window = activity?.window ?: return false - val display = getDisplay() ?: return false - val currentMode = display.mode - val targetMode = display.supportedModes - .filter { it.physicalWidth == currentMode.physicalWidth && it.physicalHeight == currentMode.physicalHeight } - .minByOrNull { Math.abs(it.refreshRate - targetRate) } - if (targetMode != null) { - val params = window.attributes - params.preferredDisplayModeId = targetMode.modeId - window.attributes = params - true - } else false - } catch (e: Exception) { false } - } - - private fun registerDisplayListener() { - val dm = context?.getSystemService(Context.DISPLAY_SERVICE) as? DisplayManager ?: return - displayListener = object : DisplayManager.DisplayListener { - override fun onDisplayChanged(displayId: Int) { - activity?.runOnUiThread { flutterApi?.onDisplayInfoChanged(getDisplayInfo()) {} } - } - override fun onDisplayAdded(displayId: Int) {} - override fun onDisplayRemoved(displayId: Int) {} - } - dm.registerDisplayListener(displayListener, null) - } - - private fun unregisterDisplayListener() { - val dm = context?.getSystemService(Context.DISPLAY_SERVICE) as? DisplayManager ?: return - displayListener?.let { dm.unregisterDisplayListener(it) } - displayListener = null - } - - @Suppress("DEPRECATION") - private fun getDisplay(): Display? = if (Build.VERSION.SDK_INT >= 30) { - activity?.display - } else { - (context?.getSystemService(Context.WINDOW_SERVICE) as? WindowManager)?.defaultDisplay - } -} diff --git a/third_party/refresh_rate/android/src/main/kotlin/in/qoder/refresh_rate/generated/RefreshRateApi.kt b/third_party/refresh_rate/android/src/main/kotlin/in/qoder/refresh_rate/generated/RefreshRateApi.kt deleted file mode 100644 index b72597dc..00000000 --- a/third_party/refresh_rate/android/src/main/kotlin/in/qoder/refresh_rate/generated/RefreshRateApi.kt +++ /dev/null @@ -1,345 +0,0 @@ -// Copyright 2026 Qoder (qoder.in). All rights reserved. -// Use of this source code is governed by a BSD-style license. -// Autogenerated from Pigeon (v22.7.4), do not edit directly. -// See also: https://pub.dev/packages/pigeon -@file:Suppress("UNCHECKED_CAST", "ArrayInDataClass") - -package `in`.qoder.refresh_rate.generated - -import android.util.Log -import io.flutter.plugin.common.BasicMessageChannel -import io.flutter.plugin.common.BinaryMessenger -import io.flutter.plugin.common.EventChannel -import io.flutter.plugin.common.MessageCodec -import io.flutter.plugin.common.StandardMethodCodec -import io.flutter.plugin.common.StandardMessageCodec -import java.io.ByteArrayOutputStream -import java.nio.ByteBuffer - -private fun wrapResult(result: Any?): List { - return listOf(result) -} - -private fun wrapError(exception: Throwable): List { - return if (exception is FlutterError) { - listOf( - exception.code, - exception.message, - exception.details - ) - } else { - listOf( - exception.javaClass.simpleName, - exception.toString(), - "Cause: " + exception.cause + ", Stacktrace: " + Log.getStackTraceString(exception) - ) - } -} - -private fun createConnectionError(channelName: String): FlutterError { - return FlutterError("channel-error", "Unable to establish connection on channel: '$channelName'.", "")} - -/** - * Error class for passing custom error details to Flutter via a thrown PlatformException. - * @property code The error code. - * @property message The error message. - * @property details The error details. Must be a datatype supported by the api codec. - */ -class FlutterError ( - val code: String, - override val message: String? = null, - val details: Any? = null -) : Throwable() - -/** Generated class from Pigeon that represents data sent in messages. */ -data class DisplayInfoMessage ( - val currentRate: Double? = null, - val maxRate: Double? = null, - val minRate: Double? = null, - val supportedRates: List? = null, - val isVariableRefreshRate: Boolean? = null, - val engineTargetRate: Double? = null, - val iosProMotionEnabled: Boolean? = null, - val androidApiLevel: Long? = null, - val isLowPowerMode: Boolean? = null, - val thermalStateIndex: Long? = null, - val hasAdaptiveRefreshRate: Boolean? = null, - val displayServer: String? = null, - val monitorCount: Long? = null -) - { - companion object { - fun fromList(pigeonVar_list: List): DisplayInfoMessage { - val currentRate = pigeonVar_list[0] as Double? - val maxRate = pigeonVar_list[1] as Double? - val minRate = pigeonVar_list[2] as Double? - val supportedRates = pigeonVar_list[3] as List? - val isVariableRefreshRate = pigeonVar_list[4] as Boolean? - val engineTargetRate = pigeonVar_list[5] as Double? - val iosProMotionEnabled = pigeonVar_list[6] as Boolean? - val androidApiLevel = pigeonVar_list[7] as Long? - val isLowPowerMode = pigeonVar_list[8] as Boolean? - val thermalStateIndex = pigeonVar_list[9] as Long? - val hasAdaptiveRefreshRate = pigeonVar_list[10] as Boolean? - val displayServer = pigeonVar_list[11] as String? - val monitorCount = pigeonVar_list[12] as Long? - return DisplayInfoMessage(currentRate, maxRate, minRate, supportedRates, isVariableRefreshRate, engineTargetRate, iosProMotionEnabled, androidApiLevel, isLowPowerMode, thermalStateIndex, hasAdaptiveRefreshRate, displayServer, monitorCount) - } - } - fun toList(): List { - return listOf( - currentRate, - maxRate, - minRate, - supportedRates, - isVariableRefreshRate, - engineTargetRate, - iosProMotionEnabled, - androidApiLevel, - isLowPowerMode, - thermalStateIndex, - hasAdaptiveRefreshRate, - displayServer, - monitorCount, - ) - } -} -private open class RefreshRateApiPigeonCodec : StandardMessageCodec() { - override fun readValueOfType(type: Byte, buffer: ByteBuffer): Any? { - return when (type) { - 129.toByte() -> { - return (readValue(buffer) as? List)?.let { - DisplayInfoMessage.fromList(it) - } - } - else -> super.readValueOfType(type, buffer) - } - } - override fun writeValue(stream: ByteArrayOutputStream, value: Any?) { - when (value) { - is DisplayInfoMessage -> { - stream.write(129) - writeValue(stream, value.toList()) - } - else -> super.writeValue(stream, value) - } - } -} - -/** Generated interface from Pigeon that represents a handler of messages from Flutter. */ -interface RefreshRateHostApi { - fun getDisplayInfo(): DisplayInfoMessage - fun enable() - fun disable() - fun preferMax() - fun preferDefault() - fun matchContent(fps: Double) - fun boost(durationMs: Long) - fun setCategory(categoryIndex: Long) - fun setTouchBoost(enabled: Boolean) - fun isSupported(): Boolean - - companion object { - /** The codec used by RefreshRateHostApi. */ - val codec: MessageCodec by lazy { - RefreshRateApiPigeonCodec() - } - /** Sets up an instance of `RefreshRateHostApi` to handle messages through the `binaryMessenger`. */ - @JvmOverloads - fun setUp(binaryMessenger: BinaryMessenger, api: RefreshRateHostApi?, messageChannelSuffix: String = "") { - val separatedMessageChannelSuffix = if (messageChannelSuffix.isNotEmpty()) ".$messageChannelSuffix" else "" - run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.refresh_rate.RefreshRateHostApi.getDisplayInfo$separatedMessageChannelSuffix", codec) - if (api != null) { - channel.setMessageHandler { _, reply -> - val wrapped: List = try { - listOf(api.getDisplayInfo()) - } catch (exception: Throwable) { - wrapError(exception) - } - reply.reply(wrapped) - } - } else { - channel.setMessageHandler(null) - } - } - run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.refresh_rate.RefreshRateHostApi.enable$separatedMessageChannelSuffix", codec) - if (api != null) { - channel.setMessageHandler { _, reply -> - val wrapped: List = try { - api.enable() - listOf(null) - } catch (exception: Throwable) { - wrapError(exception) - } - reply.reply(wrapped) - } - } else { - channel.setMessageHandler(null) - } - } - run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.refresh_rate.RefreshRateHostApi.disable$separatedMessageChannelSuffix", codec) - if (api != null) { - channel.setMessageHandler { _, reply -> - val wrapped: List = try { - api.disable() - listOf(null) - } catch (exception: Throwable) { - wrapError(exception) - } - reply.reply(wrapped) - } - } else { - channel.setMessageHandler(null) - } - } - run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.refresh_rate.RefreshRateHostApi.preferMax$separatedMessageChannelSuffix", codec) - if (api != null) { - channel.setMessageHandler { _, reply -> - val wrapped: List = try { - api.preferMax() - listOf(null) - } catch (exception: Throwable) { - wrapError(exception) - } - reply.reply(wrapped) - } - } else { - channel.setMessageHandler(null) - } - } - run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.refresh_rate.RefreshRateHostApi.preferDefault$separatedMessageChannelSuffix", codec) - if (api != null) { - channel.setMessageHandler { _, reply -> - val wrapped: List = try { - api.preferDefault() - listOf(null) - } catch (exception: Throwable) { - wrapError(exception) - } - reply.reply(wrapped) - } - } else { - channel.setMessageHandler(null) - } - } - run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.refresh_rate.RefreshRateHostApi.matchContent$separatedMessageChannelSuffix", codec) - if (api != null) { - channel.setMessageHandler { message, reply -> - val args = message as List - val fpsArg = args[0] as Double - val wrapped: List = try { - api.matchContent(fpsArg) - listOf(null) - } catch (exception: Throwable) { - wrapError(exception) - } - reply.reply(wrapped) - } - } else { - channel.setMessageHandler(null) - } - } - run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.refresh_rate.RefreshRateHostApi.boost$separatedMessageChannelSuffix", codec) - if (api != null) { - channel.setMessageHandler { message, reply -> - val args = message as List - val durationMsArg = args[0] as Long - val wrapped: List = try { - api.boost(durationMsArg) - listOf(null) - } catch (exception: Throwable) { - wrapError(exception) - } - reply.reply(wrapped) - } - } else { - channel.setMessageHandler(null) - } - } - run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.refresh_rate.RefreshRateHostApi.setCategory$separatedMessageChannelSuffix", codec) - if (api != null) { - channel.setMessageHandler { message, reply -> - val args = message as List - val categoryIndexArg = args[0] as Long - val wrapped: List = try { - api.setCategory(categoryIndexArg) - listOf(null) - } catch (exception: Throwable) { - wrapError(exception) - } - reply.reply(wrapped) - } - } else { - channel.setMessageHandler(null) - } - } - run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.refresh_rate.RefreshRateHostApi.setTouchBoost$separatedMessageChannelSuffix", codec) - if (api != null) { - channel.setMessageHandler { message, reply -> - val args = message as List - val enabledArg = args[0] as Boolean - val wrapped: List = try { - api.setTouchBoost(enabledArg) - listOf(null) - } catch (exception: Throwable) { - wrapError(exception) - } - reply.reply(wrapped) - } - } else { - channel.setMessageHandler(null) - } - } - run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.refresh_rate.RefreshRateHostApi.isSupported$separatedMessageChannelSuffix", codec) - if (api != null) { - channel.setMessageHandler { _, reply -> - val wrapped: List = try { - listOf(api.isSupported()) - } catch (exception: Throwable) { - wrapError(exception) - } - reply.reply(wrapped) - } - } else { - channel.setMessageHandler(null) - } - } - } - } -} -/** Generated class from Pigeon that represents Flutter messages that can be called from Kotlin. */ -class RefreshRateFlutterApi(private val binaryMessenger: BinaryMessenger, private val messageChannelSuffix: String = "") { - companion object { - /** The codec used by RefreshRateFlutterApi. */ - val codec: MessageCodec by lazy { - RefreshRateApiPigeonCodec() - } - } - fun onDisplayInfoChanged(infoArg: DisplayInfoMessage, callback: (Result) -> Unit) -{ - val separatedMessageChannelSuffix = if (messageChannelSuffix.isNotEmpty()) ".$messageChannelSuffix" else "" - val channelName = "dev.flutter.pigeon.refresh_rate.RefreshRateFlutterApi.onDisplayInfoChanged$separatedMessageChannelSuffix" - val channel = BasicMessageChannel(binaryMessenger, channelName, codec) - channel.send(listOf(infoArg)) { - if (it is List<*>) { - if (it.size > 1) { - callback(Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?))) - } else { - callback(Result.success(Unit)) - } - } else { - callback(Result.failure(createConnectionError(channelName))) - } - } - } -} diff --git a/third_party/refresh_rate/example/README.md b/third_party/refresh_rate/example/README.md deleted file mode 100644 index 2a77dc4a..00000000 --- a/third_party/refresh_rate/example/README.md +++ /dev/null @@ -1,17 +0,0 @@ -# refresh_rate_example - -A new Flutter project. - -## Getting Started - -This project is a starting point for a Flutter application. - -A few resources to get you started if this is your first Flutter project: - -- [Learn Flutter](https://docs.flutter.dev/get-started/learn-flutter) -- [Write your first Flutter app](https://docs.flutter.dev/get-started/codelab) -- [Flutter learning resources](https://docs.flutter.dev/reference/learning-resources) - -For help getting started with Flutter development, view the -[online documentation](https://docs.flutter.dev/), which offers tutorials, -samples, guidance on mobile development, and a full API reference. diff --git a/third_party/refresh_rate/example/analysis_options.yaml b/third_party/refresh_rate/example/analysis_options.yaml deleted file mode 100644 index 0d290213..00000000 --- a/third_party/refresh_rate/example/analysis_options.yaml +++ /dev/null @@ -1,28 +0,0 @@ -# This file configures the analyzer, which statically analyzes Dart code to -# check for errors, warnings, and lints. -# -# The issues identified by the analyzer are surfaced in the UI of Dart-enabled -# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be -# invoked from the command line by running `flutter analyze`. - -# The following line activates a set of recommended lints for Flutter apps, -# packages, and plugins designed to encourage good coding practices. -include: package:flutter_lints/flutter.yaml - -linter: - # The lint rules applied to this project can be customized in the - # section below to disable rules from the `package:flutter_lints/flutter.yaml` - # included above or to enable additional rules. A list of all available lints - # and their documentation is published at https://dart.dev/lints. - # - # Instead of disabling a lint rule for the entire project in the - # section below, it can also be suppressed for a single line of code - # or a specific dart file by using the `// ignore: name_of_lint` and - # `// ignore_for_file: name_of_lint` syntax on the line or in the file - # producing the lint. - rules: - # avoid_print: false # Uncomment to disable the `avoid_print` rule - # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule - -# Additional information about this file can be found at -# https://dart.dev/guides/language/analysis-options diff --git a/third_party/refresh_rate/example/android/app/build.gradle.kts b/third_party/refresh_rate/example/android/app/build.gradle.kts deleted file mode 100644 index ea59d5c0..00000000 --- a/third_party/refresh_rate/example/android/app/build.gradle.kts +++ /dev/null @@ -1,44 +0,0 @@ -plugins { - id("com.android.application") - id("kotlin-android") - // The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins. - id("dev.flutter.flutter-gradle-plugin") -} - -android { - namespace = "in.qoder.refresh_rate_example" - compileSdk = flutter.compileSdkVersion - ndkVersion = flutter.ndkVersion - - compileOptions { - sourceCompatibility = JavaVersion.VERSION_17 - targetCompatibility = JavaVersion.VERSION_17 - } - - kotlinOptions { - jvmTarget = JavaVersion.VERSION_17.toString() - } - - defaultConfig { - // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). - applicationId = "in.qoder.refresh_rate_example" - // You can update the following values to match your application needs. - // For more information, see: https://flutter.dev/to/review-gradle-config. - minSdk = flutter.minSdkVersion - targetSdk = flutter.targetSdkVersion - versionCode = flutter.versionCode - versionName = flutter.versionName - } - - buildTypes { - release { - // TODO: Add your own signing config for the release build. - // Signing with the debug keys for now, so `flutter run --release` works. - signingConfig = signingConfigs.getByName("debug") - } - } -} - -flutter { - source = "../.." -} diff --git a/third_party/refresh_rate/example/android/app/src/debug/AndroidManifest.xml b/third_party/refresh_rate/example/android/app/src/debug/AndroidManifest.xml deleted file mode 100644 index 399f6981..00000000 --- a/third_party/refresh_rate/example/android/app/src/debug/AndroidManifest.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - diff --git a/third_party/refresh_rate/example/android/app/src/main/AndroidManifest.xml b/third_party/refresh_rate/example/android/app/src/main/AndroidManifest.xml deleted file mode 100644 index 9d5b4340..00000000 --- a/third_party/refresh_rate/example/android/app/src/main/AndroidManifest.xml +++ /dev/null @@ -1,45 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/third_party/refresh_rate/example/android/app/src/main/kotlin/in/qoder/refresh_rate_example/MainActivity.kt b/third_party/refresh_rate/example/android/app/src/main/kotlin/in/qoder/refresh_rate_example/MainActivity.kt deleted file mode 100644 index 5b5dd1d0..00000000 --- a/third_party/refresh_rate/example/android/app/src/main/kotlin/in/qoder/refresh_rate_example/MainActivity.kt +++ /dev/null @@ -1,5 +0,0 @@ -package `in`.qoder.refresh_rate_example - -import io.flutter.embedding.android.FlutterActivity - -class MainActivity : FlutterActivity() diff --git a/third_party/refresh_rate/example/android/app/src/main/res/drawable-v21/launch_background.xml b/third_party/refresh_rate/example/android/app/src/main/res/drawable-v21/launch_background.xml deleted file mode 100644 index f74085f3..00000000 --- a/third_party/refresh_rate/example/android/app/src/main/res/drawable-v21/launch_background.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - diff --git a/third_party/refresh_rate/example/android/app/src/main/res/drawable/launch_background.xml b/third_party/refresh_rate/example/android/app/src/main/res/drawable/launch_background.xml deleted file mode 100644 index 304732f8..00000000 --- a/third_party/refresh_rate/example/android/app/src/main/res/drawable/launch_background.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - diff --git a/third_party/refresh_rate/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/third_party/refresh_rate/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index db77bb4b..00000000 Binary files a/third_party/refresh_rate/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png and /dev/null differ diff --git a/third_party/refresh_rate/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/third_party/refresh_rate/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index 17987b79..00000000 Binary files a/third_party/refresh_rate/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png and /dev/null differ diff --git a/third_party/refresh_rate/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/third_party/refresh_rate/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index 09d43914..00000000 Binary files a/third_party/refresh_rate/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ diff --git a/third_party/refresh_rate/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/third_party/refresh_rate/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index d5f1c8d3..00000000 Binary files a/third_party/refresh_rate/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ diff --git a/third_party/refresh_rate/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/third_party/refresh_rate/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index 4d6372ee..00000000 Binary files a/third_party/refresh_rate/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ diff --git a/third_party/refresh_rate/example/android/app/src/main/res/values-night/styles.xml b/third_party/refresh_rate/example/android/app/src/main/res/values-night/styles.xml deleted file mode 100644 index 06952be7..00000000 --- a/third_party/refresh_rate/example/android/app/src/main/res/values-night/styles.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - diff --git a/third_party/refresh_rate/example/android/app/src/main/res/values/styles.xml b/third_party/refresh_rate/example/android/app/src/main/res/values/styles.xml deleted file mode 100644 index cb1ef880..00000000 --- a/third_party/refresh_rate/example/android/app/src/main/res/values/styles.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - diff --git a/third_party/refresh_rate/example/android/app/src/profile/AndroidManifest.xml b/third_party/refresh_rate/example/android/app/src/profile/AndroidManifest.xml deleted file mode 100644 index 399f6981..00000000 --- a/third_party/refresh_rate/example/android/app/src/profile/AndroidManifest.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - diff --git a/third_party/refresh_rate/example/android/build.gradle.kts b/third_party/refresh_rate/example/android/build.gradle.kts deleted file mode 100644 index dbee657b..00000000 --- a/third_party/refresh_rate/example/android/build.gradle.kts +++ /dev/null @@ -1,24 +0,0 @@ -allprojects { - repositories { - google() - mavenCentral() - } -} - -val newBuildDir: Directory = - rootProject.layout.buildDirectory - .dir("../../build") - .get() -rootProject.layout.buildDirectory.value(newBuildDir) - -subprojects { - val newSubprojectBuildDir: Directory = newBuildDir.dir(project.name) - project.layout.buildDirectory.value(newSubprojectBuildDir) -} -subprojects { - project.evaluationDependsOn(":app") -} - -tasks.register("clean") { - delete(rootProject.layout.buildDirectory) -} diff --git a/third_party/refresh_rate/example/android/gradle.properties b/third_party/refresh_rate/example/android/gradle.properties deleted file mode 100644 index fbee1d8c..00000000 --- a/third_party/refresh_rate/example/android/gradle.properties +++ /dev/null @@ -1,2 +0,0 @@ -org.gradle.jvmargs=-Xmx8G -XX:MaxMetaspaceSize=4G -XX:ReservedCodeCacheSize=512m -XX:+HeapDumpOnOutOfMemoryError -android.useAndroidX=true diff --git a/third_party/refresh_rate/example/android/gradle/wrapper/gradle-wrapper.properties b/third_party/refresh_rate/example/android/gradle/wrapper/gradle-wrapper.properties deleted file mode 100644 index e4ef43fb..00000000 --- a/third_party/refresh_rate/example/android/gradle/wrapper/gradle-wrapper.properties +++ /dev/null @@ -1,5 +0,0 @@ -distributionBase=GRADLE_USER_HOME -distributionPath=wrapper/dists -zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.14-all.zip diff --git a/third_party/refresh_rate/example/android/settings.gradle.kts b/third_party/refresh_rate/example/android/settings.gradle.kts deleted file mode 100644 index ca7fe065..00000000 --- a/third_party/refresh_rate/example/android/settings.gradle.kts +++ /dev/null @@ -1,26 +0,0 @@ -pluginManagement { - val flutterSdkPath = - run { - val properties = java.util.Properties() - file("local.properties").inputStream().use { properties.load(it) } - val flutterSdkPath = properties.getProperty("flutter.sdk") - require(flutterSdkPath != null) { "flutter.sdk not set in local.properties" } - flutterSdkPath - } - - includeBuild("$flutterSdkPath/packages/flutter_tools/gradle") - - repositories { - google() - mavenCentral() - gradlePluginPortal() - } -} - -plugins { - id("dev.flutter.flutter-plugin-loader") version "1.0.0" - id("com.android.application") version "8.11.1" apply false - id("org.jetbrains.kotlin.android") version "2.2.20" apply false -} - -include(":app") diff --git a/third_party/refresh_rate/example/integration_test/screenshot_test.dart b/third_party/refresh_rate/example/integration_test/screenshot_test.dart deleted file mode 100644 index 610c8c09..00000000 --- a/third_party/refresh_rate/example/integration_test/screenshot_test.dart +++ /dev/null @@ -1,150 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_test/flutter_test.dart'; -import 'package:integration_test/integration_test.dart'; -import 'package:refresh_rate/refresh_rate.dart'; - -import 'package:refresh_rate_example/main.dart'; - -/// Waits for [finder] to match at least one widget, polling every 100 ms. -Future _waitFor( - WidgetTester tester, - Finder finder, { - Duration timeout = const Duration(seconds: 5), -}) async { - final deadline = DateTime.now().add(timeout); - while (!finder.evaluate().isNotEmpty) { - if (DateTime.now().isAfter(deadline)) return; - await tester.pump(const Duration(milliseconds: 100)); - } - await tester.pump(const Duration(milliseconds: 200)); -} - -/// Converts the Flutter surface to an image, pumps one frame, and -/// takes a named screenshot via the integration test binding. -Future _captureScreenshot( - IntegrationTestWidgetsFlutterBinding binding, - WidgetTester tester, - String name, -) async { - await binding.convertFlutterSurfaceToImage(); - await tester.pump(const Duration(milliseconds: 200)); - await binding.takeScreenshot(name); -} - -// ── Mock overlay widgets ───────────────────────────────────────────────────── -// The real FPS overlay shows "0 FPS" during integration tests because -// pump() doesn't generate real frame timings. These mock widgets render -// hardcoded values that represent a realistic 120Hz device scenario. - -/// Mock FPS badge — identical styling to FpsOverlayWidget (showFPS) with -/// a hardcoded value showing a healthy 120 FPS readout. -Widget _mockFpsOverlay() { - return Positioned( - top: 0, - right: 8, - child: SafeArea( - child: Padding( - padding: const EdgeInsets.only(top: 4), - child: IgnorePointer( - child: Material( - type: MaterialType.transparency, - child: Container( - padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), - decoration: BoxDecoration( - color: const Color(0xDD000000), - borderRadius: BorderRadius.circular(6), - ), - child: const Text( - '120 FPS', - style: TextStyle( - color: Color(0xFF4CAF50), // green — hitting target - fontSize: 13, - fontWeight: FontWeight.bold, - fontFeatures: [FontFeature.tabularFigures()], - ), - ), - ), - ), - ), - ), - ), - ); -} - -/// Mock Hz badge — identical styling to HzOverlayWidget. -Widget _mockHzOverlay() { - return Positioned( - top: 0, - right: 8, - child: SafeArea( - child: Padding( - padding: const EdgeInsets.only(top: 4), - child: IgnorePointer( - child: Material( - type: MaterialType.transparency, - child: Container( - padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), - decoration: BoxDecoration( - color: const Color(0xDD000000), - borderRadius: BorderRadius.circular(6), - ), - child: const Text( - '120Hz', - style: TextStyle( - color: Color(0xFF64B5F6), - fontSize: 13, - fontWeight: FontWeight.bold, - fontFeatures: [FontFeature.tabularFigures()], - ), - ), - ), - ), - ), - ), - ), - ); -} - -/// Wraps the example app with a mock overlay [widget] on top. -Widget _appWithOverlay(Widget overlay) { - return Directionality( - textDirection: TextDirection.ltr, - child: Stack( - children: [ - const RefreshRateExampleApp(), - overlay, - ], - ), - ); -} - -void main() { - final binding = IntegrationTestWidgetsFlutterBinding.ensureInitialized(); - - // ── 1. overlay — FPS counter showing 120 FPS in green ──────────────────── - testWidgets('screenshot: fps', (tester) async { - await tester.pumpWidget(_appWithOverlay(_mockFpsOverlay())); - await tester.pump(const Duration(seconds: 1)); - - await _waitFor(tester, find.text('Diagnostic Console')); - - // Enable high refresh so the hero panel shows real 120 Hz data. - RefreshRate.enable(); - await tester.pump(const Duration(seconds: 2)); - - await _captureScreenshot(binding, tester, 'fps'); - }); - - // ── 2. before_after — Hz badge showing 120Hz ──────────────────────────── - testWidgets('screenshot: hz', (tester) async { - await tester.pumpWidget(_appWithOverlay(_mockHzOverlay())); - await tester.pump(const Duration(seconds: 1)); - - await _waitFor(tester, find.text('Diagnostic Console')); - - RefreshRate.enable(); - await tester.pump(const Duration(seconds: 2)); - - await _captureScreenshot(binding, tester, 'hz'); - }); -} diff --git a/third_party/refresh_rate/example/ios/Flutter/AppFrameworkInfo.plist b/third_party/refresh_rate/example/ios/Flutter/AppFrameworkInfo.plist deleted file mode 100644 index 391a902b..00000000 --- a/third_party/refresh_rate/example/ios/Flutter/AppFrameworkInfo.plist +++ /dev/null @@ -1,24 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - App - CFBundleIdentifier - io.flutter.flutter.app - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - App - CFBundlePackageType - FMWK - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - 1.0 - - diff --git a/third_party/refresh_rate/example/ios/Flutter/Debug.xcconfig b/third_party/refresh_rate/example/ios/Flutter/Debug.xcconfig deleted file mode 100644 index ec97fc6f..00000000 --- a/third_party/refresh_rate/example/ios/Flutter/Debug.xcconfig +++ /dev/null @@ -1,2 +0,0 @@ -#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" -#include "Generated.xcconfig" diff --git a/third_party/refresh_rate/example/ios/Flutter/Release.xcconfig b/third_party/refresh_rate/example/ios/Flutter/Release.xcconfig deleted file mode 100644 index c4855bfe..00000000 --- a/third_party/refresh_rate/example/ios/Flutter/Release.xcconfig +++ /dev/null @@ -1,2 +0,0 @@ -#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" -#include "Generated.xcconfig" diff --git a/third_party/refresh_rate/example/ios/Podfile b/third_party/refresh_rate/example/ios/Podfile deleted file mode 100644 index 620e46eb..00000000 --- a/third_party/refresh_rate/example/ios/Podfile +++ /dev/null @@ -1,43 +0,0 @@ -# Uncomment this line to define a global platform for your project -# platform :ios, '13.0' - -# CocoaPods analytics sends network stats synchronously affecting flutter build latency. -ENV['COCOAPODS_DISABLE_STATS'] = 'true' - -project 'Runner', { - 'Debug' => :debug, - 'Profile' => :release, - 'Release' => :release, -} - -def flutter_root - generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__) - unless File.exist?(generated_xcode_build_settings_path) - raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first" - end - - File.foreach(generated_xcode_build_settings_path) do |line| - matches = line.match(/FLUTTER_ROOT\=(.*)/) - return matches[1].strip if matches - end - raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get" -end - -require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) - -flutter_ios_podfile_setup - -target 'Runner' do - use_frameworks! - - flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) - target 'RunnerTests' do - inherit! :search_paths - end -end - -post_install do |installer| - installer.pods_project.targets.each do |target| - flutter_additional_ios_build_settings(target) - end -end diff --git a/third_party/refresh_rate/example/ios/Podfile.lock b/third_party/refresh_rate/example/ios/Podfile.lock deleted file mode 100644 index 7b48a767..00000000 --- a/third_party/refresh_rate/example/ios/Podfile.lock +++ /dev/null @@ -1,28 +0,0 @@ -PODS: - - Flutter (1.0.0) - - integration_test (0.0.1): - - Flutter - - refresh_rate (1.0.2): - - Flutter - -DEPENDENCIES: - - Flutter (from `Flutter`) - - integration_test (from `.symlinks/plugins/integration_test/ios`) - - refresh_rate (from `.symlinks/plugins/refresh_rate/ios`) - -EXTERNAL SOURCES: - Flutter: - :path: Flutter - integration_test: - :path: ".symlinks/plugins/integration_test/ios" - refresh_rate: - :path: ".symlinks/plugins/refresh_rate/ios" - -SPEC CHECKSUMS: - Flutter: cabc95a1d2626b1b06e7179b784ebcf0c0cde467 - integration_test: 252f60fa39af5e17c3aa9899d35d908a0721b573 - refresh_rate: 7b70fe15ba35859a04c4ed7145ef5373073c9498 - -PODFILE CHECKSUM: 3c63482e143d1b91d2d2560aee9fb04ecc74ac7e - -COCOAPODS: 1.16.2 diff --git a/third_party/refresh_rate/example/ios/Runner.xcodeproj/project.pbxproj b/third_party/refresh_rate/example/ios/Runner.xcodeproj/project.pbxproj deleted file mode 100644 index a5d8e17e..00000000 --- a/third_party/refresh_rate/example/ios/Runner.xcodeproj/project.pbxproj +++ /dev/null @@ -1,738 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 54; - objects = { - -/* Begin PBXBuildFile section */ - 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; - 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; }; - 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; - 408442DF8837659AF5CB83DB /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7106237642409D042B52BB66 /* Pods_RunnerTests.framework */; }; - 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; - 7884E8682EC3CC0700C636F2 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7884E8672EC3CC0400C636F2 /* SceneDelegate.swift */; }; - 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; - 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; - 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; - F287BBF60D9D2B9168604931 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D93A38BCF1D017DD70781D7 /* Pods_Runner.framework */; }; -/* End PBXBuildFile section */ - -/* Begin PBXContainerItemProxy section */ - 331C8085294A63A400263BE5 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 97C146E61CF9000F007C117D /* Project object */; - proxyType = 1; - remoteGlobalIDString = 97C146ED1CF9000F007C117D; - remoteInfo = Runner; - }; -/* End PBXContainerItemProxy section */ - -/* Begin PBXCopyFilesBuildPhase section */ - 9705A1C41CF9048500538489 /* Embed Frameworks */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = ""; - dstSubfolderSpec = 10; - files = ( - ); - name = "Embed Frameworks"; - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXCopyFilesBuildPhase section */ - -/* Begin PBXFileReference section */ - 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; - 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; - 1E1F0922F0E206C0A75DF6D6 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; - 331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; - 331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; - 6D93A38BCF1D017DD70781D7 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 6DC24DB3096513F8AA853A09 /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = ""; }; - 7106237642409D042B52BB66 /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 72D8257624B60955295C8C97 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; - 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; - 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; - 7884E8672EC3CC0400C636F2 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; - 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; - 8FD1DB725A5CEDEB0388717B /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; - 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; - 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; - 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; - 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; - 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; - 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - F05CCA270615CA628AE3ACDF /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = ""; }; - F6EABD99D945E14E0AD67068 /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 213E13E82D28B3952759D378 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 408442DF8837659AF5CB83DB /* Pods_RunnerTests.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 97C146EB1CF9000F007C117D /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - F287BBF60D9D2B9168604931 /* Pods_Runner.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 331C8082294A63A400263BE5 /* RunnerTests */ = { - isa = PBXGroup; - children = ( - 331C807B294A618700263BE5 /* RunnerTests.swift */, - ); - path = RunnerTests; - sourceTree = ""; - }; - 8B93923519CFCE8A9F0A16A1 /* Frameworks */ = { - isa = PBXGroup; - children = ( - 6D93A38BCF1D017DD70781D7 /* Pods_Runner.framework */, - 7106237642409D042B52BB66 /* Pods_RunnerTests.framework */, - ); - name = Frameworks; - sourceTree = ""; - }; - 9740EEB11CF90186004384FC /* Flutter */ = { - isa = PBXGroup; - children = ( - 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, - 9740EEB21CF90195004384FC /* Debug.xcconfig */, - 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, - 9740EEB31CF90195004384FC /* Generated.xcconfig */, - ); - name = Flutter; - sourceTree = ""; - }; - 97C146E51CF9000F007C117D = { - isa = PBXGroup; - children = ( - 9740EEB11CF90186004384FC /* Flutter */, - 97C146F01CF9000F007C117D /* Runner */, - 97C146EF1CF9000F007C117D /* Products */, - 331C8082294A63A400263BE5 /* RunnerTests */, - D39C39D29B0F3A68A4AAA3D7 /* Pods */, - 8B93923519CFCE8A9F0A16A1 /* Frameworks */, - ); - sourceTree = ""; - }; - 97C146EF1CF9000F007C117D /* Products */ = { - isa = PBXGroup; - children = ( - 97C146EE1CF9000F007C117D /* Runner.app */, - 331C8081294A63A400263BE5 /* RunnerTests.xctest */, - ); - name = Products; - sourceTree = ""; - }; - 97C146F01CF9000F007C117D /* Runner */ = { - isa = PBXGroup; - children = ( - 97C146FA1CF9000F007C117D /* Main.storyboard */, - 97C146FD1CF9000F007C117D /* Assets.xcassets */, - 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, - 97C147021CF9000F007C117D /* Info.plist */, - 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, - 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, - 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, - 7884E8672EC3CC0400C636F2 /* SceneDelegate.swift */, - 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, - ); - path = Runner; - sourceTree = ""; - }; - D39C39D29B0F3A68A4AAA3D7 /* Pods */ = { - isa = PBXGroup; - children = ( - 8FD1DB725A5CEDEB0388717B /* Pods-Runner.debug.xcconfig */, - 1E1F0922F0E206C0A75DF6D6 /* Pods-Runner.release.xcconfig */, - 72D8257624B60955295C8C97 /* Pods-Runner.profile.xcconfig */, - F6EABD99D945E14E0AD67068 /* Pods-RunnerTests.debug.xcconfig */, - 6DC24DB3096513F8AA853A09 /* Pods-RunnerTests.release.xcconfig */, - F05CCA270615CA628AE3ACDF /* Pods-RunnerTests.profile.xcconfig */, - ); - name = Pods; - path = Pods; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 331C8080294A63A400263BE5 /* RunnerTests */ = { - isa = PBXNativeTarget; - buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; - buildPhases = ( - 1598A1C76FC46748D8686F89 /* [CP] Check Pods Manifest.lock */, - 331C807D294A63A400263BE5 /* Sources */, - 331C807F294A63A400263BE5 /* Resources */, - 213E13E82D28B3952759D378 /* Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - 331C8086294A63A400263BE5 /* PBXTargetDependency */, - ); - name = RunnerTests; - productName = RunnerTests; - productReference = 331C8081294A63A400263BE5 /* RunnerTests.xctest */; - productType = "com.apple.product-type.bundle.unit-test"; - }; - 97C146ED1CF9000F007C117D /* Runner */ = { - isa = PBXNativeTarget; - buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; - buildPhases = ( - 81F4AE0F9E3D19C5B6DFDAD1 /* [CP] Check Pods Manifest.lock */, - 9740EEB61CF901F6004384FC /* Run Script */, - 97C146EA1CF9000F007C117D /* Sources */, - 97C146EB1CF9000F007C117D /* Frameworks */, - 97C146EC1CF9000F007C117D /* Resources */, - 9705A1C41CF9048500538489 /* Embed Frameworks */, - 3B06AD1E1E4923F5004D2608 /* Thin Binary */, - 91C2B0F87759B0619DD56467 /* [CP] Embed Pods Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = Runner; - productName = Runner; - productReference = 97C146EE1CF9000F007C117D /* Runner.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 97C146E61CF9000F007C117D /* Project object */ = { - isa = PBXProject; - attributes = { - BuildIndependentTargetsInParallel = YES; - LastUpgradeCheck = 1510; - ORGANIZATIONNAME = ""; - TargetAttributes = { - 331C8080294A63A400263BE5 = { - CreatedOnToolsVersion = 14.0; - TestTargetID = 97C146ED1CF9000F007C117D; - }; - 97C146ED1CF9000F007C117D = { - CreatedOnToolsVersion = 7.3.1; - LastSwiftMigration = 1100; - }; - }; - }; - buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; - compatibilityVersion = "Xcode 9.3"; - developmentRegion = en; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 97C146E51CF9000F007C117D; - productRefGroup = 97C146EF1CF9000F007C117D /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 97C146ED1CF9000F007C117D /* Runner */, - 331C8080294A63A400263BE5 /* RunnerTests */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 331C807F294A63A400263BE5 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 97C146EC1CF9000F007C117D /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, - 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, - 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, - 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXShellScriptBuildPhase section */ - 1598A1C76FC46748D8686F89 /* [CP] Check Pods Manifest.lock */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; - outputFileListPaths = ( - ); - outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; - showEnvVarsInLog = 0; - }; - 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { - isa = PBXShellScriptBuildPhase; - alwaysOutOfDate = 1; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}", - ); - name = "Thin Binary"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; - }; - 81F4AE0F9E3D19C5B6DFDAD1 /* [CP] Check Pods Manifest.lock */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; - outputFileListPaths = ( - ); - outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; - showEnvVarsInLog = 0; - }; - 91C2B0F87759B0619DD56467 /* [CP] Embed Pods Frameworks */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", - ); - name = "[CP] Embed Pods Frameworks"; - outputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; - showEnvVarsInLog = 0; - }; - 9740EEB61CF901F6004384FC /* Run Script */ = { - isa = PBXShellScriptBuildPhase; - alwaysOutOfDate = 1; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - name = "Run Script"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; - }; -/* End PBXShellScriptBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 331C807D294A63A400263BE5 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 97C146EA1CF9000F007C117D /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, - 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, - 7884E8682EC3CC0700C636F2 /* SceneDelegate.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXTargetDependency section */ - 331C8086294A63A400263BE5 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 97C146ED1CF9000F007C117D /* Runner */; - targetProxy = 331C8085294A63A400263BE5 /* PBXContainerItemProxy */; - }; -/* End PBXTargetDependency section */ - -/* Begin PBXVariantGroup section */ - 97C146FA1CF9000F007C117D /* Main.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 97C146FB1CF9000F007C117D /* Base */, - ); - name = Main.storyboard; - sourceTree = ""; - }; - 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 97C147001CF9000F007C117D /* Base */, - ); - name = LaunchScreen.storyboard; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 249021D3217E4FDB00AE95B9 /* Profile */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; - CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_USER_SCRIPT_SANDBOXING = NO; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 13.0; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = iphoneos; - SUPPORTED_PLATFORMS = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; - name = Profile; - }; - 249021D4217E4FDB00AE95B9 /* Profile */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CLANG_ENABLE_MODULES = YES; - CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; - CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; - DEVELOPMENT_TEAM = ALF7HY2G9Q; - ENABLE_BITCODE = NO; - INFOPLIST_FILE = Runner/Info.plist; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - ); - PRODUCT_BUNDLE_IDENTIFIER = in.qoder.refreshRateExample; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; - SWIFT_VERSION = 5.0; - VERSIONING_SYSTEM = "apple-generic"; - }; - name = Profile; - }; - 331C8088294A63A400263BE5 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = F6EABD99D945E14E0AD67068 /* Pods-RunnerTests.debug.xcconfig */; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; - GENERATE_INFOPLIST_FILE = YES; - MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = in.qoder.refreshRateExample.RunnerTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 5.0; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; - }; - name = Debug; - }; - 331C8089294A63A400263BE5 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 6DC24DB3096513F8AA853A09 /* Pods-RunnerTests.release.xcconfig */; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; - GENERATE_INFOPLIST_FILE = YES; - MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = in.qoder.refreshRateExample.RunnerTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 5.0; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; - }; - name = Release; - }; - 331C808A294A63A400263BE5 /* Profile */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = F05CCA270615CA628AE3ACDF /* Pods-RunnerTests.profile.xcconfig */; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; - GENERATE_INFOPLIST_FILE = YES; - MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = in.qoder.refreshRateExample.RunnerTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 5.0; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; - }; - name = Profile; - }; - 97C147031CF9000F007C117D /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; - CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - ENABLE_USER_SCRIPT_SANDBOXING = NO; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 13.0; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - 97C147041CF9000F007C117D /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; - CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_USER_SCRIPT_SANDBOXING = NO; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 13.0; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = iphoneos; - SUPPORTED_PLATFORMS = iphoneos; - SWIFT_COMPILATION_MODE = wholemodule; - SWIFT_OPTIMIZATION_LEVEL = "-O"; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 97C147061CF9000F007C117D /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CLANG_ENABLE_MODULES = YES; - CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; - CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; - DEVELOPMENT_TEAM = ALF7HY2G9Q; - ENABLE_BITCODE = NO; - INFOPLIST_FILE = Runner/Info.plist; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - ); - PRODUCT_BUNDLE_IDENTIFIER = in.qoder.refreshRateExample; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 5.0; - VERSIONING_SYSTEM = "apple-generic"; - }; - name = Debug; - }; - 97C147071CF9000F007C117D /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CLANG_ENABLE_MODULES = YES; - CODE_SIGN_ENTITLEMENTS = Runner/Release.entitlements; - CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; - DEVELOPMENT_TEAM = ALF7HY2G9Q; - ENABLE_BITCODE = NO; - INFOPLIST_FILE = Runner/Info.plist; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - ); - PRODUCT_BUNDLE_IDENTIFIER = in.qoder.refreshRateExample; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; - SWIFT_VERSION = 5.0; - VERSIONING_SYSTEM = "apple-generic"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 331C8088294A63A400263BE5 /* Debug */, - 331C8089294A63A400263BE5 /* Release */, - 331C808A294A63A400263BE5 /* Profile */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 97C147031CF9000F007C117D /* Debug */, - 97C147041CF9000F007C117D /* Release */, - 249021D3217E4FDB00AE95B9 /* Profile */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 97C147061CF9000F007C117D /* Debug */, - 97C147071CF9000F007C117D /* Release */, - 249021D4217E4FDB00AE95B9 /* Profile */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 97C146E61CF9000F007C117D /* Project object */; -} diff --git a/third_party/refresh_rate/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/third_party/refresh_rate/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index 919434a6..00000000 --- a/third_party/refresh_rate/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,7 +0,0 @@ - - - - - diff --git a/third_party/refresh_rate/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/third_party/refresh_rate/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist deleted file mode 100644 index 18d98100..00000000 --- a/third_party/refresh_rate/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +++ /dev/null @@ -1,8 +0,0 @@ - - - - - IDEDidComputeMac32BitWarning - - - diff --git a/third_party/refresh_rate/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/third_party/refresh_rate/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings deleted file mode 100644 index f9b0d7c5..00000000 --- a/third_party/refresh_rate/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings +++ /dev/null @@ -1,8 +0,0 @@ - - - - - PreviewsEnabled - - - diff --git a/third_party/refresh_rate/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/third_party/refresh_rate/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme deleted file mode 100644 index e3773d42..00000000 --- a/third_party/refresh_rate/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ /dev/null @@ -1,101 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/third_party/refresh_rate/example/ios/Runner.xcworkspace/contents.xcworkspacedata b/third_party/refresh_rate/example/ios/Runner.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index 21a3cc14..00000000 --- a/third_party/refresh_rate/example/ios/Runner.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - diff --git a/third_party/refresh_rate/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/third_party/refresh_rate/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist deleted file mode 100644 index 18d98100..00000000 --- a/third_party/refresh_rate/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +++ /dev/null @@ -1,8 +0,0 @@ - - - - - IDEDidComputeMac32BitWarning - - - diff --git a/third_party/refresh_rate/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/third_party/refresh_rate/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings deleted file mode 100644 index f9b0d7c5..00000000 --- a/third_party/refresh_rate/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings +++ /dev/null @@ -1,8 +0,0 @@ - - - - - PreviewsEnabled - - - diff --git a/third_party/refresh_rate/example/ios/Runner/AppDelegate.swift b/third_party/refresh_rate/example/ios/Runner/AppDelegate.swift deleted file mode 100644 index c30b367e..00000000 --- a/third_party/refresh_rate/example/ios/Runner/AppDelegate.swift +++ /dev/null @@ -1,16 +0,0 @@ -import Flutter -import UIKit - -@main -@objc class AppDelegate: FlutterAppDelegate, FlutterImplicitEngineDelegate { - override func application( - _ application: UIApplication, - didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? - ) -> Bool { - return super.application(application, didFinishLaunchingWithOptions: launchOptions) - } - - func didInitializeImplicitFlutterEngine(_ engineBridge: FlutterImplicitEngineBridge) { - GeneratedPluginRegistrant.register(with: engineBridge.pluginRegistry) - } -} diff --git a/third_party/refresh_rate/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/third_party/refresh_rate/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index d36b1fab..00000000 --- a/third_party/refresh_rate/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,122 +0,0 @@ -{ - "images" : [ - { - "size" : "20x20", - "idiom" : "iphone", - "filename" : "Icon-App-20x20@2x.png", - "scale" : "2x" - }, - { - "size" : "20x20", - "idiom" : "iphone", - "filename" : "Icon-App-20x20@3x.png", - "scale" : "3x" - }, - { - "size" : "29x29", - "idiom" : "iphone", - "filename" : "Icon-App-29x29@1x.png", - "scale" : "1x" - }, - { - "size" : "29x29", - "idiom" : "iphone", - "filename" : "Icon-App-29x29@2x.png", - "scale" : "2x" - }, - { - "size" : "29x29", - "idiom" : "iphone", - "filename" : "Icon-App-29x29@3x.png", - "scale" : "3x" - }, - { - "size" : "40x40", - "idiom" : "iphone", - "filename" : "Icon-App-40x40@2x.png", - "scale" : "2x" - }, - { - "size" : "40x40", - "idiom" : "iphone", - "filename" : "Icon-App-40x40@3x.png", - "scale" : "3x" - }, - { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "Icon-App-60x60@2x.png", - "scale" : "2x" - }, - { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "Icon-App-60x60@3x.png", - "scale" : "3x" - }, - { - "size" : "20x20", - "idiom" : "ipad", - "filename" : "Icon-App-20x20@1x.png", - "scale" : "1x" - }, - { - "size" : "20x20", - "idiom" : "ipad", - "filename" : "Icon-App-20x20@2x.png", - "scale" : "2x" - }, - { - "size" : "29x29", - "idiom" : "ipad", - "filename" : "Icon-App-29x29@1x.png", - "scale" : "1x" - }, - { - "size" : "29x29", - "idiom" : "ipad", - "filename" : "Icon-App-29x29@2x.png", - "scale" : "2x" - }, - { - "size" : "40x40", - "idiom" : "ipad", - "filename" : "Icon-App-40x40@1x.png", - "scale" : "1x" - }, - { - "size" : "40x40", - "idiom" : "ipad", - "filename" : "Icon-App-40x40@2x.png", - "scale" : "2x" - }, - { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "Icon-App-76x76@1x.png", - "scale" : "1x" - }, - { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "Icon-App-76x76@2x.png", - "scale" : "2x" - }, - { - "size" : "83.5x83.5", - "idiom" : "ipad", - "filename" : "Icon-App-83.5x83.5@2x.png", - "scale" : "2x" - }, - { - "size" : "1024x1024", - "idiom" : "ios-marketing", - "filename" : "Icon-App-1024x1024@1x.png", - "scale" : "1x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} diff --git a/third_party/refresh_rate/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/third_party/refresh_rate/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png deleted file mode 100644 index dc9ada47..00000000 Binary files a/third_party/refresh_rate/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png and /dev/null differ diff --git a/third_party/refresh_rate/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png b/third_party/refresh_rate/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png deleted file mode 100644 index 7353c41e..00000000 Binary files a/third_party/refresh_rate/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png and /dev/null differ diff --git a/third_party/refresh_rate/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png b/third_party/refresh_rate/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png deleted file mode 100644 index 797d452e..00000000 Binary files a/third_party/refresh_rate/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png and /dev/null differ diff --git a/third_party/refresh_rate/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/third_party/refresh_rate/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png deleted file mode 100644 index 6ed2d933..00000000 Binary files a/third_party/refresh_rate/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png and /dev/null differ diff --git a/third_party/refresh_rate/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png b/third_party/refresh_rate/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png deleted file mode 100644 index 4cd7b009..00000000 Binary files a/third_party/refresh_rate/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png and /dev/null differ diff --git a/third_party/refresh_rate/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/third_party/refresh_rate/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png deleted file mode 100644 index fe730945..00000000 Binary files a/third_party/refresh_rate/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png and /dev/null differ diff --git a/third_party/refresh_rate/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png b/third_party/refresh_rate/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png deleted file mode 100644 index 321773cd..00000000 Binary files a/third_party/refresh_rate/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png and /dev/null differ diff --git a/third_party/refresh_rate/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png b/third_party/refresh_rate/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png deleted file mode 100644 index 797d452e..00000000 Binary files a/third_party/refresh_rate/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png and /dev/null differ diff --git a/third_party/refresh_rate/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/third_party/refresh_rate/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png deleted file mode 100644 index 502f463a..00000000 Binary files a/third_party/refresh_rate/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png and /dev/null differ diff --git a/third_party/refresh_rate/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/third_party/refresh_rate/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png deleted file mode 100644 index 0ec30343..00000000 Binary files a/third_party/refresh_rate/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png and /dev/null differ diff --git a/third_party/refresh_rate/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/third_party/refresh_rate/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png deleted file mode 100644 index 0ec30343..00000000 Binary files a/third_party/refresh_rate/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png and /dev/null differ diff --git a/third_party/refresh_rate/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/third_party/refresh_rate/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png deleted file mode 100644 index e9f5fea2..00000000 Binary files a/third_party/refresh_rate/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png and /dev/null differ diff --git a/third_party/refresh_rate/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/third_party/refresh_rate/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png deleted file mode 100644 index 84ac32ae..00000000 Binary files a/third_party/refresh_rate/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png and /dev/null differ diff --git a/third_party/refresh_rate/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png b/third_party/refresh_rate/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png deleted file mode 100644 index 8953cba0..00000000 Binary files a/third_party/refresh_rate/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png and /dev/null differ diff --git a/third_party/refresh_rate/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png b/third_party/refresh_rate/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png deleted file mode 100644 index 0467bf12..00000000 Binary files a/third_party/refresh_rate/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png and /dev/null differ diff --git a/third_party/refresh_rate/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json b/third_party/refresh_rate/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json deleted file mode 100644 index 0bedcf2f..00000000 --- a/third_party/refresh_rate/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "filename" : "LaunchImage.png", - "scale" : "1x" - }, - { - "idiom" : "universal", - "filename" : "LaunchImage@2x.png", - "scale" : "2x" - }, - { - "idiom" : "universal", - "filename" : "LaunchImage@3x.png", - "scale" : "3x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} diff --git a/third_party/refresh_rate/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png b/third_party/refresh_rate/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png deleted file mode 100644 index 9da19eac..00000000 Binary files a/third_party/refresh_rate/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png and /dev/null differ diff --git a/third_party/refresh_rate/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png b/third_party/refresh_rate/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png deleted file mode 100644 index 9da19eac..00000000 Binary files a/third_party/refresh_rate/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png and /dev/null differ diff --git a/third_party/refresh_rate/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png b/third_party/refresh_rate/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png deleted file mode 100644 index 9da19eac..00000000 Binary files a/third_party/refresh_rate/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png and /dev/null differ diff --git a/third_party/refresh_rate/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md b/third_party/refresh_rate/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md deleted file mode 100644 index 89c2725b..00000000 --- a/third_party/refresh_rate/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# Launch Screen Assets - -You can customize the launch screen with your own desired assets by replacing the image files in this directory. - -You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. \ No newline at end of file diff --git a/third_party/refresh_rate/example/ios/Runner/Base.lproj/LaunchScreen.storyboard b/third_party/refresh_rate/example/ios/Runner/Base.lproj/LaunchScreen.storyboard deleted file mode 100644 index f2e259c7..00000000 --- a/third_party/refresh_rate/example/ios/Runner/Base.lproj/LaunchScreen.storyboard +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/third_party/refresh_rate/example/ios/Runner/Base.lproj/Main.storyboard b/third_party/refresh_rate/example/ios/Runner/Base.lproj/Main.storyboard deleted file mode 100644 index f3c28516..00000000 --- a/third_party/refresh_rate/example/ios/Runner/Base.lproj/Main.storyboard +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/third_party/refresh_rate/example/ios/Runner/DebugProfile.entitlements b/third_party/refresh_rate/example/ios/Runner/DebugProfile.entitlements deleted file mode 100644 index 23c52e48..00000000 --- a/third_party/refresh_rate/example/ios/Runner/DebugProfile.entitlements +++ /dev/null @@ -1,12 +0,0 @@ - - - - - com.apple.security.app-sandbox - - com.apple.security.cs.allow-jit - - get-task-allow - - - diff --git a/third_party/refresh_rate/example/ios/Runner/Info.plist b/third_party/refresh_rate/example/ios/Runner/Info.plist deleted file mode 100644 index 1711d1be..00000000 --- a/third_party/refresh_rate/example/ios/Runner/Info.plist +++ /dev/null @@ -1,70 +0,0 @@ - - - - - CADisableMinimumFrameDurationOnPhone - - CFBundleDevelopmentRegion - $(DEVELOPMENT_LANGUAGE) - CFBundleDisplayName - Refresh Rate Example - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - refresh_rate_example - CFBundlePackageType - APPL - CFBundleShortVersionString - $(FLUTTER_BUILD_NAME) - CFBundleSignature - ???? - CFBundleVersion - $(FLUTTER_BUILD_NUMBER) - LSRequiresIPhoneOS - - UIApplicationSceneManifest - - UIApplicationSupportsMultipleScenes - - UISceneConfigurations - - UIWindowSceneSessionRoleApplication - - - UISceneClassName - UIWindowScene - UISceneConfigurationName - flutter - UISceneDelegateClassName - $(PRODUCT_MODULE_NAME).SceneDelegate - UISceneStoryboardFile - Main - - - - - UIApplicationSupportsIndirectInputEvents - - UILaunchStoryboardName - LaunchScreen - UIMainStoryboardFile - Main - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UISupportedInterfaceOrientations~ipad - - UIInterfaceOrientationPortrait - UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - - diff --git a/third_party/refresh_rate/example/ios/Runner/Release.entitlements b/third_party/refresh_rate/example/ios/Runner/Release.entitlements deleted file mode 100644 index e89b7f32..00000000 --- a/third_party/refresh_rate/example/ios/Runner/Release.entitlements +++ /dev/null @@ -1,8 +0,0 @@ - - - - - com.apple.security.app-sandbox - - - diff --git a/third_party/refresh_rate/example/ios/Runner/Runner-Bridging-Header.h b/third_party/refresh_rate/example/ios/Runner/Runner-Bridging-Header.h deleted file mode 100644 index 308a2a56..00000000 --- a/third_party/refresh_rate/example/ios/Runner/Runner-Bridging-Header.h +++ /dev/null @@ -1 +0,0 @@ -#import "GeneratedPluginRegistrant.h" diff --git a/third_party/refresh_rate/example/ios/Runner/SceneDelegate.swift b/third_party/refresh_rate/example/ios/Runner/SceneDelegate.swift deleted file mode 100644 index b9ce8ea2..00000000 --- a/third_party/refresh_rate/example/ios/Runner/SceneDelegate.swift +++ /dev/null @@ -1,6 +0,0 @@ -import Flutter -import UIKit - -class SceneDelegate: FlutterSceneDelegate { - -} diff --git a/third_party/refresh_rate/example/ios/RunnerTests/RunnerTests.swift b/third_party/refresh_rate/example/ios/RunnerTests/RunnerTests.swift deleted file mode 100644 index 86a7c3b1..00000000 --- a/third_party/refresh_rate/example/ios/RunnerTests/RunnerTests.swift +++ /dev/null @@ -1,12 +0,0 @@ -import Flutter -import UIKit -import XCTest - -class RunnerTests: XCTestCase { - - func testExample() { - // If you add code to the Runner application, consider adding tests here. - // See https://developer.apple.com/documentation/xctest for more information about using XCTest. - } - -} diff --git a/third_party/refresh_rate/example/lib/main.dart b/third_party/refresh_rate/example/lib/main.dart deleted file mode 100644 index f23c8c97..00000000 --- a/third_party/refresh_rate/example/lib/main.dart +++ /dev/null @@ -1,11 +0,0 @@ -import 'package:flutter/widgets.dart'; -import 'package:refresh_rate/refresh_rate.dart'; - -import 'src/example_app.dart'; -export 'src/example_app.dart'; - -void main() { - WidgetsFlutterBinding.ensureInitialized(); - RefreshRate.enable(); - runApp(const RefreshRateExampleApp()); -} diff --git a/third_party/refresh_rate/example/lib/src/example_app.dart b/third_party/refresh_rate/example/lib/src/example_app.dart deleted file mode 100644 index 06fb3ba0..00000000 --- a/third_party/refresh_rate/example/lib/src/example_app.dart +++ /dev/null @@ -1,18 +0,0 @@ -import 'package:flutter/material.dart'; - -import 'example_home.dart'; -import 'example_theme.dart'; - -class RefreshRateExampleApp extends StatelessWidget { - const RefreshRateExampleApp({super.key}); - - @override - Widget build(BuildContext context) { - return MaterialApp( - title: 'refresh_rate example', - debugShowCheckedModeBanner: false, - theme: buildExampleTheme(), - home: const ExampleHome(), - ); - } -} diff --git a/third_party/refresh_rate/example/lib/src/example_home.dart b/third_party/refresh_rate/example/lib/src/example_home.dart deleted file mode 100644 index 7b9fe61c..00000000 --- a/third_party/refresh_rate/example/lib/src/example_home.dart +++ /dev/null @@ -1,422 +0,0 @@ -import 'dart:async'; - -import 'package:flutter/material.dart'; -import 'package:refresh_rate/refresh_rate.dart'; - -import 'models/action_spec.dart'; -import 'models/info_item.dart'; -import 'sections/action_panel.dart'; -import 'sections/benchmark_panel.dart'; -import 'sections/display_info_panel.dart'; -import 'sections/hero_panel.dart'; -import 'sections/scroll_test_panel.dart'; -import 'sections/status_panel.dart'; - -class ExampleHome extends StatefulWidget { - const ExampleHome({super.key}); - - @override - State createState() => _ExampleHomeState(); -} - -class _ExampleHomeState extends State { - RefreshRateSession? _session; - SessionReport? _lastReport; - String _status = 'System nominal'; - StreamSubscription? _infoSubscription; - - @override - void initState() { - super.initState(); - _infoSubscription = RefreshRate.onChanged.listen((_) { - if (mounted) setState(() {}); - }); - RefreshRate.refresh().then((_) { - if (mounted) setState(() {}); - }); - } - - @override - void dispose() { - _infoSubscription?.cancel(); - super.dispose(); - } - - @override - Widget build(BuildContext context) { - final info = RefreshRate.info; - final width = MediaQuery.sizeOf(context).width; - final wideLayout = width >= 1040; - final largeHero = width >= 760; - final frameBudgetMs = info.currentRate > 0 ? 1000 / info.currentRate : 0.0; - final maxBudgetMs = info.maxRate > 0 ? 1000 / info.maxRate : 0.0; - final supportedRatesText = _supportedRatesText(info); - final liveStateColor = _liveStateColor(context, info); - - final displayInfoItems = [ - InfoItem('Current rate', '${info.currentRate.toStringAsFixed(1)} Hz'), - InfoItem('Max rate', '${info.maxRate.toStringAsFixed(1)} Hz'), - InfoItem('Min rate', '${info.minRate.toStringAsFixed(1)} Hz'), - InfoItem('Supported rates', supportedRatesText), - InfoItem('VRR / LTPO', info.isVariableRefreshRate ? 'Yes' : 'No'), - InfoItem( - 'ProMotion ready', - RefreshRate.isProMotionReady ? 'Ready' : 'Unavailable', - ), - InfoItem( - 'Low power mode', - RefreshRate.isLowPowerMode ? 'Enabled' : 'Off', - ), - InfoItem('Thermal state', RefreshRate.thermalState.name), - InfoItem('Android API', '${info.androidApiLevel ?? 'n/a'}'), - InfoItem('Display server', info.displayServer ?? 'n/a'), - InfoItem('Monitor count', '${info.monitorCount}'), - InfoItem( - 'Engine target', '${info.engineTargetRate.toStringAsFixed(1)} Hz'), - ]; - - return Scaffold( - body: DecoratedBox( - decoration: const BoxDecoration( - gradient: LinearGradient( - begin: Alignment.topCenter, - end: Alignment.bottomCenter, - colors: [Color(0xFF151515), Color(0xFF101010), Color(0xFF131313)], - ), - ), - child: SafeArea( - child: SingleChildScrollView( - padding: EdgeInsets.fromLTRB(16, 12, 16, width >= 760 ? 24 : 16), - child: Center( - child: ConstrainedBox( - constraints: const BoxConstraints(maxWidth: 1320), - child: wideLayout - ? Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Expanded( - flex: 7, - child: Column( - children: [ - HeroPanel( - info: info, - status: _status, - frameBudgetMs: frameBudgetMs, - maxBudgetMs: maxBudgetMs, - liveStateColor: liveStateColor, - largeHero: largeHero, - supportedRatesText: supportedRatesText, - ), - const SizedBox(height: 16), - DisplayInfoPanel(items: displayInfoItems), - const SizedBox(height: 16), - ActionPanel( - eyebrow: 'Control', - title: 'Rate Requests', - subtitle: - 'Exercise the plugin APIs directly and verify device behavior against the live telemetry above.', - actions: _controlActions(), - ), - const SizedBox(height: 16), - ScrollTestPanel(info: info), - ], - ), - ), - const SizedBox(width: 16), - Expanded( - flex: 4, - child: Column( - children: [ - ActionPanel( - eyebrow: 'Overlay', - title: 'Verification HUD', - subtitle: - 'Toggle lightweight or full in-app overlays to validate frame pacing without leaving the example app.', - actions: _overlayActions(), - footer: _overlayFooter(), - ), - const SizedBox(height: 16), - BenchmarkPanel( - actions: _benchmarkActions(), - reportItems: _lastReport == null - ? null - : _reportItems(_lastReport!), - ), - const SizedBox(height: 16), - StatusPanel(status: _status), - ], - ), - ), - ], - ) - : Column( - children: [ - HeroPanel( - info: info, - status: _status, - frameBudgetMs: frameBudgetMs, - maxBudgetMs: maxBudgetMs, - liveStateColor: liveStateColor, - largeHero: largeHero, - supportedRatesText: supportedRatesText, - ), - const SizedBox(height: 16), - DisplayInfoPanel(items: displayInfoItems), - const SizedBox(height: 16), - ActionPanel( - eyebrow: 'Control', - title: 'Rate Requests', - subtitle: - 'Exercise the plugin APIs directly and verify device behavior against the live telemetry above.', - actions: _controlActions(), - ), - const SizedBox(height: 16), - ActionPanel( - eyebrow: 'Overlay', - title: 'Verification HUD', - subtitle: - 'Toggle lightweight or full in-app overlays to validate frame pacing without leaving the example app.', - actions: _overlayActions(), - footer: _overlayFooter(), - ), - const SizedBox(height: 16), - BenchmarkPanel( - actions: _benchmarkActions(), - reportItems: _lastReport == null - ? null - : _reportItems(_lastReport!), - ), - const SizedBox(height: 16), - ScrollTestPanel(info: info), - const SizedBox(height: 16), - StatusPanel(status: _status), - ], - ), - ), - ), - ), - ), - ), - ); - } - - List _controlActions() { - return [ - ActionSpec( - label: 'ENABLE', - accent: const Color(0xFF36FF8B), - outlined: false, - onTap: () { - RefreshRate.enable(); - _setStatus('Peak mode requested'); - }, - ), - ActionSpec( - label: 'DISABLE', - accent: const Color(0xFFFFBA20), - outlined: true, - onTap: () { - RefreshRate.disable(); - _setStatus('Requests cleared'); - }, - ), - ActionSpec( - label: 'PREFER MAX', - accent: const Color(0xFF00F0FF), - outlined: true, - onTap: () { - RefreshRate.preferMax(); - _setStatus('Maximum refresh preferred'); - }, - ), - ActionSpec( - label: 'DEFAULT', - accent: const Color(0xFFB9CACB), - outlined: true, - onTap: () { - RefreshRate.preferDefault(); - _setStatus('OS-managed default restored'); - }, - ), - ActionSpec( - label: 'MATCH 24FPS', - accent: const Color(0xFF00F0FF), - outlined: false, - onTap: () { - RefreshRate.matchContent(24.0); - _setStatus('Matched content to 24fps cadence'); - }, - ), - ActionSpec( - label: 'BOOST 3S', - accent: const Color(0xFFFFBA20), - outlined: false, - onTap: () { - RefreshRate.boost(const Duration(seconds: 3)); - _setStatus('Temporary boost active for 3 seconds'); - }, - ), - ActionSpec( - label: 'CATEGORY HIGH', - accent: const Color(0xFF36FF8B), - outlined: true, - onTap: () { - RefreshRate.category(RateCategory.high); - _setStatus('Android category set to high'); - }, - ), - ActionSpec( - label: 'TOUCH BOOST', - accent: const Color(0xFF00F0FF), - outlined: true, - onTap: () { - RefreshRate.setTouchBoost(true); - _setStatus('Touch boost enabled'); - }, - ), - ]; - } - - List _overlayActions() { - return [ - ActionSpec( - label: 'SHOW FPS', - accent: const Color(0xFF00F0FF), - outlined: true, - onTap: () { - RefreshRate.showFPS(); - _setStatus('FPS overlay shown'); - }, - ), - ActionSpec( - label: 'SHOW HZ', - accent: const Color(0xFF36FF8B), - outlined: true, - onTap: () { - RefreshRate.showHz(); - _setStatus('Hz overlay shown'); - }, - ), - ActionSpec( - label: 'FULL OVERLAY', - accent: const Color(0xFFFFBA20), - outlined: false, - onTap: () { - RefreshRate.showOverlay(); - _setStatus('Full overlay mounted'); - }, - ), - ActionSpec( - label: 'HIDE', - accent: const Color(0xFFB9CACB), - outlined: true, - onTap: () { - RefreshRate.hideOverlay(); - _setStatus('Overlay hidden'); - }, - ), - ]; - } - - List _benchmarkActions() { - return [ - ActionSpec( - label: _session == null ? 'START SESSION' : 'SESSION ACTIVE', - accent: const Color(0xFF36FF8B), - outlined: _session != null, - onTap: _session == null - ? () { - setState(() { - _session = RefreshRate.startSession('example_scroll'); - _status = 'Benchmark session running'; - }); - } - : null, - ), - ActionSpec( - label: 'END SESSION', - accent: const Color(0xFFFFBA20), - outlined: true, - onTap: _session == null - ? null - : () async { - final activeSession = _session; - if (activeSession == null) return; - final report = await activeSession.end(); - if (!mounted) return; - setState(() { - _lastReport = report; - _session = null; - _status = 'Session ended: ${report.verdict.name}'; - }); - }, - ), - ]; - } - - Widget _overlayFooter() { - return Container( - padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 12), - decoration: BoxDecoration( - color: const Color(0xFF0E0E0E), - borderRadius: BorderRadius.circular(14), - ), - child: Row( - children: [ - Container( - width: 9, - height: 9, - decoration: BoxDecoration( - color: RefreshRate.isOverlayVisible - ? const Color(0xFF36FF8B) - : const Color(0xFF3B494B), - shape: BoxShape.circle, - ), - ), - const SizedBox(width: 10), - Text( - RefreshRate.isOverlayVisible - ? 'Overlay currently visible' - : 'Overlay currently hidden', - style: const TextStyle( - color: Color(0xFFB9CACB), - ), - ), - ], - ), - ); - } - - List _reportItems(SessionReport report) { - return [ - InfoItem('Verdict', report.verdict.name), - InfoItem('Bottleneck', report.likelyBottleneck.name), - InfoItem('Avg FPS', report.avgFps.toStringAsFixed(1)), - InfoItem('1% Low', report.onePercentLowFps.toStringAsFixed(1)), - InfoItem( - 'Missed frames', '${report.missedFramePercent.toStringAsFixed(1)}%'), - InfoItem('Valid duration', '${report.validDuration.inMilliseconds} ms'), - InfoItem('Excluded', '${report.excludedDuration.inMilliseconds} ms'), - ]; - } - - void _setStatus(String value) => setState(() => _status = value); - - String _supportedRatesText(DisplayInfo info) { - if (info.supportedRates.isEmpty) return 'n/a'; - return info.supportedRates - .map((rate) => '${rate.toStringAsFixed(0)}Hz') - .join(' • '); - } - - Color _liveStateColor(BuildContext context, DisplayInfo info) { - if (RefreshRate.isLowPowerMode) return const Color(0xFFFFBA20); - if (RefreshRate.thermalState.name != 'nominal') { - return const Color(0xFFFFBA20); - } - if (info.currentRate >= info.maxRate && info.maxRate > 0) { - return const Color(0xFF36FF8B); - } - return Theme.of(context).colorScheme.primary; - } -} diff --git a/third_party/refresh_rate/example/lib/src/example_theme.dart b/third_party/refresh_rate/example/lib/src/example_theme.dart deleted file mode 100644 index 709d0b45..00000000 --- a/third_party/refresh_rate/example/lib/src/example_theme.dart +++ /dev/null @@ -1,82 +0,0 @@ -import 'package:flutter/material.dart'; - -ThemeData buildExampleTheme() { - const base = Color(0xFF131313); - const panelHigh = Color(0xFF2A2A2A); - const cyan = Color(0xFF00F0FF); - const emerald = Color(0xFF36FF8B); - const amber = Color(0xFFFFBA20); - const text = Color(0xFFE5E2E1); - const muted = Color(0xFFB9CACB); - - final scheme = const ColorScheme.dark( - brightness: Brightness.dark, - surface: base, - primary: cyan, - secondary: emerald, - tertiary: amber, - onSurface: text, - onPrimary: Color(0xFF00363A), - onSecondary: Color(0xFF003919), - onTertiary: Color(0xFF412D00), - outline: Color(0xFF3B494B), - ); - - return ThemeData( - useMaterial3: true, - colorScheme: scheme, - scaffoldBackgroundColor: base, - canvasColor: base, - textTheme: ThemeData.dark().textTheme.apply( - bodyColor: text, - displayColor: text, - ), - chipTheme: ChipThemeData( - backgroundColor: panelHigh, - selectedColor: cyan.withValues(alpha: 0.16), - side: BorderSide.none, - labelStyle: const TextStyle( - color: text, - fontSize: 11, - fontWeight: FontWeight.w600, - letterSpacing: 0.3, - ), - padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 6), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(10), - ), - ), - filledButtonTheme: FilledButtonThemeData( - style: FilledButton.styleFrom( - backgroundColor: panelHigh, - foregroundColor: text, - elevation: 0, - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 14), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(14), - ), - textStyle: const TextStyle( - fontSize: 12, - fontWeight: FontWeight.w700, - letterSpacing: 0.8, - ), - ), - ), - outlinedButtonTheme: OutlinedButtonThemeData( - style: OutlinedButton.styleFrom( - foregroundColor: text, - side: BorderSide(color: cyan.withValues(alpha: 0.38)), - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 14), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(14), - ), - textStyle: const TextStyle( - fontSize: 12, - fontWeight: FontWeight.w700, - letterSpacing: 0.8, - ), - ), - ), - dividerColor: muted.withValues(alpha: 0.08), - ); -} diff --git a/third_party/refresh_rate/example/lib/src/models/action_spec.dart b/third_party/refresh_rate/example/lib/src/models/action_spec.dart deleted file mode 100644 index a467a437..00000000 --- a/third_party/refresh_rate/example/lib/src/models/action_spec.dart +++ /dev/null @@ -1,15 +0,0 @@ -import 'package:flutter/material.dart'; - -class ActionSpec { - const ActionSpec({ - required this.label, - required this.accent, - required this.outlined, - required this.onTap, - }); - - final String label; - final Color accent; - final bool outlined; - final VoidCallback? onTap; -} diff --git a/third_party/refresh_rate/example/lib/src/models/info_item.dart b/third_party/refresh_rate/example/lib/src/models/info_item.dart deleted file mode 100644 index ada745bb..00000000 --- a/third_party/refresh_rate/example/lib/src/models/info_item.dart +++ /dev/null @@ -1,6 +0,0 @@ -class InfoItem { - const InfoItem(this.label, this.value); - - final String label; - final String value; -} diff --git a/third_party/refresh_rate/example/lib/src/sections/action_panel.dart b/third_party/refresh_rate/example/lib/src/sections/action_panel.dart deleted file mode 100644 index 5661a85b..00000000 --- a/third_party/refresh_rate/example/lib/src/sections/action_panel.dart +++ /dev/null @@ -1,48 +0,0 @@ -import 'package:flutter/material.dart'; - -import '../models/action_spec.dart'; -import '../ui/panel_widgets.dart'; - -class ActionPanel extends StatelessWidget { - const ActionPanel({ - super.key, - required this.eyebrow, - required this.title, - required this.subtitle, - required this.actions, - this.footer, - }); - - final String eyebrow; - final String title; - final String subtitle; - final List actions; - final Widget? footer; - - @override - Widget build(BuildContext context) { - return SurfacePanel( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - PanelHeader( - eyebrow: eyebrow, - title: title, - subtitle: subtitle, - ), - const SizedBox(height: 14), - Wrap( - spacing: 10, - runSpacing: 10, - children: - actions.map((action) => ActionButton(spec: action)).toList(), - ), - if (footer != null) ...[ - const SizedBox(height: 14), - footer!, - ], - ], - ), - ); - } -} diff --git a/third_party/refresh_rate/example/lib/src/sections/benchmark_panel.dart b/third_party/refresh_rate/example/lib/src/sections/benchmark_panel.dart deleted file mode 100644 index fc188045..00000000 --- a/third_party/refresh_rate/example/lib/src/sections/benchmark_panel.dart +++ /dev/null @@ -1,46 +0,0 @@ -import 'package:flutter/material.dart'; - -import '../models/action_spec.dart'; -import '../models/info_item.dart'; -import '../ui/panel_widgets.dart'; -import 'action_panel.dart'; - -class BenchmarkPanel extends StatelessWidget { - const BenchmarkPanel({ - super.key, - required this.actions, - required this.reportItems, - }); - - final List actions; - final List? reportItems; - - @override - Widget build(BuildContext context) { - return ActionPanel( - eyebrow: 'Benchmark', - title: 'Session Capture', - subtitle: - 'Run a named session, exercise scrolling or animations, then inspect verdict and missed-frame behavior.', - actions: actions, - footer: reportItems == null - ? Container( - width: double.infinity, - padding: const EdgeInsets.all(14), - decoration: BoxDecoration( - color: const Color(0xFF0E0E0E), - borderRadius: BorderRadius.circular(14), - ), - child: const Text( - 'No report captured yet. Start a session, interact with the scroll test, then end the session to inspect the results.', - style: TextStyle( - color: Color(0xFFB9CACB), - fontSize: 12, - height: 1.45, - ), - ), - ) - : ReportSummary(items: reportItems!), - ); - } -} diff --git a/third_party/refresh_rate/example/lib/src/sections/display_info_panel.dart b/third_party/refresh_rate/example/lib/src/sections/display_info_panel.dart deleted file mode 100644 index 5c8216da..00000000 --- a/third_party/refresh_rate/example/lib/src/sections/display_info_panel.dart +++ /dev/null @@ -1,52 +0,0 @@ -import 'package:flutter/material.dart'; - -import '../models/info_item.dart'; -import '../ui/panel_widgets.dart'; - -class DisplayInfoPanel extends StatelessWidget { - const DisplayInfoPanel({ - super.key, - required this.items, - }); - - final List items; - - @override - Widget build(BuildContext context) { - return SurfacePanel( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const PanelHeader( - eyebrow: 'Telemetry', - title: 'Display Info', - subtitle: - 'Hardware capability, operating state, and platform-level diagnostics.', - ), - const SizedBox(height: 14), - LayoutBuilder( - builder: (context, constraints) { - final columns = constraints.maxWidth >= 900 - ? 3 - : constraints.maxWidth >= 560 - ? 2 - : 1; - return GridView.builder( - shrinkWrap: true, - physics: const NeverScrollableScrollPhysics(), - itemCount: items.length, - gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( - crossAxisCount: columns, - crossAxisSpacing: 10, - mainAxisSpacing: 10, - mainAxisExtent: 76, - ), - itemBuilder: (context, index) => InfoTile(item: items[index]), - ); - }, - ), - ], - ), - ); - } -} diff --git a/third_party/refresh_rate/example/lib/src/sections/hero_panel.dart b/third_party/refresh_rate/example/lib/src/sections/hero_panel.dart deleted file mode 100644 index 76e40526..00000000 --- a/third_party/refresh_rate/example/lib/src/sections/hero_panel.dart +++ /dev/null @@ -1,109 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:refresh_rate/refresh_rate.dart'; - -import '../ui/panel_widgets.dart'; - -class HeroPanel extends StatelessWidget { - const HeroPanel({ - super.key, - required this.info, - required this.status, - required this.frameBudgetMs, - required this.maxBudgetMs, - required this.liveStateColor, - required this.largeHero, - required this.supportedRatesText, - }); - - final DisplayInfo info; - final String status; - final double frameBudgetMs; - final double maxBudgetMs; - final Color liveStateColor; - final bool largeHero; - final String supportedRatesText; - - @override - Widget build(BuildContext context) { - return SurfacePanel( - padding: const EdgeInsets.all(18), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - children: [ - const Expanded( - child: PanelHeader( - eyebrow: 'refresh_rate v1.0', - title: 'Diagnostic Console', - subtitle: - 'Live instrumentation for display state, frame budget, control requests, and benchmark sessions.', - ), - ), - SignalBadge( - label: status.toUpperCase(), - color: liveStateColor, - ), - ], - ), - const SizedBox(height: 18), - Wrap( - spacing: 12, - runSpacing: 12, - children: [ - HeroMetric( - label: 'Current Rate', - value: '${info.currentRate.toStringAsFixed(1)} Hz', - caption: 'Observed display target', - accent: const Color(0xFF00F0FF), - wide: largeHero, - ), - HeroMetric( - label: 'Peak Capability', - value: '${info.maxRate.toStringAsFixed(1)} Hz', - caption: 'Device-reported maximum', - accent: const Color(0xFF36FF8B), - wide: largeHero, - ), - HeroMetric( - label: 'Frame Budget', - value: '${frameBudgetMs.toStringAsFixed(2)} ms', - caption: frameBudgetMs > 0 - ? 'Target at ${info.currentRate.toStringAsFixed(1)} Hz' - : 'Waiting for rate data', - accent: const Color(0xFFFFBA20), - wide: largeHero, - ), - ], - ), - const SizedBox(height: 18), - Wrap( - spacing: 8, - runSpacing: 8, - children: [ - TelemetryChip(label: 'Supported', value: supportedRatesText), - TelemetryChip( - label: 'VRR', - value: info.isVariableRefreshRate ? 'Enabled' : 'Fixed', - ), - TelemetryChip( - label: 'Low Power', - value: RefreshRate.isLowPowerMode ? 'On' : 'Off', - ), - TelemetryChip( - label: 'Thermal', - value: RefreshRate.thermalState.name, - ), - TelemetryChip( - label: 'Peak Budget', - value: maxBudgetMs > 0 - ? '${maxBudgetMs.toStringAsFixed(2)} ms' - : 'n/a', - ), - ], - ), - ], - ), - ); - } -} diff --git a/third_party/refresh_rate/example/lib/src/sections/scroll_test_panel.dart b/third_party/refresh_rate/example/lib/src/sections/scroll_test_panel.dart deleted file mode 100644 index 70f32338..00000000 --- a/third_party/refresh_rate/example/lib/src/sections/scroll_test_panel.dart +++ /dev/null @@ -1,108 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:refresh_rate/refresh_rate.dart'; - -import '../ui/panel_widgets.dart'; - -class ScrollTestPanel extends StatelessWidget { - const ScrollTestPanel({ - super.key, - required this.info, - }); - - final DisplayInfo info; - - @override - Widget build(BuildContext context) { - return SurfacePanel( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const PanelHeader( - eyebrow: 'Exercise', - title: 'Scroll Test', - subtitle: - 'Use this list to generate sustained motion and compare the on-screen experience against the live frame budget.', - ), - const SizedBox(height: 12), - Container( - height: 340, - decoration: BoxDecoration( - color: const Color(0xFF0E0E0E), - borderRadius: BorderRadius.circular(16), - ), - child: ListView.separated( - padding: const EdgeInsets.all(10), - itemCount: 30, - separatorBuilder: (_, __) => const SizedBox(height: 6), - itemBuilder: (context, index) { - final laneColor = index.isEven - ? const Color(0xFF00F0FF) - : const Color(0xFF36FF8B); - return Container( - padding: const EdgeInsets.symmetric( - horizontal: 12, - vertical: 12, - ), - decoration: BoxDecoration( - color: const Color(0xFF171717), - borderRadius: BorderRadius.circular(12), - ), - child: Row( - children: [ - Container( - width: 34, - height: 34, - decoration: BoxDecoration( - color: laneColor.withValues(alpha: 0.16), - borderRadius: BorderRadius.circular(10), - ), - alignment: Alignment.center, - child: Text( - '${index + 1}', - style: TextStyle( - color: laneColor, - fontWeight: FontWeight.w700, - ), - ), - ), - const SizedBox(width: 12), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - 'Trace sample ${index + 1}', - style: const TextStyle( - fontWeight: FontWeight.w600, - ), - ), - const SizedBox(height: 2), - Text( - 'Target ${(info.maxRate > 0 ? info.maxRate : info.currentRate).toStringAsFixed(0)} Hz • verify pacing under continuous scroll.', - style: const TextStyle( - color: Color(0xFFB9CACB), - fontSize: 12, - ), - ), - ], - ), - ), - Text( - '${(index + 1) * 8} ms', - style: const TextStyle( - color: Color(0xFFB9CACB), - fontSize: 12, - fontFeatures: [FontFeature.tabularFigures()], - ), - ), - ], - ), - ); - }, - ), - ), - ], - ), - ); - } -} diff --git a/third_party/refresh_rate/example/lib/src/sections/status_panel.dart b/third_party/refresh_rate/example/lib/src/sections/status_panel.dart deleted file mode 100644 index 52070079..00000000 --- a/third_party/refresh_rate/example/lib/src/sections/status_panel.dart +++ /dev/null @@ -1,47 +0,0 @@ -import 'package:flutter/material.dart'; - -import '../ui/panel_widgets.dart'; - -class StatusPanel extends StatelessWidget { - const StatusPanel({ - super.key, - required this.status, - }); - - final String status; - - @override - Widget build(BuildContext context) { - return SurfacePanel( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const PanelHeader( - eyebrow: 'System', - title: 'Run Status', - subtitle: - 'Recent command state and what the console is currently signaling to the platform.', - ), - const SizedBox(height: 14), - Container( - width: double.infinity, - padding: const EdgeInsets.all(14), - decoration: BoxDecoration( - color: const Color(0xFF0E0E0E), - borderRadius: BorderRadius.circular(14), - ), - child: Text( - status, - style: const TextStyle( - color: Color(0xFFE5E2E1), - fontSize: 13, - fontWeight: FontWeight.w600, - height: 1.4, - ), - ), - ), - ], - ), - ); - } -} diff --git a/third_party/refresh_rate/example/lib/src/ui/panel_widgets.dart b/third_party/refresh_rate/example/lib/src/ui/panel_widgets.dart deleted file mode 100644 index 0f2d077b..00000000 --- a/third_party/refresh_rate/example/lib/src/ui/panel_widgets.dart +++ /dev/null @@ -1,377 +0,0 @@ -import 'package:flutter/material.dart'; - -import '../models/action_spec.dart'; -import '../models/info_item.dart'; - -class SurfacePanel extends StatelessWidget { - const SurfacePanel({ - super.key, - required this.child, - this.padding = const EdgeInsets.all(16), - }); - - final Widget child; - final EdgeInsetsGeometry padding; - - @override - Widget build(BuildContext context) { - return DecoratedBox( - decoration: BoxDecoration( - color: const Color(0xFF1C1B1B), - borderRadius: BorderRadius.circular(22), - border: Border.all( - color: const Color(0xFF00F0FF).withValues(alpha: 0.08), - ), - gradient: const LinearGradient( - begin: Alignment.topLeft, - end: Alignment.bottomRight, - colors: [Color(0xFF1F1E1E), Color(0xFF181818)], - ), - ), - child: Padding( - padding: padding, - child: child, - ), - ); - } -} - -class PanelHeader extends StatelessWidget { - const PanelHeader({ - super.key, - required this.eyebrow, - required this.title, - required this.subtitle, - }); - - final String eyebrow; - final String title; - final String subtitle; - - @override - Widget build(BuildContext context) { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - eyebrow.toUpperCase(), - style: const TextStyle( - color: Color(0xFFB9CACB), - fontSize: 11, - fontWeight: FontWeight.w700, - letterSpacing: 1.2, - ), - ), - const SizedBox(height: 6), - Text( - title, - style: const TextStyle( - fontSize: 22, - fontWeight: FontWeight.w800, - letterSpacing: -0.4, - ), - ), - const SizedBox(height: 6), - Text( - subtitle, - style: const TextStyle( - color: Color(0xFFB9CACB), - fontSize: 12, - height: 1.5, - ), - ), - ], - ); - } -} - -class HeroMetric extends StatelessWidget { - const HeroMetric({ - super.key, - required this.label, - required this.value, - required this.caption, - required this.accent, - required this.wide, - }); - - final String label; - final String value; - final String caption; - final Color accent; - final bool wide; - - @override - Widget build(BuildContext context) { - return Container( - width: wide ? 240 : double.infinity, - constraints: const BoxConstraints(minHeight: 132, minWidth: 210), - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - color: const Color(0xFF0E0E0E), - borderRadius: BorderRadius.circular(18), - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - label.toUpperCase(), - style: const TextStyle( - color: Color(0xFFB9CACB), - fontSize: 11, - fontWeight: FontWeight.w700, - letterSpacing: 1.0, - ), - ), - const SizedBox(height: 22), - Text( - value, - style: TextStyle( - color: accent, - fontSize: 28, - fontWeight: FontWeight.w800, - letterSpacing: -1.0, - ), - ), - const SizedBox(height: 6), - Text( - caption, - style: const TextStyle( - color: Color(0xFFB9CACB), - fontSize: 12, - height: 1.4, - ), - ), - ], - ), - ); - } -} - -class TelemetryChip extends StatelessWidget { - const TelemetryChip({ - super.key, - required this.label, - required this.value, - }); - - final String label; - final String value; - - @override - Widget build(BuildContext context) { - return Container( - padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 8), - decoration: BoxDecoration( - color: const Color(0xFF2A2A2A), - borderRadius: BorderRadius.circular(10), - ), - child: RichText( - text: TextSpan( - children: [ - TextSpan( - text: '${label.toUpperCase()}: ', - style: const TextStyle( - color: Color(0xFFB9CACB), - fontSize: 11, - fontWeight: FontWeight.w700, - letterSpacing: 0.6, - ), - ), - TextSpan( - text: value, - style: const TextStyle( - color: Color(0xFFE5E2E1), - fontSize: 11, - fontWeight: FontWeight.w600, - ), - ), - ], - ), - ), - ); - } -} - -class SignalBadge extends StatelessWidget { - const SignalBadge({ - super.key, - required this.label, - required this.color, - }); - - final String label; - final Color color; - - @override - Widget build(BuildContext context) { - return Container( - padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 10), - decoration: BoxDecoration( - color: color.withValues(alpha: 0.14), - borderRadius: BorderRadius.circular(14), - ), - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - Container( - width: 8, - height: 8, - decoration: BoxDecoration( - color: color, - shape: BoxShape.circle, - ), - ), - const SizedBox(width: 8), - Text( - label, - style: TextStyle( - color: color, - fontSize: 11, - fontWeight: FontWeight.w800, - letterSpacing: 0.8, - ), - ), - ], - ), - ); - } -} - -class InfoTile extends StatelessWidget { - const InfoTile({ - super.key, - required this.item, - }); - - final InfoItem item; - - @override - Widget build(BuildContext context) { - return Container( - padding: const EdgeInsets.all(14), - decoration: BoxDecoration( - color: const Color(0xFF0E0E0E), - borderRadius: BorderRadius.circular(16), - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - item.label.toUpperCase(), - style: const TextStyle( - color: Color(0xFFB9CACB), - fontSize: 10, - fontWeight: FontWeight.w700, - letterSpacing: 0.9, - ), - ), - const Spacer(), - Text( - item.value, - style: const TextStyle( - fontSize: 15, - fontWeight: FontWeight.w700, - ), - maxLines: 2, - overflow: TextOverflow.ellipsis, - ), - ], - ), - ); - } -} - -class ActionButton extends StatelessWidget { - const ActionButton({ - super.key, - required this.spec, - }); - - final ActionSpec spec; - - @override - Widget build(BuildContext context) { - final foreground = spec.onTap == null - ? const Color(0xFF68787A) - : (spec.outlined ? spec.accent : const Color(0xFFE5E2E1)); - - final child = Text(spec.label); - final background = spec.onTap == null - ? const Color(0xFF171717) - : spec.accent.withValues(alpha: spec.outlined ? 0.08 : 0.18); - - if (spec.outlined) { - return OutlinedButton( - onPressed: spec.onTap, - style: OutlinedButton.styleFrom( - side: BorderSide( - color: spec.onTap == null - ? const Color(0xFF2A2A2A) - : spec.accent.withValues(alpha: 0.5), - ), - backgroundColor: background, - foregroundColor: foreground, - ), - child: child, - ); - } - - return FilledButton( - onPressed: spec.onTap, - style: FilledButton.styleFrom( - backgroundColor: background, - foregroundColor: foreground, - ), - child: child, - ); - } -} - -class ReportSummary extends StatelessWidget { - const ReportSummary({ - super.key, - required this.items, - }); - - final List items; - - @override - Widget build(BuildContext context) { - return Column( - children: items - .map( - (item) => Container( - margin: const EdgeInsets.only(bottom: 8), - padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 12), - decoration: BoxDecoration( - color: const Color(0xFF0E0E0E), - borderRadius: BorderRadius.circular(12), - ), - child: Row( - children: [ - Expanded( - child: Text( - item.label, - style: const TextStyle( - color: Color(0xFFB9CACB), - fontSize: 12, - ), - ), - ), - Text( - item.value, - style: const TextStyle( - color: Color(0xFFE5E2E1), - fontSize: 12, - fontWeight: FontWeight.w700, - ), - ), - ], - ), - ), - ) - .toList(), - ); - } -} diff --git a/third_party/refresh_rate/example/linux/CMakeLists.txt b/third_party/refresh_rate/example/linux/CMakeLists.txt deleted file mode 100644 index 2cb7e278..00000000 --- a/third_party/refresh_rate/example/linux/CMakeLists.txt +++ /dev/null @@ -1,128 +0,0 @@ -# Project-level configuration. -cmake_minimum_required(VERSION 3.13) -project(runner 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 "refresh_rate_example") -# The unique GTK application identifier for this application. See: -# https://wiki.gnome.org/HowDoI/ChooseApplicationID -set(APPLICATION_ID "in.qoder.refresh_rate_example") - -# Explicitly opt in to modern CMake behaviors to avoid warnings with recent -# versions of CMake. -cmake_policy(SET CMP0063 NEW) - -# Load bundled libraries from the lib/ directory relative to the binary. -set(CMAKE_INSTALL_RPATH "$ORIGIN/lib") - -# Root filesystem for cross-building. -if(FLUTTER_TARGET_PLATFORM_SYSROOT) - set(CMAKE_SYSROOT ${FLUTTER_TARGET_PLATFORM_SYSROOT}) - set(CMAKE_FIND_ROOT_PATH ${CMAKE_SYSROOT}) - set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) - set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) - set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) - set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) -endif() - -# Define build configuration options. -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() - -# 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_14) - target_compile_options(${TARGET} PRIVATE -Wall -Werror) - target_compile_options(${TARGET} PRIVATE "$<$>:-O3>") - target_compile_definitions(${TARGET} PRIVATE "$<$>:NDEBUG>") -endfunction() - -# Flutter library and tool build rules. -set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") -add_subdirectory(${FLUTTER_MANAGED_DIR}) - -# System-level dependencies. -find_package(PkgConfig REQUIRED) -pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) - -# Application build; see runner/CMakeLists.txt. -add_subdirectory("runner") - -# Run the Flutter tool portions of the build. This must not be removed. -add_dependencies(${BINARY_NAME} flutter_assemble) - -# Only the install-generated bundle's copy of the executable will launch -# correctly, since the resources must in the right relative locations. To avoid -# people trying to run the unbundled copy, put it in a subdirectory instead of -# the default top-level location. -set_target_properties(${BINARY_NAME} - PROPERTIES - RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/intermediates_do_not_run" -) - - -# Generated plugin build rules, which manage building the plugins and adding -# them to the application. -include(flutter/generated_plugins.cmake) - - -# === Installation === -# By default, "installing" just makes a relocatable bundle in the build -# directory. -set(BUILD_BUNDLE_DIR "${PROJECT_BINARY_DIR}/bundle") -if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) - set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) -endif() - -# Start with a clean build bundle directory every time. -install(CODE " - file(REMOVE_RECURSE \"${BUILD_BUNDLE_DIR}/\") - " COMPONENT Runtime) - -set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") -set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib") - -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) - -foreach(bundled_library ${PLUGIN_BUNDLED_LIBRARIES}) - install(FILES "${bundled_library}" - DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" - COMPONENT Runtime) -endforeach(bundled_library) - -# Copy the native assets provided by the build.dart from all packages. -set(NATIVE_ASSETS_DIR "${PROJECT_BUILD_DIR}native_assets/linux/") -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. -if(NOT CMAKE_BUILD_TYPE MATCHES "Debug") - install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" - COMPONENT Runtime) -endif() diff --git a/third_party/refresh_rate/example/linux/flutter/CMakeLists.txt b/third_party/refresh_rate/example/linux/flutter/CMakeLists.txt deleted file mode 100644 index d5bd0164..00000000 --- a/third_party/refresh_rate/example/linux/flutter/CMakeLists.txt +++ /dev/null @@ -1,88 +0,0 @@ -# This file controls Flutter-level build steps. It should not be edited. -cmake_minimum_required(VERSION 3.10) - -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. - -# Serves the same purpose as list(TRANSFORM ... PREPEND ...), -# which isn't available in 3.10. -function(list_prepend LIST_NAME PREFIX) - set(NEW_LIST "") - foreach(element ${${LIST_NAME}}) - list(APPEND NEW_LIST "${PREFIX}${element}") - endforeach(element) - set(${LIST_NAME} "${NEW_LIST}" PARENT_SCOPE) -endfunction() - -# === Flutter Library === -# System-level dependencies. -find_package(PkgConfig REQUIRED) -pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) -pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0) -pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0) - -set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/libflutter_linux_gtk.so") - -# 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/lib/libapp.so" PARENT_SCOPE) - -list(APPEND FLUTTER_LIBRARY_HEADERS - "fl_basic_message_channel.h" - "fl_binary_codec.h" - "fl_binary_messenger.h" - "fl_dart_project.h" - "fl_engine.h" - "fl_json_message_codec.h" - "fl_json_method_codec.h" - "fl_message_codec.h" - "fl_method_call.h" - "fl_method_channel.h" - "fl_method_codec.h" - "fl_method_response.h" - "fl_plugin_registrar.h" - "fl_plugin_registry.h" - "fl_standard_message_codec.h" - "fl_standard_method_codec.h" - "fl_string_codec.h" - "fl_value.h" - "fl_view.h" - "flutter_linux.h" -) -list_prepend(FLUTTER_LIBRARY_HEADERS "${EPHEMERAL_DIR}/flutter_linux/") -add_library(flutter INTERFACE) -target_include_directories(flutter INTERFACE - "${EPHEMERAL_DIR}" -) -target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}") -target_link_libraries(flutter INTERFACE - PkgConfig::GTK - PkgConfig::GLIB - PkgConfig::GIO -) -add_dependencies(flutter 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. -add_custom_command( - OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} - ${CMAKE_CURRENT_BINARY_DIR}/_phony_ - COMMAND ${CMAKE_COMMAND} -E env - ${FLUTTER_TOOL_ENVIRONMENT} - "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh" - ${FLUTTER_TARGET_PLATFORM} ${CMAKE_BUILD_TYPE} - VERBATIM -) -add_custom_target(flutter_assemble DEPENDS - "${FLUTTER_LIBRARY}" - ${FLUTTER_LIBRARY_HEADERS} -) diff --git a/third_party/refresh_rate/example/linux/flutter/generated_plugin_registrant.cc b/third_party/refresh_rate/example/linux/flutter/generated_plugin_registrant.cc deleted file mode 100644 index 080e8e35..00000000 --- a/third_party/refresh_rate/example/linux/flutter/generated_plugin_registrant.cc +++ /dev/null @@ -1,15 +0,0 @@ -// -// Generated file. Do not edit. -// - -// clang-format off - -#include "generated_plugin_registrant.h" - -#include - -void fl_register_plugins(FlPluginRegistry* registry) { - g_autoptr(FlPluginRegistrar) refresh_rate_registrar = - fl_plugin_registry_get_registrar_for_plugin(registry, "RefreshRatePlugin"); - refresh_rate_plugin_register_with_registrar(refresh_rate_registrar); -} diff --git a/third_party/refresh_rate/example/linux/flutter/generated_plugin_registrant.h b/third_party/refresh_rate/example/linux/flutter/generated_plugin_registrant.h deleted file mode 100644 index e0f0a47b..00000000 --- a/third_party/refresh_rate/example/linux/flutter/generated_plugin_registrant.h +++ /dev/null @@ -1,15 +0,0 @@ -// -// Generated file. Do not edit. -// - -// clang-format off - -#ifndef GENERATED_PLUGIN_REGISTRANT_ -#define GENERATED_PLUGIN_REGISTRANT_ - -#include - -// Registers Flutter plugins. -void fl_register_plugins(FlPluginRegistry* registry); - -#endif // GENERATED_PLUGIN_REGISTRANT_ diff --git a/third_party/refresh_rate/example/linux/flutter/generated_plugins.cmake b/third_party/refresh_rate/example/linux/flutter/generated_plugins.cmake deleted file mode 100644 index 0d162423..00000000 --- a/third_party/refresh_rate/example/linux/flutter/generated_plugins.cmake +++ /dev/null @@ -1,24 +0,0 @@ -# -# Generated file, do not edit. -# - -list(APPEND FLUTTER_PLUGIN_LIST - refresh_rate -) - -list(APPEND FLUTTER_FFI_PLUGIN_LIST -) - -set(PLUGIN_BUNDLED_LIBRARIES) - -foreach(plugin ${FLUTTER_PLUGIN_LIST}) - add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/linux 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}/linux plugins/${ffi_plugin}) - list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) -endforeach(ffi_plugin) diff --git a/third_party/refresh_rate/example/linux/runner/CMakeLists.txt b/third_party/refresh_rate/example/linux/runner/CMakeLists.txt deleted file mode 100644 index e97dabc7..00000000 --- a/third_party/refresh_rate/example/linux/runner/CMakeLists.txt +++ /dev/null @@ -1,26 +0,0 @@ -cmake_minimum_required(VERSION 3.13) -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} - "main.cc" - "my_application.cc" - "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" -) - -# 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 application ID. -add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}") - -# Add dependency libraries. Add any application-specific dependencies here. -target_link_libraries(${BINARY_NAME} PRIVATE flutter) -target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GTK) - -target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}") diff --git a/third_party/refresh_rate/example/linux/runner/main.cc b/third_party/refresh_rate/example/linux/runner/main.cc deleted file mode 100644 index e7c5c543..00000000 --- a/third_party/refresh_rate/example/linux/runner/main.cc +++ /dev/null @@ -1,6 +0,0 @@ -#include "my_application.h" - -int main(int argc, char** argv) { - g_autoptr(MyApplication) app = my_application_new(); - return g_application_run(G_APPLICATION(app), argc, argv); -} diff --git a/third_party/refresh_rate/example/linux/runner/my_application.cc b/third_party/refresh_rate/example/linux/runner/my_application.cc deleted file mode 100644 index 02c797bc..00000000 --- a/third_party/refresh_rate/example/linux/runner/my_application.cc +++ /dev/null @@ -1,148 +0,0 @@ -#include "my_application.h" - -#include -#ifdef GDK_WINDOWING_X11 -#include -#endif - -#include "flutter/generated_plugin_registrant.h" - -struct _MyApplication { - GtkApplication parent_instance; - char** dart_entrypoint_arguments; -}; - -G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION) - -// Called when first Flutter frame received. -static void first_frame_cb(MyApplication* self, FlView* view) { - gtk_widget_show(gtk_widget_get_toplevel(GTK_WIDGET(view))); -} - -// Implements GApplication::activate. -static void my_application_activate(GApplication* application) { - MyApplication* self = MY_APPLICATION(application); - GtkWindow* window = - GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application))); - - // Use a header bar when running in GNOME as this is the common style used - // by applications and is the setup most users will be using (e.g. Ubuntu - // desktop). - // If running on X and not using GNOME then just use a traditional title bar - // in case the window manager does more exotic layout, e.g. tiling. - // If running on Wayland assume the header bar will work (may need changing - // if future cases occur). - gboolean use_header_bar = TRUE; -#ifdef GDK_WINDOWING_X11 - GdkScreen* screen = gtk_window_get_screen(window); - if (GDK_IS_X11_SCREEN(screen)) { - const gchar* wm_name = gdk_x11_screen_get_window_manager_name(screen); - if (g_strcmp0(wm_name, "GNOME Shell") != 0) { - use_header_bar = FALSE; - } - } -#endif - if (use_header_bar) { - GtkHeaderBar* header_bar = GTK_HEADER_BAR(gtk_header_bar_new()); - gtk_widget_show(GTK_WIDGET(header_bar)); - gtk_header_bar_set_title(header_bar, "refresh_rate_example"); - gtk_header_bar_set_show_close_button(header_bar, TRUE); - gtk_window_set_titlebar(window, GTK_WIDGET(header_bar)); - } else { - gtk_window_set_title(window, "refresh_rate_example"); - } - - gtk_window_set_default_size(window, 1280, 720); - - g_autoptr(FlDartProject) project = fl_dart_project_new(); - fl_dart_project_set_dart_entrypoint_arguments( - project, self->dart_entrypoint_arguments); - - FlView* view = fl_view_new(project); - GdkRGBA background_color; - // Background defaults to black, override it here if necessary, e.g. #00000000 - // for transparent. - gdk_rgba_parse(&background_color, "#000000"); - fl_view_set_background_color(view, &background_color); - gtk_widget_show(GTK_WIDGET(view)); - gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view)); - - // Show the window when Flutter renders. - // Requires the view to be realized so we can start rendering. - g_signal_connect_swapped(view, "first-frame", G_CALLBACK(first_frame_cb), - self); - gtk_widget_realize(GTK_WIDGET(view)); - - fl_register_plugins(FL_PLUGIN_REGISTRY(view)); - - gtk_widget_grab_focus(GTK_WIDGET(view)); -} - -// Implements GApplication::local_command_line. -static gboolean my_application_local_command_line(GApplication* application, - gchar*** arguments, - int* exit_status) { - MyApplication* self = MY_APPLICATION(application); - // Strip out the first argument as it is the binary name. - self->dart_entrypoint_arguments = g_strdupv(*arguments + 1); - - g_autoptr(GError) error = nullptr; - if (!g_application_register(application, nullptr, &error)) { - g_warning("Failed to register: %s", error->message); - *exit_status = 1; - return TRUE; - } - - g_application_activate(application); - *exit_status = 0; - - return TRUE; -} - -// Implements GApplication::startup. -static void my_application_startup(GApplication* application) { - // MyApplication* self = MY_APPLICATION(object); - - // Perform any actions required at application startup. - - G_APPLICATION_CLASS(my_application_parent_class)->startup(application); -} - -// Implements GApplication::shutdown. -static void my_application_shutdown(GApplication* application) { - // MyApplication* self = MY_APPLICATION(object); - - // Perform any actions required at application shutdown. - - G_APPLICATION_CLASS(my_application_parent_class)->shutdown(application); -} - -// Implements GObject::dispose. -static void my_application_dispose(GObject* object) { - MyApplication* self = MY_APPLICATION(object); - g_clear_pointer(&self->dart_entrypoint_arguments, g_strfreev); - G_OBJECT_CLASS(my_application_parent_class)->dispose(object); -} - -static void my_application_class_init(MyApplicationClass* klass) { - G_APPLICATION_CLASS(klass)->activate = my_application_activate; - G_APPLICATION_CLASS(klass)->local_command_line = - my_application_local_command_line; - G_APPLICATION_CLASS(klass)->startup = my_application_startup; - G_APPLICATION_CLASS(klass)->shutdown = my_application_shutdown; - G_OBJECT_CLASS(klass)->dispose = my_application_dispose; -} - -static void my_application_init(MyApplication* self) {} - -MyApplication* my_application_new() { - // Set the program name to the application ID, which helps various systems - // like GTK and desktop environments map this running application to its - // corresponding .desktop file. This ensures better integration by allowing - // the application to be recognized beyond its binary name. - g_set_prgname(APPLICATION_ID); - - return MY_APPLICATION(g_object_new(my_application_get_type(), - "application-id", APPLICATION_ID, "flags", - G_APPLICATION_NON_UNIQUE, nullptr)); -} diff --git a/third_party/refresh_rate/example/linux/runner/my_application.h b/third_party/refresh_rate/example/linux/runner/my_application.h deleted file mode 100644 index db16367a..00000000 --- a/third_party/refresh_rate/example/linux/runner/my_application.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef FLUTTER_MY_APPLICATION_H_ -#define FLUTTER_MY_APPLICATION_H_ - -#include - -G_DECLARE_FINAL_TYPE(MyApplication, - my_application, - MY, - APPLICATION, - GtkApplication) - -/** - * my_application_new: - * - * Creates a new Flutter-based application. - * - * Returns: a new #MyApplication. - */ -MyApplication* my_application_new(); - -#endif // FLUTTER_MY_APPLICATION_H_ diff --git a/third_party/refresh_rate/example/macos/Flutter/Flutter-Debug.xcconfig b/third_party/refresh_rate/example/macos/Flutter/Flutter-Debug.xcconfig deleted file mode 100644 index 4b81f9b2..00000000 --- a/third_party/refresh_rate/example/macos/Flutter/Flutter-Debug.xcconfig +++ /dev/null @@ -1,2 +0,0 @@ -#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" -#include "ephemeral/Flutter-Generated.xcconfig" diff --git a/third_party/refresh_rate/example/macos/Flutter/Flutter-Release.xcconfig b/third_party/refresh_rate/example/macos/Flutter/Flutter-Release.xcconfig deleted file mode 100644 index 5caa9d15..00000000 --- a/third_party/refresh_rate/example/macos/Flutter/Flutter-Release.xcconfig +++ /dev/null @@ -1,2 +0,0 @@ -#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" -#include "ephemeral/Flutter-Generated.xcconfig" diff --git a/third_party/refresh_rate/example/macos/Podfile b/third_party/refresh_rate/example/macos/Podfile deleted file mode 100644 index ff5ddb3b..00000000 --- a/third_party/refresh_rate/example/macos/Podfile +++ /dev/null @@ -1,42 +0,0 @@ -platform :osx, '10.15' - -# CocoaPods analytics sends network stats synchronously affecting flutter build latency. -ENV['COCOAPODS_DISABLE_STATS'] = 'true' - -project 'Runner', { - 'Debug' => :debug, - 'Profile' => :release, - 'Release' => :release, -} - -def flutter_root - generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'ephemeral', 'Flutter-Generated.xcconfig'), __FILE__) - unless File.exist?(generated_xcode_build_settings_path) - raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure \"flutter pub get\" is executed first" - end - - File.foreach(generated_xcode_build_settings_path) do |line| - matches = line.match(/FLUTTER_ROOT\=(.*)/) - return matches[1].strip if matches - end - raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Flutter-Generated.xcconfig, then run \"flutter pub get\"" -end - -require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) - -flutter_macos_podfile_setup - -target 'Runner' do - use_frameworks! - - flutter_install_all_macos_pods File.dirname(File.realpath(__FILE__)) - target 'RunnerTests' do - inherit! :search_paths - end -end - -post_install do |installer| - installer.pods_project.targets.each do |target| - flutter_additional_macos_build_settings(target) - end -end diff --git a/third_party/refresh_rate/example/macos/Podfile.lock b/third_party/refresh_rate/example/macos/Podfile.lock deleted file mode 100644 index 776dd6e8..00000000 --- a/third_party/refresh_rate/example/macos/Podfile.lock +++ /dev/null @@ -1,22 +0,0 @@ -PODS: - - FlutterMacOS (1.0.0) - - refresh_rate (0.1.0): - - FlutterMacOS - -DEPENDENCIES: - - FlutterMacOS (from `Flutter/ephemeral`) - - refresh_rate (from `Flutter/ephemeral/.symlinks/plugins/refresh_rate/macos`) - -EXTERNAL SOURCES: - FlutterMacOS: - :path: Flutter/ephemeral - refresh_rate: - :path: Flutter/ephemeral/.symlinks/plugins/refresh_rate/macos - -SPEC CHECKSUMS: - FlutterMacOS: d0db08ddef1a9af05a5ec4b724367152bb0500b1 - refresh_rate: 75ff2e747acb2d546aa80e0f521a91607a73388b - -PODFILE CHECKSUM: 54d867c82ac51cbd61b565781b9fada492027009 - -COCOAPODS: 1.16.2 diff --git a/third_party/refresh_rate/example/macos/Runner.xcodeproj/project.pbxproj b/third_party/refresh_rate/example/macos/Runner.xcodeproj/project.pbxproj deleted file mode 100644 index 7e9b5438..00000000 --- a/third_party/refresh_rate/example/macos/Runner.xcodeproj/project.pbxproj +++ /dev/null @@ -1,801 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 54; - objects = { - -/* Begin PBXAggregateTarget section */ - 33CC111A2044C6BA0003C045 /* Flutter Assemble */ = { - isa = PBXAggregateTarget; - buildConfigurationList = 33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */; - buildPhases = ( - 33CC111E2044C6BF0003C045 /* ShellScript */, - ); - dependencies = ( - ); - name = "Flutter Assemble"; - productName = FLX; - }; -/* End PBXAggregateTarget section */ - -/* Begin PBXBuildFile section */ - 331C80D8294CF71000263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C80D7294CF71000263BE5 /* RunnerTests.swift */; }; - 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */; }; - 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC10F02044A3C60003C045 /* AppDelegate.swift */; }; - 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; }; - 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; }; - 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; }; - 910248FF45164247AED47927 /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 48DEDB687F544FA88A70B539 /* Pods_RunnerTests.framework */; }; - CAE0E1D6B3E065E67EACBD01 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 78E82EFBCFE9D8FF45D965F6 /* Pods_Runner.framework */; }; -/* End PBXBuildFile section */ - -/* Begin PBXContainerItemProxy section */ - 331C80D9294CF71000263BE5 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 33CC10E52044A3C60003C045 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 33CC10EC2044A3C60003C045; - remoteInfo = Runner; - }; - 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 33CC10E52044A3C60003C045 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 33CC111A2044C6BA0003C045; - remoteInfo = FLX; - }; -/* End PBXContainerItemProxy section */ - -/* Begin PBXCopyFilesBuildPhase section */ - 33CC110E2044A8840003C045 /* Bundle Framework */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = ""; - dstSubfolderSpec = 10; - files = ( - ); - name = "Bundle Framework"; - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXCopyFilesBuildPhase section */ - -/* Begin PBXFileReference section */ - 331C80D5294CF71000263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - 331C80D7294CF71000263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; - 333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = ""; }; - 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = ""; }; - 33CC10ED2044A3C60003C045 /* refresh_rate_example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = refresh_rate_example.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 33CC10F02044A3C60003C045 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; - 33CC10F22044A3C60003C045 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Runner/Assets.xcassets; sourceTree = ""; }; - 33CC10F52044A3C60003C045 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; - 33CC10F72044A3C60003C045 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Info.plist; path = Runner/Info.plist; sourceTree = ""; }; - 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainFlutterWindow.swift; sourceTree = ""; }; - 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Debug.xcconfig"; sourceTree = ""; }; - 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Release.xcconfig"; sourceTree = ""; }; - 33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = "Flutter-Generated.xcconfig"; path = "ephemeral/Flutter-Generated.xcconfig"; sourceTree = ""; }; - 33E51913231747F40026EE4D /* DebugProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DebugProfile.entitlements; sourceTree = ""; }; - 33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = ""; }; - 33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = ""; }; - 48DEDB687F544FA88A70B539 /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 78E82EFBCFE9D8FF45D965F6 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = ""; }; - 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = ""; }; - A5943E0CD58AC7DB09939013 /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = ""; }; - AB95905B211F4A9F4CF45C3D /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; - B36A800253185A385429601E /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = ""; }; - B949B21E5690992FF2267767 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; - CD862853BFB36B0C3DDAA1F5 /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = ""; }; - D2BF29F912559E7212913015 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 331C80D2294CF70F00263BE5 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 910248FF45164247AED47927 /* Pods_RunnerTests.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 33CC10EA2044A3C60003C045 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - CAE0E1D6B3E065E67EACBD01 /* Pods_Runner.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 331C80D6294CF71000263BE5 /* RunnerTests */ = { - isa = PBXGroup; - children = ( - 331C80D7294CF71000263BE5 /* RunnerTests.swift */, - ); - path = RunnerTests; - sourceTree = ""; - }; - 33BA886A226E78AF003329D5 /* Configs */ = { - isa = PBXGroup; - children = ( - 33E5194F232828860026EE4D /* AppInfo.xcconfig */, - 9740EEB21CF90195004384FC /* Debug.xcconfig */, - 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, - 333000ED22D3DE5D00554162 /* Warnings.xcconfig */, - ); - path = Configs; - sourceTree = ""; - }; - 33CC10E42044A3C60003C045 = { - isa = PBXGroup; - children = ( - 33FAB671232836740065AC1E /* Runner */, - 33CEB47122A05771004F2AC0 /* Flutter */, - 331C80D6294CF71000263BE5 /* RunnerTests */, - 33CC10EE2044A3C60003C045 /* Products */, - D73912EC22F37F3D000D13A0 /* Frameworks */, - C10F1240AAD4C5F3329E39AA /* Pods */, - ); - sourceTree = ""; - }; - 33CC10EE2044A3C60003C045 /* Products */ = { - isa = PBXGroup; - children = ( - 33CC10ED2044A3C60003C045 /* refresh_rate_example.app */, - 331C80D5294CF71000263BE5 /* RunnerTests.xctest */, - ); - name = Products; - sourceTree = ""; - }; - 33CC11242044D66E0003C045 /* Resources */ = { - isa = PBXGroup; - children = ( - 33CC10F22044A3C60003C045 /* Assets.xcassets */, - 33CC10F42044A3C60003C045 /* MainMenu.xib */, - 33CC10F72044A3C60003C045 /* Info.plist */, - ); - name = Resources; - path = ..; - sourceTree = ""; - }; - 33CEB47122A05771004F2AC0 /* Flutter */ = { - isa = PBXGroup; - children = ( - 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */, - 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */, - 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */, - 33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */, - ); - path = Flutter; - sourceTree = ""; - }; - 33FAB671232836740065AC1E /* Runner */ = { - isa = PBXGroup; - children = ( - 33CC10F02044A3C60003C045 /* AppDelegate.swift */, - 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */, - 33E51913231747F40026EE4D /* DebugProfile.entitlements */, - 33E51914231749380026EE4D /* Release.entitlements */, - 33CC11242044D66E0003C045 /* Resources */, - 33BA886A226E78AF003329D5 /* Configs */, - ); - path = Runner; - sourceTree = ""; - }; - C10F1240AAD4C5F3329E39AA /* Pods */ = { - isa = PBXGroup; - children = ( - B949B21E5690992FF2267767 /* Pods-Runner.debug.xcconfig */, - D2BF29F912559E7212913015 /* Pods-Runner.release.xcconfig */, - AB95905B211F4A9F4CF45C3D /* Pods-Runner.profile.xcconfig */, - CD862853BFB36B0C3DDAA1F5 /* Pods-RunnerTests.debug.xcconfig */, - B36A800253185A385429601E /* Pods-RunnerTests.release.xcconfig */, - A5943E0CD58AC7DB09939013 /* Pods-RunnerTests.profile.xcconfig */, - ); - name = Pods; - path = Pods; - sourceTree = ""; - }; - D73912EC22F37F3D000D13A0 /* Frameworks */ = { - isa = PBXGroup; - children = ( - 78E82EFBCFE9D8FF45D965F6 /* Pods_Runner.framework */, - 48DEDB687F544FA88A70B539 /* Pods_RunnerTests.framework */, - ); - name = Frameworks; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 331C80D4294CF70F00263BE5 /* RunnerTests */ = { - isa = PBXNativeTarget; - buildConfigurationList = 331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; - buildPhases = ( - 99F025F5D1F12E172730F152 /* [CP] Check Pods Manifest.lock */, - 331C80D1294CF70F00263BE5 /* Sources */, - 331C80D2294CF70F00263BE5 /* Frameworks */, - 331C80D3294CF70F00263BE5 /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - 331C80DA294CF71000263BE5 /* PBXTargetDependency */, - ); - name = RunnerTests; - productName = RunnerTests; - productReference = 331C80D5294CF71000263BE5 /* RunnerTests.xctest */; - productType = "com.apple.product-type.bundle.unit-test"; - }; - 33CC10EC2044A3C60003C045 /* Runner */ = { - isa = PBXNativeTarget; - buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */; - buildPhases = ( - EB0C5EE370B257EB4486DA5D /* [CP] Check Pods Manifest.lock */, - 33CC10E92044A3C60003C045 /* Sources */, - 33CC10EA2044A3C60003C045 /* Frameworks */, - 33CC10EB2044A3C60003C045 /* Resources */, - 33CC110E2044A8840003C045 /* Bundle Framework */, - 3399D490228B24CF009A79C7 /* ShellScript */, - FBE83B029BB64CA0A7DD0B6F /* [CP] Embed Pods Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - 33CC11202044C79F0003C045 /* PBXTargetDependency */, - ); - name = Runner; - productName = Runner; - productReference = 33CC10ED2044A3C60003C045 /* refresh_rate_example.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 33CC10E52044A3C60003C045 /* Project object */ = { - isa = PBXProject; - attributes = { - BuildIndependentTargetsInParallel = YES; - LastSwiftUpdateCheck = 0920; - LastUpgradeCheck = 1510; - ORGANIZATIONNAME = ""; - TargetAttributes = { - 331C80D4294CF70F00263BE5 = { - CreatedOnToolsVersion = 14.0; - TestTargetID = 33CC10EC2044A3C60003C045; - }; - 33CC10EC2044A3C60003C045 = { - CreatedOnToolsVersion = 9.2; - LastSwiftMigration = 1100; - ProvisioningStyle = Automatic; - SystemCapabilities = { - com.apple.Sandbox = { - enabled = 1; - }; - }; - }; - 33CC111A2044C6BA0003C045 = { - CreatedOnToolsVersion = 9.2; - ProvisioningStyle = Manual; - }; - }; - }; - buildConfigurationList = 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */; - compatibilityVersion = "Xcode 9.3"; - developmentRegion = en; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 33CC10E42044A3C60003C045; - productRefGroup = 33CC10EE2044A3C60003C045 /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 33CC10EC2044A3C60003C045 /* Runner */, - 331C80D4294CF70F00263BE5 /* RunnerTests */, - 33CC111A2044C6BA0003C045 /* Flutter Assemble */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 331C80D3294CF70F00263BE5 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 33CC10EB2044A3C60003C045 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */, - 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXShellScriptBuildPhase section */ - 3399D490228B24CF009A79C7 /* ShellScript */ = { - isa = PBXShellScriptBuildPhase; - alwaysOutOfDate = 1; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - ); - outputFileListPaths = ( - ); - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "echo \"$PRODUCT_NAME.app\" > \"$PROJECT_DIR\"/Flutter/ephemeral/.app_filename && \"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh embed\n"; - }; - 33CC111E2044C6BF0003C045 /* ShellScript */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - Flutter/ephemeral/FlutterInputs.xcfilelist, - ); - inputPaths = ( - Flutter/ephemeral/tripwire, - ); - outputFileListPaths = ( - Flutter/ephemeral/FlutterOutputs.xcfilelist, - ); - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh && touch Flutter/ephemeral/tripwire"; - }; - 99F025F5D1F12E172730F152 /* [CP] Check Pods Manifest.lock */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; - outputFileListPaths = ( - ); - outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; - showEnvVarsInLog = 0; - }; - EB0C5EE370B257EB4486DA5D /* [CP] Check Pods Manifest.lock */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; - outputFileListPaths = ( - ); - outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; - showEnvVarsInLog = 0; - }; - FBE83B029BB64CA0A7DD0B6F /* [CP] Embed Pods Frameworks */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", - ); - name = "[CP] Embed Pods Frameworks"; - outputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; - showEnvVarsInLog = 0; - }; -/* End PBXShellScriptBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 331C80D1294CF70F00263BE5 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 331C80D8294CF71000263BE5 /* RunnerTests.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 33CC10E92044A3C60003C045 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */, - 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */, - 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXTargetDependency section */ - 331C80DA294CF71000263BE5 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 33CC10EC2044A3C60003C045 /* Runner */; - targetProxy = 331C80D9294CF71000263BE5 /* PBXContainerItemProxy */; - }; - 33CC11202044C79F0003C045 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 33CC111A2044C6BA0003C045 /* Flutter Assemble */; - targetProxy = 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */; - }; -/* End PBXTargetDependency section */ - -/* Begin PBXVariantGroup section */ - 33CC10F42044A3C60003C045 /* MainMenu.xib */ = { - isa = PBXVariantGroup; - children = ( - 33CC10F52044A3C60003C045 /* Base */, - ); - name = MainMenu.xib; - path = Runner; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 331C80DB294CF71000263BE5 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = CD862853BFB36B0C3DDAA1F5 /* Pods-RunnerTests.debug.xcconfig */; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - CURRENT_PROJECT_VERSION = 1; - GENERATE_INFOPLIST_FILE = YES; - MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = in.qoder.refreshRateExample.RunnerTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 5.0; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/refresh_rate_example.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/refresh_rate_example"; - }; - name = Debug; - }; - 331C80DC294CF71000263BE5 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = B36A800253185A385429601E /* Pods-RunnerTests.release.xcconfig */; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - CURRENT_PROJECT_VERSION = 1; - GENERATE_INFOPLIST_FILE = YES; - MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = in.qoder.refreshRateExample.RunnerTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 5.0; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/refresh_rate_example.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/refresh_rate_example"; - }; - name = Release; - }; - 331C80DD294CF71000263BE5 /* Profile */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = A5943E0CD58AC7DB09939013 /* Pods-RunnerTests.profile.xcconfig */; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - CURRENT_PROJECT_VERSION = 1; - GENERATE_INFOPLIST_FILE = YES; - MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = in.qoder.refreshRateExample.RunnerTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 5.0; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/refresh_rate_example.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/refresh_rate_example"; - }; - name = Profile; - }; - 338D0CE9231458BD00FA5F75 /* Profile */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CODE_SIGN_IDENTITY = "-"; - COPY_PHASE_STRIP = NO; - DEAD_CODE_STRIPPING = YES; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_USER_SCRIPT_SANDBOXING = NO; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.15; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = macosx; - SWIFT_COMPILATION_MODE = wholemodule; - SWIFT_OPTIMIZATION_LEVEL = "-O"; - }; - name = Profile; - }; - 338D0CEA231458BD00FA5F75 /* Profile */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CLANG_ENABLE_MODULES = YES; - CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; - CODE_SIGN_STYLE = Automatic; - COMBINE_HIDPI_IMAGES = YES; - INFOPLIST_FILE = Runner/Info.plist; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/../Frameworks", - ); - PROVISIONING_PROFILE_SPECIFIER = ""; - SWIFT_VERSION = 5.0; - }; - name = Profile; - }; - 338D0CEB231458BD00FA5F75 /* Profile */ = { - isa = XCBuildConfiguration; - buildSettings = { - CODE_SIGN_STYLE = Manual; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Profile; - }; - 33CC10F92044A3C60003C045 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CODE_SIGN_IDENTITY = "-"; - COPY_PHASE_STRIP = NO; - DEAD_CODE_STRIPPING = YES; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - ENABLE_USER_SCRIPT_SANDBOXING = NO; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.15; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = macosx; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - }; - name = Debug; - }; - 33CC10FA2044A3C60003C045 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CODE_SIGN_IDENTITY = "-"; - COPY_PHASE_STRIP = NO; - DEAD_CODE_STRIPPING = YES; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_USER_SCRIPT_SANDBOXING = NO; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.15; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = macosx; - SWIFT_COMPILATION_MODE = wholemodule; - SWIFT_OPTIMIZATION_LEVEL = "-O"; - }; - name = Release; - }; - 33CC10FC2044A3C60003C045 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CLANG_ENABLE_MODULES = YES; - CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; - CODE_SIGN_STYLE = Automatic; - COMBINE_HIDPI_IMAGES = YES; - INFOPLIST_FILE = Runner/Info.plist; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/../Frameworks", - ); - PROVISIONING_PROFILE_SPECIFIER = ""; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 5.0; - }; - name = Debug; - }; - 33CC10FD2044A3C60003C045 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CLANG_ENABLE_MODULES = YES; - CODE_SIGN_ENTITLEMENTS = Runner/Release.entitlements; - CODE_SIGN_STYLE = Automatic; - COMBINE_HIDPI_IMAGES = YES; - INFOPLIST_FILE = Runner/Info.plist; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/../Frameworks", - ); - PROVISIONING_PROFILE_SPECIFIER = ""; - SWIFT_VERSION = 5.0; - }; - name = Release; - }; - 33CC111C2044C6BA0003C045 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - CODE_SIGN_STYLE = Manual; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 33CC111D2044C6BA0003C045 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - CODE_SIGN_STYLE = Automatic; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 331C80DB294CF71000263BE5 /* Debug */, - 331C80DC294CF71000263BE5 /* Release */, - 331C80DD294CF71000263BE5 /* Profile */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 33CC10F92044A3C60003C045 /* Debug */, - 33CC10FA2044A3C60003C045 /* Release */, - 338D0CE9231458BD00FA5F75 /* Profile */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 33CC10FC2044A3C60003C045 /* Debug */, - 33CC10FD2044A3C60003C045 /* Release */, - 338D0CEA231458BD00FA5F75 /* Profile */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 33CC111C2044C6BA0003C045 /* Debug */, - 33CC111D2044C6BA0003C045 /* Release */, - 338D0CEB231458BD00FA5F75 /* Profile */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 33CC10E52044A3C60003C045 /* Project object */; -} diff --git a/third_party/refresh_rate/example/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/third_party/refresh_rate/example/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist deleted file mode 100644 index 18d98100..00000000 --- a/third_party/refresh_rate/example/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +++ /dev/null @@ -1,8 +0,0 @@ - - - - - IDEDidComputeMac32BitWarning - - - diff --git a/third_party/refresh_rate/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/third_party/refresh_rate/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme deleted file mode 100644 index e27790b3..00000000 --- a/third_party/refresh_rate/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ /dev/null @@ -1,99 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/third_party/refresh_rate/example/macos/Runner.xcworkspace/contents.xcworkspacedata b/third_party/refresh_rate/example/macos/Runner.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index 21a3cc14..00000000 --- a/third_party/refresh_rate/example/macos/Runner.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - diff --git a/third_party/refresh_rate/example/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/third_party/refresh_rate/example/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist deleted file mode 100644 index 18d98100..00000000 --- a/third_party/refresh_rate/example/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +++ /dev/null @@ -1,8 +0,0 @@ - - - - - IDEDidComputeMac32BitWarning - - - diff --git a/third_party/refresh_rate/example/macos/Runner/AppDelegate.swift b/third_party/refresh_rate/example/macos/Runner/AppDelegate.swift deleted file mode 100644 index b3c17614..00000000 --- a/third_party/refresh_rate/example/macos/Runner/AppDelegate.swift +++ /dev/null @@ -1,13 +0,0 @@ -import Cocoa -import FlutterMacOS - -@main -class AppDelegate: FlutterAppDelegate { - override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { - return true - } - - override func applicationSupportsSecureRestorableState(_ app: NSApplication) -> Bool { - return true - } -} diff --git a/third_party/refresh_rate/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/third_party/refresh_rate/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index a2ec33f1..00000000 --- a/third_party/refresh_rate/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,68 +0,0 @@ -{ - "images" : [ - { - "size" : "16x16", - "idiom" : "mac", - "filename" : "app_icon_16.png", - "scale" : "1x" - }, - { - "size" : "16x16", - "idiom" : "mac", - "filename" : "app_icon_32.png", - "scale" : "2x" - }, - { - "size" : "32x32", - "idiom" : "mac", - "filename" : "app_icon_32.png", - "scale" : "1x" - }, - { - "size" : "32x32", - "idiom" : "mac", - "filename" : "app_icon_64.png", - "scale" : "2x" - }, - { - "size" : "128x128", - "idiom" : "mac", - "filename" : "app_icon_128.png", - "scale" : "1x" - }, - { - "size" : "128x128", - "idiom" : "mac", - "filename" : "app_icon_256.png", - "scale" : "2x" - }, - { - "size" : "256x256", - "idiom" : "mac", - "filename" : "app_icon_256.png", - "scale" : "1x" - }, - { - "size" : "256x256", - "idiom" : "mac", - "filename" : "app_icon_512.png", - "scale" : "2x" - }, - { - "size" : "512x512", - "idiom" : "mac", - "filename" : "app_icon_512.png", - "scale" : "1x" - }, - { - "size" : "512x512", - "idiom" : "mac", - "filename" : "app_icon_1024.png", - "scale" : "2x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} diff --git a/third_party/refresh_rate/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png b/third_party/refresh_rate/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png deleted file mode 100644 index 82b6f9d9..00000000 Binary files a/third_party/refresh_rate/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png and /dev/null differ diff --git a/third_party/refresh_rate/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png b/third_party/refresh_rate/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png deleted file mode 100644 index 13b35eba..00000000 Binary files a/third_party/refresh_rate/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png and /dev/null differ diff --git a/third_party/refresh_rate/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png b/third_party/refresh_rate/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png deleted file mode 100644 index 0a3f5fa4..00000000 Binary files a/third_party/refresh_rate/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png and /dev/null differ diff --git a/third_party/refresh_rate/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png b/third_party/refresh_rate/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png deleted file mode 100644 index bdb57226..00000000 Binary files a/third_party/refresh_rate/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png and /dev/null differ diff --git a/third_party/refresh_rate/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png b/third_party/refresh_rate/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png deleted file mode 100644 index f083318e..00000000 Binary files a/third_party/refresh_rate/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png and /dev/null differ diff --git a/third_party/refresh_rate/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png b/third_party/refresh_rate/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png deleted file mode 100644 index 326c0e72..00000000 Binary files a/third_party/refresh_rate/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png and /dev/null differ diff --git a/third_party/refresh_rate/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png b/third_party/refresh_rate/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png deleted file mode 100644 index 2f1632cf..00000000 Binary files a/third_party/refresh_rate/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png and /dev/null differ diff --git a/third_party/refresh_rate/example/macos/Runner/Base.lproj/MainMenu.xib b/third_party/refresh_rate/example/macos/Runner/Base.lproj/MainMenu.xib deleted file mode 100644 index 80e867a4..00000000 --- a/third_party/refresh_rate/example/macos/Runner/Base.lproj/MainMenu.xib +++ /dev/null @@ -1,343 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/third_party/refresh_rate/example/macos/Runner/Configs/AppInfo.xcconfig b/third_party/refresh_rate/example/macos/Runner/Configs/AppInfo.xcconfig deleted file mode 100644 index ac08879f..00000000 --- a/third_party/refresh_rate/example/macos/Runner/Configs/AppInfo.xcconfig +++ /dev/null @@ -1,14 +0,0 @@ -// Application-level settings for the Runner target. -// -// This may be replaced with something auto-generated from metadata (e.g., pubspec.yaml) in the -// future. If not, the values below would default to using the project name when this becomes a -// 'flutter create' template. - -// The application's name. By default this is also the title of the Flutter window. -PRODUCT_NAME = refresh_rate_example - -// The application's bundle identifier -PRODUCT_BUNDLE_IDENTIFIER = in.qoder.refreshRateExample - -// The copyright displayed in application information -PRODUCT_COPYRIGHT = Copyright © 2026 in.qoder. All rights reserved. diff --git a/third_party/refresh_rate/example/macos/Runner/Configs/Debug.xcconfig b/third_party/refresh_rate/example/macos/Runner/Configs/Debug.xcconfig deleted file mode 100644 index 36b0fd94..00000000 --- a/third_party/refresh_rate/example/macos/Runner/Configs/Debug.xcconfig +++ /dev/null @@ -1,2 +0,0 @@ -#include "../../Flutter/Flutter-Debug.xcconfig" -#include "Warnings.xcconfig" diff --git a/third_party/refresh_rate/example/macos/Runner/Configs/Release.xcconfig b/third_party/refresh_rate/example/macos/Runner/Configs/Release.xcconfig deleted file mode 100644 index dff4f495..00000000 --- a/third_party/refresh_rate/example/macos/Runner/Configs/Release.xcconfig +++ /dev/null @@ -1,2 +0,0 @@ -#include "../../Flutter/Flutter-Release.xcconfig" -#include "Warnings.xcconfig" diff --git a/third_party/refresh_rate/example/macos/Runner/Configs/Warnings.xcconfig b/third_party/refresh_rate/example/macos/Runner/Configs/Warnings.xcconfig deleted file mode 100644 index 42bcbf47..00000000 --- a/third_party/refresh_rate/example/macos/Runner/Configs/Warnings.xcconfig +++ /dev/null @@ -1,13 +0,0 @@ -WARNING_CFLAGS = -Wall -Wconditional-uninitialized -Wnullable-to-nonnull-conversion -Wmissing-method-return-type -Woverlength-strings -GCC_WARN_UNDECLARED_SELECTOR = YES -CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES -CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE -CLANG_WARN__DUPLICATE_METHOD_MATCH = YES -CLANG_WARN_PRAGMA_PACK = YES -CLANG_WARN_STRICT_PROTOTYPES = YES -CLANG_WARN_COMMA = YES -GCC_WARN_STRICT_SELECTOR_MATCH = YES -CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES -CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES -GCC_WARN_SHADOW = YES -CLANG_WARN_UNREACHABLE_CODE = YES diff --git a/third_party/refresh_rate/example/macos/Runner/DebugProfile.entitlements b/third_party/refresh_rate/example/macos/Runner/DebugProfile.entitlements deleted file mode 100644 index dddb8a30..00000000 --- a/third_party/refresh_rate/example/macos/Runner/DebugProfile.entitlements +++ /dev/null @@ -1,12 +0,0 @@ - - - - - com.apple.security.app-sandbox - - com.apple.security.cs.allow-jit - - com.apple.security.network.server - - - diff --git a/third_party/refresh_rate/example/macos/Runner/Info.plist b/third_party/refresh_rate/example/macos/Runner/Info.plist deleted file mode 100644 index 4789daa6..00000000 --- a/third_party/refresh_rate/example/macos/Runner/Info.plist +++ /dev/null @@ -1,32 +0,0 @@ - - - - - CFBundleDevelopmentRegion - $(DEVELOPMENT_LANGUAGE) - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIconFile - - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - APPL - CFBundleShortVersionString - $(FLUTTER_BUILD_NAME) - CFBundleVersion - $(FLUTTER_BUILD_NUMBER) - LSMinimumSystemVersion - $(MACOSX_DEPLOYMENT_TARGET) - NSHumanReadableCopyright - $(PRODUCT_COPYRIGHT) - NSMainNibFile - MainMenu - NSPrincipalClass - NSApplication - - diff --git a/third_party/refresh_rate/example/macos/Runner/MainFlutterWindow.swift b/third_party/refresh_rate/example/macos/Runner/MainFlutterWindow.swift deleted file mode 100644 index 3cc05eb2..00000000 --- a/third_party/refresh_rate/example/macos/Runner/MainFlutterWindow.swift +++ /dev/null @@ -1,15 +0,0 @@ -import Cocoa -import FlutterMacOS - -class MainFlutterWindow: NSWindow { - override func awakeFromNib() { - let flutterViewController = FlutterViewController() - let windowFrame = self.frame - self.contentViewController = flutterViewController - self.setFrame(windowFrame, display: true) - - RegisterGeneratedPlugins(registry: flutterViewController) - - super.awakeFromNib() - } -} diff --git a/third_party/refresh_rate/example/macos/Runner/Release.entitlements b/third_party/refresh_rate/example/macos/Runner/Release.entitlements deleted file mode 100644 index 852fa1a4..00000000 --- a/third_party/refresh_rate/example/macos/Runner/Release.entitlements +++ /dev/null @@ -1,8 +0,0 @@ - - - - - com.apple.security.app-sandbox - - - diff --git a/third_party/refresh_rate/example/macos/RunnerTests/RunnerTests.swift b/third_party/refresh_rate/example/macos/RunnerTests/RunnerTests.swift deleted file mode 100644 index 61f3bd1f..00000000 --- a/third_party/refresh_rate/example/macos/RunnerTests/RunnerTests.swift +++ /dev/null @@ -1,12 +0,0 @@ -import Cocoa -import FlutterMacOS -import XCTest - -class RunnerTests: XCTestCase { - - func testExample() { - // If you add code to the Runner application, consider adding tests here. - // See https://developer.apple.com/documentation/xctest for more information about using XCTest. - } - -} diff --git a/third_party/refresh_rate/example/pubspec.yaml b/third_party/refresh_rate/example/pubspec.yaml deleted file mode 100644 index 83af76af..00000000 --- a/third_party/refresh_rate/example/pubspec.yaml +++ /dev/null @@ -1,23 +0,0 @@ -name: refresh_rate_example -description: Example app demonstrating the refresh_rate plugin. -publish_to: 'none' -version: 1.0.0+1 - -environment: - sdk: ^3.5.0 - -dependencies: - flutter: - sdk: flutter - refresh_rate: - path: ../ - -dev_dependencies: - flutter_test: - sdk: flutter - integration_test: - sdk: flutter - flutter_lints: ^5.0.0 - -flutter: - uses-material-design: true diff --git a/third_party/refresh_rate/example/test/widget_test.dart b/third_party/refresh_rate/example/test/widget_test.dart deleted file mode 100644 index 7512d156..00000000 --- a/third_party/refresh_rate/example/test/widget_test.dart +++ /dev/null @@ -1,11 +0,0 @@ -import 'package:flutter_test/flutter_test.dart'; - -import 'package:refresh_rate_example/main.dart'; - -void main() { - testWidgets('App smoke test', (WidgetTester tester) async { - await tester.pumpWidget(const RefreshRateExampleApp()); - expect(find.text('Diagnostic Console'), findsOneWidget); - expect(find.text('Display Info'), findsOneWidget); - }); -} diff --git a/third_party/refresh_rate/example/test_driver/integration_test.dart b/third_party/refresh_rate/example/test_driver/integration_test.dart deleted file mode 100644 index 79c2b403..00000000 --- a/third_party/refresh_rate/example/test_driver/integration_test.dart +++ /dev/null @@ -1,30 +0,0 @@ -import 'dart:io'; - -import 'package:integration_test/integration_test_driver_extended.dart'; - -/// Flutter Drive driver for screenshot capture. -/// -/// Receives screenshot bytes from the device and writes them to the package -/// root `screenshots/` directory (one level up from `example/`). -/// -/// Run from the package root via `scripts/take_screenshots.sh`, or manually: -/// -/// cd example -/// flutter drive \ -/// --driver=test_driver/integration_test.dart \ -/// --target=integration_test/screenshot_test.dart \ -/// -d [device-id] -Future main() => integrationDriver( - onScreenshot: ( - String name, - List screenshotBytes, [ - Map? args, - ]) async { - final dir = Directory('../screenshots'); - if (!dir.existsSync()) dir.createSync(recursive: true); - final file = File('../screenshots/$name.png'); - await file.writeAsBytes(screenshotBytes); - stdout.writeln(' screenshot saved → screenshots/$name.png'); - return true; - }, - ); diff --git a/third_party/refresh_rate/example/web/favicon.png b/third_party/refresh_rate/example/web/favicon.png deleted file mode 100644 index 8aaa46ac..00000000 Binary files a/third_party/refresh_rate/example/web/favicon.png and /dev/null differ diff --git a/third_party/refresh_rate/example/web/icons/Icon-192.png b/third_party/refresh_rate/example/web/icons/Icon-192.png deleted file mode 100644 index b749bfef..00000000 Binary files a/third_party/refresh_rate/example/web/icons/Icon-192.png and /dev/null differ diff --git a/third_party/refresh_rate/example/web/icons/Icon-512.png b/third_party/refresh_rate/example/web/icons/Icon-512.png deleted file mode 100644 index 88cfd48d..00000000 Binary files a/third_party/refresh_rate/example/web/icons/Icon-512.png and /dev/null differ diff --git a/third_party/refresh_rate/example/web/icons/Icon-maskable-192.png b/third_party/refresh_rate/example/web/icons/Icon-maskable-192.png deleted file mode 100644 index eb9b4d76..00000000 Binary files a/third_party/refresh_rate/example/web/icons/Icon-maskable-192.png and /dev/null differ diff --git a/third_party/refresh_rate/example/web/icons/Icon-maskable-512.png b/third_party/refresh_rate/example/web/icons/Icon-maskable-512.png deleted file mode 100644 index d69c5669..00000000 Binary files a/third_party/refresh_rate/example/web/icons/Icon-maskable-512.png and /dev/null differ diff --git a/third_party/refresh_rate/example/web/index.html b/third_party/refresh_rate/example/web/index.html deleted file mode 100644 index 2b81a3a0..00000000 --- a/third_party/refresh_rate/example/web/index.html +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - - - - - - - - - - - - - - - refresh_rate_example - - - - - - - diff --git a/third_party/refresh_rate/example/web/manifest.json b/third_party/refresh_rate/example/web/manifest.json deleted file mode 100644 index dca8856b..00000000 --- a/third_party/refresh_rate/example/web/manifest.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "name": "refresh_rate_example", - "short_name": "refresh_rate_example", - "start_url": ".", - "display": "standalone", - "background_color": "#0175C2", - "theme_color": "#0175C2", - "description": "A new Flutter project.", - "orientation": "portrait-primary", - "prefer_related_applications": false, - "icons": [ - { - "src": "icons/Icon-192.png", - "sizes": "192x192", - "type": "image/png" - }, - { - "src": "icons/Icon-512.png", - "sizes": "512x512", - "type": "image/png" - }, - { - "src": "icons/Icon-maskable-192.png", - "sizes": "192x192", - "type": "image/png", - "purpose": "maskable" - }, - { - "src": "icons/Icon-maskable-512.png", - "sizes": "512x512", - "type": "image/png", - "purpose": "maskable" - } - ] -} diff --git a/third_party/refresh_rate/example/windows/CMakeLists.txt b/third_party/refresh_rate/example/windows/CMakeLists.txt deleted file mode 100644 index 6130394e..00000000 --- a/third_party/refresh_rate/example/windows/CMakeLists.txt +++ /dev/null @@ -1,108 +0,0 @@ -# Project-level configuration. -cmake_minimum_required(VERSION 3.14) -project(refresh_rate_example 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 "refresh_rate_example") - -# 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/third_party/refresh_rate/example/windows/flutter/CMakeLists.txt b/third_party/refresh_rate/example/windows/flutter/CMakeLists.txt deleted file mode 100644 index 903f4899..00000000 --- a/third_party/refresh_rate/example/windows/flutter/CMakeLists.txt +++ /dev/null @@ -1,109 +0,0 @@ -# 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/third_party/refresh_rate/example/windows/flutter/generated_plugin_registrant.cc b/third_party/refresh_rate/example/windows/flutter/generated_plugin_registrant.cc deleted file mode 100644 index 31208abc..00000000 --- a/third_party/refresh_rate/example/windows/flutter/generated_plugin_registrant.cc +++ /dev/null @@ -1,14 +0,0 @@ -// -// Generated file. Do not edit. -// - -// clang-format off - -#include "generated_plugin_registrant.h" - -#include - -void RegisterPlugins(flutter::PluginRegistry* registry) { - RefreshRatePluginCApiRegisterWithRegistrar( - registry->GetRegistrarForPlugin("RefreshRatePluginCApi")); -} diff --git a/third_party/refresh_rate/example/windows/flutter/generated_plugin_registrant.h b/third_party/refresh_rate/example/windows/flutter/generated_plugin_registrant.h deleted file mode 100644 index dc139d85..00000000 --- a/third_party/refresh_rate/example/windows/flutter/generated_plugin_registrant.h +++ /dev/null @@ -1,15 +0,0 @@ -// -// 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/third_party/refresh_rate/example/windows/flutter/generated_plugins.cmake b/third_party/refresh_rate/example/windows/flutter/generated_plugins.cmake deleted file mode 100644 index c7644834..00000000 --- a/third_party/refresh_rate/example/windows/flutter/generated_plugins.cmake +++ /dev/null @@ -1,24 +0,0 @@ -# -# Generated file, do not edit. -# - -list(APPEND FLUTTER_PLUGIN_LIST - refresh_rate -) - -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/third_party/refresh_rate/example/windows/runner/CMakeLists.txt b/third_party/refresh_rate/example/windows/runner/CMakeLists.txt deleted file mode 100644 index 394917c0..00000000 --- a/third_party/refresh_rate/example/windows/runner/CMakeLists.txt +++ /dev/null @@ -1,40 +0,0 @@ -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/third_party/refresh_rate/example/windows/runner/Runner.rc b/third_party/refresh_rate/example/windows/runner/Runner.rc deleted file mode 100644 index cba01e6a..00000000 --- a/third_party/refresh_rate/example/windows/runner/Runner.rc +++ /dev/null @@ -1,121 +0,0 @@ -// 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", "in.qoder" "\0" - VALUE "FileDescription", "refresh_rate_example" "\0" - VALUE "FileVersion", VERSION_AS_STRING "\0" - VALUE "InternalName", "refresh_rate_example" "\0" - VALUE "LegalCopyright", "Copyright (C) 2026 in.qoder. All rights reserved." "\0" - VALUE "OriginalFilename", "refresh_rate_example.exe" "\0" - VALUE "ProductName", "refresh_rate_example" "\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/third_party/refresh_rate/example/windows/runner/flutter_window.cpp b/third_party/refresh_rate/example/windows/runner/flutter_window.cpp deleted file mode 100644 index 955ee303..00000000 --- a/third_party/refresh_rate/example/windows/runner/flutter_window.cpp +++ /dev/null @@ -1,71 +0,0 @@ -#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/third_party/refresh_rate/example/windows/runner/flutter_window.h b/third_party/refresh_rate/example/windows/runner/flutter_window.h deleted file mode 100644 index 6da0652f..00000000 --- a/third_party/refresh_rate/example/windows/runner/flutter_window.h +++ /dev/null @@ -1,33 +0,0 @@ -#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/third_party/refresh_rate/example/windows/runner/main.cpp b/third_party/refresh_rate/example/windows/runner/main.cpp deleted file mode 100644 index 9f77364f..00000000 --- a/third_party/refresh_rate/example/windows/runner/main.cpp +++ /dev/null @@ -1,43 +0,0 @@ -#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"refresh_rate_example", 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/third_party/refresh_rate/example/windows/runner/resource.h b/third_party/refresh_rate/example/windows/runner/resource.h deleted file mode 100644 index 66a65d1e..00000000 --- a/third_party/refresh_rate/example/windows/runner/resource.h +++ /dev/null @@ -1,16 +0,0 @@ -//{{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/third_party/refresh_rate/example/windows/runner/resources/app_icon.ico b/third_party/refresh_rate/example/windows/runner/resources/app_icon.ico deleted file mode 100644 index c04e20ca..00000000 Binary files a/third_party/refresh_rate/example/windows/runner/resources/app_icon.ico and /dev/null differ diff --git a/third_party/refresh_rate/example/windows/runner/runner.exe.manifest b/third_party/refresh_rate/example/windows/runner/runner.exe.manifest deleted file mode 100644 index 153653e8..00000000 --- a/third_party/refresh_rate/example/windows/runner/runner.exe.manifest +++ /dev/null @@ -1,14 +0,0 @@ - - - - - PerMonitorV2 - - - - - - - - - diff --git a/third_party/refresh_rate/example/windows/runner/utils.cpp b/third_party/refresh_rate/example/windows/runner/utils.cpp deleted file mode 100644 index 3a0b4651..00000000 --- a/third_party/refresh_rate/example/windows/runner/utils.cpp +++ /dev/null @@ -1,65 +0,0 @@ -#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/third_party/refresh_rate/example/windows/runner/utils.h b/third_party/refresh_rate/example/windows/runner/utils.h deleted file mode 100644 index 3879d547..00000000 --- a/third_party/refresh_rate/example/windows/runner/utils.h +++ /dev/null @@ -1,19 +0,0 @@ -#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/third_party/refresh_rate/example/windows/runner/win32_window.cpp b/third_party/refresh_rate/example/windows/runner/win32_window.cpp deleted file mode 100644 index 60608d0f..00000000 --- a/third_party/refresh_rate/example/windows/runner/win32_window.cpp +++ /dev/null @@ -1,288 +0,0 @@ -#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/third_party/refresh_rate/example/windows/runner/win32_window.h b/third_party/refresh_rate/example/windows/runner/win32_window.h deleted file mode 100644 index e901dde6..00000000 --- a/third_party/refresh_rate/example/windows/runner/win32_window.h +++ /dev/null @@ -1,102 +0,0 @@ -#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_ diff --git a/third_party/refresh_rate/ios/Classes/DisplayLinkSwizzle.h b/third_party/refresh_rate/ios/Classes/DisplayLinkSwizzle.h deleted file mode 100644 index c3fcdbdb..00000000 --- a/third_party/refresh_rate/ios/Classes/DisplayLinkSwizzle.h +++ /dev/null @@ -1,14 +0,0 @@ -#import - -/// Set the max frame rate cap for all display links. Pass 0 to disable. -void RRSetOverrideMaxRate(float rate); - -/// Get the current override max rate. 0 means no override. -float RRGetOverrideMaxRate(void); - -/// Tag a display link so the swizzle bypasses it (for monitoring/boost links). -void RRBypassDisplayLink(CADisplayLink * _Nonnull link); - -/// Apply the current override to all tracked (non-bypassed) display links. -/// Call this after changing the override rate. -void RRApplyOverrideToTrackedLinks(void); diff --git a/third_party/refresh_rate/ios/Classes/DisplayLinkSwizzle.m b/third_party/refresh_rate/ios/Classes/DisplayLinkSwizzle.m deleted file mode 100644 index 255cfcf4..00000000 --- a/third_party/refresh_rate/ios/Classes/DisplayLinkSwizzle.m +++ /dev/null @@ -1,186 +0,0 @@ -#import -#import - -// Key for tagging display links that should bypass the override. -static const void *RRBypassKey = &RRBypassKey; -// Key for storing the original (uncapped) frame rate range. -static const void *RROriginalRangeKey = &RROriginalRangeKey; - -/// Global override cap. 0 means no override (pass through). -static float _rr_overrideMaxRate = 0; - -/// Storage for tracked display links (weak-ish — we check validity). -static NSPointerArray *_rr_trackedLinks = nil; -static NSLock *_rr_lock = nil; - -// Store original IMPs — declared early so swizzled functions can reference them. -static IMP _rr_origAddToRunLoop = NULL; -static IMP _rr_origSetRange = NULL; - -#pragma mark - Public C interface (called from Swift) - -/// Set the max frame rate cap. Pass 0 to disable. -void RRSetOverrideMaxRate(float rate) { - _rr_overrideMaxRate = rate; -} - -float RRGetOverrideMaxRate(void) { - return _rr_overrideMaxRate; -} - -/// Tag a display link so the swizzle bypasses it. -void RRBypassDisplayLink(CADisplayLink *link) { - objc_setAssociatedObject(link, RRBypassKey, @YES, OBJC_ASSOCIATION_RETAIN_NONATOMIC); -} - -/// Apply the current override to all tracked display links. -void RRApplyOverrideToTrackedLinks(void) { - if (!_rr_lock) return; - - [_rr_lock lock]; - - // Compact nil refs - [_rr_trackedLinks compact]; - - NSUInteger count = [_rr_trackedLinks count]; - for (NSUInteger i = 0; i < count; i++) { - CADisplayLink *link = [_rr_trackedLinks pointerAtIndex:i]; - if (!link) continue; - - // Skip bypassed links - if (objc_getAssociatedObject(link, RRBypassKey)) continue; - - if (@available(iOS 15.0, *)) { - // Read stored original range - NSDictionary *stored = objc_getAssociatedObject(link, RROriginalRangeKey); - - float cap = _rr_overrideMaxRate; - - if (cap > 0 && stored) { - float origMin = [stored[@"min"] floatValue]; - float origMax = [stored[@"max"] floatValue]; - float origPref = [stored[@"preferred"] floatValue]; - CAFrameRateRange capped = CAFrameRateRangeMake( - fminf(origMin, cap), - fminf(origMax, cap), - fminf(origPref, cap) - ); - // Use original IMP directly to avoid re-triggering our swizzle - // (which would overwrite the stored original with the capped value) - SEL sel = NSSelectorFromString(@"setPreferredFrameRateRange:"); - if (_rr_origSetRange) { - ((void (*)(id, SEL, CAFrameRateRange))_rr_origSetRange)(link, sel, capped); - } - } else if (cap <= 0 && stored) { - // Restore original - float origMin = [stored[@"min"] floatValue]; - float origMax = [stored[@"max"] floatValue]; - float origPref = [stored[@"preferred"] floatValue]; - SEL sel = NSSelectorFromString(@"setPreferredFrameRateRange:"); - if (_rr_origSetRange) { - ((void (*)(id, SEL, CAFrameRateRange))_rr_origSetRange)(link, sel, CAFrameRateRangeMake(origMin, origMax, origPref)); - } - } - } - } - - [_rr_lock unlock]; -} - -#pragma mark - Swizzled implementations - -/// Swizzled addToRunLoop:forMode: — tracks every display link. -static void rr_addToRunLoop(CADisplayLink *self, SEL _cmd, NSRunLoop *runloop, NSRunLoopMode mode) { - // Track this link - [_rr_lock lock]; - if (_rr_trackedLinks) { - // Check not already tracked - BOOL found = NO; - [_rr_trackedLinks compact]; - for (NSUInteger i = 0; i < [_rr_trackedLinks count]; i++) { - if ([_rr_trackedLinks pointerAtIndex:i] == (__bridge void *)self) { - found = YES; - break; - } - } - if (!found) { - [_rr_trackedLinks addPointer:(__bridge void *)self]; - } - } - [_rr_lock unlock]; - - // Call original — the IMP was saved during swizzle - ((void (*)(id, SEL, NSRunLoop *, NSRunLoopMode))_rr_origAddToRunLoop)(self, _cmd, runloop, mode); -} - -/// Swizzled setPreferredFrameRateRange: — stores original range and applies cap. -static void rr_setPreferredFrameRateRange(CADisplayLink *self, SEL _cmd, CAFrameRateRange range) { - // Bypass tagged links - if (objc_getAssociatedObject(self, RRBypassKey)) { - ((void (*)(id, SEL, CAFrameRateRange))_rr_origSetRange)(self, _cmd, range); - return; - } - - // Store original range - if (@available(iOS 15.0, *)) { - NSDictionary *stored = @{ - @"min": @(range.minimum), - @"max": @(range.maximum), - @"preferred": @(range.preferred), - }; - objc_setAssociatedObject(self, RROriginalRangeKey, stored, OBJC_ASSOCIATION_RETAIN_NONATOMIC); - } - - // Apply cap if active - float cap = _rr_overrideMaxRate; - if (cap > 0) { - if (@available(iOS 15.0, *)) { - CAFrameRateRange capped = CAFrameRateRangeMake( - fminf(range.minimum, cap), - fminf(range.maximum, cap), - fminf(range.preferred, cap) - ); - ((void (*)(id, SEL, CAFrameRateRange))_rr_origSetRange)(self, _cmd, capped); - } else { - ((void (*)(id, SEL, CAFrameRateRange))_rr_origSetRange)(self, _cmd, range); - } - } else { - ((void (*)(id, SEL, CAFrameRateRange))_rr_origSetRange)(self, _cmd, range); - } -} - -#pragma mark - +load (runs before main, before Flutter engine starts) - -@interface RRDisplayLinkSwizzle : NSObject -@end - -@implementation RRDisplayLinkSwizzle - -+ (void)load { - _rr_trackedLinks = [NSPointerArray weakObjectsPointerArray]; - _rr_lock = [[NSLock alloc] init]; - - Class cls = [CADisplayLink class]; - - // Swizzle addToRunLoop:forMode: - { - SEL sel = @selector(addToRunLoop:forMode:); - Method method = class_getInstanceMethod(cls, sel); - if (method) { - _rr_origAddToRunLoop = method_getImplementation(method); - method_setImplementation(method, (IMP)rr_addToRunLoop); - } - } - - // Swizzle setPreferredFrameRateRange: (iOS 15+) - if (@available(iOS 15.0, *)) { - SEL sel = NSSelectorFromString(@"setPreferredFrameRateRange:"); - Method method = class_getInstanceMethod(cls, sel); - if (method) { - _rr_origSetRange = method_getImplementation(method); - method_setImplementation(method, (IMP)rr_setPreferredFrameRateRange); - } - } -} - -@end diff --git a/third_party/refresh_rate/ios/Classes/RefreshRatePlugin.swift b/third_party/refresh_rate/ios/Classes/RefreshRatePlugin.swift deleted file mode 100644 index 1e0d806c..00000000 --- a/third_party/refresh_rate/ios/Classes/RefreshRatePlugin.swift +++ /dev/null @@ -1,210 +0,0 @@ -import Flutter -import UIKit -import QuartzCore - -public class RefreshRatePlugin: NSObject, FlutterPlugin, RefreshRateHostApi { - - private var flutterApi: RefreshRateFlutterApi? - private var displayLink: CADisplayLink? - private var boostDisplayLink: CADisplayLink? - private var lastReportedRate: Double = 0 - private var powerObserver: NSObjectProtocol? - private var thermalObserver: NSObjectProtocol? - - public static func register(with registrar: FlutterPluginRegistrar) { - let instance = RefreshRatePlugin() - RefreshRateHostApiSetup.setUp(binaryMessenger: registrar.messenger(), api: instance) - instance.flutterApi = RefreshRateFlutterApi(binaryMessenger: registrar.messenger()) - instance.startMonitoring() - } - - // MARK: - RefreshRateHostApi - - func getDisplayInfo() throws -> DisplayInfoMessage { - let maxRate = getMaxRefreshRate() - let currentRate = getCurrentRefreshRate() - let proMotion = isProMotionPlistKeySet() - let isLow = ProcessInfo.processInfo.isLowPowerModeEnabled - let thermal = thermalIndex() - - return DisplayInfoMessage( - currentRate: currentRate, - maxRate: maxRate, - minRate: 60.0, - supportedRates: getSupportedRefreshRates(), - isVariableRefreshRate: maxRate > 60, - engineTargetRate: currentRate, - iosProMotionEnabled: proMotion, - androidApiLevel: nil, - isLowPowerMode: isLow, - thermalStateIndex: thermal, - hasAdaptiveRefreshRate: maxRate > 60, - displayServer: nil, - monitorCount: nil - ) - } - - func enable() throws { try setToMax(forceHighest: false) } - func disable() throws { resetCap() } - func preferMax() throws { try setToMax(forceHighest: false) } - func preferDefault() throws { resetCap() } - - func matchContent(fps: Double) throws { - guard #available(iOS 15.0, *) else { return } - let maxRate = getMaxRefreshRate() - let multiple = max(1.0, (maxRate / fps).rounded(.down)) - let preferredMax = fps * multiple - RRSetOverrideMaxRate(Float(fps)) - RRApplyOverrideToTrackedLinks() - setupBoostDisplayLink(min: fps, max: preferredMax, preferred: preferredMax) - } - - func boost(durationMs: Int64) throws { - guard #available(iOS 15.0, *) else { return } - let maxRate = getMaxRefreshRate() - RRSetOverrideMaxRate(0) - RRApplyOverrideToTrackedLinks() - setupBoostDisplayLink(min: max(maxRate * 0.66, 60.0), max: maxRate, preferred: maxRate) - DispatchQueue.main.asyncAfter(deadline: .now() + Double(durationMs) / 1000.0) { - self.removeBoostDisplayLink() - RRSetOverrideMaxRate(0) - RRApplyOverrideToTrackedLinks() - } - } - - func setCategory(categoryIndex: Int64) throws { - switch categoryIndex { - case 3: try? enable() - case 0, 1: try? disable() - default: break - } - } - - func setTouchBoost(enabled: Bool) throws { - // No iOS equivalent; no-op - } - - func isSupported() throws -> Bool { - if #available(iOS 15.0, *) { return getMaxRefreshRate() > 60 } - return false - } - - // MARK: - Private control - - private func setToMax(forceHighest: Bool) throws { - let maxRate = getMaxRefreshRate() - let isPad = UIDevice.current.userInterfaceIdiom == .pad - let unlocked = isProMotionPlistKeySet() || isPad - if !unlocked { logPlistWarning(maxRate: maxRate) } - guard #available(iOS 15.0, *) else { return } - RRSetOverrideMaxRate(0) - RRApplyOverrideToTrackedLinks() - if forceHighest { - setupBoostDisplayLink(min: max(maxRate * 0.66, 60.0), max: maxRate, preferred: maxRate) - } else { - removeBoostDisplayLink() - } - } - - private func resetCap() { - RRSetOverrideMaxRate(60.0) - RRApplyOverrideToTrackedLinks() - removeBoostDisplayLink() - } - - // MARK: - Boost display link - - @available(iOS 15.0, *) - private func setupBoostDisplayLink(min: Double, max: Double, preferred: Double) { - removeBoostDisplayLink() - let link = CADisplayLink(target: self, selector: #selector(boostFired)) - RRBypassDisplayLink(link) - link.preferredFrameRateRange = CAFrameRateRange( - minimum: Float(min), maximum: Float(max), preferred: Float(preferred)) - link.add(to: .main, forMode: .common) - boostDisplayLink = link - } - - private func removeBoostDisplayLink() { - boostDisplayLink?.invalidate() - boostDisplayLink = nil - } - - @objc private func boostFired(_ link: CADisplayLink) {} - - // MARK: - Monitoring - - @objc private func monitorLinkFired(_ link: CADisplayLink) { - let rate = link.duration > 0 ? 1.0 / link.duration : 60.0 - if abs(rate - lastReportedRate) > 5.0 { - lastReportedRate = rate - let info = (try? getDisplayInfo()) ?? DisplayInfoMessage( - currentRate: rate, maxRate: rate, minRate: 60.0, - supportedRates: [60.0, rate], isVariableRefreshRate: rate > 60, - engineTargetRate: rate, iosProMotionEnabled: nil, - androidApiLevel: nil, isLowPowerMode: nil, - thermalStateIndex: nil, hasAdaptiveRefreshRate: nil, - displayServer: nil, monitorCount: nil) - flutterApi?.onDisplayInfoChanged(info: info) { _ in } - } - } - - private func startMonitoring() { - if displayLink == nil { - let link = CADisplayLink(target: self, selector: #selector(monitorLinkFired)) - RRBypassDisplayLink(link) - link.add(to: .main, forMode: .common) - displayLink = link - } - powerObserver = NotificationCenter.default.addObserver( - forName: .NSProcessInfoPowerStateDidChange, object: nil, queue: .main) { [weak self] _ in - guard let info = try? self?.getDisplayInfo() else { return } - self?.flutterApi?.onDisplayInfoChanged(info: info) { _ in } - } - thermalObserver = NotificationCenter.default.addObserver( - forName: ProcessInfo.thermalStateDidChangeNotification, object: nil, queue: .main) { [weak self] _ in - guard let info = try? self?.getDisplayInfo() else { return } - self?.flutterApi?.onDisplayInfoChanged(info: info) { _ in } - } - } - - // MARK: - Helpers - - private func getMaxRefreshRate() -> Double { Double(UIScreen.main.maximumFramesPerSecond) } - - private func getCurrentRefreshRate() -> Double { - if let link = displayLink, link.duration > 0 { return 1.0 / link.duration } - let max = getMaxRefreshRate() - let isPad = UIDevice.current.userInterfaceIdiom == .pad - return (max > 60 && (isProMotionPlistKeySet() || isPad)) ? max : 60.0 - } - - private func getSupportedRefreshRates() -> [Double] { - let max = getMaxRefreshRate() - return max > 60 ? [60.0, max] : [60.0] - } - - private func isProMotionPlistKeySet() -> Bool { - return Bundle.main.object(forInfoDictionaryKey: "CADisableMinimumFrameDurationOnPhone") as? Bool ?? false - } - - private func thermalIndex() -> Int64? { - switch ProcessInfo.processInfo.thermalState { - case .nominal: return 0 - case .fair: return 1 - case .serious: return 2 - case .critical: return 3 - @unknown default: return nil - } - } - - private func logPlistWarning(maxRate: Double) { - print(""" - ⚠️ [refresh_rate] CADisableMinimumFrameDurationOnPhone not set in Info.plist! - App is locked to 60Hz on this \(maxRate)Hz device. - Add to ios/Runner/Info.plist: - CADisableMinimumFrameDurationOnPhone - - """) - } -} diff --git a/third_party/refresh_rate/ios/Classes/generated/RefreshRateApi.swift b/third_party/refresh_rate/ios/Classes/generated/RefreshRateApi.swift deleted file mode 100644 index 70c230c8..00000000 --- a/third_party/refresh_rate/ios/Classes/generated/RefreshRateApi.swift +++ /dev/null @@ -1,369 +0,0 @@ -// Copyright 2026 Qoder (qoder.in). All rights reserved. -// Use of this source code is governed by a BSD-style license. -// Autogenerated from Pigeon (v22.7.4), do not edit directly. -// See also: https://pub.dev/packages/pigeon - -import Foundation - -#if os(iOS) - import Flutter -#elseif os(macOS) - import FlutterMacOS -#else - #error("Unsupported platform.") -#endif - -/// Error class for passing custom error details to Dart side. -final class PigeonError: Error { - let code: String - let message: String? - let details: Any? - - init(code: String, message: String?, details: Any?) { - self.code = code - self.message = message - self.details = details - } - - var localizedDescription: String { - return - "PigeonError(code: \(code), message: \(message ?? ""), details: \(details ?? "")" - } -} - -private func wrapResult(_ result: Any?) -> [Any?] { - return [result] -} - -private func wrapError(_ error: Any) -> [Any?] { - if let pigeonError = error as? PigeonError { - return [ - pigeonError.code, - pigeonError.message, - pigeonError.details, - ] - } - if let flutterError = error as? FlutterError { - return [ - flutterError.code, - flutterError.message, - flutterError.details, - ] - } - return [ - "\(error)", - "\(type(of: error))", - "Stacktrace: \(Thread.callStackSymbols)", - ] -} - -private func createConnectionError(withChannelName channelName: String) -> PigeonError { - return PigeonError(code: "channel-error", message: "Unable to establish connection on channel: '\(channelName)'.", details: "") -} - -private func isNullish(_ value: Any?) -> Bool { - return value is NSNull || value == nil -} - -private func nilOrValue(_ value: Any?) -> T? { - if value is NSNull { return nil } - return value as! T? -} - -/// Generated class from Pigeon that represents data sent in messages. -struct DisplayInfoMessage { - var currentRate: Double? = nil - var maxRate: Double? = nil - var minRate: Double? = nil - var supportedRates: [Double?]? = nil - var isVariableRefreshRate: Bool? = nil - var engineTargetRate: Double? = nil - var iosProMotionEnabled: Bool? = nil - var androidApiLevel: Int64? = nil - var isLowPowerMode: Bool? = nil - var thermalStateIndex: Int64? = nil - var hasAdaptiveRefreshRate: Bool? = nil - var displayServer: String? = nil - var monitorCount: Int64? = nil - - - // swift-format-ignore: AlwaysUseLowerCamelCase - static func fromList(_ pigeonVar_list: [Any?]) -> DisplayInfoMessage? { - let currentRate: Double? = nilOrValue(pigeonVar_list[0]) - let maxRate: Double? = nilOrValue(pigeonVar_list[1]) - let minRate: Double? = nilOrValue(pigeonVar_list[2]) - let supportedRates: [Double?]? = nilOrValue(pigeonVar_list[3]) - let isVariableRefreshRate: Bool? = nilOrValue(pigeonVar_list[4]) - let engineTargetRate: Double? = nilOrValue(pigeonVar_list[5]) - let iosProMotionEnabled: Bool? = nilOrValue(pigeonVar_list[6]) - let androidApiLevel: Int64? = nilOrValue(pigeonVar_list[7]) - let isLowPowerMode: Bool? = nilOrValue(pigeonVar_list[8]) - let thermalStateIndex: Int64? = nilOrValue(pigeonVar_list[9]) - let hasAdaptiveRefreshRate: Bool? = nilOrValue(pigeonVar_list[10]) - let displayServer: String? = nilOrValue(pigeonVar_list[11]) - let monitorCount: Int64? = nilOrValue(pigeonVar_list[12]) - - return DisplayInfoMessage( - currentRate: currentRate, - maxRate: maxRate, - minRate: minRate, - supportedRates: supportedRates, - isVariableRefreshRate: isVariableRefreshRate, - engineTargetRate: engineTargetRate, - iosProMotionEnabled: iosProMotionEnabled, - androidApiLevel: androidApiLevel, - isLowPowerMode: isLowPowerMode, - thermalStateIndex: thermalStateIndex, - hasAdaptiveRefreshRate: hasAdaptiveRefreshRate, - displayServer: displayServer, - monitorCount: monitorCount - ) - } - func toList() -> [Any?] { - return [ - currentRate, - maxRate, - minRate, - supportedRates, - isVariableRefreshRate, - engineTargetRate, - iosProMotionEnabled, - androidApiLevel, - isLowPowerMode, - thermalStateIndex, - hasAdaptiveRefreshRate, - displayServer, - monitorCount, - ] - } -} - -private class RefreshRateApiPigeonCodecReader: FlutterStandardReader { - override func readValue(ofType type: UInt8) -> Any? { - switch type { - case 129: - return DisplayInfoMessage.fromList(self.readValue() as! [Any?]) - default: - return super.readValue(ofType: type) - } - } -} - -private class RefreshRateApiPigeonCodecWriter: FlutterStandardWriter { - override func writeValue(_ value: Any) { - if let value = value as? DisplayInfoMessage { - super.writeByte(129) - super.writeValue(value.toList()) - } else { - super.writeValue(value) - } - } -} - -private class RefreshRateApiPigeonCodecReaderWriter: FlutterStandardReaderWriter { - override func reader(with data: Data) -> FlutterStandardReader { - return RefreshRateApiPigeonCodecReader(data: data) - } - - override func writer(with data: NSMutableData) -> FlutterStandardWriter { - return RefreshRateApiPigeonCodecWriter(data: data) - } -} - -class RefreshRateApiPigeonCodec: FlutterStandardMessageCodec, @unchecked Sendable { - static let shared = RefreshRateApiPigeonCodec(readerWriter: RefreshRateApiPigeonCodecReaderWriter()) -} - -/// Generated protocol from Pigeon that represents a handler of messages from Flutter. -protocol RefreshRateHostApi { - func getDisplayInfo() throws -> DisplayInfoMessage - func enable() throws - func disable() throws - func preferMax() throws - func preferDefault() throws - func matchContent(fps: Double) throws - func boost(durationMs: Int64) throws - func setCategory(categoryIndex: Int64) throws - func setTouchBoost(enabled: Bool) throws - func isSupported() throws -> Bool -} - -/// Generated setup class from Pigeon to handle messages through the `binaryMessenger`. -class RefreshRateHostApiSetup { - static var codec: FlutterStandardMessageCodec { RefreshRateApiPigeonCodec.shared } - /// Sets up an instance of `RefreshRateHostApi` to handle messages through the `binaryMessenger`. - static func setUp(binaryMessenger: FlutterBinaryMessenger, api: RefreshRateHostApi?, messageChannelSuffix: String = "") { - let channelSuffix = messageChannelSuffix.count > 0 ? ".\(messageChannelSuffix)" : "" - let getDisplayInfoChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.refresh_rate.RefreshRateHostApi.getDisplayInfo\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) - if let api = api { - getDisplayInfoChannel.setMessageHandler { _, reply in - do { - let result = try api.getDisplayInfo() - reply(wrapResult(result)) - } catch { - reply(wrapError(error)) - } - } - } else { - getDisplayInfoChannel.setMessageHandler(nil) - } - let enableChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.refresh_rate.RefreshRateHostApi.enable\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) - if let api = api { - enableChannel.setMessageHandler { _, reply in - do { - try api.enable() - reply(wrapResult(nil)) - } catch { - reply(wrapError(error)) - } - } - } else { - enableChannel.setMessageHandler(nil) - } - let disableChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.refresh_rate.RefreshRateHostApi.disable\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) - if let api = api { - disableChannel.setMessageHandler { _, reply in - do { - try api.disable() - reply(wrapResult(nil)) - } catch { - reply(wrapError(error)) - } - } - } else { - disableChannel.setMessageHandler(nil) - } - let preferMaxChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.refresh_rate.RefreshRateHostApi.preferMax\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) - if let api = api { - preferMaxChannel.setMessageHandler { _, reply in - do { - try api.preferMax() - reply(wrapResult(nil)) - } catch { - reply(wrapError(error)) - } - } - } else { - preferMaxChannel.setMessageHandler(nil) - } - let preferDefaultChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.refresh_rate.RefreshRateHostApi.preferDefault\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) - if let api = api { - preferDefaultChannel.setMessageHandler { _, reply in - do { - try api.preferDefault() - reply(wrapResult(nil)) - } catch { - reply(wrapError(error)) - } - } - } else { - preferDefaultChannel.setMessageHandler(nil) - } - let matchContentChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.refresh_rate.RefreshRateHostApi.matchContent\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) - if let api = api { - matchContentChannel.setMessageHandler { message, reply in - let args = message as! [Any?] - let fpsArg = args[0] as! Double - do { - try api.matchContent(fps: fpsArg) - reply(wrapResult(nil)) - } catch { - reply(wrapError(error)) - } - } - } else { - matchContentChannel.setMessageHandler(nil) - } - let boostChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.refresh_rate.RefreshRateHostApi.boost\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) - if let api = api { - boostChannel.setMessageHandler { message, reply in - let args = message as! [Any?] - let durationMsArg = args[0] as! Int64 - do { - try api.boost(durationMs: durationMsArg) - reply(wrapResult(nil)) - } catch { - reply(wrapError(error)) - } - } - } else { - boostChannel.setMessageHandler(nil) - } - let setCategoryChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.refresh_rate.RefreshRateHostApi.setCategory\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) - if let api = api { - setCategoryChannel.setMessageHandler { message, reply in - let args = message as! [Any?] - let categoryIndexArg = args[0] as! Int64 - do { - try api.setCategory(categoryIndex: categoryIndexArg) - reply(wrapResult(nil)) - } catch { - reply(wrapError(error)) - } - } - } else { - setCategoryChannel.setMessageHandler(nil) - } - let setTouchBoostChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.refresh_rate.RefreshRateHostApi.setTouchBoost\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) - if let api = api { - setTouchBoostChannel.setMessageHandler { message, reply in - let args = message as! [Any?] - let enabledArg = args[0] as! Bool - do { - try api.setTouchBoost(enabled: enabledArg) - reply(wrapResult(nil)) - } catch { - reply(wrapError(error)) - } - } - } else { - setTouchBoostChannel.setMessageHandler(nil) - } - let isSupportedChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.refresh_rate.RefreshRateHostApi.isSupported\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) - if let api = api { - isSupportedChannel.setMessageHandler { _, reply in - do { - let result = try api.isSupported() - reply(wrapResult(result)) - } catch { - reply(wrapError(error)) - } - } - } else { - isSupportedChannel.setMessageHandler(nil) - } - } -} -/// Generated protocol from Pigeon that represents Flutter messages that can be called from Swift. -protocol RefreshRateFlutterApiProtocol { - func onDisplayInfoChanged(info infoArg: DisplayInfoMessage, completion: @escaping (Result) -> Void) -} -class RefreshRateFlutterApi: RefreshRateFlutterApiProtocol { - private let binaryMessenger: FlutterBinaryMessenger - private let messageChannelSuffix: String - init(binaryMessenger: FlutterBinaryMessenger, messageChannelSuffix: String = "") { - self.binaryMessenger = binaryMessenger - self.messageChannelSuffix = messageChannelSuffix.count > 0 ? ".\(messageChannelSuffix)" : "" - } - var codec: RefreshRateApiPigeonCodec { - return RefreshRateApiPigeonCodec.shared - } - func onDisplayInfoChanged(info infoArg: DisplayInfoMessage, completion: @escaping (Result) -> Void) { - let channelName: String = "dev.flutter.pigeon.refresh_rate.RefreshRateFlutterApi.onDisplayInfoChanged\(messageChannelSuffix)" - let channel = FlutterBasicMessageChannel(name: channelName, binaryMessenger: binaryMessenger, codec: codec) - channel.sendMessage([infoArg] as [Any?]) { response in - guard let listResponse = response as? [Any?] else { - completion(.failure(createConnectionError(withChannelName: channelName))) - return - } - if listResponse.count > 1 { - let code: String = listResponse[0] as! String - let message: String? = nilOrValue(listResponse[1]) - let details: String? = nilOrValue(listResponse[2]) - completion(.failure(PigeonError(code: code, message: message, details: details))) - } else { - completion(.success(Void())) - } - } - } -} diff --git a/third_party/refresh_rate/ios/refresh_rate.podspec b/third_party/refresh_rate/ios/refresh_rate.podspec deleted file mode 100644 index a6912cfb..00000000 --- a/third_party/refresh_rate/ios/refresh_rate.podspec +++ /dev/null @@ -1,22 +0,0 @@ -Pod::Spec.new do |s| - s.name = 'refresh_rate' - s.version = '1.0.2' - s.summary = 'Control display refresh rates in Flutter.' - s.description = <<-DESC -Cross-platform Flutter plugin to query and control display refresh rates. -Unlock high refresh rates (90Hz/120Hz/144Hz) by properly communicating -with the OS compositor — something Flutter doesn't do by default. - DESC - s.homepage = 'https://qoder.in' - s.license = { :file => '../LICENSE' } - s.author = { 'Qoder' => 'dev@qoder.in' } - s.source = { :path => '.' } - s.source_files = [ - 'refresh_rate/Sources/refresh_rate/**/*.swift', - 'refresh_rate/Sources/refresh_rate_objc/**/*.{h,m}' - ] - s.public_header_files = 'refresh_rate/Sources/refresh_rate_objc/include/**/*.h' - s.dependency 'Flutter' - s.platform = :ios, '12.0' - s.swift_version = '5.0' -end diff --git a/third_party/refresh_rate/ios/refresh_rate/Package.swift b/third_party/refresh_rate/ios/refresh_rate/Package.swift deleted file mode 100644 index 08b8c9ab..00000000 --- a/third_party/refresh_rate/ios/refresh_rate/Package.swift +++ /dev/null @@ -1,32 +0,0 @@ -// swift-tools-version: 5.9 -// The swift-tools-version declares the minimum version of Swift required to build this package. -// -import PackageDescription - -let package = Package( - name: "refresh_rate", - platforms: [ - .iOS(.v12), - ], - products: [ - .library(name: "refresh-rate", targets: ["refresh_rate"]), - ], - dependencies: [ - .package(name: "FlutterFramework", path: "../FlutterFramework"), - ], - targets: [ - .target( - name: "refresh_rate_objc", - path: "Sources/refresh_rate_objc", - publicHeadersPath: "include" - ), - .target( - name: "refresh_rate", - dependencies: [ - "refresh_rate_objc", - .product(name: "FlutterFramework", package: "FlutterFramework"), - ], - path: "Sources/refresh_rate" - ), - ] -) diff --git a/third_party/refresh_rate/ios/refresh_rate/Sources/refresh_rate/RefreshRatePlugin.swift b/third_party/refresh_rate/ios/refresh_rate/Sources/refresh_rate/RefreshRatePlugin.swift deleted file mode 100644 index 6845df98..00000000 --- a/third_party/refresh_rate/ios/refresh_rate/Sources/refresh_rate/RefreshRatePlugin.swift +++ /dev/null @@ -1,214 +0,0 @@ -import Flutter -import UIKit -import QuartzCore - -#if SWIFT_PACKAGE -import refresh_rate_objc -#endif - -public class RefreshRatePlugin: NSObject, FlutterPlugin, RefreshRateHostApi { - - private var flutterApi: RefreshRateFlutterApi? - private var displayLink: CADisplayLink? - private var boostDisplayLink: CADisplayLink? - private var lastReportedRate: Double = 0 - private var powerObserver: NSObjectProtocol? - private var thermalObserver: NSObjectProtocol? - - public static func register(with registrar: FlutterPluginRegistrar) { - let instance = RefreshRatePlugin() - RefreshRateHostApiSetup.setUp(binaryMessenger: registrar.messenger(), api: instance) - instance.flutterApi = RefreshRateFlutterApi(binaryMessenger: registrar.messenger()) - instance.startMonitoring() - } - - // MARK: - RefreshRateHostApi - - func getDisplayInfo() throws -> DisplayInfoMessage { - let maxRate = getMaxRefreshRate() - let currentRate = getCurrentRefreshRate() - let proMotion = isProMotionPlistKeySet() - let isLow = ProcessInfo.processInfo.isLowPowerModeEnabled - let thermal = thermalIndex() - - return DisplayInfoMessage( - currentRate: currentRate, - maxRate: maxRate, - minRate: 60.0, - supportedRates: getSupportedRefreshRates(), - isVariableRefreshRate: maxRate > 60, - engineTargetRate: currentRate, - iosProMotionEnabled: proMotion, - androidApiLevel: nil, - isLowPowerMode: isLow, - thermalStateIndex: thermal, - hasAdaptiveRefreshRate: maxRate > 60, - displayServer: nil, - monitorCount: nil - ) - } - - func enable() throws { try setToMax(forceHighest: false) } - func disable() throws { resetCap() } - func preferMax() throws { try setToMax(forceHighest: false) } - func preferDefault() throws { resetCap() } - - func matchContent(fps: Double) throws { - guard #available(iOS 15.0, *) else { return } - let maxRate = getMaxRefreshRate() - let multiple = max(1.0, (maxRate / fps).rounded(.down)) - let preferredMax = fps * multiple - RRSetOverrideMaxRate(Float(fps)) - RRApplyOverrideToTrackedLinks() - setupBoostDisplayLink(min: fps, max: preferredMax, preferred: preferredMax) - } - - func boost(durationMs: Int64) throws { - guard #available(iOS 15.0, *) else { return } - let maxRate = getMaxRefreshRate() - RRSetOverrideMaxRate(0) - RRApplyOverrideToTrackedLinks() - setupBoostDisplayLink(min: max(maxRate * 0.66, 60.0), max: maxRate, preferred: maxRate) - DispatchQueue.main.asyncAfter(deadline: .now() + Double(durationMs) / 1000.0) { - self.removeBoostDisplayLink() - RRSetOverrideMaxRate(0) - RRApplyOverrideToTrackedLinks() - } - } - - func setCategory(categoryIndex: Int64) throws { - switch categoryIndex { - case 3: try? enable() - case 0, 1: try? disable() - default: break - } - } - - func setTouchBoost(enabled: Bool) throws { - // No iOS equivalent; no-op - } - - func isSupported() throws -> Bool { - if #available(iOS 15.0, *) { return getMaxRefreshRate() > 60 } - return false - } - - // MARK: - Private control - - private func setToMax(forceHighest: Bool) throws { - let maxRate = getMaxRefreshRate() - let isPad = UIDevice.current.userInterfaceIdiom == .pad - let unlocked = isProMotionPlistKeySet() || isPad - if !unlocked { logPlistWarning(maxRate: maxRate) } - guard #available(iOS 15.0, *) else { return } - RRSetOverrideMaxRate(0) - RRApplyOverrideToTrackedLinks() - if forceHighest { - setupBoostDisplayLink(min: max(maxRate * 0.66, 60.0), max: maxRate, preferred: maxRate) - } else { - removeBoostDisplayLink() - } - } - - private func resetCap() { - RRSetOverrideMaxRate(60.0) - RRApplyOverrideToTrackedLinks() - removeBoostDisplayLink() - } - - // MARK: - Boost display link - - @available(iOS 15.0, *) - private func setupBoostDisplayLink(min: Double, max: Double, preferred: Double) { - removeBoostDisplayLink() - let link = CADisplayLink(target: self, selector: #selector(boostFired)) - RRBypassDisplayLink(link) - link.preferredFrameRateRange = CAFrameRateRange( - minimum: Float(min), maximum: Float(max), preferred: Float(preferred)) - link.add(to: .main, forMode: .common) - boostDisplayLink = link - } - - private func removeBoostDisplayLink() { - boostDisplayLink?.invalidate() - boostDisplayLink = nil - } - - @objc private func boostFired(_ link: CADisplayLink) {} - - // MARK: - Monitoring - - @objc private func monitorLinkFired(_ link: CADisplayLink) { - let rate = link.duration > 0 ? 1.0 / link.duration : 60.0 - if abs(rate - lastReportedRate) > 5.0 { - lastReportedRate = rate - let info = (try? getDisplayInfo()) ?? DisplayInfoMessage( - currentRate: rate, maxRate: rate, minRate: 60.0, - supportedRates: [60.0, rate], isVariableRefreshRate: rate > 60, - engineTargetRate: rate, iosProMotionEnabled: nil, - androidApiLevel: nil, isLowPowerMode: nil, - thermalStateIndex: nil, hasAdaptiveRefreshRate: nil, - displayServer: nil, monitorCount: nil) - flutterApi?.onDisplayInfoChanged(info: info) { _ in } - } - } - - private func startMonitoring() { - if displayLink == nil { - let link = CADisplayLink(target: self, selector: #selector(monitorLinkFired)) - RRBypassDisplayLink(link) - link.add(to: .main, forMode: .common) - displayLink = link - } - powerObserver = NotificationCenter.default.addObserver( - forName: .NSProcessInfoPowerStateDidChange, object: nil, queue: .main) { [weak self] _ in - guard let info = try? self?.getDisplayInfo() else { return } - self?.flutterApi?.onDisplayInfoChanged(info: info) { _ in } - } - thermalObserver = NotificationCenter.default.addObserver( - forName: ProcessInfo.thermalStateDidChangeNotification, object: nil, queue: .main) { [weak self] _ in - guard let info = try? self?.getDisplayInfo() else { return } - self?.flutterApi?.onDisplayInfoChanged(info: info) { _ in } - } - } - - // MARK: - Helpers - - private func getMaxRefreshRate() -> Double { Double(UIScreen.main.maximumFramesPerSecond) } - - private func getCurrentRefreshRate() -> Double { - if let link = displayLink, link.duration > 0 { return 1.0 / link.duration } - let max = getMaxRefreshRate() - let isPad = UIDevice.current.userInterfaceIdiom == .pad - return (max > 60 && (isProMotionPlistKeySet() || isPad)) ? max : 60.0 - } - - private func getSupportedRefreshRates() -> [Double] { - let max = getMaxRefreshRate() - return max > 60 ? [60.0, max] : [60.0] - } - - private func isProMotionPlistKeySet() -> Bool { - return Bundle.main.object(forInfoDictionaryKey: "CADisableMinimumFrameDurationOnPhone") as? Bool ?? false - } - - private func thermalIndex() -> Int64? { - switch ProcessInfo.processInfo.thermalState { - case .nominal: return 0 - case .fair: return 1 - case .serious: return 2 - case .critical: return 3 - @unknown default: return nil - } - } - - private func logPlistWarning(maxRate: Double) { - print(""" - ⚠️ [refresh_rate] CADisableMinimumFrameDurationOnPhone not set in Info.plist! - App is locked to 60Hz on this \(maxRate)Hz device. - Add to ios/Runner/Info.plist: - CADisableMinimumFrameDurationOnPhone - - """) - } -} diff --git a/third_party/refresh_rate/ios/refresh_rate/Sources/refresh_rate/generated/RefreshRateApi.swift b/third_party/refresh_rate/ios/refresh_rate/Sources/refresh_rate/generated/RefreshRateApi.swift deleted file mode 100644 index 70c230c8..00000000 --- a/third_party/refresh_rate/ios/refresh_rate/Sources/refresh_rate/generated/RefreshRateApi.swift +++ /dev/null @@ -1,369 +0,0 @@ -// Copyright 2026 Qoder (qoder.in). All rights reserved. -// Use of this source code is governed by a BSD-style license. -// Autogenerated from Pigeon (v22.7.4), do not edit directly. -// See also: https://pub.dev/packages/pigeon - -import Foundation - -#if os(iOS) - import Flutter -#elseif os(macOS) - import FlutterMacOS -#else - #error("Unsupported platform.") -#endif - -/// Error class for passing custom error details to Dart side. -final class PigeonError: Error { - let code: String - let message: String? - let details: Any? - - init(code: String, message: String?, details: Any?) { - self.code = code - self.message = message - self.details = details - } - - var localizedDescription: String { - return - "PigeonError(code: \(code), message: \(message ?? ""), details: \(details ?? "")" - } -} - -private func wrapResult(_ result: Any?) -> [Any?] { - return [result] -} - -private func wrapError(_ error: Any) -> [Any?] { - if let pigeonError = error as? PigeonError { - return [ - pigeonError.code, - pigeonError.message, - pigeonError.details, - ] - } - if let flutterError = error as? FlutterError { - return [ - flutterError.code, - flutterError.message, - flutterError.details, - ] - } - return [ - "\(error)", - "\(type(of: error))", - "Stacktrace: \(Thread.callStackSymbols)", - ] -} - -private func createConnectionError(withChannelName channelName: String) -> PigeonError { - return PigeonError(code: "channel-error", message: "Unable to establish connection on channel: '\(channelName)'.", details: "") -} - -private func isNullish(_ value: Any?) -> Bool { - return value is NSNull || value == nil -} - -private func nilOrValue(_ value: Any?) -> T? { - if value is NSNull { return nil } - return value as! T? -} - -/// Generated class from Pigeon that represents data sent in messages. -struct DisplayInfoMessage { - var currentRate: Double? = nil - var maxRate: Double? = nil - var minRate: Double? = nil - var supportedRates: [Double?]? = nil - var isVariableRefreshRate: Bool? = nil - var engineTargetRate: Double? = nil - var iosProMotionEnabled: Bool? = nil - var androidApiLevel: Int64? = nil - var isLowPowerMode: Bool? = nil - var thermalStateIndex: Int64? = nil - var hasAdaptiveRefreshRate: Bool? = nil - var displayServer: String? = nil - var monitorCount: Int64? = nil - - - // swift-format-ignore: AlwaysUseLowerCamelCase - static func fromList(_ pigeonVar_list: [Any?]) -> DisplayInfoMessage? { - let currentRate: Double? = nilOrValue(pigeonVar_list[0]) - let maxRate: Double? = nilOrValue(pigeonVar_list[1]) - let minRate: Double? = nilOrValue(pigeonVar_list[2]) - let supportedRates: [Double?]? = nilOrValue(pigeonVar_list[3]) - let isVariableRefreshRate: Bool? = nilOrValue(pigeonVar_list[4]) - let engineTargetRate: Double? = nilOrValue(pigeonVar_list[5]) - let iosProMotionEnabled: Bool? = nilOrValue(pigeonVar_list[6]) - let androidApiLevel: Int64? = nilOrValue(pigeonVar_list[7]) - let isLowPowerMode: Bool? = nilOrValue(pigeonVar_list[8]) - let thermalStateIndex: Int64? = nilOrValue(pigeonVar_list[9]) - let hasAdaptiveRefreshRate: Bool? = nilOrValue(pigeonVar_list[10]) - let displayServer: String? = nilOrValue(pigeonVar_list[11]) - let monitorCount: Int64? = nilOrValue(pigeonVar_list[12]) - - return DisplayInfoMessage( - currentRate: currentRate, - maxRate: maxRate, - minRate: minRate, - supportedRates: supportedRates, - isVariableRefreshRate: isVariableRefreshRate, - engineTargetRate: engineTargetRate, - iosProMotionEnabled: iosProMotionEnabled, - androidApiLevel: androidApiLevel, - isLowPowerMode: isLowPowerMode, - thermalStateIndex: thermalStateIndex, - hasAdaptiveRefreshRate: hasAdaptiveRefreshRate, - displayServer: displayServer, - monitorCount: monitorCount - ) - } - func toList() -> [Any?] { - return [ - currentRate, - maxRate, - minRate, - supportedRates, - isVariableRefreshRate, - engineTargetRate, - iosProMotionEnabled, - androidApiLevel, - isLowPowerMode, - thermalStateIndex, - hasAdaptiveRefreshRate, - displayServer, - monitorCount, - ] - } -} - -private class RefreshRateApiPigeonCodecReader: FlutterStandardReader { - override func readValue(ofType type: UInt8) -> Any? { - switch type { - case 129: - return DisplayInfoMessage.fromList(self.readValue() as! [Any?]) - default: - return super.readValue(ofType: type) - } - } -} - -private class RefreshRateApiPigeonCodecWriter: FlutterStandardWriter { - override func writeValue(_ value: Any) { - if let value = value as? DisplayInfoMessage { - super.writeByte(129) - super.writeValue(value.toList()) - } else { - super.writeValue(value) - } - } -} - -private class RefreshRateApiPigeonCodecReaderWriter: FlutterStandardReaderWriter { - override func reader(with data: Data) -> FlutterStandardReader { - return RefreshRateApiPigeonCodecReader(data: data) - } - - override func writer(with data: NSMutableData) -> FlutterStandardWriter { - return RefreshRateApiPigeonCodecWriter(data: data) - } -} - -class RefreshRateApiPigeonCodec: FlutterStandardMessageCodec, @unchecked Sendable { - static let shared = RefreshRateApiPigeonCodec(readerWriter: RefreshRateApiPigeonCodecReaderWriter()) -} - -/// Generated protocol from Pigeon that represents a handler of messages from Flutter. -protocol RefreshRateHostApi { - func getDisplayInfo() throws -> DisplayInfoMessage - func enable() throws - func disable() throws - func preferMax() throws - func preferDefault() throws - func matchContent(fps: Double) throws - func boost(durationMs: Int64) throws - func setCategory(categoryIndex: Int64) throws - func setTouchBoost(enabled: Bool) throws - func isSupported() throws -> Bool -} - -/// Generated setup class from Pigeon to handle messages through the `binaryMessenger`. -class RefreshRateHostApiSetup { - static var codec: FlutterStandardMessageCodec { RefreshRateApiPigeonCodec.shared } - /// Sets up an instance of `RefreshRateHostApi` to handle messages through the `binaryMessenger`. - static func setUp(binaryMessenger: FlutterBinaryMessenger, api: RefreshRateHostApi?, messageChannelSuffix: String = "") { - let channelSuffix = messageChannelSuffix.count > 0 ? ".\(messageChannelSuffix)" : "" - let getDisplayInfoChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.refresh_rate.RefreshRateHostApi.getDisplayInfo\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) - if let api = api { - getDisplayInfoChannel.setMessageHandler { _, reply in - do { - let result = try api.getDisplayInfo() - reply(wrapResult(result)) - } catch { - reply(wrapError(error)) - } - } - } else { - getDisplayInfoChannel.setMessageHandler(nil) - } - let enableChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.refresh_rate.RefreshRateHostApi.enable\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) - if let api = api { - enableChannel.setMessageHandler { _, reply in - do { - try api.enable() - reply(wrapResult(nil)) - } catch { - reply(wrapError(error)) - } - } - } else { - enableChannel.setMessageHandler(nil) - } - let disableChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.refresh_rate.RefreshRateHostApi.disable\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) - if let api = api { - disableChannel.setMessageHandler { _, reply in - do { - try api.disable() - reply(wrapResult(nil)) - } catch { - reply(wrapError(error)) - } - } - } else { - disableChannel.setMessageHandler(nil) - } - let preferMaxChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.refresh_rate.RefreshRateHostApi.preferMax\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) - if let api = api { - preferMaxChannel.setMessageHandler { _, reply in - do { - try api.preferMax() - reply(wrapResult(nil)) - } catch { - reply(wrapError(error)) - } - } - } else { - preferMaxChannel.setMessageHandler(nil) - } - let preferDefaultChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.refresh_rate.RefreshRateHostApi.preferDefault\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) - if let api = api { - preferDefaultChannel.setMessageHandler { _, reply in - do { - try api.preferDefault() - reply(wrapResult(nil)) - } catch { - reply(wrapError(error)) - } - } - } else { - preferDefaultChannel.setMessageHandler(nil) - } - let matchContentChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.refresh_rate.RefreshRateHostApi.matchContent\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) - if let api = api { - matchContentChannel.setMessageHandler { message, reply in - let args = message as! [Any?] - let fpsArg = args[0] as! Double - do { - try api.matchContent(fps: fpsArg) - reply(wrapResult(nil)) - } catch { - reply(wrapError(error)) - } - } - } else { - matchContentChannel.setMessageHandler(nil) - } - let boostChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.refresh_rate.RefreshRateHostApi.boost\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) - if let api = api { - boostChannel.setMessageHandler { message, reply in - let args = message as! [Any?] - let durationMsArg = args[0] as! Int64 - do { - try api.boost(durationMs: durationMsArg) - reply(wrapResult(nil)) - } catch { - reply(wrapError(error)) - } - } - } else { - boostChannel.setMessageHandler(nil) - } - let setCategoryChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.refresh_rate.RefreshRateHostApi.setCategory\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) - if let api = api { - setCategoryChannel.setMessageHandler { message, reply in - let args = message as! [Any?] - let categoryIndexArg = args[0] as! Int64 - do { - try api.setCategory(categoryIndex: categoryIndexArg) - reply(wrapResult(nil)) - } catch { - reply(wrapError(error)) - } - } - } else { - setCategoryChannel.setMessageHandler(nil) - } - let setTouchBoostChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.refresh_rate.RefreshRateHostApi.setTouchBoost\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) - if let api = api { - setTouchBoostChannel.setMessageHandler { message, reply in - let args = message as! [Any?] - let enabledArg = args[0] as! Bool - do { - try api.setTouchBoost(enabled: enabledArg) - reply(wrapResult(nil)) - } catch { - reply(wrapError(error)) - } - } - } else { - setTouchBoostChannel.setMessageHandler(nil) - } - let isSupportedChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.refresh_rate.RefreshRateHostApi.isSupported\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) - if let api = api { - isSupportedChannel.setMessageHandler { _, reply in - do { - let result = try api.isSupported() - reply(wrapResult(result)) - } catch { - reply(wrapError(error)) - } - } - } else { - isSupportedChannel.setMessageHandler(nil) - } - } -} -/// Generated protocol from Pigeon that represents Flutter messages that can be called from Swift. -protocol RefreshRateFlutterApiProtocol { - func onDisplayInfoChanged(info infoArg: DisplayInfoMessage, completion: @escaping (Result) -> Void) -} -class RefreshRateFlutterApi: RefreshRateFlutterApiProtocol { - private let binaryMessenger: FlutterBinaryMessenger - private let messageChannelSuffix: String - init(binaryMessenger: FlutterBinaryMessenger, messageChannelSuffix: String = "") { - self.binaryMessenger = binaryMessenger - self.messageChannelSuffix = messageChannelSuffix.count > 0 ? ".\(messageChannelSuffix)" : "" - } - var codec: RefreshRateApiPigeonCodec { - return RefreshRateApiPigeonCodec.shared - } - func onDisplayInfoChanged(info infoArg: DisplayInfoMessage, completion: @escaping (Result) -> Void) { - let channelName: String = "dev.flutter.pigeon.refresh_rate.RefreshRateFlutterApi.onDisplayInfoChanged\(messageChannelSuffix)" - let channel = FlutterBasicMessageChannel(name: channelName, binaryMessenger: binaryMessenger, codec: codec) - channel.sendMessage([infoArg] as [Any?]) { response in - guard let listResponse = response as? [Any?] else { - completion(.failure(createConnectionError(withChannelName: channelName))) - return - } - if listResponse.count > 1 { - let code: String = listResponse[0] as! String - let message: String? = nilOrValue(listResponse[1]) - let details: String? = nilOrValue(listResponse[2]) - completion(.failure(PigeonError(code: code, message: message, details: details))) - } else { - completion(.success(Void())) - } - } - } -} diff --git a/third_party/refresh_rate/ios/refresh_rate/Sources/refresh_rate_objc/DisplayLinkSwizzle.m b/third_party/refresh_rate/ios/refresh_rate/Sources/refresh_rate_objc/DisplayLinkSwizzle.m deleted file mode 100644 index 2e40973b..00000000 --- a/third_party/refresh_rate/ios/refresh_rate/Sources/refresh_rate_objc/DisplayLinkSwizzle.m +++ /dev/null @@ -1,188 +0,0 @@ -#import "DisplayLinkSwizzle.h" -#import - -// Key for tagging display links that should bypass the override. -static const void *RRBypassKey = &RRBypassKey; -// Key for storing the original (uncapped) frame rate range. -static const void *RROriginalRangeKey = &RROriginalRangeKey; - -/// Global override cap. 0 means no override (pass through). -static float _rr_overrideMaxRate = 0; - -/// Storage for tracked display links (weak-ish — we check validity). -static NSPointerArray *_rr_trackedLinks = nil; -static NSLock *_rr_lock = nil; - -// Store original IMPs — declared early so swizzled functions can reference them. -static IMP _rr_origAddToRunLoop = NULL; -static IMP _rr_origSetRange = NULL; - -#pragma mark - Public C interface (called from Swift) - -/// Set the max frame rate cap. Pass 0 to disable. -void RRSetOverrideMaxRate(float rate) { - _rr_overrideMaxRate = rate; -} - -float RRGetOverrideMaxRate(void) { - return _rr_overrideMaxRate; -} - -/// Tag a display link so the swizzle bypasses it. -void RRBypassDisplayLink(CADisplayLink *link) { - objc_setAssociatedObject(link, RRBypassKey, @YES, OBJC_ASSOCIATION_RETAIN_NONATOMIC); -} - -/// Apply the current override to all tracked display links. -void RRApplyOverrideToTrackedLinks(void) { - if (!_rr_lock) return; - - [_rr_lock lock]; - - // Compact nil refs - [_rr_trackedLinks compact]; - - NSUInteger count = [_rr_trackedLinks count]; - for (NSUInteger i = 0; i < count; i++) { - CADisplayLink *link = [_rr_trackedLinks pointerAtIndex:i]; - if (!link) continue; - - // Skip bypassed links - if (objc_getAssociatedObject(link, RRBypassKey)) continue; - - if (@available(iOS 15.0, *)) { - // Read stored original range - NSDictionary *stored = objc_getAssociatedObject(link, RROriginalRangeKey); - - float cap = _rr_overrideMaxRate; - - if (cap > 0 && stored) { - float origMin = [stored[@"min"] floatValue]; - float origMax = [stored[@"max"] floatValue]; - float origPref = [stored[@"preferred"] floatValue]; - CAFrameRateRange capped = CAFrameRateRangeMake( - fminf(origMin, cap), - fminf(origMax, cap), - fminf(origPref, cap) - ); - // Use original IMP directly to avoid re-triggering our swizzle - // (which would overwrite the stored original with the capped value) - SEL sel = NSSelectorFromString(@"setPreferredFrameRateRange:"); - if (_rr_origSetRange) { - ((void (*)(id, SEL, CAFrameRateRange))_rr_origSetRange)(link, sel, capped); - } - } else if (cap <= 0 && stored) { - // Restore original - float origMin = [stored[@"min"] floatValue]; - float origMax = [stored[@"max"] floatValue]; - float origPref = [stored[@"preferred"] floatValue]; - SEL sel = NSSelectorFromString(@"setPreferredFrameRateRange:"); - if (_rr_origSetRange) { - ((void (*)(id, SEL, CAFrameRateRange))_rr_origSetRange)(link, sel, CAFrameRateRangeMake(origMin, origMax, origPref)); - } - } - } - } - - [_rr_lock unlock]; -} - -#pragma mark - Swizzled implementations - -/// Swizzled addToRunLoop:forMode: — tracks every display link. -static void rr_addToRunLoop(CADisplayLink *self, SEL _cmd, NSRunLoop *runloop, NSRunLoopMode mode) { - // Track this link - [_rr_lock lock]; - if (_rr_trackedLinks) { - // Check not already tracked - BOOL found = NO; - [_rr_trackedLinks compact]; - for (NSUInteger i = 0; i < [_rr_trackedLinks count]; i++) { - if ([_rr_trackedLinks pointerAtIndex:i] == (__bridge void *)self) { - found = YES; - break; - } - } - if (!found) { - [_rr_trackedLinks addPointer:(__bridge void *)self]; - } - } - [_rr_lock unlock]; - - // Call original — the IMP was saved during swizzle - ((void (*)(id, SEL, NSRunLoop *, NSRunLoopMode))_rr_origAddToRunLoop)(self, _cmd, runloop, mode); -} - -/// Swizzled setPreferredFrameRateRange: — stores original range and applies cap. -static void rr_setPreferredFrameRateRange(CADisplayLink *self, SEL _cmd, CAFrameRateRange range) API_AVAILABLE(ios(15.0)); - -static void rr_setPreferredFrameRateRange(CADisplayLink *self, SEL _cmd, CAFrameRateRange range) { - // Bypass tagged links - if (objc_getAssociatedObject(self, RRBypassKey)) { - ((void (*)(id, SEL, CAFrameRateRange))_rr_origSetRange)(self, _cmd, range); - return; - } - - // Store original range - if (@available(iOS 15.0, *)) { - NSDictionary *stored = @{ - @"min": @(range.minimum), - @"max": @(range.maximum), - @"preferred": @(range.preferred), - }; - objc_setAssociatedObject(self, RROriginalRangeKey, stored, OBJC_ASSOCIATION_RETAIN_NONATOMIC); - } - - // Apply cap if active - float cap = _rr_overrideMaxRate; - if (cap > 0) { - if (@available(iOS 15.0, *)) { - CAFrameRateRange capped = CAFrameRateRangeMake( - fminf(range.minimum, cap), - fminf(range.maximum, cap), - fminf(range.preferred, cap) - ); - ((void (*)(id, SEL, CAFrameRateRange))_rr_origSetRange)(self, _cmd, capped); - } else { - ((void (*)(id, SEL, CAFrameRateRange))_rr_origSetRange)(self, _cmd, range); - } - } else { - ((void (*)(id, SEL, CAFrameRateRange))_rr_origSetRange)(self, _cmd, range); - } -} - -#pragma mark - +load (runs before main, before Flutter engine starts) - -@interface RRDisplayLinkSwizzle : NSObject -@end - -@implementation RRDisplayLinkSwizzle - -+ (void)load { - _rr_trackedLinks = [NSPointerArray weakObjectsPointerArray]; - _rr_lock = [[NSLock alloc] init]; - - Class cls = [CADisplayLink class]; - - // Swizzle addToRunLoop:forMode: - { - SEL sel = @selector(addToRunLoop:forMode:); - Method method = class_getInstanceMethod(cls, sel); - if (method) { - _rr_origAddToRunLoop = method_getImplementation(method); - method_setImplementation(method, (IMP)rr_addToRunLoop); - } - } - - // Swizzle setPreferredFrameRateRange: (iOS 15+) - if (@available(iOS 15.0, *)) { - SEL sel = NSSelectorFromString(@"setPreferredFrameRateRange:"); - Method method = class_getInstanceMethod(cls, sel); - if (method) { - _rr_origSetRange = method_getImplementation(method); - method_setImplementation(method, (IMP)rr_setPreferredFrameRateRange); - } - } -} - -@end diff --git a/third_party/refresh_rate/ios/refresh_rate/Sources/refresh_rate_objc/include/DisplayLinkSwizzle.h b/third_party/refresh_rate/ios/refresh_rate/Sources/refresh_rate_objc/include/DisplayLinkSwizzle.h deleted file mode 100644 index c3fcdbdb..00000000 --- a/third_party/refresh_rate/ios/refresh_rate/Sources/refresh_rate_objc/include/DisplayLinkSwizzle.h +++ /dev/null @@ -1,14 +0,0 @@ -#import - -/// Set the max frame rate cap for all display links. Pass 0 to disable. -void RRSetOverrideMaxRate(float rate); - -/// Get the current override max rate. 0 means no override. -float RRGetOverrideMaxRate(void); - -/// Tag a display link so the swizzle bypasses it (for monitoring/boost links). -void RRBypassDisplayLink(CADisplayLink * _Nonnull link); - -/// Apply the current override to all tracked (non-bypassed) display links. -/// Call this after changing the override rate. -void RRApplyOverrideToTrackedLinks(void); diff --git a/third_party/refresh_rate/lib/refresh_rate.dart b/third_party/refresh_rate/lib/refresh_rate.dart deleted file mode 100644 index c462fa98..00000000 --- a/third_party/refresh_rate/lib/refresh_rate.dart +++ /dev/null @@ -1,5 +0,0 @@ -export 'src/refresh_rate.dart'; -export 'src/models/display_info.dart'; -export 'src/models/enums.dart'; -export 'src/models/session_report.dart'; -export 'src/verification/refresh_rate_session.dart'; diff --git a/third_party/refresh_rate/lib/refresh_rate_web.dart b/third_party/refresh_rate/lib/refresh_rate_web.dart deleted file mode 100644 index 4c8e203c..00000000 --- a/third_party/refresh_rate/lib/refresh_rate_web.dart +++ /dev/null @@ -1,27 +0,0 @@ -import 'package:flutter_web_plugins/flutter_web_plugins.dart'; - -import 'src/refresh_rate.dart'; -import 'src/web/web_refresh_rate_adapter.dart'; - -/// Web platform implementation of the RefreshRate plugin. -/// -/// Uses `requestAnimationFrame` interval timing to detect the -/// display's current refresh rate (same technique as TestUFO). -/// Control methods are graceful no-ops because browsers own their -/// vsync scheduling and expose no API to change it. -/// -/// ### What works on web -/// -/// | Feature | Status | -/// |:--------|:------:| -/// | Query current Hz | ✓ (via rAF timing) | -/// | FPS overlay / benchmark | ✓ (pure Dart, unchanged) | -/// | Unlock / control rate | ✗ (browsers own vsync) | -/// | Supported rates / max rate | ✗ (not exposed) | -/// | Low Power Mode / thermal | ✗ (no web equivalent) | -class RefreshRateWeb { - /// Registers the web plugin by swapping in [WebRefreshRateApiAdapter]. - static void registerWith(Registrar registrar) { - RefreshRate.registerAdapter(WebRefreshRateApiAdapter()); - } -} diff --git a/third_party/refresh_rate/lib/src/generated/refresh_rate_api.g.dart b/third_party/refresh_rate/lib/src/generated/refresh_rate_api.g.dart deleted file mode 100644 index 530dd070..00000000 --- a/third_party/refresh_rate/lib/src/generated/refresh_rate_api.g.dart +++ /dev/null @@ -1,446 +0,0 @@ -// Copyright 2026 Qoder (qoder.in). All rights reserved. -// Use of this source code is governed by a BSD-style license. -// Autogenerated from Pigeon (v22.7.4), do not edit directly. -// See also: https://pub.dev/packages/pigeon -// ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, prefer_null_aware_operators, omit_local_variable_types, unused_shown_name, unnecessary_import, no_leading_underscores_for_local_identifiers - -import 'dart:async'; -import 'dart:typed_data' show Float64List, Int32List, Int64List, Uint8List; - -import 'package:flutter/foundation.dart' show ReadBuffer, WriteBuffer; -import 'package:flutter/services.dart'; - -PlatformException _createConnectionError(String channelName) { - return PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel: "$channelName".', - ); -} - -List wrapResponse( - {Object? result, PlatformException? error, bool empty = false}) { - if (empty) { - return []; - } - if (error == null) { - return [result]; - } - return [error.code, error.message, error.details]; -} - -class DisplayInfoMessage { - DisplayInfoMessage({ - this.currentRate, - this.maxRate, - this.minRate, - this.supportedRates, - this.isVariableRefreshRate, - this.engineTargetRate, - this.iosProMotionEnabled, - this.androidApiLevel, - this.isLowPowerMode, - this.thermalStateIndex, - this.hasAdaptiveRefreshRate, - this.displayServer, - this.monitorCount, - }); - - double? currentRate; - - double? maxRate; - - double? minRate; - - List? supportedRates; - - bool? isVariableRefreshRate; - - double? engineTargetRate; - - bool? iosProMotionEnabled; - - int? androidApiLevel; - - bool? isLowPowerMode; - - int? thermalStateIndex; - - bool? hasAdaptiveRefreshRate; - - String? displayServer; - - int? monitorCount; - - Object encode() { - return [ - currentRate, - maxRate, - minRate, - supportedRates, - isVariableRefreshRate, - engineTargetRate, - iosProMotionEnabled, - androidApiLevel, - isLowPowerMode, - thermalStateIndex, - hasAdaptiveRefreshRate, - displayServer, - monitorCount, - ]; - } - - static DisplayInfoMessage decode(Object result) { - result as List; - return DisplayInfoMessage( - currentRate: result[0] as double?, - maxRate: result[1] as double?, - minRate: result[2] as double?, - supportedRates: (result[3] as List?)?.cast(), - isVariableRefreshRate: result[4] as bool?, - engineTargetRate: result[5] as double?, - iosProMotionEnabled: result[6] as bool?, - androidApiLevel: result[7] as int?, - isLowPowerMode: result[8] as bool?, - thermalStateIndex: result[9] as int?, - hasAdaptiveRefreshRate: result[10] as bool?, - displayServer: result[11] as String?, - monitorCount: result[12] as int?, - ); - } -} - -class _PigeonCodec extends StandardMessageCodec { - const _PigeonCodec(); - @override - void writeValue(WriteBuffer buffer, Object? value) { - if (value is int) { - buffer.putUint8(4); - buffer.putInt64(value); - } else if (value is DisplayInfoMessage) { - buffer.putUint8(129); - writeValue(buffer, value.encode()); - } else { - super.writeValue(buffer, value); - } - } - - @override - Object? readValueOfType(int type, ReadBuffer buffer) { - switch (type) { - case 129: - return DisplayInfoMessage.decode(readValue(buffer)!); - default: - return super.readValueOfType(type, buffer); - } - } -} - -class RefreshRateHostApi { - /// Constructor for [RefreshRateHostApi]. The [binaryMessenger] named argument is - /// available for dependency injection. If it is left null, the default - /// BinaryMessenger will be used which routes to the host platform. - RefreshRateHostApi( - {BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''}) - : pigeonVar_binaryMessenger = binaryMessenger, - pigeonVar_messageChannelSuffix = - messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; - final BinaryMessenger? pigeonVar_binaryMessenger; - - static const MessageCodec pigeonChannelCodec = _PigeonCodec(); - - final String pigeonVar_messageChannelSuffix; - - Future getDisplayInfo() async { - final String pigeonVar_channelName = - 'dev.flutter.pigeon.refresh_rate.RefreshRateHostApi.getDisplayInfo$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); - final List? pigeonVar_replyList = - await pigeonVar_channel.send(null) as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else if (pigeonVar_replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (pigeonVar_replyList[0] as DisplayInfoMessage?)!; - } - } - - Future enable() async { - final String pigeonVar_channelName = - 'dev.flutter.pigeon.refresh_rate.RefreshRateHostApi.enable$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); - final List? pigeonVar_replyList = - await pigeonVar_channel.send(null) as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else { - return; - } - } - - Future disable() async { - final String pigeonVar_channelName = - 'dev.flutter.pigeon.refresh_rate.RefreshRateHostApi.disable$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); - final List? pigeonVar_replyList = - await pigeonVar_channel.send(null) as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else { - return; - } - } - - Future preferMax() async { - final String pigeonVar_channelName = - 'dev.flutter.pigeon.refresh_rate.RefreshRateHostApi.preferMax$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); - final List? pigeonVar_replyList = - await pigeonVar_channel.send(null) as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else { - return; - } - } - - Future preferDefault() async { - final String pigeonVar_channelName = - 'dev.flutter.pigeon.refresh_rate.RefreshRateHostApi.preferDefault$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); - final List? pigeonVar_replyList = - await pigeonVar_channel.send(null) as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else { - return; - } - } - - Future matchContent(double fps) async { - final String pigeonVar_channelName = - 'dev.flutter.pigeon.refresh_rate.RefreshRateHostApi.matchContent$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); - final List? pigeonVar_replyList = - await pigeonVar_channel.send([fps]) as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else { - return; - } - } - - Future boost(int durationMs) async { - final String pigeonVar_channelName = - 'dev.flutter.pigeon.refresh_rate.RefreshRateHostApi.boost$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); - final List? pigeonVar_replyList = - await pigeonVar_channel.send([durationMs]) as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else { - return; - } - } - - Future setCategory(int categoryIndex) async { - final String pigeonVar_channelName = - 'dev.flutter.pigeon.refresh_rate.RefreshRateHostApi.setCategory$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); - final List? pigeonVar_replyList = await pigeonVar_channel - .send([categoryIndex]) as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else { - return; - } - } - - Future setTouchBoost(bool enabled) async { - final String pigeonVar_channelName = - 'dev.flutter.pigeon.refresh_rate.RefreshRateHostApi.setTouchBoost$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); - final List? pigeonVar_replyList = - await pigeonVar_channel.send([enabled]) as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else { - return; - } - } - - Future isSupported() async { - final String pigeonVar_channelName = - 'dev.flutter.pigeon.refresh_rate.RefreshRateHostApi.isSupported$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); - final List? pigeonVar_replyList = - await pigeonVar_channel.send(null) as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else if (pigeonVar_replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (pigeonVar_replyList[0] as bool?)!; - } - } -} - -abstract class RefreshRateFlutterApi { - static const MessageCodec pigeonChannelCodec = _PigeonCodec(); - - void onDisplayInfoChanged(DisplayInfoMessage info); - - static void setUp( - RefreshRateFlutterApi? api, { - BinaryMessenger? binaryMessenger, - String messageChannelSuffix = '', - }) { - messageChannelSuffix = - messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; - { - final BasicMessageChannel< - Object?> pigeonVar_channel = BasicMessageChannel< - Object?>( - 'dev.flutter.pigeon.refresh_rate.RefreshRateFlutterApi.onDisplayInfoChanged$messageChannelSuffix', - pigeonChannelCodec, - binaryMessenger: binaryMessenger); - if (api == null) { - pigeonVar_channel.setMessageHandler(null); - } else { - pigeonVar_channel.setMessageHandler((Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.refresh_rate.RefreshRateFlutterApi.onDisplayInfoChanged was null.'); - final List args = (message as List?)!; - final DisplayInfoMessage? arg_info = (args[0] as DisplayInfoMessage?); - assert(arg_info != null, - 'Argument for dev.flutter.pigeon.refresh_rate.RefreshRateFlutterApi.onDisplayInfoChanged was null, expected non-null DisplayInfoMessage.'); - try { - api.onDisplayInfoChanged(arg_info!); - return wrapResponse(empty: true); - } on PlatformException catch (e) { - return wrapResponse(error: e); - } catch (e) { - return wrapResponse( - error: PlatformException(code: 'error', message: e.toString())); - } - }); - } - } - } -} diff --git a/third_party/refresh_rate/lib/src/models/display_info.dart b/third_party/refresh_rate/lib/src/models/display_info.dart deleted file mode 100644 index d7b8429f..00000000 --- a/third_party/refresh_rate/lib/src/models/display_info.dart +++ /dev/null @@ -1,129 +0,0 @@ -import '../generated/refresh_rate_api.g.dart'; -import 'enums.dart'; - -/// A snapshot of the current display configuration and device health. -/// -/// Retrieve a fresh snapshot via [RefreshRate.refresh] or listen to -/// [RefreshRate.onChanged] for real-time updates. -class DisplayInfo { - /// The refresh rate the display is currently running at, in Hz. - final double currentRate; - - /// The maximum refresh rate supported by this display, in Hz. - final double maxRate; - - /// The minimum refresh rate supported by this display, in Hz. - final double minRate; - - /// All refresh rates the display hardware can run at, in Hz. - final List supportedRates; - - /// Whether the display supports variable refresh rate (VRR / LTPO). - final bool isVariableRefreshRate; - - /// The frame rate the Flutter engine is currently targeting, in Hz. - final double engineTargetRate; - - /// Whether iOS ProMotion adaptive refresh is enabled for this app. - /// - /// `null` on non-iOS platforms. - final bool? iosProMotionEnabled; - - /// The Android API level of the device. - /// - /// `null` on non-Android platforms. - final int? androidApiLevel; - - /// Whether the device is in Low Power Mode. - /// - /// `null` when the platform does not expose this information. - final bool? isLowPowerMode; - - /// The current thermal state of the device. - final ThermalState thermalState; - - /// Whether the display supports an adaptive (variable) refresh rate. - /// - /// `null` when the platform does not expose this information. - final bool? hasAdaptiveRefreshRate; - - /// The name of the display server in use (Linux only, e.g. `"wayland"`). - /// - /// `null` on non-Linux platforms. - final String? displayServer; - - /// The number of monitors connected to the device (desktop platforms only). - /// - /// `null` on mobile platforms. - final int? monitorCount; - - /// Creates a new [DisplayInfo] snapshot. - const DisplayInfo({ - required this.currentRate, - required this.maxRate, - required this.minRate, - required this.supportedRates, - required this.isVariableRefreshRate, - required this.engineTargetRate, - this.iosProMotionEnabled, - this.androidApiLevel, - this.isLowPowerMode, - required this.thermalState, - this.hasAdaptiveRefreshRate, - this.displayServer, - this.monitorCount, - }); - - /// Creates a [DisplayInfo] from a platform [DisplayInfoMessage]. - factory DisplayInfo.fromMessage(DisplayInfoMessage msg) { - return DisplayInfo( - currentRate: msg.currentRate ?? 60.0, - maxRate: msg.maxRate ?? 60.0, - minRate: msg.minRate ?? 60.0, - supportedRates: - msg.supportedRates?.whereType().toList() ?? const [60.0], - isVariableRefreshRate: msg.isVariableRefreshRate ?? false, - engineTargetRate: msg.engineTargetRate ?? 60.0, - iosProMotionEnabled: msg.iosProMotionEnabled, - androidApiLevel: msg.androidApiLevel, - isLowPowerMode: msg.isLowPowerMode, - thermalState: ThermalState.fromIndex(msg.thermalStateIndex), - hasAdaptiveRefreshRate: msg.hasAdaptiveRefreshRate, - displayServer: msg.displayServer, - monitorCount: msg.monitorCount, - ); - } - - /// A safe fallback [DisplayInfo] used before the first [RefreshRate.refresh] - /// call completes. Assumes a standard 60 Hz non-VRR display. - static const DisplayInfo fallback = DisplayInfo( - currentRate: 60.0, - maxRate: 60.0, - minRate: 60.0, - supportedRates: [60.0], - isVariableRefreshRate: false, - engineTargetRate: 60.0, - thermalState: ThermalState.unknown, - ); - - @override - bool operator ==(Object other) => - identical(this, other) || - other is DisplayInfo && - currentRate == other.currentRate && - maxRate == other.maxRate && - minRate == other.minRate && - isVariableRefreshRate == other.isVariableRefreshRate && - engineTargetRate == other.engineTargetRate && - thermalState == other.thermalState && - isLowPowerMode == other.isLowPowerMode; - - @override - int get hashCode => Object.hash(currentRate, maxRate, minRate, - isVariableRefreshRate, engineTargetRate, thermalState, isLowPowerMode); - - @override - String toString() => - 'DisplayInfo(currentRate: ${currentRate}Hz, maxRate: ${maxRate}Hz, ' - 'thermalState: $thermalState, isLowPowerMode: $isLowPowerMode)'; -} diff --git a/third_party/refresh_rate/lib/src/models/enums.dart b/third_party/refresh_rate/lib/src/models/enums.dart deleted file mode 100644 index e9339415..00000000 --- a/third_party/refresh_rate/lib/src/models/enums.dart +++ /dev/null @@ -1,151 +0,0 @@ -/// Indicates the desired performance category for the display scheduler. -/// -/// Use [RefreshRate.category] to apply one of these hints to the platform. -enum RateCategory { - /// No refresh-rate hint — the platform decides. - none, - - /// Prefer a low refresh rate (e.g. reading, static UIs). - low, - - /// Prefer the standard refresh rate (default). - normal, - - /// Prefer the highest supported refresh rate - /// (games, animations, scrolling at high speed). - high; - - /// Returns the [RateCategory] matching [index], or [none] if unknown. - static RateCategory fromIndex(int? index) { - switch (index) { - case 0: - return none; - case 1: - return low; - case 2: - return normal; - case 3: - return high; - default: - return none; - } - } -} - -/// The thermal condition of the device, as reported by the OS. -/// -/// Higher-severity states may cause the OS to throttle the display -/// refresh rate regardless of what the app requests. -enum ThermalState { - /// The device is well within thermal limits — full performance available. - nominal, - - /// The device is slightly warm; minor throttling may apply. - fair, - - /// The device is hot; significant throttling is likely. - serious, - - /// The device is critically hot; the OS may force-reduce refresh rate. - critical, - - /// Thermal state could not be determined (unsupported platform). - unknown; - - /// Returns the [ThermalState] matching [index], or [unknown] if not found. - static ThermalState fromIndex(int? index) { - switch (index) { - case 0: - return nominal; - case 1: - return fair; - case 2: - return serious; - case 3: - return critical; - default: - return unknown; - } - } -} - -/// Lifecycle state of a [RefreshRateSession] benchmark. -enum SessionState { - /// The session has not yet started collecting data. - idle, - - /// The session is actively collecting frame timings. - running, - - /// The session is in a brief warm-up period after the app resumed. - warmup, - - /// The session was paused due to the app going to the background. - interrupted, - - /// The session has finished and a [SessionReport] is available. - completed, -} - -/// Reason why a time window was excluded from a [SessionReport]. -enum ExclusionReason { - /// App moved to the background. - appBackgrounded, - - /// App became inactive (e.g. notification tray opened). - appInactive, - - /// A brief warm-up window after the app resumed from background. - resumeWarmup, - - /// Overlay opened or the window lost focus. - overlayOrFocusLoss, - - /// The display refresh rate changed mid-session. - displayRateChanged, - - /// Low Power Mode was toggled mid-session. - lowPowerModeChanged, - - /// The thermal state changed mid-session. - thermalStateChanged, -} - -/// Overall quality verdict produced by [SessionReport]. -enum Verdict { - /// Frame rate is consistently at or near the target Hz. - excellent, - - /// Frame rate is mostly stable with minor drops. - good, - - /// Frame rate is acceptable but below optimal. - fair, - - /// Frequent frame drops — the app misses its target regularly. - poor, - - /// Not enough valid data to make a determination. - inconclusive, -} - -/// The most likely rendering bottleneck identified by [SessionReport]. -enum Bottleneck { - /// The UI/build thread is the constraint (slow widget tree rebuilds). - buildBound, - - /// The raster thread is the constraint (complex paint operations). - rasterBound, - - /// The display hardware is capping the achievable frame rate. - displayCapped, - - /// Low Power Mode or battery saver is limiting performance. - powerLimited, - - /// Thermal throttling is reducing the achievable frame rate. - thermalLimited, - - /// No significant bottleneck detected. - none, -} diff --git a/third_party/refresh_rate/lib/src/models/session_report.dart b/third_party/refresh_rate/lib/src/models/session_report.dart deleted file mode 100644 index 8ceee04c..00000000 --- a/third_party/refresh_rate/lib/src/models/session_report.dart +++ /dev/null @@ -1,187 +0,0 @@ -import 'dart:convert'; -import 'enums.dart'; - -/// A point-in-time snapshot of device conditions recorded at session start. -/// -/// Captured when a [RefreshRateSession] is created and embedded in the -/// resulting [SessionReport] so analysis can account for the environment. -class DeviceStateSnapshot { - /// Whether the device was in Low Power Mode when the session started. - /// - /// `null` when the platform does not expose this information. - final bool? isLowPowerMode; - - /// The thermal state of the device when the session started. - final ThermalState thermalState; - - /// Whether the display supports an adaptive (variable) refresh rate. - /// - /// `null` when the platform does not expose this information. - final bool? hasAdaptiveRefreshRate; - - /// The display server in use (Linux only, e.g. `"wayland"`). - /// - /// `null` on non-Linux platforms. - final String? displayServer; - - /// Number of connected monitors (desktop platforms only). - /// - /// `null` on mobile platforms. - final int? monitorCount; - - /// Creates a new [DeviceStateSnapshot]. - const DeviceStateSnapshot({ - this.isLowPowerMode, - required this.thermalState, - this.hasAdaptiveRefreshRate, - this.displayServer, - this.monitorCount, - }); - - @override - bool operator ==(Object other) => - identical(this, other) || - other is DeviceStateSnapshot && - isLowPowerMode == other.isLowPowerMode && - thermalState == other.thermalState; - - @override - int get hashCode => Object.hash(isLowPowerMode, thermalState); - - /// Serializes this snapshot to a JSON-compatible map. - Map toMap() => { - 'isLowPowerMode': isLowPowerMode, - 'thermalState': thermalState.name, - 'hasAdaptiveRefreshRate': hasAdaptiveRefreshRate, - 'displayServer': displayServer, - 'monitorCount': monitorCount, - }; -} - -/// The result produced when a [RefreshRateSession] ends. -/// -/// Contains FPS statistics, frame timing breakdowns, a performance [verdict], -/// a likely [likelyBottleneck] hint, and excluded-window details. -class SessionReport { - /// The name given to the session when it was started. - final String sessionName; - - /// Overall quality assessment for this session. - final Verdict verdict; - - /// The rendering stage most likely responsible for any frame drops. - final Bottleneck likelyBottleneck; - - /// The target refresh rate in Hz at the time the session began. - final double targetHz; - - /// The average display refresh rate observed during the session, in Hz. - final double observedAvgHz; - - /// The frame duration budget at [targetHz] (1000 / targetHz), in ms. - final double frameBudgetMs; - - /// Average frames per second across all valid frames. - final double avgFps; - - /// The 1st-percentile FPS (worst 1% of frames). - final double onePercentLowFps; - - /// The 5th-percentile FPS (worst 5% of frames). - final double fivePercentLowFps; - - /// Average build (UI thread) time per frame, in ms. - final double avgBuildMs; - - /// Average raster thread time per frame, in ms. - final double avgRasterMs; - - /// Average total frame time (build + raster), in ms. - final double avgTotalFrameMs; - - /// Number of frames that exceeded the frame budget. - final int jankyFrameCount; - - /// Number of frames that exceeded twice the frame budget. - final int severeJankCount; - - /// Percentage of frames that were missed (janky), from 0–100. - final double missedFramePercent; - - /// Total duration of valid (non-excluded) measurement time. - final Duration validDuration; - - /// Total duration excluded from measurement (background, warmup, etc.). - final Duration excludedDuration; - - /// A breakdown of how many times each [ExclusionReason] occurred. - final Map exclusionReasons; - - /// Device state recorded at the start of the session. - final DeviceStateSnapshot deviceState; - - /// Creates a new [SessionReport]. - const SessionReport({ - required this.sessionName, - required this.verdict, - required this.likelyBottleneck, - required this.targetHz, - required this.observedAvgHz, - required this.frameBudgetMs, - required this.avgFps, - required this.onePercentLowFps, - required this.fivePercentLowFps, - required this.avgBuildMs, - required this.avgRasterMs, - required this.avgTotalFrameMs, - required this.jankyFrameCount, - required this.severeJankCount, - required this.missedFramePercent, - required this.validDuration, - required this.excludedDuration, - required this.exclusionReasons, - required this.deviceState, - }); - - /// Serializes this report to a JSON-compatible map. - Map toMap() => { - 'sessionName': sessionName, - 'verdict': verdict.name, - 'likelyBottleneck': likelyBottleneck.name, - 'targetHz': targetHz, - 'observedAvgHz': observedAvgHz, - 'frameBudgetMs': frameBudgetMs, - 'avgFps': avgFps, - 'onePercentLowFps': onePercentLowFps, - 'fivePercentLowFps': fivePercentLowFps, - 'avgBuildMs': avgBuildMs, - 'avgRasterMs': avgRasterMs, - 'avgTotalFrameMs': avgTotalFrameMs, - 'jankyFrameCount': jankyFrameCount, - 'severeJankCount': severeJankCount, - 'missedFramePercent': missedFramePercent, - 'validDurationMs': validDuration.inMilliseconds, - 'excludedDurationMs': excludedDuration.inMilliseconds, - 'exclusionReasons': exclusionReasons.map((k, v) => MapEntry(k.name, v)), - 'deviceState': deviceState.toMap(), - }; - - /// Serializes this report to a JSON string. - String toJson() => jsonEncode(toMap()); - - /// Serializes this report to a CSV string. - String toCsv() { - final m = toMap(); - String esc(dynamic v) { - final s = v is Map ? jsonEncode(v) : '$v'; - if (s.contains(',') || s.contains('"') || s.contains('\n')) { - return '"${s.replaceAll('"', '""')}"'; - } - return s; - } - - final headers = m.keys.join(','); - final values = m.values.map(esc).join(','); - return '$headers\n$values'; - } -} diff --git a/third_party/refresh_rate/lib/src/refresh_rate.dart b/third_party/refresh_rate/lib/src/refresh_rate.dart deleted file mode 100644 index ef7e1fb4..00000000 --- a/third_party/refresh_rate/lib/src/refresh_rate.dart +++ /dev/null @@ -1,244 +0,0 @@ -import 'dart:async'; -import 'package:flutter/widgets.dart'; - -import 'generated/refresh_rate_api.g.dart'; -import 'models/display_info.dart'; -import 'models/enums.dart'; -import 'refresh_rate_api_adapter.dart'; -import 'verification/overlay_controller.dart'; -import 'verification/refresh_rate_session.dart'; - -/// Primary entry-point for controlling and monitoring the display refresh rate. -/// -/// All members are static; this class cannot be instantiated. -/// -/// ### Quick-start -/// ```dart -/// // Unlock the highest supported refresh rate. -/// await RefreshRate.refresh(); -/// RefreshRate.preferMax(); -/// -/// // Show an FPS overlay for debugging. -/// RefreshRate.showFPS(); -/// ``` -class RefreshRate { - RefreshRate._(); - - static RefreshRateApiAdapter _api = PigeonRefreshRateApiAdapter(); - static DisplayInfo _cachedInfo = DisplayInfo.fallback; - static StreamController? _changedController; - static final _flutterApi = _RefreshRateFlutterApiImpl(); - - // ── Platform registration ────────────────────────────────────── - - /// Replaces the default platform API adapter. - /// - /// Called by platform-specific entrypoints (e.g. the web plugin) during - /// framework initialisation. Not intended for end-user consumption. - static void registerAdapter(RefreshRateApiAdapter adapter) { - _api = adapter; - } - - // ── Test seam ────────────────────────────────────────────────── - - /// Replaces the platform API implementation with a test fake. - /// - /// Call [clearApiForTesting] in `tearDown` to restore the real adapter. - @visibleForTesting - static void setApiForTesting(RefreshRateApiAdapter api) { - _api = api; - } - - /// Restores the real platform API and resets all internal state. - /// - /// Must be called in `tearDown` after [setApiForTesting]. - @visibleForTesting - static void clearApiForTesting() { - _api = PigeonRefreshRateApiAdapter(); - _flutterApi._onChanged = null; - RefreshRateFlutterApi.setUp(null); - _changedController?.close(); - _changedController = null; - } - - // ── Control ──────────────────────────────────────────────────── - - /// Opts the app into the platform's high-refresh-rate rendering pipeline. - /// - /// On Android this sets `preferredDisplayModeId` on the window surface. - /// On iOS/macOS this adjusts `CADisplayLink` preferred frame rate ranges. - /// Has no effect on platforms that do not support variable refresh rates. - static void enable() { - _api.enable(); - _refreshInfo(); - } - - /// Reverts the app to the platform default (typically 60 Hz). - /// - /// On iOS this allows the OS to manage the frame rate automatically. - static void disable() { - _api.disable(); - _refreshInfo(); - } - - /// Requests the maximum supported refresh rate for this display. - /// - /// Equivalent to calling [enable] then letting the platform pick the ceiling. - static void preferMax() => _api.preferMax(); - - /// Reverts to the display's default / preferred refresh rate. - static void preferDefault() => _api.preferDefault(); - - /// Requests a refresh rate that matches the given [fps] content rate. - /// - /// Useful when playing back video at a fixed frame rate (e.g. 24, 30, 60 fps) - /// so the display cadence aligns with the media cadence. - static void matchContent(double fps) => _api.matchContent(fps); - - /// Temporarily boosts the display to its maximum refresh rate for [duration]. - /// - /// Commonly used when a gesture or animation starts — the display snaps to - /// high-Hz immediately and returns to the preferred rate after the duration. - static void boost(Duration duration) => _api.boost(duration.inMilliseconds); - - /// Boosts the refresh rate for the lifetime of an [AnimationController]. - /// - /// Registers a status listener that calls [boost] whenever the controller - /// starts animating, and removes itself once the animation is done. - static void boostDuring(AnimationController controller) { - late final void Function(AnimationStatus) statusListener; - statusListener = (status) { - if (status == AnimationStatus.forward || - status == AnimationStatus.reverse) { - _api.boost(controller.duration?.inMilliseconds ?? 500); - } else if (status == AnimationStatus.completed || - status == AnimationStatus.dismissed) { - controller.removeStatusListener(statusListener); - } - }; - controller.addStatusListener(statusListener); - } - - /// Sets a named [RateCategory] hint for the display scheduler. - /// - /// Categories let you declare the performance class of your app - /// (`low`, `normal`, `high`) rather than specifying raw Hz values. - static void category(RateCategory c) => _api.setCategory(c.index); - - /// Enables or disables an automatic boost whenever the user touches the screen. - /// - /// When [enabled] is `true` the platform raises the refresh rate on every - /// touch-down event and lowers it again after a short idle period. - static void setTouchBoost(bool enabled) => _api.setTouchBoost(enabled); - - // ── Verification overlays ────────────────────────────────────── - - /// Shows a minimal live FPS counter overlay in the top-right corner. - static void showFPS() => OverlayController.instance.showFPS(); - - /// Shows a minimal live Hz readout overlay in the top-right corner. - static void showHz() => OverlayController.instance.showHz(); - - /// Shows the full diagnostic overlay (FPS + Hz + thermal state). - static void showOverlay() => OverlayController.instance.showFull(); - - /// Hides whatever verification overlay is currently visible. - static void hideOverlay() => OverlayController.instance.hide(); - - /// Whether the debug overlay is currently shown. - static bool get isOverlayVisible => OverlayController.instance.isVisible; - - // ── Diagnostics ──────────────────────────────────────────────── - - /// The most recently fetched [DisplayInfo] snapshot. - /// - /// Initialised to [DisplayInfo.fallback] (60 Hz, all optional fields null) - /// until [refresh] is awaited at least once. - static DisplayInfo get info => _cachedInfo; - - /// Fetches fresh [DisplayInfo] from the platform and caches the result. - /// - /// Resolves with the updated [DisplayInfo] on success. - static Future refresh() async { - final msg = await _api.getDisplayInfo(); - _cachedInfo = DisplayInfo.fromMessage(msg); - return _cachedInfo; - } - - /// A broadcast stream that emits a new [DisplayInfo] whenever the display - /// configuration changes (e.g. the user enables Low Power Mode, or the - /// device throttles under thermal pressure). - static Stream get onChanged { - if (_changedController == null) { - _changedController = StreamController.broadcast(); - _flutterApi._onChanged = (info) { - _cachedInfo = info; - _changedController!.add(info); - }; - RefreshRateFlutterApi.setUp(_flutterApi); - } - return _changedController!.stream; - } - - /// Whether iOS ProMotion (adaptive 120 Hz) is enabled for this app. - /// - /// Returns `false` until a successful [refresh] is completed and the device - /// is an iPhone/iPad with a ProMotion display. - static bool get isProMotionReady => _cachedInfo.iosProMotionEnabled == true; - - /// Whether the device is currently in Low Power Mode. - /// - /// Defaults to `false` when the value cannot be determined. - static bool get isLowPowerMode => _cachedInfo.isLowPowerMode ?? false; - - /// The current thermal state of the device. - /// - /// A state of [ThermalState.serious] or [ThermalState.critical] may cause - /// the OS to clamp the refresh rate regardless of your requested value. - static ThermalState get thermalState => _cachedInfo.thermalState; - - // ── Benchmark sessions ───────────────────────────────────────── - - /// Creates and starts a new FPS benchmark session named [name]. - /// - /// Call [RefreshRateSession.end] when the scenario under test completes to - /// receive a [SessionReport] with verdict, FPS stats, and bottleneck hints. - static RefreshRateSession startSession(String name) { - return RefreshRateSession.create(name, _cachedInfo); - } - - // ── Internal ─────────────────────────────────────────────────── - - static void _refreshInfo() { - void handle(DisplayInfoMessage msg) { - _cachedInfo = DisplayInfo.fromMessage(msg); - } - - void handleError(Object e) { - assert(() { - debugPrint('RefreshRate: _refreshInfo error: $e'); - return true; - }()); - } - - try { - final result = _api.getDisplayInfo(); - if (result is Future) { - result.then(handle).catchError(handleError); - } else { - handle(result); - } - } catch (e) { - handleError(e); - } - } -} - -class _RefreshRateFlutterApiImpl extends RefreshRateFlutterApi { - void Function(DisplayInfo)? _onChanged; - - @override - void onDisplayInfoChanged(DisplayInfoMessage info) { - _onChanged?.call(DisplayInfo.fromMessage(info)); - } -} diff --git a/third_party/refresh_rate/lib/src/refresh_rate_api_adapter.dart b/third_party/refresh_rate/lib/src/refresh_rate_api_adapter.dart deleted file mode 100644 index 7fce754b..00000000 --- a/third_party/refresh_rate/lib/src/refresh_rate_api_adapter.dart +++ /dev/null @@ -1,79 +0,0 @@ -import 'dart:async'; - -import 'generated/refresh_rate_api.g.dart'; - -/// Abstract interface for the host API, used as the test seam. -/// -/// The real implementation ([PigeonRefreshRateApiAdapter]) delegates to the -/// pigeon-generated [RefreshRateHostApi]. Tests implement this interface -/// directly with synchronous fakes — no await required. -abstract class RefreshRateApiAdapter { - /// Fetches the latest display configuration. - FutureOr getDisplayInfo(); - - /// Enables High Refresh Rate overrides. - FutureOr enable(); - - /// Disables High Refresh Rate overrides. - FutureOr disable(); - - /// Requests the highest possible display refresh rate. - FutureOr preferMax(); - - /// Resets to the system default refresh rate. - FutureOr preferDefault(); - - /// Attempts to set the display refresh rate to match [fps]. - FutureOr matchContent(double fps); - - /// Temporarily boosts the refresh rate for [durationMs]. - FutureOr boost(int durationMs); - - /// Sets the refresh rate based on a given category. - FutureOr setCategory(int categoryIndex); - - /// Enables or disables automatic refresh rate boost on touch interactions. - FutureOr setTouchBoost(bool enabled); - - /// Checks whether the refresh rate overrides are supported by the platform. - FutureOr isSupported(); -} - -/// Production implementation that delegates to the pigeon-generated channel. -class PigeonRefreshRateApiAdapter implements RefreshRateApiAdapter { - final RefreshRateHostApi _pigeon; - - /// Creates a new [PigeonRefreshRateApiAdapter]. - PigeonRefreshRateApiAdapter() : _pigeon = RefreshRateHostApi(); - - @override - Future getDisplayInfo() => _pigeon.getDisplayInfo(); - - @override - Future enable() => _pigeon.enable(); - - @override - Future disable() => _pigeon.disable(); - - @override - Future preferMax() => _pigeon.preferMax(); - - @override - Future preferDefault() => _pigeon.preferDefault(); - - @override - Future matchContent(double fps) => _pigeon.matchContent(fps); - - @override - Future boost(int durationMs) => _pigeon.boost(durationMs); - - @override - Future setCategory(int categoryIndex) => - _pigeon.setCategory(categoryIndex); - - @override - Future setTouchBoost(bool enabled) => _pigeon.setTouchBoost(enabled); - - @override - Future isSupported() => _pigeon.isSupported(); -} diff --git a/third_party/refresh_rate/lib/src/verification/fps_tracker.dart b/third_party/refresh_rate/lib/src/verification/fps_tracker.dart deleted file mode 100644 index ff44590d..00000000 --- a/third_party/refresh_rate/lib/src/verification/fps_tracker.dart +++ /dev/null @@ -1,145 +0,0 @@ -import 'dart:ui' show FramePhase; -import 'package:flutter/scheduler.dart'; - -/// Represents a single rendered frame's timing data. -class FrameSample { - /// Time spent in the UI build thread, in microseconds. - final int buildUs; - - /// Time spent in the raster thread, in microseconds. - final int rasterUs; - - /// Total time to render the frame, in microseconds. - final int totalUs; - - /// Vsync timestamp, in microseconds. - final int vsyncUs; - - /// System time when the sample was recorded. - final DateTime timestamp; - - /// Creates a new [FrameSample]. - FrameSample({ - required this.buildUs, - required this.rasterUs, - required this.totalUs, - required this.vsyncUs, - required this.timestamp, - }); -} - -/// Helper that records [FrameTiming] data and calculates FPS statistics. -class FpsTracker { - final List _samples = []; - - /// The number of recorded samples. - int get sampleCount => _samples.length; - - /// Adds raw frame timings from the Flutter engine. - void addTimings(List timings) { - final now = DateTime.now(); - for (final t in timings) { - _samples.add(FrameSample( - buildUs: t.buildDuration.inMicroseconds, - rasterUs: t.rasterDuration.inMicroseconds, - totalUs: t.totalSpan.inMicroseconds, - vsyncUs: t.timestampInMicroseconds(FramePhase.vsyncStart), - timestamp: now, - )); - } - // Keep a bounded window so memory doesn't grow unbounded during long sessions - if (_samples.length > 600) { - _samples.removeRange(0, _samples.length - 600); - } - } - - /// Clears all recorded samples. - void reset() => _samples.clear(); - - /// Returns an immutable list of currently recorded samples. - List get samples => List.unmodifiable(_samples); - - /// FPS over all samples — used by benchmark sessions. - double get avgFps => _fpsFromWindow(_samples); - - /// FPS over the last [n] frames — used by the live overlay. - double recentFps([int n = 60]) { - if (_samples.length < 2) return 0.0; - final window = - _samples.length <= n ? _samples : _samples.sublist(_samples.length - n); - return _fpsFromWindow(window); - } - - static double _fpsFromWindow(List s) { - if (s.length < 2) return 0.0; - final elapsedUs = s.last.vsyncUs - s.first.vsyncUs; - if (elapsedUs <= 0) return 0.0; - return (s.length - 1) * 1000000.0 / elapsedUs; - } - - /// Average duration of the UI build phase across all samples, in ms. - double get avgBuildMs { - if (_samples.isEmpty) return 0.0; - return _samples.fold(0, (s, f) => s + f.buildUs) / - _samples.length / - 1000.0; - } - - /// Average duration of the raster phase across all samples, in ms. - double get avgRasterMs { - if (_samples.isEmpty) return 0.0; - return _samples.fold(0, (s, f) => s + f.rasterUs) / - _samples.length / - 1000.0; - } - - /// Average total duration (build + raster) across all samples, in ms. - double get avgTotalMs { - if (_samples.isEmpty) return 0.0; - return _samples.fold(0, (s, f) => s + f.totalUs) / - _samples.length / - 1000.0; - } - - /// Worst 1-percentile frame rate. - double get onePercentLowFps { - if (_samples.isEmpty) return 0.0; - final sorted = _samples.map((s) => s.totalUs).toList()..sort(); - final cutoff = (sorted.length * 0.99).floor(); - final slowSamples = sorted.skip(cutoff).toList(); - if (slowSamples.isEmpty) return avgFps; - final avgSlowUs = - slowSamples.fold(0, (s, v) => s + v) / slowSamples.length; - return avgSlowUs > 0 ? 1000000 / avgSlowUs : 0.0; - } - - /// Worst 5-percentile frame rate. - double get fivePercentLowFps { - if (_samples.isEmpty) return 0.0; - final sorted = _samples.map((s) => s.totalUs).toList()..sort(); - final cutoff = (sorted.length * 0.95).floor(); - final slowSamples = sorted.skip(cutoff).toList(); - if (slowSamples.isEmpty) return avgFps; - final avgSlowUs = - slowSamples.fold(0, (s, v) => s + v) / slowSamples.length; - return avgSlowUs > 0 ? 1000000 / avgSlowUs : 0.0; - } - - /// Counts how many frames exceeded the target budget. - int jankyFrameCount(double targetHz) { - final budgetUs = (1000000 / targetHz).round(); - return _samples.where((s) => s.totalUs > budgetUs).length; - } - - /// Counts how many frames took more than twice the target budget. - int severeJankCount(double targetHz) { - final budgetUs = (1000000 / targetHz).round(); - return _samples.where((s) => s.totalUs > budgetUs * 2).length; - } - - /// Percentage of frames that were missed. - double missedFramePercent(double targetHz) { - if (_samples.isEmpty) return 0.0; - return jankyFrameCount(targetHz) / _samples.length * 100.0; - } -} diff --git a/third_party/refresh_rate/lib/src/verification/overlay_controller.dart b/third_party/refresh_rate/lib/src/verification/overlay_controller.dart deleted file mode 100644 index b79893d3..00000000 --- a/third_party/refresh_rate/lib/src/verification/overlay_controller.dart +++ /dev/null @@ -1,95 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter/scheduler.dart'; -import 'fps_tracker.dart'; -import 'overlay_widgets.dart'; - -enum _OverlayMode { none, fps, hz, full } - -/// Manages the visibility and rendering of debug overlays. -class OverlayController { - OverlayController._(); - - /// The singleton instance of [OverlayController]. - static final instance = OverlayController._(); - - OverlayEntry? _entry; - _OverlayMode _mode = _OverlayMode.none; - final FpsTracker _tracker = FpsTracker(); - TimingsCallback? _timingsCallback; - - /// Whether an overlay is currently visible. - bool get isVisible => _mode != _OverlayMode.none; - - /// Shows a compact FPS overlay. - void showFPS() => _show(_OverlayMode.fps); - - /// Shows a compact Hz (refresh rate) overlay. - void showHz() => _show(_OverlayMode.hz); - - /// Shows the full debug overlay with detailed metrics. - void showFull() => _show(_OverlayMode.full); - - /// Hides any currently visible overlay. - void hide() { - _entry?.remove(); - _entry = null; - _mode = _OverlayMode.none; - _stopTracking(); - } - - void _show(_OverlayMode mode) { - hide(); - _mode = mode; - _startTracking(); - WidgetsBinding.instance.addPostFrameCallback((_) { - final overlay = _findOverlay(); - if (overlay == null) return; - _entry = OverlayEntry(builder: (_) => _buildWidget()); - overlay.insert(_entry!); - }); - } - - // Walks DOWN the element tree to find the first OverlayState. - // Overlay.maybeOf(rootElement) fails because the Overlay is a descendant, - // not an ancestor, of the root element. - static OverlayState? _findOverlay() { - final root = WidgetsBinding.instance.rootElement; - if (root == null) return null; - OverlayState? found; - void visit(Element element) { - if (found != null) return; - if (element is StatefulElement && element.state is OverlayState) { - found = element.state as OverlayState; - return; - } - element.visitChildren(visit); - } - - root.visitChildren(visit); - return found; - } - - Widget _buildWidget() { - final inner = switch (_mode) { - _OverlayMode.fps => FpsOverlayWidget(tracker: _tracker), - _OverlayMode.hz => HzOverlayWidget(tracker: _tracker), - _OverlayMode.full => FullOverlayWidget(tracker: _tracker), - _OverlayMode.none => const SizedBox.shrink(), - }; - return inner; - } - - void _startTracking() { - if (_timingsCallback != null) return; - _timingsCallback = _tracker.addTimings; - SchedulerBinding.instance.addTimingsCallback(_timingsCallback!); - } - - void _stopTracking() { - if (_timingsCallback != null) { - SchedulerBinding.instance.removeTimingsCallback(_timingsCallback!); - _timingsCallback = null; - } - _tracker.reset(); - } -} diff --git a/third_party/refresh_rate/lib/src/verification/overlay_widgets.dart b/third_party/refresh_rate/lib/src/verification/overlay_widgets.dart deleted file mode 100644 index 273807e4..00000000 --- a/third_party/refresh_rate/lib/src/verification/overlay_widgets.dart +++ /dev/null @@ -1,177 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter/scheduler.dart'; -import '../models/enums.dart'; -import '../refresh_rate.dart'; -import 'fps_tracker.dart'; - -mixin _OverlayStateMixin on State { - late final Ticker _ticker; - - @override - void initState() { - super.initState(); - _ticker = Ticker((_) => setState(() {})); - _ticker.start(); - } - - @override - void dispose() { - _ticker.dispose(); - super.dispose(); - } - - Color fpsColor(double fps, double targetHz) { - if (fps >= targetHz * 0.95) return const Color(0xFF4CAF50); - if (fps >= targetHz * 0.75) return const Color(0xFFFFC107); - return const Color(0xFFF44336); - } - - Widget overlayContainer({required Widget child}) { - return Positioned( - top: MediaQueryData.fromView(View.of(context)).padding.top + 4, - right: 8, - child: IgnorePointer( - child: Material( - type: MaterialType.transparency, - child: Container( - padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), - decoration: BoxDecoration( - color: const Color(0xDD000000), - borderRadius: BorderRadius.circular(6), - ), - child: child, - ), - ), - ), - ); - } -} - -// ── FPS Badge ───────────────────────────────────────────────────── - -/// A small overlay widget that displays the current FPS. -class FpsOverlayWidget extends StatefulWidget { - /// The [FpsTracker] providing frame timings. - final FpsTracker tracker; - - /// Creates a [FpsOverlayWidget]. - const FpsOverlayWidget({super.key, required this.tracker}); - @override - State createState() => _FpsOverlayWidgetState(); -} - -class _FpsOverlayWidgetState extends State - with _OverlayStateMixin { - @override - Widget build(BuildContext context) { - final fps = widget.tracker.recentFps(); - return overlayContainer( - child: Text( - '${fps.toStringAsFixed(0)} FPS', - style: TextStyle( - color: fpsColor(fps, RefreshRate.info.maxRate), - fontSize: 13, - fontWeight: FontWeight.bold, - fontFeatures: const [FontFeature.tabularFigures()], - ), - ), - ); - } -} - -// ── Hz Badge ────────────────────────────────────────────────────── - -/// A small overlay widget that displays the current display refresh rate. -class HzOverlayWidget extends StatefulWidget { - /// The [FpsTracker] (unused but required for generic widget creation). - final FpsTracker tracker; - - /// Creates a [HzOverlayWidget]. - const HzOverlayWidget({super.key, required this.tracker}); - @override - State createState() => _HzOverlayWidgetState(); -} - -class _HzOverlayWidgetState extends State - with _OverlayStateMixin { - @override - Widget build(BuildContext context) { - final hz = RefreshRate.info.currentRate; - return overlayContainer( - child: Text( - '${hz.toStringAsFixed(0)}Hz', - style: const TextStyle( - color: Color(0xFF64B5F6), - fontSize: 13, - fontWeight: FontWeight.bold, - fontFeatures: [FontFeature.tabularFigures()], - ), - ), - ); - } -} - -// ── Full Diagnostic Overlay ──────────────────────────────────────── - -/// A larger overlay widget that displays FPS, build/raster times, and device health. -class FullOverlayWidget extends StatefulWidget { - /// The [FpsTracker] providing frame timings. - final FpsTracker tracker; - - /// Creates a [FullOverlayWidget]. - const FullOverlayWidget({super.key, required this.tracker}); - @override - State createState() => _FullOverlayWidgetState(); -} - -class _FullOverlayWidgetState extends State - with _OverlayStateMixin { - @override - Widget build(BuildContext context) { - final fps = widget.tracker.recentFps(); - final buildMs = widget.tracker.avgBuildMs; - final rasterMs = widget.tracker.avgRasterMs; - final targetHz = RefreshRate.info.maxRate; - final budgetMs = 1000.0 / targetHz; - - return overlayContainer( - child: DefaultTextStyle( - style: const TextStyle( - color: Color(0xFFFFFFFF), - fontSize: 11, - fontFeatures: [FontFeature.tabularFigures()], - ), - child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.end, - children: [ - Text( - '${fps.toStringAsFixed(0)} FPS', - style: TextStyle( - color: fpsColor(fps, targetHz), - fontSize: 14, - fontWeight: FontWeight.bold, - fontFeatures: const [FontFeature.tabularFigures()], - ), - ), - Text( - 'build ${buildMs.toStringAsFixed(1)}ms raster ${rasterMs.toStringAsFixed(1)}ms'), - Text( - 'budget ${budgetMs.toStringAsFixed(1)}ms @ ${targetHz.toStringAsFixed(0)}Hz'), - if (RefreshRate.isLowPowerMode) - const Text( - '\u26a1 Low Power', - style: TextStyle(color: Color(0xFFFFCC02)), - ), - if (RefreshRate.thermalState != ThermalState.nominal && - RefreshRate.thermalState != ThermalState.unknown) - Text( - 'thermal: ${RefreshRate.thermalState.name}', - style: const TextStyle(color: Color(0xFFFF7043)), - ), - ], - ), - ), - ); - } -} diff --git a/third_party/refresh_rate/lib/src/verification/refresh_rate_session.dart b/third_party/refresh_rate/lib/src/verification/refresh_rate_session.dart deleted file mode 100644 index 139295c5..00000000 --- a/third_party/refresh_rate/lib/src/verification/refresh_rate_session.dart +++ /dev/null @@ -1,135 +0,0 @@ -import 'package:flutter/scheduler.dart'; -import 'package:flutter/widgets.dart'; -import '../models/display_info.dart'; -import '../models/enums.dart'; -import '../models/session_report.dart'; -import 'fps_tracker.dart'; -import 'session_scorer.dart'; - -/// An active FPS benchmark session that records frame timings. -/// -/// Create via [RefreshRate.startSession] and call [end] to receive a -/// [SessionReport] with verdict, FPS stats, and bottleneck analysis. -/// -/// The session automatically pauses when the app goes to the background and -/// resumes (with a warm-up exclusion window) when the app returns to the -/// foreground. -class RefreshRateSession { - /// The human-readable name given to this session. - final String name; - SessionState _state; - final DateTime _startedAt; - final double _targetHz; - final DisplayInfo _initialInfo; - final FpsTracker _tracker = FpsTracker(); - Duration _excludedDuration = Duration.zero; - final Map _exclusions = {}; - TimingsCallback? _timingsCallback; - AppLifecycleListener? _lifecycleListener; - DateTime? _inactiveAt; - static const _warmupDuration = Duration(milliseconds: 500); - - RefreshRateSession._({ - required this.name, - required SessionState state, - required DateTime startedAt, - required double targetHz, - required DisplayInfo initialInfo, - }) : _state = state, - _startedAt = startedAt, - _targetHz = targetHz, - _initialInfo = initialInfo; - - /// Creates and starts a new tracking session. - static RefreshRateSession create(String name, DisplayInfo info) { - final session = RefreshRateSession._( - name: name, - state: SessionState.running, - startedAt: DateTime.now(), - targetHz: info.maxRate, - initialInfo: info, - ); - session._timingsCallback = session._tracker.addTimings; - SchedulerBinding.instance.addTimingsCallback(session._timingsCallback!); - session._registerLifecycleObserver(); - return session; - } - - /// Current lifecycle state of the session. - SessionState get state => _state; - - /// The time at which this session was created. - DateTime get startedAt => _startedAt; - - /// The target refresh rate in Hz (taken from [DisplayInfo.maxRate] at creation time). - double get targetHz => _targetHz; - - /// Stops frame timing collection and computes a [SessionReport]. - /// - /// Must be called exactly once. After this call the session is in - /// [SessionState.completed] and further calls have undefined behaviour. - Future end() async { - _stopTracking(); - _state = SessionState.completed; - return SessionScorer.compute( - sessionName: name, - tracker: _tracker, - targetHz: _targetHz, - validDuration: DateTime.now().difference(_startedAt) - _excludedDuration, - excludedDuration: _excludedDuration, - exclusionReasons: Map.unmodifiable(_exclusions), - deviceState: DeviceStateSnapshot( - isLowPowerMode: _initialInfo.isLowPowerMode, - thermalState: _initialInfo.thermalState, - hasAdaptiveRefreshRate: _initialInfo.hasAdaptiveRefreshRate, - displayServer: _initialInfo.displayServer, - monitorCount: _initialInfo.monitorCount, - ), - ); - } - - void _registerLifecycleObserver() { - _lifecycleListener = AppLifecycleListener( - onHide: _onInactive, - onInactive: _onInactive, - onPause: _onInactive, - onResume: _onResume, - ); - } - - void _onInactive() { - if (_state != SessionState.running) return; - _state = SessionState.interrupted; - _inactiveAt = DateTime.now(); - _addExclusion(ExclusionReason.appBackgrounded); - } - - void _onResume() { - if (_state != SessionState.interrupted) return; - if (_inactiveAt != null) { - _excludedDuration += DateTime.now().difference(_inactiveAt!); - _inactiveAt = null; - } - _state = SessionState.warmup; - Future.delayed(_warmupDuration, () { - if (_state == SessionState.warmup) { - _excludedDuration += _warmupDuration; - _addExclusion(ExclusionReason.resumeWarmup); - _state = SessionState.running; - } - }); - } - - void _addExclusion(ExclusionReason reason) { - _exclusions[reason] = (_exclusions[reason] ?? 0) + 1; - } - - void _stopTracking() { - if (_timingsCallback != null) { - SchedulerBinding.instance.removeTimingsCallback(_timingsCallback!); - _timingsCallback = null; - } - _lifecycleListener?.dispose(); - _lifecycleListener = null; - } -} diff --git a/third_party/refresh_rate/lib/src/verification/session_scorer.dart b/third_party/refresh_rate/lib/src/verification/session_scorer.dart deleted file mode 100644 index 3a56b00c..00000000 --- a/third_party/refresh_rate/lib/src/verification/session_scorer.dart +++ /dev/null @@ -1,97 +0,0 @@ -import '../models/enums.dart'; -import '../models/session_report.dart'; -import 'fps_tracker.dart'; - -/// Utility class that calculates the final [SessionReport] metrics. -abstract class SessionScorer { - /// Computes a [SessionReport] from the recorded tracking data. - static SessionReport compute({ - required String sessionName, - required FpsTracker tracker, - required double targetHz, - required Duration validDuration, - required Duration excludedDuration, - required Map exclusionReasons, - required DeviceStateSnapshot deviceState, - }) { - final frameBudgetMs = 1000.0 / targetHz; - final avgFps = tracker.avgFps; - final missed = tracker.missedFramePercent(targetHz); - final one = tracker.onePercentLowFps; - final five = tracker.fivePercentLowFps; - final janky = tracker.jankyFrameCount(targetHz); - final severe = tracker.severeJankCount(targetHz); - final avgBuild = tracker.avgBuildMs; - final avgRaster = tracker.avgRasterMs; - final avgTotal = tracker.avgTotalMs; - - final verdict = _computeVerdict(avgFps, targetHz, missed); - final bottleneck = _computeBottleneck( - avgBuild: avgBuild, - avgRaster: avgRaster, - avgFps: avgFps, - targetHz: targetHz, - isLowPowerMode: deviceState.isLowPowerMode, - thermalState: deviceState.thermalState, - ); - - return SessionReport( - sessionName: sessionName, - verdict: verdict, - likelyBottleneck: bottleneck, - targetHz: targetHz, - observedAvgHz: avgFps, - frameBudgetMs: frameBudgetMs, - avgFps: avgFps, - onePercentLowFps: one, - fivePercentLowFps: five, - avgBuildMs: avgBuild, - avgRasterMs: avgRaster, - avgTotalFrameMs: avgTotal, - jankyFrameCount: janky, - severeJankCount: severe, - missedFramePercent: missed, - validDuration: validDuration, - excludedDuration: excludedDuration, - exclusionReasons: exclusionReasons, - deviceState: deviceState, - ); - } - - static Verdict _computeVerdict( - double avgFps, double targetHz, double missedPct) { - if (avgFps == 0) return Verdict.inconclusive; - final hitRate = avgFps / targetHz; - if (hitRate >= 0.95 && missedPct < 2) return Verdict.excellent; - if (hitRate >= 0.85 && missedPct < 5) return Verdict.good; - if (hitRate >= 0.70 && missedPct < 15) return Verdict.fair; - return Verdict.poor; - } - - static Bottleneck _computeBottleneck({ - required double avgBuild, - required double avgRaster, - required double avgFps, - required double targetHz, - required bool? isLowPowerMode, - required ThermalState thermalState, - }) { - if (isLowPowerMode == true) return Bottleneck.powerLimited; - if (thermalState == ThermalState.serious || - thermalState == ThermalState.critical) { - return Bottleneck.thermalLimited; - } - final budgetMs = 1000.0 / targetHz; - // 85-90% of target: likely a display-side cap (LTPO floor, VSync rounding, etc.) - if (avgFps >= targetHz * 0.85 && avgFps < targetHz * 0.95) { - return Bottleneck.displayCapped; - } - // Below 85%: check for build vs raster bottleneck - if (avgFps < targetHz * 0.85) { - if (avgBuild > avgRaster && avgBuild > budgetMs * 0.5) - return Bottleneck.buildBound; - if (avgRaster > budgetMs * 0.5) return Bottleneck.rasterBound; - } - return Bottleneck.none; - } -} diff --git a/third_party/refresh_rate/lib/src/web/raf_hz_detector.dart b/third_party/refresh_rate/lib/src/web/raf_hz_detector.dart deleted file mode 100644 index ba6bfefe..00000000 --- a/third_party/refresh_rate/lib/src/web/raf_hz_detector.dart +++ /dev/null @@ -1,74 +0,0 @@ -import 'dart:async'; -import 'dart:js_interop'; - -import 'package:web/web.dart' as web; - -/// Detects the display's refresh rate by measuring -/// `requestAnimationFrame` callback intervals. -/// -/// Uses the same technique as TestUFO: collect a window of rAF -/// timestamps, compute the median inter-frame interval, and derive Hz. -class RafHzDetector { - /// Number of frames to sample before reporting a result. - static const int _kSampleCount = 120; - - /// Measures the current display refresh rate via rAF timing. - /// - /// Collects [_kSampleCount] frames, computes the median interval, - /// and returns `1000 / medianMs`. Returns `null` if measurement fails. - static Future measure() { - final completer = Completer(); - final timestamps = []; - late final JSFunction callback; - - void onFrame(JSNumber ts) { - timestamps.add(ts.toDartDouble); - - if (timestamps.length >= _kSampleCount + 1) { - // Compute intervals - final intervals = []; - for (var i = 1; i < timestamps.length; i++) { - intervals.add(timestamps[i] - timestamps[i - 1]); - } - intervals.sort(); - final median = intervals[intervals.length ~/ 2]; - - if (median > 0) { - // Round to nearest common Hz value (e.g. 60, 90, 120, 144, 165, 240) - final rawHz = 1000.0 / median; - completer.complete(_snapToCommonHz(rawHz)); - } else { - completer.complete(null); - } - } else { - web.window.requestAnimationFrame(callback); - } - } - - callback = onFrame.toJS; - web.window.requestAnimationFrame(callback); - - return completer.future; - } - - /// Snaps a raw Hz measurement to the nearest common display refresh rate - /// when the raw value is within 3% tolerance. - static double _snapToCommonHz(double raw) { - const commonRates = [ - 30.0, - 48.0, - 60.0, - 72.0, - 90.0, - 120.0, - 144.0, - 165.0, - 240.0, - 360.0 - ]; - for (final rate in commonRates) { - if ((raw - rate).abs() / rate < 0.03) return rate; - } - return double.parse(raw.toStringAsFixed(1)); - } -} diff --git a/third_party/refresh_rate/lib/src/web/web_refresh_rate_adapter.dart b/third_party/refresh_rate/lib/src/web/web_refresh_rate_adapter.dart deleted file mode 100644 index 96d0615b..00000000 --- a/third_party/refresh_rate/lib/src/web/web_refresh_rate_adapter.dart +++ /dev/null @@ -1,73 +0,0 @@ -import 'dart:async'; - -import '../generated/refresh_rate_api.g.dart'; -import '../refresh_rate_api_adapter.dart'; -import 'raf_hz_detector.dart'; - -/// Web implementation of [RefreshRateApiAdapter]. -/// -/// Uses `requestAnimationFrame` interval timing to detect the display's -/// current refresh rate. Control methods are graceful no-ops because -/// browsers own their vsync scheduling and expose no API to change it. -class WebRefreshRateApiAdapter implements RefreshRateApiAdapter { - double? _lastMeasuredRate; - - @override - Future getDisplayInfo() async { - _lastMeasuredRate = await RafHzDetector.measure(); - return DisplayInfoMessage( - currentRate: _lastMeasuredRate, - // Browsers don't expose max/min/supported rates. - maxRate: _lastMeasuredRate, - minRate: null, - supportedRates: _lastMeasuredRate != null ? [_lastMeasuredRate!] : null, - isVariableRefreshRate: null, - engineTargetRate: _lastMeasuredRate, - // Apple / Android specific — not applicable on web. - iosProMotionEnabled: null, - androidApiLevel: null, - // No battery/thermal APIs on web. - isLowPowerMode: null, - thermalStateIndex: null, - hasAdaptiveRefreshRate: null, - displayServer: 'web', - monitorCount: 1, - ); - } - - /// No-op — browsers manage their own vsync scheduling. - @override - FutureOr enable() {} - - /// No-op — browsers manage their own vsync scheduling. - @override - FutureOr disable() {} - - /// No-op — cannot request max rate on web. - @override - FutureOr preferMax() {} - - /// No-op — cannot change rate preference on web. - @override - FutureOr preferDefault() {} - - /// No-op — cannot match content frame rate on web. - @override - FutureOr matchContent(double fps) {} - - /// No-op — cannot boost refresh rate on web. - @override - FutureOr boost(int durationMs) {} - - /// No-op — rate categories are Android-specific. - @override - FutureOr setCategory(int categoryIndex) {} - - /// No-op — touch boost is Android-specific. - @override - FutureOr setTouchBoost(bool enabled) {} - - /// Web supports querying the refresh rate but not controlling it. - @override - FutureOr isSupported() => false; -} diff --git a/third_party/refresh_rate/linux/CMakeLists.txt b/third_party/refresh_rate/linux/CMakeLists.txt deleted file mode 100644 index 3f93096e..00000000 --- a/third_party/refresh_rate/linux/CMakeLists.txt +++ /dev/null @@ -1,18 +0,0 @@ -cmake_minimum_required(VERSION 3.10) -set(PROJECT_NAME "refresh_rate") -project(${PROJECT_NAME} LANGUAGES CXX) - -set(PLUGIN_NAME "${PROJECT_NAME}_plugin") - -add_library(${PLUGIN_NAME} SHARED - "refresh_rate_plugin.cc" -) - -apply_standard_settings(${PLUGIN_NAME}) -set_target_properties(${PLUGIN_NAME} PROPERTIES - CXX_VISIBILITY_PRESET hidden) -target_compile_definitions(${PLUGIN_NAME} PRIVATE FLUTTER_PLUGIN_IMPL) -target_include_directories(${PLUGIN_NAME} INTERFACE - "${CMAKE_CURRENT_SOURCE_DIR}/include") -target_link_libraries(${PLUGIN_NAME} PRIVATE flutter) -target_link_libraries(${PLUGIN_NAME} PRIVATE PkgConfig::GTK) diff --git a/third_party/refresh_rate/linux/include/refresh_rate/refresh_rate_plugin.h b/third_party/refresh_rate/linux/include/refresh_rate/refresh_rate_plugin.h deleted file mode 100644 index 7d23107b..00000000 --- a/third_party/refresh_rate/linux/include/refresh_rate/refresh_rate_plugin.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef FLUTTER_PLUGIN_REFRESH_RATE_PLUGIN_H_ -#define FLUTTER_PLUGIN_REFRESH_RATE_PLUGIN_H_ - -#include - -G_BEGIN_DECLS - -#ifdef FLUTTER_PLUGIN_IMPL -#define FLUTTER_PLUGIN_EXPORT __attribute__((visibility("default"))) -#else -#define FLUTTER_PLUGIN_EXPORT -#endif - -G_DECLARE_FINAL_TYPE(RefreshRatePlugin, refresh_rate_plugin, REFRESH_RATE, - PLUGIN, GObject) - -FLUTTER_PLUGIN_EXPORT void refresh_rate_plugin_register_with_registrar( - FlPluginRegistrar* registrar); - -G_END_DECLS - -#endif // FLUTTER_PLUGIN_REFRESH_RATE_PLUGIN_H_ diff --git a/third_party/refresh_rate/linux/refresh_rate_api.g.cc b/third_party/refresh_rate/linux/refresh_rate_api.g.cc deleted file mode 100644 index f4911e8a..00000000 --- a/third_party/refresh_rate/linux/refresh_rate_api.g.cc +++ /dev/null @@ -1,651 +0,0 @@ -// Copyright 2026 Qoder (qoder.in). All rights reserved. -// Use of this source code is governed by a BSD-style license. -// Autogenerated from Pigeon (v22.7.4), do not edit directly. -// See also: https://pub.dev/packages/pigeon - -#undef _HAS_EXCEPTIONS - -#include "refresh_rate_api.g.h" - -#include -#include -#include -#include - -#include -#include -#include - -namespace refresh_rate { -using flutter::BasicMessageChannel; -using flutter::CustomEncodableValue; -using flutter::EncodableList; -using flutter::EncodableMap; -using flutter::EncodableValue; - -FlutterError CreateConnectionError(const std::string channel_name) { - return FlutterError( - "channel-error", - "Unable to establish connection on channel: '" + channel_name + "'.", - EncodableValue("")); -} - -// DisplayInfoMessage - -DisplayInfoMessage::DisplayInfoMessage() {} - -DisplayInfoMessage::DisplayInfoMessage( - const double* current_rate, - const double* max_rate, - const double* min_rate, - const EncodableList* supported_rates, - const bool* is_variable_refresh_rate, - const double* engine_target_rate, - const bool* ios_pro_motion_enabled, - const int64_t* android_api_level, - const bool* is_low_power_mode, - const int64_t* thermal_state_index, - const bool* has_adaptive_refresh_rate, - const std::string* display_server, - const int64_t* monitor_count) - : current_rate_(current_rate ? std::optional(*current_rate) : std::nullopt), - max_rate_(max_rate ? std::optional(*max_rate) : std::nullopt), - min_rate_(min_rate ? std::optional(*min_rate) : std::nullopt), - supported_rates_(supported_rates ? std::optional(*supported_rates) : std::nullopt), - is_variable_refresh_rate_(is_variable_refresh_rate ? std::optional(*is_variable_refresh_rate) : std::nullopt), - engine_target_rate_(engine_target_rate ? std::optional(*engine_target_rate) : std::nullopt), - ios_pro_motion_enabled_(ios_pro_motion_enabled ? std::optional(*ios_pro_motion_enabled) : std::nullopt), - android_api_level_(android_api_level ? std::optional(*android_api_level) : std::nullopt), - is_low_power_mode_(is_low_power_mode ? std::optional(*is_low_power_mode) : std::nullopt), - thermal_state_index_(thermal_state_index ? std::optional(*thermal_state_index) : std::nullopt), - has_adaptive_refresh_rate_(has_adaptive_refresh_rate ? std::optional(*has_adaptive_refresh_rate) : std::nullopt), - display_server_(display_server ? std::optional(*display_server) : std::nullopt), - monitor_count_(monitor_count ? std::optional(*monitor_count) : std::nullopt) {} - -const double* DisplayInfoMessage::current_rate() const { - return current_rate_ ? &(*current_rate_) : nullptr; -} - -void DisplayInfoMessage::set_current_rate(const double* value_arg) { - current_rate_ = value_arg ? std::optional(*value_arg) : std::nullopt; -} - -void DisplayInfoMessage::set_current_rate(double value_arg) { - current_rate_ = value_arg; -} - - -const double* DisplayInfoMessage::max_rate() const { - return max_rate_ ? &(*max_rate_) : nullptr; -} - -void DisplayInfoMessage::set_max_rate(const double* value_arg) { - max_rate_ = value_arg ? std::optional(*value_arg) : std::nullopt; -} - -void DisplayInfoMessage::set_max_rate(double value_arg) { - max_rate_ = value_arg; -} - - -const double* DisplayInfoMessage::min_rate() const { - return min_rate_ ? &(*min_rate_) : nullptr; -} - -void DisplayInfoMessage::set_min_rate(const double* value_arg) { - min_rate_ = value_arg ? std::optional(*value_arg) : std::nullopt; -} - -void DisplayInfoMessage::set_min_rate(double value_arg) { - min_rate_ = value_arg; -} - - -const EncodableList* DisplayInfoMessage::supported_rates() const { - return supported_rates_ ? &(*supported_rates_) : nullptr; -} - -void DisplayInfoMessage::set_supported_rates(const EncodableList* value_arg) { - supported_rates_ = value_arg ? std::optional(*value_arg) : std::nullopt; -} - -void DisplayInfoMessage::set_supported_rates(const EncodableList& value_arg) { - supported_rates_ = value_arg; -} - - -const bool* DisplayInfoMessage::is_variable_refresh_rate() const { - return is_variable_refresh_rate_ ? &(*is_variable_refresh_rate_) : nullptr; -} - -void DisplayInfoMessage::set_is_variable_refresh_rate(const bool* value_arg) { - is_variable_refresh_rate_ = value_arg ? std::optional(*value_arg) : std::nullopt; -} - -void DisplayInfoMessage::set_is_variable_refresh_rate(bool value_arg) { - is_variable_refresh_rate_ = value_arg; -} - - -const double* DisplayInfoMessage::engine_target_rate() const { - return engine_target_rate_ ? &(*engine_target_rate_) : nullptr; -} - -void DisplayInfoMessage::set_engine_target_rate(const double* value_arg) { - engine_target_rate_ = value_arg ? std::optional(*value_arg) : std::nullopt; -} - -void DisplayInfoMessage::set_engine_target_rate(double value_arg) { - engine_target_rate_ = value_arg; -} - - -const bool* DisplayInfoMessage::ios_pro_motion_enabled() const { - return ios_pro_motion_enabled_ ? &(*ios_pro_motion_enabled_) : nullptr; -} - -void DisplayInfoMessage::set_ios_pro_motion_enabled(const bool* value_arg) { - ios_pro_motion_enabled_ = value_arg ? std::optional(*value_arg) : std::nullopt; -} - -void DisplayInfoMessage::set_ios_pro_motion_enabled(bool value_arg) { - ios_pro_motion_enabled_ = value_arg; -} - - -const int64_t* DisplayInfoMessage::android_api_level() const { - return android_api_level_ ? &(*android_api_level_) : nullptr; -} - -void DisplayInfoMessage::set_android_api_level(const int64_t* value_arg) { - android_api_level_ = value_arg ? std::optional(*value_arg) : std::nullopt; -} - -void DisplayInfoMessage::set_android_api_level(int64_t value_arg) { - android_api_level_ = value_arg; -} - - -const bool* DisplayInfoMessage::is_low_power_mode() const { - return is_low_power_mode_ ? &(*is_low_power_mode_) : nullptr; -} - -void DisplayInfoMessage::set_is_low_power_mode(const bool* value_arg) { - is_low_power_mode_ = value_arg ? std::optional(*value_arg) : std::nullopt; -} - -void DisplayInfoMessage::set_is_low_power_mode(bool value_arg) { - is_low_power_mode_ = value_arg; -} - - -const int64_t* DisplayInfoMessage::thermal_state_index() const { - return thermal_state_index_ ? &(*thermal_state_index_) : nullptr; -} - -void DisplayInfoMessage::set_thermal_state_index(const int64_t* value_arg) { - thermal_state_index_ = value_arg ? std::optional(*value_arg) : std::nullopt; -} - -void DisplayInfoMessage::set_thermal_state_index(int64_t value_arg) { - thermal_state_index_ = value_arg; -} - - -const bool* DisplayInfoMessage::has_adaptive_refresh_rate() const { - return has_adaptive_refresh_rate_ ? &(*has_adaptive_refresh_rate_) : nullptr; -} - -void DisplayInfoMessage::set_has_adaptive_refresh_rate(const bool* value_arg) { - has_adaptive_refresh_rate_ = value_arg ? std::optional(*value_arg) : std::nullopt; -} - -void DisplayInfoMessage::set_has_adaptive_refresh_rate(bool value_arg) { - has_adaptive_refresh_rate_ = value_arg; -} - - -const std::string* DisplayInfoMessage::display_server() const { - return display_server_ ? &(*display_server_) : nullptr; -} - -void DisplayInfoMessage::set_display_server(const std::string_view* value_arg) { - display_server_ = value_arg ? std::optional(*value_arg) : std::nullopt; -} - -void DisplayInfoMessage::set_display_server(std::string_view value_arg) { - display_server_ = value_arg; -} - - -const int64_t* DisplayInfoMessage::monitor_count() const { - return monitor_count_ ? &(*monitor_count_) : nullptr; -} - -void DisplayInfoMessage::set_monitor_count(const int64_t* value_arg) { - monitor_count_ = value_arg ? std::optional(*value_arg) : std::nullopt; -} - -void DisplayInfoMessage::set_monitor_count(int64_t value_arg) { - monitor_count_ = value_arg; -} - - -EncodableList DisplayInfoMessage::ToEncodableList() const { - EncodableList list; - list.reserve(13); - list.push_back(current_rate_ ? EncodableValue(*current_rate_) : EncodableValue()); - list.push_back(max_rate_ ? EncodableValue(*max_rate_) : EncodableValue()); - list.push_back(min_rate_ ? EncodableValue(*min_rate_) : EncodableValue()); - list.push_back(supported_rates_ ? EncodableValue(*supported_rates_) : EncodableValue()); - list.push_back(is_variable_refresh_rate_ ? EncodableValue(*is_variable_refresh_rate_) : EncodableValue()); - list.push_back(engine_target_rate_ ? EncodableValue(*engine_target_rate_) : EncodableValue()); - list.push_back(ios_pro_motion_enabled_ ? EncodableValue(*ios_pro_motion_enabled_) : EncodableValue()); - list.push_back(android_api_level_ ? EncodableValue(*android_api_level_) : EncodableValue()); - list.push_back(is_low_power_mode_ ? EncodableValue(*is_low_power_mode_) : EncodableValue()); - list.push_back(thermal_state_index_ ? EncodableValue(*thermal_state_index_) : EncodableValue()); - list.push_back(has_adaptive_refresh_rate_ ? EncodableValue(*has_adaptive_refresh_rate_) : EncodableValue()); - list.push_back(display_server_ ? EncodableValue(*display_server_) : EncodableValue()); - list.push_back(monitor_count_ ? EncodableValue(*monitor_count_) : EncodableValue()); - return list; -} - -DisplayInfoMessage DisplayInfoMessage::FromEncodableList(const EncodableList& list) { - DisplayInfoMessage decoded; - auto& encodable_current_rate = list[0]; - if (!encodable_current_rate.IsNull()) { - decoded.set_current_rate(std::get(encodable_current_rate)); - } - auto& encodable_max_rate = list[1]; - if (!encodable_max_rate.IsNull()) { - decoded.set_max_rate(std::get(encodable_max_rate)); - } - auto& encodable_min_rate = list[2]; - if (!encodable_min_rate.IsNull()) { - decoded.set_min_rate(std::get(encodable_min_rate)); - } - auto& encodable_supported_rates = list[3]; - if (!encodable_supported_rates.IsNull()) { - decoded.set_supported_rates(std::get(encodable_supported_rates)); - } - auto& encodable_is_variable_refresh_rate = list[4]; - if (!encodable_is_variable_refresh_rate.IsNull()) { - decoded.set_is_variable_refresh_rate(std::get(encodable_is_variable_refresh_rate)); - } - auto& encodable_engine_target_rate = list[5]; - if (!encodable_engine_target_rate.IsNull()) { - decoded.set_engine_target_rate(std::get(encodable_engine_target_rate)); - } - auto& encodable_ios_pro_motion_enabled = list[6]; - if (!encodable_ios_pro_motion_enabled.IsNull()) { - decoded.set_ios_pro_motion_enabled(std::get(encodable_ios_pro_motion_enabled)); - } - auto& encodable_android_api_level = list[7]; - if (!encodable_android_api_level.IsNull()) { - decoded.set_android_api_level(std::get(encodable_android_api_level)); - } - auto& encodable_is_low_power_mode = list[8]; - if (!encodable_is_low_power_mode.IsNull()) { - decoded.set_is_low_power_mode(std::get(encodable_is_low_power_mode)); - } - auto& encodable_thermal_state_index = list[9]; - if (!encodable_thermal_state_index.IsNull()) { - decoded.set_thermal_state_index(std::get(encodable_thermal_state_index)); - } - auto& encodable_has_adaptive_refresh_rate = list[10]; - if (!encodable_has_adaptive_refresh_rate.IsNull()) { - decoded.set_has_adaptive_refresh_rate(std::get(encodable_has_adaptive_refresh_rate)); - } - auto& encodable_display_server = list[11]; - if (!encodable_display_server.IsNull()) { - decoded.set_display_server(std::get(encodable_display_server)); - } - auto& encodable_monitor_count = list[12]; - if (!encodable_monitor_count.IsNull()) { - decoded.set_monitor_count(std::get(encodable_monitor_count)); - } - return decoded; -} - - -PigeonInternalCodecSerializer::PigeonInternalCodecSerializer() {} - -EncodableValue PigeonInternalCodecSerializer::ReadValueOfType( - uint8_t type, - flutter::ByteStreamReader* stream) const { - switch (type) { - case 129: { - return CustomEncodableValue(DisplayInfoMessage::FromEncodableList(std::get(ReadValue(stream)))); - } - default: - return flutter::StandardCodecSerializer::ReadValueOfType(type, stream); - } -} - -void PigeonInternalCodecSerializer::WriteValue( - const EncodableValue& value, - flutter::ByteStreamWriter* stream) const { - if (const CustomEncodableValue* custom_value = std::get_if(&value)) { - if (custom_value->type() == typeid(DisplayInfoMessage)) { - stream->WriteByte(129); - WriteValue(EncodableValue(std::any_cast(*custom_value).ToEncodableList()), stream); - return; - } - } - flutter::StandardCodecSerializer::WriteValue(value, stream); -} - -/// The codec used by RefreshRateHostApi. -const flutter::StandardMessageCodec& RefreshRateHostApi::GetCodec() { - return flutter::StandardMessageCodec::GetInstance(&PigeonInternalCodecSerializer::GetInstance()); -} - -// Sets up an instance of `RefreshRateHostApi` to handle messages through the `binary_messenger`. -void RefreshRateHostApi::SetUp( - flutter::BinaryMessenger* binary_messenger, - RefreshRateHostApi* api) { - RefreshRateHostApi::SetUp(binary_messenger, api, ""); -} - -void RefreshRateHostApi::SetUp( - flutter::BinaryMessenger* binary_messenger, - RefreshRateHostApi* api, - const std::string& message_channel_suffix) { - const std::string prepended_suffix = message_channel_suffix.length() > 0 ? std::string(".") + message_channel_suffix : ""; - { - BasicMessageChannel<> channel(binary_messenger, "dev.flutter.pigeon.refresh_rate.RefreshRateHostApi.getDisplayInfo" + prepended_suffix, &GetCodec()); - if (api != nullptr) { - channel.SetMessageHandler([api](const EncodableValue& message, const flutter::MessageReply& reply) { - try { - ErrorOr output = api->GetDisplayInfo(); - if (output.has_error()) { - reply(WrapError(output.error())); - return; - } - EncodableList wrapped; - wrapped.push_back(CustomEncodableValue(std::move(output).TakeValue())); - reply(EncodableValue(std::move(wrapped))); - } catch (const std::exception& exception) { - reply(WrapError(exception.what())); - } - }); - } else { - channel.SetMessageHandler(nullptr); - } - } - { - BasicMessageChannel<> channel(binary_messenger, "dev.flutter.pigeon.refresh_rate.RefreshRateHostApi.enable" + prepended_suffix, &GetCodec()); - if (api != nullptr) { - channel.SetMessageHandler([api](const EncodableValue& message, const flutter::MessageReply& reply) { - try { - std::optional output = api->Enable(); - if (output.has_value()) { - reply(WrapError(output.value())); - return; - } - EncodableList wrapped; - wrapped.push_back(EncodableValue()); - reply(EncodableValue(std::move(wrapped))); - } catch (const std::exception& exception) { - reply(WrapError(exception.what())); - } - }); - } else { - channel.SetMessageHandler(nullptr); - } - } - { - BasicMessageChannel<> channel(binary_messenger, "dev.flutter.pigeon.refresh_rate.RefreshRateHostApi.disable" + prepended_suffix, &GetCodec()); - if (api != nullptr) { - channel.SetMessageHandler([api](const EncodableValue& message, const flutter::MessageReply& reply) { - try { - std::optional output = api->Disable(); - if (output.has_value()) { - reply(WrapError(output.value())); - return; - } - EncodableList wrapped; - wrapped.push_back(EncodableValue()); - reply(EncodableValue(std::move(wrapped))); - } catch (const std::exception& exception) { - reply(WrapError(exception.what())); - } - }); - } else { - channel.SetMessageHandler(nullptr); - } - } - { - BasicMessageChannel<> channel(binary_messenger, "dev.flutter.pigeon.refresh_rate.RefreshRateHostApi.preferMax" + prepended_suffix, &GetCodec()); - if (api != nullptr) { - channel.SetMessageHandler([api](const EncodableValue& message, const flutter::MessageReply& reply) { - try { - std::optional output = api->PreferMax(); - if (output.has_value()) { - reply(WrapError(output.value())); - return; - } - EncodableList wrapped; - wrapped.push_back(EncodableValue()); - reply(EncodableValue(std::move(wrapped))); - } catch (const std::exception& exception) { - reply(WrapError(exception.what())); - } - }); - } else { - channel.SetMessageHandler(nullptr); - } - } - { - BasicMessageChannel<> channel(binary_messenger, "dev.flutter.pigeon.refresh_rate.RefreshRateHostApi.preferDefault" + prepended_suffix, &GetCodec()); - if (api != nullptr) { - channel.SetMessageHandler([api](const EncodableValue& message, const flutter::MessageReply& reply) { - try { - std::optional output = api->PreferDefault(); - if (output.has_value()) { - reply(WrapError(output.value())); - return; - } - EncodableList wrapped; - wrapped.push_back(EncodableValue()); - reply(EncodableValue(std::move(wrapped))); - } catch (const std::exception& exception) { - reply(WrapError(exception.what())); - } - }); - } else { - channel.SetMessageHandler(nullptr); - } - } - { - BasicMessageChannel<> channel(binary_messenger, "dev.flutter.pigeon.refresh_rate.RefreshRateHostApi.matchContent" + prepended_suffix, &GetCodec()); - if (api != nullptr) { - channel.SetMessageHandler([api](const EncodableValue& message, const flutter::MessageReply& reply) { - try { - const auto& args = std::get(message); - const auto& encodable_fps_arg = args.at(0); - if (encodable_fps_arg.IsNull()) { - reply(WrapError("fps_arg unexpectedly null.")); - return; - } - const auto& fps_arg = std::get(encodable_fps_arg); - std::optional output = api->MatchContent(fps_arg); - if (output.has_value()) { - reply(WrapError(output.value())); - return; - } - EncodableList wrapped; - wrapped.push_back(EncodableValue()); - reply(EncodableValue(std::move(wrapped))); - } catch (const std::exception& exception) { - reply(WrapError(exception.what())); - } - }); - } else { - channel.SetMessageHandler(nullptr); - } - } - { - BasicMessageChannel<> channel(binary_messenger, "dev.flutter.pigeon.refresh_rate.RefreshRateHostApi.boost" + prepended_suffix, &GetCodec()); - if (api != nullptr) { - channel.SetMessageHandler([api](const EncodableValue& message, const flutter::MessageReply& reply) { - try { - const auto& args = std::get(message); - const auto& encodable_duration_ms_arg = args.at(0); - if (encodable_duration_ms_arg.IsNull()) { - reply(WrapError("duration_ms_arg unexpectedly null.")); - return; - } - const int64_t duration_ms_arg = encodable_duration_ms_arg.LongValue(); - std::optional output = api->Boost(duration_ms_arg); - if (output.has_value()) { - reply(WrapError(output.value())); - return; - } - EncodableList wrapped; - wrapped.push_back(EncodableValue()); - reply(EncodableValue(std::move(wrapped))); - } catch (const std::exception& exception) { - reply(WrapError(exception.what())); - } - }); - } else { - channel.SetMessageHandler(nullptr); - } - } - { - BasicMessageChannel<> channel(binary_messenger, "dev.flutter.pigeon.refresh_rate.RefreshRateHostApi.setCategory" + prepended_suffix, &GetCodec()); - if (api != nullptr) { - channel.SetMessageHandler([api](const EncodableValue& message, const flutter::MessageReply& reply) { - try { - const auto& args = std::get(message); - const auto& encodable_category_index_arg = args.at(0); - if (encodable_category_index_arg.IsNull()) { - reply(WrapError("category_index_arg unexpectedly null.")); - return; - } - const int64_t category_index_arg = encodable_category_index_arg.LongValue(); - std::optional output = api->SetCategory(category_index_arg); - if (output.has_value()) { - reply(WrapError(output.value())); - return; - } - EncodableList wrapped; - wrapped.push_back(EncodableValue()); - reply(EncodableValue(std::move(wrapped))); - } catch (const std::exception& exception) { - reply(WrapError(exception.what())); - } - }); - } else { - channel.SetMessageHandler(nullptr); - } - } - { - BasicMessageChannel<> channel(binary_messenger, "dev.flutter.pigeon.refresh_rate.RefreshRateHostApi.setTouchBoost" + prepended_suffix, &GetCodec()); - if (api != nullptr) { - channel.SetMessageHandler([api](const EncodableValue& message, const flutter::MessageReply& reply) { - try { - const auto& args = std::get(message); - const auto& encodable_enabled_arg = args.at(0); - if (encodable_enabled_arg.IsNull()) { - reply(WrapError("enabled_arg unexpectedly null.")); - return; - } - const auto& enabled_arg = std::get(encodable_enabled_arg); - std::optional output = api->SetTouchBoost(enabled_arg); - if (output.has_value()) { - reply(WrapError(output.value())); - return; - } - EncodableList wrapped; - wrapped.push_back(EncodableValue()); - reply(EncodableValue(std::move(wrapped))); - } catch (const std::exception& exception) { - reply(WrapError(exception.what())); - } - }); - } else { - channel.SetMessageHandler(nullptr); - } - } - { - BasicMessageChannel<> channel(binary_messenger, "dev.flutter.pigeon.refresh_rate.RefreshRateHostApi.isSupported" + prepended_suffix, &GetCodec()); - if (api != nullptr) { - channel.SetMessageHandler([api](const EncodableValue& message, const flutter::MessageReply& reply) { - try { - ErrorOr output = api->IsSupported(); - if (output.has_error()) { - reply(WrapError(output.error())); - return; - } - EncodableList wrapped; - wrapped.push_back(EncodableValue(std::move(output).TakeValue())); - reply(EncodableValue(std::move(wrapped))); - } catch (const std::exception& exception) { - reply(WrapError(exception.what())); - } - }); - } else { - channel.SetMessageHandler(nullptr); - } - } -} - -EncodableValue RefreshRateHostApi::WrapError(std::string_view error_message) { - return EncodableValue(EncodableList{ - EncodableValue(std::string(error_message)), - EncodableValue("Error"), - EncodableValue() - }); -} - -EncodableValue RefreshRateHostApi::WrapError(const FlutterError& error) { - return EncodableValue(EncodableList{ - EncodableValue(error.code()), - EncodableValue(error.message()), - error.details() - }); -} - -// Generated class from Pigeon that represents Flutter messages that can be called from C++. -RefreshRateFlutterApi::RefreshRateFlutterApi(flutter::BinaryMessenger* binary_messenger) - : binary_messenger_(binary_messenger), - message_channel_suffix_("") {} - -RefreshRateFlutterApi::RefreshRateFlutterApi( - flutter::BinaryMessenger* binary_messenger, - const std::string& message_channel_suffix) - : binary_messenger_(binary_messenger), - message_channel_suffix_(message_channel_suffix.length() > 0 ? std::string(".") + message_channel_suffix : "") {} - -const flutter::StandardMessageCodec& RefreshRateFlutterApi::GetCodec() { - return flutter::StandardMessageCodec::GetInstance(&PigeonInternalCodecSerializer::GetInstance()); -} - -void RefreshRateFlutterApi::OnDisplayInfoChanged( - const DisplayInfoMessage& info_arg, - std::function&& on_success, - std::function&& on_error) { - const std::string channel_name = "dev.flutter.pigeon.refresh_rate.RefreshRateFlutterApi.onDisplayInfoChanged" + message_channel_suffix_; - BasicMessageChannel<> channel(binary_messenger_, channel_name, &GetCodec()); - EncodableValue encoded_api_arguments = EncodableValue(EncodableList{ - CustomEncodableValue(info_arg), - }); - channel.Send(encoded_api_arguments, [channel_name, on_success = std::move(on_success), on_error = std::move(on_error)](const uint8_t* reply, size_t reply_size) { - std::unique_ptr response = GetCodec().DecodeMessage(reply, reply_size); - const auto& encodable_return_value = *response; - const auto* list_return_value = std::get_if(&encodable_return_value); - if (list_return_value) { - if (list_return_value->size() > 1) { - on_error(FlutterError(std::get(list_return_value->at(0)), std::get(list_return_value->at(1)), list_return_value->at(2))); - } else { - on_success(); - } - } else { - on_error(CreateConnectionError(channel_name)); - } - }); -} - -} // namespace refresh_rate diff --git a/third_party/refresh_rate/linux/refresh_rate_api.g.h b/third_party/refresh_rate/linux/refresh_rate_api.g.h deleted file mode 100644 index 70ef60a0..00000000 --- a/third_party/refresh_rate/linux/refresh_rate_api.g.h +++ /dev/null @@ -1,233 +0,0 @@ -// Copyright 2026 Qoder (qoder.in). All rights reserved. -// Use of this source code is governed by a BSD-style license. -// Autogenerated from Pigeon (v22.7.4), do not edit directly. -// See also: https://pub.dev/packages/pigeon - -#ifndef PIGEON_REFRESH_RATE_API_G_H_ -#define PIGEON_REFRESH_RATE_API_G_H_ -#include -#include -#include -#include - -#include -#include -#include - -namespace refresh_rate { - - -// Generated class from Pigeon. - -class FlutterError { - public: - explicit FlutterError(const std::string& code) - : code_(code) {} - explicit FlutterError(const std::string& code, const std::string& message) - : code_(code), message_(message) {} - explicit FlutterError(const std::string& code, const std::string& message, const flutter::EncodableValue& details) - : code_(code), message_(message), details_(details) {} - - const std::string& code() const { return code_; } - const std::string& message() const { return message_; } - const flutter::EncodableValue& details() const { return details_; } - - private: - std::string code_; - std::string message_; - flutter::EncodableValue details_; -}; - -template class ErrorOr { - public: - ErrorOr(const T& rhs) : v_(rhs) {} - ErrorOr(const T&& rhs) : v_(std::move(rhs)) {} - ErrorOr(const FlutterError& rhs) : v_(rhs) {} - ErrorOr(const FlutterError&& rhs) : v_(std::move(rhs)) {} - - bool has_error() const { return std::holds_alternative(v_); } - const T& value() const { return std::get(v_); }; - const FlutterError& error() const { return std::get(v_); }; - - private: - friend class RefreshRateHostApi; - friend class RefreshRateFlutterApi; - ErrorOr() = default; - T TakeValue() && { return std::get(std::move(v_)); } - - std::variant v_; -}; - - - -// Generated class from Pigeon that represents data sent in messages. -class DisplayInfoMessage { - public: - // Constructs an object setting all non-nullable fields. - DisplayInfoMessage(); - - // Constructs an object setting all fields. - explicit DisplayInfoMessage( - const double* current_rate, - const double* max_rate, - const double* min_rate, - const flutter::EncodableList* supported_rates, - const bool* is_variable_refresh_rate, - const double* engine_target_rate, - const bool* ios_pro_motion_enabled, - const int64_t* android_api_level, - const bool* is_low_power_mode, - const int64_t* thermal_state_index, - const bool* has_adaptive_refresh_rate, - const std::string* display_server, - const int64_t* monitor_count); - - const double* current_rate() const; - void set_current_rate(const double* value_arg); - void set_current_rate(double value_arg); - - const double* max_rate() const; - void set_max_rate(const double* value_arg); - void set_max_rate(double value_arg); - - const double* min_rate() const; - void set_min_rate(const double* value_arg); - void set_min_rate(double value_arg); - - const flutter::EncodableList* supported_rates() const; - void set_supported_rates(const flutter::EncodableList* value_arg); - void set_supported_rates(const flutter::EncodableList& value_arg); - - const bool* is_variable_refresh_rate() const; - void set_is_variable_refresh_rate(const bool* value_arg); - void set_is_variable_refresh_rate(bool value_arg); - - const double* engine_target_rate() const; - void set_engine_target_rate(const double* value_arg); - void set_engine_target_rate(double value_arg); - - const bool* ios_pro_motion_enabled() const; - void set_ios_pro_motion_enabled(const bool* value_arg); - void set_ios_pro_motion_enabled(bool value_arg); - - const int64_t* android_api_level() const; - void set_android_api_level(const int64_t* value_arg); - void set_android_api_level(int64_t value_arg); - - const bool* is_low_power_mode() const; - void set_is_low_power_mode(const bool* value_arg); - void set_is_low_power_mode(bool value_arg); - - const int64_t* thermal_state_index() const; - void set_thermal_state_index(const int64_t* value_arg); - void set_thermal_state_index(int64_t value_arg); - - const bool* has_adaptive_refresh_rate() const; - void set_has_adaptive_refresh_rate(const bool* value_arg); - void set_has_adaptive_refresh_rate(bool value_arg); - - const std::string* display_server() const; - void set_display_server(const std::string_view* value_arg); - void set_display_server(std::string_view value_arg); - - const int64_t* monitor_count() const; - void set_monitor_count(const int64_t* value_arg); - void set_monitor_count(int64_t value_arg); - - - private: - static DisplayInfoMessage FromEncodableList(const flutter::EncodableList& list); - flutter::EncodableList ToEncodableList() const; - friend class RefreshRateHostApi; - friend class RefreshRateFlutterApi; - friend class PigeonInternalCodecSerializer; - std::optional current_rate_; - std::optional max_rate_; - std::optional min_rate_; - std::optional supported_rates_; - std::optional is_variable_refresh_rate_; - std::optional engine_target_rate_; - std::optional ios_pro_motion_enabled_; - std::optional android_api_level_; - std::optional is_low_power_mode_; - std::optional thermal_state_index_; - std::optional has_adaptive_refresh_rate_; - std::optional display_server_; - std::optional monitor_count_; - -}; - - -class PigeonInternalCodecSerializer : public flutter::StandardCodecSerializer { - public: - PigeonInternalCodecSerializer(); - inline static PigeonInternalCodecSerializer& GetInstance() { - static PigeonInternalCodecSerializer sInstance; - return sInstance; - } - - void WriteValue( - const flutter::EncodableValue& value, - flutter::ByteStreamWriter* stream) const override; - - protected: - flutter::EncodableValue ReadValueOfType( - uint8_t type, - flutter::ByteStreamReader* stream) const override; - -}; - -// Generated interface from Pigeon that represents a handler of messages from Flutter. -class RefreshRateHostApi { - public: - RefreshRateHostApi(const RefreshRateHostApi&) = delete; - RefreshRateHostApi& operator=(const RefreshRateHostApi&) = delete; - virtual ~RefreshRateHostApi() {} - virtual ErrorOr GetDisplayInfo() = 0; - virtual std::optional Enable() = 0; - virtual std::optional Disable() = 0; - virtual std::optional PreferMax() = 0; - virtual std::optional PreferDefault() = 0; - virtual std::optional MatchContent(double fps) = 0; - virtual std::optional Boost(int64_t duration_ms) = 0; - virtual std::optional SetCategory(int64_t category_index) = 0; - virtual std::optional SetTouchBoost(bool enabled) = 0; - virtual ErrorOr IsSupported() = 0; - - // The codec used by RefreshRateHostApi. - static const flutter::StandardMessageCodec& GetCodec(); - // Sets up an instance of `RefreshRateHostApi` to handle messages through the `binary_messenger`. - static void SetUp( - flutter::BinaryMessenger* binary_messenger, - RefreshRateHostApi* api); - static void SetUp( - flutter::BinaryMessenger* binary_messenger, - RefreshRateHostApi* api, - const std::string& message_channel_suffix); - static flutter::EncodableValue WrapError(std::string_view error_message); - static flutter::EncodableValue WrapError(const FlutterError& error); - - protected: - RefreshRateHostApi() = default; - -}; -// Generated class from Pigeon that represents Flutter messages that can be called from C++. -class RefreshRateFlutterApi { - public: - RefreshRateFlutterApi(flutter::BinaryMessenger* binary_messenger); - RefreshRateFlutterApi( - flutter::BinaryMessenger* binary_messenger, - const std::string& message_channel_suffix); - static const flutter::StandardMessageCodec& GetCodec(); - void OnDisplayInfoChanged( - const DisplayInfoMessage& info, - std::function&& on_success, - std::function&& on_error); - - private: - flutter::BinaryMessenger* binary_messenger_; - std::string message_channel_suffix_; -}; - -} // namespace refresh_rate -#endif // PIGEON_REFRESH_RATE_API_G_H_ diff --git a/third_party/refresh_rate/linux/refresh_rate_plugin.cc b/third_party/refresh_rate/linux/refresh_rate_plugin.cc deleted file mode 100644 index ca63eb64..00000000 --- a/third_party/refresh_rate/linux/refresh_rate_plugin.cc +++ /dev/null @@ -1,274 +0,0 @@ -// Linux implementation of RefreshRatePlugin. -// -// Uses GDK for query support. Implements the pigeon protocol using raw binary -// channel handlers — avoids the GObject/C++ bridge problem with BinaryMessenger. -// Control is not supported on Linux; compositor owns refresh rates. - -#include "include/refresh_rate/refresh_rate_plugin.h" - -#include -#include -#include -#include -#include - -#define REFRESH_RATE_PLUGIN(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj), refresh_rate_plugin_get_type(), RefreshRatePlugin)) - -#define PIGEON_CHANNEL_PREFIX "dev.flutter.pigeon.refresh_rate.RefreshRateHostApi." - -struct _RefreshRatePlugin { - GObject parent_instance; - FlBinaryMessenger* messenger; -}; - -G_DEFINE_TYPE(RefreshRatePlugin, refresh_rate_plugin, g_object_get_type()) - -// ─── Pigeon binary encoding helpers ───────────────────────────────── - -static void pb_byte(GByteArray* b, guint8 v) { - g_byte_array_append(b, &v, 1); -} - -static void pb_varint(GByteArray* b, gsize v) { - if (v < 254) { - pb_byte(b, (guint8)v); - } else if (v < 65536) { - pb_byte(b, 254); - guint16 u = (guint16)v; - g_byte_array_append(b, (const guint8*)&u, 2); - } else { - pb_byte(b, 255); - guint32 u = (guint32)v; - g_byte_array_append(b, (const guint8*)&u, 4); - } -} - -static void pb_null(GByteArray* b) { pb_byte(b, 0); } -static void pb_bool(GByteArray* b, gboolean v) { pb_byte(b, v ? 1 : 2); } - -static void pb_double(GByteArray* b, double v) { - pb_byte(b, 6); - g_byte_array_append(b, (const guint8*)&v, 8); -} - -static void pb_int64(GByteArray* b, gint64 v) { - pb_byte(b, 4); - g_byte_array_append(b, (const guint8*)&v, 8); -} - -static void pb_string(GByteArray* b, const char* s) { - pb_byte(b, 7); - gsize len = strlen(s); - pb_varint(b, len); - g_byte_array_append(b, (const guint8*)s, len); -} - -// Build pigeon success response: outer list [result] -// For display info: result is custom type 129 (DisplayInfoMessage) -static GBytes* build_display_info_response( - double current, double max_rate, double min_rate, - double* rates, int n_rates, - gboolean is_vrr, - const char* display_server, - gint64 monitor_count) { - - GByteArray* b = g_byte_array_new(); - - // Outer success wrapper: list([result]) - pb_byte(b, 12); pb_varint(b, 1); - - // Custom type 129 (DisplayInfoMessage) - pb_byte(b, 129); - - // Inner list of 13 fields - pb_byte(b, 12); pb_varint(b, 13); - - pb_double(b, current); // 0: currentRate - pb_double(b, max_rate); // 1: maxRate - pb_double(b, min_rate); // 2: minRate - - // 3: supportedRates list - pb_byte(b, 12); pb_varint(b, n_rates); - for (int i = 0; i < n_rates; i++) pb_double(b, rates[i]); - - pb_bool(b, is_vrr); // 4: isVariableRefreshRate - pb_double(b, 60.0); // 5: engineTargetRate - pb_null(b); // 6: iosProMotionEnabled - pb_null(b); // 7: androidApiLevel - pb_null(b); // 8: isLowPowerMode - pb_null(b); // 9: thermalStateIndex - pb_bool(b, is_vrr); // 10: hasAdaptiveRefreshRate - - if (display_server) pb_string(b, display_server); - else pb_null(b); // 11: displayServer - - pb_int64(b, monitor_count); // 12: monitorCount - - return g_byte_array_free_to_bytes(b); -} - -// Pigeon empty success response: [] -static GBytes* build_empty_success() { - GByteArray* b = g_byte_array_new(); - pb_byte(b, 12); pb_varint(b, 0); - return g_byte_array_free_to_bytes(b); -} - -// Pigeon bool success response: [bool] -static GBytes* build_bool_success(gboolean v) { - GByteArray* b = g_byte_array_new(); - pb_byte(b, 12); pb_varint(b, 1); - pb_bool(b, v); - return g_byte_array_free_to_bytes(b); -} - -// ─── GDK display helpers ──────────────────────────────────────────── - -static GdkMonitor* get_primary_monitor() { - GdkDisplay* display = gdk_display_get_default(); - if (!display) return nullptr; - GdkMonitor* monitor = gdk_display_get_primary_monitor(display); - if (!monitor) monitor = gdk_display_get_monitor(display, 0); - return monitor; -} - -static double get_monitor_rate(GdkMonitor* monitor) { - if (!monitor) return 60.0; - int rate_mhz = gdk_monitor_get_refresh_rate(monitor); - return rate_mhz > 0 ? rate_mhz / 1000.0 : 60.0; -} - -static double get_primary_refresh_rate() { - return get_monitor_rate(get_primary_monitor()); -} - -static double get_max_refresh_rate() { - GdkDisplay* display = gdk_display_get_default(); - if (!display) return 60.0; - double maxRate = 0.0; - int n = gdk_display_get_n_monitors(display); - for (int i = 0; i < n; i++) { - double rate = get_monitor_rate(gdk_display_get_monitor(display, i)); - if (rate > maxRate) maxRate = rate; - } - return maxRate > 0 ? maxRate : 60.0; -} - -static const char* get_display_server_type() { - GdkDisplay* display = gdk_display_get_default(); - if (!display) return "unknown"; - const gchar* name = G_OBJECT_TYPE_NAME(display); - if (name) { - if (g_str_has_prefix(name, "GdkWayland")) return "wayland"; - if (g_str_has_prefix(name, "GdkX11")) return "x11"; - } - const char* wayland = g_getenv("WAYLAND_DISPLAY"); - if (wayland && wayland[0] != '\0') return "wayland"; - const char* x11 = g_getenv("DISPLAY"); - if (x11 && x11[0] != '\0') return "x11"; - return "unknown"; -} - -// ─── Pigeon channel handlers ──────────────────────────────────────── - -static void handle_get_display_info( - FlBinaryMessenger* messenger, - const gchar* channel, - GBytes* message, - FlBinaryMessengerResponseHandle* response_handle, - gpointer user_data) { - - double current = get_primary_refresh_rate(); - double max_r = get_max_refresh_rate(); - double min_r = current; // GDK doesn't expose min; use current - - // Collect unique rates - GdkDisplay* display = gdk_display_get_default(); - std::set seen; - if (display) { - int n = gdk_display_get_n_monitors(display); - for (int i = 0; i < n; i++) { - int rate_mhz = gdk_monitor_get_refresh_rate(gdk_display_get_monitor(display, i)); - if (rate_mhz > 0) seen.insert((rate_mhz + 500) / 1000); - } - } - if (seen.empty()) seen.insert((int)current); - - double rates[16]; - int n_rates = 0; - for (int r : seen) { - rates[n_rates++] = (double)r; - if (n_rates >= 16) break; - } - min_r = n_rates > 0 ? rates[0] : current; - - gboolean is_vrr = (max_r > current + 5.0); - const char* display_server = get_display_server_type(); - gint64 monitor_count = display ? gdk_display_get_n_monitors(display) : 1; - - g_autoptr(GBytes) response = build_display_info_response( - current, max_r, min_r, rates, n_rates, is_vrr, display_server, monitor_count); - fl_binary_messenger_send_response(messenger, response_handle, response, nullptr); -} - -static void handle_noop( - FlBinaryMessenger* messenger, - const gchar* channel, - GBytes* message, - FlBinaryMessengerResponseHandle* response_handle, - gpointer user_data) { - g_autoptr(GBytes) response = build_empty_success(); - fl_binary_messenger_send_response(messenger, response_handle, response, nullptr); -} - -static void handle_is_supported( - FlBinaryMessenger* messenger, - const gchar* channel, - GBytes* message, - FlBinaryMessengerResponseHandle* response_handle, - gpointer user_data) { - g_autoptr(GBytes) response = build_bool_success(FALSE); - fl_binary_messenger_send_response(messenger, response_handle, response, nullptr); -} - -// ─── Plugin lifecycle ──────────────────────────────────────────────── - -static void refresh_rate_plugin_dispose(GObject* object) { - G_OBJECT_CLASS(refresh_rate_plugin_parent_class)->dispose(object); -} - -static void refresh_rate_plugin_class_init(RefreshRatePluginClass* klass) { - G_OBJECT_CLASS(klass)->dispose = refresh_rate_plugin_dispose; -} - -static void refresh_rate_plugin_init(RefreshRatePlugin* self) {} - -void refresh_rate_plugin_register_with_registrar(FlPluginRegistrar* registrar) { - RefreshRatePlugin* plugin = REFRESH_RATE_PLUGIN( - g_object_new(refresh_rate_plugin_get_type(), nullptr)); - - FlBinaryMessenger* messenger = fl_plugin_registrar_get_messenger(registrar); - plugin->messenger = messenger; - - fl_binary_messenger_set_message_handler_on_channel( - messenger, PIGEON_CHANNEL_PREFIX "getDisplayInfo", - handle_get_display_info, g_object_ref(plugin), g_object_unref); - - const char* noop_channels[] = { - "enable", "disable", "preferMax", "preferDefault", - "matchContent", "boost", "setCategory", "setTouchBoost", nullptr - }; - for (int i = 0; noop_channels[i]; i++) { - gchar* name = g_strconcat(PIGEON_CHANNEL_PREFIX, noop_channels[i], nullptr); - fl_binary_messenger_set_message_handler_on_channel( - messenger, name, handle_noop, g_object_ref(plugin), g_object_unref); - g_free(name); - } - - fl_binary_messenger_set_message_handler_on_channel( - messenger, PIGEON_CHANNEL_PREFIX "isSupported", - handle_is_supported, g_object_ref(plugin), g_object_unref); - - g_object_unref(plugin); -} diff --git a/third_party/refresh_rate/macos/Classes/RefreshRatePlugin.swift b/third_party/refresh_rate/macos/Classes/RefreshRatePlugin.swift deleted file mode 100644 index 630b2c92..00000000 --- a/third_party/refresh_rate/macos/Classes/RefreshRatePlugin.swift +++ /dev/null @@ -1,167 +0,0 @@ -import Cocoa -import FlutterMacOS -import CoreVideo -import QuartzCore - -public class RefreshRatePlugin: NSObject, FlutterPlugin, RefreshRateHostApi { - - private var flutterApi: RefreshRateFlutterApi? - private var _displayLinkRef: AnyObject? // CADisplayLink on macOS 14+ - private var lastReportedRate: Double = 0 - private var displayReconfigRegistered = false - - @available(macOS 14.0, *) - private var displayLink: CADisplayLink? { - get { _displayLinkRef as? CADisplayLink } - set { _displayLinkRef = newValue } - } - - public static func register(with registrar: FlutterPluginRegistrar) { - let instance = RefreshRatePlugin() - RefreshRateHostApiSetup.setUp(binaryMessenger: registrar.messenger, api: instance) - instance.flutterApi = RefreshRateFlutterApi(binaryMessenger: registrar.messenger) - instance.startMonitoring() - } - - // MARK: - RefreshRateHostApi - - func getDisplayInfo() throws -> DisplayInfoMessage { - let current = getCurrentRate() - let max = getMaxRate() - let rates = getSupportedRates() - let min = rates.min() ?? 60.0 - return DisplayInfoMessage( - currentRate: current, maxRate: max, minRate: min, - supportedRates: rates, isVariableRefreshRate: detectVRR(), - engineTargetRate: 60.0, - iosProMotionEnabled: nil, androidApiLevel: nil, - isLowPowerMode: nil, thermalStateIndex: nil, - hasAdaptiveRefreshRate: detectVRR(), - displayServer: nil, monitorCount: Int64(NSScreen.screens.count)) - } - - func enable() throws { - guard #available(macOS 14.0, *), getMaxRate() > 60 else { return } - let max = getMaxRate() - setupDisplayLink(minimum: 60.0, maximum: max, preferred: max) - } - - func disable() throws { - if #available(macOS 14.0, *) { displayLink?.invalidate(); displayLink = nil } - } - - func preferMax() throws { try enable() } - func preferDefault() throws { try enable() } - - func matchContent(fps: Double) throws { - guard #available(macOS 14.0, *) else { return } - let max = getMaxRate() - let multiple = Swift.max(1.0, (max / fps).rounded(.down)) - setupDisplayLink(minimum: fps, maximum: fps * multiple, preferred: fps * multiple) - } - - func boost(durationMs: Int64) throws { - guard #available(macOS 14.0, *) else { return } - let max = getMaxRate() - setupDisplayLink(minimum: Swift.max(60.0, max * 0.66), maximum: max, preferred: max) - DispatchQueue.main.asyncAfter(deadline: .now() + Double(durationMs) / 1000.0) { - try? self.enable() - } - } - - func setCategory(categoryIndex: Int64) throws { - switch categoryIndex { - case 3: try? enable() - case 0, 1: try? disable() - default: break - } - } - - func setTouchBoost(enabled: Bool) throws {} - - func isSupported() throws -> Bool { - if #available(macOS 14.0, *) { return getMaxRate() > 60 } - return false - } - - // MARK: - Private helpers - - @available(macOS 14.0, *) - private func setupDisplayLink(minimum: Double, maximum: Double, preferred: Double) { - displayLink?.invalidate() - guard let screen = NSScreen.main else { return } - let link = screen.displayLink(target: self, selector: #selector(displayLinkFired)) - link.preferredFrameRateRange = CAFrameRateRange( - minimum: Float(minimum), maximum: Float(maximum), preferred: Float(preferred)) - link.add(to: .main, forMode: .common) - displayLink = link - } - - @available(macOS 14.0, *) - @objc private func displayLinkFired(_ link: CADisplayLink) { - let rate = link.duration > 0 ? round(1.0 / link.duration) : 60.0 - if abs(rate - lastReportedRate) > 5.0 { - lastReportedRate = rate - let info = (try? getDisplayInfo()) ?? DisplayInfoMessage( - currentRate: rate, maxRate: rate, minRate: 60.0, - supportedRates: [60.0, rate], isVariableRefreshRate: rate > 60, - engineTargetRate: rate, iosProMotionEnabled: nil, - androidApiLevel: nil, isLowPowerMode: nil, - thermalStateIndex: nil, hasAdaptiveRefreshRate: nil, - displayServer: nil, monitorCount: Int64(NSScreen.screens.count)) - flutterApi?.onDisplayInfoChanged(info: info) { _ in } - } - } - - private func startMonitoring() { - guard !displayReconfigRegistered else { return } - CGDisplayRegisterReconfigurationCallback({ _, flags, userInfo in - guard let plugin = userInfo.flatMap({ - Unmanaged.fromOpaque($0).takeUnretainedValue() as RefreshRatePlugin? - }) else { return } - if flags.contains(.setModeFlag) { - guard let info = try? plugin.getDisplayInfo() else { return } - plugin.flutterApi?.onDisplayInfoChanged(info: info) { _ in } - } - }, Unmanaged.passUnretained(self).toOpaque()) - displayReconfigRegistered = true - if #available(macOS 14.0, *), displayLink == nil { - guard let screen = NSScreen.main else { return } - let link = screen.displayLink(target: self, selector: #selector(displayLinkFired)) - link.add(to: .main, forMode: .common) - displayLink = link - } - } - - private func getCurrentRate() -> Double { - if #available(macOS 14.0, *), let link = displayLink, link.duration > 0 { return round(1.0 / link.duration) } - if #available(macOS 12.0, *) { return Double(NSScreen.main?.maximumFramesPerSecond ?? 60) } - return getRefreshRateFromCGDisplay() - } - - private func getMaxRate() -> Double { - if #available(macOS 12.0, *) { return Double(NSScreen.main?.maximumFramesPerSecond ?? 60) } - return getSupportedRates().max() ?? 60.0 - } - - private func getSupportedRates() -> [Double] { - let id = (NSScreen.main?.deviceDescription[NSDeviceDescriptionKey("NSScreenNumber")] as? CGDirectDisplayID) ?? CGMainDisplayID() - guard let modes = CGDisplayCopyAllDisplayModes(id, nil) as? [CGDisplayMode] else { return [60.0] } - let rates = Set(modes.compactMap { $0.refreshRate > 0 ? round($0.refreshRate) : nil }) - return rates.isEmpty ? [60.0] : Array(rates).sorted() - } - - private func detectVRR() -> Bool { - if #available(macOS 12.0, *) { - guard let s = NSScreen.main else { return false } - return s.minimumRefreshInterval != s.maximumRefreshInterval - } - return getMaxRate() > 60 - } - - private func getRefreshRateFromCGDisplay() -> Double { - let id = CGMainDisplayID() - guard let mode = CGDisplayCopyDisplayMode(id) else { return 60.0 } - return mode.refreshRate > 0 ? mode.refreshRate : 60.0 - } -} diff --git a/third_party/refresh_rate/macos/Classes/generated/RefreshRateApi.swift b/third_party/refresh_rate/macos/Classes/generated/RefreshRateApi.swift deleted file mode 100644 index 70c230c8..00000000 --- a/third_party/refresh_rate/macos/Classes/generated/RefreshRateApi.swift +++ /dev/null @@ -1,369 +0,0 @@ -// Copyright 2026 Qoder (qoder.in). All rights reserved. -// Use of this source code is governed by a BSD-style license. -// Autogenerated from Pigeon (v22.7.4), do not edit directly. -// See also: https://pub.dev/packages/pigeon - -import Foundation - -#if os(iOS) - import Flutter -#elseif os(macOS) - import FlutterMacOS -#else - #error("Unsupported platform.") -#endif - -/// Error class for passing custom error details to Dart side. -final class PigeonError: Error { - let code: String - let message: String? - let details: Any? - - init(code: String, message: String?, details: Any?) { - self.code = code - self.message = message - self.details = details - } - - var localizedDescription: String { - return - "PigeonError(code: \(code), message: \(message ?? ""), details: \(details ?? "")" - } -} - -private func wrapResult(_ result: Any?) -> [Any?] { - return [result] -} - -private func wrapError(_ error: Any) -> [Any?] { - if let pigeonError = error as? PigeonError { - return [ - pigeonError.code, - pigeonError.message, - pigeonError.details, - ] - } - if let flutterError = error as? FlutterError { - return [ - flutterError.code, - flutterError.message, - flutterError.details, - ] - } - return [ - "\(error)", - "\(type(of: error))", - "Stacktrace: \(Thread.callStackSymbols)", - ] -} - -private func createConnectionError(withChannelName channelName: String) -> PigeonError { - return PigeonError(code: "channel-error", message: "Unable to establish connection on channel: '\(channelName)'.", details: "") -} - -private func isNullish(_ value: Any?) -> Bool { - return value is NSNull || value == nil -} - -private func nilOrValue(_ value: Any?) -> T? { - if value is NSNull { return nil } - return value as! T? -} - -/// Generated class from Pigeon that represents data sent in messages. -struct DisplayInfoMessage { - var currentRate: Double? = nil - var maxRate: Double? = nil - var minRate: Double? = nil - var supportedRates: [Double?]? = nil - var isVariableRefreshRate: Bool? = nil - var engineTargetRate: Double? = nil - var iosProMotionEnabled: Bool? = nil - var androidApiLevel: Int64? = nil - var isLowPowerMode: Bool? = nil - var thermalStateIndex: Int64? = nil - var hasAdaptiveRefreshRate: Bool? = nil - var displayServer: String? = nil - var monitorCount: Int64? = nil - - - // swift-format-ignore: AlwaysUseLowerCamelCase - static func fromList(_ pigeonVar_list: [Any?]) -> DisplayInfoMessage? { - let currentRate: Double? = nilOrValue(pigeonVar_list[0]) - let maxRate: Double? = nilOrValue(pigeonVar_list[1]) - let minRate: Double? = nilOrValue(pigeonVar_list[2]) - let supportedRates: [Double?]? = nilOrValue(pigeonVar_list[3]) - let isVariableRefreshRate: Bool? = nilOrValue(pigeonVar_list[4]) - let engineTargetRate: Double? = nilOrValue(pigeonVar_list[5]) - let iosProMotionEnabled: Bool? = nilOrValue(pigeonVar_list[6]) - let androidApiLevel: Int64? = nilOrValue(pigeonVar_list[7]) - let isLowPowerMode: Bool? = nilOrValue(pigeonVar_list[8]) - let thermalStateIndex: Int64? = nilOrValue(pigeonVar_list[9]) - let hasAdaptiveRefreshRate: Bool? = nilOrValue(pigeonVar_list[10]) - let displayServer: String? = nilOrValue(pigeonVar_list[11]) - let monitorCount: Int64? = nilOrValue(pigeonVar_list[12]) - - return DisplayInfoMessage( - currentRate: currentRate, - maxRate: maxRate, - minRate: minRate, - supportedRates: supportedRates, - isVariableRefreshRate: isVariableRefreshRate, - engineTargetRate: engineTargetRate, - iosProMotionEnabled: iosProMotionEnabled, - androidApiLevel: androidApiLevel, - isLowPowerMode: isLowPowerMode, - thermalStateIndex: thermalStateIndex, - hasAdaptiveRefreshRate: hasAdaptiveRefreshRate, - displayServer: displayServer, - monitorCount: monitorCount - ) - } - func toList() -> [Any?] { - return [ - currentRate, - maxRate, - minRate, - supportedRates, - isVariableRefreshRate, - engineTargetRate, - iosProMotionEnabled, - androidApiLevel, - isLowPowerMode, - thermalStateIndex, - hasAdaptiveRefreshRate, - displayServer, - monitorCount, - ] - } -} - -private class RefreshRateApiPigeonCodecReader: FlutterStandardReader { - override func readValue(ofType type: UInt8) -> Any? { - switch type { - case 129: - return DisplayInfoMessage.fromList(self.readValue() as! [Any?]) - default: - return super.readValue(ofType: type) - } - } -} - -private class RefreshRateApiPigeonCodecWriter: FlutterStandardWriter { - override func writeValue(_ value: Any) { - if let value = value as? DisplayInfoMessage { - super.writeByte(129) - super.writeValue(value.toList()) - } else { - super.writeValue(value) - } - } -} - -private class RefreshRateApiPigeonCodecReaderWriter: FlutterStandardReaderWriter { - override func reader(with data: Data) -> FlutterStandardReader { - return RefreshRateApiPigeonCodecReader(data: data) - } - - override func writer(with data: NSMutableData) -> FlutterStandardWriter { - return RefreshRateApiPigeonCodecWriter(data: data) - } -} - -class RefreshRateApiPigeonCodec: FlutterStandardMessageCodec, @unchecked Sendable { - static let shared = RefreshRateApiPigeonCodec(readerWriter: RefreshRateApiPigeonCodecReaderWriter()) -} - -/// Generated protocol from Pigeon that represents a handler of messages from Flutter. -protocol RefreshRateHostApi { - func getDisplayInfo() throws -> DisplayInfoMessage - func enable() throws - func disable() throws - func preferMax() throws - func preferDefault() throws - func matchContent(fps: Double) throws - func boost(durationMs: Int64) throws - func setCategory(categoryIndex: Int64) throws - func setTouchBoost(enabled: Bool) throws - func isSupported() throws -> Bool -} - -/// Generated setup class from Pigeon to handle messages through the `binaryMessenger`. -class RefreshRateHostApiSetup { - static var codec: FlutterStandardMessageCodec { RefreshRateApiPigeonCodec.shared } - /// Sets up an instance of `RefreshRateHostApi` to handle messages through the `binaryMessenger`. - static func setUp(binaryMessenger: FlutterBinaryMessenger, api: RefreshRateHostApi?, messageChannelSuffix: String = "") { - let channelSuffix = messageChannelSuffix.count > 0 ? ".\(messageChannelSuffix)" : "" - let getDisplayInfoChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.refresh_rate.RefreshRateHostApi.getDisplayInfo\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) - if let api = api { - getDisplayInfoChannel.setMessageHandler { _, reply in - do { - let result = try api.getDisplayInfo() - reply(wrapResult(result)) - } catch { - reply(wrapError(error)) - } - } - } else { - getDisplayInfoChannel.setMessageHandler(nil) - } - let enableChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.refresh_rate.RefreshRateHostApi.enable\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) - if let api = api { - enableChannel.setMessageHandler { _, reply in - do { - try api.enable() - reply(wrapResult(nil)) - } catch { - reply(wrapError(error)) - } - } - } else { - enableChannel.setMessageHandler(nil) - } - let disableChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.refresh_rate.RefreshRateHostApi.disable\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) - if let api = api { - disableChannel.setMessageHandler { _, reply in - do { - try api.disable() - reply(wrapResult(nil)) - } catch { - reply(wrapError(error)) - } - } - } else { - disableChannel.setMessageHandler(nil) - } - let preferMaxChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.refresh_rate.RefreshRateHostApi.preferMax\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) - if let api = api { - preferMaxChannel.setMessageHandler { _, reply in - do { - try api.preferMax() - reply(wrapResult(nil)) - } catch { - reply(wrapError(error)) - } - } - } else { - preferMaxChannel.setMessageHandler(nil) - } - let preferDefaultChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.refresh_rate.RefreshRateHostApi.preferDefault\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) - if let api = api { - preferDefaultChannel.setMessageHandler { _, reply in - do { - try api.preferDefault() - reply(wrapResult(nil)) - } catch { - reply(wrapError(error)) - } - } - } else { - preferDefaultChannel.setMessageHandler(nil) - } - let matchContentChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.refresh_rate.RefreshRateHostApi.matchContent\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) - if let api = api { - matchContentChannel.setMessageHandler { message, reply in - let args = message as! [Any?] - let fpsArg = args[0] as! Double - do { - try api.matchContent(fps: fpsArg) - reply(wrapResult(nil)) - } catch { - reply(wrapError(error)) - } - } - } else { - matchContentChannel.setMessageHandler(nil) - } - let boostChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.refresh_rate.RefreshRateHostApi.boost\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) - if let api = api { - boostChannel.setMessageHandler { message, reply in - let args = message as! [Any?] - let durationMsArg = args[0] as! Int64 - do { - try api.boost(durationMs: durationMsArg) - reply(wrapResult(nil)) - } catch { - reply(wrapError(error)) - } - } - } else { - boostChannel.setMessageHandler(nil) - } - let setCategoryChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.refresh_rate.RefreshRateHostApi.setCategory\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) - if let api = api { - setCategoryChannel.setMessageHandler { message, reply in - let args = message as! [Any?] - let categoryIndexArg = args[0] as! Int64 - do { - try api.setCategory(categoryIndex: categoryIndexArg) - reply(wrapResult(nil)) - } catch { - reply(wrapError(error)) - } - } - } else { - setCategoryChannel.setMessageHandler(nil) - } - let setTouchBoostChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.refresh_rate.RefreshRateHostApi.setTouchBoost\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) - if let api = api { - setTouchBoostChannel.setMessageHandler { message, reply in - let args = message as! [Any?] - let enabledArg = args[0] as! Bool - do { - try api.setTouchBoost(enabled: enabledArg) - reply(wrapResult(nil)) - } catch { - reply(wrapError(error)) - } - } - } else { - setTouchBoostChannel.setMessageHandler(nil) - } - let isSupportedChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.refresh_rate.RefreshRateHostApi.isSupported\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) - if let api = api { - isSupportedChannel.setMessageHandler { _, reply in - do { - let result = try api.isSupported() - reply(wrapResult(result)) - } catch { - reply(wrapError(error)) - } - } - } else { - isSupportedChannel.setMessageHandler(nil) - } - } -} -/// Generated protocol from Pigeon that represents Flutter messages that can be called from Swift. -protocol RefreshRateFlutterApiProtocol { - func onDisplayInfoChanged(info infoArg: DisplayInfoMessage, completion: @escaping (Result) -> Void) -} -class RefreshRateFlutterApi: RefreshRateFlutterApiProtocol { - private let binaryMessenger: FlutterBinaryMessenger - private let messageChannelSuffix: String - init(binaryMessenger: FlutterBinaryMessenger, messageChannelSuffix: String = "") { - self.binaryMessenger = binaryMessenger - self.messageChannelSuffix = messageChannelSuffix.count > 0 ? ".\(messageChannelSuffix)" : "" - } - var codec: RefreshRateApiPigeonCodec { - return RefreshRateApiPigeonCodec.shared - } - func onDisplayInfoChanged(info infoArg: DisplayInfoMessage, completion: @escaping (Result) -> Void) { - let channelName: String = "dev.flutter.pigeon.refresh_rate.RefreshRateFlutterApi.onDisplayInfoChanged\(messageChannelSuffix)" - let channel = FlutterBasicMessageChannel(name: channelName, binaryMessenger: binaryMessenger, codec: codec) - channel.sendMessage([infoArg] as [Any?]) { response in - guard let listResponse = response as? [Any?] else { - completion(.failure(createConnectionError(withChannelName: channelName))) - return - } - if listResponse.count > 1 { - let code: String = listResponse[0] as! String - let message: String? = nilOrValue(listResponse[1]) - let details: String? = nilOrValue(listResponse[2]) - completion(.failure(PigeonError(code: code, message: message, details: details))) - } else { - completion(.success(Void())) - } - } - } -} diff --git a/third_party/refresh_rate/macos/refresh_rate.podspec b/third_party/refresh_rate/macos/refresh_rate.podspec deleted file mode 100644 index 0bc79d14..00000000 --- a/third_party/refresh_rate/macos/refresh_rate.podspec +++ /dev/null @@ -1,16 +0,0 @@ -Pod::Spec.new do |s| - s.name = 'refresh_rate' - s.version = '1.0.2' - s.summary = 'Control display refresh rates in Flutter.' - s.description = <<-DESC -Cross-platform Flutter plugin to query and control display refresh rates. - DESC - s.homepage = 'https://qoder.in' - s.license = { :file => '../LICENSE' } - s.author = { 'Qoder' => 'dev@qoder.in' } - s.source = { :path => '.' } - s.source_files = 'Classes/**/*' - s.dependency 'FlutterMacOS' - s.platform = :osx, '10.14' - s.swift_version = '5.0' -end diff --git a/third_party/refresh_rate/macos/refresh_rate/Package.swift b/third_party/refresh_rate/macos/refresh_rate/Package.swift deleted file mode 100644 index 24bee2af..00000000 --- a/third_party/refresh_rate/macos/refresh_rate/Package.swift +++ /dev/null @@ -1,35 +0,0 @@ -// swift-tools-version: 5.9 -// The swift-tools-version declares the minimum version of Swift required to build this package. -// -// This Package.swift file is consumed by Swift Package Manager when the plugin -// is used via the Flutter SPM integration (flutter build / flutter run with -// Swift Package Manager enabled). It mirrors the sources and settings declared -// in refresh_rate.podspec. - -import PackageDescription - -let package = Package( - name: "refresh_rate", - platforms: [ - .macOS(.v10_14), - ], - products: [ - .library(name: "refresh-rate", targets: ["refresh_rate"]), - ], - dependencies: [ - .package(name: "FlutterFramework", path: "../FlutterFramework"), - ], - targets: [ - .target( - name: "refresh_rate", - dependencies: [ - .product(name: "FlutterFramework", package: "FlutterFramework"), - ], - path: "../Classes", - publicHeadersPath: ".", - cSettings: [ - .headerSearchPath("../Classes"), - ] - ), - ] -) diff --git a/third_party/refresh_rate/pigeons/copyright.txt b/third_party/refresh_rate/pigeons/copyright.txt deleted file mode 100644 index f131242e..00000000 --- a/third_party/refresh_rate/pigeons/copyright.txt +++ /dev/null @@ -1,2 +0,0 @@ -Copyright 2026 Qoder (qoder.in). All rights reserved. -Use of this source code is governed by a BSD-style license. diff --git a/third_party/refresh_rate/pigeons/refresh_rate_api.dart b/third_party/refresh_rate/pigeons/refresh_rate_api.dart deleted file mode 100644 index 9b34f155..00000000 --- a/third_party/refresh_rate/pigeons/refresh_rate_api.dart +++ /dev/null @@ -1,64 +0,0 @@ -import 'package:pigeon/pigeon.dart'; - -@ConfigurePigeon(PigeonOptions( - dartOut: 'lib/src/generated/refresh_rate_api.g.dart', - dartOptions: DartOptions(), - kotlinOut: - 'android/src/main/kotlin/in/qoder/refresh_rate/generated/RefreshRateApi.kt', - kotlinOptions: KotlinOptions(package: 'in.qoder.refresh_rate.generated'), - swiftOut: - 'ios/refresh_rate/Sources/refresh_rate/generated/RefreshRateApi.swift', - swiftOptions: SwiftOptions(), - cppHeaderOut: 'windows/refresh_rate_api.g.h', - cppSourceOut: 'windows/refresh_rate_api.g.cpp', - cppOptions: CppOptions(namespace: 'refresh_rate'), - copyrightHeader: 'pigeons/copyright.txt', -)) - -// ─── Data Classes ───────────────────────────────────────────────── - -class DisplayInfoMessage { - double? currentRate; - double? maxRate; - double? minRate; - List? supportedRates; - bool? isVariableRefreshRate; - double? engineTargetRate; - bool? iosProMotionEnabled; - int? androidApiLevel; - bool? isLowPowerMode; - // 0=nominal, 1=fair, 2=serious, 3=critical, null=unknown - int? thermalStateIndex; - bool? hasAdaptiveRefreshRate; - String? displayServer; - int? monitorCount; -} - -// ─── Host API (platform → Dart calls these) ────────────────────── -// These are what the Dart side calls INTO the platform - -@HostApi() -abstract class RefreshRateHostApi { - DisplayInfoMessage getDisplayInfo(); - - // Control - void enable(); - void disable(); - void preferMax(); - void preferDefault(); - void matchContent(double fps); - void boost(int durationMs); - // 0=none, 1=low, 2=normal, 3=high - void setCategory(int categoryIndex); - void setTouchBoost(bool enabled); - - bool isSupported(); -} - -// ─── Flutter API (Dart → platform listens to these) ────────────── -// These are what the platform calls UP to Dart - -@FlutterApi() -abstract class RefreshRateFlutterApi { - void onDisplayInfoChanged(DisplayInfoMessage info); -} diff --git a/third_party/refresh_rate/pigeons/refresh_rate_api_linux.dart b/third_party/refresh_rate/pigeons/refresh_rate_api_linux.dart deleted file mode 100644 index e6f0cda9..00000000 --- a/third_party/refresh_rate/pigeons/refresh_rate_api_linux.dart +++ /dev/null @@ -1,63 +0,0 @@ -// Linux-specific pigeon schema. Regenerate with: -// dart run pigeon --input pigeons/refresh_rate_api_linux.dart \ -// --one_language \ -// --cpp_header_out linux/refresh_rate_api.g.h \ -// --cpp_source_out linux/refresh_rate_api.g.cc \ -// --cpp_namespace refresh_rate \ -// --copyright_header pigeons/copyright.txt -import 'package:pigeon/pigeon.dart'; - -@ConfigurePigeon(PigeonOptions( - cppHeaderOut: 'linux/refresh_rate_api.g.h', - cppSourceOut: 'linux/refresh_rate_api.g.cc', - cppOptions: CppOptions(namespace: 'refresh_rate'), - copyrightHeader: 'pigeons/copyright.txt', -)) - -// ─── Data Classes ───────────────────────────────────────────────── - -class DisplayInfoMessage { - double? currentRate; - double? maxRate; - double? minRate; - List? supportedRates; - bool? isVariableRefreshRate; - double? engineTargetRate; - bool? iosProMotionEnabled; - int? androidApiLevel; - bool? isLowPowerMode; - // 0=nominal, 1=fair, 2=serious, 3=critical, null=unknown - int? thermalStateIndex; - bool? hasAdaptiveRefreshRate; - String? displayServer; - int? monitorCount; -} - -// ─── Host API (platform → Dart calls these) ────────────────────── -// These are what the Dart side calls INTO the platform - -@HostApi() -abstract class RefreshRateHostApi { - DisplayInfoMessage getDisplayInfo(); - - // Control - void enable(); - void disable(); - void preferMax(); - void preferDefault(); - void matchContent(double fps); - void boost(int durationMs); - // 0=none, 1=low, 2=normal, 3=high - void setCategory(int categoryIndex); - void setTouchBoost(bool enabled); - - bool isSupported(); -} - -// ─── Flutter API (Dart → platform listens to these) ────────────── -// These are what the platform calls UP to Dart - -@FlutterApi() -abstract class RefreshRateFlutterApi { - void onDisplayInfoChanged(DisplayInfoMessage info); -} diff --git a/third_party/refresh_rate/pubspec.yaml b/third_party/refresh_rate/pubspec.yaml deleted file mode 100644 index 95860623..00000000 --- a/third_party/refresh_rate/pubspec.yaml +++ /dev/null @@ -1,61 +0,0 @@ -name: refresh_rate -description: >- - Unlock 90/120/144Hz on Android, iOS & desktop. Query display rates, control - refresh, benchmark FPS with live debug overlays. Uses modern platform APIs. -version: 1.0.2 -homepage: https://qoder.in/resources/refresh_rate -repository: https://github.com/qoder-official/refresh_rate -issue_tracker: https://github.com/qoder-official/refresh_rate/issues -documentation: https://pub.dev/documentation/refresh_rate/latest/ - -topics: - - display - - performance - - animation - - debug - - ui - -screenshots: - - description: "Live FPS overlay showing 120 FPS with frame budget diagnostics" - path: screenshots/fps.png - - description: "Hz badge confirming 120Hz refresh rate on a real device" - path: screenshots/hz.png - -funding: - - https://github.com/sponsors/qoder-official - -environment: - sdk: ^3.5.0 - flutter: ">=3.24.0" - -dependencies: - flutter: - sdk: flutter - flutter_web_plugins: - sdk: flutter - plugin_platform_interface: ^2.1.7 - web: ^1.1.0 - -dev_dependencies: - flutter_test: - sdk: flutter - flutter_lints: ^5.0.0 - pigeon: ^22.0.0 - -flutter: - plugin: - platforms: - android: - package: in.qoder.refresh_rate - pluginClass: RefreshRatePlugin - ios: - pluginClass: RefreshRatePlugin - linux: - pluginClass: RefreshRatePlugin - macos: - pluginClass: RefreshRatePlugin - windows: - pluginClass: RefreshRatePluginCApi - web: - pluginClass: RefreshRateWeb - fileName: refresh_rate_web.dart diff --git a/third_party/refresh_rate/screenshots/fps.png b/third_party/refresh_rate/screenshots/fps.png deleted file mode 100644 index 1658d85f..00000000 Binary files a/third_party/refresh_rate/screenshots/fps.png and /dev/null differ diff --git a/third_party/refresh_rate/screenshots/hz.png b/third_party/refresh_rate/screenshots/hz.png deleted file mode 100644 index 261465ca..00000000 Binary files a/third_party/refresh_rate/screenshots/hz.png and /dev/null differ diff --git a/third_party/refresh_rate/test/fps_tracker_test.dart b/third_party/refresh_rate/test/fps_tracker_test.dart deleted file mode 100644 index 17c420c6..00000000 --- a/third_party/refresh_rate/test/fps_tracker_test.dart +++ /dev/null @@ -1,226 +0,0 @@ -import 'dart:ui'; - -import 'package:flutter/widgets.dart'; -import 'package:flutter_test/flutter_test.dart'; -import 'package:refresh_rate/src/verification/fps_tracker.dart'; -import 'package:refresh_rate/src/verification/refresh_rate_session.dart'; -import 'package:refresh_rate/src/verification/session_scorer.dart'; -import 'package:refresh_rate/src/models/display_info.dart'; -import 'package:refresh_rate/src/models/enums.dart'; -import 'package:refresh_rate/src/models/session_report.dart'; - -void main() { - TestWidgetsFlutterBinding.ensureInitialized(); - - group('FpsTracker', () { - test('starts with no samples', () { - final tracker = FpsTracker(); - expect(tracker.sampleCount, 0); - expect(tracker.avgFps, 0.0); - }); - - test('addTimings accumulates samples', () { - final tracker = FpsTracker(); - tracker.addTimings(_fakeTimings(10, 8333)); - expect(tracker.sampleCount, 10); - }); - - test('avgFps is reasonable for 120fps timings', () { - final tracker = FpsTracker(); - tracker.addTimings(_fakeTimings(120, 8333)); - // 119 intervals * 1e6 / (119 * 8333µs) ≈ 120fps - expect(tracker.avgFps, closeTo(120.0, 5.0)); - }); - - test('reset clears all samples', () { - final tracker = FpsTracker(); - tracker.addTimings(_fakeTimings(10, 8333)); - tracker.reset(); - expect(tracker.sampleCount, 0); - }); - - test('onePercentLow is less than or equal to avgFps', () { - final tracker = FpsTracker(); - tracker.addTimings(_fakeTimingSequence([ - ...List.filled(100, 8333), - ...List.filled(10, 33333), - ])); - expect(tracker.onePercentLowFps, lessThanOrEqualTo(tracker.avgFps)); - }); - - test('jankyFrameCount counts frames over budget', () { - final tracker = FpsTracker(); - // At 60fps, budget = ~16667µs. Add 5 frames over budget. - tracker.addTimings(_fakeTimingSequence([ - ...List.filled(10, 8333), - ...List.filled(5, 20000), - ])); - expect(tracker.jankyFrameCount(60.0), 5); - }); - - test('missedFramePercent is 0 when no jank', () { - final tracker = FpsTracker(); - tracker.addTimings(_fakeTimings(100, 8333)); - expect(tracker.missedFramePercent(120.0), 0.0); - }); - - test('onePercentLowFps works for small sample count', () { - final tracker = FpsTracker(); - // 10 frames: 9 fast + 1 slow. With floor cutoff, 1 slow frame is captured. - tracker.addTimings(_fakeTimingSequence([ - ...List.filled(9, 8333), - ...List.filled(1, 33333), - ])); - // onePercentLow should be close to 30fps (the slow frame), not avgFps - expect(tracker.onePercentLowFps, lessThan(tracker.avgFps)); - }); - }); - - group('SessionScorer.compute', () { - test('returns inconclusive for zero-frame session', () { - final report = SessionScorer.compute( - sessionName: 'empty', - tracker: FpsTracker(), - targetHz: 120.0, - validDuration: Duration(seconds: 1), - excludedDuration: Duration.zero, - exclusionReasons: {}, - deviceState: DeviceStateSnapshot(thermalState: ThermalState.nominal), - ); - expect(report.verdict, Verdict.inconclusive); - }); - - test('returns excellent for smooth 120fps session', () { - final tracker = FpsTracker(); - tracker.addTimings(_fakeTimings(120, 8333)); - final report = SessionScorer.compute( - sessionName: 'smooth', - tracker: tracker, - targetHz: 120.0, - validDuration: Duration(seconds: 1), - excludedDuration: Duration.zero, - exclusionReasons: {}, - deviceState: DeviceStateSnapshot(thermalState: ThermalState.nominal), - ); - expect(report.verdict, Verdict.excellent); - }); - - test('returns powerLimited bottleneck when LPM is true', () { - final tracker = FpsTracker(); - tracker.addTimings(_fakeTimings(60, 8333)); - final report = SessionScorer.compute( - sessionName: 'lpm', - tracker: tracker, - targetHz: 120.0, - validDuration: Duration(seconds: 1), - excludedDuration: Duration.zero, - exclusionReasons: {}, - deviceState: DeviceStateSnapshot( - thermalState: ThermalState.nominal, - isLowPowerMode: true, - ), - ); - expect(report.likelyBottleneck, Bottleneck.powerLimited); - }); - - test('returns displayCapped for 88% fps', () { - final tracker = FpsTracker(); - // 88% of 120fps ≈ 105.6fps. Frame interval: 1_000_000 / 105.6 ≈ 9470µs - tracker.addTimings(_fakeTimings(100, 9470)); - final report = SessionScorer.compute( - sessionName: 'capped', - tracker: tracker, - targetHz: 120.0, - validDuration: Duration(seconds: 1), - excludedDuration: Duration.zero, - exclusionReasons: {}, - deviceState: DeviceStateSnapshot(thermalState: ThermalState.nominal), - ); - expect(report.likelyBottleneck, Bottleneck.displayCapped); - }); - }); - - group('RefreshRateSession', () { - test('starts in running state', () { - WidgetsFlutterBinding.ensureInitialized(); - final info = DisplayInfo( - currentRate: 120.0, - maxRate: 120.0, - minRate: 60.0, - supportedRates: [60.0, 120.0], - isVariableRefreshRate: true, - engineTargetRate: 120.0, - thermalState: ThermalState.nominal, - ); - final session = RefreshRateSession.create('test', info); - expect(session.state, SessionState.running); - expect(session.name, 'test'); - }); - - test('end() returns a SessionReport', () async { - WidgetsFlutterBinding.ensureInitialized(); - final info = DisplayInfo( - currentRate: 120.0, - maxRate: 120.0, - minRate: 60.0, - supportedRates: [60.0, 120.0], - isVariableRefreshRate: true, - engineTargetRate: 120.0, - thermalState: ThermalState.nominal, - ); - final session = RefreshRateSession.create('scroll_test', info); - final report = await session.end(); - expect(report.sessionName, 'scroll_test'); - expect(report.targetHz, 120.0); - expect(report.verdict, isA()); - }); - }); -} - -/// Builds a list of fake timings with proper sequential vsync timestamps. -/// Each frame's vsync = sum of all preceding frame durations. -List _fakeTimingSequence(List durationsUs) { - int vsync = 0; - return durationsUs.map((dur) { - final t = _MockFrameTiming(dur, vsync); - vsync += dur; - return t as FrameTiming; - }).toList(); -} - -List _fakeTimings(int count, int intervalUs) => - _fakeTimingSequence(List.filled(count, intervalUs)); - -class _MockFrameTiming implements FrameTiming { - final int _totalUs; - final int _vsyncUs; - _MockFrameTiming(this._totalUs, this._vsyncUs); - - @override - Duration get buildDuration => - Duration(microseconds: (_totalUs * 0.6).toInt()); - @override - Duration get rasterDuration => - Duration(microseconds: (_totalUs * 0.4).toInt()); - @override - Duration get totalSpan => Duration(microseconds: _totalUs); - @override - int get frameNumber => 0; - @override - int get layerCacheCount => 0; - @override - int get layerCacheBytes => 0; - @override - int get pictureCacheCount => 0; - @override - int get pictureCacheBytes => 0; - @override - int timestampInMicroseconds(FramePhase phase) { - if (phase == FramePhase.vsyncStart) return _vsyncUs; - return 0; - } - - // Forward any additional SDK-version-specific members gracefully. - @override - dynamic noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation); -} diff --git a/third_party/refresh_rate/test/models_test.dart b/third_party/refresh_rate/test/models_test.dart deleted file mode 100644 index a9894511..00000000 --- a/third_party/refresh_rate/test/models_test.dart +++ /dev/null @@ -1,86 +0,0 @@ -import 'package:flutter_test/flutter_test.dart'; -import 'package:refresh_rate/src/models/enums.dart'; -import 'package:refresh_rate/src/models/display_info.dart'; -import 'package:refresh_rate/src/models/session_report.dart'; -import 'package:refresh_rate/src/generated/refresh_rate_api.g.dart'; - -void main() { - group('DisplayInfo.fromMessage', () { - test('maps all fields correctly', () { - final msg = DisplayInfoMessage( - currentRate: 120.0, - maxRate: 120.0, - minRate: 60.0, - supportedRates: [60.0, 120.0], - isVariableRefreshRate: true, - engineTargetRate: 120.0, - iosProMotionEnabled: true, - androidApiLevel: null, - isLowPowerMode: false, - thermalStateIndex: 0, - hasAdaptiveRefreshRate: true, - displayServer: null, - monitorCount: null, - ); - final info = DisplayInfo.fromMessage(msg); - expect(info.currentRate, 120.0); - expect(info.thermalState, ThermalState.nominal); - expect(info.isVariableRefreshRate, true); - }); - - test('handles null thermalStateIndex as unknown', () { - final msg = DisplayInfoMessage( - currentRate: 60.0, - maxRate: 60.0, - minRate: 60.0, - supportedRates: [60.0], - isVariableRefreshRate: false, - engineTargetRate: 60.0, - thermalStateIndex: null, - ); - final info = DisplayInfo.fromMessage(msg); - expect(info.thermalState, ThermalState.unknown); - }); - }); - - group('ThermalState', () { - test('fromIndex maps correctly', () { - expect(ThermalState.fromIndex(0), ThermalState.nominal); - expect(ThermalState.fromIndex(1), ThermalState.fair); - expect(ThermalState.fromIndex(2), ThermalState.serious); - expect(ThermalState.fromIndex(3), ThermalState.critical); - expect(ThermalState.fromIndex(null), ThermalState.unknown); - }); - }); - - group('SessionReport.toCsv', () { - test('escapes commas in sessionName', () { - final report = SessionReport( - sessionName: 'feed, scroll', - verdict: Verdict.good, - likelyBottleneck: Bottleneck.none, - targetHz: 120.0, - observedAvgHz: 118.0, - frameBudgetMs: 8.33, - avgFps: 118.0, - onePercentLowFps: 90.0, - fivePercentLowFps: 100.0, - avgBuildMs: 3.0, - avgRasterMs: 4.0, - avgTotalFrameMs: 7.0, - jankyFrameCount: 2, - severeJankCount: 0, - missedFramePercent: 1.5, - validDuration: Duration(seconds: 5), - excludedDuration: Duration.zero, - exclusionReasons: {}, - deviceState: DeviceStateSnapshot(thermalState: ThermalState.nominal), - ); - final csv = report.toCsv(); - final lines = csv.split('\n'); - expect(lines.length, 2); - // The escaped session name should appear in the values row - expect(lines[1], contains('"feed, scroll"')); - }); - }); -} diff --git a/third_party/refresh_rate/test/refresh_rate_api_test.dart b/third_party/refresh_rate/test/refresh_rate_api_test.dart deleted file mode 100644 index 9408ae93..00000000 --- a/third_party/refresh_rate/test/refresh_rate_api_test.dart +++ /dev/null @@ -1,98 +0,0 @@ -import 'package:flutter_test/flutter_test.dart'; -import 'package:refresh_rate/refresh_rate.dart'; -import 'package:refresh_rate/src/generated/refresh_rate_api.g.dart'; -import 'package:refresh_rate/src/refresh_rate_api_adapter.dart'; - -class _FakeHostApi implements RefreshRateApiAdapter { - final calls = []; - @override - DisplayInfoMessage getDisplayInfo() => DisplayInfoMessage( - currentRate: 120.0, - maxRate: 120.0, - minRate: 60.0, - supportedRates: [60.0, 120.0], - isVariableRefreshRate: true, - engineTargetRate: 120.0, - thermalStateIndex: 0, - ); - - @override - void enable() { - calls.add('enable'); - } - - @override - void disable() { - calls.add('disable'); - } - - @override - void preferMax() { - calls.add('preferMax'); - } - - @override - void preferDefault() { - calls.add('preferDefault'); - } - - @override - void matchContent(double fps) { - calls.add('matchContent:$fps'); - } - - @override - void boost(int durationMs) { - calls.add('boost:$durationMs'); - } - - @override - void setCategory(int c) { - calls.add('setCategory:$c'); - } - - @override - void setTouchBoost(bool e) { - calls.add('setTouchBoost:$e'); - } - - @override - bool isSupported() => true; -} - -void main() { - TestWidgetsFlutterBinding.ensureInitialized(); - - late _FakeHostApi fakeApi; - - setUp(() { - fakeApi = _FakeHostApi(); - RefreshRate.setApiForTesting(fakeApi); - }); - - tearDown(() => RefreshRate.clearApiForTesting()); - - test('enable() calls platform enable', () async { - RefreshRate.enable(); - expect(fakeApi.calls, contains('enable')); - }); - - test('preferMax() calls platform preferMax', () { - RefreshRate.preferMax(); - expect(fakeApi.calls, contains('preferMax')); - }); - - test('matchContent passes fps to platform', () { - RefreshRate.matchContent(24.0); - expect(fakeApi.calls, contains('matchContent:24.0')); - }); - - test('category(high) calls setCategory(3)', () { - RefreshRate.category(RateCategory.high); - expect(fakeApi.calls, contains('setCategory:3')); - }); - - test('info returns fallback before first fetch', () { - expect(RefreshRate.info.currentRate, isA()); - }); -} diff --git a/third_party/refresh_rate/windows/CMakeLists.txt b/third_party/refresh_rate/windows/CMakeLists.txt deleted file mode 100644 index cd093e07..00000000 --- a/third_party/refresh_rate/windows/CMakeLists.txt +++ /dev/null @@ -1,18 +0,0 @@ -cmake_minimum_required(VERSION 3.14) -set(PROJECT_NAME "refresh_rate") -project(${PROJECT_NAME} LANGUAGES CXX) - -set(PLUGIN_NAME "refresh_rate_plugin") - -add_library(${PLUGIN_NAME} SHARED - "refresh_rate_plugin_c_api.cpp" - "refresh_rate_api.g.cpp" -) - -apply_standard_settings(${PLUGIN_NAME}) -set_target_properties(${PLUGIN_NAME} PROPERTIES - CXX_VISIBILITY_PRESET hidden) -target_compile_definitions(${PLUGIN_NAME} PRIVATE FLUTTER_PLUGIN_IMPL) -target_include_directories(${PLUGIN_NAME} INTERFACE - "${CMAKE_CURRENT_SOURCE_DIR}/include") -target_link_libraries(${PLUGIN_NAME} PRIVATE flutter flutter_wrapper_plugin) diff --git a/third_party/refresh_rate/windows/include/refresh_rate/refresh_rate_plugin_c_api.h b/third_party/refresh_rate/windows/include/refresh_rate/refresh_rate_plugin_c_api.h deleted file mode 100644 index a4145a41..00000000 --- a/third_party/refresh_rate/windows/include/refresh_rate/refresh_rate_plugin_c_api.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef FLUTTER_PLUGIN_REFRESH_RATE_PLUGIN_C_API_H_ -#define FLUTTER_PLUGIN_REFRESH_RATE_PLUGIN_C_API_H_ - -#include - -#ifdef FLUTTER_PLUGIN_IMPL -#define FLUTTER_PLUGIN_EXPORT __declspec(dllexport) -#else -#define FLUTTER_PLUGIN_EXPORT __declspec(dllimport) -#endif - -#if defined(__cplusplus) -extern "C" { -#endif - -FLUTTER_PLUGIN_EXPORT void RefreshRatePluginCApiRegisterWithRegistrar( - FlutterDesktopPluginRegistrarRef registrar); - -#if defined(__cplusplus) -} -#endif - -#endif // FLUTTER_PLUGIN_REFRESH_RATE_PLUGIN_C_API_H_ diff --git a/third_party/refresh_rate/windows/refresh_rate_api.g.cpp b/third_party/refresh_rate/windows/refresh_rate_api.g.cpp deleted file mode 100644 index f4911e8a..00000000 --- a/third_party/refresh_rate/windows/refresh_rate_api.g.cpp +++ /dev/null @@ -1,651 +0,0 @@ -// Copyright 2026 Qoder (qoder.in). All rights reserved. -// Use of this source code is governed by a BSD-style license. -// Autogenerated from Pigeon (v22.7.4), do not edit directly. -// See also: https://pub.dev/packages/pigeon - -#undef _HAS_EXCEPTIONS - -#include "refresh_rate_api.g.h" - -#include -#include -#include -#include - -#include -#include -#include - -namespace refresh_rate { -using flutter::BasicMessageChannel; -using flutter::CustomEncodableValue; -using flutter::EncodableList; -using flutter::EncodableMap; -using flutter::EncodableValue; - -FlutterError CreateConnectionError(const std::string channel_name) { - return FlutterError( - "channel-error", - "Unable to establish connection on channel: '" + channel_name + "'.", - EncodableValue("")); -} - -// DisplayInfoMessage - -DisplayInfoMessage::DisplayInfoMessage() {} - -DisplayInfoMessage::DisplayInfoMessage( - const double* current_rate, - const double* max_rate, - const double* min_rate, - const EncodableList* supported_rates, - const bool* is_variable_refresh_rate, - const double* engine_target_rate, - const bool* ios_pro_motion_enabled, - const int64_t* android_api_level, - const bool* is_low_power_mode, - const int64_t* thermal_state_index, - const bool* has_adaptive_refresh_rate, - const std::string* display_server, - const int64_t* monitor_count) - : current_rate_(current_rate ? std::optional(*current_rate) : std::nullopt), - max_rate_(max_rate ? std::optional(*max_rate) : std::nullopt), - min_rate_(min_rate ? std::optional(*min_rate) : std::nullopt), - supported_rates_(supported_rates ? std::optional(*supported_rates) : std::nullopt), - is_variable_refresh_rate_(is_variable_refresh_rate ? std::optional(*is_variable_refresh_rate) : std::nullopt), - engine_target_rate_(engine_target_rate ? std::optional(*engine_target_rate) : std::nullopt), - ios_pro_motion_enabled_(ios_pro_motion_enabled ? std::optional(*ios_pro_motion_enabled) : std::nullopt), - android_api_level_(android_api_level ? std::optional(*android_api_level) : std::nullopt), - is_low_power_mode_(is_low_power_mode ? std::optional(*is_low_power_mode) : std::nullopt), - thermal_state_index_(thermal_state_index ? std::optional(*thermal_state_index) : std::nullopt), - has_adaptive_refresh_rate_(has_adaptive_refresh_rate ? std::optional(*has_adaptive_refresh_rate) : std::nullopt), - display_server_(display_server ? std::optional(*display_server) : std::nullopt), - monitor_count_(monitor_count ? std::optional(*monitor_count) : std::nullopt) {} - -const double* DisplayInfoMessage::current_rate() const { - return current_rate_ ? &(*current_rate_) : nullptr; -} - -void DisplayInfoMessage::set_current_rate(const double* value_arg) { - current_rate_ = value_arg ? std::optional(*value_arg) : std::nullopt; -} - -void DisplayInfoMessage::set_current_rate(double value_arg) { - current_rate_ = value_arg; -} - - -const double* DisplayInfoMessage::max_rate() const { - return max_rate_ ? &(*max_rate_) : nullptr; -} - -void DisplayInfoMessage::set_max_rate(const double* value_arg) { - max_rate_ = value_arg ? std::optional(*value_arg) : std::nullopt; -} - -void DisplayInfoMessage::set_max_rate(double value_arg) { - max_rate_ = value_arg; -} - - -const double* DisplayInfoMessage::min_rate() const { - return min_rate_ ? &(*min_rate_) : nullptr; -} - -void DisplayInfoMessage::set_min_rate(const double* value_arg) { - min_rate_ = value_arg ? std::optional(*value_arg) : std::nullopt; -} - -void DisplayInfoMessage::set_min_rate(double value_arg) { - min_rate_ = value_arg; -} - - -const EncodableList* DisplayInfoMessage::supported_rates() const { - return supported_rates_ ? &(*supported_rates_) : nullptr; -} - -void DisplayInfoMessage::set_supported_rates(const EncodableList* value_arg) { - supported_rates_ = value_arg ? std::optional(*value_arg) : std::nullopt; -} - -void DisplayInfoMessage::set_supported_rates(const EncodableList& value_arg) { - supported_rates_ = value_arg; -} - - -const bool* DisplayInfoMessage::is_variable_refresh_rate() const { - return is_variable_refresh_rate_ ? &(*is_variable_refresh_rate_) : nullptr; -} - -void DisplayInfoMessage::set_is_variable_refresh_rate(const bool* value_arg) { - is_variable_refresh_rate_ = value_arg ? std::optional(*value_arg) : std::nullopt; -} - -void DisplayInfoMessage::set_is_variable_refresh_rate(bool value_arg) { - is_variable_refresh_rate_ = value_arg; -} - - -const double* DisplayInfoMessage::engine_target_rate() const { - return engine_target_rate_ ? &(*engine_target_rate_) : nullptr; -} - -void DisplayInfoMessage::set_engine_target_rate(const double* value_arg) { - engine_target_rate_ = value_arg ? std::optional(*value_arg) : std::nullopt; -} - -void DisplayInfoMessage::set_engine_target_rate(double value_arg) { - engine_target_rate_ = value_arg; -} - - -const bool* DisplayInfoMessage::ios_pro_motion_enabled() const { - return ios_pro_motion_enabled_ ? &(*ios_pro_motion_enabled_) : nullptr; -} - -void DisplayInfoMessage::set_ios_pro_motion_enabled(const bool* value_arg) { - ios_pro_motion_enabled_ = value_arg ? std::optional(*value_arg) : std::nullopt; -} - -void DisplayInfoMessage::set_ios_pro_motion_enabled(bool value_arg) { - ios_pro_motion_enabled_ = value_arg; -} - - -const int64_t* DisplayInfoMessage::android_api_level() const { - return android_api_level_ ? &(*android_api_level_) : nullptr; -} - -void DisplayInfoMessage::set_android_api_level(const int64_t* value_arg) { - android_api_level_ = value_arg ? std::optional(*value_arg) : std::nullopt; -} - -void DisplayInfoMessage::set_android_api_level(int64_t value_arg) { - android_api_level_ = value_arg; -} - - -const bool* DisplayInfoMessage::is_low_power_mode() const { - return is_low_power_mode_ ? &(*is_low_power_mode_) : nullptr; -} - -void DisplayInfoMessage::set_is_low_power_mode(const bool* value_arg) { - is_low_power_mode_ = value_arg ? std::optional(*value_arg) : std::nullopt; -} - -void DisplayInfoMessage::set_is_low_power_mode(bool value_arg) { - is_low_power_mode_ = value_arg; -} - - -const int64_t* DisplayInfoMessage::thermal_state_index() const { - return thermal_state_index_ ? &(*thermal_state_index_) : nullptr; -} - -void DisplayInfoMessage::set_thermal_state_index(const int64_t* value_arg) { - thermal_state_index_ = value_arg ? std::optional(*value_arg) : std::nullopt; -} - -void DisplayInfoMessage::set_thermal_state_index(int64_t value_arg) { - thermal_state_index_ = value_arg; -} - - -const bool* DisplayInfoMessage::has_adaptive_refresh_rate() const { - return has_adaptive_refresh_rate_ ? &(*has_adaptive_refresh_rate_) : nullptr; -} - -void DisplayInfoMessage::set_has_adaptive_refresh_rate(const bool* value_arg) { - has_adaptive_refresh_rate_ = value_arg ? std::optional(*value_arg) : std::nullopt; -} - -void DisplayInfoMessage::set_has_adaptive_refresh_rate(bool value_arg) { - has_adaptive_refresh_rate_ = value_arg; -} - - -const std::string* DisplayInfoMessage::display_server() const { - return display_server_ ? &(*display_server_) : nullptr; -} - -void DisplayInfoMessage::set_display_server(const std::string_view* value_arg) { - display_server_ = value_arg ? std::optional(*value_arg) : std::nullopt; -} - -void DisplayInfoMessage::set_display_server(std::string_view value_arg) { - display_server_ = value_arg; -} - - -const int64_t* DisplayInfoMessage::monitor_count() const { - return monitor_count_ ? &(*monitor_count_) : nullptr; -} - -void DisplayInfoMessage::set_monitor_count(const int64_t* value_arg) { - monitor_count_ = value_arg ? std::optional(*value_arg) : std::nullopt; -} - -void DisplayInfoMessage::set_monitor_count(int64_t value_arg) { - monitor_count_ = value_arg; -} - - -EncodableList DisplayInfoMessage::ToEncodableList() const { - EncodableList list; - list.reserve(13); - list.push_back(current_rate_ ? EncodableValue(*current_rate_) : EncodableValue()); - list.push_back(max_rate_ ? EncodableValue(*max_rate_) : EncodableValue()); - list.push_back(min_rate_ ? EncodableValue(*min_rate_) : EncodableValue()); - list.push_back(supported_rates_ ? EncodableValue(*supported_rates_) : EncodableValue()); - list.push_back(is_variable_refresh_rate_ ? EncodableValue(*is_variable_refresh_rate_) : EncodableValue()); - list.push_back(engine_target_rate_ ? EncodableValue(*engine_target_rate_) : EncodableValue()); - list.push_back(ios_pro_motion_enabled_ ? EncodableValue(*ios_pro_motion_enabled_) : EncodableValue()); - list.push_back(android_api_level_ ? EncodableValue(*android_api_level_) : EncodableValue()); - list.push_back(is_low_power_mode_ ? EncodableValue(*is_low_power_mode_) : EncodableValue()); - list.push_back(thermal_state_index_ ? EncodableValue(*thermal_state_index_) : EncodableValue()); - list.push_back(has_adaptive_refresh_rate_ ? EncodableValue(*has_adaptive_refresh_rate_) : EncodableValue()); - list.push_back(display_server_ ? EncodableValue(*display_server_) : EncodableValue()); - list.push_back(monitor_count_ ? EncodableValue(*monitor_count_) : EncodableValue()); - return list; -} - -DisplayInfoMessage DisplayInfoMessage::FromEncodableList(const EncodableList& list) { - DisplayInfoMessage decoded; - auto& encodable_current_rate = list[0]; - if (!encodable_current_rate.IsNull()) { - decoded.set_current_rate(std::get(encodable_current_rate)); - } - auto& encodable_max_rate = list[1]; - if (!encodable_max_rate.IsNull()) { - decoded.set_max_rate(std::get(encodable_max_rate)); - } - auto& encodable_min_rate = list[2]; - if (!encodable_min_rate.IsNull()) { - decoded.set_min_rate(std::get(encodable_min_rate)); - } - auto& encodable_supported_rates = list[3]; - if (!encodable_supported_rates.IsNull()) { - decoded.set_supported_rates(std::get(encodable_supported_rates)); - } - auto& encodable_is_variable_refresh_rate = list[4]; - if (!encodable_is_variable_refresh_rate.IsNull()) { - decoded.set_is_variable_refresh_rate(std::get(encodable_is_variable_refresh_rate)); - } - auto& encodable_engine_target_rate = list[5]; - if (!encodable_engine_target_rate.IsNull()) { - decoded.set_engine_target_rate(std::get(encodable_engine_target_rate)); - } - auto& encodable_ios_pro_motion_enabled = list[6]; - if (!encodable_ios_pro_motion_enabled.IsNull()) { - decoded.set_ios_pro_motion_enabled(std::get(encodable_ios_pro_motion_enabled)); - } - auto& encodable_android_api_level = list[7]; - if (!encodable_android_api_level.IsNull()) { - decoded.set_android_api_level(std::get(encodable_android_api_level)); - } - auto& encodable_is_low_power_mode = list[8]; - if (!encodable_is_low_power_mode.IsNull()) { - decoded.set_is_low_power_mode(std::get(encodable_is_low_power_mode)); - } - auto& encodable_thermal_state_index = list[9]; - if (!encodable_thermal_state_index.IsNull()) { - decoded.set_thermal_state_index(std::get(encodable_thermal_state_index)); - } - auto& encodable_has_adaptive_refresh_rate = list[10]; - if (!encodable_has_adaptive_refresh_rate.IsNull()) { - decoded.set_has_adaptive_refresh_rate(std::get(encodable_has_adaptive_refresh_rate)); - } - auto& encodable_display_server = list[11]; - if (!encodable_display_server.IsNull()) { - decoded.set_display_server(std::get(encodable_display_server)); - } - auto& encodable_monitor_count = list[12]; - if (!encodable_monitor_count.IsNull()) { - decoded.set_monitor_count(std::get(encodable_monitor_count)); - } - return decoded; -} - - -PigeonInternalCodecSerializer::PigeonInternalCodecSerializer() {} - -EncodableValue PigeonInternalCodecSerializer::ReadValueOfType( - uint8_t type, - flutter::ByteStreamReader* stream) const { - switch (type) { - case 129: { - return CustomEncodableValue(DisplayInfoMessage::FromEncodableList(std::get(ReadValue(stream)))); - } - default: - return flutter::StandardCodecSerializer::ReadValueOfType(type, stream); - } -} - -void PigeonInternalCodecSerializer::WriteValue( - const EncodableValue& value, - flutter::ByteStreamWriter* stream) const { - if (const CustomEncodableValue* custom_value = std::get_if(&value)) { - if (custom_value->type() == typeid(DisplayInfoMessage)) { - stream->WriteByte(129); - WriteValue(EncodableValue(std::any_cast(*custom_value).ToEncodableList()), stream); - return; - } - } - flutter::StandardCodecSerializer::WriteValue(value, stream); -} - -/// The codec used by RefreshRateHostApi. -const flutter::StandardMessageCodec& RefreshRateHostApi::GetCodec() { - return flutter::StandardMessageCodec::GetInstance(&PigeonInternalCodecSerializer::GetInstance()); -} - -// Sets up an instance of `RefreshRateHostApi` to handle messages through the `binary_messenger`. -void RefreshRateHostApi::SetUp( - flutter::BinaryMessenger* binary_messenger, - RefreshRateHostApi* api) { - RefreshRateHostApi::SetUp(binary_messenger, api, ""); -} - -void RefreshRateHostApi::SetUp( - flutter::BinaryMessenger* binary_messenger, - RefreshRateHostApi* api, - const std::string& message_channel_suffix) { - const std::string prepended_suffix = message_channel_suffix.length() > 0 ? std::string(".") + message_channel_suffix : ""; - { - BasicMessageChannel<> channel(binary_messenger, "dev.flutter.pigeon.refresh_rate.RefreshRateHostApi.getDisplayInfo" + prepended_suffix, &GetCodec()); - if (api != nullptr) { - channel.SetMessageHandler([api](const EncodableValue& message, const flutter::MessageReply& reply) { - try { - ErrorOr output = api->GetDisplayInfo(); - if (output.has_error()) { - reply(WrapError(output.error())); - return; - } - EncodableList wrapped; - wrapped.push_back(CustomEncodableValue(std::move(output).TakeValue())); - reply(EncodableValue(std::move(wrapped))); - } catch (const std::exception& exception) { - reply(WrapError(exception.what())); - } - }); - } else { - channel.SetMessageHandler(nullptr); - } - } - { - BasicMessageChannel<> channel(binary_messenger, "dev.flutter.pigeon.refresh_rate.RefreshRateHostApi.enable" + prepended_suffix, &GetCodec()); - if (api != nullptr) { - channel.SetMessageHandler([api](const EncodableValue& message, const flutter::MessageReply& reply) { - try { - std::optional output = api->Enable(); - if (output.has_value()) { - reply(WrapError(output.value())); - return; - } - EncodableList wrapped; - wrapped.push_back(EncodableValue()); - reply(EncodableValue(std::move(wrapped))); - } catch (const std::exception& exception) { - reply(WrapError(exception.what())); - } - }); - } else { - channel.SetMessageHandler(nullptr); - } - } - { - BasicMessageChannel<> channel(binary_messenger, "dev.flutter.pigeon.refresh_rate.RefreshRateHostApi.disable" + prepended_suffix, &GetCodec()); - if (api != nullptr) { - channel.SetMessageHandler([api](const EncodableValue& message, const flutter::MessageReply& reply) { - try { - std::optional output = api->Disable(); - if (output.has_value()) { - reply(WrapError(output.value())); - return; - } - EncodableList wrapped; - wrapped.push_back(EncodableValue()); - reply(EncodableValue(std::move(wrapped))); - } catch (const std::exception& exception) { - reply(WrapError(exception.what())); - } - }); - } else { - channel.SetMessageHandler(nullptr); - } - } - { - BasicMessageChannel<> channel(binary_messenger, "dev.flutter.pigeon.refresh_rate.RefreshRateHostApi.preferMax" + prepended_suffix, &GetCodec()); - if (api != nullptr) { - channel.SetMessageHandler([api](const EncodableValue& message, const flutter::MessageReply& reply) { - try { - std::optional output = api->PreferMax(); - if (output.has_value()) { - reply(WrapError(output.value())); - return; - } - EncodableList wrapped; - wrapped.push_back(EncodableValue()); - reply(EncodableValue(std::move(wrapped))); - } catch (const std::exception& exception) { - reply(WrapError(exception.what())); - } - }); - } else { - channel.SetMessageHandler(nullptr); - } - } - { - BasicMessageChannel<> channel(binary_messenger, "dev.flutter.pigeon.refresh_rate.RefreshRateHostApi.preferDefault" + prepended_suffix, &GetCodec()); - if (api != nullptr) { - channel.SetMessageHandler([api](const EncodableValue& message, const flutter::MessageReply& reply) { - try { - std::optional output = api->PreferDefault(); - if (output.has_value()) { - reply(WrapError(output.value())); - return; - } - EncodableList wrapped; - wrapped.push_back(EncodableValue()); - reply(EncodableValue(std::move(wrapped))); - } catch (const std::exception& exception) { - reply(WrapError(exception.what())); - } - }); - } else { - channel.SetMessageHandler(nullptr); - } - } - { - BasicMessageChannel<> channel(binary_messenger, "dev.flutter.pigeon.refresh_rate.RefreshRateHostApi.matchContent" + prepended_suffix, &GetCodec()); - if (api != nullptr) { - channel.SetMessageHandler([api](const EncodableValue& message, const flutter::MessageReply& reply) { - try { - const auto& args = std::get(message); - const auto& encodable_fps_arg = args.at(0); - if (encodable_fps_arg.IsNull()) { - reply(WrapError("fps_arg unexpectedly null.")); - return; - } - const auto& fps_arg = std::get(encodable_fps_arg); - std::optional output = api->MatchContent(fps_arg); - if (output.has_value()) { - reply(WrapError(output.value())); - return; - } - EncodableList wrapped; - wrapped.push_back(EncodableValue()); - reply(EncodableValue(std::move(wrapped))); - } catch (const std::exception& exception) { - reply(WrapError(exception.what())); - } - }); - } else { - channel.SetMessageHandler(nullptr); - } - } - { - BasicMessageChannel<> channel(binary_messenger, "dev.flutter.pigeon.refresh_rate.RefreshRateHostApi.boost" + prepended_suffix, &GetCodec()); - if (api != nullptr) { - channel.SetMessageHandler([api](const EncodableValue& message, const flutter::MessageReply& reply) { - try { - const auto& args = std::get(message); - const auto& encodable_duration_ms_arg = args.at(0); - if (encodable_duration_ms_arg.IsNull()) { - reply(WrapError("duration_ms_arg unexpectedly null.")); - return; - } - const int64_t duration_ms_arg = encodable_duration_ms_arg.LongValue(); - std::optional output = api->Boost(duration_ms_arg); - if (output.has_value()) { - reply(WrapError(output.value())); - return; - } - EncodableList wrapped; - wrapped.push_back(EncodableValue()); - reply(EncodableValue(std::move(wrapped))); - } catch (const std::exception& exception) { - reply(WrapError(exception.what())); - } - }); - } else { - channel.SetMessageHandler(nullptr); - } - } - { - BasicMessageChannel<> channel(binary_messenger, "dev.flutter.pigeon.refresh_rate.RefreshRateHostApi.setCategory" + prepended_suffix, &GetCodec()); - if (api != nullptr) { - channel.SetMessageHandler([api](const EncodableValue& message, const flutter::MessageReply& reply) { - try { - const auto& args = std::get(message); - const auto& encodable_category_index_arg = args.at(0); - if (encodable_category_index_arg.IsNull()) { - reply(WrapError("category_index_arg unexpectedly null.")); - return; - } - const int64_t category_index_arg = encodable_category_index_arg.LongValue(); - std::optional output = api->SetCategory(category_index_arg); - if (output.has_value()) { - reply(WrapError(output.value())); - return; - } - EncodableList wrapped; - wrapped.push_back(EncodableValue()); - reply(EncodableValue(std::move(wrapped))); - } catch (const std::exception& exception) { - reply(WrapError(exception.what())); - } - }); - } else { - channel.SetMessageHandler(nullptr); - } - } - { - BasicMessageChannel<> channel(binary_messenger, "dev.flutter.pigeon.refresh_rate.RefreshRateHostApi.setTouchBoost" + prepended_suffix, &GetCodec()); - if (api != nullptr) { - channel.SetMessageHandler([api](const EncodableValue& message, const flutter::MessageReply& reply) { - try { - const auto& args = std::get(message); - const auto& encodable_enabled_arg = args.at(0); - if (encodable_enabled_arg.IsNull()) { - reply(WrapError("enabled_arg unexpectedly null.")); - return; - } - const auto& enabled_arg = std::get(encodable_enabled_arg); - std::optional output = api->SetTouchBoost(enabled_arg); - if (output.has_value()) { - reply(WrapError(output.value())); - return; - } - EncodableList wrapped; - wrapped.push_back(EncodableValue()); - reply(EncodableValue(std::move(wrapped))); - } catch (const std::exception& exception) { - reply(WrapError(exception.what())); - } - }); - } else { - channel.SetMessageHandler(nullptr); - } - } - { - BasicMessageChannel<> channel(binary_messenger, "dev.flutter.pigeon.refresh_rate.RefreshRateHostApi.isSupported" + prepended_suffix, &GetCodec()); - if (api != nullptr) { - channel.SetMessageHandler([api](const EncodableValue& message, const flutter::MessageReply& reply) { - try { - ErrorOr output = api->IsSupported(); - if (output.has_error()) { - reply(WrapError(output.error())); - return; - } - EncodableList wrapped; - wrapped.push_back(EncodableValue(std::move(output).TakeValue())); - reply(EncodableValue(std::move(wrapped))); - } catch (const std::exception& exception) { - reply(WrapError(exception.what())); - } - }); - } else { - channel.SetMessageHandler(nullptr); - } - } -} - -EncodableValue RefreshRateHostApi::WrapError(std::string_view error_message) { - return EncodableValue(EncodableList{ - EncodableValue(std::string(error_message)), - EncodableValue("Error"), - EncodableValue() - }); -} - -EncodableValue RefreshRateHostApi::WrapError(const FlutterError& error) { - return EncodableValue(EncodableList{ - EncodableValue(error.code()), - EncodableValue(error.message()), - error.details() - }); -} - -// Generated class from Pigeon that represents Flutter messages that can be called from C++. -RefreshRateFlutterApi::RefreshRateFlutterApi(flutter::BinaryMessenger* binary_messenger) - : binary_messenger_(binary_messenger), - message_channel_suffix_("") {} - -RefreshRateFlutterApi::RefreshRateFlutterApi( - flutter::BinaryMessenger* binary_messenger, - const std::string& message_channel_suffix) - : binary_messenger_(binary_messenger), - message_channel_suffix_(message_channel_suffix.length() > 0 ? std::string(".") + message_channel_suffix : "") {} - -const flutter::StandardMessageCodec& RefreshRateFlutterApi::GetCodec() { - return flutter::StandardMessageCodec::GetInstance(&PigeonInternalCodecSerializer::GetInstance()); -} - -void RefreshRateFlutterApi::OnDisplayInfoChanged( - const DisplayInfoMessage& info_arg, - std::function&& on_success, - std::function&& on_error) { - const std::string channel_name = "dev.flutter.pigeon.refresh_rate.RefreshRateFlutterApi.onDisplayInfoChanged" + message_channel_suffix_; - BasicMessageChannel<> channel(binary_messenger_, channel_name, &GetCodec()); - EncodableValue encoded_api_arguments = EncodableValue(EncodableList{ - CustomEncodableValue(info_arg), - }); - channel.Send(encoded_api_arguments, [channel_name, on_success = std::move(on_success), on_error = std::move(on_error)](const uint8_t* reply, size_t reply_size) { - std::unique_ptr response = GetCodec().DecodeMessage(reply, reply_size); - const auto& encodable_return_value = *response; - const auto* list_return_value = std::get_if(&encodable_return_value); - if (list_return_value) { - if (list_return_value->size() > 1) { - on_error(FlutterError(std::get(list_return_value->at(0)), std::get(list_return_value->at(1)), list_return_value->at(2))); - } else { - on_success(); - } - } else { - on_error(CreateConnectionError(channel_name)); - } - }); -} - -} // namespace refresh_rate diff --git a/third_party/refresh_rate/windows/refresh_rate_api.g.h b/third_party/refresh_rate/windows/refresh_rate_api.g.h deleted file mode 100644 index 70ef60a0..00000000 --- a/third_party/refresh_rate/windows/refresh_rate_api.g.h +++ /dev/null @@ -1,233 +0,0 @@ -// Copyright 2026 Qoder (qoder.in). All rights reserved. -// Use of this source code is governed by a BSD-style license. -// Autogenerated from Pigeon (v22.7.4), do not edit directly. -// See also: https://pub.dev/packages/pigeon - -#ifndef PIGEON_REFRESH_RATE_API_G_H_ -#define PIGEON_REFRESH_RATE_API_G_H_ -#include -#include -#include -#include - -#include -#include -#include - -namespace refresh_rate { - - -// Generated class from Pigeon. - -class FlutterError { - public: - explicit FlutterError(const std::string& code) - : code_(code) {} - explicit FlutterError(const std::string& code, const std::string& message) - : code_(code), message_(message) {} - explicit FlutterError(const std::string& code, const std::string& message, const flutter::EncodableValue& details) - : code_(code), message_(message), details_(details) {} - - const std::string& code() const { return code_; } - const std::string& message() const { return message_; } - const flutter::EncodableValue& details() const { return details_; } - - private: - std::string code_; - std::string message_; - flutter::EncodableValue details_; -}; - -template class ErrorOr { - public: - ErrorOr(const T& rhs) : v_(rhs) {} - ErrorOr(const T&& rhs) : v_(std::move(rhs)) {} - ErrorOr(const FlutterError& rhs) : v_(rhs) {} - ErrorOr(const FlutterError&& rhs) : v_(std::move(rhs)) {} - - bool has_error() const { return std::holds_alternative(v_); } - const T& value() const { return std::get(v_); }; - const FlutterError& error() const { return std::get(v_); }; - - private: - friend class RefreshRateHostApi; - friend class RefreshRateFlutterApi; - ErrorOr() = default; - T TakeValue() && { return std::get(std::move(v_)); } - - std::variant v_; -}; - - - -// Generated class from Pigeon that represents data sent in messages. -class DisplayInfoMessage { - public: - // Constructs an object setting all non-nullable fields. - DisplayInfoMessage(); - - // Constructs an object setting all fields. - explicit DisplayInfoMessage( - const double* current_rate, - const double* max_rate, - const double* min_rate, - const flutter::EncodableList* supported_rates, - const bool* is_variable_refresh_rate, - const double* engine_target_rate, - const bool* ios_pro_motion_enabled, - const int64_t* android_api_level, - const bool* is_low_power_mode, - const int64_t* thermal_state_index, - const bool* has_adaptive_refresh_rate, - const std::string* display_server, - const int64_t* monitor_count); - - const double* current_rate() const; - void set_current_rate(const double* value_arg); - void set_current_rate(double value_arg); - - const double* max_rate() const; - void set_max_rate(const double* value_arg); - void set_max_rate(double value_arg); - - const double* min_rate() const; - void set_min_rate(const double* value_arg); - void set_min_rate(double value_arg); - - const flutter::EncodableList* supported_rates() const; - void set_supported_rates(const flutter::EncodableList* value_arg); - void set_supported_rates(const flutter::EncodableList& value_arg); - - const bool* is_variable_refresh_rate() const; - void set_is_variable_refresh_rate(const bool* value_arg); - void set_is_variable_refresh_rate(bool value_arg); - - const double* engine_target_rate() const; - void set_engine_target_rate(const double* value_arg); - void set_engine_target_rate(double value_arg); - - const bool* ios_pro_motion_enabled() const; - void set_ios_pro_motion_enabled(const bool* value_arg); - void set_ios_pro_motion_enabled(bool value_arg); - - const int64_t* android_api_level() const; - void set_android_api_level(const int64_t* value_arg); - void set_android_api_level(int64_t value_arg); - - const bool* is_low_power_mode() const; - void set_is_low_power_mode(const bool* value_arg); - void set_is_low_power_mode(bool value_arg); - - const int64_t* thermal_state_index() const; - void set_thermal_state_index(const int64_t* value_arg); - void set_thermal_state_index(int64_t value_arg); - - const bool* has_adaptive_refresh_rate() const; - void set_has_adaptive_refresh_rate(const bool* value_arg); - void set_has_adaptive_refresh_rate(bool value_arg); - - const std::string* display_server() const; - void set_display_server(const std::string_view* value_arg); - void set_display_server(std::string_view value_arg); - - const int64_t* monitor_count() const; - void set_monitor_count(const int64_t* value_arg); - void set_monitor_count(int64_t value_arg); - - - private: - static DisplayInfoMessage FromEncodableList(const flutter::EncodableList& list); - flutter::EncodableList ToEncodableList() const; - friend class RefreshRateHostApi; - friend class RefreshRateFlutterApi; - friend class PigeonInternalCodecSerializer; - std::optional current_rate_; - std::optional max_rate_; - std::optional min_rate_; - std::optional supported_rates_; - std::optional is_variable_refresh_rate_; - std::optional engine_target_rate_; - std::optional ios_pro_motion_enabled_; - std::optional android_api_level_; - std::optional is_low_power_mode_; - std::optional thermal_state_index_; - std::optional has_adaptive_refresh_rate_; - std::optional display_server_; - std::optional monitor_count_; - -}; - - -class PigeonInternalCodecSerializer : public flutter::StandardCodecSerializer { - public: - PigeonInternalCodecSerializer(); - inline static PigeonInternalCodecSerializer& GetInstance() { - static PigeonInternalCodecSerializer sInstance; - return sInstance; - } - - void WriteValue( - const flutter::EncodableValue& value, - flutter::ByteStreamWriter* stream) const override; - - protected: - flutter::EncodableValue ReadValueOfType( - uint8_t type, - flutter::ByteStreamReader* stream) const override; - -}; - -// Generated interface from Pigeon that represents a handler of messages from Flutter. -class RefreshRateHostApi { - public: - RefreshRateHostApi(const RefreshRateHostApi&) = delete; - RefreshRateHostApi& operator=(const RefreshRateHostApi&) = delete; - virtual ~RefreshRateHostApi() {} - virtual ErrorOr GetDisplayInfo() = 0; - virtual std::optional Enable() = 0; - virtual std::optional Disable() = 0; - virtual std::optional PreferMax() = 0; - virtual std::optional PreferDefault() = 0; - virtual std::optional MatchContent(double fps) = 0; - virtual std::optional Boost(int64_t duration_ms) = 0; - virtual std::optional SetCategory(int64_t category_index) = 0; - virtual std::optional SetTouchBoost(bool enabled) = 0; - virtual ErrorOr IsSupported() = 0; - - // The codec used by RefreshRateHostApi. - static const flutter::StandardMessageCodec& GetCodec(); - // Sets up an instance of `RefreshRateHostApi` to handle messages through the `binary_messenger`. - static void SetUp( - flutter::BinaryMessenger* binary_messenger, - RefreshRateHostApi* api); - static void SetUp( - flutter::BinaryMessenger* binary_messenger, - RefreshRateHostApi* api, - const std::string& message_channel_suffix); - static flutter::EncodableValue WrapError(std::string_view error_message); - static flutter::EncodableValue WrapError(const FlutterError& error); - - protected: - RefreshRateHostApi() = default; - -}; -// Generated class from Pigeon that represents Flutter messages that can be called from C++. -class RefreshRateFlutterApi { - public: - RefreshRateFlutterApi(flutter::BinaryMessenger* binary_messenger); - RefreshRateFlutterApi( - flutter::BinaryMessenger* binary_messenger, - const std::string& message_channel_suffix); - static const flutter::StandardMessageCodec& GetCodec(); - void OnDisplayInfoChanged( - const DisplayInfoMessage& info, - std::function&& on_success, - std::function&& on_error); - - private: - flutter::BinaryMessenger* binary_messenger_; - std::string message_channel_suffix_; -}; - -} // namespace refresh_rate -#endif // PIGEON_REFRESH_RATE_API_G_H_ diff --git a/third_party/refresh_rate/windows/refresh_rate_plugin_c_api.cpp b/third_party/refresh_rate/windows/refresh_rate_plugin_c_api.cpp deleted file mode 100644 index 8ea0cc3b..00000000 --- a/third_party/refresh_rate/windows/refresh_rate_plugin_c_api.cpp +++ /dev/null @@ -1,155 +0,0 @@ -// Windows implementation of RefreshRatePlugin. -// -// Uses QueryDisplayConfig for accurate refresh rates (rational numbers like 59.94Hz) -// and EnumDisplaySettings for enumerating all supported modes. -// Control is query-only on Windows — rate control requires system-level access. - -#include "include/refresh_rate/refresh_rate_plugin_c_api.h" -#include "refresh_rate_api.g.h" - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -namespace refresh_rate { - -class RefreshRatePlugin : public flutter::Plugin, public RefreshRateHostApi { - public: - static void RegisterWithRegistrar(flutter::PluginRegistrarWindows* registrar); - - RefreshRatePlugin(); - virtual ~RefreshRatePlugin(); - - // RefreshRateHostApi - ErrorOr GetDisplayInfo() override; - std::optional Enable() override { return std::nullopt; } - std::optional Disable() override { return std::nullopt; } - std::optional PreferMax() override { return std::nullopt; } - std::optional PreferDefault() override { return std::nullopt; } - std::optional MatchContent(double fps) override { return std::nullopt; } - std::optional Boost(int64_t duration_ms) override { return std::nullopt; } - std::optional SetCategory(int64_t category_index) override { return std::nullopt; } - std::optional SetTouchBoost(bool enabled) override { return std::nullopt; } - ErrorOr IsSupported() override { return false; } - - private: - double GetCurrentRate(); - double GetMaxRate(); - std::vector GetSupportedRates(); - double GetCurrentRateViaQueryDisplayConfig(); - double GetCurrentRateViaEnumDisplaySettings(); -}; - -void RefreshRatePlugin::RegisterWithRegistrar( - flutter::PluginRegistrarWindows* registrar) { - auto plugin = std::make_unique(); - RefreshRateHostApi::SetUp(registrar->messenger(), plugin.get()); - registrar->AddPlugin(std::move(plugin)); -} - -RefreshRatePlugin::RefreshRatePlugin() {} -RefreshRatePlugin::~RefreshRatePlugin() {} - -double RefreshRatePlugin::GetCurrentRateViaQueryDisplayConfig() { - UINT32 pathCount = 0, modeCount = 0; - if (GetDisplayConfigBufferSizes(QDC_ONLY_ACTIVE_PATHS, &pathCount, &modeCount) != ERROR_SUCCESS) { - return 0.0; - } - std::vector paths(pathCount); - std::vector modes(modeCount); - if (QueryDisplayConfig(QDC_ONLY_ACTIVE_PATHS, &pathCount, paths.data(), - &modeCount, modes.data(), nullptr) != ERROR_SUCCESS) { - return 0.0; - } - for (UINT32 i = 0; i < modeCount; i++) { - if (modes[i].infoType == DISPLAYCONFIG_MODE_INFO_TYPE_TARGET) { - auto vsync = modes[i].targetMode.targetVideoSignalInfo.vSyncFreq; - if (vsync.Denominator > 0) { - return static_cast(vsync.Numerator) / static_cast(vsync.Denominator); - } - } - } - return 0.0; -} - -double RefreshRatePlugin::GetCurrentRateViaEnumDisplaySettings() { - DEVMODE dm; - dm.dmSize = sizeof(dm); - if (EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dm)) { - double rate = static_cast(dm.dmDisplayFrequency); - if (rate > 1) return rate; - } - return 60.0; -} - -double RefreshRatePlugin::GetCurrentRate() { - double rate = GetCurrentRateViaQueryDisplayConfig(); - if (rate > 1.0) return rate; - return GetCurrentRateViaEnumDisplaySettings(); -} - -double RefreshRatePlugin::GetMaxRate() { - auto rates = GetSupportedRates(); - if (rates.empty()) return GetCurrentRate(); - return *std::max_element(rates.begin(), rates.end()); -} - -std::vector RefreshRatePlugin::GetSupportedRates() { - DEVMODE dm, current; - dm.dmSize = sizeof(dm); - current.dmSize = sizeof(current); - EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, ¤t); - - std::set rateSet; - int modeNum = 0; - while (EnumDisplaySettings(NULL, modeNum, &dm)) { - if (dm.dmPelsWidth == current.dmPelsWidth && - dm.dmPelsHeight == current.dmPelsHeight && - dm.dmDisplayFrequency > 1) { - rateSet.insert(static_cast(dm.dmDisplayFrequency)); - } - modeNum++; - } - if (rateSet.empty()) rateSet.insert(GetCurrentRate()); - return std::vector(rateSet.begin(), rateSet.end()); -} - -ErrorOr RefreshRatePlugin::GetDisplayInfo() { - double currentRate = GetCurrentRate(); - auto supportedRates = GetSupportedRates(); - double maxRate = supportedRates.empty() ? currentRate - : *std::max_element(supportedRates.begin(), supportedRates.end()); - double minRate = supportedRates.empty() ? currentRate : supportedRates.front(); - bool isVRR = (maxRate - minRate > 30) && supportedRates.size() <= 4; - - flutter::EncodableList rates; - for (double r : supportedRates) { - rates.push_back(flutter::EncodableValue(r)); - } - - DisplayInfoMessage msg; - msg.set_current_rate(currentRate); - msg.set_max_rate(maxRate); - msg.set_min_rate(minRate); - msg.set_supported_rates(rates); - msg.set_is_variable_refresh_rate(isVRR); - msg.set_engine_target_rate(60.0); - return msg; -} - -} // namespace refresh_rate - -void RefreshRatePluginCApiRegisterWithRegistrar( - FlutterDesktopPluginRegistrarRef registrar) { - refresh_rate::RefreshRatePlugin::RegisterWithRegistrar( - flutter::PluginRegistrarManager::GetInstance() - ->GetRegistrar(registrar)); -}