view stack: rework iteration for flexibility

There is now a single iter() function which accepts a filter and context
allowing users of the api to filter the views in any arbitrary way. This
change allowed for a good amount of code cleanup, and this commit also
ensures that the correct properties are checked in each case, including
the new View.destroying field added in the previous commit. This fixes
at least one crash involving switching focus to a destroying view.
This commit is contained in:
Isaac Freund
2020-08-21 15:08:28 +02:00
parent fa08d85c58
commit db416eb119
9 changed files with 185 additions and 217 deletions

View File

@ -44,15 +44,15 @@ pub fn focusView(
// If there is a currently focused view, focus the next visible view in the stack.
const focused_node = @fieldParentPtr(ViewStack(View).Node, "view", seat.focused.view);
var it = switch (direction) {
.next => ViewStack(View).iterator(focused_node, output.current.tags),
.previous => ViewStack(View).reverseIterator(focused_node, output.current.tags),
.next => ViewStack(View).iter(focused_node, .forward, output.pending.tags, filter),
.previous => ViewStack(View).iter(focused_node, .reverse, output.pending.tags, filter),
};
// Skip past the focused node
_ = it.next();
// Focus the next visible node if there is one
if (it.next()) |node| {
seat.focus(&node.view);
if (it.next()) |view| {
seat.focus(view);
output.root.startTransaction();
return;
}
@ -61,10 +61,14 @@ pub fn focusView(
// There is either no currently focused view or the last visible view in the
// stack is focused and we need to wrap.
var it = switch (direction) {
.next => ViewStack(View).iterator(output.views.first, output.current.tags),
.previous => ViewStack(View).reverseIterator(output.views.last, output.current.tags),
.next => ViewStack(View).iter(output.views.first, .forward, output.pending.tags, filter),
.previous => ViewStack(View).iter(output.views.last, .reverse, output.pending.tags, filter),
};
seat.focus(if (it.next()) |node| &node.view else null);
seat.focus(it.next());
output.root.startTransaction();
}
fn filter(view: *View, filter_tags: u32) bool {
return !view.destroying and view.pending.tags & filter_tags != 0;
}

View File

@ -39,19 +39,14 @@ pub fn zoom(
// If the first view that is part of the layout is focused, zoom
// the next view in the layout. Otherwise zoom the focused view.
const output = seat.focused_output;
var it = ViewStack(View).iterator(output.views.first, output.current.tags);
const layout_first = while (it.next()) |node| {
if (!node.view.pending.float and !node.view.pending.fullscreen) break node;
} else unreachable;
var it = ViewStack(View).iter(output.views.first, .forward, output.pending.tags, filter);
const layout_first = @fieldParentPtr(ViewStack(View).Node, "view", it.next().?);
const focused_node = @fieldParentPtr(ViewStack(View).Node, "view", seat.focused.view);
const zoom_node = if (focused_node == layout_first) blk: {
while (it.next()) |node| {
if (!node.view.pending.float and !node.view.pending.fullscreen) break :blk node;
} else {
break :blk null;
}
} else focused_node;
const zoom_node = if (focused_node == layout_first)
if (it.next()) |view| @fieldParentPtr(ViewStack(View).Node, "view", view) else null
else
focused_node;
if (zoom_node) |to_bump| {
output.views.remove(to_bump);
@ -62,3 +57,8 @@ pub fn zoom(
}
}
}
fn filter(view: *View, filter_tags: u32) bool {
return !view.destroying and !view.pending.float and
!view.pending.fullscreen and view.pending.tags & filter_tags != 0;
}