internal WispTabletDevice(TabletDeviceInfo tabletInfo, PenThread penThread) : base(tabletInfo) { _penThread = penThread; int count = tabletInfo.StylusDevicesInfo.Length; WispStylusDevice[] styluses = new WispStylusDevice[count]; for (int i = 0; i < count; i++) { StylusDeviceInfo cursorInfo = tabletInfo.StylusDevicesInfo[i]; styluses[i] = new WispStylusDevice( this, cursorInfo.CursorName, cursorInfo.CursorId, cursorInfo.CursorInverted, cursorInfo.ButtonCollection); } _stylusDeviceCollection = new StylusDeviceCollection(styluses); // We only create a TabletDevice when one is connected (physically or virtually). // So we can log the connection in the constructor. StylusTraceLogger.LogDeviceConnect( new StylusTraceLogger.StylusDeviceInfo( Id, Name, ProductId, TabletHardwareCapabilities, TabletSize, ScreenSize, _tabletInfo.DeviceType, StylusDevices.Count)); }
internal WispStylusDevice UpdateStylusDevices(int stylusId) { // REENTRANCY NOTE: Use PenThread to talk to wisptis.exe to make sure we are not reentrant! // PenImc will cache all the stylus device info so we don't have // any Out of Proc calls to wisptis.exe to get this info. StylusDeviceInfo[] stylusDevicesInfo = _penThread.WorkerRefreshCursorInfo(_tabletInfo.PimcTablet.Value); int cCursors = stylusDevicesInfo.Length; if (cCursors > StylusDevices.Count) { for (int iCursor = 0; iCursor < cCursors; iCursor++) { StylusDeviceInfo stylusDeviceInfo = stylusDevicesInfo[iCursor]; // See if we found it. If so go and create the new StylusDevice and add it. if (stylusDeviceInfo.CursorId == stylusId) { WispStylusDevice newStylusDevice = new WispStylusDevice( this, stylusDeviceInfo.CursorName, stylusDeviceInfo.CursorId, stylusDeviceInfo.CursorInverted, stylusDeviceInfo.ButtonCollection); StylusDevices.AddStylusDevice(iCursor, newStylusDevice); return(newStylusDevice); } } } return(null); // Nothing to add }
///////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////// internal WispTabletDevice(TabletDeviceInfo tabletInfo, PenThread penThread) : base(tabletInfo) { _penThread = penThread; // Constructing a WispTabletDevice means we will actually use this tablet for input purposes. // Lock the tablet and underlying WISP tablet at this point. // This is balanced in DisposeOrDeferDisposal. _penThread.WorkerAcquireTabletLocks(tabletInfo.PimcTablet.Value, tabletInfo.WispTabletKey); int count = tabletInfo.StylusDevicesInfo.Length; WispStylusDevice[] styluses = new WispStylusDevice[count]; for (int i = 0; i < count; i++) { StylusDeviceInfo cursorInfo = tabletInfo.StylusDevicesInfo[i]; styluses[i] = new WispStylusDevice( this, cursorInfo.CursorName, cursorInfo.CursorId, cursorInfo.CursorInverted, cursorInfo.ButtonCollection); } _stylusDeviceCollection = new StylusDeviceCollection(styluses); // We only create a TabletDevice when one is connected (physically or virtually). // So we can log the connection in the constructor. StylusTraceLogger.LogDeviceConnect( new StylusTraceLogger.StylusDeviceInfo( Id, Name, ProductId, TabletHardwareCapabilities, TabletSize, ScreenSize, _tabletInfo.DeviceType, StylusDevices.Count)); }
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); }
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) }