Issues with cursor invalidation in GDI #21595

Closed
opened 2026-01-31 07:49:04 +00:00 by claunia · 3 comments
Owner

Originally created by @j4james on GitHub (Apr 28, 2024).

Originally assigned to: @lhecker on GitHub.

Windows Terminal version

Commit 378b6594bd

Windows build number

10.0.19045.4291

Other Software

No response

Steps to reproduce

  1. Make sure the conhost render engine is set to GDI (i.e. the UseDx registry entry is 0).
  2. Open a WSL shell in a recent build of OpenConsole (commit 20b0bed46d or later)
  3. Execute the following statements:
    printf "\e[2 q"; sleep 2; printf "\e[A"; sleep 2; printf "\e[B"
    

Expected Behavior

The above script is setting the cursor to a steady block so it's easy to see, sleeping for 2 seconds, moving up a line and sleeping for another 2 seconds, then moving the cursor back down again. You should be able to see the cursor the entire time.

Actual Behavior

Initially the cursor is visible, but as soon as we move up a line it becomes invisible for 2 seconds.

I believe this is a regression from PR #15500. Originally we would call InvalidateCursor (via TriggerRedrawCursor) whenever the cursor was moved, both to invalidate the old position and the new position. But since PR #15500, TriggerRedrawCursor has been nuked, and InvalidateCursor is now called at the start of every frame (regardless of whether the cursor is moved or not), and it only invalidates the old cursor position. So when the cursor moves, it's erased from the old position, but not redrawn in the new position.

This typically only affects vertical movement (other than some edge cases), because at some point I think we stopped caring about the horizontal extent of the invalidated region and just refresh the full width of the screen regardless. This also doesn't seem to affect the DX and Atlas engines, but I have no idea why.

Originally created by @j4james on GitHub (Apr 28, 2024). Originally assigned to: @lhecker on GitHub. ### Windows Terminal version Commit 378b6594bd94cf3b27f4e309a11efe25d83de0d9 ### Windows build number 10.0.19045.4291 ### Other Software _No response_ ### Steps to reproduce 1. Make sure the conhost render engine is set to GDI (i.e. the `UseDx` registry entry is 0). 2. Open a WSL shell in a recent build of OpenConsole (commit 20b0bed46df71c596b4fb68edfb6bb4b4ebf1c89 or later) 3. Execute the following statements: ``` printf "\e[2 q"; sleep 2; printf "\e[A"; sleep 2; printf "\e[B" ``` ### Expected Behavior The above script is setting the cursor to a steady block so it's easy to see, sleeping for 2 seconds, moving up a line and sleeping for another 2 seconds, then moving the cursor back down again. You should be able to see the cursor the entire time. ### Actual Behavior Initially the cursor is visible, but as soon as we move up a line it becomes invisible for 2 seconds. I believe this is a regression from PR #15500. Originally we would call `InvalidateCursor` (via `TriggerRedrawCursor`) whenever the cursor was moved, both to invalidate the old position and the new position. But since PR #15500, `TriggerRedrawCursor` has been nuked, and `InvalidateCursor` is now called at the start of every frame (regardless of whether the cursor is moved or not), and it only invalidates the old cursor position. So when the cursor moves, it's erased from the old position, but not redrawn in the new position. This typically only affects vertical movement (other than some edge cases), because at some point I think we stopped caring about the horizontal extent of the invalidated region and just refresh the full width of the screen regardless. This also doesn't seem to affect the DX and Atlas engines, but I have no idea why.
Author
Owner

@github-actions[bot] commented on GitHub (Apr 28, 2024):

Hi I'm an AI powered bot that finds similar issues based off the issue title.

Please view the issues below to see if they solve your problem, and if the issue describes your problem please consider closing this one and thumbs upping the other issue to help us prioritize it. Thank you!

Open similar issues:

Closed similar issues:

Note: You can give me feedback by thumbs upping or thumbs downing this comment.

@github-actions[bot] commented on GitHub (Apr 28, 2024): Hi I'm an AI powered bot that finds similar issues based off the issue title. Please view the issues below to see if they solve your problem, and if the issue describes your problem please consider closing this one and thumbs upping the other issue to help us prioritize it. Thank you! ### Open similar issues: - [Flickering in conhost when scrolling top part of screen (#11274)](https://github.com/microsoft/terminal/issues/11274), similarity score: 0.76 ### Closed similar issues: - [More cursor droppings (#8213)](https://github.com/microsoft/terminal/issues/8213), similarity score: 0.80 - [Cursor droppings are back in conhost (#12739)](https://github.com/microsoft/terminal/issues/12739), similarity score: 0.77 - [Weird scrolling regression in the GDI renderer (#13270)](https://github.com/microsoft/terminal/issues/13270), similarity score: 0.76 > Note: You can give me feedback by thumbs upping or thumbs downing this comment.
Author
Owner

@j4james commented on GitHub (Apr 28, 2024):

I love you github-actions bot, and I hope you'll spare my life when the robot revolution comes, but I feel a little bit hurt when you suggest a bunch of my own issues back to me, like idiot human can't remember that he's already raised this issue before. Although to be fair, that's not an unreasonable assumption.

@j4james commented on GitHub (Apr 28, 2024): I love you github-actions bot, and I hope you'll spare my life when the robot revolution comes, but I feel a little bit hurt when you suggest a bunch of my own issues back to me, like idiot human can't remember that he's already raised this issue before. Although to be fair, that's not an unreasonable assumption.
Author
Owner

@j4james commented on GitHub (Apr 28, 2024):

As to how we fix this issue, I can get it to work again by replicating most of the following code a couple of lines down:
378b6594bd/src/renderer/base/renderer.cpp (L124-L160)

That is, after we've reinitialized _currentCursorOptions with the new position, we need to invalidate that new position as well (I'm not sure about the _compositionCache, so I just ignored that bit). I don't know if this is a good solution, though.

@j4james commented on GitHub (Apr 28, 2024): As to how we fix this issue, I can get it to work again by replicating most of the following code a couple of lines down: https://github.com/microsoft/terminal/blob/378b6594bd94cf3b27f4e309a11efe25d83de0d9/src/renderer/base/renderer.cpp#L124-L160 That is, after we've reinitialized `_currentCursorOptions` with the new position, we need to invalidate that new position as well (I'm not sure about the `_compositionCache`, so I just ignored that bit). I don't know if this is a good solution, though.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/terminal#21595