From 14d111c4de295c8c0468525378535cdbd5bd40c2 Mon Sep 17 00:00:00 2001 From: FelixSe Date: Thu, 19 Jul 2018 21:22:47 +0200 Subject: [PATCH] Added mouse settings for copy&paste --- .../Implementation/DefaultValueProvider.cs | 5 +- .../Settings/GeneralPageViewModel.cs | 2 +- .../Settings/MousePageViewModel.cs | 135 ++++++++++++++++++ .../SettingsViewModel.cs | 2 + .../TerminalViewModel.cs | 11 +- FluentTerminal.App/Assets/settingsicons.ttf | Bin 2292 -> 2444 bytes FluentTerminal.App/FluentTerminal.App.csproj | 7 + FluentTerminal.App/Views/SettingsPage.xaml | 8 ++ FluentTerminal.App/Views/SettingsPage.xaml.cs | 4 + .../Views/SettingsPages/MouseSettings.xaml | 74 ++++++++++ .../Views/SettingsPages/MouseSettings.xaml.cs | 24 ++++ FluentTerminal.App/Views/TerminalView.xaml.cs | 55 +++++-- FluentTerminal.Client/src/index.js | 8 +- FluentTerminal.Models/ApplicationSettings.cs | 3 + FluentTerminal.Models/Enums/MouseAction.cs | 9 ++ .../Enums/MouseButton.cs | 9 ++ .../FluentTerminal.RuntimeComponent.csproj | 1 + .../Interfaces/ITerminalEventListener.cs | 8 +- .../WebAllowedObjects/TerminalBridge.cs | 15 +- 19 files changed, 358 insertions(+), 22 deletions(-) create mode 100644 FluentTerminal.App.ViewModels/Settings/MousePageViewModel.cs create mode 100644 FluentTerminal.App/Views/SettingsPages/MouseSettings.xaml create mode 100644 FluentTerminal.App/Views/SettingsPages/MouseSettings.xaml.cs create mode 100644 FluentTerminal.Models/Enums/MouseAction.cs create mode 100644 FluentTerminal.RuntimeComponent/Enums/MouseButton.cs diff --git a/FluentTerminal.App.Services/Implementation/DefaultValueProvider.cs b/FluentTerminal.App.Services/Implementation/DefaultValueProvider.cs index 19adbdaa..f55e7d26 100644 --- a/FluentTerminal.App.Services/Implementation/DefaultValueProvider.cs +++ b/FluentTerminal.App.Services/Implementation/DefaultValueProvider.cs @@ -15,7 +15,10 @@ public ApplicationSettings GetDefaultApplicationSettings() ConfirmClosingWindows = false, UnderlineSelectedTab = false, NewTerminalLocation = NewTerminalLocation.Tab, - TabsPosition = TabsPosition.Top + TabsPosition = TabsPosition.Top, + CopyOnSelect = false, + MouseMiddleClickAction = MouseAction.None, + MouseRightClickAction = MouseAction.ContextMenu }; } diff --git a/FluentTerminal.App.ViewModels/Settings/GeneralPageViewModel.cs b/FluentTerminal.App.ViewModels/Settings/GeneralPageViewModel.cs index 4cde47c0..ce99239d 100644 --- a/FluentTerminal.App.ViewModels/Settings/GeneralPageViewModel.cs +++ b/FluentTerminal.App.ViewModels/Settings/GeneralPageViewModel.cs @@ -132,7 +132,7 @@ public bool BottomIsSelected private async Task RestoreDefaults() { - var result = await _dialogService.ShowMessageDialogAsnyc("Please confirm", "Are you sure you want to restore the general settings?", DialogButton.OK, DialogButton.Cancel).ConfigureAwait(false); + var result = await _dialogService.ShowMessageDialogAsnyc("Please confirm", "Are you sure you want to restore the general settings?", DialogButton.OK, DialogButton.Cancel).ConfigureAwait(true); if (result == DialogButton.OK) { diff --git a/FluentTerminal.App.ViewModels/Settings/MousePageViewModel.cs b/FluentTerminal.App.ViewModels/Settings/MousePageViewModel.cs new file mode 100644 index 00000000..f523d688 --- /dev/null +++ b/FluentTerminal.App.ViewModels/Settings/MousePageViewModel.cs @@ -0,0 +1,135 @@ +using FluentTerminal.App.Services; +using FluentTerminal.Models; +using FluentTerminal.Models.Enums; +using GalaSoft.MvvmLight; +using GalaSoft.MvvmLight.Command; +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading.Tasks; + +namespace FluentTerminal.App.ViewModels.Settings +{ + public class MousePageViewModel : ViewModelBase + { + private readonly ISettingsService _settingsService; + private readonly IDialogService _dialogService; + private readonly IDefaultValueProvider _defaultValueProvider; + private readonly ApplicationSettings _applicationSettings; + private bool _editingMouseRightClickAction; + private bool _editingMouseMiddleClickAction; + + public MousePageViewModel(ISettingsService settingsService, IDialogService dialogService, IDefaultValueProvider defaultValueProvider) + { + _settingsService = settingsService; + _dialogService = dialogService; + _defaultValueProvider = defaultValueProvider; + _applicationSettings = _settingsService.GetApplicationSettings(); + + RestoreDefaultsCommand = new RelayCommand(async () => await RestoreDefaults().ConfigureAwait(false)); + } + + public bool CopyOnSelect + { + get => _applicationSettings.CopyOnSelect; + set + { + if (_applicationSettings.CopyOnSelect != value) + { + _applicationSettings.CopyOnSelect = value; + _settingsService.SaveApplicationSettings(_applicationSettings); + RaisePropertyChanged(); + } + } + } + + public MouseAction MouseRightClickAction + { + get => _applicationSettings.MouseRightClickAction; + set + { + if (_applicationSettings.MouseRightClickAction != value && !_editingMouseRightClickAction) + { + _editingMouseRightClickAction = true; + _applicationSettings.MouseRightClickAction = value; + _settingsService.SaveApplicationSettings(_applicationSettings); + RaisePropertyChanged(); + RaisePropertyChanged(nameof(MouseRightClickNoneIsSelected)); + RaisePropertyChanged(nameof(MouseRightClickContextMenuIsSelected)); + RaisePropertyChanged(nameof(MouseRightClickPasteIsSelected)); + _editingMouseRightClickAction = false; + } + } + } + + public bool MouseRightClickNoneIsSelected + { + get => MouseRightClickAction == MouseAction.None; + set => MouseRightClickAction = MouseAction.None; + } + + public bool MouseRightClickContextMenuIsSelected + { + get => MouseRightClickAction == MouseAction.ContextMenu; + set => MouseRightClickAction = MouseAction.ContextMenu; + } + + public bool MouseRightClickPasteIsSelected + { + get => MouseRightClickAction == MouseAction.Paste; + set => MouseRightClickAction = MouseAction.Paste; + } + + public MouseAction MouseMiddleClickAction + { + get => _applicationSettings.MouseMiddleClickAction; + set + { + if (_applicationSettings.MouseMiddleClickAction != value && !_editingMouseMiddleClickAction) + { + _editingMouseMiddleClickAction = true; + _applicationSettings.MouseMiddleClickAction = value; + _settingsService.SaveApplicationSettings(_applicationSettings); + RaisePropertyChanged(); + RaisePropertyChanged(nameof(MouseMiddleClickNoneIsSelected)); + RaisePropertyChanged(nameof(MouseMiddleClickContextMenuIsSelected)); + RaisePropertyChanged(nameof(MouseMiddleClickPasteIsSelected)); + _editingMouseMiddleClickAction = false; + } + } + } + + public bool MouseMiddleClickNoneIsSelected + { + get => MouseMiddleClickAction == MouseAction.None; + set => MouseMiddleClickAction = MouseAction.None; + } + + public bool MouseMiddleClickContextMenuIsSelected + { + get => MouseMiddleClickAction == MouseAction.ContextMenu; + set => MouseMiddleClickAction = MouseAction.ContextMenu; + } + + public bool MouseMiddleClickPasteIsSelected + { + get => MouseMiddleClickAction == MouseAction.Paste; + set => MouseMiddleClickAction = MouseAction.Paste; + } + + public RelayCommand RestoreDefaultsCommand { get; } + + private async Task RestoreDefaults() + { + var result = await _dialogService.ShowMessageDialogAsnyc("Please confirm", "Are you sure you want to restore the mouse settings?", DialogButton.OK, DialogButton.Cancel).ConfigureAwait(true); + + if (result == DialogButton.OK) + { + var defaults = _defaultValueProvider.GetDefaultApplicationSettings(); + CopyOnSelect = defaults.CopyOnSelect; + MouseMiddleClickAction = defaults.MouseMiddleClickAction; + MouseRightClickAction = defaults.MouseRightClickAction; + } + } + } +} diff --git a/FluentTerminal.App.ViewModels/SettingsViewModel.cs b/FluentTerminal.App.ViewModels/SettingsViewModel.cs index 5120ca51..80f6754d 100644 --- a/FluentTerminal.App.ViewModels/SettingsViewModel.cs +++ b/FluentTerminal.App.ViewModels/SettingsViewModel.cs @@ -15,6 +15,7 @@ public SettingsViewModel(ISettingsService settingsService, IDefaultValueProvider Shell = new ProfilesPageViewModel(settingsService, dialogService, defaultValueProvider, fileSystemService); Terminal = new TerminalPageViewModel(settingsService, dialogService, defaultValueProvider, systemFontService); Themes = new ThemesPageViewModel(settingsService, dialogService, defaultValueProvider, themeParserFactory, fileSystemService); + Mouse = new MousePageViewModel(settingsService, dialogService, defaultValueProvider); } public event EventHandler Closed; @@ -24,6 +25,7 @@ public SettingsViewModel(ISettingsService settingsService, IDefaultValueProvider public ProfilesPageViewModel Shell { get; } public TerminalPageViewModel Terminal { get; } public ThemesPageViewModel Themes { get; } + public MousePageViewModel Mouse { get; } public void Close() { diff --git a/FluentTerminal.App.ViewModels/TerminalViewModel.cs b/FluentTerminal.App.ViewModels/TerminalViewModel.cs index 809a8c03..5642337e 100644 --- a/FluentTerminal.App.ViewModels/TerminalViewModel.cs +++ b/FluentTerminal.App.ViewModels/TerminalViewModel.cs @@ -24,7 +24,6 @@ public class TerminalViewModel : ViewModelBase private readonly ShellProfile _shellProfile; private readonly string _startupDirectory; private readonly ITrayProcessCommunicationService _trayProcessCommunicationService; - private ApplicationSettings _applicationSettings; private bool _isSelected; private string _resizeOverlayContent; private string _searchText; @@ -54,7 +53,7 @@ public TerminalViewModel(ISettingsService settingsService, ITrayProcessCommunica _dialogService = dialogService; _keyboardCommandService = keyboardCommandService; - _applicationSettings = applicationSettings; + ApplicationSettings = applicationSettings; _startupDirectory = startupDirectory; _shellProfile = shellProfile; _applicationView = applicationView; @@ -70,6 +69,8 @@ public TerminalViewModel(ISettingsService settingsService, ITrayProcessCommunica CloseSearchPanelCommand = new RelayCommand(CloseSearchPanel); } + public ApplicationSettings ApplicationSettings { get; private set; } + public event EventHandler Closed; public RelayCommand CloseCommand { get; } @@ -100,7 +101,7 @@ public bool IsSelected } } - public bool IsUnderlined => IsSelected && _applicationSettings.UnderlineSelectedTab; + public bool IsUnderlined => IsSelected && ApplicationSettings.UnderlineSelectedTab; public string ResizeOverlayContent { @@ -241,7 +242,7 @@ private async void OnApplicationSettingsChanged(object sender, ApplicationSettin { await _applicationView.RunOnDispatcherThread(() => { - _applicationSettings = e; + ApplicationSettings = e; RaisePropertyChanged(nameof(IsUnderlined)); }); } @@ -333,7 +334,7 @@ private void OnTerminalTitleChanged(object sender, string e) private async Task TryClose() { - if (_applicationSettings.ConfirmClosingTabs) + if (ApplicationSettings.ConfirmClosingTabs) { var result = await _dialogService.ShowMessageDialogAsnyc("Please confirm", "Are you sure you want to close this tab?", DialogButton.OK, DialogButton.Cancel).ConfigureAwait(true); diff --git a/FluentTerminal.App/Assets/settingsicons.ttf b/FluentTerminal.App/Assets/settingsicons.ttf index a71f8f4c54b7fac1a6adb8f1baa8aabe85e8900b..a98c6204795ed7eb305ebbb94ae22bac06da7feb 100644 GIT binary patch delta 577 zcmX|-&ubGw6vyA&-OTJJ`y)--q-xY^ZFa4RO)Ksi5KkJVAg%ZV5v43?+#rn!Y}HD^ zR1^Men_0U6(9zEzqA@S9Khc`2y?|0tJeCOxDlVlSR01Q|G z8D>kR3ul+dTUh|DL2Bmo$x|ipfDz9UkIbB(n40->bqxS76JILV{D%Hr3y3$UrUO50 z^m=p>XlKY*gN3`--!4BY0>}lbPPO9C$79Yp^0uhlYPHhzm4XzZ=0Oq;RBMY%ECC;g zUlV5*>SbTKC*PpvVd7NHUuwV=m?r-i@yJcTR(bqR5&%3-+Ge93E`Hql^o8#3kRSXD zM*&~FxznDrj{ky~L^8nF+u?eD&h!@&V3!0H`aYcnAfecaqZkz@@R}B2r`LhQ*cC6) z#!zfv9s}_kAD|}gOREWL&cQSIhB<8E8vX!i=j4lWQ-Tl}NnJ>T12C52j59ksfmzS> zY#R2Wn@**<>$!H;&ThMeDGys#dbluUAJpBbVeX#frllQm>@jQJVoZq`reU#&%yiRu z>Nw7TnM{noAKkxiXfDCEcv&AzI!6`LGPS0IIMJ1tG(j7}*@`NCVmv zyRN{{uz_w^Sl_UAkA^$^qd&7J08O)=T1=S9$`?Jxy1)^PnW<#4$d#a7GuL7(8_|Z? zWmt*$K(H)ORwoJ82RB&<~8!hofI%BCtn02Xub7gJO6o<+(Cp%cz zCCp3`GYB&8VeMWu6On9Q>;sl<_U@Bwsr1)+c#M08n9u($#|!3mk9+5<`#xb4Yy*#E zjF)d$`5{1WY-lKRuEpnFI;oj-IY4uIlwOOkXs0)ML9GN?ATLGbH|@zCaVkSXwRv!a zC-Tq%UFChsq>`_(I>_orC%ovAKFy>0JH1_UK|8bS+=?JbkU}a|kcF(WUT>2Dy|Gne VqB1WJQu-Ve`p+Lq_y5$!_%GSmS$+Tj diff --git a/FluentTerminal.App/FluentTerminal.App.csproj b/FluentTerminal.App/FluentTerminal.App.csproj index 7c455ff0..6ff5741a 100644 --- a/FluentTerminal.App/FluentTerminal.App.csproj +++ b/FluentTerminal.App/FluentTerminal.App.csproj @@ -143,6 +143,9 @@ SettingsPage.xaml + + MouseSettings.xaml + ThemeSettings.xaml @@ -284,6 +287,10 @@ Designer MSBuild:Compile + + Designer + MSBuild:Compile + Designer MSBuild:Compile diff --git a/FluentTerminal.App/Views/SettingsPage.xaml b/FluentTerminal.App/Views/SettingsPage.xaml index 9f3a525c..25656363 100644 --- a/FluentTerminal.App/Views/SettingsPage.xaml +++ b/FluentTerminal.App/Views/SettingsPage.xaml @@ -57,6 +57,14 @@ ToolTipService.ToolTip="Keybindings" /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/FluentTerminal.App/Views/SettingsPages/MouseSettings.xaml.cs b/FluentTerminal.App/Views/SettingsPages/MouseSettings.xaml.cs new file mode 100644 index 00000000..9900e17a --- /dev/null +++ b/FluentTerminal.App/Views/SettingsPages/MouseSettings.xaml.cs @@ -0,0 +1,24 @@ +using FluentTerminal.App.ViewModels.Settings; +using Windows.UI.Xaml.Controls; +using Windows.UI.Xaml.Navigation; + +namespace FluentTerminal.App.Views.SettingsPages +{ + public sealed partial class MouseSettings : Page + { + public MouseSettings() + { + this.InitializeComponent(); + } + + public MousePageViewModel ViewModel { get; private set; } + + protected override void OnNavigatedTo(NavigationEventArgs e) + { + if (e.Parameter is MousePageViewModel viewModel) + { + ViewModel = viewModel; + } + } + } +} diff --git a/FluentTerminal.App/Views/TerminalView.xaml.cs b/FluentTerminal.App/Views/TerminalView.xaml.cs index 074e32e2..1eb82e1f 100644 --- a/FluentTerminal.App/Views/TerminalView.xaml.cs +++ b/FluentTerminal.App/Views/TerminalView.xaml.cs @@ -2,6 +2,7 @@ using FluentTerminal.App.ViewModels; using FluentTerminal.Models; using FluentTerminal.Models.Enums; +using FluentTerminal.RuntimeComponent.Enums; using FluentTerminal.RuntimeComponent.Interfaces; using FluentTerminal.RuntimeComponent.WebAllowedObjects; using Newtonsoft.Json; @@ -209,16 +210,6 @@ private async void OnLoaded(object sender, RoutedEventArgs e) await ViewModel.OnViewIsReady(this).ConfigureAwait(true); } - public void OnRightClick(int x, int y, bool hasSelection) - { - _dispatcherJobs.Add(() => - { - var flyout = (MenuFlyout)_webView.ContextFlyout; - _copyMenuItem.IsEnabled = hasSelection; - flyout.ShowAt(_webView, new Point(x, y)); - }); - } - private void Paste_Click(object sender, RoutedEventArgs e) { OnKeyboardCommand(nameof(Command.Paste)); @@ -260,5 +251,49 @@ public void FocusSearchTextBox() { SearchTextBox.Focus(FocusState.Programmatic); } + + public void OnMouseClick(MouseButton mouseButton, int x, int y, bool hasSelection) + { + _dispatcherJobs.Add(() => + { + if (mouseButton == MouseButton.Middle) + { + if (ViewModel.ApplicationSettings.MouseMiddleClickAction == MouseAction.ContextMenu) + { + ShowContextMenu(x, y, hasSelection); + } + else if (ViewModel.ApplicationSettings.MouseMiddleClickAction == MouseAction.Paste) + { + OnKeyboardCommand(nameof(Command.Paste)); + } + } + else if (mouseButton == MouseButton.Right) + { + if (ViewModel.ApplicationSettings.MouseRightClickAction == MouseAction.ContextMenu) + { + ShowContextMenu(x, y, hasSelection); + } + else if (ViewModel.ApplicationSettings.MouseRightClickAction == MouseAction.Paste) + { + OnKeyboardCommand(nameof(Command.Paste)); + } + } + }); + } + + public void OnSelectionChanged(string selection) + { + if (ViewModel.ApplicationSettings.CopyOnSelect) + { + _dispatcherJobs.Add(() => OnKeyboardCommand(nameof(Command.Copy))); + } + } + + private void ShowContextMenu(int x, int y, bool terminalHasSelection) + { + var flyout = (MenuFlyout)_webView.ContextFlyout; + _copyMenuItem.IsEnabled = terminalHasSelection; + flyout.ShowAt(_webView, new Point(x, y)); + } } } \ No newline at end of file diff --git a/FluentTerminal.Client/src/index.js b/FluentTerminal.Client/src/index.js index e9b38563..cdc045d0 100644 --- a/FluentTerminal.Client/src/index.js +++ b/FluentTerminal.Client/src/index.js @@ -50,6 +50,10 @@ function createTerminal(options, theme, keyBindings) { terminalBridge.notifyTitleChanged(title); }); + term.on('selection', function () { + terminalBridge.notifySelectionChanged(term.getSelection()); + }); + term.open(terminalContainer); term.winptyCompatInit(); term.fit(); @@ -62,7 +66,9 @@ function createTerminal(options, theme, keyBindings) { } window.onmouseup = function (e) { - if (e.button == 2) { + if (e.button == 1) { + terminalBridge.notifyMiddleClick(e.clientX, e.clientY, term.hasSelection()); + } else if (e.button == 2) { terminalBridge.notifyRightClick(e.clientX, e.clientY, term.hasSelection()); } } diff --git a/FluentTerminal.Models/ApplicationSettings.cs b/FluentTerminal.Models/ApplicationSettings.cs index 05be01b8..0f43f216 100644 --- a/FluentTerminal.Models/ApplicationSettings.cs +++ b/FluentTerminal.Models/ApplicationSettings.cs @@ -9,5 +9,8 @@ public class ApplicationSettings public bool UnderlineSelectedTab { get; set; } public NewTerminalLocation NewTerminalLocation { get; set; } public TabsPosition TabsPosition { get; set; } + public bool CopyOnSelect { get; set; } + public MouseAction MouseMiddleClickAction { get; set; } + public MouseAction MouseRightClickAction { get; set; } } } \ No newline at end of file diff --git a/FluentTerminal.Models/Enums/MouseAction.cs b/FluentTerminal.Models/Enums/MouseAction.cs new file mode 100644 index 00000000..74abf242 --- /dev/null +++ b/FluentTerminal.Models/Enums/MouseAction.cs @@ -0,0 +1,9 @@ +namespace FluentTerminal.Models.Enums +{ + public enum MouseAction + { + None, + ContextMenu, + Paste + } +} \ No newline at end of file diff --git a/FluentTerminal.RuntimeComponent/Enums/MouseButton.cs b/FluentTerminal.RuntimeComponent/Enums/MouseButton.cs new file mode 100644 index 00000000..7f403c52 --- /dev/null +++ b/FluentTerminal.RuntimeComponent/Enums/MouseButton.cs @@ -0,0 +1,9 @@ +namespace FluentTerminal.RuntimeComponent.Enums +{ + public enum MouseButton + { + Left, + Middle, + Right + } +} \ No newline at end of file diff --git a/FluentTerminal.RuntimeComponent/FluentTerminal.RuntimeComponent.csproj b/FluentTerminal.RuntimeComponent/FluentTerminal.RuntimeComponent.csproj index eff576ca..52709ebe 100644 --- a/FluentTerminal.RuntimeComponent/FluentTerminal.RuntimeComponent.csproj +++ b/FluentTerminal.RuntimeComponent/FluentTerminal.RuntimeComponent.csproj @@ -107,6 +107,7 @@ PackageReference + diff --git a/FluentTerminal.RuntimeComponent/Interfaces/ITerminalEventListener.cs b/FluentTerminal.RuntimeComponent/Interfaces/ITerminalEventListener.cs index 66ea09d3..132198b2 100644 --- a/FluentTerminal.RuntimeComponent/Interfaces/ITerminalEventListener.cs +++ b/FluentTerminal.RuntimeComponent/Interfaces/ITerminalEventListener.cs @@ -1,4 +1,6 @@ -namespace FluentTerminal.RuntimeComponent.Interfaces +using FluentTerminal.RuntimeComponent.Enums; + +namespace FluentTerminal.RuntimeComponent.Interfaces { public interface ITerminalEventListener { @@ -8,6 +10,8 @@ public interface ITerminalEventListener void OnKeyboardCommand(string command); - void OnRightClick(int x, int y, bool hasSelection); + void OnMouseClick(MouseButton mouseButton, int x, int y, bool hasSelection); + + void OnSelectionChanged(string selection); } } \ No newline at end of file diff --git a/FluentTerminal.RuntimeComponent/WebAllowedObjects/TerminalBridge.cs b/FluentTerminal.RuntimeComponent/WebAllowedObjects/TerminalBridge.cs index bce31a73..4b8a1725 100644 --- a/FluentTerminal.RuntimeComponent/WebAllowedObjects/TerminalBridge.cs +++ b/FluentTerminal.RuntimeComponent/WebAllowedObjects/TerminalBridge.cs @@ -1,4 +1,5 @@ -using FluentTerminal.RuntimeComponent.Interfaces; +using FluentTerminal.RuntimeComponent.Enums; +using FluentTerminal.RuntimeComponent.Interfaces; using Windows.Foundation.Metadata; namespace FluentTerminal.RuntimeComponent.WebAllowedObjects @@ -30,7 +31,17 @@ public void InvokeCommand(string command) public void NotifyRightClick(int x, int y, bool hasSelection) { - _terminalEventListener.OnRightClick(x, y, hasSelection); + _terminalEventListener.OnMouseClick(MouseButton.Right, x, y, hasSelection); + } + + public void NotifyMiddleClick(int x, int y, bool hasSelection) + { + _terminalEventListener.OnMouseClick(MouseButton.Middle, x, y, hasSelection); + } + + public void NotifySelectionChanged(string selection) + { + _terminalEventListener.OnSelectionChanged(selection); } } } \ No newline at end of file