fix(vt): report modern primary device attributes
- commit
- 16f5a24a32bd1fd3f5cfcec8c42c3c7ab5552b12
- author
- brice · · 2026-08-26 10:43 UTC
- parent
- 6ace063
- signature
- GPG Verified
CD88F9E564E0102646FB6077A1A07C7C7C3E349D· arch-gpg Verified for the committer email
3 files · +8 -5
M query_test.go +3 -3
| @@ -13,8 +13,8 @@ func TestScreenQueryResponses(t *testing.T) { | |||
| 13 | 13 | input string | |
| 14 | 14 | want string | |
| 15 | 15 | }{ | |
| 16 | - | {name: "primary DA bare", input: "\x1b[c", want: "\x1b[?6c"}, | |
| 17 | - | {name: "primary DA with 0", input: "\x1b[0c", want: "\x1b[?6c"}, | |
| 16 | + | {name: "primary DA bare", input: "\x1b[c", want: "\x1b[?62;22c"}, | |
| 17 | + | {name: "primary DA with 0", input: "\x1b[0c", want: "\x1b[?62;22c"}, | |
| 18 | 18 | {name: "secondary DA", input: "\x1b[>c", want: "\x1b[>0;0;0c"}, | |
| 19 | 19 | {name: "secondary DA with 0", input: "\x1b[>0c", want: "\x1b[>0;0;0c"}, | |
| 20 | 20 | {name: "DSR status report", input: "\x1b[5n", want: "\x1b[0n"}, | |
| @@ -35,7 +35,7 @@ func TestScreenQueryResponses(t *testing.T) { | |||
| 35 | 35 | {name: "DECRQM unknown mode", input: "\x1b[?1337$p", want: "\x1b[?1337;0$y"}, | |
| 36 | 36 | {name: "kitty keyboard query unanswered", input: "\x1b[?u", want: ""}, | |
| 37 | 37 | {name: "XTVERSION unanswered", input: "\x1b[>0q", want: ""}, | |
| 38 | - | {name: "DA split across writes", input: "", want: "\x1b[?6c"}, | |
| 38 | + | {name: "DA split across writes", input: "", want: "\x1b[?62;22c"}, | |
| 39 | 39 | } | |
| 40 | 40 | for _, tc := range cases { | |
| 41 | 41 | t.Run(tc.name, func(t *testing.T) { | |
| @@ -13,8 +13,8 @@ func TestScreenQueryResponses(t *testing.T) { | |||||
| 13 | input string | 13 | input string | ||
| 14 | want string | 14 | want string | ||
| 15 | }{ | 15 | }{ | ||
| 16 | - | {name: "primary DA bare", input: "\x1b[c", want: "\x1b[?6c"}, | 16 | + | {name: "primary DA bare", input: "\x1b[c", want: "\x1b[?62;22c"}, |
| 17 | - | {name: "primary DA with 0", input: "\x1b[0c", want: "\x1b[?6c"}, | 17 | + | {name: "primary DA with 0", input: "\x1b[0c", want: "\x1b[?62;22c"}, |
| 18 | {name: "secondary DA", input: "\x1b[>c", want: "\x1b[>0;0;0c"}, | 18 | {name: "secondary DA", input: "\x1b[>c", want: "\x1b[>0;0;0c"}, | ||
| 19 | {name: "secondary DA with 0", input: "\x1b[>0c", want: "\x1b[>0;0;0c"}, | 19 | {name: "secondary DA with 0", input: "\x1b[>0c", want: "\x1b[>0;0;0c"}, | ||
| 20 | {name: "DSR status report", input: "\x1b[5n", want: "\x1b[0n"}, | 20 | {name: "DSR status report", input: "\x1b[5n", want: "\x1b[0n"}, | ||
| @@ -35,7 +35,7 @@ func TestScreenQueryResponses(t *testing.T) { | |||||
| 35 | {name: "DECRQM unknown mode", input: "\x1b[?1337$p", want: "\x1b[?1337;0$y"}, | 35 | {name: "DECRQM unknown mode", input: "\x1b[?1337$p", want: "\x1b[?1337;0$y"}, | ||
| 36 | {name: "kitty keyboard query unanswered", input: "\x1b[?u", want: ""}, | 36 | {name: "kitty keyboard query unanswered", input: "\x1b[?u", want: ""}, | ||
| 37 | {name: "XTVERSION unanswered", input: "\x1b[>0q", want: ""}, | 37 | {name: "XTVERSION unanswered", input: "\x1b[>0q", want: ""}, | ||
| 38 | - | {name: "DA split across writes", input: "", want: "\x1b[?6c"}, | 38 | + | {name: "DA split across writes", input: "", want: "\x1b[?62;22c"}, |
| 39 | } | 39 | } | ||
| 40 | for _, tc := range cases { | 40 | for _, tc := range cases { | ||
| 41 | t.Run(tc.name, func(t *testing.T) { | 41 | t.Run(tc.name, func(t *testing.T) { | ||
M screen_csi.go +4 -1
| @@ -31,7 +31,10 @@ func (s *Screen) applyCSI(params string, cmd byte) { | |||
| 31 | 31 | case 'c': | |
| 32 | 32 | switch params { | |
| 33 | 33 | case "", "0": | |
| 34 | - | s.respond([]byte("\x1b[?6c")) | |
| 34 | + | // Identify as a VT220-compatible terminal with ANSI color. Modern | |
| 35 | + | // capability probes require a DA1 response with a conformance level; | |
| 36 | + | // the shorter VT102 response is ignored by kitten icat. | |
| 37 | + | s.respond([]byte("\x1b[?62;22c")) | |
| 35 | 38 | case ">", ">0": | |
| 36 | 39 | s.respond([]byte("\x1b[>0;0;0c")) | |
| 37 | 40 | } | |
| @@ -31,7 +31,10 @@ func (s *Screen) applyCSI(params string, cmd byte) { | |||||
| 31 | case 'c': | 31 | case 'c': | ||
| 32 | switch params { | 32 | switch params { | ||
| 33 | case "", "0": | 33 | case "", "0": | ||
| 34 | - | s.respond([]byte("\x1b[?6c")) | 34 | + | // Identify as a VT220-compatible terminal with ANSI color. Modern |
| 35 | + | // capability probes require a DA1 response with a conformance level; | |||
| 36 | + | // the shorter VT102 response is ignored by kitten icat. | |||
| 37 | + | s.respond([]byte("\x1b[?62;22c")) | |||
| 35 | case ">", ">0": | 38 | case ">", ">0": | ||
| 36 | s.respond([]byte("\x1b[>0;0;0c")) | 39 | s.respond([]byte("\x1b[>0;0;0c")) | ||
| 37 | } | 40 | } | ||
M screen_graphics_test.go +1 -1
| @@ -56,7 +56,7 @@ func TestScreenKittyIcatDetectionResponses(t *testing.T) { | |||
| 56 | 56 | "\x1b_Gi=1;OK\x1b\\", | |
| 57 | 57 | "\x1b_Gi=2;ENOTSUP\x1b\\", | |
| 58 | 58 | "\x1b_Gi=3;ENOTSUP\x1b\\", | |
| 59 | - | "\x1b[?6c", | |
| 59 | + | "\x1b[?62;22c", | |
| 60 | 60 | }, responses) | |
| 61 | 61 | } | |
| 62 | 62 | ||
| @@ -56,7 +56,7 @@ func TestScreenKittyIcatDetectionResponses(t *testing.T) { | |||||
| 56 | "\x1b_Gi=1;OK\x1b\\", | 56 | "\x1b_Gi=1;OK\x1b\\", | ||
| 57 | "\x1b_Gi=2;ENOTSUP\x1b\\", | 57 | "\x1b_Gi=2;ENOTSUP\x1b\\", | ||
| 58 | "\x1b_Gi=3;ENOTSUP\x1b\\", | 58 | "\x1b_Gi=3;ENOTSUP\x1b\\", | ||
| 59 | - | "\x1b[?6c", | 59 | + | "\x1b[?62;22c", |
| 60 | }, responses) | 60 | }, responses) | ||
| 61 | } | 61 | } | ||
| 62 | 62 | ||||