mirror of
https://github.com/terrymacdonald/DisplayMagician.git
synced 2024-08-30 18:32:20 +00:00
Added Windows per source DPI scaling settings
This commit is contained in:
parent
f40640ccbd
commit
a93c9e62d2
@ -26,8 +26,8 @@ using System.Resources;
|
||||
[assembly: Guid("e4ceaf5e-ad01-4695-b179-31168eb74c48")]
|
||||
|
||||
// Version information
|
||||
[assembly: AssemblyVersion("2.3.2.2")]
|
||||
[assembly: AssemblyFileVersion("2.3.2.2")]
|
||||
[assembly: AssemblyVersion("2.3.2.5")]
|
||||
[assembly: AssemblyFileVersion("2.3.2.5")]
|
||||
[assembly: NeutralResourcesLanguageAttribute( "en" )]
|
||||
[assembly: CLSCompliant(true)]
|
||||
|
||||
|
@ -19,8 +19,14 @@ namespace DisplayMagicianShared.Windows
|
||||
ERROR_BAD_CONFIGURATION = 1610,
|
||||
}
|
||||
|
||||
public enum DISPLAYCONFIG_DEVICE_INFO_TYPE : UInt32
|
||||
public enum DISPLAYCONFIG_DEVICE_INFO_TYPE : Int32
|
||||
{
|
||||
// MS Private API (which seems to use negative numbers)
|
||||
// See https://github.com/lihas/windows-DPI-scaling-sample/blob/master/DPIHelper/DpiHelper.h from Sahil Singh
|
||||
DISPLAYCONFIG_DEVICE_INFO_SET_DPI_SCALE = -4, // Set current dpi scaling value for a display
|
||||
DISPLAYCONFIG_DEVICE_INFO_GET_DPI_SCALE = -3, // Returns min, max, suggested, and currently applied DPI scaling values.
|
||||
|
||||
// MS Public API
|
||||
Zero = 0,
|
||||
DISPLAYCONFIG_DEVICE_INFO_GET_SOURCE_NAME = 1, // Specifies the source name of the display device. If the DisplayConfigGetDeviceInfo function is successful, DisplayConfigGetDeviceInfo returns the source name in the DISPLAYCONFIG_SOURCE_DEVICE_NAME structure.
|
||||
DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_NAME = 2, // Specifies information about the monitor. If the DisplayConfigGetDeviceInfo function is successful, DisplayConfigGetDeviceInfo returns info about the monitor in the DISPLAYCONFIG_TARGET_DEVICE_NAME structure.
|
||||
@ -37,7 +43,7 @@ namespace DisplayMagicianShared.Windows
|
||||
// Supported starting in Windows<77>10 Fall Creators Update (Version 1709).
|
||||
DISPLAYCONFIG_DEVICE_INFO_GET_MONITOR_SPECIALIZATION = 12,
|
||||
DISPLAYCONFIG_DEVICE_INFO_SET_MONITOR_SPECIALIZATION = 13,
|
||||
DISPLAYCONFIG_DEVICE_INFO_FORCE_UINT32 = 0xFFFFFFFF // Only here to
|
||||
//DISPLAYCONFIG_DEVICE_INFO_FORCE_UINT32 = 0xFFFFFFFF // Only here to
|
||||
}
|
||||
|
||||
[Flags]
|
||||
@ -269,6 +275,73 @@ namespace DisplayMagicianShared.Windows
|
||||
Other = 255
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* OS reports DPI scaling values in relative terms, and not absolute terms.
|
||||
* eg. if current DPI value is 250%, and recommended value is 200%, then
|
||||
* OS will give us integer 2 for DPI scaling value (starting from recommended
|
||||
* DPI scaling move 2 steps to the right in this list).
|
||||
* values observed (and extrapolated) from system settings app (immersive control panel).
|
||||
*/
|
||||
/*public enum DPI_VALUES: UInt32
|
||||
{
|
||||
DPI_100 = 100,
|
||||
DPI_125 = 125,
|
||||
DPI_150 = 150,
|
||||
DPI_175 = 175,
|
||||
DPI_200 = 200,
|
||||
DPI_225 = 225,
|
||||
DPI_250 = 250,
|
||||
DPI_300 = 300,
|
||||
DPI_350 = 350,
|
||||
DPI_400 = 400,
|
||||
DPI_450 = 450,
|
||||
DPI_500 = 500
|
||||
};*/
|
||||
|
||||
/*
|
||||
* struct DISPLAYCONFIG_SOURCE_DPI_SCALE_GET
|
||||
* @brief used to fetch min, max, suggested, and currently applied DPI scaling values.
|
||||
* All values are relative to the recommended DPI scaling value
|
||||
* Note that DPI scaling is a property of the source, and not of target.
|
||||
*/
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct DISPLAYCONFIG_SOURCE_DPI_SCALE_GET
|
||||
{
|
||||
public DISPLAYCONFIG_DEVICE_INFO_HEADER Header;
|
||||
/*
|
||||
* @brief min value of DPI scaling is always 100, minScaleRel gives no. of steps down from recommended scaling
|
||||
* eg. if minScaleRel is -3 => 100 is 3 steps down from recommended scaling => recommended scaling is 175%
|
||||
*/
|
||||
public UInt32 MinScaleRel;
|
||||
|
||||
/*
|
||||
* @brief currently applied DPI scaling value wrt the recommended value. eg. if recommended value is 175%,
|
||||
* => if curScaleRel == 0 the current scaling is 175%, if curScaleRel == -1, then current scale is 150%
|
||||
*/
|
||||
public UInt32 CurrrentScaleRel;
|
||||
|
||||
/*
|
||||
* @brief maximum supported DPI scaling wrt recommended value
|
||||
*/
|
||||
public UInt32 MaxScaleRel;
|
||||
};
|
||||
|
||||
/*
|
||||
* struct DISPLAYCONFIG_SOURCE_DPI_SCALE_SET
|
||||
* @brief set DPI scaling value of a source
|
||||
* Note that DPI scaling is a property of the source, and not of target.
|
||||
*/
|
||||
public struct DISPLAYCONFIG_SOURCE_DPI_SCALE_SET
|
||||
{
|
||||
public DISPLAYCONFIG_DEVICE_INFO_HEADER Header;
|
||||
/*
|
||||
* @brief The value we want to set. The value should be relative to the recommended DPI scaling value of source.
|
||||
* eg. if scaleRel == 1, and recommended value is 175% => we are trying to set 200% scaling for the source
|
||||
*/
|
||||
public UInt32 ScaleRel;
|
||||
};
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct DISPLAYCONFIG_DEVICE_INFO_HEADER : IEquatable<DISPLAYCONFIG_DEVICE_INFO_HEADER>
|
||||
{
|
||||
@ -1022,6 +1095,7 @@ namespace DisplayMagicianShared.Windows
|
||||
// Set some useful constants
|
||||
public const SDC SDC_CCD_TEST_IF_VALID = (SDC.SDC_VALIDATE | SDC.SDC_USE_SUPPLIED_DISPLAY_CONFIG);
|
||||
public const uint DISPLAYCONFIG_PATH_MODE_IDX_INVALID = 0xffffffff;
|
||||
public static readonly UInt32[] DPI_VALUES = { 100, 125, 150, 175, 200, 225, 250, 300, 350, 400, 450, 500 };
|
||||
|
||||
|
||||
// GetDisplayConfigBufferSizes
|
||||
@ -1069,6 +1143,10 @@ namespace DisplayMagicianShared.Windows
|
||||
[DllImport("user32")]
|
||||
public static extern WIN32STATUS DisplayConfigGetDeviceInfo(ref DISPLAYCONFIG_SDR_WHITE_LEVEL requestPacket);
|
||||
|
||||
[DllImport("user32")]
|
||||
public static extern WIN32STATUS DisplayConfigGetDeviceInfo(ref DISPLAYCONFIG_SOURCE_DPI_SCALE_GET requestPacket);
|
||||
|
||||
|
||||
// DisplayConfigSetDeviceInfo
|
||||
[DllImport("user32")]
|
||||
public static extern WIN32STATUS DisplayConfigSetDeviceInfo(ref DISPLAYCONFIG_SET_TARGET_PERSISTENCE requestPacket);
|
||||
@ -1076,6 +1154,9 @@ namespace DisplayMagicianShared.Windows
|
||||
[DllImport("user32")]
|
||||
public static extern WIN32STATUS DisplayConfigSetDeviceInfo(ref DISPLAYCONFIG_SET_ADVANCED_COLOR_STATE requestPacket);
|
||||
|
||||
[DllImport("user32")]
|
||||
public static extern WIN32STATUS DisplayConfigSetDeviceInfo(ref DISPLAYCONFIG_SOURCE_DPI_SCALE_SET requestPacket);
|
||||
|
||||
|
||||
// Have disabled the DisplayConfigSetDeviceInfo options except for SET_TARGET_PERSISTENCE, as per the note
|
||||
// from https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-displayconfigsetdeviceinfo
|
||||
@ -1086,6 +1167,5 @@ namespace DisplayMagicianShared.Windows
|
||||
// SetDisplayConfig
|
||||
[DllImport("user32")]
|
||||
public static extern WIN32STATUS SetDisplayConfig([In] uint numPathArrayElements, [In] DISPLAYCONFIG_PATH_INFO[] pathArray, [In] uint numModeInfoArrayElements, [In] DISPLAYCONFIG_MODE_INFO[] modeInfoArray, [In] SDC flags);
|
||||
|
||||
}
|
||||
}
|
@ -46,13 +46,17 @@ namespace DisplayMagicianShared.Windows
|
||||
public UInt32 SourceId;
|
||||
public UInt32 TargetId;
|
||||
public string DevicePath;
|
||||
//The value we want to set. The value should be relative to the recommended DPI scaling value of source.
|
||||
// eg. if scaleRel == 1, and recommended value is 175% => we are trying to set 200% scaling for the source
|
||||
public UInt32 SourceDpiScalingRel;
|
||||
|
||||
public override bool Equals(object obj) => obj is DISPLAY_SOURCE other && this.Equals(other);
|
||||
public bool Equals(DISPLAY_SOURCE other)
|
||||
=> true;
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return 300;
|
||||
//return 300;
|
||||
return (AdapterId, SourceId, TargetId, DevicePath, SourceDpiScalingRel).GetHashCode();
|
||||
}
|
||||
|
||||
public static bool operator ==(DISPLAY_SOURCE lhs, DISPLAY_SOURCE rhs) => lhs.Equals(rhs);
|
||||
@ -91,12 +95,14 @@ namespace DisplayMagicianShared.Windows
|
||||
// NOTE: I have disabled the TaskBar specific matching for now due to errors I cannot fix
|
||||
// WinLibrary will still track the location of the taskbars, but won't actually set them as the setting of the taskbars doesnt work at the moment.
|
||||
/*&&
|
||||
TaskBarLayout.SequenceEqual(other.TaskBarLayout) &&
|
||||
TaskBarLayout.Values.SequenceEqual(other.TaskBarLayout.Values) &&
|
||||
TaskBarSettings.Equals(other.TaskBarSettings);*/
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return (DisplayConfigPaths, DisplayConfigModes, DisplayHDRStates, IsCloned, DisplayIdentifiers, TaskBarLayout, TaskBarSettings).GetHashCode();
|
||||
// Temporarily disabled this to make sure that the hashcode generation matched the equality tests.
|
||||
//return (DisplayConfigPaths, DisplayConfigModes, DisplayHDRStates, IsCloned, DisplayIdentifiers, TaskBarLayout, TaskBarSettings).GetHashCode();
|
||||
return (DisplayConfigPaths, DisplayConfigModes, DisplayHDRStates, IsCloned, DisplayIdentifiers).GetHashCode();
|
||||
}
|
||||
public static bool operator ==(WINDOWS_DISPLAY_CONFIG lhs, WINDOWS_DISPLAY_CONFIG rhs) => lhs.Equals(rhs);
|
||||
|
||||
@ -285,7 +291,7 @@ namespace DisplayMagicianShared.Windows
|
||||
{
|
||||
SharedLogger.logger.Error(ex, "WinLibrary/PatchAdapterIDs: Exception while going through the display config paths to update the adapter id");
|
||||
}
|
||||
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
@ -315,7 +321,7 @@ namespace DisplayMagicianShared.Windows
|
||||
{
|
||||
SharedLogger.logger.Error(ex, "WinLibrary/PatchAdapterIDs: Exception while going through the display config modes to update the adapter id");
|
||||
}
|
||||
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
@ -350,7 +356,7 @@ namespace DisplayMagicianShared.Windows
|
||||
hdrInfo.SDRWhiteLevel.Header.AdapterId = AdapterValueToLUID(newAdapterValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SharedLogger.logger.Warn($"WinLibrary/PatchAdapterIDs: There are no Display HDR states to update. Skipping.");
|
||||
@ -360,7 +366,7 @@ namespace DisplayMagicianShared.Windows
|
||||
{
|
||||
SharedLogger.logger.Error(ex, "WinLibrary/PatchAdapterIDs: Exception while going through the display config HDR info to update the adapter id");
|
||||
}
|
||||
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
@ -398,7 +404,7 @@ namespace DisplayMagicianShared.Windows
|
||||
{
|
||||
SharedLogger.logger.Error(ex, "WinLibrary/PatchAdapterIDs: Exception while going through the display sources list info to update the adapter id");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
public bool UpdateActiveConfig()
|
||||
@ -525,6 +531,26 @@ namespace DisplayMagicianShared.Windows
|
||||
|
||||
// Track if this display is a cloned path
|
||||
bool isClonedPath = false;
|
||||
|
||||
// Get the Windows Scaling DPI per display
|
||||
UInt32 sourceDpiScalingRel = 0;
|
||||
DISPLAYCONFIG_SOURCE_DPI_SCALE_GET displayScalingInfo = new DISPLAYCONFIG_SOURCE_DPI_SCALE_GET();
|
||||
displayScalingInfo.Header.Type = DISPLAYCONFIG_DEVICE_INFO_TYPE.DISPLAYCONFIG_DEVICE_INFO_GET_DPI_SCALE;
|
||||
displayScalingInfo.Header.Size = (uint)Marshal.SizeOf<DISPLAYCONFIG_SOURCE_DPI_SCALE_GET>(); ;
|
||||
displayScalingInfo.Header.AdapterId = paths[i].SourceInfo.AdapterId;
|
||||
displayScalingInfo.Header.Id = paths[i].SourceInfo.Id;
|
||||
err = CCDImport.DisplayConfigGetDeviceInfo(ref displayScalingInfo);
|
||||
if (err == WIN32STATUS.ERROR_SUCCESS)
|
||||
{
|
||||
SharedLogger.logger.Trace($"WinLibrary/GetWindowsDisplayConfig: Found DPI value for source {paths[i].SourceInfo.Id} is {CCDImport.DPI_VALUES[displayScalingInfo.CurrrentScaleRel]}%.");
|
||||
sourceDpiScalingRel = displayScalingInfo.CurrrentScaleRel;
|
||||
}
|
||||
else
|
||||
{
|
||||
SharedLogger.logger.Warn($"WinLibrary/GetWindowsDisplayConfig: WARNING - Unabled to get advanced color settings for display {paths[i].TargetInfo.Id}.");
|
||||
}
|
||||
|
||||
|
||||
// get display source name
|
||||
var sourceInfo = new DISPLAYCONFIG_SOURCE_DEVICE_NAME();
|
||||
sourceInfo.Header.Type = DISPLAYCONFIG_DEVICE_INFO_TYPE.DISPLAYCONFIG_DEVICE_INFO_GET_SOURCE_NAME;
|
||||
@ -534,6 +560,7 @@ namespace DisplayMagicianShared.Windows
|
||||
err = CCDImport.DisplayConfigGetDeviceInfo(ref sourceInfo);
|
||||
if (err == WIN32STATUS.ERROR_SUCCESS)
|
||||
{
|
||||
|
||||
//gotSourceDeviceName = true;
|
||||
// Store it for later
|
||||
if (windowsDisplayConfig.DisplaySources.ContainsKey(sourceInfo.ViewGdiDeviceName))
|
||||
@ -543,6 +570,7 @@ namespace DisplayMagicianShared.Windows
|
||||
ds.AdapterId = paths[i].SourceInfo.AdapterId;
|
||||
ds.SourceId = paths[i].SourceInfo.Id;
|
||||
ds.TargetId = paths[i].TargetInfo.Id;
|
||||
ds.SourceDpiScalingRel = sourceDpiScalingRel;
|
||||
windowsDisplayConfig.DisplaySources[sourceInfo.ViewGdiDeviceName].Add(ds);
|
||||
isClonedPath = true;
|
||||
isClonedProfile = true;
|
||||
@ -556,6 +584,7 @@ namespace DisplayMagicianShared.Windows
|
||||
ds.AdapterId = paths[i].SourceInfo.AdapterId;
|
||||
ds.SourceId = paths[i].SourceInfo.Id;
|
||||
ds.TargetId = paths[i].TargetInfo.Id;
|
||||
ds.SourceDpiScalingRel = sourceDpiScalingRel;
|
||||
sources.Add(ds);
|
||||
windowsDisplayConfig.DisplaySources.Add(sourceInfo.ViewGdiDeviceName, sources);
|
||||
}
|
||||
@ -607,6 +636,7 @@ namespace DisplayMagicianShared.Windows
|
||||
//gotAdapterName = true;
|
||||
}
|
||||
|
||||
|
||||
// Get advanced color info
|
||||
SharedLogger.logger.Trace($"WinLibrary/GetWindowsDisplayConfig: Attempting to get advanced color info for display {paths[i].TargetInfo.Id}.");
|
||||
|
||||
@ -1388,9 +1418,32 @@ namespace DisplayMagicianShared.Windows
|
||||
|
||||
SharedLogger.logger.Trace($"WinLibrary/SetActiveConfig: SUCCESS! The display configuration has been successfully applied");
|
||||
|
||||
SharedLogger.logger.Trace($"WinLibrary/SetActiveConfig: Waiting 0.1 second to let the display change take place before adjusting the Windows CCD HDR settings");
|
||||
SharedLogger.logger.Trace($"WinLibrary/SetActiveConfig: Waiting 0.1 second to let the display change take place before adjusting the Windows CCD Source DPI scaling settings");
|
||||
System.Threading.Thread.Sleep(100);
|
||||
|
||||
SharedLogger.logger.Trace($"WinLibrary/SetWindowsDisplayConfig: Attempting to set Windows DPI Scaling setting for display sources.");
|
||||
foreach (var displaySourceEntry in displayConfig.DisplaySources)
|
||||
{
|
||||
// We only need to set the source on the first display source
|
||||
// Set the Windows Scaling DPI per source
|
||||
DISPLAYCONFIG_SOURCE_DPI_SCALE_SET displayScalingInfo = new DISPLAYCONFIG_SOURCE_DPI_SCALE_SET();
|
||||
displayScalingInfo.Header.Type = DISPLAYCONFIG_DEVICE_INFO_TYPE.DISPLAYCONFIG_DEVICE_INFO_SET_DPI_SCALE;
|
||||
displayScalingInfo.Header.Size = (uint)Marshal.SizeOf<DISPLAYCONFIG_SOURCE_DPI_SCALE_SET>(); ;
|
||||
displayScalingInfo.Header.AdapterId = displaySourceEntry.Value[0].AdapterId;
|
||||
displayScalingInfo.Header.Id = displaySourceEntry.Value[0].SourceId;
|
||||
displayScalingInfo.ScaleRel = displaySourceEntry.Value[0].SourceDpiScalingRel;
|
||||
err = CCDImport.DisplayConfigSetDeviceInfo(ref displayScalingInfo);
|
||||
if (err == WIN32STATUS.ERROR_SUCCESS)
|
||||
{
|
||||
SharedLogger.logger.Trace($"WinLibrary/SetWindowsDisplayConfig: Setting DPI value for source {displaySourceEntry.Value[0].SourceId} to {CCDImport.DPI_VALUES[displayScalingInfo.ScaleRel]}%.");
|
||||
}
|
||||
else
|
||||
{
|
||||
SharedLogger.logger.Warn($"WinLibrary/SetWindowsDisplayConfig: WARNING - Unable to set DPI value for source {displaySourceEntry.Value[0].SourceId} to {CCDImport.DPI_VALUES[displayScalingInfo.ScaleRel]}%.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// NOTE: There is currently no way within Windows CCD API to set the HDR settings to any particular setting
|
||||
// This code will only turn on the HDR setting.
|
||||
foreach (ADVANCED_HDR_INFO_PER_PATH myHDRstate in displayConfig.DisplayHDRStates)
|
||||
|
Loading…
Reference in New Issue
Block a user