Racket 8.17 with Windows Console Mouse Support

Written by Dominik Pantůček on 2025-06-05

racket

Today 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:

Example of tui/term usage on Windows

For each event type a specific struct is defined:

  • tkeymsg with:
    • key code and
    • mods modifiers list (like alt, shift or ctrl)
  • tmousemsg with:
    • kind wheter it is move, button-down, button-up, wheel-up or wheel-down
    • pos with coordinates within the terminal window
    • left which is #t if left button was down during this event
    • right the same for the right button
    • middle - you can probably guess this one
    • button - which button was pressed or released if applicable, can (unsurprisingly) be any of left, right, or middle
  • 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!