Java Swing - the mouse pointer "moves" in the context menu when the JFrame maximizes

I reinforced the strange behavior of handling Swing mouse position while maximizing the JFrame:

When I execute this very simple code ...

public class Test { public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { JFrame frame = new JFrame(); JMenuBar menubar = new JMenuBar(); JMenu menu = new JMenu("File"); menu.add(new JMenuItem("New")); menubar.add(menu); frame.setJMenuBar(menubar); frame.setSize(200, 200); frame.setLocationRelativeTo(null); frame.setVisible(true); } }); } } 

... Usually I can click File (first click - click, release) β†’ New (second click). But when I maximize the JFrame and click on File , the context menu immediately disappears on the mouse output. Moreover, when I hold the mouse button - to prevent fading, I have to move the mouse more to focus on the New element.

mouse shift

The red dot represents the area (more or less) where I have to move the mouse to focus on New after clicking File and holding the mouse.

I observed the same behavior when using the "context menu" context menu, for example, when right-clicking on a chart from JFreeChart.

I thought this was a JDK problem because I used Oracle JDK, but after installing OpenJDK, I have the same results.

Has anyone observed this strange behavior? Or am I missing something obvious?

I use:

  • 1.7.0_147-icedtea (or 1.7.0_04 for java-7-oracle)
  • OpenJDK workspace (IcedTea7 2.0) (7 ~ b147-2.0-0ubuntu0.11.10.1)
  • 64-bit OpenJDK virtual machine (build 21.0-b17, mixed mode)
  • Linux Mint 12 (lisa) GNOME 3.2.1
+4
source share
3 answers

Yes - this is a bug in JDK7 that was mentioned in @nIcE cOw.

I installed JDK6 and I could not reproduce this error.

 java version "1.6.0_23" OpenJDK Runtime Environment (IcedTea6 1.11pre) (6b23~pre11-0ubuntu1.11.10.2) OpenJDK 64-Bit Server VM (build 20.0-b11, mixed mode) 
+3
source

There is also a workaround when you need to use Oracle Java 7 (for example, when using JavaFX). Just add the following lines of code to the window / frame class:

  if (Arrays.asList("gnome-shell", "mate", "other...").contains(System.getenv("DESKTOP_SESSION"))) { try { Class<?> xwm = Class.forName("sun.awt.X11.XWM"); Field awt_wmgr = xwm.getDeclaredField("awt_wmgr"); awt_wmgr.setAccessible(true); Field other_wm = xwm.getDeclaredField("OTHER_WM"); other_wm.setAccessible(true); if (awt_wmgr.get(null).equals(other_wm.get(null))) { Field metacity_wm = xwm.getDeclaredField("METACITY_WM"); metacity_wm.setAccessible(true); awt_wmgr.set(null, metacity_wm.get(null)); } } catch (Exception x) { x.printStackTrace(); } } 

This piece of code is based on a workaround from Netbeans developers .

+2
source

I would like to complement the solution given by the zebra problem.

How does this still happen to me with any swing software on Linux (using the Cinnamon desktop), even on Java 6 (update 45)

The problem will be repeated every time I move the window or resize it, so you need to reuse the workaround every time the window changes. I created the following class and used it whenever I create a new window:

 class LinuxWindowFix implements WindowStateListener { private final String desktop; private Field metacity_wm; private Field awt_wmgr; private boolean applyFix; private static LinuxWindowFix instance = new LinuxWindowFix(); public static LinuxWindowFix getInstance() { return instance; } private LinuxWindowFix() { applyFix = false; List<String> linuxDesktops = Arrays.asList("gnome-shell", "mate", "cinnamon"); //add more desktop names here. desktop = System.getenv("DESKTOP_SESSION"); if (desktop != null && linuxDesktops.contains(desktop.toLowerCase())) { try { Class<?> xwm = Class.forName("sun.awt.X11.XWM"); awt_wmgr = xwm.getDeclaredField("awt_wmgr"); awt_wmgr.setAccessible(true); Field other_wm = xwm.getDeclaredField("OTHER_WM"); other_wm.setAccessible(true); if (awt_wmgr.get(null).equals(other_wm.get(null))) { metacity_wm = xwm.getDeclaredField("METACITY_WM"); metacity_wm.setAccessible(true); applyFix = true; } } catch (Exception ex) { //ignore } } } @Override public void windowStateChanged(WindowEvent e) { try { awt_wmgr.set(null, metacity_wm.get(null)); } catch (Exception ex) { //ignore } } public void apply(Window w) { if (!applyFix) { return; } w.removeWindowStateListener(this); w.addWindowStateListener(this); } } 

Just name it for each window you create and it will work as expected.

 LinuxWindowFix.getInstance().apply(myWindow); 
0
source

Source: https://habr.com/ru/post/1412262/


All Articles