mirror of
https://github.com/NativeScript/NativeScript.git
synced 2025-11-05 13:26:48 +08:00
feat(ios): allow dynamic ProMotion frame refresh rate changes (#9775)
see: https://developer.apple.com/documentation/quartzcore/optimizing_promotion_refresh_rates_for_iphone_13_pro_and_ipad_pro
This commit is contained in:
@@ -29,6 +29,10 @@ const ActivityBackPressed = 'activityBackPressed';
|
||||
const ActivityNewIntent = 'activityNewIntent';
|
||||
const ActivityRequestPermissions = 'activityRequestPermissions';
|
||||
|
||||
export function setMaxRefreshRate(options?: { min?: number; max?: number; preferred?: number }): void {
|
||||
// ignore on android, ios only
|
||||
}
|
||||
|
||||
export class AndroidApplication extends Observable implements AndroidApplicationDefinition {
|
||||
public static activityCreatedEvent = ActivityCreated;
|
||||
public static activityDestroyedEvent = ActivityDestroyed;
|
||||
|
||||
13
packages/core/application/index.d.ts
vendored
13
packages/core/application/index.d.ts
vendored
@@ -76,6 +76,19 @@ export function setAutoSystemAppearanceChanged(value: boolean): void;
|
||||
*/
|
||||
export function systemAppearanceChanged(rootView: View, newSystemAppearance: 'dark' | 'light'): void;
|
||||
|
||||
/**
|
||||
* iOS Only
|
||||
* Dynamically change the preferred frame rate
|
||||
* For devices (iOS 15+) which support min/max/preferred frame rate you can specify ranges
|
||||
* For devices (iOS < 15), you can specify the max frame rate
|
||||
* see: https://developer.apple.com/documentation/quartzcore/optimizing_promotion_refresh_rates_for_iphone_13_pro_and_ipad_pro
|
||||
* To use, ensure your Info.plist has:
|
||||
* <key>CADisableMinimumFrameDurationOnPhone</key>
|
||||
* <true/>
|
||||
* @param options { min?: number; max?: number; preferred?: number }
|
||||
*/
|
||||
export function setMaxRefreshRate(options?: { min?: number; max?: number; preferred?: number }): void;
|
||||
|
||||
/**
|
||||
* Event data containing information for the application events.
|
||||
*/
|
||||
|
||||
@@ -88,6 +88,44 @@ class CADisplayLinkTarget extends NSObject {
|
||||
};
|
||||
}
|
||||
|
||||
export function setMaxRefreshRate(options?: { min?: number; max?: number; preferred?: number }) {
|
||||
const adjustRefreshRate = function () {
|
||||
if (displayedLink) {
|
||||
const minFrameRateDisabled = NSBundle.mainBundle.objectForInfoDictionaryKey('CADisableMinimumFrameDurationOnPhone');
|
||||
if (minFrameRateDisabled) {
|
||||
let max = 120;
|
||||
const deviceMaxFrames = UIScreen.mainScreen?.maximumFramesPerSecond;
|
||||
if (options?.max) {
|
||||
if (deviceMaxFrames) {
|
||||
// iOS 10.3
|
||||
max = options.max <= deviceMaxFrames ? options.max : deviceMaxFrames;
|
||||
} else if (displayedLink.preferredFramesPerSecond) {
|
||||
// iOS 10.0
|
||||
max = options.max <= displayedLink.preferredFramesPerSecond ? options.max : displayedLink.preferredFramesPerSecond;
|
||||
}
|
||||
}
|
||||
|
||||
if (iOSNativeHelper.MajorVersion >= 15) {
|
||||
const min = options?.min || max / 2;
|
||||
const preferred = options?.preferred || max;
|
||||
displayedLink.preferredFrameRateRange = CAFrameRateRangeMake(min, max, preferred);
|
||||
} else {
|
||||
displayedLink.preferredFramesPerSecond = max;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
if (!displayedOnce) {
|
||||
displayedLinkTarget = <CADisplayLink>CADisplayLinkTarget.new();
|
||||
displayedLink = CADisplayLink.displayLinkWithTargetSelector(displayedLinkTarget, 'onDisplayed');
|
||||
adjustRefreshRate();
|
||||
displayedLink.addToRunLoopForMode(NSRunLoop.mainRunLoop, NSDefaultRunLoopMode);
|
||||
displayedLink.addToRunLoopForMode(NSRunLoop.mainRunLoop, UITrackingRunLoopMode);
|
||||
} else {
|
||||
adjustRefreshRate();
|
||||
}
|
||||
}
|
||||
|
||||
/* tslint:disable */
|
||||
export class iOSApplication implements iOSApplicationDefinition {
|
||||
/* tslint:enable */
|
||||
@@ -179,12 +217,7 @@ export class iOSApplication implements iOSApplicationDefinition {
|
||||
|
||||
@profile
|
||||
private didFinishLaunchingWithOptions(notification: NSNotification) {
|
||||
if (!displayedOnce) {
|
||||
displayedLinkTarget = CADisplayLinkTarget.new();
|
||||
displayedLink = CADisplayLink.displayLinkWithTargetSelector(displayedLinkTarget, 'onDisplayed');
|
||||
displayedLink.addToRunLoopForMode(NSRunLoop.mainRunLoop, NSDefaultRunLoopMode);
|
||||
displayedLink.addToRunLoopForMode(NSRunLoop.mainRunLoop, UITrackingRunLoopMode);
|
||||
}
|
||||
setMaxRefreshRate();
|
||||
|
||||
this._window = UIWindow.alloc().initWithFrame(UIScreen.mainScreen.bounds);
|
||||
// TODO: Expose Window module so that it can we styled from XML & CSS
|
||||
|
||||
3
packages/core/index.d.ts
vendored
3
packages/core/index.d.ts
vendored
@@ -8,7 +8,7 @@
|
||||
export type { NativeScriptConfig } from './config';
|
||||
export { iOSApplication, AndroidApplication } from './application';
|
||||
export type { ApplicationEventData, LaunchEventData, OrientationChangedEventData, UnhandledErrorEventData, DiscardedErrorEventData, CssChangedEventData, LoadAppCSSEventData, AndroidActivityEventData, AndroidActivityBundleEventData, AndroidActivityRequestPermissionsEventData, AndroidActivityResultEventData, AndroidActivityNewIntentEventData, AndroidActivityBackPressedEventData, SystemAppearanceChangedEventData } from './application';
|
||||
import { AndroidApplication, iOSApplication, systemAppearanceChanged, getMainEntry, getRootView, _resetRootView, getResources, setResources, setCssFileName, getCssFileName, loadAppCss, addCss, on, off, notify, hasListeners, run, orientation, getNativeApplication, hasLaunched, systemAppearance, setAutoSystemAppearanceChanged } from './application';
|
||||
import { AndroidApplication, iOSApplication, systemAppearanceChanged, getMainEntry, getRootView, _resetRootView, getResources, setResources, setCssFileName, getCssFileName, loadAppCss, addCss, on, off, notify, hasListeners, run, orientation, getNativeApplication, hasLaunched, systemAppearance, setAutoSystemAppearanceChanged, setMaxRefreshRate } from './application';
|
||||
export declare const Application: {
|
||||
launchEvent: string;
|
||||
displayedEvent: string;
|
||||
@@ -22,6 +22,7 @@ export declare const Application: {
|
||||
systemAppearanceChangedEvent: string;
|
||||
fontScaleChangedEvent: string;
|
||||
systemAppearanceChanged: typeof systemAppearanceChanged;
|
||||
setMaxRefreshRate: typeof setMaxRefreshRate;
|
||||
getMainEntry: typeof getMainEntry;
|
||||
getRootView: typeof getRootView;
|
||||
resetRootView: typeof _resetRootView;
|
||||
|
||||
@@ -5,7 +5,7 @@ import './globals';
|
||||
export { iOSApplication, AndroidApplication } from './application';
|
||||
export type { ApplicationEventData, LaunchEventData, OrientationChangedEventData, UnhandledErrorEventData, DiscardedErrorEventData, CssChangedEventData, LoadAppCSSEventData, AndroidActivityEventData, AndroidActivityBundleEventData, AndroidActivityRequestPermissionsEventData, AndroidActivityResultEventData, AndroidActivityNewIntentEventData, AndroidActivityBackPressedEventData, SystemAppearanceChangedEventData } from './application';
|
||||
|
||||
import { fontScaleChangedEvent, launchEvent, displayedEvent, uncaughtErrorEvent, discardedErrorEvent, suspendEvent, resumeEvent, exitEvent, lowMemoryEvent, orientationChangedEvent, systemAppearanceChanged, systemAppearanceChangedEvent, getMainEntry, getRootView, _resetRootView, getResources, setResources, setCssFileName, getCssFileName, loadAppCss, addCss, on, off, notify, hasListeners, run, orientation, getNativeApplication, hasLaunched, android as appAndroid, ios as iosApp, systemAppearance, setAutoSystemAppearanceChanged, ensureNativeApplication } from './application';
|
||||
import { fontScaleChangedEvent, launchEvent, displayedEvent, uncaughtErrorEvent, discardedErrorEvent, suspendEvent, resumeEvent, exitEvent, lowMemoryEvent, orientationChangedEvent, systemAppearanceChanged, systemAppearanceChangedEvent, getMainEntry, getRootView, _resetRootView, getResources, setResources, setCssFileName, getCssFileName, loadAppCss, addCss, on, off, notify, hasListeners, run, orientation, getNativeApplication, hasLaunched, android as appAndroid, ios as iosApp, systemAppearance, setAutoSystemAppearanceChanged, ensureNativeApplication, setMaxRefreshRate } from './application';
|
||||
export const Application = {
|
||||
launchEvent,
|
||||
displayedEvent,
|
||||
@@ -19,6 +19,7 @@ export const Application = {
|
||||
systemAppearanceChangedEvent,
|
||||
systemAppearanceChanged,
|
||||
fontScaleChangedEvent,
|
||||
setMaxRefreshRate,
|
||||
|
||||
getMainEntry,
|
||||
getRootView,
|
||||
|
||||
Reference in New Issue
Block a user