From d9b3c86e3dd1c9fe1e9d3133f7846e70dcfc8ff8 Mon Sep 17 00:00:00 2001 From: "zhenxing.shen" Date: Fri, 3 Jul 2026 07:34:15 +0800 Subject: [PATCH 1/2] fix(term): emit CSI-u sequence for Ctrl+Enter in terminal blocks Send \x1b[13;5u (CSI u) when Ctrl+Enter is pressed in a terminal block, allowing terminal applications to distinguish Ctrl+Enter from plain Enter. Previously both keys produced the same 0x0a (newline) byte, making it impossible to bind Ctrl+Enter separately (e.g. for submit vs newline in multi-line prompts). Enter and Shift+Enter behavior is unchanged. Fixes #3355 --- frontend/app/view/term/term-model.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/frontend/app/view/term/term-model.ts b/frontend/app/view/term/term-model.ts index a256929e7d..1f4927e137 100644 --- a/frontend/app/view/term/term-model.ts +++ b/frontend/app/view/term/term-model.ts @@ -732,6 +732,12 @@ export class TermViewModel implements ViewModel { return false; } } + if (keyutil.checkKeyPressed(waveEvent, "Ctrl:Enter")) { + this.sendDataToController("\x1b[13;5u"); + event.preventDefault(); + event.stopPropagation(); + return false; + } // Check for Ctrl-V paste (platform-dependent) if (this.shouldHandleCtrlVPaste() && keyutil.checkKeyPressed(waveEvent, "Ctrl:v")) { From d7dfec9d45da5fc543df7df473d3ac08217f00cb Mon Sep 17 00:00:00 2001 From: "zhenxing.shen" Date: Sat, 4 Jul 2026 07:20:04 +0800 Subject: [PATCH 2/2] fix(term): gate Ctrl+Enter CSI-u sequence behind term:ctrlenter config toggle Add term:ctrlenter configuration option (default: true) to control whether Ctrl+Enter sends the CSI-u escape sequence \x1b[13;5u, following the same pattern as term:shiftenternewline. This addresses CodeRabbit review feedback about backward compatibility by allowing users to disable the behavior if it causes issues with applications that don't understand CSI-u sequences. - Add ConfigKey_TermCtrlEnter and MetaKey_TermCtrlEnter constants - Add TermCtrlEnter field to SettingsConfig and Meta structs - Update schema files (settings.json, widgets.json) - Update TypeScript type definitions - Gate Ctrl+Enter handler behind config check in term-model.ts --- cmd/generateschema/main-generateschema.go | 1 + frontend/app/view/term/term-model.ts | 12 ++++++++---- frontend/types/gotypes.d.ts | 2 ++ pkg/waveobj/metaconsts.go | 1 + pkg/waveobj/wtypemeta.go | 1 + pkg/wconfig/metaconsts.go | 1 + pkg/wconfig/settingsconfig.go | 1 + schema/settings.json | 3 +++ schema/widgets.json | 3 +++ 9 files changed, 21 insertions(+), 4 deletions(-) diff --git a/cmd/generateschema/main-generateschema.go b/cmd/generateschema/main-generateschema.go index dd24a4df0d..46a4b1e018 100644 --- a/cmd/generateschema/main-generateschema.go +++ b/cmd/generateschema/main-generateschema.go @@ -99,6 +99,7 @@ type WidgetsMetaSchemaHints struct { TermTransparency *float64 `json:"term:transparency,omitempty"` TermAllowBracketedPaste *bool `json:"term:allowbracketedpaste,omitempty"` TermShiftEnterNewline *bool `json:"term:shiftenternewline,omitempty"` + TermCtrlEnter *bool `json:"term:ctrlenter,omitempty"` TermMacOptionIsMeta *bool `json:"term:macoptionismeta,omitempty"` TermBellSound *bool `json:"term:bellsound,omitempty"` TermBellIndicator *bool `json:"term:bellindicator,omitempty"` diff --git a/frontend/app/view/term/term-model.ts b/frontend/app/view/term/term-model.ts index 1f4927e137..5560ab9477 100644 --- a/frontend/app/view/term/term-model.ts +++ b/frontend/app/view/term/term-model.ts @@ -733,10 +733,14 @@ export class TermViewModel implements ViewModel { } } if (keyutil.checkKeyPressed(waveEvent, "Ctrl:Enter")) { - this.sendDataToController("\x1b[13;5u"); - event.preventDefault(); - event.stopPropagation(); - return false; + const ctrlEnterAtom = getOverrideConfigAtom(this.blockId, "term:ctrlenter"); + const ctrlEnterEnabled = globalStore.get(ctrlEnterAtom) ?? true; + if (ctrlEnterEnabled) { + this.sendDataToController("\x1b[13;5u"); + event.preventDefault(); + event.stopPropagation(); + return false; + } } // Check for Ctrl-V paste (platform-dependent) diff --git a/frontend/types/gotypes.d.ts b/frontend/types/gotypes.d.ts index c5b870d7ed..c5672ecd02 100644 --- a/frontend/types/gotypes.d.ts +++ b/frontend/types/gotypes.d.ts @@ -1182,6 +1182,7 @@ declare global { "term:transparency"?: number; "term:allowbracketedpaste"?: boolean; "term:shiftenternewline"?: boolean; + "term:ctrlenter"?: boolean; "term:macoptionismeta"?: boolean; "term:cursor"?: string; "term:cursorblink"?: boolean; @@ -1417,6 +1418,7 @@ declare global { "term:transparency"?: number; "term:allowbracketedpaste"?: boolean; "term:shiftenternewline"?: boolean; + "term:ctrlenter"?: boolean; "term:macoptionismeta"?: boolean; "term:cursor"?: string; "term:cursorblink"?: boolean; diff --git a/pkg/waveobj/metaconsts.go b/pkg/waveobj/metaconsts.go index 0ce08099d8..88181ffbe2 100644 --- a/pkg/waveobj/metaconsts.go +++ b/pkg/waveobj/metaconsts.go @@ -121,6 +121,7 @@ const ( MetaKey_TermTransparency = "term:transparency" MetaKey_TermAllowBracketedPaste = "term:allowbracketedpaste" MetaKey_TermShiftEnterNewline = "term:shiftenternewline" + MetaKey_TermCtrlEnter = "term:ctrlenter" MetaKey_TermMacOptionIsMeta = "term:macoptionismeta" MetaKey_TermCursor = "term:cursor" MetaKey_TermCursorBlink = "term:cursorblink" diff --git a/pkg/waveobj/wtypemeta.go b/pkg/waveobj/wtypemeta.go index 2280b55d2d..06a450e3f8 100644 --- a/pkg/waveobj/wtypemeta.go +++ b/pkg/waveobj/wtypemeta.go @@ -125,6 +125,7 @@ type MetaTSType struct { TermTransparency *float64 `json:"term:transparency,omitempty"` // default 0.5 TermAllowBracketedPaste *bool `json:"term:allowbracketedpaste,omitempty"` TermShiftEnterNewline *bool `json:"term:shiftenternewline,omitempty"` + TermCtrlEnter *bool `json:"term:ctrlenter,omitempty"` TermMacOptionIsMeta *bool `json:"term:macoptionismeta,omitempty"` TermCursor string `json:"term:cursor,omitempty"` TermCursorBlink *bool `json:"term:cursorblink,omitempty"` diff --git a/pkg/wconfig/metaconsts.go b/pkg/wconfig/metaconsts.go index 7d5bba5d9d..02a9ab48b0 100644 --- a/pkg/wconfig/metaconsts.go +++ b/pkg/wconfig/metaconsts.go @@ -52,6 +52,7 @@ const ( ConfigKey_TermTransparency = "term:transparency" ConfigKey_TermAllowBracketedPaste = "term:allowbracketedpaste" ConfigKey_TermShiftEnterNewline = "term:shiftenternewline" + ConfigKey_TermCtrlEnter = "term:ctrlenter" ConfigKey_TermMacOptionIsMeta = "term:macoptionismeta" ConfigKey_TermCursor = "term:cursor" ConfigKey_TermCursorBlink = "term:cursorblink" diff --git a/pkg/wconfig/settingsconfig.go b/pkg/wconfig/settingsconfig.go index 67118b1670..7ba63094bc 100644 --- a/pkg/wconfig/settingsconfig.go +++ b/pkg/wconfig/settingsconfig.go @@ -103,6 +103,7 @@ type SettingsType struct { TermTransparency *float64 `json:"term:transparency,omitempty"` TermAllowBracketedPaste *bool `json:"term:allowbracketedpaste,omitempty"` TermShiftEnterNewline *bool `json:"term:shiftenternewline,omitempty"` + TermCtrlEnter *bool `json:"term:ctrlenter,omitempty"` TermMacOptionIsMeta *bool `json:"term:macoptionismeta,omitempty"` TermCursor string `json:"term:cursor,omitempty"` TermCursorBlink *bool `json:"term:cursorblink,omitempty"` diff --git a/schema/settings.json b/schema/settings.json index f341a0f365..812514ab50 100644 --- a/schema/settings.json +++ b/schema/settings.json @@ -143,6 +143,9 @@ "term:shiftenternewline": { "type": "boolean" }, + "term:ctrlenter": { + "type": "boolean" + }, "term:macoptionismeta": { "type": "boolean" }, diff --git a/schema/widgets.json b/schema/widgets.json index 1c55fd8e09..1aea98b5ec 100644 --- a/schema/widgets.json +++ b/schema/widgets.json @@ -151,6 +151,9 @@ "term:shiftenternewline": { "type": "boolean" }, + "term:ctrlenter": { + "type": "boolean" + }, "term:macoptionismeta": { "type": "boolean" },