Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
745 views
in Technique[技术] by (71.8m points)

macos - Java stops capturing mouse movement events after maximizing or full screening a window in Mac OS X

When I enlarge a window by either pressing the maximize button or the full screen button on OS X, mouse movement events are no longer captured (though dragging is).

I have included a demo program below that highlights the issue. The maximization problem can be replicated using the MouseEventDemo web start example on the Java Tutorials website.

After some troubleshooting, I noted that mouse movements are recaptured if the mouse leaves the window (e.g., moves to the top of the window to access the menu bar) and then returns. It seems the issue may have something to do with the relation between the mouse position and the window during resizing animations, since the mouse is not in the frame before the resizing, but is afterward even though it didn’t necessarily move in the process.

import java.awt.Window;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.lang.reflect.Method;
import javax.swing.JFrame;
import javax.swing.JLabel;

public class Main implements MouseMotionListener {

    JLabel label = new JLabel("label");

    public static void main(String[] args) {
        Main main = new Main();
        main.init();
    }

    public void init() {
        JFrame frame = new JFrame();
        frame.setSize(640, 480);
        frame.setLocationRelativeTo(null);
        frame.getContentPane().add(label);
        frame.addMouseMotionListener(this);
        frame.setVisible(true);

        if (isMacOSX()) {
            enableFullScreenMode(frame);
        }
    }

    public void mouseDragged(MouseEvent e) {
        label.setText(e.toString());
    }

    public void mouseMoved(MouseEvent e) {
        label.setText(e.toString());
    }

    private static boolean isMacOSX() {
        return System.getProperty("os.name").indexOf("Mac OS X") >= 0;
    }

    public static void enableFullScreenMode(Window window) {
        try {
            Class<?> clazz = Class.forName("com.apple.eawt.FullScreenUtilities");
            Method method = clazz.getMethod("setWindowCanFullScreen", new Class<?>[] { Window.class, boolean.class });
            method.invoke(null, window, true);
        } catch (Throwable t) {
            t.printStackTrace();
        }
    }
}

Running the code above should reveal when the label does and does not update.

I am running OS X Version 10.9 Build 13A3017 with Java SE 7 [1.7.0_45].

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Empirically, the problem disappears if one switches away from and back to the application while maximized. Adding a ComponentListener that forces the frame toFront() seems to work. As an aside, Swing GUI objects should be constructed and manipulated only on the event dispatch thread.

frame.addComponentListener(new ComponentAdapter() {

    @Override
    public void componentResized(ComponentEvent e) {
        frame.toFront();
    }
});

As tested:

import java.awt.EventQueue;
import java.awt.Window;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.lang.reflect.Method;
import javax.swing.JFrame;
import javax.swing.JLabel;

/** @see http://stackoverflow.com/a/20054242/230513 */
public class Main implements MouseMotionListener {

    JLabel label = new JLabel("label");

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                Main main = new Main();
                main.init();
            }
        });
    }

    public void init() {
        final JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(label);
        frame.pack();
        frame.setSize(640, 480);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
        if (isMacOSX()) {
            enableFullScreenMode(frame);
        }
        frame.addMouseMotionListener(this);
        frame.addComponentListener(new ComponentAdapter() {

            @Override
            public void componentResized(ComponentEvent e) {
                frame.toFront();
            }
        });
    }

    @Override
    public void mouseDragged(MouseEvent e) {
        label.setText(e.toString());
    }

    @Override
    public void mouseMoved(MouseEvent e) {
        label.setText(e.toString());
    }

    private static boolean isMacOSX() {
        return System.getProperty("os.name").indexOf("Mac OS X") >= 0;
    }

    public static void enableFullScreenMode(Window window) {
        try {
            Class<?> clazz = Class.forName("com.apple.eawt.FullScreenUtilities");
            Method method = clazz.getMethod("setWindowCanFullScreen",
                    new Class<?>[]{Window.class, boolean.class});
            method.invoke(null, window, true);
        } catch (Throwable t) {
            t.printStackTrace();
        }
    }
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...