コード例 #1
0
        internal TabletDevice(TabletDeviceInfo tabletInfo, PenThread penThread)
        {
            _tabletInfo = tabletInfo;
            _penThread = penThread;
            int count = tabletInfo.StylusDevicesInfo.Length;

            StylusDevice[] styluses = new StylusDevice[count];
            for ( int i = 0; i < count; i++ )
            {
                StylusDeviceInfo cursorInfo = tabletInfo.StylusDevicesInfo[i];
                styluses[i] = new StylusDevice(
                    this,
                    cursorInfo.CursorName, 
                    cursorInfo.CursorId, 
                    cursorInfo.CursorInverted,
                    cursorInfo.ButtonCollection);
            }

            _stylusDeviceCollection = new StylusDeviceCollection(styluses);

            if (_tabletInfo.DeviceType == TabletDeviceType.Touch)
            {
                // 

                _multiTouchSystemGestureLogic = new MultiTouchSystemGestureLogic();
            }
        }
コード例 #2
0
        internal TabletDevice(TabletDeviceInfo tabletInfo, PenThread penThread)
        {
            _tabletInfo = tabletInfo;
            _penThread  = penThread;
            int count = tabletInfo.StylusDevicesInfo.Length;

            StylusDevice[] styluses = new StylusDevice[count];
            for (int i = 0; i < count; i++)
            {
                StylusDeviceInfo cursorInfo = tabletInfo.StylusDevicesInfo[i];
                styluses[i] = new StylusDevice(
                    this,
                    cursorInfo.CursorName,
                    cursorInfo.CursorId,
                    cursorInfo.CursorInverted,
                    cursorInfo.ButtonCollection);
            }

            _stylusDeviceCollection = new StylusDeviceCollection(styluses);

            if (_tabletInfo.DeviceType == TabletDeviceType.Touch)
            {
                //

                _multiTouchSystemGestureLogic = new MultiTouchSystemGestureLogic();
            }
        }
コード例 #3
0
        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));
        }
コード例 #4
0
ファイル: PenThreadPool.cs プロジェクト: ash2005/z
        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);
        }
コード例 #5
0
        internal void DisposeOrDeferDisposal()
        {
            // Only dispose when no input events are left in the queue
            if (CanDispose)
            {
                // Make sure this device is not the current one.
                if (Tablet.CurrentTabletDevice == this.TabletDevice)
                {
                    StylusLogic.GetCurrentStylusLogicAs <WispLogic>().SelectStylusDevice(null, null, true);
                }

                // A disconnect will be logged in the dispose as WPF will have gotten rid of the tablet.
                StylusTraceLogger.LogDeviceDisconnect(_tabletInfo.Id);

                // DDVSO:174153
                // Force tablets to clean up as soon as they are disposed.  This helps to reduce
                // COM references that might be waiting for RCWs to finalize.
                IPimcTablet2 tablet = _tabletInfo.PimcTablet?.Value;
                _tabletInfo.PimcTablet = null;

                if (tablet != null)
                {
                    // DDVSO:514949
                    // Balance calls in PenThreadWorker.GetTabletInfoHelper and CPimcTablet::Init.
                    PenThread.WorkerReleaseTabletLocks(tablet, _tabletInfo.WispTabletKey);

                    Marshal.ReleaseComObject(tablet);
                }

                StylusDeviceCollection styluses = _stylusDeviceCollection;
                _stylusDeviceCollection = null;

                if (styluses != null)
                {
                    styluses.Dispose();
                }

                _penThread         = null;
                _isDisposalPending = false;

                // DDVSO:614343
                // Ensure that we are marked disposed and no longer attempt to finalize.
                _disposed = true;
                GC.SuppressFinalize(this);
            }
            else
            {
                _isDisposalPending = true;
            }
        }
コード例 #6
0
ファイル: WispTabletDevice.cs プロジェクト: beda2280/wpf-1
        /////////////////////////////////////////////////////////////////////////

        /////////////////////////////////////////////////////////////////////
        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));
        }
コード例 #7
0
ファイル: PenThreadPool.cs プロジェクト: beda2280/wpf-1
        /// <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);
        }
コード例 #8
0
        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.
            }
        }
コード例 #9
0
        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();
        }
コード例 #10
0
ファイル: PenThreadPool.cs プロジェクト: sjyanxin/WPFSource
        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; 
        }