terminal: [1.15+] Flushing FTCS sequences causes flickering in nushell 0.66+

Windows Terminal version

1.15.2003.0

Windows build number

Microsoft Windows [Version 10.0.22000.795]

Other Software

Nushell v0.66+

Steps to reproduce

Hi, I work on a cross-platform shell called Nushell and we’ve noticed a rendering regression in Windows Terminal Preview v1.15.

Nushell’s prompt now flickers on every keystroke. The following recording illustrates the problem (but it’s a little worse in real life, the recording didn’t capture every flicker):

https://user-images.githubusercontent.com/26268125/183734387-10477dd6-220c-4f7d-8b21-f7737736d0ee.mp4

To reproduce this, run any version of Nushell from v0.66 or later and start typing. Nushell can be downloaded from our GitHub releases or installed with Scoop (scoop install nushell) or winget (winget install nushell). nu.exe is the executable for Nushell.

Details / Investigation

The flickering does not occur in Windows Terminal v1.14.1963.0.

We bisected Nushell’s code and found that the flickering did not occur prior to this PR which added some scroll mark ANSI escape codes for VS Code. WT v1.15 Preview added experimental support for scroll marks; maybe this is a bug in the experimental scroll mark code?

The flickering occurs even with the scroll mark settings (experimental.autoMarkPrompts and experimental.showMarksOnScrollbar) set to false.

If there’s anything else we can do to help with investigation or reproduction, just let me know!

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Reactions: 95
  • Comments: 29 (11 by maintainers)

Commits related to this issue

Most upvoted comments

@popcar2 When you disable shell_integration you lose the ability to have automatic OSC 133;A/B/C/D terminal markers (FTCS sequences) and automatic OSC 2 & OSC 7 term/window titles. It may also interfere with OSC 8 clickable links in nushell.

ba777dfbf doesn’t seem to flash anymore. I’ll have to make sure I didn’t blow anything else up.

I’m a tad worried about capturing the screenbuffer pointer in that lambda like that.

(huge apologies to folks following this thread, these notes are an unintelligible stream of consciousness)

Refer to #13163

My outline of events in https://github.com/microsoft/terminal/issues/13710#issuecomment-1209754247 might be wrong[1]. Look at the video closer - is that it? The left prompt is always visible, even as command and right prompt are flickering. Hmm.

This diff would seem to suggest that the prompt is written as one long string, “FTCS A + prompt + FTCS B”, presumably followed by the command, followed by the right prompt. In 1.15, ~only FTCS A would have been implemented~. I don’t think that matters

~In 1.15 we return false out of the adapter on the FTCS B which means “I didn’t understand that, just write that to the pipe NOW”.~ this is also wrong.

ConPty always flushes all FTCS’s in 1.15. On “FTCS A + prompt + FTCS B”, we do

[
  "FTCS A" -> Flush(),
  prompt + "FTCS B" -> Flush(),
  input command + right prompt -> (regularly scheduled) Paint()
]

as three frames. That it shouldn’t. That probably should all be one frame. Can we just FlushNoWrite() from the adapter? Would that be insane? We’d have to be careful to write to the buffer, not write the frame to the pipe, write the sequence, but then also leave the engine in a state where the regularly scheduled paint frame tick would still cause the actual Present to the pipe, but with a quick path for "we had nothing to do but we did have stuff we already did.

I’ll keep editing with notes as I go

[1] it might not be, I’ve re-edited this comment like 10 times as writing it


This is what I get out the debug tap. Now, where are the frames…

  • Frame 1:
