Uno: Pointer handling inconsistency

Created on 15 May 2020  路  3Comments  路  Source: unoplatform/uno

Current behavior

This issue is very specific but affects the functionality of SplitButton control in Uno (#2885).

Suppose the following XAML:

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*" />
        <ColumnDefinition Width="*" />
    </Grid.ColumnDefinitions>
    <Button
    x:Name="LeftButton"
    Grid.Column="0"
    HorizontalAlignment="Stretch"
    VerticalAlignment="Stretch">
        Left Button
    </Button>
    <Button
    x:Name="RightButton"
    Grid.Column="1"
    HorizontalAlignment="Stretch"
    VerticalAlignment="Stretch">
        Right Button
    </Button>
</Grid>

Two stretched buttons in two grid columns.

The code-behind is as follows:

public sealed partial class MainPage : Page
{
    public MainPage()
    {
        this.InitializeComponent();

        AttachEvents(LeftButton);
        AttachEvents(RightButton);
    }

    private void AttachEvents(Button button)
    {
        button.Click += OnClick;
        button.PointerEntered += OnPointerEntered;
        button.PointerExited += OnPointerExited;
        button.PointerPressed += OnPointerPressed;
        button.PointerReleased += OnPointerReleased;
        button.PointerCanceled += OnPointerCanceled;
        button.PointerCaptureLost += OnPointerCaptureLost;
    }

    private void OnClick(object sender, RoutedEventArgs e)
    {
        System.Diagnostics.Debug.WriteLine(((Button)sender).Name + " was clicked");
    }

    private void OnPointerEntered(object sender, PointerRoutedEventArgs p)
    {
        System.Diagnostics.Debug.WriteLine("Entered");
        OnPointerEvent();
    }

    private void OnPointerExited(object sender, PointerRoutedEventArgs p)
    {
        System.Diagnostics.Debug.WriteLine("Exited");
        OnPointerEvent();
    }

    private void OnPointerMoved(object sender, PointerRoutedEventArgs p)
    {
        System.Diagnostics.Debug.WriteLine("Moved");
        OnPointerEvent();
    }

    private void OnPointerReleased(object sender, PointerRoutedEventArgs p)
    {
        System.Diagnostics.Debug.WriteLine("Released");
        OnPointerEvent();
    }

    private void OnPointerPressed(object sender, PointerRoutedEventArgs p)
    {
        System.Diagnostics.Debug.WriteLine("Pressed");
        OnPointerEvent();
    }

    private void OnPointerCanceled(object sender, PointerRoutedEventArgs p)
    {
        System.Diagnostics.Debug.WriteLine("Canceled");
        OnPointerEvent();
    }

    private void OnPointerCaptureLost(object sender, PointerRoutedEventArgs p)
    {
        System.Diagnostics.Debug.WriteLine("CaptureLost");
        OnPointerEvent();
    }

    private void OnPointerEvent()
    {            
        RightButton.SetValue(Grid.ColumnProperty, 0);
        RightButton.SetValue(Grid.ColumnSpanProperty, 2);
    }
}

On any pointer event, the right button is spanned to cover both columns of the grid. Observe that under Uno, for example on Android and iOS, when the left button area is tapped, Pointer Entered event is called (which makes the right button span), but after this left button's Click event is called.

Note this affects only touch. Mouse and pen will trigger pointer moved before user is able to click, so the button will already be spanned. So macOS is the only one safe here :-D .

Expected behavior

On UWP for tap, Pointer entered event is called, which makes the right button span and right button's Click event is called.

How to reproduce it (as minimally and precisely as possible)

See above.

Environment

Nuget Package: latest

Package Version(s): dev

Affected platform(s):

  • [x] iOS
  • [x] Android
  • [x] WebAssembly
  • [ ] WebAssembly renderers for Xamarin.Forms
  • [ ] macOS
  • [ ] Windows
  • [ ] Build tasks
  • [ ] Solution Templates

Visual Studio:

  • [ ] 2017 (version: )
  • [ ] 2019 (version: )
  • [ ] for Mac (version: )

Relevant plugins:

  • [ ] Resharper (version: )

Anything else we need to know?

kinbug platforandroid platforios platforwasm projecpointers

All 3 comments

@dr1rrb is this an existing issue ?

Hum I don't think that we already have a an issue for that.

I've tested that updating the template (visual states) while pointer is pressed would result in acceptable pointers events sequence, but moving elements over another element while pointer is pressed is kind of things I've classified as "stretch case" and didn't validated it.

Thinking about it, it's totally makes sense: When we press the pointer, the Button captures the pointer and it will then receive all pointer events until release. On UWP, they are probably validating that the element is not covered when the pointer is released ... but I'm not sure that we are able to validate that with uno yet (it would requires an API to get all elements at a given coordinate)

Was this page helpful?
0 / 5 - 0 ratings

Related issues

SuperJMN picture SuperJMN  路  3Comments

bricelam picture bricelam  路  3Comments

MatFillion picture MatFillion  路  4Comments

Ali-YousefiTelori picture Ali-YousefiTelori  路  4Comments

peternary picture peternary  路  3Comments