The following seems to work, but I suspect that it's possible to do it in a neater way.
var click = mouseEnter
.SelectMany(_ => mouseDown.TakeUntil(mouseLeave))
.SelectMany(_ => mouseUp.TakeUntil(mouseLeave).Take(1));
I've renamed finalObs
to click
, obs1
to mouseDown
, obs2
to mouseUp
...
EDIT: Added Take(1) to fix the flaw pointed out by Enigmativity
EDIT(2):
Here is another solution that I like more.
You'll need to add a .Select(_ => "U")
to the definition of mouseUp, .Select(_ => "D")
to mouseDown...
var click = Observable.Merge(mouseDown, mouseUp, mouseLeave, mouseEnter)
.Scan((s, c) => c == "L" ? "" : s + c) // Create a string of the events, reset on mouseLeave
.Where(s => s.Length >= 2 && s.Substring(s.Length - 2) == "DU");
After thinking about it, it's impossible to get exactly correct behavior in the case where the user mouse downs over the item, then moves outside of the item, then moves back and mouse ups. This is because you don't get mouse ups when not over the item, so you can't be sure they didn't mouse up, then mouse down while outside.