Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

UI Infrastructure: Event Bubbling #164

Closed
bryphe opened this issue Dec 27, 2018 · 2 comments · Fixed by #173
Closed

UI Infrastructure: Event Bubbling #164

bryphe opened this issue Dec 27, 2018 · 2 comments · Fixed by #173
Labels
help wanted Extra attention is needed

Comments

@bryphe
Copy link
Member

bryphe commented Dec 27, 2018

At the current time, we have a very simple event model for handling mouse events.

That logic is in https://github.com/revery-ui/revery/blob/master/src/UI/Mouse.re , specifically here:

    let isNodeImpacted = n => n#hitTest(pos);
    let nodes: ref(list(Node.node('a))) = ref([]);
    let collect = n =>
      if (isNodeImpacted(n)) {
        nodes := List.append(nodes^, [n]);
      };
    Node.iter(collect, node);
    List.iter(n => n#handleEvent(eventToSend), nodes^);

This is very simple - we check for all the nodes that pass the 'hit-test', and dispatch the event to all of them.

However, this is unexpected behavior and not intuitive if you're coming from web programming - as webdevs, we'd expect the event to dispatch to the top-most element, and bubble up from there!

We need to implement this event-bubbling behavior in revery. This will be useful not just for the initial mouse events, but for all sorts of other events - like keyboard input, etc.

Proposal

We add a UiEvents module that has a method bubble = (node, event). The bubble would do a few things:

  • It would wrap the event with some extra methods, like stopPropagation or preventDefault - like we'd expect in Web events.
  • It would keep some internal state of whether propagation was stopped or default was prevented (ie, via refs).
  • It would call handleEvent for each node in the hierarchy. If stopPropagation is called, it should discontinue the traversal up the hierarchy.

Testability

We should be able to craft unit tests that exercise this with some simple Node objects that have handlers that call stopPropagation, along with counters that validate whether the events were hit.

Application

We can hook this up to the mouse event bubbling behavior today, by picking out the top-most node that passes the hit-test. We need to make sure our z-index tracking is working correctly for this.

@bryphe bryphe added the help wanted Extra attention is needed label Dec 27, 2018
@akinsho
Copy link
Member

akinsho commented Dec 29, 2018

Gonna give this a go, but might reach out for help at some point 👍

@bryphe
Copy link
Member Author

bryphe commented Dec 29, 2018

Sweet, thanks @Akin909 ! Let me know if you have questions 😄

One suggestion: I find a good starting point for these is sketching out some tests - helps me figure out how to make some of the abstract concepts more concrete and actionable, and start to think about how the pieces fit together.

We have a few tests here that exercise events already: https://github.com/revery-ui/revery/blob/master/test/UI/MouseTest.re

So I could see expanding on them - like tests that:

  • dispatches a MouseDown event on a child element, and verify the handler for both child and parent get called
  • dispatches a MouseDown event on a child element, calls stopPropagation, and verifies the handler for the parent does not get called.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
help wanted Extra attention is needed
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants