Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix caret cursor #212

Merged
merged 10 commits into from
Dec 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions src/Consolonia.Core/Drawing/CaretStyle.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
namespace Consolonia.Core.Drawing
{
public enum CaretStyle
{
BlinkingBar,
SteadyBar,
BlinkingBlock,
SteadyBlock,
BlinkingUnderline,
SteadyUnderline
}
}
27 changes: 20 additions & 7 deletions src/Consolonia.Core/Drawing/DrawingContextImpl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,17 @@ public void DrawGeometry(IBrush brush, IPen pen, IGeometryImpl geometry)
if (sceneBrushContent != null) sceneBrushContent.Render(this, Matrix.Identity);
return;
}
case MoveConsoleCaretToPositionBrush moveBrush:
{
Point head = r.TopLeft.Transform(Transform);
_pixelBuffer.CaretStyle = moveBrush.CaretStyle;
CurrentClip.ExecuteWithClipping(head,
() =>
{
_pixelBuffer.Set((PixelBufferCoordinate)head, pixel => pixel.Blend(new Pixel(true)));
});
return;
}
}

FillRectangleWithBrush(brush, pen, r);
Expand Down Expand Up @@ -458,6 +469,15 @@ private void DrawLineInternal(IPen pen, Line line)
return;
}

if (pen.Brush is MoveConsoleCaretToPositionBrush moveBrush)
{
_pixelBuffer.CaretStyle = moveBrush.CaretStyle;
Point head = line.PStart.Transform(Transform);
CurrentClip.ExecuteWithClipping(head,
() => { _pixelBuffer.Set((PixelBufferCoordinate)head, pixel => pixel.Blend(new Pixel(true))); });
return;
}
tomlm marked this conversation as resolved.
Show resolved Hide resolved

DrawBoxLineInternal(pen, line, RectangleLinePosition.Unknown);
}

Expand Down Expand Up @@ -532,13 +552,6 @@ private void DrawBoxLineInternal(IPen pen, Line line, RectangleLinePosition line

Point head = line.PStart;

if (pen.Brush is MoveConsoleCaretToPositionBrush)
{
CurrentClip.ExecuteWithClipping(head,
() => { _pixelBuffer.Set((PixelBufferCoordinate)head, pixel => pixel.Blend(new Pixel(true))); });
return;
}

var extractColorCheckPlatformSupported = ExtractColorOrNullWithPlatformCheck(pen, out var lineStyle);
if (extractColorCheckPlatformSupported == null)
return;
Expand Down
14 changes: 13 additions & 1 deletion src/Consolonia.Core/Drawing/MoveConsoleCaretToPositionBrush.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,20 @@

namespace Consolonia.Core.Drawing
{
public class MoveConsoleCaretToPositionBrush : IImmutableBrush
public class MoveConsoleCaretToPositionBrush : AvaloniaObject, IImmutableBrush
{
public static readonly StyledProperty<CaretStyle> CaretStyleProperty =
AvaloniaProperty.Register<MoveConsoleCaretToPositionBrush, CaretStyle>(nameof(CaretStyle));

/// <summary>
/// style of caret
/// </summary>
public CaretStyle CaretStyle
{
get => GetValue(CaretStyleProperty);
set => SetValue(CaretStyleProperty, value);
}

//todo: Search for B75ABC91-2CDD-4557-9201-16AC483C8D7B
public double Opacity => 1;
public ITransform Transform => null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ public PixelBuffer(ushort width, ushort height)
public ushort Width { get; }
public ushort Height { get; }

public CaretStyle CaretStyle { get; set; } = CaretStyle.BlinkingBar;

// ReSharper disable once UnusedMember.Global
[JsonIgnore]
public Pixel this[int i]
Expand Down
13 changes: 13 additions & 0 deletions src/Consolonia.Core/Drawing/RenderTarget.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
using Avalonia.Platform;
using Consolonia.Core.Drawing.PixelBufferImplementation;
using Consolonia.Core.Infrastructure;
using Consolonia.Core.Text;

namespace Consolonia.Core.Drawing
{
Expand Down Expand Up @@ -141,11 +142,23 @@ private void RenderToDevice()
if (caretPosition != null)
{
_console.SetCaretPosition((PixelBufferCoordinate)caretPosition);
_console.WriteText(pixelBuffer.CaretStyle switch
{
CaretStyle.BlinkingBar => Esc.BlinkingBarCursor,
CaretStyle.SteadyBar => Esc.SteadyBarCursor,
CaretStyle.BlinkingBlock => Esc.BlinkingBlockCursor,
CaretStyle.SteadyBlock => Esc.SteadyBlockCursor,
CaretStyle.BlinkingUnderline => Esc.BlinkingUnderlineCursor,
CaretStyle.SteadyUnderline => Esc.SteadyUnderlineCursor,
_ => throw new ArgumentOutOfRangeException()
});
_console.WriteText(Esc.ShowCursor);
_console.CaretVisible = true;
}
else
{
_console.CaretVisible = false;
_console.WriteText(Esc.HideCursor);
}
}

Expand Down
14 changes: 1 addition & 13 deletions src/Consolonia.Core/Infrastructure/InputLessDefaultNetConsole.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ namespace Consolonia.Core.Infrastructure
public abstract class InputLessDefaultNetConsole : IConsole
{
private const string TestEmoji = "👨‍👩‍👧‍👦";
private bool _caretVisible;
private PixelBufferCoordinate _headBufferPoint;

private bool? _supportEmoji;
Expand All @@ -32,18 +31,7 @@ protected InputLessDefaultNetConsole()

protected Task PauseTask { get; private set; }

public bool CaretVisible
{
get => _caretVisible;
#pragma warning disable CA1303 // Do not pass literals as localized parameters
set
{
if (_caretVisible == value) return;
WriteText(value ? Esc.ShowCursor : Esc.HideCursor);
_caretVisible = value;
}
#pragma warning restore CA1303 // Do not pass literals as localized parameters
}
public bool CaretVisible { get; set; }

public PixelBufferSize Size { get; private set; }

Expand Down
8 changes: 8 additions & 0 deletions src/Consolonia.Core/Text/Esc.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,14 @@ internal static class Esc
public const string HideCursor = "\u001b[?25l";
public const string ShowCursor = "\u001b[?25h";

// cursor shape
public const string BlinkingBlockCursor = "\u001b[1 q";
public const string SteadyBlockCursor = "\u001b[2 q";
public const string BlinkingUnderlineCursor = "\u001b[3 q";
public const string SteadyUnderlineCursor = "\u001b[4 q";
public const string BlinkingBarCursor = "\u001b[5 q";
public const string SteadyBarCursor = "\u001b[6 q";

// move cursor
public static string MoveCursorUp(int n)
{
Expand Down
38 changes: 12 additions & 26 deletions src/Consolonia.Themes/Templates/Controls/CaretControl.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,37 +10,23 @@
<Setter.Value>
<ControlTemplate>
<Grid Background="{TemplateBinding Background}">
<TextBlock Width="1"
Height="1"
HorizontalAlignment="Left"
VerticalAlignment="Top"
IsHitTestVisible="False"
Background="{DynamicResource ThemeActionBackgroundBrush}"
IsVisible="{TemplateBinding IsCaretShown}"
Margin="{TemplateBinding Padding}"
Tag="This TextBlock is a hack. Otherwise Line below does not get redrawn in CheckBox">
<!--<TextBlock.Background>
<drawing:ConsoleBrush Mode="Transparent"/>
</TextBlock.Background>-->
</TextBlock>
<ContentPresenter Name="PART_ContentPresenter"
ContentTemplate="{TemplateBinding ContentTemplate}"
Content="{TemplateBinding Content}"
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" />
<Line Margin="{TemplateBinding Padding}"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Name="PART_CaretLine"
Width="1"
Height="1"
IsHitTestVisible="False"
IsVisible="{TemplateBinding IsCaretShown}"
StrokeThickness="1">
<Line.Stroke>
<drawing:MoveConsoleCaretToPositionBrush />
</Line.Stroke>
</Line>
<!-- Caret should be drawn last so it is overlayed on top of any chars in the content -->
<Rectangle Name="PART_CaretLine"
Width="1"
Height="1"
HorizontalAlignment="Left"
VerticalAlignment="Top"
IsHitTestVisible="False"
IsVisible="{TemplateBinding IsCaretShown}">
<Rectangle.Fill>
<drawing:MoveConsoleCaretToPositionBrush CaretStyle="{TemplateBinding CaretStyle}" />
</Rectangle.Fill>
</Rectangle>
</Grid>
</ControlTemplate>
</Setter.Value>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.Primitives;
using Consolonia.Core.Drawing;

namespace Consolonia.Themes.Templates.Controls.Helpers
{
Expand All @@ -9,13 +10,21 @@ public class CaretControl : ContentControl
public static readonly StyledProperty<bool> IsCaretShownProperty =
AvaloniaProperty.Register<CaretControl, bool>(nameof(IsCaretShown));

public static readonly StyledProperty<CaretStyle> CaretStyleProperty =
AvaloniaProperty.Register<CaretControl, CaretStyle>(nameof(CaretStyle));

public bool IsCaretShown
{
get => GetValue(IsCaretShownProperty);
set => SetValue(IsCaretShownProperty, value);
}

public CaretStyle CaretStyle
{
get => GetValue(CaretStyleProperty);
set => SetValue(CaretStyleProperty, value);
}

protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
{
base.OnApplyTemplate(e);
Expand Down
Loading