On Mon, 3 Mar 2025 19:58:08 GMT, Andy Goryachev <ango...@openjdk.org> wrote:

>> I don't know how to use Subscription in this case.  
>> This does not work:
>> 
>> 
>>                 ObservableValue<Window> winProp = 
>> sceneProperty().flatMap(Scene::windowProperty);
>>                 accessibilityActive = winProp; // keep the reference so it 
>> won't get gc
>>                 Subscription sub = winProp.subscribe((win) -> {
>>                     if (win != null) {
>>                         if (accessibilityActive == winProp) {
>>                             accessibilityActive = null;
>>                         }
>>                         if (isAccessibilityActive()) {
>>                             handleAccessibilityActive(true);
>>                         }
>>                         //winProp.removeListener(this);
>>                         sub.unsubscribe(); <-- COMPILE ERROR
>>                     }
>>                 });
>
> @hjohn could you help here please?  How could we use Subscription in a 
> situation when it has to be unsubscribed from within the lambda?

I haven't been tracking these fixes for allowing initialization in background 
threads, but it seems to me that basically anything should be allowed as long 
as you're not part of a visible scene graph -- and I think there's also no 
expectation that all functionality of a control "works" as long as it is not 
yet part of such a graph (ie. the listeners are only needed once it is part of 
a scene graph).

If you make listeners conditional on being part of a scene graph, then I think 
you can handle these with a single code path.  Such a condition would be:

    ObservableValue<Boolean> partOfSceneGraph = node.sceneProperty()
      .flatMap(Scene::windowProperty)
      .flatMap(Window::showingProperty)
      .orElse(false);
      
You can then safely install any listeners directly, regardless if they're on a 
background thread or not:

    someProperty().when(partOfSceneGraph).subscribe( ... );

Or:

    someProperty().when(partOfSceneGraph).addListener( ... );

On a background thread, `partOfSceneGraph` will be `false`, and no listener 
gets installed (yet).  As soon as it becomes `true` all listeners with that 
same condition become active.  It becomes `true` automatically when the node 
has a scene belonging to a window that is visible.  Vice versa, if it ever 
becomes `false` again, (which it may when the Node is removed or replaced) all 
listeners using this condition are removed again.

-------------

PR Review Comment: https://git.openjdk.org/jfx/pull/1697#discussion_r1978157784

Reply via email to