2021-07-24 04:05:38 +00:00
using System ;
using System.Collections.Generic ;
using System.IO ;
using System.Linq ;
using System.Windows.Forms ;
using DisplayMagicianShared.Resources ;
using Newtonsoft.Json ;
using System.Drawing ;
2021-08-22 09:45:51 +00:00
using System.Drawing.Imaging ;
2021-07-24 04:05:38 +00:00
namespace DisplayMagicianShared.Windows
2021-08-22 06:58:08 +00:00
{
2021-07-24 04:05:38 +00:00
2021-09-04 04:32:42 +00:00
public class WinProfileItem : ProfileItem , IComparable
2021-07-24 04:05:38 +00:00
{
private static List < WinProfileItem > _allSavedProfiles = new List < WinProfileItem > ( ) ;
private ProfileIcon _profileIcon ;
private Bitmap _profileBitmap , _profileShortcutBitmap ;
private List < string > _profileDisplayIdentifiers = new List < string > ( ) ;
private List < ScreenPosition > _screens ;
2021-08-22 06:58:08 +00:00
private WINDOWS_DISPLAY_CONFIG _windowsDisplayConfig = new WINDOWS_DISPLAY_CONFIG ( ) ;
2021-07-24 04:05:38 +00:00
private static readonly string uuidV4Regex = @"(?im)^[{(]?[0-9A-F]{8}[-]?(?:[0-9A-F]{4}[-]?){3}[0-9A-F]{12}[)}]?$" ;
private string _uuid = "" ;
private bool _isPossible = false ;
private Keys _hotkey = Keys . None ;
public WinProfileItem ( )
{
}
public new static Version Version = new Version ( 2 , 1 ) ;
#region Instance Properties
[JsonIgnore]
public override bool IsPossible
{
get
{
// Return the cached answer
return _isPossible ;
}
set
{
_isPossible = value ;
}
}
[JsonIgnore]
public override bool IsActive
{
get
{
if ( this . Equals ( ProfileRepository . CurrentProfile ) )
return true ;
else
return false ;
}
}
2021-08-22 06:58:08 +00:00
public override VIDEO_MODE VideoMode { get ; } = VIDEO_MODE . WINDOWS ;
2021-07-24 04:05:38 +00:00
public override string Name { get ; set ; }
[JsonRequired]
2021-08-22 06:58:08 +00:00
public WINDOWS_DISPLAY_CONFIG WindowsDisplayConfig
2021-07-24 04:05:38 +00:00
{
get
{
2021-08-22 06:58:08 +00:00
return _windowsDisplayConfig ;
2021-07-24 04:05:38 +00:00
}
set
{
2021-08-22 06:58:08 +00:00
_windowsDisplayConfig = value ;
2021-07-24 04:05:38 +00:00
}
}
public override List < string > ProfileDisplayIdentifiers
{
get
{
if ( _profileDisplayIdentifiers . Count = = 0 )
{
_profileDisplayIdentifiers = WinLibrary . GetLibrary ( ) . GetCurrentDisplayIdentifiers ( ) ;
}
return _profileDisplayIdentifiers ;
}
set
{
if ( value is List < string > )
_profileDisplayIdentifiers = value ;
}
}
2021-08-24 08:37:32 +00:00
2021-07-24 04:05:38 +00:00
#endregion
public override bool IsValid ( )
{
2021-09-02 02:44:35 +00:00
if ( WinLibrary . GetLibrary ( ) . IsValidConfig ( _windowsDisplayConfig ) & &
2021-08-22 06:58:08 +00:00
ProfileIcon is ProfileIcon & &
2021-07-24 04:05:38 +00:00
System . IO . File . Exists ( SavedProfileIconCacheFilename ) & &
ProfileBitmap is Bitmap & &
ProfileTightestBitmap is Bitmap & &
ProfileDisplayIdentifiers . Count > 0 )
2021-09-02 02:44:35 +00:00
return true ;
2021-07-24 04:05:38 +00:00
else
return false ;
}
public bool CopyTo ( WinProfileItem profile , bool overwriteId = true )
{
if ( ! ( profile is WinProfileItem ) )
return false ;
if ( overwriteId = = true )
profile . UUID = UUID ;
// Copy all our profile data over to the other profile
profile . Name = Name ;
2021-08-22 06:58:08 +00:00
profile . WindowsDisplayConfig = WindowsDisplayConfig ;
2021-07-24 04:05:38 +00:00
profile . ProfileIcon = ProfileIcon ;
profile . SavedProfileIconCacheFilename = SavedProfileIconCacheFilename ;
profile . ProfileBitmap = ProfileBitmap ;
profile . ProfileTightestBitmap = ProfileTightestBitmap ;
profile . ProfileDisplayIdentifiers = ProfileDisplayIdentifiers ;
2021-09-02 02:44:35 +00:00
profile . WallpaperMode = WallpaperMode ;
profile . WallpaperBitmapFilename = WallpaperBitmapFilename ;
profile . WallpaperStyle = WallpaperStyle ;
2021-07-24 04:05:38 +00:00
return true ;
}
public override bool PreSave ( )
{
// Prepare our profile data for saving
if ( _profileDisplayIdentifiers . Count = = 0 )
{
_profileDisplayIdentifiers = WinLibrary . GetLibrary ( ) . GetCurrentDisplayIdentifiers ( ) ;
}
// Return if it is valid and we should continue
return IsValid ( ) ;
}
public override void RefreshPossbility ( )
{
2021-08-22 06:58:08 +00:00
// Check whether this profile is possible
2021-09-03 10:15:23 +00:00
if ( ProfileRepository . CurrentVideoMode = = VIDEO_MODE . WINDOWS & & WinLibrary . GetLibrary ( ) . IsInstalled )
2021-07-24 04:05:38 +00:00
{
2021-09-03 10:15:23 +00:00
if ( WinLibrary . GetLibrary ( ) . IsPossibleConfig ( _windowsDisplayConfig ) )
{
2021-07-24 04:05:38 +00:00
2021-09-03 10:15:23 +00:00
SharedLogger . logger . Debug ( $"ProfileRepository/IsPossibleRefresh: The Windows CCD profile {Name} is possible!" ) ;
_isPossible = true ;
2021-07-24 04:05:38 +00:00
2021-09-03 10:15:23 +00:00
}
else
{
SharedLogger . logger . Debug ( $"ProfileRepository/IsPossibleRefresh: The Windows CCD profile {Name} is NOT possible!" ) ;
_isPossible = false ;
}
2021-07-24 04:05:38 +00:00
}
else
{
_isPossible = false ;
}
}
2021-09-03 10:15:23 +00:00
2021-08-24 10:46:32 +00:00
// Actually set this profile active
public override bool SetActive ( )
{
WinLibrary winLibrary = WinLibrary . GetLibrary ( ) ;
if ( winLibrary . IsInstalled )
{
if ( ! winLibrary . IsActiveConfig ( _windowsDisplayConfig ) )
{
if ( winLibrary . SetActiveConfig ( _windowsDisplayConfig ) )
{
SharedLogger . logger . Trace ( $"ProfileRepository/SetActive: The Windows CCD display settings within profile {Name} were successfully applied." ) ;
return true ;
}
else
{
SharedLogger . logger . Trace ( $"ProfileRepository/SetActive: The Windows CCD display settings within profile {Name} were NOT applied correctly." ) ;
}
}
else
{
SharedLogger . logger . Info ( $"ProfileRepository/SetActive: The display settings in profile {Name} are already installed. No need to install them again. Exiting." ) ;
}
}
return false ;
}
2021-07-24 04:05:38 +00:00
public override bool CreateProfileFromCurrentDisplaySettings ( )
{
WinLibrary winLibrary = WinLibrary . GetLibrary ( ) ;
if ( winLibrary . IsInstalled )
{
// Create the profile data from the current config
2021-08-22 06:58:08 +00:00
_windowsDisplayConfig = winLibrary . GetActiveConfig ( ) ;
2021-07-24 04:05:38 +00:00
// Now, since the ActiveProfile has changed, we need to regenerate screen positions
_screens = GetScreenPositions ( ) ;
return true ;
}
else
{
return false ;
}
}
public override bool PerformPostLoadingTasks ( )
{
// First thing we do is to set up the Screens
_screens = GetScreenPositions ( ) ;
return true ;
}
public override List < ScreenPosition > GetScreenPositions ( )
{
2021-09-02 02:44:35 +00:00
// Set up some colours
Color primaryScreenColor = Color . FromArgb ( 0 , 174 , 241 ) ; // represents Primary screen blue
Color normalScreenColor = Color . FromArgb ( 155 , 155 , 155 ) ; // represents normal screen colour (gray)
2021-07-24 04:05:38 +00:00
// Now we create the screens structure from the AMD profile information
_screens = new List < ScreenPosition > ( ) ;
2021-08-22 06:58:08 +00:00
int pathCount = _windowsDisplayConfig . DisplayConfigPaths . Length ;
// First of all we need to figure out how many display paths we have.
if ( pathCount < 1 )
2021-07-24 04:05:38 +00:00
{
2021-08-22 06:58:08 +00:00
// Return an empty screen if we have no Display Config Paths to use!
return _screens ;
}
2021-09-02 02:44:35 +00:00
2021-08-22 06:58:08 +00:00
foreach ( var path in _windowsDisplayConfig . DisplayConfigPaths )
{
// For each path we go through and get the relevant info we need.
if ( _windowsDisplayConfig . DisplayConfigPaths . Length > 0 )
2021-07-24 04:05:38 +00:00
{
2021-08-22 06:58:08 +00:00
// Set some basics about the screen
ScreenPosition screen = new ScreenPosition ( ) ;
screen . Library = "WINDOWS" ;
2021-09-02 02:44:35 +00:00
screen . IsSpanned = false ;
screen . Colour = normalScreenColor ; // this is the default unless overridden by the primary screen
2021-08-22 06:58:08 +00:00
2021-09-02 02:44:35 +00:00
UInt32 sourceId = path . SourceInfo . Id ;
2021-08-22 06:58:08 +00:00
UInt32 targetId = path . TargetInfo . Id ;
2021-09-02 02:44:35 +00:00
// Go through the screens as Windows knows them, and then enhance the info with Mosaic data if it applies
2021-08-22 06:58:08 +00:00
foreach ( DISPLAYCONFIG_MODE_INFO displayMode in _windowsDisplayConfig . DisplayConfigModes )
2021-07-24 04:05:38 +00:00
{
2021-08-22 06:58:08 +00:00
// Find the matching Display Config Source Mode
2021-09-02 02:44:35 +00:00
if ( displayMode . InfoType = = DISPLAYCONFIG_MODE_INFO_TYPE . DISPLAYCONFIG_MODE_INFO_TYPE_SOURCE & & displayMode . Id = = sourceId )
2021-07-24 04:05:38 +00:00
{
2021-08-22 06:58:08 +00:00
screen . Name = targetId . ToString ( ) ;
//screen.DisplayConnector = displayMode.DisplayConnector;
screen . ScreenX = displayMode . SourceMode . Position . X ;
screen . ScreenY = displayMode . SourceMode . Position . Y ;
screen . ScreenWidth = ( int ) displayMode . SourceMode . Width ;
screen . ScreenHeight = ( int ) displayMode . SourceMode . Height ;
2021-07-24 04:05:38 +00:00
// If we're at the 0,0 coordinate then we're the primary monitor
if ( screen . ScreenX = = 0 & & screen . ScreenY = = 0 )
{
screen . IsPrimary = true ;
2021-09-02 02:44:35 +00:00
screen . Colour = primaryScreenColor ;
2021-07-24 04:05:38 +00:00
}
2021-09-02 02:44:35 +00:00
break ;
2021-08-22 06:58:08 +00:00
}
}
2021-07-24 04:05:38 +00:00
2021-08-22 06:58:08 +00:00
foreach ( ADVANCED_HDR_INFO_PER_PATH hdrInfo in _windowsDisplayConfig . DisplayHDRStates )
{
// Find the matching HDR information
if ( hdrInfo . Id = = targetId )
{
2021-07-24 04:05:38 +00:00
// HDR information
2021-08-22 06:58:08 +00:00
if ( hdrInfo . AdvancedColorInfo . AdvancedColorSupported )
2021-07-24 04:05:38 +00:00
{
screen . HDRSupported = true ;
2021-08-22 06:58:08 +00:00
if ( hdrInfo . AdvancedColorInfo . AdvancedColorEnabled )
2021-07-24 04:05:38 +00:00
{
screen . HDREnabled = true ;
}
else
{
screen . HDREnabled = false ;
}
2021-08-22 06:58:08 +00:00
2021-07-24 04:05:38 +00:00
}
else
{
screen . HDRSupported = false ;
screen . HDREnabled = false ;
}
2021-09-02 02:44:35 +00:00
break ;
2021-08-22 06:58:08 +00:00
}
}
2021-07-24 04:05:38 +00:00
2021-08-22 06:58:08 +00:00
_screens . Add ( screen ) ;
2021-07-24 04:05:38 +00:00
}
}
2021-09-02 02:44:35 +00:00
2021-07-24 04:05:38 +00:00
return _screens ;
}
2021-09-04 04:32:42 +00:00
public override int CompareTo ( object obj )
2021-07-24 04:05:38 +00:00
{
2021-09-02 02:44:35 +00:00
if ( ! ( obj is WinProfileItem ) ) throw new ArgumentException ( "Object to CompareTo is not a WinProfileItem" ) ; ;
WinProfileItem otherProfile = ( WinProfileItem ) obj ;
return this . Name . CompareTo ( otherProfile . Name ) ;
2021-09-04 04:32:42 +00:00
}
2021-09-02 02:44:35 +00:00
// The public override for the Object.Equals
2021-09-04 04:32:42 +00:00
public override bool Equals ( object obj )
{
return EqualsDerived ( obj ) & &
obj . GetType ( ) = = typeof ( WinProfileItem ) ;
}
2021-09-02 02:44:35 +00:00
2021-07-24 04:05:38 +00:00
// Profiles are equal if their Viewports are equal
2021-09-04 04:32:42 +00:00
public override bool EqualsDerived ( object obj )
2021-07-24 04:05:38 +00:00
{
2021-09-04 04:32:42 +00:00
return base . EqualsDerived ( obj ) & &
! object . ReferenceEquals ( obj , null ) & &
obj is WinProfileItem & &
( ( WinProfileItem ) obj ) . WindowsDisplayConfig = = this . WindowsDisplayConfig ;
2021-07-24 04:05:38 +00:00
}
// If Equals() returns true for this object compared to another
// then GetHashCode() must return the same value for these objects.
public override int GetHashCode ( )
{
// Calculate the hash code for the product.
2021-08-22 06:58:08 +00:00
return ( WindowsDisplayConfig , ProfileDisplayIdentifiers ) . GetHashCode ( ) ;
2021-07-24 04:05:38 +00:00
}
2021-09-02 02:44:35 +00:00
public static bool operator = = ( WinProfileItem lhs , WinProfileItem rhs )
{
2021-09-04 04:32:42 +00:00
if ( object . ReferenceEquals ( lhs , rhs ) )
return true ;
2021-09-02 02:44:35 +00:00
2021-09-04 04:32:42 +00:00
if ( ! object . ReferenceEquals ( lhs , null ) & &
! object . ReferenceEquals ( rhs , null ) & &
lhs . Equals ( rhs ) )
return true ;
return false ;
2021-09-02 02:44:35 +00:00
}
public static bool operator ! = ( WinProfileItem lhs , WinProfileItem rhs ) = > ! ( lhs = = rhs ) ;
2021-07-24 04:05:38 +00:00
}
2021-08-22 06:58:08 +00:00
2021-07-24 04:05:38 +00:00
}