Re: RFR: 8334868: Ensure CheckUninstallModalHook is called in WPageDialogPeer._show

2024-07-10 Thread Phil Race
On Mon, 24 Jun 2024 20:16:30 GMT, Alexey Ivanov  wrote:

> This is somewhat a continuation for 
> [JDK-8307160](https://bugs.openjdk.org/browse/JDK-8307160) and 
> [JDK-8334509](https://bugs.openjdk.org/browse/JDK-8334509).
> 
> The former removed the `doIt` flag in #18584, but it introduced a regression. 
>  
> The regression is resolved by the latter in #19786, and it added the 'doIt' 
> flag again.
> 
> I think using a flag makes the code less clear. When reading the code, one 
> has to keep track of the current value of the `doIt` flag.
> 
> I raised my concern in [comments in PR 
> 19786](https://github.com/openjdk/jdk/pull/19786#discussion_r1649191308):
> 
>> I'd rather keep `JNI_FALSE` here — it's more explicit and therefore clearer. 
>> You don't have to keep track of the value of `doIt` flag while reading the 
>> code.
>> 
>> In fact, I'd prefer no `doIt` flag at all… yet it makes handling the code 
>> below `if (ret)` slightly harder.
> 
> I came up with a solution which simplifies handling the clean-up. The 
> solution relies on C++ destructors which are called when the declared objects 
> go out of scope.
> 
> The C++ object wraps a lambda function to clean up and invokes this function 
> in its destructor. Such C++ class has to be a templated class because there's 
> no defined type to represent a lambda. The class has to be declared at the 
> top of the file because it needs C++ linkage.
> 
> There are two `Cleaner` objects declared in the code of 
> `Java_sun_awt_windows_WPageDialogPeer__1show`:
> 
> **`refCleaner`** is declared right after all the references to Java objects 
> are initialised. The corresponding `refCleanup` lambda deletes all the 
> references and replaces the `CLEANUP_SHOW` macro. Before JDK-8307160, the 
> code jumped to a go-to label to perform the clean-up.
> 
> **`postCleaner`** is declared after `AwtDialog::CheckInstallModalHook` is 
> called. Its lambda `postCleanup` uninstalls the modal hook and handles focus 
> transfer as well as saves the updated printer parameters.
> 
> It is `postCleaner` that resolves the bug JDK-8334868 by ensuring 
> `CheckUninstallModalHook` and `ModalActivateNextWindow` are called if 
> `::PageSetupDlg` is called.
> 
> As the result of using `refCleaner`, all the `return` statements in the 
> function use an explicit value, which makes the code cleaner. There's no need 
> to use a `go to` statement or insert a macro to delete references to Java 
> objects, about which one had to remember — the destructor of the `refCleaner` 
> handles deleting references when `refCleaner` goes out of scope, that is when 
> the function returns.

Sorry, but I  don't see this as better or needed. I was the one who requested 
the current code  and I don't see the need for all this complexity.
Just do the minimum change to make sure we do CheckUninstallModalHook is called.

-

Changes requested by prr (Reviewer).

PR Review: https://git.openjdk.org/jdk/pull/19867#pullrequestreview-2169910991


Re: RFR: 8334868: Ensure CheckUninstallModalHook is called in WPageDialogPeer._show

2024-06-27 Thread Alisen Chung
On Mon, 24 Jun 2024 20:16:30 GMT, Alexey Ivanov  wrote:

> This is somewhat a continuation for 
> [JDK-8307160](https://bugs.openjdk.org/browse/JDK-8307160) and 
> [JDK-8334509](https://bugs.openjdk.org/browse/JDK-8334509).
> 
> The former removed the `doIt` flag in #18584, but it introduced a regression. 
>  
> The regression is resolved by the latter in #19786, and it added the 'doIt' 
> flag again.
> 
> I think using a flag makes the code less clear. When reading the code, one 
> has to keep track of the current value of the `doIt` flag.
> 
> I raised my concern in [comments in PR 
> 19786](https://github.com/openjdk/jdk/pull/19786#discussion_r1649191308):
> 
>> I'd rather keep `JNI_FALSE` here — it's more explicit and therefore clearer. 
>> You don't have to keep track of the value of `doIt` flag while reading the 
>> code.
>> 
>> In fact, I'd prefer no `doIt` flag at all… yet it makes handling the code 
>> below `if (ret)` slightly harder.
> 
> I came up with a solution which simplifies handling the clean-up. The 
> solution relies on C++ destructors which are called when the declared objects 
> go out of scope.
> 
> The C++ object wraps a lambda function to clean up and invokes this function 
> in its destructor. Such C++ class has to be a templated class because there's 
> no defined type to represent a lambda. The class has to be declared at the 
> top of the file because it needs C++ linkage.
> 
> There are two `Cleaner` objects declared in the code of 
> `Java_sun_awt_windows_WPageDialogPeer__1show`:
> 
> **`refCleaner`** is declared right after all the references to Java objects 
> are initialised. The corresponding `refCleanup` lambda deletes all the 
> references and replaces the `CLEANUP_SHOW` macro. Before JDK-8307160, the 
> code jumped to a go-to label to perform the clean-up.
> 
> **`postCleaner`** is declared after `AwtDialog::CheckInstallModalHook` is 
> called. Its lambda `postCleanup` uninstalls the modal hook and handles focus 
> transfer as well as saves the updated printer parameters.
> 
> It is `postCleaner` that resolves the bug JDK-8334868 by ensuring 
> `CheckUninstallModalHook` and `ModalActivateNextWindow` are called if 
> `::PageSetupDlg` is called.
> 
> As the result of using `refCleaner`, all the `return` statements in the 
> function use an explicit value, which makes the code cleaner. There's no need 
> to use a `go to` statement or insert a macro to delete references to Java 
> objects, about which one had to remember — the destructor of the `refCleaner` 
> handles deleting references when `refCleaner` goes out of scope, that is when 
> the function returns.

Marked as reviewed by achung (Committer).

-

PR Review: https://git.openjdk.org/jdk/pull/19867#pullrequestreview-2147167889


Re: RFR: 8334868: Ensure CheckUninstallModalHook is called in WPageDialogPeer._show

2024-06-27 Thread Alexey Ivanov
On Thu, 27 Jun 2024 13:15:19 GMT, Julian Waters  wrote:

> It would be helpful if JNI had a jobject unique_ptr type for C++

But `std::unique_ptr` wasn't available when JNI had been conceived…

It could be added…

The declaration in your sample still looks cumbersome… or _unwieldy_ as you 
said. Writing a custom deleter for each `jobject` doesn't look good either.

Most local references don't require explicit `DeleteLocalRef`, which also 
helps, I guess.

> Oops, you sent your correction about the custom deleter just as I sent my post

C++ has got many new features… I'm learning these feature on the fly since I 
don't use C++ as often.

-

PR Comment: https://git.openjdk.org/jdk/pull/19867#issuecomment-2194699149


Re: RFR: 8334868: Ensure CheckUninstallModalHook is called in WPageDialogPeer._show

2024-06-27 Thread Julian Waters
On Mon, 24 Jun 2024 20:16:30 GMT, Alexey Ivanov  wrote:

> This is somewhat a continuation for 
> [JDK-8307160](https://bugs.openjdk.org/browse/JDK-8307160) and 
> [JDK-8334509](https://bugs.openjdk.org/browse/JDK-8334509).
> 
> The former removed the `doIt` flag in #18584, but it introduced a regression. 
>  
> The regression is resolved by the latter in #19786, and it added the 'doIt' 
> flag again.
> 
> I think using a flag makes the code less clear. When reading the code, one 
> has to keep track of the current value of the `doIt` flag.
> 
> I raised my concern in [comments in PR 
> 19786](https://github.com/openjdk/jdk/pull/19786#discussion_r1649191308):
> 
>> I'd rather keep `JNI_FALSE` here — it's more explicit and therefore clearer. 
>> You don't have to keep track of the value of `doIt` flag while reading the 
>> code.
>> 
>> In fact, I'd prefer no `doIt` flag at all… yet it makes handling the code 
>> below `if (ret)` slightly harder.
> 
> I came up with a solution which simplifies handling the clean-up. The 
> solution relies on C++ destructors which are called when the declared objects 
> go out of scope.
> 
> The C++ object wraps a lambda function to clean up and invokes this function 
> in its destructor. Such C++ class has to be a templated class because there's 
> no defined type to represent a lambda. The class has to be declared at the 
> top of the file because it needs C++ linkage.
> 
> There are two `Cleaner` objects declared in the code of 
> `Java_sun_awt_windows_WPageDialogPeer__1show`:
> 
> **`refCleaner`** is declared right after all the references to Java objects 
> are initialised. The corresponding `refCleanup` lambda deletes all the 
> references and replaces the `CLEANUP_SHOW` macro. Before JDK-8307160, the 
> code jumped to a go-to label to perform the clean-up.
> 
> **`postCleaner`** is declared after `AwtDialog::CheckInstallModalHook` is 
> called. Its lambda `postCleanup` uninstalls the modal hook and handles focus 
> transfer as well as saves the updated printer parameters.
> 
> It is `postCleaner` that resolves the bug JDK-8334868 by ensuring 
> `CheckUninstallModalHook` and `ModalActivateNextWindow` are called if 
> `::PageSetupDlg` is called.
> 
> As the result of using `refCleaner`, all the `return` statements in the 
> function use an explicit value, which makes the code cleaner. There's no need 
> to use a `go to` statement or insert a macro to delete references to Java 
> objects, about which one had to remember — the destructor of the `refCleaner` 
> handles deleting references when `refCleaner` goes out of scope, that is when 
> the function returns.

std::unique_ptr has the option for a custom deleter, meaning it can be used to 
clean up Java objects and other cases where a simple delete call does not 
suffice, for instance

```c++
std::unique_ptr self(env->GetObjectField(target, 
AwtPrintDialog::controlID), [] (jobject* object) -> void { 
 env->DeleteLocalRef(*object); });


Admittedly for jobjects this is a lot more cumbersome, since instead of 
replacing the pointer with a smart pointer, you wrap the pointer inside a smart 
pointer... Which is unwieldy. It would be helpful if JNI had a jobject 
unique_ptr type for C++

Oops, you sent your correction about the custom deleter just as I sent my post

-

PR Comment: https://git.openjdk.org/jdk/pull/19867#issuecomment-2194667659
PR Comment: https://git.openjdk.org/jdk/pull/19867#issuecomment-2194669210


Re: RFR: 8334868: Ensure CheckUninstallModalHook is called in WPageDialogPeer._show

2024-06-27 Thread Alexey Ivanov
On Thu, 27 Jun 2024 12:54:55 GMT, Alexey Ivanov  wrote:

> > …I believe I was referring to the use of C++'s std::unique_ptr, which has 
> > the functionality for cleanup that we need.
> 
> Yes, `std::unique_ptr` could be useful for handling automatic deallocation of 
> objects created with the `new` operator.
> 
> ~~It won't help with releasing references to Java objects though.~~

Since `std::unique_ptr` accepts a custom deleter, it may be used for deleting 
any object.

-

PR Comment: https://git.openjdk.org/jdk/pull/19867#issuecomment-2194662542


Re: RFR: 8334868: Ensure CheckUninstallModalHook is called in WPageDialogPeer._show

2024-06-27 Thread Alexey Ivanov
On Thu, 27 Jun 2024 11:26:24 GMT, Julian Waters  wrote:

> …I believe I was referring to the use of C++'s std::unique_ptr, which has the 
> functionality for cleanup that we need.

Yes, `std::unique_ptr` could be useful for handling automatic deallocation of 
objects created with the `new` operator.

It won't help with releasing references to Java objects though.

> That is currently blocked by awt.dll not being allowed to use the C++ 
> Standard Library, but if one looks at the current awt.dll with dumpbin, 
> awt.dll is actually already is linked to msvcp.dll, meaning it already uses 
> C++ Standard Library somehow (I don't know what exactly makes it dependent on 
> msvcp.dll)

I remember STL has been banned from AWT code, yet I don't know the reasons for 
it. It could be to keep the size smaller.

I can see that `awt.dll` depends on `msvcp140.dll` and imports one function 
from it: `?_Xlength_error@std@@YAXPEBD@Z`. It doesn't look like the C++ 
Standard Library is used. I can't find where it comes from though… It could be 
worth getting rid of this dependency.

I built a small sample app which uses `std::unique_ptr` and `std::make_unique` 
and it does not depend on `msvcp140.dll` at all. This makes sense, template 
libraries are header-only and will become part of the executable (or the 
dynamic library).

The only references to `std` namespace that I found in client are in 
`ShellFolder.cpp` which uses `std::bad_alloc`, it uses this type in `catch` 
blocks and it may throw an object of this class.

So, it looks `awt.dll` doesn't use the C++ Standard Library.

However, using C++ objects with 
[RAII](https://en.wikipedia.org/wiki/Resource_acquisition_is_initialization) 
makes the code shorter and frees the programmer from repeating clean-up blocks¹.

Indeed, it's already used by C++ classes in AWT: 
[`JNILocalFrame`](https://github.com/openjdk/jdk/blob/79a23017fc7154738c375fbb12a997525c3bf9e7/src/java.desktop/windows/native/libawt/windows/awt_Toolkit.h#L64-L77)
 and 
[`CriticalSection`](https://github.com/openjdk/jdk/blob/79a23017fc7154738c375fbb12a997525c3bf9e7/src/java.desktop/windows/native/libawt/windows/awt_Toolkit.h#L85-L119)
 along with its `Lock` class inside.

¹ Repeated clean-up blocks can be seen in #18584 in nearly all the files.

-

PR Comment: https://git.openjdk.org/jdk/pull/19867#issuecomment-2194603793


Re: RFR: 8334868: Ensure CheckUninstallModalHook is called in WPageDialogPeer._show

2024-06-27 Thread Julian Waters
On Mon, 24 Jun 2024 20:16:30 GMT, Alexey Ivanov  wrote:

> This is somewhat a continuation for 
> [JDK-8307160](https://bugs.openjdk.org/browse/JDK-8307160) and 
> [JDK-8334509](https://bugs.openjdk.org/browse/JDK-8334509).
> 
> The former removed the `doIt` flag in #18584, but it introduced a regression. 
>  
> The regression is resolved by the latter in #19786, and it added the 'doIt' 
> flag again.
> 
> I think using a flag makes the code less clear. When reading the code, one 
> has to keep track of the current value of the `doIt` flag.
> 
> I raised my concern in [comments in PR 
> 19786](https://github.com/openjdk/jdk/pull/19786#discussion_r1649191308):
> 
>> I'd rather keep `JNI_FALSE` here — it's more explicit and therefore clearer. 
>> You don't have to keep track of the value of `doIt` flag while reading the 
>> code.
>> 
>> In fact, I'd prefer no `doIt` flag at all… yet it makes handling the code 
>> below `if (ret)` slightly harder.
> 
> I came up with a solution which simplifies handling the clean-up. The 
> solution relies on C++ destructors which are called when the declared objects 
> go out of scope.
> 
> The C++ object wraps a lambda function to clean up and invokes this function 
> in its destructor. Such C++ class has to be a templated class because there's 
> no defined type to represent a lambda. The class has to be declared at the 
> top of the file because it needs C++ linkage.
> 
> There are two `Cleaner` objects declared in the code of 
> `Java_sun_awt_windows_WPageDialogPeer__1show`:
> 
> **`refCleaner`** is declared right after all the references to Java objects 
> are initialised. The corresponding `refCleanup` lambda deletes all the 
> references and replaces the `CLEANUP_SHOW` macro. Before JDK-8307160, the 
> code jumped to a go-to label to perform the clean-up.
> 
> **`postCleaner`** is declared after `AwtDialog::CheckInstallModalHook` is 
> called. Its lambda `postCleanup` uninstalls the modal hook and handles focus 
> transfer as well as saves the updated printer parameters.
> 
> It is `postCleaner` that resolves the bug JDK-8334868 by ensuring 
> `CheckUninstallModalHook` and `ModalActivateNextWindow` are called if 
> `::PageSetupDlg` is called.
> 
> As the result of using `refCleaner`, all the `return` statements in the 
> function use an explicit value, which makes the code cleaner. There's no need 
> to use a `go to` statement or insert a macro to delete references to Java 
> objects, about which one had to remember — the destructor of the `refCleaner` 
> handles deleting references when `refCleaner` goes out of scope, that is when 
> the function returns.

It's been quite a while since I said that, so I don't fully remember what I was 
talking about, but I believe I was referring to the use of C++'s 
std::unique_ptr, which has the functionality for cleanup that we need. That is 
currently blocked by awt.dll not being allowed to use the C++ Standard Library, 
but if one looks at the current awt.dll with dumpbin, awt.dll is actually 
already is linked to msvcp.dll, meaning it already uses C++ Standard Library 
somehow (I don't know what exactly makes it dependent on msvcp.dll)

-

PR Comment: https://git.openjdk.org/jdk/pull/19867#issuecomment-2194433117


Re: RFR: 8334868: Ensure CheckUninstallModalHook is called in WPageDialogPeer._show

2024-06-27 Thread Alexey Ivanov
On Mon, 24 Jun 2024 20:16:30 GMT, Alexey Ivanov  wrote:

> This is somewhat a continuation for 
> [JDK-8307160](https://bugs.openjdk.org/browse/JDK-8307160) and 
> [JDK-8334509](https://bugs.openjdk.org/browse/JDK-8334509).
> 
> The former removed the `doIt` flag in #18584, but it introduced a regression. 
>  
> The regression is resolved by the latter in #19786, and it added the 'doIt' 
> flag again.
> 
> I think using a flag makes the code less clear. When reading the code, one 
> has to keep track of the current value of the `doIt` flag.
> 
> I raised my concern in [comments in PR 
> 19786](https://github.com/openjdk/jdk/pull/19786#discussion_r1649191308):
> 
>> I'd rather keep `JNI_FALSE` here — it's more explicit and therefore clearer. 
>> You don't have to keep track of the value of `doIt` flag while reading the 
>> code.
>> 
>> In fact, I'd prefer no `doIt` flag at all… yet it makes handling the code 
>> below `if (ret)` slightly harder.
> 
> I came up with a solution which simplifies handling the clean-up. The 
> solution relies on C++ destructors which are called when the declared objects 
> go out of scope.
> 
> The C++ object wraps a lambda function to clean up and invokes this function 
> in its destructor. Such C++ class has to be a templated class because there's 
> no defined type to represent a lambda. The class has to be declared at the 
> top of the file because it needs C++ linkage.
> 
> There are two `Cleaner` objects declared in the code of 
> `Java_sun_awt_windows_WPageDialogPeer__1show`:
> 
> **`refCleaner`** is declared right after all the references to Java objects 
> are initialised. The corresponding `refCleanup` lambda deletes all the 
> references and replaces the `CLEANUP_SHOW` macro. Before JDK-8307160, the 
> code jumped to a go-to label to perform the clean-up.
> 
> **`postCleaner`** is declared after `AwtDialog::CheckInstallModalHook` is 
> called. Its lambda `postCleanup` uninstalls the modal hook and handles focus 
> transfer as well as saves the updated printer parameters.
> 
> It is `postCleaner` that resolves the bug JDK-8334868 by ensuring 
> `CheckUninstallModalHook` and `ModalActivateNextWindow` are called if 
> `::PageSetupDlg` is called.
> 
> As the result of using `refCleaner`, all the `return` statements in the 
> function use an explicit value, which makes the code cleaner. There's no need 
> to use a `go to` statement or insert a macro to delete references to Java 
> objects, about which one had to remember — the destructor of the `refCleaner` 
> handles deleting references when `refCleaner` goes out of scope, that is when 
> the function returns.

src/java.desktop/windows/native/libawt/windows/awt_PrintJob.cpp line 537:

> 535: env->DeleteLocalRef(page);
> 536: env->DeleteLocalRef(self);
> 537: };

In the long term, it is better to create a special class that deletes global 
and local references.

It could be these constructs to which @TheShermanTanker referred in [this 
comment](https://github.com/openjdk/jdk/pull/18584#pullrequestreview-1975384014):
 https://github.com/openjdk/jdk/pull/18584#pullrequestreview-1975384014";>…I
 have a change in mind relying on _RAII_ that would look much cleaner and 
neater.

-

PR Review Comment: https://git.openjdk.org/jdk/pull/19867#discussion_r1656909846


Re: RFR: 8334868: Ensure CheckUninstallModalHook is called in WPageDialogPeer._show

2024-06-27 Thread Alexey Ivanov
On Wed, 26 Jun 2024 23:42:16 GMT, Alisen Chung  wrote:

>> src/java.desktop/windows/native/libawt/windows/awt_PrintJob.cpp line 640:
>> 
>>> 638: HGLOBAL oldG = AwtPrintControl::getPrintHDMode(env, self);
>>> 639: if (setup.hDevMode != oldG) {
>>> 640:AwtPrintControl::setPrintHDMode(env, self, setup.hDevMode);
>> 
>> what does setPrintHDMode and setPrintHDName do? do they need to be called as 
>> part of cleanup even if there is an exception and we return JNI_FALSE?
>
> i think this code preserves the printer settings after the dialog closes (and 
> only on success before this fix), so is it possible in the case the printer 
> is removed and causes an exception, we shouldn't preserve these settings?

It's a good question…

Yes, the code saves (or updates) the printer name and mode.

These lines of code were called in cases where OK or Cancel is clicked in the 
print dialog. However, it was skipped in case of an error, just like 
`CheckUninstallModalHook`.

I also feel that these lines belong in the successful case, right before 
`return JNI_TRUE`, but I could quickly find any confirmation whether 
`setup.hDevMode` or `setup.hDevNames` can be modified. For this reason, I 
preserved the previous code flow.

I presume that neither `setup.hDevMode` or `setup.hDevNames` changes if the 
user clicks Cancel in `::PageSetupDlg`. It still leaves the question open what 
happens when the user clicks OK but we catch an error inside `if (ret)`. The 
old handles stored inside `self` could have become invalid, so it's safer to 
update the handles in `self` even if an error occurs.

-

PR Review Comment: https://git.openjdk.org/jdk/pull/19867#discussion_r1656892141


Re: RFR: 8334868: Ensure CheckUninstallModalHook is called in WPageDialogPeer._show

2024-06-26 Thread Alisen Chung
On Wed, 26 Jun 2024 23:37:48 GMT, Alisen Chung  wrote:

>> This is somewhat a continuation for 
>> [JDK-8307160](https://bugs.openjdk.org/browse/JDK-8307160) and 
>> [JDK-8334509](https://bugs.openjdk.org/browse/JDK-8334509).
>> 
>> The former removed the `doIt` flag in #18584, but it introduced a 
>> regression.  
>> The regression is resolved by the latter in #19786, and it added the 'doIt' 
>> flag again.
>> 
>> I think using a flag makes the code less clear. When reading the code, one 
>> has to keep track of the current value of the `doIt` flag.
>> 
>> I raised my concern in [comments in PR 
>> 19786](https://github.com/openjdk/jdk/pull/19786#discussion_r1649191308):
>> 
>>> I'd rather keep `JNI_FALSE` here — it's more explicit and therefore 
>>> clearer. You don't have to keep track of the value of `doIt` flag while 
>>> reading the code.
>>> 
>>> In fact, I'd prefer no `doIt` flag at all… yet it makes handling the code 
>>> below `if (ret)` slightly harder.
>> 
>> I came up with a solution which simplifies handling the clean-up. The 
>> solution relies on C++ destructors which are called when the declared 
>> objects go out of scope.
>> 
>> The C++ object wraps a lambda function to clean up and invokes this function 
>> in its destructor. Such C++ class has to be a templated class because 
>> there's no defined type to represent a lambda. The class has to be declared 
>> at the top of the file because it needs C++ linkage.
>> 
>> There are two `Cleaner` objects declared in the code of 
>> `Java_sun_awt_windows_WPageDialogPeer__1show`:
>> 
>> **`refCleaner`** is declared right after all the references to Java objects 
>> are initialised. The corresponding `refCleanup` lambda deletes all the 
>> references and replaces the `CLEANUP_SHOW` macro. Before JDK-8307160, the 
>> code jumped to a go-to label to perform the clean-up.
>> 
>> **`postCleaner`** is declared after `AwtDialog::CheckInstallModalHook` is 
>> called. Its lambda `postCleanup` uninstalls the modal hook and handles focus 
>> transfer as well as saves the updated printer parameters.
>> 
>> It is `postCleaner` that resolves the bug JDK-8334868 by ensuring 
>> `CheckUninstallModalHook` and `ModalActivateNextWindow` are called if 
>> `::PageSetupDlg` is called.
>> 
>> As the result of using `refCleaner`, all the `return` statements in the 
>> function use an explicit value, which makes the code cleaner. There's no 
>> need to use a `go to` statement or insert a macro to delete references to 
>> Java objects, about which one had to remember — the destructor of the 
>> `refCleaner` handles deleting references when `refCleaner` goes out of 
>> scope, that is when the function returns.
>
> src/java.desktop/windows/native/libawt/windows/awt_PrintJob.cpp line 640:
> 
>> 638: HGLOBAL oldG = AwtPrintControl::getPrintHDMode(env, self);
>> 639: if (setup.hDevMode != oldG) {
>> 640:AwtPrintControl::setPrintHDMode(env, self, setup.hDevMode);
> 
> what does setPrintHDMode and setPrintHDName do? do they need to be called as 
> part of cleanup even if there is an exception and we return JNI_FALSE?

i think this code preserves the printer settings after the dialog closes (and 
only on success before this fix), so is it possible in the case the printer is 
removed and causes an exception, we shouldn't preserve these settings?

-

PR Review Comment: https://git.openjdk.org/jdk/pull/19867#discussion_r1655642352


Re: RFR: 8334868: Ensure CheckUninstallModalHook is called in WPageDialogPeer._show

2024-06-26 Thread Alisen Chung
On Mon, 24 Jun 2024 20:16:30 GMT, Alexey Ivanov  wrote:

> This is somewhat a continuation for 
> [JDK-8307160](https://bugs.openjdk.org/browse/JDK-8307160) and 
> [JDK-8334509](https://bugs.openjdk.org/browse/JDK-8334509).
> 
> The former removed the `doIt` flag in #18584, but it introduced a regression. 
>  
> The regression is resolved by the latter in #19786, and it added the 'doIt' 
> flag again.
> 
> I think using a flag makes the code less clear. When reading the code, one 
> has to keep track of the current value of the `doIt` flag.
> 
> I raised my concern in [comments in PR 
> 19786](https://github.com/openjdk/jdk/pull/19786#discussion_r1649191308):
> 
>> I'd rather keep `JNI_FALSE` here — it's more explicit and therefore clearer. 
>> You don't have to keep track of the value of `doIt` flag while reading the 
>> code.
>> 
>> In fact, I'd prefer no `doIt` flag at all… yet it makes handling the code 
>> below `if (ret)` slightly harder.
> 
> I came up with a solution which simplifies handling the clean-up. The 
> solution relies on C++ destructors which are called when the declared objects 
> go out of scope.
> 
> The C++ object wraps a lambda function to clean up and invokes this function 
> in its destructor. Such C++ class has to be a templated class because there's 
> no defined type to represent a lambda. The class has to be declared at the 
> top of the file because it needs C++ linkage.
> 
> There are two `Cleaner` objects declared in the code of 
> `Java_sun_awt_windows_WPageDialogPeer__1show`:
> 
> **`refCleaner`** is declared right after all the references to Java objects 
> are initialised. The corresponding `refCleanup` lambda deletes all the 
> references and replaces the `CLEANUP_SHOW` macro. Before JDK-8307160, the 
> code jumped to a go-to label to perform the clean-up.
> 
> **`postCleaner`** is declared after `AwtDialog::CheckInstallModalHook` is 
> called. Its lambda `postCleanup` uninstalls the modal hook and handles focus 
> transfer as well as saves the updated printer parameters.
> 
> It is `postCleaner` that resolves the bug JDK-8334868 by ensuring 
> `CheckUninstallModalHook` and `ModalActivateNextWindow` are called if 
> `::PageSetupDlg` is called.
> 
> As the result of using `refCleaner`, all the `return` statements in the 
> function use an explicit value, which makes the code cleaner. There's no need 
> to use a `go to` statement or insert a macro to delete references to Java 
> objects, about which one had to remember — the destructor of the `refCleaner` 
> handles deleting references when `refCleaner` goes out of scope, that is when 
> the function returns.

src/java.desktop/windows/native/libawt/windows/awt_PrintJob.cpp line 640:

> 638: HGLOBAL oldG = AwtPrintControl::getPrintHDMode(env, self);
> 639: if (setup.hDevMode != oldG) {
> 640:AwtPrintControl::setPrintHDMode(env, self, setup.hDevMode);

what does setPrintHDMode and setPrintHDName do? do they need to be called as 
part of cleanup even if there is an exception and we return JNI_FALSE?

-

PR Review Comment: https://git.openjdk.org/jdk/pull/19867#discussion_r1655640044


RFR: 8334868: Ensure CheckUninstallModalHook is called in WPageDialogPeer._show

2024-06-24 Thread Alexey Ivanov
This is somewhat a continuation for 
[JDK-8307160](https://bugs.openjdk.org/browse/JDK-8307160) and 
[JDK-8334509](https://bugs.openjdk.org/browse/JDK-8334509).

The former removed the `doIt` flag in #18584, but it introduced a regression.  
The regression is resolved by the latter in #19786, and it added the 'doIt' 
flag again.

I think using a flag makes the code less clear. When reading the code, one has 
to keep track of the current value of the `doIt` flag.

I raised my concern in [comments in PR 
19786](https://github.com/openjdk/jdk/pull/19786#discussion_r1649191308):

> I'd rather keep `JNI_FALSE` here — it's more explicit and therefore clearer. 
> You don't have to keep track of the value of `doIt` flag while reading the 
> code.
> 
> In fact, I'd prefer no `doIt` flag at all… yet it makes handling the code 
> below `if (ret)` slightly harder.

I came up with a solution which simplifies handling the clean-up. The solution 
relies on C++ destructors which are called when the declared objects go out of 
scope.

The C++ object wraps a lambda function to clean up and invokes this function in 
its destructor. Such C++ class has to be a templated class because there's no 
defined type to represent a lambda. The class has to be declared at the top of 
the file because it needs C++ linkage.

There are two `Cleaner` objects declared in the code of 
`Java_sun_awt_windows_WPageDialogPeer__1show`:

**`refCleaner`** is declared right after all the references to Java objects are 
initialised. The corresponding `refCleanup` lambda deletes all the references 
and replaces the `CLEANUP_SHOW` macro. Before JDK-8307160, the code jumped to a 
go-to label to perform the clean-up.

**`postCleaner`** is declared after `AwtDialog::CheckInstallModalHook` is 
called. Its lambda `postCleanup` uninstalls the modal hook and handles focus 
transfer as well as saves the updated printer parameters.

It is `postCleaner` that resolves the bug JDK-8334868 by ensuring 
`CheckUninstallModalHook` and `ModalActivateNextWindow` are called if 
`::PageSetupDlg` is called.

As the result of using `refCleaner`, all the `return` statements in the 
function use an explicit value, which makes the code cleaner. There's no need 
to use a `go to` statement or insert a macro to delete references to Java 
objects, about which one had to remember — the destructor of the `refCleaner` 
handles deleting references when `refCleaner` goes out of scope, that is when 
the function returns.

-

Commit messages:
 - 8334868: Ensure CheckUninstallModalHook is called in WPageDialogPeer._show

Changes: https://git.openjdk.org/jdk/pull/19867/files
  Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=19867&range=00
  Issue: https://bugs.openjdk.org/browse/JDK-8334868
  Stats: 92 lines in 1 file changed: 48 ins; 36 del; 8 mod
  Patch: https://git.openjdk.org/jdk/pull/19867.diff
  Fetch: git fetch https://git.openjdk.org/jdk.git pull/19867/head:pull/19867

PR: https://git.openjdk.org/jdk/pull/19867