From 0bd30c2a7a0d5ae2094432ee02adac78ef0019d8 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Thu, 11 Mar 2021 06:27:13 -0600 Subject: [PATCH 01/82] Move everything to a fresh branch This is the code as of 4703dfe1aee2a42e2a19815232a2115c9c29e123 I'm moving it to TermControl in a new branch, to actually try checking it out now that I think it's mostly done. There are still 14 !TODO!s but this should at least let me start testing --- .vscode/settings.json | 15 +- .vscode/tasks.json | 7 +- src/cascadia/TerminalApp/TerminalPage.cpp | 3 +- src/cascadia/TerminalApp/TerminalTab.cpp | 12 +- src/cascadia/TerminalControl/ControlCore.cpp | 1259 ++++++++++++++++ src/cascadia/TerminalControl/ControlCore.h | 213 +++ src/cascadia/TerminalControl/ControlCore.idl | 16 + src/cascadia/TerminalControl/EventArgs.cpp | 12 + src/cascadia/TerminalControl/EventArgs.h | 129 ++ src/cascadia/TerminalControl/EventArgs.idl | 65 + src/cascadia/TerminalControl/ICoreState.idl | 23 + .../TerminalControl/IDirectKeyListener.idl | 14 + src/cascadia/TerminalControl/TermControl.cpp | 1313 ++++------------- src/cascadia/TerminalControl/TermControl.h | 186 +-- src/cascadia/TerminalControl/TermControl.idl | 94 +- .../TermControlAutomationPeer.cpp | 2 +- .../TerminalControl/TerminalControl.vcxproj | 16 + src/cascadia/TerminalCore/ITerminalInput.hpp | 1 - src/common.build.post.props | 2 +- src/renderer/dx/DxRenderer.cpp | 23 +- src/renderer/dx/DxRenderer.hpp | 5 +- src/renderer/dx/precomp.h | 2 + 22 files changed, 2194 insertions(+), 1218 deletions(-) create mode 100644 src/cascadia/TerminalControl/ControlCore.cpp create mode 100644 src/cascadia/TerminalControl/ControlCore.h create mode 100644 src/cascadia/TerminalControl/ControlCore.idl create mode 100644 src/cascadia/TerminalControl/EventArgs.cpp create mode 100644 src/cascadia/TerminalControl/EventArgs.h create mode 100644 src/cascadia/TerminalControl/EventArgs.idl create mode 100644 src/cascadia/TerminalControl/ICoreState.idl create mode 100644 src/cascadia/TerminalControl/IDirectKeyListener.idl diff --git a/.vscode/settings.json b/.vscode/settings.json index 4534d560156..1b6028e5aea 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -21,7 +21,20 @@ "xloctime": "cpp", "multi_span": "cpp", "pointers": "cpp", - "vector": "cpp" + "vector": "cpp", + "bitset": "cpp", + "deque": "cpp", + "initializer_list": "cpp", + "list": "cpp", + "queue": "cpp", + "random": "cpp", + "regex": "cpp", + "stack": "cpp", + "xhash": "cpp", + "xtree": "cpp", + "xutility": "cpp", + "span": "cpp", + "string_span": "cpp" }, "files.exclude": { "**/bin/**": true, diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 827e4c40762..6e92f4150a6 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -9,7 +9,7 @@ "-Command", "Import-Module ${workspaceFolder}\\tools\\OpenConsole.psm1;", "Set-MsBuildDevEnvironment;", - "$project = switch(\"${input:buildProjectChoice}\"){OpenConsole{\"Conhost\\Host_EXE\"} Terminal{\"Terminal\\CascadiaPackage\"}};", + "$project = switch(\"${input:buildProjectChoice}\"){OpenConsole{\"Conhost\\Host_EXE\"} Terminal{\"Terminal\\CascadiaPackage\"} TermControl{\"Terminal\\TerminalControl\"}};", "$target = switch(\"${input:buildModeChoice}\"){Build{\"\"} Rebuild{\":Rebuild\"} Clean{\":Clean\"}};", "$target = $project + $target;", "msbuild", @@ -98,10 +98,11 @@ "description": "OpenConsole or Terminal?", "options":[ "OpenConsole", - "Terminal" + "Terminal", + "TermControl" ], "default": "Terminal" } ] -} \ No newline at end of file +} diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp index 74b214df461..363db082fd6 100644 --- a/src/cascadia/TerminalApp/TerminalPage.cpp +++ b/src/cascadia/TerminalApp/TerminalPage.cpp @@ -2320,8 +2320,9 @@ namespace winrt::TerminalApp::implementation // Arguments: // - sender (not used) // - eventArgs: the arguments specifying how to set the progress indicator - void TerminalPage::_SetTaskbarProgressHandler(const IInspectable /*sender*/, const IInspectable /*eventArgs*/) + winrt::fire_and_forget TerminalPage::_SetTaskbarProgressHandler(const IInspectable /*sender*/, const IInspectable /*eventArgs*/) { + co_await resume_foreground(Dispatcher()); _setTaskbarProgressHandlers(*this, nullptr); } diff --git a/src/cascadia/TerminalApp/TerminalTab.cpp b/src/cascadia/TerminalApp/TerminalTab.cpp index 45db0a26f11..cf259efdb5f 100644 --- a/src/cascadia/TerminalApp/TerminalTab.cpp +++ b/src/cascadia/TerminalApp/TerminalTab.cpp @@ -167,7 +167,17 @@ namespace winrt::TerminalApp::implementation if (lastFocusedControl) { lastFocusedControl.Focus(_focusState); - lastFocusedControl.TaskbarProgressChanged(); + // !!TODO!!: This is weird: The tab calls a method on the + // control to cause the control to raise an event to the page to + // the app logic + // + // TermControl \v + // /^ TerminalPage \v + // TerminalTab /^ AppLogic \v + // AppHost + // Seems like there's a better way... + // + // lastFocusedControl.TaskbarProgressChanged(); } // When we gain focus, remove the bell indicator if it is active if (_tabStatus.BellIndicator()) diff --git a/src/cascadia/TerminalControl/ControlCore.cpp b/src/cascadia/TerminalControl/ControlCore.cpp new file mode 100644 index 00000000000..d58d4d35f6f --- /dev/null +++ b/src/cascadia/TerminalControl/ControlCore.cpp @@ -0,0 +1,1259 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +#include "pch.h" +#include "ControlCore.h" +#include +#include +#include +#include +#include +#include +#include +#include "../../types/inc/GlyphWidth.hpp" +#include "../../types/inc/Utils.hpp" +#include "../../buffer/out/search.h" + +#include "ControlCore.g.cpp" +// #include "TermControlAutomationPeer.h" // ? + +using namespace ::Microsoft::Console::Types; +using namespace ::Microsoft::Console::VirtualTerminal; +using namespace ::Microsoft::Terminal::Core; +using namespace winrt::Windows::Graphics::Display; +using namespace winrt::Windows::System; +using namespace winrt::Windows::ApplicationModel::DataTransfer; + +namespace winrt::Microsoft::Terminal::TerminalControl::implementation +{ + // Helper static function to ensure that all ambiguous-width glyphs are reported as narrow. + // See microsoft/terminal#2066 for more info. + static bool _IsGlyphWideForceNarrowFallback(const std::wstring_view /* glyph */) + { + return false; // glyph is not wide. + } + + static bool _EnsureStaticInitialization() + { + // use C++11 magic statics to make sure we only do this once. + static bool initialized = []() { + // *** THIS IS A SINGLETON *** + SetGlyphWidthFallback(_IsGlyphWideForceNarrowFallback); + + return true; + }(); + return initialized; + } + + ControlCore::ControlCore(IControlSettings settings, + TerminalConnection::ITerminalConnection connection) : + _connection{ connection }, + _settings{ settings }, + _desiredFont{ DEFAULT_FONT_FACE, 0, DEFAULT_FONT_WEIGHT, { 0, DEFAULT_FONT_SIZE }, CP_UTF8 }, + _actualFont{ DEFAULT_FONT_FACE, 0, DEFAULT_FONT_WEIGHT, { 0, DEFAULT_FONT_SIZE }, CP_UTF8, false } + { + _EnsureStaticInitialization(); + + _terminal = std::make_unique<::Microsoft::Terminal::Core::Terminal>(); + + // Subscribe to the connection's disconnected event and call our connection closed handlers. + _connectionStateChangedRevoker = _connection.StateChanged(winrt::auto_revoke, [this](auto&& /*s*/, auto&& /*v*/) { + _ConnectionStateChangedHandlers(*this, nullptr); + }); + + // This event is explicitly revoked in the destructor: does not need weak_ref + auto onReceiveOutputFn = [this](const hstring str) { + _terminal->Write(str); + + // !TODO!: _updatePatternLocations should happen in the Core, but it's + // a ThrottledFunc, which needs a CoreDispatcher. How do we plan on + // dealing with that? + // _updatePatternLocations->Run(); + }; + _connectionOutputEventToken = _connection.TerminalOutput(onReceiveOutputFn); + + _terminal->SetWriteInputCallback([this](std::wstring& wstr) { + _SendInputToConnection(wstr); + }); + + // GH#8969: pre-seed working directory to prevent potential races + _terminal->SetWorkingDirectory(_settings.StartingDirectory()); + + auto pfnCopyToClipboard = std::bind(&ControlCore::_TerminalCopyToClipboard, this, std::placeholders::_1); + _terminal->SetCopyToClipboardCallback(pfnCopyToClipboard); + + auto pfnWarningBell = std::bind(&ControlCore::_TerminalWarningBell, this); + _terminal->SetWarningBellCallback(pfnWarningBell); + + auto pfnTitleChanged = std::bind(&ControlCore::_TerminalTitleChanged, this, std::placeholders::_1); + _terminal->SetTitleChangedCallback(pfnTitleChanged); + + auto pfnTabColorChanged = std::bind(&ControlCore::_TerminalTabColorChanged, this, std::placeholders::_1); + _terminal->SetTabColorChangedCallback(pfnTabColorChanged); + + auto pfnBackgroundColorChanged = std::bind(&ControlCore::_TerminalBackgroundColorChanged, this, std::placeholders::_1); + _terminal->SetBackgroundCallback(pfnBackgroundColorChanged); + + auto pfnScrollPositionChanged = std::bind(&ControlCore::_TerminalScrollPositionChanged, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3); + _terminal->SetScrollPositionChangedCallback(pfnScrollPositionChanged); + + auto pfnTerminalCursorPositionChanged = std::bind(&ControlCore::_TerminalCursorPositionChanged, this); + _terminal->SetCursorPositionChangedCallback(pfnTerminalCursorPositionChanged); + + auto pfnTerminalTaskbarProgressChanged = std::bind(&ControlCore::_TerminalTaskbarProgressChanged, this); + _terminal->TaskbarProgressChangedCallback(pfnTerminalTaskbarProgressChanged); + + _terminal->UpdateSettings(settings); + } + + bool ControlCore::InitializeTerminal(const double actualWidth, + const double actualHeight, + const double compositionScaleX, + const double compositionScaleY) + { + _panelWidth = actualWidth; + _panelHeight = actualHeight; + _compositionScaleX = compositionScaleX; + _compositionScaleY = compositionScaleY; + + { // scope for terminalLock + auto terminalLock = _terminal->LockForWriting(); + + if (_initializedTerminal) + { + return false; + } + + const auto windowWidth = actualWidth * compositionScaleX; // Width() and Height() are NaN? + const auto windowHeight = actualHeight * compositionScaleY; + + if (windowWidth == 0 || windowHeight == 0) + { + return false; + } + + // First create the render thread. + // Then stash a local pointer to the render thread so we can initialize it and enable it + // to paint itself *after* we hand off its ownership to the renderer. + // We split up construction and initialization of the render thread object this way + // because the renderer and render thread have circular references to each other. + auto renderThread = std::make_unique<::Microsoft::Console::Render::RenderThread>(); + auto* const localPointerToThread = renderThread.get(); + + // Now create the renderer and initialize the render thread. + _renderer = std::make_unique<::Microsoft::Console::Render::Renderer>(_terminal.get(), nullptr, 0, std::move(renderThread)); + ::Microsoft::Console::Render::IRenderTarget& renderTarget = *_renderer; + + // !TODO!: We _DO_ want this + // _renderer->SetRendererEnteredErrorStateCallback([weakThis = get_weak()]() { + // if (auto strongThis{ weakThis.get() }) + // { + // strongThis->_RendererEnteredErrorState(); + // } + // }); + + THROW_IF_FAILED(localPointerToThread->Initialize(_renderer.get())); + + // Set up the DX Engine + auto dxEngine = std::make_unique<::Microsoft::Console::Render::DxEngine>(); + _renderer->AddRenderEngine(dxEngine.get()); + + // Initialize our font with the renderer + // We don't have to care about DPI. We'll get a change message immediately if it's not 96 + // and react accordingly. + _UpdateFont(true); + + const COORD windowSize{ static_cast(windowWidth), + static_cast(windowHeight) }; + + // Fist set up the dx engine with the window size in pixels. + // Then, using the font, get the number of characters that can fit. + // Resize our terminal connection to match that size, and initialize the terminal with that size. + const auto viewInPixels = Viewport::FromDimensions({ 0, 0 }, windowSize); + LOG_IF_FAILED(dxEngine->SetWindowSize({ viewInPixels.Width(), viewInPixels.Height() })); + + // Update DxEngine's SelectionBackground + dxEngine->SetSelectionBackground(_settings.SelectionBackground()); + + const auto vp = dxEngine->GetViewportInCharacters(viewInPixels); + const auto width = vp.Width(); + const auto height = vp.Height(); + _connection.Resize(height, width); + + // Override the default width and height to match the size of the swapChainPanel + _settings.InitialCols(width); + _settings.InitialRows(height); + + _terminal->CreateFromSettings(_settings, renderTarget); + + // IMPORTANT! Set this callback up sooner than later. If we do it + // after Enable, then it'll be possible to paint the frame once + // _before_ the warning handler is set up, and then warnings from + // the first paint will be ignored! + dxEngine->SetWarningCallback(std::bind(&ControlCore::_RendererWarning, this, std::placeholders::_1)); + + // Tell the DX Engine to notify us when the swap chain changes. + // We do this after we initially set the swapchain so as to avoid unnecessary callbacks (and locking problems) + _renderEngine->SetCallback(std::bind(&ControlCore::RenderEngineSwapChainChanged, this)); + + dxEngine->SetRetroTerminalEffect(_settings.RetroTerminalEffect()); + dxEngine->SetPixelShaderPath(_settings.PixelShaderPath()); + dxEngine->SetForceFullRepaintRendering(_settings.ForceFullRepaintRendering()); + dxEngine->SetSoftwareRendering(_settings.SoftwareRendering()); + + // Update DxEngine's AntialiasingMode + switch (_settings.AntialiasingMode()) + { + case TextAntialiasingMode::Cleartype: + dxEngine->SetAntialiasingMode(D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE); + break; + case TextAntialiasingMode::Aliased: + dxEngine->SetAntialiasingMode(D2D1_TEXT_ANTIALIAS_MODE_ALIASED); + break; + case TextAntialiasingMode::Grayscale: + default: + dxEngine->SetAntialiasingMode(D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE); + break; + } + + // GH#5098: Inform the engine of the opacity of the default text background. + if (_settings.UseAcrylic()) + { + dxEngine->SetDefaultTextBackgroundOpacity(::base::saturated_cast(_settings.TintOpacity())); + } + + THROW_IF_FAILED(dxEngine->Enable()); + _renderEngine = std::move(dxEngine); + + // !TODO! in the past we did _AttachDxgiSwapChainToXaml _before_ calling + // EnablePainting. Mild worry that doing EnablePainting first will + // break + localPointerToThread->EnablePainting(); + + _initializedTerminal = true; + } // scope for TerminalLock + + // Start the connection outside of lock, because it could + // start writing output immediately. + _connection.Start(); + + // !TODO!: Do we want this? + // Likewise, run the event handlers outside of lock (they could + // be reentrant) + // _InitializedHandlers(*this, nullptr); + return true; + } + // Method Description: + // - Writes the given sequence as input to the active terminal connection. + // - This method has been overloaded to allow zero-copy winrt::param::hstring optimizations. + // Arguments: + // - wstr: the string of characters to write to the terminal connection. + // Return Value: + // - + void ControlCore::_SendInputToConnection(const winrt::hstring& wstr) + { + if (_isReadOnly) + { + // !TODO!: Do we want this? + // _RaiseReadOnlyWarning(); + } + else + { + _connection.WriteInput(wstr); + } + } + + void ControlCore::_SendInputToConnection(std::wstring_view wstr) + { + if (_isReadOnly) + { + // !TODO!: Do we want this? + // _RaiseReadOnlyWarning(); + } + else + { + _connection.WriteInput(wstr); + } + } + + // Method Description: + // - Writes the given sequence as input to the active terminal connection, + // Arguments: + // - wstr: the string of characters to write to the terminal connection. + // Return Value: + // - + void ControlCore::SendInput(const winrt::hstring& wstr) + { + _SendInputToConnection(wstr); + } + + bool ControlCore::SendCharEvent(const wchar_t ch, + const WORD scanCode, + const ::Microsoft::Terminal::Core::ControlKeyStates modifiers) + { + return _terminal->SendCharEvent(ch, scanCode, modifiers); + } + + // Method Description: + // - Send this particular key event to the terminal. + // See Terminal::SendKeyEvent for more information. + // - Clears the current selection. + // - Makes the cursor briefly visible during typing. + // Arguments: + // - vkey: The vkey of the key pressed. + // - scanCode: The scan code of the key pressed. + // - states: The Microsoft::Terminal::Core::ControlKeyStates representing the modifier key states. + // - keyDown: If true, the key was pressed, otherwise the key was released. + bool ControlCore::TrySendKeyEvent(const WORD vkey, + const WORD scanCode, + const ControlKeyStates modifiers, + const bool eitherWinPressed, + const bool keyDown) + { + // When there is a selection active, escape should clear it and NOT flow through + // to the terminal. With any other keypress, it should clear the selection AND + // flow through to the terminal. + // GH#6423 - don't dismiss selection if the key that was pressed was a + // modifier key. We'll wait for a real keystroke to dismiss the + // GH #7395 - don't dismiss selection when taking PrintScreen + // selection. + // GH#8522, GH#3758 - Only dismiss the selection on key _down_. If we + // dismiss on key up, then there's chance that we'll immediately dismiss + // a selection created by an action bound to a keydown. + if (HasSelection() && + !KeyEvent::IsModifierKey(vkey) && + vkey != VK_SNAPSHOT && + keyDown) + { + // GH#8791 - don't dismiss selection if Windows key was also pressed as a key-combination. + if (!eitherWinPressed) + { + _terminal->ClearSelection(); + _renderer->TriggerSelection(); + } + + if (vkey == VK_ESCAPE) + { + return true; + } + } + + // If the terminal translated the key, mark the event as handled. + // This will prevent the system from trying to get the character out + // of it and sending us a CharacterReceived event. + const auto handled = vkey ? _terminal->SendKeyEvent(vkey, + scanCode, + modifiers, + keyDown) : + true; + + return handled; + } + + bool ControlCore::SendMouseEvent(const COORD viewportPos, + const unsigned int uiButton, + const ControlKeyStates states, + const short wheelDelta, + const ::Microsoft::Console::VirtualTerminal::TerminalInput::MouseButtonState state) + { + return _terminal->SendMouseEvent(viewportPos, uiButton, states, wheelDelta, state); + } + void ControlCore::UserScrollViewport(const int viewTop) + { + // Clear the regex pattern tree so the renderer does not try to render them while scrolling + _terminal->ClearPatternTree(); + + // This is a scroll event that wasn't initiated by the terminal + // itself - it was initiated by the mouse wheel, or the scrollbar. + _terminal->UserScrollViewport(viewTop); + } + + void ControlCore::ToggleShaderEffects() + { + auto lock = _terminal->LockForWriting(); + // Originally, this action could be used to enable the retro effects + // even when they're set to `false` in the settings. If the user didn't + // specify a custom pixel shader, manually enable the legacy retro + // effect first. This will ensure that a toggle off->on will still work, + // even if they currently have retro effect off. + if (_settings.PixelShaderPath().empty() && !_renderEngine->GetRetroTerminalEffect()) + { + // SetRetroTerminalEffect to true will enable the effect. In this + // case, the shader effect will already be disabled (because neither + // a pixel shader nor the retro effects were originally requested). + // So we _don't_ want to toggle it again below, because that would + // toggle it back off. + _renderEngine->SetRetroTerminalEffect(true); + } + else + { + _renderEngine->ToggleShaderEffects(); + } + } + + // Method Description: + // - Tell TerminalCore to update its knowledge about the locations of visible regex patterns + // - We should call this (through the throttled function) when something causes the visible + // region to change, such as when new text enters the buffer or the viewport is scrolled + void ControlCore::UpdatePatternLocations() + { + _terminal->UpdatePatterns(); + } + + // Method description: + // - Updates last hovered cell, renders / removes rendering of hyper-link if required + // Arguments: + // - terminalPosition: The terminal position of the pointer + void ControlCore::UpdateHoveredCell(const std::optional& terminalPosition) + { + if (terminalPosition == _lastHoveredCell) + { + return; + } + + _lastHoveredCell = terminalPosition; + + const uint16_t newId = terminalPosition.has_value() ? _terminal->GetHyperlinkIdAtPosition(*terminalPosition) : + 0u; + const auto newInterval = terminalPosition.has_value() ? _terminal->GetHyperlinkIntervalFromPosition(*terminalPosition) : + std::nullopt; + + // If the hyperlink ID changed or the interval changed, trigger a redraw all + // (so this will happen both when we move onto a link and when we move off a link) + if (newId != _lastHoveredId || + (newInterval != _lastHoveredInterval)) + { + _lastHoveredId = newId; + _lastHoveredInterval = newInterval; + _renderEngine->UpdateHyperlinkHoveredId(newId); + _renderer->UpdateLastHoveredInterval(newInterval); + _renderer->TriggerRedrawAll(); + + _raiseHoveredHyperlinkChanged(); + } + } + + void ControlCore::_raiseHoveredHyperlinkChanged() + { + _HoveredHyperlinkChangedHandlers(*this, nullptr); + } + + winrt::hstring ControlCore::GetHyperlink(const til::point pos) const + { + return winrt::hstring{ _terminal->GetHyperlinkAtPosition(pos) }; + } + + winrt::hstring ControlCore::GetHoveredUriText() const + { + if (_lastHoveredCell.has_value()) + { + const winrt::hstring uri{ _terminal->GetHyperlinkAtPosition(*_lastHoveredCell) }; + return uri; + } + return { L"" }; + } + + std::optional ControlCore::GetHoveredCell() const + { + return _lastHoveredCell; + } + + void ControlCore::UpdateSettings(const IControlSettings& settings) + { + _settings = settings; + + auto lock = _terminal->LockForWriting(); + + // Initialize our font information. + const auto fontFace = _settings.FontFace(); + const short fontHeight = gsl::narrow_cast(_settings.FontSize()); + const auto fontWeight = _settings.FontWeight(); + // The font width doesn't terribly matter, we'll only be using the + // height to look it up + // The other params here also largely don't matter. + // The family is only used to determine if the font is truetype or + // not, but DX doesn't use that info at all. + // The Codepage is additionally not actually used by the DX engine at all. + _actualFont = { fontFace, 0, fontWeight.Weight, { 0, fontHeight }, CP_UTF8, false }; + _desiredFont = { _actualFont }; + + // Update the terminal core with its new Core settings + _terminal->UpdateSettings(_settings); + + if (!_initializedTerminal) + { + // If we haven't initialized, there's no point in continuing. + // Initialization will handle the renderer settings. + return; + } + + // Update DxEngine settings under the lock + _renderEngine->SetSelectionBackground(_settings.SelectionBackground()); + + _renderEngine->SetRetroTerminalEffect(_settings.RetroTerminalEffect()); + _renderEngine->SetPixelShaderPath(_settings.PixelShaderPath()); + _renderEngine->SetForceFullRepaintRendering(_settings.ForceFullRepaintRendering()); + _renderEngine->SetSoftwareRendering(_settings.SoftwareRendering()); + + switch (_settings.AntialiasingMode()) + { + case TextAntialiasingMode::Cleartype: + _renderEngine->SetAntialiasingMode(D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE); + break; + case TextAntialiasingMode::Aliased: + _renderEngine->SetAntialiasingMode(D2D1_TEXT_ANTIALIAS_MODE_ALIASED); + break; + case TextAntialiasingMode::Grayscale: + default: + _renderEngine->SetAntialiasingMode(D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE); + break; + } + + // Refresh our font with the renderer + const auto actualFontOldSize = _actualFont.GetSize(); + _UpdateFont(); + const auto actualFontNewSize = _actualFont.GetSize(); + if (actualFontNewSize != actualFontOldSize) + { + _RefreshSizeUnderLock(); + } + } + + // Method Description: + // - Update the font with the renderer. This will be called either when the + // font changes or the DPI changes, as DPI changes will necessitate a + // font change. This method will *not* change the buffer/viewport size + // to account for the new glyph dimensions. Callers should make sure to + // appropriately call _DoResizeUnderLock after this method is called. + // - The write lock should be held when calling this method. + // Arguments: + // - initialUpdate: whether this font update should be considered as being + // concerned with initialization process. Value forwarded to event handler. + void ControlCore::_UpdateFont(const bool /*initialUpdate*/) + { + const int newDpi = static_cast(static_cast(USER_DEFAULT_SCREEN_DPI) * + _compositionScaleX); + + // !TODO!: MSFT:20895307 If the font doesn't exist, this doesn't + // actually fail. We need a way to gracefully fallback. + _renderer->TriggerFontChange(newDpi, _desiredFont, _actualFont); + + // If the actual font isn't what was requested... + if (_actualFont.GetFaceName() != _desiredFont.GetFaceName()) + { + // !TODO!: We _DO_ want this + // // Then warn the user that we picked something because we couldn't find their font. + // // Format message with user's choice of font and the font that was chosen instead. + // const winrt::hstring message{ fmt::format(std::wstring_view{ RS_(L"NoticeFontNotFound") }, _desiredFont.GetFaceName(), _actualFont.GetFaceName()) }; + // // Capture what we need to resume later. + // [strongThis = get_strong(), message]() -> winrt::fire_and_forget { + // // Take these out of the lambda and store them locally + // // because the coroutine will lose them into space + // // by the time it resumes. + // const auto msg = message; + // const auto strong = strongThis; + + // // Pop the rest of this function to the tail of the UI thread + // // Just in case someone was holding a lock when they called us and + // // the handlers decide to do something that take another lock + // // (like ShellExecute pumping our messaging thread...GH#7994) + // co_await strong->Dispatcher(); + + // auto noticeArgs = winrt::make(NoticeLevel::Warning, std::move(msg)); + // strong->_raiseNoticeHandlers(*strong, std::move(noticeArgs)); + // }(); + } + + // !TODO!: We _DO_ want this + // const auto actualNewSize = _actualFont.GetSize(); + // _fontSizeChangedHandlers(actualNewSize.X, actualNewSize.Y, initialUpdate); + } + + // Method Description: + // - Set the font size of the terminal control. + // Arguments: + // - fontSize: The size of the font. + void ControlCore::_SetFontSize(int fontSize) + { + try + { + // Make sure we have a non-zero font size + const auto newSize = std::max(gsl::narrow_cast(fontSize), 1); + const auto fontFace = _settings.FontFace(); + const auto fontWeight = _settings.FontWeight(); + _actualFont = { fontFace, 0, fontWeight.Weight, { 0, newSize }, CP_UTF8, false }; + _desiredFont = { _actualFont }; + + auto lock = _terminal->LockForWriting(); + + // Refresh our font with the renderer + _UpdateFont(); + + // Resize the terminal's BUFFER to match the new font size. This does + // NOT change the size of the window, because that can lead to more + // problems (like what happens when you change the font size while the + // window is maximized?) + _RefreshSizeUnderLock(); + } + CATCH_LOG(); + } + + // Method Description: + // - Reset the font size of the terminal to its default size. + // Arguments: + // - none + void ControlCore::ResetFontSize() + { + _SetFontSize(_settings.FontSize()); + } + + // Method Description: + // - Adjust the font size of the terminal control. + // Arguments: + // - fontSizeDelta: The amount to increase or decrease the font size by. + void ControlCore::AdjustFontSize(int fontSizeDelta) + { + const auto newSize = _desiredFont.GetEngineSize().Y + fontSizeDelta; + _SetFontSize(newSize); + } + + // Method Description: + // - Perform a resize for the current size of the swapchainpanel. If the + // font size changed, we'll need to resize the buffer to fit the existing + // swapchain size. This helper will call _DoResizeUnderLock with the + // current size of the swapchain, accounting for scaling due to DPI. + // - Note that a DPI change will also trigger a font size change, and will + // call into here. + // - The write lock should be held when calling this method, we might be + // changing the buffer size in _DoResizeUnderLock. + // Arguments: + // - + // Return Value: + // - + void ControlCore::_RefreshSizeUnderLock() + { + // const auto currentScaleX = SwapChainPanel().CompositionScaleX(); + // const auto currentScaleY = SwapChainPanel().CompositionScaleY(); + // const auto actualWidth = SwapChainPanel().ActualWidth(); + // const auto actualHeight = SwapChainPanel().ActualHeight(); + + const auto widthInPixels = _panelWidth * _compositionScaleX; + const auto heightInPixels = _panelHeight * _compositionScaleY; + + _DoResizeUnderLock(widthInPixels, heightInPixels); + } + + // Method Description: + // - Process a resize event that was initiated by the user. This can either + // be due to the user resizing the window (causing the swapchain to + // resize) or due to the DPI changing (causing us to need to resize the + // buffer to match) + // Arguments: + // - newWidth: the new width of the swapchain, in pixels. + // - newHeight: the new height of the swapchain, in pixels. + void ControlCore::_DoResizeUnderLock(const double newWidth, + const double newHeight) + { + SIZE size; + size.cx = static_cast(newWidth); + size.cy = static_cast(newHeight); + + // Don't actually resize so small that a single character wouldn't fit + // in either dimension. The buffer really doesn't like being size 0. + if (size.cx < _actualFont.GetSize().X || size.cy < _actualFont.GetSize().Y) + { + return; + } + + _terminal->ClearSelection(); + + // Tell the dx engine that our window is now the new size. + THROW_IF_FAILED(_renderEngine->SetWindowSize(size)); + + // Invalidate everything + _renderer->TriggerRedrawAll(); + + // Convert our new dimensions to characters + const auto viewInPixels = Viewport::FromDimensions({ 0, 0 }, + { static_cast(size.cx), static_cast(size.cy) }); + const auto vp = _renderEngine->GetViewportInCharacters(viewInPixels); + + // If this function succeeds with S_FALSE, then the terminal didn't + // actually change size. No need to notify the connection of this no-op. + const HRESULT hr = _terminal->UserResize({ vp.Width(), vp.Height() }); + if (SUCCEEDED(hr) && hr != S_FALSE) + { + _connection.Resize(vp.Height(), vp.Width()); + } + } + + void ControlCore::SizeChanged(const double width, + const double height) + { + _panelWidth = width; + _panelHeight = height; + + auto lock = _terminal->LockForWriting(); + const auto currentEngineScale = _renderEngine->GetScaling(); + + auto scaledWidth = width * currentEngineScale; + auto scaledHeight = height * currentEngineScale; + _DoResizeUnderLock(scaledWidth, scaledHeight); + } + + void ControlCore::ScaleChanged(const double scaleX, + const double scaleY) + { + if (!_renderEngine) + { + return; + } + + _compositionScaleX = scaleX; + _compositionScaleY = scaleY; + + const auto currentEngineScale = _renderEngine->GetScaling(); + // If we're getting a notification to change to the DPI we already + // have, then we're probably just beginning the DPI change. Since + // we'll get _another_ event with the real DPI, do nothing here for + // now. We'll also skip the next resize in _SwapChainSizeChanged. + const bool dpiWasUnchanged = currentEngineScale == scaleX; + if (dpiWasUnchanged) + { + return; + } + + const auto dpi = (float)(scaleX * USER_DEFAULT_SCREEN_DPI); + + const auto actualFontOldSize = _actualFont.GetSize(); + + auto lock = _terminal->LockForWriting(); + + _renderer->TriggerFontChange(::base::saturated_cast(dpi), + _desiredFont, + _actualFont); + + const auto actualFontNewSize = _actualFont.GetSize(); + if (actualFontNewSize != actualFontOldSize) + { + _RefreshSizeUnderLock(); + } + } + + // !!TODO!! Does the Control really need to ask the Core for this? Or can it + // suffice with the swapchain value? That's unclear. + float ControlCore::RendererScale() const + { + return _renderEngine->GetScaling(); + } + + void ControlCore::SetSelectionAnchor(Windows::Foundation::Point const& position) + { + auto lock = _terminal->LockForWriting(); + _terminal->SetSelectionAnchor(til::point{ til::math::rounding, + position.X, + position.Y }); + } + + // Method Description: + // - Sets selection's end position to match supplied cursor position, e.g. while mouse dragging. + // Arguments: + // - ~~cursorPosition: in pixels, relative to the origin of the control~~ + // - cursorPosition: in cells + void ControlCore::SetEndSelectionPoint(Windows::Foundation::Point const& position) + { + if (!_terminal->IsSelectionActive()) + { + return; + } + + // Have to take the lock because the renderer will not draw correctly if + // you move its endpoints while it is generating a frame. + auto lock = _terminal->LockForWriting(); + + const short lastVisibleRow = std::max(_terminal->GetViewport().Height() - 1, 0); + const short lastVisibleCol = std::max(_terminal->GetViewport().Width() - 1, 0); + + til::point terminalPosition{ til::math::rounding, + std::clamp(position.X, 0, lastVisibleCol), + std::clamp(position.Y, 0, lastVisibleRow) }; + + // save location (for rendering) + render + _terminal->SetSelectionEnd(terminalPosition); + _renderer->TriggerSelection(); + // _selectionNeedsToBeCopied = true; + } + + // Called when the Terminal wants to set something to the clipboard, i.e. + // when an OSC 52 is emitted. + void ControlCore::_TerminalCopyToClipboard(const std::wstring_view& wstr) + { + auto copyArgs = winrt::make_self(winrt::hstring(wstr)); + _CopyToClipboardHandlers(*this, *copyArgs); + } + + // Method Description: + // - Given a copy-able selection, get the selected text from the buffer and send it to the + // Windows Clipboard (CascadiaWin32:main.cpp). + // - CopyOnSelect does NOT clear the selection + // Arguments: + // - singleLine: collapse all of the text to one line + // - formats: which formats to copy (defined by action's CopyFormatting arg). nullptr + // if we should defer which formats are copied to the global setting + bool ControlCore::CopySelectionToClipboard(bool singleLine, + const Windows::Foundation::IReference& formats) + { + // no selection --> nothing to copy + if (!_terminal->IsSelectionActive()) + { + return false; + } + + // // Mark the current selection as copied + // _selectionNeedsToBeCopied = false; + + // extract text from buffer + const auto bufferData = _terminal->RetrieveSelectedTextFromBuffer(singleLine); + + // convert text: vector --> string + std::wstring textData; + for (const auto& text : bufferData.text) + { + textData += text; + } + + // convert text to HTML format + // GH#5347 - Don't provide a title for the generated HTML, as many + // web applications will paste the title first, followed by the HTML + // content, which is unexpected. + const auto htmlData = formats == nullptr || WI_IsFlagSet(formats.Value(), CopyFormat::HTML) ? + TextBuffer::GenHTML(bufferData, + _actualFont.GetUnscaledSize().Y, + _actualFont.GetFaceName(), + _settings.DefaultBackground()) : + ""; + + // convert to RTF format + const auto rtfData = formats == nullptr || WI_IsFlagSet(formats.Value(), CopyFormat::RTF) ? + TextBuffer::GenRTF(bufferData, + _actualFont.GetUnscaledSize().Y, + _actualFont.GetFaceName(), + _settings.DefaultBackground()) : + ""; + + if (!_settings.CopyOnSelect()) + { + _terminal->ClearSelection(); + _renderer->TriggerSelection(); + } + + // send data up for clipboard + auto copyArgs = winrt::make_self(winrt::hstring(textData), + winrt::to_hstring(htmlData), + winrt::to_hstring(rtfData), + formats); + _CopyToClipboardHandlers(*this, *copyArgs); + return true; + } + + // Method Description: + // - Pre-process text pasted (presumably from the clipboard) + // before sending it over the terminal's connection. + void ControlCore::PasteText(const winrt::hstring& hstr) + { + _terminal->WritePastedText(hstr); + _terminal->ClearSelection(); + _terminal->TrySnapOnInput(); + } + + FontInfo ControlCore::GetFont() const + { + return _actualFont; + } + + TerminalConnection::ConnectionState ControlCore::ConnectionState() const + { + return _connection.State(); + } + + hstring ControlCore::Title() + { + hstring hstr{ _terminal->GetConsoleTitle() }; + return hstr; + } + + hstring ControlCore::WorkingDirectory() const + { + hstring hstr{ _terminal->GetWorkingDirectory() }; + return hstr; + } + + Windows::Foundation::IReference ControlCore::TabColor() noexcept + { + auto coreColor = _terminal->GetTabColor(); + return coreColor.has_value() ? Windows::Foundation::IReference(coreColor.value()) : + nullptr; + } + + til::color ControlCore::BackgroundColor() const + { + return _backgroundColor; + } + + // Method Description: + // - Gets the internal taskbar state value + // Return Value: + // - The taskbar state of this control + const size_t ControlCore::TaskbarState() const noexcept + { + return _terminal->GetTaskbarState(); + } + + // Method Description: + // - Gets the internal taskbar progress value + // Return Value: + // - The taskbar progress of this control + const size_t ControlCore::TaskbarProgress() const noexcept + { + return _terminal->GetTaskbarProgress(); + } + + int ControlCore::ScrollOffset() + { + return _terminal->GetScrollOffset(); + } + + // Function Description: + // - Gets the height of the terminal in lines of text. This is just the + // height of the viewport. + // Return Value: + // - The height of the terminal in lines of text + int ControlCore::ViewHeight() const + { + const auto viewPort = _terminal->GetViewport(); + return viewPort.Height(); + } + + // Function Description: + // - Gets the height of the terminal in lines of text. This includes the + // history AND the viewport. + // Return Value: + // - The height of the terminal in lines of text + int ControlCore::BufferHeight() const + { + return _terminal->GetViewport().BottomExclusive(); + } + + void ControlCore::_TerminalWarningBell() + { + _WarningBellHandlers(*this, nullptr); + } + + void ControlCore::_TerminalTitleChanged(const std::wstring_view& wstr) + { + auto titleArgs = winrt::make_self(winrt::hstring{ wstr }); + _TitleChangedHandlers(*this, *titleArgs); + } + void ControlCore::_TerminalTabColorChanged(const std::optional /*color*/) + { + _TabColorChangedHandlers(*this, nullptr); + } + + void ControlCore::_TerminalBackgroundColorChanged(const COLORREF color) + { + _backgroundColor = color; + _BackgroundColorChangedHandlers(*this, nullptr); + } + + // Method Description: + // - Update the position and size of the scrollbar to match the given + // viewport top, viewport height, and buffer size. + // Additionally fires a ScrollPositionChanged event for anyone who's + // registered an event handler for us. + // Arguments: + // - viewTop: the top of the visible viewport, in rows. 0 indicates the top + // of the buffer. + // - viewHeight: the height of the viewport in rows. + // - bufferSize: the length of the buffer, in rows + void ControlCore::_TerminalScrollPositionChanged(const int viewTop, + const int viewHeight, + const int bufferSize) + { + // !!TODO!! do we need this? + // // Since this callback fires from non-UI thread, we might be already + // // closed/closing. + // if (_closing.load()) + // { + // return; + // } + + // Clear the regex pattern tree so the renderer does not try to render + // them while scrolling + _terminal->ClearPatternTree(); + + auto scrollArgs = winrt::make_self(viewTop, viewHeight, bufferSize); + _ScrollPositionChangedHandlers(*this, *scrollArgs); + } + + void ControlCore::_TerminalCursorPositionChanged() + { + _CursorPositionChangedHandlers(*this, nullptr); + } + + void ControlCore::_TerminalTaskbarProgressChanged() + { + _TaskbarProgressChangedHandlers(*this, nullptr); + } + + bool ControlCore::HasSelection() const + { + return _terminal->IsSelectionActive(); + } + + std::vector ControlCore::SelectedText(bool trimTrailingWhitespace) const + { + const auto bufferData = _terminal->RetrieveSelectedTextFromBuffer(trimTrailingWhitespace); + return bufferData.text; + } + + ::Microsoft::Console::Types::IUiaData* ControlCore::GetUiaData() const + { + return _terminal.get(); + } + + // Method Description: + // - Search text in text buffer. This is triggered if the user click + // search button or press enter. + // Arguments: + // - text: the text to search + // - goForward: boolean that represents if the current search direction is forward + // - caseSensitive: boolean that represents if the current search is case sensitive + // Return Value: + // - + void ControlCore::Search(const winrt::hstring& text, + const bool goForward, + const bool caseSensitive) + { + // !!TODO!! do we need this? + if (text.size() == 0 /* || _closing*/) + { + return; + } + + const Search::Direction direction = goForward ? + Search::Direction::Forward : + Search::Direction::Backward; + + const Search::Sensitivity sensitivity = caseSensitive ? + Search::Sensitivity::CaseSensitive : + Search::Sensitivity::CaseInsensitive; + + ::Search search(*GetUiaData(), text.c_str(), direction, sensitivity); + auto lock = _terminal->LockForWriting(); + if (search.FindNext()) + { + _terminal->SetBlockSelection(false); + search.Select(); + _renderer->TriggerSelection(); + } + } + + void ControlCore::SetBackgroundOpacity(const float opacity) + { + if (_renderEngine) + { + _renderEngine->SetDefaultTextBackgroundOpacity(::base::saturated_cast(opacity)); + } + } + + // Method Description: + // - Asynchronously close our connection. The Connection will likely wait + // until the attached process terminates before Close returns. If that's + // the case, we don't want to block the UI thread waiting on that process + // handle. + // Arguments: + // - + // Return Value: + // - + winrt::fire_and_forget ControlCore::_AsyncCloseConnection() + { + if (auto localConnection{ std::exchange(_connection, nullptr) }) + { + // Close the connection on the background thread. + co_await winrt::resume_background(); + localConnection.Close(); + // connection is destroyed. + } + } + + void ControlCore::Close() + { + // Stop accepting new output and state changes before we disconnect everything. + _connection.TerminalOutput(_connectionOutputEventToken); + _connectionStateChangedRevoker.revoke(); + + // GH#1996 - Close the connection asynchronously on a background + // thread. + // Since TermControl::Close is only ever triggered by the UI, we + // don't really care to wait for the connection to be completely + // closed. We can just do it whenever. + _AsyncCloseConnection(); + + { + // GH#8734: + // We lock the terminal here to make sure it isn't still being + // used in the connection thread before we destroy the renderer. + // However, we must unlock it again prior to triggering the + // teardown, to avoid the render thread being deadlocked. The + // renderer may be waiting to acquire the terminal lock, while + // we're waiting for the renderer to finish. + auto lock = _terminal->LockForWriting(); + } + + if (auto localRenderEngine{ std::exchange(_renderEngine, nullptr) }) + { + if (auto localRenderer{ std::exchange(_renderer, nullptr) }) + { + localRenderer->TriggerTeardown(); + // renderer is destroyed + } + // renderEngine is destroyed + } + + // we don't destroy _terminal here; it now has the same lifetime as the + // control. + } + + HANDLE ControlCore::GetSwapChainHandle() const + { + return _renderEngine->GetSwapChainHandle(); + } + + void ControlCore::_RendererWarning(const HRESULT hr) + { + auto args{ winrt::make_self(hr) }; + _RendererWarningHandlers(*this, *args); + } + + void ControlCore::RenderEngineSwapChainChanged() + { + _SwapChainChangedHandlers(*this, nullptr); + } + + void ControlCore::BlinkAttributeTick() + { + auto lock = _terminal->LockForWriting(); + + auto& renderTarget = *_renderer; + auto& blinkingState = _terminal->GetBlinkingState(); + blinkingState.ToggleBlinkingRendition(renderTarget); + } + + void ControlCore::BlinkCursor() + { + if (!_terminal->IsCursorBlinkingAllowed() && + _terminal->IsCursorVisible()) + { + return; + } + _terminal->SetCursorOn(!_terminal->IsCursorOn()); + } + + bool ControlCore::CursorOn() const + { + return _terminal->IsCursorOn(); + } + + void ControlCore::CursorOn(const bool isCursorOn) + { + _terminal->SetCursorOn(isCursorOn); + } + + void ControlCore::ResumeRendering() + { + _renderer->ResetErrorStateAndResume(); + } + + bool ControlCore::IsVtMouseModeEnabled() const + { + return _terminal != nullptr && _terminal->IsTrackingMouseInput(); + } + + til::point ControlCore::CursorPosition() const + { + // If we haven't been initialized yet, then fake it. + if (!_initializedTerminal) + { + return { 0, 0 }; + } + + auto lock = _terminal->LockForReading(); + return _terminal->GetCursorPosition(); + } + + // This one's really pushing the boundary of "encapsulation". It really + // belongs in the "Interactivity" layer, which doesn't yet exist. There's so + // many accesses to the selection in the Core though, that I just put this + // here. The Control shouldn't be futzing that much with the selection + // itself. + void ControlCore::LeftClickOnTerminal(const til::point terminalPosition, + const int numberOfClicks, + const bool altEnabled, + const bool shiftEnabled, + const bool isOnOriginalPosition, + bool& selectionNeedsToBeCopied) + { + auto lock = _terminal->LockForWriting(); + // handle ALT key + _terminal->SetBlockSelection(altEnabled); + + ::Terminal::SelectionExpansionMode mode = ::Terminal::SelectionExpansionMode::Cell; + if (numberOfClicks == 1) + { + mode = ::Terminal::SelectionExpansionMode::Cell; + } + else if (numberOfClicks == 2) + { + mode = ::Terminal::SelectionExpansionMode::Word; + } + else if (numberOfClicks == 3) + { + mode = ::Terminal::SelectionExpansionMode::Line; + } + + // Update the selection appropriately + + // We reset the active selection if one of the conditions apply: + // - shift is not held + // - GH#9384: the position is the same as of the first click starting + // the selection (we need to reset selection on double-click or + // triple-click, so it captures the word or the line, rather than + // extending the selection) + if (HasSelection() && (!shiftEnabled || isOnOriginalPosition)) + { + // Reset the selection + _terminal->ClearSelection(); + selectionNeedsToBeCopied = false; // there's no selection, so there's nothing to update + } + + if (shiftEnabled) + { + if (HasSelection()) + { + // If there is a selection we extend it using the selection mode + // (expand the "end"selection point) + _terminal->SetSelectionEnd(terminalPosition, mode); + } + else + { + // If there is no selection we establish it using the selected mode + // (expand both "start" and "end" selection points) + _terminal->MultiClickSelection(terminalPosition, mode); + } + selectionNeedsToBeCopied = true; + } + + _renderer->TriggerSelection(); + } + +} diff --git a/src/cascadia/TerminalControl/ControlCore.h b/src/cascadia/TerminalControl/ControlCore.h new file mode 100644 index 00000000000..d6df600bf32 --- /dev/null +++ b/src/cascadia/TerminalControl/ControlCore.h @@ -0,0 +1,213 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +#pragma once + +#include "EventArgs.h" +#include "ControlCore.g.h" +#include +#include "../../renderer/base/Renderer.hpp" +#include "../../renderer/dx/DxRenderer.hpp" +#include "../../renderer/uia/UiaRenderer.hpp" +#include "../../cascadia/TerminalCore/Terminal.hpp" +#include "../buffer/out/search.h" +#include "cppwinrt_utils.h" +#include "ThrottledFunc.h" + +namespace winrt::Microsoft::Terminal::TerminalControl::implementation +{ + struct ControlCore : ControlCoreT + { + public: + ControlCore(IControlSettings settings, TerminalConnection::ITerminalConnection connection); + + //////////////////////////////////////////////////////////////////////// + // These members are taken from TermControl + + bool _initializedTerminal; + + TerminalConnection::ITerminalConnection _connection; + event_token _connectionOutputEventToken; + TerminalConnection::ITerminalConnection::StateChanged_revoker _connectionStateChangedRevoker; + + std::unique_ptr<::Microsoft::Terminal::Core::Terminal> _terminal; + std::unique_ptr<::Microsoft::Console::Render::Renderer> _renderer; + + private: + std::unique_ptr<::Microsoft::Console::Render::DxEngine> _renderEngine; + + IControlSettings _settings; // ? Might be able to get away with only retrieving pieces + + FontInfoDesired _desiredFont; + FontInfo _actualFont; + + public: + // storage location for the leading surrogate of a utf-16 surrogate pair + std::optional _leadingSurrogate; + + bool _isReadOnly{ false }; // ? + + std::optional _lastHoveredCell; + // Track the last hyperlink ID we hovered over + uint16_t _lastHoveredId; + + std::optional::interval> _lastHoveredInterval; + + //////////////////////////////////////////////////////////////////////// + // These members are new + double _panelWidth; + double _panelHeight; + double _compositionScaleX; + double _compositionScaleY; + til::color _backgroundColor; // This is _in_ Terminal already! + //////////////////////////////////////////////////////////////////////// + + //////////////////////////////////////////////////////////////////////// + // These methods are taken from TermControl + bool InitializeTerminal(const double actualWidth, + const double actualHeight, + const double compositionScaleX, + const double compositionScaleY); + + void _SetFontSize(int fontSize); + void _UpdateFont(const bool initialUpdate = false); + void AdjustFontSize(int fontSizeDelta); + void ResetFontSize(); + void _RefreshSizeUnderLock(); + void _DoResizeUnderLock(const double newWidth, + const double newHeight); + + void _SendInputToConnection(const winrt::hstring& wstr); + void _SendInputToConnection(std::wstring_view wstr); + + void SendInput(const winrt::hstring& wstr); + void ToggleShaderEffects(); + void UpdatePatternLocations(); + void UpdateHoveredCell(const std::optional& terminalPosition); + + void SetSelectionAnchor(winrt::Windows::Foundation::Point const& position); + void SetEndSelectionPoint(winrt::Windows::Foundation::Point const& position); + bool CopySelectionToClipboard(bool singleLine, const Windows::Foundation::IReference& formats); + + ::Microsoft::Console::Types::IUiaData* GetUiaData() const; + + winrt::fire_and_forget _AsyncCloseConnection(); + void Close(); + +#pragma region ICoreState + // existing + Windows::Foundation::IReference TabColor() noexcept; + const size_t TaskbarState() const noexcept; + const size_t TaskbarProgress() const noexcept; + hstring Title(); + hstring WorkingDirectory() const; + TerminalConnection::ConnectionState ConnectionState() const; + // new + int ScrollOffset(); + int ViewHeight() const; + int BufferHeight() const; +#pragma endregion + +#pragma region TerminalCoreCallbacks + void _TerminalCopyToClipboard(const std::wstring_view& wstr); + void _TerminalWarningBell(); + void _TerminalTitleChanged(const std::wstring_view& wstr); + void _TerminalTabColorChanged(const std::optional color); + void _TerminalBackgroundColorChanged(const COLORREF color); + void _TerminalScrollPositionChanged(const int viewTop, + const int viewHeight, + const int bufferSize); + void _TerminalCursorPositionChanged(); + void _TerminalTaskbarProgressChanged(); +#pragma endregion + +#pragma region RendererCallbacks + void _RendererWarning(const HRESULT hr); + void RenderEngineSwapChainChanged(); +#pragma endregion + + TYPED_EVENT(CopyToClipboard, IInspectable, TerminalControl::CopyToClipboardEventArgs); + + TYPED_EVENT(TitleChanged, IInspectable, TerminalControl::TitleChangedEventArgs); + TYPED_EVENT(WarningBell, IInspectable, IInspectable); + TYPED_EVENT(TabColorChanged, IInspectable, IInspectable); + TYPED_EVENT(BackgroundColorChanged, IInspectable, IInspectable); + TYPED_EVENT(ScrollPositionChanged, IInspectable, TerminalControl::ScrollPositionChangedArgs); + TYPED_EVENT(CursorPositionChanged, IInspectable, IInspectable); + TYPED_EVENT(TaskbarProgressChanged, IInspectable, IInspectable); + TYPED_EVENT(ConnectionStateChanged, IInspectable, IInspectable); + + public: + //////////////////////////////////////////////////////////////////////// + // These methods are new + void UpdateSettings(const IControlSettings& settings); + + void SizeChanged(const double width, const double height); + void ScaleChanged(const double scaleX, const double scaleY); + float RendererScale() const; + + void _raiseHoveredHyperlinkChanged(); + winrt::hstring GetHyperlink(const til::point position) const; + winrt::hstring GetHoveredUriText() const; + std::optional GetHoveredCell() const; + + void PasteText(const winrt::hstring& hstr); + + FontInfo GetFont() const; + til::color BackgroundColor() const; + + bool HasSelection() const; + std::vector SelectedText(bool trimTrailingWhitespace) const; + + void Search(const winrt::hstring& text, + const bool goForward, + const bool caseSensitive); + + void SetBackgroundOpacity(const float opacity); + +#pragma region ITerminalInputButNotReally + bool TrySendKeyEvent(const WORD vkey, + const WORD scanCode, + const ::Microsoft::Terminal::Core::ControlKeyStates modifiers, + const bool eitherWinPressed, + const bool keyDown); + bool SendCharEvent(const wchar_t ch, + const WORD scanCode, + const ::Microsoft::Terminal::Core::ControlKeyStates modifiers); + bool SendMouseEvent(const COORD viewportPos, + const unsigned int uiButton, + const ::Microsoft::Terminal::Core::ControlKeyStates states, + const short wheelDelta, + const ::Microsoft::Console::VirtualTerminal::TerminalInput::MouseButtonState state); + void UserScrollViewport(const int viewTop); +#pragma endregion + + HANDLE GetSwapChainHandle() const; + + void BlinkAttributeTick(); + void BlinkCursor(); + bool CursorOn() const; + void CursorOn(const bool isCursorOn); + + void ResumeRendering(); + bool IsVtMouseModeEnabled() const; + til::point CursorPosition() const; + + void LeftClickOnTerminal(const til::point terminalPosition, + const int numberOfClicks, + const bool altEnabled, + const bool shiftEnabled, + const bool isOnOriginalPosition, + bool& selectionNeedsToBeCopied); + + TYPED_EVENT(HoveredHyperlinkChanged, IInspectable, IInspectable); + + TYPED_EVENT(SwapChainChanged, IInspectable, IInspectable); + TYPED_EVENT(RendererWarning, IInspectable, TerminalControl::RendererWarningArgs); + }; +} + +namespace winrt::Microsoft::Terminal::TerminalControl::factory_implementation +{ + BASIC_FACTORY(ControlCore); +} diff --git a/src/cascadia/TerminalControl/ControlCore.idl b/src/cascadia/TerminalControl/ControlCore.idl new file mode 100644 index 00000000000..256506b174b --- /dev/null +++ b/src/cascadia/TerminalControl/ControlCore.idl @@ -0,0 +1,16 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +import "ICoreState.idl"; +import "IControlSettings.idl"; +import "EventArgs.idl"; + +namespace Microsoft.Terminal.TerminalControl +{ + + [default_interface] runtimeclass ControlCore : ICoreState + { + ControlCore(Microsoft.Terminal.TerminalControl.IControlSettings settings, + Microsoft.Terminal.TerminalConnection.ITerminalConnection connection); + }; +} diff --git a/src/cascadia/TerminalControl/EventArgs.cpp b/src/cascadia/TerminalControl/EventArgs.cpp new file mode 100644 index 00000000000..3586f0314a9 --- /dev/null +++ b/src/cascadia/TerminalControl/EventArgs.cpp @@ -0,0 +1,12 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +#include "pch.h" +#include "EventArgs.h" +#include "TitleChangedEventArgs.g.cpp" +#include "CopyToClipboardEventArgs.g.cpp" +#include "PasteFromClipboardEventArgs.g.cpp" +#include "OpenHyperlinkEventArgs.g.cpp" +#include "NoticeEventArgs.g.cpp" +#include "ScrollPositionChangedArgs.g.cpp" +#include "RendererWarningArgs.g.cpp" diff --git a/src/cascadia/TerminalControl/EventArgs.h b/src/cascadia/TerminalControl/EventArgs.h new file mode 100644 index 00000000000..b3c4051152d --- /dev/null +++ b/src/cascadia/TerminalControl/EventArgs.h @@ -0,0 +1,129 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +#pragma once + +#include "TitleChangedEventArgs.g.h" +#include "CopyToClipboardEventArgs.g.h" +#include "PasteFromClipboardEventArgs.g.h" +#include "OpenHyperlinkEventArgs.g.h" +#include "NoticeEventArgs.g.h" +#include "ScrollPositionChangedArgs.g.h" +#include "RendererWarningArgs.g.h" +#include "cppwinrt_utils.h" + +namespace winrt::Microsoft::Terminal::TerminalControl::implementation +{ + struct TitleChangedEventArgs : + public TitleChangedEventArgsT + { + public: + TitleChangedEventArgs(hstring title) : + _Title(title) {} + + WINRT_PROPERTY(hstring, Title); + }; + + struct CopyToClipboardEventArgs : + public CopyToClipboardEventArgsT + { + public: + CopyToClipboardEventArgs(hstring text) : + _text(text), + _html(), + _rtf(), + _formats(static_cast(0)) {} + + CopyToClipboardEventArgs(hstring text, hstring html, hstring rtf, Windows::Foundation::IReference formats) : + _text(text), + _html(html), + _rtf(rtf), + _formats(formats) {} + + hstring Text() { return _text; }; + hstring Html() { return _html; }; + hstring Rtf() { return _rtf; }; + Windows::Foundation::IReference Formats() { return _formats; }; + + private: + hstring _text; + hstring _html; + hstring _rtf; + Windows::Foundation::IReference _formats; + }; + + struct PasteFromClipboardEventArgs : + public PasteFromClipboardEventArgsT + { + public: + PasteFromClipboardEventArgs(std::function clipboardDataHandler) : + m_clipboardDataHandler(clipboardDataHandler) {} + + void HandleClipboardData(hstring value) + { + m_clipboardDataHandler(static_cast(value)); + }; + + private: + std::function m_clipboardDataHandler; + }; + + struct OpenHyperlinkEventArgs : + public OpenHyperlinkEventArgsT + { + public: + OpenHyperlinkEventArgs(hstring uri) : + _uri(uri) {} + + hstring Uri() { return _uri; }; + + private: + hstring _uri; + }; + + struct NoticeEventArgs : + public NoticeEventArgsT + { + public: + NoticeEventArgs(const NoticeLevel level, const hstring& message) : + _level(level), + _message(message) {} + + NoticeLevel Level() { return _level; }; + hstring Message() { return _message; }; + + private: + const NoticeLevel _level; + const hstring _message; + }; + + struct ScrollPositionChangedArgs : + public ScrollPositionChangedArgsT + { + public: + ScrollPositionChangedArgs(const int viewTop, + const int viewHeight, + const int bufferSize) : + _ViewTop(viewTop), + _ViewHeight(viewHeight), + _BufferSize(bufferSize) + { + } + + WINRT_PROPERTY(int32_t, ViewTop); + WINRT_PROPERTY(int32_t, ViewHeight); + WINRT_PROPERTY(int32_t, BufferSize); + }; + + struct RendererWarningArgs : + public RendererWarningArgsT + { + public: + RendererWarningArgs(const uint64_t hr) : + _Result(hr) + { + } + + WINRT_PROPERTY(uint64_t, Result); + }; +} diff --git a/src/cascadia/TerminalControl/EventArgs.idl b/src/cascadia/TerminalControl/EventArgs.idl new file mode 100644 index 00000000000..e71c1e2a9aa --- /dev/null +++ b/src/cascadia/TerminalControl/EventArgs.idl @@ -0,0 +1,65 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +namespace Microsoft.Terminal.TerminalControl +{ + delegate void FontSizeChangedEventArgs(Int32 width, Int32 height, Boolean isInitialChange); + delegate void ScrollPositionChangedEventArgs(Int32 viewTop, Int32 viewHeight, Int32 bufferLength); + + [flags] + enum CopyFormat + { + HTML = 0x1, + RTF = 0x2, + All = 0xffffffff + }; + + runtimeclass CopyToClipboardEventArgs + { + String Text { get; }; + String Html { get; }; + String Rtf { get; }; + Windows.Foundation.IReference Formats { get; }; + } + + runtimeclass TitleChangedEventArgs + { + String Title; + } + + runtimeclass PasteFromClipboardEventArgs + { + void HandleClipboardData(String data); + } + + runtimeclass OpenHyperlinkEventArgs + { + String Uri { get; }; + } + + enum NoticeLevel + { + Debug = 10, + Info = 20, + Warning = 30, + Error = 40, + }; + + runtimeclass NoticeEventArgs + { + NoticeLevel Level { get; }; + String Message { get; }; + } + + runtimeclass ScrollPositionChangedArgs + { + Int32 ViewTop { get; }; + Int32 ViewHeight { get; }; + Int32 BufferSize { get; }; + } + + runtimeclass RendererWarningArgs + { + UInt64 Result { get; }; + } +} diff --git a/src/cascadia/TerminalControl/ICoreState.idl b/src/cascadia/TerminalControl/ICoreState.idl new file mode 100644 index 00000000000..8c066d79604 --- /dev/null +++ b/src/cascadia/TerminalControl/ICoreState.idl @@ -0,0 +1,23 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +namespace Microsoft.Terminal.TerminalControl +{ + // These are properties of the TerminalCore that should be queryable by the + // rest of the app. + interface ICoreState + { + String Title { get; }; + UInt64 TaskbarState { get; }; + UInt64 TaskbarProgress { get; }; + + String WorkingDirectory { get; }; + + Windows.Foundation.IReference TabColor { get; }; + + Int32 ScrollOffset { get; }; + Int32 ViewHeight { get; }; + + Microsoft.Terminal.TerminalConnection.ConnectionState ConnectionState { get; }; + }; +} diff --git a/src/cascadia/TerminalControl/IDirectKeyListener.idl b/src/cascadia/TerminalControl/IDirectKeyListener.idl new file mode 100644 index 00000000000..64119430665 --- /dev/null +++ b/src/cascadia/TerminalControl/IDirectKeyListener.idl @@ -0,0 +1,14 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +namespace Microsoft.Terminal.TerminalControl +{ + // C++/winrt makes it difficult to share this idl between two projects, + // Instead, we just pin the uuid and include it in both TermControl and App + // If you update this one, please update TerminalApp\IDirectKeyListener.idl. + // If you change this interface, please update the guid. + // If you press F7 or Alt and get a runtime error, go make sure both copies are the same. + [uuid("0ddf4edc-3fda-4dee-97ca-a417ee3dd510")] interface IDirectKeyListener { + Boolean OnDirectKeyEvent(UInt32 vkey, UInt8 scanCode, Boolean down); + }; +} diff --git a/src/cascadia/TerminalControl/TermControl.cpp b/src/cascadia/TerminalControl/TermControl.cpp index 136c9122102..bf3edc8e47d 100644 --- a/src/cascadia/TerminalControl/TermControl.cpp +++ b/src/cascadia/TerminalControl/TermControl.cpp @@ -62,8 +62,8 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation return initialized; } - TermControl::TermControl(IControlSettings settings, TerminalConnection::ITerminalConnection connection) : - _connection{ connection }, + TermControl::TermControl(IControlSettings settings, + TerminalConnection::ITerminalConnection connection) : _initializedTerminal{ false }, _settings{ settings }, _closing{ false }, @@ -72,65 +72,22 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation _autoScrollingPointerPoint{ std::nullopt }, _autoScrollTimer{}, _lastAutoScrollUpdateTime{ std::nullopt }, - _desiredFont{ DEFAULT_FONT_FACE, 0, DEFAULT_FONT_WEIGHT, { 0, DEFAULT_FONT_SIZE }, CP_UTF8 }, - _actualFont{ DEFAULT_FONT_FACE, 0, DEFAULT_FONT_WEIGHT, { 0, DEFAULT_FONT_SIZE }, CP_UTF8, false }, _touchAnchor{ std::nullopt }, _cursorTimer{}, _blinkTimer{}, _lastMouseClickTimestamp{}, _lastMouseClickPos{}, - _lastMouseClickPosNoSelection{}, _selectionNeedsToBeCopied{ false }, _searchBox{ nullptr } { _EnsureStaticInitialization(); InitializeComponent(); - _terminal = std::make_unique<::Microsoft::Terminal::Core::Terminal>(); + _core = winrt::make_self(settings, connection); - // GH#8969: pre-seed working directory to prevent potential races - _terminal->SetWorkingDirectory(_settings.StartingDirectory()); - - auto pfnWarningBell = std::bind(&TermControl::_TerminalWarningBell, this); - _terminal->SetWarningBellCallback(pfnWarningBell); - - auto pfnTitleChanged = std::bind(&TermControl::_TerminalTitleChanged, this, std::placeholders::_1); - _terminal->SetTitleChangedCallback(pfnTitleChanged); - - auto pfnTabColorChanged = std::bind(&TermControl::_TerminalTabColorChanged, this, std::placeholders::_1); - _terminal->SetTabColorChangedCallback(pfnTabColorChanged); - - auto pfnBackgroundColorChanged = std::bind(&TermControl::_BackgroundColorChanged, this, std::placeholders::_1); - _terminal->SetBackgroundCallback(pfnBackgroundColorChanged); - - auto pfnScrollPositionChanged = std::bind(&TermControl::_TerminalScrollPositionChanged, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3); - _terminal->SetScrollPositionChangedCallback(pfnScrollPositionChanged); - - auto pfnTerminalCursorPositionChanged = std::bind(&TermControl::_TerminalCursorPositionChanged, this); - _terminal->SetCursorPositionChangedCallback(pfnTerminalCursorPositionChanged); - - auto pfnCopyToClipboard = std::bind(&TermControl::_CopyToClipboard, this, std::placeholders::_1); - _terminal->SetCopyToClipboardCallback(pfnCopyToClipboard); - - _terminal->TaskbarProgressChangedCallback([&]() { TermControl::TaskbarProgressChanged(); }); - - // This event is explicitly revoked in the destructor: does not need weak_ref - auto onReceiveOutputFn = [this](const hstring str) { - _terminal->Write(str); - _updatePatternLocations->Run(); - }; - _connectionOutputEventToken = _connection.TerminalOutput(onReceiveOutputFn); - - _terminal->SetWriteInputCallback([this](std::wstring& wstr) { - _SendInputToConnection(wstr); - }); - - _terminal->UpdateSettings(settings); - - // Subscribe to the connection's disconnected event and call our connection closed handlers. - _connectionStateChangedRevoker = _connection.StateChanged(winrt::auto_revoke, [this](auto&& /*s*/, auto&& /*v*/) { - _ConnectionStateChangedHandlers(*this, nullptr); - }); + _core->BackgroundColorChanged({ get_weak(), &TermControl::_BackgroundColorChangedHandler }); + _core->ScrollPositionChanged({ get_weak(), &TermControl::_ScrollPositionChanged }); + _core->CursorPositionChanged({ get_weak(), &TermControl::_CursorPositionChanged }); // Initialize the terminal only once the swapchainpanel is loaded - that // way, we'll be able to query the real pixel size it got on layout @@ -161,7 +118,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation [weakThis = get_weak()]() { if (auto control{ weakThis.get() }) { - control->UpdatePatternLocations(); + control->_core->UpdatePatternLocations(); } }, UpdatePatternLocationsInterval, @@ -194,6 +151,8 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation _autoScrollTimer.Tick({ this, &TermControl::_UpdateAutoScroll }); _ApplyUISettings(_settings); + + _core->HoveredHyperlinkChanged({ get_weak(), &TermControl::_hoveredHyperlinkChanged }); } // Method Description: @@ -211,15 +170,15 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation // If a text is selected inside terminal, use it to populate the search box. // If the search box already contains a value, it will be overridden. - if (_terminal->IsSelectionActive()) + if (_core->HasSelection()) { // Currently we populate the search box only if a single line is selected. // Empirically, multi-line selection works as well on sample scenarios, // but since code paths differ, extra work is required to ensure correctness. - const auto bufferData = _terminal->RetrieveSelectedTextFromBuffer(true); - if (bufferData.text.size() == 1) + auto bufferText = _core->SelectedText(true); + if (bufferText.size() == 1) { - const auto selectedLine{ til::at(bufferData.text, 0) }; + const auto selectedLine{ til::at(bufferText, 0) }; _searchBox->PopulateTextbox(selectedLine.data()); } } @@ -231,50 +190,35 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation void TermControl::SearchMatch(const bool goForward) { + if (_closing) + { + return; + } if (!_searchBox) { CreateSearchBoxControl(); } else { - _Search(_searchBox->TextBox().Text(), goForward, false); + _core->Search(_searchBox->TextBox().Text(), goForward, false); } } - // Method Description: - // - Search text in text buffer. This is triggered if the user click - // search button or press enter. - // Arguments: - // - text: the text to search - // - goForward: boolean that represents if the current search direction is forward - // - caseSensitive: boolean that represents if the current search is case sensitive - // Return Value: - // - + // // Method Description: + // // - Search text in text buffer. This is triggered if the user click + // // search button or press enter. + // // Arguments: + // // - text: the text to search + // // - goForward: boolean that represents if the current search direction is forward + // // - caseSensitive: boolean that represents if the current search is case sensitive + // // Return Value: + // // - void TermControl::_Search(const winrt::hstring& text, const bool goForward, const bool caseSensitive) { - if (text.size() == 0 || _closing) - { - return; - } - - const Search::Direction direction = goForward ? - Search::Direction::Forward : - Search::Direction::Backward; - - const Search::Sensitivity sensitivity = caseSensitive ? - Search::Sensitivity::CaseSensitive : - Search::Sensitivity::CaseInsensitive; - - Search search(*GetUiaData(), text.c_str(), direction, sensitivity); - auto lock = _terminal->LockForWriting(); - if (search.FindNext()) - { - _terminal->SetBlockSelection(false); - search.Select(); - _renderer->TriggerSelection(); - } + // !!TODO!! This is bound in XAML, and that seems a little silly now + _core->Search(text, goForward, caseSensitive); } // Method Description: @@ -311,51 +255,10 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation return; } - auto lock = _terminal->LockForWriting(); + _core->UpdateSettings(_settings); // Update our control settings _ApplyUISettings(_settings); - - // Update the terminal core with its new Core settings - _terminal->UpdateSettings(_settings); - - if (!_initializedTerminal) - { - // If we haven't initialized, there's no point in continuing. - // Initialization will handle the renderer settings. - return; - } - - // Update DxEngine settings under the lock - _renderEngine->SetSelectionBackground(_settings.SelectionBackground()); - - _renderEngine->SetRetroTerminalEffect(_settings.RetroTerminalEffect()); - _renderEngine->SetPixelShaderPath(_settings.PixelShaderPath()); - _renderEngine->SetForceFullRepaintRendering(_settings.ForceFullRepaintRendering()); - _renderEngine->SetSoftwareRendering(_settings.SoftwareRendering()); - - switch (_settings.AntialiasingMode()) - { - case TextAntialiasingMode::Cleartype: - _renderEngine->SetAntialiasingMode(D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE); - break; - case TextAntialiasingMode::Aliased: - _renderEngine->SetAntialiasingMode(D2D1_TEXT_ANTIALIAS_MODE_ALIASED); - break; - case TextAntialiasingMode::Grayscale: - default: - _renderEngine->SetAntialiasingMode(D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE); - break; - } - - // Refresh our font with the renderer - const auto actualFontOldSize = _actualFont.GetSize(); - _UpdateFont(); - const auto actualFontNewSize = _actualFont.GetSize(); - if (actualFontNewSize != actualFontOldSize) - { - _RefreshSizeUnderLock(); - } } // Method Description: @@ -385,30 +288,12 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation // - void TermControl::SendInput(const winrt::hstring& wstr) { - _SendInputToConnection(wstr); + _core->SendInput(wstr); } void TermControl::ToggleShaderEffects() { - auto lock = _terminal->LockForWriting(); - // Originally, this action could be used to enable the retro effects - // even when they're set to `false` in the settings. If the user didn't - // specify a custom pixel shader, manually enable the legacy retro - // effect first. This will ensure that a toggle off->on will still work, - // even if they currently have retro effect off. - if (_settings.PixelShaderPath().empty() && !_renderEngine->GetRetroTerminalEffect()) - { - // SetRetroTerminalEffect to true will enable the effect. In this - // case, the shader effect will already be disabled (because neither - // a pixel shader nor the retro effects were originally requested). - // So we _don't_ want to toggle it again below, because that would - // toggle it back off. - _renderEngine->SetRetroTerminalEffect(true); - } - else - { - _renderEngine->ToggleShaderEffects(); - } + _core->ToggleShaderEffects(); } // Method Description: @@ -428,25 +313,12 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation _InitializeBackgroundBrush(); COLORREF bg = newSettings.DefaultBackground(); - _BackgroundColorChanged(bg); + _changeBackgroundColor(bg); // Apply padding as swapChainPanel's margin auto newMargin = _ParseThicknessFromPadding(newSettings.Padding()); SwapChainPanel().Margin(newMargin); - // Initialize our font information. - const auto fontFace = newSettings.FontFace(); - const short fontHeight = gsl::narrow_cast(newSettings.FontSize()); - const auto fontWeight = newSettings.FontWeight(); - // The font width doesn't terribly matter, we'll only be using the - // height to look it up - // The other params here also largely don't matter. - // The family is only used to determine if the font is truetype or - // not, but DX doesn't use that info at all. - // The Codepage is additionally not actually used by the DX engine at all. - _actualFont = { fontFace, 0, fontWeight.Weight, { 0, fontHeight }, CP_UTF8, false }; - _desiredFont = { _actualFont }; - // set TSF Foreground Media::SolidColorBrush foregroundBrush{}; foregroundBrush.Color(static_cast(newSettings.DefaultForeground())); @@ -523,10 +395,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation } // GH#5098: Inform the engine of the new opacity of the default text background. - if (_renderEngine) - { - _renderEngine->SetDefaultTextBackgroundOpacity(::base::saturated_cast(_settings.TintOpacity())); - } + _core->SetBackgroundOpacity(::base::saturated_cast(_settings.TintOpacity())); } else { @@ -534,10 +403,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation RootGrid().Background(solidColor); // GH#5098: Inform the engine of the new opacity of the default text background. - if (_renderEngine) - { - _renderEngine->SetDefaultTextBackgroundOpacity(1.0f); - } + _core->SetBackgroundOpacity(1.0f); } if (!_settings.BackgroundImage().empty()) @@ -579,24 +445,28 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation // - color: The background color to use as a uint32 (aka DWORD COLORREF) // Return Value: // - - winrt::fire_and_forget TermControl::_BackgroundColorChanged(const COLORREF color) + void TermControl::_BackgroundColorChangedHandler(const IInspectable& /*sender*/, + const IInspectable& /*args*/) { - til::color newBgColor{ color }; + til::color newBgColor{ _core->BackgroundColor() }; + _changeBackgroundColor(newBgColor); + } + winrt::fire_and_forget TermControl::_changeBackgroundColor(til::color bg) + { auto weakThis{ get_weak() }; - co_await winrt::resume_foreground(Dispatcher()); if (auto control{ weakThis.get() }) { if (auto acrylic = RootGrid().Background().try_as()) { - acrylic.FallbackColor(newBgColor); - acrylic.TintColor(newBgColor); + acrylic.FallbackColor(bg); + acrylic.TintColor(bg); } else if (auto solidColor = RootGrid().Background().try_as()) { - solidColor.Color(newBgColor); + solidColor.Color(bg); } } } @@ -619,10 +489,10 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation { // create a custom automation peer with this code pattern: // (https://docs.microsoft.com/en-us/windows/uwp/design/accessibility/custom-automation-peers) - auto autoPeer = winrt::make_self(this); + auto autoPeer = winrt::make_self(this); _uiaEngine = std::make_unique<::Microsoft::Console::Render::UiaEngine>(autoPeer.get()); - _renderer->AddRenderEngine(_uiaEngine.get()); + _core->_renderer->AddRenderEngine(_uiaEngine.get()); return *autoPeer; } return nullptr; @@ -635,12 +505,14 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation ::Microsoft::Console::Types::IUiaData* TermControl::GetUiaData() const { - return _terminal.get(); + return _core->GetUiaData(); } - const FontInfo TermControl::GetActualFont() const + // This is needed for TermControlAutomationPeer. We probably could find a + // clever way around asking the core for this. + til::point TermControl::GetFontSize() const { - return _actualFont; + return _core->GetFont().GetSize(); } const Windows::UI::Xaml::Thickness TermControl::GetPadding() @@ -650,22 +522,22 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation TerminalConnection::ConnectionState TermControl::ConnectionState() const { - return _connection.State(); + return _core->ConnectionState(); } - winrt::fire_and_forget TermControl::RenderEngineSwapChainChanged() + winrt::fire_and_forget TermControl::RenderEngineSwapChainChanged(const IInspectable& /*sender*/, const IInspectable& /*args*/) { // This event is only registered during terminal initialization, // so we don't need to check _initializedTerminal. // We also don't lock for things that come back from the renderer. - auto chain = _renderEngine->GetSwapChain(); + auto chainHandle = _core->GetSwapChainHandle(); auto weakThis{ get_weak() }; co_await winrt::resume_foreground(Dispatcher()); if (auto control{ weakThis.get() }) { - _AttachDxgiSwapChainToXaml(chain.Get()); + _AttachDxgiSwapChainToXaml(chainHandle); } } @@ -679,8 +551,11 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation // - hr: an HRESULT describing the warning // Return Value: // - - winrt::fire_and_forget TermControl::_RendererWarning(const HRESULT hr) + winrt::fire_and_forget TermControl::_RendererWarning(const IInspectable& /*sender*/, + const TerminalControl::RendererWarningArgs& args) { + const HRESULT hr = static_cast(args.Result()); + auto weakThis{ get_weak() }; co_await winrt::resume_foreground(Dispatcher()); @@ -708,187 +583,95 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation } } - void TermControl::_AttachDxgiSwapChainToXaml(IDXGISwapChain1* swapChain) + void TermControl::_AttachDxgiSwapChainToXaml(HANDLE swapChainHandle) { - auto nativePanel = SwapChainPanel().as(); - nativePanel->SetSwapChain(swapChain); + auto nativePanel = SwapChainPanel().as(); + nativePanel->SetSwapChainHandle(swapChainHandle); } bool TermControl::_InitializeTerminal() { - { // scope for terminalLock - auto terminalLock = _terminal->LockForWriting(); - - if (_initializedTerminal) - { - return false; - } - - const auto actualWidth = SwapChainPanel().ActualWidth(); - const auto actualHeight = SwapChainPanel().ActualHeight(); - - const auto windowWidth = actualWidth * SwapChainPanel().CompositionScaleX(); // Width() and Height() are NaN? - const auto windowHeight = actualHeight * SwapChainPanel().CompositionScaleY(); - - if (windowWidth == 0 || windowHeight == 0) - { - return false; - } - - // First create the render thread. - // Then stash a local pointer to the render thread so we can initialize it and enable it - // to paint itself *after* we hand off its ownership to the renderer. - // We split up construction and initialization of the render thread object this way - // because the renderer and render thread have circular references to each other. - auto renderThread = std::make_unique<::Microsoft::Console::Render::RenderThread>(); - auto* const localPointerToThread = renderThread.get(); - - // Now create the renderer and initialize the render thread. - _renderer = std::make_unique<::Microsoft::Console::Render::Renderer>(_terminal.get(), nullptr, 0, std::move(renderThread)); - ::Microsoft::Console::Render::IRenderTarget& renderTarget = *_renderer; - - _renderer->SetRendererEnteredErrorStateCallback([weakThis = get_weak()]() { - if (auto strongThis{ weakThis.get() }) - { - strongThis->_RendererEnteredErrorState(); - } - }); - - THROW_IF_FAILED(localPointerToThread->Initialize(_renderer.get())); - - // Set up the DX Engine - auto dxEngine = std::make_unique<::Microsoft::Console::Render::DxEngine>(); - _renderer->AddRenderEngine(dxEngine.get()); - - // Initialize our font with the renderer - // We don't have to care about DPI. We'll get a change message immediately if it's not 96 - // and react accordingly. - _UpdateFont(true); - - const COORD windowSize{ static_cast(windowWidth), static_cast(windowHeight) }; - - // Fist set up the dx engine with the window size in pixels. - // Then, using the font, get the number of characters that can fit. - // Resize our terminal connection to match that size, and initialize the terminal with that size. - const auto viewInPixels = Viewport::FromDimensions({ 0, 0 }, windowSize); - LOG_IF_FAILED(dxEngine->SetWindowSize({ viewInPixels.Width(), viewInPixels.Height() })); - - // Update DxEngine's SelectionBackground - dxEngine->SetSelectionBackground(_settings.SelectionBackground()); - - const auto vp = dxEngine->GetViewportInCharacters(viewInPixels); - const auto width = vp.Width(); - const auto height = vp.Height(); - _connection.Resize(height, width); - - // Override the default width and height to match the size of the swapChainPanel - _settings.InitialCols(width); - _settings.InitialRows(height); - - _terminal->CreateFromSettings(_settings, renderTarget); - - // IMPORTANT! Set this callback up sooner than later. If we do it - // after Enable, then it'll be possible to paint the frame once - // _before_ the warning handler is set up, and then warnings from - // the first paint will be ignored! - dxEngine->SetWarningCallback(std::bind(&TermControl::_RendererWarning, this, std::placeholders::_1)); - - dxEngine->SetRetroTerminalEffect(_settings.RetroTerminalEffect()); - dxEngine->SetPixelShaderPath(_settings.PixelShaderPath()); - dxEngine->SetForceFullRepaintRendering(_settings.ForceFullRepaintRendering()); - dxEngine->SetSoftwareRendering(_settings.SoftwareRendering()); - - // Update DxEngine's AntialiasingMode - switch (_settings.AntialiasingMode()) - { - case TextAntialiasingMode::Cleartype: - dxEngine->SetAntialiasingMode(D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE); - break; - case TextAntialiasingMode::Aliased: - dxEngine->SetAntialiasingMode(D2D1_TEXT_ANTIALIAS_MODE_ALIASED); - break; - case TextAntialiasingMode::Grayscale: - default: - dxEngine->SetAntialiasingMode(D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE); - break; - } - - // GH#5098: Inform the engine of the opacity of the default text background. - if (_settings.UseAcrylic()) - { - dxEngine->SetDefaultTextBackgroundOpacity(::base::saturated_cast(_settings.TintOpacity())); - } + if (_initializedTerminal) + { + return false; + } - THROW_IF_FAILED(dxEngine->Enable()); - _renderEngine = std::move(dxEngine); + // IMPORTANT! Set this callback up sooner than later. If we do it + // after Enable, then it'll be possible to paint the frame once + // _before_ the warning handler is set up, and then warnings from + // the first paint will be ignored! + _core->RendererWarning({ get_weak(), &TermControl::_RendererWarning }); - _AttachDxgiSwapChainToXaml(_renderEngine->GetSwapChain().Get()); + _core->InitializeTerminal(SwapChainPanel().ActualWidth(), + SwapChainPanel().ActualHeight(), + SwapChainPanel().CompositionScaleX(), + SwapChainPanel().CompositionScaleY()); - // Tell the DX Engine to notify us when the swap chain changes. - // We do this after we initially set the swapchain so as to avoid unnecessary callbacks (and locking problems) - _renderEngine->SetCallback(std::bind(&TermControl::RenderEngineSwapChainChanged, this)); + _AttachDxgiSwapChainToXaml(_core->GetSwapChainHandle()); - auto bottom = _terminal->GetViewport().BottomExclusive(); - auto bufferHeight = bottom; + // Tell the DX Engine to notify us when the swap chain changes. We do + // this after we initially set the swapchain so as to avoid unnecessary + // callbacks (and locking problems) + _core->SwapChainChanged({ get_weak(), &TermControl::RenderEngineSwapChainChanged }); - ScrollBar().Maximum(bufferHeight - bufferHeight); - ScrollBar().Minimum(0); - ScrollBar().Value(0); - ScrollBar().ViewportSize(bufferHeight); - ScrollBar().LargeChange(std::max(bufferHeight - 1, 0)); // scroll one "screenful" at a time when the scroll bar is clicked + auto bufferHeight = _core->BufferHeight(); - localPointerToThread->EnablePainting(); + ScrollBar().Maximum(bufferHeight - bufferHeight); + ScrollBar().Minimum(0); + ScrollBar().Value(0); + ScrollBar().ViewportSize(bufferHeight); + ScrollBar().LargeChange(std::max(bufferHeight - 1, 0)); // scroll one "screenful" at a time when the scroll bar is clicked - // Set up blinking cursor - int blinkTime = GetCaretBlinkTime(); - if (blinkTime != INFINITE) - { - // Create a timer - DispatcherTimer cursorTimer; - cursorTimer.Interval(std::chrono::milliseconds(blinkTime)); - cursorTimer.Tick({ get_weak(), &TermControl::_CursorTimerTick }); - cursorTimer.Start(); - _cursorTimer.emplace(std::move(cursorTimer)); - } - else - { - // The user has disabled cursor blinking - _cursorTimer = std::nullopt; - } + // Mild worry that doing EnablePainting in Core::InitializeTerminal, + // before we _AttachDxgiSwapChainToXaml will break + // + // localPointerToThread->EnablePainting(); - // Set up blinking attributes - BOOL animationsEnabled = TRUE; - SystemParametersInfoW(SPI_GETCLIENTAREAANIMATION, 0, &animationsEnabled, 0); - if (animationsEnabled && blinkTime != INFINITE) - { - // Create a timer - DispatcherTimer blinkTimer; - blinkTimer.Interval(std::chrono::milliseconds(blinkTime)); - blinkTimer.Tick({ get_weak(), &TermControl::_BlinkTimerTick }); - blinkTimer.Start(); - _blinkTimer.emplace(std::move(blinkTimer)); - } - else - { - // The user has disabled blinking - _blinkTimer = std::nullopt; - } + // Set up blinking cursor + int blinkTime = GetCaretBlinkTime(); + if (blinkTime != INFINITE) + { + // Create a timer + DispatcherTimer cursorTimer; + cursorTimer.Interval(std::chrono::milliseconds(blinkTime)); + cursorTimer.Tick({ get_weak(), &TermControl::_CursorTimerTick }); + cursorTimer.Start(); + _cursorTimer.emplace(std::move(cursorTimer)); + } + else + { + // The user has disabled cursor blinking + _cursorTimer = std::nullopt; + } - // import value from WinUser (convert from milli-seconds to micro-seconds) - _multiClickTimer = GetDoubleClickTime() * 1000; + // Set up blinking attributes + BOOL animationsEnabled = TRUE; + SystemParametersInfoW(SPI_GETCLIENTAREAANIMATION, 0, &animationsEnabled, 0); + if (animationsEnabled && blinkTime != INFINITE) + { + // Create a timer + DispatcherTimer blinkTimer; + blinkTimer.Interval(std::chrono::milliseconds(blinkTime)); + blinkTimer.Tick({ get_weak(), &TermControl::_BlinkTimerTick }); + blinkTimer.Start(); + _blinkTimer.emplace(std::move(blinkTimer)); + } + else + { + // The user has disabled blinking + _blinkTimer = std::nullopt; + } - // Focus the control here. If we do it during control initialization, then - // focus won't actually get passed to us. I believe this is because - // we're not technically a part of the UI tree yet, so focusing us - // becomes a no-op. - this->Focus(FocusState::Programmatic); + // import value from WinUser (convert from milli-seconds to micro-seconds) + _multiClickTimer = GetDoubleClickTime() * 1000; - _initializedTerminal = true; - } // scope for TerminalLock + // Focus the control here. If we do it during control initialization, then + // focus won't actually get passed to us. I believe this is because + // we're not technically a part of the UI tree yet, so focusing us + // becomes a no-op. + this->Focus(FocusState::Programmatic); - // Start the connection outside of lock, because it could - // start writing output immediately. - _connection.Start(); + _initializedTerminal = true; // Likewise, run the event handlers outside of lock (they could // be reentrant) @@ -913,7 +696,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation { modifiers |= ControlKeyStates::EnhancedKey; } - const bool handled = _terminal->SendCharEvent(ch, scanCode, modifiers); + const bool handled = _core->SendCharEvent(ch, scanCode, modifiers); e.Handled(handled); } @@ -1130,39 +913,12 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation const ControlKeyStates modifiers, const bool keyDown) { - // When there is a selection active, escape should clear it and NOT flow through - // to the terminal. With any other keypress, it should clear the selection AND - // flow through to the terminal. - // GH#6423 - don't dismiss selection if the key that was pressed was a - // modifier key. We'll wait for a real keystroke to dismiss the - // GH #7395 - don't dismiss selection when taking PrintScreen - // selection. - // GH#8522, GH#3758 - Only dismiss the selection on key _down_. If we - // dismiss on key up, then there's chance that we'll immediately dismiss - // a selection created by an action bound to a keydown. - if (_terminal->IsSelectionActive() && - !KeyEvent::IsModifierKey(vkey) && - vkey != VK_SNAPSHOT && - keyDown) - { - const CoreWindow window = CoreWindow::GetForCurrentThread(); - const auto leftWinKeyState = window.GetKeyState(VirtualKey::LeftWindows); - const auto rightWinKeyState = window.GetKeyState(VirtualKey::RightWindows); - const auto isLeftWinKeyDown = WI_IsFlagSet(leftWinKeyState, CoreVirtualKeyStates::Down); - const auto isRightWinKeyDown = WI_IsFlagSet(rightWinKeyState, CoreVirtualKeyStates::Down); - - // GH#8791 - don't dismiss selection if Windows key was also pressed as a key-combination. - if (!isLeftWinKeyDown && !isRightWinKeyDown) - { - _terminal->ClearSelection(); - _renderer->TriggerSelection(); - } - - if (vkey == VK_ESCAPE) - { - return true; - } - } + const CoreWindow window = CoreWindow::GetForCurrentThread(); + const auto leftWinKeyState = window.GetKeyState(VirtualKey::LeftWindows); + const auto rightWinKeyState = window.GetKeyState(VirtualKey::RightWindows); + const auto isLeftWinKeyDown = WI_IsFlagSet(leftWinKeyState, CoreVirtualKeyStates::Down); + const auto isRightWinKeyDown = WI_IsFlagSet(rightWinKeyState, CoreVirtualKeyStates::Down); + const bool eitherWinPressed = isLeftWinKeyDown || isRightWinKeyDown; if (vkey == VK_ESCAPE || vkey == VK_RETURN) @@ -1173,13 +929,19 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation // If the terminal translated the key, mark the event as handled. // This will prevent the system from trying to get the character out // of it and sending us a CharacterReceived event. - const auto handled = vkey ? _terminal->SendKeyEvent(vkey, scanCode, modifiers, keyDown) : true; + const auto handled = vkey ? + _core->TrySendKeyEvent(vkey, + scanCode, + modifiers, + eitherWinPressed, + keyDown) : + true; if (_cursorTimer.has_value()) { // Manually show the cursor when a key is pressed. Restarting // the timer prevents flickering. - _terminal->SetCursorOn(true); + _core->CursorOn(true); _cursorTimer.value().Start(); } @@ -1244,8 +1006,10 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation } const auto modifiers = _GetPressedModifierKeys(); - const TerminalInput::MouseButtonState state{ props.IsLeftButtonPressed(), props.IsMiddleButtonPressed(), props.IsRightButtonPressed() }; - return _terminal->SendMouseEvent(terminalPosition, uiButton, modifiers, sWheelDelta, state); + const TerminalInput::MouseButtonState state{ props.IsLeftButtonPressed(), + props.IsMiddleButtonPressed(), + props.IsRightButtonPressed() }; + return _core->SendMouseEvent(terminalPosition, uiButton, modifiers, sWheelDelta, state); } // Method Description: @@ -1254,10 +1018,6 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation // - point: the PointerPoint object representing a mouse event from our XAML input handler bool TermControl::_CanSendVTMouseInput() { - if (!_terminal) - { - return false; - } // If the user is holding down Shift, suppress mouse events // TODO GH#4875: disable/customize this functionality const auto modifiers = _GetPressedModifierKeys(); @@ -1265,7 +1025,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation { return false; } - return _terminal->IsTrackingMouseInput(); + return _core->IsVtMouseModeEnabled(); } // Method Description: @@ -1317,14 +1077,8 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation if (point.Properties().IsLeftButtonPressed()) { - auto lock = _terminal->LockForWriting(); - const auto cursorPosition = point.Position(); const auto terminalPosition = _GetTerminalPosition(cursorPosition); - - // handle ALT key - _terminal->SetBlockSelection(altEnabled); - auto clickCount = _NumberOfClicks(cursorPosition, point.Timestamp()); // This formula enables the number of clicks to cycle properly between single-, double-, and triple-click. @@ -1332,74 +1086,41 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation const unsigned int MAX_CLICK_COUNT = 3; const auto multiClickMapper = clickCount > MAX_CLICK_COUNT ? ((clickCount + MAX_CLICK_COUNT - 1) % MAX_CLICK_COUNT) + 1 : clickCount; - ::Terminal::SelectionExpansionMode mode = ::Terminal::SelectionExpansionMode::Cell; - if (multiClickMapper == 1) - { - mode = ::Terminal::SelectionExpansionMode::Cell; - } - else if (multiClickMapper == 2) - { - mode = ::Terminal::SelectionExpansionMode::Word; - } - else if (multiClickMapper == 3) - { - mode = ::Terminal::SelectionExpansionMode::Line; - } - - if (ctrlEnabled && multiClickMapper == 1 && - !(_terminal->GetHyperlinkAtPosition(terminalPosition).empty())) + auto hyperlink = _core->GetHyperlink(terminalPosition); + if (ctrlEnabled && + multiClickMapper == 1 && + !(hyperlink.empty())) { - _HyperlinkHandler(_terminal->GetHyperlinkAtPosition(terminalPosition)); + _HyperlinkHandler(hyperlink); } else { // Update the selection appropriately // Capture the position of the first click when no selection is active - if (mode == ::Terminal::SelectionExpansionMode::Cell && !_terminal->IsSelectionActive()) + if (multiClickMapper == 1 && + !_core->HasSelection()) { _singleClickTouchdownPos = cursorPosition; _lastMouseClickPosNoSelection = cursorPosition; } + const bool isOnOriginalPosition = _lastMouseClickPosNoSelection == cursorPosition; - // We reset the active selection if one of the conditions apply: - // - shift is not held - // - GH#9384: the position is the same as of the first click starting the selection - // (we need to reset selection on double-click or triple-click, so it captures the word or the line, - // rather than extending the selection) - if (_terminal->IsSelectionActive() && (!shiftEnabled || _lastMouseClickPosNoSelection == cursorPosition)) - { - // Reset the selection - _terminal->ClearSelection(); - _selectionNeedsToBeCopied = false; // there's no selection, so there's nothing to update - } - - if (shiftEnabled) - { - if (_terminal->IsSelectionActive()) - { - // If there is a selection we extend it using the selection mode - // (expand the "end"selection point) - _terminal->SetSelectionEnd(terminalPosition, mode); - } - else - { - // If there is no selection we establish it using the selected mode - // (expand both "start" and "end" selection points) - _terminal->MultiClickSelection(terminalPosition, mode); - } - _selectionNeedsToBeCopied = true; - } + _core->LeftClickOnTerminal(terminalPosition, + multiClickMapper, + altEnabled, + shiftEnabled, + isOnOriginalPosition, + _selectionNeedsToBeCopied); _lastMouseClickTimestamp = point.Timestamp(); _lastMouseClickPos = cursorPosition; - _renderer->TriggerSelection(); } } else if (point.Properties().IsRightButtonPressed()) { // CopyOnSelect right click always pastes - if (_settings.CopyOnSelect() || !_terminal->IsSelectionActive()) + if (_settings.CopyOnSelect() || !_core->HasSelection()) { PasteTextFromClipboard(); } @@ -1456,19 +1177,17 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation if (_focused && point.Properties().IsLeftButtonPressed()) { - auto lock = _terminal->LockForWriting(); - if (_singleClickTouchdownPos) { // Figure out if the user's moved a quarter of a cell's smaller axis away from the clickdown point auto& touchdownPoint{ *_singleClickTouchdownPos }; auto distance{ std::sqrtf(std::powf(cursorPosition.X - touchdownPoint.X, 2) + std::powf(cursorPosition.Y - touchdownPoint.Y, 2)) }; - const til::size fontSize{ _actualFont.GetSize() }; + const til::size fontSize{ _core->GetFont().GetSize() }; - const auto fontSizeInDips = fontSize.scale(til::math::rounding, 1.0f / _renderEngine->GetScaling()); + const auto fontSizeInDips = fontSize.scale(til::math::rounding, 1.0f / _core->RendererScale()); if (distance >= (std::min(fontSizeInDips.width(), fontSizeInDips.height()) / 4.f)) { - _terminal->SetSelectionAnchor(_GetTerminalPosition(touchdownPoint)); + _core->SetSelectionAnchor(_GetTerminalPosition(touchdownPoint)); // stop tracking the touchdown point _singleClickTouchdownPos = std::nullopt; } @@ -1500,7 +1219,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation } } - _UpdateHoveredCell(terminalPosition); + _core->UpdateHoveredCell(terminalPosition); } else if (_focused && ptr.PointerDeviceType() == Windows::Devices::Input::PointerDeviceType::Touch && _touchAnchor) { @@ -1508,10 +1227,10 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation winrt::Windows::Foundation::Point newTouchPoint{ contactRect.X, contactRect.Y }; const auto anchor = _touchAnchor.value(); - // Our _actualFont's size is in pixels, convert to DIPs, which the + // Our actualFont's size is in pixels, convert to DIPs, which the // rest of the Points here are in. - const til::size fontSize{ _actualFont.GetSize() }; - const auto fontSizeInDips = fontSize.scale(til::math::rounding, 1.0f / _renderEngine->GetScaling()); + const til::size fontSize{ _core->GetFont().GetSize() }; + const auto fontSizeInDips = fontSize.scale(til::math::rounding, 1.0f / _core->RendererScale()); // Get the difference between the point we've dragged to and the start of the touch. const float dy = newTouchPoint.Y - anchor.Y; @@ -1605,7 +1324,9 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation const auto point = args.GetCurrentPoint(*this); const auto props = point.Properties(); - const TerminalInput::MouseButtonState state{ props.IsLeftButtonPressed(), props.IsMiddleButtonPressed(), props.IsRightButtonPressed() }; + const TerminalInput::MouseButtonState state{ props.IsLeftButtonPressed(), + props.IsMiddleButtonPressed(), + props.IsRightButtonPressed() }; auto result = _DoMouseWheel(point.Position(), ControlKeyStates{ args.KeyModifiers() }, point.Properties().MouseWheelDelta(), @@ -1618,7 +1339,6 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation // Method Description: // - Actually handle a scrolling event, whether from a mouse wheel or a - // touchpad scroll. Depending upon what modifier keys are pressed, // different actions will take place. // * Attempts to first dispatch the mouse scroll as a VT event @@ -1642,11 +1362,11 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation // here with a PointerPoint. However, as of #979, we don't have a // PointerPoint to work with. So, we're just going to do a // mousewheel event manually - return _terminal->SendMouseEvent(_GetTerminalPosition(point), - WM_MOUSEWHEEL, - _GetPressedModifierKeys(), - ::base::saturated_cast(delta), - state); + return _core->SendMouseEvent(_GetTerminalPosition(point), + WM_MOUSEWHEEL, + _GetPressedModifierKeys(), + ::base::saturated_cast(delta), + state); } const auto ctrlPressed = modifiers.IsCtrlPressed(); @@ -1684,19 +1404,12 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation const bool rightButtonDown) { const auto modifiers = _GetPressedModifierKeys(); - TerminalInput::MouseButtonState state{ leftButtonDown, midButtonDown, rightButtonDown }; + TerminalInput::MouseButtonState state{ leftButtonDown, + midButtonDown, + rightButtonDown }; return _DoMouseWheel(location, modifiers, delta, state); } - // Method Description: - // - Tell TerminalCore to update its knowledge about the locations of visible regex patterns - // - We should call this (through the throttled function) when something causes the visible - // region to change, such as when new text enters the buffer or the viewport is scrolled - void TermControl::UpdatePatternLocations() - { - _terminal->UpdatePatterns(); - } - // Method Description: // - Adjust the opacity of the acrylic background in response to a mouse // scrolling event. @@ -1720,15 +1433,12 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation _settings.UseAcrylic(false); _InitializeBackgroundBrush(); COLORREF bg = _settings.DefaultBackground(); - _BackgroundColorChanged(bg); + _changeBackgroundColor(bg); } else { // GH#5098: Inform the engine of the new opacity of the default text background. - if (_renderEngine) - { - _renderEngine->SetDefaultTextBackgroundOpacity(::base::saturated_cast(_settings.TintOpacity())); - } + _core->SetBackgroundOpacity(::base::saturated_cast(_settings.TintOpacity())); } } CATCH_LOG(); @@ -1760,7 +1470,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation // - none void TermControl::ResetFontSize() { - _SetFontSize(_settings.FontSize()); + _core->ResetFontSize(); } // Method Description: @@ -1769,8 +1479,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation // - fontSizeDelta: The amount to increase or decrease the font size by. void TermControl::AdjustFontSize(int fontSizeDelta) { - const auto newSize = _desiredFont.GetEngineSize().Y + fontSizeDelta; - _SetFontSize(newSize); + _core->AdjustFontSize(fontSizeDelta); } // Method Description: @@ -1794,18 +1503,15 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation // WHEEL_PAGESCROLL is a Win32 constant that represents the "scroll one page // at a time" setting. If we ignore it, we will scroll a truly absurd number // of rows. - const auto rowsToScroll{ _rowsToScroll == WHEEL_PAGESCROLL ? GetViewHeight() : _rowsToScroll }; + const auto rowsToScroll{ _rowsToScroll == WHEEL_PAGESCROLL ? ViewHeight() : _rowsToScroll }; double newValue = (rowsToScroll * rowDelta) + (currentOffset); // The scroll bar's ValueChanged handler will actually move the viewport // for us. ScrollBar().Value(newValue); - if (_terminal->IsSelectionActive() && isLeftButtonPressed) + if (isLeftButtonPressed) { - // Have to take the lock or we could change the endpoints out from under the renderer actively rendering. - auto lock = _terminal->LockForWriting(); - // If user is mouse selecting and scrolls, they then point at new character. // Make sure selection reflects that immediately. _SetEndSelectionPointAtCursor(point); @@ -1823,14 +1529,8 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation return; } - // Clear the regex pattern tree so the renderer does not try to render them while scrolling - _terminal->ClearPatternTree(); - const auto newValue = static_cast(args.NewValue()); - - // This is a scroll event that wasn't initiated by the terminal - // itself - it was initiated by the mouse wheel, or the scrollbar. - _terminal->UserScrollViewport(newValue); + _core->UserScrollViewport(newValue); // User input takes priority over terminal events so cancel // any pending scroll bar update if the user scrolls. @@ -1947,9 +1647,6 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation if (_autoScrollingPointerPoint.has_value()) { - // Have to take the lock because the renderer will not draw correctly if you move its endpoints while it is generating a frame. - auto lock = _terminal->LockForWriting(); - _SetEndSelectionPointAtCursor(_autoScrollingPointerPoint.value().Position()); } } @@ -1998,7 +1695,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation if (_cursorTimer.has_value()) { // When the terminal focuses, show the cursor immediately - _terminal->SetCursorOn(true); + _core->CursorOn(true); _cursorTimer.value().Start(); } @@ -2052,7 +1749,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation if (_cursorTimer.has_value()) { _cursorTimer.value().Stop(); - _terminal->SetCursorOn(false); + _core->CursorOn(false); } if (_blinkTimer.has_value()) @@ -2061,123 +1758,12 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation } } - // Method Description: - // - Writes the given sequence as input to the active terminal connection. - // - This method has been overloaded to allow zero-copy winrt::param::hstring optimizations. - // Arguments: - // - wstr: the string of characters to write to the terminal connection. - // Return Value: - // - - void TermControl::_SendInputToConnection(const winrt::hstring& wstr) - { - if (_isReadOnly) - { - _RaiseReadOnlyWarning(); - } - else - { - _connection.WriteInput(wstr); - } - } - - void TermControl::_SendInputToConnection(std::wstring_view wstr) - { - if (_isReadOnly) - { - _RaiseReadOnlyWarning(); - } - else - { - _connection.WriteInput(wstr); - } - } - // Method Description: // - Pre-process text pasted (presumably from the clipboard) // before sending it over the terminal's connection. void TermControl::_SendPastedTextToConnection(const std::wstring& wstr) { - _terminal->WritePastedText(wstr); - _terminal->ClearSelection(); - _terminal->TrySnapOnInput(); - } - - // Method Description: - // - Update the font with the renderer. This will be called either when the - // font changes or the DPI changes, as DPI changes will necessitate a - // font change. This method will *not* change the buffer/viewport size - // to account for the new glyph dimensions. Callers should make sure to - // appropriately call _DoResizeUnderLock after this method is called. - // - The write lock should be held when calling this method. - // Arguments: - // - initialUpdate: whether this font update should be considered as being - // concerned with initialization process. Value forwarded to event handler. - void TermControl::_UpdateFont(const bool initialUpdate) - { - const int newDpi = static_cast(static_cast(USER_DEFAULT_SCREEN_DPI) * SwapChainPanel().CompositionScaleX()); - - // TODO: MSFT:20895307 If the font doesn't exist, this doesn't - // actually fail. We need a way to gracefully fallback. - _renderer->TriggerFontChange(newDpi, _desiredFont, _actualFont); - - // If the actual font isn't what was requested... - if (_actualFont.GetFaceName() != _desiredFont.GetFaceName()) - { - // Then warn the user that we picked something because we couldn't find their font. - - // Format message with user's choice of font and the font that was chosen instead. - const winrt::hstring message{ fmt::format(std::wstring_view{ RS_(L"NoticeFontNotFound") }, _desiredFont.GetFaceName(), _actualFont.GetFaceName()) }; - - // Capture what we need to resume later. - [strongThis = get_strong(), message]() -> winrt::fire_and_forget { - // Take these out of the lambda and store them locally - // because the coroutine will lose them into space - // by the time it resumes. - const auto msg = message; - const auto strong = strongThis; - - // Pop the rest of this function to the tail of the UI thread - // Just in case someone was holding a lock when they called us and - // the handlers decide to do something that take another lock - // (like ShellExecute pumping our messaging thread...GH#7994) - co_await strong->Dispatcher(); - - auto noticeArgs = winrt::make(NoticeLevel::Warning, std::move(msg)); - strong->_raiseNoticeHandlers(*strong, std::move(noticeArgs)); - }(); - } - - const auto actualNewSize = _actualFont.GetSize(); - _fontSizeChangedHandlers(actualNewSize.X, actualNewSize.Y, initialUpdate); - } - - // Method Description: - // - Set the font size of the terminal control. - // Arguments: - // - fontSize: The size of the font. - void TermControl::_SetFontSize(int fontSize) - { - try - { - // Make sure we have a non-zero font size - const auto newSize = std::max(gsl::narrow_cast(fontSize), 1); - const auto fontFace = _settings.FontFace(); - const auto fontWeight = _settings.FontWeight(); - _actualFont = { fontFace, 0, fontWeight.Weight, { 0, newSize }, CP_UTF8, false }; - _desiredFont = { _actualFont }; - - auto lock = _terminal->LockForWriting(); - - // Refresh our font with the renderer - _UpdateFont(); - - // Resize the terminal's BUFFER to match the new font size. This does - // NOT change the size of the window, because that can lead to more - // problems (like what happens when you change the font size while the - // window is maximized?) - _RefreshSizeUnderLock(); - } - CATCH_LOG(); + _core->PasteText(winrt::hstring{ wstr }); } // Method Description: @@ -2193,28 +1779,8 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation return; } - auto lock = _terminal->LockForWriting(); - const auto newSize = e.NewSize(); - const auto currentScaleX = SwapChainPanel().CompositionScaleX(); - const auto currentEngineScale = _renderEngine->GetScaling(); - auto foundationSize = newSize; - - // A strange thing can happen here. If you have two tabs open, and drag - // across a DPI boundary, then switch to the other tab, that tab will - // receive two events: First, a SizeChanged, then a ScaleChanged. In the - // SizeChanged event handler, the SwapChainPanel's CompositionScale will - // _already_ be the new scaling, but the engine won't have that value - // yet. If we scale by the CompositionScale here, we'll end up in a - // weird torn state. I'm not totally sure why. - // - // Fortunately we will be getting that following ScaleChanged event, and - // we'll end up resizing again, so we don't terribly need to worry about - // this. - foundationSize.Width *= currentEngineScale; - foundationSize.Height *= currentEngineScale; - - _DoResizeUnderLock(foundationSize.Width, foundationSize.Height); + _core->SizeChanged(newSize.Width, newSize.Height); } // Method Description: @@ -2247,35 +1813,10 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation void TermControl::_SwapChainScaleChanged(Windows::UI::Xaml::Controls::SwapChainPanel const& sender, Windows::Foundation::IInspectable const& /*args*/) { - if (_renderEngine) - { - const auto scaleX = sender.CompositionScaleX(); - const auto scaleY = sender.CompositionScaleY(); - const auto dpi = (float)(scaleX * USER_DEFAULT_SCREEN_DPI); - const auto currentEngineScale = _renderEngine->GetScaling(); + const auto scaleX = sender.CompositionScaleX(); + const auto scaleY = sender.CompositionScaleY(); - // If we're getting a notification to change to the DPI we already - // have, then we're probably just beginning the DPI change. Since - // we'll get _another_ event with the real DPI, do nothing here for - // now. We'll also skip the next resize in _SwapChainSizeChanged. - const bool dpiWasUnchanged = currentEngineScale == scaleX; - if (dpiWasUnchanged) - { - return; - } - - const auto actualFontOldSize = _actualFont.GetSize(); - - auto lock = _terminal->LockForWriting(); - - _renderer->TriggerFontChange(::base::saturated_cast(dpi), _desiredFont, _actualFont); - - const auto actualFontNewSize = _actualFont.GetSize(); - if (actualFontNewSize != actualFontOldSize) - { - _RefreshSizeUnderLock(); - } - } + _core->ScaleChanged(scaleX, scaleY); } // Method Description: @@ -2286,11 +1827,10 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation void TermControl::_CursorTimerTick(Windows::Foundation::IInspectable const& /* sender */, Windows::Foundation::IInspectable const& /* e */) { - if ((_closing) || (!_terminal->IsCursorBlinkingAllowed() && _terminal->IsCursorVisible())) + if (!_closing) { - return; + _core->BlinkCursor(); } - _terminal->SetCursorOn(!_terminal->IsCursorOn()); } // Method Description: @@ -2303,124 +1843,20 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation { if (!_closing) { - auto& renderTarget = *_renderer; - auto& blinkingState = _terminal->GetBlinkingState(); - blinkingState.ToggleBlinkingRendition(renderTarget); + _core->BlinkAttributeTick(); } } - // Method Description: - // - Sets selection's end position to match supplied cursor position, e.g. while mouse dragging. - // Arguments: - // - cursorPosition: in pixels, relative to the origin of the control + // // Method Description: + // // - Sets selection's end position to match supplied cursor position, e.g. while mouse dragging. + // // Arguments: + // // - cursorPosition: in pixels, relative to the origin of the control void TermControl::_SetEndSelectionPointAtCursor(Windows::Foundation::Point const& cursorPosition) { - if (!_terminal->IsSelectionActive()) - { - return; - } - - auto terminalPosition = _GetTerminalPosition(cursorPosition); - - const short lastVisibleRow = std::max(_terminal->GetViewport().Height() - 1, 0); - const short lastVisibleCol = std::max(_terminal->GetViewport().Width() - 1, 0); - - terminalPosition.Y = std::clamp(terminalPosition.Y, 0, lastVisibleRow); - terminalPosition.X = std::clamp(terminalPosition.X, 0, lastVisibleCol); - - // save location (for rendering) + render - _terminal->SetSelectionEnd(terminalPosition); - _renderer->TriggerSelection(); + _core->SetEndSelectionPoint(_GetTerminalPosition(cursorPosition)); _selectionNeedsToBeCopied = true; } - // Method Description: - // - Perform a resize for the current size of the swapchainpanel. If the - // font size changed, we'll need to resize the buffer to fit the existing - // swapchain size. This helper will call _DoResizeUnderLock with the current size - // of the swapchain, accounting for scaling due to DPI. - // - Note that a DPI change will also trigger a font size change, and will call into here. - // - The write lock should be held when calling this method, we might be changing the buffer size in _DoResizeUnderLock. - // Arguments: - // - - // Return Value: - // - - void TermControl::_RefreshSizeUnderLock() - { - const auto currentScaleX = SwapChainPanel().CompositionScaleX(); - const auto currentScaleY = SwapChainPanel().CompositionScaleY(); - const auto actualWidth = SwapChainPanel().ActualWidth(); - const auto actualHeight = SwapChainPanel().ActualHeight(); - - const auto widthInPixels = actualWidth * currentScaleX; - const auto heightInPixels = actualHeight * currentScaleY; - - _DoResizeUnderLock(widthInPixels, heightInPixels); - } - - // Method Description: - // - Process a resize event that was initiated by the user. This can either - // be due to the user resizing the window (causing the swapchain to - // resize) or due to the DPI changing (causing us to need to resize the - // buffer to match) - // Arguments: - // - newWidth: the new width of the swapchain, in pixels. - // - newHeight: the new height of the swapchain, in pixels. - void TermControl::_DoResizeUnderLock(const double newWidth, const double newHeight) - { - SIZE size; - size.cx = static_cast(newWidth); - size.cy = static_cast(newHeight); - - // Don't actually resize so small that a single character wouldn't fit - // in either dimension. The buffer really doesn't like being size 0. - if (size.cx < _actualFont.GetSize().X || size.cy < _actualFont.GetSize().Y) - { - return; - } - - _terminal->ClearSelection(); - - // Tell the dx engine that our window is now the new size. - THROW_IF_FAILED(_renderEngine->SetWindowSize(size)); - - // Invalidate everything - _renderer->TriggerRedrawAll(); - - // Convert our new dimensions to characters - const auto viewInPixels = Viewport::FromDimensions({ 0, 0 }, - { static_cast(size.cx), static_cast(size.cy) }); - const auto vp = _renderEngine->GetViewportInCharacters(viewInPixels); - - // If this function succeeds with S_FALSE, then the terminal didn't - // actually change size. No need to notify the connection of this no-op. - const HRESULT hr = _terminal->UserResize({ vp.Width(), vp.Height() }); - if (SUCCEEDED(hr) && hr != S_FALSE) - { - _connection.Resize(vp.Height(), vp.Width()); - } - } - - void TermControl::_TerminalWarningBell() - { - _WarningBellHandlers(*this, nullptr); - } - - void TermControl::_TerminalTitleChanged(const std::wstring_view& wstr) - { - _titleChangedHandlers(winrt::hstring{ wstr }); - } - void TermControl::_TerminalTabColorChanged(const std::optional /*color*/) - { - _TabColorChangedHandlers(*this, nullptr); - } - - void TermControl::_CopyToClipboard(const std::wstring_view& wstr) - { - auto copyArgs = winrt::make_self(winrt::hstring(wstr)); - _clipboardCopyHandlers(*this, *copyArgs); - } - // Method Description: // - Update the position and size of the scrollbar to match the given // viewport top, viewport height, and buffer size. @@ -2431,28 +1867,15 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation // of the buffer. // - viewHeight: the height of the viewport in rows. // - bufferSize: the length of the buffer, in rows - void TermControl::_TerminalScrollPositionChanged(const int viewTop, - const int viewHeight, - const int bufferSize) + void TermControl::_ScrollPositionChanged(const IInspectable& /*sender*/, + const TerminalControl::ScrollPositionChangedArgs& args) { - // Since this callback fires from non-UI thread, we might be already - // closed/closing. - if (_closing.load()) - { - return; - } - - // Clear the regex pattern tree so the renderer does not try to render them while scrolling - _terminal->ClearPatternTree(); - - _scrollPositionChangedHandlers(viewTop, viewHeight, bufferSize); - ScrollBarUpdate update; - const auto hiddenContent = bufferSize - viewHeight; + const auto hiddenContent = args.BufferSize() - args.ViewHeight(); update.newMaximum = hiddenContent; update.newMinimum = 0; - update.newViewportSize = viewHeight; - update.newValue = viewTop; + update.newViewportSize = args.ViewHeight(); + update.newValue = args.ViewTop(); _updateScrollBar->Run(update); _updatePatternLocations->Run(); @@ -2463,15 +1886,15 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation // to be where the current cursor position is. // Arguments: // - N/A - void TermControl::_TerminalCursorPositionChanged() + void TermControl::_CursorPositionChanged(const IInspectable& /*sender*/, + const IInspectable& /*args*/) { _tsfTryRedrawCanvas->Run(); } hstring TermControl::Title() { - hstring hstr{ _terminal->GetConsoleTitle() }; - return hstr; + return _core->Title(); } hstring TermControl::GetProfileName() const @@ -2481,18 +1904,17 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation hstring TermControl::WorkingDirectory() const { - hstring hstr{ _terminal->GetWorkingDirectory() }; - return hstr; + return _core->WorkingDirectory(); } - // Method Description: - // - Given a copy-able selection, get the selected text from the buffer and send it to the - // Windows Clipboard (CascadiaWin32:main.cpp). - // - CopyOnSelect does NOT clear the selection - // Arguments: - // - singleLine: collapse all of the text to one line - // - formats: which formats to copy (defined by action's CopyFormatting arg). nullptr - // if we should defer which formats are copied to the global setting + // // Method Description: + // // - Given a copy-able selection, get the selected text from the buffer and send it to the + // // Windows Clipboard (CascadiaWin32:main.cpp). + // // - CopyOnSelect does NOT clear the selection + // // Arguments: + // // - singleLine: collapse all of the text to one line + // // - formats: which formats to copy (defined by action's CopyFormatting arg). nullptr + // // if we should defer which formats are copied to the global setting bool TermControl::CopySelectionToClipboard(bool singleLine, const Windows::Foundation::IReference& formats) { if (_closing) @@ -2500,57 +1922,21 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation return false; } - // no selection --> nothing to copy - if (!_terminal->IsSelectionActive()) + if (_core) { - return false; - } - - // Mark the current selection as copied - _selectionNeedsToBeCopied = false; + // Note to future self: This should return false if there's no + // selection to copy. If there's no selection, returning false will + // indicate that the actions that trigered this should _not_ be + // marked as handled, so ctrl+c without a selection can still send + // ^C - // extract text from buffer - const auto bufferData = _terminal->RetrieveSelectedTextFromBuffer(singleLine); + // Mark the current selection as copied + _selectionNeedsToBeCopied = false; - // convert text: vector --> string - std::wstring textData; - for (const auto& text : bufferData.text) - { - textData += text; + return _core->CopySelectionToClipboard(singleLine, formats); } - // convert text to HTML format - // GH#5347 - Don't provide a title for the generated HTML, as many - // web applications will paste the title first, followed by the HTML - // content, which is unexpected. - const auto htmlData = formats == nullptr || WI_IsFlagSet(formats.Value(), CopyFormat::HTML) ? - TextBuffer::GenHTML(bufferData, - _actualFont.GetUnscaledSize().Y, - _actualFont.GetFaceName(), - _settings.DefaultBackground()) : - ""; - - // convert to RTF format - const auto rtfData = formats == nullptr || WI_IsFlagSet(formats.Value(), CopyFormat::RTF) ? - TextBuffer::GenRTF(bufferData, - _actualFont.GetUnscaledSize().Y, - _actualFont.GetFaceName(), - _settings.DefaultBackground()) : - ""; - - if (!_settings.CopyOnSelect()) - { - _terminal->ClearSelection(); - _renderer->TriggerSelection(); - } - - // send data up for clipboard - auto copyArgs = winrt::make_self(winrt::hstring(textData), - winrt::to_hstring(htmlData), - winrt::to_hstring(rtfData), - formats); - _clipboardCopyHandlers(*this, *copyArgs); - return true; + return false; } // Method Description: @@ -2566,69 +1952,17 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation _clipboardPasteHandlers(*this, *pasteArgs); } - // Method Description: - // - Asynchronously close our connection. The Connection will likely wait - // until the attached process terminates before Close returns. If that's - // the case, we don't want to block the UI thread waiting on that process - // handle. - // Arguments: - // - - // Return Value: - // - - winrt::fire_and_forget TermControl::_AsyncCloseConnection() - { - if (auto localConnection{ std::exchange(_connection, nullptr) }) - { - // Close the connection on the background thread. - co_await winrt::resume_background(); - localConnection.Close(); - // connection is destroyed. - } - } - void TermControl::Close() { if (!_closing.exchange(true)) { _RestorePointerCursorHandlers(*this, nullptr); - // Stop accepting new output and state changes before we disconnect everything. - _connection.TerminalOutput(_connectionOutputEventToken); - _connectionStateChangedRevoker.revoke(); - - TSFInputControl().Close(); // Disconnect the TSF input control so it doesn't receive EditContext events. + // Disconnect the TSF input control so it doesn't receive EditContext events. + TSFInputControl().Close(); _autoScrollTimer.Stop(); - // GH#1996 - Close the connection asynchronously on a background - // thread. - // Since TermControl::Close is only ever triggered by the UI, we - // don't really care to wait for the connection to be completely - // closed. We can just do it whenever. - _AsyncCloseConnection(); - - { - // GH#8734: - // We lock the terminal here to make sure it isn't still being - // used in the connection thread before we destroy the renderer. - // However, we must unlock it again prior to triggering the - // teardown, to avoid the render thread being deadlocked. The - // renderer may be waiting to acquire the terminal lock, while - // we're waiting for the renderer to finish. - auto lock = _terminal->LockForWriting(); - } - - if (auto localRenderEngine{ std::exchange(_renderEngine, nullptr) }) - { - if (auto localRenderer{ std::exchange(_renderer, nullptr) }) - { - localRenderer->TriggerTeardown(); - // renderer is destroyed - } - // renderEngine is destroyed - } - - // we don't destroy _terminal here; it now has the same lifetime as the - // control. + _core->Close(); } } @@ -2641,19 +1975,18 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation ScrollBar().Value(viewTop); } - int TermControl::GetScrollOffset() + int TermControl::ScrollOffset() { - return _terminal->GetScrollOffset(); + return _core->ScrollOffset(); } // Function Description: // - Gets the height of the terminal in lines of text // Return Value: // - The height of the terminal in lines of text - int TermControl::GetViewHeight() const + int TermControl::ViewHeight() const { - const auto viewPort = _terminal->GetViewport(); - return viewPort.Height(); + return _core->ViewHeight(); } // Function Description: @@ -2770,7 +2103,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation // - The dimensions of a single character of this control, in DIPs winrt::Windows::Foundation::Size TermControl::CharacterDimensions() const { - const auto fontSize = _actualFont.GetSize(); + const auto fontSize = _core->GetFont().GetSize(); return { gsl::narrow_cast(fontSize.X), gsl::narrow_cast(fontSize.Y) }; } @@ -2787,7 +2120,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation { if (_initializedTerminal) { - const auto fontSize = _actualFont.GetSize(); + const auto fontSize = _core->GetFont().GetSize(); double width = fontSize.X; double height = fontSize.Y; // Reserve additional space if scrollbar is intended to be visible @@ -2832,7 +2165,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation // - A dimension that would be aligned to the character grid. float TermControl::SnapDimensionToGrid(const bool widthOrHeight, const float dimension) { - const auto fontSize = _actualFont.GetSize(); + const auto fontSize = _core->GetFont().GetSize(); const auto fontDimension = widthOrHeight ? fontSize.X : fontSize.Y; const auto padding = GetPadding(); @@ -2963,7 +2296,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation // NOTE: origin (0,0) is top-left. // Return Value: // - the corresponding viewport terminal position for the given Point parameter - const COORD TermControl::_GetTerminalPosition(winrt::Windows::Foundation::Point cursorPosition) + const til::point TermControl::_GetTerminalPosition(winrt::Windows::Foundation::Point cursorPosition) { // cursorPosition is DIPs, relative to SwapChainPanel origin const til::point cursorPosInDIPs{ til::math::rounding, cursorPosition }; @@ -2976,7 +2309,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation const til::point relativeToMarginInPixels{ relativeToMarginInDIPs * SwapChainPanel().CompositionScaleX() }; // Get the size of the font, which is in pixels - const til::size fontSize{ _actualFont.GetSize() }; + const til::size fontSize{ _core->GetFont().GetSize() }; // Convert the location in pixels to characters within the current viewport. return til::point{ relativeToMarginInPixels / fontSize }; @@ -2996,7 +2329,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation return; } - _connection.WriteInput(text); + _core->SendInput(text); } // Method Description: @@ -3006,9 +2339,9 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation // - eventArgs: event for storing the current cursor position // Return Value: // - - void TermControl::_CurrentCursorPositionHandler(const IInspectable& /*sender*/, const CursorPositionEventArgs& eventArgs) + void TermControl::_CurrentCursorPositionHandler(const IInspectable& /*sender*/, + const CursorPositionEventArgs& eventArgs) { - auto lock = _terminal->LockForReading(); if (!_initializedTerminal) { // fake it @@ -3016,8 +2349,9 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation return; } - const til::point cursorPos = _terminal->GetCursorPosition(); - Windows::Foundation::Point p = { ::base::ClampedNumeric(cursorPos.x()), ::base::ClampedNumeric(cursorPos.y()) }; + const til::point cursorPos = _core->CursorPosition(); + Windows::Foundation::Point p = { ::base::ClampedNumeric(cursorPos.x()), + ::base::ClampedNumeric(cursorPos.y()) }; eventArgs.CurrentPosition(p); } @@ -3028,12 +2362,13 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation // - eventArgs: event for storing the current font information // Return Value: // - - void TermControl::_FontInfoHandler(const IInspectable& /*sender*/, const FontInfoEventArgs& eventArgs) + void TermControl::_FontInfoHandler(const IInspectable& /*sender*/, + const FontInfoEventArgs& eventArgs) { eventArgs.FontSize(CharacterDimensions()); - eventArgs.FontFace(_actualFont.GetFaceName()); + eventArgs.FontFace(_core->GetFont().GetFaceName()); ::winrt::Windows::UI::Text::FontWeight weight; - weight.Weight = static_cast(_actualFont.GetWeight()); + weight.Weight = static_cast(_core->GetFont().GetWeight()); eventArgs.FontWeight(weight); } @@ -3152,8 +2487,6 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation fullPath.end(), L' ') != fullPath.end(); - auto lock = _terminal->LockForWriting(); - if (containsSpaces) { fullPath.insert(0, L"\""); @@ -3162,7 +2495,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation allPaths += fullPath; } - _SendInputToConnection(allPaths); + _SendPastedTextToConnection(allPaths); } } } @@ -3257,7 +2590,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation { // It's already loaded if we get here, so just hide it. RendererFailedNotice().Visibility(Visibility::Collapsed); - _renderer->ResetErrorStateAndResume(); + _core->ResumeRendering(); } IControlSettings TermControl::Settings() const @@ -3267,18 +2600,17 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation Windows::Foundation::IReference TermControl::TabColor() noexcept { - auto coreColor = _terminal->GetTabColor(); - return coreColor.has_value() ? Windows::Foundation::IReference(coreColor.value()) : nullptr; + return _core->TabColor(); } - // Method Description: - // - Sends an event (which will be caught by TerminalPage and forwarded to AppHost after) - // to set the progress indicator on the taskbar - winrt::fire_and_forget TermControl::TaskbarProgressChanged() - { - co_await resume_foreground(Dispatcher(), CoreDispatcherPriority::High); - _setTaskbarProgressHandlers(*this, nullptr); - } + // // Method Description: + // // - Sends an event (which will be caught by TerminalPage and forwarded to AppHost after) + // // to set the progress indicator on the taskbar + // winrt::fire_and_forget TermControl::TaskbarProgressChanged() + // { + // co_await resume_foreground(Dispatcher(), CoreDispatcherPriority::High); + // _setTaskbarProgressHandlers(*this, nullptr); + // } // Method Description: // - Gets the internal taskbar state value @@ -3286,7 +2618,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation // - The taskbar state of this control const size_t TermControl::TaskbarState() const noexcept { - return _terminal->GetTaskbarState(); + return _core->TaskbarState(); } // Method Description: @@ -3295,7 +2627,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation // - The taskbar progress of this control const size_t TermControl::TaskbarProgress() const noexcept { - return _terminal->GetTaskbarProgress(); + return _core->TaskbarProgress(); } // Method Description: @@ -3326,64 +2658,6 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation control->_raiseNoticeHandlers(*control, std::move(noticeArgs)); } } - - // Method description: - // - Updates last hovered cell, renders / removes rendering of hyper-link if required - // Arguments: - // - terminalPosition: The terminal position of the pointer - void TermControl::_UpdateHoveredCell(const std::optional& terminalPosition) - { - if (terminalPosition == _lastHoveredCell) - { - return; - } - - _lastHoveredCell = terminalPosition; - - if (terminalPosition.has_value()) - { - const auto uri = _terminal->GetHyperlinkAtPosition(*terminalPosition); - if (!uri.empty()) - { - // Update the tooltip with the URI - HoveredUri().Text(uri); - - // Set the border thickness so it covers the entire cell - const auto charSizeInPixels = CharacterDimensions(); - const auto htInDips = charSizeInPixels.Height / SwapChainPanel().CompositionScaleY(); - const auto wtInDips = charSizeInPixels.Width / SwapChainPanel().CompositionScaleX(); - const Thickness newThickness{ wtInDips, htInDips, 0, 0 }; - HyperlinkTooltipBorder().BorderThickness(newThickness); - - // Compute the location of the top left corner of the cell in DIPS - const til::size marginsInDips{ til::math::rounding, GetPadding().Left, GetPadding().Top }; - const til::point startPos{ terminalPosition->X, terminalPosition->Y }; - const til::size fontSize{ _actualFont.GetSize() }; - const til::point posInPixels{ startPos * fontSize }; - const til::point posInDIPs{ posInPixels / SwapChainPanel().CompositionScaleX() }; - const til::point locationInDIPs{ posInDIPs + marginsInDips }; - - // Move the border to the top left corner of the cell - OverlayCanvas().SetLeft(HyperlinkTooltipBorder(), (locationInDIPs.x() - SwapChainPanel().ActualOffset().x)); - OverlayCanvas().SetTop(HyperlinkTooltipBorder(), (locationInDIPs.y() - SwapChainPanel().ActualOffset().y)); - } - } - - const uint16_t newId = terminalPosition.has_value() ? _terminal->GetHyperlinkIdAtPosition(*terminalPosition) : 0u; - const auto newInterval = terminalPosition.has_value() ? _terminal->GetHyperlinkIntervalFromPosition(*terminalPosition) : std::nullopt; - - // If the hyperlink ID changed or the interval changed, trigger a redraw all - // (so this will happen both when we move onto a link and when we move off a link) - if (newId != _lastHoveredId || (newInterval != _lastHoveredInterval)) - { - _lastHoveredId = newId; - _lastHoveredInterval = newInterval; - _renderEngine->UpdateHyperlinkHoveredId(newId); - _renderer->UpdateLastHoveredInterval(newInterval); - _renderer->TriggerRedrawAll(); - } - } - // Method Description: // - Handle a mouse exited event, specifically clearing last hovered cell // and removing selection from hyper link if exists @@ -3392,20 +2666,57 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation // - args: event data void TermControl::_PointerExitedHandler(Windows::Foundation::IInspectable const& /*sender*/, Windows::UI::Xaml::Input::PointerRoutedEventArgs const& /*e*/) { - _UpdateHoveredCell(std::nullopt); + _core->UpdateHoveredCell(std::nullopt); + } + + winrt::fire_and_forget TermControl::_hoveredHyperlinkChanged(const IInspectable& sender, + const IInspectable& args) + { + auto weakThis{ get_weak() }; + co_await resume_foreground(Dispatcher()); + if (auto self{ weakThis.get() }) + { + auto lastHoveredCell = _core->GetHoveredCell(); + if (lastHoveredCell.has_value()) + { + const auto uriText = _core->GetHoveredUriText(); + if (!uriText.empty()) + { + // Update the tooltip with the URI + HoveredUri().Text(uriText); + + // Set the border thickness so it covers the entire cell + const auto charSizeInPixels = CharacterDimensions(); + const auto htInDips = charSizeInPixels.Height / SwapChainPanel().CompositionScaleY(); + const auto wtInDips = charSizeInPixels.Width / SwapChainPanel().CompositionScaleX(); + const Thickness newThickness{ wtInDips, htInDips, 0, 0 }; + HyperlinkTooltipBorder().BorderThickness(newThickness); + + // Compute the location of the top left corner of the cell in DIPS + const til::size marginsInDips{ til::math::rounding, GetPadding().Left, GetPadding().Top }; + const til::point startPos{ lastHoveredCell->X, + lastHoveredCell->Y }; + const til::size fontSize{ _core->GetFont().GetSize() }; + const til::point posInPixels{ startPos * fontSize }; + const til::point posInDIPs{ posInPixels / SwapChainPanel().CompositionScaleX() }; + const til::point locationInDIPs{ posInDIPs + marginsInDips }; + + // Move the border to the top left corner of the cell + OverlayCanvas().SetLeft(HyperlinkTooltipBorder(), + (locationInDIPs.x() - SwapChainPanel().ActualOffset().x)); + OverlayCanvas().SetTop(HyperlinkTooltipBorder(), + (locationInDIPs.y() - SwapChainPanel().ActualOffset().y)); + } + } + } } // -------------------------------- WinRT Events --------------------------------- // Winrt events need a method for adding a callback to the event and removing the callback. // These macros will define them both for you. - DEFINE_EVENT(TermControl, TitleChanged, _titleChangedHandlers, TerminalControl::TitleChangedEventArgs); DEFINE_EVENT(TermControl, FontSizeChanged, _fontSizeChangedHandlers, TerminalControl::FontSizeChangedEventArgs); - DEFINE_EVENT(TermControl, ScrollPositionChanged, _scrollPositionChangedHandlers, TerminalControl::ScrollPositionChangedEventArgs); - DEFINE_EVENT_WITH_TYPED_EVENT_HANDLER(TermControl, PasteFromClipboard, _clipboardPasteHandlers, TerminalControl::TermControl, TerminalControl::PasteFromClipboardEventArgs); - DEFINE_EVENT_WITH_TYPED_EVENT_HANDLER(TermControl, CopyToClipboard, _clipboardCopyHandlers, TerminalControl::TermControl, TerminalControl::CopyToClipboardEventArgs); DEFINE_EVENT_WITH_TYPED_EVENT_HANDLER(TermControl, OpenHyperlink, _openHyperlinkHandlers, TerminalControl::TermControl, TerminalControl::OpenHyperlinkEventArgs); - DEFINE_EVENT_WITH_TYPED_EVENT_HANDLER(TermControl, SetTaskbarProgress, _setTaskbarProgressHandlers, TerminalControl::TermControl, IInspectable); DEFINE_EVENT_WITH_TYPED_EVENT_HANDLER(TermControl, RaiseNotice, _raiseNoticeHandlers, TerminalControl::TermControl, TerminalControl::NoticeEventArgs); // clang-format on } diff --git a/src/cascadia/TerminalControl/TermControl.h b/src/cascadia/TerminalControl/TermControl.h index 0cd9b463b67..ff66dd6db1c 100644 --- a/src/cascadia/TerminalControl/TermControl.h +++ b/src/cascadia/TerminalControl/TermControl.h @@ -4,10 +4,7 @@ #pragma once #include "TermControl.g.h" -#include "CopyToClipboardEventArgs.g.h" -#include "PasteFromClipboardEventArgs.g.h" -#include "OpenHyperlinkEventArgs.g.h" -#include "NoticeEventArgs.g.h" +#include "EventArgs.h" #include #include "../../renderer/base/Renderer.hpp" #include "../../renderer/dx/DxRenderer.hpp" @@ -18,6 +15,8 @@ #include "SearchBoxControl.h" #include "ThrottledFunc.h" +#include "ControlCore.h" + namespace Microsoft::Console::VirtualTerminal { struct MouseButtonState; @@ -25,79 +24,6 @@ namespace Microsoft::Console::VirtualTerminal namespace winrt::Microsoft::Terminal::TerminalControl::implementation { - struct CopyToClipboardEventArgs : - public CopyToClipboardEventArgsT - { - public: - CopyToClipboardEventArgs(hstring text) : - _text(text), - _html(), - _rtf(), - _formats(static_cast(0)) {} - - CopyToClipboardEventArgs(hstring text, hstring html, hstring rtf, Windows::Foundation::IReference formats) : - _text(text), - _html(html), - _rtf(rtf), - _formats(formats) {} - - hstring Text() { return _text; }; - hstring Html() { return _html; }; - hstring Rtf() { return _rtf; }; - Windows::Foundation::IReference Formats() { return _formats; }; - - private: - hstring _text; - hstring _html; - hstring _rtf; - Windows::Foundation::IReference _formats; - }; - - struct PasteFromClipboardEventArgs : - public PasteFromClipboardEventArgsT - { - public: - PasteFromClipboardEventArgs(std::function clipboardDataHandler) : - m_clipboardDataHandler(clipboardDataHandler) {} - - void HandleClipboardData(hstring value) - { - m_clipboardDataHandler(static_cast(value)); - }; - - private: - std::function m_clipboardDataHandler; - }; - - struct OpenHyperlinkEventArgs : - public OpenHyperlinkEventArgsT - { - public: - OpenHyperlinkEventArgs(hstring uri) : - _uri(uri) {} - - hstring Uri() { return _uri; }; - - private: - hstring _uri; - }; - - struct NoticeEventArgs : - public NoticeEventArgsT - { - public: - NoticeEventArgs(const NoticeLevel level, const hstring& message) : - _level(level), - _message(message) {} - - NoticeLevel Level() { return _level; }; - hstring Message() { return _message; }; - - private: - const NoticeLevel _level; - const hstring _message; - }; - struct TermControl : TermControlT { TermControl(IControlSettings settings, TerminalConnection::ITerminalConnection connection); @@ -116,20 +42,22 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation float SnapDimensionToGrid(const bool widthOrHeight, const float dimension); void ScrollViewport(int viewTop); - int GetScrollOffset(); - int GetViewHeight() const; + int ScrollOffset(); + int ViewHeight() const; void AdjustFontSize(int fontSizeDelta); void ResetFontSize(); + til::point GetFontSize() const; void SendInput(const winrt::hstring& input); void ToggleShaderEffects(); - winrt::fire_and_forget RenderEngineSwapChainChanged(); - void _AttachDxgiSwapChainToXaml(IDXGISwapChain1* swapChain); + winrt::fire_and_forget RenderEngineSwapChainChanged(const IInspectable& sender, const IInspectable& args); + void _AttachDxgiSwapChainToXaml(HANDLE swapChainHandle); winrt::fire_and_forget _RendererEnteredErrorState(); void _RenderRetryButton_Click(IInspectable const& button, IInspectable const& args); - winrt::fire_and_forget _RendererWarning(const HRESULT hr); + winrt::fire_and_forget _RendererWarning(const IInspectable& sender, + const TerminalControl::RendererWarningArgs& args); void CreateSearchBoxControl(); @@ -139,13 +67,10 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation bool OnMouseWheel(const Windows::Foundation::Point location, const int32_t delta, const bool leftButtonDown, const bool midButtonDown, const bool rightButtonDown); - void UpdatePatternLocations(); - ~TermControl(); Windows::UI::Xaml::Automation::Peers::AutomationPeer OnCreateAutomationPeer(); ::Microsoft::Console::Types::IUiaData* GetUiaData() const; - const FontInfo GetActualFont() const; const Windows::UI::Xaml::Thickness GetPadding(); TerminalConnection::ConnectionState ConnectionState() const; @@ -162,29 +87,29 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation Windows::Foundation::IReference TabColor() noexcept; - winrt::fire_and_forget TaskbarProgressChanged(); + // winrt::fire_and_forget TaskbarProgressChanged(); const size_t TaskbarState() const noexcept; const size_t TaskbarProgress() const noexcept; bool ReadOnly() const noexcept; void ToggleReadOnly(); - // clang-format off // -------------------------------- WinRT Events --------------------------------- - DECLARE_EVENT(TitleChanged, _titleChangedHandlers, TerminalControl::TitleChangedEventArgs); + FORWARDED_TYPED_EVENT(CopyToClipboard, IInspectable, TerminalControl::CopyToClipboardEventArgs, _core, CopyToClipboard); + FORWARDED_TYPED_EVENT(TitleChanged, IInspectable, TerminalControl::TitleChangedEventArgs, _core, TitleChanged); + FORWARDED_TYPED_EVENT(WarningBell, IInspectable, IInspectable, _core, WarningBell); + FORWARDED_TYPED_EVENT(TabColorChanged, IInspectable, IInspectable, _core, TabColorChanged); + FORWARDED_TYPED_EVENT(SetTaskbarProgress, IInspectable, IInspectable, _core, TaskbarProgressChanged); + FORWARDED_TYPED_EVENT(ConnectionStateChanged, IInspectable, IInspectable, _core, ConnectionStateChanged); + // clang-format off + DECLARE_EVENT(FontSizeChanged, _fontSizeChangedHandlers, TerminalControl::FontSizeChangedEventArgs); - DECLARE_EVENT(ScrollPositionChanged, _scrollPositionChangedHandlers, TerminalControl::ScrollPositionChangedEventArgs); DECLARE_EVENT_WITH_TYPED_EVENT_HANDLER(PasteFromClipboard, _clipboardPasteHandlers, TerminalControl::TermControl, TerminalControl::PasteFromClipboardEventArgs); - DECLARE_EVENT_WITH_TYPED_EVENT_HANDLER(CopyToClipboard, _clipboardCopyHandlers, TerminalControl::TermControl, TerminalControl::CopyToClipboardEventArgs); DECLARE_EVENT_WITH_TYPED_EVENT_HANDLER(OpenHyperlink, _openHyperlinkHandlers, TerminalControl::TermControl, TerminalControl::OpenHyperlinkEventArgs); - DECLARE_EVENT_WITH_TYPED_EVENT_HANDLER(SetTaskbarProgress, _setTaskbarProgressHandlers, TerminalControl::TermControl, IInspectable); DECLARE_EVENT_WITH_TYPED_EVENT_HANDLER(RaiseNotice, _raiseNoticeHandlers, TerminalControl::TermControl, TerminalControl::NoticeEventArgs); - TYPED_EVENT(WarningBell, IInspectable, IInspectable); - TYPED_EVENT(ConnectionStateChanged, TerminalControl::TermControl, IInspectable); TYPED_EVENT(Initialized, TerminalControl::TermControl, Windows::UI::Xaml::RoutedEventArgs); - TYPED_EVENT(TabColorChanged, IInspectable, IInspectable); TYPED_EVENT(HidePointerCursor, IInspectable, IInspectable); TYPED_EVENT(RestorePointerCursor, IInspectable, IInspectable); TYPED_EVENT(ReadOnlyChanged, IInspectable, IInspectable); @@ -193,26 +118,29 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation private: friend struct TermControlT; // friend our parent so it can bind private event handlers - TerminalConnection::ITerminalConnection _connection; + + winrt::com_ptr _core{ nullptr }; + + // TerminalConnection::ITerminalConnection _connection; bool _initializedTerminal; winrt::com_ptr _searchBox; - event_token _connectionOutputEventToken; - TerminalConnection::ITerminalConnection::StateChanged_revoker _connectionStateChangedRevoker; + // event_token _connectionOutputEventToken; + // TerminalConnection::ITerminalConnection::StateChanged_revoker _connectionStateChangedRevoker; - std::unique_ptr<::Microsoft::Terminal::Core::Terminal> _terminal; + // std::unique_ptr<::Microsoft::Terminal::Core::Terminal> _terminal; - std::unique_ptr<::Microsoft::Console::Render::Renderer> _renderer; - std::unique_ptr<::Microsoft::Console::Render::DxEngine> _renderEngine; + // std::unique_ptr<::Microsoft::Console::Render::Renderer> _renderer; + // std::unique_ptr<::Microsoft::Console::Render::DxEngine> _renderEngine; std::unique_ptr<::Microsoft::Console::Render::UiaEngine> _uiaEngine; IControlSettings _settings; bool _focused; std::atomic _closing; - FontInfoDesired _desiredFont; - FontInfo _actualFont; + // FontInfoDesired _desiredFont; + // FontInfo _actualFont; std::shared_ptr> _tsfTryRedrawCanvas; @@ -228,7 +156,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation std::shared_ptr> _updateScrollBar; bool _isInternalScrollBarUpdate; - unsigned int _rowsToScroll; + unsigned int _rowsToScroll; // Definitely Control/Interactivity // Auto scroll occurs when user, while selecting, drags cursor outside viewport. View is then scrolled to 'follow' the cursor. double _autoScrollVelocity; @@ -236,8 +164,8 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation Windows::UI::Xaml::DispatcherTimer _autoScrollTimer; std::optional _lastAutoScrollUpdateTime; - // storage location for the leading surrogate of a utf-16 surrogate pair - std::optional _leadingSurrogate; + // // storage location for the leading surrogate of a utf-16 surrogate pair + // std::optional _leadingSurrogate; std::optional _cursorTimer; std::optional _blinkTimer; @@ -246,12 +174,12 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation // viewport via touch input. std::optional _touchAnchor; - // Track the last cell we hovered over (used in pointerMovedHandler) - std::optional _lastHoveredCell; - // Track the last hyperlink ID we hovered over - uint16_t _lastHoveredId; + // // Track the last cell we hovered over (used in pointerMovedHandler) + // std::optional _lastHoveredCell; + // // Track the last hyperlink ID we hovered over + // uint16_t _lastHoveredId; - std::optional::interval> _lastHoveredInterval; + // std::optional::interval> _lastHoveredInterval; using Timestamp = uint64_t; @@ -261,25 +189,26 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation unsigned int _multiClickCounter; Timestamp _lastMouseClickTimestamp; std::optional _lastMouseClickPos; - std::optional _lastMouseClickPosNoSelection; std::optional _singleClickTouchdownPos; + std::optional _lastMouseClickPosNoSelection; // This field tracks whether the selection has changed meaningfully // since it was last copied. It's generally used to prevent copyOnSelect // from firing when the pointer _just happens_ to be released over the // terminal. - bool _selectionNeedsToBeCopied; + bool _selectionNeedsToBeCopied; // ->Interactivity winrt::Windows::UI::Xaml::Controls::SwapChainPanel::LayoutUpdated_revoker _layoutUpdatedRevoker; - bool _isReadOnly{ false }; + bool _isReadOnly{ false }; // ? void _ApplyUISettings(const IControlSettings&); void _UpdateSettingsOnUIThread(); void _UpdateSystemParameterSettings() noexcept; void _InitializeBackgroundBrush(); - winrt::fire_and_forget _BackgroundColorChanged(const COLORREF color); + void _BackgroundColorChangedHandler(const IInspectable& sender, const IInspectable& args); + winrt::fire_and_forget _changeBackgroundColor(til::color bg); bool _InitializeTerminal(); - void _UpdateFont(const bool initialUpdate = false); + // void _UpdateFont(const bool initialUpdate = false); void _SetFontSize(int fontSize); void _TappedHandler(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::Input::TappedRoutedEventArgs const& e); void _KeyDownHandler(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::Input::KeyRoutedEventArgs const& e); @@ -300,19 +229,19 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation void _CursorTimerTick(Windows::Foundation::IInspectable const& sender, Windows::Foundation::IInspectable const& e); void _BlinkTimerTick(Windows::Foundation::IInspectable const& sender, Windows::Foundation::IInspectable const& e); void _SetEndSelectionPointAtCursor(Windows::Foundation::Point const& cursorPosition); - void _SendInputToConnection(const winrt::hstring& wstr); - void _SendInputToConnection(std::wstring_view wstr); + // void _SendInputToConnection(const winrt::hstring& wstr); + // void _SendInputToConnection(std::wstring_view wstr); void _SendPastedTextToConnection(const std::wstring& wstr); void _SwapChainSizeChanged(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::SizeChangedEventArgs const& e); void _SwapChainScaleChanged(Windows::UI::Xaml::Controls::SwapChainPanel const& sender, Windows::Foundation::IInspectable const& args); - void _DoResizeUnderLock(const double newWidth, const double newHeight); - void _RefreshSizeUnderLock(); - void _TerminalWarningBell(); - void _TerminalTitleChanged(const std::wstring_view& wstr); + // void _DoResizeUnderLock(const double newWidth, const double newHeight); + // void _RefreshSizeUnderLock(); + // void _CopyToClipboard(const std::wstring_view& wstr); + // void _TerminalWarningBell(); + // void _TerminalTitleChanged(const std::wstring_view& wstr); void _TerminalTabColorChanged(const std::optional color); - void _CopyToClipboard(const std::wstring_view& wstr); - void _TerminalScrollPositionChanged(const int viewTop, const int viewHeight, const int bufferSize); - void _TerminalCursorPositionChanged(); + void _ScrollPositionChanged(const IInspectable& sender, const TerminalControl::ScrollPositionChangedArgs& args); + void _CursorPositionChanged(const IInspectable& sender, const IInspectable& args); void _MouseScrollHandler(const double mouseDelta, const Windows::Foundation::Point point, const bool isLeftButtonPressed); void _MouseZoomHandler(const double delta); @@ -336,7 +265,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation bool _TrySendMouseEvent(Windows::UI::Input::PointerPoint const& point); bool _CanSendVTMouseInput(); - const COORD _GetTerminalPosition(winrt::Windows::Foundation::Point cursorPosition); + const til::point _GetTerminalPosition(winrt::Windows::Foundation::Point cursorPosition); const unsigned int _NumberOfClicks(winrt::Windows::Foundation::Point clickPos, Timestamp clickTime); double _GetAutoScrollSpeed(double cursorDistanceFromBorder) const; @@ -347,11 +276,14 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation void _CompositionCompleted(winrt::hstring text); void _CurrentCursorPositionHandler(const IInspectable& sender, const CursorPositionEventArgs& eventArgs); void _FontInfoHandler(const IInspectable& sender, const FontInfoEventArgs& eventArgs); - winrt::fire_and_forget _AsyncCloseConnection(); + // winrt::fire_and_forget _AsyncCloseConnection(); winrt::fire_and_forget _RaiseReadOnlyWarning(); - void _UpdateHoveredCell(const std::optional& terminalPosition); + // void _UpdateHoveredCell(const std::optional& terminalPosition); + + //////////////////////////////////////////////////////////////////////// + winrt::fire_and_forget _hoveredHyperlinkChanged(const IInspectable& sender, const IInspectable& args); }; } diff --git a/src/cascadia/TerminalControl/TermControl.idl b/src/cascadia/TerminalControl/TermControl.idl index 4470c0555d6..a17be8a6ad5 100644 --- a/src/cascadia/TerminalControl/TermControl.idl +++ b/src/cascadia/TerminalControl/TermControl.idl @@ -3,63 +3,17 @@ import "IMouseWheelListener.idl"; import "IControlSettings.idl"; +import "IDirectKeyListener.idl"; +import "EventArgs.idl"; +import "ICoreState.idl"; namespace Microsoft.Terminal.TerminalControl { - delegate void TitleChangedEventArgs(String newTitle); - delegate void FontSizeChangedEventArgs(Int32 width, Int32 height, Boolean isInitialChange); - delegate void ScrollPositionChangedEventArgs(Int32 viewTop, Int32 viewHeight, Int32 bufferLength); - - // C++/winrt makes it difficult to share this idl between two projects, - // Instead, we just pin the uuid and include it in both TermControl and App - // If you update this one, please update TerminalApp\IDirectKeyListener.idl. - // If you change this interface, please update the guid. - // If you press F7 or Alt and get a runtime error, go make sure both copies are the same. - [uuid("0ddf4edc-3fda-4dee-97ca-a417ee3dd510")] interface IDirectKeyListener { - Boolean OnDirectKeyEvent(UInt32 vkey, UInt8 scanCode, Boolean down); - }; - - [flags] - enum CopyFormat - { - HTML = 0x1, - RTF = 0x2, - All = 0xffffffff - }; - - runtimeclass CopyToClipboardEventArgs - { - String Text { get; }; - String Html { get; }; - String Rtf { get; }; - Windows.Foundation.IReference Formats { get; }; - } - - runtimeclass PasteFromClipboardEventArgs - { - void HandleClipboardData(String data); - } - - runtimeclass OpenHyperlinkEventArgs - { - String Uri { get; }; - } - - enum NoticeLevel - { - Debug = 10, - Info = 20, - Warning = 30, - Error = 40, - }; - - runtimeclass NoticeEventArgs - { - NoticeLevel Level { get; }; - String Message { get; }; - } - [default_interface] runtimeclass TermControl : Windows.UI.Xaml.Controls.UserControl, IDirectKeyListener, IMouseWheelListener + [default_interface] runtimeclass TermControl : Windows.UI.Xaml.Controls.UserControl, + IDirectKeyListener, + IMouseWheelListener, + ICoreState { TermControl(Microsoft.Terminal.TerminalControl.IControlSettings settings, Microsoft.Terminal.TerminalConnection.ITerminalConnection connection); @@ -69,24 +23,26 @@ namespace Microsoft.Terminal.TerminalControl Microsoft.Terminal.TerminalControl.IControlSettings Settings { get; }; - event TitleChangedEventArgs TitleChanged; + event Windows.Foundation.TypedEventHandler TitleChanged; event FontSizeChangedEventArgs FontSizeChanged; - event Windows.Foundation.TypedEventHandler CopyToClipboard; + event Windows.Foundation.TypedEventHandler CopyToClipboard; event Windows.Foundation.TypedEventHandler PasteFromClipboard; event Windows.Foundation.TypedEventHandler OpenHyperlink; - event Windows.Foundation.TypedEventHandler SetTaskbarProgress; + event Windows.Foundation.TypedEventHandler SetTaskbarProgress; event Windows.Foundation.TypedEventHandler RaiseNotice; event Windows.Foundation.TypedEventHandler WarningBell; event Windows.Foundation.TypedEventHandler HidePointerCursor; event Windows.Foundation.TypedEventHandler RestorePointerCursor; + event Windows.Foundation.TypedEventHandler TabColorChanged; + event Windows.Foundation.TypedEventHandler ReadOnlyChanged; + event Windows.Foundation.TypedEventHandler FocusFollowMouseRequested; event Windows.Foundation.TypedEventHandler Initialized; - // This is an event handler forwarder for the underlying connection. - // We expose this and ConnectionState here so that it might eventually be data bound. - event Windows.Foundation.TypedEventHandler ConnectionStateChanged; - Microsoft.Terminal.TerminalConnection.ConnectionState ConnectionState { get; }; + // // This is an event handler forwarder for the underlying connection. + // // We expose this and ConnectionState here so that it might eventually be data bound. + event Windows.Foundation.TypedEventHandler ConnectionStateChanged; + // Microsoft.Terminal.TerminalConnection.ConnectionState ConnectionState { get; }; - String Title { get; }; Boolean CopySelectionToClipboard(Boolean singleLine, Windows.Foundation.IReference formats); void PasteTextFromClipboard(); @@ -96,9 +52,9 @@ namespace Microsoft.Terminal.TerminalControl Single SnapDimensionToGrid(Boolean widthOrHeight, Single dimension); void ScrollViewport(Int32 viewTop); - Int32 GetScrollOffset(); - Int32 GetViewHeight(); - event ScrollPositionChangedEventArgs ScrollPositionChanged; + // Int32 GetScrollOffset(); + // Int32 GetViewHeight(); + // event ScrollPositionChangedEventArgs ScrollPositionChanged; void CreateSearchBoxControl(); @@ -110,18 +66,10 @@ namespace Microsoft.Terminal.TerminalControl void ToggleShaderEffects(); void SendInput(String input); - void TaskbarProgressChanged(); - UInt64 TaskbarState { get; }; - UInt64 TaskbarProgress { get; }; - - String WorkingDirectory { get; }; + // void TaskbarProgressChanged(); - Windows.Foundation.IReference TabColor { get; }; - event Windows.Foundation.TypedEventHandler TabColorChanged; Boolean ReadOnly { get; }; void ToggleReadOnly(); - event Windows.Foundation.TypedEventHandler ReadOnlyChanged; - event Windows.Foundation.TypedEventHandler FocusFollowMouseRequested; } } diff --git a/src/cascadia/TerminalControl/TermControlAutomationPeer.cpp b/src/cascadia/TerminalControl/TermControlAutomationPeer.cpp index 80ab74ada9b..acc8a78f8de 100644 --- a/src/cascadia/TerminalControl/TermControlAutomationPeer.cpp +++ b/src/cascadia/TerminalControl/TermControlAutomationPeer.cpp @@ -199,7 +199,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation #pragma region IControlAccessibilityInfo COORD TermControlAutomationPeer::GetFontSize() const { - return _termControl->GetActualFont().GetSize(); + return _termControl->GetFontSize(); } RECT TermControlAutomationPeer::GetBounds() const diff --git a/src/cascadia/TerminalControl/TerminalControl.vcxproj b/src/cascadia/TerminalControl/TerminalControl.vcxproj index 4d07df1f530..03a2ac91e57 100644 --- a/src/cascadia/TerminalControl/TerminalControl.vcxproj +++ b/src/cascadia/TerminalControl/TerminalControl.vcxproj @@ -25,9 +25,15 @@ + + ControlCore.idl + KeyChord.idl + + EventArgs.idl + SearchBoxControl.xaml @@ -47,6 +53,12 @@ Create + + ControlCore.idl + + + EventArgs.idl + KeyChord.idl @@ -68,7 +80,11 @@ + + + + diff --git a/src/cascadia/TerminalCore/ITerminalInput.hpp b/src/cascadia/TerminalCore/ITerminalInput.hpp index 307f03b1165..c2c7c54ca1b 100644 --- a/src/cascadia/TerminalCore/ITerminalInput.hpp +++ b/src/cascadia/TerminalCore/ITerminalInput.hpp @@ -20,7 +20,6 @@ namespace Microsoft::Terminal::Core virtual bool SendMouseEvent(const COORD viewportPos, const unsigned int uiButton, const ControlKeyStates states, const short wheelDelta, const Microsoft::Console::VirtualTerminal::TerminalInput::MouseButtonState state) = 0; virtual bool SendCharEvent(const wchar_t ch, const WORD scanCode, const ControlKeyStates states) = 0; - // void SendMouseEvent(uint row, uint col, KeyModifiers modifiers); [[nodiscard]] virtual HRESULT UserResize(const COORD size) noexcept = 0; virtual void UserScrollViewport(const int viewTop) = 0; virtual int GetScrollOffset() = 0; diff --git a/src/common.build.post.props b/src/common.build.post.props index e3e563b900d..c3b0d521215 100644 --- a/src/common.build.post.props +++ b/src/common.build.post.props @@ -13,7 +13,7 @@ ProgramDatabase - onecoreuap_apiset.lib;d3dcompiler.lib;dwmapi.lib;uxtheme.lib;shlwapi.lib;ntdll.lib;%(AdditionalDependencies) + onecoreuap_apiset.lib;d3dcompiler.lib;dwmapi.lib;uxtheme.lib;shlwapi.lib;ntdll.lib;dcomp.lib;%(AdditionalDependencies) diff --git a/src/renderer/dx/DxRenderer.cpp b/src/renderer/dx/DxRenderer.cpp index 0ffbc1584ec..d1b988cb475 100644 --- a/src/renderer/dx/DxRenderer.cpp +++ b/src/renderer/dx/DxRenderer.cpp @@ -79,6 +79,7 @@ DxEngine::DxEngine() : _backgroundColor{ 0 }, _selectionBackground{}, _haveDeviceResources{ false }, + _swapChainHandle{ INVALID_HANDLE_VALUE }, _swapChainDesc{ 0 }, _swapChainFrameLatencyWaitableObject{ INVALID_HANDLE_VALUE }, _recreateDeviceRequested{ false }, @@ -618,6 +619,13 @@ try } case SwapChainMode::ForComposition: { + if (!_swapChainHandle) + { + RETURN_IF_FAILED(DCompositionCreateSurfaceHandle(GENERIC_ALL, nullptr, &_swapChainHandle)); + } + + RETURN_IF_FAILED(_dxgiFactory2.As(&_dxgiFactoryMedia)); + // Use the given target size for compositions. _swapChainDesc.Width = _displaySizePixels.width(); _swapChainDesc.Height = _displaySizePixels.height(); @@ -627,10 +635,11 @@ try // It's 100% required to use scaling mode stretch for composition. There is no other choice. _swapChainDesc.Scaling = DXGI_SCALING_STRETCH; - RETURN_IF_FAILED(_dxgiFactory2->CreateSwapChainForComposition(_d3dDevice.Get(), - &_swapChainDesc, - nullptr, - &_dxgiSwapChain)); + RETURN_IF_FAILED(_dxgiFactoryMedia->CreateSwapChainForCompositionSurfaceHandle(_d3dDevice.Get(), + _swapChainHandle.get(), + &_swapChainDesc, + nullptr, + &_dxgiSwapChain)); break; } default: @@ -1003,14 +1012,14 @@ try } CATCH_LOG() -Microsoft::WRL::ComPtr DxEngine::GetSwapChain() +HANDLE DxEngine::GetSwapChainHandle() { - if (_dxgiSwapChain.Get() == nullptr) + if (!_swapChainHandle) { THROW_IF_FAILED(_CreateDeviceResources(true)); } - return _dxgiSwapChain; + return _swapChainHandle.get(); } void DxEngine::_InvalidateRectangle(const til::rectangle& rc) diff --git a/src/renderer/dx/DxRenderer.hpp b/src/renderer/dx/DxRenderer.hpp index 39cbfbf8969..f4ae176c7e8 100644 --- a/src/renderer/dx/DxRenderer.hpp +++ b/src/renderer/dx/DxRenderer.hpp @@ -70,7 +70,7 @@ namespace Microsoft::Console::Render void SetSoftwareRendering(bool enable) noexcept; - ::Microsoft::WRL::ComPtr GetSwapChain(); + HANDLE GetSwapChainHandle(); // IRenderEngine Members [[nodiscard]] HRESULT Invalidate(const SMALL_RECT* const psrRegion) noexcept override; @@ -128,6 +128,8 @@ namespace Microsoft::Console::Render void SetAntialiasingMode(const D2D1_TEXT_ANTIALIAS_MODE antialiasingMode) noexcept; void SetDefaultTextBackgroundOpacity(const float opacity) noexcept; + wil::unique_handle _swapChainHandle; + void UpdateHyperlinkHoveredId(const uint16_t hoveredId) noexcept; protected: @@ -210,6 +212,7 @@ namespace Microsoft::Console::Render ::Microsoft::WRL::ComPtr _d2dBrushBackground; ::Microsoft::WRL::ComPtr _dxgiFactory2; + ::Microsoft::WRL::ComPtr _dxgiFactoryMedia; ::Microsoft::WRL::ComPtr _dxgiDevice; ::Microsoft::WRL::ComPtr _dxgiSurface; diff --git a/src/renderer/dx/precomp.h b/src/renderer/dx/precomp.h index 5715fd8fed3..d3d51af5f51 100644 --- a/src/renderer/dx/precomp.h +++ b/src/renderer/dx/precomp.h @@ -21,6 +21,8 @@ #include #include +#include + #include #include #include From b0f1fa4d64d10924bcc8ab6013df503c3a0ec239 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Thu, 11 Mar 2021 09:02:28 -0600 Subject: [PATCH 02/82] fix some build breaks, because I was only playing in TerminalControl --- src/cascadia/TerminalApp/Pane.cpp | 2 +- src/cascadia/TerminalApp/Pane.h | 2 +- src/cascadia/TerminalApp/TerminalPage.cpp | 4 ++-- src/cascadia/TerminalApp/TerminalPage.h | 2 +- src/cascadia/TerminalApp/TerminalTab.cpp | 4 ++-- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/cascadia/TerminalApp/Pane.cpp b/src/cascadia/TerminalApp/Pane.cpp index f7d681564a5..8058b0d37ae 100644 --- a/src/cascadia/TerminalApp/Pane.cpp +++ b/src/cascadia/TerminalApp/Pane.cpp @@ -312,7 +312,7 @@ bool Pane::NavigateFocus(const FocusDirection& direction) // - // Return Value: // - -void Pane::_ControlConnectionStateChangedHandler(const TermControl& /*sender*/, +void Pane::_ControlConnectionStateChangedHandler(const winrt::Windows::Foundation::IInspectable& /*sender*/, const winrt::Windows::Foundation::IInspectable& /*args*/) { std::unique_lock lock{ _createCloseLock }; diff --git a/src/cascadia/TerminalApp/Pane.h b/src/cascadia/TerminalApp/Pane.h index 0aa41958e1f..088cadeb25c 100644 --- a/src/cascadia/TerminalApp/Pane.h +++ b/src/cascadia/TerminalApp/Pane.h @@ -145,7 +145,7 @@ class Pane : public std::enable_shared_from_this winrt::fire_and_forget _CloseChildRoutine(const bool closeFirst); void _FocusFirstChild(); - void _ControlConnectionStateChangedHandler(const winrt::Microsoft::Terminal::TerminalControl::TermControl& sender, const winrt::Windows::Foundation::IInspectable& /*args*/); + void _ControlConnectionStateChangedHandler(const winrt::Windows::Foundation::IInspectable& sender, const winrt::Windows::Foundation::IInspectable& /*args*/); void _ControlWarningBellHandler(winrt::Windows::Foundation::IInspectable const& sender, winrt::Windows::Foundation::IInspectable const& e); void _ControlGotFocusHandler(winrt::Windows::Foundation::IInspectable const& sender, diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp index 363db082fd6..aa3f962380c 100644 --- a/src/cascadia/TerminalApp/TerminalPage.cpp +++ b/src/cascadia/TerminalApp/TerminalPage.cpp @@ -1784,7 +1784,7 @@ namespace winrt::TerminalApp::implementation { // The magic value of WHEEL_PAGESCROLL indicates that we need to scroll the entire page realRowsToScroll = _systemRowsToScroll == WHEEL_PAGESCROLL ? - terminalTab->GetActiveTerminalControl().GetViewHeight() : + terminalTab->GetActiveTerminalControl().ViewHeight() : _systemRowsToScroll; } else @@ -1924,7 +1924,7 @@ namespace winrt::TerminalApp::implementation if (const auto terminalTab{ _GetFocusedTabImpl() }) { const auto control = _GetActiveControl(); - const auto termHeight = control.GetViewHeight(); + const auto termHeight = control.ViewHeight(); auto scrollDelta = _ComputeScrollDelta(scrollDirection, termHeight); terminalTab->Scroll(scrollDelta); } diff --git a/src/cascadia/TerminalApp/TerminalPage.h b/src/cascadia/TerminalApp/TerminalPage.h index b0a5c89e76c..17471e2448e 100644 --- a/src/cascadia/TerminalApp/TerminalPage.h +++ b/src/cascadia/TerminalApp/TerminalPage.h @@ -223,7 +223,7 @@ namespace winrt::TerminalApp::implementation void _ShowCouldNotOpenDialog(winrt::hstring reason, winrt::hstring uri); bool _CopyText(const bool singleLine, const Windows::Foundation::IReference& formats); - void _SetTaskbarProgressHandler(const IInspectable sender, const IInspectable eventArgs); + winrt::fire_and_forget _SetTaskbarProgressHandler(const IInspectable sender, const IInspectable eventArgs); void _PasteText(); diff --git a/src/cascadia/TerminalApp/TerminalTab.cpp b/src/cascadia/TerminalApp/TerminalTab.cpp index cf259efdb5f..a096cb18762 100644 --- a/src/cascadia/TerminalApp/TerminalTab.cpp +++ b/src/cascadia/TerminalApp/TerminalTab.cpp @@ -388,7 +388,7 @@ namespace winrt::TerminalApp::implementation co_await winrt::resume_foreground(control.Dispatcher()); - const auto currentOffset = control.GetScrollOffset(); + const auto currentOffset = control.ScrollOffset(); control.ScrollViewport(::base::ClampAdd(currentOffset, delta)); } @@ -552,7 +552,7 @@ namespace winrt::TerminalApp::implementation { auto weakThis{ get_weak() }; - control.TitleChanged([weakThis](auto newTitle) { + control.TitleChanged([weakThis](auto&&, auto&&) { // Check if Tab's lifetime has expired if (auto tab{ weakThis.get() }) { From acf84f188fa9a41ebc6ae265de1b6bd97e609cba Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Thu, 11 Mar 2021 11:01:26 -0600 Subject: [PATCH 03/82] hey look it launches. But there's definitely a good amount of broken features O.o --- src/cascadia/TerminalControl/ControlCore.cpp | 2 +- src/cascadia/TerminalControl/ControlCore.h | 33 ++++++++++---------- src/cascadia/TerminalControl/TermControl.cpp | 25 ++++++++++++--- 3 files changed, 39 insertions(+), 21 deletions(-) diff --git a/src/cascadia/TerminalControl/ControlCore.cpp b/src/cascadia/TerminalControl/ControlCore.cpp index d58d4d35f6f..34f3d07b6d8 100644 --- a/src/cascadia/TerminalControl/ControlCore.cpp +++ b/src/cascadia/TerminalControl/ControlCore.cpp @@ -194,7 +194,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation // Tell the DX Engine to notify us when the swap chain changes. // We do this after we initially set the swapchain so as to avoid unnecessary callbacks (and locking problems) - _renderEngine->SetCallback(std::bind(&ControlCore::RenderEngineSwapChainChanged, this)); + dxEngine->SetCallback(std::bind(&ControlCore::RenderEngineSwapChainChanged, this)); dxEngine->SetRetroTerminalEffect(_settings.RetroTerminalEffect()); dxEngine->SetPixelShaderPath(_settings.PixelShaderPath()); diff --git a/src/cascadia/TerminalControl/ControlCore.h b/src/cascadia/TerminalControl/ControlCore.h index d6df600bf32..a83c5a81364 100644 --- a/src/cascadia/TerminalControl/ControlCore.h +++ b/src/cascadia/TerminalControl/ControlCore.h @@ -24,44 +24,45 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation //////////////////////////////////////////////////////////////////////// // These members are taken from TermControl - bool _initializedTerminal; + std::unique_ptr<::Microsoft::Console::Render::Renderer> _renderer{ nullptr }; - TerminalConnection::ITerminalConnection _connection; + private: + bool _initializedTerminal{ false }; + + TerminalConnection::ITerminalConnection _connection{ nullptr }; event_token _connectionOutputEventToken; TerminalConnection::ITerminalConnection::StateChanged_revoker _connectionStateChangedRevoker; - std::unique_ptr<::Microsoft::Terminal::Core::Terminal> _terminal; - std::unique_ptr<::Microsoft::Console::Render::Renderer> _renderer; + std::unique_ptr<::Microsoft::Terminal::Core::Terminal> _terminal{ nullptr }; - private: - std::unique_ptr<::Microsoft::Console::Render::DxEngine> _renderEngine; + std::unique_ptr<::Microsoft::Console::Render::DxEngine> _renderEngine{ nullptr }; - IControlSettings _settings; // ? Might be able to get away with only retrieving pieces + IControlSettings _settings{ nullptr }; // ? Might be able to get away with only retrieving pieces FontInfoDesired _desiredFont; FontInfo _actualFont; - public: // storage location for the leading surrogate of a utf-16 surrogate pair - std::optional _leadingSurrogate; + std::optional _leadingSurrogate{ std::nullopt }; bool _isReadOnly{ false }; // ? - std::optional _lastHoveredCell; + std::optional _lastHoveredCell{ std::nullopt }; // Track the last hyperlink ID we hovered over - uint16_t _lastHoveredId; + uint16_t _lastHoveredId{ 0 }; - std::optional::interval> _lastHoveredInterval; + std::optional::interval> _lastHoveredInterval{ std::nullopt }; //////////////////////////////////////////////////////////////////////// // These members are new - double _panelWidth; - double _panelHeight; - double _compositionScaleX; - double _compositionScaleY; + double _panelWidth{ 0 }; + double _panelHeight{ 0 }; + double _compositionScaleX{ 0 }; + double _compositionScaleY{ 0 }; til::color _backgroundColor; // This is _in_ Terminal already! //////////////////////////////////////////////////////////////////////// + public: //////////////////////////////////////////////////////////////////////// // These methods are taken from TermControl bool InitializeTerminal(const double actualWidth, diff --git a/src/cascadia/TerminalControl/TermControl.cpp b/src/cascadia/TerminalControl/TermControl.cpp index 757defc8e27..2c64f964dae 100644 --- a/src/cascadia/TerminalControl/TermControl.cpp +++ b/src/cascadia/TerminalControl/TermControl.cpp @@ -596,16 +596,33 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation return false; } + const auto panelWidth = SwapChainPanel().ActualWidth(); + const auto panelHeight = SwapChainPanel().ActualHeight(); + const auto panelScaleX = SwapChainPanel().CompositionScaleX(); + const auto panelScaleY = SwapChainPanel().CompositionScaleY(); + + const auto windowWidth = panelWidth * panelScaleX; + const auto windowHeight = panelHeight * panelScaleY; + + if (windowWidth == 0 || windowHeight == 0) + { + return false; + } + // IMPORTANT! Set this callback up sooner than later. If we do it // after Enable, then it'll be possible to paint the frame once // _before_ the warning handler is set up, and then warnings from // the first paint will be ignored! _core->RendererWarning({ get_weak(), &TermControl::_RendererWarning }); - _core->InitializeTerminal(SwapChainPanel().ActualWidth(), - SwapChainPanel().ActualHeight(), - SwapChainPanel().CompositionScaleX(), - SwapChainPanel().CompositionScaleY()); + const auto coreInitialized = _core->InitializeTerminal(panelWidth, + panelHeight, + panelScaleX, + panelScaleY); + if (!coreInitialized) + { + return false; + } _AttachDxgiSwapChainToXaml(_core->GetSwapChainHandle()); From 5e655ef2d851fd9506486d5f91570428d9ff608d Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Thu, 11 Mar 2021 12:47:22 -0600 Subject: [PATCH 04/82] I wasn't the murderer after all --- src/cascadia/TerminalControl/ControlCore.cpp | 34 ++++++-------------- src/cascadia/TerminalControl/ControlCore.h | 1 + src/cascadia/TerminalControl/TermControl.cpp | 8 +++-- src/cascadia/TerminalControl/TermControl.h | 2 +- src/cascadia/TerminalCore/Terminal.cpp | 1 + 5 files changed, 19 insertions(+), 27 deletions(-) diff --git a/src/cascadia/TerminalControl/ControlCore.cpp b/src/cascadia/TerminalControl/ControlCore.cpp index 34f3d07b6d8..04b0e7d1d58 100644 --- a/src/cascadia/TerminalControl/ControlCore.cpp +++ b/src/cascadia/TerminalControl/ControlCore.cpp @@ -144,13 +144,12 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation _renderer = std::make_unique<::Microsoft::Console::Render::Renderer>(_terminal.get(), nullptr, 0, std::move(renderThread)); ::Microsoft::Console::Render::IRenderTarget& renderTarget = *_renderer; - // !TODO!: We _DO_ want this - // _renderer->SetRendererEnteredErrorStateCallback([weakThis = get_weak()]() { - // if (auto strongThis{ weakThis.get() }) - // { - // strongThis->_RendererEnteredErrorState(); - // } - // }); + _renderer->SetRendererEnteredErrorStateCallback([weakThis = get_weak()]() { + if (auto strongThis{ weakThis.get() }) + { + strongThis->_RendererEnteredErrorStateHandlers(*strongThis, nullptr); + } + }); THROW_IF_FAILED(localPointerToThread->Initialize(_renderer.get())); @@ -225,9 +224,9 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation THROW_IF_FAILED(dxEngine->Enable()); _renderEngine = std::move(dxEngine); - // !TODO! in the past we did _AttachDxgiSwapChainToXaml _before_ calling - // EnablePainting. Mild worry that doing EnablePainting first will - // break + // In the past we did _AttachDxgiSwapChainToXaml _before_ calling + // EnablePainting. There's mild worry that doing EnablePainting + // first will break something, but this seems to work. localPointerToThread->EnablePainting(); _initializedTerminal = true; @@ -237,10 +236,6 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation // start writing output immediately. _connection.Start(); - // !TODO!: Do we want this? - // Likewise, run the event handlers outside of lock (they could - // be reentrant) - // _InitializedHandlers(*this, nullptr); return true; } // Method Description: @@ -979,14 +974,6 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation const int viewHeight, const int bufferSize) { - // !!TODO!! do we need this? - // // Since this callback fires from non-UI thread, we might be already - // // closed/closing. - // if (_closing.load()) - // { - // return; - // } - // Clear the regex pattern tree so the renderer does not try to render // them while scrolling _terminal->ClearPatternTree(); @@ -1034,8 +1021,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation const bool goForward, const bool caseSensitive) { - // !!TODO!! do we need this? - if (text.size() == 0 /* || _closing*/) + if (text.size() == 0) { return; } diff --git a/src/cascadia/TerminalControl/ControlCore.h b/src/cascadia/TerminalControl/ControlCore.h index a83c5a81364..f83f50c5f65 100644 --- a/src/cascadia/TerminalControl/ControlCore.h +++ b/src/cascadia/TerminalControl/ControlCore.h @@ -203,6 +203,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation TYPED_EVENT(HoveredHyperlinkChanged, IInspectable, IInspectable); + TYPED_EVENT(RendererEnteredErrorState, IInspectable, IInspectable); TYPED_EVENT(SwapChainChanged, IInspectable, IInspectable); TYPED_EVENT(RendererWarning, IInspectable, TerminalControl::RendererWarningArgs); }; diff --git a/src/cascadia/TerminalControl/TermControl.cpp b/src/cascadia/TerminalControl/TermControl.cpp index 2c64f964dae..bc617d693c7 100644 --- a/src/cascadia/TerminalControl/TermControl.cpp +++ b/src/cascadia/TerminalControl/TermControl.cpp @@ -88,6 +88,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation _core->BackgroundColorChanged({ get_weak(), &TermControl::_BackgroundColorChangedHandler }); _core->ScrollPositionChanged({ get_weak(), &TermControl::_ScrollPositionChanged }); _core->CursorPositionChanged({ get_weak(), &TermControl::_CursorPositionChanged }); + _core->RendererEnteredErrorState({ get_weak(), &TermControl::_RendererEnteredErrorState }); // Initialize the terminal only once the swapchainpanel is loaded - that // way, we'll be able to query the real pixel size it got on layout @@ -1087,7 +1088,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation const auto cursorPosition = point.Position(); const auto terminalPosition = _GetTerminalPosition(cursorPosition); - const auto clickCount = _NumberOfClicks(cursorPosition, point.Timestamp()); + // const auto clickCount = _NumberOfClicks(cursorPosition, point.Timestamp()); // GH#9396: we prioritize hyper-link over VT mouse events // @@ -1096,6 +1097,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation if (point.Properties().IsLeftButtonPressed() && ctrlEnabled && !hyperlink.empty()) { + const auto clickCount = _NumberOfClicks(cursorPosition, point.Timestamp()); // Handle hyper-link only on the first click to prevent multiple activations if (clickCount == 1) { @@ -1108,6 +1110,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation } else if (point.Properties().IsLeftButtonPressed()) { + const auto clickCount = _NumberOfClicks(cursorPosition, point.Timestamp()); // This formula enables the number of clicks to cycle properly // between single-, double-, and triple-click. To increase the // number of acceptable click states, simply increment @@ -2584,7 +2587,8 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation // Method Description: // - Produces the error dialog that notifies the user that rendering cannot proceed. - winrt::fire_and_forget TermControl::_RendererEnteredErrorState() + winrt::fire_and_forget TermControl::_RendererEnteredErrorState(IInspectable const& /*sender*/, + IInspectable const& /*args*/) { auto strongThis{ get_strong() }; co_await Dispatcher(); // pop up onto the UI thread diff --git a/src/cascadia/TerminalControl/TermControl.h b/src/cascadia/TerminalControl/TermControl.h index ff66dd6db1c..5bf0f69fb63 100644 --- a/src/cascadia/TerminalControl/TermControl.h +++ b/src/cascadia/TerminalControl/TermControl.h @@ -54,7 +54,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation winrt::fire_and_forget RenderEngineSwapChainChanged(const IInspectable& sender, const IInspectable& args); void _AttachDxgiSwapChainToXaml(HANDLE swapChainHandle); - winrt::fire_and_forget _RendererEnteredErrorState(); + winrt::fire_and_forget _RendererEnteredErrorState(const IInspectable& sender, const IInspectable& args); void _RenderRetryButton_Click(IInspectable const& button, IInspectable const& args); winrt::fire_and_forget _RendererWarning(const IInspectable& sender, const TerminalControl::RendererWarningArgs& args); diff --git a/src/cascadia/TerminalCore/Terminal.cpp b/src/cascadia/TerminalCore/Terminal.cpp index 942def662ca..cc09e98c9ec 100644 --- a/src/cascadia/TerminalCore/Terminal.cpp +++ b/src/cascadia/TerminalCore/Terminal.cpp @@ -1196,6 +1196,7 @@ void Terminal::UpdatePatterns() noexcept // visible region is changing void Terminal::ClearPatternTree() noexcept { + auto lock = LockForWriting(); auto oldTree = _patternIntervalTree; _patternIntervalTree = {}; _InvalidatePatternTree(oldTree); From 2402c59f3da0062e2e297ef269affb93539d697a Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Fri, 12 Mar 2021 06:56:33 -0600 Subject: [PATCH 05/82] Hokay, so that gets the control as a lib/dll split --- OpenConsole.sln | 45 +++++++-- .../SettingsModel.LocalTests.vcxproj | 2 +- .../TerminalApp.LocalTests.vcxproj | 2 +- .../TestHostApp/TestHostApp.vcxproj | 2 +- .../TerminalApp/dll/TerminalApp.vcxproj | 2 +- .../TerminalControl/IControlSettings.idl | 2 +- src/cascadia/TerminalControl/TermControl.h | 1 + ...rol.vcxproj => TerminalControlLib.vcxproj} | 93 +++++++------------ .../{ => dll}/TerminalControl.def | 0 .../dll/TerminalControl.vcxproj | 85 +++++++++++++++++ src/cascadia/TerminalControl/dll/pch.cpp | 4 + src/cascadia/TerminalControl/dll/pch.h | 8 ++ src/cascadia/TerminalCore/ICoreSettings.idl | 2 +- src/cascadia/TerminalCore/Terminal.cpp | 4 +- src/cascadia/TerminalCore/Terminal.hpp | 6 +- .../TerminalCore/lib/terminalcore-lib.vcxproj | 2 +- .../WindowsTerminal/WindowsTerminal.vcxproj | 2 +- .../WindowsTerminalUniversal.vcxproj | 2 +- 18 files changed, 186 insertions(+), 78 deletions(-) rename src/cascadia/TerminalControl/{TerminalControl.vcxproj => TerminalControlLib.vcxproj} (69%) rename src/cascadia/TerminalControl/{ => dll}/TerminalControl.def (100%) create mode 100644 src/cascadia/TerminalControl/dll/TerminalControl.vcxproj create mode 100644 src/cascadia/TerminalControl/dll/pch.cpp create mode 100644 src/cascadia/TerminalControl/dll/pch.h diff --git a/OpenConsole.sln b/OpenConsole.sln index 2d59b001236..13ecec8318b 100644 --- a/OpenConsole.sln +++ b/OpenConsole.sln @@ -161,7 +161,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TerminalConnection", "src\c EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TerminalCore", "src\cascadia\TerminalCore\lib\TerminalCore-lib.vcxproj", "{CA5CAD1A-ABCD-429C-B551-8562EC954746}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TerminalControl", "src\cascadia\TerminalControl\TerminalControl.vcxproj", "{CA5CAD1A-44BD-4AC7-AC72-6CA5B3AB89ED}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TerminalControlLib", "src\cascadia\TerminalControl\TerminalControlLib.vcxproj", "{CA5CAD1A-44BD-4AC7-AC72-6CA5B3AB89ED}" ProjectSection(ProjectDependencies) = postProject {CA5CAD1A-C46D-4588-B1C0-40F31AE9100B} = {CA5CAD1A-C46D-4588-B1C0-40F31AE9100B} {CA5CAD1A-ABCD-429C-B551-8562EC954746} = {CA5CAD1A-ABCD-429C-B551-8562EC954746} @@ -169,10 +169,15 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TerminalControl", "src\casc {48D21369-3D7B-4431-9967-24E81292CF63} = {48D21369-3D7B-4431-9967-24E81292CF63} EndProjectSection EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TerminalControl", "src\cascadia\TerminalControl\dll\TerminalControl.vcxproj", "{CA5CAD1A-5555-4AC7-AC72-6CA5B3AB89ED}" + ProjectSection(ProjectDependencies) = postProject + {CA5CAD1A-44BD-4AC7-AC72-6CA5B3AB89ED} = {CA5CAD1A-44BD-4AC7-AC72-6CA5B3AB89ED} + EndProjectSection +EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WindowsTerminal", "src\cascadia\WindowsTerminal\WindowsTerminal.vcxproj", "{CA5CAD1A-1754-4A9D-93D7-857A9D17CB1B}" ProjectSection(ProjectDependencies) = postProject {CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32} = {CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32} - {CA5CAD1A-44BD-4AC7-AC72-6CA5B3AB89ED} = {CA5CAD1A-44BD-4AC7-AC72-6CA5B3AB89ED} + {CA5CAD1A-5555-4AC7-AC72-6CA5B3AB89ED} = {CA5CAD1A-5555-4AC7-AC72-6CA5B3AB89ED} {CA5CAD1A-44BD-4AC7-AC72-F16E576FDD12} = {CA5CAD1A-44BD-4AC7-AC72-F16E576FDD12} {CA5CAD1A-ABCD-429C-B551-8562EC954746} = {CA5CAD1A-ABCD-429C-B551-8562EC954746} {27B5AAEB-A548-44CF-9777-F8BAA32AF7AE} = {27B5AAEB-A548-44CF-9777-F8BAA32AF7AE} @@ -185,7 +190,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TerminalApp", "src\cascadia {CA5CAD1A-082C-4476-9F33-94B339494076} = {CA5CAD1A-082C-4476-9F33-94B339494076} {CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32} = {CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32} {CA5CAD1A-C46D-4588-B1C0-40F31AE9100B} = {CA5CAD1A-C46D-4588-B1C0-40F31AE9100B} - {CA5CAD1A-44BD-4AC7-AC72-6CA5B3AB89ED} = {CA5CAD1A-44BD-4AC7-AC72-6CA5B3AB89ED} + {CA5CAD1A-5555-4AC7-AC72-6CA5B3AB89ED} = {CA5CAD1A-5555-4AC7-AC72-6CA5B3AB89ED} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WindowsTerminalShellExt", "src\cascadia\ShellExtension\WindowsTerminalShellExt.vcxproj", "{F2ED628A-DB22-446F-A081-4CC845B51A2B}" @@ -236,7 +241,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TerminalAppLib", "src\casca ProjectSection(ProjectDependencies) = postProject {CA5CAD1A-082C-4476-9F33-94B339494076} = {CA5CAD1A-082C-4476-9F33-94B339494076} {CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32} = {CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32} - {CA5CAD1A-44BD-4AC7-AC72-6CA5B3AB89ED} = {CA5CAD1A-44BD-4AC7-AC72-6CA5B3AB89ED} + {CA5CAD1A-5555-4AC7-AC72-6CA5B3AB89ED} = {CA5CAD1A-5555-4AC7-AC72-6CA5B3AB89ED} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LocalTests_TerminalApp", "src\cascadia\LocalTests_TerminalApp\TerminalApp.LocalTests.vcxproj", "{CA5CAD1A-B11C-4DDB-A4FE-C3AFAE9B5506}" @@ -326,7 +331,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Microsoft.Terminal.Settings EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Microsoft.Terminal.Settings.Model.Lib", "src\cascadia\TerminalSettingsModel\Microsoft.Terminal.Settings.ModelLib.vcxproj", "{CA5CAD1A-D7EC-4107-B7C6-79CB77AE2907}" ProjectSection(ProjectDependencies) = postProject - {CA5CAD1A-44BD-4AC7-AC72-6CA5B3AB89ED} = {CA5CAD1A-44BD-4AC7-AC72-6CA5B3AB89ED} + {CA5CAD1A-5555-4AC7-AC72-6CA5B3AB89ED} = {CA5CAD1A-5555-4AC7-AC72-6CA5B3AB89ED} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Microsoft.Terminal.Settings.Model", "src\cascadia\TerminalSettingsModel\dll\Microsoft.Terminal.Settings.Model.vcxproj", "{CA5CAD1A-082C-4476-9F33-94B339494076}" @@ -338,7 +343,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LocalTests_SettingsModel", ProjectSection(ProjectDependencies) = postProject {CA5CAD1A-082C-4476-9F33-94B339494076} = {CA5CAD1A-082C-4476-9F33-94B339494076} {CA5CAD1A-C46D-4588-B1C0-40F31AE9100B} = {CA5CAD1A-C46D-4588-B1C0-40F31AE9100B} - {CA5CAD1A-44BD-4AC7-AC72-6CA5B3AB89ED} = {CA5CAD1A-44BD-4AC7-AC72-6CA5B3AB89ED} + {CA5CAD1A-5555-4AC7-AC72-6CA5B3AB89ED} = {CA5CAD1A-5555-4AC7-AC72-6CA5B3AB89ED} {CA5CAD1A-D7EC-4107-B7C6-79CB77AE2907} = {CA5CAD1A-D7EC-4107-B7C6-79CB77AE2907} EndProjectSection EndProject @@ -1518,6 +1523,33 @@ Global {CA5CAD1A-44BD-4AC7-AC72-6CA5B3AB89ED}.Release|x64.Build.0 = Release|x64 {CA5CAD1A-44BD-4AC7-AC72-6CA5B3AB89ED}.Release|x86.ActiveCfg = Release|Win32 {CA5CAD1A-44BD-4AC7-AC72-6CA5B3AB89ED}.Release|x86.Build.0 = Release|Win32 + {CA5CAD1A-5555-4AC7-AC72-6CA5B3AB89ED}.AuditMode|Any CPU.ActiveCfg = Debug|Win32 + {CA5CAD1A-5555-4AC7-AC72-6CA5B3AB89ED}.AuditMode|ARM.ActiveCfg = AuditMode|Win32 + {CA5CAD1A-5555-4AC7-AC72-6CA5B3AB89ED}.AuditMode|ARM64.ActiveCfg = Release|ARM64 + {CA5CAD1A-5555-4AC7-AC72-6CA5B3AB89ED}.AuditMode|DotNet_x64Test.ActiveCfg = Debug|Win32 + {CA5CAD1A-5555-4AC7-AC72-6CA5B3AB89ED}.AuditMode|DotNet_x86Test.ActiveCfg = Debug|Win32 + {CA5CAD1A-5555-4AC7-AC72-6CA5B3AB89ED}.AuditMode|x64.ActiveCfg = Release|x64 + {CA5CAD1A-5555-4AC7-AC72-6CA5B3AB89ED}.AuditMode|x86.ActiveCfg = Release|Win32 + {CA5CAD1A-5555-4AC7-AC72-6CA5B3AB89ED}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {CA5CAD1A-5555-4AC7-AC72-6CA5B3AB89ED}.Debug|ARM.ActiveCfg = Debug|Win32 + {CA5CAD1A-5555-4AC7-AC72-6CA5B3AB89ED}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {CA5CAD1A-5555-4AC7-AC72-6CA5B3AB89ED}.Debug|ARM64.Build.0 = Debug|ARM64 + {CA5CAD1A-5555-4AC7-AC72-6CA5B3AB89ED}.Debug|DotNet_x64Test.ActiveCfg = Debug|Win32 + {CA5CAD1A-5555-4AC7-AC72-6CA5B3AB89ED}.Debug|DotNet_x86Test.ActiveCfg = Debug|Win32 + {CA5CAD1A-5555-4AC7-AC72-6CA5B3AB89ED}.Debug|x64.ActiveCfg = Debug|x64 + {CA5CAD1A-5555-4AC7-AC72-6CA5B3AB89ED}.Debug|x64.Build.0 = Debug|x64 + {CA5CAD1A-5555-4AC7-AC72-6CA5B3AB89ED}.Debug|x86.ActiveCfg = Debug|Win32 + {CA5CAD1A-5555-4AC7-AC72-6CA5B3AB89ED}.Debug|x86.Build.0 = Debug|Win32 + {CA5CAD1A-5555-4AC7-AC72-6CA5B3AB89ED}.Release|Any CPU.ActiveCfg = Release|Win32 + {CA5CAD1A-5555-4AC7-AC72-6CA5B3AB89ED}.Release|ARM.ActiveCfg = Release|Win32 + {CA5CAD1A-5555-4AC7-AC72-6CA5B3AB89ED}.Release|ARM64.ActiveCfg = Release|ARM64 + {CA5CAD1A-5555-4AC7-AC72-6CA5B3AB89ED}.Release|ARM64.Build.0 = Release|ARM64 + {CA5CAD1A-5555-4AC7-AC72-6CA5B3AB89ED}.Release|DotNet_x64Test.ActiveCfg = Release|Win32 + {CA5CAD1A-5555-4AC7-AC72-6CA5B3AB89ED}.Release|DotNet_x86Test.ActiveCfg = Release|Win32 + {CA5CAD1A-5555-4AC7-AC72-6CA5B3AB89ED}.Release|x64.ActiveCfg = Release|x64 + {CA5CAD1A-5555-4AC7-AC72-6CA5B3AB89ED}.Release|x64.Build.0 = Release|x64 + {CA5CAD1A-5555-4AC7-AC72-6CA5B3AB89ED}.Release|x86.ActiveCfg = Release|Win32 + {CA5CAD1A-5555-4AC7-AC72-6CA5B3AB89ED}.Release|x86.Build.0 = Release|Win32 {CA5CAD1A-1754-4A9D-93D7-857A9D17CB1B}.AuditMode|Any CPU.ActiveCfg = Debug|x64 {CA5CAD1A-1754-4A9D-93D7-857A9D17CB1B}.AuditMode|ARM.ActiveCfg = AuditMode|Win32 {CA5CAD1A-1754-4A9D-93D7-857A9D17CB1B}.AuditMode|ARM64.ActiveCfg = Release|ARM64 @@ -2619,6 +2651,7 @@ Global {CA5CAD1A-C46D-4588-B1C0-40F31AE9100B} = {59840756-302F-44DF-AA47-441A9D673202} {CA5CAD1A-ABCD-429C-B551-8562EC954746} = {59840756-302F-44DF-AA47-441A9D673202} {CA5CAD1A-44BD-4AC7-AC72-6CA5B3AB89ED} = {59840756-302F-44DF-AA47-441A9D673202} + {CA5CAD1A-5555-4AC7-AC72-6CA5B3AB89ED} = {59840756-302F-44DF-AA47-441A9D673202} {CA5CAD1A-1754-4A9D-93D7-857A9D17CB1B} = {59840756-302F-44DF-AA47-441A9D673202} {CA5CAD1A-44BD-4AC7-AC72-F16E576FDD12} = {59840756-302F-44DF-AA47-441A9D673202} {F2ED628A-DB22-446F-A081-4CC845B51A2B} = {59840756-302F-44DF-AA47-441A9D673202} diff --git a/src/cascadia/LocalTests_SettingsModel/SettingsModel.LocalTests.vcxproj b/src/cascadia/LocalTests_SettingsModel/SettingsModel.LocalTests.vcxproj index fc904d3740a..91818da434e 100644 --- a/src/cascadia/LocalTests_SettingsModel/SettingsModel.LocalTests.vcxproj +++ b/src/cascadia/LocalTests_SettingsModel/SettingsModel.LocalTests.vcxproj @@ -57,7 +57,7 @@ - + diff --git a/src/cascadia/LocalTests_TerminalApp/TerminalApp.LocalTests.vcxproj b/src/cascadia/LocalTests_TerminalApp/TerminalApp.LocalTests.vcxproj index 8363792372b..66edaa8cc4f 100644 --- a/src/cascadia/LocalTests_TerminalApp/TerminalApp.LocalTests.vcxproj +++ b/src/cascadia/LocalTests_TerminalApp/TerminalApp.LocalTests.vcxproj @@ -59,7 +59,7 @@ - + diff --git a/src/cascadia/LocalTests_TerminalApp/TestHostApp/TestHostApp.vcxproj b/src/cascadia/LocalTests_TerminalApp/TestHostApp/TestHostApp.vcxproj index 384356df6f5..d8e127175fb 100644 --- a/src/cascadia/LocalTests_TerminalApp/TestHostApp/TestHostApp.vcxproj +++ b/src/cascadia/LocalTests_TerminalApp/TestHostApp/TestHostApp.vcxproj @@ -97,7 +97,7 @@ - + {ca5cad1a-44bd-4ac7-ac72-f16e576fdd12} diff --git a/src/cascadia/TerminalApp/dll/TerminalApp.vcxproj b/src/cascadia/TerminalApp/dll/TerminalApp.vcxproj index 05d0b9a19c8..1e963a84932 100644 --- a/src/cascadia/TerminalApp/dll/TerminalApp.vcxproj +++ b/src/cascadia/TerminalApp/dll/TerminalApp.vcxproj @@ -63,7 +63,7 @@ somehow. So make sure to only include top-level dependencies here (don't include Settings and Connection, since Control will include them for us) --> - + - - DynamicLibrary + Microsoft.Terminal.TerminalControl.Lib + 10.0.17763.0 + StaticLibrary Console - true + 3 nested + + + @@ -43,6 +47,7 @@ + Create @@ -67,6 +72,7 @@ + @@ -83,13 +89,23 @@ TSFInputControl.xaml + - - + + Designer + + + Designer + + + Designer + + + @@ -110,61 +126,22 @@ false - - - Designer - - - Designer - - - Designer - - - + - - 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) - + pch.h $(OpenConsoleDir)src\cascadia\inc;$(OpenConsoleDir)src\types\inc;%(AdditionalIncludeDirectories) + + 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) + + + + false + - + + - - - $(MarkupCompilePass1DependsOn);OpenConsoleStripDuplicateWinmdFromReferencesBeforePass1 - $(MarkupCompilePass2DependsOn);OpenConsoleStripDuplicateWinmdFromReferencesBeforePass2 - - - - - - - - - - - - - - - - - - - - + diff --git a/src/cascadia/TerminalControl/TerminalControl.def b/src/cascadia/TerminalControl/dll/TerminalControl.def similarity index 100% rename from src/cascadia/TerminalControl/TerminalControl.def rename to src/cascadia/TerminalControl/dll/TerminalControl.def diff --git a/src/cascadia/TerminalControl/dll/TerminalControl.vcxproj b/src/cascadia/TerminalControl/dll/TerminalControl.vcxproj new file mode 100644 index 00000000000..723b4f42ef1 --- /dev/null +++ b/src/cascadia/TerminalControl/dll/TerminalControl.vcxproj @@ -0,0 +1,85 @@ + + + + {CA5CAD1A-5555-4AC7-AC72-6CA5B3AB89ED} + TerminalControl + + Microsoft.Terminal.TerminalControl + + + DynamicLibrary + Console + + true + + + + + + + + + + + + + + + + + Create + + + + + + + + + + + + + + + + {18D09A24-8240-42D6-8CB6-236EEE820263} + + + + + + + + + + + + true + true + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + + + 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) + + /INCLUDE:_DllMain@12 + /INCLUDE:DllMain + + + + diff --git a/src/cascadia/TerminalControl/dll/pch.cpp b/src/cascadia/TerminalControl/dll/pch.cpp new file mode 100644 index 00000000000..3c27d44d570 --- /dev/null +++ b/src/cascadia/TerminalControl/dll/pch.cpp @@ -0,0 +1,4 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +#include "pch.h" diff --git a/src/cascadia/TerminalControl/dll/pch.h b/src/cascadia/TerminalControl/dll/pch.h new file mode 100644 index 00000000000..b90061aecb7 --- /dev/null +++ b/src/cascadia/TerminalControl/dll/pch.h @@ -0,0 +1,8 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. +// +// pch.h +// Header for platform projection include files +// + +#pragma once diff --git a/src/cascadia/TerminalCore/ICoreSettings.idl b/src/cascadia/TerminalCore/ICoreSettings.idl index ebba05f4864..b3caf8c9170 100644 --- a/src/cascadia/TerminalCore/ICoreSettings.idl +++ b/src/cascadia/TerminalCore/ICoreSettings.idl @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. -namespace Microsoft.Terminal.TerminalControl +namespace Microsoft.Terminal.Core { enum CursorStyle { diff --git a/src/cascadia/TerminalCore/Terminal.cpp b/src/cascadia/TerminalCore/Terminal.cpp index 942def662ca..3d0a0b81098 100644 --- a/src/cascadia/TerminalCore/Terminal.cpp +++ b/src/cascadia/TerminalCore/Terminal.cpp @@ -11,9 +11,9 @@ #include "../../types/inc/utils.hpp" #include "../../types/inc/colorTable.hpp" -#include +#include -using namespace winrt::Microsoft::Terminal::TerminalControl; +using namespace winrt::Microsoft::Terminal::Core; using namespace Microsoft::Terminal::Core; using namespace Microsoft::Console; using namespace Microsoft::Console::Render; diff --git a/src/cascadia/TerminalCore/Terminal.hpp b/src/cascadia/TerminalCore/Terminal.hpp index fac17b22979..732e545e55e 100644 --- a/src/cascadia/TerminalCore/Terminal.hpp +++ b/src/cascadia/TerminalCore/Terminal.hpp @@ -20,7 +20,7 @@ // You have to forward decl the ICoreSettings here, instead of including the header. // If you include the header, there will be compilation errors with other // headers that include Terminal.hpp -namespace winrt::Microsoft::Terminal::TerminalControl +namespace winrt::Microsoft::Terminal::Core { struct ICoreSettings; } @@ -59,10 +59,10 @@ class Microsoft::Terminal::Core::Terminal final : SHORT scrollbackLines, Microsoft::Console::Render::IRenderTarget& renderTarget); - void CreateFromSettings(winrt::Microsoft::Terminal::TerminalControl::ICoreSettings settings, + void CreateFromSettings(winrt::Microsoft::Terminal::Core::ICoreSettings settings, Microsoft::Console::Render::IRenderTarget& renderTarget); - void UpdateSettings(winrt::Microsoft::Terminal::TerminalControl::ICoreSettings settings); + void UpdateSettings(winrt::Microsoft::Terminal::Core::ICoreSettings settings); // Write goes through the parser void Write(std::wstring_view stringView); diff --git a/src/cascadia/TerminalCore/lib/terminalcore-lib.vcxproj b/src/cascadia/TerminalCore/lib/terminalcore-lib.vcxproj index 44bb357f6bf..33520d4c745 100644 --- a/src/cascadia/TerminalCore/lib/terminalcore-lib.vcxproj +++ b/src/cascadia/TerminalCore/lib/terminalcore-lib.vcxproj @@ -7,7 +7,7 @@ TerminalCore StaticLibrary 10.0.17763.0 - Microsoft.Terminal.TerminalControl + Microsoft.Terminal.Core true diff --git a/src/cascadia/WindowsTerminal/WindowsTerminal.vcxproj b/src/cascadia/WindowsTerminal/WindowsTerminal.vcxproj index aa45f987aba..deb94e6d33d 100644 --- a/src/cascadia/WindowsTerminal/WindowsTerminal.vcxproj +++ b/src/cascadia/WindowsTerminal/WindowsTerminal.vcxproj @@ -72,7 +72,7 @@ - + diff --git a/src/cascadia/WindowsTerminalUniversal/WindowsTerminalUniversal.vcxproj b/src/cascadia/WindowsTerminalUniversal/WindowsTerminalUniversal.vcxproj index b1e16fc121c..335c9cf13b2 100644 --- a/src/cascadia/WindowsTerminalUniversal/WindowsTerminalUniversal.vcxproj +++ b/src/cascadia/WindowsTerminalUniversal/WindowsTerminalUniversal.vcxproj @@ -61,7 +61,7 @@ - + From 24765d708a437c2c952cd300a0715cc716975cdf Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Fri, 12 Mar 2021 09:24:40 -0600 Subject: [PATCH 06/82] its-all-coming-together.gif --- src/cascadia/TerminalApp/TerminalSettings.h | 2 +- src/cascadia/TerminalApp/TerminalSettings.idl | 2 +- .../TerminalControlLib.vcxproj | 2 +- .../dll/TerminalControl.vcxproj | 50 ++++++++++++++++--- ...Microsoft.Terminal.Settings.Editor.vcxproj | 8 ++- .../TerminalSettingsEditor/Profiles.cpp | 4 +- .../TerminalSettingsEditor/Profiles.h | 2 +- .../TerminalSettingsEditor/Profiles.idl | 2 +- .../TerminalSettingsModel/EnumMappings.cpp | 2 +- .../TerminalSettingsModel/EnumMappings.h | 2 +- .../TerminalSettingsModel/EnumMappings.idl | 2 +- ...crosoft.Terminal.Settings.ModelLib.vcxproj | 6 +++ src/cascadia/TerminalSettingsModel/Profile.h | 2 +- .../TerminalSettingsModel/Profile.idl | 2 +- .../TerminalSettingsSerializationHelpers.h | 2 +- .../Microsoft.Terminal.Settings.Model.vcxproj | 9 +++- 16 files changed, 77 insertions(+), 22 deletions(-) diff --git a/src/cascadia/TerminalApp/TerminalSettings.h b/src/cascadia/TerminalApp/TerminalSettings.h index f39ef44aadd..ee3e4d5e9fb 100644 --- a/src/cascadia/TerminalApp/TerminalSettings.h +++ b/src/cascadia/TerminalApp/TerminalSettings.h @@ -60,7 +60,7 @@ namespace winrt::TerminalApp::implementation INHERITABLE_SETTING(TerminalApp::TerminalSettings, bool, SnapOnInput, true); INHERITABLE_SETTING(TerminalApp::TerminalSettings, bool, AltGrAliasing, true); INHERITABLE_SETTING(TerminalApp::TerminalSettings, uint32_t, CursorColor, DEFAULT_CURSOR_COLOR); - INHERITABLE_SETTING(TerminalApp::TerminalSettings, Microsoft::Terminal::TerminalControl::CursorStyle, CursorShape, Microsoft::Terminal::TerminalControl::CursorStyle::Vintage); + INHERITABLE_SETTING(TerminalApp::TerminalSettings, Microsoft::Terminal::Core::CursorStyle, CursorShape, Microsoft::Terminal::Core::CursorStyle::Vintage); INHERITABLE_SETTING(TerminalApp::TerminalSettings, uint32_t, CursorHeight, DEFAULT_CURSOR_HEIGHT); INHERITABLE_SETTING(TerminalApp::TerminalSettings, hstring, WordDelimiters, DEFAULT_WORD_DELIMITERS); INHERITABLE_SETTING(TerminalApp::TerminalSettings, bool, CopyOnSelect, false); diff --git a/src/cascadia/TerminalApp/TerminalSettings.idl b/src/cascadia/TerminalApp/TerminalSettings.idl index 412afa7e714..acbd48fd9a1 100644 --- a/src/cascadia/TerminalApp/TerminalSettings.idl +++ b/src/cascadia/TerminalApp/TerminalSettings.idl @@ -12,7 +12,7 @@ namespace TerminalApp // The TerminalControl will pull settings it requires from this object, // and pass along the Core properties to the terminal core. [default_interface] - runtimeclass TerminalSettings : Microsoft.Terminal.TerminalControl.ICoreSettings, + runtimeclass TerminalSettings : Microsoft.Terminal.Core.ICoreSettings, Microsoft.Terminal.TerminalControl.IControlSettings { TerminalSettings(); diff --git a/src/cascadia/TerminalControl/TerminalControlLib.vcxproj b/src/cascadia/TerminalControl/TerminalControlLib.vcxproj index 54af6d33feb..e391bf668a9 100644 --- a/src/cascadia/TerminalControl/TerminalControlLib.vcxproj +++ b/src/cascadia/TerminalControl/TerminalControlLib.vcxproj @@ -5,7 +5,7 @@ Win32Proj TerminalControlLib Microsoft.Terminal.TerminalControl - Microsoft.Terminal.TerminalControl.Lib + Microsoft.Terminal.TerminalControlLib 10.0.17763.0 StaticLibrary Console diff --git a/src/cascadia/TerminalControl/dll/TerminalControl.vcxproj b/src/cascadia/TerminalControl/dll/TerminalControl.vcxproj index 723b4f42ef1..087b6fc482b 100644 --- a/src/cascadia/TerminalControl/dll/TerminalControl.vcxproj +++ b/src/cascadia/TerminalControl/dll/TerminalControl.vcxproj @@ -11,6 +11,16 @@ Console true + + + 3 @@ -47,7 +57,7 @@ make sure that if you add a cppwinrt dependency to any of these projects, you also update all the consumers --> - + + + @@ -66,19 +76,45 @@ true - - + + + + + $(OpenConsoleCommonOutDir)TerminalCore\Microsoft.Terminal.Core.winmd + true + false + false + + + + $(OpenConsoleCommonOutDir)TerminalConnection\Microsoft.Terminal.TerminalConnection.winmd + true + false + false + + + + + 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) /INCLUDE:_DllMain@12 /INCLUDE:DllMain + + + + false + diff --git a/src/cascadia/TerminalSettingsEditor/Microsoft.Terminal.Settings.Editor.vcxproj b/src/cascadia/TerminalSettingsEditor/Microsoft.Terminal.Settings.Editor.vcxproj index b8c6b360e1b..33b6d260a0a 100644 --- a/src/cascadia/TerminalSettingsEditor/Microsoft.Terminal.Settings.Editor.vcxproj +++ b/src/cascadia/TerminalSettingsEditor/Microsoft.Terminal.Settings.Editor.vcxproj @@ -267,7 +267,7 @@ false - + diff --git a/src/cascadia/TerminalSettingsModel/Profile.h b/src/cascadia/TerminalSettingsModel/Profile.h index 10cc5f164cd..c231d383abe 100644 --- a/src/cascadia/TerminalSettingsModel/Profile.h +++ b/src/cascadia/TerminalSettingsModel/Profile.h @@ -117,7 +117,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation INHERITABLE_SETTING(Model::Profile, bool, SnapOnInput, true); INHERITABLE_SETTING(Model::Profile, bool, AltGrAliasing, true); - INHERITABLE_SETTING(Model::Profile, Microsoft::Terminal::TerminalControl::CursorStyle, CursorShape, Microsoft::Terminal::TerminalControl::CursorStyle::Bar); + INHERITABLE_SETTING(Model::Profile, Microsoft::Terminal::Core::CursorStyle, CursorShape, Microsoft::Terminal::Core::CursorStyle::Bar); INHERITABLE_SETTING(Model::Profile, uint32_t, CursorHeight, DEFAULT_CURSOR_HEIGHT); INHERITABLE_SETTING(Model::Profile, Model::BellStyle, BellStyle, BellStyle::Audible); diff --git a/src/cascadia/TerminalSettingsModel/Profile.idl b/src/cascadia/TerminalSettingsModel/Profile.idl index af2e135f373..9fd21425ca0 100644 --- a/src/cascadia/TerminalSettingsModel/Profile.idl +++ b/src/cascadia/TerminalSettingsModel/Profile.idl @@ -99,7 +99,7 @@ namespace Microsoft.Terminal.Settings.Model INHERITABLE_PROFILE_SETTING(Int32, HistorySize); INHERITABLE_PROFILE_SETTING(Boolean, SnapOnInput); INHERITABLE_PROFILE_SETTING(Boolean, AltGrAliasing); - INHERITABLE_PROFILE_SETTING(Microsoft.Terminal.TerminalControl.CursorStyle, CursorShape); + INHERITABLE_PROFILE_SETTING(Microsoft.Terminal.Core.CursorStyle, CursorShape); INHERITABLE_PROFILE_SETTING(UInt32, CursorHeight); INHERITABLE_PROFILE_SETTING(BellStyle, BellStyle); } diff --git a/src/cascadia/TerminalSettingsModel/TerminalSettingsSerializationHelpers.h b/src/cascadia/TerminalSettingsModel/TerminalSettingsSerializationHelpers.h index 416a284330b..d469ee6ead1 100644 --- a/src/cascadia/TerminalSettingsModel/TerminalSettingsSerializationHelpers.h +++ b/src/cascadia/TerminalSettingsModel/TerminalSettingsSerializationHelpers.h @@ -18,7 +18,7 @@ Module Name: #include "JsonUtils.h" #include "SettingsTypes.h" -JSON_ENUM_MAPPER(::winrt::Microsoft::Terminal::TerminalControl::CursorStyle) +JSON_ENUM_MAPPER(::winrt::Microsoft::Terminal::Core::CursorStyle) { static constexpr std::array mappings = { pair_type{ "bar", ValueType::Bar }, diff --git a/src/cascadia/TerminalSettingsModel/dll/Microsoft.Terminal.Settings.Model.vcxproj b/src/cascadia/TerminalSettingsModel/dll/Microsoft.Terminal.Settings.Model.vcxproj index cea7de13f67..ff5ca15aa8d 100644 --- a/src/cascadia/TerminalSettingsModel/dll/Microsoft.Terminal.Settings.Model.vcxproj +++ b/src/cascadia/TerminalSettingsModel/dll/Microsoft.Terminal.Settings.Model.vcxproj @@ -60,7 +60,7 @@ false - + @@ -393,4 +399,4 @@ - \ No newline at end of file + diff --git a/src/cascadia/TerminalApp/dll/TerminalApp.vcxproj b/src/cascadia/TerminalApp/dll/TerminalApp.vcxproj index 1e963a84932..c6146cffe93 100644 --- a/src/cascadia/TerminalApp/dll/TerminalApp.vcxproj +++ b/src/cascadia/TerminalApp/dll/TerminalApp.vcxproj @@ -75,6 +75,28 @@ + + + + + + + $(OpenConsoleCommonOutDir)TerminalCore\Microsoft.Terminal.Core.winmd + true + false + false + + + + diff --git a/src/cascadia/WindowsTerminal/WindowsTerminal.vcxproj b/src/cascadia/WindowsTerminal/WindowsTerminal.vcxproj index deb94e6d33d..3bb9ff83ca4 100644 --- a/src/cascadia/WindowsTerminal/WindowsTerminal.vcxproj +++ b/src/cascadia/WindowsTerminal/WindowsTerminal.vcxproj @@ -72,6 +72,7 @@ + @@ -83,6 +84,15 @@ + + + + $(OpenConsoleCommonOutDir)TerminalCore\Microsoft.Terminal.Core.winmd + true + false + false + + - diff --git a/src/cascadia/TerminalControl/TSFInputControl.cpp b/src/cascadia/TerminalControl/TSFInputControl.cpp index 23bd9bcbec2..154ccbb7b4d 100644 --- a/src/cascadia/TerminalControl/TSFInputControl.cpp +++ b/src/cascadia/TerminalControl/TSFInputControl.cpp @@ -14,7 +14,7 @@ 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 +namespace winrt::Microsoft::Terminal::Control::implementation { TSFInputControl::TSFInputControl() : _editContext{ nullptr }, @@ -469,5 +469,5 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation { } - DEFINE_EVENT(TSFInputControl, CompositionCompleted, _compositionCompletedHandlers, TerminalControl::CompositionCompletedEventArgs); + DEFINE_EVENT(TSFInputControl, CompositionCompleted, _compositionCompletedHandlers, Control::CompositionCompletedEventArgs); } diff --git a/src/cascadia/TerminalControl/TSFInputControl.h b/src/cascadia/TerminalControl/TSFInputControl.h index 6344204a57d..9e96e6a9ad1 100644 --- a/src/cascadia/TerminalControl/TSFInputControl.h +++ b/src/cascadia/TerminalControl/TSFInputControl.h @@ -7,7 +7,7 @@ #include "FontInfoEventArgs.g.h" #include "cppwinrt_utils.h" -namespace winrt::Microsoft::Terminal::TerminalControl::implementation +namespace winrt::Microsoft::Terminal::Control::implementation { struct CursorPositionEventArgs : public CursorPositionEventArgsT @@ -44,9 +44,9 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation void Close(); // -------------------------------- WinRT Events --------------------------------- - TYPED_EVENT(CurrentCursorPosition, TerminalControl::TSFInputControl, TerminalControl::CursorPositionEventArgs); - TYPED_EVENT(CurrentFontInfo, TerminalControl::TSFInputControl, TerminalControl::FontInfoEventArgs); - DECLARE_EVENT(CompositionCompleted, _compositionCompletedHandlers, TerminalControl::CompositionCompletedEventArgs); + TYPED_EVENT(CurrentCursorPosition, Control::TSFInputControl, Control::CursorPositionEventArgs); + TYPED_EVENT(CurrentFontInfo, Control::TSFInputControl, Control::FontInfoEventArgs); + DECLARE_EVENT(CompositionCompleted, _compositionCompletedHandlers, Control::CompositionCompletedEventArgs); private: void _layoutRequestedHandler(winrt::Windows::UI::Text::Core::CoreTextEditContext sender, winrt::Windows::UI::Text::Core::CoreTextLayoutRequestedEventArgs const& args); @@ -87,7 +87,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation winrt::Windows::Foundation::Rect _currentWindowBounds; }; } -namespace winrt::Microsoft::Terminal::TerminalControl::factory_implementation +namespace winrt::Microsoft::Terminal::Control::factory_implementation { struct TSFInputControl : TSFInputControlT { diff --git a/src/cascadia/TerminalControl/TSFInputControl.idl b/src/cascadia/TerminalControl/TSFInputControl.idl index fda21c7ed1b..6a6f6814f2a 100644 --- a/src/cascadia/TerminalControl/TSFInputControl.idl +++ b/src/cascadia/TerminalControl/TSFInputControl.idl @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. -namespace Microsoft.Terminal.TerminalControl +namespace Microsoft.Terminal.Control { delegate void CompositionCompletedEventArgs(String text); diff --git a/src/cascadia/TerminalControl/TSFInputControl.xaml b/src/cascadia/TerminalControl/TSFInputControl.xaml index dab81c6178a..2633bbd1261 100644 --- a/src/cascadia/TerminalControl/TSFInputControl.xaml +++ b/src/cascadia/TerminalControl/TSFInputControl.xaml @@ -1,5 +1,5 @@ () }) + if (auto searchBox{ loadedSearchBox.try_as<::winrt::Microsoft::Terminal::Control::SearchBoxControl>() }) { // get at its private implementation _searchBox.copy_from(winrt::get_self(searchBox)); @@ -619,7 +619,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation { // create a custom automation peer with this code pattern: // (https://docs.microsoft.com/en-us/windows/uwp/design/accessibility/custom-automation-peers) - auto autoPeer = winrt::make_self(this); + auto autoPeer = winrt::make_self(this); _uiaEngine = std::make_unique<::Microsoft::Console::Render::UiaEngine>(autoPeer.get()); _renderer->AddRenderEngine(_uiaEngine.get()); @@ -3393,14 +3393,14 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation // -------------------------------- WinRT Events --------------------------------- // Winrt events need a method for adding a callback to the event and removing the callback. // These macros will define them both for you. - DEFINE_EVENT(TermControl, TitleChanged, _titleChangedHandlers, TerminalControl::TitleChangedEventArgs); - DEFINE_EVENT(TermControl, FontSizeChanged, _fontSizeChangedHandlers, TerminalControl::FontSizeChangedEventArgs); - DEFINE_EVENT(TermControl, ScrollPositionChanged, _scrollPositionChangedHandlers, TerminalControl::ScrollPositionChangedEventArgs); - - DEFINE_EVENT_WITH_TYPED_EVENT_HANDLER(TermControl, PasteFromClipboard, _clipboardPasteHandlers, TerminalControl::TermControl, TerminalControl::PasteFromClipboardEventArgs); - DEFINE_EVENT_WITH_TYPED_EVENT_HANDLER(TermControl, CopyToClipboard, _clipboardCopyHandlers, TerminalControl::TermControl, TerminalControl::CopyToClipboardEventArgs); - DEFINE_EVENT_WITH_TYPED_EVENT_HANDLER(TermControl, OpenHyperlink, _openHyperlinkHandlers, TerminalControl::TermControl, TerminalControl::OpenHyperlinkEventArgs); - DEFINE_EVENT_WITH_TYPED_EVENT_HANDLER(TermControl, SetTaskbarProgress, _setTaskbarProgressHandlers, TerminalControl::TermControl, IInspectable); - DEFINE_EVENT_WITH_TYPED_EVENT_HANDLER(TermControl, RaiseNotice, _raiseNoticeHandlers, TerminalControl::TermControl, TerminalControl::NoticeEventArgs); + DEFINE_EVENT(TermControl, TitleChanged, _titleChangedHandlers, Control::TitleChangedEventArgs); + DEFINE_EVENT(TermControl, FontSizeChanged, _fontSizeChangedHandlers, Control::FontSizeChangedEventArgs); + DEFINE_EVENT(TermControl, ScrollPositionChanged, _scrollPositionChangedHandlers, Control::ScrollPositionChangedEventArgs); + + DEFINE_EVENT_WITH_TYPED_EVENT_HANDLER(TermControl, PasteFromClipboard, _clipboardPasteHandlers, Control::TermControl, Control::PasteFromClipboardEventArgs); + DEFINE_EVENT_WITH_TYPED_EVENT_HANDLER(TermControl, CopyToClipboard, _clipboardCopyHandlers, Control::TermControl, Control::CopyToClipboardEventArgs); + DEFINE_EVENT_WITH_TYPED_EVENT_HANDLER(TermControl, OpenHyperlink, _openHyperlinkHandlers, Control::TermControl, Control::OpenHyperlinkEventArgs); + DEFINE_EVENT_WITH_TYPED_EVENT_HANDLER(TermControl, SetTaskbarProgress, _setTaskbarProgressHandlers, Control::TermControl, IInspectable); + DEFINE_EVENT_WITH_TYPED_EVENT_HANDLER(TermControl, RaiseNotice, _raiseNoticeHandlers, Control::TermControl, Control::NoticeEventArgs); // clang-format on } diff --git a/src/cascadia/TerminalControl/TermControl.h b/src/cascadia/TerminalControl/TermControl.h index 0ba391da6a8..2b00f444250 100644 --- a/src/cascadia/TerminalControl/TermControl.h +++ b/src/cascadia/TerminalControl/TermControl.h @@ -24,7 +24,7 @@ namespace Microsoft::Console::VirtualTerminal struct MouseButtonState; } -namespace winrt::Microsoft::Terminal::TerminalControl::implementation +namespace winrt::Microsoft::Terminal::Control::implementation { struct CopyToClipboardEventArgs : public CopyToClipboardEventArgsT @@ -172,19 +172,19 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation // clang-format off // -------------------------------- WinRT Events --------------------------------- - DECLARE_EVENT(TitleChanged, _titleChangedHandlers, TerminalControl::TitleChangedEventArgs); - DECLARE_EVENT(FontSizeChanged, _fontSizeChangedHandlers, TerminalControl::FontSizeChangedEventArgs); - DECLARE_EVENT(ScrollPositionChanged, _scrollPositionChangedHandlers, TerminalControl::ScrollPositionChangedEventArgs); + DECLARE_EVENT(TitleChanged, _titleChangedHandlers, Control::TitleChangedEventArgs); + DECLARE_EVENT(FontSizeChanged, _fontSizeChangedHandlers, Control::FontSizeChangedEventArgs); + DECLARE_EVENT(ScrollPositionChanged, _scrollPositionChangedHandlers, Control::ScrollPositionChangedEventArgs); - DECLARE_EVENT_WITH_TYPED_EVENT_HANDLER(PasteFromClipboard, _clipboardPasteHandlers, TerminalControl::TermControl, TerminalControl::PasteFromClipboardEventArgs); - DECLARE_EVENT_WITH_TYPED_EVENT_HANDLER(CopyToClipboard, _clipboardCopyHandlers, TerminalControl::TermControl, TerminalControl::CopyToClipboardEventArgs); - DECLARE_EVENT_WITH_TYPED_EVENT_HANDLER(OpenHyperlink, _openHyperlinkHandlers, TerminalControl::TermControl, TerminalControl::OpenHyperlinkEventArgs); - DECLARE_EVENT_WITH_TYPED_EVENT_HANDLER(SetTaskbarProgress, _setTaskbarProgressHandlers, TerminalControl::TermControl, IInspectable); - DECLARE_EVENT_WITH_TYPED_EVENT_HANDLER(RaiseNotice, _raiseNoticeHandlers, TerminalControl::TermControl, TerminalControl::NoticeEventArgs); + DECLARE_EVENT_WITH_TYPED_EVENT_HANDLER(PasteFromClipboard, _clipboardPasteHandlers, Control::TermControl, Control::PasteFromClipboardEventArgs); + DECLARE_EVENT_WITH_TYPED_EVENT_HANDLER(CopyToClipboard, _clipboardCopyHandlers, Control::TermControl, Control::CopyToClipboardEventArgs); + DECLARE_EVENT_WITH_TYPED_EVENT_HANDLER(OpenHyperlink, _openHyperlinkHandlers, Control::TermControl, Control::OpenHyperlinkEventArgs); + DECLARE_EVENT_WITH_TYPED_EVENT_HANDLER(SetTaskbarProgress, _setTaskbarProgressHandlers, Control::TermControl, IInspectable); + DECLARE_EVENT_WITH_TYPED_EVENT_HANDLER(RaiseNotice, _raiseNoticeHandlers, Control::TermControl, Control::NoticeEventArgs); TYPED_EVENT(WarningBell, IInspectable, IInspectable); - TYPED_EVENT(ConnectionStateChanged, TerminalControl::TermControl, IInspectable); - TYPED_EVENT(Initialized, TerminalControl::TermControl, Windows::UI::Xaml::RoutedEventArgs); + TYPED_EVENT(ConnectionStateChanged, Control::TermControl, IInspectable); + TYPED_EVENT(Initialized, Control::TermControl, Windows::UI::Xaml::RoutedEventArgs); TYPED_EVENT(TabColorChanged, IInspectable, IInspectable); TYPED_EVENT(HidePointerCursor, IInspectable, IInspectable); TYPED_EVENT(RestorePointerCursor, IInspectable, IInspectable); @@ -356,7 +356,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation }; } -namespace winrt::Microsoft::Terminal::TerminalControl::factory_implementation +namespace winrt::Microsoft::Terminal::Control::factory_implementation { struct TermControl : TermControlT { diff --git a/src/cascadia/TerminalControl/TermControl.idl b/src/cascadia/TerminalControl/TermControl.idl index 4470c0555d6..cfaa2d0642b 100644 --- a/src/cascadia/TerminalControl/TermControl.idl +++ b/src/cascadia/TerminalControl/TermControl.idl @@ -4,7 +4,7 @@ import "IMouseWheelListener.idl"; import "IControlSettings.idl"; -namespace Microsoft.Terminal.TerminalControl +namespace Microsoft.Terminal.Control { delegate void TitleChangedEventArgs(String newTitle); delegate void FontSizeChangedEventArgs(Int32 width, Int32 height, Boolean isInitialChange); @@ -61,13 +61,13 @@ namespace Microsoft.Terminal.TerminalControl [default_interface] runtimeclass TermControl : Windows.UI.Xaml.Controls.UserControl, IDirectKeyListener, IMouseWheelListener { - TermControl(Microsoft.Terminal.TerminalControl.IControlSettings settings, Microsoft.Terminal.TerminalConnection.ITerminalConnection connection); + TermControl(Microsoft.Terminal.Control.IControlSettings settings, Microsoft.Terminal.TerminalConnection.ITerminalConnection connection); - static Windows.Foundation.Size GetProposedDimensions(Microsoft.Terminal.TerminalControl.IControlSettings settings, UInt32 dpi); + static Windows.Foundation.Size GetProposedDimensions(Microsoft.Terminal.Control.IControlSettings settings, UInt32 dpi); void UpdateSettings(); - Microsoft.Terminal.TerminalControl.IControlSettings Settings { get; }; + Microsoft.Terminal.Control.IControlSettings Settings { get; }; event TitleChangedEventArgs TitleChanged; event FontSizeChangedEventArgs FontSizeChanged; diff --git a/src/cascadia/TerminalControl/TermControl.xaml b/src/cascadia/TerminalControl/TermControl.xaml index c3d34d0f244..ac642b037fb 100644 --- a/src/cascadia/TerminalControl/TermControl.xaml +++ b/src/cascadia/TerminalControl/TermControl.xaml @@ -1,11 +1,11 @@  (*owner), // pass owner to FrameworkElementAutomationPeer _termControl{ owner } { diff --git a/src/cascadia/TerminalControl/TermControlAutomationPeer.h b/src/cascadia/TerminalControl/TermControlAutomationPeer.h index 56e12e56b4d..46a90073644 100644 --- a/src/cascadia/TerminalControl/TermControlAutomationPeer.h +++ b/src/cascadia/TerminalControl/TermControlAutomationPeer.h @@ -26,12 +26,12 @@ Author(s): #include "TermControl.h" #include "TermControlAutomationPeer.g.h" -#include +#include #include "../types/TermControlUiaProvider.hpp" #include "../types/IUiaEventDispatcher.h" #include "../types/IControlAccessibilityInfo.h" -namespace winrt::Microsoft::Terminal::TerminalControl::implementation +namespace winrt::Microsoft::Terminal::Control::implementation { struct TermControlAutomationPeer : public TermControlAutomationPeerT, @@ -39,7 +39,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation ::Microsoft::Console::Types::IControlAccessibilityInfo { public: - TermControlAutomationPeer(Microsoft::Terminal::TerminalControl::implementation::TermControl* owner); + TermControlAutomationPeer(Microsoft::Terminal::Control::implementation::TermControl* owner); #pragma region FrameworkElementAutomationPeer hstring GetClassNameCore() const; @@ -81,7 +81,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation private: ::Microsoft::WRL::ComPtr<::Microsoft::Terminal::TermControlUiaProvider> _uiaProvider; - winrt::Microsoft::Terminal::TerminalControl::implementation::TermControl* _termControl; + winrt::Microsoft::Terminal::Control::implementation::TermControl* _termControl; winrt::com_array WrapArrayOfTextRangeProviders(SAFEARRAY* textRanges); }; } diff --git a/src/cascadia/TerminalControl/TermControlAutomationPeer.idl b/src/cascadia/TerminalControl/TermControlAutomationPeer.idl index 18ada03e7bc..0d777b09a51 100644 --- a/src/cascadia/TerminalControl/TermControlAutomationPeer.idl +++ b/src/cascadia/TerminalControl/TermControlAutomationPeer.idl @@ -3,7 +3,7 @@ import "TermControl.idl"; -namespace Microsoft.Terminal.TerminalControl +namespace Microsoft.Terminal.Control { [default_interface] runtimeclass TermControlAutomationPeer : Windows.UI.Xaml.Automation.Peers.FrameworkElementAutomationPeer, diff --git a/src/cascadia/TerminalControl/TerminalControl.vcxproj.filters b/src/cascadia/TerminalControl/TerminalControl.vcxproj.filters deleted file mode 100644 index d9eaaf778d3..00000000000 --- a/src/cascadia/TerminalControl/TerminalControl.vcxproj.filters +++ /dev/null @@ -1,54 +0,0 @@ - - - - - accd3aa8-1ba0-4223-9bbe-0c431709210b - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tga;tiff;tif;png;wav;mfcribbon-ms - - - {926ab91d-31b4-48c3-b9a4-e681349f27f0} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Resources - - - \ No newline at end of file diff --git a/src/cascadia/TerminalControl/TerminalControlLib.vcxproj b/src/cascadia/TerminalControl/TerminalControlLib.vcxproj index e391bf668a9..0318dcfc5a7 100644 --- a/src/cascadia/TerminalControl/TerminalControlLib.vcxproj +++ b/src/cascadia/TerminalControl/TerminalControlLib.vcxproj @@ -4,8 +4,8 @@ {CA5CAD1A-44BD-4AC7-AC72-6CA5B3AB89ED} Win32Proj TerminalControlLib - Microsoft.Terminal.TerminalControl - Microsoft.Terminal.TerminalControlLib + Microsoft.Terminal.Control + Microsoft.Terminal.ControlLib 10.0.17763.0 StaticLibrary Console @@ -13,7 +13,7 @@ - Microsoft.Terminal.TerminalControl + Microsoft.Terminal.Control DynamicLibrary @@ -14,7 +14,7 @@ - - $(OpenConsoleCommonOutDir)TerminalControl\Microsoft.Terminal.TerminalControl.winmd + + $(OpenConsoleCommonOutDir)TerminalControl\Microsoft.Terminal.Control.winmd true false false diff --git a/src/cascadia/TerminalSettingsEditor/Profiles.cpp b/src/cascadia/TerminalSettingsEditor/Profiles.cpp index 38438ce2bf2..a28d580c4ae 100644 --- a/src/cascadia/TerminalSettingsEditor/Profiles.cpp +++ b/src/cascadia/TerminalSettingsEditor/Profiles.cpp @@ -379,10 +379,10 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation INITIALIZE_BINDABLE_ENUM_SETTING(CursorShape, CursorStyle, winrt::Microsoft::Terminal::Core::CursorStyle, L"Profile_CursorShape", L"Content"); INITIALIZE_BINDABLE_ENUM_SETTING_REVERSE_ORDER(BackgroundImageStretchMode, BackgroundImageStretchMode, winrt::Windows::UI::Xaml::Media::Stretch, L"Profile_BackgroundImageStretchMode", L"Content"); - INITIALIZE_BINDABLE_ENUM_SETTING(AntiAliasingMode, TextAntialiasingMode, winrt::Microsoft::Terminal::TerminalControl::TextAntialiasingMode, L"Profile_AntialiasingMode", L"Content"); + INITIALIZE_BINDABLE_ENUM_SETTING(AntiAliasingMode, TextAntialiasingMode, winrt::Microsoft::Terminal::Control::TextAntialiasingMode, L"Profile_AntialiasingMode", L"Content"); INITIALIZE_BINDABLE_ENUM_SETTING_REVERSE_ORDER(CloseOnExitMode, CloseOnExitMode, winrt::Microsoft::Terminal::Settings::Model::CloseOnExitMode, L"Profile_CloseOnExit", L"Content"); INITIALIZE_BINDABLE_ENUM_SETTING_REVERSE_ORDER(BellStyle, BellStyle, winrt::Microsoft::Terminal::Settings::Model::BellStyle, L"Profile_BellStyle", L"Content"); - INITIALIZE_BINDABLE_ENUM_SETTING(ScrollState, ScrollbarState, winrt::Microsoft::Terminal::TerminalControl::ScrollbarState, L"Profile_ScrollbarVisibility", L"Content"); + INITIALIZE_BINDABLE_ENUM_SETTING(ScrollState, ScrollbarState, winrt::Microsoft::Terminal::Control::ScrollbarState, L"Profile_ScrollbarVisibility", L"Content"); // manually add Custom FontWeight option. Don't add it to the Map INITIALIZE_BINDABLE_ENUM_SETTING(FontWeight, FontWeight, uint16_t, L"Profile_FontWeight", L"Content"); diff --git a/src/cascadia/TerminalSettingsEditor/Profiles.h b/src/cascadia/TerminalSettingsEditor/Profiles.h index fd8bef1cc8e..4973a1911c9 100644 --- a/src/cascadia/TerminalSettingsEditor/Profiles.h +++ b/src/cascadia/TerminalSettingsEditor/Profiles.h @@ -193,10 +193,10 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation WINRT_PROPERTY(Windows::Foundation::Collections::IObservableVector, ColorSchemeList, nullptr); GETSET_BINDABLE_ENUM_SETTING(CursorShape, Microsoft::Terminal::Core::CursorStyle, State().Profile, CursorShape); GETSET_BINDABLE_ENUM_SETTING(BackgroundImageStretchMode, Windows::UI::Xaml::Media::Stretch, State().Profile, BackgroundImageStretchMode); - GETSET_BINDABLE_ENUM_SETTING(AntiAliasingMode, Microsoft::Terminal::TerminalControl::TextAntialiasingMode, State().Profile, AntialiasingMode); + GETSET_BINDABLE_ENUM_SETTING(AntiAliasingMode, Microsoft::Terminal::Control::TextAntialiasingMode, State().Profile, AntialiasingMode); GETSET_BINDABLE_ENUM_SETTING(CloseOnExitMode, Microsoft::Terminal::Settings::Model::CloseOnExitMode, State().Profile, CloseOnExit); GETSET_BINDABLE_ENUM_SETTING(BellStyle, Microsoft::Terminal::Settings::Model::BellStyle, State().Profile, BellStyle); - GETSET_BINDABLE_ENUM_SETTING(ScrollState, Microsoft::Terminal::TerminalControl::ScrollbarState, State().Profile, ScrollState); + GETSET_BINDABLE_ENUM_SETTING(ScrollState, Microsoft::Terminal::Control::ScrollbarState, State().Profile, ScrollState); private: void _UpdateBIAlignmentControl(const int32_t val); diff --git a/src/cascadia/TerminalSettingsEditor/Profiles.idl b/src/cascadia/TerminalSettingsEditor/Profiles.idl index 6ae638b275a..a3c94ef2f1d 100644 --- a/src/cascadia/TerminalSettingsEditor/Profiles.idl +++ b/src/cascadia/TerminalSettingsEditor/Profiles.idl @@ -44,7 +44,7 @@ namespace Microsoft.Terminal.Settings.Editor OBSERVABLE_PROJECTED_PROFILE_SETTING(Boolean, SuppressApplicationTitle); OBSERVABLE_PROJECTED_PROFILE_SETTING(Boolean, UseAcrylic); OBSERVABLE_PROJECTED_PROFILE_SETTING(Double, AcrylicOpacity); - OBSERVABLE_PROJECTED_PROFILE_SETTING(Microsoft.Terminal.TerminalControl.ScrollbarState, ScrollState); + OBSERVABLE_PROJECTED_PROFILE_SETTING(Microsoft.Terminal.Control.ScrollbarState, ScrollState); OBSERVABLE_PROJECTED_PROFILE_SETTING(String, FontFace); OBSERVABLE_PROJECTED_PROFILE_SETTING(Int32, FontSize); OBSERVABLE_PROJECTED_PROFILE_SETTING(Windows.UI.Text.FontWeight, FontWeight); @@ -55,7 +55,7 @@ namespace Microsoft.Terminal.Settings.Editor OBSERVABLE_PROJECTED_PROFILE_SETTING(Double, BackgroundImageOpacity); OBSERVABLE_PROJECTED_PROFILE_SETTING(Windows.UI.Xaml.Media.Stretch, BackgroundImageStretchMode); OBSERVABLE_PROJECTED_PROFILE_SETTING(Microsoft.Terminal.Settings.Model.ConvergedAlignment, BackgroundImageAlignment); - OBSERVABLE_PROJECTED_PROFILE_SETTING(Microsoft.Terminal.TerminalControl.TextAntialiasingMode, AntialiasingMode); + OBSERVABLE_PROJECTED_PROFILE_SETTING(Microsoft.Terminal.Control.TextAntialiasingMode, AntialiasingMode); OBSERVABLE_PROJECTED_PROFILE_SETTING(Boolean, RetroTerminalEffect); OBSERVABLE_PROJECTED_PROFILE_SETTING(Boolean, ForceFullRepaintRendering); OBSERVABLE_PROJECTED_PROFILE_SETTING(Boolean, SoftwareRendering); diff --git a/src/cascadia/TerminalSettingsEditor/pch.h b/src/cascadia/TerminalSettingsEditor/pch.h index d30001bcbac..c75842a182c 100644 --- a/src/cascadia/TerminalSettingsEditor/pch.h +++ b/src/cascadia/TerminalSettingsEditor/pch.h @@ -50,7 +50,7 @@ #include #include -#include +#include #include #include "shobjidl_core.h" diff --git a/src/cascadia/TerminalSettingsModel/ActionArgs.cpp b/src/cascadia/TerminalSettingsModel/ActionArgs.cpp index 2c7174eca2e..5c0ce7f52e4 100644 --- a/src/cascadia/TerminalSettingsModel/ActionArgs.cpp +++ b/src/cascadia/TerminalSettingsModel/ActionArgs.cpp @@ -29,7 +29,7 @@ #include -using namespace winrt::Microsoft::Terminal::TerminalControl; +using namespace winrt::Microsoft::Terminal::Control; namespace winrt::Microsoft::Terminal::Settings::Model::implementation { diff --git a/src/cascadia/TerminalSettingsModel/ActionArgs.h b/src/cascadia/TerminalSettingsModel/ActionArgs.h index 11691101955..cea20a7763c 100644 --- a/src/cascadia/TerminalSettingsModel/ActionArgs.h +++ b/src/cascadia/TerminalSettingsModel/ActionArgs.h @@ -122,7 +122,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation { CopyTextArgs() = default; WINRT_PROPERTY(bool, SingleLine, false); - WINRT_PROPERTY(Windows::Foundation::IReference, CopyFormatting, nullptr); + WINRT_PROPERTY(Windows::Foundation::IReference, CopyFormatting, nullptr); static constexpr std::string_view SingleLineKey{ "singleLine" }; static constexpr std::string_view CopyFormattingKey{ "copyFormatting" }; diff --git a/src/cascadia/TerminalSettingsModel/ActionArgs.idl b/src/cascadia/TerminalSettingsModel/ActionArgs.idl index d62e04c837d..0d2109fa299 100644 --- a/src/cascadia/TerminalSettingsModel/ActionArgs.idl +++ b/src/cascadia/TerminalSettingsModel/ActionArgs.idl @@ -107,7 +107,7 @@ namespace Microsoft.Terminal.Settings.Model [default_interface] runtimeclass CopyTextArgs : IActionArgs { Boolean SingleLine { get; }; - Windows.Foundation.IReference CopyFormatting { get; }; + Windows.Foundation.IReference CopyFormatting { get; }; }; [default_interface] runtimeclass NewTabArgs : IActionArgs diff --git a/src/cascadia/TerminalSettingsModel/CascadiaSettings.cpp b/src/cascadia/TerminalSettingsModel/CascadiaSettings.cpp index 52c4024a2ab..0e300c07437 100644 --- a/src/cascadia/TerminalSettingsModel/CascadiaSettings.cpp +++ b/src/cascadia/TerminalSettingsModel/CascadiaSettings.cpp @@ -19,7 +19,7 @@ #include "CascadiaSettings.g.cpp" using namespace ::Microsoft::Terminal::Settings::Model; -using namespace winrt::Microsoft::Terminal::TerminalControl; +using namespace winrt::Microsoft::Terminal::Control; using namespace winrt::Microsoft::Terminal::Settings::Model::implementation; using namespace winrt::Windows::Foundation::Collections; using namespace Microsoft::Console; diff --git a/src/cascadia/TerminalSettingsModel/EnumMappings.cpp b/src/cascadia/TerminalSettingsModel/EnumMappings.cpp index 0377f681af7..14dd008cf66 100644 --- a/src/cascadia/TerminalSettingsModel/EnumMappings.cpp +++ b/src/cascadia/TerminalSettingsModel/EnumMappings.cpp @@ -34,14 +34,14 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation DEFINE_ENUM_MAP(winrt::Microsoft::UI::Xaml::Controls::TabViewWidthMode, TabViewWidthMode); DEFINE_ENUM_MAP(Model::LaunchMode, LaunchMode); DEFINE_ENUM_MAP(Model::TabSwitcherMode, TabSwitcherMode); - DEFINE_ENUM_MAP(Microsoft::Terminal::TerminalControl::CopyFormat, CopyFormat); + DEFINE_ENUM_MAP(Microsoft::Terminal::Control::CopyFormat, CopyFormat); DEFINE_ENUM_MAP(Model::WindowingMode, WindowingMode); // Profile Settings DEFINE_ENUM_MAP(Model::CloseOnExitMode, CloseOnExitMode); - DEFINE_ENUM_MAP(Microsoft::Terminal::TerminalControl::ScrollbarState, ScrollbarState); + DEFINE_ENUM_MAP(Microsoft::Terminal::Control::ScrollbarState, ScrollbarState); DEFINE_ENUM_MAP(Windows::UI::Xaml::Media::Stretch, BackgroundImageStretchMode); - DEFINE_ENUM_MAP(Microsoft::Terminal::TerminalControl::TextAntialiasingMode, TextAntialiasingMode); + DEFINE_ENUM_MAP(Microsoft::Terminal::Control::TextAntialiasingMode, TextAntialiasingMode); DEFINE_ENUM_MAP(Microsoft::Terminal::Core::CursorStyle, CursorStyle); DEFINE_ENUM_MAP(Model::BellStyle, BellStyle); diff --git a/src/cascadia/TerminalSettingsModel/EnumMappings.h b/src/cascadia/TerminalSettingsModel/EnumMappings.h index 71c0ce114b2..de54adf3925 100644 --- a/src/cascadia/TerminalSettingsModel/EnumMappings.h +++ b/src/cascadia/TerminalSettingsModel/EnumMappings.h @@ -30,14 +30,14 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation static winrt::Windows::Foundation::Collections::IMap TabViewWidthMode(); static winrt::Windows::Foundation::Collections::IMap LaunchMode(); static winrt::Windows::Foundation::Collections::IMap TabSwitcherMode(); - static winrt::Windows::Foundation::Collections::IMap CopyFormat(); + static winrt::Windows::Foundation::Collections::IMap CopyFormat(); static winrt::Windows::Foundation::Collections::IMap WindowingMode(); // Profile Settings static winrt::Windows::Foundation::Collections::IMap CloseOnExitMode(); - static winrt::Windows::Foundation::Collections::IMap ScrollbarState(); + static winrt::Windows::Foundation::Collections::IMap ScrollbarState(); static winrt::Windows::Foundation::Collections::IMap BackgroundImageStretchMode(); - static winrt::Windows::Foundation::Collections::IMap TextAntialiasingMode(); + static winrt::Windows::Foundation::Collections::IMap TextAntialiasingMode(); static winrt::Windows::Foundation::Collections::IMap CursorStyle(); static winrt::Windows::Foundation::Collections::IMap BellStyle(); static winrt::Windows::Foundation::Collections::IMap FontWeight(); diff --git a/src/cascadia/TerminalSettingsModel/EnumMappings.idl b/src/cascadia/TerminalSettingsModel/EnumMappings.idl index 3519b27dd59..257962c59c4 100644 --- a/src/cascadia/TerminalSettingsModel/EnumMappings.idl +++ b/src/cascadia/TerminalSettingsModel/EnumMappings.idl @@ -12,14 +12,14 @@ namespace Microsoft.Terminal.Settings.Model static Windows.Foundation.Collections.IMap TabViewWidthMode { get; }; static Windows.Foundation.Collections.IMap LaunchMode { get; }; static Windows.Foundation.Collections.IMap TabSwitcherMode { get; }; - static Windows.Foundation.Collections.IMap CopyFormat { get; }; + static Windows.Foundation.Collections.IMap CopyFormat { get; }; static Windows.Foundation.Collections.IMap WindowingMode { get; }; // Profile Settings static Windows.Foundation.Collections.IMap CloseOnExitMode { get; }; - static Windows.Foundation.Collections.IMap ScrollbarState { get; }; + static Windows.Foundation.Collections.IMap ScrollbarState { get; }; static Windows.Foundation.Collections.IMap BackgroundImageStretchMode { get; }; - static Windows.Foundation.Collections.IMap TextAntialiasingMode { get; }; + static Windows.Foundation.Collections.IMap TextAntialiasingMode { get; }; static Windows.Foundation.Collections.IMap CursorStyle { get; }; static Windows.Foundation.Collections.IMap BellStyle { get; }; static Windows.Foundation.Collections.IMap FontWeight { get; }; diff --git a/src/cascadia/TerminalSettingsModel/GlobalAppSettings.h b/src/cascadia/TerminalSettingsModel/GlobalAppSettings.h index bf417f0331d..5f5f2456c9b 100644 --- a/src/cascadia/TerminalSettingsModel/GlobalAppSettings.h +++ b/src/cascadia/TerminalSettingsModel/GlobalAppSettings.h @@ -73,7 +73,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation INHERITABLE_SETTING(Model::GlobalAppSettings, hstring, WordDelimiters, DEFAULT_WORD_DELIMITERS); INHERITABLE_SETTING(Model::GlobalAppSettings, bool, CopyOnSelect, false); INHERITABLE_SETTING(Model::GlobalAppSettings, bool, InputServiceWarning, true); - INHERITABLE_SETTING(Model::GlobalAppSettings, winrt::Microsoft::Terminal::TerminalControl::CopyFormat, CopyFormatting, 0); + INHERITABLE_SETTING(Model::GlobalAppSettings, winrt::Microsoft::Terminal::Control::CopyFormat, CopyFormatting, 0); INHERITABLE_SETTING(Model::GlobalAppSettings, bool, WarnAboutLargePaste, true); INHERITABLE_SETTING(Model::GlobalAppSettings, bool, WarnAboutMultiLinePaste, true); INHERITABLE_SETTING(Model::GlobalAppSettings, Model::LaunchPosition, InitialPosition, nullptr, nullptr); diff --git a/src/cascadia/TerminalSettingsModel/GlobalAppSettings.idl b/src/cascadia/TerminalSettingsModel/GlobalAppSettings.idl index 786add2a6fd..12a58a9cae9 100644 --- a/src/cascadia/TerminalSettingsModel/GlobalAppSettings.idl +++ b/src/cascadia/TerminalSettingsModel/GlobalAppSettings.idl @@ -57,7 +57,7 @@ namespace Microsoft.Terminal.Settings.Model INHERITABLE_SETTING(String, WordDelimiters); INHERITABLE_SETTING(Boolean, CopyOnSelect); INHERITABLE_SETTING(Boolean, InputServiceWarning); - INHERITABLE_SETTING(Microsoft.Terminal.TerminalControl.CopyFormat, CopyFormatting); + INHERITABLE_SETTING(Microsoft.Terminal.Control.CopyFormat, CopyFormatting); INHERITABLE_SETTING(Boolean, WarnAboutLargePaste); INHERITABLE_SETTING(Boolean, WarnAboutMultiLinePaste); INHERITABLE_SETTING(LaunchPosition, InitialPosition); diff --git a/src/cascadia/TerminalSettingsModel/KeyChordSerialization.cpp b/src/cascadia/TerminalSettingsModel/KeyChordSerialization.cpp index b57fdc5207c..8c0fd632235 100644 --- a/src/cascadia/TerminalSettingsModel/KeyChordSerialization.cpp +++ b/src/cascadia/TerminalSettingsModel/KeyChordSerialization.cpp @@ -5,7 +5,7 @@ #include "KeyChordSerialization.h" #include "KeyChordSerialization.g.cpp" -using namespace winrt::Microsoft::Terminal::TerminalControl; +using namespace winrt::Microsoft::Terminal::Control; using namespace winrt::Microsoft::Terminal::Settings::Model::implementation; static constexpr std::wstring_view CTRL_KEY{ L"ctrl" }; diff --git a/src/cascadia/TerminalSettingsModel/KeyChordSerialization.h b/src/cascadia/TerminalSettingsModel/KeyChordSerialization.h index 53304420ba4..5b795f89040 100644 --- a/src/cascadia/TerminalSettingsModel/KeyChordSerialization.h +++ b/src/cascadia/TerminalSettingsModel/KeyChordSerialization.h @@ -12,8 +12,8 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation { KeyChordSerialization() = default; - static winrt::Microsoft::Terminal::TerminalControl::KeyChord FromString(const winrt::hstring& str); - static winrt::hstring ToString(const winrt::Microsoft::Terminal::TerminalControl::KeyChord& chord); + static winrt::Microsoft::Terminal::Control::KeyChord FromString(const winrt::hstring& str); + static winrt::hstring ToString(const winrt::Microsoft::Terminal::Control::KeyChord& chord); }; } diff --git a/src/cascadia/TerminalSettingsModel/KeyChordSerialization.idl b/src/cascadia/TerminalSettingsModel/KeyChordSerialization.idl index 966d10f23ec..6cb37fca7b1 100644 --- a/src/cascadia/TerminalSettingsModel/KeyChordSerialization.idl +++ b/src/cascadia/TerminalSettingsModel/KeyChordSerialization.idl @@ -5,7 +5,7 @@ namespace Microsoft.Terminal.Settings.Model { static runtimeclass KeyChordSerialization { - static Microsoft.Terminal.TerminalControl.KeyChord FromString(String str); - static String ToString(Microsoft.Terminal.TerminalControl.KeyChord chord); + static Microsoft.Terminal.Control.KeyChord FromString(String str); + static String ToString(Microsoft.Terminal.Control.KeyChord chord); } } diff --git a/src/cascadia/TerminalSettingsModel/KeyMapping.cpp b/src/cascadia/TerminalSettingsModel/KeyMapping.cpp index c889a091b5a..a5dd04891c4 100644 --- a/src/cascadia/TerminalSettingsModel/KeyMapping.cpp +++ b/src/cascadia/TerminalSettingsModel/KeyMapping.cpp @@ -9,7 +9,7 @@ #include "KeyMapping.g.cpp" using namespace winrt::Microsoft::Terminal::Settings::Model; -using namespace winrt::Microsoft::Terminal::TerminalControl; +using namespace winrt::Microsoft::Terminal::Control; namespace winrt::Microsoft::Terminal::Settings::Model::implementation { diff --git a/src/cascadia/TerminalSettingsModel/KeyMapping.h b/src/cascadia/TerminalSettingsModel/KeyMapping.h index 178e8812aba..ce5c811e389 100644 --- a/src/cascadia/TerminalSettingsModel/KeyMapping.h +++ b/src/cascadia/TerminalSettingsModel/KeyMapping.h @@ -31,10 +31,10 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation { struct KeyChordHash { - std::size_t operator()(const TerminalControl::KeyChord& key) const + std::size_t operator()(const Control::KeyChord& key) const { std::hash keyHash; - std::hash modifiersHash; + std::hash modifiersHash; std::size_t hashedKey = keyHash(key.Vkey()); std::size_t hashedMods = modifiersHash(key.Modifiers()); return hashedKey ^ hashedMods; @@ -43,7 +43,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation struct KeyChordEquality { - bool operator()(const TerminalControl::KeyChord& lhs, const TerminalControl::KeyChord& rhs) const + bool operator()(const Control::KeyChord& lhs, const Control::KeyChord& rhs) const { return lhs.Modifiers() == rhs.Modifiers() && lhs.Vkey() == rhs.Vkey(); } @@ -54,24 +54,24 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation KeyMapping() = default; com_ptr Copy() const; - Model::ActionAndArgs TryLookup(TerminalControl::KeyChord const& chord) const; + Model::ActionAndArgs TryLookup(Control::KeyChord const& chord) const; uint64_t Size() const; void SetKeyBinding(Model::ActionAndArgs const& actionAndArgs, - TerminalControl::KeyChord const& chord); - void ClearKeyBinding(TerminalControl::KeyChord const& chord); - TerminalControl::KeyChord GetKeyBindingForAction(Model::ShortcutAction const& action); - TerminalControl::KeyChord GetKeyBindingForActionWithArgs(Model::ActionAndArgs const& actionAndArgs); + Control::KeyChord const& chord); + void ClearKeyBinding(Control::KeyChord const& chord); + Control::KeyChord GetKeyBindingForAction(Model::ShortcutAction const& action); + Control::KeyChord GetKeyBindingForActionWithArgs(Model::ActionAndArgs const& actionAndArgs); - static Windows::System::VirtualKeyModifiers ConvertVKModifiers(TerminalControl::KeyModifiers modifiers); + static Windows::System::VirtualKeyModifiers ConvertVKModifiers(Control::KeyModifiers modifiers); // Defined in KeyMappingSerialization.cpp std::vector LayerJson(const Json::Value& json); Json::Value ToJson(); private: - std::unordered_map _keyShortcuts; - std::vector> _keyShortcutsByInsertionOrder; + std::unordered_map _keyShortcuts; + std::vector> _keyShortcutsByInsertionOrder; friend class SettingsModelLocalTests::DeserializationTests; friend class SettingsModelLocalTests::KeyBindingsTests; diff --git a/src/cascadia/TerminalSettingsModel/KeyMapping.idl b/src/cascadia/TerminalSettingsModel/KeyMapping.idl index a51a601afee..41fb1e4e3bf 100644 --- a/src/cascadia/TerminalSettingsModel/KeyMapping.idl +++ b/src/cascadia/TerminalSettingsModel/KeyMapping.idl @@ -67,13 +67,13 @@ namespace Microsoft.Terminal.Settings.Model [default_interface] runtimeclass KeyMapping { - ActionAndArgs TryLookup(Microsoft.Terminal.TerminalControl.KeyChord chord); + ActionAndArgs TryLookup(Microsoft.Terminal.Control.KeyChord chord); UInt64 Size(); - void SetKeyBinding(ActionAndArgs actionAndArgs, Microsoft.Terminal.TerminalControl.KeyChord chord); - void ClearKeyBinding(Microsoft.Terminal.TerminalControl.KeyChord chord); + void SetKeyBinding(ActionAndArgs actionAndArgs, Microsoft.Terminal.Control.KeyChord chord); + void ClearKeyBinding(Microsoft.Terminal.Control.KeyChord chord); - Microsoft.Terminal.TerminalControl.KeyChord GetKeyBindingForAction(ShortcutAction action); - Microsoft.Terminal.TerminalControl.KeyChord GetKeyBindingForActionWithArgs(ActionAndArgs actionAndArgs); + Microsoft.Terminal.Control.KeyChord GetKeyBindingForAction(ShortcutAction action); + Microsoft.Terminal.Control.KeyChord GetKeyBindingForActionWithArgs(ActionAndArgs actionAndArgs); } } diff --git a/src/cascadia/TerminalSettingsModel/KeyMappingSerialization.cpp b/src/cascadia/TerminalSettingsModel/KeyMappingSerialization.cpp index 665c938f591..24d6a4bee16 100644 --- a/src/cascadia/TerminalSettingsModel/KeyMappingSerialization.cpp +++ b/src/cascadia/TerminalSettingsModel/KeyMappingSerialization.cpp @@ -12,7 +12,7 @@ #include "KeyChordSerialization.h" #include "JsonUtils.h" -using namespace winrt::Microsoft::Terminal::TerminalControl; +using namespace winrt::Microsoft::Terminal::Control; using namespace winrt::Microsoft::Terminal::Settings::Model; static constexpr std::string_view KeysKey{ "keys" }; diff --git a/src/cascadia/TerminalSettingsModel/Microsoft.Terminal.Settings.ModelLib.vcxproj b/src/cascadia/TerminalSettingsModel/Microsoft.Terminal.Settings.ModelLib.vcxproj index 777fd057fcd..de6294c7d16 100644 --- a/src/cascadia/TerminalSettingsModel/Microsoft.Terminal.Settings.ModelLib.vcxproj +++ b/src/cascadia/TerminalSettingsModel/Microsoft.Terminal.Settings.ModelLib.vcxproj @@ -166,8 +166,8 @@ false false - - $(OpenConsoleCommonOutDir)TerminalControl\Microsoft.Terminal.TerminalControl.winmd + + $(OpenConsoleCommonOutDir)TerminalControl\Microsoft.Terminal.Control.winmd true false false diff --git a/src/cascadia/TerminalSettingsModel/Profile.cpp b/src/cascadia/TerminalSettingsModel/Profile.cpp index a539399bd7c..624d134c39e 100644 --- a/src/cascadia/TerminalSettingsModel/Profile.cpp +++ b/src/cascadia/TerminalSettingsModel/Profile.cpp @@ -14,7 +14,7 @@ using namespace Microsoft::Terminal::Settings::Model; using namespace winrt::Microsoft::Terminal::Settings::Model::implementation; -using namespace winrt::Microsoft::Terminal::TerminalControl; +using namespace winrt::Microsoft::Terminal::Control; using namespace winrt::Windows::UI; using namespace winrt::Windows::UI::Xaml; using namespace winrt::Windows::Foundation; diff --git a/src/cascadia/TerminalSettingsModel/Profile.h b/src/cascadia/TerminalSettingsModel/Profile.h index c231d383abe..3b7efbc67cd 100644 --- a/src/cascadia/TerminalSettingsModel/Profile.h +++ b/src/cascadia/TerminalSettingsModel/Profile.h @@ -85,7 +85,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation INHERITABLE_SETTING(Model::Profile, bool, UseAcrylic, false); INHERITABLE_SETTING(Model::Profile, double, AcrylicOpacity, 0.5); - INHERITABLE_SETTING(Model::Profile, Microsoft::Terminal::TerminalControl::ScrollbarState, ScrollState, Microsoft::Terminal::TerminalControl::ScrollbarState::Visible); + INHERITABLE_SETTING(Model::Profile, Microsoft::Terminal::Control::ScrollbarState, ScrollState, Microsoft::Terminal::Control::ScrollbarState::Visible); INHERITABLE_SETTING(Model::Profile, hstring, FontFace, DEFAULT_FONT_FACE); INHERITABLE_SETTING(Model::Profile, int32_t, FontSize, DEFAULT_FONT_SIZE); @@ -100,7 +100,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation INHERITABLE_SETTING(Model::Profile, Windows::UI::Xaml::Media::Stretch, BackgroundImageStretchMode, Windows::UI::Xaml::Media::Stretch::UniformToFill); INHERITABLE_SETTING(Model::Profile, ConvergedAlignment, BackgroundImageAlignment, ConvergedAlignment::Horizontal_Center | ConvergedAlignment::Vertical_Center); - INHERITABLE_SETTING(Model::Profile, Microsoft::Terminal::TerminalControl::TextAntialiasingMode, AntialiasingMode, Microsoft::Terminal::TerminalControl::TextAntialiasingMode::Grayscale); + INHERITABLE_SETTING(Model::Profile, Microsoft::Terminal::Control::TextAntialiasingMode, AntialiasingMode, Microsoft::Terminal::Control::TextAntialiasingMode::Grayscale); INHERITABLE_SETTING(Model::Profile, bool, RetroTerminalEffect, false); INHERITABLE_SETTING(Model::Profile, hstring, PixelShaderPath, L""); INHERITABLE_SETTING(Model::Profile, bool, ForceFullRepaintRendering, false); diff --git a/src/cascadia/TerminalSettingsModel/Profile.idl b/src/cascadia/TerminalSettingsModel/Profile.idl index 9fd21425ca0..a122dcb4a07 100644 --- a/src/cascadia/TerminalSettingsModel/Profile.idl +++ b/src/cascadia/TerminalSettingsModel/Profile.idl @@ -70,7 +70,7 @@ namespace Microsoft.Terminal.Settings.Model INHERITABLE_PROFILE_SETTING(Boolean, SuppressApplicationTitle); INHERITABLE_PROFILE_SETTING(Boolean, UseAcrylic); INHERITABLE_PROFILE_SETTING(Double, AcrylicOpacity); - INHERITABLE_PROFILE_SETTING(Microsoft.Terminal.TerminalControl.ScrollbarState, ScrollState); + INHERITABLE_PROFILE_SETTING(Microsoft.Terminal.Control.ScrollbarState, ScrollState); INHERITABLE_PROFILE_SETTING(String, FontFace); INHERITABLE_PROFILE_SETTING(Int32, FontSize); INHERITABLE_PROFILE_SETTING(Windows.UI.Text.FontWeight, FontWeight); @@ -86,7 +86,7 @@ namespace Microsoft.Terminal.Settings.Model INHERITABLE_PROFILE_SETTING(Double, BackgroundImageOpacity); INHERITABLE_PROFILE_SETTING(Windows.UI.Xaml.Media.Stretch, BackgroundImageStretchMode); INHERITABLE_PROFILE_SETTING(ConvergedAlignment, BackgroundImageAlignment); - INHERITABLE_PROFILE_SETTING(Microsoft.Terminal.TerminalControl.TextAntialiasingMode, AntialiasingMode); + INHERITABLE_PROFILE_SETTING(Microsoft.Terminal.Control.TextAntialiasingMode, AntialiasingMode); INHERITABLE_PROFILE_SETTING(Boolean, RetroTerminalEffect); INHERITABLE_PROFILE_SETTING(String, PixelShaderPath); INHERITABLE_PROFILE_SETTING(Boolean, ForceFullRepaintRendering); diff --git a/src/cascadia/TerminalSettingsModel/TerminalSettingsSerializationHelpers.h b/src/cascadia/TerminalSettingsModel/TerminalSettingsSerializationHelpers.h index d469ee6ead1..bdda3eef5a2 100644 --- a/src/cascadia/TerminalSettingsModel/TerminalSettingsSerializationHelpers.h +++ b/src/cascadia/TerminalSettingsModel/TerminalSettingsSerializationHelpers.h @@ -40,7 +40,7 @@ JSON_ENUM_MAPPER(::winrt::Windows::UI::Xaml::Media::Stretch) }; }; -JSON_ENUM_MAPPER(::winrt::Microsoft::Terminal::TerminalControl::ScrollbarState) +JSON_ENUM_MAPPER(::winrt::Microsoft::Terminal::Control::ScrollbarState) { static constexpr std::array mappings = { pair_type{ "visible", ValueType::Visible }, @@ -93,7 +93,7 @@ JSON_ENUM_MAPPER(::winrt::Microsoft::Terminal::Settings::Model::ConvergedAlignme }; }; -JSON_ENUM_MAPPER(::winrt::Microsoft::Terminal::TerminalControl::TextAntialiasingMode) +JSON_ENUM_MAPPER(::winrt::Microsoft::Terminal::Control::TextAntialiasingMode) { static constexpr std::array mappings = { pair_type{ "grayscale", ValueType::Grayscale }, @@ -235,7 +235,7 @@ JSON_ENUM_MAPPER(winrt::Microsoft::Terminal::Settings::Model::ExpandCommandType) }; }; -JSON_FLAG_MAPPER(::winrt::Microsoft::Terminal::TerminalControl::CopyFormat) +JSON_FLAG_MAPPER(::winrt::Microsoft::Terminal::Control::CopyFormat) { JSON_MAPPINGS(4) = { pair_type{ "none", AllClear }, diff --git a/src/cascadia/TerminalSettingsModel/dll/Microsoft.Terminal.Settings.Model.vcxproj b/src/cascadia/TerminalSettingsModel/dll/Microsoft.Terminal.Settings.Model.vcxproj index ff5ca15aa8d..e4143f01918 100644 --- a/src/cascadia/TerminalSettingsModel/dll/Microsoft.Terminal.Settings.Model.vcxproj +++ b/src/cascadia/TerminalSettingsModel/dll/Microsoft.Terminal.Settings.Model.vcxproj @@ -82,8 +82,8 @@ MDMERGE will know where the TermControl types are defined. However, we need to do it exactly like this so the packaging project won't roll up TermControl's .xbf's from both the TermControl project and this one. --> - - $(OpenConsoleCommonOutDir)TerminalControl\Microsoft.Terminal.TerminalControl.winmd + + $(OpenConsoleCommonOutDir)TerminalControl\Microsoft.Terminal.Control.winmd true false false diff --git a/src/cascadia/TerminalSettingsModel/pch.h b/src/cascadia/TerminalSettingsModel/pch.h index 3c2a685e41b..8bedb61ba67 100644 --- a/src/cascadia/TerminalSettingsModel/pch.h +++ b/src/cascadia/TerminalSettingsModel/pch.h @@ -54,7 +54,7 @@ TRACELOGGING_DECLARE_PROVIDER(g_hSettingsModelProvider); #include -#include +#include #include // Manually include til after we include Windows.Foundation to give it winrt superpowers diff --git a/src/cascadia/WindowsTerminal/AppHost.cpp b/src/cascadia/WindowsTerminal/AppHost.cpp index 4381654fc04..2b7cac81d6a 100644 --- a/src/cascadia/WindowsTerminal/AppHost.cpp +++ b/src/cascadia/WindowsTerminal/AppHost.cpp @@ -502,7 +502,7 @@ void AppHost::_WindowMouseWheeled(const til::point coord, const int32_t delta) for (const auto& e : elems) { // If that element has implemented IMouseWheelListener, call OnMouseWheel on that element. - if (auto control{ e.try_as() }) + if (auto control{ e.try_as() }) { try { diff --git a/src/cascadia/WindowsTerminal/pch.h b/src/cascadia/WindowsTerminal/pch.h index 2a4fb9c4a60..8009d455e1a 100644 --- a/src/cascadia/WindowsTerminal/pch.h +++ b/src/cascadia/WindowsTerminal/pch.h @@ -66,7 +66,7 @@ Module Name: #include #include #include -#include +#include #include #include diff --git a/src/cascadia/ut_app/JsonTests.cpp b/src/cascadia/ut_app/JsonTests.cpp index 9111893b5ad..f9bc61f6b05 100644 --- a/src/cascadia/ut_app/JsonTests.cpp +++ b/src/cascadia/ut_app/JsonTests.cpp @@ -14,7 +14,7 @@ using namespace WEX::Logging; using namespace WEX::TestExecution; using namespace WEX::Common; using namespace winrt::Microsoft::Terminal::Settings::Model; -using namespace winrt::Microsoft::Terminal::TerminalControl; +using namespace winrt::Microsoft::Terminal::Control; namespace TerminalAppUnitTests { From eee5beeaf37b215ed326679d95ab469c847950f1 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Fri, 12 Mar 2021 12:19:17 -0600 Subject: [PATCH 10/82] some dead code --- .../dll/TerminalControl.vcxproj | 27 ++----------------- .../WindowsTerminal/WindowsTerminal.vcxproj | 7 +++-- 2 files changed, 7 insertions(+), 27 deletions(-) diff --git a/src/cascadia/TerminalControl/dll/TerminalControl.vcxproj b/src/cascadia/TerminalControl/dll/TerminalControl.vcxproj index abccc9a44ae..cec5c6e3243 100644 --- a/src/cascadia/TerminalControl/dll/TerminalControl.vcxproj +++ b/src/cascadia/TerminalControl/dll/TerminalControl.vcxproj @@ -52,24 +52,8 @@ - - - - - true @@ -97,13 +81,6 @@ - - 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) diff --git a/src/cascadia/WindowsTerminal/WindowsTerminal.vcxproj b/src/cascadia/WindowsTerminal/WindowsTerminal.vcxproj index 3bb9ff83ca4..e5206c4db21 100644 --- a/src/cascadia/WindowsTerminal/WindowsTerminal.vcxproj +++ b/src/cascadia/WindowsTerminal/WindowsTerminal.vcxproj @@ -72,7 +72,6 @@ - @@ -84,7 +83,11 @@ - + $(OpenConsoleCommonOutDir)TerminalCore\Microsoft.Terminal.Core.winmd From 04d403ca97a09887a6bdf392fbba7ef82329a3b0 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Tue, 16 Mar 2021 10:35:57 -0500 Subject: [PATCH 11/82] Change the GUID, project name --- OpenConsole.sln | 68 +++++++++---------- .../TerminalApp/TerminalAppLib.vcxproj | 2 +- .../TerminalApp/dll/TerminalApp.vcxproj | 14 +--- .../TerminalControlLib.vcxproj | 7 +- .../dll/TerminalControl.vcxproj | 5 +- ...Microsoft.Terminal.Settings.Editor.vcxproj | 2 +- ...crosoft.Terminal.Settings.ModelLib.vcxproj | 2 +- .../Microsoft.Terminal.Settings.Model.vcxproj | 2 +- .../WindowsTerminalUniversal.vcxproj | 14 ++++ 9 files changed, 58 insertions(+), 58 deletions(-) diff --git a/OpenConsole.sln b/OpenConsole.sln index 3ff97f64fe0..71bc8ce925e 100644 --- a/OpenConsole.sln +++ b/OpenConsole.sln @@ -169,7 +169,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TerminalControlLib", "src\c {48D21369-3D7B-4431-9967-24E81292CF63} = {48D21369-3D7B-4431-9967-24E81292CF63} EndProjectSection EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TerminalControl", "src\cascadia\TerminalControl\dll\TerminalControl.vcxproj", "{CA5CAD1A-5555-4AC7-AC72-6CA5B3AB89ED}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TerminalControl", "src\cascadia\TerminalControl\dll\TerminalControl.vcxproj", "{CA5CAD1A-F542-4635-A069-7CAEFB930070}" ProjectSection(ProjectDependencies) = postProject {CA5CAD1A-44BD-4AC7-AC72-6CA5B3AB89ED} = {CA5CAD1A-44BD-4AC7-AC72-6CA5B3AB89ED} EndProjectSection @@ -177,7 +177,7 @@ EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WindowsTerminal", "src\cascadia\WindowsTerminal\WindowsTerminal.vcxproj", "{CA5CAD1A-1754-4A9D-93D7-857A9D17CB1B}" ProjectSection(ProjectDependencies) = postProject {CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32} = {CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32} - {CA5CAD1A-5555-4AC7-AC72-6CA5B3AB89ED} = {CA5CAD1A-5555-4AC7-AC72-6CA5B3AB89ED} + {CA5CAD1A-F542-4635-A069-7CAEFB930070} = {CA5CAD1A-F542-4635-A069-7CAEFB930070} {CA5CAD1A-44BD-4AC7-AC72-F16E576FDD12} = {CA5CAD1A-44BD-4AC7-AC72-F16E576FDD12} {CA5CAD1A-ABCD-429C-B551-8562EC954746} = {CA5CAD1A-ABCD-429C-B551-8562EC954746} {27B5AAEB-A548-44CF-9777-F8BAA32AF7AE} = {27B5AAEB-A548-44CF-9777-F8BAA32AF7AE} @@ -190,7 +190,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TerminalApp", "src\cascadia {CA5CAD1A-082C-4476-9F33-94B339494076} = {CA5CAD1A-082C-4476-9F33-94B339494076} {CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32} = {CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32} {CA5CAD1A-C46D-4588-B1C0-40F31AE9100B} = {CA5CAD1A-C46D-4588-B1C0-40F31AE9100B} - {CA5CAD1A-5555-4AC7-AC72-6CA5B3AB89ED} = {CA5CAD1A-5555-4AC7-AC72-6CA5B3AB89ED} + {CA5CAD1A-F542-4635-A069-7CAEFB930070} = {CA5CAD1A-F542-4635-A069-7CAEFB930070} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WindowsTerminalShellExt", "src\cascadia\ShellExtension\WindowsTerminalShellExt.vcxproj", "{F2ED628A-DB22-446F-A081-4CC845B51A2B}" @@ -241,7 +241,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TerminalAppLib", "src\casca ProjectSection(ProjectDependencies) = postProject {CA5CAD1A-082C-4476-9F33-94B339494076} = {CA5CAD1A-082C-4476-9F33-94B339494076} {CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32} = {CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32} - {CA5CAD1A-5555-4AC7-AC72-6CA5B3AB89ED} = {CA5CAD1A-5555-4AC7-AC72-6CA5B3AB89ED} + {CA5CAD1A-F542-4635-A069-7CAEFB930070} = {CA5CAD1A-F542-4635-A069-7CAEFB930070} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LocalTests_TerminalApp", "src\cascadia\LocalTests_TerminalApp\TerminalApp.LocalTests.vcxproj", "{CA5CAD1A-B11C-4DDB-A4FE-C3AFAE9B5506}" @@ -331,7 +331,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Microsoft.Terminal.Settings EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Microsoft.Terminal.Settings.Model.Lib", "src\cascadia\TerminalSettingsModel\Microsoft.Terminal.Settings.ModelLib.vcxproj", "{CA5CAD1A-D7EC-4107-B7C6-79CB77AE2907}" ProjectSection(ProjectDependencies) = postProject - {CA5CAD1A-5555-4AC7-AC72-6CA5B3AB89ED} = {CA5CAD1A-5555-4AC7-AC72-6CA5B3AB89ED} + {CA5CAD1A-F542-4635-A069-7CAEFB930070} = {CA5CAD1A-F542-4635-A069-7CAEFB930070} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Microsoft.Terminal.Settings.Model", "src\cascadia\TerminalSettingsModel\dll\Microsoft.Terminal.Settings.Model.vcxproj", "{CA5CAD1A-082C-4476-9F33-94B339494076}" @@ -343,7 +343,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LocalTests_SettingsModel", ProjectSection(ProjectDependencies) = postProject {CA5CAD1A-082C-4476-9F33-94B339494076} = {CA5CAD1A-082C-4476-9F33-94B339494076} {CA5CAD1A-C46D-4588-B1C0-40F31AE9100B} = {CA5CAD1A-C46D-4588-B1C0-40F31AE9100B} - {CA5CAD1A-5555-4AC7-AC72-6CA5B3AB89ED} = {CA5CAD1A-5555-4AC7-AC72-6CA5B3AB89ED} + {CA5CAD1A-F542-4635-A069-7CAEFB930070} = {CA5CAD1A-F542-4635-A069-7CAEFB930070} {CA5CAD1A-D7EC-4107-B7C6-79CB77AE2907} = {CA5CAD1A-D7EC-4107-B7C6-79CB77AE2907} EndProjectSection EndProject @@ -1529,33 +1529,33 @@ Global {CA5CAD1A-44BD-4AC7-AC72-6CA5B3AB89ED}.Release|x64.Build.0 = Release|x64 {CA5CAD1A-44BD-4AC7-AC72-6CA5B3AB89ED}.Release|x86.ActiveCfg = Release|Win32 {CA5CAD1A-44BD-4AC7-AC72-6CA5B3AB89ED}.Release|x86.Build.0 = Release|Win32 - {CA5CAD1A-5555-4AC7-AC72-6CA5B3AB89ED}.AuditMode|Any CPU.ActiveCfg = Debug|Win32 - {CA5CAD1A-5555-4AC7-AC72-6CA5B3AB89ED}.AuditMode|ARM.ActiveCfg = AuditMode|Win32 - {CA5CAD1A-5555-4AC7-AC72-6CA5B3AB89ED}.AuditMode|ARM64.ActiveCfg = Release|ARM64 - {CA5CAD1A-5555-4AC7-AC72-6CA5B3AB89ED}.AuditMode|DotNet_x64Test.ActiveCfg = Debug|Win32 - {CA5CAD1A-5555-4AC7-AC72-6CA5B3AB89ED}.AuditMode|DotNet_x86Test.ActiveCfg = Debug|Win32 - {CA5CAD1A-5555-4AC7-AC72-6CA5B3AB89ED}.AuditMode|x64.ActiveCfg = Release|x64 - {CA5CAD1A-5555-4AC7-AC72-6CA5B3AB89ED}.AuditMode|x86.ActiveCfg = Release|Win32 - {CA5CAD1A-5555-4AC7-AC72-6CA5B3AB89ED}.Debug|Any CPU.ActiveCfg = Debug|Win32 - {CA5CAD1A-5555-4AC7-AC72-6CA5B3AB89ED}.Debug|ARM.ActiveCfg = Debug|Win32 - {CA5CAD1A-5555-4AC7-AC72-6CA5B3AB89ED}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {CA5CAD1A-5555-4AC7-AC72-6CA5B3AB89ED}.Debug|ARM64.Build.0 = Debug|ARM64 - {CA5CAD1A-5555-4AC7-AC72-6CA5B3AB89ED}.Debug|DotNet_x64Test.ActiveCfg = Debug|Win32 - {CA5CAD1A-5555-4AC7-AC72-6CA5B3AB89ED}.Debug|DotNet_x86Test.ActiveCfg = Debug|Win32 - {CA5CAD1A-5555-4AC7-AC72-6CA5B3AB89ED}.Debug|x64.ActiveCfg = Debug|x64 - {CA5CAD1A-5555-4AC7-AC72-6CA5B3AB89ED}.Debug|x64.Build.0 = Debug|x64 - {CA5CAD1A-5555-4AC7-AC72-6CA5B3AB89ED}.Debug|x86.ActiveCfg = Debug|Win32 - {CA5CAD1A-5555-4AC7-AC72-6CA5B3AB89ED}.Debug|x86.Build.0 = Debug|Win32 - {CA5CAD1A-5555-4AC7-AC72-6CA5B3AB89ED}.Release|Any CPU.ActiveCfg = Release|Win32 - {CA5CAD1A-5555-4AC7-AC72-6CA5B3AB89ED}.Release|ARM.ActiveCfg = Release|Win32 - {CA5CAD1A-5555-4AC7-AC72-6CA5B3AB89ED}.Release|ARM64.ActiveCfg = Release|ARM64 - {CA5CAD1A-5555-4AC7-AC72-6CA5B3AB89ED}.Release|ARM64.Build.0 = Release|ARM64 - {CA5CAD1A-5555-4AC7-AC72-6CA5B3AB89ED}.Release|DotNet_x64Test.ActiveCfg = Release|Win32 - {CA5CAD1A-5555-4AC7-AC72-6CA5B3AB89ED}.Release|DotNet_x86Test.ActiveCfg = Release|Win32 - {CA5CAD1A-5555-4AC7-AC72-6CA5B3AB89ED}.Release|x64.ActiveCfg = Release|x64 - {CA5CAD1A-5555-4AC7-AC72-6CA5B3AB89ED}.Release|x64.Build.0 = Release|x64 - {CA5CAD1A-5555-4AC7-AC72-6CA5B3AB89ED}.Release|x86.ActiveCfg = Release|Win32 - {CA5CAD1A-5555-4AC7-AC72-6CA5B3AB89ED}.Release|x86.Build.0 = Release|Win32 + {CA5CAD1A-F542-4635-A069-7CAEFB930070}.AuditMode|Any CPU.ActiveCfg = Debug|Win32 + {CA5CAD1A-F542-4635-A069-7CAEFB930070}.AuditMode|ARM.ActiveCfg = AuditMode|Win32 + {CA5CAD1A-F542-4635-A069-7CAEFB930070}.AuditMode|ARM64.ActiveCfg = Release|ARM64 + {CA5CAD1A-F542-4635-A069-7CAEFB930070}.AuditMode|DotNet_x64Test.ActiveCfg = Debug|Win32 + {CA5CAD1A-F542-4635-A069-7CAEFB930070}.AuditMode|DotNet_x86Test.ActiveCfg = Debug|Win32 + {CA5CAD1A-F542-4635-A069-7CAEFB930070}.AuditMode|x64.ActiveCfg = Release|x64 + {CA5CAD1A-F542-4635-A069-7CAEFB930070}.AuditMode|x86.ActiveCfg = Release|Win32 + {CA5CAD1A-F542-4635-A069-7CAEFB930070}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {CA5CAD1A-F542-4635-A069-7CAEFB930070}.Debug|ARM.ActiveCfg = Debug|Win32 + {CA5CAD1A-F542-4635-A069-7CAEFB930070}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {CA5CAD1A-F542-4635-A069-7CAEFB930070}.Debug|ARM64.Build.0 = Debug|ARM64 + {CA5CAD1A-F542-4635-A069-7CAEFB930070}.Debug|DotNet_x64Test.ActiveCfg = Debug|Win32 + {CA5CAD1A-F542-4635-A069-7CAEFB930070}.Debug|DotNet_x86Test.ActiveCfg = Debug|Win32 + {CA5CAD1A-F542-4635-A069-7CAEFB930070}.Debug|x64.ActiveCfg = Debug|x64 + {CA5CAD1A-F542-4635-A069-7CAEFB930070}.Debug|x64.Build.0 = Debug|x64 + {CA5CAD1A-F542-4635-A069-7CAEFB930070}.Debug|x86.ActiveCfg = Debug|Win32 + {CA5CAD1A-F542-4635-A069-7CAEFB930070}.Debug|x86.Build.0 = Debug|Win32 + {CA5CAD1A-F542-4635-A069-7CAEFB930070}.Release|Any CPU.ActiveCfg = Release|Win32 + {CA5CAD1A-F542-4635-A069-7CAEFB930070}.Release|ARM.ActiveCfg = Release|Win32 + {CA5CAD1A-F542-4635-A069-7CAEFB930070}.Release|ARM64.ActiveCfg = Release|ARM64 + {CA5CAD1A-F542-4635-A069-7CAEFB930070}.Release|ARM64.Build.0 = Release|ARM64 + {CA5CAD1A-F542-4635-A069-7CAEFB930070}.Release|DotNet_x64Test.ActiveCfg = Release|Win32 + {CA5CAD1A-F542-4635-A069-7CAEFB930070}.Release|DotNet_x86Test.ActiveCfg = Release|Win32 + {CA5CAD1A-F542-4635-A069-7CAEFB930070}.Release|x64.ActiveCfg = Release|x64 + {CA5CAD1A-F542-4635-A069-7CAEFB930070}.Release|x64.Build.0 = Release|x64 + {CA5CAD1A-F542-4635-A069-7CAEFB930070}.Release|x86.ActiveCfg = Release|Win32 + {CA5CAD1A-F542-4635-A069-7CAEFB930070}.Release|x86.Build.0 = Release|Win32 {CA5CAD1A-1754-4A9D-93D7-857A9D17CB1B}.AuditMode|Any CPU.ActiveCfg = Debug|x64 {CA5CAD1A-1754-4A9D-93D7-857A9D17CB1B}.AuditMode|ARM.ActiveCfg = AuditMode|Win32 {CA5CAD1A-1754-4A9D-93D7-857A9D17CB1B}.AuditMode|ARM64.ActiveCfg = Release|ARM64 @@ -2657,7 +2657,7 @@ Global {CA5CAD1A-C46D-4588-B1C0-40F31AE9100B} = {59840756-302F-44DF-AA47-441A9D673202} {CA5CAD1A-ABCD-429C-B551-8562EC954746} = {9921CA0A-320C-4460-8623-3A3196E7F4CB} {CA5CAD1A-44BD-4AC7-AC72-6CA5B3AB89ED} = {9921CA0A-320C-4460-8623-3A3196E7F4CB} - {CA5CAD1A-5555-4AC7-AC72-6CA5B3AB89ED} = {9921CA0A-320C-4460-8623-3A3196E7F4CB} + {CA5CAD1A-F542-4635-A069-7CAEFB930070} = {9921CA0A-320C-4460-8623-3A3196E7F4CB} {CA5CAD1A-1754-4A9D-93D7-857A9D17CB1B} = {2D17E75D-2DDC-42C4-AD70-704D95A937AE} {CA5CAD1A-44BD-4AC7-AC72-F16E576FDD12} = {59840756-302F-44DF-AA47-441A9D673202} {F2ED628A-DB22-446F-A081-4CC845B51A2B} = {2D17E75D-2DDC-42C4-AD70-704D95A937AE} diff --git a/src/cascadia/TerminalApp/TerminalAppLib.vcxproj b/src/cascadia/TerminalApp/TerminalAppLib.vcxproj index c8cca641b2c..700ba78ca54 100644 --- a/src/cascadia/TerminalApp/TerminalAppLib.vcxproj +++ b/src/cascadia/TerminalApp/TerminalAppLib.vcxproj @@ -329,7 +329,7 @@ false - $(OpenConsoleCommonOutDir)TerminalControl\Microsoft.Terminal.Control.winmd + $(OpenConsoleCommonOutDir)Microsoft.Terminal.Control\Microsoft.Terminal.Control.winmd true false false diff --git a/src/cascadia/TerminalApp/dll/TerminalApp.vcxproj b/src/cascadia/TerminalApp/dll/TerminalApp.vcxproj index 7ed46666e23..1aa555c17c6 100644 --- a/src/cascadia/TerminalApp/dll/TerminalApp.vcxproj +++ b/src/cascadia/TerminalApp/dll/TerminalApp.vcxproj @@ -77,17 +77,9 @@ - - - + $(OpenConsoleCommonOutDir)TerminalCore\Microsoft.Terminal.Core.winmd true diff --git a/src/cascadia/TerminalControl/TerminalControlLib.vcxproj b/src/cascadia/TerminalControl/TerminalControlLib.vcxproj index 0318dcfc5a7..a665378e52e 100644 --- a/src/cascadia/TerminalControl/TerminalControlLib.vcxproj +++ b/src/cascadia/TerminalControl/TerminalControlLib.vcxproj @@ -3,10 +3,9 @@ {CA5CAD1A-44BD-4AC7-AC72-6CA5B3AB89ED} Win32Proj - TerminalControlLib + Microsoft.Terminal.Control.Lib Microsoft.Terminal.Control Microsoft.Terminal.ControlLib - 10.0.17763.0 StaticLibrary Console true @@ -132,10 +131,6 @@ pch.h $(OpenConsoleDir)src\cascadia\inc;$(OpenConsoleDir)src\types\inc;%(AdditionalIncludeDirectories) - - 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) - - false diff --git a/src/cascadia/TerminalControl/dll/TerminalControl.vcxproj b/src/cascadia/TerminalControl/dll/TerminalControl.vcxproj index cec5c6e3243..7ac145ce414 100644 --- a/src/cascadia/TerminalControl/dll/TerminalControl.vcxproj +++ b/src/cascadia/TerminalControl/dll/TerminalControl.vcxproj @@ -1,9 +1,8 @@ - {CA5CAD1A-5555-4AC7-AC72-6CA5B3AB89ED} - TerminalControl - + {CA5CAD1A-F542-4635-A069-7CAEFB930070} + Microsoft.Terminal.Control Microsoft.Terminal.Control diff --git a/src/cascadia/TerminalSettingsEditor/Microsoft.Terminal.Settings.Editor.vcxproj b/src/cascadia/TerminalSettingsEditor/Microsoft.Terminal.Settings.Editor.vcxproj index 88e5e5b6033..98acfdb1068 100644 --- a/src/cascadia/TerminalSettingsEditor/Microsoft.Terminal.Settings.Editor.vcxproj +++ b/src/cascadia/TerminalSettingsEditor/Microsoft.Terminal.Settings.Editor.vcxproj @@ -287,7 +287,7 @@ to do it exactly like this so the packaging project won't roll up TermControl's .xbf's from both the TermControl project and this one. --> - $(OpenConsoleCommonOutDir)TerminalControl\Microsoft.Terminal.Control.winmd + $(OpenConsoleCommonOutDir)Microsoft.Terminal.Control\Microsoft.Terminal.Control.winmd true false false diff --git a/src/cascadia/TerminalSettingsModel/Microsoft.Terminal.Settings.ModelLib.vcxproj b/src/cascadia/TerminalSettingsModel/Microsoft.Terminal.Settings.ModelLib.vcxproj index de6294c7d16..a662e7eb132 100644 --- a/src/cascadia/TerminalSettingsModel/Microsoft.Terminal.Settings.ModelLib.vcxproj +++ b/src/cascadia/TerminalSettingsModel/Microsoft.Terminal.Settings.ModelLib.vcxproj @@ -167,7 +167,7 @@ false - $(OpenConsoleCommonOutDir)TerminalControl\Microsoft.Terminal.Control.winmd + $(OpenConsoleCommonOutDir)Microsoft.Terminal.Control\Microsoft.Terminal.Control.winmd true false false diff --git a/src/cascadia/TerminalSettingsModel/dll/Microsoft.Terminal.Settings.Model.vcxproj b/src/cascadia/TerminalSettingsModel/dll/Microsoft.Terminal.Settings.Model.vcxproj index e4143f01918..9b8ed046cc1 100644 --- a/src/cascadia/TerminalSettingsModel/dll/Microsoft.Terminal.Settings.Model.vcxproj +++ b/src/cascadia/TerminalSettingsModel/dll/Microsoft.Terminal.Settings.Model.vcxproj @@ -83,7 +83,7 @@ to do it exactly like this so the packaging project won't roll up TermControl's .xbf's from both the TermControl project and this one. --> - $(OpenConsoleCommonOutDir)TerminalControl\Microsoft.Terminal.Control.winmd + $(OpenConsoleCommonOutDir)Microsoft.Terminal.Control\Microsoft.Terminal.Control.winmd true false false diff --git a/src/cascadia/WindowsTerminalUniversal/WindowsTerminalUniversal.vcxproj b/src/cascadia/WindowsTerminalUniversal/WindowsTerminalUniversal.vcxproj index 335c9cf13b2..ca328419044 100644 --- a/src/cascadia/WindowsTerminalUniversal/WindowsTerminalUniversal.vcxproj +++ b/src/cascadia/WindowsTerminalUniversal/WindowsTerminalUniversal.vcxproj @@ -72,6 +72,20 @@ + + + + $(OpenConsoleCommonOutDir)TerminalCore\Microsoft.Terminal.Core.winmd + true + false + false + + + From f8e969e44b58bf0e4529255db15614a21108a604 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Tue, 16 Mar 2021 12:02:32 -0500 Subject: [PATCH 12/82] oh! IT CAUGHT AN ISSUE! YAY! --- build/scripts/Test-WindowsTerminalPackage.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/scripts/Test-WindowsTerminalPackage.ps1 b/build/scripts/Test-WindowsTerminalPackage.ps1 index 2f2b5cbc349..f8bb00c8018 100644 --- a/build/scripts/Test-WindowsTerminalPackage.ps1 +++ b/build/scripts/Test-WindowsTerminalPackage.ps1 @@ -58,7 +58,7 @@ Try { ### Check the activatable class entries for a few DLLs we need. $inProcServers = $Manifest.Package.Extensions.Extension.InProcessServer.Path - $RequiredInProcServers = ("TerminalApp.dll", "TerminalControl.dll", "TerminalConnection.dll") + $RequiredInProcServers = ("TerminalApp.dll", "Microsoft.Terminal.Control.dll", "Microsoft.Terminal.Remoting.dll", "Microsoft.Terminal.Settings.Editor.dll", "Microsoft.Terminal.Settings.Model.dll", "TerminalConnection.dll") Write-Verbose "InProc Servers: $inProcServers" From 8c6c7ece5d95ed26e2914089864002f956b07135 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Wed, 17 Mar 2021 10:27:09 -0500 Subject: [PATCH 13/82] Bite-sized refactor: Move all the args in TermControl to their own file. Convert some older macro uses to TYPED_EVENT --- src/cascadia/TerminalApp/Pane.cpp | 2 +- src/cascadia/TerminalApp/Pane.h | 2 +- src/cascadia/TerminalApp/TerminalTab.cpp | 2 +- src/cascadia/TerminalControl/EventArgs.cpp | 12 ++ src/cascadia/TerminalControl/EventArgs.h | 129 ++++++++++++++++++ src/cascadia/TerminalControl/EventArgs.idl | 65 +++++++++ .../TerminalControl/IDirectKeyListener.idl | 14 ++ src/cascadia/TerminalControl/TermControl.cpp | 27 ++-- src/cascadia/TerminalControl/TermControl.h | 94 ++----------- src/cascadia/TerminalControl/TermControl.idl | 78 ++--------- .../TerminalControlLib.vcxproj | 8 ++ src/cascadia/TerminalControl/pch.h | 3 + 12 files changed, 267 insertions(+), 169 deletions(-) create mode 100644 src/cascadia/TerminalControl/EventArgs.cpp create mode 100644 src/cascadia/TerminalControl/EventArgs.h create mode 100644 src/cascadia/TerminalControl/EventArgs.idl create mode 100644 src/cascadia/TerminalControl/IDirectKeyListener.idl diff --git a/src/cascadia/TerminalApp/Pane.cpp b/src/cascadia/TerminalApp/Pane.cpp index 0c9d23b5252..8f0c126e57d 100644 --- a/src/cascadia/TerminalApp/Pane.cpp +++ b/src/cascadia/TerminalApp/Pane.cpp @@ -312,7 +312,7 @@ bool Pane::NavigateFocus(const FocusDirection& direction) // - // Return Value: // - -void Pane::_ControlConnectionStateChangedHandler(const TermControl& /*sender*/, +void Pane::_ControlConnectionStateChangedHandler(const winrt::Windows::Foundation::IInspectable& /*sender*/, const winrt::Windows::Foundation::IInspectable& /*args*/) { std::unique_lock lock{ _createCloseLock }; diff --git a/src/cascadia/TerminalApp/Pane.h b/src/cascadia/TerminalApp/Pane.h index 7a1cc69673e..28c1c13cf38 100644 --- a/src/cascadia/TerminalApp/Pane.h +++ b/src/cascadia/TerminalApp/Pane.h @@ -145,7 +145,7 @@ class Pane : public std::enable_shared_from_this winrt::fire_and_forget _CloseChildRoutine(const bool closeFirst); void _FocusFirstChild(); - void _ControlConnectionStateChangedHandler(const winrt::Microsoft::Terminal::Control::TermControl& sender, const winrt::Windows::Foundation::IInspectable& /*args*/); + void _ControlConnectionStateChangedHandler(const winrt::Windows::Foundation::IInspectable& sender, const winrt::Windows::Foundation::IInspectable& /*args*/); void _ControlWarningBellHandler(winrt::Windows::Foundation::IInspectable const& sender, winrt::Windows::Foundation::IInspectable const& e); void _ControlGotFocusHandler(winrt::Windows::Foundation::IInspectable const& sender, diff --git a/src/cascadia/TerminalApp/TerminalTab.cpp b/src/cascadia/TerminalApp/TerminalTab.cpp index 95f3399750c..5a6015220f2 100644 --- a/src/cascadia/TerminalApp/TerminalTab.cpp +++ b/src/cascadia/TerminalApp/TerminalTab.cpp @@ -542,7 +542,7 @@ namespace winrt::TerminalApp::implementation { auto weakThis{ get_weak() }; - control.TitleChanged([weakThis](auto newTitle) { + control.TitleChanged([weakThis](auto&&, auto&&) { // Check if Tab's lifetime has expired if (auto tab{ weakThis.get() }) { diff --git a/src/cascadia/TerminalControl/EventArgs.cpp b/src/cascadia/TerminalControl/EventArgs.cpp new file mode 100644 index 00000000000..3586f0314a9 --- /dev/null +++ b/src/cascadia/TerminalControl/EventArgs.cpp @@ -0,0 +1,12 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +#include "pch.h" +#include "EventArgs.h" +#include "TitleChangedEventArgs.g.cpp" +#include "CopyToClipboardEventArgs.g.cpp" +#include "PasteFromClipboardEventArgs.g.cpp" +#include "OpenHyperlinkEventArgs.g.cpp" +#include "NoticeEventArgs.g.cpp" +#include "ScrollPositionChangedArgs.g.cpp" +#include "RendererWarningArgs.g.cpp" diff --git a/src/cascadia/TerminalControl/EventArgs.h b/src/cascadia/TerminalControl/EventArgs.h new file mode 100644 index 00000000000..dfc31ad441c --- /dev/null +++ b/src/cascadia/TerminalControl/EventArgs.h @@ -0,0 +1,129 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +#pragma once + +#include "TitleChangedEventArgs.g.h" +#include "CopyToClipboardEventArgs.g.h" +#include "PasteFromClipboardEventArgs.g.h" +#include "OpenHyperlinkEventArgs.g.h" +#include "NoticeEventArgs.g.h" +#include "ScrollPositionChangedArgs.g.h" +#include "RendererWarningArgs.g.h" +#include "cppwinrt_utils.h" + +namespace winrt::Microsoft::Terminal::Control::implementation +{ + struct TitleChangedEventArgs : + public TitleChangedEventArgsT + { + public: + TitleChangedEventArgs(hstring title) : + _Title(title) {} + + WINRT_PROPERTY(hstring, Title); + }; + + struct CopyToClipboardEventArgs : + public CopyToClipboardEventArgsT + { + public: + CopyToClipboardEventArgs(hstring text) : + _text(text), + _html(), + _rtf(), + _formats(static_cast(0)) {} + + CopyToClipboardEventArgs(hstring text, hstring html, hstring rtf, Windows::Foundation::IReference formats) : + _text(text), + _html(html), + _rtf(rtf), + _formats(formats) {} + + hstring Text() { return _text; }; + hstring Html() { return _html; }; + hstring Rtf() { return _rtf; }; + Windows::Foundation::IReference Formats() { return _formats; }; + + private: + hstring _text; + hstring _html; + hstring _rtf; + Windows::Foundation::IReference _formats; + }; + + struct PasteFromClipboardEventArgs : + public PasteFromClipboardEventArgsT + { + public: + PasteFromClipboardEventArgs(std::function clipboardDataHandler) : + m_clipboardDataHandler(clipboardDataHandler) {} + + void HandleClipboardData(hstring value) + { + m_clipboardDataHandler(static_cast(value)); + }; + + private: + std::function m_clipboardDataHandler; + }; + + struct OpenHyperlinkEventArgs : + public OpenHyperlinkEventArgsT + { + public: + OpenHyperlinkEventArgs(hstring uri) : + _uri(uri) {} + + hstring Uri() { return _uri; }; + + private: + hstring _uri; + }; + + struct NoticeEventArgs : + public NoticeEventArgsT + { + public: + NoticeEventArgs(const NoticeLevel level, const hstring& message) : + _level(level), + _message(message) {} + + NoticeLevel Level() { return _level; }; + hstring Message() { return _message; }; + + private: + const NoticeLevel _level; + const hstring _message; + }; + + struct ScrollPositionChangedArgs : + public ScrollPositionChangedArgsT + { + public: + ScrollPositionChangedArgs(const int viewTop, + const int viewHeight, + const int bufferSize) : + _ViewTop(viewTop), + _ViewHeight(viewHeight), + _BufferSize(bufferSize) + { + } + + WINRT_PROPERTY(int32_t, ViewTop); + WINRT_PROPERTY(int32_t, ViewHeight); + WINRT_PROPERTY(int32_t, BufferSize); + }; + + struct RendererWarningArgs : + public RendererWarningArgsT + { + public: + RendererWarningArgs(const uint64_t hr) : + _Result(hr) + { + } + + WINRT_PROPERTY(uint64_t, Result); + }; +} diff --git a/src/cascadia/TerminalControl/EventArgs.idl b/src/cascadia/TerminalControl/EventArgs.idl new file mode 100644 index 00000000000..4fe7ff89115 --- /dev/null +++ b/src/cascadia/TerminalControl/EventArgs.idl @@ -0,0 +1,65 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +namespace Microsoft.Terminal.Control +{ + delegate void FontSizeChangedEventArgs(Int32 width, Int32 height, Boolean isInitialChange); + delegate void ScrollPositionChangedEventArgs(Int32 viewTop, Int32 viewHeight, Int32 bufferLength); + + [flags] + enum CopyFormat + { + HTML = 0x1, + RTF = 0x2, + All = 0xffffffff + }; + + runtimeclass CopyToClipboardEventArgs + { + String Text { get; }; + String Html { get; }; + String Rtf { get; }; + Windows.Foundation.IReference Formats { get; }; + } + + runtimeclass TitleChangedEventArgs + { + String Title; + } + + runtimeclass PasteFromClipboardEventArgs + { + void HandleClipboardData(String data); + } + + runtimeclass OpenHyperlinkEventArgs + { + String Uri { get; }; + } + + enum NoticeLevel + { + Debug = 10, + Info = 20, + Warning = 30, + Error = 40, + }; + + runtimeclass NoticeEventArgs + { + NoticeLevel Level { get; }; + String Message { get; }; + } + + runtimeclass ScrollPositionChangedArgs + { + Int32 ViewTop { get; }; + Int32 ViewHeight { get; }; + Int32 BufferSize { get; }; + } + + runtimeclass RendererWarningArgs + { + UInt64 Result { get; }; + } +} diff --git a/src/cascadia/TerminalControl/IDirectKeyListener.idl b/src/cascadia/TerminalControl/IDirectKeyListener.idl new file mode 100644 index 00000000000..06357270f9e --- /dev/null +++ b/src/cascadia/TerminalControl/IDirectKeyListener.idl @@ -0,0 +1,14 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +namespace Microsoft.Terminal.Control +{ + // C++/winrt makes it difficult to share this idl between two projects, + // Instead, we just pin the uuid and include it in both TermControl and App + // If you update this one, please update TerminalApp\IDirectKeyListener.idl. + // If you change this interface, please update the guid. + // If you press F7 or Alt and get a runtime error, go make sure both copies are the same. + [uuid("0ddf4edc-3fda-4dee-97ca-a417ee3dd510")] interface IDirectKeyListener { + Boolean OnDirectKeyEvent(UInt32 vkey, UInt8 scanCode, Boolean down); + }; +} diff --git a/src/cascadia/TerminalControl/TermControl.cpp b/src/cascadia/TerminalControl/TermControl.cpp index 555aeb67052..506783cf7de 100644 --- a/src/cascadia/TerminalControl/TermControl.cpp +++ b/src/cascadia/TerminalControl/TermControl.cpp @@ -704,7 +704,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation } auto noticeArgs = winrt::make(NoticeLevel::Warning, std::move(message)); - control->_raiseNoticeHandlers(*control, std::move(noticeArgs)); + control->_RaiseNoticeHandlers(*control, std::move(noticeArgs)); } } @@ -2134,7 +2134,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation co_await strong->Dispatcher(); auto noticeArgs = winrt::make(NoticeLevel::Warning, std::move(msg)); - strong->_raiseNoticeHandlers(*strong, std::move(noticeArgs)); + strong->_RaiseNoticeHandlers(*strong, std::move(noticeArgs)); }(); } @@ -2399,7 +2399,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation void TermControl::_TerminalTitleChanged(const std::wstring_view& wstr) { - _titleChangedHandlers(winrt::hstring{ wstr }); + auto titleArgs = winrt::make_self(winrt::hstring{ wstr }); + _TitleChangedHandlers(*this, *titleArgs); } void TermControl::_TerminalTabColorChanged(const std::optional /*color*/) { @@ -2409,7 +2410,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation void TermControl::_CopyToClipboard(const std::wstring_view& wstr) { auto copyArgs = winrt::make_self(winrt::hstring(wstr)); - _clipboardCopyHandlers(*this, *copyArgs); + _CopyToClipboardHandlers(*this, *copyArgs); } // Method Description: @@ -2540,7 +2541,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation winrt::to_hstring(htmlData), winrt::to_hstring(rtfData), formats); - _clipboardCopyHandlers(*this, *copyArgs); + _CopyToClipboardHandlers(*this, *copyArgs); return true; } @@ -2554,7 +2555,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation auto pasteArgs = winrt::make_self(clipboardDataHandler); // send paste event up to TermApp - _clipboardPasteHandlers(*this, *pasteArgs); + _PasteFromClipboardHandlers(*this, *pasteArgs); } // Method Description: @@ -3226,7 +3227,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation co_await Dispatcher(); auto hyperlinkArgs = winrt::make_self(heldUri); - _openHyperlinkHandlers(*strongThis, *hyperlinkArgs); + _OpenHyperlinkHandlers(*strongThis, *hyperlinkArgs); } // Method Description: @@ -3271,7 +3272,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation winrt::fire_and_forget TermControl::TaskbarProgressChanged() { co_await resume_foreground(Dispatcher(), CoreDispatcherPriority::High); - _setTaskbarProgressHandlers(*this, nullptr); + _SetTaskbarProgressHandlers(*this, nullptr); } // Method Description: @@ -3317,7 +3318,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation if (auto control{ weakThis.get() }) { auto noticeArgs = winrt::make(NoticeLevel::Info, RS_(L"TermControlReadOnly")); - control->_raiseNoticeHandlers(*control, std::move(noticeArgs)); + control->_RaiseNoticeHandlers(*control, std::move(noticeArgs)); } } @@ -3392,14 +3393,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation // -------------------------------- WinRT Events --------------------------------- // Winrt events need a method for adding a callback to the event and removing the callback. // These macros will define them both for you. - DEFINE_EVENT(TermControl, TitleChanged, _titleChangedHandlers, Control::TitleChangedEventArgs); DEFINE_EVENT(TermControl, FontSizeChanged, _fontSizeChangedHandlers, Control::FontSizeChangedEventArgs); DEFINE_EVENT(TermControl, ScrollPositionChanged, _scrollPositionChangedHandlers, Control::ScrollPositionChangedEventArgs); - - DEFINE_EVENT_WITH_TYPED_EVENT_HANDLER(TermControl, PasteFromClipboard, _clipboardPasteHandlers, Control::TermControl, Control::PasteFromClipboardEventArgs); - DEFINE_EVENT_WITH_TYPED_EVENT_HANDLER(TermControl, CopyToClipboard, _clipboardCopyHandlers, Control::TermControl, Control::CopyToClipboardEventArgs); - DEFINE_EVENT_WITH_TYPED_EVENT_HANDLER(TermControl, OpenHyperlink, _openHyperlinkHandlers, Control::TermControl, Control::OpenHyperlinkEventArgs); - DEFINE_EVENT_WITH_TYPED_EVENT_HANDLER(TermControl, SetTaskbarProgress, _setTaskbarProgressHandlers, Control::TermControl, IInspectable); - DEFINE_EVENT_WITH_TYPED_EVENT_HANDLER(TermControl, RaiseNotice, _raiseNoticeHandlers, Control::TermControl, Control::NoticeEventArgs); - // clang-format on } diff --git a/src/cascadia/TerminalControl/TermControl.h b/src/cascadia/TerminalControl/TermControl.h index 2b00f444250..3e018171bae 100644 --- a/src/cascadia/TerminalControl/TermControl.h +++ b/src/cascadia/TerminalControl/TermControl.h @@ -4,12 +4,7 @@ #pragma once #include "TermControl.g.h" -#include "CopyToClipboardEventArgs.g.h" -#include "PasteFromClipboardEventArgs.g.h" -#include "OpenHyperlinkEventArgs.g.h" -#include "NoticeEventArgs.g.h" -#include -#include +#include "EventArgs.h" #include "../../renderer/base/Renderer.hpp" #include "../../renderer/dx/DxRenderer.hpp" #include "../../renderer/uia/UiaRenderer.hpp" @@ -26,79 +21,6 @@ namespace Microsoft::Console::VirtualTerminal namespace winrt::Microsoft::Terminal::Control::implementation { - struct CopyToClipboardEventArgs : - public CopyToClipboardEventArgsT - { - public: - CopyToClipboardEventArgs(hstring text) : - _text(text), - _html(), - _rtf(), - _formats(static_cast(0)) {} - - CopyToClipboardEventArgs(hstring text, hstring html, hstring rtf, Windows::Foundation::IReference formats) : - _text(text), - _html(html), - _rtf(rtf), - _formats(formats) {} - - hstring Text() { return _text; }; - hstring Html() { return _html; }; - hstring Rtf() { return _rtf; }; - Windows::Foundation::IReference Formats() { return _formats; }; - - private: - hstring _text; - hstring _html; - hstring _rtf; - Windows::Foundation::IReference _formats; - }; - - struct PasteFromClipboardEventArgs : - public PasteFromClipboardEventArgsT - { - public: - PasteFromClipboardEventArgs(std::function clipboardDataHandler) : - m_clipboardDataHandler(clipboardDataHandler) {} - - void HandleClipboardData(hstring value) - { - m_clipboardDataHandler(static_cast(value)); - }; - - private: - std::function m_clipboardDataHandler; - }; - - struct OpenHyperlinkEventArgs : - public OpenHyperlinkEventArgsT - { - public: - OpenHyperlinkEventArgs(hstring uri) : - _uri(uri) {} - - hstring Uri() { return _uri; }; - - private: - hstring _uri; - }; - - struct NoticeEventArgs : - public NoticeEventArgsT - { - public: - NoticeEventArgs(const NoticeLevel level, const hstring& message) : - _level(level), - _message(message) {} - - NoticeLevel Level() { return _level; }; - hstring Message() { return _message; }; - - private: - const NoticeLevel _level; - const hstring _message; - }; - struct TermControl : TermControlT { TermControl(IControlSettings settings, TerminalConnection::ITerminalConnection connection); @@ -172,18 +94,18 @@ namespace winrt::Microsoft::Terminal::Control::implementation // clang-format off // -------------------------------- WinRT Events --------------------------------- - DECLARE_EVENT(TitleChanged, _titleChangedHandlers, Control::TitleChangedEventArgs); DECLARE_EVENT(FontSizeChanged, _fontSizeChangedHandlers, Control::FontSizeChangedEventArgs); DECLARE_EVENT(ScrollPositionChanged, _scrollPositionChangedHandlers, Control::ScrollPositionChangedEventArgs); - DECLARE_EVENT_WITH_TYPED_EVENT_HANDLER(PasteFromClipboard, _clipboardPasteHandlers, Control::TermControl, Control::PasteFromClipboardEventArgs); - DECLARE_EVENT_WITH_TYPED_EVENT_HANDLER(CopyToClipboard, _clipboardCopyHandlers, Control::TermControl, Control::CopyToClipboardEventArgs); - DECLARE_EVENT_WITH_TYPED_EVENT_HANDLER(OpenHyperlink, _openHyperlinkHandlers, Control::TermControl, Control::OpenHyperlinkEventArgs); - DECLARE_EVENT_WITH_TYPED_EVENT_HANDLER(SetTaskbarProgress, _setTaskbarProgressHandlers, Control::TermControl, IInspectable); - DECLARE_EVENT_WITH_TYPED_EVENT_HANDLER(RaiseNotice, _raiseNoticeHandlers, Control::TermControl, Control::NoticeEventArgs); + TYPED_EVENT(TitleChanged, IInspectable, Control::TitleChangedEventArgs); + TYPED_EVENT(PasteFromClipboard, IInspectable, Control::PasteFromClipboardEventArgs); + TYPED_EVENT(CopyToClipboard, IInspectable, Control::CopyToClipboardEventArgs); + TYPED_EVENT(OpenHyperlink, IInspectable, Control::OpenHyperlinkEventArgs); + TYPED_EVENT(SetTaskbarProgress, IInspectable, IInspectable); + TYPED_EVENT(RaiseNotice, IInspectable, Control::NoticeEventArgs); TYPED_EVENT(WarningBell, IInspectable, IInspectable); - TYPED_EVENT(ConnectionStateChanged, Control::TermControl, IInspectable); + TYPED_EVENT(ConnectionStateChanged, IInspectable, IInspectable); TYPED_EVENT(Initialized, Control::TermControl, Windows::UI::Xaml::RoutedEventArgs); TYPED_EVENT(TabColorChanged, IInspectable, IInspectable); TYPED_EVENT(HidePointerCursor, IInspectable, IInspectable); diff --git a/src/cascadia/TerminalControl/TermControl.idl b/src/cascadia/TerminalControl/TermControl.idl index cfaa2d0642b..99597123cd8 100644 --- a/src/cascadia/TerminalControl/TermControl.idl +++ b/src/cascadia/TerminalControl/TermControl.idl @@ -3,61 +3,11 @@ import "IMouseWheelListener.idl"; import "IControlSettings.idl"; +import "IDirectKeyListener.idl"; +import "EventArgs.idl"; namespace Microsoft.Terminal.Control { - delegate void TitleChangedEventArgs(String newTitle); - delegate void FontSizeChangedEventArgs(Int32 width, Int32 height, Boolean isInitialChange); - delegate void ScrollPositionChangedEventArgs(Int32 viewTop, Int32 viewHeight, Int32 bufferLength); - - // C++/winrt makes it difficult to share this idl between two projects, - // Instead, we just pin the uuid and include it in both TermControl and App - // If you update this one, please update TerminalApp\IDirectKeyListener.idl. - // If you change this interface, please update the guid. - // If you press F7 or Alt and get a runtime error, go make sure both copies are the same. - [uuid("0ddf4edc-3fda-4dee-97ca-a417ee3dd510")] interface IDirectKeyListener { - Boolean OnDirectKeyEvent(UInt32 vkey, UInt8 scanCode, Boolean down); - }; - - [flags] - enum CopyFormat - { - HTML = 0x1, - RTF = 0x2, - All = 0xffffffff - }; - - runtimeclass CopyToClipboardEventArgs - { - String Text { get; }; - String Html { get; }; - String Rtf { get; }; - Windows.Foundation.IReference Formats { get; }; - } - - runtimeclass PasteFromClipboardEventArgs - { - void HandleClipboardData(String data); - } - - runtimeclass OpenHyperlinkEventArgs - { - String Uri { get; }; - } - - enum NoticeLevel - { - Debug = 10, - Info = 20, - Warning = 30, - Error = 40, - }; - - runtimeclass NoticeEventArgs - { - NoticeLevel Level { get; }; - String Message { get; }; - } [default_interface] runtimeclass TermControl : Windows.UI.Xaml.Controls.UserControl, IDirectKeyListener, IMouseWheelListener { @@ -69,21 +19,27 @@ namespace Microsoft.Terminal.Control Microsoft.Terminal.Control.IControlSettings Settings { get; }; - event TitleChangedEventArgs TitleChanged; + event Windows.Foundation.TypedEventHandler TitleChanged; event FontSizeChangedEventArgs FontSizeChanged; - event Windows.Foundation.TypedEventHandler CopyToClipboard; - event Windows.Foundation.TypedEventHandler PasteFromClipboard; - event Windows.Foundation.TypedEventHandler OpenHyperlink; - event Windows.Foundation.TypedEventHandler SetTaskbarProgress; - event Windows.Foundation.TypedEventHandler RaiseNotice; + event Windows.Foundation.TypedEventHandler CopyToClipboard; + event Windows.Foundation.TypedEventHandler PasteFromClipboard; + event Windows.Foundation.TypedEventHandler OpenHyperlink; + event Windows.Foundation.TypedEventHandler SetTaskbarProgress; + event Windows.Foundation.TypedEventHandler RaiseNotice; event Windows.Foundation.TypedEventHandler WarningBell; event Windows.Foundation.TypedEventHandler HidePointerCursor; event Windows.Foundation.TypedEventHandler RestorePointerCursor; + event ScrollPositionChangedEventArgs ScrollPositionChanged; + event Windows.Foundation.TypedEventHandler TabColorChanged; + event Windows.Foundation.TypedEventHandler ReadOnlyChanged; + event Windows.Foundation.TypedEventHandler FocusFollowMouseRequested; + event Windows.Foundation.TypedEventHandler Initialized; // This is an event handler forwarder for the underlying connection. // We expose this and ConnectionState here so that it might eventually be data bound. - event Windows.Foundation.TypedEventHandler ConnectionStateChanged; + event Windows.Foundation.TypedEventHandler ConnectionStateChanged; + Microsoft.Terminal.TerminalConnection.ConnectionState ConnectionState { get; }; String Title { get; }; @@ -98,7 +54,6 @@ namespace Microsoft.Terminal.Control void ScrollViewport(Int32 viewTop); Int32 GetScrollOffset(); Int32 GetViewHeight(); - event ScrollPositionChangedEventArgs ScrollPositionChanged; void CreateSearchBoxControl(); @@ -117,11 +72,8 @@ namespace Microsoft.Terminal.Control String WorkingDirectory { get; }; Windows.Foundation.IReference TabColor { get; }; - event Windows.Foundation.TypedEventHandler TabColorChanged; Boolean ReadOnly { get; }; void ToggleReadOnly(); - event Windows.Foundation.TypedEventHandler ReadOnlyChanged; - event Windows.Foundation.TypedEventHandler FocusFollowMouseRequested; } } diff --git a/src/cascadia/TerminalControl/TerminalControlLib.vcxproj b/src/cascadia/TerminalControl/TerminalControlLib.vcxproj index a665378e52e..b16ab47321a 100644 --- a/src/cascadia/TerminalControl/TerminalControlLib.vcxproj +++ b/src/cascadia/TerminalControl/TerminalControlLib.vcxproj @@ -28,6 +28,9 @@ + + EventArgs.idl + KeyChord.idl @@ -51,6 +54,9 @@ Create + + EventArgs.idl + KeyChord.idl @@ -73,7 +79,9 @@ + + diff --git a/src/cascadia/TerminalControl/pch.h b/src/cascadia/TerminalControl/pch.h index a2a91ddf70f..83df9fdd5b5 100644 --- a/src/cascadia/TerminalControl/pch.h +++ b/src/cascadia/TerminalControl/pch.h @@ -48,6 +48,9 @@ #include #include +#include +#include + #include #include From 2f532bd410cf1ee9dfdd8f24561f71ecde0028b4 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Wed, 17 Mar 2021 15:28:26 -0500 Subject: [PATCH 14/82] Hey, lets clean this up while we're at it --- src/cascadia/TerminalApp/TerminalPage.cpp | 32 +++++++--------------- src/cascadia/TerminalApp/TerminalPage.h | 25 +++++++---------- src/cascadia/TerminalControl/TermControl.h | 4 +-- 3 files changed, 21 insertions(+), 40 deletions(-) diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp index 857fcc78aa6..6d4f0671a94 100644 --- a/src/cascadia/TerminalApp/TerminalPage.cpp +++ b/src/cascadia/TerminalApp/TerminalPage.cpp @@ -188,7 +188,7 @@ namespace winrt::TerminalApp::implementation } // Inform the host that our titlebar content has changed. - _setTitleBarContentHandlers(*this, _tabRow); + _SetTitleBarContentHandlers(*this, _tabRow); } // Hookup our event handlers to the ShortcutActionDispatch @@ -872,7 +872,7 @@ namespace winrt::TerminalApp::implementation if (page && tab) { - page->_raiseVisualBellHandlers(nullptr, nullptr); + page->_RaiseVisualBellHandlers(nullptr, nullptr); } }); @@ -1211,7 +1211,7 @@ namespace winrt::TerminalApp::implementation if (_settings.GlobalSettings().ShowTitleInTitlebar() && tab == _GetFocusedTab()) { - _titleChangeHandlers(*this, newTabTitle); + _TitleChangedHandlers(*this, newTabTitle); } } @@ -1377,7 +1377,7 @@ namespace winrt::TerminalApp::implementation // To close the window here, we need to close the hosting window. if (_tabs.Size() == 0) { - _lastTabClosedHandlers(*this, nullptr); + _LastTabClosedHandlers(*this, nullptr); } else if (focusedTabIndex.has_value() && focusedTabIndex.value() == gsl::narrow_cast(tabIndex)) { @@ -2352,7 +2352,7 @@ namespace winrt::TerminalApp::implementation // - eventArgs: the arguments specifying how to set the progress indicator void TerminalPage::_SetTaskbarProgressHandler(const IInspectable /*sender*/, const IInspectable /*eventArgs*/) { - _setTaskbarProgressHandlers(*this, nullptr); + _SetTaskbarProgressHandlers(*this, nullptr); } // Method Description: @@ -2490,7 +2490,7 @@ namespace winrt::TerminalApp::implementation // Raise an event that our title changed if (_settings.GlobalSettings().ShowTitleInTitlebar()) { - _titleChangeHandlers(*this, tab.Title()); + _TitleChangedHandlers(*this, tab.Title()); } } CATCH_LOG(); @@ -2628,7 +2628,7 @@ namespace winrt::TerminalApp::implementation // will let the user hot-reload this setting, but any runtime changes to // the alwaysOnTop setting will be lost. _isAlwaysOnTop = _settings.GlobalSettings().AlwaysOnTop(); - _alwaysOnTopChangedHandlers(*this, nullptr); + _AlwaysOnTopChangedHandlers(*this, nullptr); // Settings AllowDependentAnimations will affect whether animations are // enabled application-wide, so we don't need to check it each time we @@ -2807,7 +2807,7 @@ namespace winrt::TerminalApp::implementation { _isInFocusMode = !_isInFocusMode; _UpdateTabView(); - _focusModeChangedHandlers(*this, nullptr); + _FocusModeChangedHandlers(*this, nullptr); } // Method Description: @@ -2821,7 +2821,7 @@ namespace winrt::TerminalApp::implementation { _isFullscreen = !_isFullscreen; _UpdateTabView(); - _fullscreenChangedHandlers(*this, nullptr); + _FullscreenChangedHandlers(*this, nullptr); } // Method Description: @@ -2833,7 +2833,7 @@ namespace winrt::TerminalApp::implementation void TerminalPage::ToggleAlwaysOnTop() { _isAlwaysOnTop = !_isAlwaysOnTop; - _alwaysOnTopChangedHandlers(*this, nullptr); + _AlwaysOnTopChangedHandlers(*this, nullptr); } // Method Description: @@ -3340,16 +3340,4 @@ namespace winrt::TerminalApp::implementation } } } - - // -------------------------------- WinRT Events --------------------------------- - // Winrt events need a method for adding a callback to the event and removing the callback. - // These macros will define them both for you. - DEFINE_EVENT_WITH_TYPED_EVENT_HANDLER(TerminalPage, TitleChanged, _titleChangeHandlers, winrt::Windows::Foundation::IInspectable, winrt::hstring); - DEFINE_EVENT_WITH_TYPED_EVENT_HANDLER(TerminalPage, LastTabClosed, _lastTabClosedHandlers, winrt::Windows::Foundation::IInspectable, winrt::TerminalApp::LastTabClosedEventArgs); - DEFINE_EVENT_WITH_TYPED_EVENT_HANDLER(TerminalPage, SetTitleBarContent, _setTitleBarContentHandlers, winrt::Windows::Foundation::IInspectable, UIElement); - DEFINE_EVENT_WITH_TYPED_EVENT_HANDLER(TerminalPage, FocusModeChanged, _focusModeChangedHandlers, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable); - DEFINE_EVENT_WITH_TYPED_EVENT_HANDLER(TerminalPage, FullscreenChanged, _fullscreenChangedHandlers, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable); - DEFINE_EVENT_WITH_TYPED_EVENT_HANDLER(TerminalPage, AlwaysOnTopChanged, _alwaysOnTopChangedHandlers, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable); - DEFINE_EVENT_WITH_TYPED_EVENT_HANDLER(TerminalPage, RaiseVisualBell, _raiseVisualBellHandlers, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable); - DEFINE_EVENT_WITH_TYPED_EVENT_HANDLER(TerminalPage, SetTaskbarProgress, _setTaskbarProgressHandlers, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable); } diff --git a/src/cascadia/TerminalApp/TerminalPage.h b/src/cascadia/TerminalApp/TerminalPage.h index 09485baa95b..d2afb1491c4 100644 --- a/src/cascadia/TerminalApp/TerminalPage.h +++ b/src/cascadia/TerminalApp/TerminalPage.h @@ -6,9 +6,6 @@ #include "TerminalPage.g.h" #include "TerminalTab.h" #include "AppKeyBindings.h" - -#include - #include "AppCommandlineArgs.h" static constexpr uint32_t DefaultRowsToScroll{ 3 }; @@ -85,15 +82,15 @@ namespace winrt::TerminalApp::implementation const winrt::hstring cwd = L""); // -------------------------------- WinRT Events --------------------------------- - DECLARE_EVENT_WITH_TYPED_EVENT_HANDLER(TitleChanged, _titleChangeHandlers, winrt::Windows::Foundation::IInspectable, winrt::hstring); - DECLARE_EVENT_WITH_TYPED_EVENT_HANDLER(LastTabClosed, _lastTabClosedHandlers, winrt::Windows::Foundation::IInspectable, winrt::TerminalApp::LastTabClosedEventArgs); - DECLARE_EVENT_WITH_TYPED_EVENT_HANDLER(SetTitleBarContent, _setTitleBarContentHandlers, winrt::Windows::Foundation::IInspectable, winrt::Windows::UI::Xaml::UIElement); - DECLARE_EVENT_WITH_TYPED_EVENT_HANDLER(FocusModeChanged, _focusModeChangedHandlers, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable); - DECLARE_EVENT_WITH_TYPED_EVENT_HANDLER(FullscreenChanged, _fullscreenChangedHandlers, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable); - DECLARE_EVENT_WITH_TYPED_EVENT_HANDLER(AlwaysOnTopChanged, _alwaysOnTopChangedHandlers, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable); - DECLARE_EVENT_WITH_TYPED_EVENT_HANDLER(RaiseVisualBell, _raiseVisualBellHandlers, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable); - DECLARE_EVENT_WITH_TYPED_EVENT_HANDLER(SetTaskbarProgress, _setTaskbarProgressHandlers, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable); - TYPED_EVENT(Initialized, winrt::Windows::Foundation::IInspectable, winrt::Windows::UI::Xaml::RoutedEventArgs); + TYPED_EVENT(TitleChanged, IInspectable, winrt::hstring); + TYPED_EVENT(LastTabClosed, IInspectable, winrt::TerminalApp::LastTabClosedEventArgs); + TYPED_EVENT(SetTitleBarContent, IInspectable, winrt::Windows::UI::Xaml::UIElement); + TYPED_EVENT(FocusModeChanged, IInspectable, IInspectable); + TYPED_EVENT(FullscreenChanged, IInspectable, IInspectable); + TYPED_EVENT(AlwaysOnTopChanged, IInspectable, IInspectable); + TYPED_EVENT(RaiseVisualBell, IInspectable, IInspectable); + TYPED_EVENT(SetTaskbarProgress, IInspectable, IInspectable); + TYPED_EVENT(Initialized, IInspectable, winrt::Windows::UI::Xaml::RoutedEventArgs); private: friend struct TerminalPageT; // for Xaml to bind events @@ -336,7 +333,5 @@ namespace winrt::TerminalApp::implementation namespace winrt::TerminalApp::factory_implementation { - struct TerminalPage : TerminalPageT - { - }; + BASIC_FACTORY(TerminalPage); } diff --git a/src/cascadia/TerminalControl/TermControl.h b/src/cascadia/TerminalControl/TermControl.h index 3e018171bae..f4391f1f01d 100644 --- a/src/cascadia/TerminalControl/TermControl.h +++ b/src/cascadia/TerminalControl/TermControl.h @@ -280,7 +280,5 @@ namespace winrt::Microsoft::Terminal::Control::implementation namespace winrt::Microsoft::Terminal::Control::factory_implementation { - struct TermControl : TermControlT - { - }; + BASIC_FACTORY(TermControl); } From c035e6987474d90cbfc2e1665d4ae3140540e054 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Thu, 18 Mar 2021 14:28:41 -0500 Subject: [PATCH 15/82] Reorganize these files to be a little less painful to read --- src/cascadia/TerminalControl/ControlCore.cpp | 18 +- src/cascadia/TerminalControl/ControlCore.h | 227 +++++++++---------- src/cascadia/TerminalControl/TermControl.cpp | 2 +- src/cascadia/TerminalControl/TermControl.h | 35 --- 4 files changed, 124 insertions(+), 158 deletions(-) diff --git a/src/cascadia/TerminalControl/ControlCore.cpp b/src/cascadia/TerminalControl/ControlCore.cpp index 2728a08bcc4..9c9c7ff33cb 100644 --- a/src/cascadia/TerminalControl/ControlCore.cpp +++ b/src/cascadia/TerminalControl/ControlCore.cpp @@ -1177,11 +1177,11 @@ namespace winrt::Microsoft::Terminal::Control::implementation return _terminal->GetCursorPosition(); } - // This one's really pushing the boundary of "encapsulation". It really - // belongs in the "Interactivity" layer, which doesn't yet exist. There's so - // many accesses to the selection in the Core though, that I just put this - // here. The Control shouldn't be futzing that much with the selection - // itself. + // This one's really pushing the boundary of what counts as "encapsulation". + // It really belongs in the "Interactivity" layer, which doesn't yet exist. + // There's so many accesses to the selection in the Core though, that I just + // put this here. The Control shouldn't be futzing that much with the + // selection itself. void ControlCore::LeftClickOnTerminal(const til::point terminalPosition, const int numberOfClicks, const bool altEnabled, @@ -1241,4 +1241,12 @@ namespace winrt::Microsoft::Terminal::Control::implementation _renderer->TriggerSelection(); } + void ControlCore::AttachUiaEngine(::Microsoft::Console::Render::IRenderEngine* const pEngine) + { + if (_renderer) + { + _renderer->AddRenderEngine(pEngine); + } + } + } diff --git a/src/cascadia/TerminalControl/ControlCore.h b/src/cascadia/TerminalControl/ControlCore.h index 1ee4074617f..497383625c5 100644 --- a/src/cascadia/TerminalControl/ControlCore.h +++ b/src/cascadia/TerminalControl/ControlCore.h @@ -19,76 +19,42 @@ namespace winrt::Microsoft::Terminal::Control::implementation struct ControlCore : ControlCoreT { public: - ControlCore(IControlSettings settings, TerminalConnection::ITerminalConnection connection); + ControlCore(IControlSettings settings, + TerminalConnection::ITerminalConnection connection); - //////////////////////////////////////////////////////////////////////// - // These members are taken from TermControl - - std::unique_ptr<::Microsoft::Console::Render::Renderer> _renderer{ nullptr }; - - private: - bool _initializedTerminal{ false }; - - TerminalConnection::ITerminalConnection _connection{ nullptr }; - event_token _connectionOutputEventToken; - TerminalConnection::ITerminalConnection::StateChanged_revoker _connectionStateChangedRevoker; - - std::unique_ptr<::Microsoft::Terminal::Core::Terminal> _terminal{ nullptr }; - - std::unique_ptr<::Microsoft::Console::Render::DxEngine> _renderEngine{ nullptr }; - - IControlSettings _settings{ nullptr }; // ? Might be able to get away with only retrieving pieces - - FontInfoDesired _desiredFont; - FontInfo _actualFont; - - // storage location for the leading surrogate of a utf-16 surrogate pair - std::optional _leadingSurrogate{ std::nullopt }; - - bool _isReadOnly{ false }; // ? - - std::optional _lastHoveredCell{ std::nullopt }; - // Track the last hyperlink ID we hovered over - uint16_t _lastHoveredId{ 0 }; - - std::optional::interval> _lastHoveredInterval{ std::nullopt }; - - //////////////////////////////////////////////////////////////////////// - // These members are new - double _panelWidth{ 0 }; - double _panelHeight{ 0 }; - double _compositionScaleX{ 0 }; - double _compositionScaleY{ 0 }; - til::color _backgroundColor; // This is _in_ Terminal already! - //////////////////////////////////////////////////////////////////////// - - public: - //////////////////////////////////////////////////////////////////////// - // These methods are taken from TermControl bool InitializeTerminal(const double actualWidth, const double actualHeight, const double compositionScaleX, const double compositionScaleY); - void _SetFontSize(int fontSize); - void _UpdateFont(const bool initialUpdate = false); + void UpdateSettings(const IControlSettings& settings); + void SizeChanged(const double width, const double height); + void ScaleChanged(const double scaleX, const double scaleY); + float RendererScale() const; + HANDLE GetSwapChainHandle() const; + void AdjustFontSize(int fontSizeDelta); void ResetFontSize(); - void _RefreshSizeUnderLock(); - void _DoResizeUnderLock(const double newWidth, - const double newHeight); + FontInfo GetFont() const; - void _SendInputToConnection(const winrt::hstring& wstr); - void _SendInputToConnection(std::wstring_view wstr); + til::color BackgroundColor() const; + void SetBackgroundOpacity(const float opacity); void SendInput(const winrt::hstring& wstr); + void PasteText(const winrt::hstring& hstr); + bool CopySelectionToClipboard(bool singleLine, const Windows::Foundation::IReference& formats); + void ToggleShaderEffects(); + void ResumeRendering(); + void UpdatePatternLocations(); void UpdateHoveredCell(const std::optional& terminalPosition); + winrt::hstring GetHyperlink(const til::point position) const; + winrt::hstring GetHoveredUriText() const; + std::optional GetHoveredCell() const; void SetSelectionAnchor(winrt::Windows::Foundation::Point const& position); void SetEndSelectionPoint(winrt::Windows::Foundation::Point const& position); - bool CopySelectionToClipboard(bool singleLine, const Windows::Foundation::IReference& formats); ::Microsoft::Console::Types::IUiaData* GetUiaData() const; @@ -109,63 +75,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation int BufferHeight() const; #pragma endregion -#pragma region TerminalCoreCallbacks - void _TerminalCopyToClipboard(const std::wstring_view& wstr); - void _TerminalWarningBell(); - void _TerminalTitleChanged(const std::wstring_view& wstr); - void _TerminalTabColorChanged(const std::optional color); - void _TerminalBackgroundColorChanged(const COLORREF color); - void _TerminalScrollPositionChanged(const int viewTop, - const int viewHeight, - const int bufferSize); - void _TerminalCursorPositionChanged(); - void _TerminalTaskbarProgressChanged(); -#pragma endregion - -#pragma region RendererCallbacks - void _RendererWarning(const HRESULT hr); - void RenderEngineSwapChainChanged(); -#pragma endregion - - TYPED_EVENT(CopyToClipboard, IInspectable, Control::CopyToClipboardEventArgs); - - TYPED_EVENT(TitleChanged, IInspectable, Control::TitleChangedEventArgs); - TYPED_EVENT(WarningBell, IInspectable, IInspectable); - TYPED_EVENT(TabColorChanged, IInspectable, IInspectable); - TYPED_EVENT(BackgroundColorChanged, IInspectable, IInspectable); - TYPED_EVENT(ScrollPositionChanged, IInspectable, Control::ScrollPositionChangedArgs); - TYPED_EVENT(CursorPositionChanged, IInspectable, IInspectable); - TYPED_EVENT(TaskbarProgressChanged, IInspectable, IInspectable); - TYPED_EVENT(ConnectionStateChanged, IInspectable, IInspectable); - - public: - //////////////////////////////////////////////////////////////////////// - // These methods are new - void UpdateSettings(const IControlSettings& settings); - - void SizeChanged(const double width, const double height); - void ScaleChanged(const double scaleX, const double scaleY); - float RendererScale() const; - - void _raiseHoveredHyperlinkChanged(); - winrt::hstring GetHyperlink(const til::point position) const; - winrt::hstring GetHoveredUriText() const; - std::optional GetHoveredCell() const; - - void PasteText(const winrt::hstring& hstr); - - FontInfo GetFont() const; - til::color BackgroundColor() const; - - bool HasSelection() const; - std::vector SelectedText(bool trimTrailingWhitespace) const; - - void Search(const winrt::hstring& text, - const bool goForward, - const bool caseSensitive); - - void SetBackgroundOpacity(const float opacity); - #pragma region ITerminalInputButNotReally bool TrySendKeyEvent(const WORD vkey, const WORD scanCode, @@ -183,17 +92,21 @@ namespace winrt::Microsoft::Terminal::Control::implementation void UserScrollViewport(const int viewTop); #pragma endregion - HANDLE GetSwapChainHandle() const; - void BlinkAttributeTick(); void BlinkCursor(); bool CursorOn() const; void CursorOn(const bool isCursorOn); - void ResumeRendering(); bool IsVtMouseModeEnabled() const; til::point CursorPosition() const; + bool HasSelection() const; + std::vector SelectedText(bool trimTrailingWhitespace) const; + + void Search(const winrt::hstring& text, + const bool goForward, + const bool caseSensitive); + void LeftClickOnTerminal(const til::point terminalPosition, const int numberOfClicks, const bool altEnabled, @@ -201,11 +114,91 @@ namespace winrt::Microsoft::Terminal::Control::implementation const bool isOnOriginalPosition, bool& selectionNeedsToBeCopied); - TYPED_EVENT(HoveredHyperlinkChanged, IInspectable, IInspectable); - + void AttachUiaEngine(::Microsoft::Console::Render::IRenderEngine* const pEngine); + + // -------------------------------- WinRT Events --------------------------------- + // clang-format off + TYPED_EVENT(CopyToClipboard, IInspectable, Control::CopyToClipboardEventArgs); + TYPED_EVENT(TitleChanged, IInspectable, Control::TitleChangedEventArgs); + TYPED_EVENT(WarningBell, IInspectable, IInspectable); + TYPED_EVENT(TabColorChanged, IInspectable, IInspectable); + TYPED_EVENT(BackgroundColorChanged, IInspectable, IInspectable); + TYPED_EVENT(ScrollPositionChanged, IInspectable, Control::ScrollPositionChangedArgs); + TYPED_EVENT(CursorPositionChanged, IInspectable, IInspectable); + TYPED_EVENT(TaskbarProgressChanged, IInspectable, IInspectable); + TYPED_EVENT(ConnectionStateChanged, IInspectable, IInspectable); + TYPED_EVENT(HoveredHyperlinkChanged, IInspectable, IInspectable); TYPED_EVENT(RendererEnteredErrorState, IInspectable, IInspectable); - TYPED_EVENT(SwapChainChanged, IInspectable, IInspectable); - TYPED_EVENT(RendererWarning, IInspectable, Control::RendererWarningArgs); + TYPED_EVENT(SwapChainChanged, IInspectable, IInspectable); + TYPED_EVENT(RendererWarning, IInspectable, Control::RendererWarningArgs); + // clang-format on + + private: + bool _initializedTerminal{ false }; + + TerminalConnection::ITerminalConnection _connection{ nullptr }; + event_token _connectionOutputEventToken; + TerminalConnection::ITerminalConnection::StateChanged_revoker _connectionStateChangedRevoker; + + std::unique_ptr<::Microsoft::Terminal::Core::Terminal> _terminal{ nullptr }; + + std::unique_ptr<::Microsoft::Console::Render::Renderer> _renderer{ nullptr }; + std::unique_ptr<::Microsoft::Console::Render::DxEngine> _renderEngine{ nullptr }; + + IControlSettings _settings{ nullptr }; // ? Might be able to get away with only retrieving pieces + + FontInfoDesired _desiredFont; + FontInfo _actualFont; + + // storage location for the leading surrogate of a utf-16 surrogate pair + std::optional _leadingSurrogate{ std::nullopt }; + + bool _isReadOnly{ false }; // ? + + std::optional _lastHoveredCell{ std::nullopt }; + // Track the last hyperlink ID we hovered over + uint16_t _lastHoveredId{ 0 }; + + std::optional::interval> _lastHoveredInterval{ std::nullopt }; + + double _panelWidth{ 0 }; + double _panelHeight{ 0 }; + double _compositionScaleX{ 0 }; + double _compositionScaleY{ 0 }; + til::color _backgroundColor; // This is _in_ Terminal already! + + void _SetFontSize(int fontSize); + void _UpdateFont(const bool initialUpdate = false); + void _RefreshSizeUnderLock(); + void _DoResizeUnderLock(const double newWidth, + const double newHeight); + + void _SendInputToConnection(const winrt::hstring& wstr); + void _SendInputToConnection(std::wstring_view wstr); + +#pragma region TerminalCoreCallbacks + void _TerminalCopyToClipboard(const std::wstring_view& wstr); + void _TerminalWarningBell(); + void _TerminalTitleChanged(const std::wstring_view& wstr); + void _TerminalTabColorChanged(const std::optional color); + void _TerminalBackgroundColorChanged(const COLORREF color); + void _TerminalScrollPositionChanged(const int viewTop, + const int viewHeight, + const int bufferSize); + void _TerminalCursorPositionChanged(); + void _TerminalTaskbarProgressChanged(); +#pragma endregion + +#pragma region RendererCallbacks + void _RendererWarning(const HRESULT hr); + void RenderEngineSwapChainChanged(); +#pragma endregion + + public: + //////////////////////////////////////////////////////////////////////// + // These methods are new + + void _raiseHoveredHyperlinkChanged(); }; } diff --git a/src/cascadia/TerminalControl/TermControl.cpp b/src/cascadia/TerminalControl/TermControl.cpp index 1277063ab8a..b3c4f156108 100644 --- a/src/cascadia/TerminalControl/TermControl.cpp +++ b/src/cascadia/TerminalControl/TermControl.cpp @@ -493,7 +493,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation auto autoPeer = winrt::make_self(this); _uiaEngine = std::make_unique<::Microsoft::Console::Render::UiaEngine>(autoPeer.get()); - _core->_renderer->AddRenderEngine(_uiaEngine.get()); + _core->AttachUiaEngine(_uiaEngine.get()); return *autoPeer; } return nullptr; diff --git a/src/cascadia/TerminalControl/TermControl.h b/src/cascadia/TerminalControl/TermControl.h index 67e60ae663a..8526146d835 100644 --- a/src/cascadia/TerminalControl/TermControl.h +++ b/src/cascadia/TerminalControl/TermControl.h @@ -119,29 +119,17 @@ namespace winrt::Microsoft::Terminal::Control::implementation winrt::com_ptr _core{ nullptr }; - // TerminalConnection::ITerminalConnection _connection; bool _initializedTerminal; winrt::com_ptr _searchBox; - // event_token _connectionOutputEventToken; - // TerminalConnection::ITerminalConnection::StateChanged_revoker _connectionStateChangedRevoker; - - // std::unique_ptr<::Microsoft::Terminal::Core::Terminal> _terminal; - - // std::unique_ptr<::Microsoft::Console::Render::Renderer> _renderer; - // std::unique_ptr<::Microsoft::Console::Render::DxEngine> _renderEngine; std::unique_ptr<::Microsoft::Console::Render::UiaEngine> _uiaEngine; IControlSettings _settings; bool _focused; std::atomic _closing; - // FontInfoDesired _desiredFont; - // FontInfo _actualFont; - std::shared_ptr> _tsfTryRedrawCanvas; - std::shared_ptr> _updatePatternLocations; struct ScrollBarUpdate @@ -162,9 +150,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation Windows::UI::Xaml::DispatcherTimer _autoScrollTimer; std::optional _lastAutoScrollUpdateTime; - // // storage location for the leading surrogate of a utf-16 surrogate pair - // std::optional _leadingSurrogate; - std::optional _cursorTimer; std::optional _blinkTimer; @@ -172,13 +157,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation // viewport via touch input. std::optional _touchAnchor; - // // Track the last cell we hovered over (used in pointerMovedHandler) - // std::optional _lastHoveredCell; - // // Track the last hyperlink ID we hovered over - // uint16_t _lastHoveredId; - - // std::optional::interval> _lastHoveredInterval; - using Timestamp = uint64_t; // imported from WinUser @@ -206,7 +184,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation void _BackgroundColorChangedHandler(const IInspectable& sender, const IInspectable& args); winrt::fire_and_forget _changeBackgroundColor(til::color bg); bool _InitializeTerminal(); - // void _UpdateFont(const bool initialUpdate = false); void _SetFontSize(int fontSize); void _TappedHandler(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::Input::TappedRoutedEventArgs const& e); void _KeyDownHandler(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::Input::KeyRoutedEventArgs const& e); @@ -227,16 +204,9 @@ namespace winrt::Microsoft::Terminal::Control::implementation void _CursorTimerTick(Windows::Foundation::IInspectable const& sender, Windows::Foundation::IInspectable const& e); void _BlinkTimerTick(Windows::Foundation::IInspectable const& sender, Windows::Foundation::IInspectable const& e); void _SetEndSelectionPointAtCursor(Windows::Foundation::Point const& cursorPosition); - // void _SendInputToConnection(const winrt::hstring& wstr); - // void _SendInputToConnection(std::wstring_view wstr); void _SendPastedTextToConnection(const std::wstring& wstr); void _SwapChainSizeChanged(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::SizeChangedEventArgs const& e); void _SwapChainScaleChanged(Windows::UI::Xaml::Controls::SwapChainPanel const& sender, Windows::Foundation::IInspectable const& args); - // void _DoResizeUnderLock(const double newWidth, const double newHeight); - // void _RefreshSizeUnderLock(); - // void _CopyToClipboard(const std::wstring_view& wstr); - // void _TerminalWarningBell(); - // void _TerminalTitleChanged(const std::wstring_view& wstr); void _TerminalTabColorChanged(const std::optional color); void _ScrollPositionChanged(const IInspectable& sender, const Control::ScrollPositionChangedArgs& args); void _CursorPositionChanged(const IInspectable& sender, const IInspectable& args); @@ -274,13 +244,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation void _CompositionCompleted(winrt::hstring text); void _CurrentCursorPositionHandler(const IInspectable& sender, const CursorPositionEventArgs& eventArgs); void _FontInfoHandler(const IInspectable& sender, const FontInfoEventArgs& eventArgs); - // winrt::fire_and_forget _AsyncCloseConnection(); winrt::fire_and_forget _RaiseReadOnlyWarning(); - - // void _UpdateHoveredCell(const std::optional& terminalPosition); - - //////////////////////////////////////////////////////////////////////// winrt::fire_and_forget _hoveredHyperlinkChanged(const IInspectable& sender, const IInspectable& args); }; } From 801b29635ca0eea5758912070a05321e6515017b Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Thu, 18 Mar 2021 14:34:53 -0500 Subject: [PATCH 16/82] Move isReadOnly to the core as well, through that really belongs in interactivity --- src/cascadia/TerminalControl/ControlCore.cpp | 9 +++++++++ src/cascadia/TerminalControl/ControlCore.h | 5 ++++- src/cascadia/TerminalControl/TermControl.cpp | 16 ++++++++-------- src/cascadia/TerminalControl/TermControl.h | 2 -- 4 files changed, 21 insertions(+), 11 deletions(-) diff --git a/src/cascadia/TerminalControl/ControlCore.cpp b/src/cascadia/TerminalControl/ControlCore.cpp index 9c9c7ff33cb..4067fa9adca 100644 --- a/src/cascadia/TerminalControl/ControlCore.cpp +++ b/src/cascadia/TerminalControl/ControlCore.cpp @@ -1249,4 +1249,13 @@ namespace winrt::Microsoft::Terminal::Control::implementation } } + bool ControlCore::IsInReadOnlyMode() const + { + return _isReadOnly; + } + void ControlCore::ToggleReadOnlyMode() + { + _isReadOnly = !_isReadOnly; + } + } diff --git a/src/cascadia/TerminalControl/ControlCore.h b/src/cascadia/TerminalControl/ControlCore.h index 497383625c5..0264a695a5e 100644 --- a/src/cascadia/TerminalControl/ControlCore.h +++ b/src/cascadia/TerminalControl/ControlCore.h @@ -116,6 +116,9 @@ namespace winrt::Microsoft::Terminal::Control::implementation void AttachUiaEngine(::Microsoft::Console::Render::IRenderEngine* const pEngine); + bool IsInReadOnlyMode() const; + void ToggleReadOnlyMode(); + // -------------------------------- WinRT Events --------------------------------- // clang-format off TYPED_EVENT(CopyToClipboard, IInspectable, Control::CopyToClipboardEventArgs); @@ -153,7 +156,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation // storage location for the leading surrogate of a utf-16 surrogate pair std::optional _leadingSurrogate{ std::nullopt }; - bool _isReadOnly{ false }; // ? + bool _isReadOnly{ false }; // Probably belongs in Interactivity std::optional _lastHoveredCell{ std::nullopt }; // Track the last hyperlink ID we hovered over diff --git a/src/cascadia/TerminalControl/TermControl.cpp b/src/cascadia/TerminalControl/TermControl.cpp index b3c4f156108..1a67eddb1c6 100644 --- a/src/cascadia/TerminalControl/TermControl.cpp +++ b/src/cascadia/TerminalControl/TermControl.cpp @@ -726,7 +726,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation bool TermControl::OnDirectKeyEvent(const uint32_t vkey, const uint8_t scanCode, const bool down) { // Short-circuit isReadOnly check to avoid warning dialog - if (_isReadOnly) + if (_core->IsInReadOnlyMode()) { return false; } @@ -812,7 +812,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation const auto scanCode = gsl::narrow_cast(e.KeyStatus().ScanCode); // Short-circuit isReadOnly check to avoid warning dialog - if (_isReadOnly) + if (_core->IsInReadOnlyMode()) { e.Handled(!keyDown || _TryHandleKeyBinding(vkey, scanCode, modifiers)); return; @@ -1185,7 +1185,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation if (ptr.PointerDeviceType() == Windows::Devices::Input::PointerDeviceType::Mouse || ptr.PointerDeviceType() == Windows::Devices::Input::PointerDeviceType::Pen) { // Short-circuit isReadOnly check to avoid warning dialog - if (_focused && !_isReadOnly && _CanSendVTMouseInput()) + if (_focused && !_core->IsInReadOnlyMode() && _CanSendVTMouseInput()) { _TrySendMouseEvent(point); } @@ -1292,7 +1292,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation if (ptr.PointerDeviceType() == Windows::Devices::Input::PointerDeviceType::Mouse || ptr.PointerDeviceType() == Windows::Devices::Input::PointerDeviceType::Pen) { // Short-circuit isReadOnly check to avoid warning dialog - if (!_isReadOnly && _CanSendVTMouseInput()) + if (!_core->IsInReadOnlyMode() && _CanSendVTMouseInput()) { _TrySendMouseEvent(point); args.Handled(true); @@ -1369,7 +1369,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation const TerminalInput::MouseButtonState state) { // Short-circuit isReadOnly check to avoid warning dialog - if (!_isReadOnly && _CanSendVTMouseInput()) + if (!_core->IsInReadOnlyMode() && _CanSendVTMouseInput()) { // Most mouse event handlers call // _TrySendMouseEvent(point); @@ -2654,15 +2654,15 @@ namespace winrt::Microsoft::Terminal::Control::implementation // - True if the mode is read-only bool TermControl::ReadOnly() const noexcept { - return _isReadOnly; + return _core->IsInReadOnlyMode(); } // Method Description: // - Toggles the read-only flag, raises event describing the value change void TermControl::ToggleReadOnly() { - _isReadOnly = !_isReadOnly; - _ReadOnlyChangedHandlers(*this, winrt::box_value(_isReadOnly)); + _core->ToggleReadOnlyMode(); + _ReadOnlyChangedHandlers(*this, winrt::box_value(_core->IsInReadOnlyMode())); } winrt::fire_and_forget TermControl::_RaiseReadOnlyWarning() diff --git a/src/cascadia/TerminalControl/TermControl.h b/src/cascadia/TerminalControl/TermControl.h index 8526146d835..d4a167bbf09 100644 --- a/src/cascadia/TerminalControl/TermControl.h +++ b/src/cascadia/TerminalControl/TermControl.h @@ -175,8 +175,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation winrt::Windows::UI::Xaml::Controls::SwapChainPanel::LayoutUpdated_revoker _layoutUpdatedRevoker; - bool _isReadOnly{ false }; // ? - void _ApplyUISettings(const IControlSettings&); void _UpdateSettingsOnUIThread(); void _UpdateSystemParameterSettings() noexcept; From 6ab833920a789a454ab99416c4babafc368ef6e5 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Thu, 18 Mar 2021 16:27:38 -0500 Subject: [PATCH 17/82] Ooh, do the font size event too --- src/cascadia/TerminalApp/TerminalPage.cpp | 46 ++++++++++++-------- src/cascadia/TerminalApp/TerminalPage.h | 2 +- src/cascadia/TerminalControl/ControlCore.cpp | 39 +++++------------ src/cascadia/TerminalControl/ControlCore.h | 3 ++ src/cascadia/TerminalControl/TermControl.cpp | 32 ++++---------- src/cascadia/TerminalControl/TermControl.h | 6 ++- 6 files changed, 56 insertions(+), 72 deletions(-) diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp index c1649cd4d47..8089baa982b 100644 --- a/src/cascadia/TerminalApp/TerminalPage.cpp +++ b/src/cascadia/TerminalApp/TerminalPage.cpp @@ -2290,29 +2290,37 @@ namespace winrt::TerminalApp::implementation return false; } - void TerminalPage::_ControlNoticeRaisedHandler(const IInspectable /*sender*/, const Microsoft::Terminal::Control::NoticeEventArgs eventArgs) + // Important! Don't take this eventArgs by reference, we need to extend the + // lifetime of it to the other side of the co_await! + winrt::fire_and_forget TerminalPage::_ControlNoticeRaisedHandler(const IInspectable /*sender*/, + const Microsoft::Terminal::Control::NoticeEventArgs eventArgs) { - winrt::hstring message = eventArgs.Message(); + auto weakThis = get_weak(); + co_await winrt::resume_foreground(Dispatcher()); + if (auto page = weakThis.get()) + { + winrt::hstring message = eventArgs.Message(); - winrt::hstring title; + winrt::hstring title; - switch (eventArgs.Level()) - { - case NoticeLevel::Debug: - title = RS_(L"NoticeDebug"); //\xebe8 - break; - case NoticeLevel::Info: - title = RS_(L"NoticeInfo"); // \xe946 - break; - case NoticeLevel::Warning: - title = RS_(L"NoticeWarning"); //\xe7ba - break; - case NoticeLevel::Error: - title = RS_(L"NoticeError"); //\xe783 - break; - } + switch (eventArgs.Level()) + { + case NoticeLevel::Debug: + title = RS_(L"NoticeDebug"); //\xebe8 + break; + case NoticeLevel::Info: + title = RS_(L"NoticeInfo"); // \xe946 + break; + case NoticeLevel::Warning: + title = RS_(L"NoticeWarning"); //\xe7ba + break; + case NoticeLevel::Error: + title = RS_(L"NoticeError"); //\xe783 + break; + } - _ShowControlNoticeDialog(title, message); + page->_ShowControlNoticeDialog(title, message); + } } void TerminalPage::_ShowControlNoticeDialog(const winrt::hstring& title, const winrt::hstring& message) diff --git a/src/cascadia/TerminalApp/TerminalPage.h b/src/cascadia/TerminalApp/TerminalPage.h index ac43518acb2..6c090d9adf8 100644 --- a/src/cascadia/TerminalApp/TerminalPage.h +++ b/src/cascadia/TerminalApp/TerminalPage.h @@ -225,7 +225,7 @@ namespace winrt::TerminalApp::implementation void _PasteText(); - void _ControlNoticeRaisedHandler(const IInspectable sender, const Microsoft::Terminal::Control::NoticeEventArgs eventArgs); + winrt::fire_and_forget _ControlNoticeRaisedHandler(const IInspectable sender, const Microsoft::Terminal::Control::NoticeEventArgs eventArgs); void _ShowControlNoticeDialog(const winrt::hstring& title, const winrt::hstring& message); fire_and_forget _LaunchSettings(const Microsoft::Terminal::Settings::Model::SettingsTarget target); diff --git a/src/cascadia/TerminalControl/ControlCore.cpp b/src/cascadia/TerminalControl/ControlCore.cpp index 4067fa9adca..23d50ad2001 100644 --- a/src/cascadia/TerminalControl/ControlCore.cpp +++ b/src/cascadia/TerminalControl/ControlCore.cpp @@ -524,44 +524,29 @@ namespace winrt::Microsoft::Terminal::Control::implementation // Arguments: // - initialUpdate: whether this font update should be considered as being // concerned with initialization process. Value forwarded to event handler. - void ControlCore::_UpdateFont(const bool /*initialUpdate*/) + void ControlCore::_UpdateFont(const bool initialUpdate) { const int newDpi = static_cast(static_cast(USER_DEFAULT_SCREEN_DPI) * _compositionScaleX); - // !TODO!: MSFT:20895307 If the font doesn't exist, this doesn't + // TODO: MSFT:20895307 If the font doesn't exist, this doesn't // actually fail. We need a way to gracefully fallback. _renderer->TriggerFontChange(newDpi, _desiredFont, _actualFont); // If the actual font isn't what was requested... if (_actualFont.GetFaceName() != _desiredFont.GetFaceName()) { - // !TODO!: We _DO_ want this - // // Then warn the user that we picked something because we couldn't find their font. - // // Format message with user's choice of font and the font that was chosen instead. - // const winrt::hstring message{ fmt::format(std::wstring_view{ RS_(L"NoticeFontNotFound") }, _desiredFont.GetFaceName(), _actualFont.GetFaceName()) }; - // // Capture what we need to resume later. - // [strongThis = get_strong(), message]() -> winrt::fire_and_forget { - // // Take these out of the lambda and store them locally - // // because the coroutine will lose them into space - // // by the time it resumes. - // const auto msg = message; - // const auto strong = strongThis; - - // // Pop the rest of this function to the tail of the UI thread - // // Just in case someone was holding a lock when they called us and - // // the handlers decide to do something that take another lock - // // (like ShellExecute pumping our messaging thread...GH#7994) - // co_await strong->Dispatcher(); - - // auto noticeArgs = winrt::make(NoticeLevel::Warning, std::move(msg)); - // strong->_raiseNoticeHandlers(*strong, std::move(noticeArgs)); - // }(); + // Then warn the user that we picked something because we couldn't find their font. + // Format message with user's choice of font and the font that was chosen instead. + const winrt::hstring message{ fmt::format(std::wstring_view{ RS_(L"NoticeFontNotFound") }, + _desiredFont.GetFaceName(), + _actualFont.GetFaceName()) }; + auto noticeArgs = winrt::make(NoticeLevel::Warning, message); + _RaiseNoticeHandlers(*this, std::move(noticeArgs)); } - // !TODO!: We _DO_ want this - // const auto actualNewSize = _actualFont.GetSize(); - // _fontSizeChangedHandlers(actualNewSize.X, actualNewSize.Y, initialUpdate); + const auto actualNewSize = _actualFont.GetSize(); + _FontSizeChangedHandlers(actualNewSize.X, actualNewSize.Y, initialUpdate); } // Method Description: @@ -776,7 +761,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation // save location (for rendering) + render _terminal->SetSelectionEnd(terminalPosition); _renderer->TriggerSelection(); - // _selectionNeedsToBeCopied = true; + // _selectionNeedsToBeCopied = true; // !TODO! why is this commented out? } // Called when the Terminal wants to set something to the clipboard, i.e. diff --git a/src/cascadia/TerminalControl/ControlCore.h b/src/cascadia/TerminalControl/ControlCore.h index 0264a695a5e..e3bfabebb9a 100644 --- a/src/cascadia/TerminalControl/ControlCore.h +++ b/src/cascadia/TerminalControl/ControlCore.h @@ -121,6 +121,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation // -------------------------------- WinRT Events --------------------------------- // clang-format off + WINRT_CALLBACK(FontSizeChanged, Control::FontSizeChangedEventArgs); + TYPED_EVENT(CopyToClipboard, IInspectable, Control::CopyToClipboardEventArgs); TYPED_EVENT(TitleChanged, IInspectable, Control::TitleChangedEventArgs); TYPED_EVENT(WarningBell, IInspectable, IInspectable); @@ -134,6 +136,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation TYPED_EVENT(RendererEnteredErrorState, IInspectable, IInspectable); TYPED_EVENT(SwapChainChanged, IInspectable, IInspectable); TYPED_EVENT(RendererWarning, IInspectable, Control::RendererWarningArgs); + TYPED_EVENT(RaiseNotice, IInspectable, Control::NoticeEventArgs); // clang-format on private: diff --git a/src/cascadia/TerminalControl/TermControl.cpp b/src/cascadia/TerminalControl/TermControl.cpp index 1a67eddb1c6..0d7d66250ed 100644 --- a/src/cascadia/TerminalControl/TermControl.cpp +++ b/src/cascadia/TerminalControl/TermControl.cpp @@ -43,25 +43,6 @@ DEFINE_ENUM_FLAG_OPERATORS(winrt::Microsoft::Terminal::Control::CopyFormat); namespace winrt::Microsoft::Terminal::Control::implementation { - // Helper static function to ensure that all ambiguous-width glyphs are reported as narrow. - // See microsoft/terminal#2066 for more info. - static bool _IsGlyphWideForceNarrowFallback(const std::wstring_view /* glyph */) - { - return false; // glyph is not wide. - } - - static bool _EnsureStaticInitialization() - { - // use C++11 magic statics to make sure we only do this once. - static bool initialized = []() { - // *** THIS IS A SINGLETON *** - SetGlyphWidthFallback(_IsGlyphWideForceNarrowFallback); - - return true; - }(); - return initialized; - } - TermControl::TermControl(IControlSettings settings, TerminalConnection::ITerminalConnection connection) : _initializedTerminal{ false }, @@ -80,7 +61,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation _selectionNeedsToBeCopied{ false }, _searchBox{ nullptr } { - _EnsureStaticInitialization(); InitializeComponent(); _core = winrt::make_self(settings, connection); @@ -89,6 +69,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation _core->ScrollPositionChanged({ get_weak(), &TermControl::_ScrollPositionChanged }); _core->CursorPositionChanged({ get_weak(), &TermControl::_CursorPositionChanged }); _core->RendererEnteredErrorState({ get_weak(), &TermControl::_RendererEnteredErrorState }); + _core->FontSizeChanged({ get_weak(), &TermControl::_coreFontSizeChanged }); // Initialize the terminal only once the swapchainpanel is loaded - that // way, we'll be able to query the real pixel size it got on layout @@ -2729,8 +2710,11 @@ namespace winrt::Microsoft::Terminal::Control::implementation } } - // -------------------------------- WinRT Events --------------------------------- - // Winrt events need a method for adding a callback to the event and removing the callback. - // These macros will define them both for you. - DEFINE_EVENT(TermControl, FontSizeChanged, _fontSizeChangedHandlers, Control::FontSizeChangedEventArgs); + void TermControl::_coreFontSizeChanged(const int fontWidth, + const int fontHeight, + const bool isInitialChange) + { + _FontSizeChangedHandlers(fontWidth, fontHeight, isInitialChange); + } + } diff --git a/src/cascadia/TerminalControl/TermControl.h b/src/cascadia/TerminalControl/TermControl.h index d4a167bbf09..0db2fdcadab 100644 --- a/src/cascadia/TerminalControl/TermControl.h +++ b/src/cascadia/TerminalControl/TermControl.h @@ -95,7 +95,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation // -------------------------------- WinRT Events --------------------------------- // clang-format off - DECLARE_EVENT(FontSizeChanged, _fontSizeChangedHandlers, Control::FontSizeChangedEventArgs); + WINRT_CALLBACK(FontSizeChanged, Control::FontSizeChangedEventArgs); FORWARDED_TYPED_EVENT(CopyToClipboard, IInspectable, Control::CopyToClipboardEventArgs, _core, CopyToClipboard); FORWARDED_TYPED_EVENT(TitleChanged, IInspectable, Control::TitleChangedEventArgs, _core, TitleChanged); @@ -245,6 +245,10 @@ namespace winrt::Microsoft::Terminal::Control::implementation winrt::fire_and_forget _RaiseReadOnlyWarning(); winrt::fire_and_forget _hoveredHyperlinkChanged(const IInspectable& sender, const IInspectable& args); + + void _coreFontSizeChanged(const int fontWidth, + const int fontHeight, + const bool isInitialChange); }; } From c29ffbabed736f419468d7e52a5451af6675a51f Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Fri, 19 Mar 2021 12:37:54 -0500 Subject: [PATCH 18/82] Start moving things to a shared middle bit too --- .../TerminalControl/ControlInteractivity.cpp | 68 +++++++++++++++++++ .../TerminalControl/ControlInteractivity.h | 65 ++++++++++++++++++ .../TerminalControl/ControlInteractivity.idl | 17 +++++ src/cascadia/TerminalControl/TermControl.cpp | 68 +++++++++---------- src/cascadia/TerminalControl/TermControl.h | 44 ++++++------ .../TerminalControlLib.vcxproj | 7 ++ 6 files changed, 212 insertions(+), 57 deletions(-) create mode 100644 src/cascadia/TerminalControl/ControlInteractivity.cpp create mode 100644 src/cascadia/TerminalControl/ControlInteractivity.h create mode 100644 src/cascadia/TerminalControl/ControlInteractivity.idl diff --git a/src/cascadia/TerminalControl/ControlInteractivity.cpp b/src/cascadia/TerminalControl/ControlInteractivity.cpp new file mode 100644 index 00000000000..147022e4de5 --- /dev/null +++ b/src/cascadia/TerminalControl/ControlInteractivity.cpp @@ -0,0 +1,68 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +#include "pch.h" +#include "ControlInteractivity.h" +#include +#include +#include +#include +#include +#include +#include +#include "../../types/inc/GlyphWidth.hpp" +#include "../../types/inc/Utils.hpp" +#include "../../buffer/out/search.h" + +#include "ControlInteractivity.g.cpp" + +using namespace ::Microsoft::Console::Types; +using namespace ::Microsoft::Console::VirtualTerminal; +using namespace ::Microsoft::Terminal::Core; +using namespace winrt::Windows::Graphics::Display; +using namespace winrt::Windows::System; +using namespace winrt::Windows::ApplicationModel::DataTransfer; + +namespace winrt::Microsoft::Terminal::Control::implementation +{ + ControlInteractivity::ControlInteractivity(IControlSettings settings, + TerminalConnection::ITerminalConnection connection) : + _touchAnchor{ std::nullopt }, + _lastMouseClickTimestamp{}, + _lastMouseClickPos{}, + _selectionNeedsToBeCopied{ false } + { + _core = winrt::make_self(settings, connection); + } + + // Method Description: + // - Returns the number of clicks that occurred (double and triple click support). + // Every call to this function registers a click. + // Arguments: + // - clickPos: the (x,y) position of a given cursor (i.e.: mouse cursor). + // NOTE: origin (0,0) is top-left. + // - clickTime: the timestamp that the click occurred + // Return Value: + // - if the click is in the same position as the last click and within the timeout, the number of clicks within that time window + // - otherwise, 1 + unsigned int ControlInteractivity::_NumberOfClicks(winrt::Windows::Foundation::Point clickPos, + Timestamp clickTime) + { + // if click occurred at a different location or past the multiClickTimer... + Timestamp delta; + THROW_IF_FAILED(UInt64Sub(clickTime, _lastMouseClickTimestamp, &delta)); + if (clickPos != _lastMouseClickPos || delta > _multiClickTimer) + { + _multiClickCounter = 1; + } + else + { + _multiClickCounter++; + } + + _lastMouseClickTimestamp = clickTime; + _lastMouseClickPos = clickPos; + return _multiClickCounter; + } + +} diff --git a/src/cascadia/TerminalControl/ControlInteractivity.h b/src/cascadia/TerminalControl/ControlInteractivity.h new file mode 100644 index 00000000000..b05823dae3b --- /dev/null +++ b/src/cascadia/TerminalControl/ControlInteractivity.h @@ -0,0 +1,65 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +#pragma once + +#include "ControlInteractivity.g.h" +#include "EventArgs.h" +#include "../buffer/out/search.h" +#include "cppwinrt_utils.h" + +#include "ControlCore.h" + +namespace Microsoft::Console::VirtualTerminal +{ + struct MouseButtonState; +} + +namespace winrt::Microsoft::Terminal::Control::implementation +{ + struct ControlInteractivity : ControlInteractivityT + { + ControlInteractivity(IControlSettings settings, + TerminalConnection::ITerminalConnection connection); + + /////////////////////// From Control + winrt::com_ptr _core{ nullptr }; + unsigned int _rowsToScroll; // Definitely Control/Interactivity + + // If this is set, then we assume we are in the middle of panning the + // viewport via touch input. + std::optional _touchAnchor; + + using Timestamp = uint64_t; + + // imported from WinUser + // Used for PointerPoint.Timestamp Property (https://docs.microsoft.com/en-us/uwp/api/windows.ui.input.pointerpoint.timestamp#Windows_UI_Input_PointerPoint_Timestamp) + Timestamp _multiClickTimer; + unsigned int _multiClickCounter; + Timestamp _lastMouseClickTimestamp; + std::optional _lastMouseClickPos; + std::optional _singleClickTouchdownPos; + std::optional _lastMouseClickPosNoSelection; + // This field tracks whether the selection has changed meaningfully + // since it was last copied. It's generally used to prevent copyOnSelect + // from firing when the pointer _just happens_ to be released over the + // terminal. + bool _selectionNeedsToBeCopied; // ->Interactivity + + /////////////////////// From Core + bool _isReadOnly{ false }; // Probably belongs in Interactivity + + std::optional _lastHoveredCell{ std::nullopt }; + // Track the last hyperlink ID we hovered over + uint16_t _lastHoveredId{ 0 }; + + std::optional::interval> _lastHoveredInterval{ std::nullopt }; + + unsigned int _NumberOfClicks(winrt::Windows::Foundation::Point clickPos, Timestamp clickTime); + }; +} + +namespace winrt::Microsoft::Terminal::Control::factory_implementation +{ + BASIC_FACTORY(ControlInteractivity); +} diff --git a/src/cascadia/TerminalControl/ControlInteractivity.idl b/src/cascadia/TerminalControl/ControlInteractivity.idl new file mode 100644 index 00000000000..3478a7cfc97 --- /dev/null +++ b/src/cascadia/TerminalControl/ControlInteractivity.idl @@ -0,0 +1,17 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +import "ICoreState.idl"; +import "IControlSettings.idl"; +import "ControlCore.idl"; +import "EventArgs.idl"; + +namespace Microsoft.Terminal.Control +{ + + [default_interface] runtimeclass ControlInteractivity : ICoreState + { + ControlInteractivity(Microsoft.Terminal.Control.IControlSettings settings, + Microsoft.Terminal.TerminalConnection.ITerminalConnection connection); + }; +} diff --git a/src/cascadia/TerminalControl/TermControl.cpp b/src/cascadia/TerminalControl/TermControl.cpp index 0d7d66250ed..411382c045e 100644 --- a/src/cascadia/TerminalControl/TermControl.cpp +++ b/src/cascadia/TerminalControl/TermControl.cpp @@ -53,17 +53,14 @@ namespace winrt::Microsoft::Terminal::Control::implementation _autoScrollingPointerPoint{ std::nullopt }, _autoScrollTimer{}, _lastAutoScrollUpdateTime{ std::nullopt }, - _touchAnchor{ std::nullopt }, _cursorTimer{}, _blinkTimer{}, - _lastMouseClickTimestamp{}, - _lastMouseClickPos{}, - _selectionNeedsToBeCopied{ false }, _searchBox{ nullptr } { InitializeComponent(); - _core = winrt::make_self(settings, connection); + _interactivity = winrt::make_self(settings, connection); + _core = _interactivity->_core; _core->BackgroundColorChanged({ get_weak(), &TermControl::_BackgroundColorChangedHandler }); _core->ScrollPositionChanged({ get_weak(), &TermControl::_ScrollPositionChanged }); @@ -1069,7 +1066,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation const auto cursorPosition = point.Position(); const auto terminalPosition = _GetTerminalPosition(cursorPosition); - // const auto clickCount = _NumberOfClicks(cursorPosition, point.Timestamp()); // GH#9396: we prioritize hyper-link over VT mouse events // @@ -1078,7 +1074,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation if (point.Properties().IsLeftButtonPressed() && ctrlEnabled && !hyperlink.empty()) { - const auto clickCount = _NumberOfClicks(cursorPosition, point.Timestamp()); + const auto clickCount = _interactivity->_NumberOfClicks(cursorPosition, point.Timestamp()); // Handle hyper-link only on the first click to prevent multiple activations if (clickCount == 1) { @@ -1091,7 +1087,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation } else if (point.Properties().IsLeftButtonPressed()) { - const auto clickCount = _NumberOfClicks(cursorPosition, point.Timestamp()); + const auto clickCount = _interactivity->_NumberOfClicks(cursorPosition, point.Timestamp()); // This formula enables the number of clicks to cycle properly // between single-, double-, and triple-click. To increase the // number of acceptable click states, simply increment @@ -2367,34 +2363,34 @@ namespace winrt::Microsoft::Terminal::Control::implementation eventArgs.FontWeight(weight); } - // Method Description: - // - Returns the number of clicks that occurred (double and triple click support). - // Every call to this function registers a click. - // Arguments: - // - clickPos: the (x,y) position of a given cursor (i.e.: mouse cursor). - // NOTE: origin (0,0) is top-left. - // - clickTime: the timestamp that the click occurred - // Return Value: - // - if the click is in the same position as the last click and within the timeout, the number of clicks within that time window - // - otherwise, 1 - const unsigned int TermControl::_NumberOfClicks(winrt::Windows::Foundation::Point clickPos, Timestamp clickTime) - { - // if click occurred at a different location or past the multiClickTimer... - Timestamp delta; - THROW_IF_FAILED(UInt64Sub(clickTime, _lastMouseClickTimestamp, &delta)); - if (clickPos != _lastMouseClickPos || delta > _multiClickTimer) - { - _multiClickCounter = 1; - } - else - { - _multiClickCounter++; - } - - _lastMouseClickTimestamp = clickTime; - _lastMouseClickPos = clickPos; - return _multiClickCounter; - } + // // Method Description: + // // - Returns the number of clicks that occurred (double and triple click support). + // // Every call to this function registers a click. + // // Arguments: + // // - clickPos: the (x,y) position of a given cursor (i.e.: mouse cursor). + // // NOTE: origin (0,0) is top-left. + // // - clickTime: the timestamp that the click occurred + // // Return Value: + // // - if the click is in the same position as the last click and within the timeout, the number of clicks within that time window + // // - otherwise, 1 + // const unsigned int TermControl::_NumberOfClicks(winrt::Windows::Foundation::Point clickPos, Timestamp clickTime) + // { + // // if click occurred at a different location or past the multiClickTimer... + // Timestamp delta; + // THROW_IF_FAILED(UInt64Sub(clickTime, _lastMouseClickTimestamp, &delta)); + // if (clickPos != _lastMouseClickPos || delta > _multiClickTimer) + // { + // _multiClickCounter = 1; + // } + // else + // { + // _multiClickCounter++; + // } + + // _lastMouseClickTimestamp = clickTime; + // _lastMouseClickPos = clickPos; + // return _multiClickCounter; + // } // Method Description: // - Calculates speed of single axis of auto scrolling. It has to allow for both diff --git a/src/cascadia/TerminalControl/TermControl.h b/src/cascadia/TerminalControl/TermControl.h index 0db2fdcadab..d8df77f4f77 100644 --- a/src/cascadia/TerminalControl/TermControl.h +++ b/src/cascadia/TerminalControl/TermControl.h @@ -14,7 +14,8 @@ #include "SearchBoxControl.h" #include "ThrottledFunc.h" -#include "ControlCore.h" +// #include "ControlCore.h" +#include "ControlInteractivity.h" namespace Microsoft::Console::VirtualTerminal { @@ -118,6 +119,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation friend struct TermControlT; // friend our parent so it can bind private event handlers winrt::com_ptr _core{ nullptr }; + winrt::com_ptr _interactivity{ nullptr }; bool _initializedTerminal; @@ -142,7 +144,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation std::shared_ptr> _updateScrollBar; bool _isInternalScrollBarUpdate; - unsigned int _rowsToScroll; // Definitely Control/Interactivity + // unsigned int _rowsToScroll; // Definitely Control/Interactivity // Auto scroll occurs when user, while selecting, drags cursor outside viewport. View is then scrolled to 'follow' the cursor. double _autoScrollVelocity; @@ -153,25 +155,25 @@ namespace winrt::Microsoft::Terminal::Control::implementation std::optional _cursorTimer; std::optional _blinkTimer; - // If this is set, then we assume we are in the middle of panning the - // viewport via touch input. - std::optional _touchAnchor; - - using Timestamp = uint64_t; - - // imported from WinUser - // Used for PointerPoint.Timestamp Property (https://docs.microsoft.com/en-us/uwp/api/windows.ui.input.pointerpoint.timestamp#Windows_UI_Input_PointerPoint_Timestamp) - Timestamp _multiClickTimer; - unsigned int _multiClickCounter; - Timestamp _lastMouseClickTimestamp; - std::optional _lastMouseClickPos; - std::optional _singleClickTouchdownPos; - std::optional _lastMouseClickPosNoSelection; - // This field tracks whether the selection has changed meaningfully - // since it was last copied. It's generally used to prevent copyOnSelect - // from firing when the pointer _just happens_ to be released over the - // terminal. - bool _selectionNeedsToBeCopied; // ->Interactivity + // // If this is set, then we assume we are in the middle of panning the + // // viewport via touch input. + // std::optional _touchAnchor; + + // using Timestamp = uint64_t; + + // // imported from WinUser + // // Used for PointerPoint.Timestamp Property (https://docs.microsoft.com/en-us/uwp/api/windows.ui.input.pointerpoint.timestamp#Windows_UI_Input_PointerPoint_Timestamp) + // Timestamp _multiClickTimer; + // unsigned int _multiClickCounter; + // Timestamp _lastMouseClickTimestamp; + // std::optional _lastMouseClickPos; + // std::optional _singleClickTouchdownPos; + // std::optional _lastMouseClickPosNoSelection; + // // This field tracks whether the selection has changed meaningfully + // // since it was last copied. It's generally used to prevent copyOnSelect + // // from firing when the pointer _just happens_ to be released over the + // // terminal. + // bool _selectionNeedsToBeCopied; // ->Interactivity winrt::Windows::UI::Xaml::Controls::SwapChainPanel::LayoutUpdated_revoker _layoutUpdatedRevoker; diff --git a/src/cascadia/TerminalControl/TerminalControlLib.vcxproj b/src/cascadia/TerminalControl/TerminalControlLib.vcxproj index ecefdb45564..f46e83573a5 100644 --- a/src/cascadia/TerminalControl/TerminalControlLib.vcxproj +++ b/src/cascadia/TerminalControl/TerminalControlLib.vcxproj @@ -31,6 +31,9 @@ ControlCore.idl + + ControlInteractivity.idl + KeyChord.idl @@ -60,6 +63,9 @@ ControlCore.idl + + ControlInteractivity.idl + EventArgs.idl @@ -86,6 +92,7 @@ + From 72c35a8f6d1f9d26888b60409cf33d553f9ce3bb Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Fri, 19 Mar 2021 12:41:52 -0500 Subject: [PATCH 19/82] Move _UpdateSystemParameterSettings, 30 errors remain --- .../TerminalControl/ControlInteractivity.cpp | 18 +++++++++++++ .../TerminalControl/ControlInteractivity.h | 3 +++ src/cascadia/TerminalControl/TermControl.cpp | 26 +++++++++---------- src/cascadia/TerminalControl/TermControl.h | 4 +-- 4 files changed, 36 insertions(+), 15 deletions(-) diff --git a/src/cascadia/TerminalControl/ControlInteractivity.cpp b/src/cascadia/TerminalControl/ControlInteractivity.cpp index 147022e4de5..ae169c94cc6 100644 --- a/src/cascadia/TerminalControl/ControlInteractivity.cpp +++ b/src/cascadia/TerminalControl/ControlInteractivity.cpp @@ -65,4 +65,22 @@ namespace winrt::Microsoft::Terminal::Control::implementation return _multiClickCounter; } + void ControlInteractivity::GainFocus() + { + _UpdateSystemParameterSettings(); + } + + // Method Description + // - Updates internal params based on system parameters + void ControlInteractivity::_UpdateSystemParameterSettings() noexcept + { + if (!SystemParametersInfoW(SPI_GETWHEELSCROLLLINES, 0, &_rowsToScroll, 0)) + { + LOG_LAST_ERROR(); + // If SystemParametersInfoW fails, which it shouldn't, fall back to + // Windows' default value. + _rowsToScroll = 3; + } + } + } diff --git a/src/cascadia/TerminalControl/ControlInteractivity.h b/src/cascadia/TerminalControl/ControlInteractivity.h index b05823dae3b..7f496c90888 100644 --- a/src/cascadia/TerminalControl/ControlInteractivity.h +++ b/src/cascadia/TerminalControl/ControlInteractivity.h @@ -22,6 +22,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation ControlInteractivity(IControlSettings settings, TerminalConnection::ITerminalConnection connection); + void GainFocus(); + /////////////////////// From Control winrt::com_ptr _core{ nullptr }; unsigned int _rowsToScroll; // Definitely Control/Interactivity @@ -56,6 +58,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation std::optional::interval> _lastHoveredInterval{ std::nullopt }; unsigned int _NumberOfClicks(winrt::Windows::Foundation::Point clickPos, Timestamp clickTime); + void _UpdateSystemParameterSettings() noexcept; }; } diff --git a/src/cascadia/TerminalControl/TermControl.cpp b/src/cascadia/TerminalControl/TermControl.cpp index 411382c045e..3966f606206 100644 --- a/src/cascadia/TerminalControl/TermControl.cpp +++ b/src/cascadia/TerminalControl/TermControl.cpp @@ -1695,21 +1695,21 @@ namespace winrt::Microsoft::Terminal::Control::implementation _blinkTimer.value().Start(); } - _UpdateSystemParameterSettings(); + _interactivity->GainFocus(); } - // Method Description - // - Updates internal params based on system parameters - void TermControl::_UpdateSystemParameterSettings() noexcept - { - if (!SystemParametersInfoW(SPI_GETWHEELSCROLLLINES, 0, &_rowsToScroll, 0)) - { - LOG_LAST_ERROR(); - // If SystemParametersInfoW fails, which it shouldn't, fall back to - // Windows' default value. - _rowsToScroll = 3; - } - } + // // Method Description + // // - Updates internal params based on system parameters + // void TermControl::_UpdateSystemParameterSettings() noexcept + // { + // if (!SystemParametersInfoW(SPI_GETWHEELSCROLLLINES, 0, &_rowsToScroll, 0)) + // { + // LOG_LAST_ERROR(); + // // If SystemParametersInfoW fails, which it shouldn't, fall back to + // // Windows' default value. + // _rowsToScroll = 3; + // } + // } // Method Description: // - Event handler for the LostFocus event. This is used to... diff --git a/src/cascadia/TerminalControl/TermControl.h b/src/cascadia/TerminalControl/TermControl.h index d8df77f4f77..eca22032e64 100644 --- a/src/cascadia/TerminalControl/TermControl.h +++ b/src/cascadia/TerminalControl/TermControl.h @@ -179,7 +179,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation void _ApplyUISettings(const IControlSettings&); void _UpdateSettingsOnUIThread(); - void _UpdateSystemParameterSettings() noexcept; + // void _UpdateSystemParameterSettings() noexcept; void _InitializeBackgroundBrush(); void _BackgroundColorChangedHandler(const IInspectable& sender, const IInspectable& args); winrt::fire_and_forget _changeBackgroundColor(til::color bg); @@ -234,7 +234,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation bool _CanSendVTMouseInput(); const til::point _GetTerminalPosition(winrt::Windows::Foundation::Point cursorPosition); - const unsigned int _NumberOfClicks(winrt::Windows::Foundation::Point clickPos, Timestamp clickTime); + // const unsigned int _NumberOfClicks(winrt::Windows::Foundation::Point clickPos, Timestamp clickTime); double _GetAutoScrollSpeed(double cursorDistanceFromBorder) const; void _Search(const winrt::hstring& text, const bool goForward, const bool caseSensitive); From 541d1518dcb6f9278d1db34956b2f5ec15b26e8b Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Wed, 24 Mar 2021 14:36:21 -0500 Subject: [PATCH 20/82] I suppose this should have been in the parent commit --- src/cascadia/TerminalControl/ControlInteractivity.cpp | 5 +++++ src/cascadia/TerminalControl/ControlInteractivity.h | 1 + src/cascadia/TerminalControl/TermControl.cpp | 2 +- 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/cascadia/TerminalControl/ControlInteractivity.cpp b/src/cascadia/TerminalControl/ControlInteractivity.cpp index ae169c94cc6..9533125f62b 100644 --- a/src/cascadia/TerminalControl/ControlInteractivity.cpp +++ b/src/cascadia/TerminalControl/ControlInteractivity.cpp @@ -35,6 +35,11 @@ namespace winrt::Microsoft::Terminal::Control::implementation _core = winrt::make_self(settings, connection); } + void ControlInteractivity::UpdateSettings() + { + _UpdateSystemParameterSettings(); + } + // Method Description: // - Returns the number of clicks that occurred (double and triple click support). // Every call to this function registers a click. diff --git a/src/cascadia/TerminalControl/ControlInteractivity.h b/src/cascadia/TerminalControl/ControlInteractivity.h index 7f496c90888..acc4a02f1f7 100644 --- a/src/cascadia/TerminalControl/ControlInteractivity.h +++ b/src/cascadia/TerminalControl/ControlInteractivity.h @@ -23,6 +23,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation TerminalConnection::ITerminalConnection connection); void GainFocus(); + void UpdateSettings(); /////////////////////// From Control winrt::com_ptr _core{ nullptr }; diff --git a/src/cascadia/TerminalControl/TermControl.cpp b/src/cascadia/TerminalControl/TermControl.cpp index 3966f606206..f60d1640c68 100644 --- a/src/cascadia/TerminalControl/TermControl.cpp +++ b/src/cascadia/TerminalControl/TermControl.cpp @@ -320,7 +320,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation ScrollBar().Visibility(Visibility::Visible); } - _UpdateSystemParameterSettings(); + _interactivity->UpdateSettings(); } // Method Description: From bbf605b66a1677247f841f1417e774693ab53bbf Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Mon, 29 Mar 2021 09:31:12 -0500 Subject: [PATCH 21/82] I think this needs to go in main --- OpenConsole.sln | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/OpenConsole.sln b/OpenConsole.sln index 0cdb34c7ef2..4085430829c 100644 --- a/OpenConsole.sln +++ b/OpenConsole.sln @@ -164,10 +164,13 @@ EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RendererDx", "src\renderer\dx\lib\dx.vcxproj", "{48D21369-3D7B-4431-9967-24E81292CF62}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TerminalConnection", "src\cascadia\TerminalConnection\TerminalConnection.vcxproj", "{CA5CAD1A-C46D-4588-B1C0-40F31AE9100B}" + ProjectSection(ProjectDependencies) = postProject + {71CC9D78-BA29-4D93-946F-BEF5D9A3A6EF} = {71CC9D78-BA29-4D93-946F-BEF5D9A3A6EF} + EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TerminalCore", "src\cascadia\TerminalCore\lib\TerminalCore-lib.vcxproj", "{CA5CAD1A-ABCD-429C-B551-8562EC954746}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TerminalControlLib", "src\cascadia\TerminalControl\TerminalControlLib.vcxproj", "{CA5CAD1A-44BD-4AC7-AC72-6CA5B3AB89ED}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Microsoft.Terminal.Control.Lib", "src\cascadia\TerminalControl\TerminalControlLib.vcxproj", "{CA5CAD1A-44BD-4AC7-AC72-6CA5B3AB89ED}" ProjectSection(ProjectDependencies) = postProject {CA5CAD1A-C46D-4588-B1C0-40F31AE9100B} = {CA5CAD1A-C46D-4588-B1C0-40F31AE9100B} {CA5CAD1A-ABCD-429C-B551-8562EC954746} = {CA5CAD1A-ABCD-429C-B551-8562EC954746} @@ -175,15 +178,15 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TerminalControlLib", "src\c {48D21369-3D7B-4431-9967-24E81292CF63} = {48D21369-3D7B-4431-9967-24E81292CF63} EndProjectSection EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TerminalControl", "src\cascadia\TerminalControl\dll\TerminalControl.vcxproj", "{CA5CAD1A-F542-4635-A069-7CAEFB930070}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Microsoft.Terminal.Control", "src\cascadia\TerminalControl\dll\TerminalControl.vcxproj", "{CA5CAD1A-F542-4635-A069-7CAEFB930070}" ProjectSection(ProjectDependencies) = postProject {CA5CAD1A-44BD-4AC7-AC72-6CA5B3AB89ED} = {CA5CAD1A-44BD-4AC7-AC72-6CA5B3AB89ED} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WindowsTerminal", "src\cascadia\WindowsTerminal\WindowsTerminal.vcxproj", "{CA5CAD1A-1754-4A9D-93D7-857A9D17CB1B}" ProjectSection(ProjectDependencies) = postProject - {CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32} = {CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32} {CA5CAD1A-F542-4635-A069-7CAEFB930070} = {CA5CAD1A-F542-4635-A069-7CAEFB930070} + {CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32} = {CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32} {CA5CAD1A-44BD-4AC7-AC72-F16E576FDD12} = {CA5CAD1A-44BD-4AC7-AC72-F16E576FDD12} {CA5CAD1A-ABCD-429C-B551-8562EC954746} = {CA5CAD1A-ABCD-429C-B551-8562EC954746} {27B5AAEB-A548-44CF-9777-F8BAA32AF7AE} = {27B5AAEB-A548-44CF-9777-F8BAA32AF7AE} @@ -194,9 +197,9 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TerminalApp", "src\cascadia ProjectSection(ProjectDependencies) = postProject {CA5CAD1A-9A12-429C-B551-8562EC954746} = {CA5CAD1A-9A12-429C-B551-8562EC954746} {CA5CAD1A-082C-4476-9F33-94B339494076} = {CA5CAD1A-082C-4476-9F33-94B339494076} + {CA5CAD1A-F542-4635-A069-7CAEFB930070} = {CA5CAD1A-F542-4635-A069-7CAEFB930070} {CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32} = {CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32} {CA5CAD1A-C46D-4588-B1C0-40F31AE9100B} = {CA5CAD1A-C46D-4588-B1C0-40F31AE9100B} - {CA5CAD1A-F542-4635-A069-7CAEFB930070} = {CA5CAD1A-F542-4635-A069-7CAEFB930070} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WindowsTerminalShellExt", "src\cascadia\ShellExtension\WindowsTerminalShellExt.vcxproj", "{F2ED628A-DB22-446F-A081-4CC845B51A2B}" @@ -246,8 +249,8 @@ EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TerminalAppLib", "src\cascadia\TerminalApp\TerminalAppLib.vcxproj", "{CA5CAD1A-9A12-429C-B551-8562EC954746}" ProjectSection(ProjectDependencies) = postProject {CA5CAD1A-082C-4476-9F33-94B339494076} = {CA5CAD1A-082C-4476-9F33-94B339494076} - {CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32} = {CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32} {CA5CAD1A-F542-4635-A069-7CAEFB930070} = {CA5CAD1A-F542-4635-A069-7CAEFB930070} + {CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32} = {CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LocalTests_TerminalApp", "src\cascadia\LocalTests_TerminalApp\TerminalApp.LocalTests.vcxproj", "{CA5CAD1A-B11C-4DDB-A4FE-C3AFAE9B5506}" @@ -348,8 +351,8 @@ EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LocalTests_SettingsModel", "src\cascadia\LocalTests_SettingsModel\SettingsModel.LocalTests.vcxproj", "{CA5CAD1A-9B68-456A-B13E-C8218070DC42}" ProjectSection(ProjectDependencies) = postProject {CA5CAD1A-082C-4476-9F33-94B339494076} = {CA5CAD1A-082C-4476-9F33-94B339494076} - {CA5CAD1A-C46D-4588-B1C0-40F31AE9100B} = {CA5CAD1A-C46D-4588-B1C0-40F31AE9100B} {CA5CAD1A-F542-4635-A069-7CAEFB930070} = {CA5CAD1A-F542-4635-A069-7CAEFB930070} + {CA5CAD1A-C46D-4588-B1C0-40F31AE9100B} = {CA5CAD1A-C46D-4588-B1C0-40F31AE9100B} {CA5CAD1A-D7EC-4107-B7C6-79CB77AE2907} = {CA5CAD1A-D7EC-4107-B7C6-79CB77AE2907} EndProjectSection EndProject From ed79dab1ee10392e7e56143549ebad39e42a65a3 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Mon, 29 Mar 2021 10:45:47 -0500 Subject: [PATCH 22/82] Move PointerPressed to ControlInteractivity This also moved _HyperlinkHandler, and _TrySendMouseEvent Started with 29 errors, down to 24 --- src/cascadia/TerminalControl/ControlCore.cpp | 5 + src/cascadia/TerminalControl/ControlCore.h | 6 +- .../TerminalControl/ControlInteractivity.cpp | 152 ++++++++++ .../TerminalControl/ControlInteractivity.h | 10 + .../TerminalControl/ControlInteractivity.idl | 2 +- src/cascadia/TerminalControl/TermControl.cpp | 272 +++++++++--------- src/cascadia/TerminalControl/TermControl.h | 4 +- 7 files changed, 313 insertions(+), 138 deletions(-) diff --git a/src/cascadia/TerminalControl/ControlCore.cpp b/src/cascadia/TerminalControl/ControlCore.cpp index bf78d6b58b4..b541223ccbf 100644 --- a/src/cascadia/TerminalControl/ControlCore.cpp +++ b/src/cascadia/TerminalControl/ControlCore.cpp @@ -993,6 +993,11 @@ namespace winrt::Microsoft::Terminal::Control::implementation return _terminal->IsSelectionActive(); } + bool ControlCore::CopyOnSelect() const + { + return _settings.CopyOnSelect(); + } + std::vector ControlCore::SelectedText(bool trimTrailingWhitespace) const { const auto bufferData = _terminal->RetrieveSelectedTextFromBuffer(trimTrailingWhitespace); diff --git a/src/cascadia/TerminalControl/ControlCore.h b/src/cascadia/TerminalControl/ControlCore.h index e3bfabebb9a..c2003abd4fc 100644 --- a/src/cascadia/TerminalControl/ControlCore.h +++ b/src/cascadia/TerminalControl/ControlCore.h @@ -53,9 +53,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation winrt::hstring GetHoveredUriText() const; std::optional GetHoveredCell() const; - void SetSelectionAnchor(winrt::Windows::Foundation::Point const& position); - void SetEndSelectionPoint(winrt::Windows::Foundation::Point const& position); - ::Microsoft::Console::Types::IUiaData* GetUiaData() const; winrt::fire_and_forget _AsyncCloseConnection(); @@ -101,7 +98,10 @@ namespace winrt::Microsoft::Terminal::Control::implementation til::point CursorPosition() const; bool HasSelection() const; + bool CopyOnSelect() const; std::vector SelectedText(bool trimTrailingWhitespace) const; + void SetSelectionAnchor(winrt::Windows::Foundation::Point const& position); + void SetEndSelectionPoint(winrt::Windows::Foundation::Point const& position); void Search(const winrt::hstring& text, const bool goForward, diff --git a/src/cascadia/TerminalControl/ControlInteractivity.cpp b/src/cascadia/TerminalControl/ControlInteractivity.cpp index 9533125f62b..027506f6d1a 100644 --- a/src/cascadia/TerminalControl/ControlInteractivity.cpp +++ b/src/cascadia/TerminalControl/ControlInteractivity.cpp @@ -40,6 +40,12 @@ namespace winrt::Microsoft::Terminal::Control::implementation _UpdateSystemParameterSettings(); } + void ControlInteractivity::Initialize() + { + // import value from WinUser (convert from milli-seconds to micro-seconds) + _multiClickTimer = GetDoubleClickTime() * 1000; + } + // Method Description: // - Returns the number of clicks that occurred (double and triple click support). // Every call to this function registers a click. @@ -88,4 +94,150 @@ namespace winrt::Microsoft::Terminal::Control::implementation } } + // TODO: Doint take a Windows::UI::Input::PointerPoint here + void ControlInteractivity::PointerPressed(const winrt::Windows::UI::Input::PointerPoint point, + const uint32_t modifiers, + const til::point terminalPosition, + const winrt::Windows::Devices::Input::PointerDeviceType type) + { + if (type == Windows::Devices::Input::PointerDeviceType::Mouse || + type == Windows::Devices::Input::PointerDeviceType::Pen) + { + // const auto modifiers = static_cast(args.KeyModifiers()); + // static_cast to a uint32_t because we can't use the WI_IsFlagSet + // macro directly with a VirtualKeyModifiers + const auto altEnabled = WI_IsFlagSet(modifiers, static_cast(VirtualKeyModifiers::Menu)); + const auto shiftEnabled = WI_IsFlagSet(modifiers, static_cast(VirtualKeyModifiers::Shift)); + const auto ctrlEnabled = WI_IsFlagSet(modifiers, static_cast(VirtualKeyModifiers::Control)); + + const auto cursorPosition = point.Position(); + // const auto terminalPosition = _GetTerminalPosition(cursorPosition); + + // GH#9396: we prioritize hyper-link over VT mouse events + // + // !TODO! Before we'd lock the terminal before getting the hyperlink. Do we still need to? + auto hyperlink = _core->GetHyperlink(terminalPosition); + if (point.Properties().IsLeftButtonPressed() && + ctrlEnabled && !hyperlink.empty()) + { + const auto clickCount = _NumberOfClicks(cursorPosition, point.Timestamp()); + // Handle hyper-link only on the first click to prevent multiple activations + if (clickCount == 1) + { + _HyperlinkHandler(hyperlink); + } + } + else if (_CanSendVTMouseInput()) + { + _TrySendMouseEvent(point); + } + else if (point.Properties().IsLeftButtonPressed()) + { + const auto clickCount = _NumberOfClicks(cursorPosition, point.Timestamp()); + // This formula enables the number of clicks to cycle properly + // between single-, double-, and triple-click. To increase the + // number of acceptable click states, simply increment + // MAX_CLICK_COUNT and add another if-statement + const unsigned int MAX_CLICK_COUNT = 3; + const auto multiClickMapper = clickCount > MAX_CLICK_COUNT ? ((clickCount + MAX_CLICK_COUNT - 1) % MAX_CLICK_COUNT) + 1 : clickCount; + + // Capture the position of the first click when no selection is active + if (multiClickMapper == 1 && + !_core->HasSelection()) + { + _singleClickTouchdownPos = cursorPosition; + _lastMouseClickPosNoSelection = cursorPosition; + } + const bool isOnOriginalPosition = _lastMouseClickPosNoSelection == cursorPosition; + + _core->LeftClickOnTerminal(terminalPosition, + multiClickMapper, + altEnabled, + shiftEnabled, + isOnOriginalPosition, + _selectionNeedsToBeCopied); + } + else if (point.Properties().IsRightButtonPressed()) + { + // CopyOnSelect right click always pastes + if (_core->CopyOnSelect() || !_core->HasSelection()) + { + PasteTextFromClipboard(); + } + else + { + CopySelectionToClipboard(shiftEnabled, nullptr); + } + } + } + else if (type == Windows::Devices::Input::PointerDeviceType::Touch) + { + const auto contactRect = point.Properties().ContactRect(); + // Set our touch rect, to start a pan. + _touchAnchor = winrt::Windows::Foundation::Point{ contactRect.X, contactRect.Y }; + } + } + + // Method Description: + // - Send this particular mouse event to the terminal. + // See Terminal::SendMouseEvent for more information. + // Arguments: + // - point: the PointerPoint object representing a mouse event from our XAML input handler + bool ControlInteractivity::_TrySendMouseEvent(Windows::UI::Input::PointerPoint const& point, + const til::point terminalPosition) + { + const auto props = point.Properties(); + + // Get the terminal position relative to the viewport + // const auto terminalPosition = _GetTerminalPosition(point.Position()); + + // Which mouse button changed state (and how) + unsigned int uiButton{}; + switch (props.PointerUpdateKind()) + { + case winrt::Windows::UI::Input::PointerUpdateKind::LeftButtonPressed: + uiButton = WM_LBUTTONDOWN; + break; + case winrt::Windows::UI::Input::PointerUpdateKind::LeftButtonReleased: + uiButton = WM_LBUTTONUP; + break; + case winrt::Windows::UI::Input::PointerUpdateKind::MiddleButtonPressed: + uiButton = WM_MBUTTONDOWN; + break; + case winrt::Windows::UI::Input::PointerUpdateKind::MiddleButtonReleased: + uiButton = WM_MBUTTONUP; + break; + case winrt::Windows::UI::Input::PointerUpdateKind::RightButtonPressed: + uiButton = WM_RBUTTONDOWN; + break; + case winrt::Windows::UI::Input::PointerUpdateKind::RightButtonReleased: + uiButton = WM_RBUTTONUP; + break; + default: + uiButton = WM_MOUSEMOVE; + } + + // Mouse wheel data + const short sWheelDelta = ::base::saturated_cast(props.MouseWheelDelta()); + if (sWheelDelta != 0 && !props.IsHorizontalMouseWheel()) + { + // if we have a mouse wheel delta and it wasn't a horizontal wheel motion + uiButton = WM_MOUSEWHEEL; + } + + const auto modifiers = _GetPressedModifierKeys(); + const TerminalInput::MouseButtonState state{ props.IsLeftButtonPressed(), + props.IsMiddleButtonPressed(), + props.IsRightButtonPressed() }; + return _core->SendMouseEvent(terminalPosition, uiButton, modifiers, sWheelDelta, state); + } + + void ControlInteractivity::_HyperlinkHandler(const std::wstring_view uri) + { + // Save things we need to resume later. + winrt::hstring heldUri{ uri }; + auto hyperlinkArgs = winrt::make_self(heldUri); + _OpenHyperlinkHandlers(*this, *hyperlinkArgs); + } + } diff --git a/src/cascadia/TerminalControl/ControlInteractivity.h b/src/cascadia/TerminalControl/ControlInteractivity.h index acc4a02f1f7..197bff00c2b 100644 --- a/src/cascadia/TerminalControl/ControlInteractivity.h +++ b/src/cascadia/TerminalControl/ControlInteractivity.h @@ -24,6 +24,11 @@ namespace winrt::Microsoft::Terminal::Control::implementation void GainFocus(); void UpdateSettings(); + void Initialize(); + void PointerPressed(const winrt::Windows::UI::Input::PointerPoint point, + const uint32_t modifiers, + const til::point terminalPosition, + const winrt::Windows::Devices::Input::PointerDeviceType type); /////////////////////// From Control winrt::com_ptr _core{ nullptr }; @@ -60,6 +65,11 @@ namespace winrt::Microsoft::Terminal::Control::implementation unsigned int _NumberOfClicks(winrt::Windows::Foundation::Point clickPos, Timestamp clickTime); void _UpdateSystemParameterSettings() noexcept; + bool _TrySendMouseEvent(Windows::UI::Input::PointerPoint const& point, + const til::point terminalPosition); + void _HyperlinkHandler(const std::wstring_view uri); + + TYPED_EVENT(OpenHyperlink, IInspectable, Control::OpenHyperlinkEventArgs); }; } diff --git a/src/cascadia/TerminalControl/ControlInteractivity.idl b/src/cascadia/TerminalControl/ControlInteractivity.idl index 3478a7cfc97..000c8ec1ff3 100644 --- a/src/cascadia/TerminalControl/ControlInteractivity.idl +++ b/src/cascadia/TerminalControl/ControlInteractivity.idl @@ -9,7 +9,7 @@ import "EventArgs.idl"; namespace Microsoft.Terminal.Control { - [default_interface] runtimeclass ControlInteractivity : ICoreState + [default_interface] runtimeclass ControlInteractivity { ControlInteractivity(Microsoft.Terminal.Control.IControlSettings settings, Microsoft.Terminal.TerminalConnection.ITerminalConnection connection); diff --git a/src/cascadia/TerminalControl/TermControl.cpp b/src/cascadia/TerminalControl/TermControl.cpp index 765a4e8d07f..fb80cfdf14a 100644 --- a/src/cascadia/TerminalControl/TermControl.cpp +++ b/src/cascadia/TerminalControl/TermControl.cpp @@ -68,6 +68,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation _core->RendererEnteredErrorState({ get_weak(), &TermControl::_RendererEnteredErrorState }); _core->FontSizeChanged({ get_weak(), &TermControl::_coreFontSizeChanged }); + _interactivity->OpenHyperlink({ get_weak(), &TermControl::_HyperlinkHandler }); // Initialize the terminal only once the swapchainpanel is loaded - that // way, we'll be able to query the real pixel size it got on layout _layoutUpdatedRevoker = SwapChainPanel().LayoutUpdated(winrt::auto_revoke, [this](auto /*s*/, auto /*e*/) { @@ -658,8 +659,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation _blinkTimer = std::nullopt; } - // import value from WinUser (convert from milli-seconds to micro-seconds) - _multiClickTimer = GetDoubleClickTime() * 1000; + // // import value from WinUser (convert from milli-seconds to micro-seconds) + // _multiClickTimer = GetDoubleClickTime() * 1000; // Focus the control here. If we do it during control initialization, then // focus won't actually get passed to us. I believe this is because @@ -955,58 +956,58 @@ namespace winrt::Microsoft::Terminal::Control::implementation e.Handled(true); } - // Method Description: - // - Send this particular mouse event to the terminal. - // See Terminal::SendMouseEvent for more information. - // Arguments: - // - point: the PointerPoint object representing a mouse event from our XAML input handler - bool TermControl::_TrySendMouseEvent(Windows::UI::Input::PointerPoint const& point) - { - const auto props = point.Properties(); + // // Method Description: + // // - Send this particular mouse event to the terminal. + // // See Terminal::SendMouseEvent for more information. + // // Arguments: + // // - point: the PointerPoint object representing a mouse event from our XAML input handler + // bool TermControl::_TrySendMouseEvent(Windows::UI::Input::PointerPoint const& point) + // { + // const auto props = point.Properties(); - // Get the terminal position relative to the viewport - const auto terminalPosition = _GetTerminalPosition(point.Position()); - - // Which mouse button changed state (and how) - unsigned int uiButton{}; - switch (props.PointerUpdateKind()) - { - case PointerUpdateKind::LeftButtonPressed: - uiButton = WM_LBUTTONDOWN; - break; - case PointerUpdateKind::LeftButtonReleased: - uiButton = WM_LBUTTONUP; - break; - case PointerUpdateKind::MiddleButtonPressed: - uiButton = WM_MBUTTONDOWN; - break; - case PointerUpdateKind::MiddleButtonReleased: - uiButton = WM_MBUTTONUP; - break; - case PointerUpdateKind::RightButtonPressed: - uiButton = WM_RBUTTONDOWN; - break; - case PointerUpdateKind::RightButtonReleased: - uiButton = WM_RBUTTONUP; - break; - default: - uiButton = WM_MOUSEMOVE; - } + // // Get the terminal position relative to the viewport + // const auto terminalPosition = _GetTerminalPosition(point.Position()); - // Mouse wheel data - const short sWheelDelta = ::base::saturated_cast(props.MouseWheelDelta()); - if (sWheelDelta != 0 && !props.IsHorizontalMouseWheel()) - { - // if we have a mouse wheel delta and it wasn't a horizontal wheel motion - uiButton = WM_MOUSEWHEEL; - } + // // Which mouse button changed state (and how) + // unsigned int uiButton{}; + // switch (props.PointerUpdateKind()) + // { + // case PointerUpdateKind::LeftButtonPressed: + // uiButton = WM_LBUTTONDOWN; + // break; + // case PointerUpdateKind::LeftButtonReleased: + // uiButton = WM_LBUTTONUP; + // break; + // case PointerUpdateKind::MiddleButtonPressed: + // uiButton = WM_MBUTTONDOWN; + // break; + // case PointerUpdateKind::MiddleButtonReleased: + // uiButton = WM_MBUTTONUP; + // break; + // case PointerUpdateKind::RightButtonPressed: + // uiButton = WM_RBUTTONDOWN; + // break; + // case PointerUpdateKind::RightButtonReleased: + // uiButton = WM_RBUTTONUP; + // break; + // default: + // uiButton = WM_MOUSEMOVE; + // } - const auto modifiers = _GetPressedModifierKeys(); - const TerminalInput::MouseButtonState state{ props.IsLeftButtonPressed(), - props.IsMiddleButtonPressed(), - props.IsRightButtonPressed() }; - return _core->SendMouseEvent(terminalPosition, uiButton, modifiers, sWheelDelta, state); - } + // // Mouse wheel data + // const short sWheelDelta = ::base::saturated_cast(props.MouseWheelDelta()); + // if (sWheelDelta != 0 && !props.IsHorizontalMouseWheel()) + // { + // // if we have a mouse wheel delta and it wasn't a horizontal wheel motion + // uiButton = WM_MOUSEWHEEL; + // } + + // const auto modifiers = _GetPressedModifierKeys(); + // const TerminalInput::MouseButtonState state{ props.IsLeftButtonPressed(), + // props.IsMiddleButtonPressed(), + // props.IsRightButtonPressed() }; + // return _core->SendMouseEvent(terminalPosition, uiButton, modifiers, sWheelDelta, state); + // } // Method Description: // - Checks if we can send vt mouse input. @@ -1054,82 +1055,87 @@ namespace winrt::Microsoft::Terminal::Control::implementation { Focus(FocusState::Pointer); } + const auto cursorPosition = point.Position(); - if (ptr.PointerDeviceType() == Windows::Devices::Input::PointerDeviceType::Mouse || ptr.PointerDeviceType() == Windows::Devices::Input::PointerDeviceType::Pen) - { - const auto modifiers = static_cast(args.KeyModifiers()); - // static_cast to a uint32_t because we can't use the WI_IsFlagSet - // macro directly with a VirtualKeyModifiers - const auto altEnabled = WI_IsFlagSet(modifiers, static_cast(VirtualKeyModifiers::Menu)); - const auto shiftEnabled = WI_IsFlagSet(modifiers, static_cast(VirtualKeyModifiers::Shift)); - const auto ctrlEnabled = WI_IsFlagSet(modifiers, static_cast(VirtualKeyModifiers::Control)); - - const auto cursorPosition = point.Position(); - const auto terminalPosition = _GetTerminalPosition(cursorPosition); - - // GH#9396: we prioritize hyper-link over VT mouse events - // - // !TODO! Before we'd lock the terminal before getting the hyperlink. Do we still need to? - auto hyperlink = _core->GetHyperlink(terminalPosition); - if (point.Properties().IsLeftButtonPressed() && - ctrlEnabled && !hyperlink.empty()) - { - const auto clickCount = _interactivity->_NumberOfClicks(cursorPosition, point.Timestamp()); - // Handle hyper-link only on the first click to prevent multiple activations - if (clickCount == 1) - { - _HyperlinkHandler(hyperlink); - } - } - else if (_CanSendVTMouseInput()) - { - _TrySendMouseEvent(point); - } - else if (point.Properties().IsLeftButtonPressed()) - { - const auto clickCount = _interactivity->_NumberOfClicks(cursorPosition, point.Timestamp()); - // This formula enables the number of clicks to cycle properly - // between single-, double-, and triple-click. To increase the - // number of acceptable click states, simply increment - // MAX_CLICK_COUNT and add another if-statement - const unsigned int MAX_CLICK_COUNT = 3; - const auto multiClickMapper = clickCount > MAX_CLICK_COUNT ? ((clickCount + MAX_CLICK_COUNT - 1) % MAX_CLICK_COUNT) + 1 : clickCount; - - // Capture the position of the first click when no selection is active - if (multiClickMapper == 1 && - !_core->HasSelection()) - { - _singleClickTouchdownPos = cursorPosition; - _lastMouseClickPosNoSelection = cursorPosition; - } - const bool isOnOriginalPosition = _lastMouseClickPosNoSelection == cursorPosition; - - _core->LeftClickOnTerminal(terminalPosition, - multiClickMapper, - altEnabled, - shiftEnabled, - isOnOriginalPosition, - _selectionNeedsToBeCopied); - } - else if (point.Properties().IsRightButtonPressed()) - { - // CopyOnSelect right click always pastes - if (_settings.CopyOnSelect() || !_core->HasSelection()) - { - PasteTextFromClipboard(); - } - else - { - CopySelectionToClipboard(shiftEnabled, nullptr); - } - } - } - else if (ptr.PointerDeviceType() == Windows::Devices::Input::PointerDeviceType::Touch) - { - const auto contactRect = point.Properties().ContactRect(); - // Set our touch rect, to start a pan. - _touchAnchor = winrt::Windows::Foundation::Point{ contactRect.X, contactRect.Y }; - } + _interactivity->PointerPressed(point, + static_cast(args.KeyModifiers()), + _GetTerminalPosition(cursorPosition), + ptr.PointerDeviceType()); + // if (ptr.PointerDeviceType() == Windows::Devices::Input::PointerDeviceType::Mouse || ptr.PointerDeviceType() == Windows::Devices::Input::PointerDeviceType::Pen) + // { + // const auto modifiers = static_cast(args.KeyModifiers()); + // // static_cast to a uint32_t because we can't use the WI_IsFlagSet + // // macro directly with a VirtualKeyModifiers + // const auto altEnabled = WI_IsFlagSet(modifiers, static_cast(VirtualKeyModifiers::Menu)); + // const auto shiftEnabled = WI_IsFlagSet(modifiers, static_cast(VirtualKeyModifiers::Shift)); + // const auto ctrlEnabled = WI_IsFlagSet(modifiers, static_cast(VirtualKeyModifiers::Control)); + + // const auto cursorPosition = point.Position(); + // const auto terminalPosition = _GetTerminalPosition(cursorPosition); + + // // GH#9396: we prioritize hyper-link over VT mouse events + // // + // // !TODO! Before we'd lock the terminal before getting the hyperlink. Do we still need to? + // auto hyperlink = _core->GetHyperlink(terminalPosition); + // if (point.Properties().IsLeftButtonPressed() && + // ctrlEnabled && !hyperlink.empty()) + // { + // const auto clickCount = _interactivity->_NumberOfClicks(cursorPosition, point.Timestamp()); + // // Handle hyper-link only on the first click to prevent multiple activations + // if (clickCount == 1) + // { + // _HyperlinkHandler(hyperlink); + // } + // } + // else if (_CanSendVTMouseInput()) + // { + // _TrySendMouseEvent(point); + // } + // else if (point.Properties().IsLeftButtonPressed()) + // { + // const auto clickCount = _interactivity->_NumberOfClicks(cursorPosition, point.Timestamp()); + // // This formula enables the number of clicks to cycle properly + // // between single-, double-, and triple-click. To increase the + // // number of acceptable click states, simply increment + // // MAX_CLICK_COUNT and add another if-statement + // const unsigned int MAX_CLICK_COUNT = 3; + // const auto multiClickMapper = clickCount > MAX_CLICK_COUNT ? ((clickCount + MAX_CLICK_COUNT - 1) % MAX_CLICK_COUNT) + 1 : clickCount; + + // // Capture the position of the first click when no selection is active + // if (multiClickMapper == 1 && + // !_core->HasSelection()) + // { + // _singleClickTouchdownPos = cursorPosition; + // _lastMouseClickPosNoSelection = cursorPosition; + // } + // const bool isOnOriginalPosition = _lastMouseClickPosNoSelection == cursorPosition; + + // _core->LeftClickOnTerminal(terminalPosition, + // multiClickMapper, + // altEnabled, + // shiftEnabled, + // isOnOriginalPosition, + // _selectionNeedsToBeCopied); + // } + // else if (point.Properties().IsRightButtonPressed()) + // { + // // CopyOnSelect right click always pastes + // if (_settings.CopyOnSelect() || !_core->HasSelection()) + // { + // PasteTextFromClipboard(); + // } + // else + // { + // CopySelectionToClipboard(shiftEnabled, nullptr); + // } + // } + // } + // else if (ptr.PointerDeviceType() == Windows::Devices::Input::PointerDeviceType::Touch) + // { + // const auto contactRect = point.Properties().ContactRect(); + // // Set our touch rect, to start a pan. + // _touchAnchor = winrt::Windows::Foundation::Point{ contactRect.X, contactRect.Y }; + // } args.Handled(true); } @@ -1164,7 +1170,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation // Short-circuit isReadOnly check to avoid warning dialog if (_focused && !_core->IsInReadOnlyMode() && _CanSendVTMouseInput()) { - _TrySendMouseEvent(point); + _interactivity->_TrySendMouseEvent(point, terminalPosition); } else if (_focused && point.Properties().IsLeftButtonPressed()) { @@ -1271,7 +1277,9 @@ namespace winrt::Microsoft::Terminal::Control::implementation // Short-circuit isReadOnly check to avoid warning dialog if (!_core->IsInReadOnlyMode() && _CanSendVTMouseInput()) { - _TrySendMouseEvent(point); + const auto cursorPosition = point.Position(); + const auto terminalPosition = _GetTerminalPosition(cursorPosition); + _interactivity->_TrySendMouseEvent(point, terminalPosition); args.Handled(true); return; } @@ -2553,10 +2561,11 @@ namespace winrt::Microsoft::Terminal::Control::implementation // - Checks if the uri is valid and sends an event if so // Arguments: // - The uri - winrt::fire_and_forget TermControl::_HyperlinkHandler(const std::wstring_view uri) + winrt::fire_and_forget TermControl::_HyperlinkHandler(const IInspectable& /*sender*/, + const Control::OpenHyperlinkEventArgs& args) { // Save things we need to resume later. - winrt::hstring heldUri{ uri }; + Control::OpenHyperlinkEventArgs heldargs = args; auto strongThis{ get_strong() }; // Pop the rest of this function to the tail of the UI thread @@ -2565,8 +2574,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation // (like ShellExecute pumping our messaging thread...GH#7994) co_await Dispatcher(); - auto hyperlinkArgs = winrt::make_self(heldUri); - _OpenHyperlinkHandlers(*strongThis, *hyperlinkArgs); + _OpenHyperlinkHandlers(*strongThis, args); } // Method Description: diff --git a/src/cascadia/TerminalControl/TermControl.h b/src/cascadia/TerminalControl/TermControl.h index eca22032e64..9c52ba8cb67 100644 --- a/src/cascadia/TerminalControl/TermControl.h +++ b/src/cascadia/TerminalControl/TermControl.h @@ -199,7 +199,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation void _LostFocusHandler(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::RoutedEventArgs const& e); winrt::fire_and_forget _DragDropHandler(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::DragEventArgs const e); void _DragOverHandler(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::DragEventArgs const& e); - winrt::fire_and_forget _HyperlinkHandler(const std::wstring_view uri); + winrt::fire_and_forget _HyperlinkHandler(Windows::Foundation::IInspectable const& sender, Control::OpenHyperlinkEventArgs const& e); void _CursorTimerTick(Windows::Foundation::IInspectable const& sender, Windows::Foundation::IInspectable const& e); void _BlinkTimerTick(Windows::Foundation::IInspectable const& sender, Windows::Foundation::IInspectable const& e); @@ -230,7 +230,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation bool _TryHandleKeyBinding(const WORD vkey, const WORD scanCode, ::Microsoft::Terminal::Core::ControlKeyStates modifiers) const; void _ClearKeyboardState(const WORD vkey, const WORD scanCode) const noexcept; bool _TrySendKeyEvent(const WORD vkey, const WORD scanCode, ::Microsoft::Terminal::Core::ControlKeyStates modifiers, const bool keyDown); - bool _TrySendMouseEvent(Windows::UI::Input::PointerPoint const& point); + // bool _TrySendMouseEvent(Windows::UI::Input::PointerPoint const& point); bool _CanSendVTMouseInput(); const til::point _GetTerminalPosition(winrt::Windows::Foundation::Point cursorPosition); From 618b207f88aa74ef96e5435f461b0c17cb2648d5 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Mon, 29 Mar 2021 11:44:49 -0500 Subject: [PATCH 23/82] Move more mouse methods Now we're down to 12 errors. This is starting to feel like it's coming together. Mouse scrolling is scary though. --- .../TerminalControl/ControlInteractivity.cpp | 173 +++++++++++- .../TerminalControl/ControlInteractivity.h | 16 +- src/cascadia/TerminalControl/TermControl.cpp | 265 ++++++++++-------- src/cascadia/TerminalControl/TermControl.h | 2 +- 4 files changed, 337 insertions(+), 119 deletions(-) diff --git a/src/cascadia/TerminalControl/ControlInteractivity.cpp b/src/cascadia/TerminalControl/ControlInteractivity.cpp index 027506f6d1a..3d0efb38d49 100644 --- a/src/cascadia/TerminalControl/ControlInteractivity.cpp +++ b/src/cascadia/TerminalControl/ControlInteractivity.cpp @@ -94,9 +94,10 @@ namespace winrt::Microsoft::Terminal::Control::implementation } } - // TODO: Doint take a Windows::UI::Input::PointerPoint here + // TODO: Don't take a Windows::UI::Input::PointerPoint here. No WInUI here. void ControlInteractivity::PointerPressed(const winrt::Windows::UI::Input::PointerPoint point, - const uint32_t modifiers, + const ::Microsoft::Terminal::Core::ControlKeyStates modifiers, + const bool /*focused*/, const til::point terminalPosition, const winrt::Windows::Devices::Input::PointerDeviceType type) { @@ -106,9 +107,9 @@ namespace winrt::Microsoft::Terminal::Control::implementation // const auto modifiers = static_cast(args.KeyModifiers()); // static_cast to a uint32_t because we can't use the WI_IsFlagSet // macro directly with a VirtualKeyModifiers - const auto altEnabled = WI_IsFlagSet(modifiers, static_cast(VirtualKeyModifiers::Menu)); - const auto shiftEnabled = WI_IsFlagSet(modifiers, static_cast(VirtualKeyModifiers::Shift)); - const auto ctrlEnabled = WI_IsFlagSet(modifiers, static_cast(VirtualKeyModifiers::Control)); + const auto altEnabled = modifiers.IsAltPressed(); // WI_IsFlagSet(modifiers, static_cast(VirtualKeyModifiers::Menu)); + const auto shiftEnabled = modifiers.IsShiftPressed(); // WI_IsFlagSet(modifiers, static_cast(VirtualKeyModifiers::Shift)); + const auto ctrlEnabled = modifiers.IsCtrlPressed(); // WI_IsFlagSet(modifiers, static_cast(VirtualKeyModifiers::Control)); const auto cursorPosition = point.Position(); // const auto terminalPosition = _GetTerminalPosition(cursorPosition); @@ -127,7 +128,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation _HyperlinkHandler(hyperlink); } } - else if (_CanSendVTMouseInput()) + else if (_CanSendVTMouseInput(modifiers, terminalPosition)) { _TrySendMouseEvent(point); } @@ -146,6 +147,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation !_core->HasSelection()) { _singleClickTouchdownPos = cursorPosition; + _singleClickTouchdownTerminalPos = terminalPosition; _lastMouseClickPosNoSelection = cursorPosition; } const bool isOnOriginalPosition = _lastMouseClickPosNoSelection == cursorPosition; @@ -178,6 +180,144 @@ namespace winrt::Microsoft::Terminal::Control::implementation } } + // TODO: Doint take a Windows::UI::Input::PointerPoint here + void ControlInteractivity::PointerMoved(const winrt::Windows::UI::Input::PointerPoint point, + const ::Microsoft::Terminal::Core::ControlKeyStates modifiers, + const bool focused, + const til::point terminalPosition, + const winrt::Windows::Devices::Input::PointerDeviceType type) + { + const auto cursorPosition = point.Position(); + if (type == Windows::Devices::Input::PointerDeviceType::Mouse || + type == Windows::Devices::Input::PointerDeviceType::Pen) + { + // Short-circuit isReadOnly check to avoid warning dialog + if (focused && !_core->IsInReadOnlyMode() && _CanSendVTMouseInput(modifiers)) + { + _TrySendMouseEvent(point, terminalPosition); + } + else if (focused && point.Properties().IsLeftButtonPressed()) + { + if (_singleClickTouchdownPos) + { + // Figure out if the user's moved a quarter of a cell's smaller axis away from the clickdown point + auto& touchdownPoint{ *_singleClickTouchdownPos }; + auto distance{ std::sqrtf(std::powf(cursorPosition.X - touchdownPoint.X, 2) + + std::powf(cursorPosition.Y - touchdownPoint.Y, 2)) }; + const til::size fontSize{ _core->GetFont().GetSize() }; + + const auto fontSizeInDips = fontSize.scale(til::math::rounding, 1.0f / _core->RendererScale()); + if (distance >= (std::min(fontSizeInDips.width(), fontSizeInDips.height()) / 4.f)) + { + // _core->SetSelectionAnchor(_GetTerminalPosition(touchdownPoint)); + _core->SetSelectionAnchor(terminalPosition); + // stop tracking the touchdown point + _singleClickTouchdownPos = std::nullopt; + _singleClickTouchdownTerminalPos = std::nullopt; + } + } + + _SetEndSelectionPoint(terminalPosition); + + // const double cursorBelowBottomDist = cursorPosition.Y - SwapChainPanel().Margin().Top - SwapChainPanel().ActualHeight(); + // const double cursorAboveTopDist = -1 * cursorPosition.Y + SwapChainPanel().Margin().Top; + + // constexpr double MinAutoScrollDist = 2.0; // Arbitrary value + // double newAutoScrollVelocity = 0.0; + // if (cursorBelowBottomDist > MinAutoScrollDist) + // { + // newAutoScrollVelocity = _GetAutoScrollSpeed(cursorBelowBottomDist); + // } + // else if (cursorAboveTopDist > MinAutoScrollDist) + // { + // newAutoScrollVelocity = -1.0 * _GetAutoScrollSpeed(cursorAboveTopDist); + // } + + // if (newAutoScrollVelocity != 0) + // { + // _TryStartAutoScroll(point, newAutoScrollVelocity); + // } + // else + // { + // _TryStopAutoScroll(ptr.PointerId()); + // } + } + + _core->UpdateHoveredCell(terminalPosition); + } + else if (focused && + type == Windows::Devices::Input::PointerDeviceType::Touch && + _touchAnchor) + { + const auto contactRect = point.Properties().ContactRect(); + winrt::Windows::Foundation::Point newTouchPoint{ contactRect.X, contactRect.Y }; + const auto anchor = _touchAnchor.value(); + + // Our actualFont's size is in pixels, convert to DIPs, which the + // rest of the Points here are in. + const til::size fontSize{ _core->GetFont().GetSize() }; + const auto fontSizeInDips = fontSize.scale(til::math::rounding, 1.0f / _core->RendererScale()); + + // Get the difference between the point we've dragged to and the start of the touch. + const float dy = newTouchPoint.Y - anchor.Y; + + // Start viewport scroll after we've moved more than a half row of text + if (std::abs(dy) > (fontSizeInDips.height() / 2.0f)) + { + // Multiply by -1, because moving the touch point down will + // create a positive delta, but we want the viewport to move up, + // so we'll need a negative scroll amount (and the inverse for + // panning down) + const float numRows = -1.0f * (dy / fontSizeInDips.height()); + + // const auto currentOffset = ::base::ClampedNumeric(ScrollBar().Value()); + const auto currentOffset = ::base::ClampedNumeric(_core->ScrollOffset()); + const auto newValue = numRows + currentOffset; + + _core->UserScrollViewport(newValue); + // ScrollBar().Value(newValue); + + // Use this point as our new scroll anchor. + _touchAnchor = newTouchPoint; + } + } + } + + void ControlInteractivity::PointerReleased(const winrt::Windows::UI::Input::PointerPoint point, + const ::Microsoft::Terminal::Core::ControlKeyStates modifiers, + const bool /*focused*/, + const til::point terminalPosition, + const winrt::Windows::Devices::Input::PointerDeviceType type) + { + if (type == Windows::Devices::Input::PointerDeviceType::Mouse || + type == Windows::Devices::Input::PointerDeviceType::Pen) + { + // Short-circuit isReadOnly check to avoid warning dialog + if (!_core->IsInReadOnlyMode() && _CanSendVTMouseInput(modifiers)) + { + _TrySendMouseEvent(point, terminalPosition); + // args.Handled(true); + return; + } + + // Only a left click release when copy on select is active should perform a copy. + // Right clicks and middle clicks should not need to do anything when released. + if (_core->CopyOnSelect() && + point.Properties().PointerUpdateKind() == Windows::UI::Input::PointerUpdateKind::LeftButtonReleased && + _selectionNeedsToBeCopied) + { + CopySelectionToClipboard(false, nullptr); + } + } + else if (type == Windows::Devices::Input::PointerDeviceType::Touch) + { + _touchAnchor = std::nullopt; + } + + _singleClickTouchdownPos = std::nullopt; + _singleClickTouchdownTerminalPos = std::nullopt; + } + // Method Description: // - Send this particular mouse event to the terminal. // See Terminal::SendMouseEvent for more information. @@ -240,4 +380,25 @@ namespace winrt::Microsoft::Terminal::Control::implementation _OpenHyperlinkHandlers(*this, *hyperlinkArgs); } + bool ControlInteractivity::_CanSendVTMouseInput(const ::Microsoft::Terminal::Core::ControlKeyStates modifiers) + { + // If the user is holding down Shift, suppress mouse events + // TODO GH#4875: disable/customize this functionality + // const auto modifiers = _GetPressedModifierKeys(); + if (modifiers.IsShiftPressed()) + { + return false; + } + return _core->IsVtMouseModeEnabled(); + } + + // Method Description: + // - Sets selection's end position to match supplied cursor position, e.g. while mouse dragging. + // Arguments: + // - cursorPosition: in pixels, relative to the origin of the control + void ControlInteractivity::_SetEndSelectionPoint(const til::point terminalPosition) + { + _core->SetEndSelectionPoint(terminalPosition); + _selectionNeedsToBeCopied = true; + } } diff --git a/src/cascadia/TerminalControl/ControlInteractivity.h b/src/cascadia/TerminalControl/ControlInteractivity.h index 197bff00c2b..fe1246bb9d1 100644 --- a/src/cascadia/TerminalControl/ControlInteractivity.h +++ b/src/cascadia/TerminalControl/ControlInteractivity.h @@ -26,9 +26,20 @@ namespace winrt::Microsoft::Terminal::Control::implementation void UpdateSettings(); void Initialize(); void PointerPressed(const winrt::Windows::UI::Input::PointerPoint point, - const uint32_t modifiers, + const ::Microsoft::Terminal::Core::ControlKeyStates modifiers, + const bool focused, const til::point terminalPosition, const winrt::Windows::Devices::Input::PointerDeviceType type); + void PointerMoved(const winrt::Windows::UI::Input::PointerPoint point, + const ::Microsoft::Terminal::Core::ControlKeyStates modifiers, + const bool focused, + const til::point terminalPosition, + const winrt::Windows::Devices::Input::PointerDeviceType type); + void PointerReleased(const winrt::Windows::UI::Input::PointerPoint point, + const ::Microsoft::Terminal::Core::ControlKeyStates modifiers, + const bool focused, + const til::point terminalPosition, + const winrt::Windows::Devices::Input::PointerDeviceType type); /////////////////////// From Control winrt::com_ptr _core{ nullptr }; @@ -47,6 +58,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation Timestamp _lastMouseClickTimestamp; std::optional _lastMouseClickPos; std::optional _singleClickTouchdownPos; + std::optional _singleClickTouchdownTerminalPos; std::optional _lastMouseClickPosNoSelection; // This field tracks whether the selection has changed meaningfully // since it was last copied. It's generally used to prevent copyOnSelect @@ -68,6 +80,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation bool _TrySendMouseEvent(Windows::UI::Input::PointerPoint const& point, const til::point terminalPosition); void _HyperlinkHandler(const std::wstring_view uri); + bool _CanSendVTMouseInput(const ::Microsoft::Terminal::Core::ControlKeyStates modifiers); + void _SetEndSelectionPoint(const til::point terminalPosition); TYPED_EVENT(OpenHyperlink, IInspectable, Control::OpenHyperlinkEventArgs); }; diff --git a/src/cascadia/TerminalControl/TermControl.cpp b/src/cascadia/TerminalControl/TermControl.cpp index fb80cfdf14a..7383407c39a 100644 --- a/src/cascadia/TerminalControl/TermControl.cpp +++ b/src/cascadia/TerminalControl/TermControl.cpp @@ -1009,21 +1009,21 @@ namespace winrt::Microsoft::Terminal::Control::implementation // return _core->SendMouseEvent(terminalPosition, uiButton, modifiers, sWheelDelta, state); // } - // Method Description: - // - Checks if we can send vt mouse input. - // Arguments: - // - point: the PointerPoint object representing a mouse event from our XAML input handler - bool TermControl::_CanSendVTMouseInput() - { - // If the user is holding down Shift, suppress mouse events - // TODO GH#4875: disable/customize this functionality - const auto modifiers = _GetPressedModifierKeys(); - if (modifiers.IsShiftPressed()) - { - return false; - } - return _core->IsVtMouseModeEnabled(); - } + // // Method Description: + // // - Checks if we can send vt mouse input. + // // Arguments: + // // - point: the PointerPoint object representing a mouse event from our XAML input handler + // bool TermControl::_CanSendVTMouseInput() + // { + // // If the user is holding down Shift, suppress mouse events + // // TODO GH#4875: disable/customize this functionality + // const auto modifiers = _GetPressedModifierKeys(); + // if (modifiers.IsShiftPressed()) + // { + // return false; + // } + // return _core->IsVtMouseModeEnabled(); + // } // Method Description: // - handle a mouse click event. Begin selection process. @@ -1058,7 +1058,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation const auto cursorPosition = point.Position(); _interactivity->PointerPressed(point, - static_cast(args.KeyModifiers()), + ControlKeyStates(args.KeyModifiers()), + _focused, _GetTerminalPosition(cursorPosition), ptr.PointerDeviceType()); // if (ptr.PointerDeviceType() == Windows::Devices::Input::PointerDeviceType::Mouse || ptr.PointerDeviceType() == Windows::Devices::Input::PointerDeviceType::Pen) @@ -1159,97 +1160,129 @@ namespace winrt::Microsoft::Terminal::Control::implementation const auto point = args.GetCurrentPoint(*this); const auto cursorPosition = point.Position(); const auto terminalPosition = _GetTerminalPosition(cursorPosition); + const auto type = ptr.PointerDeviceType(); if (!_focused && _settings.FocusFollowMouse()) { _FocusFollowMouseRequestedHandlers(*this, nullptr); } - if (ptr.PointerDeviceType() == Windows::Devices::Input::PointerDeviceType::Mouse || ptr.PointerDeviceType() == Windows::Devices::Input::PointerDeviceType::Pen) + _interactivity->PointerMoved(point, + ControlKeyStates(args.KeyModifiers()), + _focused, + terminalPosition, + type); + + if (_focused && point.Properties().IsLeftButtonPressed()) { - // Short-circuit isReadOnly check to avoid warning dialog - if (_focused && !_core->IsInReadOnlyMode() && _CanSendVTMouseInput()) + const double cursorBelowBottomDist = cursorPosition.Y - SwapChainPanel().Margin().Top - SwapChainPanel().ActualHeight(); + const double cursorAboveTopDist = -1 * cursorPosition.Y + SwapChainPanel().Margin().Top; + + constexpr double MinAutoScrollDist = 2.0; // Arbitrary value + double newAutoScrollVelocity = 0.0; + if (cursorBelowBottomDist > MinAutoScrollDist) { - _interactivity->_TrySendMouseEvent(point, terminalPosition); + newAutoScrollVelocity = _GetAutoScrollSpeed(cursorBelowBottomDist); } - else if (_focused && point.Properties().IsLeftButtonPressed()) + else if (cursorAboveTopDist > MinAutoScrollDist) { - if (_singleClickTouchdownPos) - { - // Figure out if the user's moved a quarter of a cell's smaller axis away from the clickdown point - auto& touchdownPoint{ *_singleClickTouchdownPos }; - auto distance{ std::sqrtf(std::powf(cursorPosition.X - touchdownPoint.X, 2) + std::powf(cursorPosition.Y - touchdownPoint.Y, 2)) }; - const til::size fontSize{ _core->GetFont().GetSize() }; + newAutoScrollVelocity = -1.0 * _GetAutoScrollSpeed(cursorAboveTopDist); + } - const auto fontSizeInDips = fontSize.scale(til::math::rounding, 1.0f / _core->RendererScale()); - if (distance >= (std::min(fontSizeInDips.width(), fontSizeInDips.height()) / 4.f)) - { - _core->SetSelectionAnchor(_GetTerminalPosition(touchdownPoint)); - // stop tracking the touchdown point - _singleClickTouchdownPos = std::nullopt; - } - } + if (newAutoScrollVelocity != 0) + { + _TryStartAutoScroll(point, newAutoScrollVelocity); + } + else + { + _TryStopAutoScroll(ptr.PointerId()); + } + } + // if (ptr.PointerDeviceType() == Windows::Devices::Input::PointerDeviceType::Mouse || ptr.PointerDeviceType() == Windows::Devices::Input::PointerDeviceType::Pen) + // { + // // Short-circuit isReadOnly check to avoid warning dialog + // if (_focused && !_core->IsInReadOnlyMode() && _CanSendVTMouseInput()) + // { + // _interactivity->_TrySendMouseEvent(point, terminalPosition); + // } + // else if (_focused && point.Properties().IsLeftButtonPressed()) + // { + // if (_singleClickTouchdownPos) + // { + // // Figure out if the user's moved a quarter of a cell's smaller axis away from the clickdown point + // auto& touchdownPoint{ *_singleClickTouchdownPos }; + // auto distance{ std::sqrtf(std::powf(cursorPosition.X - touchdownPoint.X, 2) + std::powf(cursorPosition.Y - touchdownPoint.Y, 2)) }; + // const til::size fontSize{ _core->GetFont().GetSize() }; + + // const auto fontSizeInDips = fontSize.scale(til::math::rounding, 1.0f / _core->RendererScale()); + // if (distance >= (std::min(fontSizeInDips.width(), fontSizeInDips.height()) / 4.f)) + // { + // _core->SetSelectionAnchor(_GetTerminalPosition(touchdownPoint)); + // // stop tracking the touchdown point + // _singleClickTouchdownPos = std::nullopt; + // } + // } - _SetEndSelectionPointAtCursor(cursorPosition); + // _SetEndSelectionPointAtCursor(cursorPosition); - const double cursorBelowBottomDist = cursorPosition.Y - SwapChainPanel().Margin().Top - SwapChainPanel().ActualHeight(); - const double cursorAboveTopDist = -1 * cursorPosition.Y + SwapChainPanel().Margin().Top; + // const double cursorBelowBottomDist = cursorPosition.Y - SwapChainPanel().Margin().Top - SwapChainPanel().ActualHeight(); + // const double cursorAboveTopDist = -1 * cursorPosition.Y + SwapChainPanel().Margin().Top; - constexpr double MinAutoScrollDist = 2.0; // Arbitrary value - double newAutoScrollVelocity = 0.0; - if (cursorBelowBottomDist > MinAutoScrollDist) - { - newAutoScrollVelocity = _GetAutoScrollSpeed(cursorBelowBottomDist); - } - else if (cursorAboveTopDist > MinAutoScrollDist) - { - newAutoScrollVelocity = -1.0 * _GetAutoScrollSpeed(cursorAboveTopDist); - } + // constexpr double MinAutoScrollDist = 2.0; // Arbitrary value + // double newAutoScrollVelocity = 0.0; + // if (cursorBelowBottomDist > MinAutoScrollDist) + // { + // newAutoScrollVelocity = _GetAutoScrollSpeed(cursorBelowBottomDist); + // } + // else if (cursorAboveTopDist > MinAutoScrollDist) + // { + // newAutoScrollVelocity = -1.0 * _GetAutoScrollSpeed(cursorAboveTopDist); + // } - if (newAutoScrollVelocity != 0) - { - _TryStartAutoScroll(point, newAutoScrollVelocity); - } - else - { - _TryStopAutoScroll(ptr.PointerId()); - } - } + // if (newAutoScrollVelocity != 0) + // { + // _TryStartAutoScroll(point, newAutoScrollVelocity); + // } + // else + // { + // _TryStopAutoScroll(ptr.PointerId()); + // } + // } - _core->UpdateHoveredCell(terminalPosition); - } - else if (_focused && ptr.PointerDeviceType() == Windows::Devices::Input::PointerDeviceType::Touch && _touchAnchor) - { - const auto contactRect = point.Properties().ContactRect(); - winrt::Windows::Foundation::Point newTouchPoint{ contactRect.X, contactRect.Y }; - const auto anchor = _touchAnchor.value(); + // _core->UpdateHoveredCell(terminalPosition); + // } + // else if (_focused && ptr.PointerDeviceType() == Windows::Devices::Input::PointerDeviceType::Touch && _touchAnchor) + // { + // const auto contactRect = point.Properties().ContactRect(); + // winrt::Windows::Foundation::Point newTouchPoint{ contactRect.X, contactRect.Y }; + // const auto anchor = _touchAnchor.value(); - // Our actualFont's size is in pixels, convert to DIPs, which the - // rest of the Points here are in. - const til::size fontSize{ _core->GetFont().GetSize() }; - const auto fontSizeInDips = fontSize.scale(til::math::rounding, 1.0f / _core->RendererScale()); + // // Our actualFont's size is in pixels, convert to DIPs, which the + // // rest of the Points here are in. + // const til::size fontSize{ _core->GetFont().GetSize() }; + // const auto fontSizeInDips = fontSize.scale(til::math::rounding, 1.0f / _core->RendererScale()); - // Get the difference between the point we've dragged to and the start of the touch. - const float dy = newTouchPoint.Y - anchor.Y; + // // Get the difference between the point we've dragged to and the start of the touch. + // const float dy = newTouchPoint.Y - anchor.Y; - // Start viewport scroll after we've moved more than a half row of text - if (std::abs(dy) > (fontSizeInDips.height() / 2.0f)) - { - // Multiply by -1, because moving the touch point down will - // create a positive delta, but we want the viewport to move up, - // so we'll need a negative scroll amount (and the inverse for - // panning down) - const float numRows = -1.0f * (dy / fontSizeInDips.height()); + // // Start viewport scroll after we've moved more than a half row of text + // if (std::abs(dy) > (fontSizeInDips.height() / 2.0f)) + // { + // // Multiply by -1, because moving the touch point down will + // // create a positive delta, but we want the viewport to move up, + // // so we'll need a negative scroll amount (and the inverse for + // // panning down) + // const float numRows = -1.0f * (dy / fontSizeInDips.height()); - const auto currentOffset = ::base::ClampedNumeric(ScrollBar().Value()); - const auto newValue = numRows + currentOffset; + // const auto currentOffset = ::base::ClampedNumeric(ScrollBar().Value()); + // const auto newValue = numRows + currentOffset; - ScrollBar().Value(newValue); + // ScrollBar().Value(newValue); - // Use this point as our new scroll anchor. - _touchAnchor = newTouchPoint; - } - } + // // Use this point as our new scroll anchor. + // _touchAnchor = newTouchPoint; + // } + // } args.Handled(true); } @@ -1269,34 +1302,42 @@ namespace winrt::Microsoft::Terminal::Control::implementation const auto ptr = args.Pointer(); const auto point = args.GetCurrentPoint(*this); + const auto cursorPosition = point.Position(); + const auto terminalPosition = _GetTerminalPosition(cursorPosition); + const auto type = ptr.PointerDeviceType(); _ReleasePointerCapture(sender, args); + _interactivity->PointerReleased(point, + ControlKeyStates(args.KeyModifiers()), + _focused, + terminalPosition, + type); - if (ptr.PointerDeviceType() == Windows::Devices::Input::PointerDeviceType::Mouse || ptr.PointerDeviceType() == Windows::Devices::Input::PointerDeviceType::Pen) - { - // Short-circuit isReadOnly check to avoid warning dialog - if (!_core->IsInReadOnlyMode() && _CanSendVTMouseInput()) - { - const auto cursorPosition = point.Position(); - const auto terminalPosition = _GetTerminalPosition(cursorPosition); - _interactivity->_TrySendMouseEvent(point, terminalPosition); - args.Handled(true); - return; - } + // if (ptr.PointerDeviceType() == Windows::Devices::Input::PointerDeviceType::Mouse || ptr.PointerDeviceType() == Windows::Devices::Input::PointerDeviceType::Pen) + // { + // // Short-circuit isReadOnly check to avoid warning dialog + // if (!_core->IsInReadOnlyMode() && _CanSendVTMouseInput()) + // { + // const auto cursorPosition = point.Position(); + // const auto terminalPosition = _GetTerminalPosition(cursorPosition); + // _interactivity->_TrySendMouseEvent(point, terminalPosition); + // args.Handled(true); + // return; + // } - // Only a left click release when copy on select is active should perform a copy. - // Right clicks and middle clicks should not need to do anything when released. - if (_settings.CopyOnSelect() && point.Properties().PointerUpdateKind() == Windows::UI::Input::PointerUpdateKind::LeftButtonReleased && _selectionNeedsToBeCopied) - { - CopySelectionToClipboard(false, nullptr); - } - } - else if (ptr.PointerDeviceType() == Windows::Devices::Input::PointerDeviceType::Touch) - { - _touchAnchor = std::nullopt; - } + // // Only a left click release when copy on select is active should perform a copy. + // // Right clicks and middle clicks should not need to do anything when released. + // if (_settings.CopyOnSelect() && point.Properties().PointerUpdateKind() == Windows::UI::Input::PointerUpdateKind::LeftButtonReleased && _selectionNeedsToBeCopied) + // { + // CopySelectionToClipboard(false, nullptr); + // } + // } + // else if (ptr.PointerDeviceType() == Windows::Devices::Input::PointerDeviceType::Touch) + // { + // _touchAnchor = std::nullopt; + // } - _singleClickTouchdownPos = std::nullopt; + // _singleClickTouchdownPos = std::nullopt; _TryStopAutoScroll(ptr.PointerId()); @@ -1354,7 +1395,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation const TerminalInput::MouseButtonState state) { // Short-circuit isReadOnly check to avoid warning dialog - if (!_core->IsInReadOnlyMode() && _CanSendVTMouseInput()) + if (!_core->IsInReadOnlyMode() && _interactivity->_CanSendVTMouseInput(modifiers)) { // Most mouse event handlers call // _TrySendMouseEvent(point); @@ -1586,7 +1627,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation void TermControl::_TryStartAutoScroll(Windows::UI::Input::PointerPoint const& pointerPoint, const double scrollVelocity) { // Allow only one pointer at the time - if (!_autoScrollingPointerPoint.has_value() || _autoScrollingPointerPoint.value().PointerId() == pointerPoint.PointerId()) + if (!_autoScrollingPointerPoint.has_value() || + _autoScrollingPointerPoint.value().PointerId() == pointerPoint.PointerId()) { _autoScrollingPointerPoint = pointerPoint; _autoScrollVelocity = scrollVelocity; @@ -1612,7 +1654,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation // - pointerId: id of pointer for which to stop auto scroll void TermControl::_TryStopAutoScroll(const uint32_t pointerId) { - if (_autoScrollingPointerPoint.has_value() && pointerId == _autoScrollingPointerPoint.value().PointerId()) + if (_autoScrollingPointerPoint.has_value() && + pointerId == _autoScrollingPointerPoint.value().PointerId()) { _autoScrollingPointerPoint = std::nullopt; _autoScrollVelocity = 0; diff --git a/src/cascadia/TerminalControl/TermControl.h b/src/cascadia/TerminalControl/TermControl.h index 9c52ba8cb67..88d3adfe5e1 100644 --- a/src/cascadia/TerminalControl/TermControl.h +++ b/src/cascadia/TerminalControl/TermControl.h @@ -231,7 +231,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation void _ClearKeyboardState(const WORD vkey, const WORD scanCode) const noexcept; bool _TrySendKeyEvent(const WORD vkey, const WORD scanCode, ::Microsoft::Terminal::Core::ControlKeyStates modifiers, const bool keyDown); // bool _TrySendMouseEvent(Windows::UI::Input::PointerPoint const& point); - bool _CanSendVTMouseInput(); + // bool _CanSendVTMouseInput(); const til::point _GetTerminalPosition(winrt::Windows::Foundation::Point cursorPosition); // const unsigned int _NumberOfClicks(winrt::Windows::Foundation::Point clickPos, Timestamp clickTime); From e85bdff8be07e1d54e62ea620f40d0053deeead3 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Mon, 29 Mar 2021 12:39:11 -0500 Subject: [PATCH 24/82] Move around the clipboard handling methods And a bit of cleanup of things left behind by the previous commits. Down to 5 errors! --- .../TerminalControl/ControlInteractivity.cpp | 66 +++++++++++++++++-- .../TerminalControl/ControlInteractivity.h | 7 +- src/cascadia/TerminalControl/TermControl.cpp | 53 ++++++--------- src/cascadia/TerminalControl/TermControl.h | 4 +- 4 files changed, 89 insertions(+), 41 deletions(-) diff --git a/src/cascadia/TerminalControl/ControlInteractivity.cpp b/src/cascadia/TerminalControl/ControlInteractivity.cpp index 3d0efb38d49..1e1d2f260be 100644 --- a/src/cascadia/TerminalControl/ControlInteractivity.cpp +++ b/src/cascadia/TerminalControl/ControlInteractivity.cpp @@ -94,6 +94,55 @@ namespace winrt::Microsoft::Terminal::Control::implementation } } + // // Method Description: + // // - Given a copy-able selection, get the selected text from the buffer and send it to the + // // Windows Clipboard (CascadiaWin32:main.cpp). + // // - CopyOnSelect does NOT clear the selection + // // Arguments: + // // - singleLine: collapse all of the text to one line + // // - formats: which formats to copy (defined by action's CopyFormatting arg). nullptr + // // if we should defer which formats are copied to the global setting + bool ControlInteractivity::CopySelectionToClipboard(bool singleLine, + const Windows::Foundation::IReference& formats) + { + if (_core) + { + // Note to future self: This should return false if there's no + // selection to copy. If there's no selection, returning false will + // indicate that the actions that trigered this should _not_ be + // marked as handled, so ctrl+c without a selection can still send + // ^C + + // Mark the current selection as copied + _selectionNeedsToBeCopied = false; + + return _core->CopySelectionToClipboard(singleLine, formats); + } + + return false; + } + + // Method Description: + // - Initiate a paste operation. + void ControlInteractivity::PasteTextFromClipboard() + { + // attach TermControl::_SendInputToConnection() as the clipboardDataHandler. + // This is called when the clipboard data is loaded. + auto clipboardDataHandler = std::bind(&ControlInteractivity::_SendPastedTextToConnection, this, std::placeholders::_1); + auto pasteArgs = winrt::make_self(clipboardDataHandler); + + // send paste event up to TermApp + _PasteFromClipboardHandlers(*this, *pasteArgs); + } + + // Method Description: + // - Pre-process text pasted (presumably from the clipboard) + // before sending it over the terminal's connection. + void ControlInteractivity::_SendPastedTextToConnection(const std::wstring& wstr) + { + _core->PasteText(winrt::hstring{ wstr }); + } + // TODO: Don't take a Windows::UI::Input::PointerPoint here. No WInUI here. void ControlInteractivity::PointerPressed(const winrt::Windows::UI::Input::PointerPoint point, const ::Microsoft::Terminal::Core::ControlKeyStates modifiers, @@ -128,9 +177,9 @@ namespace winrt::Microsoft::Terminal::Control::implementation _HyperlinkHandler(hyperlink); } } - else if (_CanSendVTMouseInput(modifiers, terminalPosition)) + else if (_CanSendVTMouseInput(modifiers)) { - _TrySendMouseEvent(point); + _TrySendMouseEvent(point, modifiers, terminalPosition); } else if (point.Properties().IsLeftButtonPressed()) { @@ -194,7 +243,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation // Short-circuit isReadOnly check to avoid warning dialog if (focused && !_core->IsInReadOnlyMode() && _CanSendVTMouseInput(modifiers)) { - _TrySendMouseEvent(point, terminalPosition); + _TrySendMouseEvent(point, modifiers, terminalPosition); } else if (focused && point.Properties().IsLeftButtonPressed()) { @@ -274,6 +323,12 @@ namespace winrt::Microsoft::Terminal::Control::implementation const auto currentOffset = ::base::ClampedNumeric(_core->ScrollOffset()); const auto newValue = numRows + currentOffset; + // !TODO! - Very worried about using UserScrollViewport as + // opposed to the ScrollBar().Value() setter. Originally setting + // the scrollbar value would raise a event handled in + // _ScrollbarChangeHandler, which would _then_ scroll the core, + // and start the _updateScrollBar ThrottledFunc to update the + // scroll position. I'm worried that won't work like this. _core->UserScrollViewport(newValue); // ScrollBar().Value(newValue); @@ -295,7 +350,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation // Short-circuit isReadOnly check to avoid warning dialog if (!_core->IsInReadOnlyMode() && _CanSendVTMouseInput(modifiers)) { - _TrySendMouseEvent(point, terminalPosition); + _TrySendMouseEvent(point, modifiers, terminalPosition); // args.Handled(true); return; } @@ -324,6 +379,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation // Arguments: // - point: the PointerPoint object representing a mouse event from our XAML input handler bool ControlInteractivity::_TrySendMouseEvent(Windows::UI::Input::PointerPoint const& point, + const ::Microsoft::Terminal::Core::ControlKeyStates modifiers, const til::point terminalPosition) { const auto props = point.Properties(); @@ -365,7 +421,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation uiButton = WM_MOUSEWHEEL; } - const auto modifiers = _GetPressedModifierKeys(); + // const auto modifiers = _GetPressedModifierKeys(); const TerminalInput::MouseButtonState state{ props.IsLeftButtonPressed(), props.IsMiddleButtonPressed(), props.IsRightButtonPressed() }; diff --git a/src/cascadia/TerminalControl/ControlInteractivity.h b/src/cascadia/TerminalControl/ControlInteractivity.h index fe1246bb9d1..1cb424ed295 100644 --- a/src/cascadia/TerminalControl/ControlInteractivity.h +++ b/src/cascadia/TerminalControl/ControlInteractivity.h @@ -40,7 +40,9 @@ namespace winrt::Microsoft::Terminal::Control::implementation const bool focused, const til::point terminalPosition, const winrt::Windows::Devices::Input::PointerDeviceType type); - + bool CopySelectionToClipboard(bool singleLine, + const Windows::Foundation::IReference& formats); + void PasteTextFromClipboard(); /////////////////////// From Control winrt::com_ptr _core{ nullptr }; unsigned int _rowsToScroll; // Definitely Control/Interactivity @@ -78,12 +80,15 @@ namespace winrt::Microsoft::Terminal::Control::implementation unsigned int _NumberOfClicks(winrt::Windows::Foundation::Point clickPos, Timestamp clickTime); void _UpdateSystemParameterSettings() noexcept; bool _TrySendMouseEvent(Windows::UI::Input::PointerPoint const& point, + const ::Microsoft::Terminal::Core::ControlKeyStates modifiers, const til::point terminalPosition); void _HyperlinkHandler(const std::wstring_view uri); bool _CanSendVTMouseInput(const ::Microsoft::Terminal::Core::ControlKeyStates modifiers); void _SetEndSelectionPoint(const til::point terminalPosition); + void _SendPastedTextToConnection(const std::wstring& wstr); TYPED_EVENT(OpenHyperlink, IInspectable, Control::OpenHyperlinkEventArgs); + TYPED_EVENT(PasteFromClipboard, IInspectable, Control::PasteFromClipboardEventArgs); }; } diff --git a/src/cascadia/TerminalControl/TermControl.cpp b/src/cascadia/TerminalControl/TermControl.cpp index 7383407c39a..f99ba843dbc 100644 --- a/src/cascadia/TerminalControl/TermControl.cpp +++ b/src/cascadia/TerminalControl/TermControl.cpp @@ -1800,13 +1800,13 @@ namespace winrt::Microsoft::Terminal::Control::implementation } } - // Method Description: - // - Pre-process text pasted (presumably from the clipboard) - // before sending it over the terminal's connection. - void TermControl::_SendPastedTextToConnection(const std::wstring& wstr) - { - _core->PasteText(winrt::hstring{ wstr }); - } + // // Method Description: + // // - Pre-process text pasted (presumably from the clipboard) + // // before sending it over the terminal's connection. + // void TermControl::_SendPastedTextToConnection(const std::wstring& wstr) + // { + // _core->PasteText(winrt::hstring{ wstr }); + // } // Method Description: // - Triggered when the swapchain changes size. We use this to resize the @@ -1971,34 +1971,21 @@ namespace winrt::Microsoft::Terminal::Control::implementation return false; } - if (_core) - { - // Note to future self: This should return false if there's no - // selection to copy. If there's no selection, returning false will - // indicate that the actions that trigered this should _not_ be - // marked as handled, so ctrl+c without a selection can still send - // ^C - - // Mark the current selection as copied - _selectionNeedsToBeCopied = false; - - return _core->CopySelectionToClipboard(singleLine, formats); - } - - return false; + return _interactivity->CopySelectionToClipboard(singleLine, formats); } // Method Description: // - Initiate a paste operation. void TermControl::PasteTextFromClipboard() { - // attach TermControl::_SendInputToConnection() as the clipboardDataHandler. - // This is called when the clipboard data is loaded. - auto clipboardDataHandler = std::bind(&TermControl::_SendPastedTextToConnection, this, std::placeholders::_1); - auto pasteArgs = winrt::make_self(clipboardDataHandler); + // // attach TermControl::_SendInputToConnection() as the clipboardDataHandler. + // // This is called when the clipboard data is loaded. + // auto clipboardDataHandler = std::bind(&TermControl::_SendPastedTextToConnection, this, std::placeholders::_1); + // auto pasteArgs = winrt::make_self(clipboardDataHandler); - // send paste event up to TermApp - _PasteFromClipboardHandlers(*this, *pasteArgs); + // // send paste event up to TermApp + // _PasteFromClipboardHandlers(*this, *pasteArgs); + _interactivity->PasteTextFromClipboard(); } void TermControl::Close() @@ -2488,7 +2475,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation try { Windows::Foundation::Uri link{ co_await e.DataView().GetApplicationLinkAsync() }; - _SendPastedTextToConnection(std::wstring{ link.AbsoluteUri() }); + _core->PasteText(link.AbsoluteUri()); } CATCH_LOG(); } @@ -2497,7 +2484,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation try { Windows::Foundation::Uri link{ co_await e.DataView().GetWebLinkAsync() }; - _SendPastedTextToConnection(std::wstring{ link.AbsoluteUri() }); + _core->PasteText(link.AbsoluteUri()); } CATCH_LOG(); } @@ -2505,8 +2492,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation { try { - std::wstring text{ co_await e.DataView().GetTextAsync() }; - _SendPastedTextToConnection(text); + auto text{ co_await e.DataView().GetTextAsync() }; + _core->PasteText(text); } CATCH_LOG(); } @@ -2547,7 +2534,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation allPaths += fullPath; } - _SendPastedTextToConnection(allPaths); + _core->PasteText(winrt::hstring{ allPaths }); } } } diff --git a/src/cascadia/TerminalControl/TermControl.h b/src/cascadia/TerminalControl/TermControl.h index 88d3adfe5e1..2ba3214cdad 100644 --- a/src/cascadia/TerminalControl/TermControl.h +++ b/src/cascadia/TerminalControl/TermControl.h @@ -104,8 +104,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation FORWARDED_TYPED_EVENT(TabColorChanged, IInspectable, IInspectable, _core, TabColorChanged); FORWARDED_TYPED_EVENT(SetTaskbarProgress, IInspectable, IInspectable, _core, TaskbarProgressChanged); FORWARDED_TYPED_EVENT(ConnectionStateChanged, IInspectable, IInspectable, _core, ConnectionStateChanged); + FORWARDED_TYPED_EVENT(PasteFromClipboard, IInspectable, Control::PasteFromClipboardEventArgs, _interactivity, PasteFromClipboard); - TYPED_EVENT(PasteFromClipboard, IInspectable, Control::PasteFromClipboardEventArgs); TYPED_EVENT(OpenHyperlink, IInspectable, Control::OpenHyperlinkEventArgs); TYPED_EVENT(RaiseNotice, IInspectable, Control::NoticeEventArgs); TYPED_EVENT(HidePointerCursor, IInspectable, IInspectable); @@ -204,7 +204,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation void _CursorTimerTick(Windows::Foundation::IInspectable const& sender, Windows::Foundation::IInspectable const& e); void _BlinkTimerTick(Windows::Foundation::IInspectable const& sender, Windows::Foundation::IInspectable const& e); void _SetEndSelectionPointAtCursor(Windows::Foundation::Point const& cursorPosition); - void _SendPastedTextToConnection(const std::wstring& wstr); + // void _SendPastedTextToConnection(const std::wstring& wstr); void _SwapChainSizeChanged(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::SizeChangedEventArgs const& e); void _SwapChainScaleChanged(Windows::UI::Xaml::Controls::SwapChainPanel const& sender, Windows::Foundation::IInspectable const& args); void _TerminalTabColorChanged(const std::optional color); From 60b939e8d5f1e79da1ebc5ed4c4ca756793ccf4c Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Mon, 29 Mar 2021 12:41:30 -0500 Subject: [PATCH 25/82] An easy fix for 4 total errors --- src/cascadia/TerminalControl/TermControl.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/cascadia/TerminalControl/TermControl.cpp b/src/cascadia/TerminalControl/TermControl.cpp index f99ba843dbc..02ee6eb290d 100644 --- a/src/cascadia/TerminalControl/TermControl.cpp +++ b/src/cascadia/TerminalControl/TermControl.cpp @@ -1895,8 +1895,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation // // - cursorPosition: in pixels, relative to the origin of the control void TermControl::_SetEndSelectionPointAtCursor(Windows::Foundation::Point const& cursorPosition) { - _core->SetEndSelectionPoint(_GetTerminalPosition(cursorPosition)); - _selectionNeedsToBeCopied = true; + _interactivity->_SetEndSelectionPoint(_GetTerminalPosition(cursorPosition)); } // Method Description: From db1c36ce426bb027759b13a7662629b5557b9c4e Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Mon, 29 Mar 2021 14:34:35 -0500 Subject: [PATCH 26/82] Try to move most of the mouse wheel handlers The transparency one is awful, so we're at 18 errors now --- .../TerminalControl/ControlInteractivity.cpp | 149 ++++++++++ .../TerminalControl/ControlInteractivity.h | 14 + src/cascadia/TerminalControl/TermControl.cpp | 270 +++++++++--------- 3 files changed, 301 insertions(+), 132 deletions(-) diff --git a/src/cascadia/TerminalControl/ControlInteractivity.cpp b/src/cascadia/TerminalControl/ControlInteractivity.cpp index 1e1d2f260be..1dda8e4601b 100644 --- a/src/cascadia/TerminalControl/ControlInteractivity.cpp +++ b/src/cascadia/TerminalControl/ControlInteractivity.cpp @@ -428,6 +428,155 @@ namespace winrt::Microsoft::Terminal::Control::implementation return _core->SendMouseEvent(terminalPosition, uiButton, modifiers, sWheelDelta, state); } + // Method Description: + // - Actually handle a scrolling event, whether from a mouse wheel or a + // touchpad scroll. Depending upon what modifier keys are pressed, + // different actions will take place. + // * Attempts to first dispatch the mouse scroll as a VT event + // * If Ctrl+Shift are pressed, then attempts to change our opacity + // * If just Ctrl is pressed, we'll attempt to "zoom" by changing our font size + // * Otherwise, just scrolls the content of the viewport + // Arguments: + // - point: the location of the mouse during this event + // - modifiers: The modifiers pressed during this event, in the form of a VirtualKeyModifiers + // - delta: the mouse wheel delta that triggered this event. + bool ControlInteractivity::MouseWheel(const ::Microsoft::Terminal::Core::ControlKeyStates modifiers, + const int32_t delta, + const til::point terminalPosition, + const TerminalInput::MouseButtonState state) + { + // Short-circuit isReadOnly check to avoid warning dialog + if (!_core->IsInReadOnlyMode() && _CanSendVTMouseInput(modifiers)) + { + // Most mouse event handlers call + // _TrySendMouseEvent(point); + // here with a PointerPoint. However, as of #979, we don't have a + // PointerPoint to work with. So, we're just going to do a + // mousewheel event manually + return _core->SendMouseEvent(terminalPosition, + WM_MOUSEWHEEL, + modifiers, + ::base::saturated_cast(delta), + state); + } + + const auto ctrlPressed = modifiers.IsCtrlPressed(); + const auto shiftPressed = modifiers.IsShiftPressed(); + + if (ctrlPressed && shiftPressed) + { + _MouseTransparencyHandler(delta); + } + else if (ctrlPressed) + { + _MouseZoomHandler(delta); + } + else + { + _MouseScrollHandler(delta, terminalPosition, state.isLeftButtonDown); + } + return false; + } + + // Method Description: + // - Adjust the opacity of the acrylic background in response to a mouse + // scrolling event. + // Arguments: + // - mouseDelta: the mouse wheel delta that triggered this event. + void ControlInteractivity::_MouseTransparencyHandler(const double mouseDelta) + { + // Transparency is on a scale of [0.0,1.0], so only increment by .01. + const auto effectiveDelta = mouseDelta < 0 ? -.01 : .01; + + if (_settings.UseAcrylic()) + { + try + { + auto acrylicBrush = RootGrid().Background().as(); + _settings.TintOpacity(acrylicBrush.TintOpacity() + effectiveDelta); + acrylicBrush.TintOpacity(_settings.TintOpacity()); + + if (acrylicBrush.TintOpacity() == 1.0) + { + _settings.UseAcrylic(false); + _InitializeBackgroundBrush(); + COLORREF bg = _settings.DefaultBackground(); + _changeBackgroundColor(bg); + } + else + { + // GH#5098: Inform the engine of the new opacity of the default text background. + _core->SetBackgroundOpacity(::base::saturated_cast(_settings.TintOpacity())); + } + } + CATCH_LOG(); + } + else if (mouseDelta < 0) + { + _settings.UseAcrylic(true); + + //Setting initial opacity set to 1 to ensure smooth transition to acrylic during mouse scroll + _settings.TintOpacity(1.0); + _InitializeBackgroundBrush(); + } + } + + // Method Description: + // - Adjust the font size of the terminal in response to a mouse scrolling + // event. + // Arguments: + // - mouseDelta: the mouse wheel delta that triggered this event. + void ControlInteractivity::_MouseZoomHandler(const double mouseDelta) + { + const auto fontDelta = mouseDelta < 0 ? -1 : 1; + _core->AdjustFontSize(fontDelta); + } + + // Method Description: + // - Scroll the visible viewport in response to a mouse wheel event. + // Arguments: + // - mouseDelta: the mouse wheel delta that triggered this event. + // - point: the location of the mouse during this event + // - isLeftButtonPressed: true iff the left mouse button was pressed during this event. + void ControlInteractivity::_MouseScrollHandler(const double mouseDelta, + const til::point terminalPosition, + const bool isLeftButtonPressed) + { + const auto currentOffset = _core->ScrollOffset(); + // const auto currentOffset = ScrollBar().Value(); + + // negative = down, positive = up + // However, for us, the signs are flipped. + // With one of the precision mice, one click is always a multiple of 120 (WHEEL_DELTA), + // but the "smooth scrolling" mode results in non-int values + const auto rowDelta = mouseDelta / (-1.0 * WHEEL_DELTA); + + // WHEEL_PAGESCROLL is a Win32 constant that represents the "scroll one page + // at a time" setting. If we ignore it, we will scroll a truly absurd number + // of rows. + const auto rowsToScroll{ _rowsToScroll == WHEEL_PAGESCROLL ? _core->ViewHeight() : _rowsToScroll }; + double newValue = (rowsToScroll * rowDelta) + (currentOffset); + + // The scroll bar's ValueChanged handler will actually move the viewport + // for us. + // ScrollBar().Value(newValue); + + // !TODO! - Very worried about using UserScrollViewport as + // opposed to the ScrollBar().Value() setter. Originally setting + // the scrollbar value would raise a event handled in + // _ScrollbarChangeHandler, which would _then_ scroll the core, + // and start the _updateScrollBar ThrottledFunc to update the + // scroll position. I'm worried that won't work like this. + _core->UserScrollViewport(::base::saturated_cast(newValue)); + + if (isLeftButtonPressed) + { + // If user is mouse selecting and scrolls, they then point at new character. + // Make sure selection reflects that immediately. + _SetEndSelectionPoint(terminalPosition); + } + } + void ControlInteractivity::_HyperlinkHandler(const std::wstring_view uri) { // Save things we need to resume later. diff --git a/src/cascadia/TerminalControl/ControlInteractivity.h b/src/cascadia/TerminalControl/ControlInteractivity.h index 1cb424ed295..4f598681096 100644 --- a/src/cascadia/TerminalControl/ControlInteractivity.h +++ b/src/cascadia/TerminalControl/ControlInteractivity.h @@ -25,6 +25,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation void GainFocus(); void UpdateSettings(); void Initialize(); + //////////////////////////////////////////////////////////////////////// void PointerPressed(const winrt::Windows::UI::Input::PointerPoint point, const ::Microsoft::Terminal::Core::ControlKeyStates modifiers, const bool focused, @@ -40,6 +41,12 @@ namespace winrt::Microsoft::Terminal::Control::implementation const bool focused, const til::point terminalPosition, const winrt::Windows::Devices::Input::PointerDeviceType type); + bool MouseWheel(const ::Microsoft::Terminal::Core::ControlKeyStates modifiers, + const int32_t delta, + const til::point terminalPosition, + const ::Microsoft::Console::VirtualTerminal::TerminalInput::MouseButtonState state); + //////////////////////////////////////////////////////////////////////// + bool CopySelectionToClipboard(bool singleLine, const Windows::Foundation::IReference& formats); void PasteTextFromClipboard(); @@ -82,6 +89,13 @@ namespace winrt::Microsoft::Terminal::Control::implementation bool _TrySendMouseEvent(Windows::UI::Input::PointerPoint const& point, const ::Microsoft::Terminal::Core::ControlKeyStates modifiers, const til::point terminalPosition); + + void _MouseTransparencyHandler(const double mouseDelta); + void _MouseZoomHandler(const double mouseDelta); + void _MouseScrollHandler(const double mouseDelta, + const til::point terminalPosition, + const bool isLeftButtonPressed); + void _HyperlinkHandler(const std::wstring_view uri); bool _CanSendVTMouseInput(const ::Microsoft::Terminal::Core::ControlKeyStates modifiers); void _SetEndSelectionPoint(const til::point terminalPosition); diff --git a/src/cascadia/TerminalControl/TermControl.cpp b/src/cascadia/TerminalControl/TermControl.cpp index 02ee6eb290d..638958ab22f 100644 --- a/src/cascadia/TerminalControl/TermControl.cpp +++ b/src/cascadia/TerminalControl/TermControl.cpp @@ -1367,65 +1367,71 @@ namespace winrt::Microsoft::Terminal::Control::implementation const TerminalInput::MouseButtonState state{ props.IsLeftButtonPressed(), props.IsMiddleButtonPressed(), props.IsRightButtonPressed() }; - auto result = _DoMouseWheel(point.Position(), - ControlKeyStates{ args.KeyModifiers() }, - point.Properties().MouseWheelDelta(), - state); + // auto result = _DoMouseWheel(point.Position(), + // ControlKeyStates{ args.KeyModifiers() }, + // point.Properties().MouseWheelDelta(), + // state); + auto mousePosition = point.Position(); + + auto result = _interactivity->MouseWheel(ControlKeyStates{ args.KeyModifiers() }, + point.Properties().MouseWheelDelta(), + _GetTerminalPosition(mousePosition), + state); if (result) { args.Handled(true); } } - // Method Description: - // - Actually handle a scrolling event, whether from a mouse wheel or a - // touchpad scroll. Depending upon what modifier keys are pressed, - // different actions will take place. - // * Attempts to first dispatch the mouse scroll as a VT event - // * If Ctrl+Shift are pressed, then attempts to change our opacity - // * If just Ctrl is pressed, we'll attempt to "zoom" by changing our font size - // * Otherwise, just scrolls the content of the viewport - // Arguments: - // - point: the location of the mouse during this event - // - modifiers: The modifiers pressed during this event, in the form of a VirtualKeyModifiers - // - delta: the mouse wheel delta that triggered this event. - bool TermControl::_DoMouseWheel(const Windows::Foundation::Point point, - const ControlKeyStates modifiers, - const int32_t delta, - const TerminalInput::MouseButtonState state) - { - // Short-circuit isReadOnly check to avoid warning dialog - if (!_core->IsInReadOnlyMode() && _interactivity->_CanSendVTMouseInput(modifiers)) - { - // Most mouse event handlers call - // _TrySendMouseEvent(point); - // here with a PointerPoint. However, as of #979, we don't have a - // PointerPoint to work with. So, we're just going to do a - // mousewheel event manually - return _core->SendMouseEvent(_GetTerminalPosition(point), - WM_MOUSEWHEEL, - _GetPressedModifierKeys(), - ::base::saturated_cast(delta), - state); - } + // // Method Description: + // // - Actually handle a scrolling event, whether from a mouse wheel or a + // // touchpad scroll. Depending upon what modifier keys are pressed, + // // different actions will take place. + // // * Attempts to first dispatch the mouse scroll as a VT event + // // * If Ctrl+Shift are pressed, then attempts to change our opacity + // // * If just Ctrl is pressed, we'll attempt to "zoom" by changing our font size + // // * Otherwise, just scrolls the content of the viewport + // // Arguments: + // // - point: the location of the mouse during this event + // // - modifiers: The modifiers pressed during this event, in the form of a VirtualKeyModifiers + // // - delta: the mouse wheel delta that triggered this event. + // bool TermControl::_DoMouseWheel(const Windows::Foundation::Point point, + // const ControlKeyStates modifiers, + // const int32_t delta, + // const TerminalInput::MouseButtonState state) + // { + // // Short-circuit isReadOnly check to avoid warning dialog + // if (!_core->IsInReadOnlyMode() && _interactivity->_CanSendVTMouseInput(modifiers)) + // { + // // Most mouse event handlers call + // // _TrySendMouseEvent(point); + // // here with a PointerPoint. However, as of #979, we don't have a + // // PointerPoint to work with. So, we're just going to do a + // // mousewheel event manually + // return _core->SendMouseEvent(_GetTerminalPosition(point), + // WM_MOUSEWHEEL, + // _GetPressedModifierKeys(), + // ::base::saturated_cast(delta), + // state); + // } - const auto ctrlPressed = modifiers.IsCtrlPressed(); - const auto shiftPressed = modifiers.IsShiftPressed(); + // const auto ctrlPressed = modifiers.IsCtrlPressed(); + // const auto shiftPressed = modifiers.IsShiftPressed(); - if (ctrlPressed && shiftPressed) - { - _MouseTransparencyHandler(delta); - } - else if (ctrlPressed) - { - _MouseZoomHandler(delta); - } - else - { - _MouseScrollHandler(delta, point, state.isLeftButtonDown); - } - return false; - } + // if (ctrlPressed && shiftPressed) + // { + // _MouseTransparencyHandler(delta); + // } + // else if (ctrlPressed) + // { + // _MouseZoomHandler(delta); + // } + // else + // { + // _MouseScrollHandler(delta, point, state.isLeftButtonDown); + // } + // return false; + // } // Method Description: // - This is part of the solution to GH#979 @@ -1450,59 +1456,59 @@ namespace winrt::Microsoft::Terminal::Control::implementation return _DoMouseWheel(location, modifiers, delta, state); } - // Method Description: - // - Adjust the opacity of the acrylic background in response to a mouse - // scrolling event. - // Arguments: - // - mouseDelta: the mouse wheel delta that triggered this event. - void TermControl::_MouseTransparencyHandler(const double mouseDelta) - { - // Transparency is on a scale of [0.0,1.0], so only increment by .01. - const auto effectiveDelta = mouseDelta < 0 ? -.01 : .01; - - if (_settings.UseAcrylic()) - { - try - { - auto acrylicBrush = RootGrid().Background().as(); - _settings.TintOpacity(acrylicBrush.TintOpacity() + effectiveDelta); - acrylicBrush.TintOpacity(_settings.TintOpacity()); + // // Method Description: + // // - Adjust the opacity of the acrylic background in response to a mouse + // // scrolling event. + // // Arguments: + // // - mouseDelta: the mouse wheel delta that triggered this event. + // void TermControl::_MouseTransparencyHandler(const double mouseDelta) + // { + // // Transparency is on a scale of [0.0,1.0], so only increment by .01. + // const auto effectiveDelta = mouseDelta < 0 ? -.01 : .01; - if (acrylicBrush.TintOpacity() == 1.0) - { - _settings.UseAcrylic(false); - _InitializeBackgroundBrush(); - COLORREF bg = _settings.DefaultBackground(); - _changeBackgroundColor(bg); - } - else - { - // GH#5098: Inform the engine of the new opacity of the default text background. - _core->SetBackgroundOpacity(::base::saturated_cast(_settings.TintOpacity())); - } - } - CATCH_LOG(); - } - else if (mouseDelta < 0) - { - _settings.UseAcrylic(true); + // if (_settings.UseAcrylic()) + // { + // try + // { + // auto acrylicBrush = RootGrid().Background().as(); + // _settings.TintOpacity(acrylicBrush.TintOpacity() + effectiveDelta); + // acrylicBrush.TintOpacity(_settings.TintOpacity()); + + // if (acrylicBrush.TintOpacity() == 1.0) + // { + // _settings.UseAcrylic(false); + // _InitializeBackgroundBrush(); + // COLORREF bg = _settings.DefaultBackground(); + // _changeBackgroundColor(bg); + // } + // else + // { + // // GH#5098: Inform the engine of the new opacity of the default text background. + // _core->SetBackgroundOpacity(::base::saturated_cast(_settings.TintOpacity())); + // } + // } + // CATCH_LOG(); + // } + // else if (mouseDelta < 0) + // { + // _settings.UseAcrylic(true); - //Setting initial opacity set to 1 to ensure smooth transition to acrylic during mouse scroll - _settings.TintOpacity(1.0); - _InitializeBackgroundBrush(); - } - } + // //Setting initial opacity set to 1 to ensure smooth transition to acrylic during mouse scroll + // _settings.TintOpacity(1.0); + // _InitializeBackgroundBrush(); + // } + // } - // Method Description: - // - Adjust the font size of the terminal in response to a mouse scrolling - // event. - // Arguments: - // - mouseDelta: the mouse wheel delta that triggered this event. - void TermControl::_MouseZoomHandler(const double mouseDelta) - { - const auto fontDelta = mouseDelta < 0 ? -1 : 1; - AdjustFontSize(fontDelta); - } + // // Method Description: + // // - Adjust the font size of the terminal in response to a mouse scrolling + // // event. + // // Arguments: + // // - mouseDelta: the mouse wheel delta that triggered this event. + // void TermControl::_MouseZoomHandler(const double mouseDelta) + // { + // const auto fontDelta = mouseDelta < 0 ? -1 : 1; + // AdjustFontSize(fontDelta); + // } // Method Description: // - Reset the font size of the terminal to its default size. @@ -1522,41 +1528,41 @@ namespace winrt::Microsoft::Terminal::Control::implementation _core->AdjustFontSize(fontSizeDelta); } - // Method Description: - // - Scroll the visible viewport in response to a mouse wheel event. - // Arguments: - // - mouseDelta: the mouse wheel delta that triggered this event. - // - point: the location of the mouse during this event - // - isLeftButtonPressed: true iff the left mouse button was pressed during this event. - void TermControl::_MouseScrollHandler(const double mouseDelta, - const Windows::Foundation::Point point, - const bool isLeftButtonPressed) - { - const auto currentOffset = ScrollBar().Value(); + // // Method Description: + // // - Scroll the visible viewport in response to a mouse wheel event. + // // Arguments: + // // - mouseDelta: the mouse wheel delta that triggered this event. + // // - point: the location of the mouse during this event + // // - isLeftButtonPressed: true iff the left mouse button was pressed during this event. + // void TermControl::_MouseScrollHandler(const double mouseDelta, + // const Windows::Foundation::Point point, + // const bool isLeftButtonPressed) + // { + // const auto currentOffset = ScrollBar().Value(); - // negative = down, positive = up - // However, for us, the signs are flipped. - // With one of the precision mice, one click is always a multiple of 120 (WHEEL_DELTA), - // but the "smooth scrolling" mode results in non-int values - const auto rowDelta = mouseDelta / (-1.0 * WHEEL_DELTA); + // // negative = down, positive = up + // // However, for us, the signs are flipped. + // // With one of the precision mice, one click is always a multiple of 120 (WHEEL_DELTA), + // // but the "smooth scrolling" mode results in non-int values + // const auto rowDelta = mouseDelta / (-1.0 * WHEEL_DELTA); - // WHEEL_PAGESCROLL is a Win32 constant that represents the "scroll one page - // at a time" setting. If we ignore it, we will scroll a truly absurd number - // of rows. - const auto rowsToScroll{ _rowsToScroll == WHEEL_PAGESCROLL ? ViewHeight() : _rowsToScroll }; - double newValue = (rowsToScroll * rowDelta) + (currentOffset); + // // WHEEL_PAGESCROLL is a Win32 constant that represents the "scroll one page + // // at a time" setting. If we ignore it, we will scroll a truly absurd number + // // of rows. + // const auto rowsToScroll{ _rowsToScroll == WHEEL_PAGESCROLL ? ViewHeight() : _rowsToScroll }; + // double newValue = (rowsToScroll * rowDelta) + (currentOffset); - // The scroll bar's ValueChanged handler will actually move the viewport - // for us. - ScrollBar().Value(newValue); + // // The scroll bar's ValueChanged handler will actually move the viewport + // // for us. + // ScrollBar().Value(newValue); - if (isLeftButtonPressed) - { - // If user is mouse selecting and scrolls, they then point at new character. - // Make sure selection reflects that immediately. - _SetEndSelectionPointAtCursor(point); - } - } + // if (isLeftButtonPressed) + // { + // // If user is mouse selecting and scrolls, they then point at new character. + // // Make sure selection reflects that immediately. + // _SetEndSelectionPointAtCursor(point); + // } + // } void TermControl::_ScrollbarChangeHandler(Windows::Foundation::IInspectable const& /*sender*/, Controls::Primitives::RangeBaseValueChangedEventArgs const& args) From 4d8c85b811c3bd275f0ed7ac90526743017ee837 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Tue, 30 Mar 2021 05:59:46 -0500 Subject: [PATCH 27/82] Stashing this, down to 4 errors? But I don't think this is hooked up all the way --- src/cascadia/TerminalControl/ControlCore.cpp | 41 ++++++++++++ src/cascadia/TerminalControl/ControlCore.h | 2 + .../TerminalControl/ControlInteractivity.cpp | 65 ++++++++++--------- src/cascadia/TerminalControl/EventArgs.cpp | 1 + src/cascadia/TerminalControl/EventArgs.h | 33 ++++++---- src/cascadia/TerminalControl/EventArgs.idl | 5 ++ 6 files changed, 101 insertions(+), 46 deletions(-) diff --git a/src/cascadia/TerminalControl/ControlCore.cpp b/src/cascadia/TerminalControl/ControlCore.cpp index b541223ccbf..9dce172e6d0 100644 --- a/src/cascadia/TerminalControl/ControlCore.cpp +++ b/src/cascadia/TerminalControl/ControlCore.cpp @@ -363,6 +363,47 @@ namespace winrt::Microsoft::Terminal::Control::implementation _terminal->UserScrollViewport(viewTop); } + void ControlCore::AdjustOpacity(const double adjustment) + { + if (_settings.UseAcrylic()) + { + try + { + // auto acrylicBrush = RootGrid().Background().as(); + auto newOpacity = _settings.TintOpacity() + effectiveDelta; + _settings.TintOpacity(newOpacity); + // acrylicBrush.TintOpacity(_settings.TintOpacity()); + + if (newOpacity >= 1.0) + { + _settings.UseAcrylic(false); + // _InitializeBackgroundBrush(); + // COLORREF bg = _settings.DefaultBackground(); + // _changeBackgroundColor(bg); + } + else + { + // GH#5098: Inform the engine of the new opacity of the default text background. + _core->SetBackgroundOpacity(::base::saturated_cast(newOpacity)); + } + + auto eventArgs = winrt::make_self(newOpacity); + _TransparencyChangedHandlers(*this, *eventArgs); + } + CATCH_LOG(); + } + else if (adjustment < 0) + { + _settings.UseAcrylic(true); + + //Setting initial opacity set to 1 to ensure smooth transition to acrylic during mouse scroll + _settings.TintOpacity(1.0); + + auto eventArgs = winrt::make_self(1.0); + _TransparencyChangedHandlers(*this, *eventArgs); + } + } + void ControlCore::ToggleShaderEffects() { auto lock = _terminal->LockForWriting(); diff --git a/src/cascadia/TerminalControl/ControlCore.h b/src/cascadia/TerminalControl/ControlCore.h index c2003abd4fc..93eeb9ffbbd 100644 --- a/src/cascadia/TerminalControl/ControlCore.h +++ b/src/cascadia/TerminalControl/ControlCore.h @@ -45,6 +45,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation bool CopySelectionToClipboard(bool singleLine, const Windows::Foundation::IReference& formats); void ToggleShaderEffects(); + void AdjustOpacity(const double adjustment); void ResumeRendering(); void UpdatePatternLocations(); @@ -137,6 +138,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation TYPED_EVENT(SwapChainChanged, IInspectable, IInspectable); TYPED_EVENT(RendererWarning, IInspectable, Control::RendererWarningArgs); TYPED_EVENT(RaiseNotice, IInspectable, Control::NoticeEventArgs); + TYPED_EVENT(TransparencyChanged, IInspectable, Control::TransparencyChangedEventArgs); // clang-format on private: diff --git a/src/cascadia/TerminalControl/ControlInteractivity.cpp b/src/cascadia/TerminalControl/ControlInteractivity.cpp index 1dda8e4601b..00a189d16a7 100644 --- a/src/cascadia/TerminalControl/ControlInteractivity.cpp +++ b/src/cascadia/TerminalControl/ControlInteractivity.cpp @@ -487,38 +487,39 @@ namespace winrt::Microsoft::Terminal::Control::implementation { // Transparency is on a scale of [0.0,1.0], so only increment by .01. const auto effectiveDelta = mouseDelta < 0 ? -.01 : .01; - - if (_settings.UseAcrylic()) - { - try - { - auto acrylicBrush = RootGrid().Background().as(); - _settings.TintOpacity(acrylicBrush.TintOpacity() + effectiveDelta); - acrylicBrush.TintOpacity(_settings.TintOpacity()); - - if (acrylicBrush.TintOpacity() == 1.0) - { - _settings.UseAcrylic(false); - _InitializeBackgroundBrush(); - COLORREF bg = _settings.DefaultBackground(); - _changeBackgroundColor(bg); - } - else - { - // GH#5098: Inform the engine of the new opacity of the default text background. - _core->SetBackgroundOpacity(::base::saturated_cast(_settings.TintOpacity())); - } - } - CATCH_LOG(); - } - else if (mouseDelta < 0) - { - _settings.UseAcrylic(true); - - //Setting initial opacity set to 1 to ensure smooth transition to acrylic during mouse scroll - _settings.TintOpacity(1.0); - _InitializeBackgroundBrush(); - } + _core->AdjustOpacity(effectiveDelta); + + // if (_settings.UseAcrylic()) + // { + // try + // { + // auto acrylicBrush = RootGrid().Background().as(); + // _settings.TintOpacity(acrylicBrush.TintOpacity() + effectiveDelta); + // acrylicBrush.TintOpacity(_settings.TintOpacity()); + + // if (acrylicBrush.TintOpacity() == 1.0) + // { + // _settings.UseAcrylic(false); + // _InitializeBackgroundBrush(); + // COLORREF bg = _settings.DefaultBackground(); + // _changeBackgroundColor(bg); + // } + // else + // { + // // GH#5098: Inform the engine of the new opacity of the default text background. + // _core->SetBackgroundOpacity(::base::saturated_cast(_settings.TintOpacity())); + // } + // } + // CATCH_LOG(); + // } + // else if (mouseDelta < 0) + // { + // _settings.UseAcrylic(true); + + // //Setting initial opacity set to 1 to ensure smooth transition to acrylic during mouse scroll + // _settings.TintOpacity(1.0); + // _InitializeBackgroundBrush(); + // } } // Method Description: diff --git a/src/cascadia/TerminalControl/EventArgs.cpp b/src/cascadia/TerminalControl/EventArgs.cpp index 3586f0314a9..f4b4d9bc786 100644 --- a/src/cascadia/TerminalControl/EventArgs.cpp +++ b/src/cascadia/TerminalControl/EventArgs.cpp @@ -10,3 +10,4 @@ #include "NoticeEventArgs.g.cpp" #include "ScrollPositionChangedArgs.g.cpp" #include "RendererWarningArgs.g.cpp" +#include "TransparencyChangedEventArgs.g.cpp" diff --git a/src/cascadia/TerminalControl/EventArgs.h b/src/cascadia/TerminalControl/EventArgs.h index dfc31ad441c..3d1db166238 100644 --- a/src/cascadia/TerminalControl/EventArgs.h +++ b/src/cascadia/TerminalControl/EventArgs.h @@ -10,12 +10,12 @@ #include "NoticeEventArgs.g.h" #include "ScrollPositionChangedArgs.g.h" #include "RendererWarningArgs.g.h" +#include "TransparencyChangedEventArgs.g.h" #include "cppwinrt_utils.h" namespace winrt::Microsoft::Terminal::Control::implementation { - struct TitleChangedEventArgs : - public TitleChangedEventArgsT + struct TitleChangedEventArgs : public TitleChangedEventArgsT { public: TitleChangedEventArgs(hstring title) : @@ -24,8 +24,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation WINRT_PROPERTY(hstring, Title); }; - struct CopyToClipboardEventArgs : - public CopyToClipboardEventArgsT + struct CopyToClipboardEventArgs : public CopyToClipboardEventArgsT { public: CopyToClipboardEventArgs(hstring text) : @@ -52,8 +51,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation Windows::Foundation::IReference _formats; }; - struct PasteFromClipboardEventArgs : - public PasteFromClipboardEventArgsT + struct PasteFromClipboardEventArgs : public PasteFromClipboardEventArgsT { public: PasteFromClipboardEventArgs(std::function clipboardDataHandler) : @@ -68,8 +66,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation std::function m_clipboardDataHandler; }; - struct OpenHyperlinkEventArgs : - public OpenHyperlinkEventArgsT + struct OpenHyperlinkEventArgs : public OpenHyperlinkEventArgsT { public: OpenHyperlinkEventArgs(hstring uri) : @@ -81,8 +78,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation hstring _uri; }; - struct NoticeEventArgs : - public NoticeEventArgsT + struct NoticeEventArgs : public NoticeEventArgsT { public: NoticeEventArgs(const NoticeLevel level, const hstring& message) : @@ -97,8 +93,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation const hstring _message; }; - struct ScrollPositionChangedArgs : - public ScrollPositionChangedArgsT + struct ScrollPositionChangedArgs : public ScrollPositionChangedArgsT { public: ScrollPositionChangedArgs(const int viewTop, @@ -115,8 +110,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation WINRT_PROPERTY(int32_t, BufferSize); }; - struct RendererWarningArgs : - public RendererWarningArgsT + struct RendererWarningArgs : public RendererWarningArgsT { public: RendererWarningArgs(const uint64_t hr) : @@ -126,4 +120,15 @@ namespace winrt::Microsoft::Terminal::Control::implementation WINRT_PROPERTY(uint64_t, Result); }; + + struct TransparencyChangedEventArgs : public TransparencyChangedEventArgsT + { + public: + TransparencyChangedEventArgs(const double opacity) : + _Opacity(opacity) + { + } + + WINRT_PROPERTY(double, Opacity); + }; } diff --git a/src/cascadia/TerminalControl/EventArgs.idl b/src/cascadia/TerminalControl/EventArgs.idl index 4fe7ff89115..dae093f51f8 100644 --- a/src/cascadia/TerminalControl/EventArgs.idl +++ b/src/cascadia/TerminalControl/EventArgs.idl @@ -62,4 +62,9 @@ namespace Microsoft.Terminal.Control { UInt64 Result { get; }; } + + runtimeclass TransparencyChangedEventArgs + { + Double Opacity { get; }; + } } From 7b02393d8e1ddc84dd3ce44792f04fee59c088dd Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Tue, 30 Mar 2021 17:09:32 -0500 Subject: [PATCH 28/82] HAHAHAHA IT builds again, 0 ERRORS REMAIN --- src/cascadia/TerminalControl/ControlCore.cpp | 4 +- src/cascadia/TerminalControl/TermControl.cpp | 47 +++++++++++++++++++- src/cascadia/TerminalControl/TermControl.h | 9 ++-- src/host/exe/exemain.cpp | 2 - 4 files changed, 53 insertions(+), 9 deletions(-) diff --git a/src/cascadia/TerminalControl/ControlCore.cpp b/src/cascadia/TerminalControl/ControlCore.cpp index 9cd4d31bfcf..9c3440accf2 100644 --- a/src/cascadia/TerminalControl/ControlCore.cpp +++ b/src/cascadia/TerminalControl/ControlCore.cpp @@ -370,7 +370,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation try { // auto acrylicBrush = RootGrid().Background().as(); - auto newOpacity = _settings.TintOpacity() + effectiveDelta; + auto newOpacity = _settings.TintOpacity() + adjustment; _settings.TintOpacity(newOpacity); // acrylicBrush.TintOpacity(_settings.TintOpacity()); @@ -384,7 +384,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation else { // GH#5098: Inform the engine of the new opacity of the default text background. - _core->SetBackgroundOpacity(::base::saturated_cast(newOpacity)); + SetBackgroundOpacity(::base::saturated_cast(newOpacity)); } auto eventArgs = winrt::make_self(newOpacity); diff --git a/src/cascadia/TerminalControl/TermControl.cpp b/src/cascadia/TerminalControl/TermControl.cpp index b3df8fe31e4..78b4a8a01ec 100644 --- a/src/cascadia/TerminalControl/TermControl.cpp +++ b/src/cascadia/TerminalControl/TermControl.cpp @@ -67,6 +67,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation _core->CursorPositionChanged({ get_weak(), &TermControl::_CursorPositionChanged }); _core->RendererEnteredErrorState({ get_weak(), &TermControl::_RendererEnteredErrorState }); _core->FontSizeChanged({ get_weak(), &TermControl::_coreFontSizeChanged }); + _core->TransparencyChanged({ get_weak(), &TermControl::_coreTransparencyChanged }); _interactivity->OpenHyperlink({ get_weak(), &TermControl::_HyperlinkHandler }); // Initialize the terminal only once the swapchainpanel is loaded - that @@ -1448,7 +1449,51 @@ namespace winrt::Microsoft::Terminal::Control::implementation TerminalInput::MouseButtonState state{ leftButtonDown, midButtonDown, rightButtonDown }; - return _DoMouseWheel(location, modifiers, delta, state); + return _interactivity->MouseWheel(modifiers, delta, _GetTerminalPosition(location), state); + } + + winrt::fire_and_forget TermControl::_coreTransparencyChanged(const IInspectable& sender, + const Control::TransparencyChangedEventArgs& args) + { + const auto newOpacity = args.Opacity(); + co_await resume_foreground(Dispatcher()); + // if (_settings.UseAcrylic()) + // { + try + { + auto acrylicBrush = RootGrid().Background().as(); + acrylicBrush.TintOpacity(newOpacity); + + if (newOpacity == 1.0) + { + _settings.UseAcrylic(false); + _InitializeBackgroundBrush(); + const auto bg = _settings.DefaultBackground(); + _changeBackgroundColor(bg); + } + // else + // { + // // GH#5098: Inform the engine of the new opacity of the default text background. + // if (_renderEngine) + // { + // _renderEngine->SetDefaultTextBackgroundOpacity(::base::saturated_cast(_settings.TintOpacity())); + // } + // } + } + CATCH_LOG(); + // } + // else + // { + + // _InitializeBackgroundBrush(); + // } + // else if (mouseDelta < 0) + // { + // _settings.UseAcrylic(true); + + // //Setting initial opacity set to 1 to ensure smooth transition to acrylic during mouse scroll + // _settings.TintOpacity(1.0); + // } } // // Method Description: diff --git a/src/cascadia/TerminalControl/TermControl.h b/src/cascadia/TerminalControl/TermControl.h index 661d59f97ba..5dea19ca5a2 100644 --- a/src/cascadia/TerminalControl/TermControl.h +++ b/src/cascadia/TerminalControl/TermControl.h @@ -212,10 +212,10 @@ namespace winrt::Microsoft::Terminal::Control::implementation void _ScrollPositionChanged(const IInspectable& sender, const Control::ScrollPositionChangedArgs& args); void _CursorPositionChanged(const IInspectable& sender, const IInspectable& args); - void _MouseScrollHandler(const double mouseDelta, const Windows::Foundation::Point point, const bool isLeftButtonPressed); - void _MouseZoomHandler(const double delta); - void _MouseTransparencyHandler(const double delta); - bool _DoMouseWheel(const Windows::Foundation::Point point, const ::Microsoft::Terminal::Core::ControlKeyStates modifiers, const int32_t delta, const ::Microsoft::Console::VirtualTerminal::TerminalInput::MouseButtonState state); + // void _MouseScrollHandler(const double mouseDelta, const Windows::Foundation::Point point, const bool isLeftButtonPressed); + // void _MouseZoomHandler(const double delta); + // void _MouseTransparencyHandler(const double delta); + // bool _DoMouseWheel(const Windows::Foundation::Point point, const ::Microsoft::Terminal::Core::ControlKeyStates modifiers, const int32_t delta, const ::Microsoft::Console::VirtualTerminal::TerminalInput::MouseButtonState state); bool _CapturePointer(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::Input::PointerRoutedEventArgs const& e); bool _ReleasePointerCapture(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::Input::PointerRoutedEventArgs const& e); @@ -252,6 +252,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation void _coreFontSizeChanged(const int fontWidth, const int fontHeight, const bool isInitialChange); + winrt::fire_and_forget _coreTransparencyChanged(const IInspectable& sender, const Control::TransparencyChangedEventArgs& args); }; } diff --git a/src/host/exe/exemain.cpp b/src/host/exe/exemain.cpp index 53b21574a13..68057c62a11 100644 --- a/src/host/exe/exemain.cpp +++ b/src/host/exe/exemain.cpp @@ -67,8 +67,6 @@ static bool ConhostV2ForcedInRegistry() if (ERROR_SUCCESS == lStatus) { // now get the value of the ForceV2 reg value, if it exists - DWORD dwValue; - DWORD dwType; cbValue = sizeof(dwValue); lStatus = RegQueryValueExW(hConsoleSubKey.get(), L"ForceV2", From 7a0dc43e95e3f9109b1de73b46fd4aae94052847 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Tue, 30 Mar 2021 17:15:17 -0500 Subject: [PATCH 29/82] its full of bugs --- src/cascadia/TerminalCore/Terminal.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cascadia/TerminalCore/Terminal.cpp b/src/cascadia/TerminalCore/Terminal.cpp index 7d4e1691721..6b634fa9fdf 100644 --- a/src/cascadia/TerminalCore/Terminal.cpp +++ b/src/cascadia/TerminalCore/Terminal.cpp @@ -1196,7 +1196,7 @@ void Terminal::UpdatePatterns() noexcept // visible region is changing void Terminal::ClearPatternTree() noexcept { - auto lock = LockForWriting(); + // auto lock = LockForWriting(); auto oldTree = _patternIntervalTree; _patternIntervalTree = {}; _InvalidatePatternTree(oldTree); From 2ac83180f867bf38aac094eb88a710e17d2771c9 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Wed, 31 Mar 2021 06:16:30 -0500 Subject: [PATCH 30/82] dead code cleanup crew --- .../TerminalControl/ControlInteractivity.cpp | 26 +- src/cascadia/TerminalControl/TermControl.cpp | 517 +----------------- src/cascadia/TerminalControl/TermControl.h | 41 +- 3 files changed, 36 insertions(+), 548 deletions(-) diff --git a/src/cascadia/TerminalControl/ControlInteractivity.cpp b/src/cascadia/TerminalControl/ControlInteractivity.cpp index 00a189d16a7..3aaa8f356be 100644 --- a/src/cascadia/TerminalControl/ControlInteractivity.cpp +++ b/src/cascadia/TerminalControl/ControlInteractivity.cpp @@ -94,14 +94,14 @@ namespace winrt::Microsoft::Terminal::Control::implementation } } - // // Method Description: - // // - Given a copy-able selection, get the selected text from the buffer and send it to the - // // Windows Clipboard (CascadiaWin32:main.cpp). - // // - CopyOnSelect does NOT clear the selection - // // Arguments: - // // - singleLine: collapse all of the text to one line - // // - formats: which formats to copy (defined by action's CopyFormatting arg). nullptr - // // if we should defer which formats are copied to the global setting + // Method Description: + // - Given a copy-able selection, get the selected text from the buffer and send it to the + // Windows Clipboard (CascadiaWin32:main.cpp). + // - CopyOnSelect does NOT clear the selection + // Arguments: + // - singleLine: collapse all of the text to one line + // - formats: which formats to copy (defined by action's CopyFormatting arg). nullptr + // if we should defer which formats are copied to the global setting bool ControlInteractivity::CopySelectionToClipboard(bool singleLine, const Windows::Foundation::IReference& formats) { @@ -153,15 +153,11 @@ namespace winrt::Microsoft::Terminal::Control::implementation if (type == Windows::Devices::Input::PointerDeviceType::Mouse || type == Windows::Devices::Input::PointerDeviceType::Pen) { - // const auto modifiers = static_cast(args.KeyModifiers()); - // static_cast to a uint32_t because we can't use the WI_IsFlagSet - // macro directly with a VirtualKeyModifiers - const auto altEnabled = modifiers.IsAltPressed(); // WI_IsFlagSet(modifiers, static_cast(VirtualKeyModifiers::Menu)); - const auto shiftEnabled = modifiers.IsShiftPressed(); // WI_IsFlagSet(modifiers, static_cast(VirtualKeyModifiers::Shift)); - const auto ctrlEnabled = modifiers.IsCtrlPressed(); // WI_IsFlagSet(modifiers, static_cast(VirtualKeyModifiers::Control)); + const auto altEnabled = modifiers.IsAltPressed(); + const auto shiftEnabled = modifiers.IsShiftPressed(); + const auto ctrlEnabled = modifiers.IsCtrlPressed(); const auto cursorPosition = point.Position(); - // const auto terminalPosition = _GetTerminalPosition(cursorPosition); // GH#9396: we prioritize hyper-link over VT mouse events // diff --git a/src/cascadia/TerminalControl/TermControl.cpp b/src/cascadia/TerminalControl/TermControl.cpp index 78b4a8a01ec..0963db499cf 100644 --- a/src/cascadia/TerminalControl/TermControl.cpp +++ b/src/cascadia/TerminalControl/TermControl.cpp @@ -185,15 +185,15 @@ namespace winrt::Microsoft::Terminal::Control::implementation } } - // // Method Description: - // // - Search text in text buffer. This is triggered if the user click - // // search button or press enter. - // // Arguments: - // // - text: the text to search - // // - goForward: boolean that represents if the current search direction is forward - // // - caseSensitive: boolean that represents if the current search is case sensitive - // // Return Value: - // // - + // Method Description: + // - Search text in text buffer. This is triggered if the user click + // search button or press enter. + // Arguments: + // - text: the text to search + // - goForward: boolean that represents if the current search direction is forward + // - caseSensitive: boolean that represents if the current search is case sensitive + // Return Value: + // - void TermControl::_Search(const winrt::hstring& text, const bool goForward, const bool caseSensitive) @@ -655,9 +655,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation _blinkTimer = std::nullopt; } - // // import value from WinUser (convert from milli-seconds to micro-seconds) - // _multiClickTimer = GetDoubleClickTime() * 1000; - // Focus the control here. If we do it during control initialization, then // focus won't actually get passed to us. I believe this is because // we're not technically a part of the UI tree yet, so focusing us @@ -952,75 +949,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation e.Handled(true); } - // // Method Description: - // // - Send this particular mouse event to the terminal. - // // See Terminal::SendMouseEvent for more information. - // // Arguments: - // // - point: the PointerPoint object representing a mouse event from our XAML input handler - // bool TermControl::_TrySendMouseEvent(Windows::UI::Input::PointerPoint const& point) - // { - // const auto props = point.Properties(); - - // // Get the terminal position relative to the viewport - // const auto terminalPosition = _GetTerminalPosition(point.Position()); - - // // Which mouse button changed state (and how) - // unsigned int uiButton{}; - // switch (props.PointerUpdateKind()) - // { - // case PointerUpdateKind::LeftButtonPressed: - // uiButton = WM_LBUTTONDOWN; - // break; - // case PointerUpdateKind::LeftButtonReleased: - // uiButton = WM_LBUTTONUP; - // break; - // case PointerUpdateKind::MiddleButtonPressed: - // uiButton = WM_MBUTTONDOWN; - // break; - // case PointerUpdateKind::MiddleButtonReleased: - // uiButton = WM_MBUTTONUP; - // break; - // case PointerUpdateKind::RightButtonPressed: - // uiButton = WM_RBUTTONDOWN; - // break; - // case PointerUpdateKind::RightButtonReleased: - // uiButton = WM_RBUTTONUP; - // break; - // default: - // uiButton = WM_MOUSEMOVE; - // } - - // // Mouse wheel data - // const short sWheelDelta = ::base::saturated_cast(props.MouseWheelDelta()); - // if (sWheelDelta != 0 && !props.IsHorizontalMouseWheel()) - // { - // // if we have a mouse wheel delta and it wasn't a horizontal wheel motion - // uiButton = WM_MOUSEWHEEL; - // } - - // const auto modifiers = _GetPressedModifierKeys(); - // const TerminalInput::MouseButtonState state{ props.IsLeftButtonPressed(), - // props.IsMiddleButtonPressed(), - // props.IsRightButtonPressed() }; - // return _core->SendMouseEvent(terminalPosition, uiButton, modifiers, sWheelDelta, state); - // } - - // // Method Description: - // // - Checks if we can send vt mouse input. - // // Arguments: - // // - point: the PointerPoint object representing a mouse event from our XAML input handler - // bool TermControl::_CanSendVTMouseInput() - // { - // // If the user is holding down Shift, suppress mouse events - // // TODO GH#4875: disable/customize this functionality - // const auto modifiers = _GetPressedModifierKeys(); - // if (modifiers.IsShiftPressed()) - // { - // return false; - // } - // return _core->IsVtMouseModeEnabled(); - // } - // Method Description: // - handle a mouse click event. Begin selection process. // Arguments: @@ -1058,81 +986,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation _focused, _GetTerminalPosition(cursorPosition), ptr.PointerDeviceType()); - // if (ptr.PointerDeviceType() == Windows::Devices::Input::PointerDeviceType::Mouse || ptr.PointerDeviceType() == Windows::Devices::Input::PointerDeviceType::Pen) - // { - // const auto modifiers = static_cast(args.KeyModifiers()); - // // static_cast to a uint32_t because we can't use the WI_IsFlagSet - // // macro directly with a VirtualKeyModifiers - // const auto altEnabled = WI_IsFlagSet(modifiers, static_cast(VirtualKeyModifiers::Menu)); - // const auto shiftEnabled = WI_IsFlagSet(modifiers, static_cast(VirtualKeyModifiers::Shift)); - // const auto ctrlEnabled = WI_IsFlagSet(modifiers, static_cast(VirtualKeyModifiers::Control)); - - // const auto cursorPosition = point.Position(); - // const auto terminalPosition = _GetTerminalPosition(cursorPosition); - - // // GH#9396: we prioritize hyper-link over VT mouse events - // // - // // !TODO! Before we'd lock the terminal before getting the hyperlink. Do we still need to? - // auto hyperlink = _core->GetHyperlink(terminalPosition); - // if (point.Properties().IsLeftButtonPressed() && - // ctrlEnabled && !hyperlink.empty()) - // { - // const auto clickCount = _interactivity->_NumberOfClicks(cursorPosition, point.Timestamp()); - // // Handle hyper-link only on the first click to prevent multiple activations - // if (clickCount == 1) - // { - // _HyperlinkHandler(hyperlink); - // } - // } - // else if (_CanSendVTMouseInput()) - // { - // _TrySendMouseEvent(point); - // } - // else if (point.Properties().IsLeftButtonPressed()) - // { - // const auto clickCount = _interactivity->_NumberOfClicks(cursorPosition, point.Timestamp()); - // // This formula enables the number of clicks to cycle properly - // // between single-, double-, and triple-click. To increase the - // // number of acceptable click states, simply increment - // // MAX_CLICK_COUNT and add another if-statement - // const unsigned int MAX_CLICK_COUNT = 3; - // const auto multiClickMapper = clickCount > MAX_CLICK_COUNT ? ((clickCount + MAX_CLICK_COUNT - 1) % MAX_CLICK_COUNT) + 1 : clickCount; - - // // Capture the position of the first click when no selection is active - // if (multiClickMapper == 1 && - // !_core->HasSelection()) - // { - // _singleClickTouchdownPos = cursorPosition; - // _lastMouseClickPosNoSelection = cursorPosition; - // } - // const bool isOnOriginalPosition = _lastMouseClickPosNoSelection == cursorPosition; - - // _core->LeftClickOnTerminal(terminalPosition, - // multiClickMapper, - // altEnabled, - // shiftEnabled, - // isOnOriginalPosition, - // _selectionNeedsToBeCopied); - // } - // else if (point.Properties().IsRightButtonPressed()) - // { - // // CopyOnSelect right click always pastes - // if (_settings.CopyOnSelect() || !_core->HasSelection()) - // { - // PasteTextFromClipboard(); - // } - // else - // { - // CopySelectionToClipboard(shiftEnabled, nullptr); - // } - // } - // } - // else if (ptr.PointerDeviceType() == Windows::Devices::Input::PointerDeviceType::Touch) - // { - // const auto contactRect = point.Properties().ContactRect(); - // // Set our touch rect, to start a pan. - // _touchAnchor = winrt::Windows::Foundation::Point{ contactRect.X, contactRect.Y }; - // } args.Handled(true); } @@ -1194,91 +1047,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation _TryStopAutoScroll(ptr.PointerId()); } } - // if (ptr.PointerDeviceType() == Windows::Devices::Input::PointerDeviceType::Mouse || ptr.PointerDeviceType() == Windows::Devices::Input::PointerDeviceType::Pen) - // { - // // Short-circuit isReadOnly check to avoid warning dialog - // if (_focused && !_core->IsInReadOnlyMode() && _CanSendVTMouseInput()) - // { - // _interactivity->_TrySendMouseEvent(point, terminalPosition); - // } - // else if (_focused && point.Properties().IsLeftButtonPressed()) - // { - // if (_singleClickTouchdownPos) - // { - // // Figure out if the user's moved a quarter of a cell's smaller axis away from the clickdown point - // auto& touchdownPoint{ *_singleClickTouchdownPos }; - // auto distance{ std::sqrtf(std::powf(cursorPosition.X - touchdownPoint.X, 2) + std::powf(cursorPosition.Y - touchdownPoint.Y, 2)) }; - // const til::size fontSize{ _core->GetFont().GetSize() }; - - // const auto fontSizeInDips = fontSize.scale(til::math::rounding, 1.0f / _core->RendererScale()); - // if (distance >= (std::min(fontSizeInDips.width(), fontSizeInDips.height()) / 4.f)) - // { - // _core->SetSelectionAnchor(_GetTerminalPosition(touchdownPoint)); - // // stop tracking the touchdown point - // _singleClickTouchdownPos = std::nullopt; - // } - // } - - // _SetEndSelectionPointAtCursor(cursorPosition); - - // const double cursorBelowBottomDist = cursorPosition.Y - SwapChainPanel().Margin().Top - SwapChainPanel().ActualHeight(); - // const double cursorAboveTopDist = -1 * cursorPosition.Y + SwapChainPanel().Margin().Top; - - // constexpr double MinAutoScrollDist = 2.0; // Arbitrary value - // double newAutoScrollVelocity = 0.0; - // if (cursorBelowBottomDist > MinAutoScrollDist) - // { - // newAutoScrollVelocity = _GetAutoScrollSpeed(cursorBelowBottomDist); - // } - // else if (cursorAboveTopDist > MinAutoScrollDist) - // { - // newAutoScrollVelocity = -1.0 * _GetAutoScrollSpeed(cursorAboveTopDist); - // } - - // if (newAutoScrollVelocity != 0) - // { - // _TryStartAutoScroll(point, newAutoScrollVelocity); - // } - // else - // { - // _TryStopAutoScroll(ptr.PointerId()); - // } - // } - - // _core->UpdateHoveredCell(terminalPosition); - // } - // else if (_focused && ptr.PointerDeviceType() == Windows::Devices::Input::PointerDeviceType::Touch && _touchAnchor) - // { - // const auto contactRect = point.Properties().ContactRect(); - // winrt::Windows::Foundation::Point newTouchPoint{ contactRect.X, contactRect.Y }; - // const auto anchor = _touchAnchor.value(); - - // // Our actualFont's size is in pixels, convert to DIPs, which the - // // rest of the Points here are in. - // const til::size fontSize{ _core->GetFont().GetSize() }; - // const auto fontSizeInDips = fontSize.scale(til::math::rounding, 1.0f / _core->RendererScale()); - - // // Get the difference between the point we've dragged to and the start of the touch. - // const float dy = newTouchPoint.Y - anchor.Y; - - // // Start viewport scroll after we've moved more than a half row of text - // if (std::abs(dy) > (fontSizeInDips.height() / 2.0f)) - // { - // // Multiply by -1, because moving the touch point down will - // // create a positive delta, but we want the viewport to move up, - // // so we'll need a negative scroll amount (and the inverse for - // // panning down) - // const float numRows = -1.0f * (dy / fontSizeInDips.height()); - - // const auto currentOffset = ::base::ClampedNumeric(ScrollBar().Value()); - // const auto newValue = numRows + currentOffset; - - // ScrollBar().Value(newValue); - - // // Use this point as our new scroll anchor. - // _touchAnchor = newTouchPoint; - // } - // } args.Handled(true); } @@ -1309,32 +1077,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation terminalPosition, type); - // if (ptr.PointerDeviceType() == Windows::Devices::Input::PointerDeviceType::Mouse || ptr.PointerDeviceType() == Windows::Devices::Input::PointerDeviceType::Pen) - // { - // // Short-circuit isReadOnly check to avoid warning dialog - // if (!_core->IsInReadOnlyMode() && _CanSendVTMouseInput()) - // { - // const auto cursorPosition = point.Position(); - // const auto terminalPosition = _GetTerminalPosition(cursorPosition); - // _interactivity->_TrySendMouseEvent(point, terminalPosition); - // args.Handled(true); - // return; - // } - - // // Only a left click release when copy on select is active should perform a copy. - // // Right clicks and middle clicks should not need to do anything when released. - // if (_settings.CopyOnSelect() && point.Properties().PointerUpdateKind() == Windows::UI::Input::PointerUpdateKind::LeftButtonReleased && _selectionNeedsToBeCopied) - // { - // CopySelectionToClipboard(false, nullptr); - // } - // } - // else if (ptr.PointerDeviceType() == Windows::Devices::Input::PointerDeviceType::Touch) - // { - // _touchAnchor = std::nullopt; - // } - - // _singleClickTouchdownPos = std::nullopt; - _TryStopAutoScroll(ptr.PointerId()); args.Handled(true); @@ -1363,10 +1105,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation const TerminalInput::MouseButtonState state{ props.IsLeftButtonPressed(), props.IsMiddleButtonPressed(), props.IsRightButtonPressed() }; - // auto result = _DoMouseWheel(point.Position(), - // ControlKeyStates{ args.KeyModifiers() }, - // point.Properties().MouseWheelDelta(), - // state); auto mousePosition = point.Position(); auto result = _interactivity->MouseWheel(ControlKeyStates{ args.KeyModifiers() }, @@ -1379,56 +1117,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation } } - // // Method Description: - // // - Actually handle a scrolling event, whether from a mouse wheel or a - // // touchpad scroll. Depending upon what modifier keys are pressed, - // // different actions will take place. - // // * Attempts to first dispatch the mouse scroll as a VT event - // // * If Ctrl+Shift are pressed, then attempts to change our opacity - // // * If just Ctrl is pressed, we'll attempt to "zoom" by changing our font size - // // * Otherwise, just scrolls the content of the viewport - // // Arguments: - // // - point: the location of the mouse during this event - // // - modifiers: The modifiers pressed during this event, in the form of a VirtualKeyModifiers - // // - delta: the mouse wheel delta that triggered this event. - // bool TermControl::_DoMouseWheel(const Windows::Foundation::Point point, - // const ControlKeyStates modifiers, - // const int32_t delta, - // const TerminalInput::MouseButtonState state) - // { - // // Short-circuit isReadOnly check to avoid warning dialog - // if (!_core->IsInReadOnlyMode() && _interactivity->_CanSendVTMouseInput(modifiers)) - // { - // // Most mouse event handlers call - // // _TrySendMouseEvent(point); - // // here with a PointerPoint. However, as of #979, we don't have a - // // PointerPoint to work with. So, we're just going to do a - // // mousewheel event manually - // return _core->SendMouseEvent(_GetTerminalPosition(point), - // WM_MOUSEWHEEL, - // _GetPressedModifierKeys(), - // ::base::saturated_cast(delta), - // state); - // } - - // const auto ctrlPressed = modifiers.IsCtrlPressed(); - // const auto shiftPressed = modifiers.IsShiftPressed(); - - // if (ctrlPressed && shiftPressed) - // { - // _MouseTransparencyHandler(delta); - // } - // else if (ctrlPressed) - // { - // _MouseZoomHandler(delta); - // } - // else - // { - // _MouseScrollHandler(delta, point, state.isLeftButtonDown); - // } - // return false; - // } - // Method Description: // - This is part of the solution to GH#979 // - Manually handle a scrolling event. This is used to help support @@ -1471,88 +1159,10 @@ namespace winrt::Microsoft::Terminal::Control::implementation const auto bg = _settings.DefaultBackground(); _changeBackgroundColor(bg); } - // else - // { - // // GH#5098: Inform the engine of the new opacity of the default text background. - // if (_renderEngine) - // { - // _renderEngine->SetDefaultTextBackgroundOpacity(::base::saturated_cast(_settings.TintOpacity())); - // } - // } } CATCH_LOG(); - // } - // else - // { - - // _InitializeBackgroundBrush(); - // } - // else if (mouseDelta < 0) - // { - // _settings.UseAcrylic(true); - - // //Setting initial opacity set to 1 to ensure smooth transition to acrylic during mouse scroll - // _settings.TintOpacity(1.0); - // } } - // // Method Description: - // // - Adjust the opacity of the acrylic background in response to a mouse - // // scrolling event. - // // Arguments: - // // - mouseDelta: the mouse wheel delta that triggered this event. - // void TermControl::_MouseTransparencyHandler(const double mouseDelta) - // { - // // Transparency is on a scale of [0.0,1.0], so only increment by .01. - // const auto effectiveDelta = mouseDelta < 0 ? -.01 : .01; - - // if (_settings.UseAcrylic()) - // { - // try - // { - // auto acrylicBrush = RootGrid().Background().as(); - // _settings.TintOpacity(acrylicBrush.TintOpacity() + effectiveDelta); - // acrylicBrush.TintOpacity(_settings.TintOpacity()); - - // if (acrylicBrush.TintOpacity() == 1.0) - // { - // _settings.UseAcrylic(false); - // _InitializeBackgroundBrush(); - // const auto bg = _settings.DefaultBackground(); - // _BackgroundColorChanged(bg); - // } - // else - // { - // // GH#5098: Inform the engine of the new opacity of the default text background. - // if (_renderEngine) - // { - // _renderEngine->SetDefaultTextBackgroundOpacity(::base::saturated_cast(_settings.TintOpacity())); - // } - // } - // } - // CATCH_LOG(); - // } - // else if (mouseDelta < 0) - // { - // _settings.UseAcrylic(true); - - // //Setting initial opacity set to 1 to ensure smooth transition to acrylic during mouse scroll - // _settings.TintOpacity(1.0); - // _InitializeBackgroundBrush(); - // } - // } - - // // Method Description: - // // - Adjust the font size of the terminal in response to a mouse scrolling - // // event. - // // Arguments: - // // - mouseDelta: the mouse wheel delta that triggered this event. - // void TermControl::_MouseZoomHandler(const double mouseDelta) - // { - // const auto fontDelta = mouseDelta < 0 ? -1 : 1; - // AdjustFontSize(fontDelta); - // } - // Method Description: // - Reset the font size of the terminal to its default size. // Arguments: @@ -1571,42 +1181,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation _core->AdjustFontSize(fontSizeDelta); } - // // Method Description: - // // - Scroll the visible viewport in response to a mouse wheel event. - // // Arguments: - // // - mouseDelta: the mouse wheel delta that triggered this event. - // // - point: the location of the mouse during this event - // // - isLeftButtonPressed: true iff the left mouse button was pressed during this event. - // void TermControl::_MouseScrollHandler(const double mouseDelta, - // const Windows::Foundation::Point point, - // const bool isLeftButtonPressed) - // { - // const auto currentOffset = ScrollBar().Value(); - - // // negative = down, positive = up - // // However, for us, the signs are flipped. - // // With one of the precision mice, one click is always a multiple of 120 (WHEEL_DELTA), - // // but the "smooth scrolling" mode results in non-int values - // const auto rowDelta = mouseDelta / (-1.0 * WHEEL_DELTA); - - // // WHEEL_PAGESCROLL is a Win32 constant that represents the "scroll one page - // // at a time" setting. If we ignore it, we will scroll a truly absurd number - // // of rows. - // const auto rowsToScroll{ _rowsToScroll == WHEEL_PAGESCROLL ? ViewHeight() : _rowsToScroll }; - // double newValue = (rowsToScroll * rowDelta) + (currentOffset); - - // // The scroll bar's ValueChanged handler will actually move the viewport - // // for us. - // ScrollBar().Value(newValue); - - // if (isLeftButtonPressed) - // { - // // If user is mouse selecting and scrolls, they then point at new character. - // // Make sure selection reflects that immediately. - // _SetEndSelectionPointAtCursor(point); - // } - // } - void TermControl::_ScrollbarChangeHandler(Windows::Foundation::IInspectable const& /*sender*/, Controls::Primitives::RangeBaseValueChangedEventArgs const& args) { @@ -1798,19 +1372,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation _interactivity->GainFocus(); } - // // Method Description - // // - Updates internal params based on system parameters - // void TermControl::_UpdateSystemParameterSettings() noexcept - // { - // if (!SystemParametersInfoW(SPI_GETWHEELSCROLLLINES, 0, &_rowsToScroll, 0)) - // { - // LOG_LAST_ERROR(); - // // If SystemParametersInfoW fails, which it shouldn't, fall back to - // // Windows' default value. - // _rowsToScroll = 3; - // } - // } - // Method Description: // - Event handler for the LostFocus event. This is used to... // - disable accessibility notifications for this TermControl @@ -1849,14 +1410,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation } } - // // Method Description: - // // - Pre-process text pasted (presumably from the clipboard) - // // before sending it over the terminal's connection. - // void TermControl::_SendPastedTextToConnection(const std::wstring& wstr) - // { - // _core->PasteText(winrt::hstring{ wstr }); - // } - // Method Description: // - Triggered when the swapchain changes size. We use this to resize the // terminal buffers to match the new visible size. @@ -2004,14 +1557,14 @@ namespace winrt::Microsoft::Terminal::Control::implementation return _core->WorkingDirectory(); } - // // Method Description: - // // - Given a copy-able selection, get the selected text from the buffer and send it to the - // // Windows Clipboard (CascadiaWin32:main.cpp). - // // - CopyOnSelect does NOT clear the selection - // // Arguments: - // // - singleLine: collapse all of the text to one line - // // - formats: which formats to copy (defined by action's CopyFormatting arg). nullptr - // // if we should defer which formats are copied to the global setting + // Method Description: + // - Given a copy-able selection, get the selected text from the buffer and send it to the + // Windows Clipboard (CascadiaWin32:main.cpp). + // - CopyOnSelect does NOT clear the selection + // Arguments: + // - singleLine: collapse all of the text to one line + // - formats: which formats to copy (defined by action's CopyFormatting arg). nullptr + // if we should defer which formats are copied to the global setting bool TermControl::CopySelectionToClipboard(bool singleLine, const Windows::Foundation::IReference& formats) { if (_closing) @@ -2026,13 +1579,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation // - Initiate a paste operation. void TermControl::PasteTextFromClipboard() { - // // attach TermControl::_SendInputToConnection() as the clipboardDataHandler. - // // This is called when the clipboard data is loaded. - // auto clipboardDataHandler = std::bind(&TermControl::_SendPastedTextToConnection, this, std::placeholders::_1); - // auto pasteArgs = winrt::make_self(clipboardDataHandler); - - // // send paste event up to TermApp - // _PasteFromClipboardHandlers(*this, *pasteArgs); _interactivity->PasteTextFromClipboard(); } @@ -2456,35 +2002,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation eventArgs.FontWeight(weight); } - // // Method Description: - // // - Returns the number of clicks that occurred (double and triple click support). - // // Every call to this function registers a click. - // // Arguments: - // // - clickPos: the (x,y) position of a given cursor (i.e.: mouse cursor). - // // NOTE: origin (0,0) is top-left. - // // - clickTime: the timestamp that the click occurred - // // Return Value: - // // - if the click is in the same position as the last click and within the timeout, the number of clicks within that time window - // // - otherwise, 1 - // const unsigned int TermControl::_NumberOfClicks(winrt::Windows::Foundation::Point clickPos, Timestamp clickTime) - // { - // // if click occurred at a different location or past the multiClickTimer... - // Timestamp delta; - // THROW_IF_FAILED(UInt64Sub(clickTime, _lastMouseClickTimestamp, &delta)); - // if (clickPos != _lastMouseClickPos || delta > _multiClickTimer) - // { - // _multiClickCounter = 1; - // } - // else - // { - // _multiClickCounter++; - // } - - // _lastMouseClickTimestamp = clickTime; - // _lastMouseClickPos = clickPos; - // return _multiClickCounter; - // } - // Method Description: // - Calculates speed of single axis of auto scrolling. It has to allow for both // fast and precise selection. diff --git a/src/cascadia/TerminalControl/TermControl.h b/src/cascadia/TerminalControl/TermControl.h index 5dea19ca5a2..15323981d8d 100644 --- a/src/cascadia/TerminalControl/TermControl.h +++ b/src/cascadia/TerminalControl/TermControl.h @@ -14,7 +14,6 @@ #include "SearchBoxControl.h" #include "ThrottledFunc.h" -// #include "ControlCore.h" #include "ControlInteractivity.h" namespace Microsoft::Console::VirtualTerminal @@ -144,8 +143,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation std::shared_ptr> _updateScrollBar; bool _isInternalScrollBarUpdate; - // unsigned int _rowsToScroll; // Definitely Control/Interactivity - // Auto scroll occurs when user, while selecting, drags cursor outside viewport. View is then scrolled to 'follow' the cursor. double _autoScrollVelocity; std::optional _autoScrollingPointerPoint; @@ -155,31 +152,11 @@ namespace winrt::Microsoft::Terminal::Control::implementation std::optional _cursorTimer; std::optional _blinkTimer; - // // If this is set, then we assume we are in the middle of panning the - // // viewport via touch input. - // std::optional _touchAnchor; - - // using Timestamp = uint64_t; - - // // imported from WinUser - // // Used for PointerPoint.Timestamp Property (https://docs.microsoft.com/en-us/uwp/api/windows.ui.input.pointerpoint.timestamp#Windows_UI_Input_PointerPoint_Timestamp) - // Timestamp _multiClickTimer; - // unsigned int _multiClickCounter; - // Timestamp _lastMouseClickTimestamp; - // std::optional _lastMouseClickPos; - // std::optional _singleClickTouchdownPos; - // std::optional _lastMouseClickPosNoSelection; - // // This field tracks whether the selection has changed meaningfully - // // since it was last copied. It's generally used to prevent copyOnSelect - // // from firing when the pointer _just happens_ to be released over the - // // terminal. - // bool _selectionNeedsToBeCopied; // ->Interactivity - winrt::Windows::UI::Xaml::Controls::SwapChainPanel::LayoutUpdated_revoker _layoutUpdatedRevoker; void _ApplyUISettings(const IControlSettings&); void _UpdateSettingsOnUIThread(); - // void _UpdateSystemParameterSettings() noexcept; + void _InitializeBackgroundBrush(); void _BackgroundColorChangedHandler(const IInspectable& sender, const IInspectable& args); winrt::fire_and_forget _changeBackgroundColor(const til::color bg); @@ -196,27 +173,28 @@ namespace winrt::Microsoft::Terminal::Control::implementation void _PointerExitedHandler(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::Input::PointerRoutedEventArgs const& e); void _MouseWheelHandler(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::Input::PointerRoutedEventArgs const& e); void _ScrollbarChangeHandler(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::Controls::Primitives::RangeBaseValueChangedEventArgs const& e); + void _GotFocusHandler(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::RoutedEventArgs const& e); void _LostFocusHandler(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::RoutedEventArgs const& e); + winrt::fire_and_forget _DragDropHandler(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::DragEventArgs const e); void _DragOverHandler(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::DragEventArgs const& e); + winrt::fire_and_forget _HyperlinkHandler(Windows::Foundation::IInspectable const& sender, Control::OpenHyperlinkEventArgs const& e); void _CursorTimerTick(Windows::Foundation::IInspectable const& sender, Windows::Foundation::IInspectable const& e); void _BlinkTimerTick(Windows::Foundation::IInspectable const& sender, Windows::Foundation::IInspectable const& e); + void _SetEndSelectionPointAtCursor(Windows::Foundation::Point const& cursorPosition); - // void _SendPastedTextToConnection(const std::wstring& wstr); + void _SwapChainSizeChanged(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::SizeChangedEventArgs const& e); void _SwapChainScaleChanged(Windows::UI::Xaml::Controls::SwapChainPanel const& sender, Windows::Foundation::IInspectable const& args); + void _TerminalTabColorChanged(const std::optional color); + void _ScrollPositionChanged(const IInspectable& sender, const Control::ScrollPositionChangedArgs& args); void _CursorPositionChanged(const IInspectable& sender, const IInspectable& args); - // void _MouseScrollHandler(const double mouseDelta, const Windows::Foundation::Point point, const bool isLeftButtonPressed); - // void _MouseZoomHandler(const double delta); - // void _MouseTransparencyHandler(const double delta); - // bool _DoMouseWheel(const Windows::Foundation::Point point, const ::Microsoft::Terminal::Core::ControlKeyStates modifiers, const int32_t delta, const ::Microsoft::Console::VirtualTerminal::TerminalInput::MouseButtonState state); - bool _CapturePointer(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::Input::PointerRoutedEventArgs const& e); bool _ReleasePointerCapture(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::Input::PointerRoutedEventArgs const& e); @@ -231,11 +209,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation bool _TryHandleKeyBinding(const WORD vkey, const WORD scanCode, ::Microsoft::Terminal::Core::ControlKeyStates modifiers) const; void _ClearKeyboardState(const WORD vkey, const WORD scanCode) const noexcept; bool _TrySendKeyEvent(const WORD vkey, const WORD scanCode, ::Microsoft::Terminal::Core::ControlKeyStates modifiers, const bool keyDown); - // bool _TrySendMouseEvent(Windows::UI::Input::PointerPoint const& point); - // bool _CanSendVTMouseInput(); const til::point _GetTerminalPosition(winrt::Windows::Foundation::Point cursorPosition); - // const unsigned int _NumberOfClicks(winrt::Windows::Foundation::Point clickPos, Timestamp clickTime); double _GetAutoScrollSpeed(double cursorDistanceFromBorder) const; void _Search(const winrt::hstring& text, const bool goForward, const bool caseSensitive); From 1b3dd74a1a3b792793fae83b71347d91bb1aed61 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Wed, 31 Mar 2021 06:32:23 -0500 Subject: [PATCH 31/82] This lock is redundant now? --- src/cascadia/TerminalCore/Terminal.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cascadia/TerminalCore/Terminal.cpp b/src/cascadia/TerminalCore/Terminal.cpp index 6b634fa9fdf..7d4e1691721 100644 --- a/src/cascadia/TerminalCore/Terminal.cpp +++ b/src/cascadia/TerminalCore/Terminal.cpp @@ -1196,7 +1196,7 @@ void Terminal::UpdatePatterns() noexcept // visible region is changing void Terminal::ClearPatternTree() noexcept { - // auto lock = LockForWriting(); + auto lock = LockForWriting(); auto oldTree = _patternIntervalTree; _patternIntervalTree = {}; _InvalidatePatternTree(oldTree); From f355f88afb445b8a706aac227cb64ef9ccc718da Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Wed, 31 Mar 2021 09:15:56 -0500 Subject: [PATCH 32/82] Create a control unittesting project --- OpenConsole.sln | 142 +++++++++--------- .../dll/TerminalControl.vcxproj | 6 +- .../Control.UnitTests.vcxproj | 83 ++++++++++ .../UnitTests_Control/ControlCoreTests.cpp | 31 ++++ .../UnitTests_Control/UnitTests_Control.def | 3 + src/cascadia/UnitTests_Control/pch.cpp | 4 + src/cascadia/UnitTests_Control/pch.h | 50 ++++++ src/server/lib/server.vcxproj | 2 +- tools/OpenConsole.psm1 | 2 +- tools/runut.cmd | 1 + tools/tests.xml | 1 + 11 files changed, 255 insertions(+), 70 deletions(-) create mode 100644 src/cascadia/UnitTests_Control/Control.UnitTests.vcxproj create mode 100644 src/cascadia/UnitTests_Control/ControlCoreTests.cpp create mode 100644 src/cascadia/UnitTests_Control/UnitTests_Control.def create mode 100644 src/cascadia/UnitTests_Control/pch.cpp create mode 100644 src/cascadia/UnitTests_Control/pch.h diff --git a/OpenConsole.sln b/OpenConsole.sln index bc9b5383e74..adcae85d90d 100644 --- a/OpenConsole.sln +++ b/OpenConsole.sln @@ -388,6 +388,11 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Control", "Control", "{9921 EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Host.FuzzWrapper", "src\host\ft_fuzzer\Host.FuzzWrapper.vcxproj", "{05D9052F-D78F-478F-968A-2DE38A6DB996}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "UnitTests_Control", "src\cascadia\UnitTests_Control\Control.UnitTests.vcxproj", "{C323DAEE-B307-4C7B-ACE5-7293CBEFCB5B}" + ProjectSection(ProjectDependencies) = postProject + {CA5CAD1A-44BD-4AC7-AC72-6CA5B3AB89ED} = {CA5CAD1A-44BD-4AC7-AC72-6CA5B3AB89ED} + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution AuditMode|Any CPU = AuditMode|Any CPU @@ -3143,73 +3148,6 @@ Global {68A10CD3-AA64-465B-AF5F-ED4E9700543C}.Release|x64.Build.0 = Release|x64 {68A10CD3-AA64-465B-AF5F-ED4E9700543C}.Release|x86.ActiveCfg = Release|Win32 {68A10CD3-AA64-465B-AF5F-ED4E9700543C}.Release|x86.Build.0 = Release|Win32 - {E437B604-3E98-4F40-A927-E173E818EA4B}.AuditMode|Any CPU.ActiveCfg = AuditMode|Win32 - {E437B604-3E98-4F40-A927-E173E818EA4B}.AuditMode|ARM.ActiveCfg = AuditMode|Win32 - {E437B604-3E98-4F40-A927-E173E818EA4B}.AuditMode|ARM64.ActiveCfg = AuditMode|ARM64 - {E437B604-3E98-4F40-A927-E173E818EA4B}.AuditMode|ARM64.Build.0 = AuditMode|ARM64 - {E437B604-3E98-4F40-A927-E173E818EA4B}.AuditMode|DotNet_x64Test.ActiveCfg = AuditMode|Win32 - {E437B604-3E98-4F40-A927-E173E818EA4B}.AuditMode|DotNet_x86Test.ActiveCfg = AuditMode|Win32 - {E437B604-3E98-4F40-A927-E173E818EA4B}.AuditMode|x64.ActiveCfg = AuditMode|x64 - {E437B604-3E98-4F40-A927-E173E818EA4B}.AuditMode|x64.Build.0 = AuditMode|x64 - {E437B604-3E98-4F40-A927-E173E818EA4B}.AuditMode|x86.ActiveCfg = AuditMode|Win32 - {E437B604-3E98-4F40-A927-E173E818EA4B}.AuditMode|x86.Build.0 = AuditMode|Win32 - {E437B604-3E98-4F40-A927-E173E818EA4B}.Debug|Any CPU.ActiveCfg = Debug|Win32 - {E437B604-3E98-4F40-A927-E173E818EA4B}.Debug|ARM.ActiveCfg = Debug|Win32 - {E437B604-3E98-4F40-A927-E173E818EA4B}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {E437B604-3E98-4F40-A927-E173E818EA4B}.Debug|ARM64.Build.0 = Debug|ARM64 - {E437B604-3E98-4F40-A927-E173E818EA4B}.Debug|DotNet_x64Test.ActiveCfg = Debug|Win32 - {E437B604-3E98-4F40-A927-E173E818EA4B}.Debug|DotNet_x86Test.ActiveCfg = Debug|Win32 - {E437B604-3E98-4F40-A927-E173E818EA4B}.Debug|x64.ActiveCfg = Debug|x64 - {E437B604-3E98-4F40-A927-E173E818EA4B}.Debug|x64.Build.0 = Debug|x64 - {E437B604-3E98-4F40-A927-E173E818EA4B}.Debug|x86.ActiveCfg = Debug|Win32 - {E437B604-3E98-4F40-A927-E173E818EA4B}.Debug|x86.Build.0 = Debug|Win32 - {E437B604-3E98-4F40-A927-E173E818EA4B}.Fuzzing|Any CPU.ActiveCfg = Fuzzing|Win32 - {E437B604-3E98-4F40-A927-E173E818EA4B}.Fuzzing|ARM.ActiveCfg = Fuzzing|Win32 - {E437B604-3E98-4F40-A927-E173E818EA4B}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64 - {E437B604-3E98-4F40-A927-E173E818EA4B}.Fuzzing|DotNet_x64Test.ActiveCfg = Fuzzing|Win32 - {E437B604-3E98-4F40-A927-E173E818EA4B}.Fuzzing|DotNet_x86Test.ActiveCfg = Fuzzing|Win32 - {E437B604-3E98-4F40-A927-E173E818EA4B}.Fuzzing|x64.ActiveCfg = Fuzzing|x64 - {E437B604-3E98-4F40-A927-E173E818EA4B}.Fuzzing|x64.Build.0 = Fuzzing|x64 - {E437B604-3E98-4F40-A927-E173E818EA4B}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32 - {E437B604-3E98-4F40-A927-E173E818EA4B}.Release|Any CPU.ActiveCfg = Release|Win32 - {E437B604-3E98-4F40-A927-E173E818EA4B}.Release|ARM.ActiveCfg = Release|Win32 - {E437B604-3E98-4F40-A927-E173E818EA4B}.Release|ARM64.ActiveCfg = Release|ARM64 - {E437B604-3E98-4F40-A927-E173E818EA4B}.Release|ARM64.Build.0 = Release|ARM64 - {E437B604-3E98-4F40-A927-E173E818EA4B}.Release|DotNet_x64Test.ActiveCfg = Release|Win32 - {E437B604-3E98-4F40-A927-E173E818EA4B}.Release|DotNet_x86Test.ActiveCfg = Release|Win32 - {E437B604-3E98-4F40-A927-E173E818EA4B}.Release|x64.ActiveCfg = Release|x64 - {E437B604-3E98-4F40-A927-E173E818EA4B}.Release|x64.Build.0 = Release|x64 - {E437B604-3E98-4F40-A927-E173E818EA4B}.Release|x86.ActiveCfg = Release|Win32 - {E437B604-3E98-4F40-A927-E173E818EA4B}.Release|x86.Build.0 = Release|Win32 - {05D9052F-D78F-478F-968A-2DE38A6DB996}.AuditMode|Any CPU.ActiveCfg = AuditMode|Win32 - {05D9052F-D78F-478F-968A-2DE38A6DB996}.AuditMode|ARM.ActiveCfg = AuditMode|Win32 - {05D9052F-D78F-478F-968A-2DE38A6DB996}.AuditMode|ARM64.ActiveCfg = AuditMode|ARM64 - {05D9052F-D78F-478F-968A-2DE38A6DB996}.AuditMode|DotNet_x64Test.ActiveCfg = AuditMode|Win32 - {05D9052F-D78F-478F-968A-2DE38A6DB996}.AuditMode|DotNet_x86Test.ActiveCfg = AuditMode|Win32 - {05D9052F-D78F-478F-968A-2DE38A6DB996}.AuditMode|x64.ActiveCfg = AuditMode|x64 - {05D9052F-D78F-478F-968A-2DE38A6DB996}.AuditMode|x86.ActiveCfg = AuditMode|Win32 - {05D9052F-D78F-478F-968A-2DE38A6DB996}.Debug|Any CPU.ActiveCfg = Debug|Win32 - {05D9052F-D78F-478F-968A-2DE38A6DB996}.Debug|ARM.ActiveCfg = Debug|Win32 - {05D9052F-D78F-478F-968A-2DE38A6DB996}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {05D9052F-D78F-478F-968A-2DE38A6DB996}.Debug|DotNet_x64Test.ActiveCfg = Debug|Win32 - {05D9052F-D78F-478F-968A-2DE38A6DB996}.Debug|DotNet_x86Test.ActiveCfg = Debug|Win32 - {05D9052F-D78F-478F-968A-2DE38A6DB996}.Debug|x64.ActiveCfg = Debug|x64 - {05D9052F-D78F-478F-968A-2DE38A6DB996}.Debug|x86.ActiveCfg = Debug|Win32 - {05D9052F-D78F-478F-968A-2DE38A6DB996}.Fuzzing|Any CPU.ActiveCfg = Fuzzing|Win32 - {05D9052F-D78F-478F-968A-2DE38A6DB996}.Fuzzing|ARM.ActiveCfg = Fuzzing|Win32 - {05D9052F-D78F-478F-968A-2DE38A6DB996}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64 - {05D9052F-D78F-478F-968A-2DE38A6DB996}.Fuzzing|DotNet_x64Test.ActiveCfg = Fuzzing|Win32 - {05D9052F-D78F-478F-968A-2DE38A6DB996}.Fuzzing|DotNet_x86Test.ActiveCfg = Fuzzing|Win32 - {05D9052F-D78F-478F-968A-2DE38A6DB996}.Fuzzing|x64.ActiveCfg = Fuzzing|x64 - {05D9052F-D78F-478F-968A-2DE38A6DB996}.Fuzzing|x64.Build.0 = Fuzzing|x64 - {05D9052F-D78F-478F-968A-2DE38A6DB996}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32 - {05D9052F-D78F-478F-968A-2DE38A6DB996}.Release|Any CPU.ActiveCfg = Release|Win32 - {05D9052F-D78F-478F-968A-2DE38A6DB996}.Release|ARM.ActiveCfg = Release|Win32 - {05D9052F-D78F-478F-968A-2DE38A6DB996}.Release|ARM64.ActiveCfg = Release|ARM64 - {05D9052F-D78F-478F-968A-2DE38A6DB996}.Release|DotNet_x64Test.ActiveCfg = Release|Win32 - {05D9052F-D78F-478F-968A-2DE38A6DB996}.Release|DotNet_x86Test.ActiveCfg = Release|Win32 - {05D9052F-D78F-478F-968A-2DE38A6DB996}.Release|x64.ActiveCfg = Release|x64 - {05D9052F-D78F-478F-968A-2DE38A6DB996}.Release|x86.ActiveCfg = Release|Win32 {71CC9D78-BA29-4D93-946F-BEF5D9A3A6EF}.AuditMode|Any CPU.ActiveCfg = AuditMode|Win32 {71CC9D78-BA29-4D93-946F-BEF5D9A3A6EF}.AuditMode|ARM.ActiveCfg = AuditMode|Win32 {71CC9D78-BA29-4D93-946F-BEF5D9A3A6EF}.AuditMode|ARM64.ActiveCfg = AuditMode|ARM64 @@ -3248,6 +3186,75 @@ Global {71CC9D78-BA29-4D93-946F-BEF5D9A3A6EF}.Release|x64.Build.0 = Release|x64 {71CC9D78-BA29-4D93-946F-BEF5D9A3A6EF}.Release|x86.ActiveCfg = Release|Win32 {71CC9D78-BA29-4D93-946F-BEF5D9A3A6EF}.Release|x86.Build.0 = Release|Win32 + {05D9052F-D78F-478F-968A-2DE38A6DB996}.AuditMode|Any CPU.ActiveCfg = AuditMode|Win32 + {05D9052F-D78F-478F-968A-2DE38A6DB996}.AuditMode|ARM.ActiveCfg = AuditMode|Win32 + {05D9052F-D78F-478F-968A-2DE38A6DB996}.AuditMode|ARM64.ActiveCfg = AuditMode|ARM64 + {05D9052F-D78F-478F-968A-2DE38A6DB996}.AuditMode|DotNet_x64Test.ActiveCfg = AuditMode|Win32 + {05D9052F-D78F-478F-968A-2DE38A6DB996}.AuditMode|DotNet_x86Test.ActiveCfg = AuditMode|Win32 + {05D9052F-D78F-478F-968A-2DE38A6DB996}.AuditMode|x64.ActiveCfg = AuditMode|x64 + {05D9052F-D78F-478F-968A-2DE38A6DB996}.AuditMode|x86.ActiveCfg = AuditMode|Win32 + {05D9052F-D78F-478F-968A-2DE38A6DB996}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {05D9052F-D78F-478F-968A-2DE38A6DB996}.Debug|ARM.ActiveCfg = Debug|Win32 + {05D9052F-D78F-478F-968A-2DE38A6DB996}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {05D9052F-D78F-478F-968A-2DE38A6DB996}.Debug|DotNet_x64Test.ActiveCfg = Debug|Win32 + {05D9052F-D78F-478F-968A-2DE38A6DB996}.Debug|DotNet_x86Test.ActiveCfg = Debug|Win32 + {05D9052F-D78F-478F-968A-2DE38A6DB996}.Debug|x64.ActiveCfg = Debug|x64 + {05D9052F-D78F-478F-968A-2DE38A6DB996}.Debug|x86.ActiveCfg = Debug|Win32 + {05D9052F-D78F-478F-968A-2DE38A6DB996}.Fuzzing|Any CPU.ActiveCfg = Fuzzing|Win32 + {05D9052F-D78F-478F-968A-2DE38A6DB996}.Fuzzing|ARM.ActiveCfg = Fuzzing|Win32 + {05D9052F-D78F-478F-968A-2DE38A6DB996}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64 + {05D9052F-D78F-478F-968A-2DE38A6DB996}.Fuzzing|DotNet_x64Test.ActiveCfg = Fuzzing|Win32 + {05D9052F-D78F-478F-968A-2DE38A6DB996}.Fuzzing|DotNet_x86Test.ActiveCfg = Fuzzing|Win32 + {05D9052F-D78F-478F-968A-2DE38A6DB996}.Fuzzing|x64.ActiveCfg = Fuzzing|x64 + {05D9052F-D78F-478F-968A-2DE38A6DB996}.Fuzzing|x64.Build.0 = Fuzzing|x64 + {05D9052F-D78F-478F-968A-2DE38A6DB996}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32 + {05D9052F-D78F-478F-968A-2DE38A6DB996}.Release|Any CPU.ActiveCfg = Release|Win32 + {05D9052F-D78F-478F-968A-2DE38A6DB996}.Release|ARM.ActiveCfg = Release|Win32 + {05D9052F-D78F-478F-968A-2DE38A6DB996}.Release|ARM64.ActiveCfg = Release|ARM64 + {05D9052F-D78F-478F-968A-2DE38A6DB996}.Release|DotNet_x64Test.ActiveCfg = Release|Win32 + {05D9052F-D78F-478F-968A-2DE38A6DB996}.Release|DotNet_x86Test.ActiveCfg = Release|Win32 + {05D9052F-D78F-478F-968A-2DE38A6DB996}.Release|x64.ActiveCfg = Release|x64 + {05D9052F-D78F-478F-968A-2DE38A6DB996}.Release|x86.ActiveCfg = Release|Win32 + {C323DAEE-B307-4C7B-ACE5-7293CBEFCB5B}.AuditMode|Any CPU.ActiveCfg = AuditMode|Win32 + {C323DAEE-B307-4C7B-ACE5-7293CBEFCB5B}.AuditMode|ARM.ActiveCfg = AuditMode|Win32 + {C323DAEE-B307-4C7B-ACE5-7293CBEFCB5B}.AuditMode|ARM64.ActiveCfg = AuditMode|ARM64 + {C323DAEE-B307-4C7B-ACE5-7293CBEFCB5B}.AuditMode|ARM64.Build.0 = AuditMode|ARM64 + {C323DAEE-B307-4C7B-ACE5-7293CBEFCB5B}.AuditMode|DotNet_x64Test.ActiveCfg = AuditMode|Win32 + {C323DAEE-B307-4C7B-ACE5-7293CBEFCB5B}.AuditMode|DotNet_x86Test.ActiveCfg = AuditMode|Win32 + {C323DAEE-B307-4C7B-ACE5-7293CBEFCB5B}.AuditMode|x64.ActiveCfg = AuditMode|x64 + {C323DAEE-B307-4C7B-ACE5-7293CBEFCB5B}.AuditMode|x64.Build.0 = AuditMode|x64 + {C323DAEE-B307-4C7B-ACE5-7293CBEFCB5B}.AuditMode|x86.ActiveCfg = AuditMode|Win32 + {C323DAEE-B307-4C7B-ACE5-7293CBEFCB5B}.AuditMode|x86.Build.0 = AuditMode|Win32 + {C323DAEE-B307-4C7B-ACE5-7293CBEFCB5B}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {C323DAEE-B307-4C7B-ACE5-7293CBEFCB5B}.Debug|ARM.ActiveCfg = Debug|Win32 + {C323DAEE-B307-4C7B-ACE5-7293CBEFCB5B}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {C323DAEE-B307-4C7B-ACE5-7293CBEFCB5B}.Debug|ARM64.Build.0 = Debug|ARM64 + {C323DAEE-B307-4C7B-ACE5-7293CBEFCB5B}.Debug|DotNet_x64Test.ActiveCfg = Debug|Win32 + {C323DAEE-B307-4C7B-ACE5-7293CBEFCB5B}.Debug|DotNet_x86Test.ActiveCfg = Debug|Win32 + {C323DAEE-B307-4C7B-ACE5-7293CBEFCB5B}.Debug|x64.ActiveCfg = Debug|x64 + {C323DAEE-B307-4C7B-ACE5-7293CBEFCB5B}.Debug|x64.Build.0 = Debug|x64 + {C323DAEE-B307-4C7B-ACE5-7293CBEFCB5B}.Debug|x86.ActiveCfg = Debug|Win32 + {C323DAEE-B307-4C7B-ACE5-7293CBEFCB5B}.Debug|x86.Build.0 = Debug|Win32 + {C323DAEE-B307-4C7B-ACE5-7293CBEFCB5B}.Fuzzing|Any CPU.ActiveCfg = Fuzzing|Win32 + {C323DAEE-B307-4C7B-ACE5-7293CBEFCB5B}.Fuzzing|ARM.ActiveCfg = Fuzzing|Win32 + {C323DAEE-B307-4C7B-ACE5-7293CBEFCB5B}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64 + {C323DAEE-B307-4C7B-ACE5-7293CBEFCB5B}.Fuzzing|ARM64.Build.0 = Fuzzing|ARM64 + {C323DAEE-B307-4C7B-ACE5-7293CBEFCB5B}.Fuzzing|DotNet_x64Test.ActiveCfg = Fuzzing|Win32 + {C323DAEE-B307-4C7B-ACE5-7293CBEFCB5B}.Fuzzing|DotNet_x86Test.ActiveCfg = Fuzzing|Win32 + {C323DAEE-B307-4C7B-ACE5-7293CBEFCB5B}.Fuzzing|x64.ActiveCfg = Fuzzing|x64 + {C323DAEE-B307-4C7B-ACE5-7293CBEFCB5B}.Fuzzing|x64.Build.0 = Fuzzing|x64 + {C323DAEE-B307-4C7B-ACE5-7293CBEFCB5B}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32 + {C323DAEE-B307-4C7B-ACE5-7293CBEFCB5B}.Fuzzing|x86.Build.0 = Fuzzing|Win32 + {C323DAEE-B307-4C7B-ACE5-7293CBEFCB5B}.Release|Any CPU.ActiveCfg = Release|Win32 + {C323DAEE-B307-4C7B-ACE5-7293CBEFCB5B}.Release|ARM.ActiveCfg = Release|Win32 + {C323DAEE-B307-4C7B-ACE5-7293CBEFCB5B}.Release|ARM64.ActiveCfg = Release|ARM64 + {C323DAEE-B307-4C7B-ACE5-7293CBEFCB5B}.Release|ARM64.Build.0 = Release|ARM64 + {C323DAEE-B307-4C7B-ACE5-7293CBEFCB5B}.Release|DotNet_x64Test.ActiveCfg = Release|Win32 + {C323DAEE-B307-4C7B-ACE5-7293CBEFCB5B}.Release|DotNet_x86Test.ActiveCfg = Release|Win32 + {C323DAEE-B307-4C7B-ACE5-7293CBEFCB5B}.Release|x64.ActiveCfg = Release|x64 + {C323DAEE-B307-4C7B-ACE5-7293CBEFCB5B}.Release|x64.Build.0 = Release|x64 + {C323DAEE-B307-4C7B-ACE5-7293CBEFCB5B}.Release|x86.ActiveCfg = Release|Win32 + {C323DAEE-B307-4C7B-ACE5-7293CBEFCB5B}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -3344,6 +3351,7 @@ Global {77875138-BB08-49F9-8BB1-409C2150E0E1} = {59840756-302F-44DF-AA47-441A9D673202} {9921CA0A-320C-4460-8623-3A3196E7F4CB} = {59840756-302F-44DF-AA47-441A9D673202} {05D9052F-D78F-478F-968A-2DE38A6DB996} = {E8F24881-5E37-4362-B191-A3BA0ED7F4EB} + {C323DAEE-B307-4C7B-ACE5-7293CBEFCB5B} = {BDB237B6-1D1D-400F-84CC-40A58FA59C8E} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {3140B1B7-C8EE-43D1-A772-D82A7061A271} diff --git a/src/cascadia/TerminalControl/dll/TerminalControl.vcxproj b/src/cascadia/TerminalControl/dll/TerminalControl.vcxproj index 89fb2b3cd68..95049e49873 100644 --- a/src/cascadia/TerminalControl/dll/TerminalControl.vcxproj +++ b/src/cascadia/TerminalControl/dll/TerminalControl.vcxproj @@ -83,7 +83,11 @@ 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) - + /INCLUDE:_DllMain@12 /INCLUDE:DllMain diff --git a/src/cascadia/UnitTests_Control/Control.UnitTests.vcxproj b/src/cascadia/UnitTests_Control/Control.UnitTests.vcxproj new file mode 100644 index 00000000000..8c85d1b6ad8 --- /dev/null +++ b/src/cascadia/UnitTests_Control/Control.UnitTests.vcxproj @@ -0,0 +1,83 @@ + + + + {C323DAEE-B307-4C7B-ACE5-7293CBEFCB5B} + Win32Proj + ControlUnitTests + UnitTests_Control + Control.UnitTests + DynamicLibrary + 10.0.18362.0 + 10.0.18362.0 + true + + + + + + + + + + + + + + + Create + + + + + + + + + + + + + + + + + + + + + + + + + + + $(OpenConsoleDir)src\inc;$(OpenConsoleDir)src\cascadia\inc;$(OpenConsoleDir)src\inc\test;$(WinRT_IncludePath)\..\cppwinrt\winrt;"$(OpenConsoleDir)\src\cascadia\TerminalControl\Generated Files";%(AdditionalIncludeDirectories) + pch.h + + + 4702;%(DisableSpecificWarnings) + + + onecoreuap.lib;%(AdditionalDependencies) + + /INCLUDE:_DllMain@12 + /INCLUDE:DllMain + + + + + true + true + + + + + + + + diff --git a/src/cascadia/UnitTests_Control/ControlCoreTests.cpp b/src/cascadia/UnitTests_Control/ControlCoreTests.cpp new file mode 100644 index 00000000000..515b2f30d06 --- /dev/null +++ b/src/cascadia/UnitTests_Control/ControlCoreTests.cpp @@ -0,0 +1,31 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +#include "pch.h" +#include "../TerminalControl/EventArgs.h" + +using namespace Microsoft::Console; +using namespace WEX::Logging; +using namespace WEX::TestExecution; +using namespace WEX::Common; + +using namespace winrt; +using namespace winrt::Microsoft::Terminal; + +namespace ControlUnitTests +{ + class ControlCoreTests + { + BEGIN_TEST_CLASS(ControlCoreTests) + END_TEST_CLASS() + + TEST_METHOD(PlaceholderTest); + }; + + void ControlCoreTests::PlaceholderTest() + { + Log::Comment(L"This test is a placeholder while the rest of this test library is being authored."); + VERIFY_IS_TRUE(true); + } + +} diff --git a/src/cascadia/UnitTests_Control/UnitTests_Control.def b/src/cascadia/UnitTests_Control/UnitTests_Control.def new file mode 100644 index 00000000000..8c1a02932d0 --- /dev/null +++ b/src/cascadia/UnitTests_Control/UnitTests_Control.def @@ -0,0 +1,3 @@ +EXPORTS +DllCanUnloadNow = WINRT_CanUnloadNow PRIVATE +DllGetActivationFactory = WINRT_GetActivationFactory PRIVATE diff --git a/src/cascadia/UnitTests_Control/pch.cpp b/src/cascadia/UnitTests_Control/pch.cpp new file mode 100644 index 00000000000..3c27d44d570 --- /dev/null +++ b/src/cascadia/UnitTests_Control/pch.cpp @@ -0,0 +1,4 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +#include "pch.h" diff --git a/src/cascadia/UnitTests_Control/pch.h b/src/cascadia/UnitTests_Control/pch.h new file mode 100644 index 00000000000..8239e461c15 --- /dev/null +++ b/src/cascadia/UnitTests_Control/pch.h @@ -0,0 +1,50 @@ +/*++ +Copyright (c) Microsoft Corporation +Licensed under the MIT license. +--*/ + +#pragma once + +// Block minwindef.h min/max macros to prevent conflict +#define NOMINMAX + +#define WIN32_LEAN_AND_MEAN +#define NOMCX +#define NOHELP +#define NOCOMM + +#include +#include + +// Manually include til after we include Windows.Foundation to give it winrt superpowers +#define BLOCK_TIL +// This includes support libraries from the CRT, STL, WIL, and GSL +#include "LibraryIncludes.h" +// This is inexplicable, but for whatever reason, cppwinrt conflicts with the +// SDK definition of this function, so the only fix is to undef it. +// from WinBase.h +// Windows::UI::Xaml::Media::Animation::IStoryboard::GetCurrentTime +#ifdef GetCurrentTime +#undef GetCurrentTime +#endif + +#include +#include +#include + +#include +#include "consoletaeftemplates.hpp" + +#include +#include +#include +#include + +// Manually include til after we include Windows.Foundation to give it winrt superpowers +#include "til.h" + +// Common includes for most tests: +#include "../../inc/argb.h" +#include "../../inc/conattrs.hpp" +#include "../../types/inc/utils.hpp" +#include "../../inc/DefaultSettings.h" diff --git a/src/server/lib/server.vcxproj b/src/server/lib/server.vcxproj index 4ceafacd986..957ef8c0051 100644 --- a/src/server/lib/server.vcxproj +++ b/src/server/lib/server.vcxproj @@ -59,7 +59,7 @@ - {e437b604-3e98-4f40-a927-e173e818ea4b} + {71CC9D78-BA29-4D93-946F-BEF5D9A3A6EF} diff --git a/tools/OpenConsole.psm1 b/tools/OpenConsole.psm1 index f8595f8db6a..6e2180ce208 100644 --- a/tools/OpenConsole.psm1 +++ b/tools/OpenConsole.psm1 @@ -169,7 +169,7 @@ function Invoke-OpenConsoleTests() [switch]$FTOnly, [parameter(Mandatory=$false)] - [ValidateSet('host', 'interactivityWin32', 'terminal', 'adapter', 'feature', 'uia', 'textbuffer', 'til', 'types', 'terminalCore', 'terminalApp', 'localTerminalApp', 'localSettingsModel', 'unitRemoting')] + [ValidateSet('host', 'interactivityWin32', 'terminal', 'adapter', 'feature', 'uia', 'textbuffer', 'til', 'types', 'terminalCore', 'terminalApp', 'localTerminalApp', 'localSettingsModel', 'unitRemoting', 'unitControl')] [string]$Test, [parameter(Mandatory=$false)] diff --git a/tools/runut.cmd b/tools/runut.cmd index 7b7571c678b..3da64494fc3 100644 --- a/tools/runut.cmd +++ b/tools/runut.cmd @@ -24,6 +24,7 @@ call %TAEF% ^ %OPENCON%\bin\%PLATFORM%\%_LAST_BUILD_CONF%\til.unit.tests.dll ^ %OPENCON%\bin\%PLATFORM%\%_LAST_BUILD_CONF%\UnitTests_TerminalApp\Terminal.App.Unit.Tests.dll ^ %OPENCON%\bin\%PLATFORM%\%_LAST_BUILD_CONF%\UnitTests_Remoting\Remoting.UnitTests.dll ^ + %OPENCON%\bin\%PLATFORM%\%_LAST_BUILD_CONF%\UnitTests_Control\Control.UnitTests.dll ^ %_TestHostAppPath%\TerminalApp.LocalTests.dll ^ %_TestHostAppPath%\SettingsModel.LocalTests.dll ^ %* diff --git a/tools/tests.xml b/tools/tests.xml index b392c15472b..17c51ceecc3 100644 --- a/tools/tests.xml +++ b/tools/tests.xml @@ -7,6 +7,7 @@ + From 78bd8068b27e1df942a7cad9dc71eb0577cf0849 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Wed, 31 Mar 2021 09:43:23 -0500 Subject: [PATCH 33/82] Need settings to instantiate controls --- .../UnitTests_Control/ControlCoreTests.cpp | 23 ++++- .../UnitTests_Control/MockControlSettings.h | 87 +++++++++++++++++++ src/cascadia/UnitTests_Control/pch.h | 3 + 3 files changed, 109 insertions(+), 4 deletions(-) create mode 100644 src/cascadia/UnitTests_Control/MockControlSettings.h diff --git a/src/cascadia/UnitTests_Control/ControlCoreTests.cpp b/src/cascadia/UnitTests_Control/ControlCoreTests.cpp index 515b2f30d06..34f6867c0d2 100644 --- a/src/cascadia/UnitTests_Control/ControlCoreTests.cpp +++ b/src/cascadia/UnitTests_Control/ControlCoreTests.cpp @@ -3,6 +3,7 @@ #include "pch.h" #include "../TerminalControl/EventArgs.h" +#include "MockControlSettings.h" using namespace Microsoft::Console; using namespace WEX::Logging; @@ -19,13 +20,27 @@ namespace ControlUnitTests BEGIN_TEST_CLASS(ControlCoreTests) END_TEST_CLASS() - TEST_METHOD(PlaceholderTest); + TEST_METHOD(OnStackSettings); + TEST_METHOD(ComPtrSettings); }; - void ControlCoreTests::PlaceholderTest() + void ControlCoreTests::OnStackSettings() { - Log::Comment(L"This test is a placeholder while the rest of this test library is being authored."); - VERIFY_IS_TRUE(true); + Log::Comment(L"Just make sure we can instantiate a settings obj on the stack"); + + MockControlSettings settings; + + Log::Comment(L"Verify literally any setting, it doesn't matter"); + VERIFY_ARE_EQUAL(DEFAULT_FOREGROUND, settings.DefaultForeground()); + } + void ControlCoreTests::ComPtrSettings() + { + Log::Comment(L"Just make sure we can instantiate a settings obj in a com_ptr"); + winrt::com_ptr settings; + settings.attach(new MockControlSettings()); + + Log::Comment(L"Verify literally any setting, it doesn't matter"); + VERIFY_ARE_EQUAL(DEFAULT_FOREGROUND, settings->DefaultForeground()); } } diff --git a/src/cascadia/UnitTests_Control/MockControlSettings.h b/src/cascadia/UnitTests_Control/MockControlSettings.h new file mode 100644 index 00000000000..b6bcadf2f17 --- /dev/null +++ b/src/cascadia/UnitTests_Control/MockControlSettings.h @@ -0,0 +1,87 @@ +/*++ +Copyright (c) Microsoft Corporation +Licensed under the MIT license. +--*/ +#pragma once + +#include "../inc/cppwinrt_utils.h" +#include +#include + +namespace ControlUnitTests +{ + class MockControlSettings : public winrt::implements + { + public: + MockControlSettings() = default; + + // --------------------------- Core Settings --------------------------- + // All of these settings are defined in ICoreSettings. + + WINRT_PROPERTY(til::color, DefaultForeground, DEFAULT_FOREGROUND); + WINRT_PROPERTY(til::color, DefaultBackground, DEFAULT_BACKGROUND); + WINRT_PROPERTY(til::color, SelectionBackground, DEFAULT_FOREGROUND); + WINRT_PROPERTY(int32_t, HistorySize, DEFAULT_HISTORY_SIZE); + WINRT_PROPERTY(int32_t, InitialRows, 30); + WINRT_PROPERTY(int32_t, InitialCols, 80); + + WINRT_PROPERTY(bool, SnapOnInput, true); + WINRT_PROPERTY(bool, AltGrAliasing, true); + WINRT_PROPERTY(til::color, CursorColor, DEFAULT_CURSOR_COLOR); + WINRT_PROPERTY(winrt::Microsoft::Terminal::Core::CursorStyle, CursorShape, winrt::Microsoft::Terminal::Core::CursorStyle::Vintage); + WINRT_PROPERTY(uint32_t, CursorHeight, DEFAULT_CURSOR_HEIGHT); + WINRT_PROPERTY(winrt::hstring, WordDelimiters, DEFAULT_WORD_DELIMITERS); + WINRT_PROPERTY(bool, CopyOnSelect, false); + WINRT_PROPERTY(bool, InputServiceWarning, true); + WINRT_PROPERTY(bool, FocusFollowMouse, false); + + WINRT_PROPERTY(winrt::Windows::Foundation::IReference, TabColor, nullptr); + + WINRT_PROPERTY(winrt::Windows::Foundation::IReference, StartingTabColor, nullptr); + + // ------------------------ End of Core Settings ----------------------- + + WINRT_PROPERTY(winrt::hstring, ProfileName); + WINRT_PROPERTY(bool, UseAcrylic, false); + WINRT_PROPERTY(double, TintOpacity, 0.5); + WINRT_PROPERTY(winrt::hstring, Padding, DEFAULT_PADDING); + WINRT_PROPERTY(winrt::hstring, FontFace, DEFAULT_FONT_FACE); + WINRT_PROPERTY(int32_t, FontSize, DEFAULT_FONT_SIZE); + + WINRT_PROPERTY(winrt::Windows::UI::Text::FontWeight, FontWeight); + + WINRT_PROPERTY(winrt::hstring, BackgroundImage); + WINRT_PROPERTY(double, BackgroundImageOpacity, 1.0); + + WINRT_PROPERTY(winrt::Windows::UI::Xaml::Media::Stretch, BackgroundImageStretchMode, winrt::Windows::UI::Xaml::Media::Stretch::UniformToFill); + WINRT_PROPERTY(winrt::Windows::UI::Xaml::HorizontalAlignment, BackgroundImageHorizontalAlignment, winrt::Windows::UI::Xaml::HorizontalAlignment::Center); + WINRT_PROPERTY(winrt::Windows::UI::Xaml::VerticalAlignment, BackgroundImageVerticalAlignment, winrt::Windows::UI::Xaml::VerticalAlignment::Center); + + WINRT_PROPERTY(winrt::Microsoft::Terminal::Control::IKeyBindings, KeyBindings, nullptr); + + WINRT_PROPERTY(winrt::hstring, Commandline); + WINRT_PROPERTY(winrt::hstring, StartingDirectory); + WINRT_PROPERTY(winrt::hstring, StartingTitle); + WINRT_PROPERTY(bool, SuppressApplicationTitle); + WINRT_PROPERTY(winrt::hstring, EnvironmentVariables); + + WINRT_PROPERTY(winrt::Microsoft::Terminal::Control::ScrollbarState, ScrollState, winrt::Microsoft::Terminal::Control::ScrollbarState::Visible); + + WINRT_PROPERTY(winrt::Microsoft::Terminal::Control::TextAntialiasingMode, AntialiasingMode, winrt::Microsoft::Terminal::Control::TextAntialiasingMode::Grayscale); + + WINRT_PROPERTY(bool, RetroTerminalEffect, false); + WINRT_PROPERTY(bool, ForceFullRepaintRendering, false); + WINRT_PROPERTY(bool, SoftwareRendering, false); + WINRT_PROPERTY(bool, ForceVTInput, false); + + WINRT_PROPERTY(winrt::hstring, PixelShaderPath); + + private: + std::array _ColorTable; + + public: + winrt::Microsoft::Terminal::Core::Color GetColorTableEntry(int32_t index) noexcept { return _ColorTable.at(index); } + std::array ColorTable() { return _ColorTable; } + void ColorTable(std::array /*colors*/) {} + }; +} diff --git a/src/cascadia/UnitTests_Control/pch.h b/src/cascadia/UnitTests_Control/pch.h index 8239e461c15..b43edb6551e 100644 --- a/src/cascadia/UnitTests_Control/pch.h +++ b/src/cascadia/UnitTests_Control/pch.h @@ -40,6 +40,9 @@ Licensed under the MIT license. #include #include +#include +#include + // Manually include til after we include Windows.Foundation to give it winrt superpowers #include "til.h" From 8c5fabaa14bb3195e3442523ab5c0d1f5d8b55b0 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Wed, 31 Mar 2021 12:42:16 -0500 Subject: [PATCH 34/82] Successfully create an instance of ControlCore in the tests --- .../Control.UnitTests.vcxproj | 2 + .../UnitTests_Control/ControlCoreTests.cpp | 26 ++++++++++ .../UnitTests_Control/MockConnection.h | 48 +++++++++++++++++++ .../UnitTests_Control/MockControlSettings.h | 2 +- src/cascadia/UnitTests_Control/pch.h | 1 + 5 files changed, 78 insertions(+), 1 deletion(-) create mode 100644 src/cascadia/UnitTests_Control/MockConnection.h diff --git a/src/cascadia/UnitTests_Control/Control.UnitTests.vcxproj b/src/cascadia/UnitTests_Control/Control.UnitTests.vcxproj index 8c85d1b6ad8..14e4b44ebf4 100644 --- a/src/cascadia/UnitTests_Control/Control.UnitTests.vcxproj +++ b/src/cascadia/UnitTests_Control/Control.UnitTests.vcxproj @@ -18,6 +18,8 @@ + + diff --git a/src/cascadia/UnitTests_Control/ControlCoreTests.cpp b/src/cascadia/UnitTests_Control/ControlCoreTests.cpp index 34f6867c0d2..1c7ee39544d 100644 --- a/src/cascadia/UnitTests_Control/ControlCoreTests.cpp +++ b/src/cascadia/UnitTests_Control/ControlCoreTests.cpp @@ -3,7 +3,9 @@ #include "pch.h" #include "../TerminalControl/EventArgs.h" +#include "../TerminalControl/ControlCore.h" #include "MockControlSettings.h" +#include "MockConnection.h" using namespace Microsoft::Console; using namespace WEX::Logging; @@ -22,6 +24,14 @@ namespace ControlUnitTests TEST_METHOD(OnStackSettings); TEST_METHOD(ComPtrSettings); + TEST_METHOD(InstantiateCore); + + TEST_CLASS_SETUP(ModuleSetup) + { + winrt::init_apartment(winrt::apartment_type::single_threaded); + + return true; + } }; void ControlCoreTests::OnStackSettings() @@ -43,4 +53,20 @@ namespace ControlUnitTests VERIFY_ARE_EQUAL(DEFAULT_FOREGROUND, settings->DefaultForeground()); } + void ControlCoreTests::InstantiateCore() + { + Log::Comment(L"Create settings object"); + winrt::com_ptr settings; + settings.attach(new MockControlSettings()); + + Log::Comment(L"Create connection object"); + winrt::com_ptr conn; + conn.attach(new MockConnection()); + VERIFY_IS_NOT_NULL(conn); + + Log::Comment(L"Create ControlCore object"); + auto core = winrt::make_self(*settings, *conn); + VERIFY_IS_NOT_NULL(core); + } + } diff --git a/src/cascadia/UnitTests_Control/MockConnection.h b/src/cascadia/UnitTests_Control/MockConnection.h new file mode 100644 index 00000000000..81b46f0b42d --- /dev/null +++ b/src/cascadia/UnitTests_Control/MockConnection.h @@ -0,0 +1,48 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. +// +// This is literally just the EchoConnection, but we can't use the +// EchoConnection because it's in TerminalConnection.dll and loading that in +// these tests is fraught with peril. Easier just to have a local copy. + +#pragma once + +#include "../cascadia/inc/cppwinrt_utils.h" + +namespace ControlUnitTests +{ + class MockConnection : public winrt::implements + { + public: + MockConnection() noexcept = default; + + void Start() noexcept {}; + void WriteInput(winrt::hstring const& data) + { + std::wstringstream prettyPrint; + for (const auto& wch : data) + { + if (wch < 0x20) + { + prettyPrint << L"^" << gsl::narrow_cast(wch + 0x40); + } + else if (wch == 0x7f) + { + prettyPrint << L"0x7f"; + } + else + { + prettyPrint << wch; + } + } + _TerminalOutputHandlers(prettyPrint.str()); + } + void Resize(uint32_t /*rows*/, uint32_t /*columns*/) noexcept {} + void Close() noexcept {} + + winrt::Microsoft::Terminal::TerminalConnection::ConnectionState State() const noexcept { return winrt::Microsoft::Terminal::TerminalConnection::ConnectionState::Connected; } + + WINRT_CALLBACK(TerminalOutput, winrt::Microsoft::Terminal::TerminalConnection::TerminalOutputHandler); + TYPED_EVENT(StateChanged, winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection, IInspectable); + }; +} diff --git a/src/cascadia/UnitTests_Control/MockControlSettings.h b/src/cascadia/UnitTests_Control/MockControlSettings.h index b6bcadf2f17..de9e736720f 100644 --- a/src/cascadia/UnitTests_Control/MockControlSettings.h +++ b/src/cascadia/UnitTests_Control/MockControlSettings.h @@ -10,7 +10,7 @@ Licensed under the MIT license. namespace ControlUnitTests { - class MockControlSettings : public winrt::implements + class MockControlSettings : public winrt::implements { public: MockControlSettings() = default; diff --git a/src/cascadia/UnitTests_Control/pch.h b/src/cascadia/UnitTests_Control/pch.h index b43edb6551e..7568822f28f 100644 --- a/src/cascadia/UnitTests_Control/pch.h +++ b/src/cascadia/UnitTests_Control/pch.h @@ -42,6 +42,7 @@ Licensed under the MIT license. #include #include +#include // Manually include til after we include Windows.Foundation to give it winrt superpowers #include "til.h" From ae4d2f2e9dcf8dfba211cfd9f96704f58e79d0c5 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Wed, 31 Mar 2021 17:31:30 -0500 Subject: [PATCH 35/82] Start writing real tests for all this, which is just about insane --- src/cascadia/TerminalControl/ControlCore.cpp | 14 ++- src/cascadia/TerminalControl/ControlCore.h | 16 ++- .../TerminalControl/ControlInteractivity.h | 9 ++ .../Control.UnitTests.vcxproj | 1 + .../UnitTests_Control/ControlCoreTests.cpp | 98 +++++++++++++++++++ .../ControlInteractivityTests.cpp | 52 ++++++++++ 6 files changed, 182 insertions(+), 8 deletions(-) create mode 100644 src/cascadia/UnitTests_Control/ControlInteractivityTests.cpp diff --git a/src/cascadia/TerminalControl/ControlCore.cpp b/src/cascadia/TerminalControl/ControlCore.cpp index 9c3440accf2..cee7b41e528 100644 --- a/src/cascadia/TerminalControl/ControlCore.cpp +++ b/src/cascadia/TerminalControl/ControlCore.cpp @@ -106,6 +106,11 @@ namespace winrt::Microsoft::Terminal::Control::implementation _terminal->UpdateSettings(settings); } + ControlCore::~ControlCore() + { + Close(); + } + bool ControlCore::InitializeTerminal(const double actualWidth, const double actualHeight, const double compositionScaleX, @@ -365,12 +370,14 @@ namespace winrt::Microsoft::Terminal::Control::implementation void ControlCore::AdjustOpacity(const double adjustment) { + auto newOpacity = std::clamp(_settings.TintOpacity() + adjustment, + 0.0, + 1.0); if (_settings.UseAcrylic()) { try { // auto acrylicBrush = RootGrid().Background().as(); - auto newOpacity = _settings.TintOpacity() + adjustment; _settings.TintOpacity(newOpacity); // acrylicBrush.TintOpacity(_settings.TintOpacity()); @@ -397,9 +404,10 @@ namespace winrt::Microsoft::Terminal::Control::implementation _settings.UseAcrylic(true); //Setting initial opacity set to 1 to ensure smooth transition to acrylic during mouse scroll - _settings.TintOpacity(1.0); + newOpacity = std::clamp(1.0 + adjustment, 0.0, 1.0); + _settings.TintOpacity(newOpacity); - auto eventArgs = winrt::make_self(1.0); + auto eventArgs = winrt::make_self(newOpacity); _TransparencyChangedHandlers(*this, *eventArgs); } } diff --git a/src/cascadia/TerminalControl/ControlCore.h b/src/cascadia/TerminalControl/ControlCore.h index 93eeb9ffbbd..678b9d7e43d 100644 --- a/src/cascadia/TerminalControl/ControlCore.h +++ b/src/cascadia/TerminalControl/ControlCore.h @@ -14,6 +14,12 @@ #include "cppwinrt_utils.h" #include "ThrottledFunc.h" +namespace ControlUnitTests +{ + class ControlCoreTests; + class ControlInteractivityTests; +}; + namespace winrt::Microsoft::Terminal::Control::implementation { struct ControlCore : ControlCoreT @@ -21,6 +27,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation public: ControlCore(IControlSettings settings, TerminalConnection::ITerminalConnection connection); + ~ControlCore(); bool InitializeTerminal(const double actualWidth, const double actualHeight, @@ -173,7 +180,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation double _panelHeight{ 0 }; double _compositionScaleX{ 0 }; double _compositionScaleY{ 0 }; - til::color _backgroundColor; // This is _in_ Terminal already! + til::color _backgroundColor; // !TODO! This is _in_ Terminal already! void _SetFontSize(int fontSize); void _UpdateFont(const bool initialUpdate = false); @@ -202,11 +209,10 @@ namespace winrt::Microsoft::Terminal::Control::implementation void RenderEngineSwapChainChanged(); #pragma endregion - public: - //////////////////////////////////////////////////////////////////////// - // These methods are new - void _raiseHoveredHyperlinkChanged(); + + friend class ControlUnitTests::ControlCoreTests; + friend class ControlUnitTests::ControlInteractivityTests; }; } diff --git a/src/cascadia/TerminalControl/ControlInteractivity.h b/src/cascadia/TerminalControl/ControlInteractivity.h index 4f598681096..bb7c3c7bdd6 100644 --- a/src/cascadia/TerminalControl/ControlInteractivity.h +++ b/src/cascadia/TerminalControl/ControlInteractivity.h @@ -15,6 +15,12 @@ namespace Microsoft::Console::VirtualTerminal struct MouseButtonState; } +namespace ControlUnitTests +{ + class ControlCoreTests; + class ControlInteractivityTests; +}; + namespace winrt::Microsoft::Terminal::Control::implementation { struct ControlInteractivity : ControlInteractivityT @@ -103,6 +109,9 @@ namespace winrt::Microsoft::Terminal::Control::implementation void _SendPastedTextToConnection(const std::wstring& wstr); TYPED_EVENT(OpenHyperlink, IInspectable, Control::OpenHyperlinkEventArgs); TYPED_EVENT(PasteFromClipboard, IInspectable, Control::PasteFromClipboardEventArgs); + + friend class ControlUnitTests::ControlCoreTests; + friend class ControlUnitTests::ControlInteractivityTests; }; } diff --git a/src/cascadia/UnitTests_Control/Control.UnitTests.vcxproj b/src/cascadia/UnitTests_Control/Control.UnitTests.vcxproj index 14e4b44ebf4..c155262cd40 100644 --- a/src/cascadia/UnitTests_Control/Control.UnitTests.vcxproj +++ b/src/cascadia/UnitTests_Control/Control.UnitTests.vcxproj @@ -25,6 +25,7 @@ + Create diff --git a/src/cascadia/UnitTests_Control/ControlCoreTests.cpp b/src/cascadia/UnitTests_Control/ControlCoreTests.cpp index 1c7ee39544d..e26979f8971 100644 --- a/src/cascadia/UnitTests_Control/ControlCoreTests.cpp +++ b/src/cascadia/UnitTests_Control/ControlCoreTests.cpp @@ -25,6 +25,8 @@ namespace ControlUnitTests TEST_METHOD(OnStackSettings); TEST_METHOD(ComPtrSettings); TEST_METHOD(InstantiateCore); + TEST_METHOD(TestInitialize); + TEST_METHOD(TestAdjustAcrylic); TEST_CLASS_SETUP(ModuleSetup) { @@ -69,4 +71,100 @@ namespace ControlUnitTests VERIFY_IS_NOT_NULL(core); } + void ControlCoreTests::TestInitialize() + { + Log::Comment(L"Create settings object"); + winrt::com_ptr settings; + settings.attach(new MockControlSettings()); + + Log::Comment(L"Create connection object"); + winrt::com_ptr conn; + conn.attach(new MockConnection()); + VERIFY_IS_NOT_NULL(conn); + + Log::Comment(L"Create ControlCore object"); + auto core = winrt::make_self(*settings, *conn); + VERIFY_IS_NOT_NULL(core); + + VERIFY_IS_FALSE(core->_initializedTerminal); + // "Cascadia Mono" ends up with an actual size of 9x19 at 96DPI. So + // let's just arbitrarily start with a 270x380px (30x20 chars) window + core->InitializeTerminal(270, 380, 1.0, 1.0); + VERIFY_IS_TRUE(core->_initializedTerminal); + VERIFY_ARE_EQUAL(30, core->_terminal->GetViewport().Width()); + } + + void ControlCoreTests::TestAdjustAcrylic() + { + winrt::com_ptr settings; + settings.attach(new MockControlSettings()); + winrt::com_ptr conn; + conn.attach(new MockConnection()); + + settings->UseAcrylic(true); + settings->TintOpacity(0.5f); + + Log::Comment(L"Create ControlCore object"); + auto core = winrt::make_self(*settings, *conn); + VERIFY_IS_NOT_NULL(core); + + // A callback to make sure that we're raising TransparencyChanged events + double expectedOpacity = 0.5; + auto opacityCallback = [&](auto&&, Control::TransparencyChangedEventArgs args) mutable { + VERIFY_ARE_EQUAL(expectedOpacity, args.Opacity()); + VERIFY_ARE_EQUAL(expectedOpacity, settings->TintOpacity()); + VERIFY_ARE_EQUAL(expectedOpacity, core->_settings.TintOpacity()); + + if (expectedOpacity < 1.0) + { + VERIFY_IS_TRUE(settings->UseAcrylic()); + VERIFY_IS_TRUE(core->_settings.UseAcrylic()); + } + VERIFY_ARE_EQUAL(expectedOpacity < 1.0, settings->UseAcrylic()); + VERIFY_ARE_EQUAL(expectedOpacity < 1.0, core->_settings.UseAcrylic()); + }; + core->TransparencyChanged(opacityCallback); + + VERIFY_IS_FALSE(core->_initializedTerminal); + // "Cascadia Mono" ends up with an actual size of 9x19 at 96DPI. So + // let's just arbitrarily start with a 270x380px (30x20 chars) window + core->InitializeTerminal(270, 380, 1.0, 1.0); + VERIFY_IS_TRUE(core->_initializedTerminal); + + Log::Comment(L"Increasing opacity till fully opaque"); + expectedOpacity += 0.1; // = 0.6; + core->AdjustOpacity(0.1); + expectedOpacity += 0.1; // = 0.7; + core->AdjustOpacity(0.1); + expectedOpacity += 0.1; // = 0.8; + core->AdjustOpacity(0.1); + expectedOpacity += 0.1; // = 0.9; + core->AdjustOpacity(0.1); + expectedOpacity += 0.1; // = 1.0; + // cast to float because floating point numbers are mean + VERIFY_ARE_EQUAL(1.0f, base::saturated_cast(expectedOpacity)); + core->AdjustOpacity(0.1); + + Log::Comment(L"Increasing opacity more doesn't actually change it to be >1.0"); + // DebugBreak(); + expectedOpacity = 1.0; + core->AdjustOpacity(0.1); + + Log::Comment(L"Decrease opacity"); + expectedOpacity -= 0.25; // = 0.75; + core->AdjustOpacity(-0.25); + expectedOpacity -= 0.25; // = 0.5; + core->AdjustOpacity(-0.25); + expectedOpacity -= 0.25; // = 0.25; + core->AdjustOpacity(-0.25); + expectedOpacity -= 0.25; // = 0.05; + // cast to float because floating point numbers are mean + VERIFY_ARE_EQUAL(0.0f, base::saturated_cast(expectedOpacity)); + core->AdjustOpacity(-0.25); + + Log::Comment(L"Decreasing opacity more doesn't actually change it to be < 0"); + expectedOpacity = 0.0; + core->AdjustOpacity(-0.25); + } + } diff --git a/src/cascadia/UnitTests_Control/ControlInteractivityTests.cpp b/src/cascadia/UnitTests_Control/ControlInteractivityTests.cpp new file mode 100644 index 00000000000..157abdfe6f4 --- /dev/null +++ b/src/cascadia/UnitTests_Control/ControlInteractivityTests.cpp @@ -0,0 +1,52 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +#include "pch.h" +#include "../TerminalControl/EventArgs.h" +#include "../TerminalControl/ControlInteractivity.h" +#include "MockControlSettings.h" +#include "MockConnection.h" + +using namespace Microsoft::Console; +using namespace WEX::Logging; +using namespace WEX::TestExecution; +using namespace WEX::Common; + +using namespace winrt; +using namespace winrt::Microsoft::Terminal; + +namespace ControlUnitTests +{ + class ControlInteractivityTests + { + BEGIN_TEST_CLASS(ControlInteractivityTests) + END_TEST_CLASS() + + TEST_METHOD(TestAdjustAcrylic); + + TEST_CLASS_SETUP(ClassSetup) + { + winrt::init_apartment(winrt::apartment_type::single_threaded); + + return true; + } + }; + + void ControlInteractivityTests::TestAdjustAcrylic() + { + winrt::com_ptr settings; + settings.attach(new MockControlSettings()); + winrt::com_ptr conn; + conn.attach(new MockConnection()); + + settings->UseAcrylic(true); + settings->TintOpacity(0.5f); + + Log::Comment(L"Create ControlCore object"); + auto interactivity = winrt::make_self(*settings, *conn); + VERIFY_IS_NOT_NULL(interactivity); + auto core = interactivity->_core; + VERIFY_IS_NOT_NULL(core); + } + +} From fbc317525a656c630a97fc1927a7e483b25d55e4 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Fri, 2 Apr 2021 06:24:22 -0500 Subject: [PATCH 36/82] And interactivity tests! --- .../ControlInteractivityTests.cpp | 63 ++++++++++++++++++- 1 file changed, 62 insertions(+), 1 deletion(-) diff --git a/src/cascadia/UnitTests_Control/ControlInteractivityTests.cpp b/src/cascadia/UnitTests_Control/ControlInteractivityTests.cpp index 157abdfe6f4..1e19b545e7a 100644 --- a/src/cascadia/UnitTests_Control/ControlInteractivityTests.cpp +++ b/src/cascadia/UnitTests_Control/ControlInteractivityTests.cpp @@ -7,13 +7,14 @@ #include "MockControlSettings.h" #include "MockConnection.h" -using namespace Microsoft::Console; +using namespace ::Microsoft::Console; using namespace WEX::Logging; using namespace WEX::TestExecution; using namespace WEX::Common; using namespace winrt; using namespace winrt::Microsoft::Terminal; +using namespace ::Microsoft::Terminal::Core; namespace ControlUnitTests { @@ -34,6 +35,11 @@ namespace ControlUnitTests void ControlInteractivityTests::TestAdjustAcrylic() { + Log::Comment(L"Test that scrolling the mouse wheel with Ctrl+Shift changes opacity"); + Log::Comment(L"(This test won't log as it goes, because it does some 200 verifications.)"); + + WEX::TestExecution::SetVerifyOutput verifyOutputScope{ WEX::TestExecution::VerifyOutputSettings::LogOnlyFailures }; + winrt::com_ptr settings; settings.attach(new MockControlSettings()); winrt::com_ptr conn; @@ -47,6 +53,61 @@ namespace ControlUnitTests VERIFY_IS_NOT_NULL(interactivity); auto core = interactivity->_core; VERIFY_IS_NOT_NULL(core); + + // A callback to make sure that we're raising TransparencyChanged events + double expectedOpacity = 0.5; + auto opacityCallback = [&](auto&&, Control::TransparencyChangedEventArgs args) mutable { + VERIFY_ARE_EQUAL(expectedOpacity, args.Opacity()); + VERIFY_ARE_EQUAL(expectedOpacity, settings->TintOpacity()); + VERIFY_ARE_EQUAL(expectedOpacity, core->_settings.TintOpacity()); + + if (expectedOpacity < 1.0) + { + VERIFY_IS_TRUE(settings->UseAcrylic()); + VERIFY_IS_TRUE(core->_settings.UseAcrylic()); + } + VERIFY_ARE_EQUAL(expectedOpacity < 1.0, settings->UseAcrylic()); + VERIFY_ARE_EQUAL(expectedOpacity < 1.0, core->_settings.UseAcrylic()); + }; + core->TransparencyChanged(opacityCallback); + + const auto modifiers = ControlKeyStates(ControlKeyStates::RightCtrlPressed | ControlKeyStates::ShiftPressed); + + Log::Comment(L"Scroll in the positive direction, increasing opacity"); + // Scroll more than enough times to get to 1.0 from .5. + for (int i = 0; i < 55; i++) + { + // each mouse wheel only adjusts opacity by .01 + expectedOpacity += 0.01; + if (expectedOpacity >= 1.0) + { + expectedOpacity = 1.0; + } + + // The mouse location and buttons don't matter here. + interactivity->MouseWheel(modifiers, + 30, + til::point{ 0, 0 }, + { false, false, false }); + } + + Log::Comment(L"Scroll in the negative direction, decreasing opacity"); + // Scroll more than enough times to get to 0.0 from 1.0 + for (int i = 0; i < 105; i++) + { + // each mouse wheel only adjusts opacity by .01 + expectedOpacity -= 0.01; + if (expectedOpacity <= 0.0) + { + expectedOpacity = 0.0; + } + + // The mouse location and buttons don't matter here. + interactivity->MouseWheel(modifiers, + 30, + til::point{ 0, 0 }, + { false, false, false }); + } } } From c37c0730c1a7176fa3b5dcb47003558c2f2e892a Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Fri, 2 Apr 2021 07:23:19 -0500 Subject: [PATCH 37/82] Fix mousewheeling opactiy in the control --- src/cascadia/TerminalControl/TermControl.cpp | 29 ++++++++++---------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/src/cascadia/TerminalControl/TermControl.cpp b/src/cascadia/TerminalControl/TermControl.cpp index 0963db499cf..3984c0121fa 100644 --- a/src/cascadia/TerminalControl/TermControl.cpp +++ b/src/cascadia/TerminalControl/TermControl.cpp @@ -1140,25 +1140,24 @@ namespace winrt::Microsoft::Terminal::Control::implementation return _interactivity->MouseWheel(modifiers, delta, _GetTerminalPosition(location), state); } - winrt::fire_and_forget TermControl::_coreTransparencyChanged(const IInspectable& sender, - const Control::TransparencyChangedEventArgs& args) + // Method Description: + // - Called in response to the core's TransparencyChanged event. We'll use + // this to update our background brush. + // - The Core should have already updated the TintOpacity and UseAcrylic + // properties in the _settings. + // Arguments: + // - + // Return Value: + // - + winrt::fire_and_forget TermControl::_coreTransparencyChanged(const IInspectable& /*sender*/, + const Control::TransparencyChangedEventArgs& /*args*/) { - const auto newOpacity = args.Opacity(); co_await resume_foreground(Dispatcher()); - // if (_settings.UseAcrylic()) - // { try { - auto acrylicBrush = RootGrid().Background().as(); - acrylicBrush.TintOpacity(newOpacity); - - if (newOpacity == 1.0) - { - _settings.UseAcrylic(false); - _InitializeBackgroundBrush(); - const auto bg = _settings.DefaultBackground(); - _changeBackgroundColor(bg); - } + _InitializeBackgroundBrush(); + const auto bg = _settings.DefaultBackground(); + _changeBackgroundColor(bg); } CATCH_LOG(); } From 5591ef0742de63e0915223f24e8d2ee38ade6043 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Fri, 2 Apr 2021 09:03:15 -0500 Subject: [PATCH 38/82] Taking this lock is redundant now? It causes a deadlock? --- .../TerminalControl/ControlInteractivity.cpp | 33 ------------------- src/cascadia/TerminalCore/Terminal.cpp | 2 +- 2 files changed, 1 insertion(+), 34 deletions(-) diff --git a/src/cascadia/TerminalControl/ControlInteractivity.cpp b/src/cascadia/TerminalControl/ControlInteractivity.cpp index 3aaa8f356be..8d4a58a8330 100644 --- a/src/cascadia/TerminalControl/ControlInteractivity.cpp +++ b/src/cascadia/TerminalControl/ControlInteractivity.cpp @@ -417,7 +417,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation uiButton = WM_MOUSEWHEEL; } - // const auto modifiers = _GetPressedModifierKeys(); const TerminalInput::MouseButtonState state{ props.IsLeftButtonPressed(), props.IsMiddleButtonPressed(), props.IsRightButtonPressed() }; @@ -484,38 +483,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation // Transparency is on a scale of [0.0,1.0], so only increment by .01. const auto effectiveDelta = mouseDelta < 0 ? -.01 : .01; _core->AdjustOpacity(effectiveDelta); - - // if (_settings.UseAcrylic()) - // { - // try - // { - // auto acrylicBrush = RootGrid().Background().as(); - // _settings.TintOpacity(acrylicBrush.TintOpacity() + effectiveDelta); - // acrylicBrush.TintOpacity(_settings.TintOpacity()); - - // if (acrylicBrush.TintOpacity() == 1.0) - // { - // _settings.UseAcrylic(false); - // _InitializeBackgroundBrush(); - // COLORREF bg = _settings.DefaultBackground(); - // _changeBackgroundColor(bg); - // } - // else - // { - // // GH#5098: Inform the engine of the new opacity of the default text background. - // _core->SetBackgroundOpacity(::base::saturated_cast(_settings.TintOpacity())); - // } - // } - // CATCH_LOG(); - // } - // else if (mouseDelta < 0) - // { - // _settings.UseAcrylic(true); - - // //Setting initial opacity set to 1 to ensure smooth transition to acrylic during mouse scroll - // _settings.TintOpacity(1.0); - // _InitializeBackgroundBrush(); - // } } // Method Description: diff --git a/src/cascadia/TerminalCore/Terminal.cpp b/src/cascadia/TerminalCore/Terminal.cpp index 7d4e1691721..6b634fa9fdf 100644 --- a/src/cascadia/TerminalCore/Terminal.cpp +++ b/src/cascadia/TerminalCore/Terminal.cpp @@ -1196,7 +1196,7 @@ void Terminal::UpdatePatterns() noexcept // visible region is changing void Terminal::ClearPatternTree() noexcept { - auto lock = LockForWriting(); + // auto lock = LockForWriting(); auto oldTree = _patternIntervalTree; _patternIntervalTree = {}; _InvalidatePatternTree(oldTree); From 6dfa1b6202113524428751c8abd16fe17499f9db Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Fri, 2 Apr 2021 09:32:53 -0500 Subject: [PATCH 39/82] Fiz the scrollbar --- src/cascadia/TerminalControl/ControlCore.cpp | 2 +- .../TerminalControl/ControlInteractivity.cpp | 55 ++++++++++++------- .../TerminalControl/ControlInteractivity.h | 3 + src/cascadia/TerminalControl/TermControl.cpp | 1 + 4 files changed, 40 insertions(+), 21 deletions(-) diff --git a/src/cascadia/TerminalControl/ControlCore.cpp b/src/cascadia/TerminalControl/ControlCore.cpp index cee7b41e528..69edccab9ae 100644 --- a/src/cascadia/TerminalControl/ControlCore.cpp +++ b/src/cascadia/TerminalControl/ControlCore.cpp @@ -979,7 +979,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation // - The height of the terminal in lines of text int ControlCore::BufferHeight() const { - return _terminal->GetViewport().BottomExclusive(); + return _terminal->GetBufferHeight(); } void ControlCore::_TerminalWarningBell() diff --git a/src/cascadia/TerminalControl/ControlInteractivity.cpp b/src/cascadia/TerminalControl/ControlInteractivity.cpp index 8d4a58a8330..c1f7ade1d0d 100644 --- a/src/cascadia/TerminalControl/ControlInteractivity.cpp +++ b/src/cascadia/TerminalControl/ControlInteractivity.cpp @@ -319,13 +319,9 @@ namespace winrt::Microsoft::Terminal::Control::implementation const auto currentOffset = ::base::ClampedNumeric(_core->ScrollOffset()); const auto newValue = numRows + currentOffset; - // !TODO! - Very worried about using UserScrollViewport as - // opposed to the ScrollBar().Value() setter. Originally setting - // the scrollbar value would raise a event handled in - // _ScrollbarChangeHandler, which would _then_ scroll the core, - // and start the _updateScrollBar ThrottledFunc to update the - // scroll position. I'm worried that won't work like this. - _core->UserScrollViewport(newValue); + // Update the Core's viewport position, and raise a + // ScrollPositionChanged event to update the scrollbar + _updateScrollbar(newValue); // ScrollBar().Value(newValue); // Use this point as our new scroll anchor. @@ -521,26 +517,45 @@ namespace winrt::Microsoft::Terminal::Control::implementation const auto rowsToScroll{ _rowsToScroll == WHEEL_PAGESCROLL ? _core->ViewHeight() : _rowsToScroll }; double newValue = (rowsToScroll * rowDelta) + (currentOffset); - // The scroll bar's ValueChanged handler will actually move the viewport - // for us. - // ScrollBar().Value(newValue); - - // !TODO! - Very worried about using UserScrollViewport as - // opposed to the ScrollBar().Value() setter. Originally setting - // the scrollbar value would raise a event handled in - // _ScrollbarChangeHandler, which would _then_ scroll the core, - // and start the _updateScrollBar ThrottledFunc to update the - // scroll position. I'm worried that won't work like this. - _core->UserScrollViewport(::base::saturated_cast(newValue)); + // Update the Core's viewport position, and raise a + // ScrollPositionChanged event to update the scrollbar + _updateScrollbar(::base::saturated_cast(newValue)); if (isLeftButtonPressed) { - // If user is mouse selecting and scrolls, they then point at new character. - // Make sure selection reflects that immediately. + // If user is mouse selecting and scrolls, they then point at new + // character. Make sure selection reflects that immediately. _SetEndSelectionPoint(terminalPosition); } } + // Method Description: + // - Update the scroll position in such a way that should update the + // scrollbar. For example, when scrolling the buffer with the mouse or + // touch input. This will both update the Core's Terminal's buffer + // location, then also raise our own ScrollPositionChanged event. + // UserScrollViewport _won't_ raise the core's ScrollPositionChanged + // event, because it's assumed that's already being called from a context + // that knows about the change to the scrollbar. So we need to raise the + // event on our own. + // - The hosting control should make sure to listen to our own + // ScrollPositionChanged event and use that as an opportunity to update + // the location of the scrollbar. + // Arguments: + // - newValue: The new top of the viewport + // Return Value: + // - + void ControlInteractivity::_updateScrollbar(const int newValue) + { + _core->UserScrollViewport(newValue); + + // _core->ScrollOffset() is new set to newValue + auto scrollArgs = winrt::make_self(_core->ScrollOffset(), + _core->ViewHeight(), + _core->BufferHeight()); + _ScrollPositionChangedHandlers(*this, *scrollArgs); + } + void ControlInteractivity::_HyperlinkHandler(const std::wstring_view uri) { // Save things we need to resume later. diff --git a/src/cascadia/TerminalControl/ControlInteractivity.h b/src/cascadia/TerminalControl/ControlInteractivity.h index bb7c3c7bdd6..cdde32c1fd0 100644 --- a/src/cascadia/TerminalControl/ControlInteractivity.h +++ b/src/cascadia/TerminalControl/ControlInteractivity.h @@ -107,8 +107,11 @@ namespace winrt::Microsoft::Terminal::Control::implementation void _SetEndSelectionPoint(const til::point terminalPosition); void _SendPastedTextToConnection(const std::wstring& wstr); + void _updateScrollbar(const int newValue); + TYPED_EVENT(OpenHyperlink, IInspectable, Control::OpenHyperlinkEventArgs); TYPED_EVENT(PasteFromClipboard, IInspectable, Control::PasteFromClipboardEventArgs); + TYPED_EVENT(ScrollPositionChanged, IInspectable, Control::ScrollPositionChangedArgs); friend class ControlUnitTests::ControlCoreTests; friend class ControlUnitTests::ControlInteractivityTests; diff --git a/src/cascadia/TerminalControl/TermControl.cpp b/src/cascadia/TerminalControl/TermControl.cpp index 3984c0121fa..8ad7d26c475 100644 --- a/src/cascadia/TerminalControl/TermControl.cpp +++ b/src/cascadia/TerminalControl/TermControl.cpp @@ -70,6 +70,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation _core->TransparencyChanged({ get_weak(), &TermControl::_coreTransparencyChanged }); _interactivity->OpenHyperlink({ get_weak(), &TermControl::_HyperlinkHandler }); + _interactivity->ScrollPositionChanged({ get_weak(), &TermControl::_ScrollPositionChanged }); // Initialize the terminal only once the swapchainpanel is loaded - that // way, we'll be able to query the real pixel size it got on layout _layoutUpdatedRevoker = SwapChainPanel().LayoutUpdated(winrt::auto_revoke, [this](auto /*s*/, auto /*e*/) { From ff8cd22973540da0d754e8e37c7789b709560750 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Fri, 2 Apr 2021 11:36:25 -0500 Subject: [PATCH 40/82] Whoop, a test for mouse scrolling! --- .../TerminalControl/ControlInteractivity.cpp | 2 + src/cascadia/TerminalControl/TermControl.cpp | 1 + .../ControlInteractivityTests.cpp | 117 +++++++++++++++++- .../UnitTests_Control/MockConnection.h | 18 +-- 4 files changed, 120 insertions(+), 18 deletions(-) diff --git a/src/cascadia/TerminalControl/ControlInteractivity.cpp b/src/cascadia/TerminalControl/ControlInteractivity.cpp index c1f7ade1d0d..f4d29f099c5 100644 --- a/src/cascadia/TerminalControl/ControlInteractivity.cpp +++ b/src/cascadia/TerminalControl/ControlInteractivity.cpp @@ -42,6 +42,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation void ControlInteractivity::Initialize() { + _UpdateSystemParameterSettings(); + // import value from WinUser (convert from milli-seconds to micro-seconds) _multiClickTimer = GetDoubleClickTime() * 1000; } diff --git a/src/cascadia/TerminalControl/TermControl.cpp b/src/cascadia/TerminalControl/TermControl.cpp index 8ad7d26c475..7031c20e9ef 100644 --- a/src/cascadia/TerminalControl/TermControl.cpp +++ b/src/cascadia/TerminalControl/TermControl.cpp @@ -600,6 +600,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation { return false; } + _interactivity->Initialize(); _AttachDxgiSwapChainToXaml(_core->GetSwapChainHandle()); diff --git a/src/cascadia/UnitTests_Control/ControlInteractivityTests.cpp b/src/cascadia/UnitTests_Control/ControlInteractivityTests.cpp index 1e19b545e7a..f8d9e10ff52 100644 --- a/src/cascadia/UnitTests_Control/ControlInteractivityTests.cpp +++ b/src/cascadia/UnitTests_Control/ControlInteractivityTests.cpp @@ -24,6 +24,8 @@ namespace ControlUnitTests END_TEST_CLASS() TEST_METHOD(TestAdjustAcrylic); + TEST_METHOD(TestPanWithTouch); + TEST_METHOD(TestScrollWithMouse); TEST_CLASS_SETUP(ClassSetup) { @@ -48,7 +50,7 @@ namespace ControlUnitTests settings->UseAcrylic(true); settings->TintOpacity(0.5f); - Log::Comment(L"Create ControlCore object"); + Log::Comment(L"Create ControlInteractivity object"); auto interactivity = winrt::make_self(*settings, *conn); VERIFY_IS_NOT_NULL(interactivity); auto core = interactivity->_core; @@ -110,4 +112,117 @@ namespace ControlUnitTests } } + void ControlInteractivityTests::TestPanWithTouch() + { + VERIFY_IS_TRUE(false); + } + void ControlInteractivityTests::TestScrollWithMouse() + { + WEX::TestExecution::DisableVerifyExceptions disableVerifyExceptions{}; + + winrt::com_ptr settings; + settings.attach(new MockControlSettings()); + winrt::com_ptr conn; + conn.attach(new MockConnection()); + + settings->UseAcrylic(true); + settings->TintOpacity(0.5f); + + Log::Comment(L"Create ControlInteractivity object"); + auto interactivity = winrt::make_self(*settings, *conn); + VERIFY_IS_NOT_NULL(interactivity); + auto core = interactivity->_core; + VERIFY_IS_NOT_NULL(core); + // "Cascadia Mono" ends up with an actual size of 9x19 at 96DPI. So + // let's just arbitrarily start with a 270x380px (30x20 chars) window + core->InitializeTerminal(270, 380, 1.0, 1.0); + VERIFY_IS_TRUE(core->_initializedTerminal); + VERIFY_ARE_EQUAL(20, core->_terminal->GetViewport().Height()); + interactivity->Initialize(); + // For the sake of this test, scroll one line at a time + interactivity->_rowsToScroll = 1; + + int expectedTop = 0; + int expectedViewHeight = 20; + int expectedBufferHeight = 20; + + auto scrollChangedHandler = [&](auto&&, const Control::ScrollPositionChangedArgs& args) mutable { + VERIFY_ARE_EQUAL(expectedTop, args.ViewTop()); + VERIFY_ARE_EQUAL(expectedViewHeight, args.ViewHeight()); + VERIFY_ARE_EQUAL(expectedBufferHeight, args.BufferSize()); + }; + core->ScrollPositionChanged(scrollChangedHandler); + interactivity->ScrollPositionChanged(scrollChangedHandler); + + for (int i = 0; i < 40; ++i) + { + Log::Comment(NoThrowString().Format(L"Writing line #%d", i)); + // The \r\n in the 19th loop will cause the view to start moving + if (i >= 19) + { + expectedTop++; + expectedBufferHeight++; + } + + conn->WriteInput(L"Foo\r\n"); + } + // We printed that 40 times, but the final \r\n bumped the view down one MORE row. + VERIFY_ARE_EQUAL(20, core->_terminal->GetViewport().Height()); + VERIFY_ARE_EQUAL(21, core->ScrollOffset()); + VERIFY_ARE_EQUAL(20, core->ViewHeight()); + VERIFY_ARE_EQUAL(41, core->BufferHeight()); + + Log::Comment(L"Scroll up a line"); + const auto modifiers = ControlKeyStates(); + expectedBufferHeight = 41; + expectedTop = 20; + // DebugBreak(); + interactivity->MouseWheel(modifiers, + WHEEL_DELTA, + til::point{ 0, 0 }, + { false, false, false }); + + Log::Comment(L"Scroll up 19 more times, to the top"); + for (int i = 0; i < 20; ++i) + { + expectedTop--; + interactivity->MouseWheel(modifiers, + WHEEL_DELTA, + til::point{ 0, 0 }, + { false, false, false }); + } + Log::Comment(L"Scrolling up more should do nothing"); + expectedTop = 0; + interactivity->MouseWheel(modifiers, + WHEEL_DELTA, + til::point{ 0, 0 }, + { false, false, false }); + interactivity->MouseWheel(modifiers, + WHEEL_DELTA, + til::point{ 0, 0 }, + { false, false, false }); + + Log::Comment(L"Scroll down 21 more times, to the bottom"); + for (int i = 0; i < 21; ++i) + { + expectedTop++; + interactivity->MouseWheel(modifiers, + -WHEEL_DELTA, + til::point{ 0, 0 }, + { false, false, false }); + } + Log::Comment(L"Scrolling up more should do nothing"); + expectedTop = 21; + interactivity->MouseWheel(modifiers, + -WHEEL_DELTA, + til::point{ 0, 0 }, + { false, false, false }); + interactivity->MouseWheel(modifiers, + -WHEEL_DELTA, + til::point{ 0, 0 }, + { false, false, false }); + + VERIFY_IS_TRUE(false); + } + } diff --git a/src/cascadia/UnitTests_Control/MockConnection.h b/src/cascadia/UnitTests_Control/MockConnection.h index 81b46f0b42d..14b024df108 100644 --- a/src/cascadia/UnitTests_Control/MockConnection.h +++ b/src/cascadia/UnitTests_Control/MockConnection.h @@ -19,23 +19,7 @@ namespace ControlUnitTests void Start() noexcept {}; void WriteInput(winrt::hstring const& data) { - std::wstringstream prettyPrint; - for (const auto& wch : data) - { - if (wch < 0x20) - { - prettyPrint << L"^" << gsl::narrow_cast(wch + 0x40); - } - else if (wch == 0x7f) - { - prettyPrint << L"0x7f"; - } - else - { - prettyPrint << wch; - } - } - _TerminalOutputHandlers(prettyPrint.str()); + _TerminalOutputHandlers(data); } void Resize(uint32_t /*rows*/, uint32_t /*columns*/) noexcept {} void Close() noexcept {} From 01d248f4e1643a524d07490fc08bf88fae870919 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Tue, 6 Apr 2021 10:20:54 -0500 Subject: [PATCH 41/82] Yank the PointerPoint from the function signature --- src/cascadia/TerminalControl/ControlCore.cpp | 14 +- src/cascadia/TerminalControl/ControlCore.h | 1 + .../TerminalControl/ControlInteractivity.cpp | 442 ++++++++++-------- .../TerminalControl/ControlInteractivity.h | 35 +- src/cascadia/TerminalControl/TermControl.cpp | 161 +++++-- src/cascadia/TerminalControl/TermControl.h | 4 + .../ControlInteractivityTests.cpp | 51 +- 7 files changed, 460 insertions(+), 248 deletions(-) diff --git a/src/cascadia/TerminalControl/ControlCore.cpp b/src/cascadia/TerminalControl/ControlCore.cpp index 69edccab9ae..e0d16ed760f 100644 --- a/src/cascadia/TerminalControl/ControlCore.cpp +++ b/src/cascadia/TerminalControl/ControlCore.cpp @@ -65,10 +65,16 @@ namespace winrt::Microsoft::Terminal::Control::implementation auto onReceiveOutputFn = [this](const hstring str) { _terminal->Write(str); - // !TODO!: _updatePatternLocations should happen in the Core, but it's - // a ThrottledFunc, which needs a CoreDispatcher. How do we plan on - // dealing with that? - // _updatePatternLocations->Run(); + // NOTE: We're raising an event here to inform the TermControl that + // output has been recieved, so it can queue up a throttled + // UpdatePatternLocations call. In the future, we should have the + // _updatePatternLocations ThrottledFunc internal to this class, and + // run on this object's dispatcher queue. + // + // We're not doing that quite yet, because the Core will eventually + // be out-of-proc from the UI thread, and won't be able to just use + // the UI thread as the dispatcher queue thread. + _ReceivedOutputHandlers(*this, nullptr); }; _connectionOutputEventToken = _connection.TerminalOutput(onReceiveOutputFn); diff --git a/src/cascadia/TerminalControl/ControlCore.h b/src/cascadia/TerminalControl/ControlCore.h index 678b9d7e43d..f612bdb6803 100644 --- a/src/cascadia/TerminalControl/ControlCore.h +++ b/src/cascadia/TerminalControl/ControlCore.h @@ -146,6 +146,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation TYPED_EVENT(RendererWarning, IInspectable, Control::RendererWarningArgs); TYPED_EVENT(RaiseNotice, IInspectable, Control::NoticeEventArgs); TYPED_EVENT(TransparencyChanged, IInspectable, Control::TransparencyChangedEventArgs); + TYPED_EVENT(ReceivedOutput, IInspectable, IInspectable); // clang-format on private: diff --git a/src/cascadia/TerminalControl/ControlInteractivity.cpp b/src/cascadia/TerminalControl/ControlInteractivity.cpp index f4d29f099c5..cfd1f707215 100644 --- a/src/cascadia/TerminalControl/ControlInteractivity.cpp +++ b/src/cascadia/TerminalControl/ControlInteractivity.cpp @@ -145,159 +145,189 @@ namespace winrt::Microsoft::Terminal::Control::implementation _core->PasteText(winrt::hstring{ wstr }); } - // TODO: Don't take a Windows::UI::Input::PointerPoint here. No WInUI here. - void ControlInteractivity::PointerPressed(const winrt::Windows::UI::Input::PointerPoint point, + // TODO: Don't take a Windows::UI::Input::PointerPoint here. No WinUI here. + void ControlInteractivity::PointerPressed(const winrt::Windows::Foundation::Point mouseCursorPosition, + TerminalInput::MouseButtonState buttonState, + const unsigned int pointerUpdateKind, + const uint64_t timestamp, const ::Microsoft::Terminal::Core::ControlKeyStates modifiers, const bool /*focused*/, - const til::point terminalPosition, - const winrt::Windows::Devices::Input::PointerDeviceType type) + const til::point terminalPosition) { - if (type == Windows::Devices::Input::PointerDeviceType::Mouse || - type == Windows::Devices::Input::PointerDeviceType::Pen) + const auto altEnabled = modifiers.IsAltPressed(); + const auto shiftEnabled = modifiers.IsShiftPressed(); + const auto ctrlEnabled = modifiers.IsCtrlPressed(); + + // const auto cursorPosition = point.Position(); + + // GH#9396: we prioritize hyper-link over VT mouse events + // + // !TODO! Before we'd lock the terminal before getting the hyperlink. Do we still need to? + auto hyperlink = _core->GetHyperlink(terminalPosition); + if (buttonState.isLeftButtonDown && + ctrlEnabled && !hyperlink.empty()) { - const auto altEnabled = modifiers.IsAltPressed(); - const auto shiftEnabled = modifiers.IsShiftPressed(); - const auto ctrlEnabled = modifiers.IsCtrlPressed(); - - const auto cursorPosition = point.Position(); - - // GH#9396: we prioritize hyper-link over VT mouse events - // - // !TODO! Before we'd lock the terminal before getting the hyperlink. Do we still need to? - auto hyperlink = _core->GetHyperlink(terminalPosition); - if (point.Properties().IsLeftButtonPressed() && - ctrlEnabled && !hyperlink.empty()) + const auto clickCount = _NumberOfClicks(mouseCursorPosition, timestamp); + // Handle hyper-link only on the first click to prevent multiple activations + if (clickCount == 1) { - const auto clickCount = _NumberOfClicks(cursorPosition, point.Timestamp()); - // Handle hyper-link only on the first click to prevent multiple activations - if (clickCount == 1) - { - _HyperlinkHandler(hyperlink); - } + _HyperlinkHandler(hyperlink); } - else if (_CanSendVTMouseInput(modifiers)) + } + else if (_CanSendVTMouseInput(modifiers)) + { + _TrySendMouseEvent(pointerUpdateKind, buttonState, modifiers, terminalPosition); + } + else if (buttonState.isLeftButtonDown) + { + const auto clickCount = _NumberOfClicks(mouseCursorPosition, timestamp); + // This formula enables the number of clicks to cycle properly + // between single-, double-, and triple-click. To increase the + // number of acceptable click states, simply increment + // MAX_CLICK_COUNT and add another if-statement + const unsigned int MAX_CLICK_COUNT = 3; + const auto multiClickMapper = clickCount > MAX_CLICK_COUNT ? ((clickCount + MAX_CLICK_COUNT - 1) % MAX_CLICK_COUNT) + 1 : clickCount; + + // Capture the position of the first click when no selection is active + if (multiClickMapper == 1 && + !_core->HasSelection()) { - _TrySendMouseEvent(point, modifiers, terminalPosition); + _singleClickTouchdownPos = mouseCursorPosition; + _singleClickTouchdownTerminalPos = terminalPosition; + _lastMouseClickPosNoSelection = mouseCursorPosition; } - else if (point.Properties().IsLeftButtonPressed()) + const bool isOnOriginalPosition = _lastMouseClickPosNoSelection == mouseCursorPosition; + + _core->LeftClickOnTerminal(terminalPosition, + multiClickMapper, + altEnabled, + shiftEnabled, + isOnOriginalPosition, + _selectionNeedsToBeCopied); + } + else if (buttonState.isRightButtonDown) + { + // CopyOnSelect right click always pastes + if (_core->CopyOnSelect() || !_core->HasSelection()) { - const auto clickCount = _NumberOfClicks(cursorPosition, point.Timestamp()); - // This formula enables the number of clicks to cycle properly - // between single-, double-, and triple-click. To increase the - // number of acceptable click states, simply increment - // MAX_CLICK_COUNT and add another if-statement - const unsigned int MAX_CLICK_COUNT = 3; - const auto multiClickMapper = clickCount > MAX_CLICK_COUNT ? ((clickCount + MAX_CLICK_COUNT - 1) % MAX_CLICK_COUNT) + 1 : clickCount; - - // Capture the position of the first click when no selection is active - if (multiClickMapper == 1 && - !_core->HasSelection()) - { - _singleClickTouchdownPos = cursorPosition; - _singleClickTouchdownTerminalPos = terminalPosition; - _lastMouseClickPosNoSelection = cursorPosition; - } - const bool isOnOriginalPosition = _lastMouseClickPosNoSelection == cursorPosition; - - _core->LeftClickOnTerminal(terminalPosition, - multiClickMapper, - altEnabled, - shiftEnabled, - isOnOriginalPosition, - _selectionNeedsToBeCopied); + PasteTextFromClipboard(); } - else if (point.Properties().IsRightButtonPressed()) + else { - // CopyOnSelect right click always pastes - if (_core->CopyOnSelect() || !_core->HasSelection()) - { - PasteTextFromClipboard(); - } - else - { - CopySelectionToClipboard(shiftEnabled, nullptr); - } + CopySelectionToClipboard(shiftEnabled, nullptr); } } - else if (type == Windows::Devices::Input::PointerDeviceType::Touch) - { - const auto contactRect = point.Properties().ContactRect(); - // Set our touch rect, to start a pan. - _touchAnchor = winrt::Windows::Foundation::Point{ contactRect.X, contactRect.Y }; - } } - // TODO: Doint take a Windows::UI::Input::PointerPoint here - void ControlInteractivity::PointerMoved(const winrt::Windows::UI::Input::PointerPoint point, + void ControlInteractivity::Touched(const winrt::Windows::Foundation::Point contactPoint) + { + _touchAnchor = contactPoint; + } + + // TODO: Don't take a Windows::UI::Input::PointerPoint here + void ControlInteractivity::PointerMoved(const winrt::Windows::Foundation::Point mouseCursorPosition, + TerminalInput::MouseButtonState buttonState, + const unsigned int pointerUpdateKind, const ::Microsoft::Terminal::Core::ControlKeyStates modifiers, const bool focused, - const til::point terminalPosition, - const winrt::Windows::Devices::Input::PointerDeviceType type) + const til::point terminalPosition) { - const auto cursorPosition = point.Position(); - if (type == Windows::Devices::Input::PointerDeviceType::Mouse || - type == Windows::Devices::Input::PointerDeviceType::Pen) + // Short-circuit isReadOnly check to avoid warning dialog + if (focused && !_core->IsInReadOnlyMode() && _CanSendVTMouseInput(modifiers)) { - // Short-circuit isReadOnly check to avoid warning dialog - if (focused && !_core->IsInReadOnlyMode() && _CanSendVTMouseInput(modifiers)) - { - _TrySendMouseEvent(point, modifiers, terminalPosition); - } - else if (focused && point.Properties().IsLeftButtonPressed()) + _TrySendMouseEvent(pointerUpdateKind, buttonState, modifiers, terminalPosition); + } + else if (focused && buttonState.isLeftButtonDown) + { + if (_singleClickTouchdownPos) { - if (_singleClickTouchdownPos) + // Figure out if the user's moved a quarter of a cell's smaller axis away from the clickdown point + auto& touchdownPoint{ *_singleClickTouchdownPos }; + auto distance{ std::sqrtf(std::powf(mouseCursorPosition.X - touchdownPoint.X, 2) + + std::powf(mouseCursorPosition.Y - touchdownPoint.Y, 2)) }; + const til::size fontSize{ _core->GetFont().GetSize() }; + + const auto fontSizeInDips = fontSize.scale(til::math::rounding, 1.0f / _core->RendererScale()); + if (distance >= (std::min(fontSizeInDips.width(), fontSizeInDips.height()) / 4.f)) { - // Figure out if the user's moved a quarter of a cell's smaller axis away from the clickdown point - auto& touchdownPoint{ *_singleClickTouchdownPos }; - auto distance{ std::sqrtf(std::powf(cursorPosition.X - touchdownPoint.X, 2) + - std::powf(cursorPosition.Y - touchdownPoint.Y, 2)) }; - const til::size fontSize{ _core->GetFont().GetSize() }; - - const auto fontSizeInDips = fontSize.scale(til::math::rounding, 1.0f / _core->RendererScale()); - if (distance >= (std::min(fontSizeInDips.width(), fontSizeInDips.height()) / 4.f)) - { - // _core->SetSelectionAnchor(_GetTerminalPosition(touchdownPoint)); - _core->SetSelectionAnchor(terminalPosition); - // stop tracking the touchdown point - _singleClickTouchdownPos = std::nullopt; - _singleClickTouchdownTerminalPos = std::nullopt; - } + _core->SetSelectionAnchor(terminalPosition); + // stop tracking the touchdown point + _singleClickTouchdownPos = std::nullopt; + _singleClickTouchdownTerminalPos = std::nullopt; } - - _SetEndSelectionPoint(terminalPosition); - - // const double cursorBelowBottomDist = cursorPosition.Y - SwapChainPanel().Margin().Top - SwapChainPanel().ActualHeight(); - // const double cursorAboveTopDist = -1 * cursorPosition.Y + SwapChainPanel().Margin().Top; - - // constexpr double MinAutoScrollDist = 2.0; // Arbitrary value - // double newAutoScrollVelocity = 0.0; - // if (cursorBelowBottomDist > MinAutoScrollDist) - // { - // newAutoScrollVelocity = _GetAutoScrollSpeed(cursorBelowBottomDist); - // } - // else if (cursorAboveTopDist > MinAutoScrollDist) - // { - // newAutoScrollVelocity = -1.0 * _GetAutoScrollSpeed(cursorAboveTopDist); - // } - - // if (newAutoScrollVelocity != 0) - // { - // _TryStartAutoScroll(point, newAutoScrollVelocity); - // } - // else - // { - // _TryStopAutoScroll(ptr.PointerId()); - // } } - _core->UpdateHoveredCell(terminalPosition); + _SetEndSelectionPoint(terminalPosition); + + // const double cursorBelowBottomDist = cursorPosition.Y - SwapChainPanel().Margin().Top - SwapChainPanel().ActualHeight(); + // const double cursorAboveTopDist = -1 * cursorPosition.Y + SwapChainPanel().Margin().Top; + + // constexpr double MinAutoScrollDist = 2.0; // Arbitrary value + // double newAutoScrollVelocity = 0.0; + // if (cursorBelowBottomDist > MinAutoScrollDist) + // { + // newAutoScrollVelocity = _GetAutoScrollSpeed(cursorBelowBottomDist); + // } + // else if (cursorAboveTopDist > MinAutoScrollDist) + // { + // newAutoScrollVelocity = -1.0 * _GetAutoScrollSpeed(cursorAboveTopDist); + // } + + // if (newAutoScrollVelocity != 0) + // { + // _TryStartAutoScroll(point, newAutoScrollVelocity); + // } + // else + // { + // _TryStopAutoScroll(ptr.PointerId()); + // } } - else if (focused && - type == Windows::Devices::Input::PointerDeviceType::Touch && - _touchAnchor) + + _core->UpdateHoveredCell(terminalPosition); + // else if (focused && + // type == Windows::Devices::Input::PointerDeviceType::Touch && + // _touchAnchor) + // { + // const auto contactRect = point.Properties().ContactRect(); + // winrt::Windows::Foundation::Point newTouchPoint{ contactRect.X, contactRect.Y }; + // const auto anchor = _touchAnchor.value(); + + // // Our actualFont's size is in pixels, convert to DIPs, which the + // // rest of the Points here are in. + // const til::size fontSize{ _core->GetFont().GetSize() }; + // const auto fontSizeInDips = fontSize.scale(til::math::rounding, 1.0f / _core->RendererScale()); + + // // Get the difference between the point we've dragged to and the start of the touch. + // const float dy = newTouchPoint.Y - anchor.Y; + + // // Start viewport scroll after we've moved more than a half row of text + // if (std::abs(dy) > (fontSizeInDips.height() / 2.0f)) + // { + // // Multiply by -1, because moving the touch point down will + // // create a positive delta, but we want the viewport to move up, + // // so we'll need a negative scroll amount (and the inverse for + // // panning down) + // const float numRows = -1.0f * (dy / fontSizeInDips.height()); + + // const auto currentOffset = ::base::ClampedNumeric(_core->ScrollOffset()); + // const auto newValue = numRows + currentOffset; + + // // Update the Core's viewport position, and raise a + // // ScrollPositionChanged event to update the scrollbar + // _updateScrollbar(newValue); + + // // Use this point as our new scroll anchor. + // _touchAnchor = newTouchPoint; + // } + // } + } + + void ControlInteractivity::TouchMoved(const winrt::Windows::Foundation::Point newTouchPoint, + const bool focused) + { + if (focused && + _touchAnchor) { - const auto contactRect = point.Properties().ContactRect(); - winrt::Windows::Foundation::Point newTouchPoint{ contactRect.X, contactRect.Y }; const auto anchor = _touchAnchor.value(); // Our actualFont's size is in pixels, convert to DIPs, which the @@ -317,14 +347,12 @@ namespace winrt::Microsoft::Terminal::Control::implementation // panning down) const float numRows = -1.0f * (dy / fontSizeInDips.height()); - // const auto currentOffset = ::base::ClampedNumeric(ScrollBar().Value()); const auto currentOffset = ::base::ClampedNumeric(_core->ScrollOffset()); const auto newValue = numRows + currentOffset; // Update the Core's viewport position, and raise a // ScrollPositionChanged event to update the scrollbar _updateScrollbar(newValue); - // ScrollBar().Value(newValue); // Use this point as our new scroll anchor. _touchAnchor = newTouchPoint; @@ -332,93 +360,115 @@ namespace winrt::Microsoft::Terminal::Control::implementation } } - void ControlInteractivity::PointerReleased(const winrt::Windows::UI::Input::PointerPoint point, + void ControlInteractivity::PointerReleased(TerminalInput::MouseButtonState buttonState, + const unsigned int pointerUpdateKind, const ::Microsoft::Terminal::Core::ControlKeyStates modifiers, const bool /*focused*/, - const til::point terminalPosition, - const winrt::Windows::Devices::Input::PointerDeviceType type) + const til::point terminalPosition) { - if (type == Windows::Devices::Input::PointerDeviceType::Mouse || - type == Windows::Devices::Input::PointerDeviceType::Pen) + // Short-circuit isReadOnly check to avoid warning dialog + if (!_core->IsInReadOnlyMode() && _CanSendVTMouseInput(modifiers)) { - // Short-circuit isReadOnly check to avoid warning dialog - if (!_core->IsInReadOnlyMode() && _CanSendVTMouseInput(modifiers)) - { - _TrySendMouseEvent(point, modifiers, terminalPosition); - // args.Handled(true); - return; - } - - // Only a left click release when copy on select is active should perform a copy. - // Right clicks and middle clicks should not need to do anything when released. - if (_core->CopyOnSelect() && - point.Properties().PointerUpdateKind() == Windows::UI::Input::PointerUpdateKind::LeftButtonReleased && - _selectionNeedsToBeCopied) - { - CopySelectionToClipboard(false, nullptr); - } + _TrySendMouseEvent(pointerUpdateKind, buttonState, modifiers, terminalPosition); + // args.Handled(true); + return; } - else if (type == Windows::Devices::Input::PointerDeviceType::Touch) + + // Only a left click release when copy on select is active should perform a copy. + // Right clicks and middle clicks should not need to do anything when released. + const bool isLeftMouseRelease = pointerUpdateKind == WM_LBUTTONUP; + + if (_core->CopyOnSelect() && + isLeftMouseRelease && + _selectionNeedsToBeCopied) { - _touchAnchor = std::nullopt; + CopySelectionToClipboard(false, nullptr); } _singleClickTouchdownPos = std::nullopt; _singleClickTouchdownTerminalPos = std::nullopt; } + void ControlInteractivity::TouchReleased() + { + _touchAnchor = std::nullopt; + } + + // // Method Description: + // // - Send this particular mouse event to the terminal. + // // See Terminal::SendMouseEvent for more information. + // // Arguments: + // // - point: the PointerPoint object representing a mouse event from our XAML input handler + // bool ControlInteractivity::_TrySendMouseEvent(Windows::UI::Input::PointerPoint const& point, + // const ::Microsoft::Terminal::Core::ControlKeyStates modifiers, + // const til::point terminalPosition) + // { + // const auto props = point.Properties(); + + // // Which mouse button changed state (and how) + // unsigned int uiButton{}; + // switch (props.PointerUpdateKind()) + // { + // case winrt::Windows::UI::Input::PointerUpdateKind::LeftButtonPressed: + // uiButton = WM_LBUTTONDOWN; + // break; + // case winrt::Windows::UI::Input::PointerUpdateKind::LeftButtonReleased: + // uiButton = WM_LBUTTONUP; + // break; + // case winrt::Windows::UI::Input::PointerUpdateKind::MiddleButtonPressed: + // uiButton = WM_MBUTTONDOWN; + // break; + // case winrt::Windows::UI::Input::PointerUpdateKind::MiddleButtonReleased: + // uiButton = WM_MBUTTONUP; + // break; + // case winrt::Windows::UI::Input::PointerUpdateKind::RightButtonPressed: + // uiButton = WM_RBUTTONDOWN; + // break; + // case winrt::Windows::UI::Input::PointerUpdateKind::RightButtonReleased: + // uiButton = WM_RBUTTONUP; + // break; + // default: + // uiButton = WM_MOUSEMOVE; + // } + + // // Mouse wheel data + // const short sWheelDelta = ::base::saturated_cast(props.MouseWheelDelta()); + // if (sWheelDelta != 0 && !props.IsHorizontalMouseWheel()) + // { + // // if we have a mouse wheel delta and it wasn't a horizontal wheel motion + // uiButton = WM_MOUSEWHEEL; + // } + + // const TerminalInput::MouseButtonState state{ props.IsLeftButtonPressed(), + // props.IsMiddleButtonPressed(), + // props.IsRightButtonPressed() }; + // return _core->SendMouseEvent(terminalPosition, uiButton, modifiers, sWheelDelta, state); + // } + // Method Description: // - Send this particular mouse event to the terminal. // See Terminal::SendMouseEvent for more information. // Arguments: // - point: the PointerPoint object representing a mouse event from our XAML input handler - bool ControlInteractivity::_TrySendMouseEvent(Windows::UI::Input::PointerPoint const& point, + bool ControlInteractivity::_TrySendMouseEvent(const unsigned int updateKind, + const TerminalInput::MouseButtonState buttonState, const ::Microsoft::Terminal::Core::ControlKeyStates modifiers, const til::point terminalPosition) { - const auto props = point.Properties(); - - // Get the terminal position relative to the viewport - // const auto terminalPosition = _GetTerminalPosition(point.Position()); - - // Which mouse button changed state (and how) - unsigned int uiButton{}; - switch (props.PointerUpdateKind()) - { - case winrt::Windows::UI::Input::PointerUpdateKind::LeftButtonPressed: - uiButton = WM_LBUTTONDOWN; - break; - case winrt::Windows::UI::Input::PointerUpdateKind::LeftButtonReleased: - uiButton = WM_LBUTTONUP; - break; - case winrt::Windows::UI::Input::PointerUpdateKind::MiddleButtonPressed: - uiButton = WM_MBUTTONDOWN; - break; - case winrt::Windows::UI::Input::PointerUpdateKind::MiddleButtonReleased: - uiButton = WM_MBUTTONUP; - break; - case winrt::Windows::UI::Input::PointerUpdateKind::RightButtonPressed: - uiButton = WM_RBUTTONDOWN; - break; - case winrt::Windows::UI::Input::PointerUpdateKind::RightButtonReleased: - uiButton = WM_RBUTTONUP; - break; - default: - uiButton = WM_MOUSEMOVE; - } - - // Mouse wheel data - const short sWheelDelta = ::base::saturated_cast(props.MouseWheelDelta()); - if (sWheelDelta != 0 && !props.IsHorizontalMouseWheel()) - { - // if we have a mouse wheel delta and it wasn't a horizontal wheel motion - uiButton = WM_MOUSEWHEEL; - } + return _core->SendMouseEvent(terminalPosition, updateKind, modifiers, 0, buttonState); + } - const TerminalInput::MouseButtonState state{ props.IsLeftButtonPressed(), - props.IsMiddleButtonPressed(), - props.IsRightButtonPressed() }; - return _core->SendMouseEvent(terminalPosition, uiButton, modifiers, sWheelDelta, state); + // Method Description: + // - Send this particular mouse event to the terminal. + // See Terminal::SendMouseEvent for more information. + // Arguments: + // - point: the PointerPoint object representing a mouse event from our XAML input handler + bool ControlInteractivity::_TrySendMouseWheelEvent(const short scrollDelta, + const TerminalInput::MouseButtonState buttonState, + const ::Microsoft::Terminal::Core::ControlKeyStates modifiers, + const til::point terminalPosition) + { + return _core->SendMouseEvent(terminalPosition, WM_MOUSEWHEEL, modifiers, scrollDelta, buttonState); } // Method Description: @@ -505,7 +555,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation const bool isLeftButtonPressed) { const auto currentOffset = _core->ScrollOffset(); - // const auto currentOffset = ScrollBar().Value(); // negative = down, positive = up // However, for us, the signs are flipped. @@ -570,7 +619,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation { // If the user is holding down Shift, suppress mouse events // TODO GH#4875: disable/customize this functionality - // const auto modifiers = _GetPressedModifierKeys(); if (modifiers.IsShiftPressed()) { return false; diff --git a/src/cascadia/TerminalControl/ControlInteractivity.h b/src/cascadia/TerminalControl/ControlInteractivity.h index cdde32c1fd0..0aecb89d8c5 100644 --- a/src/cascadia/TerminalControl/ControlInteractivity.h +++ b/src/cascadia/TerminalControl/ControlInteractivity.h @@ -32,21 +32,28 @@ namespace winrt::Microsoft::Terminal::Control::implementation void UpdateSettings(); void Initialize(); //////////////////////////////////////////////////////////////////////// - void PointerPressed(const winrt::Windows::UI::Input::PointerPoint point, + void PointerPressed(const winrt::Windows::Foundation::Point mouseCursorPosition, + ::Microsoft::Console::VirtualTerminal::TerminalInput::MouseButtonState buttonState, + const unsigned int pointerUpdateKind, + const uint64_t timestamp, const ::Microsoft::Terminal::Core::ControlKeyStates modifiers, const bool focused, - const til::point terminalPosition, - const winrt::Windows::Devices::Input::PointerDeviceType type); - void PointerMoved(const winrt::Windows::UI::Input::PointerPoint point, + const til::point terminalPosition); + void Touched(const winrt::Windows::Foundation::Point contactPoint); + void PointerMoved(const winrt::Windows::Foundation::Point mouseCursorPosition, + ::Microsoft::Console::VirtualTerminal::TerminalInput::MouseButtonState buttonState, + const unsigned int pointerUpdateKind, const ::Microsoft::Terminal::Core::ControlKeyStates modifiers, const bool focused, - const til::point terminalPosition, - const winrt::Windows::Devices::Input::PointerDeviceType type); - void PointerReleased(const winrt::Windows::UI::Input::PointerPoint point, + const til::point terminalPosition); + void TouchMoved(const winrt::Windows::Foundation::Point newTouchPoint, + const bool focused); + void PointerReleased(::Microsoft::Console::VirtualTerminal::TerminalInput::MouseButtonState buttonState, + const unsigned int pointerUpdateKind, const ::Microsoft::Terminal::Core::ControlKeyStates modifiers, const bool focused, - const til::point terminalPosition, - const winrt::Windows::Devices::Input::PointerDeviceType type); + const til::point terminalPosition); + void TouchReleased(); bool MouseWheel(const ::Microsoft::Terminal::Core::ControlKeyStates modifiers, const int32_t delta, const til::point terminalPosition, @@ -92,9 +99,17 @@ namespace winrt::Microsoft::Terminal::Control::implementation unsigned int _NumberOfClicks(winrt::Windows::Foundation::Point clickPos, Timestamp clickTime); void _UpdateSystemParameterSettings() noexcept; - bool _TrySendMouseEvent(Windows::UI::Input::PointerPoint const& point, + // bool _TrySendMouseEvent(Windows::UI::Input::PointerPoint const& point, + // const ::Microsoft::Terminal::Core::ControlKeyStates modifiers, + // const til::point terminalPosition); + bool _TrySendMouseEvent(const unsigned int updateKind, + const ::Microsoft::Console::VirtualTerminal::TerminalInput::MouseButtonState buttonState, const ::Microsoft::Terminal::Core::ControlKeyStates modifiers, const til::point terminalPosition); + bool _TrySendMouseWheelEvent(const short scrollDelta, + const ::Microsoft::Console::VirtualTerminal::TerminalInput::MouseButtonState buttonState, + const ::Microsoft::Terminal::Core::ControlKeyStates modifiers, + const til::point terminalPosition); void _MouseTransparencyHandler(const double mouseDelta); void _MouseZoomHandler(const double mouseDelta); diff --git a/src/cascadia/TerminalControl/TermControl.cpp b/src/cascadia/TerminalControl/TermControl.cpp index 7031c20e9ef..963724e1b25 100644 --- a/src/cascadia/TerminalControl/TermControl.cpp +++ b/src/cascadia/TerminalControl/TermControl.cpp @@ -68,6 +68,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation _core->RendererEnteredErrorState({ get_weak(), &TermControl::_RendererEnteredErrorState }); _core->FontSizeChanged({ get_weak(), &TermControl::_coreFontSizeChanged }); _core->TransparencyChanged({ get_weak(), &TermControl::_coreTransparencyChanged }); + _core->ReceivedOutput({ get_weak(), &TermControl::_coreReceivedOutput }); _interactivity->OpenHyperlink({ get_weak(), &TermControl::_HyperlinkHandler }); _interactivity->ScrollPositionChanged({ get_weak(), &TermControl::_ScrollPositionChanged }); @@ -970,6 +971,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation const auto ptr = args.Pointer(); const auto point = args.GetCurrentPoint(*this); + const auto type = ptr.PointerDeviceType(); // We also TryShow in GotFocusHandler, but this call is specifically // for the case where the Terminal is in focus but the user closed the @@ -983,11 +985,22 @@ namespace winrt::Microsoft::Terminal::Control::implementation } const auto cursorPosition = point.Position(); - _interactivity->PointerPressed(point, - ControlKeyStates(args.KeyModifiers()), - _focused, - _GetTerminalPosition(cursorPosition), - ptr.PointerDeviceType()); + if (type == Windows::Devices::Input::PointerDeviceType::Touch) + { + const auto contactRect = point.Properties().ContactRect(); + auto anchor = winrt::Windows::Foundation::Point{ contactRect.X, contactRect.Y }; + _interactivity->Touched(anchor); + } + else + { + _interactivity->PointerPressed(cursorPosition, + TermControl::GetPressedMouseButtons(point), + TermControl::PointerToMouseButtons(point), + point.Timestamp(), + ControlKeyStates(args.KeyModifiers()), + _focused, + _GetTerminalPosition(cursorPosition)); + } args.Handled(true); } @@ -1018,37 +1031,50 @@ namespace winrt::Microsoft::Terminal::Control::implementation _FocusFollowMouseRequestedHandlers(*this, nullptr); } - _interactivity->PointerMoved(point, - ControlKeyStates(args.KeyModifiers()), - _focused, - terminalPosition, - type); - - if (_focused && point.Properties().IsLeftButtonPressed()) + if (type == Windows::Devices::Input::PointerDeviceType::Mouse || + type == Windows::Devices::Input::PointerDeviceType::Pen) { - const double cursorBelowBottomDist = cursorPosition.Y - SwapChainPanel().Margin().Top - SwapChainPanel().ActualHeight(); - const double cursorAboveTopDist = -1 * cursorPosition.Y + SwapChainPanel().Margin().Top; + _interactivity->PointerMoved(cursorPosition, + TermControl::GetPressedMouseButtons(point), + TermControl::PointerToMouseButtons(point), + ControlKeyStates(args.KeyModifiers()), + _focused, + terminalPosition); - constexpr double MinAutoScrollDist = 2.0; // Arbitrary value - double newAutoScrollVelocity = 0.0; - if (cursorBelowBottomDist > MinAutoScrollDist) + if (_focused && point.Properties().IsLeftButtonPressed()) { - newAutoScrollVelocity = _GetAutoScrollSpeed(cursorBelowBottomDist); - } - else if (cursorAboveTopDist > MinAutoScrollDist) - { - newAutoScrollVelocity = -1.0 * _GetAutoScrollSpeed(cursorAboveTopDist); - } + const double cursorBelowBottomDist = cursorPosition.Y - SwapChainPanel().Margin().Top - SwapChainPanel().ActualHeight(); + const double cursorAboveTopDist = -1 * cursorPosition.Y + SwapChainPanel().Margin().Top; - if (newAutoScrollVelocity != 0) - { - _TryStartAutoScroll(point, newAutoScrollVelocity); - } - else - { - _TryStopAutoScroll(ptr.PointerId()); + constexpr double MinAutoScrollDist = 2.0; // Arbitrary value + double newAutoScrollVelocity = 0.0; + if (cursorBelowBottomDist > MinAutoScrollDist) + { + newAutoScrollVelocity = _GetAutoScrollSpeed(cursorBelowBottomDist); + } + else if (cursorAboveTopDist > MinAutoScrollDist) + { + newAutoScrollVelocity = -1.0 * _GetAutoScrollSpeed(cursorAboveTopDist); + } + + if (newAutoScrollVelocity != 0) + { + _TryStartAutoScroll(point, newAutoScrollVelocity); + } + else + { + _TryStopAutoScroll(ptr.PointerId()); + } } } + else if (type == Windows::Devices::Input::PointerDeviceType::Touch) + { + const auto contactRect = point.Properties().ContactRect(); + winrt::Windows::Foundation::Point newTouchPoint{ contactRect.X, contactRect.Y }; + + _interactivity->TouchMoved(newTouchPoint, _focused); + } + args.Handled(true); } @@ -1073,11 +1099,20 @@ namespace winrt::Microsoft::Terminal::Control::implementation const auto type = ptr.PointerDeviceType(); _ReleasePointerCapture(sender, args); - _interactivity->PointerReleased(point, - ControlKeyStates(args.KeyModifiers()), - _focused, - terminalPosition, - type); + + if (type == Windows::Devices::Input::PointerDeviceType::Mouse || + type == Windows::Devices::Input::PointerDeviceType::Pen) + { + _interactivity->PointerReleased(TermControl::GetPressedMouseButtons(point), + TermControl::PointerToMouseButtons(point), + ControlKeyStates(args.KeyModifiers()), + _focused, + terminalPosition); + } + else if (type == Windows::Devices::Input::PointerDeviceType::Touch) + { + _interactivity->TouchReleased(); + } _TryStopAutoScroll(ptr.PointerId()); @@ -1164,6 +1199,23 @@ namespace winrt::Microsoft::Terminal::Control::implementation CATCH_LOG(); } + void TermControl::_coreReceivedOutput(const IInspectable& /*sender*/, + const IInspectable& /*args*/) + { + // Queue up a throttled UpdatePatternLocations call. In the future, we + // should have the _updatePatternLocations ThrottledFunc internal to + // ControlCore, and run on that object's dispatcher queue. + // + // We're not doing that quite yet, because the Core will eventually + // be out-of-proc from the UI thread, and won't be able to just use + // the UI thread as the dispatcher queue thread. + // + // THIS IS ACLLED ON EVERY STRING OF TEXT OUTPUT TO THE TERMINAL. Think + // twice before adding anything here. + + _updatePatternLocations->Run(); + } + // Method Description: // - Reset the font size of the terminal to its default size. // Arguments: @@ -2324,4 +2376,43 @@ namespace winrt::Microsoft::Terminal::Control::implementation _FontSizeChangedHandlers(fontWidth, fontHeight, isInitialChange); } + TerminalInput::MouseButtonState TermControl::GetPressedMouseButtons(const winrt::Windows::UI::Input::PointerPoint point) + { + return TerminalInput::MouseButtonState{ point.Properties().IsLeftButtonPressed(), + point.Properties().IsMiddleButtonPressed(), + point.Properties().IsRightButtonPressed() }; + } + + unsigned int TermControl::PointerToMouseButtons(const winrt::Windows::UI::Input::PointerPoint point) + { + const auto props = point.Properties(); + + // Which mouse button changed state (and how) + unsigned int uiButton{}; + switch (props.PointerUpdateKind()) + { + case winrt::Windows::UI::Input::PointerUpdateKind::LeftButtonPressed: + uiButton = WM_LBUTTONDOWN; + break; + case winrt::Windows::UI::Input::PointerUpdateKind::LeftButtonReleased: + uiButton = WM_LBUTTONUP; + break; + case winrt::Windows::UI::Input::PointerUpdateKind::MiddleButtonPressed: + uiButton = WM_MBUTTONDOWN; + break; + case winrt::Windows::UI::Input::PointerUpdateKind::MiddleButtonReleased: + uiButton = WM_MBUTTONUP; + break; + case winrt::Windows::UI::Input::PointerUpdateKind::RightButtonPressed: + uiButton = WM_RBUTTONDOWN; + break; + case winrt::Windows::UI::Input::PointerUpdateKind::RightButtonReleased: + uiButton = WM_RBUTTONUP; + break; + default: + uiButton = WM_MOUSEMOVE; + } + + return uiButton; + } } diff --git a/src/cascadia/TerminalControl/TermControl.h b/src/cascadia/TerminalControl/TermControl.h index 15323981d8d..1c94d1dac11 100644 --- a/src/cascadia/TerminalControl/TermControl.h +++ b/src/cascadia/TerminalControl/TermControl.h @@ -93,6 +93,9 @@ namespace winrt::Microsoft::Terminal::Control::implementation bool ReadOnly() const noexcept; void ToggleReadOnly(); + static ::Microsoft::Console::VirtualTerminal::TerminalInput::MouseButtonState GetPressedMouseButtons(const winrt::Windows::UI::Input::PointerPoint point); + static unsigned int PointerToMouseButtons(const winrt::Windows::UI::Input::PointerPoint point); + // -------------------------------- WinRT Events --------------------------------- // clang-format off WINRT_CALLBACK(FontSizeChanged, Control::FontSizeChangedEventArgs); @@ -228,6 +231,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation const int fontHeight, const bool isInitialChange); winrt::fire_and_forget _coreTransparencyChanged(const IInspectable& sender, const Control::TransparencyChangedEventArgs& args); + void _coreReceivedOutput(const IInspectable& sender, const IInspectable& args); }; } diff --git a/src/cascadia/UnitTests_Control/ControlInteractivityTests.cpp b/src/cascadia/UnitTests_Control/ControlInteractivityTests.cpp index f8d9e10ff52..097480d5953 100644 --- a/src/cascadia/UnitTests_Control/ControlInteractivityTests.cpp +++ b/src/cascadia/UnitTests_Control/ControlInteractivityTests.cpp @@ -27,6 +27,8 @@ namespace ControlUnitTests TEST_METHOD(TestPanWithTouch); TEST_METHOD(TestScrollWithMouse); + TEST_METHOD(CreateSubsequentSelectionWithDragging); + TEST_CLASS_SETUP(ClassSetup) { winrt::init_apartment(winrt::apartment_type::single_threaded); @@ -221,8 +223,53 @@ namespace ControlUnitTests -WHEEL_DELTA, til::point{ 0, 0 }, { false, false, false }); - - VERIFY_IS_TRUE(false); } + void ControlInteractivityTests::CreateSubsequentSelectionWithDragging() + { + WEX::TestExecution::DisableVerifyExceptions disableVerifyExceptions{}; + + winrt::com_ptr settings; + settings.attach(new MockControlSettings()); + winrt::com_ptr conn; + conn.attach(new MockConnection()); + + settings->UseAcrylic(true); + settings->TintOpacity(0.5f); + + Log::Comment(L"Create ControlInteractivity object"); + auto interactivity = winrt::make_self(*settings, *conn); + VERIFY_IS_NOT_NULL(interactivity); + auto core = interactivity->_core; + VERIFY_IS_NOT_NULL(core); + // "Cascadia Mono" ends up with an actual size of 9x19 at 96DPI. So + // let's just arbitrarily start with a 270x380px (30x20 chars) window + core->InitializeTerminal(270, 380, 1.0, 1.0); + VERIFY_IS_TRUE(core->_initializedTerminal); + VERIFY_ARE_EQUAL(20, core->_terminal->GetViewport().Height()); + interactivity->Initialize(); + + // For this test, don't use any modifiers + const auto modifiers = ControlKeyStates(); + + // Click on the terminal + interactivity->PointerPressed(); + // Verify that there's one selection + + // Drag the mouse + interactivity->PointerMoved(); + // Verify that there's still one selection + + // Release the mouse + interactivity->PointerReleased(); + // Verify that there's still one selection + + // click outside the current selection + interactivity->PointerPressed(); + // Verify that there's now no selection + + // Drag the mouse + interactivity->PointerMoved(); + // Verify that there's now one selection + } } From 3cbf37705175d94f2105fe933ca70ea70480b20e Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Tue, 6 Apr 2021 16:26:44 -0500 Subject: [PATCH 42/82] Fix the tests after the merge --- .../UnitTests_Control/Control.UnitTests.vcxproj | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/cascadia/UnitTests_Control/Control.UnitTests.vcxproj b/src/cascadia/UnitTests_Control/Control.UnitTests.vcxproj index c155262cd40..3498995f119 100644 --- a/src/cascadia/UnitTests_Control/Control.UnitTests.vcxproj +++ b/src/cascadia/UnitTests_Control/Control.UnitTests.vcxproj @@ -47,9 +47,17 @@ - + + + + $(OpenConsoleCommonOutDir)TerminalConnection\Microsoft.Terminal.TerminalConnection.winmd + true + false + false + + @@ -79,7 +87,7 @@ - + From f95961223a50a583376bdc7d118f4ebab86712de Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Tue, 6 Apr 2021 17:13:35 -0500 Subject: [PATCH 43/82] A test for #9725 --- .../ControlInteractivityTests.cpp | 108 ++++++++++++++---- 1 file changed, 88 insertions(+), 20 deletions(-) diff --git a/src/cascadia/UnitTests_Control/ControlInteractivityTests.cpp b/src/cascadia/UnitTests_Control/ControlInteractivityTests.cpp index 097480d5953..d552acd70da 100644 --- a/src/cascadia/UnitTests_Control/ControlInteractivityTests.cpp +++ b/src/cascadia/UnitTests_Control/ControlInteractivityTests.cpp @@ -15,6 +15,11 @@ using namespace WEX::Common; using namespace winrt; using namespace winrt::Microsoft::Terminal; using namespace ::Microsoft::Terminal::Core; +using namespace ::Microsoft::Console::VirtualTerminal; +// namespace winrt +// { +// using namespace Windows::Foundation; +// }; namespace ControlUnitTests { @@ -227,6 +232,7 @@ namespace ControlUnitTests void ControlInteractivityTests::CreateSubsequentSelectionWithDragging() { + // This is a test for GH#9725 WEX::TestExecution::DisableVerifyExceptions disableVerifyExceptions{}; winrt::com_ptr settings; @@ -251,25 +257,87 @@ namespace ControlUnitTests // For this test, don't use any modifiers const auto modifiers = ControlKeyStates(); - - // Click on the terminal - interactivity->PointerPressed(); - // Verify that there's one selection - - // Drag the mouse - interactivity->PointerMoved(); - // Verify that there's still one selection - - // Release the mouse - interactivity->PointerReleased(); - // Verify that there's still one selection - - // click outside the current selection - interactivity->PointerPressed(); - // Verify that there's now no selection - - // Drag the mouse - interactivity->PointerMoved(); - // Verify that there's now one selection + const TerminalInput::MouseButtonState leftMouseDown{ true, false, false }; + const TerminalInput::MouseButtonState noMouseDown{ false, false, false }; + + const til::size fontSize{ 9, 19 }; + + Log::Comment(L"Click on the terminal"); + const til::point terminalPosition0{ 0, 0 }; + const til::point cursorPosition0 = terminalPosition0 * fontSize; + interactivity->PointerPressed(cursorPosition0, + leftMouseDown, + WM_LBUTTONDOWN, //pointerUpdateKind + 0, // timestamp + modifiers, + true, // focused, + terminalPosition0); + Log::Comment(L"Verify that there's not yet a selection"); + + VERIFY_IS_FALSE(core->HasSelection()); + + Log::Comment(L"Drag the mouse just a little"); + // move not quite a whole cell, but enough to start a selection + const til::point terminalPosition1{ 0, 0 }; + const til::point cursorPosition1{ 6, 0 }; + interactivity->PointerMoved(cursorPosition1, + leftMouseDown, + WM_LBUTTONDOWN, //pointerUpdateKind + modifiers, + true, // focused, + terminalPosition1); + Log::Comment(L"Verify that there's one selection"); + VERIFY_IS_TRUE(core->HasSelection()); + VERIFY_ARE_EQUAL(1, core->_terminal->GetSelectionRects().size()); + + Log::Comment(L"Drag the mouse down a whole row"); + const til::point terminalPosition2{ 1, 1 }; + const til::point cursorPosition2 = terminalPosition2 * fontSize; + interactivity->PointerMoved(cursorPosition2, + leftMouseDown, + WM_LBUTTONDOWN, //pointerUpdateKind + modifiers, + true, // focused, + terminalPosition2); + Log::Comment(L"Verify that there's now two selections (one on each row)"); + VERIFY_IS_TRUE(core->HasSelection()); + VERIFY_ARE_EQUAL(2, core->_terminal->GetSelectionRects().size()); + + Log::Comment(L"Release the mouse"); + interactivity->PointerReleased(noMouseDown, + WM_LBUTTONUP, //pointerUpdateKind + modifiers, + true, // focused, + terminalPosition2); + Log::Comment(L"Verify that there's still two selections"); + VERIFY_IS_TRUE(core->HasSelection()); + VERIFY_ARE_EQUAL(2, core->_terminal->GetSelectionRects().size()); + + Log::Comment(L"click outside the current selection"); + const til::point terminalPosition3{ 2, 2 }; + const til::point cursorPosition3 = terminalPosition3 * fontSize; + interactivity->PointerPressed(cursorPosition3, + leftMouseDown, + WM_LBUTTONDOWN, //pointerUpdateKind + 0, // timestamp + modifiers, + true, // focused, + terminalPosition3); + Log::Comment(L"Verify that there's now no selection"); + VERIFY_IS_FALSE(core->HasSelection()); + VERIFY_ARE_EQUAL(0, core->_terminal->GetSelectionRects().size()); + + Log::Comment(L"Drag the mouse"); + const til::point terminalPosition4{ 3, 2 }; + const til::point cursorPosition4 = terminalPosition4 * fontSize; + interactivity->PointerMoved(cursorPosition4, + leftMouseDown, + WM_LBUTTONDOWN, //pointerUpdateKind + modifiers, + true, // focused, + terminalPosition4); + Log::Comment(L"Verify that there's now one selection"); + VERIFY_IS_TRUE(core->HasSelection()); + VERIFY_ARE_EQUAL(1, core->_terminal->GetSelectionRects().size()); } } From f5f9de2409851e37d3bc4443ebd49fff234d6515 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Wed, 7 Apr 2021 09:07:56 -0500 Subject: [PATCH 44/82] Fix a double free when closing the terminal --- src/cascadia/TerminalControl/ControlCore.cpp | 59 ++++++++++--------- src/cascadia/TerminalControl/ControlCore.h | 1 + .../UnitTests_Control/ControlCoreTests.cpp | 25 ++++++++ 3 files changed, 57 insertions(+), 28 deletions(-) diff --git a/src/cascadia/TerminalControl/ControlCore.cpp b/src/cascadia/TerminalControl/ControlCore.cpp index e0d16ed760f..fba602eaf93 100644 --- a/src/cascadia/TerminalControl/ControlCore.cpp +++ b/src/cascadia/TerminalControl/ControlCore.cpp @@ -1130,40 +1130,43 @@ namespace winrt::Microsoft::Terminal::Control::implementation void ControlCore::Close() { - // Stop accepting new output and state changes before we disconnect everything. - _connection.TerminalOutput(_connectionOutputEventToken); - _connectionStateChangedRevoker.revoke(); + if (!_closing.exchange(true)) + { + // Stop accepting new output and state changes before we disconnect everything. + _connection.TerminalOutput(_connectionOutputEventToken); + _connectionStateChangedRevoker.revoke(); - // GH#1996 - Close the connection asynchronously on a background - // thread. - // Since TermControl::Close is only ever triggered by the UI, we - // don't really care to wait for the connection to be completely - // closed. We can just do it whenever. - _AsyncCloseConnection(); + // GH#1996 - Close the connection asynchronously on a background + // thread. + // Since TermControl::Close is only ever triggered by the UI, we + // don't really care to wait for the connection to be completely + // closed. We can just do it whenever. + _AsyncCloseConnection(); - { - // GH#8734: - // We lock the terminal here to make sure it isn't still being - // used in the connection thread before we destroy the renderer. - // However, we must unlock it again prior to triggering the - // teardown, to avoid the render thread being deadlocked. The - // renderer may be waiting to acquire the terminal lock, while - // we're waiting for the renderer to finish. - auto lock = _terminal->LockForWriting(); - } + { + // GH#8734: + // We lock the terminal here to make sure it isn't still being + // used in the connection thread before we destroy the renderer. + // However, we must unlock it again prior to triggering the + // teardown, to avoid the render thread being deadlocked. The + // renderer may be waiting to acquire the terminal lock, while + // we're waiting for the renderer to finish. + auto lock = _terminal->LockForWriting(); + } - if (auto localRenderEngine{ std::exchange(_renderEngine, nullptr) }) - { - if (auto localRenderer{ std::exchange(_renderer, nullptr) }) + if (auto localRenderEngine{ std::exchange(_renderEngine, nullptr) }) { - localRenderer->TriggerTeardown(); - // renderer is destroyed + if (auto localRenderer{ std::exchange(_renderer, nullptr) }) + { + localRenderer->TriggerTeardown(); + // renderer is destroyed + } + // renderEngine is destroyed } - // renderEngine is destroyed - } - // we don't destroy _terminal here; it now has the same lifetime as the - // control. + // we don't destroy _terminal here; it now has the same lifetime as the + // control. + } } HANDLE ControlCore::GetSwapChainHandle() const diff --git a/src/cascadia/TerminalControl/ControlCore.h b/src/cascadia/TerminalControl/ControlCore.h index f612bdb6803..b011cf33011 100644 --- a/src/cascadia/TerminalControl/ControlCore.h +++ b/src/cascadia/TerminalControl/ControlCore.h @@ -151,6 +151,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation private: bool _initializedTerminal{ false }; + std::atomic _closing{ false }; TerminalConnection::ITerminalConnection _connection{ nullptr }; event_token _connectionOutputEventToken; diff --git a/src/cascadia/UnitTests_Control/ControlCoreTests.cpp b/src/cascadia/UnitTests_Control/ControlCoreTests.cpp index e26979f8971..8fe38eb732b 100644 --- a/src/cascadia/UnitTests_Control/ControlCoreTests.cpp +++ b/src/cascadia/UnitTests_Control/ControlCoreTests.cpp @@ -28,6 +28,8 @@ namespace ControlUnitTests TEST_METHOD(TestInitialize); TEST_METHOD(TestAdjustAcrylic); + TEST_METHOD(TestFreeAfterClose); + TEST_CLASS_SETUP(ModuleSetup) { winrt::init_apartment(winrt::apartment_type::single_threaded); @@ -167,4 +169,27 @@ namespace ControlUnitTests core->AdjustOpacity(-0.25); } + void ControlCoreTests::TestFreeAfterClose() + { + { + Log::Comment(L"Create settings object"); + winrt::com_ptr settings; + settings.attach(new MockControlSettings()); + + Log::Comment(L"Create connection object"); + winrt::com_ptr conn; + conn.attach(new MockConnection()); + VERIFY_IS_NOT_NULL(conn); + + Log::Comment(L"Create ControlCore object"); + auto core = winrt::make_self(*settings, *conn); + VERIFY_IS_NOT_NULL(core); + + Log::Comment(L"Close the Core, like a TermControl would"); + core->Close(); + } + + VERIFY_IS_TRUE(true, L"Make sure that the test didn't crash when the core when out of scope"); + } + } From 832bb667ed57aae3dd8b394bf3c95195335d81a6 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Wed, 7 Apr 2021 09:43:36 -0500 Subject: [PATCH 45/82] move around the read only warning. Now, does it work? --- src/cascadia/TerminalControl/ControlCore.cpp | 12 +- src/cascadia/TerminalControl/ControlCore.h | 5 +- .../TerminalControl/ControlInteractivity.cpp | 105 ++---------------- .../TerminalControl/ControlInteractivity.h | 22 ++-- src/cascadia/TerminalControl/TermControl.cpp | 27 ++--- src/cascadia/TerminalControl/TermControl.h | 1 - 6 files changed, 40 insertions(+), 132 deletions(-) diff --git a/src/cascadia/TerminalControl/ControlCore.cpp b/src/cascadia/TerminalControl/ControlCore.cpp index fba602eaf93..01dab1c1bcb 100644 --- a/src/cascadia/TerminalControl/ControlCore.cpp +++ b/src/cascadia/TerminalControl/ControlCore.cpp @@ -260,8 +260,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation { if (_isReadOnly) { - // !TODO!: Do we want this? - // _RaiseReadOnlyWarning(); + _RaiseReadOnlyWarning(); } else { @@ -273,8 +272,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation { if (_isReadOnly) { - // !TODO!: Do we want this? - // _RaiseReadOnlyWarning(); + _RaiseReadOnlyWarning(); } else { @@ -1312,9 +1310,15 @@ namespace winrt::Microsoft::Terminal::Control::implementation { return _isReadOnly; } + void ControlCore::ToggleReadOnlyMode() { _isReadOnly = !_isReadOnly; } + void ControlCore::_RaiseReadOnlyWarning() + { + auto noticeArgs = winrt::make(NoticeLevel::Info, RS_(L"TermControlReadOnly")); + _RaiseNoticeHandlers(*this, std::move(noticeArgs)); + } } diff --git a/src/cascadia/TerminalControl/ControlCore.h b/src/cascadia/TerminalControl/ControlCore.h index b011cf33011..e5718526ac4 100644 --- a/src/cascadia/TerminalControl/ControlCore.h +++ b/src/cascadia/TerminalControl/ControlCore.h @@ -170,12 +170,12 @@ namespace winrt::Microsoft::Terminal::Control::implementation // storage location for the leading surrogate of a utf-16 surrogate pair std::optional _leadingSurrogate{ std::nullopt }; - bool _isReadOnly{ false }; // Probably belongs in Interactivity - std::optional _lastHoveredCell{ std::nullopt }; // Track the last hyperlink ID we hovered over uint16_t _lastHoveredId{ 0 }; + bool _isReadOnly{ false }; + std::optional::interval> _lastHoveredInterval{ std::nullopt }; double _panelWidth{ 0 }; @@ -212,6 +212,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation #pragma endregion void _raiseHoveredHyperlinkChanged(); + void _RaiseReadOnlyWarning(); friend class ControlUnitTests::ControlCoreTests; friend class ControlUnitTests::ControlInteractivityTests; diff --git a/src/cascadia/TerminalControl/ControlInteractivity.cpp b/src/cascadia/TerminalControl/ControlInteractivity.cpp index 330c3439fde..b09ac0276b2 100644 --- a/src/cascadia/TerminalControl/ControlInteractivity.cpp +++ b/src/cascadia/TerminalControl/ControlInteractivity.cpp @@ -48,6 +48,11 @@ namespace winrt::Microsoft::Terminal::Control::implementation _multiClickTimer = GetDoubleClickTime() * 1000; } + winrt::com_ptr ControlInteractivity::GetCore() + { + return _core; + } + // Method Description: // - Returns the number of clicks that occurred (double and triple click support). // Every call to this function registers a click. @@ -128,8 +133,9 @@ namespace winrt::Microsoft::Terminal::Control::implementation // - Initiate a paste operation. void ControlInteractivity::PasteTextFromClipboard() { - // attach TermControl::_SendInputToConnection() as the clipboardDataHandler. - // This is called when the clipboard data is loaded. + // attach ControlInteractivity::_SendPastedTextToConnection() as the + // clipboardDataHandler. This is called when the clipboard data is + // loaded. auto clipboardDataHandler = std::bind(&ControlInteractivity::_SendPastedTextToConnection, this, std::placeholders::_1); auto pasteArgs = winrt::make_self(clipboardDataHandler); @@ -145,7 +151,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation _core->PasteText(winrt::hstring{ wstr }); } - // TODO: Don't take a Windows::UI::Input::PointerPoint here. No WinUI here. void ControlInteractivity::PointerPressed(const winrt::Windows::Foundation::Point mouseCursorPosition, TerminalInput::MouseButtonState buttonState, const unsigned int pointerUpdateKind, @@ -227,7 +232,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation _touchAnchor = contactPoint; } - // TODO: Don't take a Windows::UI::Input::PointerPoint here void ControlInteractivity::PointerMoved(const winrt::Windows::Foundation::Point mouseCursorPosition, TerminalInput::MouseButtonState buttonState, const unsigned int pointerUpdateKind, @@ -260,7 +264,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation } } - _SetEndSelectionPoint(terminalPosition); + SetEndSelectionPoint(terminalPosition); // const double cursorBelowBottomDist = cursorPosition.Y - SwapChainPanel().Margin().Top - SwapChainPanel().ActualHeight(); // const double cursorAboveTopDist = -1 * cursorPosition.Y + SwapChainPanel().Margin().Top; @@ -287,42 +291,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation } _core->UpdateHoveredCell(terminalPosition); - // else if (focused && - // type == Windows::Devices::Input::PointerDeviceType::Touch && - // _touchAnchor) - // { - // const auto contactRect = point.Properties().ContactRect(); - // winrt::Windows::Foundation::Point newTouchPoint{ contactRect.X, contactRect.Y }; - // const auto anchor = _touchAnchor.value(); - - // // Our actualFont's size is in pixels, convert to DIPs, which the - // // rest of the Points here are in. - // const til::size fontSize{ _core->GetFont().GetSize() }; - // const auto fontSizeInDips = fontSize.scale(til::math::rounding, 1.0f / _core->RendererScale()); - - // // Get the difference between the point we've dragged to and the start of the touch. - // const float dy = newTouchPoint.Y - anchor.Y; - - // // Start viewport scroll after we've moved more than a half row of text - // if (std::abs(dy) > (fontSizeInDips.height() / 2.0f)) - // { - // // Multiply by -1, because moving the touch point down will - // // create a positive delta, but we want the viewport to move up, - // // so we'll need a negative scroll amount (and the inverse for - // // panning down) - // const float numRows = -1.0f * (dy / fontSizeInDips.height()); - - // const auto currentOffset = ::base::ClampedNumeric(_core->ScrollOffset()); - // const auto newValue = numRows + currentOffset; - - // // Update the Core's viewport position, and raise a - // // ScrollPositionChanged event to update the scrollbar - // _updateScrollbar(newValue); - - // // Use this point as our new scroll anchor. - // _touchAnchor = newTouchPoint; - // } - // } } void ControlInteractivity::TouchMoved(const winrt::Windows::Foundation::Point newTouchPoint, @@ -397,57 +365,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation _touchAnchor = std::nullopt; } - // // Method Description: - // // - Send this particular mouse event to the terminal. - // // See Terminal::SendMouseEvent for more information. - // // Arguments: - // // - point: the PointerPoint object representing a mouse event from our XAML input handler - // bool ControlInteractivity::_TrySendMouseEvent(Windows::UI::Input::PointerPoint const& point, - // const ::Microsoft::Terminal::Core::ControlKeyStates modifiers, - // const til::point terminalPosition) - // { - // const auto props = point.Properties(); - - // // Which mouse button changed state (and how) - // unsigned int uiButton{}; - // switch (props.PointerUpdateKind()) - // { - // case winrt::Windows::UI::Input::PointerUpdateKind::LeftButtonPressed: - // uiButton = WM_LBUTTONDOWN; - // break; - // case winrt::Windows::UI::Input::PointerUpdateKind::LeftButtonReleased: - // uiButton = WM_LBUTTONUP; - // break; - // case winrt::Windows::UI::Input::PointerUpdateKind::MiddleButtonPressed: - // uiButton = WM_MBUTTONDOWN; - // break; - // case winrt::Windows::UI::Input::PointerUpdateKind::MiddleButtonReleased: - // uiButton = WM_MBUTTONUP; - // break; - // case winrt::Windows::UI::Input::PointerUpdateKind::RightButtonPressed: - // uiButton = WM_RBUTTONDOWN; - // break; - // case winrt::Windows::UI::Input::PointerUpdateKind::RightButtonReleased: - // uiButton = WM_RBUTTONUP; - // break; - // default: - // uiButton = WM_MOUSEMOVE; - // } - - // // Mouse wheel data - // const short sWheelDelta = ::base::saturated_cast(props.MouseWheelDelta()); - // if (sWheelDelta != 0 && !props.IsHorizontalMouseWheel()) - // { - // // if we have a mouse wheel delta and it wasn't a horizontal wheel motion - // uiButton = WM_MOUSEWHEEL; - // } - - // const TerminalInput::MouseButtonState state{ props.IsLeftButtonPressed(), - // props.IsMiddleButtonPressed(), - // props.IsRightButtonPressed() }; - // return _core->SendMouseEvent(terminalPosition, uiButton, modifiers, sWheelDelta, state); - // } - // Method Description: // - Send this particular mouse event to the terminal. // See Terminal::SendMouseEvent for more information. @@ -579,7 +496,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation { // If user is mouse selecting and scrolls, they then point at new // character. Make sure selection reflects that immediately. - _SetEndSelectionPoint(terminalPosition); + SetEndSelectionPoint(terminalPosition); } } @@ -633,7 +550,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation // - Sets selection's end position to match supplied cursor position, e.g. while mouse dragging. // Arguments: // - cursorPosition: in pixels, relative to the origin of the control - void ControlInteractivity::_SetEndSelectionPoint(const til::point terminalPosition) + void ControlInteractivity::SetEndSelectionPoint(const til::point terminalPosition) { _core->SetEndSelectionPoint(terminalPosition); _selectionNeedsToBeCopied = true; diff --git a/src/cascadia/TerminalControl/ControlInteractivity.h b/src/cascadia/TerminalControl/ControlInteractivity.h index 0aecb89d8c5..0c7a5bd0127 100644 --- a/src/cascadia/TerminalControl/ControlInteractivity.h +++ b/src/cascadia/TerminalControl/ControlInteractivity.h @@ -25,13 +25,16 @@ namespace winrt::Microsoft::Terminal::Control::implementation { struct ControlInteractivity : ControlInteractivityT { + public: ControlInteractivity(IControlSettings settings, TerminalConnection::ITerminalConnection connection); void GainFocus(); void UpdateSettings(); void Initialize(); - //////////////////////////////////////////////////////////////////////// + winrt::com_ptr GetCore(); + +#pragma region InputMethods void PointerPressed(const winrt::Windows::Foundation::Point mouseCursorPosition, ::Microsoft::Console::VirtualTerminal::TerminalInput::MouseButtonState buttonState, const unsigned int pointerUpdateKind, @@ -58,14 +61,16 @@ namespace winrt::Microsoft::Terminal::Control::implementation const int32_t delta, const til::point terminalPosition, const ::Microsoft::Console::VirtualTerminal::TerminalInput::MouseButtonState state); - //////////////////////////////////////////////////////////////////////// +#pragma endregion bool CopySelectionToClipboard(bool singleLine, const Windows::Foundation::IReference& formats); void PasteTextFromClipboard(); - /////////////////////// From Control + void SetEndSelectionPoint(const til::point terminalPosition); + + private: winrt::com_ptr _core{ nullptr }; - unsigned int _rowsToScroll; // Definitely Control/Interactivity + unsigned int _rowsToScroll; // If this is set, then we assume we are in the middle of panning the // viewport via touch input. @@ -86,10 +91,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation // since it was last copied. It's generally used to prevent copyOnSelect // from firing when the pointer _just happens_ to be released over the // terminal. - bool _selectionNeedsToBeCopied; // ->Interactivity - - /////////////////////// From Core - bool _isReadOnly{ false }; // Probably belongs in Interactivity + bool _selectionNeedsToBeCopied; std::optional _lastHoveredCell{ std::nullopt }; // Track the last hyperlink ID we hovered over @@ -99,9 +101,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation unsigned int _NumberOfClicks(winrt::Windows::Foundation::Point clickPos, Timestamp clickTime); void _UpdateSystemParameterSettings() noexcept; - // bool _TrySendMouseEvent(Windows::UI::Input::PointerPoint const& point, - // const ::Microsoft::Terminal::Core::ControlKeyStates modifiers, - // const til::point terminalPosition); bool _TrySendMouseEvent(const unsigned int updateKind, const ::Microsoft::Console::VirtualTerminal::TerminalInput::MouseButtonState buttonState, const ::Microsoft::Terminal::Core::ControlKeyStates modifiers, @@ -119,7 +118,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation void _HyperlinkHandler(const std::wstring_view uri); bool _CanSendVTMouseInput(const ::Microsoft::Terminal::Core::ControlKeyStates modifiers); - void _SetEndSelectionPoint(const til::point terminalPosition); void _SendPastedTextToConnection(const std::wstring& wstr); void _updateScrollbar(const int newValue); diff --git a/src/cascadia/TerminalControl/TermControl.cpp b/src/cascadia/TerminalControl/TermControl.cpp index 963724e1b25..b3b18ae4743 100644 --- a/src/cascadia/TerminalControl/TermControl.cpp +++ b/src/cascadia/TerminalControl/TermControl.cpp @@ -60,7 +60,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation InitializeComponent(); _interactivity = winrt::make_self(settings, connection); - _core = _interactivity->_core; + _core = _interactivity->GetCore(); _core->BackgroundColorChanged({ get_weak(), &TermControl::_BackgroundColorChangedHandler }); _core->ScrollPositionChanged({ get_weak(), &TermControl::_ScrollPositionChanged }); @@ -1346,8 +1346,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation } // Method Description: - // - Called continuously to gradually scroll viewport when user is - // mouse selecting outside it (to 'follow' the cursor). + // - Called continuously to gradually scroll viewport when user is mouse + // selecting outside it (to 'follow' the cursor). // Arguments: // - none void TermControl::_UpdateAutoScroll(Windows::Foundation::IInspectable const& /* sender */, @@ -1544,13 +1544,13 @@ namespace winrt::Microsoft::Terminal::Control::implementation } } - // // Method Description: - // // - Sets selection's end position to match supplied cursor position, e.g. while mouse dragging. - // // Arguments: - // // - cursorPosition: in pixels, relative to the origin of the control + // Method Description: + // - Sets selection's end position to match supplied cursor position, e.g. while mouse dragging. + // Arguments: + // - cursorPosition: in pixels, relative to the origin of the control void TermControl::_SetEndSelectionPointAtCursor(Windows::Foundation::Point const& cursorPosition) { - _interactivity->_SetEndSelectionPoint(_GetTerminalPosition(cursorPosition)); + _interactivity->SetEndSelectionPoint(_GetTerminalPosition(cursorPosition)); } // Method Description: @@ -2305,17 +2305,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation _ReadOnlyChangedHandlers(*this, winrt::box_value(_core->IsInReadOnlyMode())); } - winrt::fire_and_forget TermControl::_RaiseReadOnlyWarning() - { - auto weakThis{ get_weak() }; - co_await winrt::resume_foreground(Dispatcher()); - - if (auto control{ weakThis.get() }) - { - auto noticeArgs = winrt::make(NoticeLevel::Info, RS_(L"TermControlReadOnly")); - control->_RaiseNoticeHandlers(*control, std::move(noticeArgs)); - } - } // Method Description: // - Handle a mouse exited event, specifically clearing last hovered cell // and removing selection from hyper link if exists diff --git a/src/cascadia/TerminalControl/TermControl.h b/src/cascadia/TerminalControl/TermControl.h index 1c94d1dac11..a4f734cdf8d 100644 --- a/src/cascadia/TerminalControl/TermControl.h +++ b/src/cascadia/TerminalControl/TermControl.h @@ -224,7 +224,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation void _CurrentCursorPositionHandler(const IInspectable& sender, const CursorPositionEventArgs& eventArgs); void _FontInfoHandler(const IInspectable& sender, const FontInfoEventArgs& eventArgs); - winrt::fire_and_forget _RaiseReadOnlyWarning(); winrt::fire_and_forget _hoveredHyperlinkChanged(const IInspectable& sender, const IInspectable& args); void _coreFontSizeChanged(const int fontWidth, From 8bd5bb075b87c3129bad39076dc0a1de8d8fcc25 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Wed, 7 Apr 2021 09:52:41 -0500 Subject: [PATCH 46/82] Convert ControlCore's privates to _camelCase --- src/cascadia/TerminalControl/ControlCore.cpp | 100 +++++++++---------- src/cascadia/TerminalControl/ControlCore.h | 37 +++---- 2 files changed, 69 insertions(+), 68 deletions(-) diff --git a/src/cascadia/TerminalControl/ControlCore.cpp b/src/cascadia/TerminalControl/ControlCore.cpp index 01dab1c1bcb..359cf215d5b 100644 --- a/src/cascadia/TerminalControl/ControlCore.cpp +++ b/src/cascadia/TerminalControl/ControlCore.cpp @@ -79,34 +79,34 @@ namespace winrt::Microsoft::Terminal::Control::implementation _connectionOutputEventToken = _connection.TerminalOutput(onReceiveOutputFn); _terminal->SetWriteInputCallback([this](std::wstring& wstr) { - _SendInputToConnection(wstr); + _sendInputToConnection(wstr); }); // GH#8969: pre-seed working directory to prevent potential races _terminal->SetWorkingDirectory(_settings.StartingDirectory()); - auto pfnCopyToClipboard = std::bind(&ControlCore::_TerminalCopyToClipboard, this, std::placeholders::_1); + auto pfnCopyToClipboard = std::bind(&ControlCore::_terminalCopyToClipboard, this, std::placeholders::_1); _terminal->SetCopyToClipboardCallback(pfnCopyToClipboard); - auto pfnWarningBell = std::bind(&ControlCore::_TerminalWarningBell, this); + auto pfnWarningBell = std::bind(&ControlCore::_terminalWarningBell, this); _terminal->SetWarningBellCallback(pfnWarningBell); - auto pfnTitleChanged = std::bind(&ControlCore::_TerminalTitleChanged, this, std::placeholders::_1); + auto pfnTitleChanged = std::bind(&ControlCore::_terminalTitleChanged, this, std::placeholders::_1); _terminal->SetTitleChangedCallback(pfnTitleChanged); - auto pfnTabColorChanged = std::bind(&ControlCore::_TerminalTabColorChanged, this, std::placeholders::_1); + auto pfnTabColorChanged = std::bind(&ControlCore::_terminalTabColorChanged, this, std::placeholders::_1); _terminal->SetTabColorChangedCallback(pfnTabColorChanged); - auto pfnBackgroundColorChanged = std::bind(&ControlCore::_TerminalBackgroundColorChanged, this, std::placeholders::_1); + auto pfnBackgroundColorChanged = std::bind(&ControlCore::_terminalBackgroundColorChanged, this, std::placeholders::_1); _terminal->SetBackgroundCallback(pfnBackgroundColorChanged); - auto pfnScrollPositionChanged = std::bind(&ControlCore::_TerminalScrollPositionChanged, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3); + auto pfnScrollPositionChanged = std::bind(&ControlCore::_terminalScrollPositionChanged, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3); _terminal->SetScrollPositionChangedCallback(pfnScrollPositionChanged); - auto pfnTerminalCursorPositionChanged = std::bind(&ControlCore::_TerminalCursorPositionChanged, this); + auto pfnTerminalCursorPositionChanged = std::bind(&ControlCore::_terminalCursorPositionChanged, this); _terminal->SetCursorPositionChangedCallback(pfnTerminalCursorPositionChanged); - auto pfnTerminalTaskbarProgressChanged = std::bind(&ControlCore::_TerminalTaskbarProgressChanged, this); + auto pfnTerminalTaskbarProgressChanged = std::bind(&ControlCore::_terminalTaskbarProgressChanged, this); _terminal->TaskbarProgressChangedCallback(pfnTerminalTaskbarProgressChanged); _terminal->UpdateSettings(settings); @@ -171,7 +171,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation // Initialize our font with the renderer // We don't have to care about DPI. We'll get a change message immediately if it's not 96 // and react accordingly. - _UpdateFont(true); + _updateFont(true); const COORD windowSize{ static_cast(windowWidth), static_cast(windowHeight) }; @@ -200,11 +200,11 @@ namespace winrt::Microsoft::Terminal::Control::implementation // after Enable, then it'll be possible to paint the frame once // _before_ the warning handler is set up, and then warnings from // the first paint will be ignored! - dxEngine->SetWarningCallback(std::bind(&ControlCore::_RendererWarning, this, std::placeholders::_1)); + dxEngine->SetWarningCallback(std::bind(&ControlCore::_rendererWarning, this, std::placeholders::_1)); // Tell the DX Engine to notify us when the swap chain changes. // We do this after we initially set the swapchain so as to avoid unnecessary callbacks (and locking problems) - dxEngine->SetCallback(std::bind(&ControlCore::RenderEngineSwapChainChanged, this)); + dxEngine->SetCallback(std::bind(&ControlCore::_renderEngineSwapChainChanged, this)); dxEngine->SetRetroTerminalEffect(_settings.RetroTerminalEffect()); dxEngine->SetPixelShaderPath(_settings.PixelShaderPath()); @@ -235,7 +235,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation THROW_IF_FAILED(dxEngine->Enable()); _renderEngine = std::move(dxEngine); - // In the past we did _AttachDxgiSwapChainToXaml _before_ calling + // In the past we did _attachDxgiSwapChainToXaml _before_ calling // EnablePainting. There's mild worry that doing EnablePainting // first will break something, but this seems to work. localPointerToThread->EnablePainting(); @@ -256,11 +256,11 @@ namespace winrt::Microsoft::Terminal::Control::implementation // - wstr: the string of characters to write to the terminal connection. // Return Value: // - - void ControlCore::_SendInputToConnection(const winrt::hstring& wstr) + void ControlCore::_sendInputToConnection(const winrt::hstring& wstr) { if (_isReadOnly) { - _RaiseReadOnlyWarning(); + _raiseReadOnlyWarning(); } else { @@ -268,11 +268,11 @@ namespace winrt::Microsoft::Terminal::Control::implementation } } - void ControlCore::_SendInputToConnection(std::wstring_view wstr) + void ControlCore::_sendInputToConnection(std::wstring_view wstr) { if (_isReadOnly) { - _RaiseReadOnlyWarning(); + _raiseReadOnlyWarning(); } else { @@ -288,7 +288,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation // - void ControlCore::SendInput(const winrt::hstring& wstr) { - _SendInputToConnection(wstr); + _sendInputToConnection(wstr); } bool ControlCore::SendCharEvent(const wchar_t ch, @@ -388,7 +388,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation if (newOpacity >= 1.0) { _settings.UseAcrylic(false); - // _InitializeBackgroundBrush(); + // _initializeBackgroundBrush(); // COLORREF bg = _settings.DefaultBackground(); // _changeBackgroundColor(bg); } @@ -568,11 +568,11 @@ namespace winrt::Microsoft::Terminal::Control::implementation // Refresh our font with the renderer const auto actualFontOldSize = _actualFont.GetSize(); - _UpdateFont(); + _updateFont(); const auto actualFontNewSize = _actualFont.GetSize(); if (actualFontNewSize != actualFontOldSize) { - _RefreshSizeUnderLock(); + _refreshSizeUnderLock(); } } @@ -581,12 +581,12 @@ namespace winrt::Microsoft::Terminal::Control::implementation // font changes or the DPI changes, as DPI changes will necessitate a // font change. This method will *not* change the buffer/viewport size // to account for the new glyph dimensions. Callers should make sure to - // appropriately call _DoResizeUnderLock after this method is called. + // appropriately call _doResizeUnderLock after this method is called. // - The write lock should be held when calling this method. // Arguments: // - initialUpdate: whether this font update should be considered as being // concerned with initialization process. Value forwarded to event handler. - void ControlCore::_UpdateFont(const bool initialUpdate) + void ControlCore::_updateFont(const bool initialUpdate) { const int newDpi = static_cast(static_cast(USER_DEFAULT_SCREEN_DPI) * _compositionScaleX); @@ -615,7 +615,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation // - Set the font size of the terminal control. // Arguments: // - fontSize: The size of the font. - void ControlCore::_SetFontSize(int fontSize) + void ControlCore::_setFontSize(int fontSize) { try { @@ -629,13 +629,13 @@ namespace winrt::Microsoft::Terminal::Control::implementation auto lock = _terminal->LockForWriting(); // Refresh our font with the renderer - _UpdateFont(); + _updateFont(); // Resize the terminal's BUFFER to match the new font size. This does // NOT change the size of the window, because that can lead to more // problems (like what happens when you change the font size while the // window is maximized?) - _RefreshSizeUnderLock(); + _refreshSizeUnderLock(); } CATCH_LOG(); } @@ -646,7 +646,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation // - none void ControlCore::ResetFontSize() { - _SetFontSize(_settings.FontSize()); + _setFontSize(_settings.FontSize()); } // Method Description: @@ -656,23 +656,23 @@ namespace winrt::Microsoft::Terminal::Control::implementation void ControlCore::AdjustFontSize(int fontSizeDelta) { const auto newSize = _desiredFont.GetEngineSize().Y + fontSizeDelta; - _SetFontSize(newSize); + _setFontSize(newSize); } // Method Description: // - Perform a resize for the current size of the swapchainpanel. If the // font size changed, we'll need to resize the buffer to fit the existing - // swapchain size. This helper will call _DoResizeUnderLock with the + // swapchain size. This helper will call _doResizeUnderLock with the // current size of the swapchain, accounting for scaling due to DPI. // - Note that a DPI change will also trigger a font size change, and will // call into here. // - The write lock should be held when calling this method, we might be - // changing the buffer size in _DoResizeUnderLock. + // changing the buffer size in _doResizeUnderLock. // Arguments: // - // Return Value: // - - void ControlCore::_RefreshSizeUnderLock() + void ControlCore::_refreshSizeUnderLock() { // const auto currentScaleX = SwapChainPanel().CompositionScaleX(); // const auto currentScaleY = SwapChainPanel().CompositionScaleY(); @@ -682,7 +682,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation const auto widthInPixels = _panelWidth * _compositionScaleX; const auto heightInPixels = _panelHeight * _compositionScaleY; - _DoResizeUnderLock(widthInPixels, heightInPixels); + _doResizeUnderLock(widthInPixels, heightInPixels); } // Method Description: @@ -693,7 +693,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation // Arguments: // - newWidth: the new width of the swapchain, in pixels. // - newHeight: the new height of the swapchain, in pixels. - void ControlCore::_DoResizeUnderLock(const double newWidth, + void ControlCore::_doResizeUnderLock(const double newWidth, const double newHeight) { SIZE size; @@ -740,7 +740,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation auto scaledWidth = width * currentEngineScale; auto scaledHeight = height * currentEngineScale; - _DoResizeUnderLock(scaledWidth, scaledHeight); + _doResizeUnderLock(scaledWidth, scaledHeight); } void ControlCore::ScaleChanged(const double scaleX, @@ -758,7 +758,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation // If we're getting a notification to change to the DPI we already // have, then we're probably just beginning the DPI change. Since // we'll get _another_ event with the real DPI, do nothing here for - // now. We'll also skip the next resize in _SwapChainSizeChanged. + // now. We'll also skip the next resize in _swapChainSizeChanged. const bool dpiWasUnchanged = currentEngineScale == scaleX; if (dpiWasUnchanged) { @@ -778,7 +778,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation const auto actualFontNewSize = _actualFont.GetSize(); if (actualFontNewSize != actualFontOldSize) { - _RefreshSizeUnderLock(); + _refreshSizeUnderLock(); } } @@ -828,7 +828,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation // Called when the Terminal wants to set something to the clipboard, i.e. // when an OSC 52 is emitted. - void ControlCore::_TerminalCopyToClipboard(const std::wstring_view& wstr) + void ControlCore::_terminalCopyToClipboard(const std::wstring_view& wstr) { auto copyArgs = winrt::make_self(winrt::hstring(wstr)); _CopyToClipboardHandlers(*this, *copyArgs); @@ -986,22 +986,22 @@ namespace winrt::Microsoft::Terminal::Control::implementation return _terminal->GetBufferHeight(); } - void ControlCore::_TerminalWarningBell() + void ControlCore::_terminalWarningBell() { _WarningBellHandlers(*this, nullptr); } - void ControlCore::_TerminalTitleChanged(const std::wstring_view& wstr) + void ControlCore::_terminalTitleChanged(const std::wstring_view& wstr) { auto titleArgs = winrt::make_self(winrt::hstring{ wstr }); _TitleChangedHandlers(*this, *titleArgs); } - void ControlCore::_TerminalTabColorChanged(const std::optional /*color*/) + void ControlCore::_terminalTabColorChanged(const std::optional /*color*/) { _TabColorChangedHandlers(*this, nullptr); } - void ControlCore::_TerminalBackgroundColorChanged(const COLORREF color) + void ControlCore::_terminalBackgroundColorChanged(const COLORREF color) { _backgroundColor = color; _BackgroundColorChangedHandlers(*this, nullptr); @@ -1017,12 +1017,12 @@ namespace winrt::Microsoft::Terminal::Control::implementation // of the buffer. // - viewHeight: the height of the viewport in rows. // - bufferSize: the length of the buffer, in rows - void ControlCore::_TerminalScrollPositionChanged(const int viewTop, + void ControlCore::_terminalScrollPositionChanged(const int viewTop, const int viewHeight, const int bufferSize) { // Clear the regex pattern tree so the renderer does not try to render them while scrolling - // We're **NOT** taking the lock here unlike _ScrollbarChangeHandler because + // We're **NOT** taking the lock here unlike _scrollbarChangeHandler because // we are already under lock (since this usually happens as a result of writing). // TODO GH#9617: refine locking around pattern tree _terminal->ClearPatternTree(); @@ -1031,12 +1031,12 @@ namespace winrt::Microsoft::Terminal::Control::implementation _ScrollPositionChangedHandlers(*this, *scrollArgs); } - void ControlCore::_TerminalCursorPositionChanged() + void ControlCore::_terminalCursorPositionChanged() { _CursorPositionChangedHandlers(*this, nullptr); } - void ControlCore::_TerminalTaskbarProgressChanged() + void ControlCore::_terminalTaskbarProgressChanged() { _TaskbarProgressChangedHandlers(*this, nullptr); } @@ -1115,7 +1115,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation // - // Return Value: // - - winrt::fire_and_forget ControlCore::_AsyncCloseConnection() + winrt::fire_and_forget ControlCore::_asyncCloseConnection() { if (auto localConnection{ std::exchange(_connection, nullptr) }) { @@ -1139,7 +1139,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation // Since TermControl::Close is only ever triggered by the UI, we // don't really care to wait for the connection to be completely // closed. We can just do it whenever. - _AsyncCloseConnection(); + _asyncCloseConnection(); { // GH#8734: @@ -1172,13 +1172,13 @@ namespace winrt::Microsoft::Terminal::Control::implementation return _renderEngine->GetSwapChainHandle(); } - void ControlCore::_RendererWarning(const HRESULT hr) + void ControlCore::_rendererWarning(const HRESULT hr) { auto args{ winrt::make_self(hr) }; _RendererWarningHandlers(*this, *args); } - void ControlCore::RenderEngineSwapChainChanged() + void ControlCore::_renderEngineSwapChainChanged() { _SwapChainChangedHandlers(*this, nullptr); } @@ -1316,7 +1316,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation _isReadOnly = !_isReadOnly; } - void ControlCore::_RaiseReadOnlyWarning() + void ControlCore::_raiseReadOnlyWarning() { auto noticeArgs = winrt::make(NoticeLevel::Info, RS_(L"TermControlReadOnly")); _RaiseNoticeHandlers(*this, std::move(noticeArgs)); diff --git a/src/cascadia/TerminalControl/ControlCore.h b/src/cascadia/TerminalControl/ControlCore.h index e5718526ac4..91e0a795984 100644 --- a/src/cascadia/TerminalControl/ControlCore.h +++ b/src/cascadia/TerminalControl/ControlCore.h @@ -63,7 +63,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation ::Microsoft::Console::Types::IUiaData* GetUiaData() const; - winrt::fire_and_forget _AsyncCloseConnection(); void Close(); #pragma region ICoreState @@ -184,35 +183,37 @@ namespace winrt::Microsoft::Terminal::Control::implementation double _compositionScaleY{ 0 }; til::color _backgroundColor; // !TODO! This is _in_ Terminal already! - void _SetFontSize(int fontSize); - void _UpdateFont(const bool initialUpdate = false); - void _RefreshSizeUnderLock(); - void _DoResizeUnderLock(const double newWidth, + winrt::fire_and_forget _asyncCloseConnection(); + + void _setFontSize(int fontSize); + void _updateFont(const bool initialUpdate = false); + void _refreshSizeUnderLock(); + void _doResizeUnderLock(const double newWidth, const double newHeight); - void _SendInputToConnection(const winrt::hstring& wstr); - void _SendInputToConnection(std::wstring_view wstr); + void _sendInputToConnection(const winrt::hstring& wstr); + void _sendInputToConnection(std::wstring_view wstr); #pragma region TerminalCoreCallbacks - void _TerminalCopyToClipboard(const std::wstring_view& wstr); - void _TerminalWarningBell(); - void _TerminalTitleChanged(const std::wstring_view& wstr); - void _TerminalTabColorChanged(const std::optional color); - void _TerminalBackgroundColorChanged(const COLORREF color); - void _TerminalScrollPositionChanged(const int viewTop, + void _terminalCopyToClipboard(const std::wstring_view& wstr); + void _terminalWarningBell(); + void _terminalTitleChanged(const std::wstring_view& wstr); + void _terminalTabColorChanged(const std::optional color); + void _terminalBackgroundColorChanged(const COLORREF color); + void _terminalScrollPositionChanged(const int viewTop, const int viewHeight, const int bufferSize); - void _TerminalCursorPositionChanged(); - void _TerminalTaskbarProgressChanged(); + void _terminalCursorPositionChanged(); + void _terminalTaskbarProgressChanged(); #pragma endregion #pragma region RendererCallbacks - void _RendererWarning(const HRESULT hr); - void RenderEngineSwapChainChanged(); + void _rendererWarning(const HRESULT hr); + void _renderEngineSwapChainChanged(); #pragma endregion void _raiseHoveredHyperlinkChanged(); - void _RaiseReadOnlyWarning(); + void _raiseReadOnlyWarning(); friend class ControlUnitTests::ControlCoreTests; friend class ControlUnitTests::ControlInteractivityTests; From 61e91f686dfabb5b34d090934c3e4e5b343cb4a4 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Wed, 7 Apr 2021 10:00:31 -0500 Subject: [PATCH 47/82] Same deal, _camelCase the privates of ControlInteractivity --- .../TerminalControl/ControlInteractivity.cpp | 69 +++++++++---------- .../TerminalControl/ControlInteractivity.h | 20 +++--- src/cascadia/TerminalControl/TermControl.cpp | 2 +- 3 files changed, 44 insertions(+), 47 deletions(-) diff --git a/src/cascadia/TerminalControl/ControlInteractivity.cpp b/src/cascadia/TerminalControl/ControlInteractivity.cpp index b09ac0276b2..f65a3f659c4 100644 --- a/src/cascadia/TerminalControl/ControlInteractivity.cpp +++ b/src/cascadia/TerminalControl/ControlInteractivity.cpp @@ -37,12 +37,12 @@ namespace winrt::Microsoft::Terminal::Control::implementation void ControlInteractivity::UpdateSettings() { - _UpdateSystemParameterSettings(); + _updateSystemParameterSettings(); } void ControlInteractivity::Initialize() { - _UpdateSystemParameterSettings(); + _updateSystemParameterSettings(); // import value from WinUser (convert from milli-seconds to micro-seconds) _multiClickTimer = GetDoubleClickTime() * 1000; @@ -63,7 +63,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation // Return Value: // - if the click is in the same position as the last click and within the timeout, the number of clicks within that time window // - otherwise, 1 - unsigned int ControlInteractivity::_NumberOfClicks(winrt::Windows::Foundation::Point clickPos, + unsigned int ControlInteractivity::_numberOfClicks(winrt::Windows::Foundation::Point clickPos, Timestamp clickTime) { // if click occurred at a different location or past the multiClickTimer... @@ -85,12 +85,12 @@ namespace winrt::Microsoft::Terminal::Control::implementation void ControlInteractivity::GainFocus() { - _UpdateSystemParameterSettings(); + _updateSystemParameterSettings(); } // Method Description // - Updates internal params based on system parameters - void ControlInteractivity::_UpdateSystemParameterSettings() noexcept + void ControlInteractivity::_updateSystemParameterSettings() noexcept { if (!SystemParametersInfoW(SPI_GETWHEELSCROLLLINES, 0, &_rowsToScroll, 0)) { @@ -133,10 +133,10 @@ namespace winrt::Microsoft::Terminal::Control::implementation // - Initiate a paste operation. void ControlInteractivity::PasteTextFromClipboard() { - // attach ControlInteractivity::_SendPastedTextToConnection() as the + // attach ControlInteractivity::_sendPastedTextToConnection() as the // clipboardDataHandler. This is called when the clipboard data is // loaded. - auto clipboardDataHandler = std::bind(&ControlInteractivity::_SendPastedTextToConnection, this, std::placeholders::_1); + auto clipboardDataHandler = std::bind(&ControlInteractivity::_sendPastedTextToConnection, this, std::placeholders::_1); auto pasteArgs = winrt::make_self(clipboardDataHandler); // send paste event up to TermApp @@ -146,7 +146,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation // Method Description: // - Pre-process text pasted (presumably from the clipboard) // before sending it over the terminal's connection. - void ControlInteractivity::_SendPastedTextToConnection(const std::wstring& wstr) + void ControlInteractivity::_sendPastedTextToConnection(const std::wstring& wstr) { _core->PasteText(winrt::hstring{ wstr }); } @@ -163,8 +163,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation const auto shiftEnabled = modifiers.IsShiftPressed(); const auto ctrlEnabled = modifiers.IsCtrlPressed(); - // const auto cursorPosition = point.Position(); - // GH#9396: we prioritize hyper-link over VT mouse events // // !TODO! Before we'd lock the terminal before getting the hyperlink. Do we still need to? @@ -172,20 +170,20 @@ namespace winrt::Microsoft::Terminal::Control::implementation if (buttonState.isLeftButtonDown && ctrlEnabled && !hyperlink.empty()) { - const auto clickCount = _NumberOfClicks(mouseCursorPosition, timestamp); + const auto clickCount = _numberOfClicks(mouseCursorPosition, timestamp); // Handle hyper-link only on the first click to prevent multiple activations if (clickCount == 1) { - _HyperlinkHandler(hyperlink); + _hyperlinkHandler(hyperlink); } } - else if (_CanSendVTMouseInput(modifiers)) + else if (_canSendVTMouseInput(modifiers)) { - _TrySendMouseEvent(pointerUpdateKind, buttonState, modifiers, terminalPosition); + _trySendMouseEvent(pointerUpdateKind, buttonState, modifiers, terminalPosition); } else if (buttonState.isLeftButtonDown) { - const auto clickCount = _NumberOfClicks(mouseCursorPosition, timestamp); + const auto clickCount = _numberOfClicks(mouseCursorPosition, timestamp); // This formula enables the number of clicks to cycle properly // between single-, double-, and triple-click. To increase the // number of acceptable click states, simply increment @@ -240,9 +238,9 @@ namespace winrt::Microsoft::Terminal::Control::implementation const til::point terminalPosition) { // Short-circuit isReadOnly check to avoid warning dialog - if (focused && !_core->IsInReadOnlyMode() && _CanSendVTMouseInput(modifiers)) + if (focused && !_core->IsInReadOnlyMode() && _canSendVTMouseInput(modifiers)) { - _TrySendMouseEvent(pointerUpdateKind, buttonState, modifiers, terminalPosition); + _trySendMouseEvent(pointerUpdateKind, buttonState, modifiers, terminalPosition); } else if (focused && buttonState.isLeftButtonDown) { @@ -273,20 +271,20 @@ namespace winrt::Microsoft::Terminal::Control::implementation // double newAutoScrollVelocity = 0.0; // if (cursorBelowBottomDist > MinAutoScrollDist) // { - // newAutoScrollVelocity = _GetAutoScrollSpeed(cursorBelowBottomDist); + // newAutoScrollVelocity = _getAutoScrollSpeed(cursorBelowBottomDist); // } // else if (cursorAboveTopDist > MinAutoScrollDist) // { - // newAutoScrollVelocity = -1.0 * _GetAutoScrollSpeed(cursorAboveTopDist); + // newAutoScrollVelocity = -1.0 * _getAutoScrollSpeed(cursorAboveTopDist); // } // if (newAutoScrollVelocity != 0) // { - // _TryStartAutoScroll(point, newAutoScrollVelocity); + // _tryStartAutoScroll(point, newAutoScrollVelocity); // } // else // { - // _TryStopAutoScroll(ptr.PointerId()); + // _tryStopAutoScroll(ptr.PointerId()); // } } @@ -338,10 +336,9 @@ namespace winrt::Microsoft::Terminal::Control::implementation const til::point terminalPosition) { // Short-circuit isReadOnly check to avoid warning dialog - if (!_core->IsInReadOnlyMode() && _CanSendVTMouseInput(modifiers)) + if (!_core->IsInReadOnlyMode() && _canSendVTMouseInput(modifiers)) { - _TrySendMouseEvent(pointerUpdateKind, buttonState, modifiers, terminalPosition); - // args.Handled(true); + _trySendMouseEvent(pointerUpdateKind, buttonState, modifiers, terminalPosition); return; } @@ -370,7 +367,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation // See Terminal::SendMouseEvent for more information. // Arguments: // - point: the PointerPoint object representing a mouse event from our XAML input handler - bool ControlInteractivity::_TrySendMouseEvent(const unsigned int updateKind, + bool ControlInteractivity::_trySendMouseEvent(const unsigned int updateKind, const TerminalInput::MouseButtonState buttonState, const ::Microsoft::Terminal::Core::ControlKeyStates modifiers, const til::point terminalPosition) @@ -383,7 +380,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation // See Terminal::SendMouseEvent for more information. // Arguments: // - point: the PointerPoint object representing a mouse event from our XAML input handler - bool ControlInteractivity::_TrySendMouseWheelEvent(const short scrollDelta, + bool ControlInteractivity::_trySendMouseWheelEvent(const short scrollDelta, const TerminalInput::MouseButtonState buttonState, const ::Microsoft::Terminal::Core::ControlKeyStates modifiers, const til::point terminalPosition) @@ -409,10 +406,10 @@ namespace winrt::Microsoft::Terminal::Control::implementation const TerminalInput::MouseButtonState state) { // Short-circuit isReadOnly check to avoid warning dialog - if (!_core->IsInReadOnlyMode() && _CanSendVTMouseInput(modifiers)) + if (!_core->IsInReadOnlyMode() && _canSendVTMouseInput(modifiers)) { // Most mouse event handlers call - // _TrySendMouseEvent(point); + // _trySendMouseEvent(point); // here with a PointerPoint. However, as of #979, we don't have a // PointerPoint to work with. So, we're just going to do a // mousewheel event manually @@ -428,15 +425,15 @@ namespace winrt::Microsoft::Terminal::Control::implementation if (ctrlPressed && shiftPressed) { - _MouseTransparencyHandler(delta); + _mouseTransparencyHandler(delta); } else if (ctrlPressed) { - _MouseZoomHandler(delta); + _mouseZoomHandler(delta); } else { - _MouseScrollHandler(delta, terminalPosition, state.isLeftButtonDown); + _mouseScrollHandler(delta, terminalPosition, state.isLeftButtonDown); } return false; } @@ -446,7 +443,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation // scrolling event. // Arguments: // - mouseDelta: the mouse wheel delta that triggered this event. - void ControlInteractivity::_MouseTransparencyHandler(const double mouseDelta) + void ControlInteractivity::_mouseTransparencyHandler(const double mouseDelta) { // Transparency is on a scale of [0.0,1.0], so only increment by .01. const auto effectiveDelta = mouseDelta < 0 ? -.01 : .01; @@ -458,7 +455,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation // event. // Arguments: // - mouseDelta: the mouse wheel delta that triggered this event. - void ControlInteractivity::_MouseZoomHandler(const double mouseDelta) + void ControlInteractivity::_mouseZoomHandler(const double mouseDelta) { const auto fontDelta = mouseDelta < 0 ? -1 : 1; _core->AdjustFontSize(fontDelta); @@ -470,7 +467,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation // - mouseDelta: the mouse wheel delta that triggered this event. // - point: the location of the mouse during this event // - isLeftButtonPressed: true iff the left mouse button was pressed during this event. - void ControlInteractivity::_MouseScrollHandler(const double mouseDelta, + void ControlInteractivity::_mouseScrollHandler(const double mouseDelta, const til::point terminalPosition, const bool isLeftButtonPressed) { @@ -527,7 +524,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation _ScrollPositionChangedHandlers(*this, *scrollArgs); } - void ControlInteractivity::_HyperlinkHandler(const std::wstring_view uri) + void ControlInteractivity::_hyperlinkHandler(const std::wstring_view uri) { // Save things we need to resume later. winrt::hstring heldUri{ uri }; @@ -535,7 +532,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation _OpenHyperlinkHandlers(*this, *hyperlinkArgs); } - bool ControlInteractivity::_CanSendVTMouseInput(const ::Microsoft::Terminal::Core::ControlKeyStates modifiers) + bool ControlInteractivity::_canSendVTMouseInput(const ::Microsoft::Terminal::Core::ControlKeyStates modifiers) { // If the user is holding down Shift, suppress mouse events // TODO GH#4875: disable/customize this functionality diff --git a/src/cascadia/TerminalControl/ControlInteractivity.h b/src/cascadia/TerminalControl/ControlInteractivity.h index 0c7a5bd0127..a61e6d40b99 100644 --- a/src/cascadia/TerminalControl/ControlInteractivity.h +++ b/src/cascadia/TerminalControl/ControlInteractivity.h @@ -99,27 +99,27 @@ namespace winrt::Microsoft::Terminal::Control::implementation std::optional::interval> _lastHoveredInterval{ std::nullopt }; - unsigned int _NumberOfClicks(winrt::Windows::Foundation::Point clickPos, Timestamp clickTime); - void _UpdateSystemParameterSettings() noexcept; - bool _TrySendMouseEvent(const unsigned int updateKind, + unsigned int _numberOfClicks(winrt::Windows::Foundation::Point clickPos, Timestamp clickTime); + void _updateSystemParameterSettings() noexcept; + bool _trySendMouseEvent(const unsigned int updateKind, const ::Microsoft::Console::VirtualTerminal::TerminalInput::MouseButtonState buttonState, const ::Microsoft::Terminal::Core::ControlKeyStates modifiers, const til::point terminalPosition); - bool _TrySendMouseWheelEvent(const short scrollDelta, + bool _trySendMouseWheelEvent(const short scrollDelta, const ::Microsoft::Console::VirtualTerminal::TerminalInput::MouseButtonState buttonState, const ::Microsoft::Terminal::Core::ControlKeyStates modifiers, const til::point terminalPosition); - void _MouseTransparencyHandler(const double mouseDelta); - void _MouseZoomHandler(const double mouseDelta); - void _MouseScrollHandler(const double mouseDelta, + void _mouseTransparencyHandler(const double mouseDelta); + void _mouseZoomHandler(const double mouseDelta); + void _mouseScrollHandler(const double mouseDelta, const til::point terminalPosition, const bool isLeftButtonPressed); - void _HyperlinkHandler(const std::wstring_view uri); - bool _CanSendVTMouseInput(const ::Microsoft::Terminal::Core::ControlKeyStates modifiers); + void _hyperlinkHandler(const std::wstring_view uri); + bool _canSendVTMouseInput(const ::Microsoft::Terminal::Core::ControlKeyStates modifiers); - void _SendPastedTextToConnection(const std::wstring& wstr); + void _sendPastedTextToConnection(const std::wstring& wstr); void _updateScrollbar(const int newValue); TYPED_EVENT(OpenHyperlink, IInspectable, Control::OpenHyperlinkEventArgs); diff --git a/src/cascadia/TerminalControl/TermControl.cpp b/src/cascadia/TerminalControl/TermControl.cpp index b3b18ae4743..7e7f1c54ad1 100644 --- a/src/cascadia/TerminalControl/TermControl.cpp +++ b/src/cascadia/TerminalControl/TermControl.cpp @@ -1210,7 +1210,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation // be out-of-proc from the UI thread, and won't be able to just use // the UI thread as the dispatcher queue thread. // - // THIS IS ACLLED ON EVERY STRING OF TEXT OUTPUT TO THE TERMINAL. Think + // THIS IS CALLED ON EVERY STRING OF TEXT OUTPUT TO THE TERMINAL. Think // twice before adding anything here. _updatePatternLocations->Run(); From 06a9a10172031b17e4ea44fba8cda40648d36edf Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Wed, 7 Apr 2021 10:16:11 -0500 Subject: [PATCH 48/82] Fix read-only mode --- src/cascadia/TerminalControl/ControlCore.cpp | 13 +------------ src/cascadia/TerminalControl/TermControl.cpp | 7 +++++++ src/cascadia/TerminalControl/TermControl.h | 1 + 3 files changed, 9 insertions(+), 12 deletions(-) diff --git a/src/cascadia/TerminalControl/ControlCore.cpp b/src/cascadia/TerminalControl/ControlCore.cpp index 359cf215d5b..d26c548612d 100644 --- a/src/cascadia/TerminalControl/ControlCore.cpp +++ b/src/cascadia/TerminalControl/ControlCore.cpp @@ -15,7 +15,6 @@ #include "../../buffer/out/search.h" #include "ControlCore.g.cpp" -// #include "TermControlAutomationPeer.h" // ? using namespace ::Microsoft::Console::Types; using namespace ::Microsoft::Console::VirtualTerminal; @@ -135,7 +134,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation return false; } - const auto windowWidth = actualWidth * compositionScaleX; // Width() and Height() are NaN? + const auto windowWidth = actualWidth * compositionScaleX; const auto windowHeight = actualHeight * compositionScaleY; if (windowWidth == 0 || windowHeight == 0) @@ -381,16 +380,11 @@ namespace winrt::Microsoft::Terminal::Control::implementation { try { - // auto acrylicBrush = RootGrid().Background().as(); _settings.TintOpacity(newOpacity); - // acrylicBrush.TintOpacity(_settings.TintOpacity()); if (newOpacity >= 1.0) { _settings.UseAcrylic(false); - // _initializeBackgroundBrush(); - // COLORREF bg = _settings.DefaultBackground(); - // _changeBackgroundColor(bg); } else { @@ -674,11 +668,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation // - void ControlCore::_refreshSizeUnderLock() { - // const auto currentScaleX = SwapChainPanel().CompositionScaleX(); - // const auto currentScaleY = SwapChainPanel().CompositionScaleY(); - // const auto actualWidth = SwapChainPanel().ActualWidth(); - // const auto actualHeight = SwapChainPanel().ActualHeight(); - const auto widthInPixels = _panelWidth * _compositionScaleX; const auto heightInPixels = _panelHeight * _compositionScaleY; diff --git a/src/cascadia/TerminalControl/TermControl.cpp b/src/cascadia/TerminalControl/TermControl.cpp index 7e7f1c54ad1..a757129da99 100644 --- a/src/cascadia/TerminalControl/TermControl.cpp +++ b/src/cascadia/TerminalControl/TermControl.cpp @@ -69,6 +69,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation _core->FontSizeChanged({ get_weak(), &TermControl::_coreFontSizeChanged }); _core->TransparencyChanged({ get_weak(), &TermControl::_coreTransparencyChanged }); _core->ReceivedOutput({ get_weak(), &TermControl::_coreReceivedOutput }); + _core->RaiseNotice({ get_weak(), &TermControl::_coreRaisedNotice }); _interactivity->OpenHyperlink({ get_weak(), &TermControl::_HyperlinkHandler }); _interactivity->ScrollPositionChanged({ get_weak(), &TermControl::_ScrollPositionChanged }); @@ -2365,6 +2366,12 @@ namespace winrt::Microsoft::Terminal::Control::implementation _FontSizeChangedHandlers(fontWidth, fontHeight, isInitialChange); } + void TermControl::_coreRaisedNotice(const IInspectable& /*sender*/, + const Control::NoticeEventArgs& eventArgs) + { + _RaiseNoticeHandlers(*this, eventArgs); + } + TerminalInput::MouseButtonState TermControl::GetPressedMouseButtons(const winrt::Windows::UI::Input::PointerPoint point) { return TerminalInput::MouseButtonState{ point.Properties().IsLeftButtonPressed(), diff --git a/src/cascadia/TerminalControl/TermControl.h b/src/cascadia/TerminalControl/TermControl.h index a4f734cdf8d..e2c9992d636 100644 --- a/src/cascadia/TerminalControl/TermControl.h +++ b/src/cascadia/TerminalControl/TermControl.h @@ -231,6 +231,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation const bool isInitialChange); winrt::fire_and_forget _coreTransparencyChanged(const IInspectable& sender, const Control::TransparencyChangedEventArgs& args); void _coreReceivedOutput(const IInspectable& sender, const IInspectable& args); + void _coreRaisedNotice(const IInspectable& s, const Control::NoticeEventArgs& args); }; } From 198576a7b59f1563ed3a044a1c5758da3a6f2ff9 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Wed, 7 Apr 2021 12:08:10 -0500 Subject: [PATCH 49/82] Okay, this clearly isn't working. WTF did I do wrong? --- src/cascadia/TerminalApp/TerminalPage.cpp | 13 +++-- src/cascadia/TerminalApp/TerminalTab.cpp | 62 +++++++++++++---------- src/cascadia/TerminalApp/TerminalTab.h | 3 ++ 3 files changed, 48 insertions(+), 30 deletions(-) diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp index 6e176bf4136..54be253c4d9 100644 --- a/src/cascadia/TerminalApp/TerminalPage.cpp +++ b/src/cascadia/TerminalApp/TerminalPage.cpp @@ -993,9 +993,6 @@ namespace winrt::TerminalApp::implementation term.OpenHyperlink({ this, &TerminalPage::_OpenHyperlinkHandler }); - // Add an event handler for when the terminal wants to set a progress indicator on the taskbar - term.SetTaskbarProgress({ this, &TerminalPage::_SetTaskbarProgressHandler }); - term.HidePointerCursor({ get_weak(), &TerminalPage::_HidePointerCursorHandler }); term.RestorePointerCursor({ get_weak(), &TerminalPage::_RestorePointerCursorHandler }); @@ -1050,6 +1047,16 @@ namespace winrt::TerminalApp::implementation } }); + hostingTab.TaskbarProgressChanged([weakThis](const auto& s, const auto& args) { + if (auto page{ weakThis.get() }) + { + page->_SetTaskbarProgressHandler(s, args); + } + }); + + // Add an event handler for when the terminal wants to set a progress indicator on the taskbar + term.SetTaskbarProgress({ this, &TerminalPage::_SetTaskbarProgressHandler }); + // TODO GH#3327: Once we support colorizing the NewTab button based on // the color of the tab, we'll want to make sure to call // _ClearNewTabButtonColor here, to reset it to the default (for the diff --git a/src/cascadia/TerminalApp/TerminalTab.cpp b/src/cascadia/TerminalApp/TerminalTab.cpp index 6b6e0848bad..be521e61a12 100644 --- a/src/cascadia/TerminalApp/TerminalTab.cpp +++ b/src/cascadia/TerminalApp/TerminalTab.cpp @@ -178,6 +178,8 @@ namespace winrt::TerminalApp::implementation // Seems like there's a better way... // // lastFocusedControl.TaskbarProgressChanged(); + _UpdateProgressState(); + _TaskbarProgressChangedHandlers(lastFocusedControl, nullptr); } // When we gain focus, remove the bell indicator if it is active if (_tabStatus.BellIndicator()) @@ -590,33 +592,7 @@ namespace winrt::TerminalApp::implementation // Check if Tab's lifetime has expired if (auto tab{ weakThis.get() }) { - // The progress of the control changed, but not necessarily the progress of the tab. - // Set the tab's progress ring to the active pane's progress - if (tab->GetActiveTerminalControl().TaskbarState() > 0) - { - if (tab->GetActiveTerminalControl().TaskbarState() == 3) - { - // 3 is the indeterminate state, set the progress ring as such - tab->_tabStatus.IsProgressRingIndeterminate(true); - } - else - { - // any non-indeterminate state has a value, set the progress ring as such - tab->_tabStatus.IsProgressRingIndeterminate(false); - - const auto progressValue = gsl::narrow(tab->GetActiveTerminalControl().TaskbarProgress()); - tab->_tabStatus.ProgressValue(progressValue); - } - // Hide the tab icon (the progress ring is placed over it) - tab->HideIcon(true); - tab->_tabStatus.IsProgressRingActive(true); - } - else - { - // Show the tab icon - tab->HideIcon(false); - tab->_tabStatus.IsProgressRingActive(false); - } + tab->_UpdateProgressState(); } }); @@ -641,6 +617,37 @@ namespace winrt::TerminalApp::implementation }); } + void TerminalTab::_UpdateProgressState() + { + // The progress of the control changed, but not necessarily the progress of the tab. + // Set the tab's progress ring to the active pane's progress + if (GetActiveTerminalControl().TaskbarState() > 0) + { + if (GetActiveTerminalControl().TaskbarState() == 3) + { + // 3 is the indeterminate state, set the progress ring as such + _tabStatus.IsProgressRingIndeterminate(true); + } + else + { + // any non-indeterminate state has a value, set the progress ring as such + _tabStatus.IsProgressRingIndeterminate(false); + + const auto progressValue = gsl::narrow(GetActiveTerminalControl().TaskbarProgress()); + _tabStatus.ProgressValue(progressValue); + } + // Hide the tab icon (the progress ring is placed over it) + HideIcon(true); + _tabStatus.IsProgressRingActive(true); + } + else + { + // Show the tab icon + HideIcon(false); + _tabStatus.IsProgressRingActive(false); + } + } + // Method Description: // - Mark the given pane as the active pane in this tab. All other panes // will be marked as inactive. We'll also update our own UI state to @@ -658,6 +665,7 @@ namespace winrt::TerminalApp::implementation // Update our own title text to match the newly-active pane. UpdateTitle(); + _UpdateProgressState(); // We need to move the pane to the top of our mru list // If its already somewhere in the list, remove it first diff --git a/src/cascadia/TerminalApp/TerminalTab.h b/src/cascadia/TerminalApp/TerminalTab.h index e349bf36ad8..ddade2a84d4 100644 --- a/src/cascadia/TerminalApp/TerminalTab.h +++ b/src/cascadia/TerminalApp/TerminalTab.h @@ -91,6 +91,7 @@ namespace winrt::TerminalApp::implementation DECLARE_EVENT(TabRaiseVisualBell, _TabRaiseVisualBellHandlers, winrt::delegate<>); DECLARE_EVENT(DuplicateRequested, _DuplicateRequestedHandlers, winrt::delegate<>); FORWARDED_TYPED_EVENT(TabRenamerDeactivated, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable, (&_headerControl), RenameEnded); + TYPED_EVENT(TaskbarProgressChanged, IInspectable, IInspectable); private: std::shared_ptr _rootPane{ nullptr }; @@ -144,6 +145,8 @@ namespace winrt::TerminalApp::implementation void _RecalculateAndApplyReadOnly(); + void _UpdateProgressState(); + void _DuplicateTab(); friend class ::TerminalAppLocalTests::TabTests; From f057930958cc066900e22c2a6a0a8c09d86c192f Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Wed, 7 Apr 2021 12:08:19 -0500 Subject: [PATCH 50/82] Revert "Okay, this clearly isn't working. WTF did I do wrong?" This reverts commit 198576a7b59f1563ed3a044a1c5758da3a6f2ff9. --- src/cascadia/TerminalApp/TerminalPage.cpp | 13 ++--- src/cascadia/TerminalApp/TerminalTab.cpp | 62 ++++++++++------------- src/cascadia/TerminalApp/TerminalTab.h | 3 -- 3 files changed, 30 insertions(+), 48 deletions(-) diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp index 54be253c4d9..6e176bf4136 100644 --- a/src/cascadia/TerminalApp/TerminalPage.cpp +++ b/src/cascadia/TerminalApp/TerminalPage.cpp @@ -993,6 +993,9 @@ namespace winrt::TerminalApp::implementation term.OpenHyperlink({ this, &TerminalPage::_OpenHyperlinkHandler }); + // Add an event handler for when the terminal wants to set a progress indicator on the taskbar + term.SetTaskbarProgress({ this, &TerminalPage::_SetTaskbarProgressHandler }); + term.HidePointerCursor({ get_weak(), &TerminalPage::_HidePointerCursorHandler }); term.RestorePointerCursor({ get_weak(), &TerminalPage::_RestorePointerCursorHandler }); @@ -1047,16 +1050,6 @@ namespace winrt::TerminalApp::implementation } }); - hostingTab.TaskbarProgressChanged([weakThis](const auto& s, const auto& args) { - if (auto page{ weakThis.get() }) - { - page->_SetTaskbarProgressHandler(s, args); - } - }); - - // Add an event handler for when the terminal wants to set a progress indicator on the taskbar - term.SetTaskbarProgress({ this, &TerminalPage::_SetTaskbarProgressHandler }); - // TODO GH#3327: Once we support colorizing the NewTab button based on // the color of the tab, we'll want to make sure to call // _ClearNewTabButtonColor here, to reset it to the default (for the diff --git a/src/cascadia/TerminalApp/TerminalTab.cpp b/src/cascadia/TerminalApp/TerminalTab.cpp index be521e61a12..6b6e0848bad 100644 --- a/src/cascadia/TerminalApp/TerminalTab.cpp +++ b/src/cascadia/TerminalApp/TerminalTab.cpp @@ -178,8 +178,6 @@ namespace winrt::TerminalApp::implementation // Seems like there's a better way... // // lastFocusedControl.TaskbarProgressChanged(); - _UpdateProgressState(); - _TaskbarProgressChangedHandlers(lastFocusedControl, nullptr); } // When we gain focus, remove the bell indicator if it is active if (_tabStatus.BellIndicator()) @@ -592,7 +590,33 @@ namespace winrt::TerminalApp::implementation // Check if Tab's lifetime has expired if (auto tab{ weakThis.get() }) { - tab->_UpdateProgressState(); + // The progress of the control changed, but not necessarily the progress of the tab. + // Set the tab's progress ring to the active pane's progress + if (tab->GetActiveTerminalControl().TaskbarState() > 0) + { + if (tab->GetActiveTerminalControl().TaskbarState() == 3) + { + // 3 is the indeterminate state, set the progress ring as such + tab->_tabStatus.IsProgressRingIndeterminate(true); + } + else + { + // any non-indeterminate state has a value, set the progress ring as such + tab->_tabStatus.IsProgressRingIndeterminate(false); + + const auto progressValue = gsl::narrow(tab->GetActiveTerminalControl().TaskbarProgress()); + tab->_tabStatus.ProgressValue(progressValue); + } + // Hide the tab icon (the progress ring is placed over it) + tab->HideIcon(true); + tab->_tabStatus.IsProgressRingActive(true); + } + else + { + // Show the tab icon + tab->HideIcon(false); + tab->_tabStatus.IsProgressRingActive(false); + } } }); @@ -617,37 +641,6 @@ namespace winrt::TerminalApp::implementation }); } - void TerminalTab::_UpdateProgressState() - { - // The progress of the control changed, but not necessarily the progress of the tab. - // Set the tab's progress ring to the active pane's progress - if (GetActiveTerminalControl().TaskbarState() > 0) - { - if (GetActiveTerminalControl().TaskbarState() == 3) - { - // 3 is the indeterminate state, set the progress ring as such - _tabStatus.IsProgressRingIndeterminate(true); - } - else - { - // any non-indeterminate state has a value, set the progress ring as such - _tabStatus.IsProgressRingIndeterminate(false); - - const auto progressValue = gsl::narrow(GetActiveTerminalControl().TaskbarProgress()); - _tabStatus.ProgressValue(progressValue); - } - // Hide the tab icon (the progress ring is placed over it) - HideIcon(true); - _tabStatus.IsProgressRingActive(true); - } - else - { - // Show the tab icon - HideIcon(false); - _tabStatus.IsProgressRingActive(false); - } - } - // Method Description: // - Mark the given pane as the active pane in this tab. All other panes // will be marked as inactive. We'll also update our own UI state to @@ -665,7 +658,6 @@ namespace winrt::TerminalApp::implementation // Update our own title text to match the newly-active pane. UpdateTitle(); - _UpdateProgressState(); // We need to move the pane to the top of our mru list // If its already somewhere in the list, remove it first diff --git a/src/cascadia/TerminalApp/TerminalTab.h b/src/cascadia/TerminalApp/TerminalTab.h index ddade2a84d4..e349bf36ad8 100644 --- a/src/cascadia/TerminalApp/TerminalTab.h +++ b/src/cascadia/TerminalApp/TerminalTab.h @@ -91,7 +91,6 @@ namespace winrt::TerminalApp::implementation DECLARE_EVENT(TabRaiseVisualBell, _TabRaiseVisualBellHandlers, winrt::delegate<>); DECLARE_EVENT(DuplicateRequested, _DuplicateRequestedHandlers, winrt::delegate<>); FORWARDED_TYPED_EVENT(TabRenamerDeactivated, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable, (&_headerControl), RenameEnded); - TYPED_EVENT(TaskbarProgressChanged, IInspectable, IInspectable); private: std::shared_ptr _rootPane{ nullptr }; @@ -145,8 +144,6 @@ namespace winrt::TerminalApp::implementation void _RecalculateAndApplyReadOnly(); - void _UpdateProgressState(); - void _DuplicateTab(); friend class ::TerminalAppLocalTests::TabTests; From 15b993699791a259fb2a79ba153ac2a75113d92e Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Thu, 8 Apr 2021 10:50:53 -0500 Subject: [PATCH 51/82] These are all unnecessary, and might be slowing our builds down! --- src/cascadia/TerminalApp/Pane.h | 3 +-- src/cascadia/TerminalApp/SettingsTab.h | 2 -- src/cascadia/TerminalControl/ControlCore.h | 1 - 3 files changed, 1 insertion(+), 5 deletions(-) diff --git a/src/cascadia/TerminalApp/Pane.h b/src/cascadia/TerminalApp/Pane.h index e92c0880557..ff2a50d7300 100644 --- a/src/cascadia/TerminalApp/Pane.h +++ b/src/cascadia/TerminalApp/Pane.h @@ -19,8 +19,7 @@ // - Mike Griese (zadjii-msft) 16-May-2019 #pragma once -#include -#include + #include "../../cascadia/inc/cppwinrt_utils.h" enum class Borders : int diff --git a/src/cascadia/TerminalApp/SettingsTab.h b/src/cascadia/TerminalApp/SettingsTab.h index 1c83fc243ba..221214eff41 100644 --- a/src/cascadia/TerminalApp/SettingsTab.h +++ b/src/cascadia/TerminalApp/SettingsTab.h @@ -18,8 +18,6 @@ Author(s): #pragma once #include "TabBase.h" #include "SettingsTab.g.h" -#include -#include #include "../../cascadia/inc/cppwinrt_utils.h" namespace winrt::TerminalApp::implementation diff --git a/src/cascadia/TerminalControl/ControlCore.h b/src/cascadia/TerminalControl/ControlCore.h index 91e0a795984..136831f27c2 100644 --- a/src/cascadia/TerminalControl/ControlCore.h +++ b/src/cascadia/TerminalControl/ControlCore.h @@ -5,7 +5,6 @@ #include "EventArgs.h" #include "ControlCore.g.h" -#include #include "../../renderer/base/Renderer.hpp" #include "../../renderer/dx/DxRenderer.hpp" #include "../../renderer/uia/UiaRenderer.hpp" From 021dc57be6364341e21006cfe69dc88f35a81172 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Thu, 8 Apr 2021 10:51:57 -0500 Subject: [PATCH 52/82] This is how the original taskbar update worked, which turns out, doesn't work either --- src/cascadia/TerminalApp/TerminalTab.cpp | 2 +- src/cascadia/TerminalControl/ControlCore.cpp | 5 +++++ src/cascadia/TerminalControl/ControlCore.h | 2 ++ src/cascadia/TerminalControl/TermControl.cpp | 15 +++++++-------- src/cascadia/TerminalControl/TermControl.h | 2 +- src/cascadia/TerminalControl/TermControl.idl | 2 +- 6 files changed, 17 insertions(+), 11 deletions(-) diff --git a/src/cascadia/TerminalApp/TerminalTab.cpp b/src/cascadia/TerminalApp/TerminalTab.cpp index 6b6e0848bad..d04573488a4 100644 --- a/src/cascadia/TerminalApp/TerminalTab.cpp +++ b/src/cascadia/TerminalApp/TerminalTab.cpp @@ -177,7 +177,7 @@ namespace winrt::TerminalApp::implementation // AppHost // Seems like there's a better way... // - // lastFocusedControl.TaskbarProgressChanged(); + lastFocusedControl.TaskbarProgressChanged(); } // When we gain focus, remove the bell indicator if it is active if (_tabStatus.BellIndicator()) diff --git a/src/cascadia/TerminalControl/ControlCore.cpp b/src/cascadia/TerminalControl/ControlCore.cpp index d26c548612d..a4b2aa5dd17 100644 --- a/src/cascadia/TerminalControl/ControlCore.cpp +++ b/src/cascadia/TerminalControl/ControlCore.cpp @@ -1310,4 +1310,9 @@ namespace winrt::Microsoft::Terminal::Control::implementation auto noticeArgs = winrt::make(NoticeLevel::Info, RS_(L"TermControlReadOnly")); _RaiseNoticeHandlers(*this, std::move(noticeArgs)); } + + void ControlCore::PumpTaskbarUpdate() + { + _TaskbarProgressChangedHandlers(*this, nullptr); + } } diff --git a/src/cascadia/TerminalControl/ControlCore.h b/src/cascadia/TerminalControl/ControlCore.h index 136831f27c2..c6fa0003c60 100644 --- a/src/cascadia/TerminalControl/ControlCore.h +++ b/src/cascadia/TerminalControl/ControlCore.h @@ -62,6 +62,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation ::Microsoft::Console::Types::IUiaData* GetUiaData() const; + void PumpTaskbarUpdate(); + void Close(); #pragma region ICoreState diff --git a/src/cascadia/TerminalControl/TermControl.cpp b/src/cascadia/TerminalControl/TermControl.cpp index a757129da99..c7dd40c5b7c 100644 --- a/src/cascadia/TerminalControl/TermControl.cpp +++ b/src/cascadia/TerminalControl/TermControl.cpp @@ -2262,14 +2262,13 @@ namespace winrt::Microsoft::Terminal::Control::implementation return _core->TabColor(); } - // // Method Description: - // // - Sends an event (which will be caught by TerminalPage and forwarded to AppHost after) - // // to set the progress indicator on the taskbar - // winrt::fire_and_forget TermControl::TaskbarProgressChanged() - // { - // co_await resume_foreground(Dispatcher(), CoreDispatcherPriority::High); - // _setTaskbarProgressHandlers(*this, nullptr); - // } + // Method Description: + // - Sends an event (which will be caught by TerminalPage and forwarded to AppHost after) + // to set the progress indicator on the taskbar + void TermControl::TaskbarProgressChanged() + { + _core->PumpTaskbarUpdate(); + } // Method Description: // - Gets the internal taskbar state value diff --git a/src/cascadia/TerminalControl/TermControl.h b/src/cascadia/TerminalControl/TermControl.h index e2c9992d636..6cffbd48e5a 100644 --- a/src/cascadia/TerminalControl/TermControl.h +++ b/src/cascadia/TerminalControl/TermControl.h @@ -86,7 +86,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation Windows::Foundation::IReference TabColor() noexcept; - // winrt::fire_and_forget TaskbarProgressChanged(); + void TaskbarProgressChanged(); const size_t TaskbarState() const noexcept; const size_t TaskbarProgress() const noexcept; diff --git a/src/cascadia/TerminalControl/TermControl.idl b/src/cascadia/TerminalControl/TermControl.idl index 243f07c38fb..c15ab65c455 100644 --- a/src/cascadia/TerminalControl/TermControl.idl +++ b/src/cascadia/TerminalControl/TermControl.idl @@ -62,7 +62,7 @@ namespace Microsoft.Terminal.Control void ToggleShaderEffects(); void SendInput(String input); - // void TaskbarProgressChanged(); + void TaskbarProgressChanged(); Boolean ReadOnly { get; }; void ToggleReadOnly(); From be8058349ea7d61c9072c6a44c146ffbf1123fa1 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Thu, 8 Apr 2021 10:52:18 -0500 Subject: [PATCH 53/82] Revert "This is how the original taskbar update worked, which turns out, doesn't work either" This reverts commit 021dc57be6364341e21006cfe69dc88f35a81172. --- src/cascadia/TerminalApp/TerminalTab.cpp | 2 +- src/cascadia/TerminalControl/ControlCore.cpp | 5 ----- src/cascadia/TerminalControl/ControlCore.h | 2 -- src/cascadia/TerminalControl/TermControl.cpp | 15 ++++++++------- src/cascadia/TerminalControl/TermControl.h | 2 +- src/cascadia/TerminalControl/TermControl.idl | 2 +- 6 files changed, 11 insertions(+), 17 deletions(-) diff --git a/src/cascadia/TerminalApp/TerminalTab.cpp b/src/cascadia/TerminalApp/TerminalTab.cpp index d04573488a4..6b6e0848bad 100644 --- a/src/cascadia/TerminalApp/TerminalTab.cpp +++ b/src/cascadia/TerminalApp/TerminalTab.cpp @@ -177,7 +177,7 @@ namespace winrt::TerminalApp::implementation // AppHost // Seems like there's a better way... // - lastFocusedControl.TaskbarProgressChanged(); + // lastFocusedControl.TaskbarProgressChanged(); } // When we gain focus, remove the bell indicator if it is active if (_tabStatus.BellIndicator()) diff --git a/src/cascadia/TerminalControl/ControlCore.cpp b/src/cascadia/TerminalControl/ControlCore.cpp index a4b2aa5dd17..d26c548612d 100644 --- a/src/cascadia/TerminalControl/ControlCore.cpp +++ b/src/cascadia/TerminalControl/ControlCore.cpp @@ -1310,9 +1310,4 @@ namespace winrt::Microsoft::Terminal::Control::implementation auto noticeArgs = winrt::make(NoticeLevel::Info, RS_(L"TermControlReadOnly")); _RaiseNoticeHandlers(*this, std::move(noticeArgs)); } - - void ControlCore::PumpTaskbarUpdate() - { - _TaskbarProgressChangedHandlers(*this, nullptr); - } } diff --git a/src/cascadia/TerminalControl/ControlCore.h b/src/cascadia/TerminalControl/ControlCore.h index c6fa0003c60..136831f27c2 100644 --- a/src/cascadia/TerminalControl/ControlCore.h +++ b/src/cascadia/TerminalControl/ControlCore.h @@ -62,8 +62,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation ::Microsoft::Console::Types::IUiaData* GetUiaData() const; - void PumpTaskbarUpdate(); - void Close(); #pragma region ICoreState diff --git a/src/cascadia/TerminalControl/TermControl.cpp b/src/cascadia/TerminalControl/TermControl.cpp index c7dd40c5b7c..a757129da99 100644 --- a/src/cascadia/TerminalControl/TermControl.cpp +++ b/src/cascadia/TerminalControl/TermControl.cpp @@ -2262,13 +2262,14 @@ namespace winrt::Microsoft::Terminal::Control::implementation return _core->TabColor(); } - // Method Description: - // - Sends an event (which will be caught by TerminalPage and forwarded to AppHost after) - // to set the progress indicator on the taskbar - void TermControl::TaskbarProgressChanged() - { - _core->PumpTaskbarUpdate(); - } + // // Method Description: + // // - Sends an event (which will be caught by TerminalPage and forwarded to AppHost after) + // // to set the progress indicator on the taskbar + // winrt::fire_and_forget TermControl::TaskbarProgressChanged() + // { + // co_await resume_foreground(Dispatcher(), CoreDispatcherPriority::High); + // _setTaskbarProgressHandlers(*this, nullptr); + // } // Method Description: // - Gets the internal taskbar state value diff --git a/src/cascadia/TerminalControl/TermControl.h b/src/cascadia/TerminalControl/TermControl.h index 6cffbd48e5a..e2c9992d636 100644 --- a/src/cascadia/TerminalControl/TermControl.h +++ b/src/cascadia/TerminalControl/TermControl.h @@ -86,7 +86,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation Windows::Foundation::IReference TabColor() noexcept; - void TaskbarProgressChanged(); + // winrt::fire_and_forget TaskbarProgressChanged(); const size_t TaskbarState() const noexcept; const size_t TaskbarProgress() const noexcept; diff --git a/src/cascadia/TerminalControl/TermControl.idl b/src/cascadia/TerminalControl/TermControl.idl index c15ab65c455..243f07c38fb 100644 --- a/src/cascadia/TerminalControl/TermControl.idl +++ b/src/cascadia/TerminalControl/TermControl.idl @@ -62,7 +62,7 @@ namespace Microsoft.Terminal.Control void ToggleShaderEffects(); void SendInput(String input); - void TaskbarProgressChanged(); + // void TaskbarProgressChanged(); Boolean ReadOnly { get; }; void ToggleReadOnly(); From 4189bb0d5264a222ee7108cde9311fddd3d642fd Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Wed, 7 Apr 2021 12:08:10 -0500 Subject: [PATCH 54/82] Okay, this clearly isn't working. WTF did I do wrong? (cherry picked from commit 198576a7b59f1563ed3a044a1c5758da3a6f2ff9) --- src/cascadia/TerminalApp/TerminalPage.cpp | 13 +++-- src/cascadia/TerminalApp/TerminalTab.cpp | 62 +++++++++++++---------- src/cascadia/TerminalApp/TerminalTab.h | 3 ++ 3 files changed, 48 insertions(+), 30 deletions(-) diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp index 6e176bf4136..54be253c4d9 100644 --- a/src/cascadia/TerminalApp/TerminalPage.cpp +++ b/src/cascadia/TerminalApp/TerminalPage.cpp @@ -993,9 +993,6 @@ namespace winrt::TerminalApp::implementation term.OpenHyperlink({ this, &TerminalPage::_OpenHyperlinkHandler }); - // Add an event handler for when the terminal wants to set a progress indicator on the taskbar - term.SetTaskbarProgress({ this, &TerminalPage::_SetTaskbarProgressHandler }); - term.HidePointerCursor({ get_weak(), &TerminalPage::_HidePointerCursorHandler }); term.RestorePointerCursor({ get_weak(), &TerminalPage::_RestorePointerCursorHandler }); @@ -1050,6 +1047,16 @@ namespace winrt::TerminalApp::implementation } }); + hostingTab.TaskbarProgressChanged([weakThis](const auto& s, const auto& args) { + if (auto page{ weakThis.get() }) + { + page->_SetTaskbarProgressHandler(s, args); + } + }); + + // Add an event handler for when the terminal wants to set a progress indicator on the taskbar + term.SetTaskbarProgress({ this, &TerminalPage::_SetTaskbarProgressHandler }); + // TODO GH#3327: Once we support colorizing the NewTab button based on // the color of the tab, we'll want to make sure to call // _ClearNewTabButtonColor here, to reset it to the default (for the diff --git a/src/cascadia/TerminalApp/TerminalTab.cpp b/src/cascadia/TerminalApp/TerminalTab.cpp index 6b6e0848bad..be521e61a12 100644 --- a/src/cascadia/TerminalApp/TerminalTab.cpp +++ b/src/cascadia/TerminalApp/TerminalTab.cpp @@ -178,6 +178,8 @@ namespace winrt::TerminalApp::implementation // Seems like there's a better way... // // lastFocusedControl.TaskbarProgressChanged(); + _UpdateProgressState(); + _TaskbarProgressChangedHandlers(lastFocusedControl, nullptr); } // When we gain focus, remove the bell indicator if it is active if (_tabStatus.BellIndicator()) @@ -590,33 +592,7 @@ namespace winrt::TerminalApp::implementation // Check if Tab's lifetime has expired if (auto tab{ weakThis.get() }) { - // The progress of the control changed, but not necessarily the progress of the tab. - // Set the tab's progress ring to the active pane's progress - if (tab->GetActiveTerminalControl().TaskbarState() > 0) - { - if (tab->GetActiveTerminalControl().TaskbarState() == 3) - { - // 3 is the indeterminate state, set the progress ring as such - tab->_tabStatus.IsProgressRingIndeterminate(true); - } - else - { - // any non-indeterminate state has a value, set the progress ring as such - tab->_tabStatus.IsProgressRingIndeterminate(false); - - const auto progressValue = gsl::narrow(tab->GetActiveTerminalControl().TaskbarProgress()); - tab->_tabStatus.ProgressValue(progressValue); - } - // Hide the tab icon (the progress ring is placed over it) - tab->HideIcon(true); - tab->_tabStatus.IsProgressRingActive(true); - } - else - { - // Show the tab icon - tab->HideIcon(false); - tab->_tabStatus.IsProgressRingActive(false); - } + tab->_UpdateProgressState(); } }); @@ -641,6 +617,37 @@ namespace winrt::TerminalApp::implementation }); } + void TerminalTab::_UpdateProgressState() + { + // The progress of the control changed, but not necessarily the progress of the tab. + // Set the tab's progress ring to the active pane's progress + if (GetActiveTerminalControl().TaskbarState() > 0) + { + if (GetActiveTerminalControl().TaskbarState() == 3) + { + // 3 is the indeterminate state, set the progress ring as such + _tabStatus.IsProgressRingIndeterminate(true); + } + else + { + // any non-indeterminate state has a value, set the progress ring as such + _tabStatus.IsProgressRingIndeterminate(false); + + const auto progressValue = gsl::narrow(GetActiveTerminalControl().TaskbarProgress()); + _tabStatus.ProgressValue(progressValue); + } + // Hide the tab icon (the progress ring is placed over it) + HideIcon(true); + _tabStatus.IsProgressRingActive(true); + } + else + { + // Show the tab icon + HideIcon(false); + _tabStatus.IsProgressRingActive(false); + } + } + // Method Description: // - Mark the given pane as the active pane in this tab. All other panes // will be marked as inactive. We'll also update our own UI state to @@ -658,6 +665,7 @@ namespace winrt::TerminalApp::implementation // Update our own title text to match the newly-active pane. UpdateTitle(); + _UpdateProgressState(); // We need to move the pane to the top of our mru list // If its already somewhere in the list, remove it first diff --git a/src/cascadia/TerminalApp/TerminalTab.h b/src/cascadia/TerminalApp/TerminalTab.h index e349bf36ad8..ddade2a84d4 100644 --- a/src/cascadia/TerminalApp/TerminalTab.h +++ b/src/cascadia/TerminalApp/TerminalTab.h @@ -91,6 +91,7 @@ namespace winrt::TerminalApp::implementation DECLARE_EVENT(TabRaiseVisualBell, _TabRaiseVisualBellHandlers, winrt::delegate<>); DECLARE_EVENT(DuplicateRequested, _DuplicateRequestedHandlers, winrt::delegate<>); FORWARDED_TYPED_EVENT(TabRenamerDeactivated, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable, (&_headerControl), RenameEnded); + TYPED_EVENT(TaskbarProgressChanged, IInspectable, IInspectable); private: std::shared_ptr _rootPane{ nullptr }; @@ -144,6 +145,8 @@ namespace winrt::TerminalApp::implementation void _RecalculateAndApplyReadOnly(); + void _UpdateProgressState(); + void _DuplicateTab(); friend class ::TerminalAppLocalTests::TabTests; From d8beada5de7b4cc98dc890528a84dc338f940096 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Thu, 8 Apr 2021 12:08:45 -0500 Subject: [PATCH 55/82] This fixes #9743, but I think I'm still doing something off the UI thread --- src/cascadia/TerminalApp/TabManagement.cpp | 3 +++ src/cascadia/TerminalApp/TerminalTab.cpp | 8 +++++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/cascadia/TerminalApp/TabManagement.cpp b/src/cascadia/TerminalApp/TabManagement.cpp index ee2d49aa468..07e6a7712b2 100644 --- a/src/cascadia/TerminalApp/TabManagement.cpp +++ b/src/cascadia/TerminalApp/TabManagement.cpp @@ -153,6 +153,9 @@ namespace winrt::TerminalApp::implementation { // Possibly update the icon of the tab. page->_UpdateTabIcon(*tab); + + // Update the taskbar progress + page->_SetTaskbarProgressHandlers(*page, nullptr); } }); diff --git a/src/cascadia/TerminalApp/TerminalTab.cpp b/src/cascadia/TerminalApp/TerminalTab.cpp index be521e61a12..b94722dbb87 100644 --- a/src/cascadia/TerminalApp/TerminalTab.cpp +++ b/src/cascadia/TerminalApp/TerminalTab.cpp @@ -619,11 +619,13 @@ namespace winrt::TerminalApp::implementation void TerminalTab::_UpdateProgressState() { + const auto activeControl = GetActiveTerminalControl(); + const auto taskbarState = activeControl.TaskbarState(); // The progress of the control changed, but not necessarily the progress of the tab. // Set the tab's progress ring to the active pane's progress - if (GetActiveTerminalControl().TaskbarState() > 0) + if (taskbarState > 0) { - if (GetActiveTerminalControl().TaskbarState() == 3) + if (taskbarState == 3) { // 3 is the indeterminate state, set the progress ring as such _tabStatus.IsProgressRingIndeterminate(true); @@ -633,7 +635,7 @@ namespace winrt::TerminalApp::implementation // any non-indeterminate state has a value, set the progress ring as such _tabStatus.IsProgressRingIndeterminate(false); - const auto progressValue = gsl::narrow(GetActiveTerminalControl().TaskbarProgress()); + const auto progressValue = gsl::narrow(activeControl.TaskbarProgress()); _tabStatus.ProgressValue(progressValue); } // Hide the tab icon (the progress ring is placed over it) From a34cc1ad55f30880b40820cd553ede0ed087ec0f Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Thu, 8 Apr 2021 12:21:39 -0500 Subject: [PATCH 56/82] I did forget the co_await after all. --- src/cascadia/TerminalApp/TabManagement.cpp | 4 +++- src/cascadia/TerminalApp/TerminalTab.cpp | 17 ++++++++++++++++- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/src/cascadia/TerminalApp/TabManagement.cpp b/src/cascadia/TerminalApp/TabManagement.cpp index 07e6a7712b2..6712d7d02fd 100644 --- a/src/cascadia/TerminalApp/TabManagement.cpp +++ b/src/cascadia/TerminalApp/TabManagement.cpp @@ -154,7 +154,9 @@ namespace winrt::TerminalApp::implementation // Possibly update the icon of the tab. page->_UpdateTabIcon(*tab); - // Update the taskbar progress + // Update the taskbar progress as well. We'll raise our own + // SetTaskbarProgress event here, to get tell the hosting + // application to re-query this value from us. page->_SetTaskbarProgressHandlers(*page, nullptr); } }); diff --git a/src/cascadia/TerminalApp/TerminalTab.cpp b/src/cascadia/TerminalApp/TerminalTab.cpp index b94722dbb87..dda1f2b09db 100644 --- a/src/cascadia/TerminalApp/TerminalTab.cpp +++ b/src/cascadia/TerminalApp/TerminalTab.cpp @@ -553,6 +553,7 @@ namespace winrt::TerminalApp::implementation void TerminalTab::_AttachEventHandlersToControl(const TermControl& control) { auto weakThis{ get_weak() }; + auto dispatcher = TabViewItem().Dispatcher(); control.TitleChanged([weakThis](auto&&, auto&&) { // Check if Tab's lifetime has expired @@ -588,7 +589,8 @@ namespace winrt::TerminalApp::implementation } }); - control.SetTaskbarProgress([weakThis](auto&&, auto&&) { + control.SetTaskbarProgress([dispatcher, weakThis](auto&&, auto &&) -> winrt::fire_and_forget { + co_await winrt::resume_foreground(dispatcher); // Check if Tab's lifetime has expired if (auto tab{ weakThis.get() }) { @@ -617,6 +619,19 @@ namespace winrt::TerminalApp::implementation }); } + // Method Description: + // - This should be called on the UI thread. If you don't, then it might + // silently do nothing. + // - Update our TabStatus to reflect the progress state of the currently + // active pane. + // - This is called every time _any_ control's progress state changes, + // regardless of if that control is the active one or not. This is simpler + // then re-attaching this handler to the active control each time it + // changes. + // Arguments: + // - + // Return Value: + // - void TerminalTab::_UpdateProgressState() { const auto activeControl = GetActiveTerminalControl(); From fa0897ab6071a95036dd2d9bf4f47b8cbc38de2f Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Thu, 8 Apr 2021 12:45:41 -0500 Subject: [PATCH 57/82] Get rid of some TODOs --- src/cascadia/TerminalApp/TerminalTab.cpp | 14 +++----------- src/cascadia/TerminalControl/ControlCore.cpp | 13 ++++++------- src/cascadia/TerminalControl/ControlCore.h | 2 +- .../TerminalControl/ControlInteractivity.cpp | 8 ++++---- 4 files changed, 14 insertions(+), 23 deletions(-) diff --git a/src/cascadia/TerminalApp/TerminalTab.cpp b/src/cascadia/TerminalApp/TerminalTab.cpp index dda1f2b09db..9015852161c 100644 --- a/src/cascadia/TerminalApp/TerminalTab.cpp +++ b/src/cascadia/TerminalApp/TerminalTab.cpp @@ -167,17 +167,9 @@ namespace winrt::TerminalApp::implementation if (lastFocusedControl) { lastFocusedControl.Focus(_focusState); - // !!TODO!!: This is weird: The tab calls a method on the - // control to cause the control to raise an event to the page to - // the app logic - // - // TermControl \v - // /^ TerminalPage \v - // TerminalTab /^ AppLogic \v - // AppHost - // Seems like there's a better way... - // - // lastFocusedControl.TaskbarProgressChanged(); + + // Update our own progress state, and fire an event signalling + // that our taskbar progress changed. _UpdateProgressState(); _TaskbarProgressChangedHandlers(lastFocusedControl, nullptr); } diff --git a/src/cascadia/TerminalControl/ControlCore.cpp b/src/cascadia/TerminalControl/ControlCore.cpp index d26c548612d..6e2f021e285 100644 --- a/src/cascadia/TerminalControl/ControlCore.cpp +++ b/src/cascadia/TerminalControl/ControlCore.cpp @@ -771,13 +771,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation } } - // !!TODO!! Does the Control really need to ask the Core for this? Or can it - // suffice with the swapchain value? That's unclear. - float ControlCore::RendererScale() const - { - return _renderEngine->GetScaling(); - } - void ControlCore::SetSelectionAnchor(Windows::Foundation::Point const& position) { auto lock = _terminal->LockForWriting(); @@ -902,6 +895,12 @@ namespace winrt::Microsoft::Terminal::Control::implementation return _actualFont; } + til::size ControlCore::FontSizeInDips() const + { + const til::size fontSize{ GetFont().GetSize() }; + return fontSize.scale(til::math::rounding, 1.0f / ::base::saturated_cast(_compositionScaleX)); + } + TerminalConnection::ConnectionState ControlCore::ConnectionState() const { return _connection.State(); diff --git a/src/cascadia/TerminalControl/ControlCore.h b/src/cascadia/TerminalControl/ControlCore.h index 136831f27c2..5f108a443da 100644 --- a/src/cascadia/TerminalControl/ControlCore.h +++ b/src/cascadia/TerminalControl/ControlCore.h @@ -36,12 +36,12 @@ namespace winrt::Microsoft::Terminal::Control::implementation void UpdateSettings(const IControlSettings& settings); void SizeChanged(const double width, const double height); void ScaleChanged(const double scaleX, const double scaleY); - float RendererScale() const; HANDLE GetSwapChainHandle() const; void AdjustFontSize(int fontSizeDelta); void ResetFontSize(); FontInfo GetFont() const; + til::size FontSizeInDips() const; til::color BackgroundColor() const; void SetBackgroundOpacity(const float opacity); diff --git a/src/cascadia/TerminalControl/ControlInteractivity.cpp b/src/cascadia/TerminalControl/ControlInteractivity.cpp index f65a3f659c4..26139b842ca 100644 --- a/src/cascadia/TerminalControl/ControlInteractivity.cpp +++ b/src/cascadia/TerminalControl/ControlInteractivity.cpp @@ -250,9 +250,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation auto& touchdownPoint{ *_singleClickTouchdownPos }; auto distance{ std::sqrtf(std::powf(mouseCursorPosition.X - touchdownPoint.X, 2) + std::powf(mouseCursorPosition.Y - touchdownPoint.Y, 2)) }; - const til::size fontSize{ _core->GetFont().GetSize() }; - const auto fontSizeInDips = fontSize.scale(til::math::rounding, 1.0f / _core->RendererScale()); + const auto fontSizeInDips{ _core->FontSizeInDips() }; if (distance >= (std::min(fontSizeInDips.width(), fontSizeInDips.height()) / 4.f)) { _core->SetSelectionAnchor(terminalPosition); @@ -264,6 +263,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation SetEndSelectionPoint(terminalPosition); + // TODO: Make sure this still works + // // const double cursorBelowBottomDist = cursorPosition.Y - SwapChainPanel().Margin().Top - SwapChainPanel().ActualHeight(); // const double cursorAboveTopDist = -1 * cursorPosition.Y + SwapChainPanel().Margin().Top; @@ -301,8 +302,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation // Our actualFont's size is in pixels, convert to DIPs, which the // rest of the Points here are in. - const til::size fontSize{ _core->GetFont().GetSize() }; - const auto fontSizeInDips = fontSize.scale(til::math::rounding, 1.0f / _core->RendererScale()); + const auto fontSizeInDips{ _core->FontSizeInDips() }; // Get the difference between the point we've dragged to and the start of the touch. const float dy = newTouchPoint.Y - anchor.Y; From 643f1b73eb133edaa48ae8df5f2e99a8b2445ee3 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Thu, 8 Apr 2021 14:15:44 -0500 Subject: [PATCH 58/82] Oh my, the last of the TODO!s --- src/cascadia/TerminalControl/ControlCore.cpp | 41 +++++++++++++++---- src/cascadia/TerminalControl/ControlCore.h | 7 ++-- .../TerminalControl/ControlInteractivity.cpp | 2 - src/cascadia/TerminalControl/TermControl.cpp | 1 - src/cascadia/TerminalCore/Terminal.cpp | 1 - src/cascadia/TerminalCore/Terminal.hpp | 1 + src/cascadia/TerminalCore/TerminalApi.cpp | 5 +++ 7 files changed, 44 insertions(+), 14 deletions(-) diff --git a/src/cascadia/TerminalControl/ControlCore.cpp b/src/cascadia/TerminalControl/ControlCore.cpp index 6e2f021e285..d85774a72ad 100644 --- a/src/cascadia/TerminalControl/ControlCore.cpp +++ b/src/cascadia/TerminalControl/ControlCore.cpp @@ -490,6 +490,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation winrt::hstring ControlCore::GetHyperlink(const til::point pos) const { + // Lock for the duration of our reads. + auto lock = _terminal->LockForReading(); return winrt::hstring{ _terminal->GetHyperlinkAtPosition(pos) }; } @@ -805,7 +807,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation // save location (for rendering) + render _terminal->SetSelectionEnd(terminalPosition); _renderer->TriggerSelection(); - // _selectionNeedsToBeCopied = true; // !TODO! why is this commented out? } // Called when the Terminal wants to set something to the clipboard, i.e. @@ -833,9 +834,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation return false; } - // // Mark the current selection as copied - // _selectionNeedsToBeCopied = false; - // extract text from buffer const auto bufferData = _terminal->RetrieveSelectedTextFromBuffer(singleLine); @@ -927,7 +925,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation til::color ControlCore::BackgroundColor() const { - return _backgroundColor; + return _terminal->GetDefaultBackground(); } // Method Description: @@ -979,19 +977,48 @@ namespace winrt::Microsoft::Terminal::Control::implementation _WarningBellHandlers(*this, nullptr); } + // Method Description: + // - Called for the Terminal's TitleChanged callback. This will re-raise + // a new winrt TypedEvent that can be listened to. + // - The listeners to this event will re-query the control for the current + // value of Title(). + // Arguments: + // - wstr: the new title of this terminal. + // Return Value: + // - void ControlCore::_terminalTitleChanged(const std::wstring_view& wstr) { auto titleArgs = winrt::make_self(winrt::hstring{ wstr }); _TitleChangedHandlers(*this, *titleArgs); } + + // Method Description: + // - Called for the Terminal's TabColorChanged callback. This will re-raise + // a new winrt TypedEvent that can be listened to. + // - The listeners to this event will re-query the control for the current + // value of TabColor(). + // Arguments: + // - + // Return Value: + // - void ControlCore::_terminalTabColorChanged(const std::optional /*color*/) { + // Raise a TabColorChanged event _TabColorChangedHandlers(*this, nullptr); } - void ControlCore::_terminalBackgroundColorChanged(const COLORREF color) + // Method Description: + // - Called for the Terminal's BackgroundColorChanged callback. This will + // re-raise a new winrt TypedEvent that can be listened to. + // - The listeners to this event will re-query the control for the current + // value of BackgroundColor(). + // Arguments: + // - + // Return Value: + // - + void ControlCore::_terminalBackgroundColorChanged(const COLORREF /*color*/) { - _backgroundColor = color; + // Raise a BackgroundColorChanged event _BackgroundColorChangedHandlers(*this, nullptr); } diff --git a/src/cascadia/TerminalControl/ControlCore.h b/src/cascadia/TerminalControl/ControlCore.h index 5f108a443da..404c61473ec 100644 --- a/src/cascadia/TerminalControl/ControlCore.h +++ b/src/cascadia/TerminalControl/ControlCore.h @@ -78,7 +78,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation int BufferHeight() const; #pragma endregion -#pragma region ITerminalInputButNotReally +#pragma region ITerminalInput bool TrySendKeyEvent(const WORD vkey, const WORD scanCode, const ::Microsoft::Terminal::Core::ControlKeyStates modifiers, @@ -160,7 +160,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation std::unique_ptr<::Microsoft::Console::Render::Renderer> _renderer{ nullptr }; std::unique_ptr<::Microsoft::Console::Render::DxEngine> _renderEngine{ nullptr }; - IControlSettings _settings{ nullptr }; // ? Might be able to get away with only retrieving pieces + IControlSettings _settings{ nullptr }; FontInfoDesired _desiredFont; FontInfo _actualFont; @@ -176,11 +176,12 @@ namespace winrt::Microsoft::Terminal::Control::implementation std::optional::interval> _lastHoveredInterval{ std::nullopt }; + // These members represent the size of the surface that we should be + // rendering to. double _panelWidth{ 0 }; double _panelHeight{ 0 }; double _compositionScaleX{ 0 }; double _compositionScaleY{ 0 }; - til::color _backgroundColor; // !TODO! This is _in_ Terminal already! winrt::fire_and_forget _asyncCloseConnection(); diff --git a/src/cascadia/TerminalControl/ControlInteractivity.cpp b/src/cascadia/TerminalControl/ControlInteractivity.cpp index 26139b842ca..7be9e5e9fea 100644 --- a/src/cascadia/TerminalControl/ControlInteractivity.cpp +++ b/src/cascadia/TerminalControl/ControlInteractivity.cpp @@ -164,8 +164,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation const auto ctrlEnabled = modifiers.IsCtrlPressed(); // GH#9396: we prioritize hyper-link over VT mouse events - // - // !TODO! Before we'd lock the terminal before getting the hyperlink. Do we still need to? auto hyperlink = _core->GetHyperlink(terminalPosition); if (buttonState.isLeftButtonDown && ctrlEnabled && !hyperlink.empty()) diff --git a/src/cascadia/TerminalControl/TermControl.cpp b/src/cascadia/TerminalControl/TermControl.cpp index a757129da99..c87c4dd3040 100644 --- a/src/cascadia/TerminalControl/TermControl.cpp +++ b/src/cascadia/TerminalControl/TermControl.cpp @@ -201,7 +201,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation const bool goForward, const bool caseSensitive) { - // !!TODO!! This is bound in XAML, and that seems a little silly now _core->Search(text, goForward, caseSensitive); } diff --git a/src/cascadia/TerminalCore/Terminal.cpp b/src/cascadia/TerminalCore/Terminal.cpp index 6b634fa9fdf..ae64d38a00c 100644 --- a/src/cascadia/TerminalCore/Terminal.cpp +++ b/src/cascadia/TerminalCore/Terminal.cpp @@ -1196,7 +1196,6 @@ void Terminal::UpdatePatterns() noexcept // visible region is changing void Terminal::ClearPatternTree() noexcept { - // auto lock = LockForWriting(); auto oldTree = _patternIntervalTree; _patternIntervalTree = {}; _InvalidatePatternTree(oldTree); diff --git a/src/cascadia/TerminalCore/Terminal.hpp b/src/cascadia/TerminalCore/Terminal.hpp index 231c35a826c..e90c19c295a 100644 --- a/src/cascadia/TerminalCore/Terminal.hpp +++ b/src/cascadia/TerminalCore/Terminal.hpp @@ -208,6 +208,7 @@ class Microsoft::Terminal::Core::Terminal final : void ClearPatternTree() noexcept; const std::optional GetTabColor() const noexcept; + til::color GetDefaultBackground() const noexcept; Microsoft::Console::Render::BlinkingState& GetBlinkingState() const noexcept; diff --git a/src/cascadia/TerminalCore/TerminalApi.cpp b/src/cascadia/TerminalCore/TerminalApi.cpp index aaf61778dbf..73fdcbd8453 100644 --- a/src/cascadia/TerminalCore/TerminalApi.cpp +++ b/src/cascadia/TerminalCore/TerminalApi.cpp @@ -472,6 +472,11 @@ try } CATCH_LOG_RETURN_FALSE() +til::color Terminal::GetDefaultBackground() const noexcept +{ + return _defaultBg; +} + bool Terminal::EnableWin32InputMode(const bool win32InputMode) noexcept { _terminalInput->ChangeWin32InputMode(win32InputMode); From 4e8dace6371bed73794bd13831d0dca493f7a8b1 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Tue, 13 Apr 2021 16:47:15 -0500 Subject: [PATCH 59/82] Fix my font loading bug --- src/cascadia/TerminalControl/ControlCore.cpp | 2 +- .../UnitTests_Control/ControlCoreTests.cpp | 28 +++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/src/cascadia/TerminalControl/ControlCore.cpp b/src/cascadia/TerminalControl/ControlCore.cpp index 16736f24048..36a6c7302f3 100644 --- a/src/cascadia/TerminalControl/ControlCore.cpp +++ b/src/cascadia/TerminalControl/ControlCore.cpp @@ -108,7 +108,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation auto pfnTerminalTaskbarProgressChanged = std::bind(&ControlCore::_terminalTaskbarProgressChanged, this); _terminal->TaskbarProgressChangedCallback(pfnTerminalTaskbarProgressChanged); - _terminal->UpdateSettings(settings); + UpdateSettings(settings); } ControlCore::~ControlCore() diff --git a/src/cascadia/UnitTests_Control/ControlCoreTests.cpp b/src/cascadia/UnitTests_Control/ControlCoreTests.cpp index 8fe38eb732b..743a9711da5 100644 --- a/src/cascadia/UnitTests_Control/ControlCoreTests.cpp +++ b/src/cascadia/UnitTests_Control/ControlCoreTests.cpp @@ -30,6 +30,8 @@ namespace ControlUnitTests TEST_METHOD(TestFreeAfterClose); + TEST_METHOD(TestFontInitializedInCtor); + TEST_CLASS_SETUP(ModuleSetup) { winrt::init_apartment(winrt::apartment_type::single_threaded); @@ -192,4 +194,30 @@ namespace ControlUnitTests VERIFY_IS_TRUE(true, L"Make sure that the test didn't crash when the core when out of scope"); } + void ControlCoreTests::TestFontInitializedInCtor() + { + // This is to catch a dumb programming mistake I made while working on + // the ore/control split. We want the font initialized in the ctor, + // before we even get to Core::Initialize. + VERIFY_IS_TRUE(false, L"Make sure the core's _font is initialized from the settings in the ctor"); + + Log::Comment(L"Create settings object"); + winrt::com_ptr settings; + settings.attach(new MockControlSettings()); + // Make sure to use something dumb like "Impact" as a font name here so + // that you don't default to Cascadia* + settings->FontFace(L"Impact"); + + Log::Comment(L"Create connection object"); + winrt::com_ptr conn; + conn.attach(new MockConnection()); + VERIFY_IS_NOT_NULL(conn); + + Log::Comment(L"Create ControlCore object"); + auto core = winrt::make_self(*settings, *conn); + VERIFY_IS_NOT_NULL(core); + + VERIFY_ARE_EQUAL(L"Impact", std::wstring{ core->_actualFont.GetFaceName() }); + } + } From f3ea7c12d11bbbdbaf7bbda6b07aa15f66f3ecb2 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Tue, 13 Apr 2021 17:01:25 -0500 Subject: [PATCH 60/82] fix some unit tests --- src/cascadia/UnitTests_Control/ControlCoreTests.cpp | 1 - src/cascadia/UnitTests_Control/MockControlSettings.h | 3 ++- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cascadia/UnitTests_Control/ControlCoreTests.cpp b/src/cascadia/UnitTests_Control/ControlCoreTests.cpp index 743a9711da5..99c4a5847f3 100644 --- a/src/cascadia/UnitTests_Control/ControlCoreTests.cpp +++ b/src/cascadia/UnitTests_Control/ControlCoreTests.cpp @@ -199,7 +199,6 @@ namespace ControlUnitTests // This is to catch a dumb programming mistake I made while working on // the ore/control split. We want the font initialized in the ctor, // before we even get to Core::Initialize. - VERIFY_IS_TRUE(false, L"Make sure the core's _font is initialized from the settings in the ctor"); Log::Comment(L"Create settings object"); winrt::com_ptr settings; diff --git a/src/cascadia/UnitTests_Control/MockControlSettings.h b/src/cascadia/UnitTests_Control/MockControlSettings.h index de9e736720f..302fbcbf9d2 100644 --- a/src/cascadia/UnitTests_Control/MockControlSettings.h +++ b/src/cascadia/UnitTests_Control/MockControlSettings.h @@ -10,7 +10,7 @@ Licensed under the MIT license. namespace ControlUnitTests { - class MockControlSettings : public winrt::implements + class MockControlSettings : public winrt::implements { public: MockControlSettings() = default; @@ -39,6 +39,7 @@ namespace ControlUnitTests WINRT_PROPERTY(winrt::Windows::Foundation::IReference, StartingTabColor, nullptr); + winrt::Microsoft::Terminal::Core::ICoreAppearance UnfocusedAppearance() { return {}; }; // ------------------------ End of Core Settings ----------------------- WINRT_PROPERTY(winrt::hstring, ProfileName); From 148807984368c4a9072bcaa9755e52fa221056b6 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Wed, 14 Apr 2021 14:41:02 -0500 Subject: [PATCH 61/82] Some cleanup for review --- src/cascadia/TerminalControl/ControlCore.h | 7 ++--- src/cascadia/TerminalControl/TermControl.cpp | 9 ------- src/cascadia/TerminalControl/TermControl.h | 27 +++++++++++-------- .../ControlInteractivityTests.cpp | 6 +---- 4 files changed, 21 insertions(+), 28 deletions(-) diff --git a/src/cascadia/TerminalControl/ControlCore.h b/src/cascadia/TerminalControl/ControlCore.h index bc110329d35..92aa58eaf7b 100644 --- a/src/cascadia/TerminalControl/ControlCore.h +++ b/src/cascadia/TerminalControl/ControlCore.h @@ -66,14 +66,15 @@ namespace winrt::Microsoft::Terminal::Control::implementation void Close(); #pragma region ICoreState - // existing - Windows::Foundation::IReference TabColor() noexcept; const size_t TaskbarState() const noexcept; const size_t TaskbarProgress() const noexcept; + hstring Title(); + Windows::Foundation::IReference TabColor() noexcept; hstring WorkingDirectory() const; + TerminalConnection::ConnectionState ConnectionState() const; - // new + int ScrollOffset(); int ViewHeight() const; int BufferHeight() const; diff --git a/src/cascadia/TerminalControl/TermControl.cpp b/src/cascadia/TerminalControl/TermControl.cpp index 32bb19e61d8..1e33ea76765 100644 --- a/src/cascadia/TerminalControl/TermControl.cpp +++ b/src/cascadia/TerminalControl/TermControl.cpp @@ -2334,15 +2334,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation return _core->TabColor(); } - // // Method Description: - // // - Sends an event (which will be caught by TerminalPage and forwarded to AppHost after) - // // to set the progress indicator on the taskbar - // winrt::fire_and_forget TermControl::TaskbarProgressChanged() - // { - // co_await resume_foreground(Dispatcher(), CoreDispatcherPriority::High); - // _setTaskbarProgressHandlers(*this, nullptr); - // } - // Method Description: // - Gets the internal taskbar state value // Return Value: diff --git a/src/cascadia/TerminalControl/TermControl.h b/src/cascadia/TerminalControl/TermControl.h index 7bbf98709d2..071f0c92b8e 100644 --- a/src/cascadia/TerminalControl/TermControl.h +++ b/src/cascadia/TerminalControl/TermControl.h @@ -30,11 +30,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation winrt::fire_and_forget UpdateSettings(); winrt::fire_and_forget UpdateAppearance(const IControlAppearance newAppearance); - hstring Title(); hstring GetProfileName() const; - hstring WorkingDirectory() const; - bool BracketedPasteEnabled() const noexcept; bool CopySelectionToClipboard(bool singleLine, const Windows::Foundation::IReference& formats); void PasteTextFromClipboard(); void Close(); @@ -42,9 +39,24 @@ namespace winrt::Microsoft::Terminal::Control::implementation Windows::Foundation::Size MinimumSize(); float SnapDimensionToGrid(const bool widthOrHeight, const float dimension); - void ScrollViewport(int viewTop); +#pragma region ICoreState + const size_t TaskbarState() const noexcept; + const size_t TaskbarProgress() const noexcept; + + hstring Title(); + Windows::Foundation::IReference TabColor() noexcept; + hstring WorkingDirectory() const; + + TerminalConnection::ConnectionState ConnectionState() const; + int ScrollOffset(); int ViewHeight() const; + int BufferHeight() const; + + bool BracketedPasteEnabled() const noexcept; +#pragma endregion + + void ScrollViewport(int viewTop); void AdjustFontSize(int fontSizeDelta); void ResetFontSize(); @@ -74,7 +86,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation ::Microsoft::Console::Types::IUiaData* GetUiaData() const; const Windows::UI::Xaml::Thickness GetPadding(); - TerminalConnection::ConnectionState ConnectionState() const; IControlSettings Settings() const; static Windows::Foundation::Size GetProposedDimensions(IControlSettings const& settings, const uint32_t dpi); @@ -86,12 +97,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation const winrt::hstring& padding, const uint32_t dpi); - Windows::Foundation::IReference TabColor() noexcept; - - // winrt::fire_and_forget TaskbarProgressChanged(); - const size_t TaskbarState() const noexcept; - const size_t TaskbarProgress() const noexcept; - bool ReadOnly() const noexcept; void ToggleReadOnly(); diff --git a/src/cascadia/UnitTests_Control/ControlInteractivityTests.cpp b/src/cascadia/UnitTests_Control/ControlInteractivityTests.cpp index d552acd70da..d65e4cdf5ec 100644 --- a/src/cascadia/UnitTests_Control/ControlInteractivityTests.cpp +++ b/src/cascadia/UnitTests_Control/ControlInteractivityTests.cpp @@ -16,10 +16,6 @@ using namespace winrt; using namespace winrt::Microsoft::Terminal; using namespace ::Microsoft::Terminal::Core; using namespace ::Microsoft::Console::VirtualTerminal; -// namespace winrt -// { -// using namespace Windows::Foundation; -// }; namespace ControlUnitTests { @@ -183,7 +179,7 @@ namespace ControlUnitTests const auto modifiers = ControlKeyStates(); expectedBufferHeight = 41; expectedTop = 20; - // DebugBreak(); + interactivity->MouseWheel(modifiers, WHEEL_DELTA, til::point{ 0, 0 }, From c14bdd6c87c021b4e011cccbc9f70139e6b3ec7e Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Mon, 19 Apr 2021 10:01:40 -0500 Subject: [PATCH 62/82] what? I'm not just guessing at the compiler error rather than building x86 --- .github/actions/spelling/dictionary/apis.txt | 4 ++++ src/cascadia/TerminalControl/ControlCore.cpp | 2 +- src/cascadia/TerminalControl/ControlInteractivity.cpp | 2 +- src/cascadia/TerminalControl/TermControl.cpp | 2 +- .../UnitTests_Control/ControlInteractivityTests.cpp | 10 +++++----- 5 files changed, 12 insertions(+), 8 deletions(-) diff --git a/.github/actions/spelling/dictionary/apis.txt b/.github/actions/spelling/dictionary/apis.txt index 2abb30978f3..38db6c576a5 100644 --- a/.github/actions/spelling/dictionary/apis.txt +++ b/.github/actions/spelling/dictionary/apis.txt @@ -11,6 +11,7 @@ CXICON CYICON D2DERR_SHADER_COMPILE_FAILED dataobject +dcomp DERR dlldata DONTADDTORECENT @@ -126,9 +127,12 @@ wsregex wwinmain XDocument XElement +xhash xlocmes xlocmon xlocnum xloctime XParse xstring +xtree +xutility diff --git a/src/cascadia/TerminalControl/ControlCore.cpp b/src/cascadia/TerminalControl/ControlCore.cpp index c949ecb26d3..8ce076328ac 100644 --- a/src/cascadia/TerminalControl/ControlCore.cpp +++ b/src/cascadia/TerminalControl/ControlCore.cpp @@ -65,7 +65,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation _terminal->Write(str); // NOTE: We're raising an event here to inform the TermControl that - // output has been recieved, so it can queue up a throttled + // output has been received, so it can queue up a throttled // UpdatePatternLocations call. In the future, we should have the // _updatePatternLocations ThrottledFunc internal to this class, and // run on this object's dispatcher queue. diff --git a/src/cascadia/TerminalControl/ControlInteractivity.cpp b/src/cascadia/TerminalControl/ControlInteractivity.cpp index 5ebf73c2fdc..1757fa3fa4a 100644 --- a/src/cascadia/TerminalControl/ControlInteractivity.cpp +++ b/src/cascadia/TerminalControl/ControlInteractivity.cpp @@ -116,7 +116,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation { // Note to future self: This should return false if there's no // selection to copy. If there's no selection, returning false will - // indicate that the actions that trigered this should _not_ be + // indicate that the actions that triggered this should _not_ be // marked as handled, so ctrl+c without a selection can still send // ^C diff --git a/src/cascadia/TerminalControl/TermControl.cpp b/src/cascadia/TerminalControl/TermControl.cpp index f3f35fe946a..000bf3958e2 100644 --- a/src/cascadia/TerminalControl/TermControl.cpp +++ b/src/cascadia/TerminalControl/TermControl.cpp @@ -2303,7 +2303,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation const Control::OpenHyperlinkEventArgs& args) { // Save things we need to resume later. - Control::OpenHyperlinkEventArgs heldargs = args; + Control::OpenHyperlinkEventArgs heldArgs = args; auto strongThis{ get_strong() }; // Pop the rest of this function to the tail of the UI thread diff --git a/src/cascadia/UnitTests_Control/ControlInteractivityTests.cpp b/src/cascadia/UnitTests_Control/ControlInteractivityTests.cpp index d65e4cdf5ec..e7c5f872d6c 100644 --- a/src/cascadia/UnitTests_Control/ControlInteractivityTests.cpp +++ b/src/cascadia/UnitTests_Control/ControlInteractivityTests.cpp @@ -284,7 +284,7 @@ namespace ControlUnitTests terminalPosition1); Log::Comment(L"Verify that there's one selection"); VERIFY_IS_TRUE(core->HasSelection()); - VERIFY_ARE_EQUAL(1, core->_terminal->GetSelectionRects().size()); + VERIFY_ARE_EQUAL(1u, core->_terminal->GetSelectionRects().size()); Log::Comment(L"Drag the mouse down a whole row"); const til::point terminalPosition2{ 1, 1 }; @@ -297,7 +297,7 @@ namespace ControlUnitTests terminalPosition2); Log::Comment(L"Verify that there's now two selections (one on each row)"); VERIFY_IS_TRUE(core->HasSelection()); - VERIFY_ARE_EQUAL(2, core->_terminal->GetSelectionRects().size()); + VERIFY_ARE_EQUAL(2u, core->_terminal->GetSelectionRects().size()); Log::Comment(L"Release the mouse"); interactivity->PointerReleased(noMouseDown, @@ -307,7 +307,7 @@ namespace ControlUnitTests terminalPosition2); Log::Comment(L"Verify that there's still two selections"); VERIFY_IS_TRUE(core->HasSelection()); - VERIFY_ARE_EQUAL(2, core->_terminal->GetSelectionRects().size()); + VERIFY_ARE_EQUAL(2u, core->_terminal->GetSelectionRects().size()); Log::Comment(L"click outside the current selection"); const til::point terminalPosition3{ 2, 2 }; @@ -321,7 +321,7 @@ namespace ControlUnitTests terminalPosition3); Log::Comment(L"Verify that there's now no selection"); VERIFY_IS_FALSE(core->HasSelection()); - VERIFY_ARE_EQUAL(0, core->_terminal->GetSelectionRects().size()); + VERIFY_ARE_EQUAL(0u, core->_terminal->GetSelectionRects().size()); Log::Comment(L"Drag the mouse"); const til::point terminalPosition4{ 3, 2 }; @@ -334,6 +334,6 @@ namespace ControlUnitTests terminalPosition4); Log::Comment(L"Verify that there's now one selection"); VERIFY_IS_TRUE(core->HasSelection()); - VERIFY_ARE_EQUAL(1, core->_terminal->GetSelectionRects().size()); + VERIFY_ARE_EQUAL(1u, core->_terminal->GetSelectionRects().size()); } } From 668fab4176646219e64cc1aba2f6d7009457b9ff Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Tue, 20 Apr 2021 09:16:49 -0500 Subject: [PATCH 63/82] nits from carlos --- src/cascadia/TerminalApp/TerminalTab.cpp | 48 +++++----- src/cascadia/TerminalControl/ControlCore.h | 12 +++ src/cascadia/TerminalControl/ControlCore.idl | 2 +- .../TerminalControl/ControlInteractivity.h | 13 +++ src/cascadia/TerminalControl/TermControl.idl | 2 - .../Control.UnitTests.vcxproj | 3 - .../UnitTests_Control/ControlCoreTests.cpp | 60 +++++------- .../ControlInteractivityTests.cpp | 96 ++++++++++--------- 8 files changed, 122 insertions(+), 114 deletions(-) diff --git a/src/cascadia/TerminalApp/TerminalTab.cpp b/src/cascadia/TerminalApp/TerminalTab.cpp index 904a678fbaf..2a5e91f14b5 100644 --- a/src/cascadia/TerminalApp/TerminalTab.cpp +++ b/src/cascadia/TerminalApp/TerminalTab.cpp @@ -168,7 +168,7 @@ namespace winrt::TerminalApp::implementation { lastFocusedControl.Focus(_focusState); - // Update our own progress state, and fire an event signalling + // Update our own progress state, and fire an event signaling // that our taskbar progress changed. _UpdateProgressState(); _TaskbarProgressChangedHandlers(lastFocusedControl, nullptr); @@ -626,34 +626,36 @@ namespace winrt::TerminalApp::implementation // - void TerminalTab::_UpdateProgressState() { - const auto activeControl = GetActiveTerminalControl(); - const auto taskbarState = activeControl.TaskbarState(); - // The progress of the control changed, but not necessarily the progress of the tab. - // Set the tab's progress ring to the active pane's progress - if (taskbarState > 0) + if (const auto& activeControl{ GetActiveTerminalControl() }) { - if (taskbarState == 3) + const auto taskbarState = activeControl.TaskbarState(); + // The progress of the control changed, but not necessarily the progress of the tab. + // Set the tab's progress ring to the active pane's progress + if (taskbarState > 0) { - // 3 is the indeterminate state, set the progress ring as such - _tabStatus.IsProgressRingIndeterminate(true); + if (taskbarState == 3) + { + // 3 is the indeterminate state, set the progress ring as such + _tabStatus.IsProgressRingIndeterminate(true); + } + else + { + // any non-indeterminate state has a value, set the progress ring as such + _tabStatus.IsProgressRingIndeterminate(false); + + const auto progressValue = gsl::narrow(activeControl.TaskbarProgress()); + _tabStatus.ProgressValue(progressValue); + } + // Hide the tab icon (the progress ring is placed over it) + HideIcon(true); + _tabStatus.IsProgressRingActive(true); } else { - // any non-indeterminate state has a value, set the progress ring as such - _tabStatus.IsProgressRingIndeterminate(false); - - const auto progressValue = gsl::narrow(activeControl.TaskbarProgress()); - _tabStatus.ProgressValue(progressValue); + // Show the tab icon + HideIcon(false); + _tabStatus.IsProgressRingActive(false); } - // Hide the tab icon (the progress ring is placed over it) - HideIcon(true); - _tabStatus.IsProgressRingActive(true); - } - else - { - // Show the tab icon - HideIcon(false); - _tabStatus.IsProgressRingActive(false); } } diff --git a/src/cascadia/TerminalControl/ControlCore.h b/src/cascadia/TerminalControl/ControlCore.h index 92aa58eaf7b..1d92e56041a 100644 --- a/src/cascadia/TerminalControl/ControlCore.h +++ b/src/cascadia/TerminalControl/ControlCore.h @@ -1,5 +1,17 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. +// +// Module Name: +// - ControlCore.h +// +// Abstract: +// - This encapsulates a `Terminal` instance, a `DxEngine` and `Renderer`, and +// an `ITerminalConnection`. This is intended to everything that someone might +// need to stand up a terminal instance in a control, but without any regard +// for how the UX works. +// +// Author: +// - Mike Griese (zadjii-msft) 01-Apr-2021 #pragma once diff --git a/src/cascadia/TerminalControl/ControlCore.idl b/src/cascadia/TerminalControl/ControlCore.idl index 41682e2c9aa..c3074000f75 100644 --- a/src/cascadia/TerminalControl/ControlCore.idl +++ b/src/cascadia/TerminalControl/ControlCore.idl @@ -10,7 +10,7 @@ namespace Microsoft.Terminal.Control [default_interface] runtimeclass ControlCore : ICoreState { - ControlCore(Microsoft.Terminal.Control.IControlSettings settings, + ControlCore(IControlSettings settings, Microsoft.Terminal.TerminalConnection.ITerminalConnection connection); }; } diff --git a/src/cascadia/TerminalControl/ControlInteractivity.h b/src/cascadia/TerminalControl/ControlInteractivity.h index a61e6d40b99..c4207365971 100644 --- a/src/cascadia/TerminalControl/ControlInteractivity.h +++ b/src/cascadia/TerminalControl/ControlInteractivity.h @@ -1,5 +1,18 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. +// +// Module Name: +// - ControlInteractivity.h +// +// Abstract: +// - This is a wrapper for the `ControlCore`. It holds the logic for things like +// double-click, right click copy/paste, selection, etc. This is intended to +// be a UI framework-independent abstraction. The methods this layer exposes +// can be called the same from both the WinUI `TermControl` and the WPF +// control. +// +// Author: +// - Mike Griese (zadjii-msft) 01-Apr-2021 #pragma once diff --git a/src/cascadia/TerminalControl/TermControl.idl b/src/cascadia/TerminalControl/TermControl.idl index 6c541838fff..6242436eb01 100644 --- a/src/cascadia/TerminalControl/TermControl.idl +++ b/src/cascadia/TerminalControl/TermControl.idl @@ -63,8 +63,6 @@ namespace Microsoft.Terminal.Control void ToggleShaderEffects(); void SendInput(String input); - // void TaskbarProgressChanged(); - Boolean ReadOnly { get; }; void ToggleReadOnly(); } diff --git a/src/cascadia/UnitTests_Control/Control.UnitTests.vcxproj b/src/cascadia/UnitTests_Control/Control.UnitTests.vcxproj index 3498995f119..6dba330010c 100644 --- a/src/cascadia/UnitTests_Control/Control.UnitTests.vcxproj +++ b/src/cascadia/UnitTests_Control/Control.UnitTests.vcxproj @@ -45,9 +45,6 @@ - - diff --git a/src/cascadia/UnitTests_Control/ControlCoreTests.cpp b/src/cascadia/UnitTests_Control/ControlCoreTests.cpp index 99c4a5847f3..c2d025963c5 100644 --- a/src/cascadia/UnitTests_Control/ControlCoreTests.cpp +++ b/src/cascadia/UnitTests_Control/ControlCoreTests.cpp @@ -38,6 +38,20 @@ namespace ControlUnitTests return true; } + + std::tuple, winrt::com_ptr> _createSettingsAndConnection() + { + Log::Comment(L"Create settings object"); + winrt::com_ptr settings; + settings.attach(new MockControlSettings()); + + Log::Comment(L"Create connection object"); + winrt::com_ptr conn; + conn.attach(new MockConnection()); + VERIFY_IS_NOT_NULL(conn); + + return { settings, conn }; + } }; void ControlCoreTests::OnStackSettings() @@ -61,14 +75,7 @@ namespace ControlUnitTests void ControlCoreTests::InstantiateCore() { - Log::Comment(L"Create settings object"); - winrt::com_ptr settings; - settings.attach(new MockControlSettings()); - - Log::Comment(L"Create connection object"); - winrt::com_ptr conn; - conn.attach(new MockConnection()); - VERIFY_IS_NOT_NULL(conn); + auto [settings, conn] = _createSettingsAndConnection(); Log::Comment(L"Create ControlCore object"); auto core = winrt::make_self(*settings, *conn); @@ -77,14 +84,7 @@ namespace ControlUnitTests void ControlCoreTests::TestInitialize() { - Log::Comment(L"Create settings object"); - winrt::com_ptr settings; - settings.attach(new MockControlSettings()); - - Log::Comment(L"Create connection object"); - winrt::com_ptr conn; - conn.attach(new MockConnection()); - VERIFY_IS_NOT_NULL(conn); + auto [settings, conn] = _createSettingsAndConnection(); Log::Comment(L"Create ControlCore object"); auto core = winrt::make_self(*settings, *conn); @@ -100,10 +100,7 @@ namespace ControlUnitTests void ControlCoreTests::TestAdjustAcrylic() { - winrt::com_ptr settings; - settings.attach(new MockControlSettings()); - winrt::com_ptr conn; - conn.attach(new MockConnection()); + auto [settings, conn] = _createSettingsAndConnection(); settings->UseAcrylic(true); settings->TintOpacity(0.5f); @@ -150,7 +147,7 @@ namespace ControlUnitTests core->AdjustOpacity(0.1); Log::Comment(L"Increasing opacity more doesn't actually change it to be >1.0"); - // DebugBreak(); + expectedOpacity = 1.0; core->AdjustOpacity(0.1); @@ -174,14 +171,7 @@ namespace ControlUnitTests void ControlCoreTests::TestFreeAfterClose() { { - Log::Comment(L"Create settings object"); - winrt::com_ptr settings; - settings.attach(new MockControlSettings()); - - Log::Comment(L"Create connection object"); - winrt::com_ptr conn; - conn.attach(new MockConnection()); - VERIFY_IS_NOT_NULL(conn); + auto [settings, conn] = _createSettingsAndConnection(); Log::Comment(L"Create ControlCore object"); auto core = winrt::make_self(*settings, *conn); @@ -197,21 +187,15 @@ namespace ControlUnitTests void ControlCoreTests::TestFontInitializedInCtor() { // This is to catch a dumb programming mistake I made while working on - // the ore/control split. We want the font initialized in the ctor, + // the core/control split. We want the font initialized in the ctor, // before we even get to Core::Initialize. - Log::Comment(L"Create settings object"); - winrt::com_ptr settings; - settings.attach(new MockControlSettings()); + auto [settings, conn] = _createSettingsAndConnection(); + // Make sure to use something dumb like "Impact" as a font name here so // that you don't default to Cascadia* settings->FontFace(L"Impact"); - Log::Comment(L"Create connection object"); - winrt::com_ptr conn; - conn.attach(new MockConnection()); - VERIFY_IS_NOT_NULL(conn); - Log::Comment(L"Create ControlCore object"); auto core = winrt::make_self(*settings, *conn); VERIFY_IS_NOT_NULL(core); diff --git a/src/cascadia/UnitTests_Control/ControlInteractivityTests.cpp b/src/cascadia/UnitTests_Control/ControlInteractivityTests.cpp index e7c5f872d6c..c34d4797e9a 100644 --- a/src/cascadia/UnitTests_Control/ControlInteractivityTests.cpp +++ b/src/cascadia/UnitTests_Control/ControlInteractivityTests.cpp @@ -36,6 +36,47 @@ namespace ControlUnitTests return true; } + + std::tuple, + winrt::com_ptr> + _createSettingsAndConnection() + { + Log::Comment(L"Create settings object"); + winrt::com_ptr settings; + settings.attach(new MockControlSettings()); + + Log::Comment(L"Create connection object"); + winrt::com_ptr conn; + conn.attach(new MockConnection()); + VERIFY_IS_NOT_NULL(conn); + + return { settings, conn }; + } + + std::tuple, + winrt::com_ptr> + _createCoreAndInteractivity(Control::IControlSettings settings, + TerminalConnection::ITerminalConnection conn) + { + Log::Comment(L"Create ControlInteractivity object"); + auto interactivity = winrt::make_self(settings, conn); + VERIFY_IS_NOT_NULL(interactivity); + auto core = interactivity->_core; + VERIFY_IS_NOT_NULL(core); + + return { core, interactivity }; + } + + void _standardInit(winrt::com_ptr core, + winrt::com_ptr interactivity) + { + // "Cascadia Mono" ends up with an actual size of 9x19 at 96DPI. So + // let's just arbitrarily start with a 270x380px (30x20 chars) window + core->InitializeTerminal(270, 380, 1.0, 1.0); + VERIFY_IS_TRUE(core->_initializedTerminal); + VERIFY_ARE_EQUAL(20, core->_terminal->GetViewport().Height()); + interactivity->Initialize(); + } }; void ControlInteractivityTests::TestAdjustAcrylic() @@ -45,19 +86,12 @@ namespace ControlUnitTests WEX::TestExecution::SetVerifyOutput verifyOutputScope{ WEX::TestExecution::VerifyOutputSettings::LogOnlyFailures }; - winrt::com_ptr settings; - settings.attach(new MockControlSettings()); - winrt::com_ptr conn; - conn.attach(new MockConnection()); + auto [settings, conn] = _createSettingsAndConnection(); settings->UseAcrylic(true); settings->TintOpacity(0.5f); - Log::Comment(L"Create ControlInteractivity object"); - auto interactivity = winrt::make_self(*settings, *conn); - VERIFY_IS_NOT_NULL(interactivity); - auto core = interactivity->_core; - VERIFY_IS_NOT_NULL(core); + auto [core, interactivity] = _createCoreAndInteractivity(*settings, *conn); // A callback to make sure that we're raising TransparencyChanged events double expectedOpacity = 0.5; @@ -123,25 +157,9 @@ namespace ControlUnitTests { WEX::TestExecution::DisableVerifyExceptions disableVerifyExceptions{}; - winrt::com_ptr settings; - settings.attach(new MockControlSettings()); - winrt::com_ptr conn; - conn.attach(new MockConnection()); - - settings->UseAcrylic(true); - settings->TintOpacity(0.5f); - - Log::Comment(L"Create ControlInteractivity object"); - auto interactivity = winrt::make_self(*settings, *conn); - VERIFY_IS_NOT_NULL(interactivity); - auto core = interactivity->_core; - VERIFY_IS_NOT_NULL(core); - // "Cascadia Mono" ends up with an actual size of 9x19 at 96DPI. So - // let's just arbitrarily start with a 270x380px (30x20 chars) window - core->InitializeTerminal(270, 380, 1.0, 1.0); - VERIFY_IS_TRUE(core->_initializedTerminal); - VERIFY_ARE_EQUAL(20, core->_terminal->GetViewport().Height()); - interactivity->Initialize(); + auto [settings, conn] = _createSettingsAndConnection(); + auto [core, interactivity] = _createCoreAndInteractivity(*settings, *conn); + _standardInit(core, interactivity); // For the sake of this test, scroll one line at a time interactivity->_rowsToScroll = 1; @@ -231,25 +249,9 @@ namespace ControlUnitTests // This is a test for GH#9725 WEX::TestExecution::DisableVerifyExceptions disableVerifyExceptions{}; - winrt::com_ptr settings; - settings.attach(new MockControlSettings()); - winrt::com_ptr conn; - conn.attach(new MockConnection()); - - settings->UseAcrylic(true); - settings->TintOpacity(0.5f); - - Log::Comment(L"Create ControlInteractivity object"); - auto interactivity = winrt::make_self(*settings, *conn); - VERIFY_IS_NOT_NULL(interactivity); - auto core = interactivity->_core; - VERIFY_IS_NOT_NULL(core); - // "Cascadia Mono" ends up with an actual size of 9x19 at 96DPI. So - // let's just arbitrarily start with a 270x380px (30x20 chars) window - core->InitializeTerminal(270, 380, 1.0, 1.0); - VERIFY_IS_TRUE(core->_initializedTerminal); - VERIFY_ARE_EQUAL(20, core->_terminal->GetViewport().Height()); - interactivity->Initialize(); + auto [settings, conn] = _createSettingsAndConnection(); + auto [core, interactivity] = _createCoreAndInteractivity(*settings, *conn); + _standardInit(core, interactivity); // For this test, don't use any modifiers const auto modifiers = ControlKeyStates(); From 69f22a711349ff2021642d697d0f7676bd72cb1b Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Tue, 20 Apr 2021 12:02:22 -0500 Subject: [PATCH 64/82] hot reload anti-aliasing --- src/cascadia/TerminalControl/ControlCore.cpp | 48 ++++++++------------ src/cascadia/TerminalControl/ControlCore.h | 1 + src/renderer/dx/DxRenderer.cpp | 1 + 3 files changed, 22 insertions(+), 28 deletions(-) diff --git a/src/cascadia/TerminalControl/ControlCore.cpp b/src/cascadia/TerminalControl/ControlCore.cpp index 8ce076328ac..de9926320e7 100644 --- a/src/cascadia/TerminalControl/ControlCore.cpp +++ b/src/cascadia/TerminalControl/ControlCore.cpp @@ -210,20 +210,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation dxEngine->SetForceFullRepaintRendering(_settings.ForceFullRepaintRendering()); dxEngine->SetSoftwareRendering(_settings.SoftwareRendering()); - // Update DxEngine's AntialiasingMode - switch (_settings.AntialiasingMode()) - { - case TextAntialiasingMode::Cleartype: - dxEngine->SetAntialiasingMode(D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE); - break; - case TextAntialiasingMode::Aliased: - dxEngine->SetAntialiasingMode(D2D1_TEXT_ANTIALIAS_MODE_ALIASED); - break; - case TextAntialiasingMode::Grayscale: - default: - dxEngine->SetAntialiasingMode(D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE); - break; - } + _updateAntiAliasingMode(dxEngine.get()); // GH#5098: Inform the engine of the opacity of the default text background. if (_settings.UseAcrylic()) @@ -542,20 +529,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation _renderEngine->SetForceFullRepaintRendering(_settings.ForceFullRepaintRendering()); _renderEngine->SetSoftwareRendering(_settings.SoftwareRendering()); - - switch (_settings.AntialiasingMode()) - { - case TextAntialiasingMode::Cleartype: - _renderEngine->SetAntialiasingMode(D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE); - break; - case TextAntialiasingMode::Aliased: - _renderEngine->SetAntialiasingMode(D2D1_TEXT_ANTIALIAS_MODE_ALIASED); - break; - case TextAntialiasingMode::Grayscale: - default: - _renderEngine->SetAntialiasingMode(D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE); - break; - } + _updateAntiAliasingMode(_renderEngine.get()); // TODO!: UpdateAppearance() ? @@ -585,6 +559,24 @@ namespace winrt::Microsoft::Terminal::Control::implementation } } + void ControlCore::_updateAntiAliasingMode(::Microsoft::Console::Render::DxEngine* const dxEngine) + { + // Update DxEngine's AntialiasingMode + switch (_settings.AntialiasingMode()) + { + case TextAntialiasingMode::Cleartype: + dxEngine->SetAntialiasingMode(D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE); + break; + case TextAntialiasingMode::Aliased: + dxEngine->SetAntialiasingMode(D2D1_TEXT_ANTIALIAS_MODE_ALIASED); + break; + case TextAntialiasingMode::Grayscale: + default: + dxEngine->SetAntialiasingMode(D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE); + break; + } + } + // Method Description: // - Update the font with the renderer. This will be called either when the // font changes or the DPI changes, as DPI changes will necessitate a diff --git a/src/cascadia/TerminalControl/ControlCore.h b/src/cascadia/TerminalControl/ControlCore.h index 1d92e56041a..ac124412fe5 100644 --- a/src/cascadia/TerminalControl/ControlCore.h +++ b/src/cascadia/TerminalControl/ControlCore.h @@ -230,6 +230,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation void _raiseHoveredHyperlinkChanged(); void _raiseReadOnlyWarning(); + void _updateAntiAliasingMode(::Microsoft::Console::Render::DxEngine* const dxEngine); friend class ControlUnitTests::ControlCoreTests; friend class ControlUnitTests::ControlInteractivityTests; diff --git a/src/renderer/dx/DxRenderer.cpp b/src/renderer/dx/DxRenderer.cpp index d1b988cb475..77709d932f4 100644 --- a/src/renderer/dx/DxRenderer.cpp +++ b/src/renderer/dx/DxRenderer.cpp @@ -2175,6 +2175,7 @@ try if (_antialiasingMode != antialiasingMode) { _antialiasingMode = antialiasingMode; + _recreateDeviceRequested = true; LOG_IF_FAILED(InvalidateAll()); } } From c113b65d9b15028281f6383909a73dba6af55bfc Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Tue, 20 Apr 2021 12:16:31 -0500 Subject: [PATCH 65/82] Revert "Use DComp surface handle for Swap Chain management." This reverts commit 30b833547928d6dcbf88d49df0dbd5b3f6a7c879. --- src/cascadia/TerminalControl/ControlCore.cpp | 4 ++-- src/cascadia/TerminalControl/ControlCore.h | 2 +- src/cascadia/TerminalControl/TermControl.cpp | 12 +++++----- src/cascadia/TerminalControl/TermControl.h | 3 ++- src/common.build.post.props | 2 +- src/renderer/dx/DxRenderer.cpp | 23 ++++++-------------- src/renderer/dx/DxRenderer.hpp | 3 +-- src/renderer/dx/precomp.h | 2 -- 8 files changed, 20 insertions(+), 31 deletions(-) diff --git a/src/cascadia/TerminalControl/ControlCore.cpp b/src/cascadia/TerminalControl/ControlCore.cpp index de9926320e7..ac88139c24e 100644 --- a/src/cascadia/TerminalControl/ControlCore.cpp +++ b/src/cascadia/TerminalControl/ControlCore.cpp @@ -1192,9 +1192,9 @@ namespace winrt::Microsoft::Terminal::Control::implementation } } - HANDLE ControlCore::GetSwapChainHandle() const + IDXGISwapChain1* ControlCore::GetSwapChain() const { - return _renderEngine->GetSwapChainHandle(); + return _renderEngine->GetSwapChain().Get(); } void ControlCore::_rendererWarning(const HRESULT hr) diff --git a/src/cascadia/TerminalControl/ControlCore.h b/src/cascadia/TerminalControl/ControlCore.h index ac124412fe5..29ce4a532c3 100644 --- a/src/cascadia/TerminalControl/ControlCore.h +++ b/src/cascadia/TerminalControl/ControlCore.h @@ -49,7 +49,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation void UpdateAppearance(IControlAppearance newAppearance); void SizeChanged(const double width, const double height); void ScaleChanged(const double scaleX, const double scaleY); - HANDLE GetSwapChainHandle() const; + IDXGISwapChain1* GetSwapChain() const; void AdjustFontSize(int fontSizeDelta); void ResetFontSize(); diff --git a/src/cascadia/TerminalControl/TermControl.cpp b/src/cascadia/TerminalControl/TermControl.cpp index 000bf3958e2..51486718c5a 100644 --- a/src/cascadia/TerminalControl/TermControl.cpp +++ b/src/cascadia/TerminalControl/TermControl.cpp @@ -572,14 +572,14 @@ namespace winrt::Microsoft::Terminal::Control::implementation // This event is only registered during terminal initialization, // so we don't need to check _initializedTerminal. // We also don't lock for things that come back from the renderer. - auto chainHandle = _core->GetSwapChainHandle(); + auto chain = _core->GetSwapChain(); auto weakThis{ get_weak() }; co_await winrt::resume_foreground(Dispatcher()); if (auto control{ weakThis.get() }) { - _AttachDxgiSwapChainToXaml(chainHandle); + _AttachDxgiSwapChainToXaml(chain); } } @@ -625,10 +625,10 @@ namespace winrt::Microsoft::Terminal::Control::implementation } } - void TermControl::_AttachDxgiSwapChainToXaml(HANDLE swapChainHandle) + void TermControl::_AttachDxgiSwapChainToXaml(IDXGISwapChain1* swapChain) { - auto nativePanel = SwapChainPanel().as(); - nativePanel->SetSwapChainHandle(swapChainHandle); + auto nativePanel = SwapChainPanel().as(); + nativePanel->SetSwapChain(swapChain); } bool TermControl::_InitializeTerminal() @@ -667,7 +667,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation } _interactivity->Initialize(); - _AttachDxgiSwapChainToXaml(_core->GetSwapChainHandle()); + _AttachDxgiSwapChainToXaml(_core->GetSwapChain()); // Tell the DX Engine to notify us when the swap chain changes. We do // this after we initially set the swapchain so as to avoid unnecessary diff --git a/src/cascadia/TerminalControl/TermControl.h b/src/cascadia/TerminalControl/TermControl.h index a4ebffc924a..1fcb48ee1f7 100644 --- a/src/cascadia/TerminalControl/TermControl.h +++ b/src/cascadia/TerminalControl/TermControl.h @@ -66,8 +66,9 @@ namespace winrt::Microsoft::Terminal::Control::implementation void ToggleShaderEffects(); winrt::fire_and_forget RenderEngineSwapChainChanged(const IInspectable& sender, const IInspectable& args); - void _AttachDxgiSwapChainToXaml(HANDLE swapChainHandle); + void _AttachDxgiSwapChainToXaml(IDXGISwapChain1* swapChain); winrt::fire_and_forget _RendererEnteredErrorState(const IInspectable& sender, const IInspectable& args); + void _RenderRetryButton_Click(IInspectable const& button, IInspectable const& args); winrt::fire_and_forget _RendererWarning(const IInspectable& sender, const Control::RendererWarningArgs& args); diff --git a/src/common.build.post.props b/src/common.build.post.props index c3b0d521215..e3e563b900d 100644 --- a/src/common.build.post.props +++ b/src/common.build.post.props @@ -13,7 +13,7 @@ ProgramDatabase - onecoreuap_apiset.lib;d3dcompiler.lib;dwmapi.lib;uxtheme.lib;shlwapi.lib;ntdll.lib;dcomp.lib;%(AdditionalDependencies) + onecoreuap_apiset.lib;d3dcompiler.lib;dwmapi.lib;uxtheme.lib;shlwapi.lib;ntdll.lib;%(AdditionalDependencies) diff --git a/src/renderer/dx/DxRenderer.cpp b/src/renderer/dx/DxRenderer.cpp index 77709d932f4..1763f3c5b5a 100644 --- a/src/renderer/dx/DxRenderer.cpp +++ b/src/renderer/dx/DxRenderer.cpp @@ -79,7 +79,6 @@ DxEngine::DxEngine() : _backgroundColor{ 0 }, _selectionBackground{}, _haveDeviceResources{ false }, - _swapChainHandle{ INVALID_HANDLE_VALUE }, _swapChainDesc{ 0 }, _swapChainFrameLatencyWaitableObject{ INVALID_HANDLE_VALUE }, _recreateDeviceRequested{ false }, @@ -619,13 +618,6 @@ try } case SwapChainMode::ForComposition: { - if (!_swapChainHandle) - { - RETURN_IF_FAILED(DCompositionCreateSurfaceHandle(GENERIC_ALL, nullptr, &_swapChainHandle)); - } - - RETURN_IF_FAILED(_dxgiFactory2.As(&_dxgiFactoryMedia)); - // Use the given target size for compositions. _swapChainDesc.Width = _displaySizePixels.width(); _swapChainDesc.Height = _displaySizePixels.height(); @@ -635,11 +627,10 @@ try // It's 100% required to use scaling mode stretch for composition. There is no other choice. _swapChainDesc.Scaling = DXGI_SCALING_STRETCH; - RETURN_IF_FAILED(_dxgiFactoryMedia->CreateSwapChainForCompositionSurfaceHandle(_d3dDevice.Get(), - _swapChainHandle.get(), - &_swapChainDesc, - nullptr, - &_dxgiSwapChain)); + RETURN_IF_FAILED(_dxgiFactory2->CreateSwapChainForComposition(_d3dDevice.Get(), + &_swapChainDesc, + nullptr, + &_dxgiSwapChain)); break; } default: @@ -1012,14 +1003,14 @@ try } CATCH_LOG() -HANDLE DxEngine::GetSwapChainHandle() +Microsoft::WRL::ComPtr DxEngine::GetSwapChain() { - if (!_swapChainHandle) + if (_dxgiSwapChain.Get() == nullptr) { THROW_IF_FAILED(_CreateDeviceResources(true)); } - return _swapChainHandle.get(); + return _dxgiSwapChain; } void DxEngine::_InvalidateRectangle(const til::rectangle& rc) diff --git a/src/renderer/dx/DxRenderer.hpp b/src/renderer/dx/DxRenderer.hpp index f4ae176c7e8..7de6832146e 100644 --- a/src/renderer/dx/DxRenderer.hpp +++ b/src/renderer/dx/DxRenderer.hpp @@ -70,7 +70,7 @@ namespace Microsoft::Console::Render void SetSoftwareRendering(bool enable) noexcept; - HANDLE GetSwapChainHandle(); + ::Microsoft::WRL::ComPtr GetSwapChain(); // IRenderEngine Members [[nodiscard]] HRESULT Invalidate(const SMALL_RECT* const psrRegion) noexcept override; @@ -212,7 +212,6 @@ namespace Microsoft::Console::Render ::Microsoft::WRL::ComPtr _d2dBrushBackground; ::Microsoft::WRL::ComPtr _dxgiFactory2; - ::Microsoft::WRL::ComPtr _dxgiFactoryMedia; ::Microsoft::WRL::ComPtr _dxgiDevice; ::Microsoft::WRL::ComPtr _dxgiSurface; diff --git a/src/renderer/dx/precomp.h b/src/renderer/dx/precomp.h index d3d51af5f51..5715fd8fed3 100644 --- a/src/renderer/dx/precomp.h +++ b/src/renderer/dx/precomp.h @@ -21,8 +21,6 @@ #include #include -#include - #include #include #include From bddae1cfdd3cd874ea97ddfdc66500473a130c83 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Tue, 20 Apr 2021 12:45:33 -0500 Subject: [PATCH 66/82] make_self for fun and profit --- .../UnitTests_Control/ControlCoreTests.cpp | 22 +++++-------------- .../ControlInteractivityTests.cpp | 7 +++--- 2 files changed, 8 insertions(+), 21 deletions(-) diff --git a/src/cascadia/UnitTests_Control/ControlCoreTests.cpp b/src/cascadia/UnitTests_Control/ControlCoreTests.cpp index c2d025963c5..3c8bb7bd93f 100644 --- a/src/cascadia/UnitTests_Control/ControlCoreTests.cpp +++ b/src/cascadia/UnitTests_Control/ControlCoreTests.cpp @@ -22,7 +22,6 @@ namespace ControlUnitTests BEGIN_TEST_CLASS(ControlCoreTests) END_TEST_CLASS() - TEST_METHOD(OnStackSettings); TEST_METHOD(ComPtrSettings); TEST_METHOD(InstantiateCore); TEST_METHOD(TestInitialize); @@ -42,32 +41,21 @@ namespace ControlUnitTests std::tuple, winrt::com_ptr> _createSettingsAndConnection() { Log::Comment(L"Create settings object"); - winrt::com_ptr settings; - settings.attach(new MockControlSettings()); + auto settings = winrt::make_self(); + VERIFY_IS_NOT_NULL(settings); Log::Comment(L"Create connection object"); - winrt::com_ptr conn; - conn.attach(new MockConnection()); + auto conn = winrt::make_self(); VERIFY_IS_NOT_NULL(conn); return { settings, conn }; } }; - void ControlCoreTests::OnStackSettings() - { - Log::Comment(L"Just make sure we can instantiate a settings obj on the stack"); - - MockControlSettings settings; - - Log::Comment(L"Verify literally any setting, it doesn't matter"); - VERIFY_ARE_EQUAL(DEFAULT_FOREGROUND, settings.DefaultForeground()); - } void ControlCoreTests::ComPtrSettings() { Log::Comment(L"Just make sure we can instantiate a settings obj in a com_ptr"); - winrt::com_ptr settings; - settings.attach(new MockControlSettings()); + auto settings = winrt::make_self(); Log::Comment(L"Verify literally any setting, it doesn't matter"); VERIFY_ARE_EQUAL(DEFAULT_FOREGROUND, settings->DefaultForeground()); @@ -200,7 +188,7 @@ namespace ControlUnitTests auto core = winrt::make_self(*settings, *conn); VERIFY_IS_NOT_NULL(core); - VERIFY_ARE_EQUAL(L"Impact", std::wstring{ core->_actualFont.GetFaceName() }); + VERIFY_ARE_EQUAL(L"Impact", std::wstring_view{ core->_actualFont.GetFaceName() }); } } diff --git a/src/cascadia/UnitTests_Control/ControlInteractivityTests.cpp b/src/cascadia/UnitTests_Control/ControlInteractivityTests.cpp index c34d4797e9a..b2965e6070c 100644 --- a/src/cascadia/UnitTests_Control/ControlInteractivityTests.cpp +++ b/src/cascadia/UnitTests_Control/ControlInteractivityTests.cpp @@ -42,12 +42,11 @@ namespace ControlUnitTests _createSettingsAndConnection() { Log::Comment(L"Create settings object"); - winrt::com_ptr settings; - settings.attach(new MockControlSettings()); + auto settings = winrt::make_self(); + VERIFY_IS_NOT_NULL(settings); Log::Comment(L"Create connection object"); - winrt::com_ptr conn; - conn.attach(new MockConnection()); + auto conn = winrt::make_self(); VERIFY_IS_NOT_NULL(conn); return { settings, conn }; From 0e72f777449671d6a6ca9fe69a8b1429f359bb8d Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Tue, 20 Apr 2021 12:51:21 -0500 Subject: [PATCH 67/82] woah look, none of these tests were ever running :yikes: --- build/pipelines/templates/build-console-steps.yml | 6 +++--- src/cascadia/UnitTests_Control/Control.UnitTests.vcxproj | 2 +- src/cascadia/UnitTests_Remoting/Remoting.UnitTests.vcxproj | 2 +- tools/runut.cmd | 4 ++-- tools/tests.xml | 4 ++-- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/build/pipelines/templates/build-console-steps.yml b/build/pipelines/templates/build-console-steps.yml index 4a3adcb4054..e5455dc8c4e 100644 --- a/build/pipelines/templates/build-console-steps.yml +++ b/build/pipelines/templates/build-console-steps.yml @@ -22,7 +22,7 @@ steps: configPath: NuGet.config restoreSolution: OpenConsole.sln restoreDirectory: '$(Build.SourcesDirectory)\packages' - + - task: 333b11bd-d341-40d9-afcf-b32d5ce6f23b@2 displayName: Restore NuGet packages for extraneous build actions inputs: @@ -96,7 +96,7 @@ steps: displayName: 'Upload converted test logs' inputs: testResultsFormat: 'xUnit' # Options: JUnit, NUnit, VSTest, xUnit, cTest - testResultsFiles: '**/onBuildMachineResults.xml' + testResultsFiles: '**/onBuildMachineResults.xml' #searchFolder: '$(System.DefaultWorkingDirectory)' # Optional #mergeTestResults: false # Optional #failTaskOnFailedTests: false # Optional @@ -147,4 +147,4 @@ steps: displayName: 'Publish All Build Artifacts' inputs: PathtoPublish: '$(Build.ArtifactStagingDirectory)' - ArtifactName: 'drop' \ No newline at end of file + ArtifactName: 'drop' diff --git a/src/cascadia/UnitTests_Control/Control.UnitTests.vcxproj b/src/cascadia/UnitTests_Control/Control.UnitTests.vcxproj index 6dba330010c..5ebe26096cb 100644 --- a/src/cascadia/UnitTests_Control/Control.UnitTests.vcxproj +++ b/src/cascadia/UnitTests_Control/Control.UnitTests.vcxproj @@ -5,7 +5,7 @@ Win32Proj ControlUnitTests UnitTests_Control - Control.UnitTests + Control.Unit.Tests DynamicLibrary 10.0.18362.0 10.0.18362.0 diff --git a/src/cascadia/UnitTests_Remoting/Remoting.UnitTests.vcxproj b/src/cascadia/UnitTests_Remoting/Remoting.UnitTests.vcxproj index a151a594027..a67eba4f3d2 100644 --- a/src/cascadia/UnitTests_Remoting/Remoting.UnitTests.vcxproj +++ b/src/cascadia/UnitTests_Remoting/Remoting.UnitTests.vcxproj @@ -16,7 +16,7 @@ Win32Proj RemotingUnitTests UnitTests_Remoting - Remoting.UnitTests + Remoting.Unit.Tests DynamicLibrary 10.0.18362.0 10.0.18362.0 diff --git a/tools/runut.cmd b/tools/runut.cmd index 3da64494fc3..48cb13a39e6 100644 --- a/tools/runut.cmd +++ b/tools/runut.cmd @@ -23,8 +23,8 @@ call %TAEF% ^ %OPENCON%\bin\%PLATFORM%\%_LAST_BUILD_CONF%\Types.Unit.Tests.dll ^ %OPENCON%\bin\%PLATFORM%\%_LAST_BUILD_CONF%\til.unit.tests.dll ^ %OPENCON%\bin\%PLATFORM%\%_LAST_BUILD_CONF%\UnitTests_TerminalApp\Terminal.App.Unit.Tests.dll ^ - %OPENCON%\bin\%PLATFORM%\%_LAST_BUILD_CONF%\UnitTests_Remoting\Remoting.UnitTests.dll ^ - %OPENCON%\bin\%PLATFORM%\%_LAST_BUILD_CONF%\UnitTests_Control\Control.UnitTests.dll ^ + %OPENCON%\bin\%PLATFORM%\%_LAST_BUILD_CONF%\UnitTests_Remoting\Remoting.Unit.Tests.dll ^ + %OPENCON%\bin\%PLATFORM%\%_LAST_BUILD_CONF%\UnitTests_Control\Control.Unit.Tests.dll ^ %_TestHostAppPath%\TerminalApp.LocalTests.dll ^ %_TestHostAppPath%\SettingsModel.LocalTests.dll ^ %* diff --git a/tools/tests.xml b/tools/tests.xml index 17c51ceecc3..19507741d04 100644 --- a/tools/tests.xml +++ b/tools/tests.xml @@ -6,8 +6,8 @@ - - + + From e271bdf70ee1ad9988a54e3477f808dc50336dba Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Tue, 20 Apr 2021 14:40:24 -0500 Subject: [PATCH 68/82] the really easy feedback from dustin --- src/cascadia/TerminalControl/TermControl.cpp | 68 +++++++++---------- src/cascadia/TerminalControl/TermControl.h | 20 +++--- .../ControlInteractivityTests.cpp | 2 +- 3 files changed, 45 insertions(+), 45 deletions(-) diff --git a/src/cascadia/TerminalControl/TermControl.cpp b/src/cascadia/TerminalControl/TermControl.cpp index 51486718c5a..5ba58c2f752 100644 --- a/src/cascadia/TerminalControl/TermControl.cpp +++ b/src/cascadia/TerminalControl/TermControl.cpp @@ -65,18 +65,25 @@ namespace winrt::Microsoft::Terminal::Control::implementation _interactivity = winrt::make_self(settings, connection); _core = _interactivity->GetCore(); - _core->BackgroundColorChanged({ get_weak(), &TermControl::_BackgroundColorChangedHandler }); + // These all need weak refs - they could be triggered by the connection, + // which would happen off the UI thread. _core->ScrollPositionChanged({ get_weak(), &TermControl::_ScrollPositionChanged }); _core->CursorPositionChanged({ get_weak(), &TermControl::_CursorPositionChanged }); _core->RendererEnteredErrorState({ get_weak(), &TermControl::_RendererEnteredErrorState }); - _core->FontSizeChanged({ get_weak(), &TermControl::_coreFontSizeChanged }); - _core->TransparencyChanged({ get_weak(), &TermControl::_coreTransparencyChanged }); - _core->ReceivedOutput({ get_weak(), &TermControl::_coreReceivedOutput }); - _core->RaiseNotice({ get_weak(), &TermControl::_coreRaisedNotice }); _core->WarningBell({ get_weak(), &TermControl::_coreWarningBell }); + _core->ReceivedOutput({ get_weak(), &TermControl::_coreReceivedOutput }); + + // These callbacks can only really be triggered by UI interactions. So + // they don't need weak refs - they can't be triggered unless we're + // alive. + _core->BackgroundColorChanged({ this, &TermControl::_BackgroundColorChangedHandler }); + _core->FontSizeChanged({ this, &TermControl::_coreFontSizeChanged }); + _core->TransparencyChanged({ this, &TermControl::_coreTransparencyChanged }); + _core->RaiseNotice({ this, &TermControl::_coreRaisedNotice }); + _core->HoveredHyperlinkChanged({ this, &TermControl::_hoveredHyperlinkChanged }); + _interactivity->OpenHyperlink({ this, &TermControl::_HyperlinkHandler }); + _interactivity->ScrollPositionChanged({ this, &TermControl::_ScrollPositionChanged }); - _interactivity->OpenHyperlink({ get_weak(), &TermControl::_HyperlinkHandler }); - _interactivity->ScrollPositionChanged({ get_weak(), &TermControl::_ScrollPositionChanged }); // Initialize the terminal only once the swapchainpanel is loaded - that // way, we'll be able to query the real pixel size it got on layout _layoutUpdatedRevoker = SwapChainPanel().LayoutUpdated(winrt::auto_revoke, [this](auto /*s*/, auto /*e*/) { @@ -149,8 +156,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation _autoScrollTimer.Tick({ this, &TermControl::_UpdateAutoScroll }); _ApplyUISettings(_settings); - - _core->HoveredHyperlinkChanged({ get_weak(), &TermControl::_hoveredHyperlinkChanged }); } // Method Description: @@ -351,14 +356,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation TSFInputControl().Foreground(foregroundBrush); _core->UpdateAppearance(newAppearance); - // // Update the terminal core with its new Core settings - // _terminal->UpdateAppearance(newAppearance); - - // // Update DxEngine settings under the lock - // _renderEngine->SetSelectionBackground(til::color{ newAppearance.SelectionBackground() }); - // _renderEngine->SetRetroTerminalEffect(newAppearance.RetroTerminalEffect()); - // _renderEngine->SetPixelShaderPath(newAppearance.PixelShaderPath()); - // _renderer->TriggerRedrawAll(); } // Method Description: @@ -567,7 +564,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation return _core->ConnectionState(); } - winrt::fire_and_forget TermControl::RenderEngineSwapChainChanged(const IInspectable& /*sender*/, const IInspectable& /*args*/) + winrt::fire_and_forget TermControl::RenderEngineSwapChainChanged(IInspectable /*sender*/, IInspectable /*args*/) { // This event is only registered during terminal initialization, // so we don't need to check _initializedTerminal. @@ -593,10 +590,10 @@ namespace winrt::Microsoft::Terminal::Control::implementation // - hr: an HRESULT describing the warning // Return Value: // - - winrt::fire_and_forget TermControl::_RendererWarning(const IInspectable& /*sender*/, - const Control::RendererWarningArgs& args) + winrt::fire_and_forget TermControl::_RendererWarning(IInspectable /*sender*/, + Control::RendererWarningArgs args) { - const HRESULT hr = static_cast(args.Result()); + const auto hr = static_cast(args.Result()); auto weakThis{ get_weak() }; co_await winrt::resume_foreground(Dispatcher()); @@ -651,7 +648,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation return false; } - // IMPORTANT! Set this callback up sooner than later. If we do it + // IMPORTANT! Set this callback up sooner rather than later. If we do it // after Enable, then it'll be possible to paint the frame once // _before_ the warning handler is set up, and then warnings from // the first paint will be ignored! @@ -1065,7 +1062,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation TermControl::GetPressedMouseButtons(point), TermControl::PointerToMouseButtons(point), point.Timestamp(), - ControlKeyStates(args.KeyModifiers()), + ControlKeyStates{ args.KeyModifiers() }, _focused, _GetTerminalPosition(cursorPosition)); } @@ -1254,8 +1251,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation // - // Return Value: // - - winrt::fire_and_forget TermControl::_coreTransparencyChanged(const IInspectable& /*sender*/, - const Control::TransparencyChangedEventArgs& /*args*/) + winrt::fire_and_forget TermControl::_coreTransparencyChanged(IInspectable /*sender*/, + Control::TransparencyChangedEventArgs /*args*/) { co_await resume_foreground(Dispatcher()); try @@ -2170,8 +2167,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation // - e: The DragEventArgs from the Drop event // Return Value: // - - winrt::fire_and_forget TermControl::_DragDropHandler(Windows::Foundation::IInspectable const& /*sender*/, - DragEventArgs const e) + winrt::fire_and_forget TermControl::_DragDropHandler(Windows::Foundation::IInspectable /*sender*/, + DragEventArgs e) { if (_closing) { @@ -2299,11 +2296,10 @@ namespace winrt::Microsoft::Terminal::Control::implementation // - Checks if the uri is valid and sends an event if so // Arguments: // - The uri - winrt::fire_and_forget TermControl::_HyperlinkHandler(const IInspectable& /*sender*/, - const Control::OpenHyperlinkEventArgs& args) + winrt::fire_and_forget TermControl::_HyperlinkHandler(IInspectable /*sender*/, + Control::OpenHyperlinkEventArgs args) { // Save things we need to resume later. - Control::OpenHyperlinkEventArgs heldArgs = args; auto strongThis{ get_strong() }; // Pop the rest of this function to the tail of the UI thread @@ -2317,8 +2313,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation // Method Description: // - Produces the error dialog that notifies the user that rendering cannot proceed. - winrt::fire_and_forget TermControl::_RendererEnteredErrorState(IInspectable const& /*sender*/, - IInspectable const& /*args*/) + winrt::fire_and_forget TermControl::_RendererEnteredErrorState(IInspectable /*sender*/, + IInspectable /*args*/) { auto strongThis{ get_strong() }; co_await Dispatcher(); // pop up onto the UI thread @@ -2348,6 +2344,10 @@ namespace winrt::Microsoft::Terminal::Control::implementation Windows::Foundation::IReference TermControl::TabColor() noexcept { + // NOTE TO FUTURE READERS: TabColor is down in the Core for the + // hypothetical future where we allow an application to set the tab + // color with VT sequences like they're currently allowed to with the + // title. return _core->TabColor(); } @@ -2397,8 +2397,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation _core->UpdateHoveredCell(std::nullopt); } - winrt::fire_and_forget TermControl::_hoveredHyperlinkChanged(const IInspectable& sender, - const IInspectable& args) + winrt::fire_and_forget TermControl::_hoveredHyperlinkChanged(IInspectable sender, + IInspectable args) { auto weakThis{ get_weak() }; co_await resume_foreground(Dispatcher()); diff --git a/src/cascadia/TerminalControl/TermControl.h b/src/cascadia/TerminalControl/TermControl.h index 1fcb48ee1f7..eabec66a84e 100644 --- a/src/cascadia/TerminalControl/TermControl.h +++ b/src/cascadia/TerminalControl/TermControl.h @@ -65,13 +65,13 @@ namespace winrt::Microsoft::Terminal::Control::implementation void SendInput(const winrt::hstring& input); void ToggleShaderEffects(); - winrt::fire_and_forget RenderEngineSwapChainChanged(const IInspectable& sender, const IInspectable& args); + winrt::fire_and_forget RenderEngineSwapChainChanged(IInspectable sender, IInspectable args); void _AttachDxgiSwapChainToXaml(IDXGISwapChain1* swapChain); - winrt::fire_and_forget _RendererEnteredErrorState(const IInspectable& sender, const IInspectable& args); + winrt::fire_and_forget _RendererEnteredErrorState(IInspectable sender, IInspectable args); void _RenderRetryButton_Click(IInspectable const& button, IInspectable const& args); - winrt::fire_and_forget _RendererWarning(const IInspectable& sender, - const Control::RendererWarningArgs& args); + winrt::fire_and_forget _RendererWarning(IInspectable sender, + Control::RendererWarningArgs args); void CreateSearchBoxControl(); @@ -130,8 +130,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation private: friend struct TermControlT; // friend our parent so it can bind private event handlers - winrt::com_ptr _core{ nullptr }; - winrt::com_ptr _interactivity{ nullptr }; + winrt::com_ptr _core; + winrt::com_ptr _interactivity; bool _initializedTerminal; @@ -193,10 +193,10 @@ namespace winrt::Microsoft::Terminal::Control::implementation void _GotFocusHandler(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::RoutedEventArgs const& e); void _LostFocusHandler(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::RoutedEventArgs const& e); - winrt::fire_and_forget _DragDropHandler(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::DragEventArgs const e); + winrt::fire_and_forget _DragDropHandler(Windows::Foundation::IInspectable sender, Windows::UI::Xaml::DragEventArgs e); void _DragOverHandler(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::DragEventArgs const& e); - winrt::fire_and_forget _HyperlinkHandler(Windows::Foundation::IInspectable const& sender, Control::OpenHyperlinkEventArgs const& e); + winrt::fire_and_forget _HyperlinkHandler(Windows::Foundation::IInspectable sender, Control::OpenHyperlinkEventArgs e); void _CursorTimerTick(Windows::Foundation::IInspectable const& sender, Windows::Foundation::IInspectable const& e); void _BlinkTimerTick(Windows::Foundation::IInspectable const& sender, Windows::Foundation::IInspectable const& e); @@ -237,12 +237,12 @@ namespace winrt::Microsoft::Terminal::Control::implementation void _CurrentCursorPositionHandler(const IInspectable& sender, const CursorPositionEventArgs& eventArgs); void _FontInfoHandler(const IInspectable& sender, const FontInfoEventArgs& eventArgs); - winrt::fire_and_forget _hoveredHyperlinkChanged(const IInspectable& sender, const IInspectable& args); + winrt::fire_and_forget _hoveredHyperlinkChanged(IInspectable sender, IInspectable args); void _coreFontSizeChanged(const int fontWidth, const int fontHeight, const bool isInitialChange); - winrt::fire_and_forget _coreTransparencyChanged(const IInspectable& sender, const Control::TransparencyChangedEventArgs& args); + winrt::fire_and_forget _coreTransparencyChanged(IInspectable sender, Control::TransparencyChangedEventArgs args); void _coreReceivedOutput(const IInspectable& sender, const IInspectable& args); void _coreRaisedNotice(const IInspectable& s, const Control::NoticeEventArgs& args); void _coreWarningBell(const IInspectable& sender, const IInspectable& args); diff --git a/src/cascadia/UnitTests_Control/ControlInteractivityTests.cpp b/src/cascadia/UnitTests_Control/ControlInteractivityTests.cpp index b2965e6070c..f5b3602f096 100644 --- a/src/cascadia/UnitTests_Control/ControlInteractivityTests.cpp +++ b/src/cascadia/UnitTests_Control/ControlInteractivityTests.cpp @@ -150,7 +150,7 @@ namespace ControlUnitTests void ControlInteractivityTests::TestPanWithTouch() { - VERIFY_IS_TRUE(false); + VERIFY_IS_TRUE(false, L"TODO: Implement this test"); } void ControlInteractivityTests::TestScrollWithMouse() { From 0d78c169a7ed656c7466bdf34137cb860e125e14 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Wed, 21 Apr 2021 06:00:08 -0500 Subject: [PATCH 69/82] some minor renames --- .../TerminalControl/ControlInteractivity.cpp | 2 +- .../TerminalControl/ControlInteractivity.h | 5 ++++- src/cascadia/TerminalControl/TermControl.cpp | 19 +++++++------------ src/cascadia/TerminalControl/TermControl.h | 2 +- 4 files changed, 13 insertions(+), 15 deletions(-) diff --git a/src/cascadia/TerminalControl/ControlInteractivity.cpp b/src/cascadia/TerminalControl/ControlInteractivity.cpp index 1757fa3fa4a..ea461416c48 100644 --- a/src/cascadia/TerminalControl/ControlInteractivity.cpp +++ b/src/cascadia/TerminalControl/ControlInteractivity.cpp @@ -230,7 +230,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation } } - void ControlInteractivity::Touched(const winrt::Windows::Foundation::Point contactPoint) + void ControlInteractivity::TouchPressed(const winrt::Windows::Foundation::Point contactPoint) { _touchAnchor = contactPoint; } diff --git a/src/cascadia/TerminalControl/ControlInteractivity.h b/src/cascadia/TerminalControl/ControlInteractivity.h index c4207365971..4d0877f3aad 100644 --- a/src/cascadia/TerminalControl/ControlInteractivity.h +++ b/src/cascadia/TerminalControl/ControlInteractivity.h @@ -55,7 +55,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation const ::Microsoft::Terminal::Core::ControlKeyStates modifiers, const bool focused, const til::point terminalPosition); - void Touched(const winrt::Windows::Foundation::Point contactPoint); + void TouchPressed(const winrt::Windows::Foundation::Point contactPoint); + void PointerMoved(const winrt::Windows::Foundation::Point mouseCursorPosition, ::Microsoft::Console::VirtualTerminal::TerminalInput::MouseButtonState buttonState, const unsigned int pointerUpdateKind, @@ -64,12 +65,14 @@ namespace winrt::Microsoft::Terminal::Control::implementation const til::point terminalPosition); void TouchMoved(const winrt::Windows::Foundation::Point newTouchPoint, const bool focused); + void PointerReleased(::Microsoft::Console::VirtualTerminal::TerminalInput::MouseButtonState buttonState, const unsigned int pointerUpdateKind, const ::Microsoft::Terminal::Core::ControlKeyStates modifiers, const bool focused, const til::point terminalPosition); void TouchReleased(); + bool MouseWheel(const ::Microsoft::Terminal::Core::ControlKeyStates modifiers, const int32_t delta, const til::point terminalPosition, diff --git a/src/cascadia/TerminalControl/TermControl.cpp b/src/cascadia/TerminalControl/TermControl.cpp index 5ba58c2f752..5ed9ea802aa 100644 --- a/src/cascadia/TerminalControl/TermControl.cpp +++ b/src/cascadia/TerminalControl/TermControl.cpp @@ -1054,13 +1054,13 @@ namespace winrt::Microsoft::Terminal::Control::implementation { const auto contactRect = point.Properties().ContactRect(); auto anchor = winrt::Windows::Foundation::Point{ contactRect.X, contactRect.Y }; - _interactivity->Touched(anchor); + _interactivity->TouchPressed(anchor); } else { _interactivity->PointerPressed(cursorPosition, TermControl::GetPressedMouseButtons(point), - TermControl::PointerToMouseButtons(point), + TermControl::GetPointerUpdateKind(point), point.Timestamp(), ControlKeyStates{ args.KeyModifiers() }, _focused, @@ -1101,7 +1101,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation { _interactivity->PointerMoved(cursorPosition, TermControl::GetPressedMouseButtons(point), - TermControl::PointerToMouseButtons(point), + TermControl::GetPointerUpdateKind(point), ControlKeyStates(args.KeyModifiers()), _focused, terminalPosition); @@ -1169,7 +1169,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation type == Windows::Devices::Input::PointerDeviceType::Pen) { _interactivity->PointerReleased(TermControl::GetPressedMouseButtons(point), - TermControl::PointerToMouseButtons(point), + TermControl::GetPointerUpdateKind(point), ControlKeyStates(args.KeyModifiers()), _focused, terminalPosition); @@ -1203,16 +1203,11 @@ namespace winrt::Microsoft::Terminal::Control::implementation _RestorePointerCursorHandlers(*this, nullptr); const auto point = args.GetCurrentPoint(*this); - const auto props = point.Properties(); - const TerminalInput::MouseButtonState state{ props.IsLeftButtonPressed(), - props.IsMiddleButtonPressed(), - props.IsRightButtonPressed() }; - auto mousePosition = point.Position(); auto result = _interactivity->MouseWheel(ControlKeyStates{ args.KeyModifiers() }, point.Properties().MouseWheelDelta(), - _GetTerminalPosition(mousePosition), - state); + _GetTerminalPosition(point.Position()), + TermControl::GetPressedMouseButtons(point)); if (result) { args.Handled(true); @@ -2459,7 +2454,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation point.Properties().IsRightButtonPressed() }; } - unsigned int TermControl::PointerToMouseButtons(const winrt::Windows::UI::Input::PointerPoint point) + unsigned int TermControl::GetPointerUpdateKind(const winrt::Windows::UI::Input::PointerPoint point) { const auto props = point.Properties(); diff --git a/src/cascadia/TerminalControl/TermControl.h b/src/cascadia/TerminalControl/TermControl.h index eabec66a84e..343aa55420d 100644 --- a/src/cascadia/TerminalControl/TermControl.h +++ b/src/cascadia/TerminalControl/TermControl.h @@ -102,7 +102,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation void ToggleReadOnly(); static ::Microsoft::Console::VirtualTerminal::TerminalInput::MouseButtonState GetPressedMouseButtons(const winrt::Windows::UI::Input::PointerPoint point); - static unsigned int PointerToMouseButtons(const winrt::Windows::UI::Input::PointerPoint point); + static unsigned int GetPointerUpdateKind(const winrt::Windows::UI::Input::PointerPoint point); // -------------------------------- WinRT Events --------------------------------- // clang-format off From e2499a48f2c1263735d34515bd6770810f3983d5 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Wed, 21 Apr 2021 08:47:48 -0500 Subject: [PATCH 70/82] Change the paste handler to a wstring_view --- src/cascadia/TerminalControl/ControlInteractivity.cpp | 2 +- src/cascadia/TerminalControl/ControlInteractivity.h | 2 +- src/cascadia/TerminalControl/EventArgs.h | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/cascadia/TerminalControl/ControlInteractivity.cpp b/src/cascadia/TerminalControl/ControlInteractivity.cpp index ea461416c48..82233457fcc 100644 --- a/src/cascadia/TerminalControl/ControlInteractivity.cpp +++ b/src/cascadia/TerminalControl/ControlInteractivity.cpp @@ -146,7 +146,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation // Method Description: // - Pre-process text pasted (presumably from the clipboard) // before sending it over the terminal's connection. - void ControlInteractivity::_sendPastedTextToConnection(const std::wstring& wstr) + void ControlInteractivity::_sendPastedTextToConnection(std::wstring_view wstr) { _core->PasteText(winrt::hstring{ wstr }); } diff --git a/src/cascadia/TerminalControl/ControlInteractivity.h b/src/cascadia/TerminalControl/ControlInteractivity.h index 4d0877f3aad..ef382c2487d 100644 --- a/src/cascadia/TerminalControl/ControlInteractivity.h +++ b/src/cascadia/TerminalControl/ControlInteractivity.h @@ -135,7 +135,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation void _hyperlinkHandler(const std::wstring_view uri); bool _canSendVTMouseInput(const ::Microsoft::Terminal::Core::ControlKeyStates modifiers); - void _sendPastedTextToConnection(const std::wstring& wstr); + void _sendPastedTextToConnection(std::wstring_view wstr); void _updateScrollbar(const int newValue); TYPED_EVENT(OpenHyperlink, IInspectable, Control::OpenHyperlinkEventArgs); diff --git a/src/cascadia/TerminalControl/EventArgs.h b/src/cascadia/TerminalControl/EventArgs.h index 3d1db166238..92b60f393d1 100644 --- a/src/cascadia/TerminalControl/EventArgs.h +++ b/src/cascadia/TerminalControl/EventArgs.h @@ -54,16 +54,16 @@ namespace winrt::Microsoft::Terminal::Control::implementation struct PasteFromClipboardEventArgs : public PasteFromClipboardEventArgsT { public: - PasteFromClipboardEventArgs(std::function clipboardDataHandler) : + PasteFromClipboardEventArgs(std::function clipboardDataHandler) : m_clipboardDataHandler(clipboardDataHandler) {} void HandleClipboardData(hstring value) { - m_clipboardDataHandler(static_cast(value)); + m_clipboardDataHandler(value); }; private: - std::function m_clipboardDataHandler; + std::function m_clipboardDataHandler; }; struct OpenHyperlinkEventArgs : public OpenHyperlinkEventArgsT From 03949ac48beb569df0be6c603e308154b65cd5df Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Wed, 21 Apr 2021 08:51:09 -0500 Subject: [PATCH 71/82] get rid of unnecessary `focused` param --- .../TerminalControl/ControlInteractivity.cpp | 26 ------------------- .../TerminalControl/ControlInteractivity.h | 1 - src/cascadia/TerminalControl/TermControl.cpp | 1 - .../ControlInteractivityTests.cpp | 2 -- 4 files changed, 30 deletions(-) diff --git a/src/cascadia/TerminalControl/ControlInteractivity.cpp b/src/cascadia/TerminalControl/ControlInteractivity.cpp index 82233457fcc..406273de3cd 100644 --- a/src/cascadia/TerminalControl/ControlInteractivity.cpp +++ b/src/cascadia/TerminalControl/ControlInteractivity.cpp @@ -156,7 +156,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation const unsigned int pointerUpdateKind, const uint64_t timestamp, const ::Microsoft::Terminal::Core::ControlKeyStates modifiers, - const bool /*focused*/, const til::point terminalPosition) { const auto altEnabled = modifiers.IsAltPressed(); @@ -267,31 +266,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation } SetEndSelectionPoint(terminalPosition); - - // TODO: Make sure this still works - // - // const double cursorBelowBottomDist = cursorPosition.Y - SwapChainPanel().Margin().Top - SwapChainPanel().ActualHeight(); - // const double cursorAboveTopDist = -1 * cursorPosition.Y + SwapChainPanel().Margin().Top; - - // constexpr double MinAutoScrollDist = 2.0; // Arbitrary value - // double newAutoScrollVelocity = 0.0; - // if (cursorBelowBottomDist > MinAutoScrollDist) - // { - // newAutoScrollVelocity = _getAutoScrollSpeed(cursorBelowBottomDist); - // } - // else if (cursorAboveTopDist > MinAutoScrollDist) - // { - // newAutoScrollVelocity = -1.0 * _getAutoScrollSpeed(cursorAboveTopDist); - // } - - // if (newAutoScrollVelocity != 0) - // { - // _tryStartAutoScroll(point, newAutoScrollVelocity); - // } - // else - // { - // _tryStopAutoScroll(ptr.PointerId()); - // } } _core->UpdateHoveredCell(terminalPosition); diff --git a/src/cascadia/TerminalControl/ControlInteractivity.h b/src/cascadia/TerminalControl/ControlInteractivity.h index ef382c2487d..0c9b5e876c7 100644 --- a/src/cascadia/TerminalControl/ControlInteractivity.h +++ b/src/cascadia/TerminalControl/ControlInteractivity.h @@ -53,7 +53,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation const unsigned int pointerUpdateKind, const uint64_t timestamp, const ::Microsoft::Terminal::Core::ControlKeyStates modifiers, - const bool focused, const til::point terminalPosition); void TouchPressed(const winrt::Windows::Foundation::Point contactPoint); diff --git a/src/cascadia/TerminalControl/TermControl.cpp b/src/cascadia/TerminalControl/TermControl.cpp index 5ed9ea802aa..f2aee0f4698 100644 --- a/src/cascadia/TerminalControl/TermControl.cpp +++ b/src/cascadia/TerminalControl/TermControl.cpp @@ -1063,7 +1063,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation TermControl::GetPointerUpdateKind(point), point.Timestamp(), ControlKeyStates{ args.KeyModifiers() }, - _focused, _GetTerminalPosition(cursorPosition)); } diff --git a/src/cascadia/UnitTests_Control/ControlInteractivityTests.cpp b/src/cascadia/UnitTests_Control/ControlInteractivityTests.cpp index f5b3602f096..51ce872e26d 100644 --- a/src/cascadia/UnitTests_Control/ControlInteractivityTests.cpp +++ b/src/cascadia/UnitTests_Control/ControlInteractivityTests.cpp @@ -267,7 +267,6 @@ namespace ControlUnitTests WM_LBUTTONDOWN, //pointerUpdateKind 0, // timestamp modifiers, - true, // focused, terminalPosition0); Log::Comment(L"Verify that there's not yet a selection"); @@ -318,7 +317,6 @@ namespace ControlUnitTests WM_LBUTTONDOWN, //pointerUpdateKind 0, // timestamp modifiers, - true, // focused, terminalPosition3); Log::Comment(L"Verify that there's now no selection"); VERIFY_IS_FALSE(core->HasSelection()); From 85fc41a824cd069504ecdc679bf7bc17cea93e82 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Wed, 21 Apr 2021 09:12:26 -0500 Subject: [PATCH 72/82] A pile of nits --- src/cascadia/TerminalControl/ControlCore.cpp | 47 +++++++++---------- src/cascadia/TerminalControl/ControlCore.h | 26 +++++----- .../TerminalControl/ControlInteractivity.cpp | 4 +- .../TerminalControl/ControlInteractivity.h | 2 +- src/cascadia/TerminalControl/TermControl.cpp | 19 ++++---- src/cascadia/TerminalCore/Terminal.cpp | 4 +- src/cascadia/TerminalCore/Terminal.hpp | 8 ++-- .../UnitTests_Control/ControlCoreTests.cpp | 7 ++- .../ControlInteractivityTests.cpp | 5 +- 9 files changed, 56 insertions(+), 66 deletions(-) diff --git a/src/cascadia/TerminalControl/ControlCore.cpp b/src/cascadia/TerminalControl/ControlCore.cpp index ac88139c24e..a78b275d20f 100644 --- a/src/cascadia/TerminalControl/ControlCore.cpp +++ b/src/cascadia/TerminalControl/ControlCore.cpp @@ -116,15 +116,13 @@ namespace winrt::Microsoft::Terminal::Control::implementation Close(); } - bool ControlCore::InitializeTerminal(const double actualWidth, - const double actualHeight, - const double compositionScaleX, - const double compositionScaleY) + bool ControlCore::Initialize(const double actualWidth, + const double actualHeight, + const double compositionScale) { _panelWidth = actualWidth; _panelHeight = actualHeight; - _compositionScaleX = compositionScaleX; - _compositionScaleY = compositionScaleY; + _compositionScale = compositionScale; { // scope for terminalLock auto terminalLock = _terminal->LockForWriting(); @@ -134,8 +132,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation return false; } - const auto windowWidth = actualWidth * compositionScaleX; - const auto windowHeight = actualHeight * compositionScaleY; + const auto windowWidth = actualWidth * compositionScale; + const auto windowHeight = actualHeight * compositionScale; if (windowWidth == 0 || windowHeight == 0) { @@ -340,7 +338,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation return handled; } - bool ControlCore::SendMouseEvent(const COORD viewportPos, + bool ControlCore::SendMouseEvent(const til::point viewportPos, const unsigned int uiButton, const ControlKeyStates states, const short wheelDelta, @@ -433,7 +431,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation // - Updates last hovered cell, renders / removes rendering of hyper-link if required // Arguments: // - terminalPosition: The terminal position of the pointer - void ControlCore::UpdateHoveredCell(const std::optional& terminalPosition) + void ControlCore::UpdateHoveredCell(const std::optional& terminalPosition) { if (terminalPosition == _lastHoveredCell) { @@ -445,7 +443,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation _lastHoveredCell = terminalPosition; uint16_t newId{ 0u }; // we can't use auto here because we're pre-declaring newInterval. - decltype(_terminal->GetHyperlinkIntervalFromPosition(COORD{})) newInterval{ std::nullopt }; + decltype(_terminal->GetHyperlinkIntervalFromPosition(til::point{})) newInterval{ std::nullopt }; if (terminalPosition.has_value()) { auto lock = _terminal->LockForReading(); // Lock for the duration of our reads. @@ -493,7 +491,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation return { L"" }; } - std::optional ControlCore::GetHoveredCell() const + std::optional ControlCore::GetHoveredCell() const { return _lastHoveredCell; } @@ -543,7 +541,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation } } - void ControlCore::UpdateAppearance(IControlAppearance newAppearance) + void ControlCore::UpdateAppearance(const IControlAppearance& newAppearance) { // Update the terminal core with its new Core settings _terminal->UpdateAppearance(newAppearance); @@ -590,7 +588,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation void ControlCore::_updateFont(const bool initialUpdate) { const int newDpi = static_cast(static_cast(USER_DEFAULT_SCREEN_DPI) * - _compositionScaleX); + _compositionScale); // TODO: MSFT:20895307 If the font doesn't exist, this doesn't // actually fail. We need a way to gracefully fallback. @@ -675,8 +673,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation // - void ControlCore::_refreshSizeUnderLock() { - const auto widthInPixels = _panelWidth * _compositionScaleX; - const auto heightInPixels = _panelHeight * _compositionScaleY; + const auto widthInPixels = _panelWidth * _compositionScale; + const auto heightInPixels = _panelHeight * _compositionScale; _doResizeUnderLock(widthInPixels, heightInPixels); } @@ -739,33 +737,30 @@ namespace winrt::Microsoft::Terminal::Control::implementation _doResizeUnderLock(scaledWidth, scaledHeight); } - void ControlCore::ScaleChanged(const double scaleX, - const double scaleY) + void ControlCore::ScaleChanged(const double scale) { if (!_renderEngine) { return; } - _compositionScaleX = scaleX; - _compositionScaleY = scaleY; - const auto currentEngineScale = _renderEngine->GetScaling(); // If we're getting a notification to change to the DPI we already // have, then we're probably just beginning the DPI change. Since // we'll get _another_ event with the real DPI, do nothing here for // now. We'll also skip the next resize in _swapChainSizeChanged. - const bool dpiWasUnchanged = currentEngineScale == scaleX; + const bool dpiWasUnchanged = currentEngineScale == scale; if (dpiWasUnchanged) { return; } - const auto dpi = (float)(scaleX * USER_DEFAULT_SCREEN_DPI); + const auto dpi = (float)(scale * USER_DEFAULT_SCREEN_DPI); const auto actualFontOldSize = _actualFont.GetSize(); auto lock = _terminal->LockForWriting(); + _compositionScale = scale; _renderer->TriggerFontChange(::base::saturated_cast(dpi), _desiredFont, @@ -816,7 +811,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation // Called when the Terminal wants to set something to the clipboard, i.e. // when an OSC 52 is emitted. - void ControlCore::_terminalCopyToClipboard(const std::wstring_view& wstr) + void ControlCore::_terminalCopyToClipboard(std::wstring_view wstr) { auto copyArgs = winrt::make_self(winrt::hstring(wstr)); _CopyToClipboardHandlers(*this, *copyArgs); @@ -901,7 +896,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation til::size ControlCore::FontSizeInDips() const { const til::size fontSize{ GetFont().GetSize() }; - return fontSize.scale(til::math::rounding, 1.0f / ::base::saturated_cast(_compositionScaleX)); + return fontSize.scale(til::math::rounding, 1.0f / ::base::saturated_cast(_compositionScale)); } TerminalConnection::ConnectionState ControlCore::ConnectionState() const @@ -996,7 +991,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation // - wstr: the new title of this terminal. // Return Value: // - - void ControlCore::_terminalTitleChanged(const std::wstring_view& wstr) + void ControlCore::_terminalTitleChanged(std::wstring_view wstr) { auto titleArgs = winrt::make_self(winrt::hstring{ wstr }); _TitleChangedHandlers(*this, *titleArgs); diff --git a/src/cascadia/TerminalControl/ControlCore.h b/src/cascadia/TerminalControl/ControlCore.h index 29ce4a532c3..162223ddb7a 100644 --- a/src/cascadia/TerminalControl/ControlCore.h +++ b/src/cascadia/TerminalControl/ControlCore.h @@ -40,15 +40,14 @@ namespace winrt::Microsoft::Terminal::Control::implementation TerminalConnection::ITerminalConnection connection); ~ControlCore(); - bool InitializeTerminal(const double actualWidth, - const double actualHeight, - const double compositionScaleX, - const double compositionScaleY); + bool Initialize(const double actualWidth, + const double actualHeight, + const double compositionScale); void UpdateSettings(const IControlSettings& settings); - void UpdateAppearance(IControlAppearance newAppearance); + void UpdateAppearance(const IControlAppearance& newAppearance); void SizeChanged(const double width, const double height); - void ScaleChanged(const double scaleX, const double scaleY); + void ScaleChanged(const double scale); IDXGISwapChain1* GetSwapChain() const; void AdjustFontSize(int fontSizeDelta); @@ -68,10 +67,10 @@ namespace winrt::Microsoft::Terminal::Control::implementation void ResumeRendering(); void UpdatePatternLocations(); - void UpdateHoveredCell(const std::optional& terminalPosition); + void UpdateHoveredCell(const std::optional& terminalPosition); winrt::hstring GetHyperlink(const til::point position) const; winrt::hstring GetHoveredUriText() const; - std::optional GetHoveredCell() const; + std::optional GetHoveredCell() const; ::Microsoft::Console::Types::IUiaData* GetUiaData() const; @@ -103,7 +102,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation bool SendCharEvent(const wchar_t ch, const WORD scanCode, const ::Microsoft::Terminal::Core::ControlKeyStates modifiers); - bool SendMouseEvent(const COORD viewportPos, + bool SendMouseEvent(const til::point viewportPos, const unsigned int uiButton, const ::Microsoft::Terminal::Core::ControlKeyStates states, const short wheelDelta, @@ -184,7 +183,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation // storage location for the leading surrogate of a utf-16 surrogate pair std::optional _leadingSurrogate{ std::nullopt }; - std::optional _lastHoveredCell{ std::nullopt }; + std::optional _lastHoveredCell{ std::nullopt }; // Track the last hyperlink ID we hovered over uint16_t _lastHoveredId{ 0 }; @@ -196,8 +195,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation // rendering to. double _panelWidth{ 0 }; double _panelHeight{ 0 }; - double _compositionScaleX{ 0 }; - double _compositionScaleY{ 0 }; + double _compositionScale{ 0 }; winrt::fire_and_forget _asyncCloseConnection(); @@ -211,9 +209,9 @@ namespace winrt::Microsoft::Terminal::Control::implementation void _sendInputToConnection(std::wstring_view wstr); #pragma region TerminalCoreCallbacks - void _terminalCopyToClipboard(const std::wstring_view& wstr); + void _terminalCopyToClipboard(std::wstring_view wstr); void _terminalWarningBell(); - void _terminalTitleChanged(const std::wstring_view& wstr); + void _terminalTitleChanged(std::wstring_view wstr); void _terminalTabColorChanged(const std::optional color); void _terminalBackgroundColorChanged(const COLORREF color); void _terminalScrollPositionChanged(const int viewTop, diff --git a/src/cascadia/TerminalControl/ControlInteractivity.cpp b/src/cascadia/TerminalControl/ControlInteractivity.cpp index 406273de3cd..12db114d576 100644 --- a/src/cascadia/TerminalControl/ControlInteractivity.cpp +++ b/src/cascadia/TerminalControl/ControlInteractivity.cpp @@ -131,7 +131,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation // Method Description: // - Initiate a paste operation. - void ControlInteractivity::PasteTextFromClipboard() + void ControlInteractivity::RequestPasteTextFromClipboard() { // attach ControlInteractivity::_sendPastedTextToConnection() as the // clipboardDataHandler. This is called when the clipboard data is @@ -220,7 +220,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation // CopyOnSelect right click always pastes if (_core->CopyOnSelect() || !_core->HasSelection()) { - PasteTextFromClipboard(); + RequestPasteTextFromClipboard(); } else { diff --git a/src/cascadia/TerminalControl/ControlInteractivity.h b/src/cascadia/TerminalControl/ControlInteractivity.h index 0c9b5e876c7..6c8915aa801 100644 --- a/src/cascadia/TerminalControl/ControlInteractivity.h +++ b/src/cascadia/TerminalControl/ControlInteractivity.h @@ -80,7 +80,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation bool CopySelectionToClipboard(bool singleLine, const Windows::Foundation::IReference& formats); - void PasteTextFromClipboard(); + void RequestPasteTextFromClipboard(); void SetEndSelectionPoint(const til::point terminalPosition); private: diff --git a/src/cascadia/TerminalControl/TermControl.cpp b/src/cascadia/TerminalControl/TermControl.cpp index f2aee0f4698..0890df783c0 100644 --- a/src/cascadia/TerminalControl/TermControl.cpp +++ b/src/cascadia/TerminalControl/TermControl.cpp @@ -143,7 +143,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation scrollBar.Maximum(update.newMaximum); scrollBar.Minimum(update.newMinimum); scrollBar.ViewportSize(update.newViewportSize); - scrollBar.LargeChange(std::max(update.newViewportSize - 1, 0.)); // scroll one "screenful" at a time when the scroll bar is clicked + // scroll one full screen worth at a time when the scroll bar is clicked + scrollBar.LargeChange(std::max(update.newViewportSize - 1, 0.)); control->_isInternalScrollBarUpdate = false; } @@ -654,10 +655,9 @@ namespace winrt::Microsoft::Terminal::Control::implementation // the first paint will be ignored! _core->RendererWarning({ get_weak(), &TermControl::_RendererWarning }); - const auto coreInitialized = _core->InitializeTerminal(panelWidth, - panelHeight, - panelScaleX, - panelScaleY); + const auto coreInitialized = _core->Initialize(panelWidth, + panelHeight, + panelScaleX); if (!coreInitialized) { return false; @@ -1585,9 +1585,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation Windows::Foundation::IInspectable const& /*args*/) { const auto scaleX = sender.CompositionScaleX(); - const auto scaleY = sender.CompositionScaleY(); - _core->ScaleChanged(scaleX, scaleY); + _core->ScaleChanged(scaleX); } // Method Description: @@ -1711,7 +1710,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation // - Initiate a paste operation. void TermControl::PasteTextFromClipboard() { - _interactivity->PasteTextFromClipboard(); + _interactivity->RequestPasteTextFromClipboard(); } void TermControl::Close() @@ -2416,8 +2415,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation // Compute the location of the top left corner of the cell in DIPS const til::size marginsInDips{ til::math::rounding, GetPadding().Left, GetPadding().Top }; - const til::point startPos{ lastHoveredCell->X, - lastHoveredCell->Y }; + const til::point startPos{ lastHoveredCell->x(), + lastHoveredCell->y() }; const til::size fontSize{ _core->GetFont().GetSize() }; const til::point posInPixels{ startPos * fontSize }; const til::point posInDIPs{ posInPixels / SwapChainPanel().CompositionScaleX() }; diff --git a/src/cascadia/TerminalCore/Terminal.cpp b/src/cascadia/TerminalCore/Terminal.cpp index d11efd7acaa..596fcf6de7e 100644 --- a/src/cascadia/TerminalCore/Terminal.cpp +++ b/src/cascadia/TerminalCore/Terminal.cpp @@ -1110,7 +1110,7 @@ void Terminal::SetWarningBellCallback(std::function pfn) noexcept _pfnWarningBell.swap(pfn); } -void Terminal::SetTitleChangedCallback(std::function pfn) noexcept +void Terminal::SetTitleChangedCallback(std::function pfn) noexcept { _pfnTitleChanged.swap(pfn); } @@ -1120,7 +1120,7 @@ void Terminal::SetTabColorChangedCallback(std::function pfn) noexcept +void Terminal::SetCopyToClipboardCallback(std::function pfn) noexcept { _pfnCopyToClipboard.swap(pfn); } diff --git a/src/cascadia/TerminalCore/Terminal.hpp b/src/cascadia/TerminalCore/Terminal.hpp index 6630e7027ce..6bbfdd19697 100644 --- a/src/cascadia/TerminalCore/Terminal.hpp +++ b/src/cascadia/TerminalCore/Terminal.hpp @@ -196,9 +196,9 @@ class Microsoft::Terminal::Core::Terminal final : void SetWriteInputCallback(std::function pfn) noexcept; void SetWarningBellCallback(std::function pfn) noexcept; - void SetTitleChangedCallback(std::function pfn) noexcept; + void SetTitleChangedCallback(std::function pfn) noexcept; void SetTabColorChangedCallback(std::function)> pfn) noexcept; - void SetCopyToClipboardCallback(std::function pfn) noexcept; + void SetCopyToClipboardCallback(std::function pfn) noexcept; void SetScrollPositionChangedCallback(std::function pfn) noexcept; void SetCursorPositionChangedCallback(std::function pfn) noexcept; void SetBackgroundCallback(std::function pfn) noexcept; @@ -237,8 +237,8 @@ class Microsoft::Terminal::Core::Terminal final : private: std::function _pfnWriteInput; std::function _pfnWarningBell; - std::function _pfnTitleChanged; - std::function _pfnCopyToClipboard; + std::function _pfnTitleChanged; + std::function _pfnCopyToClipboard; std::function _pfnScrollPositionChanged; std::function _pfnBackgroundColorChanged; std::function _pfnCursorPositionChanged; diff --git a/src/cascadia/UnitTests_Control/ControlCoreTests.cpp b/src/cascadia/UnitTests_Control/ControlCoreTests.cpp index 3c8bb7bd93f..0b60410ae0b 100644 --- a/src/cascadia/UnitTests_Control/ControlCoreTests.cpp +++ b/src/cascadia/UnitTests_Control/ControlCoreTests.cpp @@ -19,8 +19,7 @@ namespace ControlUnitTests { class ControlCoreTests { - BEGIN_TEST_CLASS(ControlCoreTests) - END_TEST_CLASS() + TEST_CLASS(ControlCoreTests) TEST_METHOD(ComPtrSettings); TEST_METHOD(InstantiateCore); @@ -81,7 +80,7 @@ namespace ControlUnitTests VERIFY_IS_FALSE(core->_initializedTerminal); // "Cascadia Mono" ends up with an actual size of 9x19 at 96DPI. So // let's just arbitrarily start with a 270x380px (30x20 chars) window - core->InitializeTerminal(270, 380, 1.0, 1.0); + core->Initialize(270, 380, 1.0); VERIFY_IS_TRUE(core->_initializedTerminal); VERIFY_ARE_EQUAL(30, core->_terminal->GetViewport().Width()); } @@ -117,7 +116,7 @@ namespace ControlUnitTests VERIFY_IS_FALSE(core->_initializedTerminal); // "Cascadia Mono" ends up with an actual size of 9x19 at 96DPI. So // let's just arbitrarily start with a 270x380px (30x20 chars) window - core->InitializeTerminal(270, 380, 1.0, 1.0); + core->Initialize(270, 380, 1.0); VERIFY_IS_TRUE(core->_initializedTerminal); Log::Comment(L"Increasing opacity till fully opaque"); diff --git a/src/cascadia/UnitTests_Control/ControlInteractivityTests.cpp b/src/cascadia/UnitTests_Control/ControlInteractivityTests.cpp index 51ce872e26d..7a3f4f359ff 100644 --- a/src/cascadia/UnitTests_Control/ControlInteractivityTests.cpp +++ b/src/cascadia/UnitTests_Control/ControlInteractivityTests.cpp @@ -21,8 +21,7 @@ namespace ControlUnitTests { class ControlInteractivityTests { - BEGIN_TEST_CLASS(ControlInteractivityTests) - END_TEST_CLASS() + TEST_CLASS(ControlInteractivityTests) TEST_METHOD(TestAdjustAcrylic); TEST_METHOD(TestPanWithTouch); @@ -71,7 +70,7 @@ namespace ControlUnitTests { // "Cascadia Mono" ends up with an actual size of 9x19 at 96DPI. So // let's just arbitrarily start with a 270x380px (30x20 chars) window - core->InitializeTerminal(270, 380, 1.0, 1.0); + core->Initialize(270, 380, 1.0); VERIFY_IS_TRUE(core->_initializedTerminal); VERIFY_ARE_EQUAL(20, core->_terminal->GetViewport().Height()); interactivity->Initialize(); From e6f93bac9e2ab360846c1bb1b06fec8e9af632a5 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Wed, 21 Apr 2021 09:35:12 -0500 Subject: [PATCH 73/82] a TON of `til::point`s --- src/cascadia/TerminalControl/ControlCore.cpp | 2 +- src/cascadia/TerminalControl/ControlCore.h | 6 +++--- .../TerminalControl/ControlInteractivity.cpp | 18 ++++++++++-------- .../TerminalControl/ControlInteractivity.h | 18 +++++++++--------- .../TerminalControl/ControlInteractivity.idl | 2 +- src/cascadia/TerminalControl/TermControl.cpp | 10 +++++----- 6 files changed, 29 insertions(+), 27 deletions(-) diff --git a/src/cascadia/TerminalControl/ControlCore.cpp b/src/cascadia/TerminalControl/ControlCore.cpp index a78b275d20f..4698b01b0c7 100644 --- a/src/cascadia/TerminalControl/ControlCore.cpp +++ b/src/cascadia/TerminalControl/ControlCore.cpp @@ -173,7 +173,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation const COORD windowSize{ static_cast(windowWidth), static_cast(windowHeight) }; - // Fist set up the dx engine with the window size in pixels. + // First set up the dx engine with the window size in pixels. // Then, using the font, get the number of characters that can fit. // Resize our terminal connection to match that size, and initialize the terminal with that size. const auto viewInPixels = Viewport::FromDimensions({ 0, 0 }, windowSize); diff --git a/src/cascadia/TerminalControl/ControlCore.h b/src/cascadia/TerminalControl/ControlCore.h index 162223ddb7a..f5ee458f0f2 100644 --- a/src/cascadia/TerminalControl/ControlCore.h +++ b/src/cascadia/TerminalControl/ControlCore.h @@ -6,9 +6,9 @@ // // Abstract: // - This encapsulates a `Terminal` instance, a `DxEngine` and `Renderer`, and -// an `ITerminalConnection`. This is intended to everything that someone might -// need to stand up a terminal instance in a control, but without any regard -// for how the UX works. +// an `ITerminalConnection`. This is intended to be everything that someone +// might need to stand up a terminal instance in a control, but without any +// regard for how the UX works. // // Author: // - Mike Griese (zadjii-msft) 01-Apr-2021 diff --git a/src/cascadia/TerminalControl/ControlInteractivity.cpp b/src/cascadia/TerminalControl/ControlInteractivity.cpp index 12db114d576..b7dc55d0bf7 100644 --- a/src/cascadia/TerminalControl/ControlInteractivity.cpp +++ b/src/cascadia/TerminalControl/ControlInteractivity.cpp @@ -63,7 +63,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation // Return Value: // - if the click is in the same position as the last click and within the timeout, the number of clicks within that time window // - otherwise, 1 - unsigned int ControlInteractivity::_numberOfClicks(winrt::Windows::Foundation::Point clickPos, + unsigned int ControlInteractivity::_numberOfClicks(til::point clickPos, Timestamp clickTime) { // if click occurred at a different location or past the multiClickTimer... @@ -151,7 +151,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation _core->PasteText(winrt::hstring{ wstr }); } - void ControlInteractivity::PointerPressed(const winrt::Windows::Foundation::Point mouseCursorPosition, + void ControlInteractivity::PointerPressed(const til::point mouseCursorPosition, TerminalInput::MouseButtonState buttonState, const unsigned int pointerUpdateKind, const uint64_t timestamp, @@ -229,12 +229,12 @@ namespace winrt::Microsoft::Terminal::Control::implementation } } - void ControlInteractivity::TouchPressed(const winrt::Windows::Foundation::Point contactPoint) + void ControlInteractivity::TouchPressed(const til::point contactPoint) { _touchAnchor = contactPoint; } - void ControlInteractivity::PointerMoved(const winrt::Windows::Foundation::Point mouseCursorPosition, + void ControlInteractivity::PointerMoved(const til::point mouseCursorPosition, TerminalInput::MouseButtonState buttonState, const unsigned int pointerUpdateKind, const ::Microsoft::Terminal::Core::ControlKeyStates modifiers, @@ -252,8 +252,10 @@ namespace winrt::Microsoft::Terminal::Control::implementation { // Figure out if the user's moved a quarter of a cell's smaller axis away from the clickdown point auto& touchdownPoint{ *_singleClickTouchdownPos }; - auto distance{ std::sqrtf(std::powf(mouseCursorPosition.X - touchdownPoint.X, 2) + - std::powf(mouseCursorPosition.Y - touchdownPoint.Y, 2)) }; + float dx = ::base::saturated_cast(mouseCursorPosition.x() - touchdownPoint.x()); + float dy = ::base::saturated_cast(mouseCursorPosition.y() - touchdownPoint.y()); + auto distance{ std::sqrtf(std::powf(dx, 2) + + std::powf(dy, 2)) }; const auto fontSizeInDips{ _core->FontSizeInDips() }; if (distance >= (std::min(fontSizeInDips.width(), fontSizeInDips.height()) / 4.f)) @@ -271,7 +273,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation _core->UpdateHoveredCell(terminalPosition); } - void ControlInteractivity::TouchMoved(const winrt::Windows::Foundation::Point newTouchPoint, + void ControlInteractivity::TouchMoved(const til::point newTouchPoint, const bool focused) { if (focused && @@ -284,7 +286,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation const auto fontSizeInDips{ _core->FontSizeInDips() }; // Get the difference between the point we've dragged to and the start of the touch. - const float dy = newTouchPoint.Y - anchor.Y; + const float dy = ::base::saturated_cast(newTouchPoint.y() - anchor.y()); // Start viewport scroll after we've moved more than a half row of text if (std::abs(dy) > (fontSizeInDips.height() / 2.0f)) diff --git a/src/cascadia/TerminalControl/ControlInteractivity.h b/src/cascadia/TerminalControl/ControlInteractivity.h index 6c8915aa801..0327094777a 100644 --- a/src/cascadia/TerminalControl/ControlInteractivity.h +++ b/src/cascadia/TerminalControl/ControlInteractivity.h @@ -48,21 +48,21 @@ namespace winrt::Microsoft::Terminal::Control::implementation winrt::com_ptr GetCore(); #pragma region InputMethods - void PointerPressed(const winrt::Windows::Foundation::Point mouseCursorPosition, + void PointerPressed(const til::point mouseCursorPosition, ::Microsoft::Console::VirtualTerminal::TerminalInput::MouseButtonState buttonState, const unsigned int pointerUpdateKind, const uint64_t timestamp, const ::Microsoft::Terminal::Core::ControlKeyStates modifiers, const til::point terminalPosition); - void TouchPressed(const winrt::Windows::Foundation::Point contactPoint); + void TouchPressed(const til::point contactPoint); - void PointerMoved(const winrt::Windows::Foundation::Point mouseCursorPosition, + void PointerMoved(const til::point mouseCursorPosition, ::Microsoft::Console::VirtualTerminal::TerminalInput::MouseButtonState buttonState, const unsigned int pointerUpdateKind, const ::Microsoft::Terminal::Core::ControlKeyStates modifiers, const bool focused, const til::point terminalPosition); - void TouchMoved(const winrt::Windows::Foundation::Point newTouchPoint, + void TouchMoved(const til::point newTouchPoint, const bool focused); void PointerReleased(::Microsoft::Console::VirtualTerminal::TerminalInput::MouseButtonState buttonState, @@ -89,7 +89,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation // If this is set, then we assume we are in the middle of panning the // viewport via touch input. - std::optional _touchAnchor; + std::optional _touchAnchor; using Timestamp = uint64_t; @@ -98,10 +98,10 @@ namespace winrt::Microsoft::Terminal::Control::implementation Timestamp _multiClickTimer; unsigned int _multiClickCounter; Timestamp _lastMouseClickTimestamp; - std::optional _lastMouseClickPos; - std::optional _singleClickTouchdownPos; + std::optional _lastMouseClickPos; + std::optional _singleClickTouchdownPos; std::optional _singleClickTouchdownTerminalPos; - std::optional _lastMouseClickPosNoSelection; + std::optional _lastMouseClickPosNoSelection; // This field tracks whether the selection has changed meaningfully // since it was last copied. It's generally used to prevent copyOnSelect // from firing when the pointer _just happens_ to be released over the @@ -114,7 +114,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation std::optional::interval> _lastHoveredInterval{ std::nullopt }; - unsigned int _numberOfClicks(winrt::Windows::Foundation::Point clickPos, Timestamp clickTime); + unsigned int _numberOfClicks(til::point clickPos, Timestamp clickTime); void _updateSystemParameterSettings() noexcept; bool _trySendMouseEvent(const unsigned int updateKind, const ::Microsoft::Console::VirtualTerminal::TerminalInput::MouseButtonState buttonState, diff --git a/src/cascadia/TerminalControl/ControlInteractivity.idl b/src/cascadia/TerminalControl/ControlInteractivity.idl index 000c8ec1ff3..3a9afaa1409 100644 --- a/src/cascadia/TerminalControl/ControlInteractivity.idl +++ b/src/cascadia/TerminalControl/ControlInteractivity.idl @@ -11,7 +11,7 @@ namespace Microsoft.Terminal.Control [default_interface] runtimeclass ControlInteractivity { - ControlInteractivity(Microsoft.Terminal.Control.IControlSettings settings, + ControlInteractivity(IControlSettings settings, Microsoft.Terminal.TerminalConnection.ITerminalConnection connection); }; } diff --git a/src/cascadia/TerminalControl/TermControl.cpp b/src/cascadia/TerminalControl/TermControl.cpp index 0890df783c0..9aebc8c0716 100644 --- a/src/cascadia/TerminalControl/TermControl.cpp +++ b/src/cascadia/TerminalControl/TermControl.cpp @@ -1048,17 +1048,17 @@ namespace winrt::Microsoft::Terminal::Control::implementation { Focus(FocusState::Pointer); } - const auto cursorPosition = point.Position(); if (type == Windows::Devices::Input::PointerDeviceType::Touch) { const auto contactRect = point.Properties().ContactRect(); - auto anchor = winrt::Windows::Foundation::Point{ contactRect.X, contactRect.Y }; + auto anchor = til::point{ til::math::rounding, contactRect.X, contactRect.Y }; _interactivity->TouchPressed(anchor); } else { - _interactivity->PointerPressed(cursorPosition, + const auto cursorPosition = point.Position(); + _interactivity->PointerPressed(til::point{ til::math::rounding, cursorPosition }, TermControl::GetPressedMouseButtons(point), TermControl::GetPointerUpdateKind(point), point.Timestamp(), @@ -1098,7 +1098,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation if (type == Windows::Devices::Input::PointerDeviceType::Mouse || type == Windows::Devices::Input::PointerDeviceType::Pen) { - _interactivity->PointerMoved(cursorPosition, + _interactivity->PointerMoved(til::point{ til::math::rounding, cursorPosition }, TermControl::GetPressedMouseButtons(point), TermControl::GetPointerUpdateKind(point), ControlKeyStates(args.KeyModifiers()), @@ -1134,7 +1134,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation else if (type == Windows::Devices::Input::PointerDeviceType::Touch) { const auto contactRect = point.Properties().ContactRect(); - winrt::Windows::Foundation::Point newTouchPoint{ contactRect.X, contactRect.Y }; + til::point newTouchPoint{ til::math::rounding, contactRect.X, contactRect.Y }; _interactivity->TouchMoved(newTouchPoint, _focused); } From 6e4722166bb75f7e7dbd28a8442e7432c9b8aa0b Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Wed, 21 Apr 2021 10:29:19 -0500 Subject: [PATCH 74/82] another pile of nits --- src/cascadia/TerminalControl/ControlCore.cpp | 106 +++++++----------- src/cascadia/TerminalControl/ControlCore.h | 7 +- .../TerminalControl/ControlInteractivity.cpp | 15 +-- src/cascadia/TerminalControl/TermControl.cpp | 18 +-- 4 files changed, 60 insertions(+), 86 deletions(-) diff --git a/src/cascadia/TerminalControl/ControlCore.cpp b/src/cascadia/TerminalControl/ControlCore.cpp index 4698b01b0c7..6e71d8d917f 100644 --- a/src/cascadia/TerminalControl/ControlCore.cpp +++ b/src/cascadia/TerminalControl/ControlCore.cpp @@ -73,6 +73,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation // We're not doing that quite yet, because the Core will eventually // be out-of-proc from the UI thread, and won't be able to just use // the UI thread as the dispatcher queue thread. + // + // See TODO: https://github.com/microsoft/terminal/projects/5#card-50760282 _ReceivedOutputHandlers(*this, nullptr); }; _connectionOutputEventToken = _connection.TerminalOutput(onReceiveOutputFn); @@ -240,18 +242,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation // - wstr: the string of characters to write to the terminal connection. // Return Value: // - - void ControlCore::_sendInputToConnection(const winrt::hstring& wstr) - { - if (_isReadOnly) - { - _raiseReadOnlyWarning(); - } - else - { - _connection.WriteInput(wstr); - } - } - void ControlCore::_sendInputToConnection(std::wstring_view wstr) { if (_isReadOnly) @@ -290,12 +280,11 @@ namespace winrt::Microsoft::Terminal::Control::implementation // Arguments: // - vkey: The vkey of the key pressed. // - scanCode: The scan code of the key pressed. - // - states: The Microsoft::Terminal::Core::ControlKeyStates representing the modifier key states. + // - modifiers: The Microsoft::Terminal::Core::ControlKeyStates representing the modifier key states. // - keyDown: If true, the key was pressed, otherwise the key was released. bool ControlCore::TrySendKeyEvent(const WORD vkey, const WORD scanCode, const ControlKeyStates modifiers, - const bool eitherWinPressed, const bool keyDown) { // When there is a selection active, escape should clear it and NOT flow through @@ -314,7 +303,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation keyDown) { // GH#8791 - don't dismiss selection if Windows key was also pressed as a key-combination. - if (!eitherWinPressed) + if (!modifiers.IsWinPressed()) { _terminal->ClearSelection(); _renderer->TriggerSelection(); @@ -329,23 +318,22 @@ namespace winrt::Microsoft::Terminal::Control::implementation // If the terminal translated the key, mark the event as handled. // This will prevent the system from trying to get the character out // of it and sending us a CharacterReceived event. - const auto handled = vkey ? _terminal->SendKeyEvent(vkey, - scanCode, - modifiers, - keyDown) : - true; - - return handled; + return vkey ? _terminal->SendKeyEvent(vkey, + scanCode, + modifiers, + keyDown) : + true; } bool ControlCore::SendMouseEvent(const til::point viewportPos, const unsigned int uiButton, const ControlKeyStates states, const short wheelDelta, - const ::Microsoft::Console::VirtualTerminal::TerminalInput::MouseButtonState state) + const TerminalInput::MouseButtonState state) { return _terminal->SendMouseEvent(viewportPos, uiButton, states, wheelDelta, state); } + void ControlCore::UserScrollViewport(const int viewTop) { // Clear the regex pattern tree so the renderer does not try to render them while scrolling @@ -358,6 +346,11 @@ namespace winrt::Microsoft::Terminal::Control::implementation void ControlCore::AdjustOpacity(const double adjustment) { + if (adjustment == 0) + { + return; + } + auto newOpacity = std::clamp(_settings.TintOpacity() + adjustment, 0.0, 1.0); @@ -464,15 +457,10 @@ namespace winrt::Microsoft::Terminal::Control::implementation _renderer->UpdateLastHoveredInterval(newInterval); _renderer->TriggerRedrawAll(); - _raiseHoveredHyperlinkChanged(); + _HoveredHyperlinkChangedHandlers(*this, nullptr); } } - void ControlCore::_raiseHoveredHyperlinkChanged() - { - _HoveredHyperlinkChangedHandlers(*this, nullptr); - } - winrt::hstring ControlCore::GetHyperlink(const til::point pos) const { // Lock for the duration of our reads. @@ -485,8 +473,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation auto lock = _terminal->LockForReading(); // Lock for the duration of our reads. if (_lastHoveredCell.has_value()) { - const winrt::hstring uri{ _terminal->GetHyperlinkAtPosition(*_lastHoveredCell) }; - return uri; + return winrt::hstring{ _terminal->GetHyperlinkAtPosition(*_lastHoveredCell) }; } return { L"" }; } @@ -504,7 +491,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation // Initialize our font information. const auto fontFace = _settings.FontFace(); - const short fontHeight = gsl::narrow_cast(_settings.FontSize()); + const short fontHeight = ::base::saturated_cast(_settings.FontSize()); const auto fontWeight = _settings.FontWeight(); // The font width doesn't terribly matter, we'll only be using the // height to look it up @@ -773,20 +760,17 @@ namespace winrt::Microsoft::Terminal::Control::implementation } } - void ControlCore::SetSelectionAnchor(Windows::Foundation::Point const& position) + void ControlCore::SetSelectionAnchor(til::point const& position) { auto lock = _terminal->LockForWriting(); - _terminal->SetSelectionAnchor(til::point{ til::math::rounding, - position.X, - position.Y }); + _terminal->SetSelectionAnchor(position); } // Method Description: // - Sets selection's end position to match supplied cursor position, e.g. while mouse dragging. // Arguments: - // - ~~cursorPosition: in pixels, relative to the origin of the control~~ - // - cursorPosition: in cells - void ControlCore::SetEndSelectionPoint(Windows::Foundation::Point const& position) + // - position: the point in terminal coordinates (in cells, not pixels) + void ControlCore::SetEndSelectionPoint(til::point const& position) { if (!_terminal->IsSelectionActive()) { @@ -800,9 +784,10 @@ namespace winrt::Microsoft::Terminal::Control::implementation const short lastVisibleRow = std::max(_terminal->GetViewport().Height() - 1, 0); const short lastVisibleCol = std::max(_terminal->GetViewport().Width() - 1, 0); - til::point terminalPosition{ til::math::rounding, - std::clamp(position.X, 0, lastVisibleCol), - std::clamp(position.Y, 0, lastVisibleRow) }; + til::point terminalPosition{ + std::clamp(position.x(), 0, lastVisibleCol), + std::clamp(position.y(), 0, lastVisibleRow) + }; // save location (for rendering) + render _terminal->SetSelectionEnd(terminalPosition); @@ -813,8 +798,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation // when an OSC 52 is emitted. void ControlCore::_terminalCopyToClipboard(std::wstring_view wstr) { - auto copyArgs = winrt::make_self(winrt::hstring(wstr)); - _CopyToClipboardHandlers(*this, *copyArgs); + _CopyToClipboardHandlers(*this, winrt::make(winrt::hstring{ wstr })); } // Method Description: @@ -870,11 +854,11 @@ namespace winrt::Microsoft::Terminal::Control::implementation } // send data up for clipboard - auto copyArgs = winrt::make_self(winrt::hstring(textData), - winrt::to_hstring(htmlData), - winrt::to_hstring(rtfData), - formats); - _CopyToClipboardHandlers(*this, *copyArgs); + _CopyToClipboardHandlers(*this, + winrt::make(winrt::hstring(textData), + winrt::to_hstring(htmlData), + winrt::to_hstring(rtfData), + formats)); return true; } @@ -906,14 +890,12 @@ namespace winrt::Microsoft::Terminal::Control::implementation hstring ControlCore::Title() { - hstring hstr{ _terminal->GetConsoleTitle() }; - return hstr; + return hstring{ _terminal->GetConsoleTitle() }; } hstring ControlCore::WorkingDirectory() const { - hstring hstr{ _terminal->GetWorkingDirectory() }; - return hstr; + return hstring{ _terminal->GetWorkingDirectory() }; } bool ControlCore::BracketedPasteEnabled() const noexcept @@ -963,8 +945,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation // - The height of the terminal in lines of text int ControlCore::ViewHeight() const { - const auto viewPort = _terminal->GetViewport(); - return viewPort.Height(); + return _terminal->GetViewport().Height(); } // Function Description: @@ -993,8 +974,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation // - void ControlCore::_terminalTitleChanged(std::wstring_view wstr) { - auto titleArgs = winrt::make_self(winrt::hstring{ wstr }); - _TitleChangedHandlers(*this, *titleArgs); + _TitleChangedHandlers(*this, winrt::make(winrt::hstring{ wstr })); } // Method Description: @@ -1047,8 +1027,10 @@ namespace winrt::Microsoft::Terminal::Control::implementation // TODO GH#9617: refine locking around pattern tree _terminal->ClearPatternTree(); - auto scrollArgs = winrt::make_self(viewTop, viewHeight, bufferSize); - _ScrollPositionChangedHandlers(*this, *scrollArgs); + _ScrollPositionChangedHandlers(*this, + winrt::make(viewTop, + viewHeight, + bufferSize)); } void ControlCore::_terminalCursorPositionChanged() @@ -1073,8 +1055,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation std::vector ControlCore::SelectedText(bool trimTrailingWhitespace) const { - const auto bufferData = _terminal->RetrieveSelectedTextFromBuffer(trimTrailingWhitespace); - return bufferData.text; + return _terminal->RetrieveSelectedTextFromBuffer(trimTrailingWhitespace).text; } ::Microsoft::Console::Types::IUiaData* ControlCore::GetUiaData() const @@ -1194,8 +1175,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation void ControlCore::_rendererWarning(const HRESULT hr) { - auto args{ winrt::make_self(hr) }; - _RendererWarningHandlers(*this, *args); + _RendererWarningHandlers(*this, winrt::make(hr)); } void ControlCore::_renderEngineSwapChainChanged() diff --git a/src/cascadia/TerminalControl/ControlCore.h b/src/cascadia/TerminalControl/ControlCore.h index f5ee458f0f2..9ed2c049a03 100644 --- a/src/cascadia/TerminalControl/ControlCore.h +++ b/src/cascadia/TerminalControl/ControlCore.h @@ -97,7 +97,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation bool TrySendKeyEvent(const WORD vkey, const WORD scanCode, const ::Microsoft::Terminal::Core::ControlKeyStates modifiers, - const bool eitherWinPressed, const bool keyDown); bool SendCharEvent(const wchar_t ch, const WORD scanCode, @@ -121,8 +120,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation bool HasSelection() const; bool CopyOnSelect() const; std::vector SelectedText(bool trimTrailingWhitespace) const; - void SetSelectionAnchor(winrt::Windows::Foundation::Point const& position); - void SetEndSelectionPoint(winrt::Windows::Foundation::Point const& position); + void SetSelectionAnchor(til::point const& position); + void SetEndSelectionPoint(til::point const& position); void Search(const winrt::hstring& text, const bool goForward, @@ -205,7 +204,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation void _doResizeUnderLock(const double newWidth, const double newHeight); - void _sendInputToConnection(const winrt::hstring& wstr); void _sendInputToConnection(std::wstring_view wstr); #pragma region TerminalCoreCallbacks @@ -226,7 +224,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation void _renderEngineSwapChainChanged(); #pragma endregion - void _raiseHoveredHyperlinkChanged(); void _raiseReadOnlyWarning(); void _updateAntiAliasingMode(::Microsoft::Console::Render::DxEngine* const dxEngine); diff --git a/src/cascadia/TerminalControl/ControlInteractivity.cpp b/src/cascadia/TerminalControl/ControlInteractivity.cpp index b7dc55d0bf7..65bc9d38c01 100644 --- a/src/cascadia/TerminalControl/ControlInteractivity.cpp +++ b/src/cascadia/TerminalControl/ControlInteractivity.cpp @@ -498,19 +498,16 @@ namespace winrt::Microsoft::Terminal::Control::implementation { _core->UserScrollViewport(newValue); - // _core->ScrollOffset() is new set to newValue - auto scrollArgs = winrt::make_self(_core->ScrollOffset(), - _core->ViewHeight(), - _core->BufferHeight()); - _ScrollPositionChangedHandlers(*this, *scrollArgs); + // _core->ScrollOffset() is now set to newValue + _ScrollPositionChangedHandlers(*this, + winrt::make(_core->ScrollOffset(), + _core->ViewHeight(), + _core->BufferHeight())); } void ControlInteractivity::_hyperlinkHandler(const std::wstring_view uri) { - // Save things we need to resume later. - winrt::hstring heldUri{ uri }; - auto hyperlinkArgs = winrt::make_self(heldUri); - _OpenHyperlinkHandlers(*this, *hyperlinkArgs); + _OpenHyperlinkHandlers(*this, winrt::make(winrt::hstring{ uri })); } bool ControlInteractivity::_canSendVTMouseInput(const ::Microsoft::Terminal::Core::ControlKeyStates modifiers) diff --git a/src/cascadia/TerminalControl/TermControl.cpp b/src/cascadia/TerminalControl/TermControl.cpp index 9aebc8c0716..2e8c3c20898 100644 --- a/src/cascadia/TerminalControl/TermControl.cpp +++ b/src/cascadia/TerminalControl/TermControl.cpp @@ -99,6 +99,11 @@ namespace winrt::Microsoft::Terminal::Control::implementation } }); + // Many of these ThrottledFunc's should be inside ControlCore. However, + // currently they depend on the Dispatcher() of the UI thread, which the + // Core eventually won't have access to. When we get to + // https://github.com/microsoft/terminal/projects/5#card-50760282 + // then we'll move the applicable ones. _tsfTryRedrawCanvas = std::make_shared>( [weakThis = get_weak()]() { if (auto control{ weakThis.get() }) @@ -570,13 +575,13 @@ namespace winrt::Microsoft::Terminal::Control::implementation // This event is only registered during terminal initialization, // so we don't need to check _initializedTerminal. // We also don't lock for things that come back from the renderer. - auto chain = _core->GetSwapChain(); auto weakThis{ get_weak() }; co_await winrt::resume_foreground(Dispatcher()); if (auto control{ weakThis.get() }) { + const auto chain = control->_core->GetSwapChain(); _AttachDxgiSwapChainToXaml(chain); } } @@ -972,11 +977,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation const bool keyDown) { const CoreWindow window = CoreWindow::GetForCurrentThread(); - const auto leftWinKeyState = window.GetKeyState(VirtualKey::LeftWindows); - const auto rightWinKeyState = window.GetKeyState(VirtualKey::RightWindows); - const auto isLeftWinKeyDown = WI_IsFlagSet(leftWinKeyState, CoreVirtualKeyStates::Down); - const auto isRightWinKeyDown = WI_IsFlagSet(rightWinKeyState, CoreVirtualKeyStates::Down); - const bool eitherWinPressed = isLeftWinKeyDown || isRightWinKeyDown; if (vkey == VK_ESCAPE || vkey == VK_RETURN) @@ -991,7 +991,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation _core->TrySendKeyEvent(vkey, scanCode, modifiers, - eitherWinPressed, keyDown) : true; @@ -2128,10 +2127,11 @@ namespace winrt::Microsoft::Terminal::Control::implementation void TermControl::_FontInfoHandler(const IInspectable& /*sender*/, const FontInfoEventArgs& eventArgs) { + const auto fontInfo = _core->GetFont(); eventArgs.FontSize(CharacterDimensions()); - eventArgs.FontFace(_core->GetFont().GetFaceName()); + eventArgs.FontFace(fontInfo.GetFaceName()); ::winrt::Windows::UI::Text::FontWeight weight; - weight.Weight = static_cast(_core->GetFont().GetWeight()); + weight.Weight = static_cast(fontInfo.GetWeight()); eventArgs.FontWeight(weight); } From 3cc4717fc390dbacb582c76aa338d07e9b97a15d Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Wed, 21 Apr 2021 12:34:27 -0500 Subject: [PATCH 75/82] bunch of comments --- src/cascadia/TerminalControl/ControlCore.cpp | 77 +++++++++++++------ src/cascadia/TerminalControl/ControlCore.h | 1 + .../TerminalControl/ControlInteractivity.cpp | 16 ++-- .../TerminalControl/ControlInteractivity.h | 2 +- src/cascadia/TerminalControl/TermControl.cpp | 4 + 5 files changed, 68 insertions(+), 32 deletions(-) diff --git a/src/cascadia/TerminalControl/ControlCore.cpp b/src/cascadia/TerminalControl/ControlCore.cpp index 6e71d8d917f..87ced432cc3 100644 --- a/src/cascadia/TerminalControl/ControlCore.cpp +++ b/src/cascadia/TerminalControl/ControlCore.cpp @@ -61,23 +61,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation }); // This event is explicitly revoked in the destructor: does not need weak_ref - auto onReceiveOutputFn = [this](const hstring str) { - _terminal->Write(str); - - // NOTE: We're raising an event here to inform the TermControl that - // output has been received, so it can queue up a throttled - // UpdatePatternLocations call. In the future, we should have the - // _updatePatternLocations ThrottledFunc internal to this class, and - // run on this object's dispatcher queue. - // - // We're not doing that quite yet, because the Core will eventually - // be out-of-proc from the UI thread, and won't be able to just use - // the UI thread as the dispatcher queue thread. - // - // See TODO: https://github.com/microsoft/terminal/projects/5#card-50760282 - _ReceivedOutputHandlers(*this, nullptr); - }; - _connectionOutputEventToken = _connection.TerminalOutput(onReceiveOutputFn); + _connectionOutputEventToken = _connection.TerminalOutput({ this, &ControlCore::_connectionOutputHandler }); _terminal->SetWriteInputCallback([this](std::wstring& wstr) { _sendInputToConnection(wstr); @@ -449,13 +433,19 @@ namespace winrt::Microsoft::Terminal::Control::implementation if (newId != _lastHoveredId || (newInterval != _lastHoveredInterval)) { - auto lock = _terminal->LockForWriting(); + // Introduce scope for lock - we don't want to raise the + // HoveredHyperlinkChanged event under lock, because then handlers + // wouldn't be able to ask us about the hyperlink text/position + // without deadlocking us. + { + auto lock = _terminal->LockForWriting(); - _lastHoveredId = newId; - _lastHoveredInterval = newInterval; - _renderEngine->UpdateHyperlinkHoveredId(newId); - _renderer->UpdateLastHoveredInterval(newInterval); - _renderer->TriggerRedrawAll(); + _lastHoveredId = newId; + _lastHoveredInterval = newInterval; + _renderEngine->UpdateHyperlinkHoveredId(newId); + _renderer->UpdateLastHoveredInterval(newInterval); + _renderer->TriggerRedrawAll(); + } _HoveredHyperlinkChangedHandlers(*this, nullptr); } @@ -475,7 +465,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation { return winrt::hstring{ _terminal->GetHyperlinkAtPosition(*_lastHoveredCell) }; } - return { L"" }; + return {}; } std::optional ControlCore::GetHoveredCell() const @@ -960,6 +950,9 @@ namespace winrt::Microsoft::Terminal::Control::implementation void ControlCore::_terminalWarningBell() { + // Since this can only ever be triggered by output from the connection, + // then the Terminal already has the write lock when calling this + // callback. _WarningBellHandlers(*this, nullptr); } @@ -974,6 +967,9 @@ namespace winrt::Microsoft::Terminal::Control::implementation // - void ControlCore::_terminalTitleChanged(std::wstring_view wstr) { + // Since this can only ever be triggered by output from the connection, + // then the Terminal already has the write lock when calling this + // callback. _TitleChangedHandlers(*this, winrt::make(winrt::hstring{ wstr })); } @@ -1121,7 +1117,13 @@ namespace winrt::Microsoft::Terminal::Control::implementation if (auto localConnection{ std::exchange(_connection, nullptr) }) { // Close the connection on the background thread. - co_await winrt::resume_background(); + co_await winrt::resume_background(); // ** DO NOT INTERACT WITH THE CONTROLCORE AFTER THIS LINE ** + + // Here, the ControlCore very well might be gone. + // _asyncCloseConnection is called on the dtor, so it's entirely + // possible that the background thread is resuming after we've been + // cleaned up. + localConnection.Close(); // connection is destroyed. } @@ -1170,6 +1172,12 @@ namespace winrt::Microsoft::Terminal::Control::implementation IDXGISwapChain1* ControlCore::GetSwapChain() const { + // This is called by: + // * TermControl::RenderEngineSwapChainChanged, who is only registered + // after Core::Initialize() is called. + // * TermControl::_InitializeTerminal, after the call to Initialize, for + // _AttachDxgiSwapChainToXaml. + // In both cases, we'll have a _renderEngine by then. return _renderEngine->GetSwapChain().Get(); } @@ -1199,6 +1207,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation { return; } + // SetCursorOn will take the write lock for you. _terminal->SetCursorOn(!_terminal->IsCursorOn()); } @@ -1321,4 +1330,22 @@ namespace winrt::Microsoft::Terminal::Control::implementation auto noticeArgs = winrt::make(NoticeLevel::Info, RS_(L"TermControlReadOnly")); _RaiseNoticeHandlers(*this, std::move(noticeArgs)); } + void ControlCore::_connectionOutputHandler(const hstring& hstr) + { + _terminal->Write(hstr); + + // NOTE: We're raising an event here to inform the TermControl that + // output has been received, so it can queue up a throttled + // UpdatePatternLocations call. In the future, we should have the + // _updatePatternLocations ThrottledFunc internal to this class, and + // run on this object's dispatcher queue. + // + // We're not doing that quite yet, because the Core will eventually + // be out-of-proc from the UI thread, and won't be able to just use + // the UI thread as the dispatcher queue thread. + // + // See TODO: https://github.com/microsoft/terminal/projects/5#card-50760282 + _ReceivedOutputHandlers(*this, nullptr); + } + } diff --git a/src/cascadia/TerminalControl/ControlCore.h b/src/cascadia/TerminalControl/ControlCore.h index 9ed2c049a03..7718b14fd12 100644 --- a/src/cascadia/TerminalControl/ControlCore.h +++ b/src/cascadia/TerminalControl/ControlCore.h @@ -226,6 +226,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation void _raiseReadOnlyWarning(); void _updateAntiAliasingMode(::Microsoft::Console::Render::DxEngine* const dxEngine); + void _connectionOutputHandler(const hstring& hstr); friend class ControlUnitTests::ControlCoreTests; friend class ControlUnitTests::ControlInteractivityTests; diff --git a/src/cascadia/TerminalControl/ControlInteractivity.cpp b/src/cascadia/TerminalControl/ControlInteractivity.cpp index 65bc9d38c01..bacd9aa0f9b 100644 --- a/src/cascadia/TerminalControl/ControlInteractivity.cpp +++ b/src/cascadia/TerminalControl/ControlInteractivity.cpp @@ -23,6 +23,8 @@ using namespace winrt::Windows::Graphics::Display; using namespace winrt::Windows::System; using namespace winrt::Windows::ApplicationModel::DataTransfer; +static constexpr unsigned int MAX_CLICK_COUNT = 3; + namespace winrt::Microsoft::Terminal::Control::implementation { ControlInteractivity::ControlInteractivity(IControlSettings settings, @@ -114,11 +116,14 @@ namespace winrt::Microsoft::Terminal::Control::implementation { if (_core) { - // Note to future self: This should return false if there's no - // selection to copy. If there's no selection, returning false will - // indicate that the actions that triggered this should _not_ be - // marked as handled, so ctrl+c without a selection can still send - // ^C + // Return false if there's no selection to copy. If there's no + // selection, returning false will indicate that the actions that + // triggered this should _not_ be marked as handled, so ctrl+c + // without a selection can still send ^C + if (!_core->HasSelection()) + { + return false; + } // Mark the current selection as copied _selectionNeedsToBeCopied = false; @@ -185,7 +190,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation // between single-, double-, and triple-click. To increase the // number of acceptable click states, simply increment // MAX_CLICK_COUNT and add another if-statement - const unsigned int MAX_CLICK_COUNT = 3; const auto multiClickMapper = clickCount > MAX_CLICK_COUNT ? ((clickCount + MAX_CLICK_COUNT - 1) % MAX_CLICK_COUNT) + 1 : clickCount; // Capture the position of the first click when no selection is active diff --git a/src/cascadia/TerminalControl/ControlInteractivity.h b/src/cascadia/TerminalControl/ControlInteractivity.h index 0327094777a..402ae74920a 100644 --- a/src/cascadia/TerminalControl/ControlInteractivity.h +++ b/src/cascadia/TerminalControl/ControlInteractivity.h @@ -47,7 +47,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation void Initialize(); winrt::com_ptr GetCore(); -#pragma region InputMethods +#pragma region Input Methods void PointerPressed(const til::point mouseCursorPosition, ::Microsoft::Console::VirtualTerminal::TerminalInput::MouseButtonState buttonState, const unsigned int pointerUpdateKind, diff --git a/src/cascadia/TerminalControl/TermControl.cpp b/src/cascadia/TerminalControl/TermControl.cpp index 2e8c3c20898..1fd1c085e04 100644 --- a/src/cascadia/TerminalControl/TermControl.cpp +++ b/src/cascadia/TerminalControl/TermControl.cpp @@ -2436,12 +2436,16 @@ namespace winrt::Microsoft::Terminal::Control::implementation const int fontHeight, const bool isInitialChange) { + // Don't try to inspect the core here. The Core is raising this while + // it's holding its write lock. _FontSizeChangedHandlers(fontWidth, fontHeight, isInitialChange); } void TermControl::_coreRaisedNotice(const IInspectable& /*sender*/, const Control::NoticeEventArgs& eventArgs) { + // Don't try to inspect the core here. The Core might be raising this + // while it's holding its write lock. _RaiseNoticeHandlers(*this, eventArgs); } From 753ca1b7c323618166fd9d2f059d1e637523d125 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Wed, 21 Apr 2021 15:25:20 -0500 Subject: [PATCH 76/82] patch the tests up to not use Cascadia Mono anymore --- OpenConsole.sln | 3 +- src/cascadia/TerminalControl/ControlCore.cpp | 18 ++++++++--- src/cascadia/TerminalControl/TermControl.cpp | 30 ++++++++----------- src/cascadia/TerminalControl/TermControl.h | 4 +-- src/cascadia/TerminalCore/Terminal.hpp | 2 +- .../TerminalCore/TerminalSelection.cpp | 4 ++- .../UnitTests_Control/ControlCoreTests.cpp | 6 ++-- .../ControlInteractivityTests.cpp | 6 ++-- .../UnitTests_Control/MockControlSettings.h | 2 +- 9 files changed, 42 insertions(+), 33 deletions(-) diff --git a/OpenConsole.sln b/OpenConsole.sln index d82d43341f4..2b644ae98a8 100644 --- a/OpenConsole.sln +++ b/OpenConsole.sln @@ -175,7 +175,9 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Microsoft.Terminal.Control. {CA5CAD1A-C46D-4588-B1C0-40F31AE9100B} = {CA5CAD1A-C46D-4588-B1C0-40F31AE9100B} {CA5CAD1A-ABCD-429C-B551-8562EC954746} = {CA5CAD1A-ABCD-429C-B551-8562EC954746} {1CF55140-EF6A-4736-A403-957E4F7430BB} = {1CF55140-EF6A-4736-A403-957E4F7430BB} + {48D21369-3D7B-4431-9967-24E81292CF62} = {48D21369-3D7B-4431-9967-24E81292CF62} {48D21369-3D7B-4431-9967-24E81292CF63} = {48D21369-3D7B-4431-9967-24E81292CF63} + {AF0A096A-8B3A-4949-81EF-7DF8F0FEE91F} = {AF0A096A-8B3A-4949-81EF-7DF8F0FEE91F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Microsoft.Terminal.Control", "src\cascadia\TerminalControl\dll\TerminalControl.vcxproj", "{CA5CAD1A-F542-4635-A069-7CAEFB930070}" @@ -3221,7 +3223,6 @@ Global {C323DAEE-B307-4C7B-ACE5-7293CBEFCB5B}.AuditMode|ARM64.Build.0 = AuditMode|ARM64 {C323DAEE-B307-4C7B-ACE5-7293CBEFCB5B}.AuditMode|DotNet_x64Test.ActiveCfg = AuditMode|Win32 {C323DAEE-B307-4C7B-ACE5-7293CBEFCB5B}.AuditMode|DotNet_x86Test.ActiveCfg = AuditMode|Win32 - {C323DAEE-B307-4C7B-ACE5-7293CBEFCB5B}.AuditMode|x64.ActiveCfg = AuditMode|x64 {C323DAEE-B307-4C7B-ACE5-7293CBEFCB5B}.AuditMode|x64.ActiveCfg = Release|x64 {C323DAEE-B307-4C7B-ACE5-7293CBEFCB5B}.AuditMode|x86.ActiveCfg = AuditMode|Win32 {C323DAEE-B307-4C7B-ACE5-7293CBEFCB5B}.AuditMode|x86.Build.0 = AuditMode|Win32 diff --git a/src/cascadia/TerminalControl/ControlCore.cpp b/src/cascadia/TerminalControl/ControlCore.cpp index 87ced432cc3..b2f3c84093b 100644 --- a/src/cascadia/TerminalControl/ControlCore.cpp +++ b/src/cascadia/TerminalControl/ControlCore.cpp @@ -473,12 +473,15 @@ namespace winrt::Microsoft::Terminal::Control::implementation return _lastHoveredCell; } + // Method Description: + // - Updates the settings of the current terminal. + // - INVARIANT: This method can only be called if the caller DOES NOT HAVE writing lock on the terminal. void ControlCore::UpdateSettings(const IControlSettings& settings) { - _settings = settings; - auto lock = _terminal->LockForWriting(); + _settings = settings; + // Initialize our font information. const auto fontFace = _settings.FontFace(); const short fontHeight = ::base::saturated_cast(_settings.FontSize()); @@ -518,8 +521,13 @@ namespace winrt::Microsoft::Terminal::Control::implementation } } + // Method Description: + // - Updates the appearance of the current terminal. + // - INVARIANT: This method can only be called if the caller DOES NOT HAVE writing lock on the terminal. void ControlCore::UpdateAppearance(const IControlAppearance& newAppearance) { + auto lock = _terminal->LockForWriting(); + // Update the terminal core with its new Core settings _terminal->UpdateAppearance(newAppearance); @@ -809,6 +817,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation } // extract text from buffer + // RetrieveSelectedTextFromBuffer will lock while it's reading const auto bufferData = _terminal->RetrieveSelectedTextFromBuffer(singleLine); // convert text: vector --> string @@ -845,7 +854,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation // send data up for clipboard _CopyToClipboardHandlers(*this, - winrt::make(winrt::hstring(textData), + winrt::make(winrt::hstring{ textData }, winrt::to_hstring(htmlData), winrt::to_hstring(rtfData), formats)); @@ -1051,6 +1060,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation std::vector ControlCore::SelectedText(bool trimTrailingWhitespace) const { + // RetrieveSelectedTextFromBuffer will lock while it's reading return _terminal->RetrieveSelectedTextFromBuffer(trimTrailingWhitespace).text; } @@ -1117,7 +1127,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation if (auto localConnection{ std::exchange(_connection, nullptr) }) { // Close the connection on the background thread. - co_await winrt::resume_background(); // ** DO NOT INTERACT WITH THE CONTROLCORE AFTER THIS LINE ** + co_await winrt::resume_background(); // ** DO NOT INTERACT WITH THE CONTROL CORE AFTER THIS LINE ** // Here, the ControlCore very well might be gone. // _asyncCloseConnection is called on the dtor, so it's entirely diff --git a/src/cascadia/TerminalControl/TermControl.cpp b/src/cascadia/TerminalControl/TermControl.cpp index 1fd1c085e04..0bbd80dd189 100644 --- a/src/cascadia/TerminalControl/TermControl.cpp +++ b/src/cascadia/TerminalControl/TermControl.cpp @@ -258,17 +258,14 @@ namespace winrt::Microsoft::Terminal::Control::implementation // terminal. co_await winrt::resume_foreground(Dispatcher()); - // // Take the lock before calling the helper functions to update the settings and appearance - // auto lock = _terminal->LockForWriting(); - - _UpdateSettingsFromUIThreadUnderLock(_settings); + _UpdateSettingsFromUIThread(_settings); auto appearance = _settings.try_as(); if (!_focused && _UnfocusedAppearance) { appearance = _UnfocusedAppearance; } - _UpdateAppearanceFromUIThreadUnderLock(appearance); + _UpdateAppearanceFromUIThread(appearance); } // Method Description: @@ -280,9 +277,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation // Dispatch a call to the UI thread co_await winrt::resume_foreground(Dispatcher()); - // // Take the lock before calling the helper function to update the appearance - // auto lock = _terminal->LockForWriting(); - _UpdateAppearanceFromUIThreadUnderLock(newAppearance); + _UpdateAppearanceFromUIThread(newAppearance); } // Method Description: @@ -291,10 +286,9 @@ namespace winrt::Microsoft::Terminal::Control::implementation // issue that causes one of our hstring -> wstring_view conversions to result in garbage, // but only from a coroutine context. See GH#8723. // - INVARIANT: This method must be called from the UI thread. - // - INVARIANT: This method can only be called if the caller has the writing lock on the terminal. // Arguments: // - newSettings: the new settings to set - void TermControl::_UpdateSettingsFromUIThreadUnderLock(IControlSettings newSettings) + void TermControl::_UpdateSettingsFromUIThread(IControlSettings newSettings) { if (_closing) { @@ -310,10 +304,9 @@ namespace winrt::Microsoft::Terminal::Control::implementation // Method Description: // - Updates the appearance // - INVARIANT: This method must be called from the UI thread. - // - INVARIANT: This method can only be called if the caller has the writing lock on the terminal. // Arguments: // - newAppearance: the new appearance to set - void TermControl::_UpdateAppearanceFromUIThreadUnderLock(IControlAppearance newAppearance) + void TermControl::_UpdateAppearanceFromUIThread(IControlAppearance newAppearance) { if (_closing) { @@ -725,7 +718,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation } // Now that the renderer is set up, update the appearance for initialization - _UpdateAppearanceFromUIThreadUnderLock(_settings); + _UpdateAppearanceFromUIThread(_settings); // Focus the control here. If we do it during control initialization, then // focus won't actually get passed to us. I believe this is because @@ -2415,8 +2408,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation // Compute the location of the top left corner of the cell in DIPS const til::size marginsInDips{ til::math::rounding, GetPadding().Left, GetPadding().Top }; - const til::point startPos{ lastHoveredCell->x(), - lastHoveredCell->y() }; + const til::point startPos{ *lastHoveredCell }; const til::size fontSize{ _core->GetFont().GetSize() }; const til::point posInPixels{ startPos * fontSize }; const til::point posInDIPs{ posInPixels / SwapChainPanel().CompositionScaleX() }; @@ -2437,7 +2429,9 @@ namespace winrt::Microsoft::Terminal::Control::implementation const bool isInitialChange) { // Don't try to inspect the core here. The Core is raising this while - // it's holding its write lock. + // it's holding its write lock. If the handlers calls back to some + // method on the TermControl on the same thread, and that _method_ calls + // to ControlCore, we might be in danger of deadlocking. _FontSizeChangedHandlers(fontWidth, fontHeight, isInitialChange); } @@ -2445,7 +2439,9 @@ namespace winrt::Microsoft::Terminal::Control::implementation const Control::NoticeEventArgs& eventArgs) { // Don't try to inspect the core here. The Core might be raising this - // while it's holding its write lock. + // while it's holding its write lock. If the handlers calls back to some + // method on the TermControl on the same thread, and _that_ method calls + // to ControlCore, we might be in danger of deadlocking. _RaiseNoticeHandlers(*this, eventArgs); } diff --git a/src/cascadia/TerminalControl/TermControl.h b/src/cascadia/TerminalControl/TermControl.h index 343aa55420d..230ace8e6a3 100644 --- a/src/cascadia/TerminalControl/TermControl.h +++ b/src/cascadia/TerminalControl/TermControl.h @@ -169,8 +169,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation winrt::Windows::UI::Xaml::Controls::SwapChainPanel::LayoutUpdated_revoker _layoutUpdatedRevoker; - void _UpdateSettingsFromUIThreadUnderLock(IControlSettings newSettings); - void _UpdateAppearanceFromUIThreadUnderLock(IControlAppearance newAppearance); + void _UpdateSettingsFromUIThread(IControlSettings newSettings); + void _UpdateAppearanceFromUIThread(IControlAppearance newAppearance); void _ApplyUISettings(const IControlSettings&); void _InitializeBackgroundBrush(); diff --git a/src/cascadia/TerminalCore/Terminal.hpp b/src/cascadia/TerminalCore/Terminal.hpp index 6bbfdd19697..7e9304bca11 100644 --- a/src/cascadia/TerminalCore/Terminal.hpp +++ b/src/cascadia/TerminalCore/Terminal.hpp @@ -231,7 +231,7 @@ class Microsoft::Terminal::Core::Terminal final : void SetSelectionEnd(const COORD position, std::optional newExpansionMode = std::nullopt); void SetBlockSelection(const bool isEnabled) noexcept; - const TextBuffer::TextAndColor RetrieveSelectedTextFromBuffer(bool trimTrailingWhitespace) const; + const TextBuffer::TextAndColor RetrieveSelectedTextFromBuffer(bool trimTrailingWhitespace); #pragma endregion private: diff --git a/src/cascadia/TerminalCore/TerminalSelection.cpp b/src/cascadia/TerminalCore/TerminalSelection.cpp index f638a940422..ec285979e66 100644 --- a/src/cascadia/TerminalCore/TerminalSelection.cpp +++ b/src/cascadia/TerminalCore/TerminalSelection.cpp @@ -249,8 +249,10 @@ void Terminal::ClearSelection() // - singleLine: collapse all of the text to one line // Return Value: // - wstring text from buffer. If extended to multiple lines, each line is separated by \r\n -const TextBuffer::TextAndColor Terminal::RetrieveSelectedTextFromBuffer(bool singleLine) const +const TextBuffer::TextAndColor Terminal::RetrieveSelectedTextFromBuffer(bool singleLine) { + auto lock = LockForReading(); + const auto selectionRects = _GetSelectionRects(); const auto GetAttributeColors = std::bind(&Terminal::GetAttributeColors, this, std::placeholders::_1); diff --git a/src/cascadia/UnitTests_Control/ControlCoreTests.cpp b/src/cascadia/UnitTests_Control/ControlCoreTests.cpp index 0b60410ae0b..1efb4a04dea 100644 --- a/src/cascadia/UnitTests_Control/ControlCoreTests.cpp +++ b/src/cascadia/UnitTests_Control/ControlCoreTests.cpp @@ -78,9 +78,9 @@ namespace ControlUnitTests VERIFY_IS_NOT_NULL(core); VERIFY_IS_FALSE(core->_initializedTerminal); - // "Cascadia Mono" ends up with an actual size of 9x19 at 96DPI. So - // let's just arbitrarily start with a 270x380px (30x20 chars) window - core->Initialize(270, 380, 1.0); + // "Consolas" ends up with an actual size of 9x21 at 96DPI. So + // let's just arbitrarily start with a 270x420px (30x20 chars) window + core->Initialize(270, 420, 1.0); VERIFY_IS_TRUE(core->_initializedTerminal); VERIFY_ARE_EQUAL(30, core->_terminal->GetViewport().Width()); } diff --git a/src/cascadia/UnitTests_Control/ControlInteractivityTests.cpp b/src/cascadia/UnitTests_Control/ControlInteractivityTests.cpp index 7a3f4f359ff..7d541c57e41 100644 --- a/src/cascadia/UnitTests_Control/ControlInteractivityTests.cpp +++ b/src/cascadia/UnitTests_Control/ControlInteractivityTests.cpp @@ -68,9 +68,9 @@ namespace ControlUnitTests void _standardInit(winrt::com_ptr core, winrt::com_ptr interactivity) { - // "Cascadia Mono" ends up with an actual size of 9x19 at 96DPI. So - // let's just arbitrarily start with a 270x380px (30x20 chars) window - core->Initialize(270, 380, 1.0); + // "Consolas" ends up with an actual size of 9x21 at 96DPI. So + // let's just arbitrarily start with a 270x420px (30x20 chars) window + core->Initialize(270, 420, 1.0); VERIFY_IS_TRUE(core->_initializedTerminal); VERIFY_ARE_EQUAL(20, core->_terminal->GetViewport().Height()); interactivity->Initialize(); diff --git a/src/cascadia/UnitTests_Control/MockControlSettings.h b/src/cascadia/UnitTests_Control/MockControlSettings.h index 302fbcbf9d2..6d906755f62 100644 --- a/src/cascadia/UnitTests_Control/MockControlSettings.h +++ b/src/cascadia/UnitTests_Control/MockControlSettings.h @@ -46,7 +46,7 @@ namespace ControlUnitTests WINRT_PROPERTY(bool, UseAcrylic, false); WINRT_PROPERTY(double, TintOpacity, 0.5); WINRT_PROPERTY(winrt::hstring, Padding, DEFAULT_PADDING); - WINRT_PROPERTY(winrt::hstring, FontFace, DEFAULT_FONT_FACE); + WINRT_PROPERTY(winrt::hstring, FontFace, L"Consolas"); WINRT_PROPERTY(int32_t, FontSize, DEFAULT_FONT_SIZE); WINRT_PROPERTY(winrt::Windows::UI::Text::FontWeight, FontWeight); From 144d95ad2d6d77cd283368e7be4432794e5ff2d0 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Wed, 21 Apr 2021 15:40:08 -0500 Subject: [PATCH 77/82] punt this test to future me in #7001 --- src/cascadia/UnitTests_Control/ControlInteractivityTests.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/cascadia/UnitTests_Control/ControlInteractivityTests.cpp b/src/cascadia/UnitTests_Control/ControlInteractivityTests.cpp index 7d541c57e41..1f74ae809f2 100644 --- a/src/cascadia/UnitTests_Control/ControlInteractivityTests.cpp +++ b/src/cascadia/UnitTests_Control/ControlInteractivityTests.cpp @@ -24,7 +24,6 @@ namespace ControlUnitTests TEST_CLASS(ControlInteractivityTests) TEST_METHOD(TestAdjustAcrylic); - TEST_METHOD(TestPanWithTouch); TEST_METHOD(TestScrollWithMouse); TEST_METHOD(CreateSubsequentSelectionWithDragging); @@ -147,10 +146,6 @@ namespace ControlUnitTests } } - void ControlInteractivityTests::TestPanWithTouch() - { - VERIFY_IS_TRUE(false, L"TODO: Implement this test"); - } void ControlInteractivityTests::TestScrollWithMouse() { WEX::TestExecution::DisableVerifyExceptions disableVerifyExceptions{}; From 65b84ff48a6bb1bac7e2b4e4e192d01f4d9344ce Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Wed, 21 Apr 2021 16:13:30 -0500 Subject: [PATCH 78/82] I think this is the last of the 'trivial' notes. I still have to do the pixels thing dustin wanted --- src/cascadia/TerminalControl/ControlCore.cpp | 3 +- .../TerminalControl/ControlInteractivity.cpp | 32 ++----------------- .../TerminalControl/ControlInteractivity.h | 8 ----- src/cascadia/TerminalControl/TermControl.cpp | 13 ++++---- src/cascadia/TerminalControl/TermControl.h | 2 ++ .../UnitTests_Control/ControlCoreTests.cpp | 9 +++++- .../ControlInteractivityTests.cpp | 9 +++++- 7 files changed, 29 insertions(+), 47 deletions(-) diff --git a/src/cascadia/TerminalControl/ControlCore.cpp b/src/cascadia/TerminalControl/ControlCore.cpp index b2f3c84093b..d66a59b8a9d 100644 --- a/src/cascadia/TerminalControl/ControlCore.cpp +++ b/src/cascadia/TerminalControl/ControlCore.cpp @@ -417,6 +417,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation // GH#9618 - lock while we're reading from the terminal, and if we need // to update something, then lock again to write the terminal. + _lastHoveredCell = terminalPosition; uint16_t newId{ 0u }; // we can't use auto here because we're pre-declaring newInterval. @@ -509,8 +510,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation _renderEngine->SetSoftwareRendering(_settings.SoftwareRendering()); _updateAntiAliasingMode(_renderEngine.get()); - // TODO!: UpdateAppearance() ? - // Refresh our font with the renderer const auto actualFontOldSize = _actualFont.GetSize(); _updateFont(); diff --git a/src/cascadia/TerminalControl/ControlInteractivity.cpp b/src/cascadia/TerminalControl/ControlInteractivity.cpp index bacd9aa0f9b..c7899c2e056 100644 --- a/src/cascadia/TerminalControl/ControlInteractivity.cpp +++ b/src/cascadia/TerminalControl/ControlInteractivity.cpp @@ -181,7 +181,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation } else if (_canSendVTMouseInput(modifiers)) { - _trySendMouseEvent(pointerUpdateKind, buttonState, modifiers, terminalPosition); + _core->SendMouseEvent(terminalPosition, pointerUpdateKind, modifiers, 0, buttonState); } else if (buttonState.isLeftButtonDown) { @@ -248,7 +248,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation // Short-circuit isReadOnly check to avoid warning dialog if (focused && !_core->IsInReadOnlyMode() && _canSendVTMouseInput(modifiers)) { - _trySendMouseEvent(pointerUpdateKind, buttonState, modifiers, terminalPosition); + _core->SendMouseEvent(terminalPosition, pointerUpdateKind, modifiers, 0, buttonState); } else if (focused && buttonState.isLeftButtonDown) { @@ -323,7 +323,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation // Short-circuit isReadOnly check to avoid warning dialog if (!_core->IsInReadOnlyMode() && _canSendVTMouseInput(modifiers)) { - _trySendMouseEvent(pointerUpdateKind, buttonState, modifiers, terminalPosition); + _core->SendMouseEvent(terminalPosition, pointerUpdateKind, modifiers, 0, buttonState); return; } @@ -347,32 +347,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation _touchAnchor = std::nullopt; } - // Method Description: - // - Send this particular mouse event to the terminal. - // See Terminal::SendMouseEvent for more information. - // Arguments: - // - point: the PointerPoint object representing a mouse event from our XAML input handler - bool ControlInteractivity::_trySendMouseEvent(const unsigned int updateKind, - const TerminalInput::MouseButtonState buttonState, - const ::Microsoft::Terminal::Core::ControlKeyStates modifiers, - const til::point terminalPosition) - { - return _core->SendMouseEvent(terminalPosition, updateKind, modifiers, 0, buttonState); - } - - // Method Description: - // - Send this particular mouse event to the terminal. - // See Terminal::SendMouseEvent for more information. - // Arguments: - // - point: the PointerPoint object representing a mouse event from our XAML input handler - bool ControlInteractivity::_trySendMouseWheelEvent(const short scrollDelta, - const TerminalInput::MouseButtonState buttonState, - const ::Microsoft::Terminal::Core::ControlKeyStates modifiers, - const til::point terminalPosition) - { - return _core->SendMouseEvent(terminalPosition, WM_MOUSEWHEEL, modifiers, scrollDelta, buttonState); - } - // Method Description: // - Actually handle a scrolling event, whether from a mouse wheel or a // touchpad scroll. Depending upon what modifier keys are pressed, diff --git a/src/cascadia/TerminalControl/ControlInteractivity.h b/src/cascadia/TerminalControl/ControlInteractivity.h index 402ae74920a..ed6a4474dd2 100644 --- a/src/cascadia/TerminalControl/ControlInteractivity.h +++ b/src/cascadia/TerminalControl/ControlInteractivity.h @@ -116,14 +116,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation unsigned int _numberOfClicks(til::point clickPos, Timestamp clickTime); void _updateSystemParameterSettings() noexcept; - bool _trySendMouseEvent(const unsigned int updateKind, - const ::Microsoft::Console::VirtualTerminal::TerminalInput::MouseButtonState buttonState, - const ::Microsoft::Terminal::Core::ControlKeyStates modifiers, - const til::point terminalPosition); - bool _trySendMouseWheelEvent(const short scrollDelta, - const ::Microsoft::Console::VirtualTerminal::TerminalInput::MouseButtonState buttonState, - const ::Microsoft::Terminal::Core::ControlKeyStates modifiers, - const til::point terminalPosition); void _mouseTransparencyHandler(const double mouseDelta); void _mouseZoomHandler(const double mouseDelta); diff --git a/src/cascadia/TerminalControl/TermControl.cpp b/src/cascadia/TerminalControl/TermControl.cpp index 0bbd80dd189..b42cd01878a 100644 --- a/src/cascadia/TerminalControl/TermControl.cpp +++ b/src/cascadia/TerminalControl/TermControl.cpp @@ -65,13 +65,12 @@ namespace winrt::Microsoft::Terminal::Control::implementation _interactivity = winrt::make_self(settings, connection); _core = _interactivity->GetCore(); - // These all need weak refs - they could be triggered by the connection, - // which would happen off the UI thread. - _core->ScrollPositionChanged({ get_weak(), &TermControl::_ScrollPositionChanged }); - _core->CursorPositionChanged({ get_weak(), &TermControl::_CursorPositionChanged }); + _coreOutputEventToken = _core->ReceivedOutput({ this, &TermControl::_coreReceivedOutput }); + _core->ScrollPositionChanged({ this, &TermControl::_ScrollPositionChanged }); + _core->WarningBell({ this, &TermControl::_coreWarningBell }); + _core->CursorPositionChanged({ this, &TermControl::_CursorPositionChanged }); + _core->RendererEnteredErrorState({ get_weak(), &TermControl::_RendererEnteredErrorState }); - _core->WarningBell({ get_weak(), &TermControl::_coreWarningBell }); - _core->ReceivedOutput({ get_weak(), &TermControl::_coreReceivedOutput }); // These callbacks can only really be triggered by UI interactions. So // they don't need weak refs - they can't be triggered unless we're @@ -1709,6 +1708,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation { if (!_closing.exchange(true)) { + _core->ReceivedOutput(_coreOutputEventToken); + _RestorePointerCursorHandlers(*this, nullptr); // Disconnect the TSF input control so it doesn't receive EditContext events. diff --git a/src/cascadia/TerminalControl/TermControl.h b/src/cascadia/TerminalControl/TermControl.h index 230ace8e6a3..e63032526f1 100644 --- a/src/cascadia/TerminalControl/TermControl.h +++ b/src/cascadia/TerminalControl/TermControl.h @@ -167,6 +167,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation std::optional _cursorTimer; std::optional _blinkTimer; + event_token _coreOutputEventToken; + winrt::Windows::UI::Xaml::Controls::SwapChainPanel::LayoutUpdated_revoker _layoutUpdatedRevoker; void _UpdateSettingsFromUIThread(IControlSettings newSettings); diff --git a/src/cascadia/UnitTests_Control/ControlCoreTests.cpp b/src/cascadia/UnitTests_Control/ControlCoreTests.cpp index 1efb4a04dea..96617b513ae 100644 --- a/src/cascadia/UnitTests_Control/ControlCoreTests.cpp +++ b/src/cascadia/UnitTests_Control/ControlCoreTests.cpp @@ -19,7 +19,9 @@ namespace ControlUnitTests { class ControlCoreTests { - TEST_CLASS(ControlCoreTests) + BEGIN_TEST_CLASS(ControlCoreTests) + TEST_CLASS_PROPERTY(L"TestTimeout", L"0:0:10") // 10s timeout + END_TEST_CLASS() TEST_METHOD(ComPtrSettings); TEST_METHOD(InstantiateCore); @@ -36,6 +38,11 @@ namespace ControlUnitTests return true; } + TEST_CLASS_CLEANUP(ClassCleanup) + { + winrt::uninit_apartment(); + return true; + } std::tuple, winrt::com_ptr> _createSettingsAndConnection() { diff --git a/src/cascadia/UnitTests_Control/ControlInteractivityTests.cpp b/src/cascadia/UnitTests_Control/ControlInteractivityTests.cpp index 1f74ae809f2..9a07e94b352 100644 --- a/src/cascadia/UnitTests_Control/ControlInteractivityTests.cpp +++ b/src/cascadia/UnitTests_Control/ControlInteractivityTests.cpp @@ -21,7 +21,9 @@ namespace ControlUnitTests { class ControlInteractivityTests { - TEST_CLASS(ControlInteractivityTests) + BEGIN_TEST_CLASS(ControlInteractivityTests) + TEST_CLASS_PROPERTY(L"TestTimeout", L"0:0:10") // 10s timeout + END_TEST_CLASS() TEST_METHOD(TestAdjustAcrylic); TEST_METHOD(TestScrollWithMouse); @@ -34,6 +36,11 @@ namespace ControlUnitTests return true; } + TEST_CLASS_CLEANUP(ClassCleanup) + { + winrt::uninit_apartment(); + return true; + } std::tuple, winrt::com_ptr> From 6d5351ec2cbbfe60ebf6c7e1c9bc327b054eb6ec Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Wed, 21 Apr 2021 16:55:06 -0500 Subject: [PATCH 79/82] This is all the major blockers IMO. not like anyone will review it while I'm out lol --- .../TerminalControl/ControlInteractivity.cpp | 58 +++++++++++++------ .../TerminalControl/ControlInteractivity.h | 18 +++--- src/cascadia/TerminalControl/TermControl.cpp | 47 +++++++-------- src/cascadia/TerminalControl/TermControl.h | 2 +- .../ControlInteractivityTests.cpp | 30 ++++------ 5 files changed, 82 insertions(+), 73 deletions(-) diff --git a/src/cascadia/TerminalControl/ControlInteractivity.cpp b/src/cascadia/TerminalControl/ControlInteractivity.cpp index c7899c2e056..ecee7cc0e56 100644 --- a/src/cascadia/TerminalControl/ControlInteractivity.cpp +++ b/src/cascadia/TerminalControl/ControlInteractivity.cpp @@ -156,13 +156,14 @@ namespace winrt::Microsoft::Terminal::Control::implementation _core->PasteText(winrt::hstring{ wstr }); } - void ControlInteractivity::PointerPressed(const til::point mouseCursorPosition, - TerminalInput::MouseButtonState buttonState, + void ControlInteractivity::PointerPressed(TerminalInput::MouseButtonState buttonState, const unsigned int pointerUpdateKind, const uint64_t timestamp, const ::Microsoft::Terminal::Core::ControlKeyStates modifiers, - const til::point terminalPosition) + const til::point pixelPosition) { + const til::point terminalPosition = _getTerminalPosition(pixelPosition); + const auto altEnabled = modifiers.IsAltPressed(); const auto shiftEnabled = modifiers.IsShiftPressed(); const auto ctrlEnabled = modifiers.IsCtrlPressed(); @@ -172,7 +173,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation if (buttonState.isLeftButtonDown && ctrlEnabled && !hyperlink.empty()) { - const auto clickCount = _numberOfClicks(mouseCursorPosition, timestamp); + const auto clickCount = _numberOfClicks(pixelPosition, timestamp); // Handle hyper-link only on the first click to prevent multiple activations if (clickCount == 1) { @@ -185,7 +186,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation } else if (buttonState.isLeftButtonDown) { - const auto clickCount = _numberOfClicks(mouseCursorPosition, timestamp); + const auto clickCount = _numberOfClicks(pixelPosition, timestamp); // This formula enables the number of clicks to cycle properly // between single-, double-, and triple-click. To increase the // number of acceptable click states, simply increment @@ -195,15 +196,15 @@ namespace winrt::Microsoft::Terminal::Control::implementation // Capture the position of the first click when no selection is active if (multiClickMapper == 1) { - _singleClickTouchdownPos = mouseCursorPosition; + _singleClickTouchdownPos = pixelPosition; _singleClickTouchdownTerminalPos = terminalPosition; if (!_core->HasSelection()) { - _lastMouseClickPosNoSelection = mouseCursorPosition; + _lastMouseClickPosNoSelection = pixelPosition; } } - const bool isOnOriginalPosition = _lastMouseClickPosNoSelection == mouseCursorPosition; + const bool isOnOriginalPosition = _lastMouseClickPosNoSelection == pixelPosition; _core->LeftClickOnTerminal(terminalPosition, multiClickMapper, @@ -238,13 +239,14 @@ namespace winrt::Microsoft::Terminal::Control::implementation _touchAnchor = contactPoint; } - void ControlInteractivity::PointerMoved(const til::point mouseCursorPosition, - TerminalInput::MouseButtonState buttonState, + void ControlInteractivity::PointerMoved(TerminalInput::MouseButtonState buttonState, const unsigned int pointerUpdateKind, const ::Microsoft::Terminal::Core::ControlKeyStates modifiers, const bool focused, - const til::point terminalPosition) + const til::point pixelPosition) { + const til::point terminalPosition = _getTerminalPosition(pixelPosition); + // Short-circuit isReadOnly check to avoid warning dialog if (focused && !_core->IsInReadOnlyMode() && _canSendVTMouseInput(modifiers)) { @@ -256,8 +258,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation { // Figure out if the user's moved a quarter of a cell's smaller axis away from the clickdown point auto& touchdownPoint{ *_singleClickTouchdownPos }; - float dx = ::base::saturated_cast(mouseCursorPosition.x() - touchdownPoint.x()); - float dy = ::base::saturated_cast(mouseCursorPosition.y() - touchdownPoint.y()); + float dx = ::base::saturated_cast(pixelPosition.x() - touchdownPoint.x()); + float dy = ::base::saturated_cast(pixelPosition.y() - touchdownPoint.y()); auto distance{ std::sqrtf(std::powf(dx, 2) + std::powf(dy, 2)) }; @@ -271,7 +273,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation } } - SetEndSelectionPoint(terminalPosition); + SetEndSelectionPoint(pixelPosition); } _core->UpdateHoveredCell(terminalPosition); @@ -317,9 +319,9 @@ namespace winrt::Microsoft::Terminal::Control::implementation void ControlInteractivity::PointerReleased(TerminalInput::MouseButtonState buttonState, const unsigned int pointerUpdateKind, const ::Microsoft::Terminal::Core::ControlKeyStates modifiers, - const bool /*focused*/, - const til::point terminalPosition) + const til::point pixelPosition) { + const til::point terminalPosition = _getTerminalPosition(pixelPosition); // Short-circuit isReadOnly check to avoid warning dialog if (!_core->IsInReadOnlyMode() && _canSendVTMouseInput(modifiers)) { @@ -361,9 +363,11 @@ namespace winrt::Microsoft::Terminal::Control::implementation // - delta: the mouse wheel delta that triggered this event. bool ControlInteractivity::MouseWheel(const ::Microsoft::Terminal::Core::ControlKeyStates modifiers, const int32_t delta, - const til::point terminalPosition, + const til::point pixelPosition, const TerminalInput::MouseButtonState state) { + const til::point terminalPosition = _getTerminalPosition(pixelPosition); + // Short-circuit isReadOnly check to avoid warning dialog if (!_core->IsInReadOnlyMode() && _canSendVTMouseInput(modifiers)) { @@ -503,9 +507,25 @@ namespace winrt::Microsoft::Terminal::Control::implementation // - Sets selection's end position to match supplied cursor position, e.g. while mouse dragging. // Arguments: // - cursorPosition: in pixels, relative to the origin of the control - void ControlInteractivity::SetEndSelectionPoint(const til::point terminalPosition) + void ControlInteractivity::SetEndSelectionPoint(const til::point pixelPosition) { - _core->SetEndSelectionPoint(terminalPosition); + _core->SetEndSelectionPoint(_getTerminalPosition(pixelPosition)); _selectionNeedsToBeCopied = true; } + + // Method Description: + // - Gets the corresponding viewport terminal position for the point in + // pixels, by normalizing with the font size. + // Arguments: + // - pixelPosition: the (x,y) position of a given point (i.e.: mouse cursor). + // NOTE: origin (0,0) is top-left. + // Return Value: + // - the corresponding viewport terminal position for the given Point parameter + til::point ControlInteractivity::_getTerminalPosition(const til::point& pixelPosition) + { + // Get the size of the font, which is in pixels + const til::size fontSize{ _core->GetFont().GetSize() }; + // Convert the location in pixels to characters within the current viewport. + return til::point{ pixelPosition / fontSize }; + } } diff --git a/src/cascadia/TerminalControl/ControlInteractivity.h b/src/cascadia/TerminalControl/ControlInteractivity.h index ed6a4474dd2..cd099dff3a4 100644 --- a/src/cascadia/TerminalControl/ControlInteractivity.h +++ b/src/cascadia/TerminalControl/ControlInteractivity.h @@ -48,40 +48,37 @@ namespace winrt::Microsoft::Terminal::Control::implementation winrt::com_ptr GetCore(); #pragma region Input Methods - void PointerPressed(const til::point mouseCursorPosition, - ::Microsoft::Console::VirtualTerminal::TerminalInput::MouseButtonState buttonState, + void PointerPressed(::Microsoft::Console::VirtualTerminal::TerminalInput::MouseButtonState buttonState, const unsigned int pointerUpdateKind, const uint64_t timestamp, const ::Microsoft::Terminal::Core::ControlKeyStates modifiers, - const til::point terminalPosition); + const til::point pixelPosition); void TouchPressed(const til::point contactPoint); - void PointerMoved(const til::point mouseCursorPosition, - ::Microsoft::Console::VirtualTerminal::TerminalInput::MouseButtonState buttonState, + void PointerMoved(::Microsoft::Console::VirtualTerminal::TerminalInput::MouseButtonState buttonState, const unsigned int pointerUpdateKind, const ::Microsoft::Terminal::Core::ControlKeyStates modifiers, const bool focused, - const til::point terminalPosition); + const til::point pixelPosition); void TouchMoved(const til::point newTouchPoint, const bool focused); void PointerReleased(::Microsoft::Console::VirtualTerminal::TerminalInput::MouseButtonState buttonState, const unsigned int pointerUpdateKind, const ::Microsoft::Terminal::Core::ControlKeyStates modifiers, - const bool focused, - const til::point terminalPosition); + const til::point pixelPosition); void TouchReleased(); bool MouseWheel(const ::Microsoft::Terminal::Core::ControlKeyStates modifiers, const int32_t delta, - const til::point terminalPosition, + const til::point pixelPosition, const ::Microsoft::Console::VirtualTerminal::TerminalInput::MouseButtonState state); #pragma endregion bool CopySelectionToClipboard(bool singleLine, const Windows::Foundation::IReference& formats); void RequestPasteTextFromClipboard(); - void SetEndSelectionPoint(const til::point terminalPosition); + void SetEndSelectionPoint(const til::point pixelPosition); private: winrt::com_ptr _core{ nullptr }; @@ -128,6 +125,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation void _sendPastedTextToConnection(std::wstring_view wstr); void _updateScrollbar(const int newValue); + til::point _getTerminalPosition(const til::point& pixelPosition); TYPED_EVENT(OpenHyperlink, IInspectable, Control::OpenHyperlinkEventArgs); TYPED_EVENT(PasteFromClipboard, IInspectable, Control::PasteFromClipboardEventArgs); diff --git a/src/cascadia/TerminalControl/TermControl.cpp b/src/cascadia/TerminalControl/TermControl.cpp index b42cd01878a..7004271ccfa 100644 --- a/src/cascadia/TerminalControl/TermControl.cpp +++ b/src/cascadia/TerminalControl/TermControl.cpp @@ -65,11 +65,18 @@ namespace winrt::Microsoft::Terminal::Control::implementation _interactivity = winrt::make_self(settings, connection); _core = _interactivity->GetCore(); + // Use a manual revoker on the output event, so we can immediately stop + // worrying about it on destruction. _coreOutputEventToken = _core->ReceivedOutput({ this, &TermControl::_coreReceivedOutput }); + + // These events might all be triggered by the connection, but that + // should be drained and closed before we complete destruction. So these + // are safe. _core->ScrollPositionChanged({ this, &TermControl::_ScrollPositionChanged }); _core->WarningBell({ this, &TermControl::_coreWarningBell }); _core->CursorPositionChanged({ this, &TermControl::_CursorPositionChanged }); + // This event is specifically triggered by the renderer thread, a BG thread. Use a weak ref here. _core->RendererEnteredErrorState({ get_weak(), &TermControl::_RendererEnteredErrorState }); // These callbacks can only really be triggered by UI interactions. So @@ -388,10 +395,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation { _InitializeBackgroundBrush(); - // TODO!: I added the following, do we still need it? const auto bg = newSettings.DefaultBackground(); _changeBackgroundColor(bg); - // // Apply padding as swapChainPanel's margin auto newMargin = _ParseThicknessFromPadding(newSettings.Padding()); @@ -1049,12 +1054,11 @@ namespace winrt::Microsoft::Terminal::Control::implementation else { const auto cursorPosition = point.Position(); - _interactivity->PointerPressed(til::point{ til::math::rounding, cursorPosition }, - TermControl::GetPressedMouseButtons(point), + _interactivity->PointerPressed(TermControl::GetPressedMouseButtons(point), TermControl::GetPointerUpdateKind(point), point.Timestamp(), ControlKeyStates{ args.KeyModifiers() }, - _GetTerminalPosition(cursorPosition)); + _toTerminalOrigin(cursorPosition)); } args.Handled(true); @@ -1078,7 +1082,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation const auto ptr = args.Pointer(); const auto point = args.GetCurrentPoint(*this); const auto cursorPosition = point.Position(); - const auto terminalPosition = _GetTerminalPosition(cursorPosition); + const auto pixelPosition = _toTerminalOrigin(cursorPosition); const auto type = ptr.PointerDeviceType(); if (!_focused && _settings.FocusFollowMouse()) @@ -1089,12 +1093,11 @@ namespace winrt::Microsoft::Terminal::Control::implementation if (type == Windows::Devices::Input::PointerDeviceType::Mouse || type == Windows::Devices::Input::PointerDeviceType::Pen) { - _interactivity->PointerMoved(til::point{ til::math::rounding, cursorPosition }, - TermControl::GetPressedMouseButtons(point), + _interactivity->PointerMoved(TermControl::GetPressedMouseButtons(point), TermControl::GetPointerUpdateKind(point), ControlKeyStates(args.KeyModifiers()), _focused, - terminalPosition); + pixelPosition); if (_focused && point.Properties().IsLeftButtonPressed()) { @@ -1150,7 +1153,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation const auto ptr = args.Pointer(); const auto point = args.GetCurrentPoint(*this); const auto cursorPosition = point.Position(); - const auto terminalPosition = _GetTerminalPosition(cursorPosition); + const auto pixelPosition = _toTerminalOrigin(cursorPosition); const auto type = ptr.PointerDeviceType(); _ReleasePointerCapture(sender, args); @@ -1161,8 +1164,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation _interactivity->PointerReleased(TermControl::GetPressedMouseButtons(point), TermControl::GetPointerUpdateKind(point), ControlKeyStates(args.KeyModifiers()), - _focused, - terminalPosition); + pixelPosition); } else if (type == Windows::Devices::Input::PointerDeviceType::Touch) { @@ -1196,7 +1198,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation auto result = _interactivity->MouseWheel(ControlKeyStates{ args.KeyModifiers() }, point.Properties().MouseWheelDelta(), - _GetTerminalPosition(point.Position()), + _toTerminalOrigin(point.Position()), TermControl::GetPressedMouseButtons(point)); if (result) { @@ -1224,7 +1226,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation TerminalInput::MouseButtonState state{ leftButtonDown, midButtonDown, rightButtonDown }; - return _interactivity->MouseWheel(modifiers, delta, _GetTerminalPosition(location), state); + return _interactivity->MouseWheel(modifiers, delta, _toTerminalOrigin(location), state); } // Method Description: @@ -1614,7 +1616,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation // - cursorPosition: in pixels, relative to the origin of the control void TermControl::_SetEndSelectionPointAtCursor(Windows::Foundation::Point const& cursorPosition) { - _interactivity->SetEndSelectionPoint(_GetTerminalPosition(cursorPosition)); + _interactivity->SetEndSelectionPoint(_toTerminalOrigin(cursorPosition)); } // Method Description: @@ -2044,15 +2046,14 @@ namespace winrt::Microsoft::Terminal::Control::implementation } // Method Description: - // - Gets the corresponding viewport terminal position for the cursor - // by excluding the padding and normalizing with the font size. - // This is used for selection. + // - Gets the corresponding viewport pixel position for the cursor + // by excluding the padding. // Arguments: // - cursorPosition: the (x,y) position of a given cursor (i.e.: mouse cursor). // NOTE: origin (0,0) is top-left. // Return Value: - // - the corresponding viewport terminal position for the given Point parameter - const til::point TermControl::_GetTerminalPosition(winrt::Windows::Foundation::Point cursorPosition) + // - the corresponding viewport terminal position (in pixels) for the given Point parameter + const til::point TermControl::_toTerminalOrigin(winrt::Windows::Foundation::Point cursorPosition) { // cursorPosition is DIPs, relative to SwapChainPanel origin const til::point cursorPosInDIPs{ til::math::rounding, cursorPosition }; @@ -2064,11 +2065,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation // Convert it to pixels const til::point relativeToMarginInPixels{ relativeToMarginInDIPs * SwapChainPanel().CompositionScaleX() }; - // Get the size of the font, which is in pixels - const til::size fontSize{ _core->GetFont().GetSize() }; - - // Convert the location in pixels to characters within the current viewport. - return til::point{ relativeToMarginInPixels / fontSize }; + return relativeToMarginInPixels; } // Method Description: diff --git a/src/cascadia/TerminalControl/TermControl.h b/src/cascadia/TerminalControl/TermControl.h index e63032526f1..54fd49c37f2 100644 --- a/src/cascadia/TerminalControl/TermControl.h +++ b/src/cascadia/TerminalControl/TermControl.h @@ -228,7 +228,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation void _ClearKeyboardState(const WORD vkey, const WORD scanCode) const noexcept; bool _TrySendKeyEvent(const WORD vkey, const WORD scanCode, ::Microsoft::Terminal::Core::ControlKeyStates modifiers, const bool keyDown); - const til::point _GetTerminalPosition(winrt::Windows::Foundation::Point cursorPosition); + const til::point _toTerminalOrigin(winrt::Windows::Foundation::Point cursorPosition); double _GetAutoScrollSpeed(double cursorDistanceFromBorder) const; void _Search(const winrt::hstring& text, const bool goForward, const bool caseSensitive); diff --git a/src/cascadia/UnitTests_Control/ControlInteractivityTests.cpp b/src/cascadia/UnitTests_Control/ControlInteractivityTests.cpp index 9a07e94b352..eeb9825475f 100644 --- a/src/cascadia/UnitTests_Control/ControlInteractivityTests.cpp +++ b/src/cascadia/UnitTests_Control/ControlInteractivityTests.cpp @@ -258,17 +258,16 @@ namespace ControlUnitTests const TerminalInput::MouseButtonState leftMouseDown{ true, false, false }; const TerminalInput::MouseButtonState noMouseDown{ false, false, false }; - const til::size fontSize{ 9, 19 }; + const til::size fontSize{ 9, 21 }; Log::Comment(L"Click on the terminal"); const til::point terminalPosition0{ 0, 0 }; const til::point cursorPosition0 = terminalPosition0 * fontSize; - interactivity->PointerPressed(cursorPosition0, - leftMouseDown, + interactivity->PointerPressed(leftMouseDown, WM_LBUTTONDOWN, //pointerUpdateKind 0, // timestamp modifiers, - terminalPosition0); + cursorPosition0); Log::Comment(L"Verify that there's not yet a selection"); VERIFY_IS_FALSE(core->HasSelection()); @@ -277,12 +276,11 @@ namespace ControlUnitTests // move not quite a whole cell, but enough to start a selection const til::point terminalPosition1{ 0, 0 }; const til::point cursorPosition1{ 6, 0 }; - interactivity->PointerMoved(cursorPosition1, - leftMouseDown, + interactivity->PointerMoved(leftMouseDown, WM_LBUTTONDOWN, //pointerUpdateKind modifiers, true, // focused, - terminalPosition1); + cursorPosition1); Log::Comment(L"Verify that there's one selection"); VERIFY_IS_TRUE(core->HasSelection()); VERIFY_ARE_EQUAL(1u, core->_terminal->GetSelectionRects().size()); @@ -290,12 +288,11 @@ namespace ControlUnitTests Log::Comment(L"Drag the mouse down a whole row"); const til::point terminalPosition2{ 1, 1 }; const til::point cursorPosition2 = terminalPosition2 * fontSize; - interactivity->PointerMoved(cursorPosition2, - leftMouseDown, + interactivity->PointerMoved(leftMouseDown, WM_LBUTTONDOWN, //pointerUpdateKind modifiers, true, // focused, - terminalPosition2); + cursorPosition2); Log::Comment(L"Verify that there's now two selections (one on each row)"); VERIFY_IS_TRUE(core->HasSelection()); VERIFY_ARE_EQUAL(2u, core->_terminal->GetSelectionRects().size()); @@ -304,8 +301,7 @@ namespace ControlUnitTests interactivity->PointerReleased(noMouseDown, WM_LBUTTONUP, //pointerUpdateKind modifiers, - true, // focused, - terminalPosition2); + cursorPosition2); Log::Comment(L"Verify that there's still two selections"); VERIFY_IS_TRUE(core->HasSelection()); VERIFY_ARE_EQUAL(2u, core->_terminal->GetSelectionRects().size()); @@ -313,12 +309,11 @@ namespace ControlUnitTests Log::Comment(L"click outside the current selection"); const til::point terminalPosition3{ 2, 2 }; const til::point cursorPosition3 = terminalPosition3 * fontSize; - interactivity->PointerPressed(cursorPosition3, - leftMouseDown, + interactivity->PointerPressed(leftMouseDown, WM_LBUTTONDOWN, //pointerUpdateKind 0, // timestamp modifiers, - terminalPosition3); + cursorPosition3); Log::Comment(L"Verify that there's now no selection"); VERIFY_IS_FALSE(core->HasSelection()); VERIFY_ARE_EQUAL(0u, core->_terminal->GetSelectionRects().size()); @@ -326,12 +321,11 @@ namespace ControlUnitTests Log::Comment(L"Drag the mouse"); const til::point terminalPosition4{ 3, 2 }; const til::point cursorPosition4 = terminalPosition4 * fontSize; - interactivity->PointerMoved(cursorPosition4, - leftMouseDown, + interactivity->PointerMoved(leftMouseDown, WM_LBUTTONDOWN, //pointerUpdateKind modifiers, true, // focused, - terminalPosition4); + cursorPosition4); Log::Comment(L"Verify that there's now one selection"); VERIFY_IS_TRUE(core->HasSelection()); VERIFY_ARE_EQUAL(1u, core->_terminal->GetSelectionRects().size()); From efbec1f9fbb4a724f26402b7724afbd2b99162f0 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Fri, 23 Apr 2021 11:06:41 -0500 Subject: [PATCH 80/82] Leonard is right, this is better --- src/cascadia/TerminalApp/TerminalPage.cpp | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp index 16e1195f646..0979a25769a 100644 --- a/src/cascadia/TerminalApp/TerminalPage.cpp +++ b/src/cascadia/TerminalApp/TerminalPage.cpp @@ -1048,15 +1048,10 @@ namespace winrt::TerminalApp::implementation } }); - hostingTab.TaskbarProgressChanged([weakThis](const auto& s, const auto& args) { - if (auto page{ weakThis.get() }) - { - page->_SetTaskbarProgressHandler(s, args); - } - }); - - // Add an event handler for when the terminal wants to set a progress indicator on the taskbar - term.SetTaskbarProgress({ this, &TerminalPage::_SetTaskbarProgressHandler }); + // Add an event handler for when the terminal or tab wants to set a + // progress indicator on the taskbar + hostingTab.TaskbarProgressChanged({ get_weak(), &TerminalPage::_SetTaskbarProgressHandler }); + term.SetTaskbarProgress({ get_weak(), &TerminalPage::_SetTaskbarProgressHandler }); // TODO GH#3327: Once we support colorizing the NewTab button based on // the color of the tab, we'll want to make sure to call From 0f62cea5e8cb29e1144737aa2c0f72692e558861 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Mon, 26 Apr 2021 09:19:17 -0500 Subject: [PATCH 81/82] LOAD BEARING COMMIT --- src/cascadia/TerminalControl/ControlCore.cpp | 22 +++++++++++++++----- src/cascadia/TerminalControl/ControlCore.h | 1 + src/cascadia/TerminalControl/TermControl.cpp | 15 ++++++++----- 3 files changed, 28 insertions(+), 10 deletions(-) diff --git a/src/cascadia/TerminalControl/ControlCore.cpp b/src/cascadia/TerminalControl/ControlCore.cpp index d66a59b8a9d..46775a70310 100644 --- a/src/cascadia/TerminalControl/ControlCore.cpp +++ b/src/cascadia/TerminalControl/ControlCore.cpp @@ -205,11 +205,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation THROW_IF_FAILED(dxEngine->Enable()); _renderEngine = std::move(dxEngine); - // In the past we did _attachDxgiSwapChainToXaml _before_ calling - // EnablePainting. There's mild worry that doing EnablePainting - // first will break something, but this seems to work. - localPointerToThread->EnablePainting(); - _initializedTerminal = true; } // scope for TerminalLock @@ -219,6 +214,23 @@ namespace winrt::Microsoft::Terminal::Control::implementation return true; } + + // Method Description: + // - Tell the renderer to start painting. + // - !! IMPORTANT !! Make sure that we've attached our swap chain to an + // actual target before calling this. + // Arguments: + // - + // Return Value: + // - + void ControlCore::EnablePainting() + { + if (_initializedTerminal) + { + _renderer->EnablePainting(); + } + } + // Method Description: // - Writes the given sequence as input to the active terminal connection. // - This method has been overloaded to allow zero-copy winrt::param::hstring optimizations. diff --git a/src/cascadia/TerminalControl/ControlCore.h b/src/cascadia/TerminalControl/ControlCore.h index 7718b14fd12..8ab58a2243d 100644 --- a/src/cascadia/TerminalControl/ControlCore.h +++ b/src/cascadia/TerminalControl/ControlCore.h @@ -43,6 +43,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation bool Initialize(const double actualWidth, const double actualHeight, const double compositionScale); + void EnablePainting(); void UpdateSettings(const IControlSettings& settings); void UpdateAppearance(const IControlAppearance& newAppearance); diff --git a/src/cascadia/TerminalControl/TermControl.cpp b/src/cascadia/TerminalControl/TermControl.cpp index 7004271ccfa..5346d0507c9 100644 --- a/src/cascadia/TerminalControl/TermControl.cpp +++ b/src/cascadia/TerminalControl/TermControl.cpp @@ -673,6 +673,16 @@ namespace winrt::Microsoft::Terminal::Control::implementation // callbacks (and locking problems) _core->SwapChainChanged({ get_weak(), &TermControl::RenderEngineSwapChainChanged }); + // !! LOAD BEARING !! + // Make sure you enable painting _AFTER_ calling _AttachDxgiSwapChainToXaml + // + // If you EnablePainting first, then you almost certainly won't have any + // problems when running in Debug. However, in Release, you'll run into + // issues where the Renderer starts trying to paint before we've + // actually attached the swapchain to anything, and the DxEngine is not + // prepared to handle that. + _core->EnablePainting(); + auto bufferHeight = _core->BufferHeight(); ScrollBar().Maximum(bufferHeight - bufferHeight); @@ -681,11 +691,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation ScrollBar().ViewportSize(bufferHeight); ScrollBar().LargeChange(std::max(bufferHeight - 1, 0)); // scroll one "screenful" at a time when the scroll bar is clicked - // Mild worry that doing EnablePainting in Core::InitializeTerminal, - // before we _AttachDxgiSwapChainToXaml will break - // - // localPointerToThread->EnablePainting(); - // Set up blinking cursor int blinkTime = GetCaretBlinkTime(); if (blinkTime != INFINITE) From 973163652bafa2f514e657c7e79fab0dfa1392ab Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Tue, 27 Apr 2021 05:20:01 -0500 Subject: [PATCH 82/82] an update from main --- src/cascadia/UnitTests_Control/MockControlSettings.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/cascadia/UnitTests_Control/MockControlSettings.h b/src/cascadia/UnitTests_Control/MockControlSettings.h index 6d906755f62..06392d440d4 100644 --- a/src/cascadia/UnitTests_Control/MockControlSettings.h +++ b/src/cascadia/UnitTests_Control/MockControlSettings.h @@ -40,6 +40,8 @@ namespace ControlUnitTests WINRT_PROPERTY(winrt::Windows::Foundation::IReference, StartingTabColor, nullptr); winrt::Microsoft::Terminal::Core::ICoreAppearance UnfocusedAppearance() { return {}; }; + + WINRT_PROPERTY(bool, TrimBlockSelection, false); // ------------------------ End of Core Settings ----------------------- WINRT_PROPERTY(winrt::hstring, ProfileName);