Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 23 additions & 23 deletions vibrance.GUI/AMD/AmdDynamicVibranceProxy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -114,14 +114,21 @@ private void OnWinEventHook(object sender, WinEventHookEventArgs e)
{
//test if a resolution change is needed
Screen screen = Screen.FromHandle(e.Handle);
if (_vibranceInfo.neverChangeResolution == false &&
applicationSetting.IsResolutionChangeNeeded &&
IsResolutionChangeNeeded(screen, applicationSetting.ResolutionSettings) &&
if (_vibranceInfo.neverChangeResolution == false &&
applicationSetting.IsResolutionChangeNeeded &&
ResolutionHelper.IsResolutionChangeNeeded(screen.DeviceName, applicationSetting.ResolutionSettings) &&
_windowsResolutionSettings.ContainsKey(screen.DeviceName) &&
_windowsResolutionSettings[screen.DeviceName].Item2.Contains(applicationSetting.ResolutionSettings))
{
_gameScreen = screen;
PerformResolutionChange(screen, applicationSetting.ResolutionSettings);
ResolutionHelper.ResolutionChangeResult result = ResolutionHelper.ChangeResolutionEx(
applicationSetting.ResolutionSettings, screen.DeviceName, false);
// AppliedUnverified means CDS_UPDATEREGISTRY itself reported success but the
// post-apply readback did not confirm it - see the matching comment in
// NvidiaDynamicVibranceProxy's OnWinEventHook.
_vibranceInfo.isResolutionChangeApplied =
result == ResolutionHelper.ResolutionChangeResult.Applied ||
result == ResolutionHelper.ResolutionChangeResult.AppliedUnverified;
}

_amdAdapter.SetSaturationOnAllDisplays(_vibranceInfo.userVibranceSettingDefault);
Expand All @@ -142,32 +149,25 @@ private void OnWinEventHook(object sender, WinEventHookEventArgs e)

//test if a resolution change is needed
Screen screen = Screen.FromHandle(processHandle);
if (_vibranceInfo.neverChangeResolution == false &&
_gameScreen != null && _gameScreen.Equals(screen) &&
if (_vibranceInfo.neverChangeResolution == false &&
_gameScreen != null && _gameScreen.Equals(screen) &&
_windowsResolutionSettings.ContainsKey(screen.DeviceName) &&
IsResolutionChangeNeeded(screen, _windowsResolutionSettings[screen.DeviceName].Item1))
ResolutionHelper.IsResolutionChangeNeeded(screen.DeviceName, _windowsResolutionSettings[screen.DeviceName].Item1))
{
PerformResolutionChange(screen, _windowsResolutionSettings[screen.DeviceName].Item1);
ResolutionHelper.ResolutionChangeResult result = ResolutionHelper.ChangeResolutionEx(
_windowsResolutionSettings[screen.DeviceName].Item1, screen.DeviceName, true);
// A failed (or unverified) revert must leave the flag true so the next
// foreground event retries it; Suppressed (the give-up state) deliberately
// still clears it - see the matching comment in NvidiaDynamicVibranceProxy's
// OnWinEventHook.
if (result != ResolutionHelper.ResolutionChangeResult.Failed &&
result != ResolutionHelper.ResolutionChangeResult.AppliedUnverified)
_vibranceInfo.isResolutionChangeApplied = false;
}

_amdAdapter.SetSaturationOnAllDisplays(_vibranceInfo.userVibranceSettingDefault);
}
}
}

private static bool IsResolutionChangeNeeded(Screen screen, ResolutionModeWrapper resolutionSettings)
{
Devmode mode;
if (resolutionSettings != null && ResolutionHelper.GetCurrentResolutionSettings(out mode, screen.DeviceName) && !resolutionSettings.Equals(mode))
{
return true;
}
return false;
}

