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].
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();
}
}
}
Oracle responded to the bug report I submitted, noting in their comments that the issue should be resolved in Java 8. The code above works as expected on the 1.8.0 JRE (build 1.8.0-b132) using OS X 10.9.2.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With