diff --git a/csi.c b/csi.c index 0224dd80..45bf1a16 100644 --- a/csi.c +++ b/csi.c @@ -1444,6 +1444,16 @@ csi_dispatch(struct terminal *term, uint8_t final) break; } + case 'u': { + enum kitty_kbd_flags flags = + term->grid->kitty_kbd.flags[term->grid->kitty_kbd.idx]; + + char reply[8]; + int chars = snprintf(reply, sizeof(reply), "\033[?%uu", flags); + term_to_slave(term, reply, chars); + break; + } + default: UNHANDLED(); break; @@ -1532,6 +1542,26 @@ csi_dispatch(struct terminal *term, uint8_t final) } break; /* final == 'm' */ + case 'u': { + int flags = vt_param_get(term, 0, 0) & KITTY_KBD_MASK; + + struct grid *grid = term->grid; + uint8_t idx = grid->kitty_kbd.idx; + + if (idx + 1 >= ALEN(grid->kitty_kbd.flags)) { + /* Stack full, evict oldest by wrapping around */ + idx = 0; + } else + idx++; + + grid->kitty_kbd.flags[idx] = flags; + grid->kitty_kbd.idx = idx; + + xassert(grid->kitty_kbd.idx < ALEN(grid->kitty_kbd.flags)); + LOG_DBG("kitty kbd: pushed new mode: 0x%03x", flags); + break; + } + case 'q': { /* XTVERSION */ if (vt_param_get(term, 0, 0) != 0) { @@ -1556,6 +1586,37 @@ csi_dispatch(struct terminal *term, uint8_t final) break; /* private[0] == '>' */ } + case '<': { + switch (final) { + case 'u': { + int count = vt_param_get(term, 0, 1); + LOG_DBG("kitty kbd: popping %d levels of flags", count); + + struct grid *grid = term->grid; + uint8_t idx = grid->kitty_kbd.idx; + + for (int i = 0; i < count; i++) { + /* Reset flags. This ensures we get flags=0 when + * over-popping */ + grid->kitty_kbd.flags[idx] = 0; + + if (idx == 0) + idx = ALEN(grid->kitty_kbd.flags) - 1; + else + idx--; + } + + grid->kitty_kbd.idx = idx; + xassert(grid->kitty_kbd.idx < ALEN(grid->kitty_kbd.flags)); + + LOG_DBG("kitty kbd: mode after pop: 0x%03x", + term->grid->kitty_kbd.flags[idx]); + break; + } + } + break; /* private[0] == ‘<’ */ + } + case ' ': { switch (final) { case 'q': { @@ -1633,6 +1694,36 @@ csi_dispatch(struct terminal *term, uint8_t final) term_to_slave(term, "\033P!|464f4f54\033\\", 14); /* FOOT */ break; + case 'u': { + int flag_set = vt_param_get(term, 0, 0) & KITTY_KBD_MASK; + int mode = vt_param_get(term, 1, 1); + + struct grid *grid = term->grid; + uint8_t idx = grid->kitty_kbd.idx; + + switch (mode) { + case 1: + /* set bits are set, unset bits are reset */ + grid->kitty_kbd.flags[idx] = flag_set; + break; + + case 2: + /* set bits are set, unset bits are left unchanged */ + grid->kitty_kbd.flags[idx] |= flag_set; + break; + + case 3: + /* set bits are reset, unset bits are left unchanged */ + grid->kitty_kbd.flags[idx] &= ~flag_set; + break; + + default: + UNHANDLED(); + break; + } + break; + } + default: UNHANDLED(); break; diff --git a/terminal.c b/terminal.c index 03ff1898..a56ead03 100644 --- a/terminal.c +++ b/terminal.c @@ -1815,6 +1815,10 @@ term_reset(struct terminal *term, bool hard) tll_free_and_free(term->window_title_stack, free); term_set_window_title(term, term->conf->title); + memset(term->normal.kitty_kbd.flags, 0, sizeof(term->normal.kitty_kbd.flags)); + memset(term->alt.kitty_kbd.flags, 0, sizeof(term->alt.kitty_kbd.flags)); + term->normal.kitty_kbd.idx = term->alt.kitty_kbd.idx = 0; + term->scroll_region.start = 0; term->scroll_region.end = term->rows; diff --git a/terminal.h b/terminal.h index 3096186f..c20e30fc 100644 --- a/terminal.h +++ b/terminal.h @@ -127,6 +127,15 @@ struct sixel { bool opaque; }; +enum kitty_kbd_flags { + KITTY_KBD_DISAMBIGUATE = 0x01, + KITTY_KBD_REPORT_EVENT = 0x02, + KITTY_BKD_REPORT_ALTERNATE = 0x04, + KITTY_KBD_REPORT_ALL = 0x08, + KITTY_KBD_REPORT_ASSOCIATED = 0x10, + KITTY_KBD_MASK = 0x1f, +}; + struct grid { int num_rows; int num_cols; @@ -149,6 +158,12 @@ struct grid { tll(struct damage) scroll_damage; tll(struct sixel) sixel_images; + + struct { + enum kitty_kbd_flags flags[8]; + uint8_t idx; + } kitty_kbd; + }; struct vt_subparams {