52 if (_focusables.empty()) {
56 if (focus_start(ctx)) {
59 auto it = std::ranges::find(_focusables, _focused);
60 if (it == _focusables.end()) {
61 set_focus(ctx, _focusables.front());
65 if (it == _focusables.end()) {
66 it = _focusables.begin();
96 if (_focusables.empty()) {
100 if (focus_start(ctx)) {
104 Widget*
const from_widget = _focused;
105 const bool vertical = dy != 0;
106 const int dir = vertical ? dy : dx;
109 Widget* override_target =
nullptr;
111 override_target = from_widget->
nav_up;
113 override_target = from_widget->
nav_down;
115 override_target = from_widget->
nav_left;
117 override_target = from_widget->
nav_right;
119 if (override_target !=
nullptr
120 && std::ranges::find(_focusables, override_target) != _focusables.end()) {
121 set_focus(ctx, override_target);
127 return vertical ? q.position.y : q.position.x;
130 return vertical ? q.position.y + q.size.y : q.position.x + q.size.x;
133 return vertical ? q.position.x : q.position.y;
136 return vertical ? q.position.x + q.size.x : q.position.y + q.size.y;
139 const auto& from = from_widget->
transform;
143 std::optional<float>& lane = vertical ? _lane_x : _lane_y;
144 const float anchor = lane.value_or((across_lo(from) + across_hi(from)) / 2.0F);
147 bool best_in_lane =
false;
148 float best_distance = 0.0F;
149 float best_offset = 0.0F;
151 for (
Widget* w : _focusables) {
152 if (w == from_widget) {
155 const auto& to = w->transform;
159 const float to_center = (along_lo(to) + along_hi(to)) / 2.0F;
160 const float leading_edge = dir > 0 ? along_hi(from) : along_lo(from);
161 if ((to_center - leading_edge) *
static_cast<float>(dir) <= 0.0F) {
166 const float gap = dir > 0 ? along_lo(to) - along_hi(from) : along_lo(from) - along_hi(to);
167 const float along = std::max(0.0F, gap);
170 const float overlap = std::min(across_hi(from), across_hi(to))
171 - std::max(across_lo(from), across_lo(to));
172 const bool in_lane = overlap > 0.0F;
173 const float across_gap = in_lane ? 0.0F : -overlap;
176 const float distance = in_lane ? along : along + (across_gap * 2.0F);
177 const float offset = std::abs(((across_lo(to) + across_hi(to)) / 2.0F) - anchor);
179 const bool better = best ==
nullptr || (in_lane && !best_in_lane)
180 || (in_lane == best_in_lane
181 && (distance < best_distance
182 || (distance == best_distance && offset < best_offset)));
185 best_in_lane = in_lane;
186 best_distance = distance;
187 best_offset = offset;
191 if (best !=
nullptr) {
192 set_focus(ctx, best);
Shared state for the UI system.
UI context and focus management for the ASW UI module.