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 PenContext[] CreateContexts(IntPtr hwnd, PenContexts contexts) { int c = Count + _deferredTablets.Count; PenContext[] ctxs = new PenContext[c]; int i = 0; foreach (TabletDevice tablet in _tablets) { ctxs[i++] = tablet.CreateContext(hwnd, contexts); } // DevDiv:1078091 // We need to re-enable contexts for anything that is marked // as a pending disposal. This is so we continue getting any // Wisp messages that might be waiting to come over the shared // memory channel. foreach (TabletDevice tablet in _deferredTablets) { ctxs[i++] = tablet.CreateContext(hwnd, contexts); } return(ctxs); }
/// <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 bool ConsiderInRange(int timestamp) { if (_contexts != null) { for (int i = 0; i < _contexts.Length; i++) { PenContext context = _contexts[i]; // We consider it InRange if we have a queued up context event or // the timestamp - LastInRangeTime <= 500 (seen one in the last 500ms) // Here's some info on how this works... // int.MaxValue - int.MinValue = -1 (subtracting any negative # from MaxValue keeps this negative) // int.MinValue - int.MaxValue = 1 (subtracting any positive # from MinValue keeps this positive) // So subtracting wrapping values will return proper sign depending on which was earlier. // We do have the assumption that these values will be relative close in time. If the // time wraps we'll say yet but the only harm is that we may defer a mouse move event temporarily // which won't cause any harm. if (context.QueuedInRangeCount > 0 || (Math.Abs(unchecked (timestamp - context.LastInRangeTime)) <= 500)) { return(true); } } } return(false); }
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 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 static PenThread GetPenThreadForPenContext(PenContext penContext) { // Create the threadstatic DynamicRendererThreadManager as needed for calling thread. // It only creates one if (_penThreadPool == null) { _penThreadPool = new PenThreadPool(); } return _penThreadPool.GetPenThreadForPenContextHelper(penContext); // Adds to weak ref list if creating new one. }
///////////////////////////////////////////////////////////////////// /// <summary> /// </summary> internal static PenThread GetPenThreadForPenContext(PenContext penContext) { // Create the threadstatic DynamicRendererThreadManager as needed for calling thread. // It only creates one if (_penThreadPool == null) { _penThreadPool = new PenThreadPool(); } return(_penThreadPool.GetPenThreadForPenContextHelper(penContext)); // Adds to weak ref list if creating new one. }
private PenThread GetPenThreadForPenContextHelper(PenContext penContext) { bool needCleanup = false; PenThread penThread = null; int i; // Scan existing penthreads to see if we have an available slot for context. for (i = 0; i < _penThreadWeakRefList.Count; i++) { PenThread penThreadFound = _penThreadWeakRefList[i].Target as PenThread; if (penThreadFound == null) { needCleanup = true; } else { // See if we can use this one if (penContext == null || penThreadFound.AddPenContext(penContext)) { // We can use this one. penThread = penThreadFound; break; } } } if (needCleanup) { // prune invalid refs for (i = _penThreadWeakRefList.Count - 1; i >= 0; i--) { if (_penThreadWeakRefList[i].Target == null) { _penThreadWeakRefList.RemoveAt(i); } } } if (penThread == null) { penThread = new PenThread(); // Make sure we add this context to the penthread if (penContext != null) { penThread.AddPenContext(penContext); } _penThreadWeakRefList.Add(new WeakReference(penThread)); } return(penThread); }
internal PenContext[] CreateContexts(IntPtr hwnd, PenContexts contexts) { int c = Count; PenContext[] ctxs = new PenContext[c]; int i = 0; foreach (TabletDevice tablet in _tablets) { ctxs[i] = tablet.CreateContext(hwnd, contexts); i++; } return(ctxs); }
///////////////////////////////////////////////////////////////////// /// <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); }
///////////////////////////////////////////////////////////////////////// internal PenContext GetTabletDeviceIDPenContext(int tabletDeviceId) { if (_contexts != null) { for (int i = 0; i < _contexts.Length; i++) { PenContext context = _contexts[i]; if (context.TabletDeviceId == tabletDeviceId) { return(context); } } } return(null); }
internal PenContext CreateContext(IntPtr hwnd, PenContexts contexts) { PenContext penContext; bool supportInRange = (this.TabletHardwareCapabilities & TabletHardwareCapabilities.HardProximity) != 0; bool isIntegrated = (this.TabletHardwareCapabilities & TabletHardwareCapabilities.Integrated) != 0; // Use a PenThread to create a tablet context so we don't cause reentrancy. PenContextInfo result = _penThread.WorkerCreateContext(hwnd, _tabletInfo.PimcTablet.Value); penContext = new PenContext(result.PimcContext != null ? result.PimcContext.Value : null, hwnd, contexts, supportInRange, isIntegrated, result.ContextId, result.CommHandle != null ? result.CommHandle.Value : IntPtr.Zero, Id); return(penContext); }
///////////////////////////////////////////////////////////////////// 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); }
///////////////////////////////////////////////////////////////////// /// <summary> /// This method adds the specified pen context index in response /// to the WM_TABLET_ADDED notification /// </summary> internal void AddContext(uint index) { // We only tear down the old context when PenContexts are enabled without being // dispose and we have a valid index. Otherwise, no-op here. if (_contexts != null && index <= _contexts.Length && _inputSource.Value.CriticalHandle != IntPtr.Zero) { PenContext[] ctxs = new PenContext[_contexts.Length + 1]; uint preCopyCount = index; uint postCopyCount = (uint)_contexts.Length - index; Array.Copy(_contexts, 0, ctxs, 0, preCopyCount); PenContext newContext = _stylusLogic.TabletDevices[(int)index].As <WispTabletDevice>().CreateContext(_inputSource.Value.CriticalHandle, this); ctxs[index] = newContext; Array.Copy(_contexts, index, ctxs, index + 1, postCopyCount); _contexts = ctxs; newContext.Enable(); } }
///////////////////////////////////////////////////////////////////// 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); }
///////////////////////////////////////////////////////////////////// /// <summary> /// This method removes the specified pen context index in response /// to the WM_TABLET_REMOVED notification /// </summary> internal void RemoveContext(uint index) { // We only tear down the old context when PenContexts are enabled without being // dispose and we have a valid index. Otherwise, no-op here. if (_contexts != null && index < _contexts.Length) { PenContext removeCtx = _contexts[index]; PenContext[] ctxs = new PenContext[_contexts.Length - 1]; uint preCopyCount = index; uint postCopyCount = (uint)_contexts.Length - index - 1; Array.Copy(_contexts, 0, ctxs, 0, preCopyCount); Array.Copy(_contexts, index + 1, ctxs, index, postCopyCount); removeCtx.Disable(false); // shut down this context. _contexts = ctxs; } }
bool DoCacheEvent(int evt, PenContext penContext, int stylusPointerId, int [] data, int timestamp) { // NOTE: Big assumption is that we always get other events between packets (ie don't get move // down position followed by move in up position). We don't account for that here but it should // never happen. if (evt == PenEventPackets) { // If no cache then just cache it. if (_cachedMoveData == null) { _cachedMovePenContext = penContext; _cachedMoveStylusPointerId = stylusPointerId; _cachedMoveStartTimestamp = timestamp; _cachedMoveData = data; return true; } else if (_cachedMovePenContext == penContext && stylusPointerId == _cachedMoveStylusPointerId) { int sinceBeginning = timestamp - _cachedMoveStartTimestamp; if (timestamp < _cachedMoveStartTimestamp) sinceBeginning = (Int32.MaxValue - _cachedMoveStartTimestamp) + timestamp; if (EventsFrequency > sinceBeginning) { // Add to cache data int[] data0 = _cachedMoveData; _cachedMoveData = new int [data0.Length + data.Length]; data0.CopyTo(_cachedMoveData, 0); data.CopyTo(_cachedMoveData, data0.Length); return true; } } } return false; }
void FlushCache(bool goingOutOfRange) { // Force any cached move/inairmove data to be flushed if we have any. if (_cachedMoveData != null) { // If we are going out of range and this stylus id is not currently in range // then eat these cached events (keeps from going in and out of range quickly) if (!goingOutOfRange || _cachedMovePenContext.IsInRange(_cachedMoveStylusPointerId)) { _cachedMovePenContext.FirePenInRange(_cachedMoveStylusPointerId, _cachedMoveData, _cachedMoveStartTimestamp); _cachedMovePenContext.FirePackets(_cachedMoveStylusPointerId, _cachedMoveData, _cachedMoveStartTimestamp); } _cachedMoveData = null; _cachedMovePenContext = null; _cachedMoveStylusPointerId = 0; } }
internal void OnPenOutOfRange(PenContext penContext, int tabletDeviceId, int stylusPointerId, int timestamp) { ProcessInput(RawStylusActions.OutOfRange, penContext, tabletDeviceId, stylusPointerId, new int[]{}, timestamp); }
internal PenContext[] CreateContexts(IntPtr hwnd, PenContexts contexts) { int c = Count; PenContext[] ctxs = new PenContext[c]; int i = 0; foreach (TabletDevice tablet in _tablets) { ctxs[i] = tablet.CreateContext(hwnd, contexts); i++; } return ctxs; }
internal PenContext CreateContext(IntPtr hwnd, PenContexts contexts) { PenContext penContext; bool supportInRange = (this.TabletHardwareCapabilities & TabletHardwareCapabilities.HardProximity) != 0; bool isIntegrated = (this.TabletHardwareCapabilities & TabletHardwareCapabilities.Integrated) != 0; // Use a PenThread to create a tablet context so we don't cause reentrancy. PenContextInfo result = _penThread.WorkerCreateContext(hwnd, _tabletInfo.PimcTablet.Value); penContext = new PenContext(result.PimcContext != null ? result.PimcContext.Value : null, hwnd, contexts, supportInRange, isIntegrated, result.ContextId, result.CommHandle != null ? result.CommHandle.Value : IntPtr.Zero, Id); return penContext; }
///////////////////////////////////////////////////////////////////// internal void OnPenOutOfRange(PenContext penContext, int tabletDeviceId, int stylusPointerId, int timestamp) { ProcessInput(RawStylusActions.OutOfRange, penContext, tabletDeviceId, stylusPointerId, new int[] {}, timestamp); }
internal bool AddPenContext(PenContext penContext) { return _penThreadWorker.WorkerAddPenContext(penContext); }
internal void OnInAirPackets(PenContext penContext, int tabletDeviceId, int stylusPointerId, int[] data, int timestamp) { ProcessInput(RawStylusActions.InAirMove, penContext, tabletDeviceId, stylusPointerId, data, timestamp); }
internal bool AddPenContext(PenContext penContext) { return(_penThreadWorker.WorkerAddPenContext(penContext)); }
internal void AddContext(uint index) { // We only tear down the old context when PenContexts are enabled without being // dispose and we have a valid index. Otherwise, no-op here. if (_contexts != null && index <= _contexts.Length && _inputSource.Value.CriticalHandle != IntPtr.Zero) { PenContext[] ctxs = new PenContext[_contexts.Length + 1]; uint preCopyCount = index; uint postCopyCount = (uint)_contexts.Length - index; Array.Copy(_contexts, 0, ctxs, 0, preCopyCount); PenContext newContext = _stylusLogic.TabletDevices[(int)index].CreateContext(_inputSource.Value.CriticalHandle, this); ctxs[index] = newContext; Array.Copy(_contexts, index, ctxs, index+1, postCopyCount); _contexts = ctxs; newContext.Enable(); } }
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); }
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 void FireEvent(PenContext penContext, int evt, int stylusPointerId, int cPackets, int cbPacket, IntPtr pPackets) { // disposed? if (__disposed) { return; // Don't process this event if we're in the process of shutting down. } // marshal the data to our cache if (cbPacket % 4 != 0) { throw new InvalidOperationException(SR.Get(SRID.PenService_InvalidPacketData)); } int cItems = cPackets * (cbPacket / 4); int[] data = null; if (0 < cItems) { data = new int [cItems]; // GetDataArray(cItems); // see comment on GetDataArray Marshal.Copy(pPackets, data, 0, cItems); penContext.CheckForRectMappingChanged(data, cPackets); } else { data = null; } int timestamp = Environment.TickCount; // Deal with caching packet data. if (DoCacheEvent(evt, penContext, stylusPointerId, data, timestamp)) { return; } else { FlushCache(false); // make sure we flush cache if not caching. } // // fire it // switch (evt) { case PenEventPenDown: penContext.FirePenInRange(stylusPointerId, data, timestamp); penContext.FirePenDown(stylusPointerId, data, timestamp); break; case PenEventPenUp: penContext.FirePenInRange(stylusPointerId, data, timestamp); penContext.FirePenUp(stylusPointerId, data, timestamp); break; case PenEventPackets: penContext.FirePenInRange(stylusPointerId, data, timestamp); penContext.FirePackets(stylusPointerId, data, timestamp); break; case PenEventPenInRange: // We fire this special event just to give the app thread an early peak at // the inrange to filter out mouse moves before we get our first stylus event. penContext.FirePenInRange(stylusPointerId, null, timestamp); break; case PenEventPenOutOfRange: penContext.FirePenOutOfRange(stylusPointerId, timestamp); break; case PenEventSystem: penContext.FireSystemGesture(stylusPointerId, timestamp); break; } }
internal bool RemovePenContext(PenContext penContext) { return _penThreadWorker.WorkerRemovePenContext(penContext); }
internal void UpdateInRange(bool inRange, PenContext penContext) { _fInRange = inRange; // Make sure we clean the last _inputSource for down at this time. //_inputSourceForDown = null; if (inRange) _activePenContext = new SecurityCriticalDataClass<PenContext>(penContext); else _activePenContext = null; }
///////////////////////////////////////////////////////////////////// internal void OnInAirPackets(PenContext penContext, int tabletDeviceId, int stylusPointerId, int[] data, int timestamp) { ProcessInput(RawStylusActions.InAirMove, penContext, tabletDeviceId, stylusPointerId, data, timestamp); }
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); }
internal WorkerOperationRemoveContext(PenContext penContext, PenThreadWorker penThreadWorker) { _penContextToRemove = penContext; _penThreadWorker = penThreadWorker; }
internal bool WorkerAddPenContext(PenContext penContext) { if (__disposed) { throw new ObjectDisposedException(null, SR.Get(SRID.Penservice_Disposed)); } Debug.Assert(penContext != null); WorkerOperationAddContext addContextOperation = new WorkerOperationAddContext(penContext, this); lock(_workerOperationLock) { _workerOperation.Add(addContextOperation); } // Kick thread to do this work. MS.Win32.Penimc.UnsafeNativeMethods.RaiseResetEvent(_pimcResetHandle.Value); // Wait for this work to be completed. addContextOperation.DoneEvent.WaitOne(); addContextOperation.DoneEvent.Close(); return addContextOperation.Result; }
private PenThread GetPenThreadForPenContextHelper(PenContext penContext) { bool needCleanup = false; PenThread penThread = null; int i; // Scan existing penthreads to see if we have an available slot for context. for (i=0; i < _penThreadWeakRefList.Count; i++) { PenThread penThreadFound = _penThreadWeakRefList[i].Target as PenThread; if (penThreadFound == null) { needCleanup = true; } else { // See if we can use this one if (penContext == null || penThreadFound.AddPenContext(penContext)) { // We can use this one. penThread = penThreadFound; break; } } } if (needCleanup) { // prune invalid refs for (i=_penThreadWeakRefList.Count - 1; i >= 0; i--) { if (_penThreadWeakRefList[i].Target == null) { _penThreadWeakRefList.RemoveAt(i); } } } if (penThread == null) { penThread = new PenThread(); // Make sure we add this context to the penthread if (penContext != null) { penThread.AddPenContext(penContext); } _penThreadWeakRefList.Add(new WeakReference(penThread)); } return penThread; }
internal bool WorkerRemovePenContext(PenContext penContext) { if (__disposed) { return true; } Debug.Assert(penContext != null); WorkerOperationRemoveContext removeContextOperation = new WorkerOperationRemoveContext(penContext, this); lock(_workerOperationLock) { _workerOperation.Add(removeContextOperation); } // Kick thread to do this work. MS.Win32.Penimc.UnsafeNativeMethods.RaiseResetEvent(_pimcResetHandle.Value); // Wait for this work to be completed. removeContextOperation.DoneEvent.WaitOne(); removeContextOperation.DoneEvent.Close(); return removeContextOperation.Result; }
internal void RemoveContext(uint index) { // We only tear down the old context when PenContexts are enabled without being // dispose and we have a valid index. Otherwise, no-op here. if (_contexts != null && index < _contexts.Length) { PenContext removeCtx = _contexts[index]; PenContext[] ctxs = new PenContext[_contexts.Length - 1]; uint preCopyCount = index; uint postCopyCount = (uint)_contexts.Length - index - 1; Array.Copy(_contexts, 0, ctxs, 0, preCopyCount); Array.Copy(_contexts, index+1, ctxs, index, postCopyCount); removeCtx.Disable(false); // shut down this context. _contexts = ctxs; } }
internal void OnPenInRange(PenContext penContext, int tabletDeviceId, int stylusPointerId, int[] data, int timestamp) { ProcessInput(RawStylusActions.InRange, penContext, tabletDeviceId, stylusPointerId, data, timestamp); }
///////////////////////////////////////////////////////////////////// internal void OnPenUp(PenContext penContext, int tabletDeviceId, int stylusPointerId, int[] data, int timestamp) { ProcessInput(RawStylusActions.Up, penContext, tabletDeviceId, stylusPointerId, data, timestamp); }
internal bool AddPenContext(PenContext penContext) { List <PenContext> penContextRefs = new List<PenContext>(); // keep them alive while processing! int i; bool result = false; // Now go through and figure out the good entries // Need to clean up the list for gc'd references. for (i=0; i<_penContexts.Length; i++) { if (_penContexts[i].IsAlive) { PenContext pc = _penContexts[i].Target as PenContext; // We only need to ref if we have a penContext. if (pc != null) { penContextRefs.Add(pc); } } } // Now try again to see if we have room. if (penContextRefs.Count < MaxContextPerThread) { penContextRefs.Add(penContext); // add the new one to our list. // Now build up the handle array and PimcContext ref array. _pimcContexts = new IPimcContext[penContextRefs.Count]; _penContexts = new WeakReference[penContextRefs.Count]; _handles = new IntPtr[penContextRefs.Count]; for (i=0; i < penContextRefs.Count; i++) { PenContext pc = penContextRefs[i]; // We'd have hole in our array if this ever happened. Debug.Assert(pc != null && pc.CommHandle != IntPtr.Zero); _handles[i] = pc.CommHandle; // Add to array. _pimcContexts[i] = pc._pimcContext.Value; _penContexts[i] = new WeakReference(pc); pc = null; } result = true; } // Now clean up old refs and assign new array. penContextRefs.Clear(); // Make sure we remove refs! penContextRefs = null; return result; }
internal bool RemovePenContext(PenContext penContext) { return(_penThreadWorker.WorkerRemovePenContext(penContext)); }
internal bool RemovePenContext(PenContext penContext) { List <PenContext> penContextRefs = new List<PenContext>(); // keep them alive while processing! int i; bool removed = false; // Now go through and figure out the good entries // Need to clean up the list for gc'd references. for (i=0; i<_penContexts.Length; i++) { if (_penContexts[i].IsAlive) { PenContext pc = _penContexts[i].Target as PenContext; // See if we should keep this PenContext. // We keep if not GC'd and not the removing one (except if it is // in range where we need to wait till it goes out of range). if (pc != null && (pc != penContext || pc.IsInRange(0))) { penContextRefs.Add(pc); } } } removed = !penContextRefs.Contains(penContext); // Now build up the handle array and PimcContext ref array. _pimcContexts = new IPimcContext[penContextRefs.Count]; _penContexts = new WeakReference[penContextRefs.Count]; _handles = new IntPtr[penContextRefs.Count]; for (i=0; i < penContextRefs.Count; i++) { PenContext pc = penContextRefs[i]; // We'd have hole in our array if this ever happened. Debug.Assert(pc != null && pc.CommHandle != IntPtr.Zero); _handles[i] = pc.CommHandle; // Add to array. _pimcContexts[i] = pc._pimcContext.Value; _penContexts[i] = new WeakReference(pc); pc = null; } // Now clean up old refs and assign new array. penContextRefs.Clear(); // Make sure we remove refs! penContextRefs = null; return removed; }
/// <summary> /// DevDiv:1192272 /// /// This function has been changed to avoid re-entrancy issues. Previously, the /// PenThread selection depended on calls to AddPenContext in the selection mechanism /// or when creating a new PenThread. Since AddPenContext will wait on operations done /// on a PenThread, this would allow re-entrant calls to occur. These calls had the /// potential to generate redundant PenThreads that could cause performance and functional /// issues in touch-enabled applications. /// /// By removing calls to AddPenContext from the selection loops, we can be certain that there is /// no re-entrancy possible during this part of the code. The call to AddPenContext is now done /// post thread selection/creation. While this is still re-entrant, we handle the possible issues /// from that case by retrying thread selection for any failed AddPenContext calls, ignoring the /// specific thread that failed. After MAX_PENTHREAD_RETRIES, we exit and log an error. /// </summary> private PenThread GetPenThreadForPenContextHelper(PenContext penContext) { // A list of full PenThreads that we should ignore when attempting to select a thread // for this context. List <PenThread> ignoredThreads = new List <PenThread>(); PenThread selectedPenThread = null; // We have gone over the max retries, something is forcing a huge amount // of re-entrancy. In this case, break the loop and exit even if we might // have some issues with missing touch contexts and bad touch behavior. while (ignoredThreads.Count < MAX_PENTHREAD_RETRIES) { // Scan existing penthreads to find one to add the context to // We scan back to front to enable list cleanup. for (int i = _penThreadWeakRefList.Count - 1; i >= 0; i--) { PenThread candidatePenThread = null; // Select a thread if it's a valid WeakReference and we're not ignoring it // Allow selection to happen multiple times so we get the first valid candidate // in forward order. if (_penThreadWeakRefList[i].TryGetTarget(out candidatePenThread) && !ignoredThreads.Contains(candidatePenThread)) { selectedPenThread = candidatePenThread; } // This is an invalid WeakReference and should be removed else if (candidatePenThread == null) { _penThreadWeakRefList.RemoveAt(i); } } // If no valid thread was found, create a new one and add to the pool if (selectedPenThread == null) { selectedPenThread = new PenThread(); _penThreadWeakRefList.Add(new WeakReference <PenThread>(selectedPenThread)); } // If we have no context or we can successfully add to it, then end with this thread if (penContext == null || selectedPenThread.AddPenContext(penContext)) { break; } // If the add wasn't successful, this thread is full, so try again and ignore it else { ignoredThreads.Add(selectedPenThread); selectedPenThread = null; // Log re-entrant calls StylusTraceLogger.LogReentrancy(); } } // If we're here due to max retries, log errors appropriately if (selectedPenThread == null) { StylusTraceLogger.LogReentrancyRetryLimitReached(); Debug.Assert(false, "Retry limit reached when acquiring PenThread"); } return(selectedPenThread); }
internal WorkerOperationAddContext(PenContext penContext, PenThreadWorker penThreadWorker) { _newPenContext = penContext; _penThreadWorker = penThreadWorker; }
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); } }