internal void Enable() { if (_pimcContext != null && _pimcContext.Value != null) { _penThreadPenContext = PenThreadPool.GetPenThreadForPenContext(this); } }
///////////////////////////////////////////////////////////////////// /// <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. }
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. }
internal bool HandleTabletAdded(uint wisptisIndex, ref uint tabletIndexChanged) { if (_tablets == null) { throw new ObjectDisposedException("TabletDeviceCollection"); } tabletIndexChanged = UInt32.MaxValue; // REENTRANCY NOTE: Let a PenThread do this work to avoid reentrancy! // On return you get the tablet info needed to // create a tablet devices (and stylus device info gets // cached in penimc too which avoids calls to wisptis.exe). // Use existing penthread if we have one otherwise grab an available one. PenThread penThread = _tablets.Length > 0 ? _tablets[0].PenThread : PenThreadPool.GetPenThreadForPenContext(null); TabletDeviceInfo tabletInfo = penThread.WorkerGetTabletInfo(wisptisIndex); // If we failed due to a COM exception on the pen thread then return if (tabletInfo.PimcTablet == null) { return(true); // make sure we rebuild our tablet collection. (return true + MaxValue). } // if mouse tabletdevice then ignore it. if (tabletInfo.DeviceType == (TabletDeviceType)(-1)) { _indexMouseTablet = wisptisIndex; // update index. return(false); // TabletDevices did not change. } // Now see if this is a duplicate add call we want to filter out (ie - already added to tablet collection). uint indexFound = UInt32.MaxValue; for (uint i = 0; i < _tablets.Length; i++) { // If it is the mouse tablet device we want to ignore it. if (_tablets[i].Id == tabletInfo.Id) { indexFound = i; break; } } // We only want to add this if it is not currently in the collection. Wisptis will send // us duplicate adds at times so this is a work around for that issue. uint tabletIndex = UInt32.MaxValue; if (indexFound == UInt32.MaxValue) { tabletIndex = wisptisIndex; if (tabletIndex > _indexMouseTablet) { tabletIndex--; } else { _indexMouseTablet++; } // if index is out of range then ignore it. Return of MaxValue causes a rebuild of the devices. if (tabletIndex <= _tablets.Length) { try { // Add new tablet at end of collection AddTablet(tabletIndex, new TabletDevice(tabletInfo, penThread)); } catch (InvalidOperationException ex) { // This is caused by the Stylus ID not being unique when trying // to register it in the StylusLogic.__stylusDeviceMap. If we // come across a dup then we should rebuild the tablet device collection. // There seems to be an issue in wisptis where different tablet IDs get // duplicate Stylus Ids when installing the VHID test devices. if (ex.Data.Contains("System.Windows.Input.StylusLogic")) { return(true); // trigger the tabletdevices to be rebuilt. } else { throw; // not an expected exception, rethrow it. } } tabletIndexChanged = tabletIndex; return(true); } else { return(true); // bogus index. Return true so that the caller can rebuild the collection. } } else { return(false); // We found this tablet device already. Don't do anything. } }
void UpdateTabletsImpl() { // REENTRANCY NOTE: Let a PenThread do this work to avoid reentrancy! // On return you get entire list of tablet and info needed to // create all the tablet devices (and stylus device info gets // cached too in penimc which avoids calls to wisptis.exe). // Use existing penthread if we have one otherwise grab an available one. PenThread penThread = _tablets.Length > 0 ? _tablets[0].PenThread : PenThreadPool.GetPenThreadForPenContext(null); TabletDeviceInfo [] tabletdevices = penThread.WorkerGetTabletsInfo(); // First find out the index of the mouse device (usually the first at index 0) uint indexMouseTablet = UInt32.MaxValue; for (uint i = 0; i < tabletdevices.Length; i++) { // See if this is a bogus entry first. if (tabletdevices[i].PimcTablet == null) { continue; } // If it is the mouse tablet device we want to ignore it. if (tabletdevices[i].DeviceType == (TabletDeviceType)(-1)) { indexMouseTablet = i; tabletdevices[i].PimcTablet = null; // ignore this one! } } // Now figure out count of valid tablet devices left uint count = 0; for (uint k = 0; k < tabletdevices.Length; k++) { if (tabletdevices[k].PimcTablet != null) { count++; } } TabletDevice[] tablets = new TabletDevice[count]; uint tabletsIndex = 0; uint unchangedTabletCount = 0; for (uint iTablet = 0; iTablet < tabletdevices.Length; iTablet++) { if (tabletdevices[iTablet].PimcTablet == null) { continue; // Skip looking at this index (mouse and bogus tablets are ignored). } int id = tabletdevices[iTablet].Id; // First see if same index has not changed (typical case) if (tabletsIndex < _tablets.Length && _tablets[tabletsIndex] != null && _tablets[tabletsIndex].Id == id) { tablets[tabletsIndex] = _tablets[tabletsIndex]; _tablets[tabletsIndex] = null; // clear to ignore on cleanup pass. unchangedTabletCount++; } else { // Look up and see if we have this tabletdevice created already... TabletDevice tablet = null; for (uint i = 0; i < _tablets.Length; i++) { if (_tablets[i] != null && _tablets[i].Id == id) { tablet = _tablets[i]; _tablets[i] = null; // clear it so we don't dispose it. break; } } // Not found so create it. if (tablet == null) { try { tablet = new TabletDevice(tabletdevices[iTablet], penThread); } catch (InvalidOperationException ex) { // This is caused by the Stylus ID not being unique when trying // to register it in the StylusLogic.__stylusDeviceMap. If we // come across a dup then just ignore registering this tablet device. // There seems to be an issue in wisptis where different tablet IDs get // duplicate Stylus Ids when installing the VHID test devices. if (ex.Data.Contains("System.Windows.Input.StylusLogic")) { continue; // Just go to next without adding this one. } else { throw; // not an expected exception, rethrow it. } } } tablets[tabletsIndex] = tablet; } tabletsIndex++; } if (unchangedTabletCount == _tablets.Length && unchangedTabletCount == tabletsIndex && tabletsIndex == count) { // Keep the _tablet reference when nothing changes. // The reason is that if this method gets called from within // CreateContexts while looping on _tablets, it could result in // a null ref exception since the original _tablets array has // been purged to nulls. // NOTE: There is still the case of changing the ref (else case below) // when tablet devices actually change. But such a case is rare // (if not improbable) from within CreateContexts. Array.Copy(tablets, 0, _tablets, 0, count); _indexMouseTablet = indexMouseTablet; } else { // See if we need to re alloc the array due to invalid tabletdevice being seen. if (tabletsIndex != count) { TabletDevice[] updatedTablets = new TabletDevice[tabletsIndex]; Array.Copy(tablets, 0, updatedTablets, 0, tabletsIndex); tablets = updatedTablets; } DisposeTablets(); // Clean up any non null TabletDevice entries on old array. _tablets = tablets; // set updated tabletdevice array _indexMouseTablet = indexMouseTablet; } // DevDiv:1078091 // Any deferred tablet should be properly disposed of when applicable and // removed from the list of deferred tablets. DisposeDeferredTablets(); }