diff --git a/src/Consolonia.Core/Dummy/DummyConsole.cs b/src/Consolonia.Core/Dummy/DummyConsole.cs
index f3fc6efc..883fc56f 100644
--- a/src/Consolonia.Core/Dummy/DummyConsole.cs
+++ b/src/Consolonia.Core/Dummy/DummyConsole.cs
@@ -34,6 +34,8 @@ public bool CaretVisible
public bool SupportsComplexEmoji => true;
public bool SupportsAltSolo => false;
+ public bool SupportsMouse => false;
+ public bool SupportsMouseMove => false;
public void ClearOutput()
{
diff --git a/src/Consolonia.Core/Infrastructure/DefaultNetConsole.cs b/src/Consolonia.Core/Infrastructure/DefaultNetConsole.cs
index 3437cd57..ffffbc18 100644
--- a/src/Consolonia.Core/Infrastructure/DefaultNetConsole.cs
+++ b/src/Consolonia.Core/Infrastructure/DefaultNetConsole.cs
@@ -48,6 +48,8 @@ public DefaultNetConsole()
}
public override bool SupportsAltSolo => false;
+ public override bool SupportsMouse => false;
+ public override bool SupportsMouseMove => false;
protected override void Dispose(bool disposing)
{
diff --git a/src/Consolonia.Core/Infrastructure/IConsole.cs b/src/Consolonia.Core/Infrastructure/IConsole.cs
index d4975340..d9f94b3b 100644
--- a/src/Consolonia.Core/Infrastructure/IConsole.cs
+++ b/src/Consolonia.Core/Infrastructure/IConsole.cs
@@ -22,6 +22,8 @@ public interface IConsole : IDisposable
bool SupportsComplexEmoji { get; }
bool SupportsAltSolo { get; }
+ bool SupportsMouse { get; }
+ bool SupportsMouseMove { get; }
void SetTitle(string title);
diff --git a/src/Consolonia.Core/Infrastructure/InputLessDefaultNetConsole.cs b/src/Consolonia.Core/Infrastructure/InputLessDefaultNetConsole.cs
index dff6c716..d5c39dab 100644
--- a/src/Consolonia.Core/Infrastructure/InputLessDefaultNetConsole.cs
+++ b/src/Consolonia.Core/Infrastructure/InputLessDefaultNetConsole.cs
@@ -37,6 +37,8 @@ protected InputLessDefaultNetConsole()
public bool SupportsComplexEmoji => _supportEmoji ?? false;
public abstract bool SupportsAltSolo { get; }
+ public abstract bool SupportsMouse { get; }
+ public abstract bool SupportsMouseMove { get; }
public void SetTitle(string title)
{
diff --git a/src/Consolonia.Core/InternalHelpers/CommonInternalHelper.cs b/src/Consolonia.Core/InternalHelpers/CommonInternalHelper.cs
index dc15318f..3a0658f3 100644
--- a/src/Consolonia.Core/InternalHelpers/CommonInternalHelper.cs
+++ b/src/Consolonia.Core/InternalHelpers/CommonInternalHelper.cs
@@ -3,7 +3,7 @@
namespace Consolonia.Core.InternalHelpers
{
- internal static class CommonInternalHelper
+ public static class CommonInternalHelper
{
public static bool IsNearlyEqual(this double value, double compareTo)
{
diff --git a/src/Consolonia.Gallery/Gallery/GalleryViews/GalleryTextBlock.axaml b/src/Consolonia.Gallery/Gallery/GalleryViews/GalleryTextBlock.axaml
index b0899a84..1d20256c 100644
--- a/src/Consolonia.Gallery/Gallery/GalleryViews/GalleryTextBlock.axaml
+++ b/src/Consolonia.Gallery/Gallery/GalleryViews/GalleryTextBlock.axaml
@@ -20,6 +20,10 @@
FontWeight="Bold"
Background="DarkMagenta"
Foreground="Chartreuse" />
+
+ Selectable text: Loreum ipsum dolor sit amet, consectetur adipiscing elit. Vivamus magna. Cras in mi at felis aliquet congue. Ut a est eget ligula molestie gravida. Curabitur massa. Donec eleifend, libero at sagittis
+
true;
public bool SupportsAltSolo => true;
+ public bool SupportsMouse => false;
+ public bool SupportsMouseMove => false;
public void SetTitle(string title)
{
diff --git a/src/Consolonia.PlatformSupport/CursesConsole.cs b/src/Consolonia.PlatformSupport/CursesConsole.cs
index 809fed4b..78c8fcfc 100644
--- a/src/Consolonia.PlatformSupport/CursesConsole.cs
+++ b/src/Consolonia.PlatformSupport/CursesConsole.cs
@@ -93,12 +93,12 @@ private static readonly FlagTranslator
(Curses.Event.Button1Pressed, RawPointerEventType.LeftButtonDown),
(Curses.Event.Button1Clicked, RawPointerEventType.LeftButtonDown),
(Curses.Event.Button1Released, RawPointerEventType.LeftButtonUp),
- (Curses.Event.Button2Pressed, RawPointerEventType.RightButtonDown),
- (Curses.Event.Button2Clicked, RawPointerEventType.RightButtonDown),
- (Curses.Event.Button2Released, RawPointerEventType.RightButtonUp),
- (Curses.Event.Button3Pressed, RawPointerEventType.MiddleButtonDown),
- (Curses.Event.Button3Clicked, RawPointerEventType.MiddleButtonDown),
- (Curses.Event.Button3Released, RawPointerEventType.MiddleButtonUp),
+ (Curses.Event.Button2Pressed, RawPointerEventType.MiddleButtonDown),
+ (Curses.Event.Button2Clicked, RawPointerEventType.MiddleButtonDown),
+ (Curses.Event.Button2Released, RawPointerEventType.MiddleButtonUp),
+ (Curses.Event.Button3Pressed, RawPointerEventType.RightButtonDown),
+ (Curses.Event.Button3Clicked, RawPointerEventType.RightButtonDown),
+ (Curses.Event.Button3Released, RawPointerEventType.RightButtonUp),
(Curses.Event.Button4Pressed, RawPointerEventType.XButton1Down),
(Curses.Event.Button4Clicked, RawPointerEventType.XButton1Down),
(Curses.Event.Button4Released, RawPointerEventType.XButton1Up),
@@ -116,6 +116,8 @@ public CursesConsole()
}
public override bool SupportsAltSolo => false;
+ public override bool SupportsMouse => true;
+ public override bool SupportsMouseMove => false;
private void StartEventLoop()
{
diff --git a/src/Consolonia.PlatformSupport/WindowsConsole.cs b/src/Consolonia.PlatformSupport/WindowsConsole.cs
index 596e37db..283756b1 100644
--- a/src/Consolonia.PlatformSupport/WindowsConsole.cs
+++ b/src/Consolonia.PlatformSupport/WindowsConsole.cs
@@ -62,6 +62,8 @@ public Win32Console()
}
public override bool SupportsAltSolo => true;
+ public override bool SupportsMouse => true;
+ public override bool SupportsMouseMove => true;
public override void PauseIO(Task task)
{
diff --git a/src/Consolonia.Themes/Templates/Controls/AllControls.axaml b/src/Consolonia.Themes/Templates/Controls/AllControls.axaml
index a7236e04..91f4ec93 100644
--- a/src/Consolonia.Themes/Templates/Controls/AllControls.axaml
+++ b/src/Consolonia.Themes/Templates/Controls/AllControls.axaml
@@ -4,6 +4,7 @@
+
diff --git a/src/Consolonia.Themes/Templates/Controls/Helpers/SelectTextWithPointerUpExtension.cs b/src/Consolonia.Themes/Templates/Controls/Helpers/SelectTextWithPointerUpExtension.cs
new file mode 100644
index 00000000..a3ae2634
--- /dev/null
+++ b/src/Consolonia.Themes/Templates/Controls/Helpers/SelectTextWithPointerUpExtension.cs
@@ -0,0 +1,60 @@
+using System;
+using Avalonia;
+using Avalonia.Controls;
+using Avalonia.Input;
+using Avalonia.Media;
+using Avalonia.Utilities;
+using Consolonia.Core.Helpers;
+using Consolonia.Core.Infrastructure;
+using Consolonia.Core.InternalHelpers;
+
+namespace Consolonia.Themes.Templates.Controls.Helpers
+{
+ internal static class SelectTextWithPointerUpExtension
+ {
+ public static readonly AttachedProperty SelectOnMouseLeftUpProperty =
+ AvaloniaProperty.RegisterAttached(CommonInternalHelper.GetStyledPropertyName(),
+ typeof(SelectTextWithPointerUpExtension));
+
+ static SelectTextWithPointerUpExtension()
+ {
+ var console = AvaloniaLocator.Current.GetService();
+ bool supportsMouse = console.SupportsMouse;
+ bool supportsMouseMove = console.SupportsMouseMove;
+ if (!supportsMouse || supportsMouseMove)
+ return;
+
+ SelectOnMouseLeftUpProperty.Changed.SubscribeAction(OnPropertyChanged);
+ }
+
+ private static void OnPropertyChanged(AvaloniaPropertyChangedEventArgs args)
+ {
+ if (args.Sender is not SelectableTextBlock selectableTextBlock) return;
+
+ selectableTextBlock.PointerReleased -= OnPointerReleased;
+
+ if (args.GetNewValue()) selectableTextBlock.PointerReleased += OnPointerReleased;
+ }
+
+ private static void OnPointerReleased(object sender, PointerReleasedEventArgs e)
+ {
+ // simplified copy of SelectableTextBlock.PointerMove
+ var tb = (SelectableTextBlock)sender;
+
+ if (e.InitialPressMouseButton != MouseButton.Left)
+ return;
+
+ Thickness padding = tb.Padding;
+
+ Point point = e.GetPosition(tb) - new Point(padding.Left, padding.Top);
+
+ point = new Point(
+ MathUtilities.Clamp(point.X, 0, Math.Max(tb.TextLayout.WidthIncludingTrailingWhitespace, 0)),
+ MathUtilities.Clamp(point.Y, 0, Math.Max(tb.TextLayout.Height, 0)));
+
+ TextHitTestResult hit = tb.TextLayout.HitTestPoint(point);
+ int textPosition = hit.TextPosition;
+ tb.SetCurrentValue(SelectableTextBlock.SelectionEndProperty, textPosition);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Consolonia.Themes/Templates/Controls/SelectableTextBlock.axaml b/src/Consolonia.Themes/Templates/Controls/SelectableTextBlock.axaml
new file mode 100644
index 00000000..492dd575
--- /dev/null
+++ b/src/Consolonia.Themes/Templates/Controls/SelectableTextBlock.axaml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
\ No newline at end of file