private static void PerformResolutionChange(Screen screen, ResolutionModeWrapper resolutionSettings)
{
ResolutionHelper.ChangeResolutionEx(resolutionSettings, screen.DeviceName);
}
}
}
55 changes: 31 additions & 24 deletions vibrance.GUI/NVIDIA/NvidiaDynamicVibranceProxy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -219,13 +219,23 @@ private static void OnWinEventHook(object sender, WinEventHookEventArgs e)
{
//test if a resolution change is needed
Screen screen = Screen.FromHandle(e.Handle);
if (_vibranceInfo.neverChangeResolution == false &&
applicationSetting.IsResolutionChangeNeeded &&
IsResolutionChangeNeeded(screen, applicationSetting.ResolutionSettings) &&
if (_vibranceInfo.neverChangeResolution == false &&
applicationSetting.IsResolutionChangeNeeded &&
ResolutionHelper.IsResolutionChangeNeeded(screen.DeviceName, applicationSetting.ResolutionSettings) &&
_windowsResolutionSettings.ContainsKey(screen.DeviceName) &&
_windowsResolutionSettings[screen.DeviceName].Item2.Contains(applicationSetting.ResolutionSettings))
{
PerformResolutionChange(screen, applicationSetting.ResolutionSettings);
ResolutionHelper.ResolutionChangeResult result = ResolutionHelper.ChangeResolutionEx(
applicationSetting.ResolutionSettings, screen.DeviceName, false);
// AppliedUnverified means CDS_UPDATEREGISTRY itself reported success but
// the post-apply readback did not confirm it - the mode most likely DID
// change, so this still counts as applied for the purpose of a later
// revert attempt. Treating it as "not applied" would both strand the
// desktop at whatever this change actually produced AND tell the user the
// opposite of what happened.
_vibranceInfo.isResolutionChangeApplied =
result == ResolutionHelper.ResolutionChangeResult.Applied ||
result == ResolutionHelper.ResolutionChangeResult.AppliedUnverified;
}
_gameScreen = screen;
_vibranceInfo.defaultHandle = displayHandle;
Expand All @@ -241,13 +251,25 @@ private static void OnWinEventHook(object sender, WinEventHookEventArgs e)

//test if a resolution change is needed
Screen currentScreen = Screen.FromHandle(processHandle);
if (_vibranceInfo.neverChangeResolution == false &&
_gameScreen != null &&
_gameScreen.Equals(currentScreen) &&
if (_vibranceInfo.neverChangeResolution == false &&
_gameScreen != null &&
_gameScreen.Equals(currentScreen) &&
_windowsResolutionSettings.ContainsKey(currentScreen.DeviceName) &&
IsResolutionChangeNeeded(currentScreen, _windowsResolutionSettings[currentScreen.DeviceName].Item1))
ResolutionHelper.IsResolutionChangeNeeded(currentScreen.DeviceName, _windowsResolutionSettings[currentScreen.DeviceName].Item1))
{
PerformResolutionChange(currentScreen, _windowsResolutionSettings[currentScreen.DeviceName].Item1);
ResolutionHelper.ResolutionChangeResult result = ResolutionHelper.ChangeResolutionEx(
_windowsResolutionSettings[currentScreen.DeviceName].Item1, currentScreen.DeviceName, true);
// A failed (or unverified) revert must leave the flag true, or the next
// foreground event would never retry it - AppliedUnverified here means the
// revert's own CDS_UPDATEREGISTRY reported success but the readback did not
// confirm the desktop is really back, so it is treated the same as Failed:
// still worth another attempt. Suppressed (the give-up state) deliberately
// still clears it: once ChangeResolutionEx has stopped calling the driver at
// all, holding this true would retry forever with the device call skipped
// every time.
if (result != ResolutionHelper.ResolutionChangeResult.Failed &&
result != ResolutionHelper.ResolutionChangeResult.AppliedUnverified)
_vibranceInfo.isResolutionChangeApplied = false;
}

//test if changing the vibrance value is needed
Expand All @@ -268,21 +290,6 @@ private static void OnWinEventHook(object sender, WinEventHookEventArgs e)
}
}

