1212import java .awt .event .MouseAdapter ;
1313import java .awt .event .MouseEvent ;
1414import java .awt .event .MouseMotionAdapter ;
15- import java .util .List ;
1615import java .util .Set ;
1716import java .util .Vector ;
1817import java .util .function .Consumer ;
2221import javax .swing .JPopupMenu ;
2322import javax .swing .JScrollPane ;
2423import javax .swing .ListSelectionModel ;
24+ import javax .swing .SwingUtilities ;
25+ import javax .swing .event .PopupMenuEvent ;
26+ import javax .swing .event .PopupMenuListener ;
2527import javax .swing .text .BadLocationException ;
2628import javax .swing .text .JTextComponent ;
2729
@@ -42,7 +44,7 @@ public class AutocompletePopup extends JPopupMenu {
4244 /**
4345 * @param parent text component where completion will be performed
4446 * @param position position to perform completion at
45- * @param onCompletion
47+ * @param onCompletion to pass the final selected completion string to
4648 */
4749 public AutocompletePopup (
4850 @ NotNull JTextComponent parent ,
@@ -58,7 +60,7 @@ public AutocompletePopup(
5860 suggestionList .setVisibleRowCount (maxVisibleRows );
5961
6062 // single-click to accept selection
61- suggestionList . addMouseListener (
63+ addMouseListener (
6264 new MouseAdapter () {
6365 @ Override
6466 public void mouseClicked (MouseEvent e ) {
@@ -67,7 +69,7 @@ public void mouseClicked(MouseEvent e) {
6769 });
6870
6971 // highlight item hovered over with mouse
70- suggestionList . addMouseMotionListener (
72+ addMouseMotionListener (
7173 new MouseMotionAdapter () {
7274 @ Override
7375 public void mouseMoved (MouseEvent e ) {
@@ -78,7 +80,7 @@ public void mouseMoved(MouseEvent e) {
7880 }
7981 });
8082
81- suggestionList . addKeyListener (
83+ addKeyListener (
8284 new KeyAdapter () {
8385 @ Override
8486 public void keyPressed (KeyEvent e ) {
@@ -92,6 +94,22 @@ public void keyTyped(KeyEvent e) {
9294 }
9395 });
9496
97+ // Ensure the suggestion list gains focus
98+ // Without this, on Windows the popup shows but the keyboard becomes unresponsive
99+ addPopupMenuListener (
100+ new PopupMenuListener () {
101+ @ Override
102+ public void popupMenuWillBecomeVisible (PopupMenuEvent e ) {
103+ SwingUtilities .invokeLater (() -> requestFocusInWindow ());
104+ }
105+
106+ @ Override
107+ public void popupMenuWillBecomeInvisible (PopupMenuEvent e ) {}
108+
109+ @ Override
110+ public void popupMenuCanceled (PopupMenuEvent e ) {}
111+ });
112+
95113 // Calculate the preferred height based on the number of items
96114 int rowHeight = suggestionList .getFixedCellHeight ();
97115 if (rowHeight == 0 ) {
@@ -147,12 +165,14 @@ private void handleKeyPressed(
147165 return ;
148166 }
149167 // Close the popup if a meta key (Ctrl, Alt, Cmd) is pressed with another key, as this is likely
150- // the invocation of some other shortcut such as undo/redo, and we would need more logic to handle
151- // that gracefully
152- if ((e .getModifiersEx () & (KeyEvent .CTRL_DOWN_MASK | KeyEvent .ALT_DOWN_MASK | KeyEvent .META_DOWN_MASK )) != 0
153- && e .getKeyCode () != KeyEvent .VK_CONTROL
154- && e .getKeyCode () != KeyEvent .VK_ALT
155- && e .getKeyCode () != KeyEvent .VK_META ) {
168+ // the invocation of some other shortcut such as undo/redo, and we would need more logic to
169+ // handle that gracefully
170+ if ((e .getModifiersEx ()
171+ & (KeyEvent .CTRL_DOWN_MASK | KeyEvent .ALT_DOWN_MASK | KeyEvent .META_DOWN_MASK ))
172+ != 0
173+ && e .getKeyCode () != KeyEvent .VK_CONTROL
174+ && e .getKeyCode () != KeyEvent .VK_ALT
175+ && e .getKeyCode () != KeyEvent .VK_META ) {
156176 setVisible (false );
157177 parent .dispatchEvent (e );
158178 return ;
0 commit comments