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

Keyboard navigation in scroll containers uses screen-position for auto-focus-neighbors instead of actual node order #98445

Closed
harrison-munitz opened this issue Oct 23, 2024 · 1 comment · Fixed by #63059

Comments

@harrison-munitz
Copy link

harrison-munitz commented Oct 23, 2024

Tested versions

v4.3.stable.official [77dcf97]

Also confirmed in v4.2.1.stable.official [b09f793]

System information

Win 11

Issue description

When a ScrollContainer has a keyboard-focusable node before it (up or left typically) and the ScrollContainer is full of focusable nodes, like buttons, the keyboard navigation will jump from one of those inner nodes to the outer node if it lines up with the boundary of the scroll container, instead of moving to it's own actual neighbor within the scroll container.

If you navigate in the same direction (up/left) again, it will jump back into the scroll container, but having skipped one node. If you click the opposite direction (down/right) from the outer node, it will go back to the node you were just on; this means that if it skips the first node in the list while going up, you will no longer be able to navigate to it whatsoever since going "up" goes to the outer node and going "down" goes back to the second node.

It does not matter if follow_focus is set (although it makes it much easier to reproduce). If you manually set the scroll position so that the inner focused node is right at the boundary, it will jump out of the ScrollContainer instead of jumping to the inner-node's sibling.

Although, explicitly setting the relevant focus_neighbor seems to fix this, so it is at least not overly difficult to work around.

Steps to reproduce

The attached reproducable example includes a single scene with no scripts. It uses a VBoxContainer to position a "Top Button" above a ScrollContainer which fills the rest of the screen. The ScrollContainer has follow_focus set to true. The ScrollContainer also contains a bunch of buttons with default settings and differing only by me numbering them so that the scrolling behavior is more obvious. I was also able to create the same issue using HBoxContainers, but did not include them as it's identical except for pressing left/right instead of up/down.

The scroll container was given a top border to make the alignment stuff easier to see.

The entire project has been given a very low base-resolution which is stretched via window height/width overrides and the stretch settings to make the manual alignment steps below easier, since there are fewer pixels and they are larger and easier to see. I have also tested this with the default resolution and stretch settings and confirmed that the issue still occurs, so this should not be an issue for minimum-reproducibility.

Standard reproduction, using follow_focus:

  1. Run the scene attached below
  2. Click on any button to create an initial focus target, enabling keyboard navigation
  3. Navigate to the bottom of the list of buttons.
  4. Use the keyboard to navigate up, one at a time.
  5. When the focus reaches the edge of the screen, since it won't be perfectly aligned on this first scroll, it will scroll to the next focused neighbor, perfectly aligning it with the boundary of the scroll-container.
  6. Use the keyboard to navigate "up" one more time. It will focus the button at the top of the screen instead of the next button up in the list.
  7. Press "up" several more times to observe the 'skipping' behavior that I wrote about in the description.

Manual Scroll Reproduction:

  1. Launch the scene and scroll down so that the first few buttons are off screen.
  2. Click any button to create the initial focus target, enabling keyboard navigation.
  3. Manually position the scrollbar via the mouse so that any button except the first is aligned with the edge of the scroll-container. This is fairly precise (see the note below)
  4. Click "up" on the keyboard. It will focus the button at the top of the screen as in step 6 above.

Notes on manual alignment:

  • The alignment seems pretty strict, it may take multiple attempts, but I was able to do it fairly consistently. I've used a low base resolution in the project and overrode the settings to stretch it and make the pixels appear larger to make it easier to align.
  • It also seems like having the button overflow and get clipped a little is fine but having even a pixel of the gap between it and it's neighbor showing will make this bug not occur.

Workaround:
If you manually set the focus_neighbor_top property on any of the buttons, the issue will not occur when that button is the one aligned with the edge of the screen.

Minimal reproduction project (MRP)

scrollcontainerbug.zip

@Rindbee
Copy link
Contributor

Rindbee commented Jan 3, 2025

I'm trying to solve a similar issue in #63059, you can give it a try.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants