Beispiel #1
0
        /// <summary>
        ///     Validates an array of paths before applying
        /// </summary>
        /// <param name="pathInfos">The array of paths</param>
        /// <param name="allowChanges">true to allow changes and reordering of the provided paths, otherwise false</param>
        /// <returns>true if the provided paths are valid, otherwise false</returns>
        public static bool ValidatePathInfos(IEnumerable <PathInfo> pathInfos, bool allowChanges = true)
        {
            DisplayConfigModeInfo[] displayConfigModeInfos;
            var displayConfigPathInfos = GetDisplayConfigPathInfos(pathInfos, out displayConfigModeInfos);

            if (displayConfigPathInfos.Length <= 0)
            {
                return(false);
            }
            var flags = displayConfigModeInfos.Length == 0
                ? SetDisplayConfigFlags.TopologySupplied
                : SetDisplayConfigFlags.UseSuppliedDisplayConfig;

            if (allowChanges)
            {
                flags |= displayConfigModeInfos.Length == 0
                    ? SetDisplayConfigFlags.AllowPathOrderChanges
                    : SetDisplayConfigFlags.AllowChanges;
            }
            return
                (DisplayConfigApi.SetDisplayConfig(
                     (uint)displayConfigPathInfos.Length,
                     displayConfigPathInfos,
                     (uint)displayConfigModeInfos.Length,
                     displayConfigModeInfos.Length > 0 ? displayConfigModeInfos : null,
                     SetDisplayConfigFlags.Validate | flags) == Win32Status.Success);
        }
Beispiel #2
0
        /// <summary>
        ///     Validates a topology before applying
        /// </summary>
        /// <param name="topology">The topology identification</param>
        /// <returns>true if topology is applicable, otherwise false</returns>
        /// <exception cref="ArgumentOutOfRangeException"></exception>
        public static bool ValidateTopology(DisplayConfigTopologyId topology)
        {
            if (topology == DisplayConfigTopologyId.None)
            {
                throw new ArgumentOutOfRangeException(nameof(topology), "Topology should not be empty.");
            }
            var flags = (SetDisplayConfigFlags)topology;

            return(DisplayConfigApi.SetDisplayConfig(0, null, 0, null, SetDisplayConfigFlags.Validate | flags) ==
                   Win32Status.Success);
        }
Beispiel #3
0
        /// <summary>
        ///     Applies an array of paths
        /// </summary>
        /// <param name="pathInfos">The array of paths</param>
        /// <param name="allowChanges">true to allow changes and reordering of the provided paths, otherwise false</param>
        /// <param name="saveToDatabase">true to save the paths to the persistence database if call succeed, otherwise false</param>
        /// <param name="forceModeEnumeration">true to force driver mode enumeration before applying the paths</param>
        /// <exception cref="PathChangeException">Error in changing paths</exception>
        public static void ApplyPathInfos(IEnumerable <PathInfo> pathInfos, bool allowChanges = true,
                                          bool saveToDatabase = false, bool forceModeEnumeration = false)
        {
            var pathInfosArray = pathInfos.ToArray();

            if (!ValidatePathInfos(pathInfosArray, allowChanges))
            {
                throw new PathChangeException("Invalid paths information.");
            }
            DisplayConfigModeInfo[] displayConfigModeInfos;
            var displayConfigPathInfos = GetDisplayConfigPathInfos(pathInfosArray, out displayConfigModeInfos);

            if (displayConfigPathInfos.Length <= 0)
            {
                return;
            }
            var flags = displayConfigModeInfos.Length == 0
                ? SetDisplayConfigFlags.TopologySupplied
                : SetDisplayConfigFlags.UseSuppliedDisplayConfig;

            if (allowChanges)
            {
                flags |= displayConfigModeInfos.Length == 0
                    ? SetDisplayConfigFlags.AllowPathOrderChanges
                    : SetDisplayConfigFlags.AllowChanges;
            }
            else if (displayConfigModeInfos.Length > 0)
            {
                flags |= SetDisplayConfigFlags.NoOptimization;
            }
            if (saveToDatabase && (displayConfigModeInfos.Length > 0))
            {
                flags |= SetDisplayConfigFlags.SaveToDatabase;
            }
            if (forceModeEnumeration && (displayConfigModeInfos.Length > 0))
            {
                flags |= SetDisplayConfigFlags.ForceModeEnumeration;
            }
            var result =
                DisplayConfigApi.SetDisplayConfig(
                    (uint)displayConfigPathInfos.Length,
                    displayConfigPathInfos,
                    (uint)displayConfigModeInfos.Length,
                    displayConfigModeInfos.Length > 0 ? displayConfigModeInfos : null,
                    SetDisplayConfigFlags.Apply | flags);

            if (result != Win32Status.Success)
            {
                throw new PathChangeException("An error occurred while applying the paths information.",
                                              new Win32Exception((int)result));
            }
        }
