private void OnHitTest(object sender, GazeHitTestArgs e) { Debug.Assert(_targetting); if (!e.Handled) { if (_sampleTail == 0) { Debug.WriteLine("Targetting first sample"); _targettingEpoch = e.Timestamp; _targettingExpire = _targettingEpoch + MaxTargettingTime; } if (_targettingExpire <= e.Timestamp) { Debug.WriteLine($"Expired after {_targettingEpoch - e.Timestamp}"); _targetting = false; GazeInput.HitTest -= OnHitTest; GazeInput.ResetCustomCursor(); } else { if (_sampleTail == MaxSamples) { //Debug.WriteLine("Samples wrapping around"); _sampleTail = 0; } { var screenWidth = Screen.PrimaryScreen.Bounds.Width; var screenHeight = Screen.PrimaryScreen.Bounds.Height; var dx = (int)Math.Round(0x10000 * e.X / screenWidth); var dy = (int)Math.Round(0x10000 * e.Y / screenHeight); InteropHelper.SendMouseMove(dx, dy); } _targetTimestamps[_sampleTail] = e.Timestamp; _targetXs[_sampleTail] = e.X; _targetYs[_sampleTail] = e.Y; _sampleTail++; if (_sampleCount < MaxSamples) { _sampleCount++; } var cutoff = e.Timestamp - VarianceTime; var count = 0; var index = _sampleTail - 1; var sumX = 0.0; var sumXX = 0.0; var sumY = 0.0; var sumYY = 0.0; while (cutoff <= _targetTimestamps[index] && count < _sampleCount) { var x = _targetXs[index]; var y = _targetYs[index]; sumX += x; sumXX += x * x; sumY += y; sumYY += y * y; if (index == 0) { index = MaxSamples - 1; } else { index--; } count++; } var varianceX = sumXX - sumX * sumX / count; var varianceY = sumYY - sumY * sumY / count; var varianceXY = varianceX + varianceY; //Debug.WriteLine($"Running,{e.X},{e.Y},{varianceXY},{varianceX},{varianceY},{count},{_sampleCount}"); if (_isArmed) { if (varianceXY < DownVarianceThreshold) { Debug.WriteLine("Clicking"); var screenWidth = Screen.PrimaryScreen.Bounds.Width; var screenHeight = Screen.PrimaryScreen.Bounds.Height; var dx = (int)Math.Round(0x10000 * e.X / screenWidth); var dy = (int)Math.Round(0x10000 * e.Y / screenHeight); InteropHelper.SendMouseClick(dx, dy); _targetting = false; GazeInput.HitTest -= OnHitTest; GazeInput.ResetCustomCursor(); } } else if (UpVarianceThreshold < varianceXY) { Debug.WriteLine("Arming"); _isArmed = true; } e.SetTarget(_mouseMoveGazeTarget); } } }