You have to be careful with race conditions here.
With some setup.
IObservable<Unit> keyDown = Observable.FromEvent(/*keydown*/).Select(_=>true);
IObservable<Unit> keyUp = Observable.FromEvent(/*keyup*/).Select(_=>false);
IObservable<Point> mouseMoves = Observable.FromEvent(...);
Now create an observable that we know will start with a keyDown event
var keys = keyDown.Merge(keyUp).DistinctUntilChanged().SkipWhile(_=>!_);
Use this observable to create a window.
IOBservable<IObservable<Point> mousePaths =
mouseMoves
.Window(keys)
.Where((_,i)=>i%2==0);
Note that we want to skip the odd windows. Even windows are key down. Odd windows are key up.
Now there are no race conditions and we will never miss a keyDown or keyUp event.
Explanation If you use the other overload of Window, the one with a seperate open and closing trigger, the problem is that the closing trigger generation is lazy. It is not generated and does not subscribe to it's source until the opening edge of the window is triggered. That means there is a small time window for a keyUp event to occur before the window closing trigger is registered.