261016.4 · cf5820dfd8c68e5d305d88cb3b45c9e69ab58764
fix(windows): size the screen from the console window, not its buffer
reading declarations
@@ -93,6 +93,12 @@ type consoleInfo struct { maxsz coord } +// windowSize returns the size of the visible window. Before the alternate+// screen is entered, the buffer includes scrollback and is taller.+func (ci *consoleInfo) windowSize() (cols, rows uint16) {+ return uint16(ci.win.right - ci.win.left + 1), uint16(ci.win.bottom - ci.win.top + 1)+}+ type inputRecord struct { typ uint16 _ uint16@@ -249,9 +255,14 @@ func (w *winTty) getConsoleInput() error { } case resizeEvent:+ // The event carries the buffer size, which includes scrollback+ // outside the alternate screen, so read the window instead.+ var ci consoleInfo+ rv, _, _ := procGetConsoleScreenBufferInfo.Call(uintptr(w.out), uintptr(unsafe.Pointer(&ci))) w.Lock()- w.cols = binary.LittleEndian.Uint16(ir.data[0:])- w.rows = binary.LittleEndian.Uint16(ir.data[2:])+ if rv != 0 {+ w.cols, w.rows = ci.windowSize()+ } if w.resizeQ != nil { select { case w.resizeQ <- true:@@ -345,8 +356,7 @@ func NewDevTty() (Tty, error) { _, _, _ = procGetConsoleScreenBufferInfo.Call(uintptr(w.out), uintptr(unsafe.Pointer(&w.oscreen))) _, _, _ = procGetConsoleMode.Call(uintptr(w.out), uintptr(unsafe.Pointer(&w.oomode))) _, _, _ = procGetConsoleMode.Call(uintptr(w.in), uintptr(unsafe.Pointer(&w.oimode)))- w.rows = uint16(w.oscreen.size.y)- w.cols = uint16(w.oscreen.size.x)+ w.cols, w.rows = w.oscreen.windowSize() return w, nil }@@ -368,8 +378,7 @@ func NewStdIoTty() (Tty, error) { if r, _, err := procGetConsoleMode.Call(uintptr(w.in), uintptr(unsafe.Pointer(&w.oimode))); r == 0 || err != nil { return nil, errors.New("input is not a terminal") }- w.rows = uint16(w.oscreen.size.y)- w.cols = uint16(w.oscreen.size.x)+ w.cols, w.rows = w.oscreen.windowSize() return w, nil }
@@ -85,3 +85,14 @@ func TestEncodeWinKeyRecordFallbackIgnoresRelease(t *testing.T) { t.Fatalf("encodeWinKeyRecord() = %q, want %q", got, "AAA") } }++func TestConsoleInfoWindowSize(t *testing.T) {+ // A scrolled window into a buffer with scrollback, as conhost reports it.+ ci := consoleInfo{+ size: coord{x: 92, y: 9001},+ win: rect{left: 0, top: 38, right: 91, bottom: 59},+ }+ if cols, rows := ci.windowSize(); cols != 92 || rows != 22 {+ t.Fatalf("windowSize() = %dx%d, want 92x22", cols, rows)+ }+}