From 3f03c6016b8860c2616776ad59d2fd1de16f7ac0 Mon Sep 17 00:00:00 2001 From: Youssef1313 Date: Sat, 14 Aug 2021 01:31:02 +0200 Subject: [PATCH 1/2] feat: Support PasswordBox on Skia --- .../UI/Xaml/Controls/TextBoxViewExtension.cs | 36 +++++++++++++++---- .../UI/Xaml/Controls/TextBoxViewExtension.cs | 4 +++ .../Controls/PasswordBox/PasswordBox.skia.cs | 14 ++++++++ .../TextBox/ITextBoxExtension.skia.cs | 4 ++- .../UI/Xaml/Controls/TextBox/TextBox.skia.cs | 2 ++ .../Xaml/Controls/TextBox/TextBoxView.skia.cs | 4 ++- 6 files changed, 55 insertions(+), 9 deletions(-) create mode 100644 src/Uno.UI/UI/Xaml/Controls/PasswordBox/PasswordBox.skia.cs diff --git a/src/Uno.UI.Runtime.Skia.Gtk/UI/Xaml/Controls/TextBoxViewExtension.cs b/src/Uno.UI.Runtime.Skia.Gtk/UI/Xaml/Controls/TextBoxViewExtension.cs index 52e3e6105c2b..04538de70af0 100644 --- a/src/Uno.UI.Runtime.Skia.Gtk/UI/Xaml/Controls/TextBoxViewExtension.cs +++ b/src/Uno.UI.Runtime.Skia.Gtk/UI/Xaml/Controls/TextBoxViewExtension.cs @@ -13,6 +13,7 @@ using Object = GLib.Object; using Point = Windows.Foundation.Point; using Scale = Pango.Scale; +using System.Diagnostics; namespace Uno.UI.Runtime.Skia.GTK.Extensions.UI.Xaml.Controls { @@ -38,7 +39,7 @@ public TextBoxViewExtension(TextBoxView owner, GtkWindow window) private Fixed GetWindowTextInputLayer() { // now we have the GtkEventBox - var overlay = (Overlay)((EventBox) _window.Child).Child; + var overlay = (Overlay)((EventBox)_window.Child).Child; return overlay.Children.OfType().First(); } @@ -53,7 +54,7 @@ public void StartEntry() _contentElement = textBox.ContentElement; - EnsureWidgetForAcceptsReturn(textBox.AcceptsReturn); + EnsureWidgetForAcceptsReturn(textBox.AcceptsReturn, isPassword: textBox is PasswordBox); var textInputLayer = GetWindowTextInputLayer(); textInputLayer.Put(_currentInputWidget!, 0, 0); @@ -107,7 +108,7 @@ public void UpdateNativeView() return; } - EnsureWidgetForAcceptsReturn(textBox.AcceptsReturn); + EnsureWidgetForAcceptsReturn(textBox.AcceptsReturn, isPassword: textBox is PasswordBox); var fontDescription = new FontDescription { @@ -170,24 +171,29 @@ private void UpdateEntryProperties(Entry entry, TextBox textBox) { entry.IsEditable = !textBox.IsReadOnly; entry.MaxLength = textBox.MaxLength; - } - private void EnsureWidgetForAcceptsReturn(bool acceptsReturn) + private void EnsureWidgetForAcceptsReturn(bool acceptsReturn, bool isPassword) { + // On UWP, A PasswordBox doesn't have AcceptsReturn property. + // The property exists on Uno because PasswordBox incorrectly inherits TextBox. + // If we have PasswordBox, ignore AcceptsReturnValue and always use Gtk.Entry + acceptsReturn = acceptsReturn && !isPassword; + var isIncompatibleInputType = (acceptsReturn && !(_currentInputWidget is TextView)) || (!acceptsReturn && !(_currentInputWidget is Entry)); if (isIncompatibleInputType) { var inputText = GetInputText(); - _currentInputWidget = CreateInputWidget(acceptsReturn); + _currentInputWidget = CreateInputWidget(acceptsReturn, isPassword); SetWidgetText(inputText ?? string.Empty); } } - private Widget CreateInputWidget(bool acceptsReturn) + private Widget CreateInputWidget(bool acceptsReturn, bool isPassword) { + Debug.Assert(!acceptsReturn || !isPassword); Widget widget; if (acceptsReturn) { @@ -199,6 +205,12 @@ private Widget CreateInputWidget(bool acceptsReturn) else { var entry = new Entry(); + if (isPassword) + { + entry.InputPurpose = InputPurpose.Password; + entry.Visibility = false; + } + entry.Changed += WidgetTextChanged; _textChangedDisposable.Disposable = Disposable.Create(() => entry.Changed -= WidgetTextChanged); widget = entry; @@ -261,5 +273,15 @@ private void ContentElementSizeChanged(object sender, Windows.UI.Xaml.SizeChange UpdateSize(); UpdatePosition(); } + + public void SetIsPassword(bool isPassword) + { + if (_currentInputWidget is Entry entry) + { + entry.Visibility = !isPassword; + // InputPurpose doesn't have any visual effects. + entry.InputPurpose = InputPurpose.Password; + } + } } } diff --git a/src/Uno.UI.Runtime.Skia.Wpf/Extensions/UI/Xaml/Controls/TextBoxViewExtension.cs b/src/Uno.UI.Runtime.Skia.Wpf/Extensions/UI/Xaml/Controls/TextBoxViewExtension.cs index 7cf57e6d8f10..2e867e729716 100644 --- a/src/Uno.UI.Runtime.Skia.Wpf/Extensions/UI/Xaml/Controls/TextBoxViewExtension.cs +++ b/src/Uno.UI.Runtime.Skia.Wpf/Extensions/UI/Xaml/Controls/TextBoxViewExtension.cs @@ -183,5 +183,9 @@ private void ContentElementSizeChanged(object sender, Windows.UI.Xaml.SizeChange UpdatePosition(); } + public void SetIsPassword(bool isPassword) + { + // No support for now. + } } } diff --git a/src/Uno.UI/UI/Xaml/Controls/PasswordBox/PasswordBox.skia.cs b/src/Uno.UI/UI/Xaml/Controls/PasswordBox/PasswordBox.skia.cs new file mode 100644 index 000000000000..80a169f4da6d --- /dev/null +++ b/src/Uno.UI/UI/Xaml/Controls/PasswordBox/PasswordBox.skia.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Windows.UI.Xaml.Controls +{ + public partial class PasswordBox + { + partial void SetPasswordScope(bool shouldHideText) + { + SetIsPassword(shouldHideText); + } + } +} diff --git a/src/Uno.UI/UI/Xaml/Controls/TextBox/ITextBoxExtension.skia.cs b/src/Uno.UI/UI/Xaml/Controls/TextBox/ITextBoxExtension.skia.cs index 825e222dea73..a7bdb11bf971 100644 --- a/src/Uno.UI/UI/Xaml/Controls/TextBox/ITextBoxExtension.skia.cs +++ b/src/Uno.UI/UI/Xaml/Controls/TextBox/ITextBoxExtension.skia.cs @@ -15,5 +15,7 @@ internal interface ITextBoxViewExtension void UpdatePosition(); void SetTextNative(string text); - } + + void SetIsPassword(bool isPassword); + } } diff --git a/src/Uno.UI/UI/Xaml/Controls/TextBox/TextBox.skia.cs b/src/Uno.UI/UI/Xaml/Controls/TextBox/TextBox.skia.cs index 618768238db4..ad76ca0157f3 100644 --- a/src/Uno.UI/UI/Xaml/Controls/TextBox/TextBox.skia.cs +++ b/src/Uno.UI/UI/Xaml/Controls/TextBox/TextBox.skia.cs @@ -22,5 +22,7 @@ private void UpdateTextBoxView() } partial void OnFocusStateChangedPartial(FocusState focusState) => _textBoxView?.OnFocusStateChanged(focusState); + + protected void SetIsPassword(bool isPassword) => _textBoxView?.SetIsPassword(isPassword); } } diff --git a/src/Uno.UI/UI/Xaml/Controls/TextBox/TextBoxView.skia.cs b/src/Uno.UI/UI/Xaml/Controls/TextBox/TextBoxView.skia.cs index 27d11d05db8d..fe641aeb06f0 100644 --- a/src/Uno.UI/UI/Xaml/Controls/TextBox/TextBoxView.skia.cs +++ b/src/Uno.UI/UI/Xaml/Controls/TextBox/TextBoxView.skia.cs @@ -45,7 +45,7 @@ public TextBox? TextBox internal void SetTextNative(string text) { - DisplayBlock.Text = text; + DisplayBlock.Text = new string('•', text.Length); _textBoxExtension?.SetTextNative(text); } @@ -65,6 +65,8 @@ internal void OnFocusStateChanged(FocusState focusState) } } + internal void SetIsPassword(bool isPassword) => _textBoxExtension?.SetIsPassword(isPassword); + internal void UpdateTextFromNative(string newText) { var textBox = _textBox?.GetTarget(); From 1303438498f420ed082c2e1801332f1e40c16f51 Mon Sep 17 00:00:00 2001 From: Youssef Victor Date: Mon, 16 Aug 2021 16:23:06 +0200 Subject: [PATCH 2/2] chore: Address feedback (remove redundant assignment) --- .../UI/Xaml/Controls/TextBoxViewExtension.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Uno.UI.Runtime.Skia.Gtk/UI/Xaml/Controls/TextBoxViewExtension.cs b/src/Uno.UI.Runtime.Skia.Gtk/UI/Xaml/Controls/TextBoxViewExtension.cs index 04538de70af0..211fa6779fcc 100644 --- a/src/Uno.UI.Runtime.Skia.Gtk/UI/Xaml/Controls/TextBoxViewExtension.cs +++ b/src/Uno.UI.Runtime.Skia.Gtk/UI/Xaml/Controls/TextBoxViewExtension.cs @@ -279,8 +279,6 @@ public void SetIsPassword(bool isPassword) if (_currentInputWidget is Entry entry) { entry.Visibility = !isPassword; - // InputPurpose doesn't have any visual effects. - entry.InputPurpose = InputPurpose.Password; } } }