private bool handleNewPressed(InputState state, InputKey newKey) { var pressedCombination = KeyCombination.FromInputState(state); bool handled = false; var newlyPressed = KeyBindings.Except(pressedBindings).Where(m => m.KeyCombination.Keys.Contains(newKey) && // only handle bindings matching current key (not required for correct logic) m.KeyCombination.IsPressed(pressedCombination)); if (isModifier(newKey)) { // if the current key pressed was a modifier, only handle modifier-only bindings. newlyPressed = newlyPressed.Where(b => b.KeyCombination.Keys.All(isModifier)); } // we want to always handle bindings with more keys before bindings with less. newlyPressed = newlyPressed.OrderByDescending(b => b.KeyCombination.Keys.Count()).ToList(); pressedBindings.AddRange(newlyPressed); foreach (var newBinding in newlyPressed) { handled |= PropagatePressed(KeyBindingInputQueue, newBinding.GetAction <T>()); // 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); }
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) { handled |= PropagatePressed(KeyBindingInputQueue, 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); }
private bool handleNewPressed(InputState state, InputKey newKey, bool repeat) { var pressedCombination = KeyCombination.FromInputState(state); // MouseWheelUp/Down cannot be obtained from KeyCombination.FromInputState so we manually add that here. if (!pressedCombination.Keys.Contains(newKey)) { pressedCombination = new KeyCombination(pressedCombination.Keys.Concat(new[] { newKey })); } bool handled = false; var bindings = repeat ? KeyBindings : KeyBindings.Except(pressedBindings); 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, simultaneousMode == SimultaneousBindingMode.NoneExact)); if (isModifier(newKey)) { // if the current key pressed was a modifier, only handle modifier-only bindings. newlyPressed = newlyPressed.Where(b => b.KeyCombination.Keys.All(isModifier)); } // 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.NoneExact) { // 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, simultaneousMode == SimultaneousBindingMode.NoneExact))) { releasePressedActions(); } } foreach (var newBinding in newlyPressed) { handled |= PropagatePressed(KeyBindingInputQueue, newBinding.GetAction <T>()); // we only want to handle the first valid binding (the one with the most keys) in non-simultaneous mode. if ((simultaneousMode == SimultaneousBindingMode.None || simultaneousMode == SimultaneousBindingMode.NoneExact) && handled) { break; } } return(handled); }
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.Length).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(); } List <Drawable> inputQueue = getInputQueue(newBinding, true); Drawable handledBy = PropagatePressed(inputQueue, 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). var count = inputQueue.IndexOf(handledBy) + 1; inputQueue.RemoveRange(count, inputQueue.Count - count); handled = true; } // 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); }
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); }