internal RawStylusInputReport( InputMode mode, int timestamp, PresentationSource inputSource, PenContext penContext, RawStylusActions actions, int tabletDeviceId, int stylusDeviceId, int[] data) : base(inputSource, InputType.Stylus, mode, timestamp) { // Validate parameters if (!RawStylusActionsHelper.IsValid(actions)) { throw new InvalidEnumArgumentException(SR.Get(SRID.Enum_Invalid, "actions")); } if (data == null && actions != RawStylusActions.InRange) { throw new ArgumentNullException("data"); } _penContext = new SecurityCriticalDataClass <PenContext>(penContext); _actions = actions; _tabletDeviceId = tabletDeviceId; _stylusDeviceId = stylusDeviceId; _data = data; _isSynchronize = false; }
/// <summary> /// Constructs an instance of the RawStylusInputReport class. /// </summary> /// <param name="mode"> /// The mode in which the input is being provided. /// </param> /// <param name="timestamp"> /// The time when the input occurred. /// </param> /// <param name="inputSource"> /// The PresentationSource over which the stylus moved. /// <param name="actions"> /// The set of actions being reported. /// </param> /// /// </param> /// <param name="stylusPointDescGenerator"> /// Function to generate the stylus point description. /// </param> /// <param name="tabletDeviceId"> /// Tablet device id. /// </param> /// <param name="stylusDeviceId"> /// Stylus device id. /// </param> /// <param name="data"> /// Raw stylus data. /// </param> internal RawStylusInputReport( InputMode mode, int timestamp, PresentationSource inputSource, RawStylusActions actions, Func <StylusPointDescription> stylusPointDescGenerator, int tabletDeviceId, int stylusDeviceId, int[] data) : base(inputSource, InputType.Stylus, mode, timestamp) { // Validate parameters if (!RawStylusActionsHelper.IsValid(actions)) { throw new InvalidEnumArgumentException(SR.Get(SRID.Enum_Invalid, nameof(actions))); } if (data == null && actions != RawStylusActions.InRange) { throw new ArgumentNullException(nameof(data)); } _actions = actions; _stylusPointDescGenerator = stylusPointDescGenerator; _data = data; _isSynchronize = false; _tabletDeviceId = tabletDeviceId; _stylusDeviceId = stylusDeviceId; }
internal RawStylusInputReport( InputMode mode, int timestamp, PresentationSource inputSource, RawStylusActions actions, StylusPointDescription mousePointDescription, int[] mouseData) : base(inputSource, InputType.Stylus, mode, timestamp) { // Validate parameters if (!RawStylusActionsHelper.IsValid(actions)) { throw new InvalidEnumArgumentException(SR.Get(SRID.Enum_Invalid, "actions")); } if (mouseData == null) { throw new ArgumentNullException("mouseData"); } _penContext = new SecurityCriticalDataClass <PenContext>(null); _actions = actions; _tabletDeviceId = 0; _stylusDeviceId = 0; _data = mouseData; _isSynchronize = false; _mousePointDescription = mousePointDescription; _isMouseInput = true; }
/// <summary> /// Constructs an instance of the RawStylusInputReport class. /// </summary> /// <param name="mode"> /// The mode in which the input is being provided. /// </param> /// <param name="timestamp"> /// The time when the input occurred. /// </param> /// <param name="inputSource"> /// The PresentationSource over which the stylus moved. /// </param> /// <param name="penContext"> /// The PenContext. /// </param> /// <param name="actions"> /// The set of actions being reported. /// </param> /// <param name="tabletDeviceId"> /// Tablet device id. /// </param> /// <param name="stylusDeviceId"> /// Stylus device id. /// </param> /// <param name="data"> /// Raw stylus data. /// </param> internal RawStylusInputReport( InputMode mode, int timestamp, PresentationSource inputSource, PenContext penContext, RawStylusActions actions, int tabletDeviceId, int stylusDeviceId, int[] data) : this(mode, timestamp, inputSource, actions, () => { return(penContext.StylusPointDescription); }, tabletDeviceId, stylusDeviceId, data) { // Validate parameters if (!RawStylusActionsHelper.IsValid(actions)) { throw new InvalidEnumArgumentException(SR.Get(SRID.Enum_Invalid, nameof(actions))); } if (data == null && actions != RawStylusActions.InRange) { throw new ArgumentNullException(nameof(data)); } _actions = actions; _data = data; _isSynchronize = false; _tabletDeviceId = tabletDeviceId; _stylusDeviceId = stylusDeviceId; PenContext = penContext; }
internal RawStylusInputReport( InputMode mode, int timestamp, PresentationSource inputSource, PenContext penContext, RawStylusActions actions, int tabletDeviceId, int stylusDeviceId, int[] data) : base(inputSource, InputType.Stylus, mode, timestamp) { // Validate parameters if (!RawStylusActionsHelper.IsValid(actions)) { throw new InvalidEnumArgumentException(SR.Get(SRID.Enum_Invalid, "actions")); } if (data == null && actions != RawStylusActions.InRange) { throw new ArgumentNullException("data"); } _penContext = new SecurityCriticalDataClass<PenContext>(penContext); _actions = actions; _tabletDeviceId = tabletDeviceId; _stylusDeviceId = stylusDeviceId; _data = data; _isSynchronize = false; }
internal static bool IsValid(RawStylusActions action) { if (action < RawStylusActions.None || action > MaxActions) { return(false); } return(true); }
internal static bool IsValid(RawStylusActions action) { if (action < RawStylusActions.None || action > MaxActions) { return false; } return true; }
internal static RoutedEvent GetPreviewEventFromRawStylusActions(RawStylusActions actions) { RoutedEvent previewEvent = null; switch (actions) { case RawStylusActions.Down: { previewEvent = Stylus.PreviewStylusDownEvent; } break; case RawStylusActions.Up: { previewEvent = Stylus.PreviewStylusUpEvent; } break; case RawStylusActions.Move: { previewEvent = Stylus.PreviewStylusMoveEvent; } break; case RawStylusActions.InAirMove: { previewEvent = Stylus.PreviewStylusInAirMoveEvent; } break; case RawStylusActions.InRange: { previewEvent = Stylus.PreviewStylusInRangeEvent; } break; case RawStylusActions.OutOfRange: { previewEvent = Stylus.PreviewStylusOutOfRangeEvent; } break; case RawStylusActions.SystemGesture: { previewEvent = Stylus.PreviewStylusSystemGestureEvent; } break; } return(previewEvent); }
///////////////////////////////////////////////////////////////////// void ProcessInput( RawStylusActions actions, PenContext penContext, int tabletDeviceId, int stylusPointerId, int[] data, int timestamp) { // (all events but SystemEvent go thru here) _stylusLogic.ProcessInput( actions, penContext, tabletDeviceId, stylusPointerId, data, timestamp, _inputSource.Value); }
///////////////////////////////////////////////////////////////////// // (on app Dispatcher) internal void FireCustomData(object callbackData, RawStylusActions action, bool targetVerified) { // Only fire if plugin is enabled and hooked up to plugincollection. if (__enabled && _pic != null) { switch (action) { case RawStylusActions.Down: OnStylusDownProcessed(callbackData, targetVerified); break; case RawStylusActions.Move: OnStylusMoveProcessed(callbackData, targetVerified); break; case RawStylusActions.Up: OnStylusUpProcessed(callbackData, targetVerified); break; } } }
internal void ProcessInput( RawStylusActions actions, PenContext penContext, int tabletDeviceId, int stylusDeviceId, int[] data, int timestamp, PresentationSource inputSource) { RawStylusInputReport inputReport = new RawStylusInputReport(InputMode.Foreground, timestamp, inputSource, penContext, actions, tabletDeviceId, stylusDeviceId, data); ProcessInputReport(inputReport); }
/// <summary> /// Processes the latest WM_POINTER message and forwards it to the WPF input stack. /// </summary> /// <param name="pointerId">The id of the pointer message</param> /// <param name="action">The stylus action being done</param> /// <param name="timestamp">The time (in ticks) the message arrived</param> /// <returns>True if successfully processed (handled), false otherwise</returns> private bool ProcessMessage(uint pointerId, RawStylusActions action, int timestamp) { bool handled = false; // Acquire all pointer data needed PointerData data = new PointerData(pointerId); // Only process touch or pen messages, do not process mouse or touchpad if (data.IsValid && (data.Info.pointerType == UnsafeNativeMethods.POINTER_INPUT_TYPE.PT_TOUCH || data.Info.pointerType == UnsafeNativeMethods.POINTER_INPUT_TYPE.PT_PEN)) { uint cursorId = 0; if (UnsafeNativeMethods.GetPointerCursorId(pointerId, ref cursorId)) { IntPtr deviceId = data.Info.sourceDevice; // If we cannot acquire the latest tablet and stylus then wait for the // next message. if (!UpdateCurrentTabletAndStylus(deviceId, cursorId)) { return(false); } // Convert move to InAirMove if applicable if (action == RawStylusActions.Move && (!data.Info.pointerFlags.HasFlag(UnsafeNativeMethods.POINTER_FLAGS.POINTER_FLAG_INCONTACT) && data.Info.pointerFlags.HasFlag(UnsafeNativeMethods.POINTER_FLAGS.POINTER_FLAG_INRANGE))) { action = RawStylusActions.InAirMove; } // Generate a raw input to send to the input manager to start the event chain in PointerLogic RawStylusInputReport rsir = new RawStylusInputReport( InputMode.Foreground, timestamp, _source.Value, action, () => { return(_currentTabletDevice.StylusPointDescription); }, _currentTabletDevice.Id, _currentStylusDevice.Id, GenerateRawStylusData(data, _currentTabletDevice)) { StylusDevice = _currentStylusDevice.StylusDevice, }; // Send the input report to the stylus plugins if we're not doing a drag and the window // is currently enabled. if (!_pointerLogic.Value.InDragDrop && IsWindowEnabled) { PointerStylusPlugInManager manager; if (_pointerLogic.Value.PlugInManagers.TryGetValue(_source.Value, out manager)) { manager.InvokeStylusPluginCollection(rsir); } } // Update the data in the stylus device with the latest pointer data _currentStylusDevice.Update(this, _source.Value, data, rsir); // Call the StylusDevice to process and fire any interactions that // might have resulted from the input. If the originating inputs // have been handled, we don't want to generate any gestures. _currentStylusDevice.UpdateInteractions(rsir); InputReportEventArgs irea = new InputReportEventArgs(_currentStylusDevice.StylusDevice, rsir) { RoutedEvent = InputManager.PreviewInputReportEvent, }; // Now send the input report InputManager.UnsecureCurrent.ProcessInput(irea); // If this is not a primary pointer input, we don't want to // allow it to go to DefWindowProc, so we should handle it. // This ensures that primary pointer to mouse promotions // will occur in multi-touch scenarios. // We don't use the results of the input processing here as doing // so could possibly cause some messages of a pointer chain as // being handled, and some as being unhandled. This results in // undefined behavior in the WM_POINTER stack. // <see cref="https://msdn.microsoft.com/en-us/library/windows/desktop/hh454923(v=vs.85).aspx"/> handled = !_currentStylusDevice.IsPrimary; } } return(handled); }
/// <summary> /// Used in order to allow StylusPlugins to affect mouse inputs as well as touch. /// </summary> internal static void InvokePlugInsForMouse(ProcessInputEventArgs e) { if (!e.StagingItem.Input.Handled) { // if we see a preview mouse event that is not generated by a stylus // then send on to plugin if ((e.StagingItem.Input.RoutedEvent != Mouse.PreviewMouseDownEvent) && (e.StagingItem.Input.RoutedEvent != Mouse.PreviewMouseUpEvent) && (e.StagingItem.Input.RoutedEvent != Mouse.PreviewMouseMoveEvent) && (e.StagingItem.Input.RoutedEvent != InputManager.InputReportEvent)) { return; } // record the mouse capture for later reference.. MouseDevice mouseDevice; PresentationSource source; bool leftButtonDown; bool rightButtonDown; RawStylusActions stylusActions = RawStylusActions.None; int timestamp; // See if we need to deal sending a leave due to this PresentationSource being Deactivated // If not then we just return and do nothing. if (e.StagingItem.Input.RoutedEvent == InputManager.InputReportEvent) { if (_activeMousePlugInCollection?.Element == null) { return; } InputReportEventArgs input = e.StagingItem.Input as InputReportEventArgs; if (input.Report.Type != InputType.Mouse) { return; } RawMouseInputReport mouseInputReport = (RawMouseInputReport)input.Report; if ((mouseInputReport.Actions & RawMouseActions.Deactivate) != RawMouseActions.Deactivate) { return; } mouseDevice = InputManager.UnsecureCurrent.PrimaryMouseDevice; // Mouse set directly over to null when truly deactivating. if (mouseDevice == null || mouseDevice.DirectlyOver != null) { return; } leftButtonDown = mouseDevice.LeftButton == MouseButtonState.Pressed; rightButtonDown = mouseDevice.RightButton == MouseButtonState.Pressed; timestamp = mouseInputReport.Timestamp; // Get presentationsource from element. source = PresentationSource.CriticalFromVisual(_activeMousePlugInCollection.Element as Visual); } else { MouseEventArgs mouseEventArgs = e.StagingItem.Input as MouseEventArgs; mouseDevice = mouseEventArgs.MouseDevice; leftButtonDown = mouseDevice.LeftButton == MouseButtonState.Pressed; rightButtonDown = mouseDevice.RightButton == MouseButtonState.Pressed; // Only look at mouse input reports that truly come from a mouse (and is not an up or deactivate) and it // must be pressed state if a move (we don't fire stylus inair moves currently) if (mouseEventArgs.StylusDevice != null && e.StagingItem.Input.RoutedEvent != Mouse.PreviewMouseUpEvent) { return; } if (e.StagingItem.Input.RoutedEvent == Mouse.PreviewMouseMoveEvent) { if (!leftButtonDown) { return; } stylusActions = RawStylusActions.Move; } if (e.StagingItem.Input.RoutedEvent == Mouse.PreviewMouseDownEvent) { MouseButtonEventArgs mouseButtonEventArgs = mouseEventArgs as MouseButtonEventArgs; if (mouseButtonEventArgs.ChangedButton != MouseButton.Left) { return; } stylusActions = RawStylusActions.Down; } if (e.StagingItem.Input.RoutedEvent == Mouse.PreviewMouseUpEvent) { MouseButtonEventArgs mouseButtonEventArgs = mouseEventArgs as MouseButtonEventArgs; if (mouseButtonEventArgs.ChangedButton != MouseButton.Left) { return; } stylusActions = RawStylusActions.Up; } timestamp = mouseEventArgs.Timestamp; Visual directlyOverVisual = mouseDevice.DirectlyOver as Visual; if (directlyOverVisual == null) { return; } // // Take the presentation source which is associated to the directly over element. source = PresentationSource.CriticalFromVisual(directlyOverVisual); } if ((source != null) && (source.CompositionTarget != null) && !source.CompositionTarget.IsDisposed) { IInputElement directlyOver = mouseDevice.DirectlyOver; int packetStatus = (leftButtonDown ? 1 : 0) | (rightButtonDown ? 9 : 0); // pen tip down == 1, barrel = 8 Point ptClient = mouseDevice.GetPosition(source.RootVisual as IInputElement); ptClient = source.CompositionTarget.TransformToDevice.Transform(ptClient); int buttons = (leftButtonDown ? 1 : 0) | (rightButtonDown ? 3 : 0); int[] data = { (int)ptClient.X, (int)ptClient.Y, packetStatus, buttons }; RawStylusInputReport inputReport = new RawStylusInputReport( InputMode.Foreground, timestamp, source, stylusActions, () => { return(MousePointDescription); }, 0, 0, data); PointerStylusPlugInManager manager = StylusLogic.GetCurrentStylusLogicAs <PointerLogic>()?.GetManagerForSource(source); // Avoid re-entrancy due to lock() being used. using (Dispatcher.CurrentDispatcher.DisableProcessing()) { // Call plugins (does enter/leave and FireCustomData as well) _activeMousePlugInCollection = manager?.InvokeStylusPluginCollectionForMouse(inputReport, directlyOver, _activeMousePlugInCollection); } } } }
internal RawStylusInputReport( InputMode mode, int timestamp, PresentationSource inputSource, RawStylusActions actions, StylusPointDescription mousePointDescription, int[] mouseData) : base(inputSource, InputType.Stylus, mode, timestamp) { // Validate parameters if (!RawStylusActionsHelper.IsValid(actions)) { throw new InvalidEnumArgumentException(SR.Get(SRID.Enum_Invalid, "actions")); } if (mouseData == null) { throw new ArgumentNullException("mouseData"); } _penContext = new SecurityCriticalDataClass<PenContext>(null); _actions = actions; _tabletDeviceId = 0; _stylusDeviceId = 0; _data = mouseData; _isSynchronize = false; _mousePointDescription = mousePointDescription; _isMouseInput = true; }
void ProcessInput( RawStylusActions actions, PenContext penContext, int tabletDeviceId, int stylusPointerId, int[] data, int timestamp) { // (all events but SystemEvent go thru here) _stylusLogic.ProcessInput( actions, penContext, tabletDeviceId, stylusPointerId, data, timestamp, _inputSource.Value); }
///////////////////////////////////////////////////////////////////// RoutedEvent GetPreviewEventFromRawStylusActions(RawStylusActions actions) { if((actions & RawStylusActions.Down) != 0) return Stylus.PreviewStylusDownEvent; if ((actions & RawStylusActions.Up) != 0) return Stylus.PreviewStylusUpEvent; if ((actions & RawStylusActions.Move) != 0) return Stylus.PreviewStylusMoveEvent; if ((actions & RawStylusActions.InAirMove) != 0) return Stylus.PreviewStylusInAirMoveEvent; if ((actions & RawStylusActions.InRange) != 0) return Stylus.PreviewStylusInRangeEvent; if ((actions & RawStylusActions.OutOfRange) != 0) return Stylus.PreviewStylusOutOfRangeEvent; if ((actions & RawStylusActions.SystemGesture) != 0) return Stylus.PreviewStylusSystemGestureEvent; return null; }