private void InputDeviceEvents_PreProcessInput(object sender, PreProcessInputEventArgs e) { if (e.StagingItem.Input.Device is TouchDevice) { InputReportEventArgs irea = e.StagingItem.Input as InputReportEventArgs; if (irea != null) { RawTouchInputReport rtir = irea.Report as RawTouchInputReport; if (rtir != null) { // cancel any touch event that does not start within the modal window //if (!this.ContainsPoint(rtir.Touches[0].X, rtir.Touches[0].Y)) // e.Cancel(); int x = rtir.Touches[0].X; int y = rtir.Touches[0].Y; PointToClient(ref x, ref y); if (!Utils.IsWithinRectangle(x, y, ActualWidth, ActualWidth)) { e.Cancel(); } } } } }
internal override void Synchronize() { // Simulate a stylus move (if we are current stylus, inrange, visuals still valid to update // and has moved). if (InRange && _inputSource != null && _inputSource.Value != null && _inputSource.Value.CompositionTarget != null && !_inputSource.Value.CompositionTarget.IsDisposed) { Point rawScreenPoint = new Point(_pointerData.Info.ptPixelLocationRaw.X, _pointerData.Info.ptPixelLocationRaw.Y); Point ptDevice = PointUtil.ScreenToClient(rawScreenPoint, _inputSource.Value); // GlobalHitTest always returns an IInputElement, so we are sure to have one. IInputElement stylusOver = Input.StylusDevice.GlobalHitTest(_inputSource.Value, ptDevice); bool fOffsetChanged = false; if (_stylusOver == stylusOver) { Point ptOffset = GetPosition(stylusOver); fOffsetChanged = MS.Internal.DoubleUtil.AreClose(ptOffset.X, _rawElementRelativePosition.X) == false || MS.Internal.DoubleUtil.AreClose(ptOffset.Y, _rawElementRelativePosition.Y) == false; } if (fOffsetChanged || _stylusOver != stylusOver) { int timeStamp = Environment.TickCount; if (_currentStylusPoints != null && _currentStylusPoints.Count > 0 && StylusPointDescription.AreCompatible(PointerTabletDevice.StylusPointDescription, _currentStylusPoints.Description)) { StylusPoint stylusPoint = _currentStylusPoints[_currentStylusPoints.Count - 1]; int[] data = stylusPoint.GetPacketData(); // get back to the correct coordinate system Matrix m = _tabletDevice.TabletToScreen; m.Invert(); Point ptTablet = ptDevice * m; data[0] = (int)ptTablet.X; data[1] = (int)ptTablet.Y; RawStylusInputReport report = new RawStylusInputReport(InputMode.Foreground, timeStamp, _inputSource.Value, InAir ? RawStylusActions.InAirMove : RawStylusActions.Move, () => { return(PointerTabletDevice.StylusPointDescription); }, TabletDevice.Id, Id, data); report.Synchronized = true; InputReportEventArgs inputReportEventArgs = new InputReportEventArgs(StylusDevice, report); inputReportEventArgs.RoutedEvent = InputManager.PreviewInputReportEvent; InputManager.Current.ProcessInput(inputReportEventArgs); } } } }
private void HandleInteraction(object clientData, RawStylusSystemGestureInputReport originalReport) { RawStylusSystemGestureInputReport report = new RawStylusSystemGestureInputReport( InputMode.Foreground, Environment.TickCount, CriticalActiveSource, () => { return(PointerTabletDevice.StylusPointDescription); }, TabletDevice.Id, Id, originalReport.SystemGesture, originalReport.GestureX, originalReport.GestureY, originalReport.ButtonState) { StylusDevice = StylusDevice, }; // For a flick, update the points in the stylus device to the flick location. // This forces processing of the stylus over to use the initial flick location // instead of the last WM_POINTER message location allowing command processing to // be done on the flick location itself. if (report.SystemGesture == SystemGesture.Flick) { StylusPoint flickPoint = _currentStylusPoints[_currentStylusPoints.Count - 1]; flickPoint.X = report.GestureX; flickPoint.Y = report.GestureY; _currentStylusPoints = new StylusPointCollection(flickPoint.Description, flickPoint.GetPacketData(), GetTabletToElementTransform(null), Matrix.Identity); } InputReportEventArgs irea = new InputReportEventArgs(StylusDevice, report) { RoutedEvent = InputManager.PreviewInputReportEvent, }; // Now send the input report InputManager.UnsecureCurrent.ProcessInput(irea); }
private void InputDeviceEvents_PreProcessInput(object sender, PreProcessInputEventArgs e) { if (e.StagingItem.Input.Device is TouchDevice) { InputReportEventArgs irea = e.StagingItem.Input as InputReportEventArgs; if (irea != null) { RawTouchInputReport rtir = irea.Report as RawTouchInputReport; if (rtir != null) { int x = rtir.Touches[0].X; int y = rtir.Touches[0].Y; PointToClient(ref x, ref y); if (!Utils.IsWithinRectangle(x, y, ActualWidth, ActualWidth)) { e.Cancel(); } } } } }
/// <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); }
private void OnPostProcessInput(object sender, ProcessInputEventArgs e) { if (e.StagingItem.Input.RoutedEvent == InputManager.InputReportEvent) { InputReportEventArgs inputReportEventArgs = (InputReportEventArgs)e.StagingItem.Input; if (!inputReportEventArgs.Handled && inputReportEventArgs.Report.Type == InputType.Mouse) { RawMouseInputReport rawMouseInputReport = (RawMouseInputReport)inputReportEventArgs.Report; if ((rawMouseInputReport.Actions & RawMouseActions.AbsoluteMove) == RawMouseActions.AbsoluteMove) { if (Mouse.LeftButton == MouseButtonState.Pressed || Mouse.RightButton == MouseButtonState.Pressed) { this.RaiseToolTipClosingEvent(true); return; } IInputElement inputElement = Mouse.PrimaryDevice.RawDirectlyOver; if (inputElement != null) { Point position = Mouse.PrimaryDevice.GetPosition(inputElement); if (Mouse.CapturedMode != CaptureMode.None) { PresentationSource presentationSource = PresentationSource.CriticalFromVisual((DependencyObject)inputElement); UIElement uIElement = (presentationSource != null) ? (presentationSource.RootVisual as UIElement) : null; if (uIElement != null) { position = Mouse.PrimaryDevice.GetPosition(uIElement); IInputElement inputElement2; uIElement.InputHitTest(position, out inputElement2, out inputElement); position = Mouse.PrimaryDevice.GetPosition(inputElement); } else { inputElement = null; } } if (inputElement != null) { this.OnMouseMove(inputElement, position); return; } } } else if ((rawMouseInputReport.Actions & RawMouseActions.Deactivate) == RawMouseActions.Deactivate && this.LastMouseDirectlyOver != null) { this.LastMouseDirectlyOver = null; if (this.LastMouseOverWithToolTip != null) { this.RaiseToolTipClosingEvent(true); if (SafeNativeMethods.GetCapture() == IntPtr.Zero) { this.LastMouseOverWithToolTip = null; return; } } } } } else { if (e.StagingItem.Input.RoutedEvent == Keyboard.KeyDownEvent) { this.ProcessKeyDown(sender, (KeyEventArgs)e.StagingItem.Input); return; } if (e.StagingItem.Input.RoutedEvent == Keyboard.KeyUpEvent) { this.ProcessKeyUp(sender, (KeyEventArgs)e.StagingItem.Input); return; } if (e.StagingItem.Input.RoutedEvent == Mouse.MouseUpEvent) { this.ProcessMouseUp(sender, (MouseButtonEventArgs)e.StagingItem.Input); return; } if (e.StagingItem.Input.RoutedEvent == Mouse.MouseDownEvent) { this.RaiseToolTipClosingEvent(true); } } }
///////////////////////////////////////////////////////////////////// private void OnPostProcessInput(object sender, ProcessInputEventArgs e) { if (e.StagingItem.Input.RoutedEvent == InputManager.InputReportEvent) { InputReportEventArgs report = (InputReportEventArgs)e.StagingItem.Input; if (!report.Handled) { if (report.Report.Type == InputType.Mouse) { RawMouseInputReport mouseReport = (RawMouseInputReport)report.Report; if ((mouseReport.Actions & RawMouseActions.AbsoluteMove) == RawMouseActions.AbsoluteMove) { if ((Mouse.LeftButton == MouseButtonState.Pressed) || (Mouse.RightButton == MouseButtonState.Pressed)) { RaiseToolTipClosingEvent(true /* reset */); } else { IInputElement directlyOver = Mouse.PrimaryDevice.RawDirectlyOver; if (directlyOver != null) { Point pt = Mouse.PrimaryDevice.GetPosition(directlyOver); // If possible, check that the mouse position is within the render bounds // (avoids mouse capture confusion). if (Mouse.CapturedMode != CaptureMode.None) { // Get the root visual PresentationSource source = PresentationSource.CriticalFromVisual((DependencyObject)directlyOver); UIElement rootAsUIElement = source != null ? source.RootVisual as UIElement : null; if (rootAsUIElement != null) { // Get mouse position wrt to root pt = Mouse.PrimaryDevice.GetPosition(rootAsUIElement); // Hittest to find the element the mouse is over IInputElement enabledHit; rootAsUIElement.InputHitTest(pt, out enabledHit, out directlyOver); // Find the position of the mouse relative the element that the mouse is over pt = Mouse.PrimaryDevice.GetPosition(directlyOver); } else { directlyOver = null; } } if (directlyOver != null) { // Process the mouse move OnMouseMove(directlyOver, pt); } } } } else if ((mouseReport.Actions & RawMouseActions.Deactivate) == RawMouseActions.Deactivate) { if (LastMouseDirectlyOver != null) { LastMouseDirectlyOver = null; if (LastMouseOverWithToolTip != null) { RaiseToolTipClosingEvent(true /* reset */); // When the user moves the cursor outside of the window, // clear the LastMouseOverWithToolTip property so if the user returns // the mouse to the same item, the tooltip will reappear. If // the deactivation is coming from a window grabbing capture // (such as Drag and Drop) do not clear the property. if (MS.Win32.SafeNativeMethods.GetCapture() == IntPtr.Zero) { LastMouseOverWithToolTip = null; } } } } } } } else if (e.StagingItem.Input.RoutedEvent == Keyboard.KeyDownEvent) { ProcessKeyDown(sender, (KeyEventArgs)e.StagingItem.Input); } else if (e.StagingItem.Input.RoutedEvent == Keyboard.KeyUpEvent) { ProcessKeyUp(sender, (KeyEventArgs)e.StagingItem.Input); } else if (e.StagingItem.Input.RoutedEvent == Mouse.MouseUpEvent) { ProcessMouseUp(sender, (MouseButtonEventArgs)e.StagingItem.Input); } else if (e.StagingItem.Input.RoutedEvent == Mouse.MouseDownEvent) { RaiseToolTipClosingEvent(true /* reset */); } }
/// <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); } } } }