Re: RFR: 8285893: Hiding dialog and showing new one causes dialog to be frozen

2024-05-29 Thread Martin Fox
On Thu, 23 May 2024 14:21:27 GMT, Marius Hanl  wrote:

> That is exactly what I also figured out. If a second new nested event loop is 
> started directly after the first one was requested to leave, the native code 
> will never 'return'. That's why this code exists: 
> https://github.com/openjdk/jfx/blob/master/modules/javafx.graphics/src/main/java/com/sun/glass/ui/EventLoop.java#L118
>  which I slightly modified to not run `invokeLater` in my PR.

I think the invokeLater call is required. On Mac and Windows calls into Glass 
can only affect the innermost loop. For each loop you want to exit you have to 
call `Application.leaveNestedEventLoop` and then allow the execution stack to 
unwind to Glass so it can remove the loop. Only then can you initiate the 
process of leaving the next loop. So if there’s multiple loops in a LEAVING 
state each one needs to be handled in a separate runnable so the execution 
stack can unwind between runnables.

When leaving the innermost loop the steps of interest are:

1. call Application.leaveNestedEventLoop
2. disable the InvokeLaterDispatcher
3. unwind the execution stack to glass
4. enable the InvokeLaterDispatcher

My tweak to the code ensures that the InvokeLaterDispatcher is re-enabled if we 
start at step 1 but enter a new event loop before we can reach step 3. On Mac 
and Windows we’ll always restart the leaving process at step 1 for all loops. 
That’s not happening on Linux, the old loop is leaving without starting at step 
1. I’m pretty sure this is opening a window where the InvokeLaterDispatcher can 
dispatch a runnable to the old loop while it’s leaving. That’s not supposed to 
happen but I’m not sure what the consequences might be on Linux (I know it 
would be very bad on Mac).

-

PR Comment: https://git.openjdk.org/jfx/pull/1449#issuecomment-2137836685


Re: RFR: 8285893: Hiding dialog and showing new one causes dialog to be frozen [v9]

2024-05-23 Thread Marius Hanl
> This PR fixes the dialog freeze problem once and for all. 
> 
> This one is a bit tricky to understand, here is how it works:
> This bug happens on every platform, although the implementation of nested 
> event loops differs on every platform.
> E.g. on Linux we use `gtk_main` and `gtk_main_quit`, on Windows and Mac we 
> have an own implementation of a nested event loop (while loop), controlled by 
> a boolean flag.
> 
> Funny enough, the reason why this bug happens is always the same: Timing.
> 
> 1. When we hide a dialog, `_leaveNestedEventLoop` is called. 
> 2. This will call native code to get out of the nested event loop, e.g. on 
> Windows we try to break out of the while loop with a boolean flag, on Linux 
> we call `gtk_main_quit`.
> 3. Now, if we immediately open a new dialog, we enter a new nested event loop 
> via `_enterNestedEventLoop`, as a consequence we do not break out of the 
> while loop on Windows (the flag is set back again, the while loop is still 
> running), and we do not return from `gtk_main` on Linux.
> 4. And this will result in the Java code never returning and calling 
> `notifyLeftNestedEventLoop`, which we need to recover the UI.
> 
> So it is actually not trivial to fix this problem, and we can not really do 
> anything on the Java side. We may can try to wait until one more frame has 
> run so that things will hopefully be right, but that sounds rather hacky.
> 
> I therefore analyzed, if we even need to return from `_enterNestedEventLoop`. 
> Turns out, we don't need to. 
> There is a return value which we actually do not use (it does not have any 
> meaning to us, other that it is used inside an assert statement).
> ~Without the need of a return value, we also do not need to care when 
> `_enterNestedEventLoop` is returning - instead we cleanup and call 
> `notifyLeftNestedEventLoop` in `_leaveNestedEventLoop`, after the native code 
> was called.~
> See below for more information. To recover the UI (and in general nested 
> nested event loops ;) we need to set a flag for the `InvokeLaterDispatcher`.
> 
> Lets see if this is the right approach (for all platforms).
> Testing appreciated.
> #
> - [x] Tested on Windows
> - [x] Tested on Linux
> - [x] Tested on Mac
> - [ ] Tested on iOS (although the nested event loop code is the same as for 
> Mac) (I would appreciate if someone can do this as I have no access to an iOS 
> device)
> - [x] Adjust copyright
> - [x] Write Systemtest
> - [x] Document the new behaviour - in general, there should be more 
> information what to expect

Marius Hanl has updated the pull request incrementally with one additional 
commit since the last revision:

  Fix javadoc

-

Changes:
  - all: https://git.openjdk.org/jfx/pull/1324/files
  - new: https://git.openjdk.org/jfx/pull/1324/files/ec43f2e3..ede84ef1

Webrevs:
 - full: https://webrevs.openjdk.org/?repo=jfx=1324=08
 - incr: https://webrevs.openjdk.org/?repo=jfx=1324=07-08

  Stats: 2 lines in 1 file changed: 0 ins; 0 del; 2 mod
  Patch: https://git.openjdk.org/jfx/pull/1324.diff
  Fetch: git fetch https://git.openjdk.org/jfx.git pull/1324/head:pull/1324

PR: https://git.openjdk.org/jfx/pull/1324


Re: RFR: 8285893: Hiding dialog and showing new one causes dialog to be frozen

2024-05-23 Thread Marius Hanl
On Tue, 14 May 2024 18:42:47 GMT, Martin Fox  wrote:

> On Linux leaveNestedEventLoop makes changes in glass that cannot be erased or 
> undone (it calls gtk_main_quit which updates internal GTK state that we don’t 
> have access to). In the end GTK will exit the loops in the correct order but 
> it will exit loop A before the core code has a chance to call 
> Application.leaveNestedEventLoop again. This is throwing off the bookkeeping 
> including some debug checks.

That is exactly what I also figured out. If a second new nested event loop is 
started directly after the first one was requested to leave, the native code 
will never 'return'.
That's why this code exists: 
https://github.com/openjdk/jfx/blob/master/modules/javafx.graphics/src/main/java/com/sun/glass/ui/EventLoop.java#L118
which I slightly modified to not run `invokeLater` in my PR.

Otherwise it would never return any value and code after `enterNestedEventLoop` 
is never called:

Object o = Platform.enterNestedEventLoop(this);
System.out.println(o); // <- never called


And since you fixed the event jam so that we are not stuck anymore and Linux is 
implemented different with a global stateful variable, we will get that 
'inconsistency', which I don't think is relevant or a problem here, hence I 
removed it in my PR.

I also don't found any other way to deal with that situation, as you also 
stated, there is nothing else we can do, and while the other OS implementation 
have some kind of while loop where we can try to implement something, on the 
Linux side we completely rely on `gtk_main` and `gtk_main_quit`.

-

PR Comment: https://git.openjdk.org/jfx/pull/1449#issuecomment-2127252021


Re: RFR: 8285893: Hiding dialog and showing new one causes dialog to be frozen [v8]

2024-05-23 Thread Marius Hanl
> This PR fixes the dialog freeze problem once and for all. 
> 
> This one is a bit tricky to understand, here is how it works:
> This bug happens on every platform, although the implementation of nested 
> event loops differs on every platform.
> E.g. on Linux we use `gtk_main` and `gtk_main_quit`, on Windows and Mac we 
> have an own implementation of a nested event loop (while loop), controlled by 
> a boolean flag.
> 
> Funny enough, the reason why this bug happens is always the same: Timing.
> 
> 1. When we hide a dialog, `_leaveNestedEventLoop` is called. 
> 2. This will call native code to get out of the nested event loop, e.g. on 
> Windows we try to break out of the while loop with a boolean flag, on Linux 
> we call `gtk_main_quit`.
> 3. Now, if we immediately open a new dialog, we enter a new nested event loop 
> via `_enterNestedEventLoop`, as a consequence we do not break out of the 
> while loop on Windows (the flag is set back again, the while loop is still 
> running), and we do not return from `gtk_main` on Linux.
> 4. And this will result in the Java code never returning and calling 
> `notifyLeftNestedEventLoop`, which we need to recover the UI.
> 
> So it is actually not trivial to fix this problem, and we can not really do 
> anything on the Java side. We may can try to wait until one more frame has 
> run so that things will hopefully be right, but that sounds rather hacky.
> 
> I therefore analyzed, if we even need to return from `_enterNestedEventLoop`. 
> Turns out, we don't need to. 
> There is a return value which we actually do not use (it does not have any 
> meaning to us, other that it is used inside an assert statement).
> ~Without the need of a return value, we also do not need to care when 
> `_enterNestedEventLoop` is returning - instead we cleanup and call 
> `notifyLeftNestedEventLoop` in `_leaveNestedEventLoop`, after the native code 
> was called.~
> See below for more information. To recover the UI (and in general nested 
> nested event loops ;) we need to set a flag for the `InvokeLaterDispatcher`.
> 
> Lets see if this is the right approach (for all platforms).
> Testing appreciated.
> #
> - [x] Tested on Windows
> - [x] Tested on Linux
> - [x] Tested on Mac
> - [ ] Tested on iOS (although the nested event loop code is the same as for 
> Mac) (I would appreciate if someone can do this as I have no access to an iOS 
> device)
> - [x] Adjust copyright
> - [x] Write Systemtest
> - [x] Document the new behaviour - in general, there should be more 
> information what to expect

Marius Hanl has updated the pull request with a new target base due to a merge 
or a rebase. The incremental webrev excludes the unrelated changes brought in 
by the merge/rebase. The pull request contains 11 additional commits since the 
last revision:

 - Merge branch 'master' of https://github.com/openjdk/jfx into 
JDK-8285893-dialog-freezing-略
 - Integrate changes as outline by beldenfox
 - test for multiple nested event loops
 - try leave outer loop after finishing inner loop
 - update copyright
 - trigger an outer nested event loop leave attempt
 - do not attempt to leave eventloop after leaving another eventloop
 - Merge branch 'master' of https://github.com/openjdk/jfx into 
JDK-8285893-dialog-freezing-略
 - Merge remote-tracking branch 'openjfx/master' into 
JDK-8285893-dialog-freezing-略
 - JDK-8285893: Decrement nestedEventLoopCounter in leaveNestedEventLoop
 - ... and 1 more: https://git.openjdk.org/jfx/compare/ea0d1a15...ec43f2e3

-

Changes:
  - all: https://git.openjdk.org/jfx/pull/1324/files
  - new: https://git.openjdk.org/jfx/pull/1324/files/bba7fc23..ec43f2e3

Webrevs:
 - full: https://webrevs.openjdk.org/?repo=jfx=1324=07
 - incr: https://webrevs.openjdk.org/?repo=jfx=1324=06-07

  Stats: 86781 lines in 1031 files changed: 46446 ins; 20952 del; 19383 mod
  Patch: https://git.openjdk.org/jfx/pull/1324.diff
  Fetch: git fetch https://git.openjdk.org/jfx.git pull/1324/head:pull/1324

PR: https://git.openjdk.org/jfx/pull/1324


Re: RFR: 8285893: Hiding dialog and showing new one causes dialog to be frozen

2024-05-16 Thread Marius Hanl
On Mon, 6 May 2024 21:11:35 GMT, Martin Fox  wrote:

> I'll look into the Linux failure. The core EventLoop code passes an object 
> into the application's leaveNestedEventLoop and expects to see that object 
> returned from the applications's matching enterNestedEventLoop call. On Mac 
> and Windows this object is passed through to glass as an argument on the 
> stack. On Linux this value is handled as an application global. I suspect the 
> Linux bookkeeping isn't robust enough to handle this case but it will take a 
> bit to nail down the details.

There is one additional change I made, which might be relevant for Linux: 
https://github.com/openjdk/jfx/pull/1324/files#diff-af779aafb50953f57cab2478dd220d0322592b60e92065cf658644866572b7e7R117

Worth to check. I remember that the code there was problematic to me.

Otherwise this looks good.
https://github.com/openjdk/jfx/pull/1324 also cleans up the unused return value 
which is allocated in the C++/Objective-C side, but never really used on the 
Java side. So might be worth to do at some point, but I would agree to do the 
minimal changes first.

-

PR Comment: https://git.openjdk.org/jfx/pull/1449#issuecomment-2114266915


Re: RFR: 8285893: Hiding dialog and showing new one causes dialog to be frozen

2024-05-14 Thread Martin Fox
On Sat, 4 May 2024 22:55:13 GMT, Martin Fox  wrote:

> This PR is based on a discussion that happened over in PR #1324. Some of this 
> explanation is copied from that thread.
> 
> When `exitNestedEventLoop` is called on the innermost loop the 
> invokeLaterDispatcher suspends operation until the loop finishes. But if you 
> immediately start a new event loop the previous one won't finish and the 
> dispatcher will jam up and stop dispatching indefinitely.
> 
> When the invokeLaterDispatcher is told that the innermost loop is exiting it 
> sets `leavingNestedEventLoop` to true expecting it to be set to false when 
> the loop actually exits. When the dispatcher is told that a new event loop 
> has started it is not clearing `leavingNestedEventLoop` which is causing the 
> jam. Basically it should follow the same logic used in glass; leaving the 
> innermost loop updates a boolean indicating that the loop should exit but if 
> a new loop is started the boolean is set back to a running state since it now 
> applies to the new loop, not the previous one.
> 
> I suspect the invokeLaterDispatcher exists in part to deal with the specifics 
> of how deferred runnables are handled on the Mac. I investigated this a bit 
> and wrote up some comments in the Mac glass code.

I now understand what’s going wrong on Linux but I don’t know how to fix it.

When the test case tries to leave the innermost loop (let’s call it A) the 
cross-platform Java code calls Application.leaveNestedEventLoop to tell glass 
that the loop should exit. But before the loop can exit the test case starts a 
new loop leading to a call to Application.enterNestedEventLoop.

On Mac the leaveNestedEventLoop call sets a few global state variables in glass 
and the enterNestedEventLoop call wipes out all those changes. So as far as 
glass is concerned the leaveNestedEventLoop call was never made. This works 
because the cross-platform Java code is holding onto an object that represents 
loop A; it’s down one level in the event loop stack and marked as LEAVING. When 
that object reaches the top of the event loop stack the core will once again 
call Application.leaveNestedEventLoop to exit loop A.

On Linux leaveNestedEventLoop makes changes in glass that cannot be erased or 
undone (it calls gtk_main_quit which updates internal GTK state that we don’t 
have access to). In the end GTK will exit the loops in the correct order but it 
will exit loop A before the core code has a chance to call 
Application.leaveNestedEventLoop again. This is throwing off the bookkeeping 
including some debug checks.

(JavaFX struggles with this scenario because the original test case behaves in 
such an unexpected way. While processing a click event on a modal stage the 
event handler hides that modal and then immediately starts a new modal. The 
original modal can’t really go away; the handler for the click event originated 
there and is still in progress. That first modal might not be visible but it 
can’t truly close until the second modal is dismissed.)

-

PR Comment: https://git.openjdk.org/jfx/pull/1449#issuecomment-2110892622


Re: RFR: 8285893: Hiding dialog and showing new one causes dialog to be frozen

2024-05-06 Thread Martin Fox
On Sat, 4 May 2024 22:55:13 GMT, Martin Fox  wrote:

> This PR is based on a discussion that happened over in PR #1324. Some of this 
> explanation is copied from that thread.
> 
> When `exitNestedEventLoop` is called on the innermost loop the 
> invokeLaterDispatcher suspends operation until the loop finishes. But if you 
> immediately start a new event loop the previous one won't finish and the 
> dispatcher will jam up and stop dispatching indefinitely.
> 
> When the invokeLaterDispatcher is told that the innermost loop is exiting it 
> sets `leavingNestedEventLoop` to true expecting it to be set to false when 
> the loop actually exits. When the dispatcher is told that a new event loop 
> has started it is not clearing `leavingNestedEventLoop` which is causing the 
> jam. Basically it should follow the same logic used in glass; leaving the 
> innermost loop updates a boolean indicating that the loop should exit but if 
> a new loop is started the boolean is set back to a running state since it now 
> applies to the new loop, not the previous one.
> 
> I suspect the invokeLaterDispatcher exists in part to deal with the specifics 
> of how deferred runnables are handled on the Mac. I investigated this a bit 
> and wrote up some comments in the Mac glass code.

I'll look into the Linux failure. The core EventLoop code passes an object into 
the application's leaveNestedEventLoop and expects to see that object returned 
from the applications's matching enterNestedEventLoop call. On Mac and Windows 
this object is passed through to glass as an argument on the stack. On Linux 
this value is handled as an application global. I suspect the Linux bookkeeping 
isn't robust enough to handle this case but it will take a bit to nail down the 
details.

-

PR Comment: https://git.openjdk.org/jfx/pull/1449#issuecomment-2096926552


Re: RFR: 8285893: Hiding dialog and showing new one causes dialog to be frozen

2024-05-06 Thread Kevin Rushforth
On Sat, 4 May 2024 22:55:13 GMT, Martin Fox  wrote:

