Skip to content

Instantly share code, notes, and snippets.

@scturtle
Created February 27, 2026 01:55
Show Gist options
  • Select an option

  • Save scturtle/6e7184176a067ac31c3dd5c31ce2a861 to your computer and use it in GitHub Desktop.

Select an option

Save scturtle/6e7184176a067ac31c3dd5c31ce2a861 to your computer and use it in GitHub Desktop.
kitty keyboard protocol demo
#include <poll.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <termios.h>
#include <unistd.h>
struct termios orig_termios;
void reset_terminal() {
printf("\033[<u\033[?25h"); // 退出 KKP 并显示光标
tcsetattr(STDIN_FILENO, TCSANOW, &orig_termios);
fflush(stdout);
}
void set_terminal() {
tcgetattr(STDIN_FILENO, &orig_termios);
atexit(reset_terminal);
struct termios raw = orig_termios;
raw.c_lflag &= ~(ECHO | ICANON | ISIG);
tcsetattr(STDIN_FILENO, TCSANOW, &raw);
printf("\033[?25l\033[>11u"); // 隐藏光标开启 KKP
fflush(stdout);
}
const char *get_mods(int m) {
static char buf[32];
m -= 1; // modifier = mask + 1
snprintf(buf, sizeof(buf), "%s%s%s%s", (m & 1) ? "Shift " : "",
(m & 2) ? "Alt " : "", (m & 4) ? "Ctrl " : "",
(m & 8) ? "Super " : "");
return buf;
}
int main() {
set_terminal();
printf("Kitty Keyboard Protocol Demo. Press 'q' or 'ESC' to exit.\r\n");
while (1) {
unsigned char buf[64];
int n = read(STDIN_FILENO, buf, sizeof(buf) - 1);
if (n <= 0)
continue;
buf[n] = '\0';
if (buf[0] == 27 && n > 1 && buf[1] == '[') {
int code = 0, mods = 1, event = 1;
char cmd = buf[n - 1];
const char *evtname[] = {"", "PRESS", "REPEAT", "RELEASE"};
if (cmd == 'u' || (cmd >= 'A' && cmd <= 'Z')) {
if (sscanf((char *)buf + 2, "%d;%d:%d", &code, &mods, &event) < 3)
if (sscanf((char *)buf + 2, "%d;%d", &code, &mods) < 2)
sscanf((char *)buf + 2, "%d", &code);
if (cmd == 'u') {
printf("[%7s] Key: %-10d | Mods: %s\n",
evtname[event > 3 ? 0 : event], code, get_mods(mods));
if (code == 'q' || code == 27)
break;
} else if (cmd >= 'A' && cmd <= 'Z') {
const char *arrow[] = {"UP", "DOWN", "RIGHT", "LEFT"};
printf("[%7s] Key: %-10s | Mods: %s\n",
evtname[event > 3 ? 0 : event], arrow[cmd - 'A'],
get_mods(mods));
}
} else {
printf("Other CSI: %s\r\n", buf + 1);
}
} else if (buf[0] == 27 && n == 1) {
printf("Legacy ESC pressed.\r\n");
break;
} else {
printf("Legacy Char: %c (%d)\r\n", buf[0] >= 32 ? buf[0] : '.', buf[0]);
if (buf[0] == 'q')
break;
}
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment