private void Handle3FingerGestures(SYNCOMLib.SynPacket packet)
        {
            int x = 0;
            int y = 0;

            packet.GetProperty((int)SYNCTRLLib.SynPacketProperty.SP_X, ref x);
            packet.GetProperty((int)SYNCTRLLib.SynPacketProperty.SP_Y, ref y);

            if (!m_gestureInProgress)
            {
                m_gestureInProgress = true;
                m_startPosition     = new System.Drawing.Point(x, y);
            }
            else
            {
                int xSwipe = x - m_startPosition.X;
                int ySwipe = y - m_startPosition.Y;

                if (Math.Abs(ySwipe) > Math.Abs(xSwipe))
                {
                    if (ySwipe > pushPullThreshold)
                    {
                        // push
                        m_actionStarted = true;
                        DoKeySeq(m_cpl.UpAction.KeySeq);
                    }
                    else if (ySwipe < (-pushPullThreshold))
                    {
                        // pull
                        m_actionStarted = true;
                        DoKeySeq(m_cpl.DownAction.KeySeq);
                    }
                }
                else
                {
                    if (xSwipe < -swipeThreshold)
                    {
                        // left
                        m_actionStarted = true;
                        DoKeySeq(m_cpl.LeftAction.KeySeq);
                    }
                    else if (xSwipe > swipeThreshold)
                    {
                        // right
                        m_actionStarted = true;
                        DoKeySeq(m_cpl.RightAction.KeySeq);
                    }
                }
            }
        }
        void ProcessPacket(SYNCOMLib.SynPacket packet)
        {
            int extraState  = 0;
            int fingerState = 0;
            int xDelta      = 0;
            int yDelta      = 0;

            packet.GetProperty((int)SYNCTRLLib.SynPacketProperty.SP_ExtraFingerState, ref extraState);
            packet.GetProperty((int)SYNCTRLLib.SynPacketProperty.SP_FingerState, ref fingerState);
            // only read horizontal offset when shift key is down or caps lock is on
            if (Control.ModifierKeys.HasFlag(Keys.Shift) || Control.IsKeyLocked(Keys.CapsLock))
            {
                packet.GetProperty((int)SYNCTRLLib.SynPacketProperty.SP_XDelta, ref xDelta);
            }
            packet.GetProperty((int)SYNCTRLLib.SynPacketProperty.SP_YDelta, ref yDelta);

            int numOfFingers = extraState & 3;

            // no finger
            if ((fingerState & (int)SYNCTRLLib.SynFingerFlags.SF_FingerPresent) == 0)
            {
                m_actionStarted     = false;
                m_gestureInProgress = false;
                m_scrolling         = false;
                return;
            }

            if ((fingerState & (int)SYNCTRLLib.SynFingerFlags.SF_FingerMotion) == 0)
            {
                return;
            }

            if (Math.Abs(xDelta) > motionThreshhold || Math.Abs(yDelta) > motionThreshhold)
            {
                return;
            }

            // 2 finger scroll
            if (numOfFingers == 2)
            {
                int x = 0;
                int y = 0;
                packet.GetProperty((int)SYNCTRLLib.SynPacketProperty.SP_X, ref x);
                packet.GetProperty((int)SYNCTRLLib.SynPacketProperty.SP_Y, ref y);
                // not at edges
                if (!(x <= m_xMin || x >= m_xMax || y <= m_yMin || y >= m_yMax))
                {
                    DoScroll(xDelta, yDelta);
                }
                m_scrolling = true;
            }
            else if (numOfFingers == 1 && m_scrolling)
            {
                DoScroll(xDelta, yDelta);
            }
            else if (numOfFingers == 3 && !m_actionStarted)
            {
                Handle3FingerGestures(packet);
            }
        }