> This PR is based on a discussion that happened over in PR #1324. Some of this 
> explanation is copied from that thread.
> 
> When `exitNestedEventLoop` is called on the innermost loop the 
> invokeLaterDispatcher suspends operation until the loop finishes. But if you 
> immediately start a new event loop the previous one won't finish and the 
> dispatcher will jam up and stop dispatching indefinitely.
> 
> When the invokeLaterDispatcher is told that the innermost loop is exiting it 
> sets `leavingNestedEventLoop` to true expecting it to be set to false when 
> the loop actually exits. When the dispatcher is told that a new event loop 
> has started it is not clearing `leavingNestedEventLoop` which is causing the 
> jam. Basically it should follow the same logic used in glass; leaving the 
> innermost loop updates a boolean indicating that the loop should exit but if 
> a new loop is started the boolean is set back to a running state since it now 
> applies to the new loop, not the previous one.
> 
> I suspect the invokeLaterDispatcher exists in part to deal with the specifics 
> of how deferred runnables are handled on the Mac. I investigated this a bit 
> and wrote up some comments in the Mac glass code.

I get the following internal assertion failure when running the test on Linux:


NestedEventLoopTest > testCanExitAndThenEnterNewLoop FAILED
java.lang.AssertionError: Internal inconsistency - wrong EventLoop
at 
javafx.graphics@23-ea/com.sun.glass.ui.EventLoop.enter(EventLoop.java:108)
at 
javafx.graphics@23-ea/com.sun.javafx.tk.quantum.QuantumToolkit.enterNestedEventLoop(QuantumToolkit.java:656)
at 
javafx.graphics@23-ea/javafx.application.Platform.enterNestedEventLoop(Platform.java:310)
at 
test.javafx.stage.NestedEventLoopTest.lambda$testCanExitAndThenEnterNewLoop$29(NestedEventLoopTest.java:326


It ran cleanly on Mac and Windows.

-

PR Comment: https://git.openjdk.org/jfx/pull/1449#issuecomment-2096641134


Re: RFR: 8285893: Hiding dialog and showing new one causes dialog to be frozen

2024-05-06 Thread Kevin Rushforth
On Sat, 4 May 2024 22:55:13 GMT, Martin Fox  wrote:

> This PR is based on a discussion that happened over in PR #1324. Some of this 
> explanation is copied from that thread.
> 
> When `exitNestedEventLoop` is called on the innermost loop the 
> invokeLaterDispatcher suspends operation until the loop finishes. But if you 
> immediately start a new event loop the previous one won't finish and the 
> dispatcher will jam up and stop dispatching indefinitely.
> 
> When the invokeLaterDispatcher is told that the innermost loop is exiting it 
> sets `leavingNestedEventLoop` to true expecting it to be set to false when 
> the loop actually exits. When the dispatcher is told that a new event loop 
> has started it is not clearing `leavingNestedEventLoop` which is causing the 
> jam. Basically it should follow the same logic used in glass; leaving the 
> innermost loop updates a boolean indicating that the loop should exit but if 
> a new loop is started the boolean is set back to a running state since it now 
> applies to the new loop, not the previous one.
> 
> I suspect the invokeLaterDispatcher exists in part to deal with the specifics 
> of how deferred runnables are handled on the Mac. I investigated this a bit 
> and wrote up some comments in the Mac glass code.

This looks like a safe, targeted fix for the problem. It will need to be tested 
on all platforms with a full run of all system tests.

-

PR Comment: https://git.openjdk.org/jfx/pull/1449#issuecomment-2096441265


Re: RFR: 8285893: Hiding dialog and showing new one causes dialog to be frozen

2024-05-06 Thread Kevin Rushforth
On Sat, 4 May 2024 22:55:13 GMT, Martin Fox  wrote:

> This PR is based on a discussion that happened over in PR #1324. Some of this 
> explanation is copied from that thread.
> 
> When `exitNestedEventLoop` is called on the innermost loop the 
> invokeLaterDispatcher suspends operation until the loop finishes. But if you 
> immediately start a new event loop the previous one won't finish and the 
> dispatcher will jam up and stop dispatching indefinitely.
> 
> When the invokeLaterDispatcher is told that the innermost loop is exiting it 
> sets `leavingNestedEventLoop` to true expecting it to be set to false when 
> the loop actually exits. When the dispatcher is told that a new event loop 
> has started it is not clearing `leavingNestedEventLoop` which is causing the 
> jam. Basically it should follow the same logic used in glass; leaving the 
> innermost loop updates a boolean indicating that the loop should exit but if 
> a new loop is started the boolean is set back to a running state since it now 
> applies to the new loop, not the previous one.
> 
> I suspect the invokeLaterDispatcher exists in part to deal with the specifics 
> of how deferred runnables are handled on the Mac. I investigated this a bit 
> and wrote up some comments in the Mac glass code.

As with the earlier PR, this will need a lot of testing and careful review.

@Maran23 I'd be interested in your thoughts on this approach.

-

PR Comment: https://git.openjdk.org/jfx/pull/1449#issuecomment-2096342944


Re: RFR: 8285893: Hiding dialog and showing new one causes dialog to be frozen [v7]

2024-05-04 Thread Martin Fox
On Thu, 7 Mar 2024 22:32:13 GMT, Marius Hanl  wrote:

>> This PR fixes the dialog freeze problem once and for all. 
>> 
>> This one is a bit tricky to understand, here is how it works:
>> This bug happens on every platform, although the implementation of nested 
>> event loops differs on every platform.
>> E.g. on Linux we use `gtk_main` and `gtk_main_quit`, on Windows and Mac we 
>> have an own implementation of a nested event loop (while loop), controlled 
>> by a boolean flag.
>> 
>> Funny enough, the reason why this bug happens is always the same: Timing.
>> 
>> 1. When we hide a dialog, `_leaveNestedEventLoop` is called. 
>> 2. This will call native code to get out of the nested event loop, e.g. on 
>> Windows we try to break out of the while loop with a boolean flag, on Linux 
>> we call `gtk_main_quit`.
>> 3. Now, if we immediately open a new dialog, we enter a new nested event 
>> loop via `_enterNestedEventLoop`, as a consequence we do not break out of 
>> the while loop on Windows (the flag is set back again, the while loop is 
>> still running), and we do not return from `gtk_main` on Linux.
>> 4. And this will result in the Java code never returning and calling 
>> `notifyLeftNestedEventLoop`, which we need to recover the UI.
>> 
>> So it is actually not trivial to fix this problem, and we can not really do 
>> anything on the Java side. We may can try to wait until one more frame has 
>> run so that things will hopefully be right, but that sounds rather hacky.
>> 
>> I therefore analyzed, if we even need to return from 
>> `_enterNestedEventLoop`. Turns out, we don't need to. 
>> There is a return value which we actually do not use (it does not have any 
>> meaning to us, other that it is used inside an assert statement).
>> ~Without the need of a return value, we also do not need to care when 
>> `_enterNestedEventLoop` is returning - instead we cleanup and call 
>> `notifyLeftNestedEventLoop` in `_leaveNestedEventLoop`, after the native 
>> code was called.~
>> See below for more information. To recover the UI (and in general nested 
>> nested event loops ;) we need to set a flag for the `InvokeLaterDispatcher`.
>> 
>> Lets see if this is the right approach (for all platforms).
>> Testing appreciated.
>> #
>> - [x] Tested on Windows
>> - [x] Tested on Linux
>> - [x] Tested on Mac
>> - [ ] Tested on iOS (although the nested event loop code is the same as for 
>> Mac) (I would appreciate if someone can do this as I have no access to an 
>> iOS device)
>> - [x] Adjust copyright
>> - [x] Write Systemtest
>> - [x] Document the new behaviour - in general, there should be more 
>> information what to expect
>
> Marius Hanl has updated the pull request incrementally with one additional 
> commit since the last revision:
> 
>   Integrate changes as outline by beldenfox

I just submitted my proposed fix for this issue as PR #1449.

-

PR Comment: https://git.openjdk.org/jfx/pull/1324#issuecomment-2094495851


RFR: 8285893: Hiding dialog and showing new one causes dialog to be frozen

2024-05-04 Thread Martin Fox
This PR is based on a discussion that happened over in PR #1324. Some of this 
explanation is copied from that thread.

When `exitNestedEventLoop` is called on the innermost loop the 
invokeLaterDispatcher suspends operation until the loop finishes. But if you 
immediately start a new event loop the previous one won't finish and the 
dispatcher will jam up and stop dispatching indefinitely.

When the invokeLaterDispatcher is told that the innermost loop is exiting it 
sets `leavingNestedEventLoop` to true expecting it to be set to false when the 
loop actually exits. When the dispatcher is told that a new event loop has 
started it is not clearing `leavingNestedEventLoop` which is causing the jam. 
Basically it should follow the same logic used in glass; leaving the innermost 
loop updates a boolean indicating that the loop should exit but if a new loop 
is started the boolean is set back to a running state since it now applies to 
the new loop, not the previous one.

I suspect the invokeLaterDispatcher exists in part to deal with the specifics 
of how deferred runnables are handled on the Mac. I investigated this a bit and 
wrote up some comments in the Mac glass code.

-

Commit messages:
 - Merge remote-tracking branch 'upstream/master' into eventloopjam
 - Background information on how Mac Glass handles invokeLater runnables
 - Unblock invokeLater runnables when entering new loop just after exiting 
current one

Changes: https://git.openjdk.org/jfx/pull/1449/files
  Webrev: https://webrevs.openjdk.org/?repo=jfx=1449=00
  Issue: https://bugs.openjdk.org/browse/JDK-8285893
  Stats: 58 lines in 3 files changed: 58 ins; 0 del; 0 mod
  Patch: https://git.openjdk.org/jfx/pull/1449.diff
  Fetch: git fetch https://git.openjdk.org/jfx.git pull/1449/head:pull/1449

PR: https://git.openjdk.org/jfx/pull/1449


Re: RFR: 8285893: Hiding dialog and showing new one causes dialog to be frozen [v7]

2024-05-02 Thread Undecium
On Thu, 7 Mar 2024 22:32:13 GMT, Marius Hanl  wrote:

>> This PR fixes the dialog freeze problem once and for all. 
>> 
>> This one is a bit tricky to understand, here is how it works:
>> This bug happens on every platform, although the implementation of nested 
>> event loops differs on every platform.
>> E.g. on Linux we use `gtk_main` and `gtk_main_quit`, on Windows and Mac we 
>> have an own implementation of a nested event loop (while loop), controlled 
>> by a boolean flag.
>> 
>> Funny enough, the reason why this bug happens is always the same: Timing.
>> 
>> 1. When we hide a dialog, `_leaveNestedEventLoop` is called. 
>> 2. This will call native code to get out of the nested event loop, e.g. on 
>> Windows we try to break out of the while loop with a boolean flag, on Linux 
>> we call `gtk_main_quit`.
>> 3. Now, if we immediately open a new dialog, we enter a new nested event 
>> loop via `_enterNestedEventLoop`, as a consequence we do not break out of 
>> the while loop on Windows (the flag is set back again, the while loop is 
>> still running), and we do not return from `gtk_main` on Linux.
>> 4. And this will result in the Java code never returning and calling 
>> `notifyLeftNestedEventLoop`, which we need to recover the UI.
>> 
>> So it is actually not trivial to fix this problem, and we can not really do 
>> anything on the Java side. We may can try to wait until one more frame has 
>> run so that things will hopefully be right, but that sounds rather hacky.
>> 
>> I therefore analyzed, if we even need to return from 
>> `_enterNestedEventLoop`. Turns out, we don't need to. 
>> There is a return value which we actually do not use (it does not have any 
>> meaning to us, other that it is used inside an assert statement).
>> ~Without the need of a return value, we also do not need to care when 
>> `_enterNestedEventLoop` is returning - instead we cleanup and call 
>> `notifyLeftNestedEventLoop` in `_leaveNestedEventLoop`, after the native 
>> code was called.~
>> See below for more information. To recover the UI (and in general nested 
>> nested event loops ;) we need to set a flag for the `InvokeLaterDispatcher`.
>> 
>> Lets see if this is the right approach (for all platforms).
>> Testing appreciated.
>> #
>> - [x] Tested on Windows
>> - [x] Tested on Linux
>> - [x] Tested on Mac
>> - [ ] Tested on iOS (although the nested event loop code is the same as for 
>> Mac) (I would appreciate if someone can do this as I have no access to an 
>> iOS device)
>> - [x] Adjust copyright
>> - [x] Write Systemtest
>> - [x] Document the new behaviour - in general, there should be more 
>> information what to expect
>
> Marius Hanl has updated the pull request incrementally with one additional 
> commit since the last revision:
> 
>   Integrate changes as outline by beldenfox

Please don't close this pull request. I really need this fix.

-

PR Comment: https://git.openjdk.org/jfx/pull/1324#issuecomment-2089657232