IObservable <IRecordStep> Observe(IMouseKeyHook Hook, CancellationToken CancellationToken, out IObservable <Unit> ShotObservable) { var subject = new Subject <IRecordStep>(); var shotSubject = new Subject <Unit>(); ShotObservable = shotSubject; void OnNext(IRecordStep NextStep) { if (_lastStep != null) { if (_lastStep.Merge(NextStep)) { return; } subject.OnNext(_lastStep); } shotSubject.OnNext(Unit.Default); _lastStep = NextStep; } Hook.MouseClick += (S, E) => { var step = new MouseClickStep(_mouseClickSettings, _keystrokesSettings, E, _keymap); OnNext(step); }; Hook.MouseDoubleClick += (S, E) => { var step = new MouseClickStep(_mouseClickSettings, _keystrokesSettings, E, _keymap); OnNext(step); }; Hook.MouseDragStarted += (S, E) => { var step = new MouseDragBeginStep(E.Location, _mouseClickSettings, _keystrokesSettings, _keymap); OnNext(step); }; Hook.MouseDragFinished += (S, E) => { var step = new MouseDragStep(E.Location, _mouseClickSettings, _keystrokesSettings, _keymap); OnNext(step); }; if (_stepsSettings.IncludeScrolls) { // TODO: Event is not firing for touchpad scroll Hook.MouseWheel += (S, E) => { var step = new ScrollStep(E, _mouseClickSettings, _keystrokesSettings, _keymap); OnNext(step); }; } Hook.KeyDown += (S, E) => { _modifierSingleDown = false; var record = new KeyRecord(E, _keymap); var display = record.Display; if (display == _keymap.Control || display == _keymap.Alt || display == _keymap.Shift) { _modifierSingleDown = true; } else { OnNext(new KeyStep(_keystrokesSettings, record)); } }; Hook.KeyUp += (S, E) => { var record = new KeyRecord(E, _keymap); var display = record.Display; if (display == _keymap.Control || display == _keymap.Alt || display == _keymap.Shift) { if (_modifierSingleDown) { OnNext(new KeyStep(_keystrokesSettings, record)); } } }; CancellationToken.Register(() => { shotSubject.OnCompleted(); subject.OnNext(_lastStep); subject.OnCompleted(); }); return(subject .Where(M => _recording)); }