Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cursor shape gets reverted to legacy style after hiding the cursor and then making it visible again in console window #4124

Closed
daxian-dbw opened this issue Jan 6, 2020 · 3 comments · Fixed by #5251
Labels
Area-Settings Issues related to settings and customizability, for console or terminal Issue-Bug It either shouldn't be doing this or needs an investigation. Needs-Tag-Fix Doesn't match tag requirements Product-Conhost For issues in the Console codebase Resolution-Fix-Committed Fix is checked in, but it might be 3-4 weeks until a release.
Milestone

Comments

@daxian-dbw
Copy link
Member

daxian-dbw commented Jan 6, 2020

Environment

Windows build number: Microsoft Windows [Version 10.0.18363.535]
Windows Terminal version (if applicable): NA

Any other software? No

Steps to reproduce

After setting the cursor shape in Properties->Terminal, hiding and then showing the cursor by setting Console.CursorVisible to false and then true causes the cursor shape to be restored to the legacy style in console host.

The following simple C# program can show the problem:

using System;
using System.Text;

namespace cursorShape
{
    class Program
    {
        static void Main(string[] args)
        {
            const string prompt = "PROMP> ";
            StringBuilder sb = new StringBuilder();
            int top = Console.CursorTop;

            Console.OutputEncoding = Encoding.UTF8;
            Console.Write(prompt);

            while (true)
            {
                var key = Console.ReadKey();
                if (key.Key == ConsoleKey.Q)
                {
                    break;
                }

                sb.Append(key.KeyChar);

                Console.CursorVisible = false;   // Hide the cursor before rewriting
                Console.SetCursorPosition(0, top);
                Console.Write($"{prompt}{sb}");
                Console.SetCursorPosition(Console.CursorLeft, top);
                Console.CursorVisible = true;    // Show the cursor afterwards
            }
        }
    }
}

Expected behavior

Setting Console.CursorVisible should not revert the cursor shape.

Actual behavior

The cursor shape gets reverted from Solid Box to the legacy style (Underline):
linux

Related issues

#409 and #1145 and PowerShell/PSReadLine#903
Those 2 issues were reported in the PowerShell+PSReadLine context. PSReadLine depends on Console.CursorVisible to hide and show the cursor during rendering, so the cursor shape gets reverted.

@ghost ghost added Needs-Triage It's a new issue that the core contributor team needs to triage at the next triage meeting Needs-Tag-Fix Doesn't match tag requirements labels Jan 6, 2020
@DHowett-MSFT DHowett-MSFT added Area-Settings Issues related to settings and customizability, for console or terminal Help Wanted We encourage anyone to jump in on these. Issue-Bug It either shouldn't be doing this or needs an investigation. Product-Conhost For issues in the Console codebase and removed Needs-Triage It's a new issue that the core contributor team needs to triage at the next triage meeting labels Jan 6, 2020
@ghost ghost removed the Needs-Tag-Fix Doesn't match tag requirements label Jan 6, 2020
@DHowett-MSFT DHowett-MSFT added this to the 21H1 milestone Jan 6, 2020
@DHowett-MSFT
Copy link
Contributor

Well, heck.

@j4james
Copy link
Collaborator

j4james commented Jan 7, 2020

As explained in #409, the problem is that calling the SetConsoleCursorInfo sets the cursor size, and setting the cursor size forces the cursor shape back to the legacy style (because that's the only shape for which the size is applicable AFAIK).

It's easy enough to "fix". We could just delete this line from the SetCursorInformation method:

cursor.SetType(CursorType::Legacy);

But that's a change in behavior for a public API, and it's possible some applications could actually be relying on that behavior (although I would think that unlikely).

Ideally the Console.CursorVisible property should be using an API that just sets the visibility and nothing else, but but I don't think there is such a thing. The best you could do is use a VT sequence, but that's obviously not going to work with older versions of Windows.

@ghost ghost added the In-PR This issue has a related PR label Apr 6, 2020
@ghost ghost added Needs-Tag-Fix Doesn't match tag requirements and removed Help Wanted We encourage anyone to jump in on these. labels Apr 6, 2020
DHowett-MSFT pushed a commit that referenced this issue Apr 6, 2020
A side effect of the `SetConsoleCursorInfo` API is that it resets the
cursor type to _Legacy_. This makes it impossible to change the cursor
visibility via the console APIs without also resetting the user's
preferred cursor type. This PR attempts to fix that limitation, by only
resetting the cursor type if the size has also been changed.

## PR Checklist
* [x] Closes #4124
* [x] CLA signed
* [ ] Tests added/passed
* [ ] Requires documentation to be updated

## Detailed Description of the Pull Request / Additional comments

I suspect the reason for the original behaviour was because the
`SetConsoleCursorInfo` API sets both the visibility and the size, and if
you're setting the size, it's assumed you'd want the _Legacy_ cursor
type, because that's the only style for which the size is applicable.

So my solution was to only reset the cursor type if the requested cursor
size was actually different from the current size. That should be
reasonably backwards compatible with most size-changing code, but also
allow for changing the visibility without resetting the cursor type.

## Validation Steps Performed

I've tested the example code from issue #4124, and confirmed that it now
works correctly without resetting the cursor type.

I've also tested the console's _mark mode_, which temporarily changes
the cursor size while selecting. I've confirmed that the size still
changes, and that the original cursor type is restored afterwards.
@ghost ghost added Resolution-Fix-Committed Fix is checked in, but it might be 3-4 weeks until a release. and removed In-PR This issue has a related PR labels Apr 6, 2020
@ghost
Copy link

ghost commented Apr 22, 2020

🎉This issue was addressed in #5251, which has now been successfully released as Windows Terminal Preview v0.11.1121.0.:tada:

Handy links:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area-Settings Issues related to settings and customizability, for console or terminal Issue-Bug It either shouldn't be doing this or needs an investigation. Needs-Tag-Fix Doesn't match tag requirements Product-Conhost For issues in the Console codebase Resolution-Fix-Committed Fix is checked in, but it might be 3-4 weeks until a release.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants