Allow storing *View in ViewStack
This is done in preparation for implementing focus stacks.
This commit is contained in:
parent
0f52f664f2
commit
b822084f39
@ -3,6 +3,7 @@ const c = @import("c.zig");
|
|||||||
|
|
||||||
const Log = @import("log.zig").Log;
|
const Log = @import("log.zig").Log;
|
||||||
const Server = @import("server.zig").Server;
|
const Server = @import("server.zig").Server;
|
||||||
|
const View = @import("view.zig").View;
|
||||||
const ViewStack = @import("view_stack.zig").ViewStack;
|
const ViewStack = @import("view_stack.zig").ViewStack;
|
||||||
|
|
||||||
pub const Arg = union {
|
pub const Arg = union {
|
||||||
@ -60,7 +61,7 @@ pub fn modifyMasterFactor(server: *Server, arg: Arg) void {
|
|||||||
pub fn zoom(server: *Server, arg: Arg) void {
|
pub fn zoom(server: *Server, arg: Arg) void {
|
||||||
if (server.root.focused_view) |current_focus| {
|
if (server.root.focused_view) |current_focus| {
|
||||||
const output = server.root.focusedOutput();
|
const output = server.root.focusedOutput();
|
||||||
const node = @fieldParentPtr(ViewStack.Node, "view", current_focus);
|
const node = @fieldParentPtr(ViewStack(View).Node, "view", current_focus);
|
||||||
if (node != output.views.first) {
|
if (node != output.views.first) {
|
||||||
output.views.remove(node);
|
output.views.remove(node);
|
||||||
output.views.push(node);
|
output.views.push(node);
|
||||||
|
@ -6,6 +6,7 @@ const Box = @import("box.zig").Box;
|
|||||||
const LayerSurface = @import("layer_surface.zig").LayerSurface;
|
const LayerSurface = @import("layer_surface.zig").LayerSurface;
|
||||||
const Log = @import("log.zig").Log;
|
const Log = @import("log.zig").Log;
|
||||||
const Root = @import("root.zig").Root;
|
const Root = @import("root.zig").Root;
|
||||||
|
const View = @import("view.zig").View;
|
||||||
const ViewStack = @import("view_stack.zig").ViewStack;
|
const ViewStack = @import("view_stack.zig").ViewStack;
|
||||||
|
|
||||||
pub const Output = struct {
|
pub const Output = struct {
|
||||||
@ -22,7 +23,7 @@ pub const Output = struct {
|
|||||||
usable_box: Box,
|
usable_box: Box,
|
||||||
|
|
||||||
/// The top of the stack is the "most important" view.
|
/// The top of the stack is the "most important" view.
|
||||||
views: ViewStack,
|
views: ViewStack(View),
|
||||||
|
|
||||||
/// A bit field of focused tags
|
/// A bit field of focused tags
|
||||||
current_focused_tags: u32,
|
current_focused_tags: u32,
|
||||||
@ -100,7 +101,7 @@ pub const Output = struct {
|
|||||||
/// Add a new view to the output. arrangeViews() will be called by the view
|
/// Add a new view to the output. arrangeViews() will be called by the view
|
||||||
/// when it is mapped.
|
/// when it is mapped.
|
||||||
pub fn addView(self: *Self, wlr_xdg_surface: *c.wlr_xdg_surface) void {
|
pub fn addView(self: *Self, wlr_xdg_surface: *c.wlr_xdg_surface) void {
|
||||||
const node = self.root.server.allocator.create(ViewStack.Node) catch unreachable;
|
const node = self.root.server.allocator.create(ViewStack(View).Node) catch unreachable;
|
||||||
node.view.init(self, wlr_xdg_surface, self.current_focused_tags);
|
node.view.init(self, wlr_xdg_surface, self.current_focused_tags);
|
||||||
self.views.push(node);
|
self.views.push(node);
|
||||||
}
|
}
|
||||||
@ -129,7 +130,7 @@ pub const Output = struct {
|
|||||||
|
|
||||||
const visible_count = blk: {
|
const visible_count = blk: {
|
||||||
var count: u32 = 0;
|
var count: u32 = 0;
|
||||||
var it = ViewStack.pendingIterator(self.views.first, output_tags);
|
var it = ViewStack(View).pendingIterator(self.views.first, output_tags);
|
||||||
while (it.next() != null) count += 1;
|
while (it.next() != null) count += 1;
|
||||||
break :blk count;
|
break :blk count;
|
||||||
};
|
};
|
||||||
@ -157,8 +158,9 @@ pub const Output = struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var i: u32 = 0;
|
var i: u32 = 0;
|
||||||
var it = ViewStack.pendingIterator(self.views.first, output_tags);
|
var it = ViewStack(View).pendingIterator(self.views.first, output_tags);
|
||||||
while (it.next()) |view| {
|
while (it.next()) |node| {
|
||||||
|
const view = &node.view;
|
||||||
if (i < master_count) {
|
if (i < master_count) {
|
||||||
// Add the remainder to the first master to ensure every pixel of height is used
|
// Add the remainder to the first master to ensure every pixel of height is used
|
||||||
const master_height = @divTrunc(layout_height, master_count);
|
const master_height = @divTrunc(layout_height, master_count);
|
||||||
|
@ -44,8 +44,9 @@ pub fn renderOutput(output: *Output) void {
|
|||||||
renderLayer(output.*, output.layers[c.ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM], &now, ox, oy);
|
renderLayer(output.*, output.layers[c.ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM], &now, ox, oy);
|
||||||
|
|
||||||
// The first view in the list is "on top" so iterate in reverse.
|
// The first view in the list is "on top" so iterate in reverse.
|
||||||
var it = ViewStack.reverseIterator(output.views.last, output.current_focused_tags);
|
var it = ViewStack(View).reverseIterator(output.views.last, output.current_focused_tags);
|
||||||
while (it.next()) |view| {
|
while (it.next()) |node| {
|
||||||
|
const view = &node.view;
|
||||||
// This check prevents a race condition when a frame is requested
|
// This check prevents a race condition when a frame is requested
|
||||||
// between mapping of a view and the first configure being handled.
|
// between mapping of a view and the first configure being handled.
|
||||||
if (view.current_box.width == 0 or view.current_box.height == 0) {
|
if (view.current_box.width == 0 or view.current_box.height == 0) {
|
||||||
|
46
src/root.zig
46
src/root.zig
@ -71,10 +71,10 @@ pub const Root = struct {
|
|||||||
var output_it = self.outputs.first;
|
var output_it = self.outputs.first;
|
||||||
while (output_it) |node| : (output_it = node.next) {
|
while (output_it) |node| : (output_it = node.next) {
|
||||||
const output = &node.data;
|
const output = &node.data;
|
||||||
var view_it = ViewStack.iterator(output.views.first, 0xFFFFFFFF);
|
var view_it = ViewStack(View).iterator(output.views.first, 0xFFFFFFFF);
|
||||||
while (view_it.next()) |view| {
|
while (view_it.next()) |view_node| {
|
||||||
if (view.isAt(lx, ly, surface, sx, sy)) {
|
if (view_node.view.isAt(lx, ly, surface, sx, sy)) {
|
||||||
return view;
|
return &view_node.view;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -95,22 +95,22 @@ pub const Root = struct {
|
|||||||
const output = self.focusedOutput();
|
const output = self.focusedOutput();
|
||||||
if (self.focused_view) |current_focus| {
|
if (self.focused_view) |current_focus| {
|
||||||
// If there is a currently focused view, focus the next visible view in the stack.
|
// If there is a currently focused view, focus the next visible view in the stack.
|
||||||
const current_node = @fieldParentPtr(ViewStack.Node, "view", current_focus);
|
const current_node = @fieldParentPtr(ViewStack(View).Node, "view", current_focus);
|
||||||
var it = ViewStack.iterator(current_node, output.current_focused_tags);
|
var it = ViewStack(View).iterator(current_node, output.current_focused_tags);
|
||||||
// Skip past the current node
|
// Skip past the current node
|
||||||
_ = it.next();
|
_ = it.next();
|
||||||
// Focus the next visible node if there is one
|
// Focus the next visible node if there is one
|
||||||
if (it.next()) |view| {
|
if (it.next()) |node| {
|
||||||
view.focus(view.wlr_xdg_surface.surface);
|
node.view.focus(node.view.wlr_xdg_surface.surface);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// There is either no currently focused view or the last visible view in the
|
// There is either no currently focused view or the last visible view in the
|
||||||
// stack is focused and we need to wrap.
|
// stack is focused and we need to wrap.
|
||||||
var it = ViewStack.iterator(output.views.first, output.current_focused_tags);
|
var it = ViewStack(View).iterator(output.views.first, output.current_focused_tags);
|
||||||
if (it.next()) |view| {
|
if (it.next()) |node| {
|
||||||
view.focus(view.wlr_xdg_surface.surface);
|
node.view.focus(node.view.wlr_xdg_surface.surface);
|
||||||
} else {
|
} else {
|
||||||
// Otherwise clear the focus since there are no visible views
|
// Otherwise clear the focus since there are no visible views
|
||||||
self.clearFocus();
|
self.clearFocus();
|
||||||
@ -123,22 +123,22 @@ pub const Root = struct {
|
|||||||
const output = self.focusedOutput();
|
const output = self.focusedOutput();
|
||||||
if (self.focused_view) |current_focus| {
|
if (self.focused_view) |current_focus| {
|
||||||
// If there is a currently focused view, focus the previous visible view in the stack.
|
// If there is a currently focused view, focus the previous visible view in the stack.
|
||||||
const current_node = @fieldParentPtr(ViewStack.Node, "view", current_focus);
|
const current_node = @fieldParentPtr(ViewStack(View).Node, "view", current_focus);
|
||||||
var it = ViewStack.reverseIterator(current_node, output.current_focused_tags);
|
var it = ViewStack(View).reverseIterator(current_node, output.current_focused_tags);
|
||||||
// Skip past the current node
|
// Skip past the current node
|
||||||
_ = it.next();
|
_ = it.next();
|
||||||
// Focus the previous visible node if there is one
|
// Focus the previous visible node if there is one
|
||||||
if (it.next()) |view| {
|
if (it.next()) |node| {
|
||||||
view.focus(view.wlr_xdg_surface.surface);
|
node.view.focus(node.view.wlr_xdg_surface.surface);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// There is either no currently focused view or the first visible view in the
|
// There is either no currently focused view or the first visible view in the
|
||||||
// stack is focused and we need to wrap.
|
// stack is focused and we need to wrap.
|
||||||
var it = ViewStack.reverseIterator(output.views.last, output.current_focused_tags);
|
var it = ViewStack(View).reverseIterator(output.views.last, output.current_focused_tags);
|
||||||
if (it.next()) |view| {
|
if (it.next()) |node| {
|
||||||
view.focus(view.wlr_xdg_surface.surface);
|
node.view.focus(node.view.wlr_xdg_surface.surface);
|
||||||
} else {
|
} else {
|
||||||
// Otherwise clear the focus since there are no visible views
|
// Otherwise clear the focus since there are no visible views
|
||||||
self.clearFocus();
|
self.clearFocus();
|
||||||
@ -166,8 +166,9 @@ pub const Root = struct {
|
|||||||
var output_it = self.outputs.first;
|
var output_it = self.outputs.first;
|
||||||
while (output_it) |node| : (output_it = node.next) {
|
while (output_it) |node| : (output_it = node.next) {
|
||||||
const output = &node.data;
|
const output = &node.data;
|
||||||
var view_it = ViewStack.iterator(output.views.first, 0xFFFFFFFF);
|
var view_it = ViewStack(View).iterator(output.views.first, 0xFFFFFFFF);
|
||||||
while (view_it.next()) |view| {
|
while (view_it.next()) |view_node| {
|
||||||
|
const view = &view_node.view;
|
||||||
// Clear the serial in case this transaction is interrupting a prior one.
|
// Clear the serial in case this transaction is interrupting a prior one.
|
||||||
view.pending_serial = null;
|
view.pending_serial = null;
|
||||||
|
|
||||||
@ -259,8 +260,9 @@ pub const Root = struct {
|
|||||||
self.focusNextView();
|
self.focusNextView();
|
||||||
}
|
}
|
||||||
|
|
||||||
var view_it = ViewStack.iterator(output.views.first, 0xFFFFFFFF);
|
var view_it = ViewStack(View).iterator(output.views.first, 0xFFFFFFFF);
|
||||||
while (view_it.next()) |view| {
|
while (view_it.next()) |view_node| {
|
||||||
|
const view = &view_node.view;
|
||||||
// Ensure that all pending state is cleared
|
// Ensure that all pending state is cleared
|
||||||
view.pending_serial = null;
|
view.pending_serial = null;
|
||||||
if (view.pending_box) |state| {
|
if (view.pending_box) |state| {
|
||||||
|
@ -156,7 +156,7 @@ pub const View = struct {
|
|||||||
const view = @fieldParentPtr(View, "listen_destroy", listener.?);
|
const view = @fieldParentPtr(View, "listen_destroy", listener.?);
|
||||||
const output = view.output;
|
const output = view.output;
|
||||||
|
|
||||||
const node = @fieldParentPtr(ViewStack.Node, "view", view);
|
const node = @fieldParentPtr(ViewStack(View).Node, "view", view);
|
||||||
output.views.remove(node);
|
output.views.remove(node);
|
||||||
output.root.server.allocator.destroy(node);
|
output.root.server.allocator.destroy(node);
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,12 @@
|
|||||||
const View = @import("view.zig").View;
|
const View = @import("view.zig").View;
|
||||||
|
|
||||||
/// A specialized doubly-linked stack that allows for filtered iteration
|
/// A specialized doubly-linked stack that allows for filtered iteration
|
||||||
/// over the nodes
|
/// over the nodes. T must be View or *View.
|
||||||
pub const ViewStack = struct {
|
pub fn ViewStack(comptime T: type) type {
|
||||||
|
if (!(T == View or T == *View)) {
|
||||||
|
@compileError("ViewStack: T must be View or *View");
|
||||||
|
}
|
||||||
|
return struct {
|
||||||
const Self = @This();
|
const Self = @This();
|
||||||
|
|
||||||
pub const Node = struct {
|
pub const Node = struct {
|
||||||
@ -11,7 +15,7 @@ pub const ViewStack = struct {
|
|||||||
next: ?*Node,
|
next: ?*Node,
|
||||||
|
|
||||||
/// The view stored in this node
|
/// The view stored in this node
|
||||||
view: View,
|
view: T,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Top/bottom nodes in the stack
|
/// Top/bottom nodes in the stack
|
||||||
@ -69,7 +73,7 @@ pub const ViewStack = struct {
|
|||||||
|
|
||||||
/// Returns the next node in iteration order, or null if done.
|
/// Returns the next node in iteration order, or null if done.
|
||||||
/// This function is horribly ugly, but it's well tested below.
|
/// This function is horribly ugly, but it's well tested below.
|
||||||
pub fn next(self: *Iterator) ?*View {
|
pub fn next(self: *Iterator) ?*Node {
|
||||||
while (self.it) |node| : (self.it = if (self.reverse) node.prev else node.next) {
|
while (self.it) |node| : (self.it = if (self.reverse) node.prev else node.next) {
|
||||||
if (node.view.mapped and if (self.pending)
|
if (node.view.mapped and if (self.pending)
|
||||||
if (node.view.pending_tags) |pending_tags|
|
if (node.view.pending_tags) |pending_tags|
|
||||||
@ -78,9 +82,8 @@ pub const ViewStack = struct {
|
|||||||
self.tags & node.view.current_tags != 0
|
self.tags & node.view.current_tags != 0
|
||||||
else
|
else
|
||||||
self.tags & node.view.current_tags != 0) {
|
self.tags & node.view.current_tags != 0) {
|
||||||
const ret = &node.view;
|
|
||||||
self.it = if (self.reverse) node.prev else node.next;
|
self.it = if (self.reverse) node.prev else node.next;
|
||||||
return ret;
|
return node;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
@ -124,24 +127,25 @@ pub const ViewStack = struct {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
|
||||||
const testing = @import("std").testing;
|
const testing = @import("std").testing;
|
||||||
|
|
||||||
test "push/remove" {
|
test "push/remove (*View)" {
|
||||||
const allocator = testing.allocator;
|
const allocator = testing.allocator;
|
||||||
|
|
||||||
var views: ViewStack = undefined;
|
var views: ViewStack(*View) = undefined;
|
||||||
views.init();
|
views.init();
|
||||||
|
|
||||||
const one = try allocator.create(ViewStack.Node);
|
const one = try allocator.create(ViewStack(*View).Node);
|
||||||
defer allocator.destroy(one);
|
defer allocator.destroy(one);
|
||||||
const two = try allocator.create(ViewStack.Node);
|
const two = try allocator.create(ViewStack(*View).Node);
|
||||||
defer allocator.destroy(two);
|
defer allocator.destroy(two);
|
||||||
const three = try allocator.create(ViewStack.Node);
|
const three = try allocator.create(ViewStack(*View).Node);
|
||||||
defer allocator.destroy(three);
|
defer allocator.destroy(three);
|
||||||
const four = try allocator.create(ViewStack.Node);
|
const four = try allocator.create(ViewStack(*View).Node);
|
||||||
defer allocator.destroy(four);
|
defer allocator.destroy(four);
|
||||||
const five = try allocator.create(ViewStack.Node);
|
const five = try allocator.create(ViewStack(*View).Node);
|
||||||
defer allocator.destroy(five);
|
defer allocator.destroy(five);
|
||||||
|
|
||||||
views.push(three); // {3}
|
views.push(three); // {3}
|
||||||
@ -255,40 +259,40 @@ test "push/remove" {
|
|||||||
testing.expect(views.last == null);
|
testing.expect(views.last == null);
|
||||||
}
|
}
|
||||||
|
|
||||||
test "iteration" {
|
test "iteration (View)" {
|
||||||
const allocator = testing.allocator;
|
const allocator = testing.allocator;
|
||||||
|
|
||||||
var views: ViewStack = undefined;
|
var views: ViewStack(View) = undefined;
|
||||||
views.init();
|
views.init();
|
||||||
|
|
||||||
const one_a_pb = try allocator.create(ViewStack.Node);
|
const one_a_pb = try allocator.create(ViewStack(View).Node);
|
||||||
defer allocator.destroy(one_a_pb);
|
defer allocator.destroy(one_a_pb);
|
||||||
one_a_pb.view.mapped = true;
|
one_a_pb.view.mapped = true;
|
||||||
one_a_pb.view.current_tags = 1 << 0;
|
one_a_pb.view.current_tags = 1 << 0;
|
||||||
one_a_pb.view.pending_tags = 1 << 1;
|
one_a_pb.view.pending_tags = 1 << 1;
|
||||||
|
|
||||||
const two_a = try allocator.create(ViewStack.Node);
|
const two_a = try allocator.create(ViewStack(View).Node);
|
||||||
defer allocator.destroy(two_a);
|
defer allocator.destroy(two_a);
|
||||||
two_a.view.mapped = true;
|
two_a.view.mapped = true;
|
||||||
two_a.view.current_tags = 1 << 0;
|
two_a.view.current_tags = 1 << 0;
|
||||||
|
|
||||||
const three_b_pa = try allocator.create(ViewStack.Node);
|
const three_b_pa = try allocator.create(ViewStack(View).Node);
|
||||||
defer allocator.destroy(three_b_pa);
|
defer allocator.destroy(three_b_pa);
|
||||||
three_b_pa.view.mapped = true;
|
three_b_pa.view.mapped = true;
|
||||||
three_b_pa.view.current_tags = 1 << 1;
|
three_b_pa.view.current_tags = 1 << 1;
|
||||||
three_b_pa.view.pending_tags = 1 << 0;
|
three_b_pa.view.pending_tags = 1 << 0;
|
||||||
|
|
||||||
const four_b = try allocator.create(ViewStack.Node);
|
const four_b = try allocator.create(ViewStack(View).Node);
|
||||||
defer allocator.destroy(four_b);
|
defer allocator.destroy(four_b);
|
||||||
four_b.view.mapped = true;
|
four_b.view.mapped = true;
|
||||||
four_b.view.current_tags = 1 << 1;
|
four_b.view.current_tags = 1 << 1;
|
||||||
|
|
||||||
const five_b = try allocator.create(ViewStack.Node);
|
const five_b = try allocator.create(ViewStack(View).Node);
|
||||||
defer allocator.destroy(five_b);
|
defer allocator.destroy(five_b);
|
||||||
five_b.view.mapped = true;
|
five_b.view.mapped = true;
|
||||||
five_b.view.current_tags = 1 << 1;
|
five_b.view.current_tags = 1 << 1;
|
||||||
|
|
||||||
const unmapped_1 = try allocator.create(ViewStack.Node);
|
const unmapped_1 = try allocator.create(ViewStack(View).Node);
|
||||||
defer allocator.destroy(unmapped_1);
|
defer allocator.destroy(unmapped_1);
|
||||||
unmapped_1.view.mapped = false;
|
unmapped_1.view.mapped = false;
|
||||||
|
|
||||||
@ -301,92 +305,92 @@ test "iteration" {
|
|||||||
|
|
||||||
// Iteration over all tags
|
// Iteration over all tags
|
||||||
{
|
{
|
||||||
var it = ViewStack.iterator(views.first, 0xFFFFFFFF);
|
var it = ViewStack(View).iterator(views.first, 0xFFFFFFFF);
|
||||||
testing.expect(it.next() == &two_a.view);
|
testing.expect((if (it.next()) |node| &node.view else null) == &two_a.view);
|
||||||
testing.expect(it.next() == &five_b.view);
|
testing.expect((if (it.next()) |node| &node.view else null) == &five_b.view);
|
||||||
testing.expect(it.next() == &four_b.view);
|
testing.expect((if (it.next()) |node| &node.view else null) == &four_b.view);
|
||||||
testing.expect(it.next() == &one_a_pb.view);
|
testing.expect((if (it.next()) |node| &node.view else null) == &one_a_pb.view);
|
||||||
testing.expect(it.next() == &three_b_pa.view);
|
testing.expect((if (it.next()) |node| &node.view else null) == &three_b_pa.view);
|
||||||
testing.expect(it.next() == null);
|
testing.expect(it.next() == null);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Iteration over 'a' tags
|
// Iteration over 'a' tags
|
||||||
{
|
{
|
||||||
var it = ViewStack.iterator(views.first, 1 << 0);
|
var it = ViewStack(View).iterator(views.first, 1 << 0);
|
||||||
testing.expect(it.next() == &two_a.view);
|
testing.expect((if (it.next()) |node| &node.view else null) == &two_a.view);
|
||||||
testing.expect(it.next() == &one_a_pb.view);
|
testing.expect((if (it.next()) |node| &node.view else null) == &one_a_pb.view);
|
||||||
testing.expect(it.next() == null);
|
testing.expect(it.next() == null);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Iteration over 'b' tags
|
// Iteration over 'b' tags
|
||||||
{
|
{
|
||||||
var it = ViewStack.iterator(views.first, 1 << 1);
|
var it = ViewStack(View).iterator(views.first, 1 << 1);
|
||||||
testing.expect(it.next() == &five_b.view);
|
testing.expect((if (it.next()) |node| &node.view else null) == &five_b.view);
|
||||||
testing.expect(it.next() == &four_b.view);
|
testing.expect((if (it.next()) |node| &node.view else null) == &four_b.view);
|
||||||
testing.expect(it.next() == &three_b_pa.view);
|
testing.expect((if (it.next()) |node| &node.view else null) == &three_b_pa.view);
|
||||||
testing.expect(it.next() == null);
|
testing.expect(it.next() == null);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Iteration over tags that aren't present
|
// Iteration over tags that aren't present
|
||||||
{
|
{
|
||||||
var it = ViewStack.iterator(views.first, 1 << 2);
|
var it = ViewStack(View).iterator(views.first, 1 << 2);
|
||||||
testing.expect(it.next() == null);
|
testing.expect(it.next() == null);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reverse iteration over all tags
|
// Reverse iteration over all tags
|
||||||
{
|
{
|
||||||
var it = ViewStack.reverseIterator(views.last, 0xFFFFFFFF);
|
var it = ViewStack(View).reverseIterator(views.last, 0xFFFFFFFF);
|
||||||
testing.expect(it.next() == &three_b_pa.view);
|
testing.expect((if (it.next()) |node| &node.view else null) == &three_b_pa.view);
|
||||||
testing.expect(it.next() == &one_a_pb.view);
|
testing.expect((if (it.next()) |node| &node.view else null) == &one_a_pb.view);
|
||||||
testing.expect(it.next() == &four_b.view);
|
testing.expect((if (it.next()) |node| &node.view else null) == &four_b.view);
|
||||||
testing.expect(it.next() == &five_b.view);
|
testing.expect((if (it.next()) |node| &node.view else null) == &five_b.view);
|
||||||
testing.expect(it.next() == &two_a.view);
|
testing.expect((if (it.next()) |node| &node.view else null) == &two_a.view);
|
||||||
testing.expect(it.next() == null);
|
testing.expect(it.next() == null);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reverse iteration over 'a' tags
|
// Reverse iteration over 'a' tags
|
||||||
{
|
{
|
||||||
var it = ViewStack.reverseIterator(views.last, 1 << 0);
|
var it = ViewStack(View).reverseIterator(views.last, 1 << 0);
|
||||||
testing.expect(it.next() == &one_a_pb.view);
|
testing.expect((if (it.next()) |node| &node.view else null) == &one_a_pb.view);
|
||||||
testing.expect(it.next() == &two_a.view);
|
testing.expect((if (it.next()) |node| &node.view else null) == &two_a.view);
|
||||||
testing.expect(it.next() == null);
|
testing.expect(it.next() == null);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reverse iteration over 'b' tags
|
// Reverse iteration over 'b' tags
|
||||||
{
|
{
|
||||||
var it = ViewStack.reverseIterator(views.last, 1 << 1);
|
var it = ViewStack(View).reverseIterator(views.last, 1 << 1);
|
||||||
testing.expect(it.next() == &three_b_pa.view);
|
testing.expect((if (it.next()) |node| &node.view else null) == &three_b_pa.view);
|
||||||
testing.expect(it.next() == &four_b.view);
|
testing.expect((if (it.next()) |node| &node.view else null) == &four_b.view);
|
||||||
testing.expect(it.next() == &five_b.view);
|
testing.expect((if (it.next()) |node| &node.view else null) == &five_b.view);
|
||||||
testing.expect(it.next() == null);
|
testing.expect(it.next() == null);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reverse iteration over tags that aren't present
|
// Reverse iteration over tags that aren't present
|
||||||
{
|
{
|
||||||
var it = ViewStack.reverseIterator(views.first, 1 << 2);
|
var it = ViewStack(View).reverseIterator(views.first, 1 << 2);
|
||||||
testing.expect(it.next() == null);
|
testing.expect(it.next() == null);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Iteration over (pending) 'a' tags
|
// Iteration over (pending) 'a' tags
|
||||||
{
|
{
|
||||||
var it = ViewStack.pendingIterator(views.first, 1 << 0);
|
var it = ViewStack(View).pendingIterator(views.first, 1 << 0);
|
||||||
testing.expect(it.next() == &two_a.view);
|
testing.expect((if (it.next()) |node| &node.view else null) == &two_a.view);
|
||||||
testing.expect(it.next() == &three_b_pa.view);
|
testing.expect((if (it.next()) |node| &node.view else null) == &three_b_pa.view);
|
||||||
testing.expect(it.next() == null);
|
testing.expect(it.next() == null);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Iteration over (pending) 'b' tags
|
// Iteration over (pending) 'b' tags
|
||||||
{
|
{
|
||||||
var it = ViewStack.pendingIterator(views.first, 1 << 1);
|
var it = ViewStack(View).pendingIterator(views.first, 1 << 1);
|
||||||
testing.expect(it.next() == &five_b.view);
|
testing.expect((if (it.next()) |node| &node.view else null) == &five_b.view);
|
||||||
testing.expect(it.next() == &four_b.view);
|
testing.expect((if (it.next()) |node| &node.view else null) == &four_b.view);
|
||||||
testing.expect(it.next() == &one_a_pb.view);
|
testing.expect((if (it.next()) |node| &node.view else null) == &one_a_pb.view);
|
||||||
testing.expect(it.next() == null);
|
testing.expect(it.next() == null);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Iteration over (pending) tags that aren't present
|
// Iteration over (pending) tags that aren't present
|
||||||
{
|
{
|
||||||
var it = ViewStack.pendingIterator(views.first, 1 << 2);
|
var it = ViewStack(View).pendingIterator(views.first, 1 << 2);
|
||||||
testing.expect(it.next() == null);
|
testing.expect(it.next() == null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user