Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

processWindowEvent in mac

I have a java swing application which has a processWindowEvent method. below is the snippet

@Override
  protected void processWindowEvent(WindowEvent e) {
    if (e.getID() == WindowEvent.WINDOW_CLOSING) {
        //exit application with proper error message
    }
  }

Now when my swing application is launched in windows.

  1. close with the cross in swing UI. ==> proper error message is shown
  2. close the application from taskbar ==>proper error message is shown

but now if the same step is done in mac.

  1. close with the cross in swing UI. ==> proper error message is shown
  2. close the application from taskbar ==>does not come inside above method. So no proper message.

I wanted to know what is the default method which will be called in mac when java swing app is closed from taskbar(the dock)

like image 730
Mendon Ashwini Avatar asked Feb 25 '26 20:02

Mendon Ashwini


1 Answers

A world without com.apple.eawt.*

You need to look towards java.awt.Desktop instead.

For example...

Desktop.getDesktop().setQuitHandler(new QuitHandler() {
    @Override
    public void handleQuitRequestWith(QuitEvent e, QuitResponse response) {
        // Do some stuff
        //response.cancelQuit();
        //response.performQuit();
    }
});
Desktop.getDesktop().setQuitStrategy(QuitStrategy.CLOSE_ALL_WINDOWS);

Original Answer

Welcome to the wonderful world of "Apple does everything differently"

Basically what's happening is, when you "Quit" the program, Apple is calling System.exit(0), basically the same thing that would occur if your used CMD+Q

Now, Apple provides an API which provides functionality which you can use to "configure" your App with MacOS and perform some functionality which is unique to Apple, the problem is, it's a complete pain in the ... code to find useful information about and use.

What you're looking for is com.apple.eawt.ApplictionsetQuitStrategy. This defaults to calling System.exit(0), but you can change it to "close all windows" instead.

In this case, it would allow you to trap the WindowEvent and do what ever it is you want to do

import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class Test {

    public static void main(String[] args) {
        new Test();
    }

    public Test() {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new JFrame();
                frame.add(new TestPane());
                frame.addWindowListener(new WindowAdapter() {
                    @Override
                    public void windowClosing(WindowEvent e) {
                        System.out.println("Closing");
                        System.exit(0);
                    }
                });
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);

                try {
                    Class quitStrategies = Class.forName("com.apple.eawt.QuitStrategy");
                    Object quitStrategy = null;
                    for (Object o : quitStrategies.getEnumConstants()) {
                        if ("CLOSE_ALL_WINDOWS".equals(o.toString())) {
                            quitStrategy = o;
                        }
                    }
                    if (quitStrategy != null) {
                        Class appClass = Class.forName("com.apple.eawt.Application");
                        Class params[] = new Class[]{};

                        Method getApplication = appClass.getMethod("getApplication", params);
                        Object application = getApplication.invoke(appClass);
                        Method setQuitStrategy = application.getClass().getMethod("setQuitStrategy", quitStrategies);
                        setQuitStrategy.invoke(application, quitStrategy);
                    }

                } catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | ClassNotFoundException ex) {
                    ex.printStackTrace();
                }
            }
        });
    }

    public class TestPane extends JPanel {
    }
}

My general advice is, build a nice "Mac" utilities class which encapsulates the functionality you want to play with and call that.

Also beware, this functionality may disappear suddenly in future releases.

It should be noted that if you intend to have a "one for all" application, you will need to use reflection, as the required API is not available in the standard API, but if you wanted to make a "Apple" only release, you should have a look at this for more information about how you can compile the code on MacOS, because using...

Application.getApplication().setQuitStrategy(QuitStrategy.CLOSE_ALL_WINDOWS);

is hell of a lot easier to write and understand

like image 190
MadProgrammer Avatar answered Feb 27 '26 09:02

MadProgrammer