Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
- Added a setting to control whether the choice menu grabs keyboard focus (https://github.com/nbclaudecodegui/NetbeansClaudeCodeGui/issues/20)
- Added a global setting to choose the default dock position of the Claude Code session tab (https://github.com/nbclaudecodegui/NetbeansClaudeCodeGui/issues/24)

# 0.21.50 (2026-04-19)
Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

<groupId>io.github.nbclaudecodegui</groupId>
<artifactId>netbeans-claude-code-gui</artifactId>
<version>0.22.6-SNAPSHOT</version>
<version>0.22.7-SNAPSHOT</version>
<packaging>nbm</packaging>
<name>Netbeans Claude Code GUI</name>
<description>NetBeans plugin that provides a GUI for Claude Code CLI — run claude code sessions directly inside the IDE.</description>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,15 @@
*/
public final class ClaudeCodeOptionsPanel extends JPanel {

private static final String[] CHOICE_MENU_FOCUS_VALUES = {
ClaudeCodePreferences.CHOICE_MENU_GRAB_FOCUS,
ClaudeCodePreferences.CHOICE_MENU_SHOW_NO_FOCUS,
ClaudeCodePreferences.CHOICE_MENU_HIDE_MENU
};
private static final String[] CHOICE_MENU_FOCUS_LABELS = {
"Grab focus (default)", "Show without grabbing focus", "Hide menu"
};

private static final String[] DOCK_MODE_VALUES = {
"editor", "commonpalette", "explorer", "navigator", "output"
};
Expand Down Expand Up @@ -77,6 +86,8 @@ public final class ClaudeCodeOptionsPanel extends JPanel {
private JSpinner sessionListLimitSpinner;
/** Dropdown for the dock position of the Claude Code session tab. */
private javax.swing.JComboBox<String> dockModeCombo;
/** Dropdown for the choice menu focus behavior. */
private javax.swing.JComboBox<String> choiceMenuFocusCombo;
/** Spinner for the hang-detection timeout in seconds (0 = disabled). */
private JSpinner hangTimeoutSpinner;
/** Checkbox to enable MCP integration (pass --mcp-config flag). */
Expand Down Expand Up @@ -238,6 +249,13 @@ private JPanel buildGeneralPanel() {
form.add(dockModeCombo, gbc(1, row, false));
row++;

// --- choice menu focus mode ---
form.add(new JLabel("Choice menu focus:"), gbc(0, row, false));
choiceMenuFocusCombo = new javax.swing.JComboBox<>(CHOICE_MENU_FOCUS_LABELS);
choiceMenuFocusCombo.setToolTipText("Controls whether the choice menu grabs keyboard focus when it appears");
form.add(choiceMenuFocusCombo, gbc(1, row, false));
row++;

// spacer
GridBagConstraints spacer = new GridBagConstraints();
spacer.gridx = 0; spacer.gridy = row;
Expand Down Expand Up @@ -376,6 +394,9 @@ void load() {
String dockMode = ClaudeCodePreferences.getSessionDockMode();
int dockIdx = java.util.Arrays.asList(DOCK_MODE_VALUES).indexOf(dockMode);
dockModeCombo.setSelectedIndex(dockIdx >= 0 ? dockIdx : 0);
String focusMode = ClaudeCodePreferences.getChoiceMenuFocusMode();
int focusIdx = java.util.Arrays.asList(CHOICE_MENU_FOCUS_VALUES).indexOf(focusMode);
choiceMenuFocusCombo.setSelectedIndex(focusIdx >= 0 ? focusIdx : 0);
hangTimeoutSpinner.setValue(ClaudeCodePreferences.getHangTimeoutSeconds());
mcpEnabledCheckBox.setSelected(ClaudeCodePreferences.isMcpEnabled());

Expand Down Expand Up @@ -415,6 +436,11 @@ void store() {
dockSel >= 0 && dockSel < DOCK_MODE_VALUES.length
? DOCK_MODE_VALUES[dockSel]
: ClaudeCodePreferences.DEFAULT_SESSION_DOCK_MODE);
int focusSel = choiceMenuFocusCombo.getSelectedIndex();
ClaudeCodePreferences.setChoiceMenuFocusMode(
focusSel >= 0 && focusSel < CHOICE_MENU_FOCUS_VALUES.length
? CHOICE_MENU_FOCUS_VALUES[focusSel]
: ClaudeCodePreferences.DEFAULT_CHOICE_MENU_FOCUS_MODE);
ClaudeCodePreferences.setHangTimeoutSeconds((Integer) hangTimeoutSpinner.getValue());
ClaudeCodePreferences.setMcpEnabled(mcpEnabledCheckBox.isSelected());
ClaudeCodePreferences.setSendKey(selectedValue(sendRadios));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -570,6 +570,31 @@ public static void setSessionDockMode(String mode) {
.put(KEY_SESSION_DOCK_MODE, mode != null ? mode : DEFAULT_SESSION_DOCK_MODE);
}

// -------------------------------------------------------------------------
// choiceMenuFocusMode
// -------------------------------------------------------------------------

/** Preference key: focus behavior when the choice menu appears. */
public static final String KEY_CHOICE_MENU_FOCUS_MODE = "choiceMenuFocusMode";
/** Value: grab keyboard focus (current / default behavior). */
public static final String CHOICE_MENU_GRAB_FOCUS = "grab_focus";
/** Value: show the panel without grabbing keyboard focus. */
public static final String CHOICE_MENU_SHOW_NO_FOCUS = "show_no_focus";
/** Value: do not show the choice menu panel at all. */
public static final String CHOICE_MENU_HIDE_MENU = "hide_menu";
/** Default: grab focus. */
public static final String DEFAULT_CHOICE_MENU_FOCUS_MODE = CHOICE_MENU_GRAB_FOCUS;

public static String getChoiceMenuFocusMode() {
return NbPreferences.forModule(ClaudeCodePreferences.class)
.get(KEY_CHOICE_MENU_FOCUS_MODE, DEFAULT_CHOICE_MENU_FOCUS_MODE);
}

public static void setChoiceMenuFocusMode(String mode) {
NbPreferences.forModule(ClaudeCodePreferences.class)
.put(KEY_CHOICE_MENU_FOCUS_MODE, mode != null ? mode : DEFAULT_CHOICE_MENU_FOCUS_MODE);
}

private static String validated(String value, String fallback) {
return ENTER.equals(value) || SHIFT_ENTER.equals(value)
|| CTRL_ENTER.equals(value) || ALT_ENTER.equals(value)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ public ChoiceMenuPanel(Supplier<String> workingDirSupplier) {
* @param model the menu model
* @param callback invoked with the chosen response string, or {@code null} on Cancel
*/
public void show(ChoiceMenuModel model, Consumer<String> callback) {
public void show(ChoiceMenuModel model, Consumer<String> callback, boolean grabFocus) {
this.callback = callback;
removeAll();

Expand Down Expand Up @@ -520,7 +520,7 @@ public void keyPressed(java.awt.event.KeyEvent e) {
} else {
focusTarget = sendBtn;
}
if (focusTarget != null) {
if (grabFocus && focusTarget != null) {
javax.swing.SwingUtilities.invokeLater(focusTarget::requestFocusInWindow);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -489,13 +489,18 @@ public void onChoiceMenuChanged(ChoiceMenuModel menu) {
if (menu != null) {
LOG.fine(sessionTag + "[onChoiceMenuChanged] showing menu: \"" + menu.text()
+ "\" EDT=" + SwingUtilities.isEventDispatchThread());
String focusMode = io.github.nbclaudecodegui.settings.ClaudeCodePreferences.getChoiceMenuFocusMode();
if (io.github.nbclaudecodegui.settings.ClaudeCodePreferences.CHOICE_MENU_HIDE_MENU.equals(focusMode)) {
return;
}
boolean grabFocus = io.github.nbclaudecodegui.settings.ClaudeCodePreferences.CHOICE_MENU_GRAB_FOCUS.equals(focusMode);
choiceMenuPanel.show(menu, answer -> {
LOG.fine(sessionTag + "[PTY prompt answer] " + answer);
SwingUtilities.invokeLater(() -> switchSouthCard(CARD_PROMPT));
revalidate();
repaint();
controller.writePtyAnswer(answer);
});
}, grabFocus);
switchSouthCard(CARD_CHOICE);
} else {
if (CARD_CHOICE.equals(activeCard)) {
Expand Down
Loading
Loading