diff --git a/src/cascadia/TerminalControl/TSFInputControl.cpp b/src/cascadia/TerminalControl/TSFInputControl.cpp new file mode 100644 index 00000000000..bd8ab2c5232 --- /dev/null +++ b/src/cascadia/TerminalControl/TSFInputControl.cpp @@ -0,0 +1,349 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +#include "pch.h" +#include "TSFInputControl.h" +#include "TSFInputControl.g.cpp" + +#include + +using namespace winrt::Windows::Foundation; +using namespace winrt::Windows::Graphics::Display; +using namespace winrt::Windows::UI::Core; +using namespace winrt::Windows::UI::Text; +using namespace winrt::Windows::UI::Text::Core; +using namespace winrt::Windows::UI::Xaml; + +namespace winrt::Microsoft::Terminal::TerminalControl::implementation +{ + TSFInputControl::TSFInputControl() : + _editContext{ nullptr } + { + _Create(); + } + + // Method Description: + // - Creates XAML controls for displaying user input and hooks up CoreTextEditContext handlers + // for handling text input from the Text Services Framework. + // Arguments: + // - + // Return Value: + // - + void TSFInputControl::_Create() + { + // TextBlock for user input form TSF + _textBlock = Controls::TextBlock(); + _textBlock.Visibility(Visibility::Collapsed); + _textBlock.IsTextSelectionEnabled(false); + _textBlock.TextDecorations(TextDecorations::Underline); + + // Canvas for controlling exact position of the TextBlock + _canvas = Windows::UI::Xaml::Controls::Canvas(); + _canvas.Visibility(Visibility::Collapsed); + + // add the Textblock to the Canvas + _canvas.Children().Append(_textBlock); + + // set the content of this control to be the Canvas + this->Content(_canvas); + + // Create a CoreTextEditingContext for since we are acting like a custom edit control + auto manager = Core::CoreTextServicesManager::GetForCurrentView(); + _editContext = manager.CreateEditContext(); + + // sets the Input Pane display policy to Manual for now so that it can manually show the + // software keyboard when the control gains focus and dismiss it when the control loses focus. + // TODO GitHub #3639: Should Input Pane display policy be Automatic + _editContext.InputPaneDisplayPolicy(Core::CoreTextInputPaneDisplayPolicy::Manual); + + // set the input scope to Text because this control is for any text. + _editContext.InputScope(Core::CoreTextInputScope::Text); + + _editContext.TextRequested({ this, &TSFInputControl::_textRequestedHandler }); + + _editContext.SelectionRequested({ this, &TSFInputControl::_selectionRequestedHandler }); + + _editContext.FocusRemoved({ this, &TSFInputControl::_focusRemovedHandler }); + + _editContext.TextUpdating({ this, &TSFInputControl::_textUpdatingHandler }); + + _editContext.SelectionUpdating({ this, &TSFInputControl::_selectionUpdatingHandler }); + + _editContext.FormatUpdating({ this, &TSFInputControl::_formatUpdatingHandler }); + + _editContext.LayoutRequested({ this, &TSFInputControl::_layoutRequestedHandler }); + + _editContext.CompositionStarted({ this, &TSFInputControl::_compositionStartedHandler }); + + _editContext.CompositionCompleted({ this, &TSFInputControl::_compositionCompletedHandler }); + } + + // Method Description: + // - NotifyFocusEnter handler for notifying CoreEditTextContext of focus enter + // when TerminalControl receives focus. + // Arguments: + // - + // Return Value: + // - + void TSFInputControl::NotifyFocusEnter() + { + if (_editContext != nullptr) + { + _editContext.NotifyFocusEnter(); + } + } + + // Method Description: + // - NotifyFocusEnter handler for notifying CoreEditTextContext of focus leaving. + // when TerminalControl no longer has focus. + // Arguments: + // - + // Return Value: + // - + void TSFInputControl::NotifyFocusLeave() + { + if (_editContext != nullptr) + { + // _editContext.NotifyFocusLeave(); TODO GitHub #3645: Enabling causes IME to no longer show up, need to determine if required + } + } + + // Method Description: + // - Handler for LayoutRequested event by CoreEditContext responsible + // for returning the current position the IME should be placed + // in screen coordinates on the screen. TSFInputControls internal + // XAML controls (TextBlock/Canvas) are also positioned and updated. + // NOTE: documentation says application should handle this event + // Arguments: + // - sender: CoreTextEditContext sending the request. + // - args: CoreTextLayoutRequestedEventArgs to be updated with position information. + // Return Value: + // - + void TSFInputControl::_layoutRequestedHandler(CoreTextEditContext sender, CoreTextLayoutRequestedEventArgs const& args) + { + auto request = args.Request(); + + // Get window in screen coordinates, this is the entire window including tabs + const auto windowBounds = CoreWindow::GetForCurrentThread().Bounds(); + + // Get the cursor position in text buffer position + auto cursorArgs = winrt::make_self(); + _CurrentCursorPositionHandlers(*this, *cursorArgs); + const COORD cursorPos = { gsl::narrow_cast(cursorArgs->CurrentPosition().X), gsl::narrow_cast(cursorArgs->CurrentPosition().Y) }; + + // Get Font Info as we use this is the pixel size for characters in the display + auto fontArgs = winrt::make_self(); + _CurrentFontInfoHandlers(*this, *fontArgs); + + const float fontWidth = fontArgs->FontSize().Width; + const float fontHeight = fontArgs->FontSize().Height; + + // Convert text buffer cursor position to client coordinate position within the window + COORD clientCursorPos; + COORD screenCursorPos; + THROW_IF_FAILED(ShortMult(cursorPos.X, gsl::narrow(fontWidth), &clientCursorPos.X)); + THROW_IF_FAILED(ShortMult(cursorPos.Y, gsl::narrow(fontHeight), &clientCursorPos.Y)); + + // Convert from client coordinate to screen coordinate by adding window position + THROW_IF_FAILED(ShortAdd(clientCursorPos.X, gsl::narrow_cast(windowBounds.X), &screenCursorPos.X)); + THROW_IF_FAILED(ShortAdd(clientCursorPos.Y, gsl::narrow_cast(windowBounds.Y), &screenCursorPos.Y)); + + // get any offset (margin + tabs, etc..) of the control within the window + const auto offsetPoint = this->TransformToVisual(nullptr).TransformPoint(winrt::Windows::Foundation::Point(0, 0)); + + // add the margin offsets if any + const auto currentMargin = this->Margin(); + THROW_IF_FAILED(ShortAdd(screenCursorPos.X, gsl::narrow_cast(offsetPoint.X), &screenCursorPos.X)); + THROW_IF_FAILED(ShortAdd(screenCursorPos.Y, gsl::narrow_cast(offsetPoint.Y), &screenCursorPos.Y)); + + // Get scale factor for view + const double scaleFactor = DisplayInformation::GetForCurrentView().RawPixelsPerViewPixel(); + + // Set the selection layout bounds + Rect selectionRect = Rect(screenCursorPos.X, screenCursorPos.Y, 0, fontHeight); + request.LayoutBounds().TextBounds(ScaleRect(selectionRect, scaleFactor)); + + // Set the control bounds of the whole control + Rect controlRect = Rect(screenCursorPos.X, screenCursorPos.Y, 0, fontHeight); + request.LayoutBounds().ControlBounds(ScaleRect(controlRect, scaleFactor)); + + // position textblock to cursor position + _canvas.SetLeft(_textBlock, clientCursorPos.X); + _canvas.SetTop(_textBlock, static_cast(clientCursorPos.Y)); + + // width is cursor to end of canvas + _textBlock.Width(200); // TODO GitHub #3640: Determine proper Width + _textBlock.Height(fontHeight); + + // calculate FontSize in pixels from DIPs + const double fontSizePx = (fontHeight * 72) / USER_DEFAULT_SCREEN_DPI; + _textBlock.FontSize(fontSizePx); + + _textBlock.FontFamily(Media::FontFamily(fontArgs->FontFace())); + } + + // Method Description: + // - Handler for CompositionStarted event by CoreEditContext responsible + // for making internal TSFInputControl controls visisble. + // Arguments: + // - sender: CoreTextEditContext sending the request. Not used in method. + // - args: CoreTextCompositionStartedEventArgs. Not used in method. + // Return Value: + // - + void TSFInputControl::_compositionStartedHandler(CoreTextEditContext sender, CoreTextCompositionStartedEventArgs const& /*args*/) + { + _canvas.Visibility(Visibility::Visible); + _textBlock.Visibility(Visibility::Visible); + } + + // Method Description: + // - Handler for CompositionCompleted event by CoreEditContext responsible + // for making internal TSFInputControl controls visisble. + // Arguments: + // - sender: CoreTextEditContext sending the request. Not used in method. + // - args: CoreTextCompositionCompletedEventArgs. Not used in method. + // Return Value: + // - + void TSFInputControl::_compositionCompletedHandler(CoreTextEditContext sender, CoreTextCompositionCompletedEventArgs const& /*args*/) + { + // only need to do work if the current buffer has text + if (!_inputBuffer.empty()) + { + const auto hstr = to_hstring(_inputBuffer.c_str()); + + // call event handler with data handled by parent + _compositionCompletedHandlers(hstr); + + // clear the buffer for next round + _inputBuffer.clear(); + _textBlock.Text(L""); + + // tell the input server that we've cleared the buffer + CoreTextRange emptyTextRange; + emptyTextRange.StartCaretPosition = 0; + emptyTextRange.EndCaretPosition = 0; + + // indicate text is now 0 + _editContext.NotifyTextChanged(emptyTextRange, 0, emptyTextRange); + _editContext.NotifySelectionChanged(emptyTextRange); + + // hide the controls until composition starts again + _canvas.Visibility(Visibility::Collapsed); + _textBlock.Visibility(Visibility::Collapsed); + } + } + + // Method Description: + // - Handler for FocusRemoved event by CoreEditContext responsible + // for removing focus for the TSFInputControl control accordingly + // when focus was forecibly removed from text input control. (TODO GitHub #3644) + // NOTE: Documentation says application should handle this event + // Arguments: + // - sender: CoreTextEditContext sending the request. Not used in method. + // - object: CoreTextCompositionStartedEventArgs. Not used in method. + // Return Value: + // - + void TSFInputControl::_focusRemovedHandler(CoreTextEditContext sender, winrt::Windows::Foundation::IInspectable const& /*object*/) + { + } + + // Method Description: + // - Handler for TextRequested event by CoreEditContext responsible + // for returning the range of text requested. + // NOTE: Documentation says application should handle this event + // Arguments: + // - sender: CoreTextEditContext sending the request. Not used in method. + // - args: CoreTextTextRequestedEventArgs to be updated with requested range text. + // Return Value: + // - + void TSFInputControl::_textRequestedHandler(CoreTextEditContext sender, CoreTextTextRequestedEventArgs const& args) + { + // the range the TSF wants to know about + const auto range = args.Request().Range(); + + try + { + const auto textRequested = _inputBuffer.substr(range.StartCaretPosition, static_cast(range.EndCaretPosition) - static_cast(range.StartCaretPosition)); + + args.Request().Text(winrt::to_hstring(textRequested.c_str())); + } + CATCH_LOG(); + } + + // Method Description: + // - Handler for SelectionRequested event by CoreEditContext responsible + // for returning the currently selected text. + // TSFInputControl currently doesn't allow selection, so nothing happens. + // NOTE: Documentation says application should handle this event + // Arguments: + // - sender: CoreTextEditContext sending the request. Not used in method. + // - args: CoreTextSelectionRequestedEventArgs for providing data for the SelectionRequested event. Not used in method. + // Return Value: + // - + void TSFInputControl::_selectionRequestedHandler(CoreTextEditContext sender, CoreTextSelectionRequestedEventArgs const& /*args*/) + { + } + + // Method Description: + // - Handler for SelectionUpdating event by CoreEditContext responsible + // for handling modifications to the range of text currently selected. + // TSFInputControl doesn't currently allow selection, so nothing happens. + // NOTE: Documentation says application should set its selection range accordingly + // Arguments: + // - sender: CoreTextEditContext sending the request. Not used in method. + // - args: CoreTextSelectionUpdatingEventArgs for providing data for the SelectionUpdating event. Not used in method. + // Return Value: + // - + void TSFInputControl::_selectionUpdatingHandler(CoreTextEditContext sender, CoreTextSelectionUpdatingEventArgs const& /*args*/) + { + } + + // Method Description: + // - Handler for TextUpdating event by CoreEditContext responsible + // for handling text updates. + // Arguments: + // - sender: CoreTextEditContext sending the request. Not used in method. + // - args: CoreTextTextUpdatingEventArgs contains new text to update buffer with. + // Return Value: + // - + void TSFInputControl::_textUpdatingHandler(CoreTextEditContext sender, CoreTextTextUpdatingEventArgs const& args) + { + const auto text = args.Text(); + const auto range = args.Range(); + + try + { + _inputBuffer = _inputBuffer.replace( + range.StartCaretPosition, + static_cast(range.EndCaretPosition) - static_cast(range.StartCaretPosition), + text.c_str()); + + _textBlock.Text(_inputBuffer); + + // Notify the TSF that the update succeeded + args.Result(CoreTextTextUpdatingResult::Succeeded); + } + catch (...) + { + LOG_CAUGHT_EXCEPTION(); + + // indicate updating failed. + args.Result(CoreTextTextUpdatingResult::Failed); + } + } + + // Method Description: + // - Handler for FormatUpdating event by CoreEditContext responsible + // for handling different format updates for a particular range of text. + // TSFInputControl doesn't do anything with this event. + // Arguments: + // - sender: CoreTextEditContext sending the request. Not used in method. + // - args: CoreTextFormatUpdatingEventArgs Provides data for the FormatUpdating event. Not used in method. + // Return Value: + // - + void TSFInputControl::_formatUpdatingHandler(CoreTextEditContext sender, CoreTextFormatUpdatingEventArgs const& /*args*/) + { + } + + DEFINE_EVENT(TSFInputControl, CompositionCompleted, _compositionCompletedHandlers, TerminalControl::CompositionCompletedEventArgs); +} diff --git a/src/cascadia/TerminalControl/TSFInputControl.h b/src/cascadia/TerminalControl/TSFInputControl.h new file mode 100644 index 00000000000..91d7c59c759 --- /dev/null +++ b/src/cascadia/TerminalControl/TSFInputControl.h @@ -0,0 +1,73 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +#pragma once +#include "TSFInputControl.g.h" +#include "CursorPositionEventArgs.g.h" +#include "FontInfoEventArgs.g.h" +#include "cppwinrt_utils.h" + +namespace winrt::Microsoft::Terminal::TerminalControl::implementation +{ + struct CursorPositionEventArgs : + public CursorPositionEventArgsT + { + public: + CursorPositionEventArgs() = default; + + GETSET_PROPERTY(Windows::Foundation::Point, CurrentPosition); + }; + + struct FontInfoEventArgs : + public FontInfoEventArgsT + { + public: + FontInfoEventArgs() = default; + + GETSET_PROPERTY(Windows::Foundation::Size, FontSize); + + GETSET_PROPERTY(winrt::hstring, FontFace); + }; + + struct TSFInputControl : TSFInputControlT + { + public: + TSFInputControl(); + + void NotifyFocusEnter(); + void NotifyFocusLeave(); + + static void OnCompositionChanged(Windows::UI::Xaml::DependencyObject const&, Windows::UI::Xaml::DependencyPropertyChangedEventArgs const&); + + // -------------------------------- WinRT Events --------------------------------- + TYPED_EVENT(CurrentCursorPosition, TerminalControl::TSFInputControl, TerminalControl::CursorPositionEventArgs); + TYPED_EVENT(CurrentFontInfo, TerminalControl::TSFInputControl, TerminalControl::FontInfoEventArgs); + DECLARE_EVENT(CompositionCompleted, _compositionCompletedHandlers, TerminalControl::CompositionCompletedEventArgs); + + private: + void _layoutRequestedHandler(winrt::Windows::UI::Text::Core::CoreTextEditContext sender, winrt::Windows::UI::Text::Core::CoreTextLayoutRequestedEventArgs const& args); + void _compositionStartedHandler(winrt::Windows::UI::Text::Core::CoreTextEditContext sender, winrt::Windows::UI::Text::Core::CoreTextCompositionStartedEventArgs const& args); + void _compositionCompletedHandler(winrt::Windows::UI::Text::Core::CoreTextEditContext sender, winrt::Windows::UI::Text::Core::CoreTextCompositionCompletedEventArgs const& args); + void _focusRemovedHandler(winrt::Windows::UI::Text::Core::CoreTextEditContext sender, winrt::Windows::Foundation::IInspectable const& object); + void _selectionRequestedHandler(winrt::Windows::UI::Text::Core::CoreTextEditContext sender, winrt::Windows::UI::Text::Core::CoreTextSelectionRequestedEventArgs const& args); + void _textRequestedHandler(winrt::Windows::UI::Text::Core::CoreTextEditContext sender, winrt::Windows::UI::Text::Core::CoreTextTextRequestedEventArgs const& args); + void _selectionUpdatingHandler(winrt::Windows::UI::Text::Core::CoreTextEditContext sender, winrt::Windows::UI::Text::Core::CoreTextSelectionUpdatingEventArgs const& args); + void _textUpdatingHandler(winrt::Windows::UI::Text::Core::CoreTextEditContext sender, winrt::Windows::UI::Text::Core::CoreTextTextUpdatingEventArgs const& args); + void _formatUpdatingHandler(winrt::Windows::UI::Text::Core::CoreTextEditContext sender, winrt::Windows::UI::Text::Core::CoreTextFormatUpdatingEventArgs const& args); + + Windows::UI::Xaml::Controls::Canvas _canvas; + Windows::UI::Xaml::Controls::TextBlock _textBlock; + + Windows::UI::Text::Core::CoreTextEditContext _editContext; + + std::wstring _inputBuffer; + + void _Create(); + }; +} +namespace winrt::Microsoft::Terminal::TerminalControl::factory_implementation +{ + struct TSFInputControl : TSFInputControlT + { + }; +} diff --git a/src/cascadia/TerminalControl/TSFInputControl.idl b/src/cascadia/TerminalControl/TSFInputControl.idl new file mode 100644 index 00000000000..f2eaa9a5f55 --- /dev/null +++ b/src/cascadia/TerminalControl/TSFInputControl.idl @@ -0,0 +1,31 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +namespace Microsoft.Terminal.TerminalControl +{ + delegate void CompositionCompletedEventArgs(String text); + + runtimeclass CursorPositionEventArgs + { + Windows.Foundation.Point CurrentPosition { get; set; }; + } + + runtimeclass FontInfoEventArgs + { + String FontFace { get; set; }; + Windows.Foundation.Size FontSize { get; set; }; + } + + [default_interface] + runtimeclass TSFInputControl : Windows.UI.Xaml.Controls.UserControl + { + TSFInputControl(); + + event CompositionCompletedEventArgs CompositionCompleted; + event Windows.Foundation.TypedEventHandler CurrentCursorPosition; + event Windows.Foundation.TypedEventHandler CurrentFontInfo; + + void NotifyFocusEnter(); + void NotifyFocusLeave(); + } +} diff --git a/src/cascadia/TerminalControl/TermControl.cpp b/src/cascadia/TerminalControl/TermControl.cpp index d2ca39067c8..7275f23bc08 100644 --- a/src/cascadia/TerminalControl/TermControl.cpp +++ b/src/cascadia/TerminalControl/TermControl.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include "..\..\types\inc\GlyphWidth.hpp" @@ -68,7 +69,8 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation _touchAnchor{ std::nullopt }, _cursorTimer{}, _lastMouseClick{}, - _lastMouseClickPos{} + _lastMouseClickPos{}, + _tsfInputControl{ nullptr } { _EnsureStaticInitialization(); _Create(); @@ -101,6 +103,12 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation _scrollBar.LargeChange(4); _scrollBar.Visibility(Visibility::Visible); + _tsfInputControl = TSFInputControl(); + _tsfInputControl.CompositionCompleted({ this, &TermControl::_CompositionCompleted }); + _tsfInputControl.CurrentCursorPosition({ this, &TermControl::_CurrentCursorPositionHandler }); + _tsfInputControl.CurrentFontInfo({ this, &TermControl::_FontInfoHandler }); + container.Children().Append(_tsfInputControl); + // Create the SwapChainPanel that will display our content Controls::SwapChainPanel swapChainPanel; @@ -193,6 +201,11 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation auto lock = _terminal->LockForWriting(); _DoResize(width, height); } + + // set TSF Foreground + Media::SolidColorBrush foregroundBrush{}; + foregroundBrush.Color(ColorRefToColor(_settings.DefaultForeground())); + _tsfInputControl.Foreground(foregroundBrush); }); } @@ -245,6 +258,12 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation // The Codepage is additionally not actually used by the DX engine at all. _actualFont = { fontFace, 0, 10, { 0, fontHeight }, CP_UTF8, false }; _desiredFont = { _actualFont }; + + // set TSF Foreground + Media::SolidColorBrush foregroundBrush{}; + foregroundBrush.Color(ColorRefToColor(_settings.DefaultForeground())); + _tsfInputControl.Foreground(foregroundBrush); + _tsfInputControl.Margin(newMargin); } // Method Description: @@ -1188,6 +1207,11 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation } _focused = true; + if (_tsfInputControl != nullptr) + { + _tsfInputControl.NotifyFocusEnter(); + } + if (_cursorTimer.has_value()) { _cursorTimer.value().Start(); @@ -1206,6 +1230,11 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation } _focused = false; + if (_tsfInputControl != nullptr) + { + _tsfInputControl.NotifyFocusLeave(); + } + if (_cursorTimer.has_value()) { _cursorTimer.value().Stop(); @@ -1866,6 +1895,45 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation return terminalPosition; } + // Method Description: + // - Composition Completion handler for the TSFInputControl that + // handles writing text out to TerminalConnection + // Arguments: + // - text: the text to write to TerminalConnection + // Return Value: + // - + void TermControl::_CompositionCompleted(winrt::hstring text) + { + _connection.WriteInput(text); + } + + // Method Description: + // - CurrentCursorPosition handler for the TSFInputControl that + // handles returning current cursor position. + // Arguments: + // - eventArgs: event for storing the current cursor position + // Return Value: + // - + void TermControl::_CurrentCursorPositionHandler(const IInspectable& /*sender*/, const CursorPositionEventArgs& eventArgs) + { + const COORD cursorPos = _terminal->GetCursorPosition(); + Windows::Foundation::Point p = { gsl::narrow(cursorPos.X), gsl::narrow(cursorPos.Y) }; + eventArgs.CurrentPosition(p); + } + + // Method Description: + // - FontInfo handler for the TSFInputControl that + // handles returning current font information + // Arguments: + // - eventArgs: event for storing the current font information + // Return Value: + // - + void TermControl::_FontInfoHandler(const IInspectable& /*sender*/, const FontInfoEventArgs& eventArgs) + { + eventArgs.FontSize(CharacterDimensions()); + eventArgs.FontFace(_actualFont.GetFaceName()); + } + // Method Description: // - Returns the number of clicks that occurred (double and triple click support) // Arguments: diff --git a/src/cascadia/TerminalControl/TermControl.h b/src/cascadia/TerminalControl/TermControl.h index 2f6afbe990d..9fa32179556 100644 --- a/src/cascadia/TerminalControl/TermControl.h +++ b/src/cascadia/TerminalControl/TermControl.h @@ -11,7 +11,7 @@ #include "../../renderer/base/Renderer.hpp" #include "../../renderer/dx/DxRenderer.hpp" #include "../../cascadia/TerminalCore/Terminal.hpp" -#include "../../cascadia/inc/cppwinrt_utils.h" +#include "cppwinrt_utils.h" namespace winrt::Microsoft::Terminal::TerminalControl::implementation { @@ -101,6 +101,8 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation Windows::UI::Xaml::Controls::Image _bgImageLayer; Windows::UI::Xaml::Controls::SwapChainPanel _swapChainPanel; Windows::UI::Xaml::Controls::Primitives::ScrollBar _scrollBar; + TSFInputControl _tsfInputControl; + event_token _connectionOutputEventToken; std::unique_ptr<::Microsoft::Terminal::Core::Terminal> _terminal; @@ -196,6 +198,11 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation const COORD _GetTerminalPosition(winrt::Windows::Foundation::Point cursorPosition); const unsigned int _NumberOfClicks(winrt::Windows::Foundation::Point clickPos, Timestamp clickTime); double _GetAutoScrollSpeed(double cursorDistanceFromBorder) const; + + // TSFInputControl Handlers + void _CompositionCompleted(winrt::hstring text); + void _CurrentCursorPositionHandler(const IInspectable& /*sender*/, const CursorPositionEventArgs& eventArgs); + void _FontInfoHandler(const IInspectable& /*sender*/, const FontInfoEventArgs& eventArgs); }; } diff --git a/src/cascadia/TerminalControl/TerminalControl.vcxproj b/src/cascadia/TerminalControl/TerminalControl.vcxproj index 0006cc30d28..cc52c89312f 100644 --- a/src/cascadia/TerminalControl/TerminalControl.vcxproj +++ b/src/cascadia/TerminalControl/TerminalControl.vcxproj @@ -31,6 +31,9 @@ TermControlAutomationPeer.idl + + TSFInputControl.idl + @@ -43,6 +46,9 @@ TermControl.idl + + TSFInputControl.idl + TermControlAutomationPeer.idl @@ -53,6 +59,7 @@ + @@ -84,7 +91,7 @@ dwrite.lib;dxgi.lib;d2d1.lib;d3d11.lib;shcore.lib;winmm.lib;pathcch.lib;propsys.lib;uiautomationcore.lib;Shlwapi.lib;ntdll.lib;user32.lib;kernel32.lib;%(AdditionalDependencies) - $(OpenConsoleDir)src\types\inc;%(AdditionalIncludeDirectories) + $(OpenConsoleDir)src\cascadia\inc;$(OpenConsoleDir)src\types\inc;%(AdditionalIncludeDirectories) diff --git a/src/cascadia/TerminalControl/pch.h b/src/cascadia/TerminalControl/pch.h index 42151988cd2..f945b320f8b 100644 --- a/src/cascadia/TerminalControl/pch.h +++ b/src/cascadia/TerminalControl/pch.h @@ -23,15 +23,19 @@ #include #include #include +#include #include #include #include #include +#include #include #include -#include -#include -#include +#include +#include +#include +#include +#include #include diff --git a/src/cascadia/WinRTUtils/WinRTUtils.vcxproj b/src/cascadia/WinRTUtils/WinRTUtils.vcxproj index 60a41a343d6..5936d7f78d1 100644 --- a/src/cascadia/WinRTUtils/WinRTUtils.vcxproj +++ b/src/cascadia/WinRTUtils/WinRTUtils.vcxproj @@ -16,40 +16,34 @@ --> true - - + - Create - - - - @@ -57,8 +51,6 @@ $(MSBuildThisFileDirectory)\inc;%(AdditionalIncludeDirectories) - - - + \ No newline at end of file diff --git a/src/cascadia/WinRTUtils/inc/Utils.h b/src/cascadia/WinRTUtils/inc/Utils.h new file mode 100644 index 00000000000..6f82043f9aa --- /dev/null +++ b/src/cascadia/WinRTUtils/inc/Utils.h @@ -0,0 +1,36 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +#pragma once + +// Method Description: +// - Converts a COLORREF to Color +// Arguments: +// - colorref: COLORREF to convert to Color +// Return Value: +// - Color containing the RGB values from colorref +inline winrt::Windows::UI::Color ColorRefToColor(const COLORREF& colorref) +{ + winrt::Windows::UI::Color color; + color.R = GetRValue(colorref); + color.G = GetGValue(colorref); + color.B = GetBValue(colorref); + return color; +} + +// Method Description: +// - Scales a Rect based on a scale factor +// Arguments: +// - rect: Rect to scale by scale +// - scale: amount to scale rect by +// Return Value: +// - Rect scaled by scale +inline winrt::Windows::Foundation::Rect ScaleRect(winrt::Windows::Foundation::Rect rect, double scale) +{ + const float scaleLocal = gsl::narrow(scale); + rect.X *= scaleLocal; + rect.Y *= scaleLocal; + rect.Width *= scaleLocal; + rect.Height *= scaleLocal; + return rect; +}