mirror of
https://github.com/terrymacdonald/DisplayMagician.git
synced 2024-08-30 18:32:20 +00:00
First attempt at setting Process DPI Awareness
This is required so that the undocumented DISPLAYCONFIG_SOURCE_DPI_SCALE_GET Windows CCD call is given the correct information by Windows 10/11. It gives an abnormal number on some hardware if this is not set. What we do now is set the process DPI context to "System Aware" on boot, but when we are either getting or setting the Windows DPI settings, we quickly swap to "Monitor Aware v2" DPI context, before swapping back to "System Aware" when we're done. This *should* return the correct per monitor settings.
This commit is contained in:
parent
e0d1d13c54
commit
01d6c1b9a9
@ -26,8 +26,8 @@ using System.Resources;
|
||||
[assembly: Guid("e4ceaf5e-ad01-4695-b179-31168eb74c48")]
|
||||
|
||||
// Version information
|
||||
[assembly: AssemblyVersion("2.4.0.52")]
|
||||
[assembly: AssemblyFileVersion("2.4.0.52")]
|
||||
[assembly: AssemblyVersion("2.4.0.57")]
|
||||
[assembly: AssemblyFileVersion("2.4.0.57")]
|
||||
[assembly: NeutralResourcesLanguageAttribute( "en" )]
|
||||
[assembly: CLSCompliant(true)]
|
||||
|
||||
|
@ -19,6 +19,16 @@ namespace DisplayMagicianShared.Windows
|
||||
ERROR_BAD_CONFIGURATION = 1610,
|
||||
}
|
||||
|
||||
public enum DPI_AWARENESS_CONTEXT : Int32
|
||||
{
|
||||
DPI_AWARENESS_CONTEXT_UNDEFINED = 0,
|
||||
DPI_AWARENESS_CONTEXT_UNAWARE = -1, //' DPI unaware. This window does not scale for DPI changes and is always assumed to have a scale factor of 100% (96 DPI). It will be automatically scaled by the system on any other DPI setting.
|
||||
DPI_AWARENESS_CONTEXT_SYSTEM_AWARE = -2, //' System DPI aware. This window does not scale for DPI changes. It will query for the DPI once and use that value for the lifetime of the process. If the DPI changes, the process will not adjust to the new DPI value. It will be automatically scaled up or down by the system when the DPI changes from the system value.
|
||||
DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE = -3, // ' Per monitor DPI aware. This window checks for the DPI when it is created and adjusts the scale factor whenever the DPI changes. These processes are not automatically scaled by the system.
|
||||
DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 = -4, //' Also known as Per Monitor v2. An advancement over the original per-monitor DPI awareness mode, which enables applications to access new DPI-related scaling behaviors on a per top-level window basis.
|
||||
DPI_AWARENESS_CONTEXT_UNAWARE_GDISCALED = -5, //' DPI unaware with improved quality of GDI-based content. This mode behaves similarly to DPI_AWARENESS_CONTEXT_UNAWARE, but also enables the system to automatically improve the rendering quality of text and other GDI-based primitives when the window is displayed on a high-DPI monitor.
|
||||
};
|
||||
|
||||
public enum DISPLAYCONFIG_DEVICE_INFO_TYPE : Int32
|
||||
{
|
||||
// MS Private API (which seems to use negative numbers)
|
||||
@ -1167,5 +1177,11 @@ 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);
|
||||
|
||||
[DllImport("user32")]
|
||||
public static extern bool SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT value);
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
@ -169,6 +169,10 @@ namespace DisplayMagicianShared.Windows
|
||||
|
||||
SharedLogger.logger.Trace("WinLibrary/WinLibrary: Intialising Windows CCD library interface");
|
||||
_initialised = true;
|
||||
|
||||
// Set the DPI awareness for the process this thread is running within so that the DPI calls return the right values at the right times
|
||||
CCDImport.SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT.DPI_AWARENESS_CONTEXT_SYSTEM_AWARE);
|
||||
|
||||
_activeDisplayConfig = GetActiveConfig();
|
||||
_allConnectedDisplayIdentifiers = GetAllConnectedDisplayIdentifiers();
|
||||
}
|
||||
@ -564,9 +568,13 @@ namespace DisplayMagicianShared.Windows
|
||||
}
|
||||
}
|
||||
|
||||
// Now cycle through the paths and grab the HDR state information
|
||||
// Now cycle through the paths and grab the state information we need
|
||||
// and map the adapter name to adapter id
|
||||
// and populate the display source information
|
||||
|
||||
// Set the DPI awareness for the process this thread is running within so that the DPI calls return the right values
|
||||
CCDImport.SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT.DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);
|
||||
|
||||
List<uint> targetPathIdsToChange = new List<uint>();
|
||||
List<uint> targetModeIdsToChange = new List<uint>();
|
||||
List<uint> targetIdsFound = new List<uint>();
|
||||
@ -602,11 +610,21 @@ namespace DisplayMagicianShared.Windows
|
||||
displayScalingInfo.Header.Id = paths[i].SourceInfo.Id;
|
||||
err = CCDImport.DisplayConfigGetDeviceInfo(ref displayScalingInfo);
|
||||
if (err == WIN32STATUS.ERROR_SUCCESS)
|
||||
{
|
||||
// Now we need to check if there is a strange value returned by the displayScalingInfo object. If so we reset it to 100% DPI
|
||||
if (displayScalingInfo.CurrrentScaleRel >= 0 && displayScalingInfo.CurrrentScaleRel < CCDImport.DPI_VALUES.Length)
|
||||
{
|
||||
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.Trace($"WinLibrary/GetWindowsDisplayConfig: Found DPI value for source {paths[i].SourceInfo.Id} is out of range. Windows CCD returned an abnormal value. Using the default Windows DPI Scaling value instead of 100%");
|
||||
sourceDpiScalingRel = 0;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
SharedLogger.logger.Warn($"WinLibrary/GetWindowsDisplayConfig: WARNING - Unabled to get advanced color settings for display {paths[i].TargetInfo.Id}.");
|
||||
}
|
||||
@ -774,6 +792,9 @@ namespace DisplayMagicianShared.Windows
|
||||
}
|
||||
}
|
||||
|
||||
// Set the DPI awareness for the process this thread is running within so that the DPI calls return the right values
|
||||
CCDImport.SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT.DPI_AWARENESS_CONTEXT_SYSTEM_AWARE);
|
||||
|
||||
// Get all the DisplayAdapters currently in the system
|
||||
// This will be used for windows to translate the adapter details beween reboots
|
||||
windowsDisplayConfig.DisplayAdapters = GetAllAdapterIDs();
|
||||
@ -1510,6 +1531,7 @@ namespace DisplayMagicianShared.Windows
|
||||
System.Threading.Thread.Sleep(100);
|
||||
|
||||
SharedLogger.logger.Trace($"WinLibrary/SetWindowsDisplayConfig: Attempting to set Windows DPI Scaling setting for display sources.");
|
||||
CCDImport.SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT.DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);
|
||||
foreach (var displaySourceEntry in displayConfig.DisplaySources)
|
||||
{
|
||||
// We only need to set the source on the first display source
|
||||
@ -1530,6 +1552,7 @@ namespace DisplayMagicianShared.Windows
|
||||
SharedLogger.logger.Warn($"WinLibrary/SetWindowsDisplayConfig: WARNING - Unable to set DPI value for source {displaySourceEntry.Value[0].SourceId} to {CCDImport.DPI_VALUES[displayScalingInfo.ScaleRel]}%.");
|
||||
}
|
||||
}
|
||||
CCDImport.SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT.DPI_AWARENESS_CONTEXT_SYSTEM_AWARE);
|
||||
|
||||
|
||||
// NOTE: There is currently no way within Windows CCD API to set the HDR settings to any particular setting
|
||||
|
Loading…
Reference in New Issue
Block a user