window: fix negative offset clip
Accumulate any negative offsets in order to properly clip windows to their parents. Previously, we only clipped if the window would be off the screen from a negative offset. In the diagram below, we should expect that if B is a child of A, it can't print in the non-overlapping area. That is, B can only print in the overlapping region with A because it is a child of A. This patch fixes this. +-----------------------------------------------------+ | | | +--------+ | | | B | | | | +---|-----+ | | | | | | | | +--------+ | | | | | | | | A | | | +---------+ | | | | | | | +-----------------------------------------------------+
This commit is contained in:
parent
497b544c59
commit
9d8dd75111
2 changed files with 54 additions and 6 deletions
|
@ -205,6 +205,8 @@ pub fn window(self: *Vaxis) Window {
|
|||
return .{
|
||||
.x_off = 0,
|
||||
.y_off = 0,
|
||||
.parent_x_off = 0,
|
||||
.parent_y_off = 0,
|
||||
.width = self.screen.width,
|
||||
.height = self.screen.height,
|
||||
.screen = &self.screen,
|
||||
|
|
|
@ -9,10 +9,16 @@ const gw = @import("gwidth.zig");
|
|||
|
||||
const Window = @This();
|
||||
|
||||
/// horizontal offset from the screen
|
||||
/// absolute horizontal offset from the screen
|
||||
x_off: i17,
|
||||
/// vertical offset from the screen
|
||||
/// absolute vertical offset from the screen
|
||||
y_off: i17,
|
||||
/// relative horizontal offset, from parent window. This only accumulates if it is negative so that
|
||||
/// we can clip the window correctly
|
||||
parent_x_off: i17,
|
||||
/// relative vertical offset, from parent window. This only accumulates if it is negative so that
|
||||
/// we can clip the window correctly
|
||||
parent_y_off: i17,
|
||||
/// width of the window. This can't be larger than the terminal screen
|
||||
width: u16,
|
||||
/// height of the window. This can't be larger than the terminal screen
|
||||
|
@ -36,6 +42,8 @@ fn initChild(
|
|||
return Window{
|
||||
.x_off = x_off + self.x_off,
|
||||
.y_off = y_off + self.y_off,
|
||||
.parent_x_off = @min(self.parent_x_off + x_off, 0),
|
||||
.parent_y_off = @min(self.parent_y_off + y_off, 0),
|
||||
.width = width,
|
||||
.height = height,
|
||||
.screen = self.screen,
|
||||
|
@ -165,9 +173,14 @@ pub fn child(self: Window, opts: ChildOptions) Window {
|
|||
|
||||
/// writes a cell to the location in the window
|
||||
pub fn writeCell(self: Window, col: u16, row: u16, cell: Cell) void {
|
||||
if (self.height <= row or self.width <= col) return;
|
||||
if (self.x_off + col < 0) return;
|
||||
if (self.y_off + row < 0) return;
|
||||
if (self.height <= row or
|
||||
self.width <= col or
|
||||
self.x_off + col < 0 or
|
||||
self.y_off + row < 0 or
|
||||
self.parent_x_off + col < 0 or
|
||||
self.parent_y_off + row < 0)
|
||||
return;
|
||||
|
||||
self.screen.writeCell(@intCast(col + self.x_off), @intCast(row + self.y_off), cell);
|
||||
}
|
||||
|
||||
|
@ -176,7 +189,9 @@ pub fn readCell(self: Window, col: u16, row: u16) ?Cell {
|
|||
if (self.height <= row or
|
||||
self.width <= col or
|
||||
self.x_off + col < 0 or
|
||||
self.y_off + row < 0)
|
||||
self.y_off + row < 0 or
|
||||
self.parent_x_off + col < 0 or
|
||||
self.parent_y_off + row < 0)
|
||||
return null;
|
||||
return self.screen.readCell(@intCast(col + self.x_off), @intCast(row + self.y_off));
|
||||
}
|
||||
|
@ -465,6 +480,8 @@ test "Window size set" {
|
|||
var parent = Window{
|
||||
.x_off = 0,
|
||||
.y_off = 0,
|
||||
.parent_x_off = 0,
|
||||
.parent_y_off = 0,
|
||||
.width = 20,
|
||||
.height = 20,
|
||||
.screen = undefined,
|
||||
|
@ -479,6 +496,8 @@ test "Window size set too big" {
|
|||
var parent = Window{
|
||||
.x_off = 0,
|
||||
.y_off = 0,
|
||||
.parent_x_off = 0,
|
||||
.parent_y_off = 0,
|
||||
.width = 20,
|
||||
.height = 20,
|
||||
.screen = undefined,
|
||||
|
@ -493,6 +512,8 @@ test "Window size set too big with offset" {
|
|||
var parent = Window{
|
||||
.x_off = 0,
|
||||
.y_off = 0,
|
||||
.parent_x_off = 0,
|
||||
.parent_y_off = 0,
|
||||
.width = 20,
|
||||
.height = 20,
|
||||
.screen = undefined,
|
||||
|
@ -507,6 +528,8 @@ test "Window size nested offsets" {
|
|||
var parent = Window{
|
||||
.x_off = 1,
|
||||
.y_off = 1,
|
||||
.parent_x_off = 0,
|
||||
.parent_y_off = 0,
|
||||
.width = 20,
|
||||
.height = 20,
|
||||
.screen = undefined,
|
||||
|
@ -517,6 +540,25 @@ test "Window size nested offsets" {
|
|||
try std.testing.expectEqual(11, ch.y_off);
|
||||
}
|
||||
|
||||
test "Window offsets" {
|
||||
var parent = Window{
|
||||
.x_off = 0,
|
||||
.y_off = 0,
|
||||
.parent_x_off = 0,
|
||||
.parent_y_off = 0,
|
||||
.width = 20,
|
||||
.height = 20,
|
||||
.screen = undefined,
|
||||
};
|
||||
|
||||
const ch = parent.initChild(10, 10, 21, 21);
|
||||
const ch2 = ch.initChild(-4, -4, null, null);
|
||||
// Reading ch2 at row 0 should be null
|
||||
try std.testing.expect(ch2.readCell(0, 0) == null);
|
||||
// Should not panic us
|
||||
ch2.writeCell(0, 0, undefined);
|
||||
}
|
||||
|
||||
test "print: grapheme" {
|
||||
const alloc = std.testing.allocator_instance.allocator();
|
||||
const unicode = try Unicode.init(alloc);
|
||||
|
@ -525,6 +567,8 @@ test "print: grapheme" {
|
|||
const win: Window = .{
|
||||
.x_off = 0,
|
||||
.y_off = 0,
|
||||
.parent_x_off = 0,
|
||||
.parent_y_off = 0,
|
||||
.width = 4,
|
||||
.height = 2,
|
||||
.screen = &screen,
|
||||
|
@ -592,6 +636,8 @@ test "print: word" {
|
|||
const win: Window = .{
|
||||
.x_off = 0,
|
||||
.y_off = 0,
|
||||
.parent_x_off = 0,
|
||||
.parent_y_off = 0,
|
||||
.width = 4,
|
||||
.height = 2,
|
||||
.screen = &screen,
|
||||
|
|
Loading…
Add table
Reference in a new issue