shell/tiling: Fix next_focus for different orientation

This commit is contained in:
Victoria Brekenfeld 2022-10-25 19:08:17 +02:00
parent 634319a823
commit 3588978f68

View file

@ -435,13 +435,14 @@ impl TilingLayout {
// TODO: Rather use something like seat.current_keyboard_focus // TODO: Rather use something like seat.current_keyboard_focus
// TODO https://github.com/Smithay/smithay/pull/777 // TODO https://github.com/Smithay/smithay/pull/777
if let Some(last_active) = TilingLayout::last_active_window(tree, focus_stack) { if let Some(last_active) = TilingLayout::last_active_window(tree, focus_stack) {
let (last_window, mut node_id) = last_active; let (last_window, last_node_id) = last_active;
// stacks may handle focus internally // stacks may handle focus internally
if last_window.handle_focus(direction) { if last_window.handle_focus(direction) {
return None; return None;
} }
let mut node_id = last_node_id.clone();
while let Some(group) = tree.get(&node_id).unwrap().parent() { while let Some(group) = tree.get(&node_id).unwrap().parent() {
let child = node_id.clone(); let child = node_id.clone();
let group_data = tree.get(&group).unwrap().data(); let group_data = tree.get(&group).unwrap().data();
@ -511,50 +512,46 @@ impl TilingLayout {
} }
Data::Group { .. } => { Data::Group { .. } => {
let center = { let center = {
let geo = tree.get(&child).unwrap().data().geometry(); let geo = tree.get(&last_node_id).unwrap().data().geometry();
let mut point = geo.loc; let mut point = geo.loc;
match direction { match direction {
FocusDirection::Down => { FocusDirection::Down => {
point += Point::from((geo.size.w / 2, geo.size.h)) point += Point::from((geo.size.w / 2 - 1, geo.size.h))
} }
FocusDirection::Up => point.x += geo.size.w, FocusDirection::Up => point.x += geo.size.w / 2 - 1,
FocusDirection::Left => point.y += geo.size.h / 2, FocusDirection::Left => point.y += geo.size.h / 2 - 1,
FocusDirection::Right => { FocusDirection::Right => {
point += Point::from((geo.size.w, geo.size.h / 2)) point += Point::from((geo.size.w, geo.size.h / 2 - 1))
} }
_ => unreachable!(), _ => unreachable!(),
}; };
point.to_f64() point.to_f64()
}; };
let distance = |candidate: &&NodeId| -> f64 {
let geo = tree.get(candidate).unwrap().data().geometry();
let mut point = geo.loc;
match direction {
FocusDirection::Up => {
point += Point::from((geo.size.w / 2, geo.size.h))
}
FocusDirection::Down => point.x += geo.size.w,
FocusDirection::Right => point.y += geo.size.h / 2,
FocusDirection::Left => {
point += Point::from((geo.size.w, geo.size.h / 2))
}
_ => unreachable!(),
};
let point = point.to_f64();
((point.x - center.x).powi(2) + (point.y - center.y).powi(2))
.sqrt()
};
node_id = tree node_id = tree
.children_ids(node_id.as_ref().unwrap()) .children_ids(node_id.as_ref().unwrap())
.unwrap() .unwrap()
.min_by(|node1, node2| { .min_by(|node1, node2| {
let distance = |candidate: &&NodeId| -> f64 { distance(node1).abs().total_cmp(&distance(node2).abs())
let geo =
tree.get(candidate).unwrap().data().geometry();
let mut point = geo.loc;
match direction {
FocusDirection::Up => {
point +=
Point::from((geo.size.w / 2, geo.size.h))
}
FocusDirection::Down => point.x += geo.size.w,
FocusDirection::Right => point.y += geo.size.h / 2,
FocusDirection::Left => {
point +=
Point::from((geo.size.w, geo.size.h / 2))
}
_ => unreachable!(),
};
let point = point.to_f64();
((point.x - center.x).powi(2)
+ (point.y - center.y).powi(2))
.sqrt()
};
distance(node1).total_cmp(&distance(node2))
}); });
} }
Data::Mapped { mapped, .. } => { Data::Mapped { mapped, .. } => {
@ -745,7 +742,7 @@ impl TilingLayout {
.map(|(output_data, tree)| (&output_data.output, tree)) .map(|(output_data, tree)| (&output_data.output, tree))
{ {
if let Some(root) = tree.root_node_id() { if let Some(root) = tree.root_node_id() {
let mut stack = VecDeque::new(); let mut stack = Vec::new();
let mut geo = Some(layer_map_for_output(&output).non_exclusive_zone()); let mut geo = Some(layer_map_for_output(&output).non_exclusive_zone());
// TODO saturate? minimum? // TODO saturate? minimum?
@ -763,7 +760,7 @@ impl TilingLayout {
.into_iter() .into_iter()
{ {
let node = tree.get_mut(&node_id).unwrap(); let node = tree.get_mut(&node_id).unwrap();
let geo = stack.pop_front().unwrap_or(geo); let geo = stack.pop().unwrap_or(geo);
if let Some(geo) = geo { if let Some(geo) = geo {
let data = node.data_mut(); let data = node.data_mut();
data.update_geometry(geo); data.update_geometry(geo);
@ -772,23 +769,23 @@ impl TilingLayout {
orientation, sizes, .. orientation, sizes, ..
} => match orientation { } => match orientation {
Orientation::Horizontal => { Orientation::Horizontal => {
let mut previous = 0; let mut previous: i32 = sizes.iter().sum();
for size in sizes { for size in sizes.iter().rev() {
stack.push_back(Some(Rectangle::from_loc_and_size( previous -= *size;
stack.push(Some(Rectangle::from_loc_and_size(
(geo.loc.x, geo.loc.y + previous), (geo.loc.x, geo.loc.y + previous),
(geo.size.w, *size), (geo.size.w, *size),
))); )));
previous += *size;
} }
} }
Orientation::Vertical => { Orientation::Vertical => {
let mut previous = 0; let mut previous: i32 = sizes.iter().sum();
for size in sizes { for size in sizes.iter().rev() {
stack.push_back(Some(Rectangle::from_loc_and_size( previous -= *size;
stack.push(Some(Rectangle::from_loc_and_size(
(geo.loc.x + previous, geo.loc.y), (geo.loc.x + previous, geo.loc.y),
(*size, geo.size.h), (*size, geo.size.h),
))); )));
previous += *size;
} }
} }
}, },
@ -803,8 +800,8 @@ impl TilingLayout {
} }
} }
} else if node.data().is_group() { } else if node.data().is_group() {
stack.push_back(None); stack.push(None);
stack.push_back(None); stack.push(None);
} }
} }
} }