internal void AddStylusPlugInCollection(StylusPlugInCollection pic) { // must be called from inside of lock(__rtiLock) // insert in ZOrder _plugInCollectionList.Insert(FindZOrderIndex(pic), pic); }
internal StylusPlugInCollection InvokeStylusPluginCollectionForMouse(RawStylusInputReport inputReport, IInputElement directlyOver, StylusPlugInCollection currentPlugInCollection) { StylusPlugInCollection newPlugInCollection = null; // lock to make sure only one event is processed at a time and no changes to state can // be made until we finish routing this event. lock (__rtiLock) { //Debug.Assert(inputReport.Actions == RawStylusActions.Down || // inputReport.Actions == RawStylusActions.Up || // inputReport.Actions == RawStylusActions.Move); // Find new target plugin collection if (directlyOver != null) { UIElement uiElement = InputElement.GetContainingUIElement(directlyOver as DependencyObject) as UIElement; if (uiElement != null) { newPlugInCollection = FindPlugInCollection(uiElement); } } // Fire Leave event to old pluginCollection if we need to. if (currentPlugInCollection != null && currentPlugInCollection != newPlugInCollection) { // NOTE: input report points for mouse are in avalon measured units and not device! RawStylusInput tempRawStylusInput = new RawStylusInput(inputReport, currentPlugInCollection.ViewToElement, currentPlugInCollection); currentPlugInCollection.FireEnterLeave(false, tempRawStylusInput, true); // Indicate we've used a stylus plugin _stylusLogic.Statistics.FeaturesUsed |= Tracing.StylusTraceLogger.FeatureFlags.StylusPluginsUsed; } if (newPlugInCollection != null) { // NOTE: input report points for mouse are in avalon measured units and not device! RawStylusInput rawStylusInput = new RawStylusInput(inputReport, newPlugInCollection.ViewToElement, newPlugInCollection); inputReport.RawStylusInput = rawStylusInput; if (newPlugInCollection != currentPlugInCollection) { newPlugInCollection.FireEnterLeave(true, rawStylusInput, true); } // We are on the pen thread, just call directly. newPlugInCollection.FireRawStylusInput(rawStylusInput); // Indicate we've used a stylus plugin _stylusLogic.Statistics.FeaturesUsed |= Tracing.StylusTraceLogger.FeatureFlags.StylusPluginsUsed; // Fire custom data events (always confirmed for mouse) foreach (RawStylusInputCustomData customData in rawStylusInput.CustomDataList) { customData.Owner.FireCustomData(customData.Data, inputReport.Actions, true); } } } return(newPlugInCollection); }
/// <summary> /// </summary> internal StylusPlugInCollection InvokeStylusPluginCollectionForMouse(RawStylusInputReport inputReport, IInputElement directlyOver, StylusPlugInCollection currentPlugInCollection) { StylusPlugInCollection newPlugInCollection = null; // Find new target plugin collection if (directlyOver != null) { UIElement uiElement = InputElement.GetContainingUIElement(directlyOver as DependencyObject) as UIElement; if (uiElement != null) { newPlugInCollection = FindPlugInCollection(uiElement); } } // Fire Leave event to old pluginCollection if we need to. if (currentPlugInCollection != null && currentPlugInCollection != newPlugInCollection) { // NOTE: input report points for mouse are in avalon measured units and not device! RawStylusInput tempRawStylusInput = new RawStylusInput(inputReport, currentPlugInCollection.ViewToElement, currentPlugInCollection); currentPlugInCollection.FireEnterLeave(false, tempRawStylusInput, true); // Indicate we've used a stylus plugin StylusLogic.CurrentStylusLogic.Statistics.FeaturesUsed |= Tracing.StylusTraceLogger.FeatureFlags.StylusPluginsUsed; } if (newPlugInCollection != null) { // NOTE: input report points for mouse are in avalon measured units and not device! RawStylusInput rawStylusInput = new RawStylusInput(inputReport, newPlugInCollection.ViewToElement, newPlugInCollection); inputReport.RawStylusInput = rawStylusInput; if (newPlugInCollection != currentPlugInCollection) { newPlugInCollection.FireEnterLeave(true, rawStylusInput, true); } // (Comment not applicable until RTI back in) We are on the RTI thread, just call directly. newPlugInCollection.FireRawStylusInput(rawStylusInput); // Indicate we've used a stylus plugin StylusLogic.CurrentStylusLogic.Statistics.FeaturesUsed |= Tracing.StylusTraceLogger.FeatureFlags.StylusPluginsUsed; // Fire custom data events (always confirmed for mouse) foreach (RawStylusInputCustomData customData in rawStylusInput.CustomDataList) { customData.Owner.FireCustomData(customData.Data, inputReport.Actions, true); } } return(newPlugInCollection); }
internal StylusPlugInCollection TargetPlugInCollection(RawStylusInputReport inputReport) { // Caller must make call to this routine inside of lock(__rtiLock)! StylusPlugInCollection pic = null; // We should only be called when not on the application thread! System.Diagnostics.Debug.Assert(!inputReport.StylusDevice.CheckAccess()); WispStylusDevice stylusDevice = inputReport.StylusDevice.As <WispStylusDevice>(); // We're on the pen thread so can't touch visual tree. Use capturedPlugIn (if capture on) or cached rects. bool elementHasCapture = false; pic = stylusDevice.GetCapturedPlugInCollection(ref elementHasCapture); int pointLength = inputReport.PenContext.StylusPointDescription.GetInputArrayLengthPerPoint(); // Make sure that the captured Plugin Collection is still in the list. CaptureChanges are // deferred so there is a window where the stylus device is not updated yet. This protects us // from using a bogus plugin collecton for an element that is in an invalid state. if (elementHasCapture && !_plugInCollectionList.Contains(pic)) { elementHasCapture = false; // force true hittesting to be done! } if (!elementHasCapture && inputReport.Data != null && inputReport.Data.Length >= pointLength) { int[] data = inputReport.Data; System.Diagnostics.Debug.Assert(data.Length % pointLength == 0); Point ptTablet = new Point(data[data.Length - pointLength], data[data.Length - pointLength + 1]); // Note: the StylusLogic data inside DeviceUnitsFromMeasurUnits is protected by __rtiLock. ptTablet = ptTablet * stylusDevice.TabletDevice.TabletDeviceImpl.TabletToScreen; ptTablet.X = (int)Math.Round(ptTablet.X); // Make sure we snap to whole window pixels. ptTablet.Y = (int)Math.Round(ptTablet.Y); ptTablet = _stylusLogic.MeasureUnitsFromDeviceUnits(ptTablet); // change to measured units now. pic = HittestPlugInCollection(ptTablet); // Use cached rectangles for UIElements. } return(pic); }
/// <summary> /// Target a plugin collection that either has capture or passes a hit test. /// raw input. /// </summary> /// <param name="inputReport">The raw input to process</param> /// <returns>The appropriate collection target</returns> internal StylusPlugInCollection TargetPlugInCollection(RawStylusInputReport inputReport) { StylusPlugInCollection pic = null; PointerStylusDevice stylusDevice = inputReport.StylusDevice.As <PointerStylusDevice>(); bool elementHasCapture = false; pic = stylusDevice.GetCapturedPlugInCollection(ref elementHasCapture); int pointLength = inputReport.StylusPointDescription.GetInputArrayLengthPerPoint(); // Make sure that the captured Plugin Collection is still in the list. CaptureChanges are // deferred so there is a window where the stylus device is not updated yet. This protects us // from using a bogus plugin collecton for an element that is in an invalid state. if (elementHasCapture && !_plugInCollectionList.Contains(pic)) { elementHasCapture = false; // force true hittesting to be done! } if (!elementHasCapture && inputReport.Data != null && inputReport.Data.Length >= pointLength) { int[] data = inputReport.Data; System.Diagnostics.Debug.Assert(data.Length % pointLength == 0); Point ptTablet = new Point(data[data.Length - pointLength], data[data.Length - pointLength + 1]); // Note: the StylusLogic data inside DeviceUnitsFromMeasurUnits is protected by __rtiLock. ptTablet = ptTablet * stylusDevice.TabletDevice.TabletDeviceImpl.TabletToScreen; ptTablet.X = (int)Math.Round(ptTablet.X); // Make sure we snap to whole window pixels. ptTablet.Y = (int)Math.Round(ptTablet.Y); ptTablet *= inputReport.InputSource.CompositionTarget.TransformFromDevice; // change to measured units now. pic = HittestPlugInCollection(ptTablet); // Use cached rectangles for UIElements. } return(pic); }
///////////////////////////////////////////////////////////////////// /// <summary> /// [TBS] /// </summary> /// <param name="report">[TBS]</param> /// <param name="tabletToElementTransform">[TBS]</param> /// <param name="targetPlugInCollection">[TBS]</param> internal RawStylusInput( RawStylusInputReport report, GeneralTransform tabletToElementTransform, StylusPlugInCollection targetPlugInCollection) { if (report == null) { throw new ArgumentNullException("report"); } if (tabletToElementTransform.Inverse == null) { throw new ArgumentException(SR.Get(SRID.Stylus_MatrixNotInvertable), "tabletToElementTransform"); } if (targetPlugInCollection == null) { throw new ArgumentNullException("targetPlugInCollection"); } // We should always see this GeneralTransform is frozen since we access this from multiple threads. System.Diagnostics.Debug.Assert(tabletToElementTransform.IsFrozen); _report = report; _tabletToElementTransform = tabletToElementTransform; _targetPlugInCollection = targetPlugInCollection; }
internal void RemoveStylusPlugInCollection(StylusPlugInCollection pic) { // must be called from inside of lock(__rtiLock) _plugInCollectionList.Remove(pic); }
internal void InvokeStylusPluginCollection(RawStylusInputReport inputReport) { // Find PenContexts object for this inputReport. StylusPlugInCollection pic = null; // lock to make sure only one event is processed at a time and no changes to state can // be made until we finish routing this event. lock (__rtiLock) { switch (inputReport.Actions) { case RawStylusActions.Down: case RawStylusActions.Move: case RawStylusActions.Up: // Figure out current target plugincollection. pic = TargetPlugInCollection(inputReport); break; default: return; // Nothing to do unless one of the above events } WispStylusDevice stylusDevice = inputReport.StylusDevice.As <WispStylusDevice>(); StylusPlugInCollection currentPic = stylusDevice.CurrentNonVerifiedTarget; // Fire Leave event if we need to. if (currentPic != null && currentPic != pic) { // Create new RawStylusInput to send GeneralTransformGroup transformTabletToView = new GeneralTransformGroup(); transformTabletToView.Children.Add(new MatrixTransform(_stylusLogic.GetTabletToViewTransform(stylusDevice.TabletDevice))); // this gives matrix in measured units (not device) transformTabletToView.Children.Add(currentPic.ViewToElement); // Make it relative to the element. transformTabletToView.Freeze(); // Must be frozen for multi-threaded access. RawStylusInput tempRawStylusInput = new RawStylusInput(inputReport, transformTabletToView, currentPic); currentPic.FireEnterLeave(false, tempRawStylusInput, false); // Indicate we've used a stylus plugin _stylusLogic.Statistics.FeaturesUsed |= Tracing.StylusTraceLogger.FeatureFlags.StylusPluginsUsed; stylusDevice.CurrentNonVerifiedTarget = null; } if (pic != null) { // NOTE: PenContext info will not change (it gets rebuilt instead so keeping ref is fine) // The transformTabletToView matrix and plugincollection rects though can change based // off of layout events which is why we need to lock this. GeneralTransformGroup transformTabletToView = new GeneralTransformGroup(); transformTabletToView.Children.Add(new MatrixTransform(_stylusLogic.GetTabletToViewTransform(stylusDevice.TabletDevice))); // this gives matrix in measured units (not device) transformTabletToView.Children.Add(pic.ViewToElement); // Make it relative to the element. transformTabletToView.Freeze(); // Must be frozen for multi-threaded access. RawStylusInput rawStylusInput = new RawStylusInput(inputReport, transformTabletToView, pic); inputReport.RawStylusInput = rawStylusInput; if (pic != currentPic) { stylusDevice.CurrentNonVerifiedTarget = pic; pic.FireEnterLeave(true, rawStylusInput, false); } // We are on the pen thread, just call directly. pic.FireRawStylusInput(rawStylusInput); // Indicate we've used a stylus plugin _stylusLogic.Statistics.FeaturesUsed |= Tracing.StylusTraceLogger.FeatureFlags.StylusPluginsUsed; } } // lock(__rtiLock) }
/// <summary> /// Adds a plugin collection in the Z order that its owning element appears graphically /// </summary> /// <param name="pic"></param> internal void AddStylusPlugInCollection(StylusPlugInCollection pic) { // insert in ZOrder _plugInCollectionList.Insert(FindZOrderIndex(pic), pic); }
internal int FindZOrderIndex(StylusPlugInCollection spicAdding) { //should be called inside of lock(__rtiLock) DependencyObject spicAddingVisual = spicAdding.Element as Visual; int i; for (i = 0; i < _plugInCollectionList.Count; i++) { // first see if parent of node, if it is then we can just scan till we find the // first non parent and we're done DependencyObject curV = _plugInCollectionList[i].Element as Visual; if (VisualTreeHelper.IsAncestorOf(spicAddingVisual, curV)) { i++; while (i < _plugInCollectionList.Count) { curV = _plugInCollectionList[i].Element as Visual; if (!VisualTreeHelper.IsAncestorOf(spicAddingVisual, curV)) { break; // done } i++; } return(i); } else { // Look to see if spicAddingVisual is higher in ZOrder than i, if so then we're done DependencyObject commonParent = VisualTreeHelper.FindCommonAncestor(spicAddingVisual, curV); // If no common parent found then we must have multiple plugincollection elements // that have been removed from the visual tree and we haven't been notified yet of // that change. In this case just ignore this plugincollection element and go to // the next. if (commonParent == null) { continue; } // If curV is the commonParent we find then we're done. This new plugin should be // above this one. if (curV == commonParent) { return(i); } // now find first child for each under that common visual that these fall under (not they must be different or common parent is sort of busted. while (VisualTreeHelper.GetParentInternal(spicAddingVisual) != commonParent) { spicAddingVisual = VisualTreeHelper.GetParentInternal(spicAddingVisual); } while (VisualTreeHelper.GetParentInternal(curV) != commonParent) { curV = VisualTreeHelper.GetParentInternal(curV); } // now see which is higher in zorder int count = VisualTreeHelper.GetChildrenCount(commonParent); for (int j = 0; j < count; j++) { DependencyObject child = VisualTreeHelper.GetChild(commonParent, j); if (child == spicAddingVisual) { return(i); } else if (child == curV) { break; // look at next index in _piList. } } } } return(i); // this wasn't higher so return last index. }
internal void RemoveStylusPlugInCollection(StylusPlugInCollection pic) { _plugInCollectionList.Remove(pic); }
internal StylusPlugInCollection InvokeStylusPluginCollectionForMouse(RawStylusInputReport inputReport, IInputElement directlyOver, StylusPlugInCollection currentPlugInCollection) { StylusPlugInCollection newPlugInCollection = null; // lock to make sure only one event is processed at a time and no changes to state can // be made until we finish routing this event. lock(__rtiLock) { //Debug.Assert(inputReport.Actions == RawStylusActions.Down || // inputReport.Actions == RawStylusActions.Up || // inputReport.Actions == RawStylusActions.Move); // Find new target plugin collection if (directlyOver != null) { UIElement uiElement = InputElement.GetContainingUIElement(directlyOver as DependencyObject) as UIElement; if (uiElement != null) { newPlugInCollection = FindPlugInCollection(uiElement); } } // Fire Leave event to old pluginCollection if we need to. if (currentPlugInCollection != null && currentPlugInCollection != newPlugInCollection) { // NOTE: input report points for mouse are in avalon measured units and not device! RawStylusInput tempRawStylusInput = new RawStylusInput(inputReport, currentPlugInCollection.ViewToElement, currentPlugInCollection); currentPlugInCollection.FireEnterLeave(false, tempRawStylusInput, true); } if (newPlugInCollection != null) { // NOTE: input report points for mouse are in avalon measured units and not device! RawStylusInput rawStylusInput = new RawStylusInput(inputReport, newPlugInCollection.ViewToElement, newPlugInCollection); inputReport.RawStylusInput = rawStylusInput; if (newPlugInCollection != currentPlugInCollection) { newPlugInCollection.FireEnterLeave(true, rawStylusInput, true); } // We are on the pen thread, just call directly. newPlugInCollection.FireRawStylusInput(rawStylusInput); // Fire custom data events (always confirmed for mouse) foreach (RawStylusInputCustomData customData in rawStylusInput.CustomDataList) { customData.Owner.FireCustomData(customData.Data, inputReport.Actions, true); } } } return newPlugInCollection; }
internal int FindZOrderIndex(StylusPlugInCollection spicAdding) { //should be called inside of lock(__rtiLock) DependencyObject spicAddingVisual = spicAdding.Element as Visual; int i; for (i=0; i < _plugInCollectionList.Count; i++) { // first see if parent of node, if it is then we can just scan till we find the // first non parent and we're done DependencyObject curV = _plugInCollectionList[i].Element as Visual; if (VisualTreeHelper.IsAncestorOf(spicAddingVisual, curV)) { i++; while (i < _plugInCollectionList.Count) { curV = _plugInCollectionList[i].Element as Visual; if (!VisualTreeHelper.IsAncestorOf(spicAddingVisual, curV)) break; // done i++; } return i; } else { // Look to see if spicAddingVisual is higher in ZOrder than i, if so then we're done DependencyObject commonParent = VisualTreeHelper.FindCommonAncestor(spicAddingVisual, curV); // If no common parent found then we must have multiple plugincollection elements // that have been removed from the visual tree and we haven't been notified yet of // that change. In this case just ignore this plugincollection element and go to // the next. if (commonParent == null) continue; // If curV is the commonParent we find then we're done. This new plugin should be // above this one. if (curV == commonParent) return i; // now find first child for each under that common visual that these fall under (not they must be different or common parent is sort of busted. while (VisualTreeHelper.GetParentInternal(spicAddingVisual) != commonParent) spicAddingVisual = VisualTreeHelper.GetParentInternal(spicAddingVisual); while (VisualTreeHelper.GetParentInternal(curV) != commonParent) curV = VisualTreeHelper.GetParentInternal(curV); // now see which is higher in zorder int count = VisualTreeHelper.GetChildrenCount(commonParent); for (int j = 0; j < count; j++) { DependencyObject child = VisualTreeHelper.GetChild(commonParent, j); if (child == spicAddingVisual) return i; else if (child == curV) break; // look at next index in _piList. } } } return i; // this wasn't higher so return last index. }
/// <summary> /// Verifies that the call to the stylus plugin on the RTI thread was valid against the current visual tree. /// If this verification fails, we will rebuild and resend the raw input and custom data in order to inform /// the target collections of the error and fix it. /// </summary> /// <remarks> /// This is a remnant of verifying hits to the collections based on the UI thread calling this /// after the real time input thread has previously called a collection. This is due to the RTI thread /// not being 100% synchronous with the visual tree in terms of hitting the collections. This is sort of /// redundant right now, but needs to be here when we re-implement the RTI. /// </remarks> internal void VerifyStylusPlugInCollectionTarget(RawStylusInputReport rawStylusInputReport) { switch (rawStylusInputReport.Actions) { case RawStylusActions.Down: case RawStylusActions.Move: case RawStylusActions.Up: break; default: return; // do nothing if not Down, Move or Up. } PointerLogic pointerLogic = StylusLogic.GetCurrentStylusLogicAs <PointerLogic>(); RawStylusInput originalRSI = rawStylusInputReport.RawStylusInput; // See if we have a plugin for the target of this input. StylusPlugInCollection targetPIC = null; StylusPlugInCollection targetRtiPIC = (originalRSI != null) ? originalRSI.Target : null; bool updateEventPoints = false; // Make sure we use UIElement for target if non NULL and hit ContentElement. UIElement newTarget = InputElement.GetContainingUIElement(rawStylusInputReport.StylusDevice.DirectlyOver as DependencyObject) as UIElement; if (newTarget != null) { targetPIC = FindPlugInCollection(newTarget); } // Make sure any lock() calls do not reenter on us. using (Dispatcher.CurrentDispatcher.DisableProcessing()) { // See if we hit the wrong PlugInCollection on the pen thread and clean things up if we did. if (targetRtiPIC != null && targetRtiPIC != targetPIC && originalRSI != null) { // Fire custom data not confirmed events for both pre and post since bad target... foreach (RawStylusInputCustomData customData in originalRSI.CustomDataList) { customData.Owner.FireCustomData(customData.Data, rawStylusInputReport.Actions, false); } updateEventPoints = originalRSI.StylusPointsModified; // Clear RawStylusInput data. rawStylusInputReport.RawStylusInput = null; } // See if we need to build up an RSI to send to the plugincollection (due to a mistarget). bool sendRawStylusInput = false; if (targetPIC != null && rawStylusInputReport.RawStylusInput == null) { // NOTE: (This applies when RTI is back in) Info will not change (it gets rebuilt instead so keeping ref is fine) // The transformTabletToView matrix and plugincollection rects though can change based // off of layout events which is why we need to lock this. GeneralTransformGroup transformTabletToView = new GeneralTransformGroup(); transformTabletToView.Children.Add(rawStylusInputReport.StylusDevice.As <PointerStylusDevice>().GetTabletToElementTransform(null)); // this gives matrix in measured units (not device) transformTabletToView.Children.Add(targetPIC.ViewToElement); // Make it relative to the element. transformTabletToView.Freeze(); // Must be frozen for multi-threaded access. RawStylusInput rawStylusInput = new RawStylusInput(rawStylusInputReport, transformTabletToView, targetPIC); rawStylusInputReport.RawStylusInput = rawStylusInput; sendRawStylusInput = true; } PointerStylusDevice stylusDevice = rawStylusInputReport.StylusDevice.As <PointerStylusDevice>(); // Now fire the confirmed enter/leave events as necessary. StylusPlugInCollection currentTarget = stylusDevice.CurrentVerifiedTarget; if (targetPIC != currentTarget) { if (currentTarget != null) { // Fire leave event. If we never had a plugin for this event then create a temp one. if (originalRSI == null) { GeneralTransformGroup transformTabletToView = new GeneralTransformGroup(); transformTabletToView.Children.Add(stylusDevice.GetTabletToElementTransform(null)); // this gives matrix in measured units (not device) transformTabletToView.Children.Add(currentTarget.ViewToElement); // Make it relative to the element. transformTabletToView.Freeze(); // Must be frozen for multi-threaded access. originalRSI = new RawStylusInput(rawStylusInputReport, transformTabletToView, currentTarget); } currentTarget.FireEnterLeave(false, originalRSI, true); } if (targetPIC != null) { // Fire Enter event targetPIC.FireEnterLeave(true, rawStylusInputReport.RawStylusInput, true); // Indicate we've used a stylus plugin pointerLogic.Statistics.FeaturesUsed |= Tracing.StylusTraceLogger.FeatureFlags.StylusPluginsUsed; } // Update the verified target. stylusDevice.CurrentVerifiedTarget = targetPIC; } // Now fire RawStylusInput if needed to the right plugincollection. if (sendRawStylusInput) { // We are on the pen thread, just call directly. targetPIC.FireRawStylusInput(rawStylusInputReport.RawStylusInput); updateEventPoints = (updateEventPoints || rawStylusInputReport.RawStylusInput.StylusPointsModified); // Indicate we've used a stylus plugin pointerLogic.Statistics.FeaturesUsed |= Tracing.StylusTraceLogger.FeatureFlags.StylusPluginsUsed; } // Now fire PrePreviewCustomData events. if (targetPIC != null) { // Send custom data pre event foreach (RawStylusInputCustomData customData in rawStylusInputReport.RawStylusInput.CustomDataList) { customData.Owner.FireCustomData(customData.Data, rawStylusInputReport.Actions, true); } } // VerifyRawTarget might resend to correct plugins or may have hit the wrong plugincollection. The StylusPackets // may be overriden in those plugins so we need to call UpdateEventStylusPoints to update things. if (updateEventPoints) { rawStylusInputReport.StylusDevice.As <PointerStylusDevice>().UpdateEventStylusPoints(rawStylusInputReport, true); } } }
internal void ChangeStylusCapture(IInputElement stylusCapture, CaptureMode captureMode, int timestamp) { // if the capture changed... if (stylusCapture != _stylusCapture) { // Actually change the capture first. Invalidate the properties, // and then send the events. IInputElement oldStylusCapture = _stylusCapture; _stylusCapture = stylusCapture; _captureMode = captureMode; // We also need to figure out ahead of time if any plugincollections on this captured element (or a parent) // for the penthread hittesting code. _stylusCapturePlugInCollection = null; if (stylusCapture != null) { UIElement uiElement = InputElement.GetContainingUIElement(stylusCapture as DependencyObject) as UIElement; if (uiElement != null) { PresentationSource source = PresentationSource.CriticalFromVisual(uiElement as Visual); if (source != null) { PointerStylusPlugInManager manager; if (_pointerLogic.PlugInManagers.TryGetValue(source, out manager)) { _stylusCapturePlugInCollection = manager.FindPlugInCollection(uiElement); } } } } _pointerLogic.UpdateStylusCapture(this, oldStylusCapture, _stylusCapture, timestamp); // Send the LostStylusCapture and GotStylusCapture events. if (oldStylusCapture != null) { StylusEventArgs lostCapture = new StylusEventArgs(StylusDevice, timestamp); lostCapture.RoutedEvent = Stylus.LostStylusCaptureEvent; lostCapture.Source = oldStylusCapture; InputManager.UnsecureCurrent.ProcessInput(lostCapture); } if (_stylusCapture != null) { StylusEventArgs gotCapture = new StylusEventArgs(StylusDevice, timestamp); gotCapture.RoutedEvent = Stylus.GotStylusCaptureEvent; gotCapture.Source = _stylusCapture; InputManager.UnsecureCurrent.ProcessInput(gotCapture); } // Now update the stylus over state (only if this is the current stylus and // it is inrange). if (_pointerLogic.CurrentStylusDevice == this || InRange) { if (_stylusCapture != null) { IInputElement inputElementHit = _stylusCapture; // See if we need to update over for subtree mode. if (CapturedMode == CaptureMode.SubTree && _inputSource != null && _inputSource.Value != null) { Point pt = _pointerLogic.DeviceUnitsFromMeasureUnits(GetPosition(null)); inputElementHit = FindTarget(_inputSource.Value, pt); } ChangeStylusOver(inputElementHit); } else { // Only try to update over if we have a valid input source. if (_inputSource != null && _inputSource.Value != null) { Point pt = GetPosition(null); // relative to window (root element) pt = _pointerLogic.DeviceUnitsFromMeasureUnits(pt); // change back to device coords. IInputElement currentOver = Input.StylusDevice.GlobalHitTest(_inputSource.Value, pt); ChangeStylusOver(currentOver); } } } // For Mouse StylusDevice we want to make sure Mouse capture is set up the same. if (Mouse.Captured != _stylusCapture || Mouse.CapturedMode != _captureMode) { Mouse.Capture(_stylusCapture, _captureMode); } } }
///////////////////////////////////////////////////////////////////// // (in Dispatcher) internal void Added(StylusPlugInCollection plugInCollection) { _pic = plugInCollection; OnAdded(); InvalidateIsActiveForInput(); // Make sure we fire OnIsActivateForInputChanged. }