1
0
mirror of https://github.com/ppy/osu.git synced 2024-12-14 10:12:54 +08:00

Merge pull request #15668 from peppy/key-repeat

Update `KeyBindingContainer` usage to block key repeat where applicable
This commit is contained in:
Dan Balasescu 2021-11-18 15:21:35 +09:00 committed by GitHub
commit 698b6c4242
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
37 changed files with 100 additions and 155 deletions

View File

@ -52,7 +52,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="ppy.osu.Game.Resources" Version="2021.1112.0" /> <PackageReference Include="ppy.osu.Game.Resources" Version="2021.1112.0" />
<PackageReference Include="ppy.osu.Framework.Android" Version="2021.1108.0" /> <PackageReference Include="ppy.osu.Framework.Android" Version="2021.1118.0" />
</ItemGroup> </ItemGroup>
<ItemGroup Label="Transitive Dependencies"> <ItemGroup Label="Transitive Dependencies">
<!-- Realm needs to be directly referenced in all Xamarin projects, as it will not pull in its transitive dependencies otherwise. --> <!-- Realm needs to be directly referenced in all Xamarin projects, as it will not pull in its transitive dependencies otherwise. -->

View File

@ -83,6 +83,9 @@ namespace osu.Game.Tests.Visual.Gameplay
public bool OnPressed(KeyBindingPressEvent<TestAction> e) public bool OnPressed(KeyBindingPressEvent<TestAction> e)
{ {
if (e.Repeat)
return false;
ReceivedAction = e.Action == TestAction.Down; ReceivedAction = e.Action == TestAction.Down;
return true; return true;
} }

View File

@ -231,6 +231,9 @@ namespace osu.Game.Tests.Visual.Gameplay
public bool OnPressed(KeyBindingPressEvent<TestAction> e) public bool OnPressed(KeyBindingPressEvent<TestAction> e)
{ {
if (e.Repeat)
return false;
box.Colour = Color4.White; box.Colour = Color4.White;
return true; return true;
} }

View File

@ -164,6 +164,9 @@ namespace osu.Game.Tests.Visual.Gameplay
public bool OnPressed(KeyBindingPressEvent<TestAction> e) public bool OnPressed(KeyBindingPressEvent<TestAction> e)
{ {
if (e.Repeat)
return false;
box.Colour = Color4.White; box.Colour = Color4.White;
return true; return true;
} }

View File

@ -283,6 +283,9 @@ namespace osu.Game.Tests.Visual.Gameplay
public bool OnPressed(KeyBindingPressEvent<TestAction> e) public bool OnPressed(KeyBindingPressEvent<TestAction> e)
{ {
if (e.Repeat)
return false;
box.Colour = Color4.White; box.Colour = Color4.White;
return true; return true;
} }

View File

