internal RawStylusSystemGestureInputReport( InputMode mode, int timestamp, PresentationSource inputSource, PenContext penContext, int tabletId, int stylusDeviceId, SystemGesture systemGesture, int gestureX, int gestureY, int buttonState) : base(mode, timestamp, inputSource, penContext, RawStylusActions.SystemGesture, tabletId, stylusDeviceId, new int[] {}) { if (!RawStylusSystemGestureInputReport.IsValidSystemGesture(systemGesture, true, true)) { throw new InvalidEnumArgumentException(SR.Get(SRID.Enum_Invalid, "systemGesture")); } _id = systemGesture; _gestureX = gestureX; _gestureY = gestureY; _buttonState = buttonState; }
/// <summary> /// Validates whether a given SystemGesture has an allowable value. /// </summary> /// <param name="systemGesture">The SysemGesture to test.</param> /// <param name="allowFlick">Whether Flick is allowed.</param> /// <param name="allowDoubleTap">Whether DoubleTab is allowed.</param> /// <returns>True if the SystemGesture matches an allowed gesture. False otherwise.</returns> internal static bool IsValidSystemGesture(SystemGesture systemGesture, bool allowFlick, bool allowDoubleTap) { switch (systemGesture) { case SystemGesture.None: case SystemGesture.Tap: case SystemGesture.RightTap: case SystemGesture.Drag: case SystemGesture.RightDrag: case SystemGesture.HoldEnter: case SystemGesture.HoldLeave: case SystemGesture.HoverEnter: case SystemGesture.HoverLeave: case SystemGesture.TwoFingerTap: #if ROLLOVER_IMPLEMENTED case SystemGesture.Rollover: #endif return true; case SystemGesture.Flick: return allowFlick; case InternalSystemGestureDoubleTap: return allowDoubleTap; default: return false; } }
/// <summary> /// Validates whether a given SystemGesture has an allowable value. /// </summary> /// <param name="systemGesture">The SysemGesture to test.</param> /// <param name="allowFlick">Whether Flick is allowed.</param> /// <param name="allowDoubleTap">Whether DoubleTab is allowed.</param> /// <returns>True if the SystemGesture matches an allowed gesture. False otherwise.</returns> internal static bool IsValidSystemGesture(SystemGesture systemGesture, bool allowFlick, bool allowDoubleTap) { switch (systemGesture) { case SystemGesture.None: case SystemGesture.Tap: case SystemGesture.RightTap: case SystemGesture.Drag: case SystemGesture.RightDrag: case SystemGesture.HoldEnter: case SystemGesture.HoldLeave: case SystemGesture.HoverEnter: case SystemGesture.HoverLeave: case SystemGesture.TwoFingerTap: return(true); case SystemGesture.Flick: return(allowFlick); case InternalSystemGestureDoubleTap: return(allowDoubleTap); default: return(false); } }
private void Callback(IntPtr clientData, ref UnsafeNativeMethods.INTERACTION_CONTEXT_OUTPUT output) { SystemGesture gesture = SystemGesture.None; // Create the appropriate gesture based on interaction output switch (output.interactionId) { case UnsafeNativeMethods.INTERACTION_ID.INTERACTION_ID_TAP: { gesture = SystemGesture.Tap; } break; case UnsafeNativeMethods.INTERACTION_ID.INTERACTION_ID_SECONDARY_TAP: { gesture = SystemGesture.RightTap; } break; case UnsafeNativeMethods.INTERACTION_ID.INTERACTION_ID_HOLD: { _firedHold = true; if (output.interactionFlags.HasFlag(UnsafeNativeMethods.INTERACTION_FLAGS.INTERACTION_FLAG_BEGIN)) { gesture = SystemGesture.HoldEnter; } else { gesture = SystemGesture.HoldLeave; } } break; case UnsafeNativeMethods.INTERACTION_ID.INTERACTION_ID_MANIPULATION: { gesture = DetectDragOrFlick(output); } break; } if (gesture != SystemGesture.None) { InteractionDetected?.Invoke(this, new RawStylusSystemGestureInputReport( InputMode.Foreground, Environment.TickCount, _stylusDevice.CriticalActiveSource, (Func <StylusPointDescription>)null, -1, -1, gesture, Convert.ToInt32(output.x), Convert.ToInt32(output.y), 0)); } }
private void Initialize(SystemGesture systemGesture, int gestureX, int gestureY, int buttonState) { if (!RawStylusSystemGestureInputReport.IsValidSystemGesture(systemGesture, true, true)) { throw new InvalidEnumArgumentException(SR.Get(SRID.Enum_Invalid, nameof(systemGesture))); } _id = systemGesture; _gestureX = gestureX; _gestureY = gestureY; _buttonState = buttonState; }
///////////////////////////////////////////////////////////////////// /// <summary> /// Initializes a new instance of the StylusSystemGestureEventArgs class. /// </summary> /// <param name="stylusDevice"> /// The logical Stylus device associated with this event. /// </param> /// <param name="timestamp"> /// The time when the input occured. /// </param> /// <param name="systemGesture"> /// The type of system gesture. /// </param> public StylusSystemGestureEventArgs( StylusDevice stylusDevice, int timestamp, SystemGesture systemGesture) : base(stylusDevice, timestamp) { if (!RawStylusSystemGestureInputReport.IsValidSystemGesture(systemGesture, false, false)) { throw new InvalidEnumArgumentException(SR.Get(SRID.Enum_Invalid, "systemGesture")); } _id = systemGesture; }
///////////////////////////////////////////////////////////////////// /// <summary> /// Constructs an instance of the RawStylusSystemGestureInputReport class. /// </summary> /// <param name="mode"> /// The mode in which the input is being provided. /// </param> /// <param name="timestamp"> /// The time when the input occured. /// </param> /// <param name="inputSource"> /// The PresentationSource over which the stylus moved. /// </param> /// <param name="penContext"> /// PenContext that generated this event. /// </param> /// <param name="tabletId"> /// tablet id. /// </param> /// <param name="stylusDeviceId"> /// Stylus device id. /// </param> /// <param name="systemGesture"> /// System Gesture. /// </param> /// <param name="gestureX"> /// X location of the system gesture (in tablet device coordindates). /// </param> /// <param name="gestureY"> /// Y location of the system gesture (in tablet device coordindates). /// </param> /// <param name="buttonState"> /// Button state info data. /// </param> internal RawStylusSystemGestureInputReport( InputMode mode, int timestamp, PresentationSource inputSource, PenContext penContext, int tabletId, int stylusDeviceId, SystemGesture systemGesture, int gestureX, int gestureY, int buttonState) : base(mode, timestamp, inputSource, penContext, RawStylusActions.SystemGesture, tabletId, stylusDeviceId, new int[] { }) { Initialize(systemGesture, gestureX, gestureY, buttonState); }
///////////////////////////////////////////////////////////////////// /// <summary> /// Constructs an instance of the RawStylusSystemGestureInputReport class. /// </summary> /// <param name="mode"> /// The mode in which the input is being provided. /// </param> /// <param name="timestamp"> /// The time when the input occured. /// </param> /// <param name="inputSource"> /// The PresentationSource over which the stylus moved. /// </param> /// <param name="penContext"> /// PenContext that generated this event. /// </param> /// <param name="tabletId"> /// tablet id. /// </param> /// <param name="stylusDeviceId"> /// Stylus device id. /// </param> /// <param name="systemGesture"> /// System Gesture. /// </param> /// <param name="gestureX"> /// X location of the system gesture (in tablet device coordindates). /// </param> /// <param name="gestureY"> /// Y location of the system gesture (in tablet device coordindates). /// </param> /// <param name="buttonState"> /// Button state info data. /// </param> internal RawStylusSystemGestureInputReport( InputMode mode, int timestamp, PresentationSource inputSource, Func <StylusPointDescription> stylusPointDescGenerator, int tabletId, int stylusDeviceId, SystemGesture systemGesture, int gestureX, int gestureY, int buttonState) : base(mode, timestamp, inputSource, RawStylusActions.SystemGesture, stylusPointDescGenerator, tabletId, stylusDeviceId, new int[] { }) { Initialize(systemGesture, gestureX, gestureY, buttonState); }
///////////////////////////////////////////////////////////////////// /// <summary> /// Initializes a new instance of the StylusSystemGestureEventArgs class. /// </summary> /// <param name="stylusDevice"> /// The logical Stylus device associated with this event. /// </param> /// <param name="timestamp"> /// The time when the input occured. /// </param> /// <param name="systemGesture"> /// The type of system gesture. /// </param> /// <param name="gestureX"> /// The X location reported with this system gesture. In tablet /// device coordinates. /// </param> /// <param name="gestureY"> /// The Y location reported with this system gesture. In tablet /// device coordinates. /// </param> /// <param name="buttonState"> /// The button state at the time of the system gesture. /// Note: A flick gesture will pass the flick data in the parameter. /// </param> internal StylusSystemGestureEventArgs( StylusDevice stylusDevice, int timestamp, SystemGesture systemGesture, int gestureX, int gestureY, int buttonState) : base(stylusDevice, timestamp) { if (!RawStylusSystemGestureInputReport.IsValidSystemGesture(systemGesture, true, false)) { throw new InvalidEnumArgumentException(SR.Get(SRID.Enum_Invalid, "systemGesture")); } _id = systemGesture; _buttonState = buttonState; _gestureX = gestureX; _gestureY = gestureY; }
///////////////////////////////////////////////////////////////////// internal void OnSystemEvent(PenContext penContext, int tabletDeviceId, int stylusPointerId, int timestamp, SystemGesture id, int gestureX, int gestureY, int buttonState) { _stylusLogic.ProcessSystemEvent(penContext, tabletDeviceId, stylusPointerId, timestamp, id, gestureX, gestureY, buttonState, _inputSource.Value); }
private SystemGesture DetectDragOrFlick(UnsafeNativeMethods.INTERACTION_CONTEXT_OUTPUT output) { SystemGesture gesture = SystemGesture.None; if (output.interactionFlags.HasFlag(UnsafeNativeMethods.INTERACTION_FLAGS.INTERACTION_FLAG_END)) { // At the end of an interaction, any drag/flick/hold state is no longer needed _firedDrag = false; _firedHold = false; _firedFlick = false; } else { // If we have not already fired a drag/flick and we cannot be a flick if (!_firedDrag && !_firedFlick && (!_flickEngine?.Result?.CanBeFlick ?? true)) { // Convert screen pixels to inches using current DPI DpiScale dpi = VisualTreeHelper.GetDpi(_stylusDevice.CriticalActiveSource.RootVisual); double xChangeInches = output.arguments.manipulation.cumulative.translationX / dpi.PixelsPerInchX; double yChangeInches = output.arguments.manipulation.cumulative.translationY / dpi.PixelsPerInchY; // If the cumulative change is greater than our threshold // (taken from WISP, converted to inches) then fire a drag. if (xChangeInches > DragThresholdInches || yChangeInches > DragThresholdInches) { // If we have a current hold being tracked, convert to right drag gesture = (_firedHold) ? SystemGesture.RightDrag : SystemGesture.Drag; // This pointer has seen a drag _firedDrag = true; } } } return(gesture); }
private void UpdateStateForSystemGesture(SystemGesture gesture, RawStylusSystemGestureInputReport report) { switch (gesture) { case SystemGesture.Tap: case SystemGesture.Drag: // request the next mouse move to become LeftButtonDown _fLeftButtonDownTrigger = true; _fGestureWasFired = true; break; case SystemGesture.RightTap: case SystemGesture.RightDrag: // request the next mouse move to become RightButtonDown _fLeftButtonDownTrigger = false; _fGestureWasFired = true; break; case SystemGesture.HoldEnter: // press & hold animation started.. _seenHoldEnterGesture = true; break; case SystemGesture.Flick: // We don't do any mouse promotion for a flick! _fGestureWasFired = true; // Update the stylus location info just for flick gestures. This is because // we want to fire the flick event not from the last stylus location // (end of flick gesture) but from the beginning of the flick gesture // (stylus down point) since this is the element that we query whether they // allow flicks and since scrolling is targetted we need to scroll the // element you really flicked on. // Only route the flick if we have data we can send. if (report != null && report.InputSource != null && _eventStylusPoints != null && _eventStylusPoints.Count > 0) { StylusPoint stylusPoint = _eventStylusPoints[_eventStylusPoints.Count - 1]; stylusPoint.X = report.GestureX; stylusPoint.Y = report.GestureY; // Update the current point with this data. _eventStylusPoints = new StylusPointCollection(stylusPoint.Description, stylusPoint.GetPacketData(), GetTabletToElementTransform(null), Matrix.Identity); PresentationSource inputSource = DetermineValidSource(report.InputSource, _eventStylusPoints, report.PenContext.Contexts); if (inputSource != null) { // See if we need to remap the stylus data X and Y values to different presentation source. if (inputSource != report.InputSource) { Point newWindowLocation = PointUtil.ClientToScreen(new Point(0, 0), inputSource); newWindowLocation = _stylusLogic.MeasureUnitsFromDeviceUnits(newWindowLocation); Point oldWindowLocation = _stylusLogic.MeasureUnitsFromDeviceUnits(report.PenContext.Contexts.DestroyedLocation); // Create translate matrix transform to shift coords to map points to new window location. MatrixTransform additionalTransform = new MatrixTransform(new Matrix(1, 0, 0, 1, oldWindowLocation.X - newWindowLocation.X, oldWindowLocation.Y - newWindowLocation.Y)); _eventStylusPoints = _eventStylusPoints.Reformat(report.StylusPointDescription, additionalTransform); } _rawPosition = _eventStylusPoints[_eventStylusPoints.Count - 1]; _inputSource = new SecurityCriticalDataClass<PresentationSource>(inputSource); Point pt = _stylusLogic.DeviceUnitsFromMeasureUnits((Point)_rawPosition); _lastScreenLocation = PointUtil.ClientToScreen(pt, inputSource); } } break; } }
private void DetectHover() { // Hover only applies to Pen if (_stylusDevice.TabletDevice.Type == TabletDeviceType.Stylus) { SystemGesture gesture = SystemGesture.None; if (_stylusDevice.IsNew) { // Any new stylus should automatically await hover _hoverState = HoverState.AwaitingHover; } switch (_hoverState) { case HoverState.AwaitingHover: { if (_stylusDevice.InAir) { // If we see an InAir while awaiting, start timing _hoverStartTicks = _stylusDevice.TimeStamp; _hoverState = HoverState.TimingHover; } } break; case HoverState.TimingHover: { if (_stylusDevice.InAir) { if (_stylusDevice.TimeStamp < _hoverStartTicks) { // We looped over in ticks, just retry using the new ticks as the start. // At worst this doubles the hover time, but it is rare and simplifies logic. _hoverStartTicks = _stylusDevice.TimeStamp; } else if (_stylusDevice.TimeStamp - _hoverStartTicks > HoverActivationThresholdTicks) { // We should now activate a hover, so send HoverEnter and switch state gesture = SystemGesture.HoverEnter; _hoverState = HoverState.InHover; } } else if (_stylusDevice.IsDown) { // The device is no longer in air so cancel _hoverState = HoverState.HoverCancelled; } } break; case HoverState.HoverCancelled: { if (_stylusDevice.InAir) { // If we are back in air post cancellation, we might need to trigger another hover // so restart the state machine _hoverState = HoverState.AwaitingHover; } } break; case HoverState.InHover: { if (_stylusDevice.IsDown || !_stylusDevice.InRange) { // We are cancelling a hover so send HoverLeave and switch state. gesture = SystemGesture.HoverLeave; _hoverState = HoverState.HoverCancelled; } } break; } if (gesture != SystemGesture.None) { InteractionDetected?.Invoke(this, new RawStylusSystemGestureInputReport( InputMode.Foreground, Environment.TickCount, _stylusDevice.CriticalActiveSource, (Func <StylusPointDescription>)null, -1, -1, gesture, Convert.ToInt32(_stylusDevice.RawStylusPoint.X), Convert.ToInt32(_stylusDevice.RawStylusPoint.Y), 0)); } } }
public StylusSystemGestureEventArgs(StylusDevice stylusDevice, int timestamp, SystemGesture systemGesture) : base(default(StylusDevice), default(int)) { }
public StylusSystemGestureEventArgs(StylusDevice stylusDevice, int timestamp, SystemGesture systemGesture) : base (default(StylusDevice), default(int)) { }
public StylusSystemGestureEventArgs(StylusDevice stylusDevice, int timestamp, SystemGesture systemGesture) : base(stylusDevice, timestamp) { }
private void GenerateGesture(RawStylusInputReport rawStylusInputReport, SystemGesture gesture) { StylusDevice stylusDevice = rawStylusInputReport.StylusDevice; System.Diagnostics.Debug.Assert(stylusDevice != null); RawStylusSystemGestureInputReport inputReport = new RawStylusSystemGestureInputReport( InputMode.Foreground, rawStylusInputReport.Timestamp, rawStylusInputReport.InputSource, rawStylusInputReport.PenContext, rawStylusInputReport.TabletDeviceId, rawStylusInputReport.StylusDeviceId, gesture, 0, // Gesture X location (only used for flicks) 0, // Gesture Y location (only used for flicks) 0); // ButtonState (only used for flicks) inputReport.StylusDevice = stylusDevice; InputReportEventArgs input = new InputReportEventArgs(stylusDevice, inputReport); input.RoutedEvent=InputManager.PreviewInputReportEvent; // Process this directly instead of doing a push. We want this event to get // to the user before the StylusUp and MouseUp event. InputManagerProcessInputEventArgs(input); }
public StylusSystemGestureEventArgs (StylusDevice stylusDevice, int timestamp, SystemGesture systemGesture) : base (stylusDevice, timestamp) { }
internal void OnSystemEvent(PenContext penContext, int tabletDeviceId, int stylusPointerId, int timestamp, SystemGesture id, int gestureX, int gestureY, int buttonState) { _stylusLogic.ProcessSystemEvent(penContext, tabletDeviceId, stylusPointerId, timestamp, id, gestureX, gestureY, buttonState, _inputSource.Value); }
internal RawStylusSystemGestureInputReport( InputMode mode, int timestamp, PresentationSource inputSource, PenContext penContext, int tabletId, int stylusDeviceId, SystemGesture systemGesture, int gestureX, int gestureY, int buttonState) : base( mode, timestamp, inputSource, penContext, RawStylusActions.SystemGesture, tabletId, stylusDeviceId, new int[] {}) { if (!RawStylusSystemGestureInputReport.IsValidSystemGesture(systemGesture, true, true)) { throw new InvalidEnumArgumentException(SR.Get( SRID.Enum_Invalid, "systemGesture")); } _id = systemGesture; _gestureX = gestureX; _gestureY = gestureY; _buttonState = buttonState; }
internal void ProcessSystemEvent(PenContext penContext, int tabletDeviceId, int stylusDeviceId, int timestamp, SystemGesture systemGesture, int gestureX, int gestureY, int buttonState, PresentationSource inputSource) { // We only want to process the system events we expose in the public enum // for SystemSystemGesture. There are a bunch of other system gestures that // can come through. if (systemGesture == SystemGesture.Tap || systemGesture == SystemGesture.RightTap || systemGesture == SystemGesture.Drag || systemGesture == SystemGesture.RightDrag || systemGesture == SystemGesture.HoldEnter || systemGesture == SystemGesture.HoldLeave || systemGesture == SystemGesture.HoverEnter || systemGesture == SystemGesture.HoverLeave || systemGesture == SystemGesture.Flick || systemGesture == RawStylusSystemGestureInputReport.InternalSystemGestureDoubleTap || systemGesture == SystemGesture.None) { Debug.Assert(systemGesture != SystemGesture.None); // We should ever see this as input. RawStylusSystemGestureInputReport inputReport = new RawStylusSystemGestureInputReport( InputMode.Foreground, timestamp, inputSource, penContext, tabletDeviceId, stylusDeviceId, systemGesture, gestureX, // location of system gesture in tablet device coordinates gestureY, buttonState); // flicks passes the flickinfo in this param // actions: RawStylusActions.StylusSystemEvent ProcessInputReport(inputReport); } }