Make sure cursor visibility is restored after using an IME (#6207)

## Summary of the Pull Request

When using an _Input Method Editor_ in conhost for East Asian languages, the text cursor is temporarily hidden while the characters are being composed. When the composition is complete, the cursor visibility is meant to be restored, but that doesn't always happen if the IME composition is cancelled. This PR makes sure the cursor visibility is always restored, regardless of how the IME is closed.

## PR Checklist
* [x] Closes #810
* [x] CLA signed.
* [ ] Tests added/passed
* [ ] Requires documentation to be updated
* [ ] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan.

## Detailed Description of the Pull Request / Additional comments

The original implementation hid the cursor whenever `ConsoleImeInfo::WriteCompMessage` was called (which could be multiple times in the course of a composition), and then only restored the visibility when `ConsoleImeInfo::WriteResultMessage` was called. If a composition is cancelled, though, `WriteResultMessage` would never be called, so the cursor visibility wouldn't be restored.

I've now made the `SaveCursorVisibility` and `RestoreCursorVisibility` methods public, so they can instead be called from the `ImeStartComposition` and `ImeEndComposition` functions. This makes sure `RestoreCursorVisibility` is always called, regardless of how the composition ended, and `SaveCursorVisibility` is only called once at the start of the composition (which isn't essential, but seems cleaner to me).

## Validation Steps Performed

I've manually tested opening and closing the IME, both while submitting characters and while cancelling a composition, and in all cases the cursor visibility was correctly restored.
This commit is contained in:
James Holderness 2020-05-27 17:31:09 +01:00 committed by GitHub
parent 2af722b43d
commit 8752054f5b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 11 additions and 9 deletions

View file

@ -60,9 +60,6 @@ void ConsoleImeInfo::WriteCompMessage(const std::wstring_view text,
const std::basic_string_view<BYTE> attributes,
const std::basic_string_view<WORD> colorArray)
{
// Backup the cursor visibility state and turn it off for drawing.
_SaveCursorVisibility();
ClearAllAreas();
// Save copies of the composition message in case we need to redraw it as things scroll/resize
@ -80,8 +77,6 @@ void ConsoleImeInfo::WriteCompMessage(const std::wstring_view text,
// - text - The actual text of what the user would like to insert (UTF-16)
void ConsoleImeInfo::WriteResultMessage(const std::wstring_view text)
{
_RestoreCursorVisibility();
ClearAllAreas();
_InsertConvertedString(text);
@ -471,7 +466,7 @@ void ConsoleImeInfo::_InsertConvertedString(const std::wstring_view text)
// Routine Description:
// - Backs up the global cursor visibility state if it is shown and disables
// it while we work on the conversion areas.
void ConsoleImeInfo::_SaveCursorVisibility()
void ConsoleImeInfo::SaveCursorVisibility()
{
CONSOLE_INFORMATION& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
Cursor& cursor = gci.GetActiveOutputBuffer().GetTextBuffer().GetCursor();
@ -487,7 +482,7 @@ void ConsoleImeInfo::_SaveCursorVisibility()
// Routine Description:
// - Restores the global cursor visibility state if it was on when it was backed up.
void ConsoleImeInfo::_RestoreCursorVisibility()
void ConsoleImeInfo::RestoreCursorVisibility()
{
if (_isSavedCursorVisible)
{

View file

@ -55,6 +55,9 @@ public:
void RedrawCompMessage();
void SaveCursorVisibility();
void RestoreCursorVisibility();
private:
[[nodiscard]] HRESULT _AddConversionArea();
@ -80,8 +83,6 @@ private:
const Microsoft::Console::Types::Viewport view,
SCREEN_INFORMATION& screenInfo);
void _SaveCursorVisibility();
void _RestoreCursorVisibility();
bool _isSavedCursorVisible;
std::wstring _text;

View file

@ -104,6 +104,9 @@ void WriteConvRegionToScreen(const SCREEN_INFORMATION& ScreenInfo,
gci.LockConsole();
auto unlock = wil::scope_exit([&] { gci.UnlockConsole(); });
ConsoleImeInfo* const pIme = &gci.ConsoleIme;
pIme->SaveCursorVisibility();
gci.pInputBuffer->fInComposition = true;
return S_OK;
}
@ -114,6 +117,9 @@ void WriteConvRegionToScreen(const SCREEN_INFORMATION& ScreenInfo,
gci.LockConsole();
auto unlock = wil::scope_exit([&] { gci.UnlockConsole(); });
ConsoleImeInfo* const pIme = &gci.ConsoleIme;
pIme->RestoreCursorVisibility();
gci.pInputBuffer->fInComposition = false;
return S_OK;
}