mirror of https://github.com/ppy/osu
Remove global action container input queue workaround
As described in #24248, the workaround employed by `GlobalActionContainer`, wherein it tried to handle actions with priority before its children by being placed in front of the children and not _actually containing_ said children, is blocking the resolution of some rather major input handling issues that allow key releases to be received by deparented drawables. To resolve, migrate `GlobalActionContainer` to use `Prioritised`, which can be done without regressing certain mouse button flows after ppy/osu-framework#5966.
This commit is contained in:
parent
aa5680a8aa
commit
5454d1caa1
|
@ -3,33 +3,26 @@
|
||||||
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using osu.Framework.Graphics;
|
|
||||||
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.Localisation;
|
using osu.Framework.Localisation;
|
||||||
using osu.Game.Localisation;
|
using osu.Game.Localisation;
|
||||||
|
|
||||||
namespace osu.Game.Input.Bindings
|
namespace osu.Game.Input.Bindings
|
||||||
{
|
{
|
||||||
public partial class GlobalActionContainer : DatabasedKeyBindingContainer<GlobalAction>, IHandleGlobalKeyboardInput
|
public partial class GlobalActionContainer : DatabasedKeyBindingContainer<GlobalAction>, IHandleGlobalKeyboardInput, IKeyBindingHandler<GlobalAction>
|
||||||
{
|
{
|
||||||
private readonly Drawable? handler;
|
private readonly IKeyBindingHandler<GlobalAction>? handler;
|
||||||
|
|
||||||
private InputManager? parentInputManager;
|
|
||||||
|
|
||||||
public GlobalActionContainer(OsuGameBase? game)
|
public GlobalActionContainer(OsuGameBase? game)
|
||||||
: base(matchingMode: KeyCombinationMatchingMode.Modifiers)
|
: base(matchingMode: KeyCombinationMatchingMode.Modifiers)
|
||||||
{
|
{
|
||||||
if (game is IKeyBindingHandler<GlobalAction>)
|
if (game is IKeyBindingHandler<GlobalAction> h)
|
||||||
handler = game;
|
handler = h;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void LoadComplete()
|
protected override bool Prioritised => true;
|
||||||
{
|
|
||||||
base.LoadComplete();
|
|
||||||
|
|
||||||
parentInputManager = GetContainingInputManager();
|
|
||||||
}
|
|
||||||
|
|
||||||
// IMPORTANT: Take care when changing order of the items in the enumerable.
|
// IMPORTANT: Take care when changing order of the items in the enumerable.
|
||||||
// It is used to decide the order of precedence, with the earlier items having higher precedence.
|
// It is used to decide the order of precedence, with the earlier items having higher precedence.
|
||||||
|
@ -161,20 +154,9 @@ protected override void LoadComplete()
|
||||||
new KeyBinding(InputKey.F3, GlobalAction.MusicPlay)
|
new KeyBinding(InputKey.F3, GlobalAction.MusicPlay)
|
||||||
};
|
};
|
||||||
|
|
||||||
protected override IEnumerable<Drawable> KeyBindingInputQueue
|
public bool OnPressed(KeyBindingPressEvent<GlobalAction> e) => handler?.OnPressed(e) == true;
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
// To ensure the global actions are handled with priority, this GlobalActionContainer is actually placed after game content.
|
|
||||||
// It does not contain children as expected, so we need to forward the NonPositionalInputQueue from the parent input manager to correctly
|
|
||||||
// allow the whole game to handle these actions.
|
|
||||||
|
|
||||||
// An eventual solution to this hack is to create localised action containers for individual components like SongSelect, but this will take some rearranging.
|
public void OnReleased(KeyBindingReleaseEvent<GlobalAction> e) => handler?.OnReleased(e);
|
||||||
var inputQueue = parentInputManager?.NonPositionalInputQueue ?? base.KeyBindingInputQueue;
|
|
||||||
|
|
||||||
return handler != null ? inputQueue.Prepend(handler) : inputQueue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum GlobalAction
|
public enum GlobalAction
|
||||||
|
|
|
@ -392,17 +392,18 @@ private void load(ReadableKeyCombinationProvider keyCombinationProvider, Framewo
|
||||||
{
|
{
|
||||||
SafeAreaOverrideEdges = SafeAreaOverrideEdges,
|
SafeAreaOverrideEdges = SafeAreaOverrideEdges,
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
Child = CreateScalingContainer().WithChildren(new Drawable[]
|
Child = CreateScalingContainer().WithChild(globalBindings = new GlobalActionContainer(this)
|
||||||
{
|
{
|
||||||
(GlobalCursorDisplay = new GlobalCursorDisplay
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both
|
(GlobalCursorDisplay = new GlobalCursorDisplay
|
||||||
}).WithChild(content = new OsuTooltipContainer(GlobalCursorDisplay.MenuCursor)
|
{
|
||||||
{
|
RelativeSizeAxes = Axes.Both
|
||||||
RelativeSizeAxes = Axes.Both
|
}).WithChild(content = new OsuTooltipContainer(GlobalCursorDisplay.MenuCursor)
|
||||||
}),
|
{
|
||||||
// to avoid positional input being blocked by children, ensure the GlobalActionContainer is above everything.
|
RelativeSizeAxes = Axes.Both
|
||||||
globalBindings = new GlobalActionContainer(this)
|
}),
|
||||||
|
}
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -57,7 +57,13 @@ protected OsuManualInputManagerTestScene()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CreateNestedActionContainer)
|
if (CreateNestedActionContainer)
|
||||||
mainContent.Add(new GlobalActionContainer(null));
|
{
|
||||||
|
var globalActionContainer = new GlobalActionContainer(null)
|
||||||
|
{
|
||||||
|
Child = mainContent
|
||||||
|
};
|
||||||
|
mainContent = globalActionContainer;
|
||||||
|
}
|
||||||
|
|
||||||
base.Content.AddRange(new Drawable[]
|
base.Content.AddRange(new Drawable[]
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue