using WindowsDisplayAPI.Exceptions;
using WindowsDisplayAPI.Native.DisplayConfig;
using WindowsDisplayAPI.Native.DisplayConfig.Structures;
namespace WindowsDisplayAPI.DisplayConfig
{
///
/// Represents a path and its target
///
public class PathTargetInfo
{
private readonly PathTargetDesktopImage _desktopImage;
private readonly PathTargetSignalInfo _signalInfo;
///
/// Creates a new PathTargetInfo
///
/// The display target device
/// A boolean value indicating the target virtual mode support
public PathTargetInfo(PathDisplayTarget displayTarget, bool isVirtualModeSupported = false)
{
DisplayTarget = displayTarget;
IsVirtualModeSupportedByPath = isVirtualModeSupported;
}
///
/// Creates a new PathTargetInfo
///
/// The display target device
/// Display frequency in millihertz
/// Display scan line ordering
/// Display rotation
/// Display scaling
/// A boolean value indicating the target virtual mode support
public PathTargetInfo(
PathDisplayTarget displayTarget,
ulong frequencyInMillihertz,
DisplayConfigScanLineOrdering scanLineOrdering = DisplayConfigScanLineOrdering.NotSpecified,
DisplayConfigRotation rotation = DisplayConfigRotation.NotSpecified,
DisplayConfigScaling scaling = DisplayConfigScaling.Preferred,
bool isVirtualModeSupported = false
) : this(displayTarget, isVirtualModeSupported)
{
FrequencyInMillihertz = frequencyInMillihertz;
ScanLineOrdering = scanLineOrdering;
Rotation = rotation;
Scaling = scaling;
}
///
/// Creates a new PathTargetInfo
///
/// The display target device
/// The display signal information
/// A boolean value indicating the target virtual mode support
public PathTargetInfo(
PathDisplayTarget displayTarget,
PathTargetSignalInfo signalInfo,
bool isVirtualModeSupported = false
) : this(displayTarget, isVirtualModeSupported)
{
_signalInfo = signalInfo;
FrequencyInMillihertz = signalInfo.VerticalSyncFrequencyInMillihertz;
ScanLineOrdering = signalInfo.ScanLineOrdering;
IsSignalInformationAvailable = true;
}
///
/// Creates a new PathTargetInfo
///
/// The display target device
/// The display signal information
/// Display rotation
/// Display scaling
/// A boolean value indicating the target virtual mode support
public PathTargetInfo(
PathDisplayTarget displayTarget,
PathTargetSignalInfo signalInfo,
DisplayConfigRotation rotation = DisplayConfigRotation.NotSpecified,
DisplayConfigScaling scaling = DisplayConfigScaling.Preferred,
bool isVirtualModeSupported = false
) : this(
displayTarget,
0,
DisplayConfigScanLineOrdering.NotSpecified,
rotation,
scaling,
isVirtualModeSupported
)
{
_signalInfo = signalInfo;
FrequencyInMillihertz = signalInfo.VerticalSyncFrequencyInMillihertz;
ScanLineOrdering = signalInfo.ScanLineOrdering;
IsSignalInformationAvailable = true;
}
///
/// Creates a new PathTargetInfo
///
/// The display target device
/// The display signal information
/// The display desktop image information
/// A boolean value indicating the target virtual mode support
public PathTargetInfo(
PathDisplayTarget displayTarget,
PathTargetSignalInfo signalInfo,
PathTargetDesktopImage desktopImage,
bool isVirtualModeSupported = false
) : this(displayTarget, signalInfo, isVirtualModeSupported)
{
_desktopImage = desktopImage;
IsDesktopImageInformationAvailable = true;
}
///
/// Creates a new PathTargetInfo
///
/// The display target device
/// The display signal information
/// The display desktop image information
/// Display rotation
/// Display scaling
/// A boolean value indicating the target virtual mode support
public PathTargetInfo(
PathDisplayTarget displayTarget,
PathTargetSignalInfo signalInfo,
PathTargetDesktopImage desktopImage,
DisplayConfigRotation rotation = DisplayConfigRotation.NotSpecified,
DisplayConfigScaling scaling = DisplayConfigScaling.Preferred,
bool isVirtualModeSupported = false
) : this(displayTarget, signalInfo, rotation, scaling, isVirtualModeSupported)
{
_desktopImage = desktopImage;
IsDesktopImageInformationAvailable = true;
}
internal PathTargetInfo(
DisplayConfigPathInfoFlags pathFlags,
DisplayConfigPathTargetInfo targetInfo,
DisplayConfigTargetMode? targetMode,
DisplayConfigDesktopImageInfo? desktopImageMode
)
{
IsPathActive = pathFlags.HasFlag(DisplayConfigPathInfoFlags.Active);
IsVirtualModeSupportedByPath = pathFlags.HasFlag(DisplayConfigPathInfoFlags.SupportVirtualMode);
DisplayTarget = new PathDisplayTarget(
new PathDisplayAdapter(targetInfo.AdapterId),
targetInfo.TargetId,
targetInfo.TargetAvailable
);
OutputTechnology = targetInfo.OutputTechnology;
Rotation = targetInfo.Rotation;
Scaling = targetInfo.Scaling;
ScanLineOrdering = targetInfo.ScanLineOrdering;
FrequencyInMillihertz = targetInfo.RefreshRate.ToValue(1000);
ForcedBootAvailability = targetInfo.StatusFlags.HasFlag(
DisplayConfigPathTargetInfoFlags.AvailabilityBoot
);
ForcedPathAvailability = targetInfo.StatusFlags.HasFlag(
DisplayConfigPathTargetInfoFlags.AvailabilityPath
);
ForcedSystemAvailability = targetInfo.StatusFlags.HasFlag(
DisplayConfigPathTargetInfoFlags.AvailabilitySystem
);
IsCurrentlyInUse = targetInfo.StatusFlags.HasFlag(
DisplayConfigPathTargetInfoFlags.InUse
);
IsForcible = targetInfo.StatusFlags.HasFlag(
DisplayConfigPathTargetInfoFlags.Forcible
);
IsSignalInformationAvailable = targetMode.HasValue;
if (targetMode.HasValue)
{
_signalInfo = new PathTargetSignalInfo(targetMode.Value.TargetVideoSignalInfo);
}
IsDesktopImageInformationAvailable = desktopImageMode.HasValue;
if (desktopImageMode.HasValue)
{
_desktopImage = new PathTargetDesktopImage(desktopImageMode.Value);
}
}
///
/// Gets an instance of PathTargetDesktopImage containing information about this target desktop image
///
/// Target mode information is missing
public PathTargetDesktopImage DesktopImage
{
get
{
if (!IsDesktopImageInformationAvailable)
{
throw new MissingModeException(
"Desktop image information is missing or not available.",
DisplayConfigModeInfoType.DesktopImage
);
}
return _desktopImage;
}
}
///
/// Gets extra information about the representing display target device
///
public PathDisplayTarget DisplayTarget { get; }
///
/// Gets a boolean value indicating that the output is currently being forced in a boot-persistent manner
///
public bool ForcedBootAvailability { get; }
///
/// Gets a boolean value indicating that the output is currently being forced in a path-persistent manner
///
public bool ForcedPathAvailability { get; }
///
/// Gets a boolean value indicating that the output is currently being forced in a non-persistent manner
///
public bool ForcedSystemAvailability { get; }
///
/// Gets a value that specifies the refresh rate of the target
///
public ulong FrequencyInMillihertz { get; }
///
/// Gets a boolean value indicating if the target is in use on an active path
///
public bool IsCurrentlyInUse { get; }
///
/// Gets a boolean value indicating the presence of the desktop image information
///
public bool IsDesktopImageInformationAvailable { get; }
///
/// Gets a boolean value indicating that the output can be forced on this target even if a monitor is not detected
///
public bool IsForcible { get; }
///
/// Gets a boolean value indicating if this path is or should be active
///
public bool IsPathActive { get; } = true;
///
/// Gets a boolean value indicating the presence of the signal information
///
public bool IsSignalInformationAvailable { get; }
///
/// Gets a boolean value that indicates if the path supports virtual mode
///
public bool IsVirtualModeSupportedByPath { get; }
///
/// Gets the type of the display device connection
///
public DisplayConfigVideoOutputTechnology OutputTechnology { get; } = DisplayConfigVideoOutputTechnology.Other;
///
/// Gets the rotation of the target
///
public DisplayConfigRotation Rotation { get; }
///
/// Gets the value that specifies how the source image is scaled to the target
///
public DisplayConfigScaling Scaling { get; }
///
/// Gets the value that specifies the scan-line ordering of the output on the target
///
public DisplayConfigScanLineOrdering ScanLineOrdering { get; }
///
/// Gets the target device signal information
///
/// Target mode information is missing
public PathTargetSignalInfo SignalInfo
{
get
{
if (!IsSignalInformationAvailable)
{
throw new MissingModeException(
"Target mode information is missing or not available.",
DisplayConfigModeInfoType.Target
);
}
return _signalInfo;
}
}
///
public override string ToString()
{
return $"{DisplayTarget}: {FrequencyInMillihertz / 1000}hz{(IsCurrentlyInUse ? " [In Use]" : "")}";
}
internal DisplayConfigDesktopImageInfo? GetDisplayConfigDesktopImageInfo()
{
if (IsDesktopImageInformationAvailable)
{
return DesktopImage.GetDisplayConfigDesktopImageInfo();
}
return null;
}
internal DisplayConfigTargetMode? GetDisplayConfigTargetMode()
{
if (IsSignalInformationAvailable)
{
return new DisplayConfigTargetMode(SignalInfo.GetDisplayConfigVideoSignalInfo());
}
return null;
}
}
}