about summary refs log tree commit diff
path: root/saneterm
diff options
context:
space:
mode:
authorSören Tempel <soeren+git@soeren-tempel.net>2021-05-23 04:34:01 +0200
committerSören Tempel <soeren+git@soeren-tempel.net>2021-05-23 04:34:01 +0200
commit2fcae54b6205761b0e0fdc6be2d15370e50a0862 (patch)
treea35def7ebff7a764d132aec32a92310f65a12af0 /saneterm
parente7b616561e5973bb0eb7987c3b18a6aadd9dfb41 (diff)
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.
Diffstat (limited to 'saneterm')
-rw-r--r--saneterm/terminal.py27
1 files changed, 27 insertions, 0 deletions
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: