public RawKeyboardInputReport( PresentationSource inputSource, InputMode mode, int timestamp, RawKeyboardActions actions, int scanCode, bool isExtendedKey, bool isSystemKey, int virtualKey, IntPtr extraInformation) : base(inputSource, InputType.Keyboard, mode, timestamp) { if (!IsValidRawKeyboardActions(actions)) throw new System.ComponentModel.InvalidEnumArgumentException("actions", (int)actions, typeof(RawKeyboardActions)); _actions = actions; _scanCode = scanCode; _isExtendedKey = isExtendedKey; _isSystemKey = isSystemKey; _virtualKey = virtualKey; _extraInformation = new SecurityCriticalData<IntPtr>(extraInformation); }
private RawKeyboardActions GetNonRedundantActions(NotifyInputEventArgs e) { RawKeyboardActions actions; // The CLR throws a null-ref exception if it tries to unbox a // null. So we have to special case that. object o = e.StagingItem.GetData(_tagNonRedundantActions); if(o != null) { actions = (RawKeyboardActions) o; } else { actions = new RawKeyboardActions(); } return actions; }
// IsValid Method for RawKeyboardActions. Relies on the enum being flags. internal static bool IsValidRawKeyboardActions(RawKeyboardActions actions) { if (((RawKeyboardActions.AttributesChanged | RawKeyboardActions.Activate | RawKeyboardActions.Deactivate | RawKeyboardActions.KeyDown | RawKeyboardActions.KeyUp) & actions) == actions) { if (!((((RawKeyboardActions.KeyUp | RawKeyboardActions.KeyDown) & actions) == (RawKeyboardActions.KeyUp | RawKeyboardActions.KeyDown)) || ((RawKeyboardActions.Deactivate & actions) == actions && RawKeyboardActions.Deactivate != actions))) { return true; } } return false; }
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 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 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); }
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; }
/// <summary> /// Construct RawKeyboardInputReportWrapper with keyboard state /// </summary> /// <param name="inputSource">inputSource</param> /// <param name="mode">mode</param> /// <param name="timestamp">timestamp</param> /// <param name="actions">actions</param> /// <param name="scanCode">scanCode</param> /// <param name="isExtendedKey">isExtendedKey</param> /// <param name="isSystemKey">isSystemKey</param> /// <param name="virtualKey">virtualKey</param> /// <param name="extraInformation">extraInformation</param> /// <param name="keyboardState">keyboardState</param> public RawKeyboardInputReportWrapper(PresentationSource inputSource, InputMode mode, int timestamp, RawKeyboardActions actions, int scanCode, bool isExtendedKey, bool isSystemKey, int virtualKey, IntPtr extraInformation, RawKeyboardState keyboardState) : base() { object[] objArrayInputReportConstructor = new object[] { inputSource, mode, timestamp, actions, scanCode, isExtendedKey, isSystemKey, virtualKey, extraInformation, keyboardState }; this.InnerObject = Activator.CreateInstance(ReportType, objArrayInputReportConstructor); Trace.Assert(this.InnerObject != null, "Uh oh, not an input report"); }