Skip to content

ButtonDownInputQueue includes sibling drawables to the one handling it #3625

Description

@frenzibyte

As the title says, the ButtonDownInputQueue in ButtonEventManager includes sibling drawables to the one handling it, which is probably incorrect as the down queue should only include the drawable handling the event and its children that are built to the queue.

I presume the logic behind this:

var count = inputQueue.IndexOf(handledBy) + 1;
inputQueue.RemoveRange(count, inputQueue.Count - count);

is meant to allow children to receive click events when their parent has handled a mouse button down event, so removing this and letting only the handled drawable to be in the queue will not work well. (osu!lazer becomes unplayable from testing)

Here's a simple reproducing (demonstrating) example:

Children = new[]
{
    new KeyEventHandler(Key.A),
    new KeyEventHandler(Key.B),
    new KeyEventHandler(Key.C),    
};

private class KeyEventHandler : Component
{
    override OnKeyDown(KeyDownEvent e) => e.Key == associatedKey;

    override OnKeyUp(KeyUpEvent e) => Logger.Log($"Receptor{ChildID}: Key {e.Key} has been released");
}

where it would log (with written comments):

Receptor3: Key A has been released // (didn't handle and yet received)
Receptor2: Key A has been released // (didn't handle and yet received)
Receptor1: Key A has been released // (correctly received)
Receptor3: Key B has been released // (didn't handle and yet received)
Receptor2: Key B has been released // (correctly received)
Receptor3: Key C has been released // (correctly received)

Here's also a test case attachable to KeyboardInputTest.cs that would log what the receptor received, same as above. (requires some minor changes to declaration of KeyDown and KeyUp to work).


I've tried fixing this by doing some simple algorithm to cut siblings / ancestors of the handler from above, but it turns out to be impossible to do as there's no simple way to tell if a drawable is an ancestor / sibling to another.

So as per above, the only fix I'm finding here is by introducing something like a ParentDepth (definitely needs another name) that provides how deep the drawable is in the hierarchy in comparison to another, open for suggestions if I completely missed something that can fix this.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions