Racket 8.17 with Windows Console Mouse Support
Written by Dominik Pantůček on 2025-06-05
racketToday we are bringing some unifying good news for all Racket and Chez Scheme folks having to run their applications on that alternative operating system called Windows. With Racket 8.17 released, it is possible to fully suport even mouse input in terminal applications on that strange platform!
As a part of our effort to bring back the good old days of awesome TUIs of the early 90's era which are still unmatched by today's bloated, resources-hungry applications, modern operating systems have different means of supporting keyboard and mouse input in terminal emulators. Originally there were no terminal emulators, just terminals. And these terminals reported special keys as special sequences of characters in the input stream sent to the computer.
The same can be said about mouse input when it became ubiquitous. There were many
competing standards, however only some survived the test of time. The one we chose to
implement is the one that is already supported on the major platforms like Linux and
Mac. It is the SGR_EXT_MODE
as can be seen in the most comprehensive
XTerm
Control Sequences documentation.
And after some work, the latest Racket 8.17 and (yet unreleased) Chez Scheme support
translating Windows console mouse events to these VT input sequences of SGR EXT
MODE
type. However there is no cross-platform way for making the terminal
emulator application send these events to the applications -- as it is very
Windows-specific. But first things first.
Before merging this functionality into Racket an upstream PR had to be merged with the commit implementing this translation. After this merge, Racket inherited this in the same commit brought to its main branch. Original PR could then be closed as for such low-level functionality has to go through the ChezScheme repository first.
And that is all, now we only need to enable mouse reporting. But there is another piece to this puzzle - a new tui-term package which performs all the platform-specific setup for us. The following program works on all supported platforms:
#lang racket
(require tui/term)
(with-term (make-tty-term)
(term-enable-mouse)
(let loop ()
(define ch (read))
(writeln ch)
(when (not (and (tkeymsg? ch)
(eq? (tkeymsg-key ch) #\q)))
(loop))))
Yes, that really is all and now we start getting all the interesting events:
For each event type a specific struct is defined:
- tkeymsg with:
key
code andmods
modifiers list (likealt
,shift
orctrl
)
- tmousemsg with:
kind
wheter it ismove
,button-down
,button-up
,wheel-up
orwheel-down
pos
with coordinates within the terminal windowleft
which is#t
if left button was down during this eventright
the same for the right buttonmiddle
- you can probably guess this onebutton
- which button was pressed or released if applicable, can (unsurprisingly) be any ofleft
,right
, ormiddle
- tsizemsg with:
cols
- the number of columns (terminal width)rows
- the number of rows (terminal height)
Yes, this means a unified terminal input across all three major platforms. Isn't that great?
Hope you will also write more terminal applications with mouse support using these new features and in the meantime - see ya next time!