Beispiel #4
0
        /// <summary>
        ///     Applies a saved topology
        /// </summary>
        /// <param name="topology">The topology identification to apply</param>
        /// <param name="allowPersistence">true to allows persistence of the changes, otherwise false</param>
        /// <exception cref="PathChangeException">Error in changing paths</exception>
        public static void ApplyTopology(DisplayConfigTopologyId topology, bool allowPersistence = false)
        {
            if (!ValidateTopology(topology))
            {
                throw new PathChangeException("Invalid topology request.");
            }
            var flags = (SetDisplayConfigFlags)topology;

            if (allowPersistence)
            {
                flags |= SetDisplayConfigFlags.PathPersistIfRequired;
            }
            var result = DisplayConfigApi.SetDisplayConfig(0, null, 0, null, SetDisplayConfigFlags.Apply | flags);

            if (result != Win32Status.Success)
            {
                throw new PathChangeException("An error occurred while applying the requested topology.",
                                              new Win32Exception((int)result));
            }
        }
Beispiel #5
0
        private static PathInfo[] GetPathInfos(QueryDeviceConfigFlags flags, out DisplayConfigTopologyId topologyId)
        {
            DisplayConfigPathInfo[] displayPaths;
            DisplayConfigModeInfo[] displayModes;
            uint pathCount;

            while (true)
            {
                uint modeCount;
                var  error = DisplayConfigApi.GetDisplayConfigBufferSizes(flags,
                                                                          out pathCount,
                                                                          out modeCount);
                if (error != Win32Status.Success)
                {
                    throw new Win32Exception((int)error);
                }

                displayPaths = new DisplayConfigPathInfo[pathCount];
                displayModes = new DisplayConfigModeInfo[modeCount];
                if (flags == QueryDeviceConfigFlags.DatabaseCurrent)
                {
                    error = DisplayConfigApi.QueryDisplayConfig(flags,
                                                                ref pathCount, displayPaths, ref modeCount, displayModes, out topologyId);
                }
                else
                {
                    topologyId = DisplayConfigTopologyId.None;
                    error      = DisplayConfigApi.QueryDisplayConfig(flags,
                                                                     ref pathCount, displayPaths, ref modeCount, displayModes, IntPtr.Zero);
                }
                if (error == Win32Status.Success)
                {
                    break;
                }
                if (error != Win32Status.ErrorInsufficientBuffer)
                {
                    throw new Win32Exception((int)error);
                }
            }
            var pathInfos =
                new Dictionary
                <uint,
                 Tuple
                 <DisplayConfigPathSourceInfo, DisplayConfigSourceMode?,
                  List
                  <
                      Tuple
                      <DisplayConfigPathInfoFlags, DisplayConfigPathTargetInfo, DisplayConfigTargetMode?,
                       DisplayConfigDesktopImageInfo?> >
                 > >
                    ();

            var sourceId = uint.MaxValue;

            for (var i = 0u; i < pathCount; i++)
            {
                var displayPath = displayPaths[i];
                DisplayConfigSourceMode?sourceMode = null;
                var key = sourceId;
                var isVirtualSupported = displayPath.Flags.HasFlag(DisplayConfigPathInfoFlags.SupportVirtualMode);
                if (isVirtualSupported &&
                    (displayPath.SourceInfo.SourceModeInfoIndex != DisplayConfigSourceMode.InvalidSourceModeIndex) &&
                    (displayModes[displayPath.SourceInfo.SourceModeInfoIndex].InfoType ==
                     DisplayConfigModeInfoType.Source))
                {
                    sourceMode = displayModes[displayPath.SourceInfo.SourceModeInfoIndex].SourceMode;
                    key        = displayPath.SourceInfo.SourceModeInfoIndex;
                }
                else if (!isVirtualSupported &&
                         (displayPath.SourceInfo.ModeInfoIndex != DisplayConfigModeInfo.InvalidModeIndex) &&
                         (displayModes[displayPath.SourceInfo.ModeInfoIndex].InfoType ==
                          DisplayConfigModeInfoType.Source))
                {
                    sourceMode = displayModes[displayPath.SourceInfo.ModeInfoIndex].SourceMode;
                    key        = displayPath.SourceInfo.ModeInfoIndex;
                }
                else
                {
                    sourceId--;
                }

                if (!pathInfos.ContainsKey(key))
                {
                    pathInfos.Add(key,
                                  new Tuple
                                  <DisplayConfigPathSourceInfo, DisplayConfigSourceMode?,
                                   List
                                   <
                                       Tuple
                                       <DisplayConfigPathInfoFlags, DisplayConfigPathTargetInfo, DisplayConfigTargetMode?,
                                        DisplayConfigDesktopImageInfo?> >
                                  >(
                                      displayPath.SourceInfo, sourceMode,
                                      new List
                                      <
                                          Tuple
                                          <DisplayConfigPathInfoFlags, DisplayConfigPathTargetInfo, DisplayConfigTargetMode?,
                                           DisplayConfigDesktopImageInfo?> >
                                          ()));
                }

                DisplayConfigTargetMode?targetMode = null;
                if (isVirtualSupported &&
                    (displayPath.TargetInfo.TargetModeInfoIndex != DisplayConfigTargetMode.InvalidTargetModeIndex) &&
                    (displayModes[displayPath.TargetInfo.TargetModeInfoIndex].InfoType ==
                     DisplayConfigModeInfoType.Target))
                {
                    targetMode = displayModes[displayPath.TargetInfo.TargetModeInfoIndex].TargetMode;
                }
                else if (!isVirtualSupported &&
                         (displayPath.TargetInfo.ModeInfoIndex != DisplayConfigModeInfo.InvalidModeIndex) &&
                         (displayModes[displayPath.TargetInfo.ModeInfoIndex].InfoType ==
                          DisplayConfigModeInfoType.Target))
                {
                    targetMode = displayModes[displayPath.TargetInfo.ModeInfoIndex].TargetMode;
                }

                DisplayConfigDesktopImageInfo?desktopImageMode = null;
                if (isVirtualSupported &&
                    (displayPath.TargetInfo.DesktopModeInfoIndex !=
                     DisplayConfigDesktopImageInfo.InvalidDesktopImageModeIndex) &&
                    (displayModes[displayPath.TargetInfo.DesktopModeInfoIndex].InfoType ==
                     DisplayConfigModeInfoType.DesktopImage))
                {
                    desktopImageMode = displayModes[displayPath.TargetInfo.DesktopModeInfoIndex].DesktopImageInfo;
                }

                pathInfos[key].Item3.Add(
                    new Tuple
                    <DisplayConfigPathInfoFlags, DisplayConfigPathTargetInfo, DisplayConfigTargetMode?,
                     DisplayConfigDesktopImageInfo?>(
                        displayPath.Flags, displayPath.TargetInfo, targetMode, desktopImageMode));
            }
            return
                (pathInfos.Select(pair => new PathInfo(pair.Value.Item1, pair.Value.Item2, pair.Value.Item3)).ToArray());
        }