Compare commits

...

2 Commits

Author SHA1 Message Date
Mike Griese
ee8082050e helper script 2023-05-09 15:13:58 -05:00
Mike Griese
c365792868 Proof-of-concept: Click text, get input
* uses the actual payload instead of the visible text
* no tooltip
* Shouldn't be a 9001 OSC, should probably be a property on osc8
* feels dirty
* works
2023-05-09 12:00:36 -05:00
17 changed files with 142 additions and 30 deletions

View File

@@ -2637,9 +2637,9 @@ HRESULT TextBuffer::Reflow(TextBuffer& oldBuffer,
// - Adds or updates a hyperlink in our hyperlink table
// Arguments:
// - The hyperlink URI, the hyperlink id (could be new or old)
void TextBuffer::AddHyperlinkToMap(std::wstring_view uri, uint16_t id)
void TextBuffer::AddHyperlinkToMap(LinkData data, uint16_t id)
{
_hyperlinkMap[id] = uri;
_hyperlinkMap[id] = data;
}
// Method Description:
@@ -2648,7 +2648,7 @@ void TextBuffer::AddHyperlinkToMap(std::wstring_view uri, uint16_t id)
// - The hyperlink ID
// Return Value:
// - The URI
std::wstring TextBuffer::GetHyperlinkUriFromId(uint16_t id) const
const LinkData& TextBuffer::GetHyperlinkUriFromId(uint16_t id) const
{
return _hyperlinkMap.at(id);
}

View File

@@ -64,6 +64,20 @@ namespace Microsoft::Console::Render
class Renderer;
}
enum class LinkType
{
None = 0,
Url,
SendInput,
};
struct LinkData
{
std::wstring payload;
LinkType type{ LinkType::None };
bool IsUrl() const { return type == LinkType::Url; };
};
class TextBuffer final
{
public:
@@ -167,8 +181,8 @@ public:
const std::vector<til::inclusive_rect> GetTextRects(til::point start, til::point end, bool blockSelection, bool bufferCoordinates) const;
std::vector<til::point_span> GetTextSpans(til::point start, til::point end, bool blockSelection, bool bufferCoordinates) const;
void AddHyperlinkToMap(std::wstring_view uri, uint16_t id);
std::wstring GetHyperlinkUriFromId(uint16_t id) const;
void AddHyperlinkToMap(LinkData uri, uint16_t id);
const LinkData& GetHyperlinkUriFromId(uint16_t id) const;
uint16_t GetHyperlinkId(std::wstring_view uri, std::wstring_view id);
void RemoveHyperlinkFromMap(uint16_t id) noexcept;
std::wstring GetCustomIdFromId(uint16_t id) const;
@@ -242,7 +256,7 @@ private:
Microsoft::Console::Render::Renderer& _renderer;
std::unordered_map<uint16_t, std::wstring> _hyperlinkMap;
std::unordered_map<uint16_t, LinkData> _hyperlinkMap;
std::unordered_map<std::wstring, uint16_t> _hyperlinkCustomIdMap;
uint16_t _currentHyperlinkId = 1;

View File

@@ -544,9 +544,9 @@ namespace winrt::Microsoft::Terminal::Control::implementation
{
// Ctrl + Enter --> Open URL
auto lock = _terminal->LockForReading();
if (const auto uri = _terminal->GetHyperlinkAtBufferPosition(_terminal->GetSelectionAnchor()); !uri.empty())
if (const auto uri = _terminal->GetHyperlinkAtBufferPosition(_terminal->GetSelectionAnchor()); !uri.payload.empty())
{
_OpenHyperlinkHandlers(*this, winrt::make<OpenHyperlinkEventArgs>(winrt::hstring{ uri }));
_OpenHyperlinkHandlers(*this, winrt::make<OpenHyperlinkEventArgs>(winrt::hstring{ uri.payload }));
}
else
{
@@ -780,11 +780,12 @@ namespace winrt::Microsoft::Terminal::Control::implementation
}
}
winrt::hstring ControlCore::GetHyperlink(const Core::Point pos) const
LinkData ControlCore::GetHyperlink(const Core::Point pos) const
{
// Lock for the duration of our reads.
auto lock = _terminal->LockForReading();
return winrt::hstring{ _terminal->GetHyperlinkAtViewportPosition(til::point{ pos }) };
// return winrt::hstring{ _terminal->GetHyperlinkAtViewportPosition(til::point{ pos }) };
return _terminal->GetHyperlinkAtViewportPosition(til::point{ pos });
}
winrt::hstring ControlCore::HoveredUriText() const
@@ -792,9 +793,11 @@ namespace winrt::Microsoft::Terminal::Control::implementation
auto lock = _terminal->LockForReading(); // Lock for the duration of our reads.
if (_lastHoveredCell.has_value())
{
auto uri{ _terminal->GetHyperlinkAtViewportPosition(*_lastHoveredCell) };
uri.resize(std::min<size_t>(1024u, uri.size())); // Truncate for display
return winrt::hstring{ uri };
auto uriData{ _terminal->GetHyperlinkAtViewportPosition(*_lastHoveredCell) };
if (!uriData.IsUrl())
return {};
uriData.payload.resize(std::min<size_t>(1024u, uriData.payload.size())); // Truncate for display
return winrt::hstring{ uriData.payload };
}
return {};
}

View File

@@ -121,7 +121,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
void SetHoveredCell(Core::Point terminalPosition);
void ClearHoveredCell();
winrt::hstring GetHyperlink(const Core::Point position) const;
LinkData GetHyperlink(const Core::Point position) const;
winrt::hstring HoveredUriText() const;
Windows::Foundation::IReference<Core::Point> HoveredCell() const;

View File

@@ -255,16 +255,16 @@ namespace winrt::Microsoft::Terminal::Control::implementation
const auto ctrlEnabled = modifiers.IsCtrlPressed();
// GH#9396: we prioritize hyper-link over VT mouse events
auto hyperlink = _core->GetHyperlink(terminalPosition.to_core_point());
auto hyperlinkData = _core->GetHyperlink(terminalPosition.to_core_point());
if (WI_IsFlagSet(buttonState, MouseButtonState::IsLeftButtonDown) &&
ctrlEnabled &&
!hyperlink.empty())
!hyperlinkData.payload.empty())
{
const auto clickCount = _numberOfClicks(pixelPosition, timestamp);
// Handle hyper-link only on the first click to prevent multiple activations
if (clickCount == 1)
{
_hyperlinkHandler(hyperlink);
_hyperlinkHandler(hyperlinkData);
}
}
else if (_canSendVTMouseInput(modifiers))
@@ -632,9 +632,16 @@ namespace winrt::Microsoft::Terminal::Control::implementation
}
}
void ControlInteractivity::_hyperlinkHandler(const std::wstring_view uri)
void ControlInteractivity::_hyperlinkHandler(const LinkData& uriData)
{
_OpenHyperlinkHandlers(*this, winrt::make<OpenHyperlinkEventArgs>(winrt::hstring{ uri }));
if (uriData.type == LinkType::Url)
{
_OpenHyperlinkHandlers(*this, winrt::make<OpenHyperlinkEventArgs>(winrt::hstring{ uriData.payload }));
}
else if (uriData.type == LinkType::SendInput)
{
_sendPastedTextToConnection(uriData.payload);
}
}
bool ControlInteractivity::_canSendVTMouseInput(const ::Microsoft::Terminal::Core::ControlKeyStates modifiers)

View File

@@ -151,7 +151,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
const Core::Point terminalPosition,
const bool isLeftButtonPressed);
void _hyperlinkHandler(const std::wstring_view uri);
void _hyperlinkHandler(const LinkData& uri);
bool _canSendVTMouseInput(const ::Microsoft::Terminal::Core::ControlKeyStates modifiers);
bool _shouldSendAlternateScroll(const ::Microsoft::Terminal::Core::ControlKeyStates modifiers, const int32_t delta);