private static bool IsResolutionChangeNeeded(Screen screen, ResolutionModeWrapper resolutionSettings)
{
Devmode mode;
if (resolutionSettings != null && ResolutionHelper.GetCurrentResolutionSettings(out mode, screen.DeviceName) && !resolutionSettings.Equals(mode))
{
return true;
}
return false;
}

private static void PerformResolutionChange(Screen screen, ResolutionModeWrapper resolutionSettings)
{
ResolutionHelper.ChangeResolutionEx(resolutionSettings, screen.DeviceName);
}

private void EnumerateDisplayHandles()
{
for (int i = 0, displayHandle = 0; displayHandle != -1; i++)
Expand Down
31 changes: 31 additions & 0 deletions vibrance.GUI/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ static class Program
private const string ErrorGraphicsAdapterUnknown = "Failed to determine your Graphic GraphicsAdapter type (NVIDIA/AMD). Make sure you have installed a proper GPU driver. Intel laptops are not supported as stated on the website. When installing your GPU driver did not work, please contact @juvlarN at twitter. Press Yes to open twitter in your browser now. Error: ";
private const string ErrorGraphicsAdapterAmbiguous = "Both NVIDIA and AMD graphic drivers have been found on your system. This can happen when you recently switched your graphic card and did not uninstall the old drivers. Make sure to uninstall unused graphic drivers to keep your system safe and stable. Use the program \"Display Driver Uninstaller\" to uninstall your old drivers!\n\nPress Yes to open \"Display Driver Uninstaller\" download website now.\nPress No to quit vibranceGUI.";
private const string MessageBoxCaption = "vibranceGUI Error";
private const string ResolutionSelfTestMessageBoxCaption = "vibranceGUI resolution change self test";

[STAThread]
static void Main(string[] args)
Expand All @@ -33,6 +34,21 @@ static void Main(string[] args)

Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);

// Runs before the GPU vendor detection below on purpose: ResolutionChangeFixture only
// ever drives ChangeResolutionEx through a fake IDisplayModeDevice, so it needs no
// driver and stays runnable on a machine GetAdapter() cannot resolve and would exit
// from. There is deliberately no hardware variant of this self test, and there must
// never be one - a display mode has no guaranteed undo, and a mode the panel cannot
// show would leave a user unable to even see a dialog asking them to confirm it, which
// is literally what issue #114 reports.
if (args.Contains("--selftest-resolution"))
{
MessageBox.Show(string.Join(Environment.NewLine, ResolutionChangeFixture.Run().ToArray()),
ResolutionSelfTestMessageBoxCaption, MessageBoxButtons.OK, MessageBoxIcon.Information);
return;
}

NativeMethods.SetDllDirectory(CommonUtils.GetVibrance_GUI_AppDataPath());

GraphicsAdapter adapter = GraphicsAdapterHelper.GetAdapter();
Expand Down Expand Up @@ -97,5 +113,20 @@ static void Main(string[] args)

GC.KeepAlive(mutex);
}

// Internal rather than private: ResolutionHelper's WinEvent-reachable failure-recording
// path (ChangeResolutionEx) reuses this so a broken log write (e.g. File.AppendText
// failing) cannot itself throw an exception across the native WinEvent callback frame.
internal static void LogSafely(string message)
{
try
{
VibranceGUI.Log(message);
}
catch (Exception)
{
// Logging must never be the reason a resolution change fails to complete.
}
}
}
}
5 changes: 5 additions & 0 deletions vibrance.GUI/common/Definitions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,10 @@ public struct VibranceInfo
public List<int> displayHandles;
public bool affectPrimaryMonitorOnly;
public bool neverChangeResolution;
// Tracks whether ResolutionHelper.ChangeResolutionEx last reported the game's resolution as
// applied (Applied or AppliedUnverified) for the current foreground game, so
// VibranceGUI.RebuildWindowsResolutionSettings knows not to overwrite the captured Windows
// mode with a live read while one of the proxies' own changes is in effect.
public bool isResolutionChangeApplied;
}
}
Loading