File: DeviceDisplay\DeviceDisplay.shared.cs
Web Access
Project: src\src\Essentials\src\Essentials.csproj (Microsoft.Maui.Essentials)
#nullable enable
using System;
 
namespace Microsoft.Maui.Devices
{
	/// <summary>
	/// Represents information about the device screen.
	/// </summary>
	public interface IDeviceDisplay
	{
		/// <summary>
		/// Gets or sets if the screen should be kept on.
		/// </summary>
		bool KeepScreenOn { get; set; }
 
		/// <summary>
		/// Gets the main screen's display info.
		/// </summary>
		DisplayInfo MainDisplayInfo { get; }
 
		/// <summary>
		/// Occurs when the main display's info changes.
		/// </summary>
		event EventHandler<DisplayInfoChangedEventArgs> MainDisplayInfoChanged;
	}
 
	/// <summary>
	/// Main display information event arguments.
	/// </summary>
	public class DisplayInfoChangedEventArgs : EventArgs
	{
		/// <summary>
		/// Initializes a new instance of the <see cref="DisplayInfoChangedEventArgs"/> class.
		/// </summary>
		/// <param name="displayInfo">The display info associated to this event.</param>
		public DisplayInfoChangedEventArgs(DisplayInfo displayInfo) =>
			DisplayInfo = displayInfo;
 
		/// <summary>
		/// Gets the current display info for the main display associated to this event.
		/// </summary>
		public DisplayInfo DisplayInfo { get; }
	}
 
	/// <summary>
	/// Represents information about the device screen.
	/// </summary>
	public static class DeviceDisplay
	{
		/// <summary>
		/// Gets or sets if the screen should be kept on.
		/// </summary>
		public static bool KeepScreenOn
		{
			get => Current.KeepScreenOn;
			set => Current.KeepScreenOn = value;
		}
 
		/// <summary>
		/// Gets the main screen's display info.
		/// </summary>
		public static DisplayInfo MainDisplayInfo => Current.MainDisplayInfo;
 
		/// <summary>
		/// Occurs when the main display's info changes.
		/// </summary>
		public static event EventHandler<DisplayInfoChangedEventArgs> MainDisplayInfoChanged
		{
			add => Current.MainDisplayInfoChanged += value;
			remove => Current.MainDisplayInfoChanged -= value;
		}
 
#if WINDOWS
		internal const float BaseLogicalDpi = 96.0f;
#elif ANDROID || TIZEN
		internal const float BaseLogicalDpi = 160.0f;
#endif
 
		static IDeviceDisplay? currentImplementation;
 
		/// <summary>
		/// Provides the default implementation for static usage of this API.
		/// </summary>
		public static IDeviceDisplay Current =>
			currentImplementation ??= new DeviceDisplayImplementation();
 
		internal static void SetCurrent(IDeviceDisplay? implementation) =>
			currentImplementation = implementation;
	}
 
	sealed partial class DeviceDisplayImplementation : DeviceDisplayImplementationBase
	{
	}
 
	abstract class DeviceDisplayImplementationBase : IDeviceDisplay
	{
		event EventHandler<DisplayInfoChangedEventArgs>? MainDisplayInfoChangedInternal;
 
		DisplayInfo _currentMetrics;
 
		public DisplayInfo MainDisplayInfo => GetMainDisplayInfo();
 
		public bool KeepScreenOn
		{
			get => GetKeepScreenOn();
			set => SetKeepScreenOn(value);
		}
 
		public event EventHandler<DisplayInfoChangedEventArgs> MainDisplayInfoChanged
		{
			add
			{
				if (MainDisplayInfoChangedInternal is null)
				{
					SetCurrent(MainDisplayInfo);
					StartScreenMetricsListeners();
				}
				MainDisplayInfoChangedInternal += value;
			}
			remove
			{
				var wasStopped = MainDisplayInfoChangedInternal is null;
				MainDisplayInfoChangedInternal -= value;
				if (!wasStopped && MainDisplayInfoChangedInternal is null)
					StopScreenMetricsListeners();
			}
		}
 
		void SetCurrent(DisplayInfo metrics) =>
			_currentMetrics = new DisplayInfo(
				metrics.Width, metrics.Height,
				metrics.Density,
				metrics.Orientation,
				metrics.Rotation,
				metrics.RefreshRate);
 
		protected void OnMainDisplayInfoChanged(DisplayInfoChangedEventArgs e)
		{
			if (!_currentMetrics.Equals(e.DisplayInfo))
			{
				SetCurrent(e.DisplayInfo);
				MainDisplayInfoChangedInternal?.Invoke(null, e);
			}
		}
 
		protected void OnMainDisplayInfoChanged()
		{
			var metrics = GetMainDisplayInfo();
			OnMainDisplayInfoChanged(new DisplayInfoChangedEventArgs(metrics));
		}
 
		protected abstract DisplayInfo GetMainDisplayInfo();
 
		protected abstract bool GetKeepScreenOn();
 
		protected abstract void SetKeepScreenOn(bool keepScreenOn);
 
		protected abstract void StartScreenMetricsListeners();
 
		protected abstract void StopScreenMetricsListeners();
	}
}