Add 'effective utf8' field to ncinput struct. This field will contain the utf8 emitted by a key with all modifiers taken into account.

pull/2696/head
Jeroen Domburg 1 year ago
parent 90135203e8
commit d8c9081fe0

@ -37,6 +37,7 @@ typedef struct ncinput {
ncintype_e evtype;
unsigned modifiers;// bitmask over NCKEY_MOD_*
int ypx, xpx; // pixel offsets within cell, -1 for undefined
char utf8_eff[5]; // Effective utf8 representation, taking modifier keys into account
} ncinput;
@ -242,6 +243,12 @@ issues are resolved. You can determine whether the protocol is in use
by examining the output of **notcurses-info(1)**. If the **kbd** property
is indicated, you're using the Kitty protocol.
Note that utf_eff will always return the effective text value of the key,
taking into account any meta keys pressed. (So shift-a will always return
'A' in this field, regardless of if the Kitty keyboard disambiguation
protocol is used.) This field generally only can be trusted on
**NCTYPE_PRESS** and **NCTYPE_REPEAT** events, however.
Mouse events in the left margins will never be delivered to the
application (as is intended), but mouse events in the bottom and right margins
sometimes can be if the event occurs prior to a window resize.

@ -1214,6 +1214,7 @@ typedef struct ncinput {
ncintype_e evtype;
unsigned modifiers;// bitmask over NCKEY_MOD_*
int ypx, xpx; // pixel offsets within cell, -1 for undefined
char utf8_eff[5]; // Effective utf8 representation, taking modifier keys into account
} ncinput;
static inline bool

