Repository: microsoft/terminal
File: src/cascadia/TerminalControl/TermControl.cpp (C++)

Code before:
                const unsigned int MAX_CLICK_COUNT = 3;
                const auto multiClickMapper = clickCount > MAX_CLICK_COUNT ? ((clickCount + MAX_CLICK_COUNT - 1) % MAX_CLICK_COUNT) + 1 : clickCount;

                ::Terminal::SelectionExpansionMode mode = ::Terminal::SelectionExpansionMode::Cell;
                if (multiClickMapper == 1)
                {
                    mode = ::Terminal::SelectionExpansionMode::Cell;
                }
                else if (multiClickMapper == 2)
                {
                    mode = ::Terminal::SelectionExpansionMode::Word;
                }
                else if (multiClickMapper == 3)
                {
                    mode = ::Terminal::SelectionExpansionMode::Line;
                }

                if (ctrlEnabled && multiClickMapper == 1 &&
                    !(_terminal->GetHyperlinkAtPosition(terminalPosition).empty()))
                {
                    _HyperlinkHandler(_terminal->GetHyperlinkAtPosition(terminalPosition));
                }
                else if (_CanSendVTMouseInput())
                {
                    // GH#9396: hyper-link gets higher priority than mouse mode
                    _TrySendMouseEvent(point);
                }
                else
                {
                    // Update the selection appropriately

                    // Capture the position of the first click when no selection is active
                    if (mode == ::Terminal::SelectionExpansionMode::Cell && !_terminal->IsSelectionActive())
                    {
                        _singleClickTouchdownPos = cursorPosition;
                        _lastMouseClickPosNoSelection = cursorPosition;
                    }

                    // We reset the active selection if one of the conditions apply:
                    // - shift is not held
                    // - GH#9384: the position is the same as of the first click starting the selection
                    // (we need to reset selection on double-click or triple-click, so it captures the word or the line,
                    // rather than extending the selection)
                    if (_terminal->IsSelectionActive() && (!shiftEnabled || _lastMouseClickPosNoSelection == cursorPosition))
                    {
                        // Reset the selection
                        _terminal->ClearSelection();
                        _selectionNeedsToBeCopied = false; // there's no selection, so there's nothing to update
                    }

                    if (shiftEnabled)

Review comment (refactor):
I'm a bit worried about the flow of code through these conditionals. This will change the block selection state, track click counts, etc. before dispatching a mouse event.

We might be overdue for refactoring the click dispatcher. . . but this seems a bit too entangled for my taste?

Code after:
            else if (_CanSendVTMouseInput())
            {
                _TrySendMouseEvent(point);
            }
            else if (point.Properties().IsLeftButtonPressed())
            {
                // Update the selection appropriately
                // handle ALT key
                _terminal->SetBlockSelection(altEnabled);

                const auto clickCount = _NumberOfClicks(cursorPosition, point.Timestamp());

                // This formula enables the number of clicks to cycle properly between single-, double-, and triple-click.
                // To increase the number of acceptable click states, simply increment MAX_CLICK_COUNT and add another if-statement
                const unsigned int MAX_CLICK_COUNT = 3;
                const auto multiClickMapper = clickCount > MAX_CLICK_COUNT ? ((clickCount + MAX_CLICK_COUNT - 1) % MAX_CLICK_COUNT) + 1 : clickCount;

                ::Terminal::SelectionExpansionMode mode = ::Terminal::SelectionExpansionMode::Cell;
                if (multiClickMapper == 1)
                {
                    mode = ::Terminal::SelectionExpansionMode::Cell;
                }
                else if (multiClickMapper == 2)
                {
                    mode = ::Terminal::SelectionExpansionMode::Word;
                }
                else if (multiClickMapper == 3)
                {
                    mode = ::Terminal::SelectionExpansionMode::Line;
                }

                // Capture the position of the first click when no selection is active
                if (mode == ::Terminal::SelectionExpansionMode::Cell && !_terminal->IsSelectionActive())
                {
                    _singleClickTouchdownPos = cursorPosition;
                    _lastMouseClickPosNoSelection = cursorPosition;
                }

                // We reset the active selection if one of the conditions apply:
                // - shift is not held
                // - GH#9384: the position is the same as of the first click starting the selection
                // (we need to reset selection on double-click or triple-click, so it captures the word or the line,
                // rather than extending the selection)
                if (_terminal->IsSelectionActive() && (!shiftEnabled || _lastMouseClickPosNoSelection == cursorPosition))
                {
                    // Reset the selection
                    _terminal->ClearSelection();
                    _selectionNeedsToBeCopied = false; // there's no selection, so there's nothing to update
                }

                if (shiftEnabled)