1
0
mirror of https://github.com/ppy/osu.git synced 2025-01-14 20:03:21 +08:00

Avoid bindable/event feedback when changing resolution

This commit is contained in:
Bartłomiej Dach 2023-05-16 20:40:12 +02:00
parent 267e63320f
commit 88ce627c8e
No known key found for this signature in database

View File

@ -244,7 +244,8 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics
{
Scheduler.AddOnce(d =>
{
displayDropdown.Items = d;
if (!displayDropdown.Items.SequenceEqual(d, DisplayListComparer.DEFAULT))
displayDropdown.Items = d;
updateDisplaySettingsVisibility();
}, displays);
}
@ -376,5 +377,43 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics
}
}
}
/// <summary>
/// Contrary to <see cref="Display.Equals(osu.Framework.Platform.Display?)"/>, this comparer disregards the value of <see cref="Display.Bounds"/>.
/// We want to just show a list of displays, and for the purposes of settings we don't care about their bounds when it comes to the list.
/// However, <see cref="IWindow.DisplaysChanged"/> fires even if only the resolution of the current display was changed
/// (because it causes the bounds of all displays to also change).
/// We're not interested in those changes, so compare only the rest that we actually care about.
/// This helps to avoid a bindable/event feedback loop, in which a resolution change
/// would trigger a display "change", which would in turn reset resolution again.
/// </summary>
private class DisplayListComparer : IEqualityComparer<Display>
{
public static readonly DisplayListComparer DEFAULT = new DisplayListComparer();
public bool Equals(Display? x, Display? y)
{
if (ReferenceEquals(x, y)) return true;
if (ReferenceEquals(x, null)) return false;
if (ReferenceEquals(y, null)) return false;
return x.Index == y.Index
&& x.Name == y.Name
&& x.DisplayModes.SequenceEqual(y.DisplayModes);
}
public int GetHashCode(Display obj)
{
var hashCode = new HashCode();
hashCode.Add(obj.Index);
hashCode.Add(obj.Name);
hashCode.Add(obj.DisplayModes.Length);
foreach (var displayMode in obj.DisplayModes)
hashCode.Add(displayMode);
return hashCode.ToHashCode();
}
}
}
}