mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-09-04 03:35:19 +02:00
UI: Tab and Shift+Tab move focus through the view hierarchy
Unlike the directional moves, this doesn't look at where anything ended up on screen - it walks the hierarchy in the order views were added, flattening nested groups in place. That's what makes it predictable in the layouts where "what's to the right of this" has no good answer. A view is a stop if it's focusable and enabled, the same test the directional moves apply, so the two agree on what's reachable. Hidden subtrees are skipped whole, which is what keeps a TabHolder's inactive tabs - V_GONE rather than removed - out of the order without any special casing. Containers are gated on visibility only, not enabled, matching Key/Touch/Axis: disabling a container doesn't stop its children being interactive anywhere else either. Ctrl+Tab stays with ChoiceStrip, which uses it to switch tabs. focusMoves now holds FocusMove rather than raw keycodes, so the direction is decided in one place while the modifiers are still around, and a held key repeats in the direction it was originally pressed with - the synthesized repeat has no modifiers of its own. That also retires the keycode switch in UpdateViewHierarchy and IsScrollKey, which had no other callers. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SfY7iFJEjmRXf1XGrTs4MF
This commit is contained in:
co-authored by
Claude Opus 5
parent
8cb5ce7585
commit
ea1ad8ffed
@@ -489,6 +489,27 @@ NeighborResult ViewGroup::FindNeighbor(View *view, FocusMove direction, Neighbor
|
||||
}
|
||||
}
|
||||
|
||||
void ViewGroup::CollectTabOrder(std::vector<View *> *outViews) const {
|
||||
for (View *view : views_) {
|
||||
// Gate on visibility only, like Key/Touch/Axis do - a container being disabled doesn't
|
||||
// stop its children from being interactive elsewhere, so it shouldn't here either.
|
||||
if (view->GetVisibility() != V_VISIBLE) {
|
||||
continue;
|
||||
}
|
||||
if (view->IsViewGroup()) {
|
||||
// A group can be focusable itself (rare), in which case it's a stop and we still
|
||||
// descend into it - same as arrow navigation, which considers both.
|
||||
ViewGroup *vg = static_cast<ViewGroup *>(view);
|
||||
if (vg->CanBeFocused() && vg->IsEnabled()) {
|
||||
outViews->push_back(vg);
|
||||
}
|
||||
vg->CollectTabOrder(outViews);
|
||||
} else if (view->CanBeFocused() && view->IsEnabled()) {
|
||||
outViews->push_back(view);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NeighborResult ViewGroup::FindScrollNeighbor(View *view, const Point2D &target, FocusMove direction, NeighborResult best) {
|
||||
if (!IsEnabled())
|
||||
return best;
|
||||
|
||||
Reference in New Issue
Block a user