summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/tty/tty.zig41
1 files changed, 38 insertions, 3 deletions
diff --git a/src/tty/tty.zig b/src/tty/tty.zig
index 6f7cc5ba..343452b5 100644
--- a/src/tty/tty.zig
+++ b/src/tty/tty.zig
@@ -176,6 +176,31 @@ fn kittyImageRepresentable(place: pardes.ImagePlace) bool {
place.iw <= std.math.maxInt(u16) and place.ih <= std.math.maxInt(u16);
}
+const PdfWheelTarget = struct { pane: usize, page: usize };
+
+/// A native PDF's page geometry is invalid between `setPdfPage` and the next
+/// render. Remember the page under a vertical wheel press so the input batch
+/// can stop exactly when that press crosses a page boundary. The following
+/// queued wheel report then sees the newly rastered page instead of treating
+/// missing geometry as another page-wise fallback.
+fn nativePdfWheelTarget(core: *const pardes.Pardes, mouse: vaxis.Mouse) ?PdfWheelTarget {
+ if (comptime !pardes.pdf_enabled) return null;
+ if (!core.native_images or mouse.type != .press or
+ (mouse.button != .wheel_up and mouse.button != .wheel_down) or
+ mouse.col < 0 or mouse.row < 0) return null;
+ const col: u16 = @intCast(mouse.col);
+ const row: u16 = @intCast(mouse.row);
+ for (core.panes, 0..) |slot, id| {
+ const pane = slot orelse continue;
+ const rect = core.rects[id];
+ if (col < rect.x or col >= rect.x + rect.w or
+ row < rect.y or row >= rect.y + rect.h) continue;
+ const page = pane.pdfPage() orelse return null;
+ return .{ .pane = id, .page = page };
+ }
+ return null;
+}
+
pub fn run(init: std.process.Init, opts: pardes.Options) !void {
const io = init.io;
const gpa = init.gpa;
@@ -353,12 +378,15 @@ pub fn run(init: std.process.Init, opts: pardes.Options) !void {
const tz_event = tracy.zone(@src(), "event");
// Apply every queued INPUT event, then render ONCE — the gui shell
// drains SDL's queue the same way. Without this a wheel flick is fifty
- // full render+repaint (and re-highlight) cycles instead of one.
- // pty output keeps a frame per chunk: progress paints as it arrives.
+ // full render+repaint (and re-highlight) cycles instead of one. A
+ // native PDF page crossing is the one input boundary below: its next
+ // wheel report needs geometry produced by this render. Pty output also
+ // keeps a frame per chunk so progress paints as it arrives.
var stop = false;
var batch: usize = 0;
while (true) {
var output = false;
+ var native_pdf_page_changed = false;
switch (event) {
.nop, .tick => {},
.quit => stop = true,
@@ -390,6 +418,7 @@ pub fn run(init: std.process.Init, opts: pardes.Options) !void {
.shift = key.mods.shift,
} }),
.mouse => |m| {
+ const pdf_before = nativePdfWheelTarget(core, m);
const button: ?pardes.Mouse.Button = switch (m.button) {
.left => .left,
.middle => .middle,
@@ -413,6 +442,12 @@ pub fn run(init: std.process.Init, opts: pardes.Options) !void {
.row = @intCast(m.row),
.ctrl = m.mods.ctrl,
} });
+ if (pdf_before) |before| {
+ if (core.panes[before.pane]) |pane| {
+ if (pane.pdfPage()) |page|
+ native_pdf_page_changed = page != before.page;
+ }
+ }
},
.paste => |bytes| {
core.update(.{ .paste = bytes });
@@ -434,7 +469,7 @@ pub fn run(init: std.process.Init, opts: pardes.Options) !void {
},
}
batch += 1;
- if (stop or output or batch >= 64) break;
+ if (stop or output or native_pdf_page_changed or batch >= 64) break;
event = (try loop.tryEvent()) orelse break;
}
tz_event.end();