RFC. Closes https://github.com/ppy/osu/issues/27883.
The idea here is that `PopOut()` is called _when the hide is requested_,
so once an overlay trigger would hide, the overlay would
`StopAnyPlaying()`, but because of async load things, the actual track
would start playing after that but before the overlay has fully hidden.
(That last part is significant because after the overlay has fully
hidden, schedules save the day.)
Due to the loose coupling between `PreviewTrackManager` and
`IPreviewTrackOwner` there's really no easy way to handle this locally
to the usages of the preview tracks. Heck, `PreviewTrackManager` doesn't
really know which preview track owner is to be considered _present_ at
any time, it just kinda works on vibes based on DI until the owner tells
all of its preview tracks to stop.
This solution causes the preview tracks to stop a little bit later but
maybe that's fine? Just trying to not overthink the issue is all.
No tests because this is going to suck to test automatically while it is
pretty easy to test manually (got it in a few tries on master).
The issue also mentions that the track can sometimes resume playing
after the overlay is pulled up again, but I don't see that as a problem
necessarily, and even if it was, it's not going to be that easy to
address due to the aforementioned loose coupling - to fix that, play
buttons would have to know who is the current preview track owner and
cancel schedules upon determining that their preview track owner has
gone away.
Closes https://github.com/ppy/osu/issues/25633.
The reason why that particular beatmap did not have a double skip
on stable is here:
e53980dd76/osu!/GameModes/Play/Player.cs#L1761-L1770
The particular place of interest is the `leadInTime < 10000` check.
If `leadInTime < 10000`, then `leadIn == leadInTime`, and it turns out
that `AudioEngine.Time` will always be more than or equal to `leadIn`,
because it's also the gameplay start time:
e53980dd76/osu!/GameModes/Play/Player.cs#L2765
This essentially means that if the `leadInTime` is less than 10000,
that particular check is just dead. So a double skip can only occur
if the gameplay starts at time -10000 or earlier due to the storyboard.
In the Mod selection area, the search bar's focus could be changed by pressing TAB.
However, when clicking outside of the search bar, the focus would be killed but two TABs were required to get the focus back on the search bar.
This happened because the action of clicking in an empty area would trigger the search bar to change its appearence, but not its internal state.
In my solution, I made the OnClick function aware of the search bar's state, so it would not only change its appearance, but also its state.
Now, after clicking in an empty area, there is only needed one TAB to select the search box again, as expected.