private void PreProcessInput(object sender, PreProcessInputEventArgs e) { RawKeyboardInputReport keyboardInput = ExtractRawKeyboardInputReport(e, InputManager.PreviewInputReportEvent); if (keyboardInput != null) { // Claim the input for the keyboard. e.StagingItem.Input.Device = this; } }
private RawKeyboardInputReport ExtractRawKeyboardInputReport(NotifyInputEventArgs e, RoutedEvent Event) { RawKeyboardInputReport keyboardInput = null; InputReportEventArgs input = e.StagingItem.Input as InputReportEventArgs; if (input != null) { if (input.Report.Type == InputType.Keyboard && input.RoutedEvent == Event) { keyboardInput = input.Report as RawKeyboardInputReport; } } return(keyboardInput); }
private void PostProcessInput(object sender, ProcessInputEventArgs e) { // PreviewKeyDown --> KeyDown if (e.StagingItem.Input.RoutedEvent == Keyboard.PreviewKeyDownEvent) { CheckForDisconnectedFocus(); if (!e.StagingItem.Input.Handled) { KeyEventArgs previewKeyDown = (KeyEventArgs)e.StagingItem.Input; // Dig out the real key. bool isSystemKey = false; bool isImeProcessed = false; bool isDeadCharProcessed = false; Key key = previewKeyDown.Key; if (key == Key.System) { isSystemKey = true; key = previewKeyDown.RealKey; } else if (key == Key.ImeProcessed) { isImeProcessed = true; key = previewKeyDown.RealKey; } else if (key == Key.DeadCharProcessed) { isDeadCharProcessed = true; key = previewKeyDown.RealKey; } KeyEventArgs keyDown = new KeyEventArgs(this, previewKeyDown.UnsafeInputSource, previewKeyDown.Timestamp, key); keyDown.SetRepeat(previewKeyDown.IsRepeat); // Mark the new event as SystemKey as appropriate. if (isSystemKey) { keyDown.MarkSystem(); } else if (isImeProcessed) { // Mark the new event as ImeProcessed as appropriate. keyDown.MarkImeProcessed(); } else if (isDeadCharProcessed) { keyDown.MarkDeadCharProcessed(); } keyDown.RoutedEvent = Keyboard.KeyDownEvent; keyDown.ScanCode = previewKeyDown.ScanCode; keyDown.IsExtendedKey = previewKeyDown.IsExtendedKey; e.PushInput(keyDown, e.StagingItem); } } // PreviewKeyUp --> KeyUp if (e.StagingItem.Input.RoutedEvent == Keyboard.PreviewKeyUpEvent) { CheckForDisconnectedFocus(); if (!e.StagingItem.Input.Handled) { KeyEventArgs previewKeyUp = (KeyEventArgs)e.StagingItem.Input; // Dig out the real key. bool isSystemKey = false; bool isImeProcessed = false; bool isDeadCharProcessed = false; Key key = previewKeyUp.Key; if (key == Key.System) { isSystemKey = true; key = previewKeyUp.RealKey; } else if (key == Key.ImeProcessed) { isImeProcessed = true; key = previewKeyUp.RealKey; } else if (key == Key.DeadCharProcessed) { isDeadCharProcessed = true; key = previewKeyUp.RealKey; } KeyEventArgs keyUp = new KeyEventArgs(this, previewKeyUp.UnsafeInputSource, previewKeyUp.Timestamp, key); // Mark the new event as SystemKey as appropriate. if (isSystemKey) { keyUp.MarkSystem(); } else if (isImeProcessed) { // Mark the new event as ImeProcessed as appropriate. keyUp.MarkImeProcessed(); } else if (isDeadCharProcessed) { keyUp.MarkDeadCharProcessed(); } keyUp.RoutedEvent = Keyboard.KeyUpEvent; keyUp.ScanCode = previewKeyUp.ScanCode; keyUp.IsExtendedKey = previewKeyUp.IsExtendedKey; e.PushInput(keyUp, e.StagingItem); } } RawKeyboardInputReport keyboardInput = ExtractRawKeyboardInputReport(e, InputManager.InputReportEvent); if (keyboardInput != null) { CheckForDisconnectedFocus(); if (!e.StagingItem.Input.Handled) { // In general, this is where we promote the non-redundant // reported actions to our premier events. RawKeyboardActions actions = GetNonRedundantActions(e); // Raw --> PreviewKeyDown if ((actions & RawKeyboardActions.KeyDown) == RawKeyboardActions.KeyDown) { Key key = (Key)e.StagingItem.GetData(_tagKey); if (key != Key.None) { KeyEventArgs previewKeyDown = new KeyEventArgs(this, keyboardInput.InputSource, keyboardInput.Timestamp, key); ScanCode scanCode = (ScanCode)e.StagingItem.GetData(_tagScanCode); previewKeyDown.ScanCode = scanCode.Code; previewKeyDown.IsExtendedKey = scanCode.IsExtended; if (keyboardInput.IsSystemKey) { previewKeyDown.MarkSystem(); } previewKeyDown.RoutedEvent = Keyboard.PreviewKeyDownEvent; e.PushInput(previewKeyDown, e.StagingItem); } } // Raw --> PreviewKeyUp if ((actions & RawKeyboardActions.KeyUp) == RawKeyboardActions.KeyUp) { Key key = (Key)e.StagingItem.GetData(_tagKey); if (key != Key.None) { KeyEventArgs previewKeyUp = new KeyEventArgs(this, keyboardInput.InputSource, keyboardInput.Timestamp, key); ScanCode scanCode = (ScanCode)e.StagingItem.GetData(_tagScanCode); previewKeyUp.ScanCode = scanCode.Code; previewKeyUp.IsExtendedKey = scanCode.IsExtended; if (keyboardInput.IsSystemKey) { previewKeyUp.MarkSystem(); } previewKeyUp.RoutedEvent = Keyboard.PreviewKeyUpEvent; e.PushInput(previewKeyUp, e.StagingItem); } } } // Deactivate if ((keyboardInput.Actions & RawKeyboardActions.Deactivate) == RawKeyboardActions.Deactivate) { if (IsActive) { _activeSource = null; // Even if handled, a keyboard deactivate results in a lost focus. ChangeFocus(null, e.StagingItem.Input.Timestamp); } } } }
private void PreNotifyInput(object sender, NotifyInputEventArgs e) { RawKeyboardInputReport keyboardInput = ExtractRawKeyboardInputReport(e, InputManager.PreviewInputReportEvent); if (keyboardInput != null) { CheckForDisconnectedFocus(); // Activation // // MITIGATION: KEYBOARD_STATE_OUT_OF_SYNC // // It is very important that we allow multiple activate events. // This is how we deal with the fact that Win32 sometimes sends // us a WM_SETFOCUS message BEFORE it has updated it's internal // internal keyboard state information. When we get the // WM_SETFOCUS message, we activate the keyboard with the // keyboard state (even though it could be wrong). Then when // we get the first "real" keyboard input event, we activate // the keyboard again, since Win32 will have updated the // keyboard state correctly by then. // if ((keyboardInput.Actions & RawKeyboardActions.Activate) == RawKeyboardActions.Activate) { //if active source is null, no need to do special-case handling if (_activeSource == null) { // we are now active. _activeSource = new SecurityCriticalDataClass <PresentationSource>(keyboardInput.InputSource); } else if (_activeSource.Value != keyboardInput.InputSource) { IKeyboardInputProvider toDeactivate = _activeSource.Value.GetInputProvider(typeof(KeyboardDevice)) as IKeyboardInputProvider; // we are now active. _activeSource = new SecurityCriticalDataClass <PresentationSource>(keyboardInput.InputSource); if (toDeactivate != null) { toDeactivate.NotifyDeactivate(); } } } // Generally, we need to check against redundant actions. // We never prevet the raw event from going through, but we // will only generate the high-level events for non-redundant // actions. We store the set of non-redundant actions in // the dictionary of this event. // If the input is reporting a key down, the action is never // considered redundant. if ((keyboardInput.Actions & RawKeyboardActions.KeyDown) == RawKeyboardActions.KeyDown) { RawKeyboardActions actions = GetNonRedundantActions(e); actions |= RawKeyboardActions.KeyDown; e.StagingItem.SetData(_tagNonRedundantActions, actions); // Pass along the key that was pressed, and update our state. Key key = KeyInterop.KeyFromVirtualKey(keyboardInput.VirtualKey); e.StagingItem.SetData(_tagKey, key); e.StagingItem.SetData(_tagScanCode, new ScanCode(keyboardInput.ScanCode, keyboardInput.IsExtendedKey)); // Tell the InputManager that the MostRecentDevice is us. if (_inputManager != null) { _inputManager.Value.MostRecentInputDevice = this; } } // We are missing detection for redundant ups if ((keyboardInput.Actions & RawKeyboardActions.KeyUp) == RawKeyboardActions.KeyUp) { RawKeyboardActions actions = GetNonRedundantActions(e); actions |= RawKeyboardActions.KeyUp; e.StagingItem.SetData(_tagNonRedundantActions, actions); // Pass along the key that was pressed, and update our state. Key key = KeyInterop.KeyFromVirtualKey(keyboardInput.VirtualKey); e.StagingItem.SetData(_tagKey, key); e.StagingItem.SetData(_tagScanCode, new ScanCode(keyboardInput.ScanCode, keyboardInput.IsExtendedKey)); // Tell the InputManager that the MostRecentDevice is us. if (_inputManager != null) { _inputManager.Value.MostRecentInputDevice = this; } } } // On KeyDown, we might need to set the Repeat flag if (e.StagingItem.Input.RoutedEvent == Keyboard.PreviewKeyDownEvent) { CheckForDisconnectedFocus(); KeyEventArgs args = (KeyEventArgs)e.StagingItem.Input; // Is this the same as the previous key? (Look at the real key, e.g. TextManager // might have changed args.Key it to Key.TextInput.) if (_previousKey == args.RealKey) { // Yes, this is a repeat (we got the keydown for it twice, with no KeyUp in between) args.SetRepeat(true); } // Otherwise, keep this key to check against next time. else { _previousKey = args.RealKey; args.SetRepeat(false); } } // On KeyUp, we clear Repeat flag else if (e.StagingItem.Input.RoutedEvent == Keyboard.PreviewKeyUpEvent) { CheckForDisconnectedFocus(); KeyEventArgs args = (KeyEventArgs)e.StagingItem.Input; args.SetRepeat(false); // Clear _previousKey, so that down/up/down/up doesn't look like a repeat _previousKey = Key.None; } }
private bool ReportInput( IntPtr hwnd, InputMode mode, int timestamp, RawKeyboardActions actions, int scanCode, bool isExtendedKey, bool isSystemKey, int virtualKey) { Debug.Assert( null != _source ); // The first event should also activate the keyboard device. if((actions & RawKeyboardActions.Deactivate) == 0) { if(!_active || _partialActive) { try { // Include the activation action. actions |= RawKeyboardActions.Activate; // Remember that we are active. _active = true; _partialActive = false; } catch(System.ComponentModel.Win32Exception) { System.Diagnostics.Debug.WriteLine("HwndMouseInputProvider: GetKeyboardState failed!"); // We'll go ahead and report the input, but we'll try to "activate" next time. } } } // Get the extra information sent along with the message. IntPtr extraInformation = IntPtr.Zero; try { extraInformation = UnsafeNativeMethods.GetMessageExtraInfo(); } catch(System.ComponentModel.Win32Exception) { System.Diagnostics.Debug.WriteLine("HwndMouseInputProvider: GetMessageExtraInfo failed!"); } RawKeyboardInputReport report = new RawKeyboardInputReport(_source.Value, mode, timestamp, actions, scanCode, isExtendedKey, isSystemKey, virtualKey, extraInformation); bool handled = _site.Value.ReportInput(report); return handled; }