terminal/src/interactivity/win32/WindowIme.cpp
Yoshiko 3f1befb06e
Fix Touch Keyboard invocation issue (#11389)
This fixes an issue that Touch Keyboard is not invoked when user taps on the PowerShell. 

Before this change, it was returning small rectangle on the right of the cursor. Touch Keyboard should be invoked by tapping anywhere inside the console.

## PR Checklist
* [ ] Closes #xxx
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [ ] Tests added/passed
* [ ] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
* [ ] Schema updated.
* [x] 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. Issue number where discussion took place: #xxx

## Detailed Description of the Pull Request / Additional comments
ITfContextOwner::GetScreenExt is used to define rectangle that can invoke Touch Keyboard. 
https://docs.microsoft.com/en-us/windows/win32/api/msctf/nf-msctf-itfcontextowner-getscreenext

## Validation Steps Performed
* [x] Touch keyboard was invoked by tapping inside the Console while Hardware Keyboard was not attached.
* [x] Selecting text worked as expected without invoking touch keyboard.
* [x] Long tapping the console invoked Touch Keyboard. I would like to confirm if this is the expected behavior.
2021-10-04 14:29:56 +00:00

69 lines
2.8 KiB
C++

// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#include "precomp.h"
#include "../inc/ServiceLocator.hpp"
#include "window.hpp"
#pragma hdrstop
// Routine Description:
// - This method gives a rectangle to where the command edit line text is currently rendered
// such that the IME suggestion window can pop up in a suitable location adjacent to the given rectangle.
// Arguments:
// - <none>
// Return Value:
// - Rectangle specifying current command line edit area.
RECT GetImeSuggestionWindowPos()
{
using Microsoft::Console::Interactivity::ServiceLocator;
const CONSOLE_INFORMATION& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
const auto& screenBuffer = gci.GetActiveOutputBuffer();
const COORD coordFont = screenBuffer.GetCurrentFont().GetSize();
COORD coordCursor = screenBuffer.GetTextBuffer().GetCursor().GetPosition();
// Adjust the cursor position to be relative to the viewport.
// This means that if the cursor is at row 30 in the buffer but the viewport is showing rows 20-40 right now on screen
// that the "relative" position is that it is on the 11th line from the top (or 10th by index).
// Correct by subtracting the top/left corner from the cursor's position.
SMALL_RECT const srViewport = screenBuffer.GetViewport().ToInclusive();
coordCursor.X -= srViewport.Left;
coordCursor.Y -= srViewport.Top;
// Map the point to be just under the current cursor position. Convert from coordinate to pixels using font.
POINT ptSuggestion;
ptSuggestion.x = (coordCursor.X + 1) * coordFont.X;
ptSuggestion.y = (coordCursor.Y) * coordFont.Y;
// Adjust client point to screen point via HWND.
ClientToScreen(ServiceLocator::LocateConsoleWindow()->GetWindowHandle(), &ptSuggestion);
// Move into suggestion rectangle.
RECT rcSuggestion = { 0 };
rcSuggestion.top = rcSuggestion.bottom = ptSuggestion.y;
rcSuggestion.left = rcSuggestion.right = ptSuggestion.x;
// Add 1 line height and a few characters of width to represent the area where we're writing text.
// This could be more exact by looking up the CONVAREA but it works well enough this way.
// If there is a future issue with the pop-up window, tweak these metrics.
rcSuggestion.bottom += coordFont.Y;
rcSuggestion.right += (coordFont.X * 10);
return rcSuggestion;
}
// Routine Description:
// - This method gives a rectangle to where text box is currently rendered
// such that the touch keyboard can pop up when the rectangle is tapped.
// Arguments:
// - <none>
// Return Value:
// - Rectangle specifying current text box area.
RECT GetTextBoxArea()
{
return Microsoft::Console::Interactivity::ServiceLocator::LocateConsoleWindow()->GetWindowRect();
}