@ -1,11 +1,8 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using System;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.Input.Bindings;
using osu.Framework.Threading;
using osu.Game.Screens.Play.HUD; using osu.Game.Screens.Play.HUD;
using osu.Game.Skinning; using osu.Game.Skinning;
using osuTK; using osuTK;
@ -14,30 +11,6 @@ namespace osu.Game.Extensions
{ {
public static class DrawableExtensions public static class DrawableExtensions
{ {
public const double REPEAT_INTERVAL = 70;
public const double INITIAL_DELAY = 250;
/// <summary>
/// Helper method that is used while <see cref="IKeyBindingHandler"/> doesn't support repetitions of <see cref="IKeyBindingHandler{T}.OnPressed"/>.
/// Simulates repetitions by continually invoking a delegate according to the default key repeat rate.
/// </summary>
/// <remarks>
/// The returned delegate can be cancelled to stop repeat events from firing (usually in <see cref="IKeyBindingHandler{T}.OnReleased"/>).
/// </remarks>
/// <param name="handler">The <see cref="IKeyBindingHandler{T}"/> which is handling the repeat.</param>
/// <param name="scheduler">The <see cref="Scheduler"/> to schedule repetitions on.</param>
/// <param name="action">The <see cref="Action"/> to be invoked once immediately and with every repetition.</param>
/// <param name="initialRepeatDelay">The delay imposed on the first repeat. Defaults to <see cref="INITIAL_DELAY"/>.</param>
/// <returns>A <see cref="ScheduledDelegate"/> which can be cancelled to stop the repeat events from firing.</returns>
public static ScheduledDelegate BeginKeyRepeat(this IKeyBindingHandler handler, Scheduler scheduler, Action action, double initialRepeatDelay = INITIAL_DELAY)
{
action();
ScheduledDelegate repeatDelegate = new ScheduledDelegate(action, handler.Time.Current + initialRepeatDelay, REPEAT_INTERVAL);
scheduler.Add(repeatDelegate);
return repeatDelegate;
}
/// <summary> /// <summary>
/// Shakes this drawable. /// Shakes this drawable.
/// </summary> /// </summary>

View File

@ -90,6 +90,9 @@ namespace osu.Game.Graphics.Containers
public virtual bool OnPressed(KeyBindingPressEvent<GlobalAction> e) public virtual bool OnPressed(KeyBindingPressEvent<GlobalAction> e)
{ {
if (e.Repeat)
return false;
switch (e.Action) switch (e.Action)
{ {
case GlobalAction.Back: case GlobalAction.Back:

View File

@ -60,6 +60,9 @@ namespace osu.Game.Graphics
public bool OnPressed(KeyBindingPressEvent<GlobalAction> e) public bool OnPressed(KeyBindingPressEvent<GlobalAction> e)
{ {
if (e.Repeat)
return false;
switch (e.Action) switch (e.Action)
{ {
case GlobalAction.TakeScreenshot: case GlobalAction.TakeScreenshot:

View File

@ -64,6 +64,9 @@ namespace osu.Game.Graphics.UserInterface
public bool OnPressed(KeyBindingPressEvent<GlobalAction> e) public bool OnPressed(KeyBindingPressEvent<GlobalAction> e)
{ {
if (e.Repeat)
return false;
switch (e.Action) switch (e.Action)
{ {
case GlobalAction.Back: case GlobalAction.Back:

View File

@ -75,6 +75,9 @@ namespace osu.Game.Graphics.UserInterface
public virtual bool OnPressed(KeyBindingPressEvent<GlobalAction> e) public virtual bool OnPressed(KeyBindingPressEvent<GlobalAction> e)
{ {
if (e.Repeat)
return false;
if (!HasFocus) return false; if (!HasFocus) return false;
if (e.Action == GlobalAction.Back) if (e.Action == GlobalAction.Back)

View File

@ -58,6 +58,9 @@ namespace osu.Game.Graphics.UserInterfaceV2
public bool OnPressed(KeyBindingPressEvent<GlobalAction> e) public bool OnPressed(KeyBindingPressEvent<GlobalAction> e)
{ {
if (e.Repeat)
return false;
if (State.Value == Visibility.Hidden) if (State.Value == Visibility.Hidden)
return false; return false;

View File

@ -1007,6 +1007,9 @@ namespace osu.Game
public bool OnPressed(KeyBindingPressEvent<GlobalAction> e) public bool OnPressed(KeyBindingPressEvent<GlobalAction> e)
{ {
if (e.Repeat)
return false;
if (introScreen == null) return false; if (introScreen == null) return false;
switch (e.Action) switch (e.Action)

View File

@ -94,6 +94,9 @@ namespace osu.Game.Overlays
public override bool OnPressed(KeyBindingPressEvent<GlobalAction> e) public override bool OnPressed(KeyBindingPressEvent<GlobalAction> e)
{ {
if (e.Repeat)
return false;
switch (e.Action) switch (e.Action)
{ {
case GlobalAction.Back: case GlobalAction.Back:

View File

@ -102,6 +102,9 @@ namespace osu.Game.Overlays
public override bool OnPressed(KeyBindingPressEvent<GlobalAction> e) public override bool OnPressed(KeyBindingPressEvent<GlobalAction> e)
{ {
if (e.Repeat)
return false;
switch (e.Action) switch (e.Action)
{ {
case GlobalAction.Select: case GlobalAction.Select:

View File

@ -32,6 +32,9 @@ namespace osu.Game.Overlays.Music
public bool OnPressed(KeyBindingPressEvent<GlobalAction> e) public bool OnPressed(KeyBindingPressEvent<GlobalAction> e)
{ {
if (e.Repeat)
return false;
if (beatmap.Disabled) if (beatmap.Disabled)
return false; return false;

View File

@ -6,8 +6,6 @@ using osu.Framework.Graphics.Containers;
using osu.Framework.Input; using osu.Framework.Input;
using osu.Framework.Input.Bindings; using osu.Framework.Input.Bindings;
using osu.Framework.Input.Events; using osu.Framework.Input.Events;
using osu.Framework.Threading;
using osu.Game.Extensions;
using osu.Game.Input.Bindings; using osu.Game.Input.Bindings;
namespace osu.Game.Overlays.Volume namespace osu.Game.Overlays.Volume
@ -17,18 +15,12 @@ namespace osu.Game.Overlays.Volume
public Func<GlobalAction, bool> ActionRequested; public Func<GlobalAction, bool> ActionRequested;
public Func<GlobalAction, float, bool, bool> ScrollActionRequested; public Func<GlobalAction, float, bool, bool> ScrollActionRequested;
private ScheduledDelegate keyRepeat;
public bool OnPressed(KeyBindingPressEvent<GlobalAction> e) public bool OnPressed(KeyBindingPressEvent<GlobalAction> e)
{ {
switch (e.Action) switch (e.Action)
{ {
case GlobalAction.DecreaseVolume: case GlobalAction.DecreaseVolume:
case GlobalAction.IncreaseVolume: case GlobalAction.IncreaseVolume:
keyRepeat?.Cancel();
keyRepeat = this.BeginKeyRepeat(Scheduler, () => ActionRequested?.Invoke(e.Action), 150);
return true;
case GlobalAction.ToggleMute: case GlobalAction.ToggleMute:
case GlobalAction.NextVolumeMeter: case GlobalAction.NextVolumeMeter:
case GlobalAction.PreviousVolumeMeter: case GlobalAction.PreviousVolumeMeter:
@ -41,7 +33,6 @@ namespace osu.Game.Overlays.Volume
public void OnReleased(KeyBindingReleaseEvent<GlobalAction> e) public void OnReleased(KeyBindingReleaseEvent<GlobalAction> e)
{ {
keyRepeat?.Cancel();
} }
protected override bool OnScroll(ScrollEvent e) protected override bool OnScroll(ScrollEvent e)

View File

@ -168,6 +168,8 @@ namespace osu.Game.Rulesets.UI
public class RulesetKeyBindingContainer : DatabasedKeyBindingContainer<T> public class RulesetKeyBindingContainer : DatabasedKeyBindingContainer<T>
{ {
protected override bool HandleRepeats => false;
public RulesetKeyBindingContainer(RulesetInfo ruleset, int variant, SimultaneousBindingMode unique) public RulesetKeyBindingContainer(RulesetInfo ruleset, int variant, SimultaneousBindingMode unique)
: base(ruleset, variant, unique) : base(ruleset, variant, unique)
{ {

View File

@ -14,7 +14,6 @@ using osu.Framework.Threading;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Beatmaps.ControlPoints; using osu.Game.Beatmaps.ControlPoints;
using osu.Game.Configuration; using osu.Game.Configuration;
using osu.Game.Extensions;
using osu.Game.Input.Bindings; using osu.Game.Input.Bindings;
using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects;
@ -204,11 +203,11 @@ namespace osu.Game.Rulesets.UI.Scrolling
switch (e.Action) switch (e.Action)
{ {
case GlobalAction.IncreaseScrollSpeed: case GlobalAction.IncreaseScrollSpeed:
scheduleScrollSpeedAdjustment(1); AdjustScrollSpeed(1);
return true; return true;
case GlobalAction.DecreaseScrollSpeed: case GlobalAction.DecreaseScrollSpeed:
scheduleScrollSpeedAdjustment(-1); AdjustScrollSpeed(-1);
return true; return true;
} }
@ -223,12 +222,6 @@ namespace osu.Game.Rulesets.UI.Scrolling
scheduledScrollSpeedAdjustment = null; scheduledScrollSpeedAdjustment = null;
} }
private void scheduleScrollSpeedAdjustment(int amount)
{
scheduledScrollSpeedAdjustment?.Cancel();
scheduledScrollSpeedAdjustment = this.BeginKeyRepeat(Scheduler, () => AdjustScrollSpeed(amount));
}
private class LocalScrollingInfo : IScrollingInfo private class LocalScrollingInfo : IScrollingInfo
{ {
public IBindable<ScrollingDirection> Direction { get; } = new Bindable<ScrollingDirection>(); public IBindable<ScrollingDirection> Direction { get; } = new Bindable<ScrollingDirection>();

View File

@ -239,6 +239,9 @@ namespace osu.Game.Screens.Edit.Compose.Components
public bool OnPressed(KeyBindingPressEvent<PlatformAction> e) public bool OnPressed(KeyBindingPressEvent<PlatformAction> e)
{ {
if (e.Repeat)
return false;
switch (e.Action) switch (e.Action)
{ {
case PlatformAction.SelectAll: case PlatformAction.SelectAll:

View File

@ -393,6 +393,9 @@ namespace osu.Game.Screens.Edit
return true; return true;
case PlatformAction.Save: case PlatformAction.Save:
if (e.Repeat)
return false;
Save(); Save();
return true; return true;
} }
@ -457,6 +460,9 @@ namespace osu.Game.Screens.Edit
public bool OnPressed(KeyBindingPressEvent<GlobalAction> e) public bool OnPressed(KeyBindingPressEvent<GlobalAction> e)
{ {
if (e.Repeat)
return false;
switch (e.Action) switch (e.Action)
{ {
case GlobalAction.Back: case GlobalAction.Back:

View File

@ -220,6 +220,9 @@ namespace osu.Game.Screens.Menu
public bool OnPressed(KeyBindingPressEvent<GlobalAction> e) public bool OnPressed(KeyBindingPressEvent<GlobalAction> e)
{ {
if (e.Repeat)
return false;
switch (e.Action) switch (e.Action)
{ {
case GlobalAction.Back: case GlobalAction.Back:

View File

@ -21,6 +21,9 @@ namespace osu.Game.Screens.Menu
public bool OnPressed(KeyBindingPressEvent<GlobalAction> e) public bool OnPressed(KeyBindingPressEvent<GlobalAction> e)
{ {
if (e.Repeat)
return false;
if (e.Action == GlobalAction.Back) if (e.Action == GlobalAction.Back)
{ {
BeginConfirm(); BeginConfirm();

View File

@ -12,7 +12,6 @@ using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.Input.Bindings; using osu.Framework.Input.Bindings;
using osu.Framework.Input.Events; using osu.Framework.Input.Events;
using osu.Framework.Threading;
using osu.Game.Extensions; using osu.Game.Extensions;
using osu.Game.Graphics.Cursor; using osu.Game.Graphics.Cursor;
using osu.Game.Input.Bindings; using osu.Game.Input.Bindings;
@ -146,11 +145,11 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components
switch (e.Action) switch (e.Action)
{ {
case GlobalAction.SelectNext: case GlobalAction.SelectNext:
beginRepeatSelection(() => selectNext(1), e.Action); selectNext(1);
return true; return true;
case GlobalAction.SelectPrevious: case GlobalAction.SelectPrevious:
beginRepeatSelection(() => selectNext(-1), e.Action); selectNext(-1);
return true; return true;
} }
@ -159,40 +158,6 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components
public void OnReleased(KeyBindingReleaseEvent<GlobalAction> e) public void OnReleased(KeyBindingReleaseEvent<GlobalAction> e)
{ {
switch (e.Action)
{
case GlobalAction.SelectNext:
case GlobalAction.SelectPrevious:
endRepeatSelection(e.Action);
break;
}
}
private ScheduledDelegate repeatDelegate;
private object lastRepeatSource;
/// <summary>
/// Begin repeating the specified selection action.
/// </summary>
/// <param name="action">The action to perform.</param>
/// <param name="source">The source of the action. Used in conjunction with <see cref="endRepeatSelection"/> to only cancel the correct action (most recently pressed key).</param>
private void beginRepeatSelection(Action action, object source)
{
endRepeatSelection();
lastRepeatSource = source;
repeatDelegate = this.BeginKeyRepeat(Scheduler, action);
}
private void endRepeatSelection(object source = null)
{
// only the most recent source should be able to cancel the current action.
if (source != null && !EqualityComparer<object>.Default.Equals(lastRepeatSource, source))
return;
repeatDelegate?.Cancel();
repeatDelegate = null;
lastRepeatSource = null;
} }
private void selectNext(int direction) private void selectNext(int direction)

View File

@ -134,6 +134,9 @@ namespace osu.Game.Screens.OnlinePlay.Lounge
public bool OnPressed(KeyBindingPressEvent<GlobalAction> e) public bool OnPressed(KeyBindingPressEvent<GlobalAction> e)
{ {
if (e.Repeat)
return false;
if (SelectedRoom.Value != Room) if (SelectedRoom.Value != Room)
return false; return false;

View File

@ -19,6 +19,9 @@ namespace osu.Game.Screens.OnlinePlay.Match.Components
public bool OnPressed(KeyBindingPressEvent<PlatformAction> e) public bool OnPressed(KeyBindingPressEvent<PlatformAction> e)
{ {
if (e.Repeat)
return false;
if (!Enabled.Value) if (!Enabled.Value)
return false; return false;

View File

@ -65,6 +65,9 @@ namespace osu.Game.Screens.OnlinePlay.Match.Components
public bool OnPressed(KeyBindingPressEvent<GlobalAction> e) public bool OnPressed(KeyBindingPressEvent<GlobalAction> e)
{ {
if (e.Repeat)
return false;
switch (e.Action) switch (e.Action)
{ {
case GlobalAction.Select: case GlobalAction.Select:

View File

@ -208,6 +208,9 @@ namespace osu.Game.Screens.Play.HUD
public bool OnPressed(KeyBindingPressEvent<GlobalAction> e) public bool OnPressed(KeyBindingPressEvent<GlobalAction> e)
{ {
if (e.Repeat)
return false;
switch (e.Action) switch (e.Action)
{ {
case GlobalAction.Back: case GlobalAction.Back:

View File

@ -283,6 +283,9 @@ namespace osu.Game.Screens.Play
public bool OnPressed(KeyBindingPressEvent<GlobalAction> e) public bool OnPressed(KeyBindingPressEvent<GlobalAction> e)
{ {
if (e.Repeat)
return false;
switch (e.Action) switch (e.Action)
{ {
case GlobalAction.HoldForHUD: case GlobalAction.HoldForHUD:

View File

@ -12,6 +12,9 @@ namespace osu.Game.Screens.Play
{ {
public bool OnPressed(KeyBindingPressEvent<GlobalAction> e) public bool OnPressed(KeyBindingPressEvent<GlobalAction> e)
{ {
if (e.Repeat)
return false;
if (e.Action != GlobalAction.QuickExit) return false; if (e.Action != GlobalAction.QuickExit) return false;
BeginConfirm(); BeginConfirm();

View File

@ -12,6 +12,9 @@ namespace osu.Game.Screens.Play
{ {
public bool OnPressed(KeyBindingPressEvent<GlobalAction> e) public bool OnPressed(KeyBindingPressEvent<GlobalAction> e)
{ {
if (e.Repeat)
return false;
if (e.Action != GlobalAction.QuickRetry) return false; if (e.Action != GlobalAction.QuickRetry) return false;
BeginConfirm(); BeginConfirm();

View File

@ -7,9 +7,7 @@ using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using osu.Framework.Input.Bindings; using osu.Framework.Input.Bindings;
using osu.Framework.Input.Events; using osu.Framework.Input.Events;
using osu.Framework.Threading;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Extensions;
using osu.Game.Input.Bindings; using osu.Game.Input.Bindings;
using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects;
@ -48,8 +46,6 @@ namespace osu.Game.Screens.Play
protected override ResultsScreen CreateResults(ScoreInfo score) => new SoloResultsScreen(score, false); protected override ResultsScreen CreateResults(ScoreInfo score) => new SoloResultsScreen(score, false);
private ScheduledDelegate keyboardSeekDelegate;
public bool OnPressed(KeyBindingPressEvent<GlobalAction> e) public bool OnPressed(KeyBindingPressEvent<GlobalAction> e)
{ {
const double keyboard_seek_amount = 5000; const double keyboard_seek_amount = 5000;
@ -57,13 +53,11 @@ namespace osu.Game.Screens.Play
switch (e.Action) switch (e.Action)
{ {
case GlobalAction.SeekReplayBackward: case GlobalAction.SeekReplayBackward:
keyboardSeekDelegate?.Cancel(); keyboardSeek(-1);
keyboardSeekDelegate = this.BeginKeyRepeat(Scheduler, () => keyboardSeek(-1));
return true; return true;
case GlobalAction.SeekReplayForward: case GlobalAction.SeekReplayForward:
keyboardSeekDelegate?.Cancel(); keyboardSeek(1);
keyboardSeekDelegate = this.BeginKeyRepeat(Scheduler, () => keyboardSeek(1));
return true; return true;
case GlobalAction.TogglePauseReplay: case GlobalAction.TogglePauseReplay:
@ -86,13 +80,6 @@ namespace osu.Game.Screens.Play
public void OnReleased(KeyBindingReleaseEvent<GlobalAction> e) public void OnReleased(KeyBindingReleaseEvent<GlobalAction> e)
{ {
switch (e.Action)
{
case GlobalAction.SeekReplayBackward:
case GlobalAction.SeekReplayForward:
keyboardSeekDelegate?.Cancel();
break;
}
} }
} }
} }

View File

@ -146,6 +146,9 @@ namespace osu.Game.Screens.Play
public bool OnPressed(KeyBindingPressEvent<GlobalAction> e) public bool OnPressed(KeyBindingPressEvent<GlobalAction> e)
{ {
if (e.Repeat)
return false;
switch (e.Action) switch (e.Action)
{ {
case GlobalAction.SkipCutscene: case GlobalAction.SkipCutscene:

View File

@ -330,6 +330,9 @@ namespace osu.Game.Screens.Ranking
public bool OnPressed(KeyBindingPressEvent<GlobalAction> e) public bool OnPressed(KeyBindingPressEvent<GlobalAction> e)
{ {
if (e.Repeat)
return false;
switch (e.Action) switch (e.Action)
{ {
case GlobalAction.Select: case GlobalAction.Select:

View File

@ -18,7 +18,6 @@ using osu.Framework.Threading;
using osu.Framework.Utils; using osu.Framework.Utils;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Configuration; using osu.Game.Configuration;
using osu.Game.Extensions;
using osu.Game.Graphics.Containers; using osu.Game.Graphics.Containers;
using osu.Game.Graphics.Cursor; using osu.Game.Graphics.Cursor;
using osu.Game.Input.Bindings; using osu.Game.Input.Bindings;
@ -479,42 +478,27 @@ namespace osu.Game.Screens.Select
switch (e.Key) switch (e.Key)
{ {
case Key.Left: case Key.Left:
if (!e.Repeat) SelectNext(-1);
beginRepeatSelection(() => SelectNext(-1), e.Key);
return true; return true;
case Key.Right: case Key.Right:
if (!e.Repeat) SelectNext();
beginRepeatSelection(() => SelectNext(), e.Key);
return true; return true;
} }
return false; return false;
} }
protected override void OnKeyUp(KeyUpEvent e)
{
switch (e.Key)
{
case Key.Left:
case Key.Right:
endRepeatSelection(e.Key);
break;
}
base.OnKeyUp(e);
}
public bool OnPressed(KeyBindingPressEvent<GlobalAction> e) public bool OnPressed(KeyBindingPressEvent<GlobalAction> e)
{ {
switch (e.Action) switch (e.Action)
{ {
case GlobalAction.SelectNext: case GlobalAction.SelectNext:
beginRepeatSelection(() => SelectNext(1, false), e.Action); SelectNext(1, false);
return true; return true;
case GlobalAction.SelectPrevious: case GlobalAction.SelectPrevious:
beginRepeatSelection(() => SelectNext(-1, false), e.Action); SelectNext(-1, false);
return true; return true;
} }
@ -523,40 +507,6 @@ namespace osu.Game.Screens.Select
public void OnReleased(KeyBindingReleaseEvent<GlobalAction> e) public void OnReleased(KeyBindingReleaseEvent<GlobalAction> e)
{ {
switch (e.Action)
{
case GlobalAction.SelectNext:
case GlobalAction.SelectPrevious:
endRepeatSelection(e.Action);
break;
}
}
private ScheduledDelegate repeatDelegate;
private object lastRepeatSource;
/// <summary>
/// Begin repeating the specified selection action.
/// </summary>
/// <param name="action">The action to perform.</param>
/// <param name="source">The source of the action. Used in conjunction with <see cref="endRepeatSelection"/> to only cancel the correct action (most recently pressed key).</param>
private void beginRepeatSelection(Action action, object source)
{
endRepeatSelection();
lastRepeatSource = source;
repeatDelegate = this.BeginKeyRepeat(Scheduler, action);
}
private void endRepeatSelection(object source = null)
{
// only the most recent source should be able to cancel the current action.
if (source != null && !EqualityComparer<object>.Default.Equals(lastRepeatSource, source))
return;
repeatDelegate?.Cancel();
repeatDelegate = null;
lastRepeatSource = null;
} }
#endregion #endregion

View File

@ -821,6 +821,9 @@ namespace osu.Game.Screens.Select
public virtual bool OnPressed(KeyBindingPressEvent<GlobalAction> e) public virtual bool OnPressed(KeyBindingPressEvent<GlobalAction> e)
{ {
if (e.Repeat)
return false;
if (!this.IsCurrentScreen()) return false; if (!this.IsCurrentScreen()) return false;
switch (e.Action) switch (e.Action)

View File

@ -36,7 +36,7 @@
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference> </PackageReference>
<PackageReference Include="Realm" Version="10.6.0" /> <PackageReference Include="Realm" Version="10.6.0" />
<PackageReference Include="ppy.osu.Framework" Version="2021.1108.0" /> <PackageReference Include="ppy.osu.Framework" Version="2021.1118.0" />
<PackageReference Include="ppy.osu.Game.Resources" Version="2021.1112.0" /> <PackageReference Include="ppy.osu.Game.Resources" Version="2021.1112.0" />
<PackageReference Include="Sentry" Version="3.10.0" /> <PackageReference Include="Sentry" Version="3.10.0" />
<PackageReference Include="SharpCompress" Version="0.30.0" /> <PackageReference Include="SharpCompress" Version="0.30.0" />

View File

@ -70,7 +70,7 @@
<Reference Include="System.Net.Http" /> <Reference Include="System.Net.Http" />
</ItemGroup> </ItemGroup>
<ItemGroup Label="Package References"> <ItemGroup Label="Package References">
<PackageReference Include="ppy.osu.Framework.iOS" Version="2021.1108.0" /> <PackageReference Include="ppy.osu.Framework.iOS" Version="2021.1118.0" />
<PackageReference Include="ppy.osu.Game.Resources" Version="2021.1112.0" /> <PackageReference Include="ppy.osu.Game.Resources" Version="2021.1112.0" />
</ItemGroup> </ItemGroup>
<!-- See https://github.com/dotnet/runtime/issues/35988 (can be removed after Xamarin uses net5.0 / net6.0) --> <!-- See https://github.com/dotnet/runtime/issues/35988 (can be removed after Xamarin uses net5.0 / net6.0) -->
@ -93,7 +93,7 @@
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.2.6" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.2.6" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="2.2.6" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="2.2.6" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" /> <PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="ppy.osu.Framework" Version="2021.1108.0" /> <PackageReference Include="ppy.osu.Framework" Version="2021.1118.0" />
<PackageReference Include="SharpCompress" Version="0.30.0" /> <PackageReference Include="SharpCompress" Version="0.30.0" />
<PackageReference Include="NUnit" Version="3.13.2" /> <PackageReference Include="NUnit" Version="3.13.2" />
<PackageReference Include="SharpRaven" Version="2.4.0" /> <PackageReference Include="SharpRaven" Version="2.4.0" />