Skip to content

Commit

Permalink
Merge branch 'master' into vortice
Browse files Browse the repository at this point in the history
  • Loading branch information
jmacato committed May 6, 2024
2 parents f3b77e8 + 76f4e7a commit 14a5083
Show file tree
Hide file tree
Showing 30 changed files with 145 additions and 19 deletions.
5 changes: 3 additions & 2 deletions src/Avalonia.Controls/IToolTipService.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
using Avalonia.Metadata;
using Avalonia.Input;
using Avalonia.Metadata;

namespace Avalonia.Controls;

[Unstable, PrivateApi]
internal interface IToolTipService
{
void Update(Visual? candidateToolTipHost);
void Update(IInputRoot root, Visual? candidateToolTipHost);
}
2 changes: 1 addition & 1 deletion src/Avalonia.Controls/TextBox.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1650,7 +1650,7 @@ protected override void OnPointerMoved(PointerEventArgs e)
if (Math.Abs(caretIndex - previousIndex) == 1)
e.PreventGestureRecognition();

if (e.Pointer.Type == PointerType.Mouse)
if (e.Pointer.Type == PointerType.Mouse || _isDoubleTapped)
{
var selectionStart = SelectionStart;
var selectionEnd = SelectionEnd;
Expand Down
32 changes: 24 additions & 8 deletions src/Avalonia.Controls/ToolTipService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ internal sealed class ToolTipService : IToolTipService, IDisposable
private long _lastTipCloseTime;
private DispatcherTimer? _timer;
private ulong _lastTipEventTime;
private ulong _lastWindowEventTime;

public ToolTipService(IInputManager inputManager)
{
Expand All @@ -36,18 +37,23 @@ private void InputManager_OnProcess(RawInputEventArgs e)
{
if (e is RawPointerEventArgs pointerEvent)
{
bool isTooltipEvent = false;
if (_tipControl?.GetValue(ToolTip.ToolTipProperty) is { } currentTip && e.Root == currentTip.PopupHost)
{
isTooltipEvent = true;
_lastTipEventTime = pointerEvent.Timestamp;

var simultaneousTipEvent = _lastTipEventTime == pointerEvent.Timestamp;
}
else if (e.Root == _tipControl?.VisualRoot)
{
_lastWindowEventTime = pointerEvent.Timestamp;
}

switch (pointerEvent.Type)
{
// sometimes there is a null hit test as soon as the pointer enters a tooltip
case RawPointerEventType.Move when !(simultaneousTipEvent && pointerEvent.InputHitTestResult.element == null):
Update(pointerEvent.InputHitTestResult.element as Visual);
case RawPointerEventType.Move:
Update(pointerEvent.Root, pointerEvent.InputHitTestResult.element as Visual);
break;
case RawPointerEventType.LeaveWindow when e.Root == _tipControl?.VisualRoot && !simultaneousTipEvent:
case RawPointerEventType.LeaveWindow when (e.Root == _tipControl?.VisualRoot && _lastTipEventTime != e.Timestamp) || (isTooltipEvent && _lastWindowEventTime != e.Timestamp):
ClearTip();
_tipControl = null;
break;
Expand All @@ -68,10 +74,16 @@ void ClearTip()
}
}

public void Update(Visual? candidateToolTipHost)
public void Update(IInputRoot root, Visual? candidateToolTipHost)
{
var currentToolTip = _tipControl?.GetValue(ToolTip.ToolTipProperty);

if (root == currentToolTip?.VisualRoot)
{
// Don't update while the pointer is over a tooltip
return;
}

while (candidateToolTipHost != null)
{
if (candidateToolTipHost == currentToolTip) // when OverlayPopupHost is in use, the tooltip is in the same window as the host control
Expand Down Expand Up @@ -193,7 +205,11 @@ private void ToolTipPointerExited(object? sender, PointerEventArgs e)
private void StartShowTimer(int showDelay, Control control)
{
_timer = new DispatcherTimer { Interval = TimeSpan.FromMilliseconds(showDelay), Tag = (this, control) };
_timer.Tick += (o, e) => Open(control);
_timer.Tick += (o, e) =>
{
if (_timer != null)
Open(control);
};
_timer.Start();
}

Expand Down
4 changes: 2 additions & 2 deletions src/Avalonia.Controls/TopLevel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -896,12 +896,12 @@ private static void OnToolTipServiceEnabledChanged(AvaloniaPropertyChangedEventA

private void UpdateToolTip(Rect dirtyRect)
{
if (_tooltipService != null && _pointerOverPreProcessor?.LastPosition is { } lastPos)
if (_tooltipService != null && IsPointerOver && _pointerOverPreProcessor?.LastPosition is { } lastPos)
{
var clientPoint = this.PointToClient(lastPos);
if (dirtyRect.Contains(clientPoint))
{
_tooltipService.Update(HitTester.HitTestFirst(clientPoint, this, null));
_tooltipService.Update(this, HitTester.HitTestFirst(clientPoint, this, null));
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ namespace Avalonia.Generators.NameGenerator;

internal class InitializeComponentCodeGenerator : ICodeGenerator
{
private string _generatorName = typeof(InitializeComponentCodeGenerator).FullName;
private string _generatorVersion = typeof(InitializeComponentCodeGenerator).Assembly.GetName().Version.ToString();
private readonly bool _diagnosticsAreConnected;
private const string AttachDevToolsCodeBlock = @"
#if DEBUG
Expand All @@ -31,6 +33,7 @@ public string GenerateCode(string className, string nameSpace, IXamlType xamlTyp
var initializations = new List<string>();
const string thisFindNameScopeVariable = " var __thisNameScope__ = this.FindNameScope();";
bool hasNames = false;

foreach (var resolvedName in names)
{
if (!hasNames)
Expand All @@ -39,7 +42,12 @@ public string GenerateCode(string className, string nameSpace, IXamlType xamlTyp
}

var (typeName, name, fieldModifier) = resolvedName;
properties.Add($" {fieldModifier} {typeName} {name};");
var propertySource =
$"""
[global::System.CodeDom.Compiler.GeneratedCode("{_generatorName}", "{_generatorVersion}")]
{fieldModifier} {typeName} {name};
""";
properties.Add(propertySource);
initializations.Add($" {name} = __thisNameScope__?.Find<{typeName}>(\"{name}\");");

hasNames = true;
Expand All @@ -64,6 +72,8 @@ partial class {className}
/// </summary>
/// <param name=""loadXaml"">Should the XAML be loaded into the component.</param>
{(attachDevTools ? AttachDevToolsParameterDocumentation : string.Empty)}
[global::System.CodeDom.Compiler.GeneratedCode(""{_generatorName}"", ""{_generatorVersion}"")]
[global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
public void InitializeComponent(bool loadXaml = true{(attachDevTools ? ", bool attachDevTools = true" : string.Empty)})
{{
if (loadXaml)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,15 @@ namespace Avalonia.Generators.NameGenerator;

internal class OnlyPropertiesCodeGenerator : ICodeGenerator
{
private string _generatorName = typeof(OnlyPropertiesCodeGenerator).FullName;
private string _generatorVersion = typeof(OnlyPropertiesCodeGenerator).Assembly.GetName().Version.ToString();

public string GenerateCode(string className, string nameSpace, IXamlType xamlType, IEnumerable<ResolvedName> names)
{
var namedControls = names
.Select(info => " " +
$"[global::System.CodeDom.Compiler.GeneratedCode(\"{_generatorName}\", \"{_generatorVersion}\")]\n" +
" " +
$"{info.FieldModifier} {info.TypeName} {info.Name} => " +
$"this.FindNameScope()?.Find<{info.TypeName}>(\"{info.Name}\");")
.ToList();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,16 @@ namespace Sample.App
{
partial class SampleView
{
[global::System.CodeDom.Compiler.GeneratedCode("Avalonia.Generators.NameGenerator.InitializeComponentCodeGenerator", "$GeneratorVersion")]
internal global::Avalonia.Controls.TextBox UserNameTextBox;

/// <summary>
/// Wires up the controls and optionally loads XAML markup and attaches dev tools (if Avalonia.Diagnostics package is referenced).
/// </summary>
/// <param name="loadXaml">Should the XAML be loaded into the component.</param>

[global::System.CodeDom.Compiler.GeneratedCode("Avalonia.Generators.NameGenerator.InitializeComponentCodeGenerator", "$GeneratorVersion")]
[global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
public void InitializeComponent(bool loadXaml = true)
{
if (loadXaml)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ namespace Sample.App
{
partial class SampleView
{
[global::System.CodeDom.Compiler.GeneratedCode("Avalonia.Generators.NameGenerator.InitializeComponentCodeGenerator", "$GeneratorVersion")]
internal global::Avalonia.Controls.TextBox UserNameTextBox;

/// <summary>
Expand All @@ -16,6 +17,8 @@ namespace Sample.App
/// <param name="loadXaml">Should the XAML be loaded into the component.</param>
/// <param name="attachDevTools">Should the dev tools be attached.</param>

[global::System.CodeDom.Compiler.GeneratedCode("Avalonia.Generators.NameGenerator.InitializeComponentCodeGenerator", "$GeneratorVersion")]
[global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
public void InitializeComponent(bool loadXaml = true, bool attachDevTools = true)
{
if (loadXaml)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,16 @@ namespace Sample.App
{
partial class SampleView
{
[global::System.CodeDom.Compiler.GeneratedCode("Avalonia.Generators.NameGenerator.InitializeComponentCodeGenerator", "$GeneratorVersion")]
internal global::Avalonia.Controls.TextBox UserNameTextBox;

/// <summary>
/// Wires up the controls and optionally loads XAML markup and attaches dev tools (if Avalonia.Diagnostics package is referenced).
/// </summary>
/// <param name="loadXaml">Should the XAML be loaded into the component.</param>

[global::System.CodeDom.Compiler.GeneratedCode("Avalonia.Generators.NameGenerator.InitializeComponentCodeGenerator", "$GeneratorVersion")]
[global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
public void InitializeComponent(bool loadXaml = true)
{
if (loadXaml)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,20 @@ namespace Sample.App
{
partial class SampleView
{
[global::System.CodeDom.Compiler.GeneratedCode("Avalonia.Generators.NameGenerator.InitializeComponentCodeGenerator", "$GeneratorVersion")]
internal global::Avalonia.ReactiveUI.RoutedViewHost ClrNamespaceRoutedViewHost;
[global::System.CodeDom.Compiler.GeneratedCode("Avalonia.Generators.NameGenerator.InitializeComponentCodeGenerator", "$GeneratorVersion")]
internal global::Avalonia.ReactiveUI.RoutedViewHost UriRoutedViewHost;
[global::System.CodeDom.Compiler.GeneratedCode("Avalonia.Generators.NameGenerator.InitializeComponentCodeGenerator", "$GeneratorVersion")]
internal global::Controls.CustomTextBox UserNameTextBox;

/// <summary>
/// Wires up the controls and optionally loads XAML markup and attaches dev tools (if Avalonia.Diagnostics package is referenced).
/// </summary>
/// <param name="loadXaml">Should the XAML be loaded into the component.</param>

[global::System.CodeDom.Compiler.GeneratedCode("Avalonia.Generators.NameGenerator.InitializeComponentCodeGenerator", "$GeneratorVersion")]
[global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
public void InitializeComponent(bool loadXaml = true)
{
if (loadXaml)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,18 @@ namespace Sample.App
{
partial class SampleView
{
[global::System.CodeDom.Compiler.GeneratedCode("Avalonia.Generators.NameGenerator.InitializeComponentCodeGenerator", "$GeneratorVersion")]
internal global::Avalonia.Controls.TextBox UserNameTextBox;
[global::System.CodeDom.Compiler.GeneratedCode("Avalonia.Generators.NameGenerator.InitializeComponentCodeGenerator", "$GeneratorVersion")]
internal global::Avalonia.Controls.ListBox NamedListBox;

/// <summary>
/// Wires up the controls and optionally loads XAML markup and attaches dev tools (if Avalonia.Diagnostics package is referenced).
/// </summary>
/// <param name="loadXaml">Should the XAML be loaded into the component.</param>

[global::System.CodeDom.Compiler.GeneratedCode("Avalonia.Generators.NameGenerator.InitializeComponentCodeGenerator", "$GeneratorVersion")]
[global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
public void InitializeComponent(bool loadXaml = true)
{
if (loadXaml)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,26 @@ namespace Sample.App
{
partial class SampleView
{
[global::System.CodeDom.Compiler.GeneratedCode("Avalonia.Generators.NameGenerator.InitializeComponentCodeGenerator", "$GeneratorVersion")]
public global::Avalonia.Controls.TextBox FirstNameTextBox;
[global::System.CodeDom.Compiler.GeneratedCode("Avalonia.Generators.NameGenerator.InitializeComponentCodeGenerator", "$GeneratorVersion")]
public global::Avalonia.Controls.TextBox LastNameTextBox;
[global::System.CodeDom.Compiler.GeneratedCode("Avalonia.Generators.NameGenerator.InitializeComponentCodeGenerator", "$GeneratorVersion")]
protected global::Avalonia.Controls.TextBox PasswordTextBox;
[global::System.CodeDom.Compiler.GeneratedCode("Avalonia.Generators.NameGenerator.InitializeComponentCodeGenerator", "$GeneratorVersion")]
private global::Avalonia.Controls.TextBox ConfirmPasswordTextBox;
[global::System.CodeDom.Compiler.GeneratedCode("Avalonia.Generators.NameGenerator.InitializeComponentCodeGenerator", "$GeneratorVersion")]
internal global::Avalonia.Controls.Button SignUpButton;
[global::System.CodeDom.Compiler.GeneratedCode("Avalonia.Generators.NameGenerator.InitializeComponentCodeGenerator", "$GeneratorVersion")]
internal global::Avalonia.Controls.Button RegisterButton;

/// <summary>
/// Wires up the controls and optionally loads XAML markup and attaches dev tools (if Avalonia.Diagnostics package is referenced).
/// </summary>
/// <param name="loadXaml">Should the XAML be loaded into the component.</param>

[global::System.CodeDom.Compiler.GeneratedCode("Avalonia.Generators.NameGenerator.InitializeComponentCodeGenerator", "$GeneratorVersion")]
[global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
public void InitializeComponent(bool loadXaml = true)
{
if (loadXaml)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,16 @@ namespace Sample.App
{
partial class SampleView
{
[global::System.CodeDom.Compiler.GeneratedCode("Avalonia.Generators.NameGenerator.InitializeComponentCodeGenerator", "$GeneratorVersion")]
internal global::Avalonia.Controls.TextBox UserNameTextBox;

/// <summary>
/// Wires up the controls and optionally loads XAML markup and attaches dev tools (if Avalonia.Diagnostics package is referenced).
/// </summary>
/// <param name="loadXaml">Should the XAML be loaded into the component.</param>

[global::System.CodeDom.Compiler.GeneratedCode("Avalonia.Generators.NameGenerator.InitializeComponentCodeGenerator", "$GeneratorVersion")]
[global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
public void InitializeComponent(bool loadXaml = true)
{
if (loadXaml)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,20 @@ namespace Sample.App
{
partial class SampleView
{
[global::System.CodeDom.Compiler.GeneratedCode("Avalonia.Generators.NameGenerator.InitializeComponentCodeGenerator", "$GeneratorVersion")]
internal global::Avalonia.Controls.TextBox UserNameTextBox;
[global::System.CodeDom.Compiler.GeneratedCode("Avalonia.Generators.NameGenerator.InitializeComponentCodeGenerator", "$GeneratorVersion")]
internal global::Avalonia.Controls.TextBox PasswordTextBox;
[global::System.CodeDom.Compiler.GeneratedCode("Avalonia.Generators.NameGenerator.InitializeComponentCodeGenerator", "$GeneratorVersion")]
internal global::Avalonia.Controls.Button SignUpButton;

/// <summary>
/// Wires up the controls and optionally loads XAML markup and attaches dev tools (if Avalonia.Diagnostics package is referenced).
/// </summary>
/// <param name="loadXaml">Should the XAML be loaded into the component.</param>

[global::System.CodeDom.Compiler.GeneratedCode("Avalonia.Generators.NameGenerator.InitializeComponentCodeGenerator", "$GeneratorVersion")]
[global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
public void InitializeComponent(bool loadXaml = true)
{
if (loadXaml)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ namespace Sample.App
/// </summary>
/// <param name="loadXaml">Should the XAML be loaded into the component.</param>

[global::System.CodeDom.Compiler.GeneratedCode("Avalonia.Generators.NameGenerator.InitializeComponentCodeGenerator", "$GeneratorVersion")]
[global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
public void InitializeComponent(bool loadXaml = true)
{
if (loadXaml)
Expand Down
Loading

0 comments on commit 14a5083

Please sign in to comment.