HI, Starting with the rollout of Java8 via the auto-updater we received several reports that one of our applications has servere focus issues. The application registers a KeyListener on a JTextField showing an auto-completion JPopupMenu every time a character is typed.
Every time a key is typed, the following sequence is run: - Hide existing JPopupMenu in case there is one - Create new JPopupMenu and populate with contents (in this case a JTable) - JPopupMenu.show() below the JTextField which caused the keyTyped-event - JTextField.requestFocus(), so the user can continue typing. I've created a self-contained testcase available here: http://pastebin.com/GEQ1ZW28 This worked fine with Java6 & Java7, however since JDK8-b119 it failes when the popup is heavyweight - for lightweight popups it still succeeds (unfourtunately, we need heavyweight ones). I tried to analyze what happend and registered a global focus listener: This is the focus-history without the fix for JDK-7160604 - once the JTextField got it's focus no changes can be observed, despite new JPopups are being opened: javax.swing.JTextField[,241,115,197x19,... javax.swing.JRootPane[,5,27,955x384,..... javax.swing.JTextField[,241,115,197x19,... (focus stays here, despite new JPopups are beeing opened and old ones closed) With the fix, the focus history looks like this: javax.swing.JTextField[,241,115,197x19,.... javax.swing.JTextField[,241,115,197x19,.... javax.swing.JRootPane[,5,27,938x588,...(focus stays here, no further keyEvents are received by the JTextField) Beside some refactorings, the only functional change I can spot is that the order of the assignment of the "popup"-member and popup.show() have changed in JPopupMenu.showPopup(): Popup newPopup = getUI().getPopup(this, desiredLocationX, desiredLocationY); popupFactory.setPopupType(PopupFactory.LIGHT_WEIGHT_POPUP); popup = newPopup; newPopup.show(); If I change the order of newPopup.show() and popup=newPopup, the old behaviour is restored. At least it looks somehow suspicious the original author introduced a variable "newPopup" (and the patch still uses it without a good reason, "popup" could be assigned directly), so at first sight it looks intentional to assign popup only after show() was called. During the call to newPopup.show() the method JPopupMenu.isVisible() is called several times. Before the fix for JDK-7160604 it would return false, now it returns true - the focus issue mentioned is triggered by returning "true" at the following call-stack (full one available at http://pastebin.com/4qG8h7Td). at javax.swing.JPopupMenu.isVisible(JPopupMenu.java:854) at javax.swing.SortingFocusTraversalPolicy.enumerateCycle(SortingFocusTraversalPolicy.java:141) at javax.swing.SortingFocusTraversalPolicy.enumerateCycle(SortingFocusTraversalPolicy.java:156) at javax.swing.SortingFocusTraversalPolicy.enumerateCycle(SortingFocusTraversalPolicy.java:156) at javax.swing.SortingFocusTraversalPolicy.enumerateCycle(SortingFocusTraversalPolicy.java:156) at javax.swing.SortingFocusTraversalPolicy.enumerateCycle(SortingFocusTraversalPolicy.java:156) at javax.swing.SortingFocusTraversalPolicy.enumerateAndSortCycle(SortingFocusTraversalPolicy.java:135) at javax.swing.SortingFocusTraversalPolicy.getFocusTraversalCycle(SortingFocusTraversalPolicy.java:110) at javax.swing.SortingFocusTraversalPolicy.getFirstComponent(SortingFocusTraversalPolicy.java:445) at javax.swing.LayoutFocusTraversalPolicy.getFirstComponent(LayoutFocusTraversalPolicy.java:166) at javax.swing.SortingFocusTraversalPolicy.getDefaultComponent(SortingFocusTraversalPolicy.java:535) at java.awt.Window.isFocusableWindow(Window.java:2496) If I introspect the call-stack and return "false" only when "enumerateCycle" is contained in the stack, everything works again. So from what I understand the JPopupMenu would never receive focus before the fix, because during show() it wasn't believed to be visible. What I wonder, is the code in the testcase even supposed to work - or did it just because of an accident? Also a mystery remains why the JPopupMenu has to contain a JTable to trigger the issue - with a JLabel everything works like it ever did. Thank you in advance, Clemens
