public bool HandleKeyEvent(string name, Keys?key, char?ch, KeyboardModifiers?modifiers = null, bool isVirtual = false, bool isRepeat = false) { // HACK to simplify writing input sources if (name == null) { return(false); } // HACK: Ensure that key repeat doesn't continue if the original repeat target becomes defocused var suppressRepeat = isRepeat && (LastNonRepeatKeyPressTarget != Focused); var evt = new KeyEventArgs { Context = this, Modifiers = modifiers ?? CurrentModifiers, Key = key, Char = ch, IsVirtualInput = isVirtual, IsRepeat = isRepeat && !suppressRepeat }; if (name == UIEvents.KeyDown) { if ((key == Keys.LeftAlt) || (key == Keys.RightAlt)) { HasPressedKeySincePressingAlt = false; } else if (key == Keys.Escape) { AcceleratorOverlayVisible = false; } else if (key == Keys.Tab) { } else if (key.HasValue && !ModifierKeys.Contains(key.Value)) { if (evt.Modifiers.Alt) { HasPressedKeySincePressingAlt = true; } AcceleratorOverlayVisible = false; } } else if (name == UIEvents.KeyUp) { if ((key == Keys.LeftAlt) || (key == Keys.RightAlt)) { if (!HasPressedKeySincePressingAlt) { AcceleratorOverlayVisible = !AcceleratorOverlayVisible; } } } if ((name == UIEvents.KeyPress) && !isRepeat) { LastNonRepeatKeyPressTarget = Focused; } // FIXME: Suppress events with a char if the target doesn't accept text input? if (FireEvent(name, Focused, evt, filtersOnly: suppressRepeat)) { return(true); } bool needsToClearFocus = false; if (name == UIEvents.KeyPress) { switch (key) { case Keys.Escape: needsToClearFocus = true; break; case Keys.Tab: int tabDelta = evt.Modifiers.Shift ? -1 : 1; return(RotateFocus(topLevel: evt.Modifiers.Control, delta: tabDelta, isUserInitiated: true)); case Keys.Space: if (Focused?.IsValidMouseInputTarget == true) { return(FireSyntheticClick(Focused)); } break; } } if (suppressRepeat) { return(false); } var activeModal = ActiveModal; if ((activeModal != null) && activeModal.OnUnhandledKeyEvent(name, evt)) { return(true); } // FIXME: Allow OnKeyEvent to block this? if (needsToClearFocus) { Focused = null; } if (OnKeyEvent != null) { return(OnKeyEvent(name, key, ch)); } return(false); }