/* * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ package com.facebook.react.uimanager import android.content.Context import android.util.DisplayMetrics import android.view.WindowManager import com.facebook.react.bridge.WritableMap import com.facebook.react.bridge.WritableNativeMap /** * Holds an instance of the current DisplayMetrics so we don't have to thread it through all the * classes that need it. */ public object DisplayMetricsHolder { private const val INITIALIZATION_MISSING_MESSAGE = "DisplayMetricsHolder must be initialized with initDisplayMetricsIfNotInitialized or initDisplayMetrics" @JvmStatic private var windowDisplayMetrics: DisplayMetrics? = null @JvmStatic private var screenDisplayMetrics: DisplayMetrics? = null /** The metrics of the window associated to the Context used to initialize ReactNative */ @JvmStatic public fun getWindowDisplayMetrics(): DisplayMetrics { checkNotNull(windowDisplayMetrics) { DisplayMetricsHolder.INITIALIZATION_MISSING_MESSAGE } return windowDisplayMetrics as DisplayMetrics } @JvmStatic public fun setWindowDisplayMetrics(displayMetrics: DisplayMetrics?) { windowDisplayMetrics = displayMetrics } /** Screen metrics returns the metrics of the default screen on the device. */ @JvmStatic public fun getScreenDisplayMetrics(): DisplayMetrics { checkNotNull(screenDisplayMetrics) { DisplayMetricsHolder.INITIALIZATION_MISSING_MESSAGE } return screenDisplayMetrics as DisplayMetrics } @JvmStatic public fun setScreenDisplayMetrics(displayMetrics: DisplayMetrics?) { screenDisplayMetrics = displayMetrics } @JvmStatic public fun initDisplayMetricsIfNotInitialized(context: Context) { if (screenDisplayMetrics != null) { return } initDisplayMetrics(context) } @JvmStatic public fun initDisplayMetrics(context: Context) { val displayMetrics = context.resources.displayMetrics windowDisplayMetrics = displayMetrics val screenDisplayMetrics = DisplayMetrics() screenDisplayMetrics.setTo(displayMetrics) val wm = context.getSystemService(Context.WINDOW_SERVICE) as WindowManager checkNotNull(wm) { "WindowManager is null!" } // Get the real display metrics if we are using API level 17 or higher. // The real metrics include system decor elements (e.g. soft menu bar). // // See: // http://developer.android.com/reference/android/view/Display.html#getRealMetrics(android.util.DisplayMetrics) @Suppress("DEPRECATION") wm.defaultDisplay.getRealMetrics(screenDisplayMetrics) DisplayMetricsHolder.screenDisplayMetrics = screenDisplayMetrics } @JvmStatic public fun getDisplayMetricsWritableMap(fontScale: Double): WritableMap { checkNotNull(windowDisplayMetrics) { DisplayMetricsHolder.INITIALIZATION_MISSING_MESSAGE } checkNotNull(screenDisplayMetrics) { DisplayMetricsHolder.INITIALIZATION_MISSING_MESSAGE } return WritableNativeMap().apply { putMap( "windowPhysicalPixels", getPhysicalPixelsWritableMap(windowDisplayMetrics as DisplayMetrics, fontScale)) putMap( "screenPhysicalPixels", getPhysicalPixelsWritableMap(screenDisplayMetrics as DisplayMetrics, fontScale)) } } private fun getPhysicalPixelsWritableMap( displayMetrics: DisplayMetrics, fontScale: Double ): WritableMap = WritableNativeMap().apply { putInt("width", displayMetrics.widthPixels) putInt("height", displayMetrics.heightPixels) putDouble("scale", displayMetrics.density.toDouble()) putDouble("fontScale", fontScale) putDouble("densityDpi", displayMetrics.densityDpi.toDouble()) } }