␍
␛[K
␛[?25l
␛[57C
␛]133;A␛\

CR, cursor off, Cursor Forward 17 (?!), mark

  • Frame 2:
␛[32m
␛[1m
␍
C:\Users\migrie
␛]133;B␛\
␛[2␣q
␛[m
␛[38;5;14m
␛[1m
〉
␛[36m
␛[22m
z
␛[38;5;5m
␛[1m
␛[17C
01/11/2023␣09:43:35␣AM
␛[24;19H
␛[?25h
␛[m

This is what actually gets written to conhost

[?25l




]133;A\

C:\Users\migrie
]133;B\


〉


7

01/11/2023 10:40:54 AM
8


zmh

7
8
[2 q
[?25h

[2 q looks out of place…


Okay playing with this more locally, and staring at it, I do see the prompt section flickering as I’d expect.

So, I guess the trick now is that even if we do not immediately flush the frame, a regular frame might come in in the middle of the string. Hmm.

Bad idea

  • if we have buffered output on StartPaint, but there’s nothing to do, don’t flush.
  • At the end of a VT string, in pty mode, poke the render engine to let it know it’s safe to flush.

The console should be locked for that whole write, start to finish. ApiRoutines::WriteConsoleWImpl takes the lock and holds it till it’s all processed. So that must mean we’re getting a Flush we’re not expecting, during the handling of the string. After the 133;A, before the B. Hmm.

I would also really appreciate a solution for this. Makes using Windows Terminal a pain right now because of all the flickering.

A fix was mentioned in another thread and I can confirm it works:

  • Type config nu
  • In the config file, find shell_integration and set it to false

It should stop flickering now. I don’t know what the downside is for disabling shell integration, everything seems to work totally fine over a month in.

Alas, no. I haven’t noodled on this too much since getting back from leave, and I’m only just getting back into the swing of things after the holidays.

I’ve got this marked up to take a look at ~this month, but I seriously doubt I’ll have a good solution that fast.

IIRC we briefly discussed some ideas, that might work okay in this specific scenario, but wouldn’t work more broadly for the other sequences that are leveraging the same flushing that we do here (looking at you alt buffer sequences). I can’t remember the details though 😕

Thanks! That was super easy to reproduce. I should’ve realized that given that this issue was also about FTCS. I’ve opened #16769 so we don’t ping the ~dozen people on this issue unnecessarily. I’ll try to fix it soon (if possible).

@wez wezterm nightly, downloaded from here exhibits a similar issue as before but slightly different. wezterm

if one of you could check this behavior with the current nightly build of wezterm, I’d appreciate it: I updated the bundled conpty pieces to match 0ee2c74cd432eda153f3f3e77588164cde95044f of this repo, so my understanding is that this should be fixed in wezterm now too.

Oh good, I’m glad! This was a tricky fix so I’m really glad it did work after all.

Looks like our friendly neighborhood bot is having a tough time this week and forgot to come around with release notes. This fix shipped in Terminal Preview 1.18 earlier this week.

(I’m supposed to be on vacation RN so apologies for the brevity in my notes)

Hmmmmmmmmm. I wonder if this isn’t playing nicely with the frame flushing. Like, when the prompt gets drawn, what’s happening is a

  • Move the cursor to the start of the prompt
  • erase the rest of the line
  • mark here as the start of the prompt (FLUSHES THE FRAME)
  • draw the prompt
  • mark here as the end of the prompt (flushes maybe? maybe not yet)
  • draw the right side of the status

The trick is that we’re flushing all buffered state to the Terminal when we see a prompt sequence. The problem is that at the time the mark is re-rendered, the prompt line is empty, causing the flickering.

No clever solutions off the top of the dome. I’ll noodle on the drive home.


Edit 2023/01/10: The above set of steps is wrong. Don’t use that as a guide for what’s happening.

any update?

This problem does not occur when nushell runs on alacritty 😉

an updated copy of Windows 11

I mean, FTCS support landed literally 3 months ago - I’m not sure it’s even made its way to any official Windows builds yet 😅

Uh oh, the terminal flickering is back!

I can reproduce it in Terminal Preview 1.20.10303.0 and Nu 0.90.1. I cannot reproduce it in Terminal 1.18.10301.0.

It seems to occur with or without AtlasEngine enabled.

@zadjii-msft Would you like me to open a new issue for this?

Nushell is still flickering when used within Windows Terminal (both MS store stable/preview + latest GitHub release).

FWIW, wezterm bundles and uses openconsole.exe and conpty.dll built from GitHub. I just updated it to the most recent tag this morning and the issue reproduces there too.

https://github.com/wez/wezterm/commit/0d85d05442a2ca38264a2cd3a21f57d565a4464f