@ -797,7 +797,7 @@ kitty_functional(uint32_t val){
}
static void
kitty_kbd(inputctx* ictx, int val, int mods, int evtype){
kitty_kbd_txt(inputctx* ictx, int val, int mods, unsigned *txt, int evtype){
assert(evtype >= 0);
assert(mods >= 0);
assert(val > 0);
@ -830,9 +830,33 @@ kitty_kbd(inputctx* ictx, int val, int mods, int evtype){
tni.evtype = NCTYPE_UNKNOWN;
break;
}
// Validate the txt array. It needs to be a non-zero-length set of up to 4 bytes.
int txt_valid = 0;
if(txt){
for (int i = 0 ; i<4 ; i++){
if(txt[i]==0) break;
if(txt[i]>255){
txt_valid = 0;
break;
}
txt_valid = 1;
}
}
//note: if we don't populate .utf8_eff here, it will be set to what becomes .utf8 in
//internal_get().
if(txt_valid){
for(int i=0 ; i<4 ; i++){
tni.utf8_eff[i] = (char)txt[i];
}
}
load_ncinput(ictx, &tni);
}
static void
kitty_kbd(inputctx* ictx, int val, int mods, int evtype){
kitty_kbd_txt(ictx, val, mods, NULL, evtype);
}
static int
kitty_cb_simple(inputctx* ictx){
unsigned val = amata_next_numeric(&ictx->amata, "\x1b[", 'u');
@ -849,6 +873,66 @@ kitty_cb(inputctx* ictx){
return 2;
}
static int
kitty_cb_atxtn(inputctx* ictx, int n, int with_event){
unsigned txt[5]={0};
unsigned val = amata_next_numeric(&ictx->amata, "\x1b[", ';');
unsigned ev = 0;
unsigned mods = 0;
if (with_event) {
mods = amata_next_numeric(&ictx->amata, "", ':');
ev = amata_next_numeric(&ictx->amata, "", ';');
} else {
mods = amata_next_numeric(&ictx->amata, "", ';');
}
for (int i = 0; i<n; i++) {
txt[i] = amata_next_numeric(&ictx->amata, "", (i==n-1)?'u':';');
}
kitty_kbd_txt(ictx, val, mods, txt, ev);
return 2;
}
static int
kitty_cb_atxt1(inputctx* ictx){
return kitty_cb_atxtn(ictx, 1, 0);
}
static int
kitty_cb_atxt2(inputctx* ictx){
return kitty_cb_atxtn(ictx, 2, 0);
}
static int
kitty_cb_atxt3(inputctx* ictx){
return kitty_cb_atxtn(ictx, 3, 0);
}
static int
kitty_cb_atxt4(inputctx* ictx){
return kitty_cb_atxtn(ictx, 4, 0);
}
static int
kitty_cb_complex_atxt1(inputctx* ictx){
return kitty_cb_atxtn(ictx, 1, 1);
}
static int
kitty_cb_complex_atxt2(inputctx* ictx){
return kitty_cb_atxtn(ictx, 2, 1);
}
static int
kitty_cb_complex_atxt3(inputctx* ictx){
return kitty_cb_atxtn(ictx, 3, 1);
}
static int
kitty_cb_complex_atxt4(inputctx* ictx){
return kitty_cb_atxtn(ictx, 4, 1);
}
static uint32_t
legacy_functional(uint32_t id){
switch(id){
@ -1702,7 +1786,15 @@ build_cflow_automaton(inputctx* ictx){
{ "[\\Nu", kitty_cb_simple, },
{ "[\\N;\\N~", wezterm_cb, },
{ "[\\N;\\Nu", kitty_cb, },
{ "[\\N;\\N;\\Nu", kitty_cb_atxt1, },
{ "[\\N;\\N;\\N;\\Nu", kitty_cb_atxt2, },
{ "[\\N;\\N;\\N;\\N;\\Nu", kitty_cb_atxt3, },
{ "[\\N;\\N;\\N;\\N;\\N;\\Nu", kitty_cb_atxt4, },
{ "[\\N;\\N:\\Nu", kitty_cb_complex, },
{ "[\\N;\\N:\\N;\\Nu", kitty_cb_complex_atxt1, },
{ "[\\N;\\N:\\N;\\N;\\Nu", kitty_cb_complex_atxt2, },
{ "[\\N;\\N:\\N;\\N;\\N;\\Nu", kitty_cb_complex_atxt3, },
{ "[\\N;\\N:\\N;\\N;\\N;\\N;\\Nu", kitty_cb_complex_atxt4, },
{ "[\\N;\\N;\\N~", xtmodkey_cb, },
{ "[\\N;\\N:\\N~", kitty_cb_functional, },
{ "[1;\\NP", legacy_cb_f1, },
@ -2617,6 +2709,9 @@ internal_get(inputctx* ictx, const struct timespec* ts, ncinput* ni){
if(notcurses_ucs32_to_utf8(&ni->id, 1, (unsigned char*)ni->utf8, sizeof(ni->utf8)) < 0){
ni->utf8[0] = 0;
}
if(ni->utf8_eff[0] == 0){
memcpy(ni->utf8_eff, ni->utf8, sizeof(ni->utf8_eff));
}
}
if(++ictx->iread == ictx->isize){
ictx->iread = 0;

@ -400,12 +400,8 @@ bool ncreader_offer_input(ncreader* n, const ncinput* ni){
}else if(nckey_synthesized_p(ni->id)){
return false;
}
// FIXME need to collect full EGCs
char wbuf[WCHAR_MAX_UTF8BYTES + 1];
// FIXME breaks for wint_t < 32bits
if(snprintf(wbuf, sizeof(wbuf), "%lc", (wint_t)ni->id) < (int)sizeof(wbuf)){
ncreader_write_egc(n, wbuf);
}
ncreader_write_egc(n, ni->utf8_eff);
return true;
}

@ -351,9 +351,9 @@ init_terminfo_esc(tinfo* ti, const char* name, escape_e idx,
#define KITTYQUERY
#endif
// request kitty keyboard protocol features 1, 2, and 8, first pushing current.
// request kitty keyboard protocol features 1, 2, 8 and 16, first pushing current.
// see https://sw.kovidgoyal.net/kitty/keyboard-protocol/#progressive-enhancement
#define KKBDSUPPORT "\x1b[=11u"
#define KKBDSUPPORT "\x1b[=27u"
// the kitty keyboard protocol allows unambiguous, complete identification of
// input events. this queries for the level of support. we want to do this

Loading…
Cancel
Save