View File

@@ -561,18 +561,28 @@ bool Terminal::ShouldSendAlternateScroll(const unsigned int uiButton,
// - Given a coord, get the URI at that location
// Arguments:
// - The position relative to the viewport
std::wstring Terminal::GetHyperlinkAtViewportPosition(const til::point viewportPos)
LinkData Terminal::GetHyperlinkAtViewportPosition(const til::point viewportPos)
{
return GetHyperlinkAtBufferPosition(_ConvertToBufferCell(viewportPos));
}
std::wstring Terminal::GetHyperlinkAtBufferPosition(const til::point bufferPos)
LinkData Terminal::GetHyperlinkAtBufferPosition(const til::point bufferPos)
{
// Case 1: buffer position has a hyperlink stored in the buffer
const auto attr = _activeBuffer().GetCellDataAt(bufferPos)->TextAttr();
if (attr.IsHyperlink())
{
return _activeBuffer().GetHyperlinkUriFromId(attr.GetHyperlinkId());
const auto& linkData{ _activeBuffer().GetHyperlinkUriFromId(attr.GetHyperlinkId()) };
return linkData;
// if (linkData.IsUrl())
// {
// return linkData.payload;
// }
// else
// {
// return {};
// }
// return _activeBuffer().GetHyperlinkUriFromId(attr.GetHyperlinkId());
}
// Case 2: buffer position may point to an auto-detected hyperlink
@@ -619,9 +629,9 @@ std::wstring Terminal::GetHyperlinkAtBufferPosition(const til::point bufferPos)
{
uri += iter->Chars();
}
return uri;
return LinkData{ uri, LinkType::Url };
}
return {};
return LinkData{};
}
// Method Description:

View File

@@ -161,8 +161,8 @@ public:
void FocusChanged(const bool focused) noexcept override;
std::wstring GetHyperlinkAtViewportPosition(const til::point viewportPos);
std::wstring GetHyperlinkAtBufferPosition(const til::point bufferPos);
LinkData GetHyperlinkAtViewportPosition(const til::point viewportPos);
LinkData GetHyperlinkAtBufferPosition(const til::point bufferPos);
uint16_t GetHyperlinkIdAtViewportPosition(const til::point viewportPos);
std::optional<interval_tree::IntervalTree<til::point, size_t>::interval> GetHyperlinkIntervalFromViewportPosition(const til::point viewportPos);
#pragma endregion

View File

@@ -89,7 +89,15 @@ const bool Terminal::IsGridLineDrawingAllowed() noexcept
const std::wstring Microsoft::Terminal::Core::Terminal::GetHyperlinkUri(uint16_t id) const
{
return _activeBuffer().GetHyperlinkUriFromId(id);
const auto& linkData{ _activeBuffer().GetHyperlinkUriFromId(id) };
if (linkData.IsUrl())
{
return linkData.payload;
}
else
{
return {};
}
}
const std::wstring Microsoft::Terminal::Core::Terminal::GetHyperlinkCustomId(uint16_t id) const

View File

@@ -297,7 +297,15 @@ const std::wstring_view RenderData::GetConsoleTitle() const noexcept
const std::wstring RenderData::GetHyperlinkUri(uint16_t id) const
{
const auto& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
return gci.GetActiveOutputBuffer().GetTextBuffer().GetHyperlinkUriFromId(id);
const auto& linkData{ gci.GetActiveOutputBuffer().GetTextBuffer().GetHyperlinkUriFromId(id) };
if (linkData.IsUrl())
{
return linkData.payload;
}
else
{
return {};
}
}
// Method Description:

View File

@@ -132,6 +132,8 @@ public:
virtual bool DoFinalTermAction(const std::wstring_view string) = 0;
virtual bool DoWtAction(const std::wstring_view string) = 0;
virtual StringHandler DownloadDRCS(const VTInt fontNumber,
const VTParameter startChar,
const DispatchTypes::DrcsEraseControl eraseControl,

View File

@@ -3076,7 +3076,7 @@ bool AdaptDispatch::AddHyperlink(const std::wstring_view uri, const std::wstring
const auto id = textBuffer.GetHyperlinkId(uri, params);
attr.SetHyperlinkId(id);
textBuffer.SetCurrentAttributes(attr);
textBuffer.AddHyperlinkToMap(uri, id);
textBuffer.AddHyperlinkToMap(LinkData{ std::wstring{ uri }, LinkType::Url }, id);
return true;
}
@@ -3331,6 +3331,51 @@ bool AdaptDispatch::DoFinalTermAction(const std::wstring_view string)
return false;
}
bool AdaptDispatch::DoWtAction(const std::wstring_view string)
{
// This is not implemented in conhost.
if (_api.IsConsolePty())
{
// Flush the frame manually, to make sure marks end up on the right line, like the alt buffer sequence.
_renderer.TriggerFlush(false);
return false;
}
const auto parts = Utils::SplitString(string, L';');
if (parts.size() < 1)
{
return false;
}
const auto action = til::at(parts, 0);
if (action == L"a")
{
if (parts.size() < 2)
{
return false;
}
auto uri = til::at(parts, 1);
auto& textBuffer = _api.GetTextBuffer();
auto attr = textBuffer.GetCurrentAttributes();
const auto id = textBuffer.GetHyperlinkId(uri, {});
attr.SetHyperlinkId(id);
textBuffer.SetCurrentAttributes(attr);
textBuffer.AddHyperlinkToMap(LinkData{ std::wstring{ uri }, LinkType::SendInput }, id);
return true;
}
else if (action == L"/a")
{
auto& textBuffer = _api.GetTextBuffer();
auto attr = textBuffer.GetCurrentAttributes();
attr.SetHyperlinkId(0);
textBuffer.SetCurrentAttributes(attr);
return true;
}
return false;
}
// Method Description:
// - DECDLD - Downloads one or more characters of a dynamically redefinable
// character set (DRCS) with a specified pixel pattern. The pixel array is

View File

@@ -133,6 +133,8 @@ namespace Microsoft::Console::VirtualTerminal
bool DoFinalTermAction(const std::wstring_view string) override;
bool DoWtAction(const std::wstring_view string) override;
StringHandler DownloadDRCS(const VTInt fontNumber,
const VTParameter startChar,
const DispatchTypes::DrcsEraseControl eraseControl,

View File

@@ -125,6 +125,8 @@ public:
bool DoFinalTermAction(const std::wstring_view /*string*/) override { return false; }
bool DoWtAction(const std::wstring_view /*string*/) override { return false; }
StringHandler DownloadDRCS(const VTInt /*fontNumber*/,
const VTParameter /*startChar*/,
const DispatchTypes::DrcsEraseControl /*eraseControl*/,

View File

@@ -943,6 +943,11 @@ bool OutputStateMachineEngine::ActionOscDispatch(const wchar_t /*wch*/,
success = _dispatch->DoITerm2Action(string);
break;
}
case OscActionCodes::WtAction:
{
success = _dispatch->DoWtAction(string);
break;
}
case OscActionCodes::FinalTermAction:
{
success = _dispatch->DoFinalTermAction(string);

View File

@@ -212,6 +212,7 @@ namespace Microsoft::Console::VirtualTerminal
ResetCursorColor = 112,
FinalTermAction = 133,
ITerm2Action = 1337,
WtAction = 9001,
};
bool _GetOscTitle(const std::wstring_view string,

View File

@@ -0,0 +1,5 @@
write-host "`e[1;31mfatal`e[m: The current branch dev/migrie/fhl-clickable-send-input has no upstream branch."
write-host "To push the current branch and set the remote as upstream, use"
write-host ""
write-host " `e]9001;a;git push --set-upstream origin dev/migrie/fhl-clickable-send-input`e\git push --set-upstream origin dev/migrie/fhl-clickable-send-input`e]9001;/a;`e\"
write-host ""