Add cancel option to "requestClose" method?

Hi,

I was trying to implement something similar to the onClosing event handler in WinForms (I know, ugh). This event has the option to cancel the close and also can trigger a new MessageBox or a completely new modal form (thus not blocking the UI thread) to confirm with the user.

I was able to do something similar by overriding the stop() method in LegacyApplication. Basically I create a new CompletableFuture<Boolean> and ask my hierarchy of states if it is ok to close. If it is, they call complete(false);. Otherwise, they call complete(true);. Back in my override, I attach a lambda to the future like this:

future.thenAccept(cancel -> {
  if (!cancel) {
    super.stop();
  }
});

This works great if I call the stop from anywhere in my program. But if the user clicks the “X” in the corner or if they press Alt + F4, then the stop is not called. From my research, what is called instead is requestClose.

I tried doing the same override in here, but the problem is that the close flag in LWJGL does not reset, and as such, in each cycle of the game loop, it triggers this method, and such keeps firing infinite futures which are just displaying a dialog to the user over and over again.

I saw that the specific implementation for LWJGL has a glfwSetWindowShouldClose(window, value) method which could reset the flag, but this would need to be updated in the LwjglWindow implementation of JmeContext. Plus, this is only one of the implementations that call requestClose. I don’t know if it is possible with other implementations to cancel this. It would be nice if the interface could be changed to return a boolean to confirm. If we don’t want to break the API, what if the “close” flag was reset right after being checked but before calling the requestClose method, so that the request is triggered only once.

Right now, from what I see, it is not possible to prevent closing the game if using Alt + F4 or the “X” button (which is probably not a problem in fullscreen, but it is in windowed).

Sorry if this is the wrong category. Feel free to move to the right one if that is the case.

Thanks.

EDIT: I just saw the implementation for Jogl, and it does exactly what I say. it resets the “close” flag to false right after calling the request method. I was not able to find where it is called for android. AWT doesn’t seem to even call this method.

1 Like

Да, та же проблема.
При нажатии на X я вывожу модальное окно, где можно отказаться от выхода, но даже при нажатии на ‘no’ - окно JME закрывается, только основной поток продолжает работать, так как не был вызван мой метод завершения работы программы, естественно.

Есть решение?

I don’t know if there is a cleaner way but it is possible to cancel the close by directly reaching into LWJGL

    public void requestClose (boolean esc) {
        //actually, don't close after all
        long windowHandle = ((LwjglWindow)getContext()).getWindowHandle()
        GLFW.glfwSetWindowShouldClose(windowHandle, false);
    }

(Obviously this will only work when running under LWJGL so not portable to android)

3 Likes

Да, я как раз недавно решил проблему похожим способом. Видимо, он верный.

1 Like