| ... | @@ -157,6 +157,7 @@ describe("GhosttyTerminalSurface visibility", () => { | ... | @@ -157,6 +157,7 @@ describe("GhosttyTerminalSurface visibility", () => { |
| 157 | "window", | 157 | "window", |
| 158 | Object.assign(new EventTarget(), { | 158 | Object.assign(new EventTarget(), { |
| 159 | devicePixelRatio: 1, | 159 | devicePixelRatio: 1, |
| | 160 | innerHeight: 104, |
| 160 | requestAnimationFrame: requestFrame, | 161 | requestAnimationFrame: requestFrame, |
| 161 | cancelAnimationFrame: (id: number) => frames.delete(id), | 162 | cancelAnimationFrame: (id: number) => frames.delete(id), |
| 162 | setTimeout, | 163 | setTimeout, |
| ... | @@ -214,11 +215,12 @@ describe("GhosttyTerminalSurface visibility", () => { | ... | @@ -214,11 +215,12 @@ describe("GhosttyTerminalSurface visibility", () => { |
| 214 | buttons: number, | 215 | buttons: number, |
| 215 | modifiers: boolean | Partial<Pick<MouseEvent, "ctrlKey" | "metaKey" | "shiftKey">> = {}, | 216 | modifiers: boolean | Partial<Pick<MouseEvent, "ctrlKey" | "metaKey" | "shiftKey">> = {}, |
| 216 | button = 0, | 217 | button = 0, |
| | 218 | clientY = 5, |
| 217 | ) { | 219 | ) { |
| 218 | canvas.dispatchEvent( | 220 | canvas.dispatchEvent( |
| 219 | Object.assign(new Event(type, { cancelable: true }), { | 221 | Object.assign(new Event(type, { cancelable: true }), { |
| 220 | clientX, | 222 | clientX, |
| 221 | clientY: 5, | 223 | clientY, |
| 222 | pointerId: 1, | 224 | pointerId: 1, |
| 223 | button, | 225 | button, |
| 224 | buttons, | 226 | buttons, |
| ... | @@ -611,6 +613,29 @@ describe("GhosttyTerminalSurface visibility", () => { | ... | @@ -611,6 +613,29 @@ describe("GhosttyTerminalSurface visibility", () => { |
| 611 | expect(harness.renderedSnapshot.rowData[0]?.cells.some((cell) => cell.selected)).toBe(false); | 613 | expect(harness.renderedSnapshot.rowData[0]?.cells.some((cell) => cell.selected)).toBe(false); |
| 612 | }); | 614 | }); |
| 613 | | 615 | |
| | 616 | it("scrolls a selection drag held at the terminal edge, even when the window ends there", async () => { |
| | 617 | const harness = createHarness(); |
| | 618 | const surface = await harness.create(); |
| | 619 | surface.write(Array.from({ length: 40 }, (_, index) => `line ${index}`).join("\r\n")); |
| | 620 | harness.flushFrame(); |
| | 621 | const latest = harness.renderedSnapshot.rowData[0]?.text; |
| | 622 | |
| | 623 | harness.pointer("pointerdown", 5, 1, {}, 0, 50); |
| | 624 | harness.pointer("pointermove", 5, 1, {}, 0, 1); |
| | 625 | vi.advanceTimersByTime(400); |
| | 626 | harness.flushFrame(); |
| | 627 | expect(surface.isAtBottom()).toBe(false); |
| | 628 | |
| | 629 | harness.pointer("pointermove", 5, 1, {}, 0, 103); |
| | 630 | vi.advanceTimersByTime(2_000); |
| | 631 | harness.pointer("pointerup", 5, 0, {}, 0, 103); |
| | 632 | harness.flushFrame(); |
| | 633 | expect(surface.isAtBottom()).toBe(true); |
| | 634 | expect(harness.renderedSnapshot.rowData[0]?.text).toBe(latest); |
| | 635 | expect(surface.getSelection()).not.toBe(""); |
| | 636 | expect(surface.getSelectionPosition()?.end.y).toBe(39); |
| | 637 | }); |
| | 638 | |
| 614 | it("pastes the terminal selection, and only that, on a Linux middle click", async () => { | 639 | it("pastes the terminal selection, and only that, on a Linux middle click", async () => { |
| 615 | const harness = createHarness(); | 640 | const harness = createHarness(); |
| 616 | const readText = vi.fn(async () => "clipboard text"); | 641 | const readText = vi.fn(async () => "clipboard text"); |