On 31/10/2023 18:12, Martin Fox wrote:
I understand John’s point: you want all the user installed filters and handlers across all levels to be processed before switching to system level processing. I also understand this prioritization proposal is designed to push our existing set of system handlers to a separate phase. But is that all we’re talking about here? I need some clarification.

The goal is to give the user (not a control author) a way to handle events before the system handles them, no matter where the handler (or filter) is installed in the scene graph.  This makes sense as users should be the only real "users" of JavaFX nodes and controls, or at least it should feel that way.  The sharing of the event infrastructure (for memory or performance reasons) by Behaviors and Skins is unexpected by users, and unpredictable as it depends on what order handlers are installed.  Sharing of this infrastructure is fine, but the user should not have to deal with the unpredictability, and preferably wouldn't need to be aware of the fact that FX is installing handlers of its own at all (but that is a little late).

There are two proposals here to solve this.

1. Using waves, where events are first dispatched to handlers with the highest priority, then if unconsumed, dispatched to the next lower priority, and so on.

2. Using registation of default handlers per event; events are dispatched as normal, but system handlers play nice by only registering their interest in the event (ie. they receive the event as normal, but don't consume it). When an event fully bubbles up and is unconsumed, the default handlers get their turn to consume the event without a new dispatch cycle.


Within a given control the order of event processing gets involved. If a Control is subclassed the subclass should get first shot at the event. The same is true for Behaviors and Skins. Beyond that I’m still not clear if the behavior or skin should get the event first or if the skin should get it via the behavior or the other way around. In any case, you’ve got the control, the behavior, the skin, and all of their subclasses trying to sort out the execution order.

I don't think we need to get involved here; there are only two actors, the user and the control authorl (and its default behavior).  The execution order for default behavior is fixed by the order the handlers were installed. If you subclass a control you can be first if you want to (in the constructor).  As you are implementing a control, you should be using the same priority level as other system handlers would do (like Behaviors and Skins) so that a user of your control can override it still with a higher priority.

Also, I think if you design controls/behaviors and skins correctly, with good separation, the only part that is installing event handlers should be the Behaviors. Controls probably shouldn't install handlers, and neither should Skins (although some do).


Based on this discussion (and I might be mistaken on this) it sounds like you're trying to handle all this using this proposal, namely registering event handlers with a prioritization scheme. Wouldn’t it be easier to just grab the event and pass it around using Java method calls? Perhaps the call is handleEvent(). A control implements handleEvent() by passing the event off to the behavior’s handleEvent() which passes it off to the skin’s handleEvent(). The skin sends it up the superclass chain by calling super.handleEvent(), etc. so on.

This is not really possible, and is basically describing an alternative dispatching mechanism (Node could also pass events to their children); events are typed and you can create new event types.  Having a `handleEvent` method would require instanceof checks to determine the event type.  Having a handle method for each type is impossible as you can create new event types that can be sent to existing controls.

It's also not needed; event handlers are already called in order, and the order is fixed by how the control gets constructed.  A subclass should have sufficient opportunity to be "first" if they want to.  The rest of the events should be handled by the behavior, which should be aware in which order it wants things installed.  Skins and Controls shouldn't be installing event handlers at all.

All this happens on the "system" side.  When you write your own control you should install the handlers as system handlers (using scheme 1 or 2 described above).  The user of the control should however not have to care how many handlers are installed by the system, or in what order; they should be able to override anything by having a higher priority (using scheme 1 or 2 above).


This would make for an easy sell to outside developers. We can tell them that if they subclass a Control and implement handleEvent() they will get events first during the system phase. The same is true if they subclass a behavior or skin. They don’t need to buy into or even see a complicated event prioritization scheme to get exactly what they expect, namely first access to events.

I don't think Control authors have any such problems currently. Skins get installed after the first CSS pass, so if you install handlers in your subclass constructor you'll always be first.

The proposal is all about allowing users to get to events first when using standard controls directly.

--John


But, again, maybe I’m off base here. Let me know.

Martin

On Oct 30, 2023, at 12:53 PM, Andy Goryachev <andy.goryac...@oracle.com> wrote:

Dear Michael:
Thank you, this is very helpful.
Questions/Comments:
1. Does this proposal changes the way events are dispatched with respect to priority?  In other words, does it first go through the list of all handlers registred on the leaf Node (high priority first, then lower, then lowest), then bubble up?  Or do they propagate upwards looking for high priority handlers first, then the process restarts for lower priorities, as I saw in some previous emails?  (I could be mistaken) 2. Do you propose to abort event dispatching immediately after the event is consumed?  This probably should be mentioned earlier in the Motivation (the problem statement) section. 3. I wonder if three priority levels are sufficient.  Let me explain.  We have two possible actors who can register an event listener: the application code and the FX (or, rather more specifically, the skin and its behavior, whatever that might be).
Application code might want to add handlers at three possible priorities:

  * App handler must always be called before any fx handler
  * App hander does not care
  * App handler must always be called after any fx handlers

For fx/skin handlers we might have fewer levels:

  * Skin handler does not care
  * Skin handler must be called after all other skin handlers

This situation maps to 5 priorities and 4 effective levels (or 5).
We should also mention the fact that when any actor adds two or more handlers for the same event with the same priority, they get invoked in the order added. Would you agree, or am I missing some critical aspect of the proposed solution?
Thank you
-andy

*From:*openjfx-dev <openjfx-dev-r...@openjdk.org> on behalf of Michael Strauß <michaelstr...@gmail.com>
*Date:*Friday, October 27, 2023 at 19:41
*To:*openjfx-dev <openjfx-dev@openjdk.org>
*Subject:*Re: Prioritized event handlers

Here is the proposal:
https://gist.github.com/mstr2/4bde9c97dcf608a0501030ade1ae7dc1

Comments are welcome.


On Fri, Oct 27, 2023 at 8:21 PM Andy Goryachev
<andy.goryac...@oracle.com> wrote:
>
> Would it be possible to create a proposal in the JEP format outlining the proposed public API?
>
>
>
> Thank you
>
> -andy

Reply via email to