mirror of
https://github.com/microsoft/terminal.git
synced 2026-05-17 15:36:35 +00:00
Compare commits
7 Commits
dev/cazamo
...
dev/duhowe
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8a5d2ae730 | ||
|
|
904eb9ec07 | ||
|
|
236038a110 | ||
|
|
6525ceeb8f | ||
|
|
b8629c366b | ||
|
|
ba2b0af843 | ||
|
|
d1da3c06c6 |
@@ -26,7 +26,7 @@
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="!Exists('CascadiaPackage_TemporaryKey.pfx')">
|
||||
<AppxPackageSigningEnabled>false</AppxPackageSigningEnabled>
|
||||
<AppxBundle>Never</AppxBundle>
|
||||
<!--<AppxBundle>Never</AppxBundle>-->
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="Exists('CascadiaPackage_TemporaryKey.pfx')">
|
||||
<AppxPackageSigningEnabled>true</AppxPackageSigningEnabled>
|
||||
|
||||
@@ -78,6 +78,7 @@
|
||||
<Project>{18D09A24-8240-42D6-8CB6-236EEE820263}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="$(OpenConsoleDir)src\cascadia\WinRTUtils\WinRTUtils.vcxproj">
|
||||
<Private>true</Private>
|
||||
<Project>{CA5CAD1A-039A-4929-BA2A-8BEB2E4106FE}</Project>
|
||||
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
|
||||
</ProjectReference>
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include "winrt/Windows.Data.Json.h"
|
||||
#include <Windows.h>
|
||||
|
||||
#include <wrl.h>
|
||||
#include <winhttp.h>
|
||||
#include <wil/resource.h>
|
||||
|
||||
|
||||
@@ -179,6 +179,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
|
||||
void ControlCore::_setupDispatcherAndCallbacks()
|
||||
{
|
||||
///* TODO(DH) */ return;
|
||||
// Get our dispatcher. If we're hosted in-proc with XAML, this will get
|
||||
// us the same dispatcher as TermControl::Dispatcher(). If we're out of
|
||||
// proc, this'll return null. We'll need to instead make a new
|
||||
@@ -433,12 +434,15 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
_terminal->Create(viewportSize, Utils::ClampToShortMax(_settings.HistorySize(), 0), *_renderer);
|
||||
_terminal->UpdateSettings(_settings);
|
||||
|
||||
// Tell the render engine to notify us when the swap chain changes.
|
||||
// We do this after we initially set the swapchain so as to avoid
|
||||
// unnecessary callbacks (and locking problems)
|
||||
_renderEngine->SetCallback([this](HANDLE handle) {
|
||||
_renderEngineSwapChainChanged(handle);
|
||||
});
|
||||
if (_hookup == HookupMode::ForComposition)
|
||||
{
|
||||
// Tell the render engine to notify us when the swap chain changes.
|
||||
// We do this after we initially set the swapchain so as to avoid
|
||||
// unnecessary callbacks (and locking problems)
|
||||
_renderEngine->SetCallback([this](HANDLE handle) {
|
||||
_renderEngineSwapChainChanged(handle);
|
||||
});
|
||||
}
|
||||
|
||||
_renderEngine->SetRetroTerminalEffect(_settings.RetroTerminalEffect());
|
||||
_renderEngine->SetPixelShaderPath(_settings.PixelShaderPath());
|
||||
@@ -459,6 +463,23 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ControlCore::InitializeWithHwnd(const float actualWidth,
|
||||
const float actualHeight,
|
||||
const float compositionScale,
|
||||
const uint64_t hwnd)
|
||||
{
|
||||
_owningHwnd = hwnd;
|
||||
_hookup = HookupMode::ForHwnd;
|
||||
|
||||
auto i = Initialize(actualWidth, actualHeight, compositionScale);
|
||||
if (i)
|
||||
{
|
||||
auto lock = _terminal->LockForWriting();
|
||||
(void)_renderEngine->SetHwnd(reinterpret_cast<HWND>(hwnd));
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Tell the renderer to start painting.
|
||||
// - !! IMPORTANT !! Make sure that we've attached our swap chain to an
|
||||
@@ -1959,7 +1980,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
RendererWarning.raise(*this, winrt::make<RendererWarningArgs>(hr, winrt::hstring{ parameter }));
|
||||
}
|
||||
|
||||
safe_void_coroutine ControlCore::_renderEngineSwapChainChanged(const HANDLE sourceHandle)
|
||||
/* TODO(DH) */ void ControlCore::_renderEngineSwapChainChanged(const HANDLE sourceHandle)
|
||||
{
|
||||
// `sourceHandle` is a weak ref to a HANDLE that's ultimately owned by the
|
||||
// render engine's own unique_handle. We'll add another ref to it here.
|
||||
@@ -1977,7 +1998,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
|
||||
// Concurrent read of _dispatcher is safe, because Detach() calls TriggerTeardown()
|
||||
// which blocks until this call returns. _dispatcher will only be changed afterwards.
|
||||
co_await wil::resume_foreground(_dispatcher);
|
||||
// TODO(DH) co_await wil::resume_foreground(_dispatcher);
|
||||
|
||||
if (auto core{ weakThis.get() })
|
||||
{
|
||||
@@ -2941,4 +2962,39 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
{
|
||||
_terminal->PreviewText(input);
|
||||
}
|
||||
|
||||
ControlCore::TimerHandle ControlCore::RegisterTimer(const char* name, std::function<void()> callback)
|
||||
{
|
||||
return _renderer->RegisterTimer(name, [cb = std::move(callback)](auto&&, auto&&) {
|
||||
cb();
|
||||
});
|
||||
}
|
||||
bool ControlCore::IsTimerRunning(TimerHandle h)
|
||||
{
|
||||
return _renderer->IsTimerRunning(h);
|
||||
}
|
||||
void ControlCore::StartRepeatingTimer(TimerHandle h, uint64_t micros)
|
||||
{
|
||||
_renderer->StartRepeatingTimer(h, std::chrono::microseconds(micros));
|
||||
}
|
||||
void ControlCore::StopTimer(TimerHandle h)
|
||||
{
|
||||
_renderer->StopTimer(h);
|
||||
}
|
||||
|
||||
winrt::Windows::Foundation::Size ControlCore::RenderedSize()
|
||||
{
|
||||
return { _panelWidth, _panelHeight };
|
||||
}
|
||||
|
||||
void ControlCore::ResizeToDimensions(uint32_t width, uint32_t height, winrt::Windows::Foundation::Size& newSizeInPixels)
|
||||
{
|
||||
if (!_renderEngine)
|
||||
{
|
||||
throw winrt::hresult_error(E_INVALIDARG);
|
||||
}
|
||||
auto pixelSize = _renderEngine->GetViewportInPixels(Viewport::FromDimensions({ 0, 0 }, til::size{ static_cast<til::CoordType>(width), static_cast<til::CoordType>(height) }));
|
||||
SizeOrScaleChanged(static_cast<float>(pixelSize.Width()), static_cast<float>(pixelSize.Height()), _compositionScale);
|
||||
newSizeInPixels = RenderedSize();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,6 +24,8 @@
|
||||
#include "../../cascadia/TerminalCore/Terminal.hpp"
|
||||
#include "../../renderer/inc/FontInfoDesired.hpp"
|
||||
|
||||
#include <functional>
|
||||
|
||||
namespace Microsoft::Console::Render::Atlas
|
||||
{
|
||||
class AtlasEngine;
|
||||
@@ -78,6 +80,12 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
|
||||
struct ControlCore : ControlCoreT<ControlCore>
|
||||
{
|
||||
private:
|
||||
enum class HookupMode
|
||||
{
|
||||
ForHwnd = 0x0,
|
||||
ForComposition = 0x1,
|
||||
};
|
||||
public:
|
||||
ControlCore(Control::IControlSettings settings,
|
||||
Control::IControlAppearance unfocusedAppearance,
|
||||
@@ -87,6 +95,10 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
bool Initialize(const float actualWidth,
|
||||
const float actualHeight,
|
||||
const float compositionScale);
|
||||
bool InitializeWithHwnd(const float actualWidth,
|
||||
const float actualHeight,
|
||||
const float compositionScale,
|
||||
const uint64_t hwnd);
|
||||
void EnablePainting();
|
||||
|
||||
void Detach();
|
||||
@@ -262,8 +274,17 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
bool ShouldShowSelectCommand();
|
||||
bool ShouldShowSelectOutput();
|
||||
|
||||
winrt::Windows::Foundation::Size RenderedSize();
|
||||
void ResizeToDimensions(uint32_t width, uint32_t height, winrt::Windows::Foundation::Size& newSizeInPixels);
|
||||
|
||||
void PreviewInput(std::wstring_view input);
|
||||
|
||||
using TimerHandle = ::Microsoft::Console::Render::TimerHandle;
|
||||
TimerHandle RegisterTimer(const char* name, std::function<void()> callback);
|
||||
bool IsTimerRunning(TimerHandle h);
|
||||
void StartRepeatingTimer(TimerHandle h, uint64_t micros);
|
||||
void StopTimer(TimerHandle h);
|
||||
|
||||
RUNTIME_SETTING(float, Opacity, _settings.Opacity());
|
||||
RUNTIME_SETTING(float, FocusedOpacity, FocusedAppearance().Opacity());
|
||||
RUNTIME_SETTING(bool, UseAcrylic, _settings.UseAcrylic());
|
||||
@@ -340,7 +361,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
|
||||
#pragma region RendererCallbacks
|
||||
void _rendererWarning(const HRESULT hr, wil::zwstring_view parameter);
|
||||
safe_void_coroutine _renderEngineSwapChainChanged(const HANDLE handle);
|
||||
/* TODO(DH) */ void _renderEngineSwapChainChanged(const HANDLE handle);
|
||||
void _rendererBackgroundColorChanged();
|
||||
void _rendererTabColorChanged();
|
||||
void _rendererEnteredErrorState();
|
||||
@@ -375,7 +396,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
//
|
||||
// Though, the unit tests don't actually run in TAEF's main
|
||||
// thread, so we don't care when we're running in tests.
|
||||
assert(_inUnitTests || _dispatcher.HasThreadAccess());
|
||||
assert(_hookup == HookupMode::ForHwnd || _inUnitTests || _dispatcher.HasThreadAccess());
|
||||
}
|
||||
#endif
|
||||
return _closing;
|
||||
@@ -421,6 +442,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
std::atomic<bool> _initializedTerminal{ false };
|
||||
bool _isReadOnly{ false };
|
||||
bool _closing{ false };
|
||||
HookupMode _hookup{ HookupMode::ForComposition };
|
||||
|
||||
struct StashedColorScheme
|
||||
{
|
||||
|
||||
@@ -93,6 +93,9 @@ namespace Microsoft.Terminal.Control
|
||||
Boolean Initialize(Single actualWidth,
|
||||
Single actualHeight,
|
||||
Single compositionScale);
|
||||
Boolean InitializeWithHwnd(Single actualWidth,
|
||||
Single actualHeight,
|
||||
Single compositionScale, UInt64 hwnd);
|
||||
|
||||
void UpdateSettings(IControlSettings settings, IControlAppearance appearance);
|
||||
void ApplyAppearance(Boolean focused);
|
||||
@@ -184,6 +187,9 @@ namespace Microsoft.Terminal.Control
|
||||
Boolean ShouldShowSelectCommand();
|
||||
Boolean ShouldShowSelectOutput();
|
||||
|
||||
Windows.Foundation.Size RenderedSize { get; };
|
||||
void ResizeToDimensions(UInt32 width, UInt32 height, out Windows.Foundation.Size newSizeInPixels);
|
||||
|
||||
void OpenCWD();
|
||||
|
||||
void ClearQuickFix();
|
||||
|
||||
@@ -68,6 +68,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
_createInteractivityTimers();
|
||||
}
|
||||
|
||||
uint64_t ControlInteractivity::Id()
|
||||
@@ -94,12 +96,14 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
LOG_IF_FAILED(_uiaEngine->Disable());
|
||||
_core->DetachUiaEngine(_uiaEngine.get());
|
||||
}
|
||||
_destroyInteractivityTimers();
|
||||
_core->Detach();
|
||||
}
|
||||
|
||||
void ControlInteractivity::AttachToNewControl()
|
||||
{
|
||||
_core->AttachToNewControl();
|
||||
//_createInteractivityTimers();
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
@@ -131,12 +135,31 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
void ControlInteractivity::Close()
|
||||
{
|
||||
Closed.raise(*this, nullptr);
|
||||
_destroyInteractivityTimers();
|
||||
if (_core)
|
||||
{
|
||||
_core->Close();
|
||||
}
|
||||
}
|
||||
|
||||
void ControlInteractivity::_createInteractivityTimers()
|
||||
{
|
||||
_autoScrollTimer = _core->RegisterTimer("autoscroll", [weak = get_weak()]() {
|
||||
if (auto strong = weak.get())
|
||||
{
|
||||
strong->_updateAutoScroll();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void ControlInteractivity::_destroyInteractivityTimers()
|
||||
{
|
||||
if (_autoScrollTimer)
|
||||
{
|
||||
_core->StopTimer(_autoScrollTimer);
|
||||
}
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Returns the number of clicks that occurred (double and triple click support).
|
||||
// Every call to this function registers a click.
|
||||
@@ -369,7 +392,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
_touchAnchor = contactPoint;
|
||||
}
|
||||
|
||||
bool ControlInteractivity::PointerMoved(const uint32_t /*pointerId*/,
|
||||
bool ControlInteractivity::PointerMoved(const uint32_t pointerId,
|
||||
Control::MouseButtonState buttonState,
|
||||
const unsigned int pointerUpdateKind,
|
||||
const ::Microsoft::Terminal::Core::ControlKeyStates modifiers,
|
||||
@@ -429,6 +452,40 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
}
|
||||
|
||||
SetEndSelectionPoint(pixelPosition);
|
||||
|
||||
// GH#9109 - Only start an auto-scroll when the drag actually
|
||||
// started within our bounds. Otherwise, someone could start a drag
|
||||
// outside the terminal control, drag into the padding, and trick us
|
||||
// into starting to scroll.
|
||||
{
|
||||
// We want to find the distance relative to the bounds of the
|
||||
// SwapChainPanel, not the entire control. If they drag out of
|
||||
// the bounds of the text, into the padding, we still what that
|
||||
// to auto-scroll
|
||||
const auto height = _core->ViewHeight() * _core->FontSize().Height;
|
||||
const auto cursorBelowBottomDist = pixelPosition.Y - height;
|
||||
const auto cursorAboveTopDist = -1 * pixelPosition.Y;
|
||||
|
||||
constexpr auto MinAutoScrollDist = 2.0; // Arbitrary value
|
||||
auto newAutoScrollVelocity = 0.0;
|
||||
if (cursorBelowBottomDist > MinAutoScrollDist)
|
||||
{
|
||||
newAutoScrollVelocity = _getAutoScrollSpeed(cursorBelowBottomDist);
|
||||
}
|
||||
else if (cursorAboveTopDist > MinAutoScrollDist)
|
||||
{
|
||||
newAutoScrollVelocity = -1.0 * _getAutoScrollSpeed(cursorAboveTopDist);
|
||||
}
|
||||
|
||||
if (newAutoScrollVelocity != 0)
|
||||
{
|
||||
_tryStartAutoScroll(pointerId, pixelPosition, newAutoScrollVelocity);
|
||||
}
|
||||
else
|
||||
{
|
||||
_tryStopAutoScroll(pointerId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_core->SetHoveredCell(terminalPosition.to_core_point());
|
||||
@@ -471,7 +528,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
}
|
||||
}
|
||||
|
||||
void ControlInteractivity::PointerReleased(const uint32_t /*pointerId*/,
|
||||
void ControlInteractivity::PointerReleased(const uint32_t pointerId,
|
||||
Control::MouseButtonState buttonState,
|
||||
const unsigned int pointerUpdateKind,
|
||||
const ::Microsoft::Terminal::Core::ControlKeyStates modifiers,
|
||||
@@ -502,6 +559,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
}
|
||||
|
||||
_singleClickTouchdownPos = std::nullopt;
|
||||
_tryStopAutoScroll(pointerId);
|
||||
}
|
||||
|
||||
void ControlInteractivity::TouchReleased()
|
||||
@@ -797,4 +855,97 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
{
|
||||
return _core->GetRenderData();
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Calculates speed of single axis of auto scrolling. It has to allow for both
|
||||
// fast and precise selection.
|
||||
// Arguments:
|
||||
// - cursorDistanceFromBorder: distance from viewport border to cursor, in pixels. Must be non-negative.
|
||||
// Return Value:
|
||||
// - positive speed in characters / sec
|
||||
double ControlInteractivity::_getAutoScrollSpeed(double cursorDistanceFromBorder) const
|
||||
{
|
||||
// The numbers below just feel well, feel free to change.
|
||||
// TODO: Maybe account for space beyond border that user has available
|
||||
return std::pow(cursorDistanceFromBorder, 2.0) / 25.0 + 2.0;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Starts new pointer related auto scroll behavior, or continues existing one.
|
||||
// Does nothing when there is already auto scroll associated with another pointer.
|
||||
// Arguments:
|
||||
// - pointerId, point: info about pointer that causes auto scroll. Pointer's position
|
||||
// is later used to update selection.
|
||||
// - scrollVelocity: target velocity of scrolling in characters / sec
|
||||
void ControlInteractivity::_tryStartAutoScroll(const uint32_t pointerId, const Core::Point& point, const double scrollVelocity)
|
||||
{
|
||||
// Allow only one pointer at the time
|
||||
if (!_autoScrollingPointerId ||
|
||||
_autoScrollingPointerId == pointerId)
|
||||
{
|
||||
_autoScrollingPointerId = pointerId;
|
||||
_autoScrollingPointerPoint = point;
|
||||
_autoScrollVelocity = scrollVelocity;
|
||||
|
||||
// If this is first time the auto scroll update is about to be called,
|
||||
// kick-start it by initializing its time delta as if it started now
|
||||
if (!_lastAutoScrollUpdateTime)
|
||||
{
|
||||
_lastAutoScrollUpdateTime = std::chrono::high_resolution_clock::now();
|
||||
}
|
||||
|
||||
// Apparently this check is not necessary but greatly improves performance
|
||||
if (!_core->IsTimerRunning(_autoScrollTimer))
|
||||
{
|
||||
static constexpr auto AutoScrollUpdateInterval = std::chrono::microseconds(static_cast<int>(1.0 / 30.0 * 1000000));
|
||||
_core->StartRepeatingTimer(_autoScrollTimer, AutoScrollUpdateInterval.count());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Stops auto scroll if it's active and is associated with supplied pointer id.
|
||||
// Arguments:
|
||||
// - pointerId: id of pointer for which to stop auto scroll
|
||||
void ControlInteractivity::_tryStopAutoScroll(const uint32_t pointerId)
|
||||
{
|
||||
if (_autoScrollingPointerId &&
|
||||
pointerId == _autoScrollingPointerId)
|
||||
{
|
||||
_autoScrollingPointerId = std::nullopt;
|
||||
_autoScrollingPointerPoint = std::nullopt;
|
||||
_autoScrollVelocity = 0;
|
||||
_lastAutoScrollUpdateTime = std::nullopt;
|
||||
|
||||
// Apparently this check is not necessary but greatly improves performance
|
||||
_core->StopTimer(_autoScrollTimer);
|
||||
}
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Called continuously to gradually scroll viewport when user is mouse
|
||||
// selecting outside it (to 'follow' the cursor).
|
||||
// Arguments:
|
||||
// - none
|
||||
void ControlInteractivity::_updateAutoScroll()
|
||||
{
|
||||
if (_autoScrollVelocity != 0)
|
||||
{
|
||||
const auto timeNow = std::chrono::high_resolution_clock::now();
|
||||
|
||||
if (_lastAutoScrollUpdateTime)
|
||||
{
|
||||
static constexpr auto microSecPerSec = 1000000.0;
|
||||
const auto deltaTime = std::chrono::duration_cast<std::chrono::microseconds>(timeNow - *_lastAutoScrollUpdateTime).count() / microSecPerSec;
|
||||
UpdateScrollbar(static_cast<float>(_core->ScrollOffset()) + static_cast<float>(_autoScrollVelocity * deltaTime) /* TODO(DH) */);
|
||||
|
||||
if (_autoScrollingPointerPoint)
|
||||
{
|
||||
SetEndSelectionPoint(*_autoScrollingPointerPoint);
|
||||
}
|
||||
}
|
||||
|
||||
_lastAutoScrollUpdateTime = timeNow;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -143,8 +143,24 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
static std::atomic<uint64_t> _nextId;
|
||||
|
||||
bool _focused{ false };
|
||||
|
||||
// Auto scroll occurs when user, while selecting, drags cursor outside
|
||||
// viewport. View is then scrolled to 'follow' the cursor.
|
||||
double _autoScrollVelocity;
|
||||
std::optional<uint32_t> _autoScrollingPointerId;
|
||||
std::optional<Core::Point> _autoScrollingPointerPoint;
|
||||
ControlCore::TimerHandle _autoScrollTimer;
|
||||
std::optional<std::chrono::high_resolution_clock::time_point> _lastAutoScrollUpdateTime;
|
||||
bool _pointerPressedInBounds{ false };
|
||||
|
||||
void _tryStartAutoScroll(const uint32_t id, const Core::Point& point, const double scrollVelocity);
|
||||
void _tryStopAutoScroll(const uint32_t pointerId);
|
||||
void _updateAutoScroll();
|
||||
double _getAutoScrollSpeed(double cursorDistanceFromBorder) const;
|
||||
|
||||
void _createInteractivityTimers();
|
||||
void _destroyInteractivityTimers();
|
||||
|
||||
unsigned int _numberOfClicks(Core::Point clickPos, Timestamp clickTime);
|
||||
void _updateSystemParameterSettings() noexcept;
|
||||
|
||||
|
||||
641
src/cascadia/TerminalControl/FlatC.cpp
Normal file
641
src/cascadia/TerminalControl/FlatC.cpp
Normal file
@@ -0,0 +1,641 @@
|
||||
#include "pch.h"
|
||||
#include "FlatC.h"
|
||||
#include "winrt/Microsoft.Terminal.Control.h"
|
||||
#include "winrt/Microsoft.Terminal.Core.h"
|
||||
#include "../TerminalCore/ControlKeyStates.hpp"
|
||||
#include "../types/inc/colorTable.hpp"
|
||||
#include "../inc/DefaultSettings.h"
|
||||
#include "../inc/cppwinrt_utils.h"
|
||||
#include "../../tsf/Handle.h"
|
||||
|
||||
#include "ControlCore.h"
|
||||
#include "ControlInteractivity.h"
|
||||
|
||||
#include <windowsx.h>
|
||||
|
||||
#pragma warning(disable : 4100)
|
||||
|
||||
#define HARDCODED_PROPERTY(type, name, ...) \
|
||||
type name() const \
|
||||
{ \
|
||||
return type{ __VA_ARGS__ }; \
|
||||
} \
|
||||
void name(const type&) \
|
||||
{ \
|
||||
}
|
||||
|
||||
using namespace winrt::Microsoft::Terminal::Control;
|
||||
using namespace winrt::Microsoft::Terminal::Core;
|
||||
using CKS = ::Microsoft::Terminal::Core::ControlKeyStates;
|
||||
|
||||
static CKS getControlKeyState() noexcept
|
||||
{
|
||||
struct KeyModifier
|
||||
{
|
||||
int vkey;
|
||||
CKS flags;
|
||||
};
|
||||
|
||||
constexpr std::array<KeyModifier, 5> modifiers{ {
|
||||
{ VK_RMENU, CKS::RightAltPressed },
|
||||
{ VK_LMENU, CKS::LeftAltPressed },
|
||||
{ VK_RCONTROL, CKS::RightCtrlPressed },
|
||||
{ VK_LCONTROL, CKS::LeftCtrlPressed },
|
||||
{ VK_SHIFT, CKS::ShiftPressed },
|
||||
} };
|
||||
|
||||
CKS flags;
|
||||
|
||||
for (const auto& mod : modifiers)
|
||||
{
|
||||
const auto state = GetKeyState(mod.vkey);
|
||||
const auto isDown = state < 0;
|
||||
|
||||
if (isDown)
|
||||
{
|
||||
flags |= mod.flags;
|
||||
}
|
||||
}
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
static MouseButtonState MouseButtonStateFromWParam(WPARAM wParam)
|
||||
{
|
||||
MouseButtonState state{};
|
||||
WI_UpdateFlag(state, MouseButtonState::IsLeftButtonDown, WI_IsFlagSet(wParam, MK_LBUTTON));
|
||||
WI_UpdateFlag(state, MouseButtonState::IsMiddleButtonDown, WI_IsFlagSet(wParam, MK_MBUTTON));
|
||||
WI_UpdateFlag(state, MouseButtonState::IsRightButtonDown, WI_IsFlagSet(wParam, MK_RBUTTON));
|
||||
return state;
|
||||
}
|
||||
|
||||
static Point PointFromLParam(LPARAM lParam)
|
||||
{
|
||||
return { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
|
||||
}
|
||||
|
||||
struct CsBridgeConnection : public winrt::implements<CsBridgeConnection, winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection>
|
||||
{
|
||||
void Initialize(IInspectable x) {}
|
||||
void Start() {}
|
||||
void WriteInput(winrt::array_view<const char16_t> d)
|
||||
{
|
||||
if (_pfnWriteCallback)
|
||||
{
|
||||
_pfnWriteCallback(reinterpret_cast<const wchar_t*>(d.data()));
|
||||
}
|
||||
}
|
||||
void Resize(uint32_t r, uint32_t c) {}
|
||||
void Close() {}
|
||||
winrt::Microsoft::Terminal::TerminalConnection::ConnectionState State() const noexcept { return winrt::Microsoft::Terminal::TerminalConnection::ConnectionState::Connected; }
|
||||
WINRT_CALLBACK(TerminalOutput, winrt::Microsoft::Terminal::TerminalConnection::TerminalOutputHandler);
|
||||
|
||||
TYPED_EVENT(StateChanged, winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection, winrt::Windows::Foundation::IInspectable);
|
||||
|
||||
public:
|
||||
HARDCODED_PROPERTY(winrt::guid, SessionId, winrt::guid{});
|
||||
|
||||
public:
|
||||
PWRITECB _pfnWriteCallback{ nullptr };
|
||||
void OriginateOutputFromConnection(const wchar_t* data)
|
||||
{
|
||||
std::wstring_view wsv{ data };
|
||||
_TerminalOutputHandlers(winrt::array_view<const char16_t>(reinterpret_cast<const char16_t*>(wsv.data()), static_cast<uint32_t>(wsv.size())));
|
||||
}
|
||||
};
|
||||
|
||||
struct CsBridgeTerminalSettings : winrt::implements<CsBridgeTerminalSettings, IControlSettings, ICoreSettings, IControlAppearance, ICoreAppearance, ICoreScheme>
|
||||
{
|
||||
using IFontAxesMap = winrt::Windows::Foundation::Collections::IMap<winrt::hstring, float>;
|
||||
using IFontFeatureMap = winrt::Windows::Foundation::Collections::IMap<winrt::hstring, float>;
|
||||
CsBridgeTerminalSettings()
|
||||
{
|
||||
const auto campbellSpan = Microsoft::Console::Utils::CampbellColorTable();
|
||||
std::transform(campbellSpan.begin(), campbellSpan.end(), std::begin(_theme.ColorTable), [](auto&& color) {
|
||||
return color;
|
||||
});
|
||||
}
|
||||
~CsBridgeTerminalSettings() = default;
|
||||
|
||||
void GetColorTable(winrt::com_array<::winrt::Microsoft::Terminal::Core::Color>& table) noexcept
|
||||
{
|
||||
std::array<winrt::Microsoft::Terminal::Core::Color, COLOR_TABLE_SIZE> colorTable{};
|
||||
std::transform(&_theme.ColorTable[0], &_theme.ColorTable[16], colorTable.begin(), [](auto&& color) {
|
||||
return static_cast<winrt::Microsoft::Terminal::Core::Color>(til::color{ color });
|
||||
});
|
||||
|
||||
table = winrt::com_array(colorTable.begin(), colorTable.end());
|
||||
}
|
||||
|
||||
til::color DefaultForeground() const
|
||||
{
|
||||
return _theme.DefaultForeground;
|
||||
}
|
||||
til::color DefaultBackground() const
|
||||
{
|
||||
return _theme.DefaultBackground;
|
||||
}
|
||||
til::color SelectionBackground() const
|
||||
{
|
||||
return til::color{ _theme.DefaultSelectionBackground };
|
||||
}
|
||||
winrt::hstring FontFace() const
|
||||
{
|
||||
return _fontFace;
|
||||
}
|
||||
float FontSize() const
|
||||
{
|
||||
return _fontSize;
|
||||
}
|
||||
winrt::Microsoft::Terminal::Core::CursorStyle CursorShape() const
|
||||
{
|
||||
return static_cast<winrt::Microsoft::Terminal::Core::CursorStyle>(_theme.CursorStyle);
|
||||
}
|
||||
|
||||
void DefaultForeground(const til::color&) {}
|
||||
void DefaultBackground(const til::color&) {}
|
||||
void SelectionBackground(const til::color&) {}
|
||||
void FontFace(const winrt::hstring&) {}
|
||||
void FontSize(const float&) {}
|
||||
void CursorShape(const winrt::Microsoft::Terminal::Core::CursorStyle&) {}
|
||||
|
||||
HARDCODED_PROPERTY(int32_t, HistorySize, DEFAULT_HISTORY_SIZE);
|
||||
HARDCODED_PROPERTY(int32_t, InitialRows, 30);
|
||||
HARDCODED_PROPERTY(int32_t, InitialCols, 80);
|
||||
HARDCODED_PROPERTY(bool, SnapOnInput, true);
|
||||
HARDCODED_PROPERTY(bool, AltGrAliasing, true);
|
||||
HARDCODED_PROPERTY(til::color, CursorColor, DEFAULT_CURSOR_COLOR);
|
||||
HARDCODED_PROPERTY(uint32_t, CursorHeight, DEFAULT_CURSOR_HEIGHT);
|
||||
HARDCODED_PROPERTY(winrt::hstring, WordDelimiters, DEFAULT_WORD_DELIMITERS);
|
||||
HARDCODED_PROPERTY(bool, CopyOnSelect, false);
|
||||
HARDCODED_PROPERTY(bool, InputServiceWarning, true);
|
||||
HARDCODED_PROPERTY(bool, FocusFollowMouse, false);
|
||||
HARDCODED_PROPERTY(bool, TrimBlockSelection, false);
|
||||
HARDCODED_PROPERTY(bool, DetectURLs, true);
|
||||
HARDCODED_PROPERTY(winrt::Windows::Foundation::IReference<winrt::Microsoft::Terminal::Core::Color>, TabColor, nullptr);
|
||||
HARDCODED_PROPERTY(winrt::Windows::Foundation::IReference<winrt::Microsoft::Terminal::Core::Color>, StartingTabColor, nullptr);
|
||||
HARDCODED_PROPERTY(bool, UseAcrylic, false);
|
||||
HARDCODED_PROPERTY(float, Opacity, 1.0);
|
||||
HARDCODED_PROPERTY(winrt::hstring, Padding, DEFAULT_PADDING);
|
||||
HARDCODED_PROPERTY(winrt::Windows::UI::Text::FontWeight, FontWeight, winrt::Windows::UI::Text::FontWeight{ 400 });
|
||||
HARDCODED_PROPERTY(IFontAxesMap, FontAxes);
|
||||
HARDCODED_PROPERTY(IFontFeatureMap, FontFeatures);
|
||||
HARDCODED_PROPERTY(winrt::hstring, BackgroundImage);
|
||||
HARDCODED_PROPERTY(float, BackgroundImageOpacity, 1.0);
|
||||
HARDCODED_PROPERTY(winrt::Windows::UI::Xaml::Media::Stretch, BackgroundImageStretchMode, winrt::Windows::UI::Xaml::Media::Stretch::UniformToFill);
|
||||
HARDCODED_PROPERTY(winrt::Windows::UI::Xaml::HorizontalAlignment, BackgroundImageHorizontalAlignment, winrt::Windows::UI::Xaml::HorizontalAlignment::Center);
|
||||
HARDCODED_PROPERTY(winrt::Windows::UI::Xaml::VerticalAlignment, BackgroundImageVerticalAlignment, winrt::Windows::UI::Xaml::VerticalAlignment::Center);
|
||||
HARDCODED_PROPERTY(winrt::hstring, Commandline);
|
||||
HARDCODED_PROPERTY(winrt::hstring, StartingDirectory);
|
||||
HARDCODED_PROPERTY(winrt::hstring, StartingTitle);
|
||||
HARDCODED_PROPERTY(bool, SuppressApplicationTitle);
|
||||
HARDCODED_PROPERTY(winrt::hstring, EnvironmentVariables);
|
||||
HARDCODED_PROPERTY(winrt::Microsoft::Terminal::Control::ScrollbarState, ScrollState, winrt::Microsoft::Terminal::Control::ScrollbarState::Visible);
|
||||
HARDCODED_PROPERTY(winrt::Microsoft::Terminal::Control::TextAntialiasingMode, AntialiasingMode, winrt::Microsoft::Terminal::Control::TextAntialiasingMode::Grayscale);
|
||||
HARDCODED_PROPERTY(bool, RetroTerminalEffect, false);
|
||||
HARDCODED_PROPERTY(bool, ForceFullRepaintRendering, false);
|
||||
HARDCODED_PROPERTY(bool, SoftwareRendering, false);
|
||||
HARDCODED_PROPERTY(bool, ForceVTInput, false);
|
||||
HARDCODED_PROPERTY(winrt::hstring, PixelShaderPath);
|
||||
HARDCODED_PROPERTY(winrt::hstring, PixelShaderImagePath);
|
||||
HARDCODED_PROPERTY(bool, IntenseIsBright);
|
||||
HARDCODED_PROPERTY(bool, IntenseIsBold);
|
||||
HARDCODED_PROPERTY(bool, ShowMarks);
|
||||
HARDCODED_PROPERTY(bool, UseBackgroundImageForWindow);
|
||||
HARDCODED_PROPERTY(bool, AutoMarkPrompts);
|
||||
HARDCODED_PROPERTY(bool, VtPassthrough);
|
||||
HARDCODED_PROPERTY(bool, UseAtlasEngine, false);
|
||||
HARDCODED_PROPERTY(AdjustTextMode, AdjustIndistinguishableColors, AdjustTextMode::Never);
|
||||
HARDCODED_PROPERTY(bool, RightClickContextMenu, false);
|
||||
HARDCODED_PROPERTY(winrt::hstring, CellWidth, L"");
|
||||
HARDCODED_PROPERTY(winrt::hstring, CellHeight, L"");
|
||||
HARDCODED_PROPERTY(bool, RepositionCursorWithMouse, false);
|
||||
HARDCODED_PROPERTY(bool, EnableUnfocusedAcrylic, false);
|
||||
HARDCODED_PROPERTY(bool, RainbowSuggestions, false);
|
||||
HARDCODED_PROPERTY(bool, AllowVtClipboardWrite, true);
|
||||
HARDCODED_PROPERTY(bool, AllowVtChecksumReport, false);
|
||||
HARDCODED_PROPERTY(winrt::hstring, AnswerbackMessage, L"");
|
||||
HARDCODED_PROPERTY(winrt::Microsoft::Terminal::Control::PathTranslationStyle, PathTranslationStyle, winrt::Microsoft::Terminal::Control::PathTranslationStyle::None);
|
||||
HARDCODED_PROPERTY(winrt::Microsoft::Terminal::Control::DefaultInputScope, DefaultInputScope, winrt::Microsoft::Terminal::Control::DefaultInputScope::Default);
|
||||
HARDCODED_PROPERTY(winrt::Microsoft::Terminal::Control::TextMeasurement, TextMeasurement, winrt::Microsoft::Terminal::Control::TextMeasurement::Graphemes);
|
||||
HARDCODED_PROPERTY(bool, DisablePartialInvalidation, false);
|
||||
HARDCODED_PROPERTY(winrt::Microsoft::Terminal::Control::GraphicsAPI, GraphicsAPI, winrt::Microsoft::Terminal::Control::GraphicsAPI::Automatic);
|
||||
HARDCODED_PROPERTY(winrt::Microsoft::Terminal::Control::CopyFormat, CopyFormatting, winrt::Microsoft::Terminal::Control::CopyFormat::All);
|
||||
HARDCODED_PROPERTY(bool, EnableColorGlyphs, true);
|
||||
HARDCODED_PROPERTY(bool, EnableBuiltinGlyphs, true);
|
||||
HARDCODED_PROPERTY(bool, AllowKittyKeyboardMode, true);
|
||||
HARDCODED_PROPERTY(winrt::hstring, DragDropDelimiter, L" ");
|
||||
HARDCODED_PROPERTY(winrt::Microsoft::Terminal::Control::AmbiguousWidth, AmbiguousWidth, winrt::Microsoft::Terminal::Control::AmbiguousWidth::Narrow);
|
||||
HARDCODED_PROPERTY(bool, ScrollToChangeOpacity, false);
|
||||
HARDCODED_PROPERTY(bool, ScrollToZoom, false);
|
||||
HARDCODED_PROPERTY(winrt::guid, SessionId, winrt::guid{});
|
||||
|
||||
public:
|
||||
void SetTheme(TerminalTheme theme, LPCWSTR fontFamily, til::CoordType fontSize, int newDpi)
|
||||
{
|
||||
_theme = std::move(theme);
|
||||
_fontFace = fontFamily;
|
||||
_fontSize = static_cast<float>(fontSize);
|
||||
}
|
||||
|
||||
private:
|
||||
TerminalTheme _theme;
|
||||
winrt::hstring _fontFace{ L"Cascadia Mono" };
|
||||
float _fontSize = 12.0f;
|
||||
};
|
||||
|
||||
struct HwndTerminal
|
||||
{
|
||||
static constexpr LPCWSTR term_window_class = L"HwndTerminalClass";
|
||||
|
||||
static LRESULT CALLBACK HwndTerminalWndProc(
|
||||
HWND hwnd,
|
||||
UINT uMsg,
|
||||
WPARAM wParam,
|
||||
LPARAM lParam) noexcept
|
||||
try
|
||||
{
|
||||
#pragma warning(suppress : 26490) // Win32 APIs can only store void*, have to use reinterpret_cast
|
||||
HwndTerminal* terminal = reinterpret_cast<HwndTerminal*>(GetWindowLongPtr(hwnd, GWLP_USERDATA));
|
||||
if (terminal)
|
||||
{
|
||||
return terminal->WindowProc(hwnd, uMsg, wParam, lParam);
|
||||
}
|
||||
return DefWindowProcW(hwnd, uMsg, wParam, lParam);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
LOG_CAUGHT_EXCEPTION();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool RegisterTermClass(HINSTANCE hInstance) noexcept
|
||||
{
|
||||
WNDCLASSW wc;
|
||||
if (GetClassInfoW(hInstance, term_window_class, &wc))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
wc.style = 0;
|
||||
wc.lpfnWndProc = HwndTerminal::HwndTerminalWndProc;
|
||||
wc.cbClsExtra = 0;
|
||||
wc.cbWndExtra = 0;
|
||||
wc.hInstance = hInstance;
|
||||
wc.hIcon = nullptr;
|
||||
wc.hCursor = LoadCursor(nullptr, IDC_ARROW);
|
||||
wc.hbrBackground = nullptr;
|
||||
wc.lpszMenuName = nullptr;
|
||||
wc.lpszClassName = term_window_class;
|
||||
|
||||
return RegisterClassW(&wc) != 0;
|
||||
}
|
||||
|
||||
LRESULT WindowProc(
|
||||
HWND hwnd,
|
||||
UINT uMsg,
|
||||
WPARAM wParam,
|
||||
LPARAM lParam) noexcept
|
||||
{
|
||||
switch (uMsg)
|
||||
{
|
||||
case WM_LBUTTONDOWN:
|
||||
case WM_MBUTTONDOWN:
|
||||
case WM_RBUTTONDOWN:
|
||||
SetCapture(_hwnd.get());
|
||||
_interactivity->PointerPressed(
|
||||
0, // Mouse
|
||||
MouseButtonStateFromWParam(wParam),
|
||||
uMsg,
|
||||
std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::system_clock::now().time_since_epoch()).count(),
|
||||
getControlKeyState(),
|
||||
PointFromLParam(lParam));
|
||||
return 0;
|
||||
case WM_MOUSEMOVE:
|
||||
_interactivity->PointerMoved(
|
||||
0, // Mouse
|
||||
MouseButtonStateFromWParam(wParam),
|
||||
WM_MOUSEMOVE,
|
||||
getControlKeyState(),
|
||||
PointFromLParam(lParam));
|
||||
return 0;
|
||||
case WM_LBUTTONUP:
|
||||
case WM_MBUTTONUP:
|
||||
case WM_RBUTTONUP:
|
||||
_interactivity->PointerReleased(
|
||||
0, // Mouse
|
||||
MouseButtonStateFromWParam(wParam),
|
||||
uMsg,
|
||||
getControlKeyState(),
|
||||
PointFromLParam(lParam));
|
||||
ReleaseCapture();
|
||||
return 0;
|
||||
case WM_POINTERDOWN:
|
||||
if (!IS_POINTER_INCONTACT_WPARAM(wParam))
|
||||
{
|
||||
break;
|
||||
}
|
||||
SetCapture(_hwnd.get());
|
||||
_interactivity->TouchPressed(PointFromLParam(lParam));
|
||||
return 0;
|
||||
case WM_POINTERUPDATE:
|
||||
if (!IS_POINTER_INCONTACT_WPARAM(wParam))
|
||||
{
|
||||
break;
|
||||
}
|
||||
_interactivity->TouchMoved(PointFromLParam(lParam));
|
||||
return 0;
|
||||
case WM_POINTERUP:
|
||||
if (!IS_POINTER_INCONTACT_WPARAM(wParam))
|
||||
{
|
||||
break;
|
||||
}
|
||||
_interactivity->TouchReleased();
|
||||
ReleaseCapture();
|
||||
return 0;
|
||||
case WM_MOUSEWHEEL:
|
||||
case WM_MOUSEHWHEEL:
|
||||
{
|
||||
winrt::Microsoft::Terminal::Core::Point delta{ 0, GET_WHEEL_DELTA_WPARAM(wParam) };
|
||||
if (uMsg == WM_MOUSEHWHEEL)
|
||||
{
|
||||
std::swap(delta.X, delta.Y);
|
||||
}
|
||||
|
||||
if (_interactivity->MouseWheel(getControlKeyState(), delta, PointFromLParam(lParam), MouseButtonStateFromWParam(wParam)))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case WM_SETFOCUS:
|
||||
_interactivity->GotFocus();
|
||||
_focused = true;
|
||||
_core->ApplyAppearance(_focused);
|
||||
break;
|
||||
case WM_KILLFOCUS:
|
||||
_interactivity->LostFocus();
|
||||
_focused = true;
|
||||
_core->ApplyAppearance(_focused);
|
||||
break;
|
||||
}
|
||||
|
||||
return DefWindowProcW(hwnd, uMsg, wParam, lParam);
|
||||
}
|
||||
|
||||
wil::unique_hwnd _hwnd;
|
||||
|
||||
HwndTerminal(HWND parentHwnd)
|
||||
{
|
||||
HINSTANCE hInstance = wil::GetModuleInstanceHandle();
|
||||
|
||||
if (RegisterTermClass(hInstance))
|
||||
{
|
||||
_hwnd.reset(CreateWindowExW(
|
||||
0,
|
||||
term_window_class,
|
||||
nullptr,
|
||||
WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_VISIBLE,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
parentHwnd,
|
||||
nullptr,
|
||||
hInstance,
|
||||
nullptr));
|
||||
|
||||
#pragma warning(suppress : 26490) // Win32 APIs can only store void*, so we have to use reinterpret_cast
|
||||
SetWindowLongPtr(_hwnd.get(), GWLP_USERDATA, reinterpret_cast<LONG_PTR>(this));
|
||||
}
|
||||
|
||||
_settingsBridge = winrt::make_self<CsBridgeTerminalSettings>();
|
||||
_connection = winrt::make_self<CsBridgeConnection>();
|
||||
_interactivity = winrt::make_self<implementation::ControlInteractivity>(*_settingsBridge, nullptr, *_connection);
|
||||
_core.copy_from(winrt::get_self<implementation::ControlCore>(_interactivity->Core()));
|
||||
|
||||
_core->ScrollPositionChanged({ this, &HwndTerminal::_scrollPositionChanged });
|
||||
_interactivity->ScrollPositionChanged({ this, &HwndTerminal::_scrollPositionChanged });
|
||||
}
|
||||
|
||||
/*( PUBLIC API )*/
|
||||
HRESULT SendOutput(LPCWSTR data)
|
||||
{
|
||||
_connection->OriginateOutputFromConnection(data);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT RegisterScrollCallback(PSCROLLCB callback)
|
||||
{
|
||||
_scrollCallback = callback;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT TriggerResize(_In_ til::CoordType width, _In_ til::CoordType height, _Out_ til::size* dimensions)
|
||||
{
|
||||
if (!_initialized)
|
||||
return S_FALSE;
|
||||
|
||||
SetWindowPos(_hwnd.get(), nullptr, 0, 0, width, height, 0);
|
||||
|
||||
// **NOTE** The sizes we get here are unscaled ...
|
||||
auto dpi = GetDpiForWindow(_hwnd.get());
|
||||
float w = static_cast<float>(width * USER_DEFAULT_SCREEN_DPI) / dpi;
|
||||
float h = static_cast<float>(height * USER_DEFAULT_SCREEN_DPI) / dpi;
|
||||
// ... but ControlCore expects scaled sizes.
|
||||
_core->SizeChanged(w, h);
|
||||
|
||||
// TODO(DH): ControlCore has no API that returns the new size in cells
|
||||
//wil::assign_to_opt_param(dimensions, /*thing*/);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT TriggerResizeWithDimension(_In_ til::size dimensions, _Out_ til::size* dimensionsInPixels)
|
||||
{
|
||||
if (!_initialized)
|
||||
return S_FALSE;
|
||||
|
||||
winrt::Windows::Foundation::Size outSizeInPixels;
|
||||
_core->ResizeToDimensions(dimensions.width, dimensions.height, outSizeInPixels);
|
||||
wil::assign_to_opt_param(dimensionsInPixels, til::size{ til::math::rounding, outSizeInPixels });
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT CalculateResize(_In_ til::CoordType width, _In_ til::CoordType height, _Out_ til::size* dimensions)
|
||||
{
|
||||
// TODO(DH): It seems weird to have to do this manually.
|
||||
auto fontSizeInPx = _core->FontSize();
|
||||
wil::assign_to_opt_param(dimensions, til::size{
|
||||
static_cast<til::CoordType>(width / fontSizeInPx.Width),
|
||||
static_cast<til::CoordType>(height / fontSizeInPx.Height),
|
||||
});
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT DpiChanged(int newDpi)
|
||||
{
|
||||
_core->ScaleChanged((float)newDpi / 96.0f);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT UserScroll(int viewTop)
|
||||
{
|
||||
_interactivity->UpdateScrollbar(static_cast<float>(viewTop) /* TODO(DH) */);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT GetSelection(const wchar_t** out)
|
||||
{
|
||||
auto strings = _core->SelectedText(true);
|
||||
auto concatenated = std::accumulate(std::begin(strings), std::end(strings), std::wstring{}, [](auto&& l, auto&& r) {
|
||||
return l + r;
|
||||
});
|
||||
auto returnText = wil::make_cotaskmem_string_nothrow(concatenated.c_str());
|
||||
*out = returnText.release();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT IsSelectionActive(bool* out)
|
||||
{
|
||||
*out = _core->HasSelection();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT SetTheme(TerminalTheme theme, LPCWSTR fontFamily, til::CoordType fontSize, int newDpi)
|
||||
{
|
||||
_settingsBridge->SetTheme(theme, fontFamily, fontSize, newDpi);
|
||||
_core->UpdateSettings(*_settingsBridge, nullptr);
|
||||
_interactivity->UpdateSettings();
|
||||
_core->ScaleChanged((static_cast<float>(newDpi) / USER_DEFAULT_SCREEN_DPI));
|
||||
_core->ApplyAppearance(_focused);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT RegisterWriteCallback(PWRITECB callback)
|
||||
{
|
||||
_connection->_pfnWriteCallback = callback;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT SendKeyEvent(WORD vkey, WORD scanCode, WORD flags, bool keyDown)
|
||||
{
|
||||
_core->TrySendKeyEvent(vkey, scanCode, getControlKeyState(), keyDown);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT SendCharEvent(wchar_t ch, WORD flags, WORD scanCode)
|
||||
{
|
||||
_core->SendCharEvent(ch, scanCode, getControlKeyState());
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
void Initialize()
|
||||
{
|
||||
RECT windowRect;
|
||||
GetWindowRect(_hwnd.get(), &windowRect);
|
||||
auto dpi = GetDpiForWindow(_hwnd.get());
|
||||
// BODGY: the +/-1 is because ControlCore will ignore an Initialize with zero size (oops)
|
||||
// because in the old days, TermControl would accidentally try to resize the Swap Chain to 0x0 (oops)
|
||||
// and therefore resize the connection to 0x0 (oops)
|
||||
_core->InitializeWithHwnd(
|
||||
gsl::narrow_cast<float>(windowRect.right - windowRect.left + 1),
|
||||
gsl::narrow_cast<float>(windowRect.bottom - windowRect.top + 1),
|
||||
(static_cast<float>(dpi) / USER_DEFAULT_SCREEN_DPI),
|
||||
reinterpret_cast<uint64_t>(_hwnd.get()));
|
||||
_interactivity->Initialize();
|
||||
_core->ApplyAppearance(_focused);
|
||||
|
||||
_core->EnablePainting();
|
||||
|
||||
_initialized = true;
|
||||
}
|
||||
|
||||
private:
|
||||
winrt::com_ptr<CsBridgeConnection> _connection;
|
||||
winrt::com_ptr<CsBridgeTerminalSettings> _settingsBridge;
|
||||
winrt::com_ptr<implementation::ControlInteractivity> _interactivity{ nullptr };
|
||||
winrt::com_ptr<implementation::ControlCore> _core{ nullptr };
|
||||
bool _initialized{ false };
|
||||
bool _focused{ false };
|
||||
PSCROLLCB _scrollCallback{};
|
||||
|
||||
void _scrollPositionChanged(const winrt::Windows::Foundation::IInspectable& i, const ScrollPositionChangedArgs& update)
|
||||
{
|
||||
if (_scrollCallback)
|
||||
{
|
||||
_scrollCallback(update.ViewTop(), update.ViewHeight(), update.BufferSize());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
extern "C" void _stdcall AvoidBuggyTSFConsoleFlags()
|
||||
{
|
||||
Microsoft::Console::TSF::Handle::AvoidBuggyTSFConsoleFlags();
|
||||
}
|
||||
|
||||
__declspec(dllexport) HRESULT _stdcall CreateTerminal(HWND parentHwnd, _Out_ void** hwnd, _Out_ PTERM* terminal)
|
||||
{
|
||||
auto inner = new HwndTerminal{ parentHwnd };
|
||||
*terminal = inner;
|
||||
*hwnd = inner->_hwnd.get();
|
||||
inner->Initialize();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
__declspec(dllexport) void _stdcall DestroyTerminal(PTERM terminal)
|
||||
{
|
||||
delete (HwndTerminal*)terminal;
|
||||
}
|
||||
|
||||
// Generate all of the C->C++ bridge functions.
|
||||
#define API_NAME(name) Terminal##name
|
||||
#define GENERATOR_0(name) \
|
||||
__declspec(dllexport) HRESULT _stdcall API_NAME(name)(PTERM terminal) \
|
||||
try \
|
||||
{ \
|
||||
return ((HwndTerminal*)(terminal))->name(); \
|
||||
} \
|
||||
CATCH_RETURN()
|
||||
#define GENERATOR_1(name, t1, a1) \
|
||||
__declspec(dllexport) HRESULT _stdcall API_NAME(name)(PTERM terminal, t1 a1) \
|
||||
try \
|
||||
{ \
|
||||
return ((HwndTerminal*)(terminal))->name(a1); \
|
||||
} \
|
||||
CATCH_RETURN()
|
||||
#define GENERATOR_2(name, t1, a1, t2, a2) \
|
||||
__declspec(dllexport) HRESULT _stdcall API_NAME(name)(PTERM terminal, t1 a1, t2 a2) \
|
||||
try \
|
||||
{ \
|
||||
return ((HwndTerminal*)(terminal))->name(a1, a2); \
|
||||
} \
|
||||
CATCH_RETURN()
|
||||
#define GENERATOR_3(name, t1, a1, t2, a2, t3, a3) \
|
||||
__declspec(dllexport) HRESULT _stdcall API_NAME(name)(PTERM terminal, t1 a1, t2 a2, t3 a3) \
|
||||
try \
|
||||
{ \
|
||||
return ((HwndTerminal*)(terminal))->name(a1, a2, a3); \
|
||||
} \
|
||||
CATCH_RETURN()
|
||||
#define GENERATOR_4(name, t1, a1, t2, a2, t3, a3, t4, a4) \
|
||||
__declspec(dllexport) HRESULT _stdcall API_NAME(name)(PTERM terminal, t1 a1, t2 a2, t3 a3, t4 a4) \
|
||||
try \
|
||||
{ \
|
||||
return ((HwndTerminal*)(terminal))->name(a1, a2, a3, a4); \
|
||||
} \
|
||||
CATCH_RETURN()
|
||||
#define GENERATOR_N(name, t1, a1, t2, a2, t3, a3, t4, a4, MACRO, ...) MACRO
|
||||
#define GENERATOR(...) \
|
||||
GENERATOR_N(__VA_ARGS__, GENERATOR_4, GENERATOR_4, GENERATOR_3, GENERATOR_3, GENERATOR_2, GENERATOR_2, GENERATOR_1, GENERATOR_1, GENERATOR_0) \
|
||||
(__VA_ARGS__)
|
||||
TERMINAL_API_TABLE(GENERATOR)
|
||||
#undef GENERATOR_0
|
||||
#undef GENERATOR_1
|
||||
#undef GENERATOR_2
|
||||
#undef GENERATOR_3
|
||||
#undef GENERATOR_4
|
||||
#undef GENERATOR_N
|
||||
#undef GENERATOR
|
||||
|
||||
#undef API_NAME
|
||||
63
src/cascadia/TerminalControl/FlatC.h
Normal file
63
src/cascadia/TerminalControl/FlatC.h
Normal file
@@ -0,0 +1,63 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#pragma once
|
||||
|
||||
// Keep in sync with TerminalTheme.cs
|
||||
typedef struct _TerminalTheme
|
||||
{
|
||||
COLORREF DefaultBackground;
|
||||
COLORREF DefaultForeground;
|
||||
COLORREF DefaultSelectionBackground;
|
||||
uint32_t CursorStyle; // This will be converted to DispatchTypes::CursorStyle (size_t), but C# cannot marshal an enum type and have it fit in a size_t.
|
||||
COLORREF ColorTable[16];
|
||||
} TerminalTheme;
|
||||
|
||||
using PTERM = void*;
|
||||
using PSCROLLCB = void(_stdcall*)(int, int, int);
|
||||
using PWRITECB = void(_stdcall*)(const wchar_t*);
|
||||
|
||||
#define TERMINAL_API_TABLE(XX) \
|
||||
XX(SendOutput, LPCWSTR, data) \
|
||||
XX(RegisterScrollCallback, PSCROLLCB, callback) \
|
||||
XX(TriggerResize, _In_ til::CoordType, width, _In_ til::CoordType, height, _Out_ til::size*, dimensions) \
|
||||
XX(TriggerResizeWithDimension, _In_ til::size, dimensions, _Out_ til::size*, dimensionsInPixels) \
|
||||
XX(CalculateResize, _In_ til::CoordType, width, _In_ til::CoordType, height, _Out_ til::size*, dimensions) \
|
||||
XX(DpiChanged, int, newDpi) \
|
||||
XX(UserScroll, int, viewTop) \
|
||||
XX(GetSelection, const wchar_t**, out) \
|
||||
XX(IsSelectionActive, bool*, out) \
|
||||
XX(SetTheme, TerminalTheme, theme, LPCWSTR, fontFamily, til::CoordType, fontSize, int, newDpi) \
|
||||
XX(RegisterWriteCallback, PWRITECB, callback) \
|
||||
XX(SendKeyEvent, WORD, vkey, WORD, scanCode, WORD, flags, bool, keyDown) \
|
||||
XX(SendCharEvent, wchar_t, ch, WORD, flags, WORD, scanCode)
|
||||
|
||||
extern "C" {
|
||||
#define API_NAME(name) Terminal##name
|
||||
#define GENERATOR_0(name) \
|
||||
__declspec(dllexport) HRESULT _stdcall API_NAME(name)(PTERM);
|
||||
#define GENERATOR_1(name, t1, a1) \
|
||||
__declspec(dllexport) HRESULT _stdcall API_NAME(name)(PTERM, t1);
|
||||
#define GENERATOR_2(name, t1, a1, t2, a2) \
|
||||
__declspec(dllexport) HRESULT _stdcall API_NAME(name)(PTERM, t1, t2);
|
||||
#define GENERATOR_3(name, t1, a1, t2, a2, t3, a3) \
|
||||
__declspec(dllexport) HRESULT _stdcall API_NAME(name)(PTERM, t1, t2, t3);
|
||||
#define GENERATOR_4(name, t1, a1, t2, a2, t3, a3, t4, a4) \
|
||||
__declspec(dllexport) HRESULT _stdcall API_NAME(name)(PTERM, t1, t2, t3, t4);
|
||||
#define GENERATOR_N(name, t1, a1, t2, a2, t3, a3, t4, a4, MACRO, ...) MACRO
|
||||
#define GENERATOR(...) \
|
||||
GENERATOR_N(__VA_ARGS__, GENERATOR_4, GENERATOR_4, GENERATOR_3, GENERATOR_3, GENERATOR_2, GENERATOR_2, GENERATOR_1, GENERATOR_1, GENERATOR_0) \
|
||||
(__VA_ARGS__)
|
||||
TERMINAL_API_TABLE(GENERATOR)
|
||||
#undef GENERATOR
|
||||
#undef GENERATOR_0
|
||||
#undef GENERATOR_1
|
||||
#undef GENERATOR_2
|
||||
#undef GENERATOR_3
|
||||
#undef GENERATOR_4
|
||||
#undef GENERATOR_N
|
||||
#undef API_NAME
|
||||
|
||||
__declspec(dllexport) HRESULT _stdcall CreateTerminal(HWND parentHwnd, _Out_ void** hwnd, _Out_ PTERM* terminal);
|
||||
__declspec(dllexport) void _stdcall DestroyTerminal(PTERM terminal);
|
||||
};
|
||||
@@ -272,9 +272,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
TermControl::TermControl(Control::ControlInteractivity content) :
|
||||
_interactivity{ content },
|
||||
_isInternalScrollBarUpdate{ false },
|
||||
_autoScrollVelocity{ 0 },
|
||||
_autoScrollingPointerPoint{ std::nullopt },
|
||||
_lastAutoScrollUpdateTime{ std::nullopt },
|
||||
_searchBox{ nullptr }
|
||||
{
|
||||
InitializeComponent();
|
||||
@@ -394,10 +391,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
_revokers.coreScrollPositionChanged = _core.ScrollPositionChanged(winrt::auto_revoke, { get_weak(), &TermControl::_ScrollPositionChanged });
|
||||
_revokers.WarningBell = _core.WarningBell(winrt::auto_revoke, { get_weak(), &TermControl::_coreWarningBell });
|
||||
|
||||
static constexpr auto AutoScrollUpdateInterval = std::chrono::microseconds(static_cast<int>(1.0 / 30.0 * 1000000));
|
||||
_autoScrollTimer.Interval(AutoScrollUpdateInterval);
|
||||
_autoScrollTimer.Tick({ get_weak(), &TermControl::_UpdateAutoScroll });
|
||||
|
||||
_ApplyUISettings();
|
||||
|
||||
_originalPrimaryElements = winrt::single_threaded_observable_vector<Controls::ICommandBarElement>();
|
||||
@@ -1981,10 +1974,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
Focus(FocusState::Pointer);
|
||||
}
|
||||
|
||||
// Mark that this pointer event actually started within our bounds.
|
||||
// We'll need this later, for PointerMoved events.
|
||||
_pointerPressedInBounds = true;
|
||||
|
||||
if (type == Windows::Devices::Input::PointerDeviceType::Touch)
|
||||
{
|
||||
// NB: I don't think this is correct because the touch should be in the center of the rect.
|
||||
@@ -2041,40 +2030,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
TermControl::GetPointerUpdateKind(point),
|
||||
ControlKeyStates(args.KeyModifiers()),
|
||||
pixelPosition);
|
||||
|
||||
// GH#9109 - Only start an auto-scroll when the drag actually
|
||||
// started within our bounds. Otherwise, someone could start a drag
|
||||
// outside the terminal control, drag into the padding, and trick us
|
||||
// into starting to scroll.
|
||||
if (!suppressFurtherHandling && _focused && _pointerPressedInBounds && point.Properties().IsLeftButtonPressed())
|
||||
{
|
||||
// We want to find the distance relative to the bounds of the
|
||||
// SwapChainPanel, not the entire control. If they drag out of
|
||||
// the bounds of the text, into the padding, we still what that
|
||||
// to auto-scroll
|
||||
const auto cursorBelowBottomDist = cursorPosition.Y - SwapChainPanel().Margin().Top - SwapChainPanel().ActualHeight();
|
||||
const auto cursorAboveTopDist = -1 * cursorPosition.Y + SwapChainPanel().Margin().Top;
|
||||
|
||||
constexpr auto MinAutoScrollDist = 2.0; // Arbitrary value
|
||||
auto newAutoScrollVelocity = 0.0;
|
||||
if (cursorBelowBottomDist > MinAutoScrollDist)
|
||||
{
|
||||
newAutoScrollVelocity = _GetAutoScrollSpeed(cursorBelowBottomDist);
|
||||
}
|
||||
else if (cursorAboveTopDist > MinAutoScrollDist)
|
||||
{
|
||||
newAutoScrollVelocity = -1.0 * _GetAutoScrollSpeed(cursorAboveTopDist);
|
||||
}
|
||||
|
||||
if (newAutoScrollVelocity != 0)
|
||||
{
|
||||
_TryStartAutoScroll(point, newAutoScrollVelocity);
|
||||
}
|
||||
else
|
||||
{
|
||||
_TryStopAutoScroll(ptr.PointerId());
|
||||
}
|
||||
}
|
||||
/* TODO(DH) */ UNREFERENCED_PARAMETER(suppressFurtherHandling);
|
||||
}
|
||||
else if (type == Windows::Devices::Input::PointerDeviceType::Touch)
|
||||
{
|
||||
@@ -2101,8 +2057,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
return;
|
||||
}
|
||||
|
||||
_pointerPressedInBounds = false;
|
||||
|
||||
const auto ptr = args.Pointer();
|
||||
const auto point = args.GetCurrentPoint(*this);
|
||||
const auto cursorPosition = point.Position();
|
||||
@@ -2125,8 +2079,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
_interactivity.TouchReleased();
|
||||
}
|
||||
|
||||
_TryStopAutoScroll(ptr.PointerId());
|
||||
|
||||
args.Handled(true);
|
||||
}
|
||||
|
||||
@@ -2281,86 +2233,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
return false;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Starts new pointer related auto scroll behavior, or continues existing one.
|
||||
// Does nothing when there is already auto scroll associated with another pointer.
|
||||
// Arguments:
|
||||
// - pointerPoint: info about pointer that causes auto scroll. Pointer's position
|
||||
// is later used to update selection.
|
||||
// - scrollVelocity: target velocity of scrolling in characters / sec
|
||||
void TermControl::_TryStartAutoScroll(const Windows::UI::Input::PointerPoint& pointerPoint, const double scrollVelocity)
|
||||
{
|
||||
// Allow only one pointer at the time
|
||||
if (!_autoScrollingPointerPoint ||
|
||||
_autoScrollingPointerPoint->PointerId() == pointerPoint.PointerId())
|
||||
{
|
||||
_autoScrollingPointerPoint = pointerPoint;
|
||||
_autoScrollVelocity = scrollVelocity;
|
||||
|
||||
// If this is first time the auto scroll update is about to be called,
|
||||
// kick-start it by initializing its time delta as if it started now
|
||||
if (!_lastAutoScrollUpdateTime)
|
||||
{
|
||||
_lastAutoScrollUpdateTime = std::chrono::high_resolution_clock::now();
|
||||
}
|
||||
|
||||
// Apparently this check is not necessary but greatly improves performance
|
||||
if (!_autoScrollTimer.IsEnabled())
|
||||
{
|
||||
_autoScrollTimer.Start();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Stops auto scroll if it's active and is associated with supplied pointer id.
|
||||
// Arguments:
|
||||
// - pointerId: id of pointer for which to stop auto scroll
|
||||
void TermControl::_TryStopAutoScroll(const uint32_t pointerId)
|
||||
{
|
||||
if (_autoScrollingPointerPoint &&
|
||||
pointerId == _autoScrollingPointerPoint->PointerId())
|
||||
{
|
||||
_autoScrollingPointerPoint = std::nullopt;
|
||||
_autoScrollVelocity = 0;
|
||||
_lastAutoScrollUpdateTime = std::nullopt;
|
||||
|
||||
// Apparently this check is not necessary but greatly improves performance
|
||||
if (_autoScrollTimer.IsEnabled())
|
||||
{
|
||||
_autoScrollTimer.Stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Called continuously to gradually scroll viewport when user is mouse
|
||||
// selecting outside it (to 'follow' the cursor).
|
||||
// Arguments:
|
||||
// - none
|
||||
void TermControl::_UpdateAutoScroll(const Windows::Foundation::IInspectable& /* sender */,
|
||||
const Windows::Foundation::IInspectable& /* e */)
|
||||
{
|
||||
if (_autoScrollVelocity != 0)
|
||||
{
|
||||
const auto timeNow = std::chrono::high_resolution_clock::now();
|
||||
|
||||
if (_lastAutoScrollUpdateTime)
|
||||
{
|
||||
static constexpr auto microSecPerSec = 1000000.0;
|
||||
const auto deltaTime = std::chrono::duration_cast<std::chrono::microseconds>(timeNow - *_lastAutoScrollUpdateTime).count() / microSecPerSec;
|
||||
ScrollBar().Value(ScrollBar().Value() + _autoScrollVelocity * deltaTime);
|
||||
|
||||
if (_autoScrollingPointerPoint)
|
||||
{
|
||||
_SetEndSelectionPointAtCursor(_autoScrollingPointerPoint->Position());
|
||||
}
|
||||
}
|
||||
|
||||
_lastAutoScrollUpdateTime = timeNow;
|
||||
}
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Event handler for the GotFocus event. This is used to...
|
||||
// - enable accessibility notifications for this TermControl
|
||||
@@ -2495,15 +2367,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
_core.ScaleChanged(scaleX);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Sets selection's end position to match supplied cursor position, e.g. while mouse dragging.
|
||||
// Arguments:
|
||||
// - cursorPosition: in pixels, relative to the origin of the control
|
||||
void TermControl::_SetEndSelectionPointAtCursor(const Windows::Foundation::Point& cursorPosition)
|
||||
{
|
||||
_interactivity.SetEndSelectionPoint(_toTerminalOrigin(cursorPosition));
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Update the position and size of the scrollbar to match the given
|
||||
// viewport top, viewport height, and buffer size.
|
||||
@@ -2661,7 +2524,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
// On Win10 we don't destroy window threads due to bugs in DesktopWindowXamlSource.
|
||||
// In turn, we leak TermControl instances. This results in constant HWND messages
|
||||
// while the thread is supposed to be idle. Stop these timers avoids this.
|
||||
_autoScrollTimer.Stop();
|
||||
_bellLightTimer.Stop();
|
||||
|
||||
// This is absolutely crucial, as the TSF code tries to hold a strong reference to _tsfDataProvider,
|
||||
@@ -2809,7 +2671,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
|
||||
// UWP XAML scrollbars aren't guaranteed to be the same size as the
|
||||
// ComCtl scrollbars, but it's certainly close enough.
|
||||
const auto scrollbarSize = GetSystemMetricsForDpi(SM_CXVSCROLL, dpi);
|
||||
auto scrollbarSize = GetSystemMetrics(SM_CXVSCROLL);
|
||||
scrollbarSize = gsl::narrow_cast<decltype(scrollbarSize)>(scrollbarSize * (dpi / 96));
|
||||
|
||||
float width = cols * static_cast<float>(actualFontSize.width);
|
||||
|
||||
@@ -3059,20 +2922,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
};
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Calculates speed of single axis of auto scrolling. It has to allow for both
|
||||
// fast and precise selection.
|
||||
// Arguments:
|
||||
// - cursorDistanceFromBorder: distance from viewport border to cursor, in pixels. Must be non-negative.
|
||||
// Return Value:
|
||||
// - positive speed in characters / sec
|
||||
double TermControl::_GetAutoScrollSpeed(double cursorDistanceFromBorder) const
|
||||
{
|
||||
// The numbers below just feel well, feel free to change.
|
||||
// TODO: Maybe account for space beyond border that user has available
|
||||
return std::pow(cursorDistanceFromBorder, 2.0) / 25.0 + 2.0;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Async handler for the "Drop" event. If a file was dropped onto our
|
||||
// root, we'll try to get the path of the file dropped onto us, and write
|
||||
|
||||
@@ -300,14 +300,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
|
||||
bool _isInternalScrollBarUpdate;
|
||||
|
||||
// Auto scroll occurs when user, while selecting, drags cursor outside
|
||||
// viewport. View is then scrolled to 'follow' the cursor.
|
||||
double _autoScrollVelocity;
|
||||
std::optional<Windows::UI::Input::PointerPoint> _autoScrollingPointerPoint;
|
||||
SafeDispatcherTimer _autoScrollTimer;
|
||||
std::optional<std::chrono::high_resolution_clock::time_point> _lastAutoScrollUpdateTime;
|
||||
bool _pointerPressedInBounds{ false };
|
||||
|
||||
winrt::Windows::UI::Composition::ScalarKeyFrameAnimation _bellLightAnimation{ nullptr };
|
||||
winrt::Windows::UI::Composition::ScalarKeyFrameAnimation _bellDarkAnimation{ nullptr };
|
||||
SafeDispatcherTimer _bellLightTimer;
|
||||
@@ -385,8 +377,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
|
||||
void _BellLightOff(const Windows::Foundation::IInspectable& sender, const Windows::Foundation::IInspectable& e);
|
||||
|
||||
void _SetEndSelectionPointAtCursor(const Windows::Foundation::Point& cursorPosition);
|
||||
|
||||
void _SwapChainSizeChanged(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::SizeChangedEventArgs& e);
|
||||
void _SwapChainScaleChanged(const Windows::UI::Xaml::Controls::SwapChainPanel& sender, const Windows::Foundation::IInspectable& args);
|
||||
|
||||
@@ -395,10 +385,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
bool _CapturePointer(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::Input::PointerRoutedEventArgs& e);
|
||||
bool _ReleasePointerCapture(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::Input::PointerRoutedEventArgs& e);
|
||||
|
||||
void _TryStartAutoScroll(const Windows::UI::Input::PointerPoint& pointerPoint, const double scrollVelocity);
|
||||
void _TryStopAutoScroll(const uint32_t pointerId);
|
||||
void _UpdateAutoScroll(const Windows::Foundation::IInspectable& sender, const Windows::Foundation::IInspectable& e);
|
||||
|
||||
void _KeyHandler(const Windows::UI::Xaml::Input::KeyRoutedEventArgs& e, const bool keyDown);
|
||||
bool _KeyHandler(WORD vkey, WORD scanCode, ::Microsoft::Terminal::Core::ControlKeyStates modifiers, bool keyDown);
|
||||
static ::Microsoft::Terminal::Core::ControlKeyStates _GetPressedModifierKeys() noexcept;
|
||||
@@ -409,8 +395,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
winrt::Windows::Foundation::Point _toControlOrigin(const til::point terminalPosition);
|
||||
Core::Point _toTerminalOrigin(winrt::Windows::Foundation::Point cursorPosition);
|
||||
|
||||
double _GetAutoScrollSpeed(double cursorDistanceFromBorder) const;
|
||||
|
||||
void _Search(const winrt::hstring& text, const bool goForward, const bool caseSensitive, const bool regularExpression);
|
||||
void _SearchChanged(const winrt::hstring& text, const bool goForward, const bool caseSensitive, const bool regularExpression);
|
||||
void _CloseSearchBoxControl(const winrt::Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& args);
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
<!-- ========================= Headers ======================== -->
|
||||
<ItemGroup>
|
||||
<ClInclude Include="pch.h" />
|
||||
<ClInclude Include="FlatC.h" />
|
||||
<ClInclude Include="ControlCore.h">
|
||||
<DependentUpon>ControlCore.idl</DependentUpon>
|
||||
</ClInclude>
|
||||
@@ -61,14 +62,13 @@
|
||||
<DependentUpon>InteractivityAutomationPeer.idl</DependentUpon>
|
||||
</ClInclude>
|
||||
<ClInclude Include="XamlUiaTextRange.h" />
|
||||
<ClInclude Include="HwndTerminal.hpp" />
|
||||
<ClInclude Include="HwndTerminalAutomationPeer.hpp" />
|
||||
</ItemGroup>
|
||||
<!-- ========================= Cpp Files ======================== -->
|
||||
<ItemGroup>
|
||||
<ClCompile Include="pch.cpp">
|
||||
<PrecompiledHeader>Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="FlatC.cpp" />
|
||||
<ClCompile Include="ControlCore.cpp">
|
||||
<DependentUpon>ControlCore.idl</DependentUpon>
|
||||
</ClCompile>
|
||||
@@ -102,8 +102,6 @@
|
||||
<DependentUpon>InteractivityAutomationPeer.idl</DependentUpon>
|
||||
</ClCompile>
|
||||
<ClCompile Include="XamlUiaTextRange.cpp" />
|
||||
<ClCompile Include="HwndTerminal.cpp" />
|
||||
<ClCompile Include="HwndTerminalAutomationPeer.cpp" />
|
||||
</ItemGroup>
|
||||
<!-- ========================= idl Files ======================== -->
|
||||
<ItemGroup>
|
||||
@@ -160,6 +158,7 @@
|
||||
<CopyLocalSatelliteAssemblies>false</CopyLocalSatelliteAssemblies>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="$(OpenConsoleDir)src\cascadia\WinRTUtils\WinRTUtils.vcxproj">
|
||||
<Private>true</Private>
|
||||
<Project>{CA5CAD1A-039A-4929-BA2A-8BEB2E4106FE}</Project>
|
||||
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
|
||||
</ProjectReference>
|
||||
|
||||
@@ -7,17 +7,16 @@ EXPORTS
|
||||
AvoidBuggyTSFConsoleFlags
|
||||
CreateTerminal
|
||||
DestroyTerminal
|
||||
TerminalCalculateResize
|
||||
TerminalDpiChanged
|
||||
TerminalGetSelection
|
||||
TerminalIsSelectionActive
|
||||
TerminalRegisterScrollCallback
|
||||
TerminalRegisterWriteCallback
|
||||
TerminalSendCharEvent
|
||||
TerminalSendKeyEvent
|
||||
TerminalSendOutput
|
||||
TerminalSetFocused
|
||||
TerminalSetTheme
|
||||
TerminalRegisterScrollCallback
|
||||
TerminalTriggerResize
|
||||
TerminalTriggerResizeWithDimension
|
||||
TerminalCalculateResize
|
||||
TerminalDpiChanged
|
||||
TerminalUserScroll
|
||||
TerminalGetSelection
|
||||
TerminalIsSelectionActive
|
||||
TerminalSetTheme
|
||||
TerminalRegisterWriteCallback
|
||||
TerminalSendKeyEvent
|
||||
TerminalSendCharEvent
|
||||
|
||||
@@ -115,4 +115,12 @@
|
||||
|
||||
<!-- This -must- go after cppwinrt.build.post.props because that includes many VS-provided props including appcontainer.common.props, which stomps on what cppwinrt.targets did. -->
|
||||
<Import Project="$(OpenConsoleDir)src\common.nugetversions.targets" />
|
||||
|
||||
<!--LATE LATE LATE-->
|
||||
<ItemDefinitionGroup>
|
||||
<Link>
|
||||
<AdditionalDependencies>delayimp.lib;uiautomationcore.lib;oleaut32.lib;onecoreuap.lib;user32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<DelayLoadDLLs>uiautomationcore.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
</Project>
|
||||
|
||||
@@ -76,6 +76,7 @@ static void EnsureAllResourcesArePresent(const ScopedResourceLoader& loader)
|
||||
|
||||
#endif
|
||||
|
||||
static ScopedResourceLoader no_resources{ ScopedResourceLoader::NoResourcesT{} };
|
||||
const ScopedResourceLoader& GetLibraryResourceLoader()
|
||||
try
|
||||
{
|
||||
@@ -85,18 +86,30 @@ try
|
||||
#endif
|
||||
return loader;
|
||||
}
|
||||
CATCH_FAIL_FAST()
|
||||
catch (...)
|
||||
{
|
||||
LOG_CAUGHT_EXCEPTION();
|
||||
return no_resources;
|
||||
}
|
||||
|
||||
winrt::hstring GetLibraryResourceString(const std::wstring_view key)
|
||||
try
|
||||
{
|
||||
return GetLibraryResourceLoader().GetLocalizedString(key);
|
||||
}
|
||||
CATCH_FAIL_FAST()
|
||||
catch (...)
|
||||
{
|
||||
LOG_CAUGHT_EXCEPTION();
|
||||
return winrt::hstring{};
|
||||
}
|
||||
|
||||
bool HasLibraryResourceWithName(const std::wstring_view key)
|
||||
try
|
||||
{
|
||||
return GetLibraryResourceLoader().HasResourceWithName(key);
|
||||
}
|
||||
CATCH_FAIL_FAST()
|
||||
catch (...)
|
||||
{
|
||||
LOG_CAUGHT_EXCEPTION();
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -6,7 +6,12 @@
|
||||
class ScopedResourceLoader
|
||||
{
|
||||
public:
|
||||
struct NoResourcesT
|
||||
{
|
||||
};
|
||||
ScopedResourceLoader(const std::wstring_view resourceLocatorBase);
|
||||
ScopedResourceLoader(const NoResourcesT&) :
|
||||
_resourceMap{ nullptr }, _resourceContext{ nullptr } {}
|
||||
winrt::Windows::ApplicationModel::Resources::Core::ResourceMap GetResourceMap() const noexcept;
|
||||
winrt::hstring GetLocalizedString(const std::wstring_view resourceName) const;
|
||||
bool HasResourceWithName(const std::wstring_view resourceName) const;
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
<runtime>
|
||||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Castle.Core" publicKeyToken="407dd0808d44fbdc" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.1.1.0" newVersion="4.1.1.0" />
|
||||
<assemblyIdentity name="Castle.Core" publicKeyToken="407dd0808d44fbdc" culture="neutral"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.1.1.0" newVersion="4.1.1.0"/>
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
|
||||
|
||||
@@ -177,7 +177,10 @@ namespace Microsoft.Terminal.Wpf
|
||||
[DllImport("Microsoft.Terminal.Control.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall, PreserveSig = false)]
|
||||
public static extern void CreateTerminal(IntPtr parent, out IntPtr hwnd, out IntPtr terminal);
|
||||
|
||||
[DllImport("Microsoft.Terminal.Control.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall, PreserveSig = true)]
|
||||
[DllImport("Microsoft.Terminal.Control.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
|
||||
public static extern void DestroyTerminal(IntPtr terminal);
|
||||
|
||||
[DllImport("Microsoft.Terminal.Control.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall, PreserveSig = false)]
|
||||
public static extern void TerminalSendOutput(IntPtr terminal, string lpdata);
|
||||
|
||||
[DllImport("Microsoft.Terminal.Control.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall, PreserveSig = false)]
|
||||
@@ -189,44 +192,44 @@ namespace Microsoft.Terminal.Wpf
|
||||
[DllImport("Microsoft.Terminal.Control.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall, PreserveSig = false)]
|
||||
public static extern void TerminalCalculateResize(IntPtr terminal, int width, int height, out TilSize dimensions);
|
||||
|
||||
[DllImport("Microsoft.Terminal.Control.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall, PreserveSig = true)]
|
||||
[DllImport("Microsoft.Terminal.Control.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall, PreserveSig = false)]
|
||||
public static extern void TerminalDpiChanged(IntPtr terminal, int newDpi);
|
||||
|
||||
[DllImport("Microsoft.Terminal.Control.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall, PreserveSig = true)]
|
||||
[DllImport("Microsoft.Terminal.Control.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall, PreserveSig = false)]
|
||||
public static extern void TerminalRegisterScrollCallback(IntPtr terminal, [MarshalAs(UnmanagedType.FunctionPtr)] ScrollCallback callback);
|
||||
|
||||
[DllImport("Microsoft.Terminal.Control.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall, PreserveSig = true)]
|
||||
[DllImport("Microsoft.Terminal.Control.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall, PreserveSig = false)]
|
||||
public static extern void TerminalRegisterWriteCallback(IntPtr terminal, [MarshalAs(UnmanagedType.FunctionPtr)] WriteCallback callback);
|
||||
|
||||
[DllImport("Microsoft.Terminal.Control.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall, PreserveSig = true)]
|
||||
[DllImport("Microsoft.Terminal.Control.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall, PreserveSig = false)]
|
||||
public static extern void TerminalUserScroll(IntPtr terminal, int viewTop);
|
||||
|
||||
[DllImport("Microsoft.Terminal.Control.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall, PreserveSig = true)]
|
||||
[DllImport("Microsoft.Terminal.Control.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall, PreserveSig = false)]
|
||||
[return: MarshalAs(UnmanagedType.LPWStr)]
|
||||
public static extern string TerminalGetSelection(IntPtr terminal);
|
||||
|
||||
[DllImport("Microsoft.Terminal.Control.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall, PreserveSig = true)]
|
||||
[DllImport("Microsoft.Terminal.Control.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall, PreserveSig = false)]
|
||||
[return: MarshalAs(UnmanagedType.I1)]
|
||||
public static extern bool TerminalIsSelectionActive(IntPtr terminal);
|
||||
|
||||
[DllImport("Microsoft.Terminal.Control.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
|
||||
public static extern void DestroyTerminal(IntPtr terminal);
|
||||
|
||||
[DllImport("Microsoft.Terminal.Control.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall, PreserveSig = true)]
|
||||
[DllImport("Microsoft.Terminal.Control.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall, PreserveSig = false)]
|
||||
public static extern void TerminalSendKeyEvent(IntPtr terminal, ushort vkey, ushort scanCode, ushort flags, bool keyDown);
|
||||
|
||||
[DllImport("Microsoft.Terminal.Control.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall, PreserveSig = true)]
|
||||
[DllImport("Microsoft.Terminal.Control.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall, PreserveSig = false)]
|
||||
public static extern void TerminalSendCharEvent(IntPtr terminal, char ch, ushort scanCode, ushort flags);
|
||||
|
||||
[DllImport("Microsoft.Terminal.Control.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall, PreserveSig = true)]
|
||||
[DllImport("Microsoft.Terminal.Control.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall, PreserveSig = false)]
|
||||
public static extern void TerminalSetTheme(IntPtr terminal, [MarshalAs(UnmanagedType.Struct)] TerminalTheme theme, string fontFamily, short fontSize, int newDpi);
|
||||
|
||||
[DllImport("Microsoft.Terminal.Control.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall, PreserveSig = true)]
|
||||
public static extern void TerminalSetFocused(IntPtr terminal, bool focused);
|
||||
|
||||
[DllImport("user32.dll", SetLastError = true)]
|
||||
public static extern IntPtr SetFocus(IntPtr hWnd);
|
||||
|
||||
[DllImport("user32.dll", SetLastError = true)]
|
||||
public static extern IntPtr GetFocus();
|
||||
|
||||
[DllImport("user32.dll", SetLastError = true)]
|
||||
public static extern short GetKeyState(int keyCode);
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct WINDOWPOS
|
||||
{
|
||||
|
||||
@@ -37,7 +37,6 @@ namespace Microsoft.Terminal.Wpf
|
||||
NativeMethods.AvoidBuggyTSFConsoleFlags();
|
||||
|
||||
this.MessageHook += this.TerminalContainer_MessageHook;
|
||||
this.GotFocus += this.TerminalContainer_GotFocus;
|
||||
this.Focusable = true;
|
||||
}
|
||||
|
||||
@@ -324,24 +323,12 @@ namespace Microsoft.Terminal.Wpf
|
||||
character = (char)vKey;
|
||||
}
|
||||
|
||||
private void TerminalContainer_GotFocus(object sender, RoutedEventArgs e)
|
||||
{
|
||||
e.Handled = true;
|
||||
NativeMethods.SetFocus(this.hwnd);
|
||||
}
|
||||
|
||||
private IntPtr TerminalContainer_MessageHook(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
|
||||
{
|
||||
if (hwnd == this.hwnd)
|
||||
{
|
||||
switch ((NativeMethods.WindowMessage)msg)
|
||||
{
|
||||
case NativeMethods.WindowMessage.WM_SETFOCUS:
|
||||
NativeMethods.TerminalSetFocused(this.terminal, true);
|
||||
break;
|
||||
case NativeMethods.WindowMessage.WM_KILLFOCUS:
|
||||
NativeMethods.TerminalSetFocused(this.terminal, false);
|
||||
break;
|
||||
case NativeMethods.WindowMessage.WM_MOUSEACTIVATE:
|
||||
this.Focus();
|
||||
NativeMethods.SetFocus(this.hwnd);
|
||||
@@ -349,6 +336,7 @@ namespace Microsoft.Terminal.Wpf
|
||||
case NativeMethods.WindowMessage.WM_SYSKEYDOWN: // fallthrough
|
||||
case NativeMethods.WindowMessage.WM_KEYDOWN:
|
||||
{
|
||||
// WM_KEYDOWN lParam layout documentation: https://docs.microsoft.com/en-us/windows/win32/inputdev/wm-keydown
|
||||
UnpackKeyMessage(wParam, lParam, out ushort vkey, out ushort scanCode, out ushort flags);
|
||||
NativeMethods.TerminalSendKeyEvent(this.terminal, vkey, scanCode, flags, true);
|
||||
break;
|
||||
@@ -403,10 +391,10 @@ namespace Microsoft.Terminal.Wpf
|
||||
this.Connection?.Resize((uint)dimensions.Y, (uint)dimensions.X);
|
||||
break;
|
||||
|
||||
case NativeMethods.WindowMessage.WM_MOUSEWHEEL:
|
||||
var delta = (short)(((long)wParam) >> 16);
|
||||
this.UserScrolled?.Invoke(this, delta);
|
||||
break;
|
||||
//case NativeMethods.WindowMessage.WM_MOUSEWHEEL:
|
||||
//var delta = (short)(((long)wParam) >> 16);
|
||||
//this.UserScrolled?.Invoke(this, delta);
|
||||
//break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,117 @@ namespace WpfTerminalTestNetCore
|
||||
{
|
||||
public class EchoConnection : Microsoft.Terminal.Wpf.ITerminalConnection
|
||||
{
|
||||
byte[] __foo_txt = {
|
||||
0x1b, 0x5b, 0x48, 0x1b, 0x5b, 0x32, 0x4a, 0x1b, 0x5b, 0x33, 0x4a, 0x0d,
|
||||
0x0a, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x31, 0x38, 0x6d,
|
||||
0x54, 0x1b, 0x5b, 0x30, 0x6d, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b,
|
||||
0x31, 0x35, 0x34, 0x6d, 0x68, 0x1b, 0x5b, 0x30, 0x6d, 0x1b, 0x5b, 0x33,
|
||||
0x38, 0x3b, 0x35, 0x3b, 0x31, 0x35, 0x34, 0x6d, 0x61, 0x1b, 0x5b, 0x30,
|
||||
0x6d, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x35, 0x34, 0x6d,
|
||||
0x6e, 0x1b, 0x5b, 0x30, 0x6d, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b,
|
||||
0x31, 0x34, 0x38, 0x6d, 0x6b, 0x1b, 0x5b, 0x30, 0x6d, 0x1b, 0x5b, 0x33,
|
||||
0x38, 0x3b, 0x35, 0x3b, 0x31, 0x38, 0x34, 0x6d, 0x73, 0x1b, 0x5b, 0x30,
|
||||
0x6d, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x38, 0x34, 0x6d,
|
||||
0x20, 0x1b, 0x5b, 0x30, 0x6d, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b,
|
||||
0x31, 0x38, 0x34, 0x6d, 0x66, 0x1b, 0x5b, 0x30, 0x6d, 0x1b, 0x5b, 0x33,
|
||||
0x38, 0x3b, 0x35, 0x3b, 0x31, 0x37, 0x38, 0x6d, 0x6f, 0x1b, 0x5b, 0x30,
|
||||
0x6d, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x31, 0x34, 0x6d,
|
||||
0x72, 0x1b, 0x5b, 0x30, 0x6d, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b,
|
||||
0x32, 0x31, 0x34, 0x6d, 0x20, 0x1b, 0x5b, 0x30, 0x6d, 0x1b, 0x5b, 0x33,
|
||||
0x38, 0x3b, 0x35, 0x3b, 0x32, 0x31, 0x34, 0x6d, 0x76, 0x1b, 0x5b, 0x30,
|
||||
0x6d, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x30, 0x38, 0x6d,
|
||||
0x69, 0x1b, 0x5b, 0x30, 0x6d, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b,
|
||||
0x32, 0x30, 0x38, 0x6d, 0x73, 0x1b, 0x5b, 0x30, 0x6d, 0x1b, 0x5b, 0x33,
|
||||
0x38, 0x3b, 0x35, 0x3b, 0x32, 0x30, 0x38, 0x6d, 0x69, 0x1b, 0x5b, 0x30,
|
||||
0x6d, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x30, 0x33, 0x6d,
|
||||
0x74, 0x1b, 0x5b, 0x30, 0x6d, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b,
|
||||
0x32, 0x30, 0x33, 0x6d, 0x69, 0x1b, 0x5b, 0x30, 0x6d, 0x1b, 0x5b, 0x33,
|
||||
0x38, 0x3b, 0x35, 0x3b, 0x32, 0x30, 0x33, 0x6d, 0x6e, 0x1b, 0x5b, 0x30,
|
||||
0x6d, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x30, 0x33, 0x6d,
|
||||
0x67, 0x1b, 0x5b, 0x30, 0x6d, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b,
|
||||
0x31, 0x39, 0x38, 0x6d, 0x20, 0x1b, 0x5b, 0x30, 0x6d, 0x1b, 0x5b, 0x33,
|
||||
0x38, 0x3b, 0x35, 0x3b, 0x31, 0x39, 0x38, 0x6d, 0x6d, 0x1b, 0x5b, 0x30,
|
||||
0x6d, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x39, 0x38, 0x6d,
|
||||
0x79, 0x1b, 0x5b, 0x30, 0x6d, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b,
|
||||
0x31, 0x39, 0x39, 0x6d, 0x20, 0x1b, 0x5b, 0x30, 0x6d, 0x1b, 0x5b, 0x33,
|
||||
0x38, 0x3b, 0x35, 0x3b, 0x31, 0x39, 0x39, 0x6d, 0x77, 0x1b, 0x5b, 0x30,
|
||||
0x6d, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x39, 0x39, 0x6d,
|
||||
0x65, 0x1b, 0x5b, 0x30, 0x6d, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b,
|
||||
0x31, 0x36, 0x33, 0x6d, 0x62, 0x1b, 0x5b, 0x30, 0x6d, 0x1b, 0x5b, 0x33,
|
||||
0x38, 0x3b, 0x35, 0x3b, 0x31, 0x36, 0x34, 0x6d, 0x73, 0x1b, 0x5b, 0x30,
|
||||
0x6d, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x36, 0x34, 0x6d,
|
||||
0x69, 0x1b, 0x5b, 0x30, 0x6d, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b,
|
||||
0x31, 0x36, 0x34, 0x6d, 0x74, 0x1b, 0x5b, 0x30, 0x6d, 0x1b, 0x5b, 0x33,
|
||||
0x38, 0x3b, 0x35, 0x3b, 0x31, 0x32, 0x38, 0x6d, 0x65, 0x1b, 0x5b, 0x30,
|
||||
0x6d, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x32, 0x39, 0x6d,
|
||||
0x21, 0x1b, 0x5b, 0x30, 0x6d, 0x0d, 0x0a, 0x0d, 0x0a, 0x54, 0x68, 0x69,
|
||||
0x73, 0x20, 0x69, 0x73, 0x20, 0x6d, 0x79, 0x20, 0x63, 0x6f, 0x6f, 0x6c,
|
||||
0x20, 0x77, 0x65, 0x62, 0x73, 0x69, 0x74, 0x65, 0x20, 0x61, 0x62, 0x6f,
|
||||
0x75, 0x74, 0x20, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x73,
|
||||
0x0d, 0x0a, 0x48, 0x65, 0x72, 0x65, 0x20, 0x69, 0x73, 0x20, 0x61, 0x20,
|
||||
0x6c, 0x69, 0x73, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x63, 0x6f, 0x6f, 0x6c,
|
||||
0x20, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x73, 0x0d, 0x0a,
|
||||
0x2a, 0x20, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x73, 0x20, 0x54, 0x65,
|
||||
0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x20, 0x28, 0x68, 0x74, 0x74, 0x70,
|
||||
0x73, 0x3a, 0x2f, 0x2f, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63,
|
||||
0x6f, 0x6d, 0x2f, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, 0x74,
|
||||
0x2f, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x29, 0x0d, 0x0a,
|
||||
0x0d, 0x0a, 0x1b, 0x5b, 0x35, 0x6d, 0x5b, 0x55, 0x4e, 0x44, 0x45, 0x52,
|
||||
0x20, 0x43, 0x4f, 0x4e, 0x53, 0x54, 0x52, 0x55, 0x43, 0x54, 0x49, 0x4f,
|
||||
0x4e, 0x5d, 0x1b, 0x5b, 0x6d, 0x0d, 0x0a, 0x0d, 0x0a, 0x59, 0x6f, 0x75,
|
||||
0x20, 0x61, 0x72, 0x65, 0x20, 0x76, 0x69, 0x73, 0x69, 0x74, 0x6f, 0x72,
|
||||
0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x20, 0x1b, 0x5b, 0x35, 0x33,
|
||||
0x3b, 0x34, 0x3b, 0x39, 0x32, 0x6d, 0x30, 0x30, 0x30, 0x30, 0x32, 0x1b,
|
||||
0x5b, 0x6d, 0x20, 0x74, 0x6f, 0x20, 0x6d, 0x79, 0x20, 0x77, 0x65, 0x62,
|
||||
0x73, 0x69, 0x74, 0x65, 0x2e, 0x0d, 0x0a, 0x0d, 0x0a, 0x1b, 0x5b, 0x33,
|
||||
0x38, 0x3b, 0x35, 0x3b, 0x32, 0x34, 0x34, 0x6d, 0x1b, 0x5b, 0x35, 0x33,
|
||||
0x6d, 0x20, 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x70, 0x61,
|
||||
0x72, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x43, 0x6f,
|
||||
0x6f, 0x6c, 0x20, 0x54, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x73,
|
||||
0x20, 0x77, 0x65, 0x62, 0x72, 0x69, 0x6e, 0x67, 0x21, 0x20, 0x1b, 0x5b,
|
||||
0x35, 0x35, 0x6d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x56, 0x69, 0x73, 0x69,
|
||||
0x74, 0x20, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20, 0x73, 0x69, 0x74, 0x65,
|
||||
0x73, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x65, 0x62,
|
||||
0x20, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x2e, 0x2e, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x1b, 0x5b, 0x39, 0x34, 0x6d, 0x1b, 0x5d, 0x38, 0x3b,
|
||||
0x69, 0x64, 0x3d, 0x70, 0x72, 0x65, 0x76, 0x3b, 0x68, 0x74, 0x74, 0x70,
|
||||
0x73, 0x3a, 0x2f, 0x2f, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c,
|
||||
0x2e, 0x73, 0x69, 0x74, 0x65, 0x2f, 0x3f, 0x70, 0x72, 0x65, 0x76, 0x69,
|
||||
0x6f, 0x75, 0x73, 0x3d, 0x31, 0x1b, 0x5c, 0x50, 0x72, 0x65, 0x76, 0x69,
|
||||
0x6f, 0x75, 0x73, 0x1b, 0x5d, 0x38, 0x3b, 0x3b, 0x1b, 0x5c, 0x1b, 0x5b,
|
||||
0x6d, 0x20, 0x20, 0x20, 0x20, 0x20, 0x1b, 0x5b, 0x39, 0x34, 0x6d, 0x1b,
|
||||
0x5d, 0x38, 0x3b, 0x69, 0x64, 0x3d, 0x72, 0x61, 0x6e, 0x64, 0x3b, 0x68,
|
||||
0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x74, 0x65, 0x72, 0x6d, 0x69,
|
||||
0x6e, 0x61, 0x6c, 0x2e, 0x73, 0x69, 0x74, 0x65, 0x2f, 0x3f, 0x72, 0x61,
|
||||
0x6e, 0x64, 0x6f, 0x6d, 0x3d, 0x31, 0x1b, 0x5c, 0x52, 0x61, 0x6e, 0x64,
|
||||
0x6f, 0x6d, 0x1b, 0x5d, 0x38, 0x3b, 0x3b, 0x1b, 0x5c, 0x1b, 0x5b, 0x6d,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x1b, 0x5b, 0x39, 0x34, 0x6d, 0x1b, 0x5d,
|
||||
0x38, 0x3b, 0x69, 0x64, 0x3d, 0x6e, 0x65, 0x78, 0x74, 0x3b, 0x68, 0x74,
|
||||
0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e,
|
||||
0x61, 0x6c, 0x2e, 0x73, 0x69, 0x74, 0x65, 0x2f, 0x3f, 0x6e, 0x65, 0x78,
|
||||
0x74, 0x3d, 0x31, 0x1b, 0x5c, 0x4e, 0x65, 0x78, 0x74, 0x1b, 0x5d, 0x38,
|
||||
0x3b, 0x3b, 0x1b, 0x5c, 0x1b, 0x5b, 0x6d, 0x20, 0x0d, 0x0a, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x1b, 0x5b, 0x39, 0x34, 0x6d, 0x1b, 0x5d,
|
||||
0x38, 0x3b, 0x69, 0x64, 0x3d, 0x70, 0x72, 0x65, 0x76, 0x3b, 0x68, 0x74,
|
||||
0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e,
|
||||
0x61, 0x6c, 0x2e, 0x73, 0x69, 0x74, 0x65, 0x2f, 0x3f, 0x70, 0x72, 0x65,
|
||||
0x76, 0x69, 0x6f, 0x75, 0x73, 0x3d, 0x31, 0x1b, 0x5c, 0x20, 0x20, 0x53,
|
||||
0x69, 0x74, 0x65, 0x20, 0x20, 0x1b, 0x5d, 0x38, 0x3b, 0x3b, 0x1b, 0x5c,
|
||||
0x1b, 0x5b, 0x6d, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x1b, 0x5b, 0x39, 0x34, 0x6d,
|
||||
0x1b, 0x5d, 0x38, 0x3b, 0x69, 0x64, 0x3d, 0x6e, 0x65, 0x78, 0x74, 0x3b,
|
||||
0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x74, 0x65, 0x72, 0x6d,
|
||||
0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x73, 0x69, 0x74, 0x65, 0x2f, 0x3f, 0x6e,
|
||||
0x65, 0x78, 0x74, 0x3d, 0x31, 0x1b, 0x5c, 0x53, 0x69, 0x74, 0x65, 0x1b,
|
||||
0x5d, 0x38, 0x3b, 0x3b, 0x1b, 0x5c, 0x1b, 0x5b, 0x6d, 0x20, 0x0d, 0x0a,
|
||||
0x1b, 0x5b, 0x34, 0x3b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x32, 0x34, 0x34,
|
||||
0x6d, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x1b, 0x5b,
|
||||
0x6d, 0x0d, 0x0a
|
||||
};
|
||||
public event EventHandler<TerminalOutputEventArgs> TerminalOutput;
|
||||
|
||||
public void Resize(uint rows, uint columns)
|
||||
@@ -18,10 +129,15 @@ namespace WpfTerminalTestNetCore
|
||||
return;
|
||||
}
|
||||
|
||||
private void _preamble()
|
||||
{
|
||||
_print(System.Text.Encoding.UTF8.GetString(__foo_txt));
|
||||
_print("^A: prt esc ^B: sgrmouse ^C: win32im ^D: again!\r\n");
|
||||
return;
|
||||
}
|
||||
public void Start()
|
||||
{
|
||||
TerminalOutput.Invoke(this, new TerminalOutputEventArgs("ECHO CONNECTION\r\n^A: toggle printable ESC\r\n^B: toggle SGR mouse mode\r\n^C: toggle win32 input mode\r\n\r\n"));
|
||||
return;
|
||||
_preamble();
|
||||
}
|
||||
|
||||
private bool _escapeMode;
|
||||
@@ -62,18 +178,27 @@ namespace WpfTerminalTestNetCore
|
||||
TerminalOutput.Invoke(this, new TerminalOutputEventArgs($"Printable ESC mode: {_escapeMode}\r\n"));
|
||||
}
|
||||
}
|
||||
else if (data[0] == '\x04')
|
||||
{
|
||||
_preamble();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Echo back to the terminal, but make backspace/newline work properly.
|
||||
var str = data.Replace("\r", "\r\n").Replace("\x7f", "\x08 \x08");
|
||||
if (_escapeMode)
|
||||
{
|
||||
str = str.Replace("\x1b", "\u241b");
|
||||
}
|
||||
TerminalOutput.Invoke(this, new TerminalOutputEventArgs(str));
|
||||
_print(str);
|
||||
}
|
||||
}
|
||||
|
||||
private void _print(string str)
|
||||
{
|
||||
if (_escapeMode)
|
||||
{
|
||||
str = str.Replace("\x1b", "\u241b");
|
||||
}
|
||||
TerminalOutput.Invoke(this, new TerminalOutputEventArgs(str));
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
return;
|
||||
|
||||
@@ -137,7 +137,7 @@
|
||||
This diagnostic is broken in VS 17.7 which our CI currently uses. It's fixed in 17.8.
|
||||
-->
|
||||
<DisableSpecificWarnings>4201;4312;4467;5105;26434;26445;26456;26478;26494;%(DisableSpecificWarnings)</DisableSpecificWarnings>
|
||||
<PreprocessorDefinitions>_WINDOWS;EXTERNAL_BUILD;_SILENCE_STDEXT_ARR_ITERS_DEPRECATION_WARNING;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>_SILENCE_STDEXT_ARR_ITERS_DEPRECATION_WARNING;_WINDOWS;EXTERNAL_BUILD;_SILENCE_STDEXT_ARR_ITERS_DEPRECATION_WARNING;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PrecompiledHeaderFile>precomp.h</PrecompiledHeaderFile>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
<runtime>
|
||||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Castle.Core" publicKeyToken="407dd0808d44fbdc" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.1.1.0" newVersion="4.1.1.0" />
|
||||
<assemblyIdentity name="Castle.Core" publicKeyToken="407dd0808d44fbdc" culture="neutral"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.1.1.0" newVersion="4.1.1.0"/>
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
|
||||
|
||||
Reference in New Issue
Block a user