From 2fcae54b6205761b0e0fdc6be2d15370e50a0862 Mon Sep 17 00:00:00 2001 From: Sören Tempel Date: Sun, 23 May 2021 04:34:01 +0200 Subject: Implement support for retrieving terminal windows size Even if TUIs are not supported, this is used by some applications (most notably) ls(1) for outputting text in multiple columns. --- saneterm/terminal.py | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/saneterm/terminal.py b/saneterm/terminal.py index da41590..96665f7 100644 --- a/saneterm/terminal.py +++ b/saneterm/terminal.py @@ -3,6 +3,8 @@ import pty import os import codecs import termios +import fcntl +import struct import keys from termview import * @@ -13,6 +15,7 @@ gi.require_version("Gtk", "3.0") from gi.repository import Gtk from gi.repository import Gdk from gi.repository import GLib +from gi.repository import Pango NAME = "saneterm" TERM = "dumb" @@ -67,6 +70,7 @@ class Terminal(Gtk.Window): self.termview.connect("new-user-input", self.user_input) self.termview.connect("termios-ctrlkey", self.termios_ctrl) + self.connect("size-allocate", self.update_size) bindings = keys.Bindings(self.termview) for key, idx in keys.CTRL.items(): @@ -78,6 +82,29 @@ class Terminal(Gtk.Window): scroll.add(self.termview) self.add(scroll) + def update_size(self, widget, rect): + # PTY must already be initialized + if self.pty.master == -1: + return + + # Widget width/height in pixels, is later converted + # to rows/columns by dividing these values by the + # font width/height as determined by the PangoLayout. + width, height = widget.get_size() + + ctx = self.termview.get_pango_context() + layout = Pango.Layout(ctx) + layout.set_markup(" ") # assumes monospace + fw, fh = layout.get_pixel_size() + + rows = int(height / fh) + cols = int(width / fw) + + # TODO: use tcsetwinsize() instead of the ioctl. + # See: https://github.com/python/cpython/pull/23686 + ws = struct.pack('HHHH', rows, cols, width, height) # struct winsize + fcntl.ioctl(self.pty.master, termios.TIOCSWINSZ, ws) + def handle_pty(self, source, tag, master): cond = source.query_unix_fd(tag) if cond & GLib.IOCondition.HUP: -- cgit 1.4.1