protected override bool OnJoystickRelease(InputState state, JoystickEventArgs args) => handleNewReleased(state, KeyCombination.FromJoystickButton(args.Button));
protected override bool OnKeyUp(InputState state, KeyUpEventArgs args) => handleNewReleased(state, KeyCombination.FromKey(args.Key));
protected override bool OnJoystickPress(InputState state, JoystickEventArgs args) => handleNewPressed(state, KeyCombination.FromJoystickButton(args.Button), false);
protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) => handleNewPressed(state, KeyCombination.FromMouseButton(args.Button), false);
protected override bool OnMouseUp(InputState state, MouseUpEventArgs args) => handleNewReleased(state, KeyCombination.FromMouseButton(args.Button));
protected override bool Handle(UIEvent e) { var state = e.CurrentState; switch (e) { case MouseDownEvent mouseDown: return(handleNewPressed(state, KeyCombination.FromMouseButton(mouseDown.Button))); case MouseUpEvent mouseUp: handleNewReleased(state, KeyCombination.FromMouseButton(mouseUp.Button)); return(false); case KeyDownEvent keyDown: if (keyDown.Repeat) { return(handleRepeat(state)); } else { return(handleNewPressed(state, KeyCombination.FromKey(keyDown.Key))); } case KeyUpEvent keyUp: handleNewReleased(state, KeyCombination.FromKey(keyUp.Key)); return(false); case JoystickPressEvent joystickPress: return(handleNewPressed(state, KeyCombination.FromJoystickButton(joystickPress.Button))); case JoystickReleaseEvent joystickRelease: handleNewReleased(state, KeyCombination.FromJoystickButton(joystickRelease.Button)); return(false); case MidiDownEvent midiDown: return(handleNewPressed(state, KeyCombination.FromMidiKey(midiDown.Key))); case MidiUpEvent midiUp: handleNewReleased(state, KeyCombination.FromMidiKey(midiUp.Key)); return(false); case TabletPenButtonPressEvent tabletPenButtonPress: return(handleNewPressed(state, KeyCombination.FromTabletPenButton(tabletPenButtonPress.Button))); case TabletPenButtonReleaseEvent tabletPenButtonRelease: handleNewReleased(state, KeyCombination.FromTabletPenButton(tabletPenButtonRelease.Button)); return(false); case TabletAuxiliaryButtonPressEvent tabletAuxiliaryButtonPress: return(handleNewPressed(state, KeyCombination.FromTabletAuxiliaryButton(tabletAuxiliaryButtonPress.Button))); case TabletAuxiliaryButtonReleaseEvent tabletAuxiliaryButtonRelease: handleNewReleased(state, KeyCombination.FromTabletAuxiliaryButton(tabletAuxiliaryButtonRelease.Button)); return(false); case ScrollEvent scroll: { var keys = KeyCombination.FromScrollDelta(scroll.ScrollDelta); bool handled = false; foreach (var key in keys) { handled |= handleNewPressed(state, key, scroll.ScrollDelta, scroll.IsPrecise); handleNewReleased(state, key); } return(handled); } } return(false); }
private bool handleNewPressed(InputState state, InputKey newKey, Vector2?scrollDelta = null, bool isPrecise = false) { pressedInputKeys.Add(newKey); float scrollAmount = getScrollAmount(newKey, scrollDelta); var pressedCombination = new KeyCombination(pressedInputKeys); bool handled = false; var bindings = KeyBindings?.Except(pressedBindings) ?? Enumerable.Empty <IKeyBinding>(); var newlyPressed = bindings.Where(m => m.KeyCombination.IsPressed(pressedCombination, matchingMode)); if (KeyCombination.IsModifierKey(newKey)) { // if the current key pressed was a modifier, only handle modifier-only bindings. // lambda expression is used so that the delegate is cached (see: https://github.com/dotnet/roslyn/issues/5835) newlyPressed = newlyPressed.Where(b => b.KeyCombination.Keys.All(key => KeyCombination.IsModifierKey(key))); } // we want to always handle bindings with more keys before bindings with less. newlyPressed = newlyPressed.OrderByDescending(b => b.KeyCombination.Keys.Length).ToList(); pressedBindings.AddRange(newlyPressed); // exact matching may result in no pressed (new or old) bindings, in which case we want to trigger releases for existing actions if (simultaneousMode == SimultaneousBindingMode.None && (matchingMode == KeyCombinationMatchingMode.Exact || matchingMode == KeyCombinationMatchingMode.Modifiers)) { // only want to release pressed actions if no existing bindings would still remain pressed if (pressedBindings.Count > 0 && !pressedBindings.Any(m => m.KeyCombination.IsPressed(pressedCombination, matchingMode))) { releasePressedActions(state); } } foreach (var newBinding in newlyPressed) { // we handled a new binding and there is an existing one. if we don't want concurrency, let's propagate a released event. if (simultaneousMode == SimultaneousBindingMode.None) { releasePressedActions(state); } List <Drawable> inputQueue = getInputQueue(newBinding, true); Drawable handledBy = PropagatePressed(inputQueue, state, newBinding.GetAction <T>(), scrollAmount, isPrecise); if (handledBy != null) { // only drawables up to the one that handled the press should handle the release, so remove all subsequent drawables from the queue (for future use). int count = inputQueue.IndexOf(handledBy) + 1; inputQueue.RemoveRange(count, inputQueue.Count - count); handled = true; } keyRepeatInputQueue = inputQueue; // we only want to handle the first valid binding (the one with the most keys) in non-simultaneous mode. if (simultaneousMode == SimultaneousBindingMode.None && handled) { break; } } return(handled); }
protected override bool Handle(UIEvent e) { switch (e) { case MouseDownEvent mouseDown: return(handleNewPressed(KeyCombination.FromMouseButton(mouseDown.Button), false)); case MouseUpEvent mouseUp: handleNewReleased(KeyCombination.FromMouseButton(mouseUp.Button)); return(false); case KeyDownEvent keyDown: if (keyDown.Repeat && !SendRepeats) { return(pressedBindings.Count > 0); } if (handleNewPressed(KeyCombination.FromKey(keyDown.Key), keyDown.Repeat)) { return(true); } return(false); case KeyUpEvent keyUp: handleNewReleased(KeyCombination.FromKey(keyUp.Key)); return(false); case JoystickPressEvent joystickPress: return(handleNewPressed(KeyCombination.FromJoystickButton(joystickPress.Button), false)); case JoystickReleaseEvent joystickRelease: handleNewReleased(KeyCombination.FromJoystickButton(joystickRelease.Button)); return(false); case MidiDownEvent midiDown: return(handleNewPressed(KeyCombination.FromMidiKey(midiDown.Key), false)); case MidiUpEvent midiUp: handleNewReleased(KeyCombination.FromMidiKey(midiUp.Key)); return(false); case TabletPenButtonPressEvent tabletPenButtonPress: return(handleNewPressed(KeyCombination.FromTabletPenButton(tabletPenButtonPress.Button), false)); case TabletPenButtonReleaseEvent tabletPenButtonRelease: handleNewReleased(KeyCombination.FromTabletPenButton(tabletPenButtonRelease.Button)); return(false); case TabletAuxiliaryButtonPressEvent tabletAuxiliaryButtonPress: return(handleNewPressed(KeyCombination.FromTabletAuxiliaryButton(tabletAuxiliaryButtonPress.Button), false)); case TabletAuxiliaryButtonReleaseEvent tabletAuxiliaryButtonRelease: handleNewReleased(KeyCombination.FromTabletAuxiliaryButton(tabletAuxiliaryButtonRelease.Button)); return(false); case ScrollEvent scroll: { var keys = KeyCombination.FromScrollDelta(scroll.ScrollDelta); bool handled = false; foreach (var key in keys) { handled |= handleNewPressed(key, false, scroll.ScrollDelta, scroll.IsPrecise); handleNewReleased(key); } return(handled); } } return(false); }
protected override bool PropagateKeyUp(IEnumerable <Drawable> drawables, InputState state, KeyUpEventArgs args) => base.PropagateKeyUp(drawables, state, args) || handleNewReleased(state, KeyCombination.FromKey(args.Key));
protected override bool PropagateKeyDown(IEnumerable <Drawable> drawables, InputState state, KeyDownEventArgs args) { if (args.Repeat) { if (pressedBindings.Count > 0) { return(true); } return(base.PropagateKeyDown(drawables, state, args)); } return(base.PropagateKeyDown(drawables, state, args) || handleNewPressed(state, KeyCombination.FromKey(args.Key))); }
protected override bool PropagateMouseUp(IEnumerable <Drawable> drawables, InputState state, MouseUpEventArgs args) => base.PropagateMouseUp(drawables, state, args) || handleNewReleased(state, KeyCombination.FromMouseButton(args.Button));
private bool handleNewPressed(InputState state, InputKey newKey, bool repeat, Vector2?scrollDelta = null, bool isPrecise = false) { float scrollAmount = 0; if (newKey == InputKey.MouseWheelUp) { scrollAmount = scrollDelta?.Y ?? 0; } else if (newKey == InputKey.MouseWheelDown) { scrollAmount = -(scrollDelta?.Y ?? 0); } var pressedCombination = KeyCombination.FromInputState(state, scrollDelta); bool handled = false; var bindings = (repeat ? KeyBindings : KeyBindings?.Except(pressedBindings)) ?? Enumerable.Empty <KeyBinding>(); var newlyPressed = bindings.Where(m => m.KeyCombination.Keys.Contains(newKey) && // only handle bindings matching current key (not required for correct logic) m.KeyCombination.IsPressed(pressedCombination, matchingMode)); if (KeyCombination.IsModifierKey(newKey)) { // if the current key pressed was a modifier, only handle modifier-only bindings. newlyPressed = newlyPressed.Where(b => b.KeyCombination.Keys.All(KeyCombination.IsModifierKey)); } // we want to always handle bindings with more keys before bindings with less. newlyPressed = newlyPressed.OrderByDescending(b => b.KeyCombination.Keys.Count()).ToList(); if (!repeat) { pressedBindings.AddRange(newlyPressed); } // exact matching may result in no pressed (new or old) bindings, in which case we want to trigger releases for existing actions if (simultaneousMode == SimultaneousBindingMode.None && (matchingMode == KeyCombinationMatchingMode.Exact || matchingMode == KeyCombinationMatchingMode.Modifiers)) { // only want to release pressed actions if no existing bindings would still remain pressed if (pressedBindings.Count > 0 && !pressedBindings.Any(m => m.KeyCombination.IsPressed(pressedCombination, matchingMode))) { releasePressedActions(); } } foreach (var newBinding in newlyPressed) { // we handled a new binding and there is an existing one. if we don't want concurrency, let's propagate a released event. if (simultaneousMode == SimultaneousBindingMode.None) { releasePressedActions(); } handled |= PropagatePressed(getInputQueue(newBinding, true), newBinding.GetAction <T>(), scrollAmount, isPrecise); // we only want to handle the first valid binding (the one with the most keys) in non-simultaneous mode. if (simultaneousMode == SimultaneousBindingMode.None && handled) { break; } } return(handled); }