terminal/src/cascadia/TerminalCore/TerminalSelection.cpp

518 lines
18 KiB
C++
Raw Normal View History

2019-06-19 00:53:29 +02:00
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#include "pch.h"
#include "Terminal.hpp"
#include "unicode.hpp"
2019-06-19 00:53:29 +02:00
using namespace Microsoft::Terminal::Core;
Move rect expansion to textbuffer; refactor selection code (#4560) - When performing chunk selection, the expansion now occurs at the time of the selection, not the rendering of the selection - `GetSelectionRects()` was moved to the `TextBuffer` and is now shared between ConHost and Windows Terminal - Some of the selection variables were renamed for clarity - Selection COORDs are now in the Text Buffer coordinate space - Fixes an issue with Shift+Click after performing a Multi-Click Selection ## References This also contributes to... - #4509: UIA Box Selection - #2447: UIA Signaling for Selection - #1354: UIA support for Wide Glyphs Now that the expansion occurs at before render-time, the selection anchors are an accurate representation of what is selected. We just need to move `GetText` to the `TextBuffer`. Then we can have those three issues just rely on code from the text buffer. This also means ConHost gets some of this stuff for free 😀 ### TextBuffer - `GetTextRects` is the abstracted form of `GetSelectionRects` - `_ExpandTextRow` is still needed to handle wide glyphs properly ### Terminal - Rename... - `_boxSelection` --> `_blockSelection` for consistency with ConHost - `_selectionAnchor` --> `_selectionStart` for consistency with UIA - `_endSelectionPosition` --> `_selectionEnd` for consistency with UIA - Selection anchors are in Text Buffer coordinates now - Really rely on `SetSelectionEnd` to accomplish appropriate chunk selection and shift+click actions ## Validation Steps Performed - Shift+Click - Multi-Click --> Shift+Click - Chunk Selection at... - top of buffer - bottom of buffer - random region in scrollback Closes #4465 Closes #4547
2020-02-28 01:42:26 +01:00
/* Selection Pivot Description:
* The pivot helps properly update the selection when a user moves a selection over itself
* See SelectionTest::DoubleClickDrag_Left for an example of the functionality mentioned here
* As an example, consider the following scenario...
* 1. Perform a word selection (double-click) on a word
*
* |-position where we double-clicked
* _|_
* |word|
* |--|
Move rect expansion to textbuffer; refactor selection code (#4560) - When performing chunk selection, the expansion now occurs at the time of the selection, not the rendering of the selection - `GetSelectionRects()` was moved to the `TextBuffer` and is now shared between ConHost and Windows Terminal - Some of the selection variables were renamed for clarity - Selection COORDs are now in the Text Buffer coordinate space - Fixes an issue with Shift+Click after performing a Multi-Click Selection ## References This also contributes to... - #4509: UIA Box Selection - #2447: UIA Signaling for Selection - #1354: UIA support for Wide Glyphs Now that the expansion occurs at before render-time, the selection anchors are an accurate representation of what is selected. We just need to move `GetText` to the `TextBuffer`. Then we can have those three issues just rely on code from the text buffer. This also means ConHost gets some of this stuff for free 😀 ### TextBuffer - `GetTextRects` is the abstracted form of `GetSelectionRects` - `_ExpandTextRow` is still needed to handle wide glyphs properly ### Terminal - Rename... - `_boxSelection` --> `_blockSelection` for consistency with ConHost - `_selectionAnchor` --> `_selectionStart` for consistency with UIA - `_endSelectionPosition` --> `_selectionEnd` for consistency with UIA - Selection anchors are in Text Buffer coordinates now - Really rely on `SetSelectionEnd` to accomplish appropriate chunk selection and shift+click actions ## Validation Steps Performed - Shift+Click - Multi-Click --> Shift+Click - Chunk Selection at... - top of buffer - bottom of buffer - random region in scrollback Closes #4465 Closes #4547
2020-02-28 01:42:26 +01:00
* start & pivot-| |-end
*
* 2. Drag your mouse down a line
*
*
* start & pivot-|__________
Move rect expansion to textbuffer; refactor selection code (#4560) - When performing chunk selection, the expansion now occurs at the time of the selection, not the rendering of the selection - `GetSelectionRects()` was moved to the `TextBuffer` and is now shared between ConHost and Windows Terminal - Some of the selection variables were renamed for clarity - Selection COORDs are now in the Text Buffer coordinate space - Fixes an issue with Shift+Click after performing a Multi-Click Selection ## References This also contributes to... - #4509: UIA Box Selection - #2447: UIA Signaling for Selection - #1354: UIA support for Wide Glyphs Now that the expansion occurs at before render-time, the selection anchors are an accurate representation of what is selected. We just need to move `GetText` to the `TextBuffer`. Then we can have those three issues just rely on code from the text buffer. This also means ConHost gets some of this stuff for free 😀 ### TextBuffer - `GetTextRects` is the abstracted form of `GetSelectionRects` - `_ExpandTextRow` is still needed to handle wide glyphs properly ### Terminal - Rename... - `_boxSelection` --> `_blockSelection` for consistency with ConHost - `_selectionAnchor` --> `_selectionStart` for consistency with UIA - `_endSelectionPosition` --> `_selectionEnd` for consistency with UIA - Selection anchors are in Text Buffer coordinates now - Really rely on `SetSelectionEnd` to accomplish appropriate chunk selection and shift+click actions ## Validation Steps Performed - Shift+Click - Multi-Click --> Shift+Click - Chunk Selection at... - top of buffer - bottom of buffer - random region in scrollback Closes #4465 Closes #4547
2020-02-28 01:42:26 +01:00
* __|word_______|
* |______|
Move rect expansion to textbuffer; refactor selection code (#4560) - When performing chunk selection, the expansion now occurs at the time of the selection, not the rendering of the selection - `GetSelectionRects()` was moved to the `TextBuffer` and is now shared between ConHost and Windows Terminal - Some of the selection variables were renamed for clarity - Selection COORDs are now in the Text Buffer coordinate space - Fixes an issue with Shift+Click after performing a Multi-Click Selection ## References This also contributes to... - #4509: UIA Box Selection - #2447: UIA Signaling for Selection - #1354: UIA support for Wide Glyphs Now that the expansion occurs at before render-time, the selection anchors are an accurate representation of what is selected. We just need to move `GetText` to the `TextBuffer`. Then we can have those three issues just rely on code from the text buffer. This also means ConHost gets some of this stuff for free 😀 ### TextBuffer - `GetTextRects` is the abstracted form of `GetSelectionRects` - `_ExpandTextRow` is still needed to handle wide glyphs properly ### Terminal - Rename... - `_boxSelection` --> `_blockSelection` for consistency with ConHost - `_selectionAnchor` --> `_selectionStart` for consistency with UIA - `_endSelectionPosition` --> `_selectionEnd` for consistency with UIA - Selection anchors are in Text Buffer coordinates now - Really rely on `SetSelectionEnd` to accomplish appropriate chunk selection and shift+click actions ## Validation Steps Performed - Shift+Click - Multi-Click --> Shift+Click - Chunk Selection at... - top of buffer - bottom of buffer - random region in scrollback Closes #4465 Closes #4547
2020-02-28 01:42:26 +01:00
* |
* |-end & mouse position
*
* 3. Drag your mouse up two lines
*
* |-start & mouse position
* |________
* ____| ______|
* |___w|ord
Move rect expansion to textbuffer; refactor selection code (#4560) - When performing chunk selection, the expansion now occurs at the time of the selection, not the rendering of the selection - `GetSelectionRects()` was moved to the `TextBuffer` and is now shared between ConHost and Windows Terminal - Some of the selection variables were renamed for clarity - Selection COORDs are now in the Text Buffer coordinate space - Fixes an issue with Shift+Click after performing a Multi-Click Selection ## References This also contributes to... - #4509: UIA Box Selection - #2447: UIA Signaling for Selection - #1354: UIA support for Wide Glyphs Now that the expansion occurs at before render-time, the selection anchors are an accurate representation of what is selected. We just need to move `GetText` to the `TextBuffer`. Then we can have those three issues just rely on code from the text buffer. This also means ConHost gets some of this stuff for free 😀 ### TextBuffer - `GetTextRects` is the abstracted form of `GetSelectionRects` - `_ExpandTextRow` is still needed to handle wide glyphs properly ### Terminal - Rename... - `_boxSelection` --> `_blockSelection` for consistency with ConHost - `_selectionAnchor` --> `_selectionStart` for consistency with UIA - `_endSelectionPosition` --> `_selectionEnd` for consistency with UIA - Selection anchors are in Text Buffer coordinates now - Really rely on `SetSelectionEnd` to accomplish appropriate chunk selection and shift+click actions ## Validation Steps Performed - Shift+Click - Multi-Click --> Shift+Click - Chunk Selection at... - top of buffer - bottom of buffer - random region in scrollback Closes #4465 Closes #4547
2020-02-28 01:42:26 +01:00
* |-end & pivot
*
* The pivot never moves until a new selection is created. It ensures that that cell will always be selected.
*/
2019-06-19 00:53:29 +02:00
// Method Description:
// - Helper to determine the selected region of the buffer. Used for rendering.
// Return Value:
// - A vector of rectangles representing the regions to select, line by line. They are absolute coordinates relative to the buffer origin.
std::vector<SMALL_RECT> Terminal::_GetSelectionRects() const noexcept
2019-06-19 00:53:29 +02:00
{
std::vector<SMALL_RECT> result;
2019-06-19 00:53:29 +02:00
if (!IsSelectionActive())
2019-06-19 00:53:29 +02:00
{
return result;
2019-06-19 00:53:29 +02:00
}
try
{
Add support for double-width/double-height lines in conhost (#8664) This PR adds support for the VT line rendition attributes, which allow for double-width and double-height line renditions. These renditions are enabled with the `DECDWL` (double-width line) and `DECDHL` (double-height line) escape sequences. Both reset to the default rendition with the `DECSWL` (single-width line) escape sequence. For now this functionality is only supported by the GDI renderer in conhost. There are a lot of changes, so this is just a general overview of the main areas affected. Previously it was safe to assume that the screen had a fixed width, at least for a given point in time. But now we need to deal with the possibility of different lines have different widths, so all the functions that are constrained by the right border (text wrapping, cursor movement operations, and sequences like `EL` and `ICH`) now need to lookup the width of the active line in order to behave correctly. Similarly it used to be safe to assume that buffer and screen coordinates were the same thing, but that is no longer true. Lots of places now need to translate back and forth between coordinate systems dependent on the line rendition. This includes clipboard handling, the conhost color selection and search, accessibility location tracking and screen reading, IME editor positioning, "snapping" the viewport, and of course all the rendering calculations. For the rendering itself, I've had to introduce a new `PrepareLineTransform` method that the render engines can use to setup the necessary transform matrix for a given line rendition. This is also now used to handle the horizontal viewport offset, since that could no longer be achieved just by changing the target coordinates (on a double width line, the viewport offset may be halfway through a character). I've also had to change the renderer's existing `InvalidateCursor` method to take a `SMALL_RECT` rather than a `COORD`, to allow for the cursor being a variable width. Technically this was already a problem, because the cursor could occupy two screen cells when over a double-width character, but now it can be anything between one and four screen cells (e.g. a double-width character on the double-width line). In terms of architectural changes, there is now a new `lineRendition` field in the `ROW` class that keeps track of the line rendition for each row, and several new methods in the `ROW` and `TextBuffer` classes for manipulating that state. This includes a few helper methods for handling the various issues discussed above, e.g. position clamping and translating between coordinate systems. ## Validation Steps Performed I've manually confirmed all the double-width and double-height tests in _Vttest_ are now working as expected, and the _VT100 Torture Test_ now renders correctly (at least the line rendition aspects). I've also got my own test scripts that check many of the line rendition boundary cases and have confirmed that those are now passing. I've manually tested as many areas of the conhost UI that I could think of, that might be affected by line rendition, including things like searching, selection, copying, and color highlighting. For accessibility, I've confirmed that the _Magnifier_ and _Narrator_ correctly handle double-width lines. And I've also tested the Japanese IME, which while not perfect, is at least useable. Closes #7865
2021-02-18 06:44:50 +01:00
return _buffer->GetTextRects(_selection->start, _selection->end, _blockSelection, false);
}
CATCH_LOG();
return result;
}
// Method Description:
Search - add search box control and implement search experience (#3590) <!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? --> This is the PR for feature Search: #605 This PR includes the newly introduced SearchBoxControl in TermControl dir, which is the search bar for the search experience. And the codes that enable Search in Windows Terminal. <!-- Other than the issue solved, is this relevant to any other issues/existing PRs? --> The PR that migrates the Conhost search module: https://github.com/microsoft/terminal/pull/3279 Spec (still actively updating): https://github.com/microsoft/terminal/pull/3299 <!-- Please review the items on the PR checklist before submitting--> ## PR Checklist * [x] Closes #605 * [ ] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA * [ ] Tests added/passed * [ ] Requires documentation to be updated * [ ] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #xxx <!-- Provide a more detailed description of the PR, other things fixed or any additional comments/features here --> These functionalities are included in the search experience. 1. Search in Terminal text buffer. 2. Automatic wrap-around. 3. Search up or down switch by clicking different buttons. 4. Search case sensitively/insensitively by clicking a button. S. Move the search box to the top/bottom by clicking a button. 6. Close by clicking 'X'. 7. Open search by ctrl + F. When the searchbox is open, the user could still interact with the terminal by clicking the terminal input area. While I already have the search functionalities, currently there are still some known to-do works and I will keep updating my PR: 1. Optimize the search box UI, this includes: 1) Theme adaptation. The search box background and font color should change according to the theme, 2) Add background. Currently the elements in search box are all transparent. However, we need a background. 3) Move button should be highlighted once clicked. 2. Accessibility: search process should be able to performed without mouse. Once the search box is focused, the user should be able to navigate between all interactive elements on the searchbox using keyboard. <!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well --> To test: 1. checkout this branch. 2. Build the project. 3. Start Windows Terminal and press Ctrl+F 4. The search box should appear on the top right corner.
2019-12-17 16:52:37 +01:00
// - Get the current anchor position relative to the whole text buffer
// Arguments:
// - None
// Return Value:
// - None
const COORD Terminal::GetSelectionAnchor() const noexcept
{
Move rect expansion to textbuffer; refactor selection code (#4560) - When performing chunk selection, the expansion now occurs at the time of the selection, not the rendering of the selection - `GetSelectionRects()` was moved to the `TextBuffer` and is now shared between ConHost and Windows Terminal - Some of the selection variables were renamed for clarity - Selection COORDs are now in the Text Buffer coordinate space - Fixes an issue with Shift+Click after performing a Multi-Click Selection ## References This also contributes to... - #4509: UIA Box Selection - #2447: UIA Signaling for Selection - #1354: UIA support for Wide Glyphs Now that the expansion occurs at before render-time, the selection anchors are an accurate representation of what is selected. We just need to move `GetText` to the `TextBuffer`. Then we can have those three issues just rely on code from the text buffer. This also means ConHost gets some of this stuff for free 😀 ### TextBuffer - `GetTextRects` is the abstracted form of `GetSelectionRects` - `_ExpandTextRow` is still needed to handle wide glyphs properly ### Terminal - Rename... - `_boxSelection` --> `_blockSelection` for consistency with ConHost - `_selectionAnchor` --> `_selectionStart` for consistency with UIA - `_endSelectionPosition` --> `_selectionEnd` for consistency with UIA - Selection anchors are in Text Buffer coordinates now - Really rely on `SetSelectionEnd` to accomplish appropriate chunk selection and shift+click actions ## Validation Steps Performed - Shift+Click - Multi-Click --> Shift+Click - Chunk Selection at... - top of buffer - bottom of buffer - random region in scrollback Closes #4465 Closes #4547
2020-02-28 01:42:26 +01:00
return _selection->start;
}
// Method Description:
// - Get the current end anchor position relative to the whole text buffer
// Arguments:
// - None
// Return Value:
// - None
Move rect expansion to textbuffer; refactor selection code (#4560) - When performing chunk selection, the expansion now occurs at the time of the selection, not the rendering of the selection - `GetSelectionRects()` was moved to the `TextBuffer` and is now shared between ConHost and Windows Terminal - Some of the selection variables were renamed for clarity - Selection COORDs are now in the Text Buffer coordinate space - Fixes an issue with Shift+Click after performing a Multi-Click Selection ## References This also contributes to... - #4509: UIA Box Selection - #2447: UIA Signaling for Selection - #1354: UIA support for Wide Glyphs Now that the expansion occurs at before render-time, the selection anchors are an accurate representation of what is selected. We just need to move `GetText` to the `TextBuffer`. Then we can have those three issues just rely on code from the text buffer. This also means ConHost gets some of this stuff for free 😀 ### TextBuffer - `GetTextRects` is the abstracted form of `GetSelectionRects` - `_ExpandTextRow` is still needed to handle wide glyphs properly ### Terminal - Rename... - `_boxSelection` --> `_blockSelection` for consistency with ConHost - `_selectionAnchor` --> `_selectionStart` for consistency with UIA - `_endSelectionPosition` --> `_selectionEnd` for consistency with UIA - Selection anchors are in Text Buffer coordinates now - Really rely on `SetSelectionEnd` to accomplish appropriate chunk selection and shift+click actions ## Validation Steps Performed - Shift+Click - Multi-Click --> Shift+Click - Chunk Selection at... - top of buffer - bottom of buffer - random region in scrollback Closes #4465 Closes #4547
2020-02-28 01:42:26 +01:00
const COORD Terminal::GetSelectionEnd() const noexcept
2019-06-19 00:53:29 +02:00
{
Move rect expansion to textbuffer; refactor selection code (#4560) - When performing chunk selection, the expansion now occurs at the time of the selection, not the rendering of the selection - `GetSelectionRects()` was moved to the `TextBuffer` and is now shared between ConHost and Windows Terminal - Some of the selection variables were renamed for clarity - Selection COORDs are now in the Text Buffer coordinate space - Fixes an issue with Shift+Click after performing a Multi-Click Selection ## References This also contributes to... - #4509: UIA Box Selection - #2447: UIA Signaling for Selection - #1354: UIA support for Wide Glyphs Now that the expansion occurs at before render-time, the selection anchors are an accurate representation of what is selected. We just need to move `GetText` to the `TextBuffer`. Then we can have those three issues just rely on code from the text buffer. This also means ConHost gets some of this stuff for free 😀 ### TextBuffer - `GetTextRects` is the abstracted form of `GetSelectionRects` - `_ExpandTextRow` is still needed to handle wide glyphs properly ### Terminal - Rename... - `_boxSelection` --> `_blockSelection` for consistency with ConHost - `_selectionAnchor` --> `_selectionStart` for consistency with UIA - `_endSelectionPosition` --> `_selectionEnd` for consistency with UIA - Selection anchors are in Text Buffer coordinates now - Really rely on `SetSelectionEnd` to accomplish appropriate chunk selection and shift+click actions ## Validation Steps Performed - Shift+Click - Multi-Click --> Shift+Click - Chunk Selection at... - top of buffer - bottom of buffer - random region in scrollback Closes #4465 Closes #4547
2020-02-28 01:42:26 +01:00
return _selection->end;
2019-06-19 00:53:29 +02:00
}
// Method Description:
// - Checks if selection is active
// Return Value:
// - bool representing if selection is active. Used to decide copy/paste on right click
const bool Terminal::IsSelectionActive() const noexcept
{
Move rect expansion to textbuffer; refactor selection code (#4560) - When performing chunk selection, the expansion now occurs at the time of the selection, not the rendering of the selection - `GetSelectionRects()` was moved to the `TextBuffer` and is now shared between ConHost and Windows Terminal - Some of the selection variables were renamed for clarity - Selection COORDs are now in the Text Buffer coordinate space - Fixes an issue with Shift+Click after performing a Multi-Click Selection ## References This also contributes to... - #4509: UIA Box Selection - #2447: UIA Signaling for Selection - #1354: UIA support for Wide Glyphs Now that the expansion occurs at before render-time, the selection anchors are an accurate representation of what is selected. We just need to move `GetText` to the `TextBuffer`. Then we can have those three issues just rely on code from the text buffer. This also means ConHost gets some of this stuff for free 😀 ### TextBuffer - `GetTextRects` is the abstracted form of `GetSelectionRects` - `_ExpandTextRow` is still needed to handle wide glyphs properly ### Terminal - Rename... - `_boxSelection` --> `_blockSelection` for consistency with ConHost - `_selectionAnchor` --> `_selectionStart` for consistency with UIA - `_endSelectionPosition` --> `_selectionEnd` for consistency with UIA - Selection anchors are in Text Buffer coordinates now - Really rely on `SetSelectionEnd` to accomplish appropriate chunk selection and shift+click actions ## Validation Steps Performed - Shift+Click - Multi-Click --> Shift+Click - Chunk Selection at... - top of buffer - bottom of buffer - random region in scrollback Closes #4465 Closes #4547
2020-02-28 01:42:26 +01:00
return _selection.has_value();
2019-06-19 00:53:29 +02:00
}
const bool Terminal::IsBlockSelection() const noexcept
{
return _blockSelection;
}
// Method Description:
Move rect expansion to textbuffer; refactor selection code (#4560) - When performing chunk selection, the expansion now occurs at the time of the selection, not the rendering of the selection - `GetSelectionRects()` was moved to the `TextBuffer` and is now shared between ConHost and Windows Terminal - Some of the selection variables were renamed for clarity - Selection COORDs are now in the Text Buffer coordinate space - Fixes an issue with Shift+Click after performing a Multi-Click Selection ## References This also contributes to... - #4509: UIA Box Selection - #2447: UIA Signaling for Selection - #1354: UIA support for Wide Glyphs Now that the expansion occurs at before render-time, the selection anchors are an accurate representation of what is selected. We just need to move `GetText` to the `TextBuffer`. Then we can have those three issues just rely on code from the text buffer. This also means ConHost gets some of this stuff for free 😀 ### TextBuffer - `GetTextRects` is the abstracted form of `GetSelectionRects` - `_ExpandTextRow` is still needed to handle wide glyphs properly ### Terminal - Rename... - `_boxSelection` --> `_blockSelection` for consistency with ConHost - `_selectionAnchor` --> `_selectionStart` for consistency with UIA - `_endSelectionPosition` --> `_selectionEnd` for consistency with UIA - Selection anchors are in Text Buffer coordinates now - Really rely on `SetSelectionEnd` to accomplish appropriate chunk selection and shift+click actions ## Validation Steps Performed - Shift+Click - Multi-Click --> Shift+Click - Chunk Selection at... - top of buffer - bottom of buffer - random region in scrollback Closes #4465 Closes #4547
2020-02-28 01:42:26 +01:00
// - Perform a multi-click selection at viewportPos expanding according to the expansionMode
// Arguments:
Move rect expansion to textbuffer; refactor selection code (#4560) - When performing chunk selection, the expansion now occurs at the time of the selection, not the rendering of the selection - `GetSelectionRects()` was moved to the `TextBuffer` and is now shared between ConHost and Windows Terminal - Some of the selection variables were renamed for clarity - Selection COORDs are now in the Text Buffer coordinate space - Fixes an issue with Shift+Click after performing a Multi-Click Selection ## References This also contributes to... - #4509: UIA Box Selection - #2447: UIA Signaling for Selection - #1354: UIA support for Wide Glyphs Now that the expansion occurs at before render-time, the selection anchors are an accurate representation of what is selected. We just need to move `GetText` to the `TextBuffer`. Then we can have those three issues just rely on code from the text buffer. This also means ConHost gets some of this stuff for free 😀 ### TextBuffer - `GetTextRects` is the abstracted form of `GetSelectionRects` - `_ExpandTextRow` is still needed to handle wide glyphs properly ### Terminal - Rename... - `_boxSelection` --> `_blockSelection` for consistency with ConHost - `_selectionAnchor` --> `_selectionStart` for consistency with UIA - `_endSelectionPosition` --> `_selectionEnd` for consistency with UIA - Selection anchors are in Text Buffer coordinates now - Really rely on `SetSelectionEnd` to accomplish appropriate chunk selection and shift+click actions ## Validation Steps Performed - Shift+Click - Multi-Click --> Shift+Click - Chunk Selection at... - top of buffer - bottom of buffer - random region in scrollback Closes #4465 Closes #4547
2020-02-28 01:42:26 +01:00
// - viewportPos: the (x,y) coordinate on the visible viewport
// - expansionMode: the SelectionExpansion to dictate the boundaries of the selection anchors
void Terminal::MultiClickSelection(const COORD viewportPos, SelectionExpansion expansionMode)
{
Move rect expansion to textbuffer; refactor selection code (#4560) - When performing chunk selection, the expansion now occurs at the time of the selection, not the rendering of the selection - `GetSelectionRects()` was moved to the `TextBuffer` and is now shared between ConHost and Windows Terminal - Some of the selection variables were renamed for clarity - Selection COORDs are now in the Text Buffer coordinate space - Fixes an issue with Shift+Click after performing a Multi-Click Selection ## References This also contributes to... - #4509: UIA Box Selection - #2447: UIA Signaling for Selection - #1354: UIA support for Wide Glyphs Now that the expansion occurs at before render-time, the selection anchors are an accurate representation of what is selected. We just need to move `GetText` to the `TextBuffer`. Then we can have those three issues just rely on code from the text buffer. This also means ConHost gets some of this stuff for free 😀 ### TextBuffer - `GetTextRects` is the abstracted form of `GetSelectionRects` - `_ExpandTextRow` is still needed to handle wide glyphs properly ### Terminal - Rename... - `_boxSelection` --> `_blockSelection` for consistency with ConHost - `_selectionAnchor` --> `_selectionStart` for consistency with UIA - `_endSelectionPosition` --> `_selectionEnd` for consistency with UIA - Selection anchors are in Text Buffer coordinates now - Really rely on `SetSelectionEnd` to accomplish appropriate chunk selection and shift+click actions ## Validation Steps Performed - Shift+Click - Multi-Click --> Shift+Click - Chunk Selection at... - top of buffer - bottom of buffer - random region in scrollback Closes #4465 Closes #4547
2020-02-28 01:42:26 +01:00
// set the selection pivot to expand the selection using SetSelectionEnd()
_selection = SelectionAnchors{};
_selection->pivot = _ConvertToBufferCell(viewportPos);
Move rect expansion to textbuffer; refactor selection code (#4560) - When performing chunk selection, the expansion now occurs at the time of the selection, not the rendering of the selection - `GetSelectionRects()` was moved to the `TextBuffer` and is now shared between ConHost and Windows Terminal - Some of the selection variables were renamed for clarity - Selection COORDs are now in the Text Buffer coordinate space - Fixes an issue with Shift+Click after performing a Multi-Click Selection ## References This also contributes to... - #4509: UIA Box Selection - #2447: UIA Signaling for Selection - #1354: UIA support for Wide Glyphs Now that the expansion occurs at before render-time, the selection anchors are an accurate representation of what is selected. We just need to move `GetText` to the `TextBuffer`. Then we can have those three issues just rely on code from the text buffer. This also means ConHost gets some of this stuff for free 😀 ### TextBuffer - `GetTextRects` is the abstracted form of `GetSelectionRects` - `_ExpandTextRow` is still needed to handle wide glyphs properly ### Terminal - Rename... - `_boxSelection` --> `_blockSelection` for consistency with ConHost - `_selectionAnchor` --> `_selectionStart` for consistency with UIA - `_endSelectionPosition` --> `_selectionEnd` for consistency with UIA - Selection anchors are in Text Buffer coordinates now - Really rely on `SetSelectionEnd` to accomplish appropriate chunk selection and shift+click actions ## Validation Steps Performed - Shift+Click - Multi-Click --> Shift+Click - Chunk Selection at... - top of buffer - bottom of buffer - random region in scrollback Closes #4465 Closes #4547
2020-02-28 01:42:26 +01:00
_multiClickSelectionMode = expansionMode;
SetSelectionEnd(viewportPos);
Move rect expansion to textbuffer; refactor selection code (#4560) - When performing chunk selection, the expansion now occurs at the time of the selection, not the rendering of the selection - `GetSelectionRects()` was moved to the `TextBuffer` and is now shared between ConHost and Windows Terminal - Some of the selection variables were renamed for clarity - Selection COORDs are now in the Text Buffer coordinate space - Fixes an issue with Shift+Click after performing a Multi-Click Selection ## References This also contributes to... - #4509: UIA Box Selection - #2447: UIA Signaling for Selection - #1354: UIA support for Wide Glyphs Now that the expansion occurs at before render-time, the selection anchors are an accurate representation of what is selected. We just need to move `GetText` to the `TextBuffer`. Then we can have those three issues just rely on code from the text buffer. This also means ConHost gets some of this stuff for free 😀 ### TextBuffer - `GetTextRects` is the abstracted form of `GetSelectionRects` - `_ExpandTextRow` is still needed to handle wide glyphs properly ### Terminal - Rename... - `_boxSelection` --> `_blockSelection` for consistency with ConHost - `_selectionAnchor` --> `_selectionStart` for consistency with UIA - `_endSelectionPosition` --> `_selectionEnd` for consistency with UIA - Selection anchors are in Text Buffer coordinates now - Really rely on `SetSelectionEnd` to accomplish appropriate chunk selection and shift+click actions ## Validation Steps Performed - Shift+Click - Multi-Click --> Shift+Click - Chunk Selection at... - top of buffer - bottom of buffer - random region in scrollback Closes #4465 Closes #4547
2020-02-28 01:42:26 +01:00
// we need to set the _selectionPivot again
// for future shift+clicks
_selection->pivot = _selection->start;
}
// Method Description:
Move rect expansion to textbuffer; refactor selection code (#4560) - When performing chunk selection, the expansion now occurs at the time of the selection, not the rendering of the selection - `GetSelectionRects()` was moved to the `TextBuffer` and is now shared between ConHost and Windows Terminal - Some of the selection variables were renamed for clarity - Selection COORDs are now in the Text Buffer coordinate space - Fixes an issue with Shift+Click after performing a Multi-Click Selection ## References This also contributes to... - #4509: UIA Box Selection - #2447: UIA Signaling for Selection - #1354: UIA support for Wide Glyphs Now that the expansion occurs at before render-time, the selection anchors are an accurate representation of what is selected. We just need to move `GetText` to the `TextBuffer`. Then we can have those three issues just rely on code from the text buffer. This also means ConHost gets some of this stuff for free 😀 ### TextBuffer - `GetTextRects` is the abstracted form of `GetSelectionRects` - `_ExpandTextRow` is still needed to handle wide glyphs properly ### Terminal - Rename... - `_boxSelection` --> `_blockSelection` for consistency with ConHost - `_selectionAnchor` --> `_selectionStart` for consistency with UIA - `_endSelectionPosition` --> `_selectionEnd` for consistency with UIA - Selection anchors are in Text Buffer coordinates now - Really rely on `SetSelectionEnd` to accomplish appropriate chunk selection and shift+click actions ## Validation Steps Performed - Shift+Click - Multi-Click --> Shift+Click - Chunk Selection at... - top of buffer - bottom of buffer - random region in scrollback Closes #4465 Closes #4547
2020-02-28 01:42:26 +01:00
// - Record the position of the beginning of a selection
// Arguments:
// - position: the (x,y) coordinate on the visible viewport
Move rect expansion to textbuffer; refactor selection code (#4560) - When performing chunk selection, the expansion now occurs at the time of the selection, not the rendering of the selection - `GetSelectionRects()` was moved to the `TextBuffer` and is now shared between ConHost and Windows Terminal - Some of the selection variables were renamed for clarity - Selection COORDs are now in the Text Buffer coordinate space - Fixes an issue with Shift+Click after performing a Multi-Click Selection ## References This also contributes to... - #4509: UIA Box Selection - #2447: UIA Signaling for Selection - #1354: UIA support for Wide Glyphs Now that the expansion occurs at before render-time, the selection anchors are an accurate representation of what is selected. We just need to move `GetText` to the `TextBuffer`. Then we can have those three issues just rely on code from the text buffer. This also means ConHost gets some of this stuff for free 😀 ### TextBuffer - `GetTextRects` is the abstracted form of `GetSelectionRects` - `_ExpandTextRow` is still needed to handle wide glyphs properly ### Terminal - Rename... - `_boxSelection` --> `_blockSelection` for consistency with ConHost - `_selectionAnchor` --> `_selectionStart` for consistency with UIA - `_endSelectionPosition` --> `_selectionEnd` for consistency with UIA - Selection anchors are in Text Buffer coordinates now - Really rely on `SetSelectionEnd` to accomplish appropriate chunk selection and shift+click actions ## Validation Steps Performed - Shift+Click - Multi-Click --> Shift+Click - Chunk Selection at... - top of buffer - bottom of buffer - random region in scrollback Closes #4465 Closes #4547
2020-02-28 01:42:26 +01:00
void Terminal::SetSelectionAnchor(const COORD viewportPos)
{
Move rect expansion to textbuffer; refactor selection code (#4560) - When performing chunk selection, the expansion now occurs at the time of the selection, not the rendering of the selection - `GetSelectionRects()` was moved to the `TextBuffer` and is now shared between ConHost and Windows Terminal - Some of the selection variables were renamed for clarity - Selection COORDs are now in the Text Buffer coordinate space - Fixes an issue with Shift+Click after performing a Multi-Click Selection ## References This also contributes to... - #4509: UIA Box Selection - #2447: UIA Signaling for Selection - #1354: UIA support for Wide Glyphs Now that the expansion occurs at before render-time, the selection anchors are an accurate representation of what is selected. We just need to move `GetText` to the `TextBuffer`. Then we can have those three issues just rely on code from the text buffer. This also means ConHost gets some of this stuff for free 😀 ### TextBuffer - `GetTextRects` is the abstracted form of `GetSelectionRects` - `_ExpandTextRow` is still needed to handle wide glyphs properly ### Terminal - Rename... - `_boxSelection` --> `_blockSelection` for consistency with ConHost - `_selectionAnchor` --> `_selectionStart` for consistency with UIA - `_endSelectionPosition` --> `_selectionEnd` for consistency with UIA - Selection anchors are in Text Buffer coordinates now - Really rely on `SetSelectionEnd` to accomplish appropriate chunk selection and shift+click actions ## Validation Steps Performed - Shift+Click - Multi-Click --> Shift+Click - Chunk Selection at... - top of buffer - bottom of buffer - random region in scrollback Closes #4465 Closes #4547
2020-02-28 01:42:26 +01:00
_selection = SelectionAnchors{};
_selection->pivot = _ConvertToBufferCell(viewportPos);
_multiClickSelectionMode = SelectionExpansion::Char;
Move rect expansion to textbuffer; refactor selection code (#4560) - When performing chunk selection, the expansion now occurs at the time of the selection, not the rendering of the selection - `GetSelectionRects()` was moved to the `TextBuffer` and is now shared between ConHost and Windows Terminal - Some of the selection variables were renamed for clarity - Selection COORDs are now in the Text Buffer coordinate space - Fixes an issue with Shift+Click after performing a Multi-Click Selection ## References This also contributes to... - #4509: UIA Box Selection - #2447: UIA Signaling for Selection - #1354: UIA support for Wide Glyphs Now that the expansion occurs at before render-time, the selection anchors are an accurate representation of what is selected. We just need to move `GetText` to the `TextBuffer`. Then we can have those three issues just rely on code from the text buffer. This also means ConHost gets some of this stuff for free 😀 ### TextBuffer - `GetTextRects` is the abstracted form of `GetSelectionRects` - `_ExpandTextRow` is still needed to handle wide glyphs properly ### Terminal - Rename... - `_boxSelection` --> `_blockSelection` for consistency with ConHost - `_selectionAnchor` --> `_selectionStart` for consistency with UIA - `_endSelectionPosition` --> `_selectionEnd` for consistency with UIA - Selection anchors are in Text Buffer coordinates now - Really rely on `SetSelectionEnd` to accomplish appropriate chunk selection and shift+click actions ## Validation Steps Performed - Shift+Click - Multi-Click --> Shift+Click - Chunk Selection at... - top of buffer - bottom of buffer - random region in scrollback Closes #4465 Closes #4547
2020-02-28 01:42:26 +01:00
SetSelectionEnd(viewportPos);
_selection->start = _selection->pivot;
}
2019-06-19 00:53:29 +02:00
// Method Description:
Move rect expansion to textbuffer; refactor selection code (#4560) - When performing chunk selection, the expansion now occurs at the time of the selection, not the rendering of the selection - `GetSelectionRects()` was moved to the `TextBuffer` and is now shared between ConHost and Windows Terminal - Some of the selection variables were renamed for clarity - Selection COORDs are now in the Text Buffer coordinate space - Fixes an issue with Shift+Click after performing a Multi-Click Selection ## References This also contributes to... - #4509: UIA Box Selection - #2447: UIA Signaling for Selection - #1354: UIA support for Wide Glyphs Now that the expansion occurs at before render-time, the selection anchors are an accurate representation of what is selected. We just need to move `GetText` to the `TextBuffer`. Then we can have those three issues just rely on code from the text buffer. This also means ConHost gets some of this stuff for free 😀 ### TextBuffer - `GetTextRects` is the abstracted form of `GetSelectionRects` - `_ExpandTextRow` is still needed to handle wide glyphs properly ### Terminal - Rename... - `_boxSelection` --> `_blockSelection` for consistency with ConHost - `_selectionAnchor` --> `_selectionStart` for consistency with UIA - `_endSelectionPosition` --> `_selectionEnd` for consistency with UIA - Selection anchors are in Text Buffer coordinates now - Really rely on `SetSelectionEnd` to accomplish appropriate chunk selection and shift+click actions ## Validation Steps Performed - Shift+Click - Multi-Click --> Shift+Click - Chunk Selection at... - top of buffer - bottom of buffer - random region in scrollback Closes #4465 Closes #4547
2020-02-28 01:42:26 +01:00
// - Update selection anchors when dragging to a position
// - based on the selection expansion mode
2019-06-19 00:53:29 +02:00
// Arguments:
Move rect expansion to textbuffer; refactor selection code (#4560) - When performing chunk selection, the expansion now occurs at the time of the selection, not the rendering of the selection - `GetSelectionRects()` was moved to the `TextBuffer` and is now shared between ConHost and Windows Terminal - Some of the selection variables were renamed for clarity - Selection COORDs are now in the Text Buffer coordinate space - Fixes an issue with Shift+Click after performing a Multi-Click Selection ## References This also contributes to... - #4509: UIA Box Selection - #2447: UIA Signaling for Selection - #1354: UIA support for Wide Glyphs Now that the expansion occurs at before render-time, the selection anchors are an accurate representation of what is selected. We just need to move `GetText` to the `TextBuffer`. Then we can have those three issues just rely on code from the text buffer. This also means ConHost gets some of this stuff for free 😀 ### TextBuffer - `GetTextRects` is the abstracted form of `GetSelectionRects` - `_ExpandTextRow` is still needed to handle wide glyphs properly ### Terminal - Rename... - `_boxSelection` --> `_blockSelection` for consistency with ConHost - `_selectionAnchor` --> `_selectionStart` for consistency with UIA - `_endSelectionPosition` --> `_selectionEnd` for consistency with UIA - Selection anchors are in Text Buffer coordinates now - Really rely on `SetSelectionEnd` to accomplish appropriate chunk selection and shift+click actions ## Validation Steps Performed - Shift+Click - Multi-Click --> Shift+Click - Chunk Selection at... - top of buffer - bottom of buffer - random region in scrollback Closes #4465 Closes #4547
2020-02-28 01:42:26 +01:00
// - viewportPos: the (x,y) coordinate on the visible viewport
// - newExpansionMode: overwrites the _multiClickSelectionMode for this function call. Used for ShiftClick
void Terminal::SetSelectionEnd(const COORD viewportPos, std::optional<SelectionExpansion> newExpansionMode)
2019-06-19 00:53:29 +02:00
{
if (!_selection.has_value())
{
// capture a log for spurious endpoint sets without an active selection
LOG_HR(E_ILLEGAL_STATE_CHANGE);
return;
}
Move rect expansion to textbuffer; refactor selection code (#4560) - When performing chunk selection, the expansion now occurs at the time of the selection, not the rendering of the selection - `GetSelectionRects()` was moved to the `TextBuffer` and is now shared between ConHost and Windows Terminal - Some of the selection variables were renamed for clarity - Selection COORDs are now in the Text Buffer coordinate space - Fixes an issue with Shift+Click after performing a Multi-Click Selection ## References This also contributes to... - #4509: UIA Box Selection - #2447: UIA Signaling for Selection - #1354: UIA support for Wide Glyphs Now that the expansion occurs at before render-time, the selection anchors are an accurate representation of what is selected. We just need to move `GetText` to the `TextBuffer`. Then we can have those three issues just rely on code from the text buffer. This also means ConHost gets some of this stuff for free 😀 ### TextBuffer - `GetTextRects` is the abstracted form of `GetSelectionRects` - `_ExpandTextRow` is still needed to handle wide glyphs properly ### Terminal - Rename... - `_boxSelection` --> `_blockSelection` for consistency with ConHost - `_selectionAnchor` --> `_selectionStart` for consistency with UIA - `_endSelectionPosition` --> `_selectionEnd` for consistency with UIA - Selection anchors are in Text Buffer coordinates now - Really rely on `SetSelectionEnd` to accomplish appropriate chunk selection and shift+click actions ## Validation Steps Performed - Shift+Click - Multi-Click --> Shift+Click - Chunk Selection at... - top of buffer - bottom of buffer - random region in scrollback Closes #4465 Closes #4547
2020-02-28 01:42:26 +01:00
const auto textBufferPos = _ConvertToBufferCell(viewportPos);
2019-06-19 00:53:29 +02:00
Move rect expansion to textbuffer; refactor selection code (#4560) - When performing chunk selection, the expansion now occurs at the time of the selection, not the rendering of the selection - `GetSelectionRects()` was moved to the `TextBuffer` and is now shared between ConHost and Windows Terminal - Some of the selection variables were renamed for clarity - Selection COORDs are now in the Text Buffer coordinate space - Fixes an issue with Shift+Click after performing a Multi-Click Selection ## References This also contributes to... - #4509: UIA Box Selection - #2447: UIA Signaling for Selection - #1354: UIA support for Wide Glyphs Now that the expansion occurs at before render-time, the selection anchors are an accurate representation of what is selected. We just need to move `GetText` to the `TextBuffer`. Then we can have those three issues just rely on code from the text buffer. This also means ConHost gets some of this stuff for free 😀 ### TextBuffer - `GetTextRects` is the abstracted form of `GetSelectionRects` - `_ExpandTextRow` is still needed to handle wide glyphs properly ### Terminal - Rename... - `_boxSelection` --> `_blockSelection` for consistency with ConHost - `_selectionAnchor` --> `_selectionStart` for consistency with UIA - `_endSelectionPosition` --> `_selectionEnd` for consistency with UIA - Selection anchors are in Text Buffer coordinates now - Really rely on `SetSelectionEnd` to accomplish appropriate chunk selection and shift+click actions ## Validation Steps Performed - Shift+Click - Multi-Click --> Shift+Click - Chunk Selection at... - top of buffer - bottom of buffer - random region in scrollback Closes #4465 Closes #4547
2020-02-28 01:42:26 +01:00
// if this is a shiftClick action, we need to overwrite the _multiClickSelectionMode value (even if it's the same)
// Otherwise, we may accidentally expand during other selection-based actions
_multiClickSelectionMode = newExpansionMode.has_value() ? *newExpansionMode : _multiClickSelectionMode;
2019-06-19 00:53:29 +02:00
bool targetStart = false;
const auto anchors = _PivotSelection(textBufferPos, targetStart);
const auto expandedAnchors = _ExpandSelectionAnchors(anchors);
if (newExpansionMode.has_value())
{
// shift-click operations only expand the target side
auto& anchorToExpand = targetStart ? _selection->start : _selection->end;
anchorToExpand = targetStart ? expandedAnchors.first : expandedAnchors.second;
// the other anchor should then become the pivot (we don't expand it)
auto& anchorToPivot = targetStart ? _selection->end : _selection->start;
anchorToPivot = _selection->pivot;
}
else
{
// expand both anchors
std::tie(_selection->start, _selection->end) = expandedAnchors;
}
2019-06-19 00:53:29 +02:00
}
// Method Description:
Move rect expansion to textbuffer; refactor selection code (#4560) - When performing chunk selection, the expansion now occurs at the time of the selection, not the rendering of the selection - `GetSelectionRects()` was moved to the `TextBuffer` and is now shared between ConHost and Windows Terminal - Some of the selection variables were renamed for clarity - Selection COORDs are now in the Text Buffer coordinate space - Fixes an issue with Shift+Click after performing a Multi-Click Selection ## References This also contributes to... - #4509: UIA Box Selection - #2447: UIA Signaling for Selection - #1354: UIA support for Wide Glyphs Now that the expansion occurs at before render-time, the selection anchors are an accurate representation of what is selected. We just need to move `GetText` to the `TextBuffer`. Then we can have those three issues just rely on code from the text buffer. This also means ConHost gets some of this stuff for free 😀 ### TextBuffer - `GetTextRects` is the abstracted form of `GetSelectionRects` - `_ExpandTextRow` is still needed to handle wide glyphs properly ### Terminal - Rename... - `_boxSelection` --> `_blockSelection` for consistency with ConHost - `_selectionAnchor` --> `_selectionStart` for consistency with UIA - `_endSelectionPosition` --> `_selectionEnd` for consistency with UIA - Selection anchors are in Text Buffer coordinates now - Really rely on `SetSelectionEnd` to accomplish appropriate chunk selection and shift+click actions ## Validation Steps Performed - Shift+Click - Multi-Click --> Shift+Click - Chunk Selection at... - top of buffer - bottom of buffer - random region in scrollback Closes #4465 Closes #4547
2020-02-28 01:42:26 +01:00
// - returns a new pair of selection anchors for selecting around the pivot
// - This ensures start < end when compared
2019-06-19 00:53:29 +02:00
// Arguments:
Move rect expansion to textbuffer; refactor selection code (#4560) - When performing chunk selection, the expansion now occurs at the time of the selection, not the rendering of the selection - `GetSelectionRects()` was moved to the `TextBuffer` and is now shared between ConHost and Windows Terminal - Some of the selection variables were renamed for clarity - Selection COORDs are now in the Text Buffer coordinate space - Fixes an issue with Shift+Click after performing a Multi-Click Selection ## References This also contributes to... - #4509: UIA Box Selection - #2447: UIA Signaling for Selection - #1354: UIA support for Wide Glyphs Now that the expansion occurs at before render-time, the selection anchors are an accurate representation of what is selected. We just need to move `GetText` to the `TextBuffer`. Then we can have those three issues just rely on code from the text buffer. This also means ConHost gets some of this stuff for free 😀 ### TextBuffer - `GetTextRects` is the abstracted form of `GetSelectionRects` - `_ExpandTextRow` is still needed to handle wide glyphs properly ### Terminal - Rename... - `_boxSelection` --> `_blockSelection` for consistency with ConHost - `_selectionAnchor` --> `_selectionStart` for consistency with UIA - `_endSelectionPosition` --> `_selectionEnd` for consistency with UIA - Selection anchors are in Text Buffer coordinates now - Really rely on `SetSelectionEnd` to accomplish appropriate chunk selection and shift+click actions ## Validation Steps Performed - Shift+Click - Multi-Click --> Shift+Click - Chunk Selection at... - top of buffer - bottom of buffer - random region in scrollback Closes #4465 Closes #4547
2020-02-28 01:42:26 +01:00
// - targetPos: the (x,y) coordinate we are moving to on the text buffer
// - targetStart: if true, target will be the new start. Otherwise, target will be the new end.
Move rect expansion to textbuffer; refactor selection code (#4560) - When performing chunk selection, the expansion now occurs at the time of the selection, not the rendering of the selection - `GetSelectionRects()` was moved to the `TextBuffer` and is now shared between ConHost and Windows Terminal - Some of the selection variables were renamed for clarity - Selection COORDs are now in the Text Buffer coordinate space - Fixes an issue with Shift+Click after performing a Multi-Click Selection ## References This also contributes to... - #4509: UIA Box Selection - #2447: UIA Signaling for Selection - #1354: UIA support for Wide Glyphs Now that the expansion occurs at before render-time, the selection anchors are an accurate representation of what is selected. We just need to move `GetText` to the `TextBuffer`. Then we can have those three issues just rely on code from the text buffer. This also means ConHost gets some of this stuff for free 😀 ### TextBuffer - `GetTextRects` is the abstracted form of `GetSelectionRects` - `_ExpandTextRow` is still needed to handle wide glyphs properly ### Terminal - Rename... - `_boxSelection` --> `_blockSelection` for consistency with ConHost - `_selectionAnchor` --> `_selectionStart` for consistency with UIA - `_endSelectionPosition` --> `_selectionEnd` for consistency with UIA - Selection anchors are in Text Buffer coordinates now - Really rely on `SetSelectionEnd` to accomplish appropriate chunk selection and shift+click actions ## Validation Steps Performed - Shift+Click - Multi-Click --> Shift+Click - Chunk Selection at... - top of buffer - bottom of buffer - random region in scrollback Closes #4465 Closes #4547
2020-02-28 01:42:26 +01:00
// Return Value:
// - the new start/end for a selection
std::pair<COORD, COORD> Terminal::_PivotSelection(const COORD targetPos, bool& targetStart) const
2019-06-19 00:53:29 +02:00
{
if (targetStart = _buffer->GetSize().CompareInBounds(targetPos, _selection->pivot) <= 0)
Move rect expansion to textbuffer; refactor selection code (#4560) - When performing chunk selection, the expansion now occurs at the time of the selection, not the rendering of the selection - `GetSelectionRects()` was moved to the `TextBuffer` and is now shared between ConHost and Windows Terminal - Some of the selection variables were renamed for clarity - Selection COORDs are now in the Text Buffer coordinate space - Fixes an issue with Shift+Click after performing a Multi-Click Selection ## References This also contributes to... - #4509: UIA Box Selection - #2447: UIA Signaling for Selection - #1354: UIA support for Wide Glyphs Now that the expansion occurs at before render-time, the selection anchors are an accurate representation of what is selected. We just need to move `GetText` to the `TextBuffer`. Then we can have those three issues just rely on code from the text buffer. This also means ConHost gets some of this stuff for free 😀 ### TextBuffer - `GetTextRects` is the abstracted form of `GetSelectionRects` - `_ExpandTextRow` is still needed to handle wide glyphs properly ### Terminal - Rename... - `_boxSelection` --> `_blockSelection` for consistency with ConHost - `_selectionAnchor` --> `_selectionStart` for consistency with UIA - `_endSelectionPosition` --> `_selectionEnd` for consistency with UIA - Selection anchors are in Text Buffer coordinates now - Really rely on `SetSelectionEnd` to accomplish appropriate chunk selection and shift+click actions ## Validation Steps Performed - Shift+Click - Multi-Click --> Shift+Click - Chunk Selection at... - top of buffer - bottom of buffer - random region in scrollback Closes #4465 Closes #4547
2020-02-28 01:42:26 +01:00
{
// target is before pivot
// treat target as start
return std::make_pair(targetPos, _selection->pivot);
}
else
{
// target is after pivot
// treat pivot as start
return std::make_pair(_selection->pivot, targetPos);
}
}
2019-06-19 00:53:29 +02:00
Move rect expansion to textbuffer; refactor selection code (#4560) - When performing chunk selection, the expansion now occurs at the time of the selection, not the rendering of the selection - `GetSelectionRects()` was moved to the `TextBuffer` and is now shared between ConHost and Windows Terminal - Some of the selection variables were renamed for clarity - Selection COORDs are now in the Text Buffer coordinate space - Fixes an issue with Shift+Click after performing a Multi-Click Selection ## References This also contributes to... - #4509: UIA Box Selection - #2447: UIA Signaling for Selection - #1354: UIA support for Wide Glyphs Now that the expansion occurs at before render-time, the selection anchors are an accurate representation of what is selected. We just need to move `GetText` to the `TextBuffer`. Then we can have those three issues just rely on code from the text buffer. This also means ConHost gets some of this stuff for free 😀 ### TextBuffer - `GetTextRects` is the abstracted form of `GetSelectionRects` - `_ExpandTextRow` is still needed to handle wide glyphs properly ### Terminal - Rename... - `_boxSelection` --> `_blockSelection` for consistency with ConHost - `_selectionAnchor` --> `_selectionStart` for consistency with UIA - `_endSelectionPosition` --> `_selectionEnd` for consistency with UIA - Selection anchors are in Text Buffer coordinates now - Really rely on `SetSelectionEnd` to accomplish appropriate chunk selection and shift+click actions ## Validation Steps Performed - Shift+Click - Multi-Click --> Shift+Click - Chunk Selection at... - top of buffer - bottom of buffer - random region in scrollback Closes #4465 Closes #4547
2020-02-28 01:42:26 +01:00
// Method Description:
// - Update the selection anchors to expand according to the expansion mode
// Arguments:
// - anchors: a pair of selection anchors representing a desired selection
// Return Value:
// - the new start/end for a selection
std::pair<COORD, COORD> Terminal::_ExpandSelectionAnchors(std::pair<COORD, COORD> anchors) const
{
COORD start = anchors.first;
COORD end = anchors.second;
Move rect expansion to textbuffer; refactor selection code (#4560) - When performing chunk selection, the expansion now occurs at the time of the selection, not the rendering of the selection - `GetSelectionRects()` was moved to the `TextBuffer` and is now shared between ConHost and Windows Terminal - Some of the selection variables were renamed for clarity - Selection COORDs are now in the Text Buffer coordinate space - Fixes an issue with Shift+Click after performing a Multi-Click Selection ## References This also contributes to... - #4509: UIA Box Selection - #2447: UIA Signaling for Selection - #1354: UIA support for Wide Glyphs Now that the expansion occurs at before render-time, the selection anchors are an accurate representation of what is selected. We just need to move `GetText` to the `TextBuffer`. Then we can have those three issues just rely on code from the text buffer. This also means ConHost gets some of this stuff for free 😀 ### TextBuffer - `GetTextRects` is the abstracted form of `GetSelectionRects` - `_ExpandTextRow` is still needed to handle wide glyphs properly ### Terminal - Rename... - `_boxSelection` --> `_blockSelection` for consistency with ConHost - `_selectionAnchor` --> `_selectionStart` for consistency with UIA - `_endSelectionPosition` --> `_selectionEnd` for consistency with UIA - Selection anchors are in Text Buffer coordinates now - Really rely on `SetSelectionEnd` to accomplish appropriate chunk selection and shift+click actions ## Validation Steps Performed - Shift+Click - Multi-Click --> Shift+Click - Chunk Selection at... - top of buffer - bottom of buffer - random region in scrollback Closes #4465 Closes #4547
2020-02-28 01:42:26 +01:00
const auto bufferSize = _buffer->GetSize();
switch (_multiClickSelectionMode)
{
case SelectionExpansion::Line:
Move rect expansion to textbuffer; refactor selection code (#4560) - When performing chunk selection, the expansion now occurs at the time of the selection, not the rendering of the selection - `GetSelectionRects()` was moved to the `TextBuffer` and is now shared between ConHost and Windows Terminal - Some of the selection variables were renamed for clarity - Selection COORDs are now in the Text Buffer coordinate space - Fixes an issue with Shift+Click after performing a Multi-Click Selection ## References This also contributes to... - #4509: UIA Box Selection - #2447: UIA Signaling for Selection - #1354: UIA support for Wide Glyphs Now that the expansion occurs at before render-time, the selection anchors are an accurate representation of what is selected. We just need to move `GetText` to the `TextBuffer`. Then we can have those three issues just rely on code from the text buffer. This also means ConHost gets some of this stuff for free 😀 ### TextBuffer - `GetTextRects` is the abstracted form of `GetSelectionRects` - `_ExpandTextRow` is still needed to handle wide glyphs properly ### Terminal - Rename... - `_boxSelection` --> `_blockSelection` for consistency with ConHost - `_selectionAnchor` --> `_selectionStart` for consistency with UIA - `_endSelectionPosition` --> `_selectionEnd` for consistency with UIA - Selection anchors are in Text Buffer coordinates now - Really rely on `SetSelectionEnd` to accomplish appropriate chunk selection and shift+click actions ## Validation Steps Performed - Shift+Click - Multi-Click --> Shift+Click - Chunk Selection at... - top of buffer - bottom of buffer - random region in scrollback Closes #4465 Closes #4547
2020-02-28 01:42:26 +01:00
start = { bufferSize.Left(), start.Y };
end = { bufferSize.RightInclusive(), end.Y };
break;
case SelectionExpansion::Word:
Move rect expansion to textbuffer; refactor selection code (#4560) - When performing chunk selection, the expansion now occurs at the time of the selection, not the rendering of the selection - `GetSelectionRects()` was moved to the `TextBuffer` and is now shared between ConHost and Windows Terminal - Some of the selection variables were renamed for clarity - Selection COORDs are now in the Text Buffer coordinate space - Fixes an issue with Shift+Click after performing a Multi-Click Selection ## References This also contributes to... - #4509: UIA Box Selection - #2447: UIA Signaling for Selection - #1354: UIA support for Wide Glyphs Now that the expansion occurs at before render-time, the selection anchors are an accurate representation of what is selected. We just need to move `GetText` to the `TextBuffer`. Then we can have those three issues just rely on code from the text buffer. This also means ConHost gets some of this stuff for free 😀 ### TextBuffer - `GetTextRects` is the abstracted form of `GetSelectionRects` - `_ExpandTextRow` is still needed to handle wide glyphs properly ### Terminal - Rename... - `_boxSelection` --> `_blockSelection` for consistency with ConHost - `_selectionAnchor` --> `_selectionStart` for consistency with UIA - `_endSelectionPosition` --> `_selectionEnd` for consistency with UIA - Selection anchors are in Text Buffer coordinates now - Really rely on `SetSelectionEnd` to accomplish appropriate chunk selection and shift+click actions ## Validation Steps Performed - Shift+Click - Multi-Click --> Shift+Click - Chunk Selection at... - top of buffer - bottom of buffer - random region in scrollback Closes #4465 Closes #4547
2020-02-28 01:42:26 +01:00
start = _buffer->GetWordStart(start, _wordDelimiters);
end = _buffer->GetWordEnd(end, _wordDelimiters);
break;
case SelectionExpansion::Char:
Move rect expansion to textbuffer; refactor selection code (#4560) - When performing chunk selection, the expansion now occurs at the time of the selection, not the rendering of the selection - `GetSelectionRects()` was moved to the `TextBuffer` and is now shared between ConHost and Windows Terminal - Some of the selection variables were renamed for clarity - Selection COORDs are now in the Text Buffer coordinate space - Fixes an issue with Shift+Click after performing a Multi-Click Selection ## References This also contributes to... - #4509: UIA Box Selection - #2447: UIA Signaling for Selection - #1354: UIA support for Wide Glyphs Now that the expansion occurs at before render-time, the selection anchors are an accurate representation of what is selected. We just need to move `GetText` to the `TextBuffer`. Then we can have those three issues just rely on code from the text buffer. This also means ConHost gets some of this stuff for free 😀 ### TextBuffer - `GetTextRects` is the abstracted form of `GetSelectionRects` - `_ExpandTextRow` is still needed to handle wide glyphs properly ### Terminal - Rename... - `_boxSelection` --> `_blockSelection` for consistency with ConHost - `_selectionAnchor` --> `_selectionStart` for consistency with UIA - `_endSelectionPosition` --> `_selectionEnd` for consistency with UIA - Selection anchors are in Text Buffer coordinates now - Really rely on `SetSelectionEnd` to accomplish appropriate chunk selection and shift+click actions ## Validation Steps Performed - Shift+Click - Multi-Click --> Shift+Click - Chunk Selection at... - top of buffer - bottom of buffer - random region in scrollback Closes #4465 Closes #4547
2020-02-28 01:42:26 +01:00
default:
// no expansion is necessary
break;
}
Move rect expansion to textbuffer; refactor selection code (#4560) - When performing chunk selection, the expansion now occurs at the time of the selection, not the rendering of the selection - `GetSelectionRects()` was moved to the `TextBuffer` and is now shared between ConHost and Windows Terminal - Some of the selection variables were renamed for clarity - Selection COORDs are now in the Text Buffer coordinate space - Fixes an issue with Shift+Click after performing a Multi-Click Selection ## References This also contributes to... - #4509: UIA Box Selection - #2447: UIA Signaling for Selection - #1354: UIA support for Wide Glyphs Now that the expansion occurs at before render-time, the selection anchors are an accurate representation of what is selected. We just need to move `GetText` to the `TextBuffer`. Then we can have those three issues just rely on code from the text buffer. This also means ConHost gets some of this stuff for free 😀 ### TextBuffer - `GetTextRects` is the abstracted form of `GetSelectionRects` - `_ExpandTextRow` is still needed to handle wide glyphs properly ### Terminal - Rename... - `_boxSelection` --> `_blockSelection` for consistency with ConHost - `_selectionAnchor` --> `_selectionStart` for consistency with UIA - `_endSelectionPosition` --> `_selectionEnd` for consistency with UIA - Selection anchors are in Text Buffer coordinates now - Really rely on `SetSelectionEnd` to accomplish appropriate chunk selection and shift+click actions ## Validation Steps Performed - Shift+Click - Multi-Click --> Shift+Click - Chunk Selection at... - top of buffer - bottom of buffer - random region in scrollback Closes #4465 Closes #4547
2020-02-28 01:42:26 +01:00
return std::make_pair(start, end);
2019-06-19 00:53:29 +02:00
}
// Method Description:
Move rect expansion to textbuffer; refactor selection code (#4560) - When performing chunk selection, the expansion now occurs at the time of the selection, not the rendering of the selection - `GetSelectionRects()` was moved to the `TextBuffer` and is now shared between ConHost and Windows Terminal - Some of the selection variables were renamed for clarity - Selection COORDs are now in the Text Buffer coordinate space - Fixes an issue with Shift+Click after performing a Multi-Click Selection ## References This also contributes to... - #4509: UIA Box Selection - #2447: UIA Signaling for Selection - #1354: UIA support for Wide Glyphs Now that the expansion occurs at before render-time, the selection anchors are an accurate representation of what is selected. We just need to move `GetText` to the `TextBuffer`. Then we can have those three issues just rely on code from the text buffer. This also means ConHost gets some of this stuff for free 😀 ### TextBuffer - `GetTextRects` is the abstracted form of `GetSelectionRects` - `_ExpandTextRow` is still needed to handle wide glyphs properly ### Terminal - Rename... - `_boxSelection` --> `_blockSelection` for consistency with ConHost - `_selectionAnchor` --> `_selectionStart` for consistency with UIA - `_endSelectionPosition` --> `_selectionEnd` for consistency with UIA - Selection anchors are in Text Buffer coordinates now - Really rely on `SetSelectionEnd` to accomplish appropriate chunk selection and shift+click actions ## Validation Steps Performed - Shift+Click - Multi-Click --> Shift+Click - Chunk Selection at... - top of buffer - bottom of buffer - random region in scrollback Closes #4465 Closes #4547
2020-02-28 01:42:26 +01:00
// - enable/disable block selection (ALT + selection)
2019-06-19 00:53:29 +02:00
// Arguments:
Move rect expansion to textbuffer; refactor selection code (#4560) - When performing chunk selection, the expansion now occurs at the time of the selection, not the rendering of the selection - `GetSelectionRects()` was moved to the `TextBuffer` and is now shared between ConHost and Windows Terminal - Some of the selection variables were renamed for clarity - Selection COORDs are now in the Text Buffer coordinate space - Fixes an issue with Shift+Click after performing a Multi-Click Selection ## References This also contributes to... - #4509: UIA Box Selection - #2447: UIA Signaling for Selection - #1354: UIA support for Wide Glyphs Now that the expansion occurs at before render-time, the selection anchors are an accurate representation of what is selected. We just need to move `GetText` to the `TextBuffer`. Then we can have those three issues just rely on code from the text buffer. This also means ConHost gets some of this stuff for free 😀 ### TextBuffer - `GetTextRects` is the abstracted form of `GetSelectionRects` - `_ExpandTextRow` is still needed to handle wide glyphs properly ### Terminal - Rename... - `_boxSelection` --> `_blockSelection` for consistency with ConHost - `_selectionAnchor` --> `_selectionStart` for consistency with UIA - `_endSelectionPosition` --> `_selectionEnd` for consistency with UIA - Selection anchors are in Text Buffer coordinates now - Really rely on `SetSelectionEnd` to accomplish appropriate chunk selection and shift+click actions ## Validation Steps Performed - Shift+Click - Multi-Click --> Shift+Click - Chunk Selection at... - top of buffer - bottom of buffer - random region in scrollback Closes #4465 Closes #4547
2020-02-28 01:42:26 +01:00
// - isEnabled: new value for _blockSelection
void Terminal::SetBlockSelection(const bool isEnabled) noexcept
2019-06-19 00:53:29 +02:00
{
Move rect expansion to textbuffer; refactor selection code (#4560) - When performing chunk selection, the expansion now occurs at the time of the selection, not the rendering of the selection - `GetSelectionRects()` was moved to the `TextBuffer` and is now shared between ConHost and Windows Terminal - Some of the selection variables were renamed for clarity - Selection COORDs are now in the Text Buffer coordinate space - Fixes an issue with Shift+Click after performing a Multi-Click Selection ## References This also contributes to... - #4509: UIA Box Selection - #2447: UIA Signaling for Selection - #1354: UIA support for Wide Glyphs Now that the expansion occurs at before render-time, the selection anchors are an accurate representation of what is selected. We just need to move `GetText` to the `TextBuffer`. Then we can have those three issues just rely on code from the text buffer. This also means ConHost gets some of this stuff for free 😀 ### TextBuffer - `GetTextRects` is the abstracted form of `GetSelectionRects` - `_ExpandTextRow` is still needed to handle wide glyphs properly ### Terminal - Rename... - `_boxSelection` --> `_blockSelection` for consistency with ConHost - `_selectionAnchor` --> `_selectionStart` for consistency with UIA - `_endSelectionPosition` --> `_selectionEnd` for consistency with UIA - Selection anchors are in Text Buffer coordinates now - Really rely on `SetSelectionEnd` to accomplish appropriate chunk selection and shift+click actions ## Validation Steps Performed - Shift+Click - Multi-Click --> Shift+Click - Chunk Selection at... - top of buffer - bottom of buffer - random region in scrollback Closes #4465 Closes #4547
2020-02-28 01:42:26 +01:00
_blockSelection = isEnabled;
2019-06-19 00:53:29 +02:00
}
Terminal::UpdateSelectionParams Terminal::ConvertKeyEventToUpdateSelectionParams(const ControlKeyStates mods, const WORD vkey)
{
if (mods.IsShiftPressed() && !mods.IsAltPressed())
{
if (mods.IsCtrlPressed())
{
// Ctrl + Shift + _
switch (vkey)
{
case VK_LEFT:
return UpdateSelectionParams{ std::in_place, SelectionDirection::Left, SelectionExpansion::Word };
case VK_RIGHT:
return UpdateSelectionParams{ std::in_place, SelectionDirection::Right, SelectionExpansion::Word };
case VK_HOME:
return UpdateSelectionParams{ std::in_place, SelectionDirection::Left, SelectionExpansion::Buffer };
case VK_END:
return UpdateSelectionParams{ std::in_place, SelectionDirection::Right, SelectionExpansion::Buffer };
}
}
else
{
// Shift + _
switch (vkey)
{
case VK_HOME:
return UpdateSelectionParams{ std::in_place, SelectionDirection::Left, SelectionExpansion::Viewport };
case VK_END:
return UpdateSelectionParams{ std::in_place, SelectionDirection::Right, SelectionExpansion::Viewport };
case VK_PRIOR:
return UpdateSelectionParams{ std::in_place, SelectionDirection::Up, SelectionExpansion::Viewport };
case VK_NEXT:
return UpdateSelectionParams{ std::in_place, SelectionDirection::Down, SelectionExpansion::Viewport };
case VK_LEFT:
return UpdateSelectionParams{ std::in_place, SelectionDirection::Left, SelectionExpansion::Char };
case VK_RIGHT:
return UpdateSelectionParams{ std::in_place, SelectionDirection::Right, SelectionExpansion::Char };
case VK_UP:
return UpdateSelectionParams{ std::in_place, SelectionDirection::Up, SelectionExpansion::Char };
case VK_DOWN:
return UpdateSelectionParams{ std::in_place, SelectionDirection::Down, SelectionExpansion::Char };
}
}
}
return std::nullopt;
}
void Terminal::UpdateSelection(SelectionDirection direction, SelectionExpansion mode)
{
// 1. Figure out which endpoint to update
// One of the endpoints is the pivot, signifying that the other endpoint is the one we want to move.
const bool movingEnd{ _selection->start == _selection->pivot };
auto targetPos{ movingEnd ? _selection->end : _selection->start };
// 2. Perform the movement
switch (mode)
{
case SelectionExpansion::Char:
_MoveByChar(direction, targetPos);
break;
case SelectionExpansion::Word:
_MoveByWord(direction, targetPos);
break;
case SelectionExpansion::Viewport:
_MoveByViewport(direction, targetPos);
break;
case SelectionExpansion::Buffer:
_MoveByBuffer(direction, targetPos);
break;
}
// 3. Actually modify the selection
// NOTE: targetStart doesn't matter here
bool targetStart = false;
std::tie(_selection->start, _selection->end) = _PivotSelection(targetPos, targetStart);
// 4. Scroll (if necessary)
if (const auto viewport = _GetVisibleViewport(); !viewport.IsInBounds(targetPos))
{
if (const auto amtAboveView = viewport.Top() - targetPos.Y; amtAboveView > 0)
{
// anchor is above visible viewport, scroll by that amount
_scrollOffset += amtAboveView;
}
else
{
// anchor is below visible viewport, scroll by that amount
const auto amtBelowView = targetPos.Y - viewport.BottomInclusive();
_scrollOffset -= amtBelowView;
}
_NotifyScrollEvent();
_buffer->GetRenderTarget().TriggerScroll();
}
}
void Terminal::_MoveByChar(SelectionDirection direction, COORD& pos)
{
switch (direction)
{
case SelectionDirection::Left:
_buffer->GetSize().DecrementInBounds(pos);
pos = _buffer->GetGlyphStart(pos);
break;
case SelectionDirection::Right:
_buffer->GetSize().IncrementInBounds(pos);
pos = _buffer->GetGlyphEnd(pos);
break;
case SelectionDirection::Up:
{
const auto bufferSize{ _buffer->GetSize() };
pos = { pos.X, std::clamp(base::ClampSub<short, short>(pos.Y, 1).RawValue(), bufferSize.Top(), bufferSize.BottomInclusive()) };
break;
}
case SelectionDirection::Down:
{
const auto bufferSize{ _buffer->GetSize() };
pos = { pos.X, std::clamp(base::ClampAdd<short, short>(pos.Y, 1).RawValue(), bufferSize.Top(), bufferSize.BottomInclusive()) };
break;
}
}
}
void Terminal::_MoveByWord(SelectionDirection direction, COORD& pos)
{
switch (direction)
{
case SelectionDirection::Left:
const auto wordStartPos{ _buffer->GetWordStart(pos, _wordDelimiters) };
if (_buffer->GetSize().CompareInBounds(_selection->pivot, pos) < 0)
{
// If we're moving towards the pivot, move one more cell
pos = wordStartPos;
_buffer->GetSize().DecrementInBounds(pos);
}
else if (wordStartPos == pos)
{
// already at the beginning of the current word,
// move to the beginning of the previous word
_buffer->GetSize().DecrementInBounds(pos);
pos = _buffer->GetWordStart(pos, _wordDelimiters);
}
else
{
// move to the beginning of the current word
pos = wordStartPos;
}
break;
case SelectionDirection::Right:
const auto wordEndPos{ _buffer->GetWordEnd(pos, _wordDelimiters) };
if (_buffer->GetSize().CompareInBounds(pos, _selection->pivot) < 0)
{
// If we're moving towards the pivot, move one more cell
pos = _buffer->GetWordEnd(pos, _wordDelimiters);
_buffer->GetSize().IncrementInBounds(pos);
}
else if (wordEndPos == pos)
{
// already at the end of the current word,
// move to the end of the next word
_buffer->GetSize().IncrementInBounds(pos);
pos = _buffer->GetWordEnd(pos, _wordDelimiters);
}
else
{
// move to the end of the current word
pos = wordEndPos;
}
break;
case SelectionDirection::Up:
_MoveByChar(direction, pos);
pos = _buffer->GetWordStart(pos, _wordDelimiters);
break;
case SelectionDirection::Down:
_MoveByChar(direction, pos);
pos = _buffer->GetWordEnd(pos, _wordDelimiters);
break;
}
}
void Terminal::_MoveByViewport(SelectionDirection direction, COORD& pos)
{
const auto bufferSize{ _buffer->GetSize() };
switch (direction)
{
case SelectionDirection::Left:
pos = { bufferSize.Left(), pos.Y };
break;
case SelectionDirection::Right:
pos = { bufferSize.RightInclusive(), pos.Y };
break;
case SelectionDirection::Up:
{
const auto viewportHeight{ _mutableViewport.Height() };
const auto newY{ base::ClampSub<short, short>(pos.Y, viewportHeight) };
pos = newY < bufferSize.Top() ? bufferSize.Origin() : COORD{ pos.X, newY };
break;
}
case SelectionDirection::Down:
{
const auto viewportHeight{ _mutableViewport.Height() };
const auto mutableBottom{ _mutableViewport.BottomInclusive() };
const auto newY{ base::ClampAdd<short, short>(pos.Y, viewportHeight) };
pos = newY > mutableBottom ? COORD{ bufferSize.RightInclusive(), mutableBottom } : COORD{ pos.X, newY };
break;
}
}
}
void Terminal::_MoveByBuffer(SelectionDirection direction, COORD& pos)
{
const auto bufferSize{ _buffer->GetSize() };
switch (direction)
{
case SelectionDirection::Left:
case SelectionDirection::Up:
pos = bufferSize.Origin();
break;
case SelectionDirection::Right:
case SelectionDirection::Down:
pos = { bufferSize.RightInclusive(), _mutableViewport.BottomInclusive() };
break;
}
}
2019-06-19 00:53:29 +02:00
// Method Description:
// - clear selection data and disable rendering it
#pragma warning(disable : 26440) // changing this to noexcept would require a change to ConHost's selection model
Accessibility: Set-up UIA Tree (#1691) **The Basics of Accessibility** - [What is a User Interaction Automation (UIA) Tree?](https://docs.microsoft.com/en-us/dotnet/framework/ui-automation/ui-automation-tree-overview) - Other projects (i.e.: Narrator) can take advantage of this UIA tree and are used to present information within it. - Some things like XAML already have a UIA Tree. So some UIA tree navigation and features are already there. It's just a matter of getting them hooked up and looking right. **Accessibility in our Project** There's a few important classes... regarding Accessibility... - **WindowUiaProvider**: This sets up the UIA tree for a window. So this is the top-level for the UIA tree. - **ScreenInfoUiaProvider**: This sets up the UIA tree for a terminal buffer. - **UiaTextRange**: This is essential to interacting with the UIA tree for the terminal buffer. Actually gets portions of the buffer and presents them. regarding the Windows Terminal window... - **BaseWindow**: The foundation to a window. Deals with HWNDs and that kind of stuff. - **IslandWindow**: This extends `BaseWindow` and is actually what holds our Windows Terminal - **NonClientIslandWindow**: An extension of the `IslandWindow` regarding ConHost... - **IConsoleWindow**: This is an interface for the console window. - **Window**: This is the actual window for ConHost. Extends `IConsoleWindow` - `IConsoleWindow` changes: - move into `Microsoft::Console::Types` (a shared space) - Have `IslandWindow` extend it - `WindowUiaProvider` changes: - move into `Microsoft::Console::Types` (a shared space) - Hook up `WindowUiaProvider` to IslandWindow (yay! we now have a tree) ### Changes to the WindowUiaProvider As mentioned earlier, the WindowUiaProvider is the top-level UIA provider for our projects. To reuse as much code as possible, I created `Microsoft::Console::Types::WindowUiaProviderBase`. Any existing functions that reference a `ScreenInfoUiaProvider` were virtual-ized. In each project, a `WindowUiaProvider : WindowUiaProviderBase` was created to define those virtual functions. Note that that will be the main difference between ConHost and Windows Terminal moving forward: how many TextBuffers are on the screen. So, ConHost should be the same as before, with only one `ScreenInfoUiaProvider`, whereas Windows Terminal needs to (1) update which one is on the screen and (2) may have multiple on the screen. 🚨 Windows Terminal doesn't have the `ScreenInfoUiaProvider` hooked up yet. We'll have all the XAML elements in the UIA tree. But, since `TermControl` is a custom XAML Control, I need to hook up the `ScreenInfoUiaProvider` to it. This work will be done in a new PR and resolve GitHub Issue #1352. ### Moved to `Microsoft::Console::Types` These files got moved to a shared area so that they can be used by both ConHost and Windows Terminal. This means that any references to the `ServiceLocator` had to be removed. - `IConsoleWindow` - Windows Terminal: `IslandWindow : IConsoleWindow` - `ScreenInfoUiaProvider` - all references to `ServiceLocator` and `SCREEN_INFORMATION` were removed. `IRenderData` was used to accomplish this. Refer to next section for more details. - `UiaTextRange` - all references to `ServiceLocator` and `SCREEN_INFORMATION` were removed. `IRenderData` was used to accomplish this. Refer to next section for more details. - since most of the functions were `static`, that means that an `IRenderData` had to be added into most of them. ### Changes to IRenderData Since `IRenderData` is now being used to abstract out `ServiceLocator` and `SCREEN_INFORMATION`, I had to add a few functions here: - `bool IsAreaSelected()` - `void ClearSelection()` - `void SelectNewRegion(...)` - `HRESULT SearchForText(...)` `SearchForText()` is a problem here. The overall new design is great! But Windows Terminal doesn't have a way to search for text in the buffer yet, whereas ConHost does. So I'm punting on this issue for now. It looks nasty, but just look at all the other pretty things here. :)
2019-07-30 00:21:15 +02:00
void Terminal::ClearSelection()
2019-06-19 00:53:29 +02:00
{
Move rect expansion to textbuffer; refactor selection code (#4560) - When performing chunk selection, the expansion now occurs at the time of the selection, not the rendering of the selection - `GetSelectionRects()` was moved to the `TextBuffer` and is now shared between ConHost and Windows Terminal - Some of the selection variables were renamed for clarity - Selection COORDs are now in the Text Buffer coordinate space - Fixes an issue with Shift+Click after performing a Multi-Click Selection ## References This also contributes to... - #4509: UIA Box Selection - #2447: UIA Signaling for Selection - #1354: UIA support for Wide Glyphs Now that the expansion occurs at before render-time, the selection anchors are an accurate representation of what is selected. We just need to move `GetText` to the `TextBuffer`. Then we can have those three issues just rely on code from the text buffer. This also means ConHost gets some of this stuff for free 😀 ### TextBuffer - `GetTextRects` is the abstracted form of `GetSelectionRects` - `_ExpandTextRow` is still needed to handle wide glyphs properly ### Terminal - Rename... - `_boxSelection` --> `_blockSelection` for consistency with ConHost - `_selectionAnchor` --> `_selectionStart` for consistency with UIA - `_endSelectionPosition` --> `_selectionEnd` for consistency with UIA - Selection anchors are in Text Buffer coordinates now - Really rely on `SetSelectionEnd` to accomplish appropriate chunk selection and shift+click actions ## Validation Steps Performed - Shift+Click - Multi-Click --> Shift+Click - Chunk Selection at... - top of buffer - bottom of buffer - random region in scrollback Closes #4465 Closes #4547
2020-02-28 01:42:26 +01:00
_selection = std::nullopt;
2019-06-19 00:53:29 +02:00
}
// Method Description:
// - get wstring text from highlighted portion of text buffer
// Arguments:
// - singleLine: collapse all of the text to one line
2019-06-19 00:53:29 +02:00
// Return Value:
// - wstring text from buffer. If extended to multiple lines, each line is separated by \r\n
Split `TermControl` into a Core, Interactivity, and Control layer (#9820) ## Summary of the Pull Request Brace yourselves, it's finally here. This PR does the dirty work of splitting the monolithic `TermControl` into three components. These components are: * `ControlCore`: This encapsulates the `Terminal` instance, the `DxEngine` and `Renderer`, and the `Connection`. 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. * `ControlInteractivity`: This is a wrapper for the `ControlCore`, which 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. * `TermControl`: This is the UWP control. It's got a Core and Interactivity inside it, which it uses for the actual logic of the terminal itself. TermControl's main responsibility is now By splitting into smaller pieces, it will enable us to * write unit tests for the `Core` and `Interactivity` bits, which we desparately need * Combine `ControlCore` and `ControlInteractivity` in an out-of-proc core process in the future, to enable tab tearout. However, we're not doing that work quite yet. There's still lots of work to be done to enable that, thought this is likely the biggest portion. Ideally, this would just be methods moved wholesale from one file to another. Unfortunately, there are a bunch of cases where that didn't work as well as expected. Especially when trying to better enforce the boundary between the classes. We've got a couple tests here that I've added. These are partially examples, and partially things I ran into while implementing this. A bunch of things from #7001 can go in now that we have this. This PR is gonna be a huge pain to review - 38 files with 3,730 additions and 1,661 deletions is nothing to scoff at. It will also conflict 100% with anything that's targeting `TermControl`. I'm hoping we can review this over the course of the next week and just be done with it, and leave plenty of runway for 1.9 bugs in post. ## References * In pursuit of #1256 * Proc Model: #5000 * https://github.com/microsoft/terminal/projects/5 ## PR Checklist * [x] Closes #6842 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760249 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760258 * [x] I work here * [x] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments * I don't love the names `ControlCore` and `ControlInteractivity`. Open to other names. * I added a `ICoreState` interface for "properties that come from the `ControlCore`, but consumers of the `TermControl` need to know". In the future, these will all need to be handled specially, because they might involve an RPC call to retrieve the info from the core (or cache it) in the window process. * I've added more `EventArgs` to make more events proper `TypedEvent`s. * I've changed how the TerminalApp layer requests updated TaskbarProgress state. It doesn't need to pump TermControl to raise a new event anymore. * ~~Something that snuck into this branch in the very long history is the switch to `DCompositionCreateSurfaceHandle` for the `DxEngine`. @miniksa wrote this originally in 30b8335, I'm just finally committing it here. We'll need that in the future for the out-of-proc stuff.~~ * I reverted this in c113b65d9. We can revert _that_ commit when we want to come back to it. * I've changed the acrylic handler a decent amount. But added tests! * All the `ThrottledFunc` things are left in `TermControl`. Some might be able to move down into core/interactivity, but once we figure out how to use a different kind of Dispatcher (because a UI thread won't necessarily exist for those components). * I've undoubtably messed up the merging of the locking around the appearance config stuff recently ## Validation Steps Performed I've got a rolling list in https://github.com/microsoft/terminal/issues/6842#issuecomment-810990460 that I'm updating as I go.
2021-04-27 17:50:45 +02:00
const TextBuffer::TextAndColor Terminal::RetrieveSelectedTextFromBuffer(bool singleLine)
2019-06-19 00:53:29 +02:00
{
Split `TermControl` into a Core, Interactivity, and Control layer (#9820) ## Summary of the Pull Request Brace yourselves, it's finally here. This PR does the dirty work of splitting the monolithic `TermControl` into three components. These components are: * `ControlCore`: This encapsulates the `Terminal` instance, the `DxEngine` and `Renderer`, and the `Connection`. 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. * `ControlInteractivity`: This is a wrapper for the `ControlCore`, which 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. * `TermControl`: This is the UWP control. It's got a Core and Interactivity inside it, which it uses for the actual logic of the terminal itself. TermControl's main responsibility is now By splitting into smaller pieces, it will enable us to * write unit tests for the `Core` and `Interactivity` bits, which we desparately need * Combine `ControlCore` and `ControlInteractivity` in an out-of-proc core process in the future, to enable tab tearout. However, we're not doing that work quite yet. There's still lots of work to be done to enable that, thought this is likely the biggest portion. Ideally, this would just be methods moved wholesale from one file to another. Unfortunately, there are a bunch of cases where that didn't work as well as expected. Especially when trying to better enforce the boundary between the classes. We've got a couple tests here that I've added. These are partially examples, and partially things I ran into while implementing this. A bunch of things from #7001 can go in now that we have this. This PR is gonna be a huge pain to review - 38 files with 3,730 additions and 1,661 deletions is nothing to scoff at. It will also conflict 100% with anything that's targeting `TermControl`. I'm hoping we can review this over the course of the next week and just be done with it, and leave plenty of runway for 1.9 bugs in post. ## References * In pursuit of #1256 * Proc Model: #5000 * https://github.com/microsoft/terminal/projects/5 ## PR Checklist * [x] Closes #6842 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760249 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760258 * [x] I work here * [x] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments * I don't love the names `ControlCore` and `ControlInteractivity`. Open to other names. * I added a `ICoreState` interface for "properties that come from the `ControlCore`, but consumers of the `TermControl` need to know". In the future, these will all need to be handled specially, because they might involve an RPC call to retrieve the info from the core (or cache it) in the window process. * I've added more `EventArgs` to make more events proper `TypedEvent`s. * I've changed how the TerminalApp layer requests updated TaskbarProgress state. It doesn't need to pump TermControl to raise a new event anymore. * ~~Something that snuck into this branch in the very long history is the switch to `DCompositionCreateSurfaceHandle` for the `DxEngine`. @miniksa wrote this originally in 30b8335, I'm just finally committing it here. We'll need that in the future for the out-of-proc stuff.~~ * I reverted this in c113b65d9. We can revert _that_ commit when we want to come back to it. * I've changed the acrylic handler a decent amount. But added tests! * All the `ThrottledFunc` things are left in `TermControl`. Some might be able to move down into core/interactivity, but once we figure out how to use a different kind of Dispatcher (because a UI thread won't necessarily exist for those components). * I've undoubtably messed up the merging of the locking around the appearance config stuff recently ## Validation Steps Performed I've got a rolling list in https://github.com/microsoft/terminal/issues/6842#issuecomment-810990460 that I'm updating as I go.
2021-04-27 17:50:45 +02:00
auto lock = LockForReading();
const auto selectionRects = _GetSelectionRects();
Refactor the renderer color calculations (#6853) This is a refactoring of the renderer color calculations to simplify the implementation, and to make it easier to support additional color-altering rendition attributes in the future (e.g. _faint_ and _conceal_). ## References * This is a followup to PRs #3817 and #6809, which introduced additional complexity in the color calculations, and which suggested the need for refactoring. ## Detailed Description of the Pull Request / Additional comments When we added support for `DECSCNM`, that required the foreground and background color lookup methods to be able to return the opposite of what was requested when the reversed mode was set. That made those methods unnecessarily complicated, and I thought we could simplify them considerably just by combining the calculations into a single method that derived both colors at the same time. And since both conhost and Windows Terminal needed to perform the same calculations, it also made sense to move that functionality into the `TextAttribute` class, where it could easily be shared. In general this way of doing things is a bit more efficient. However, it does result in some unnecessary work when only one of the colors is required, as is the case for the gridline painter. So to make that less of an issue, I've reordered the gridline code a bit so it at least avoids looking up the colors when no gridlines are needed. ## Validation Steps Performed Because of the API changes, quite a lot of the unit tests had to be updated. For example instead of verifying colors with two separate calls to `LookupForegroundColor` and `LookupBackgroundColor`, that's now achieved with a single `LookupAttributeColors` call, comparing against a pair of values. The specifics of the tests haven't changed though, and they're all still working as expected. I've also manually confirmed that the various color sequences and rendition attributes are rendering correctly with the new refactoring.
2020-07-11 00:26:34 +02:00
const auto GetAttributeColors = std::bind(&Terminal::GetAttributeColors, this, std::placeholders::_1);
2019-06-19 00:53:29 +02:00
// GH#6740: Block selection should preserve the visual structure:
// - CRLFs need to be added - so the lines structure is preserved
// - We should apply formatting above to wrapped rows as well (newline should be added).
// GH#9706: Trimming of trailing white-spaces in block selection is configurable.
const auto includeCRLF = !singleLine || _blockSelection;
const auto trimTrailingWhitespace = !singleLine && (!_blockSelection || _trimBlockSelection);
const auto formatWrappedRows = _blockSelection;
return _buffer->GetText(includeCRLF, trimTrailingWhitespace, selectionRects, GetAttributeColors, formatWrappedRows);
2019-06-19 00:53:29 +02:00
}
// Method Description:
// - convert viewport position to the corresponding location on the buffer
// Arguments:
// - viewportPos: a coordinate on the viewport
// Return Value:
// - the corresponding location on the buffer
COORD Terminal::_ConvertToBufferCell(const COORD viewportPos) const
{
Move rect expansion to textbuffer; refactor selection code (#4560) - When performing chunk selection, the expansion now occurs at the time of the selection, not the rendering of the selection - `GetSelectionRects()` was moved to the `TextBuffer` and is now shared between ConHost and Windows Terminal - Some of the selection variables were renamed for clarity - Selection COORDs are now in the Text Buffer coordinate space - Fixes an issue with Shift+Click after performing a Multi-Click Selection ## References This also contributes to... - #4509: UIA Box Selection - #2447: UIA Signaling for Selection - #1354: UIA support for Wide Glyphs Now that the expansion occurs at before render-time, the selection anchors are an accurate representation of what is selected. We just need to move `GetText` to the `TextBuffer`. Then we can have those three issues just rely on code from the text buffer. This also means ConHost gets some of this stuff for free 😀 ### TextBuffer - `GetTextRects` is the abstracted form of `GetSelectionRects` - `_ExpandTextRow` is still needed to handle wide glyphs properly ### Terminal - Rename... - `_boxSelection` --> `_blockSelection` for consistency with ConHost - `_selectionAnchor` --> `_selectionStart` for consistency with UIA - `_endSelectionPosition` --> `_selectionEnd` for consistency with UIA - Selection anchors are in Text Buffer coordinates now - Really rely on `SetSelectionEnd` to accomplish appropriate chunk selection and shift+click actions ## Validation Steps Performed - Shift+Click - Multi-Click --> Shift+Click - Chunk Selection at... - top of buffer - bottom of buffer - random region in scrollback Closes #4465 Closes #4547
2020-02-28 01:42:26 +01:00
const auto yPos = base::ClampedNumeric<short>(_VisibleStartIndex()) + viewportPos.Y;
COORD bufferPos = { viewportPos.X, yPos };
_buffer->GetSize().Clamp(bufferPos);
return bufferPos;
}
// Method Description:
// - This method won't be used. We just throw and do nothing. For now we
// need this method to implement UiaData interface
// Arguments:
// - coordSelectionStart - Not used
// - coordSelectionEnd - Not used
// - attr - Not used.
void Terminal::ColorSelection(const COORD, const COORD, const TextAttribute)
{
THROW_HR(E_NOTIMPL);
}