use crate::server::ui::Mode;
use crate::server::{ClientId, Server, frame_bytes};
const KEYS_BY_PLACE: &[u8] = b"\x1b[=29;1u";
const KEYS_ASK: &[u8] = b"\x1b[?u";
const KEYS_AS_TEXT: &[u8] = b"\x1b[=5;1u";
const BY_PLACE: u32 = 4 | 8 | 16;
impl Server {
pub(in crate::server) fn follow_keyboard(&mut self) {
for c in self.clients.values_mut().filter(|c| c.attached) {
let wants = matches!(c.mode, Mode::Leader { .. }) && c.keys_full != Some(false);
if c.keys_by_place == wants {
continue;
}
let mut bytes = if wants { KEYS_BY_PLACE.to_vec() } else { KEYS_AS_TEXT.to_vec() };
if wants && c.keys_full.is_none() {
bytes.extend_from_slice(KEYS_ASK);
}
if c.out.try_send(frame_bytes(&bytes)).is_ok() {
c.keys_by_place = wants;
}
}
}
pub(super) fn keyboard_reply(&mut self, id: ClientId, raw: &[u8]) -> bool {
let Some(flags) = raw
.strip_prefix(b"\x1b[?")
.and_then(|r| r.strip_suffix(b"u"))
.and_then(|d| std::str::from_utf8(d).ok())
.and_then(|d| d.parse::<u32>().ok())
else {
return false;
};
if let Some(c) = self.clients.get_mut(&id) {
c.keys_full = Some(flags & BY_PLACE == BY_PLACE);
}
self.follow_keyboard();
true
}
}