Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Do not unfocus on click if the focused drawable changed during the click #6345

Merged
merged 7 commits into from
Aug 9, 2024

Conversation

smoogipoo
Copy link
Contributor

RFC.

I'm not happy with this because means that FocusedDrawable is null during OnClick() handling. What I'd really like to do is "snapshot" FocusedDrawable. I'm not sure/don't think anything expects FocusedDrawable to be correct during click handling, though.

These could be useful in code that needs to perform actions on an
external component, such as in this PR's new test.

`Drawable.FindClosestParent<>` is already `public static` so I don't see
a reason to _not_ expose these.
@smoogipoo smoogipoo force-pushed the fix-focus-change-during-click branch from d4ec11b to 5d8d54d Compare July 25, 2024 05:11
@bdach
Copy link
Collaborator

bdach commented Aug 1, 2024

What I'd really like to do is "snapshot" FocusedDrawable.

I would really much prefer that too, why isn't this done? At least conceptually it seems like it should be at most a minor adjustment to this diff - something like so?

diff --git a/osu.Framework/Input/MouseButtonEventManager.cs b/osu.Framework/Input/MouseButtonEventManager.cs
index d08a5aafc..4884224a1 100644
--- a/osu.Framework/Input/MouseButtonEventManager.cs
+++ b/osu.Framework/Input/MouseButtonEventManager.cs
@@ -155,17 +155,13 @@ private void handleClick(InputState state, List<Drawable>? targets)
                                    .Where(t => t.IsAlive && t.IsPresent && t.ReceivePositionalInputAt(state.Mouse.Position));
 
             Drawable focusedDrawableBeforeClick = InputManager.FocusedDrawable;
-            InputManager.FocusedDrawable = null;
 
             Drawable? clicked = PropagateButtonEvent(drawables, new ClickEvent(state, Button, MouseDownPosition));
             ClickedDrawable.SetTarget(clicked!);
 
             // Focus shall only change if it wasn't changed during the click (for example, using a button to open a menu).
-            if (InputManager.FocusedDrawable == null)
+            if (ReferenceEquals(InputManager.FocusedDrawable, focusedDrawableBeforeClick))
             {
-                // Restore the previous focus target (it may get unfocused below).
-                InputManager.FocusedDrawable = focusedDrawableBeforeClick;
-
                 if (ChangeFocusOnClick && clicked?.ChangeFocusOnClick != false)
                     InputManager.ChangeFocusFromClick(clicked);
             }

@smoogipoo
Copy link
Contributor Author

Tests failing.

Whoops, I didn't notice. I'll need to think about this one a bit more because it's an interesting/weird case.

What's the relation between this and #6346

This is all about removing that schedule from #6346. The schedule was initially present because some tests would open the dropdown by clicking on a test button, which is exactly the interaction demonstrated by TestChangeFocusDuringInputHandling_ShouldRetainFocus in this PR. #6346 expands that interaction so it happens on every click of the header instead, rather than some special case.

But, #6346 works on its own regardless of this PR.

At least conceptually it seems like it should be at most a minor adjustment to this diff

The problem with your diff is if you click the button twice, the first time it will work correctly because the reference changes, but the second time the reference will not have changed and focus will be changed (suppose that button press action is Menu.Open() as in this PR's added test).

So by snapshotting I'm really imagining a system where FocusedDrawable remains unchanged during a click and the new value is transferred to it after the click concludes.

Resetting `FocusedDrawable` causes `ChangeFocus(null)` to fail.

This commit basically implements what I meant by "snapshotting"
`FocusedDrawable` - rather than changing it directly, it's maintained
during a click and its "new value" (which may be the same as its current
value) is duplicated into an isolated variable.
@smoogipoo
Copy link
Contributor Author

Alright, I basically implemented what I meant by "snapshotting" in 055b53d, should fix the tests.

Rider didn't warn me about this one :(
@peppy peppy self-requested a review August 5, 2024 06:54
peppy
peppy previously approved these changes Aug 5, 2024
Copy link
Member

@peppy peppy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems correct otherwise.

@@ -1491,15 +1491,15 @@ protected internal virtual bool ShouldBeAlive
/// </summary>
/// <returns>The first parent <see cref="InputManager"/>.</returns>
[CanBeNull]
protected InputManager GetContainingInputManager() => this.FindClosestParent<InputManager>();
public InputManager GetContainingInputManager() => this.FindClosestParent<InputManager>();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess this is okay to make public, but could also be proected internal.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I felt like these methods could be useful outside of o!f too, but I have no strong feelings. Made protected internal.

@peppy peppy requested a review from bdach August 5, 2024 07:32
@peppy
Copy link
Member

peppy commented Aug 9, 2024

Going to get this one in for a release.

@peppy peppy merged commit 7d89a14 into ppy:master Aug 9, 2024
21 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants