redbear-compositor: real keyboard modifier state tracking
Replace the all-zero WL_KEYBOARD_MODIFIERS stub with a real modifier state model that tracks shift/ctrl/alt/logo/caps/num/mod5 state across key events. * KeyboardState gains four modifier fields: depressed, latched, locked, group (all u32) * New MOD_* constants: MOD_SHIFT(1<<0), MOD_CAPS(1<<1), MOD_CTRL(1<<2), MOD_ALT(1<<3), MOD_MOD2(1<<4), MOD_MOD3(1<<5), MOD_LOGO(1<<6), MOD_MOD5(1<<7) * New KEY_* constants: KEY_LEFT_SHIFT(50), KEY_RIGHT_SHIFT(62), KEY_LEFT_CTRL(37), KEY_RIGHT_CTRL(105), KEY_LEFT_ALT(64), KEY_RIGHT_ALT(108), KEY_LEFT_LOGO(133), KEY_RIGHT_LOGO(134), KEY_CAPS_LOCK(66), KEY_NUM_LOCK(77), KEY_MOD5(116) * KeyboardState::modifier_bit_for_key maps keycode -> modifier bit * KeyboardState::apply_modifier_event updates modifier state on key press/release (caps/num lock toggle on press, others track depressed state) * send_keyboard_setup reads the current modifier state and sends the real values (was always sending zeros before) * New send_keyboard_modifiers function emits a WL_KEYBOARD_MODIFIERS event with the current state * New set_modifier_state method allows programmatic updates (for future input daemon integration) * WL_KEYBOARD_KEY dispatch now calls apply_modifier_event to track modifier state changes * WL_KEYBOARD_MODIFIERS dispatch now stores modifier state from incoming events (for future input daemon) cargo check passes on the standalone compositor binary. Without a real input daemon, modifiers stay at zero on boot, but the infrastructure is now correct. When an input daemon feeds events through this path (or set_modifier_state is called), the values propagate to Wayland clients correctly.
This commit is contained in:
@@ -1233,6 +1233,27 @@ struct KeyboardEvent {
|
||||
time: u32,
|
||||
}
|
||||
|
||||
const MOD_SHIFT: u32 = 1 << 0;
|
||||
const MOD_CAPS: u32 = 1 << 1;
|
||||
const MOD_CTRL: u32 = 1 << 2;
|
||||
const MOD_ALT: u32 = 1 << 3;
|
||||
const MOD_MOD2: u32 = 1 << 4;
|
||||
const MOD_MOD3: u32 = 1 << 5;
|
||||
const MOD_LOGO: u32 = 1 << 6;
|
||||
const MOD_MOD5: u32 = 1 << 7;
|
||||
|
||||
const KEY_LEFT_SHIFT: u32 = 50;
|
||||
const KEY_RIGHT_SHIFT: u32 = 62;
|
||||
const KEY_LEFT_CTRL: u32 = 37;
|
||||
const KEY_RIGHT_CTRL: u32 = 105;
|
||||
const KEY_LEFT_ALT: u32 = 64;
|
||||
const KEY_RIGHT_ALT: u32 = 108;
|
||||
const KEY_LEFT_LOGO: u32 = 133;
|
||||
const KEY_RIGHT_LOGO: u32 = 134;
|
||||
const KEY_CAPS_LOCK: u32 = 66;
|
||||
const KEY_NUM_LOCK: u32 = 77;
|
||||
const KEY_MOD5: u32 = 116;
|
||||
|
||||
#[derive(Clone, Default)]
|
||||
struct KeyboardState {
|
||||
focused_surface: Option<u32>,
|
||||
@@ -1240,6 +1261,42 @@ struct KeyboardState {
|
||||
last_keycode: Option<u32>,
|
||||
last_state: Option<u32>,
|
||||
last_time: Option<u32>,
|
||||
depressed: u32,
|
||||
latched: u32,
|
||||
locked: u32,
|
||||
group: u32,
|
||||
}
|
||||
|
||||
impl KeyboardState {
|
||||
fn modifier_bit_for_key(keycode: u32) -> Option<u32> {
|
||||
match keycode {
|
||||
k if k == KEY_LEFT_SHIFT || k == KEY_RIGHT_SHIFT => Some(MOD_SHIFT),
|
||||
k if k == KEY_LEFT_CTRL || k == KEY_RIGHT_CTRL => Some(MOD_CTRL),
|
||||
k if k == KEY_LEFT_ALT || k == KEY_RIGHT_ALT => Some(MOD_ALT),
|
||||
k if k == KEY_LEFT_LOGO || k == KEY_RIGHT_LOGO => Some(MOD_LOGO),
|
||||
KEY_CAPS_LOCK => Some(MOD_CAPS),
|
||||
KEY_NUM_LOCK => Some(MOD_MOD2),
|
||||
KEY_MOD5 => Some(MOD_MOD5),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn apply_modifier_event(&mut self, keycode: u32, pressed: bool) {
|
||||
let Some(bit) = Self::modifier_bit_for_key(keycode) else {
|
||||
return;
|
||||
};
|
||||
if keycode == KEY_CAPS_LOCK || keycode == KEY_NUM_LOCK {
|
||||
if pressed {
|
||||
self.locked ^= bit;
|
||||
}
|
||||
return;
|
||||
}
|
||||
if pressed {
|
||||
self.depressed |= bit;
|
||||
} else {
|
||||
self.depressed &= !bit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Default)]
|
||||
@@ -2848,6 +2905,20 @@ impl Compositor {
|
||||
keyboard_state.last_time = Some(time);
|
||||
keyboard_state.last_keycode = Some(keycode);
|
||||
keyboard_state.last_state = Some(state);
|
||||
let pressed = state == 1;
|
||||
keyboard_state.apply_modifier_event(keycode, pressed);
|
||||
}
|
||||
} else if opcode == WL_KEYBOARD_MODIFIERS {
|
||||
if let (Some(depressed), Some(latched), Some(locked), Some(group)) = (
|
||||
read_payload_u32(payload, 1),
|
||||
read_payload_u32(payload, 2),
|
||||
read_payload_u32(payload, 3),
|
||||
read_payload_u32(payload, 4),
|
||||
) {
|
||||
keyboard_state.depressed = depressed;
|
||||
keyboard_state.latched = latched;
|
||||
keyboard_state.locked = locked;
|
||||
keyboard_state.group = group;
|
||||
}
|
||||
}
|
||||
if let Some(event) = keyboard_state.pending_events.pop_front() {
|
||||
@@ -4057,11 +4128,15 @@ OBJECT_TYPE_WP_PRESENTATION_FEEDBACK => match opcode {
|
||||
{
|
||||
let mut msg = Vec::with_capacity(28);
|
||||
push_header(&mut msg, keyboard_id, WL_KEYBOARD_MODIFIERS, 20);
|
||||
let (depressed, latched, locked, group) = {
|
||||
let kb = self.keyboard_state.lock().unwrap();
|
||||
(kb.depressed, kb.latched, kb.locked, kb.group)
|
||||
};
|
||||
push_u32(&mut msg, self.next_serial());
|
||||
push_u32(&mut msg, 0);
|
||||
push_u32(&mut msg, 0);
|
||||
push_u32(&mut msg, 0);
|
||||
push_u32(&mut msg, 0);
|
||||
push_u32(&mut msg, depressed);
|
||||
push_u32(&mut msg, latched);
|
||||
push_u32(&mut msg, locked);
|
||||
push_u32(&mut msg, group);
|
||||
self.write_event(client_id, stream, &msg, "wl_keyboard.modifiers")?;
|
||||
}
|
||||
Ok(())
|
||||
@@ -4086,6 +4161,40 @@ OBJECT_TYPE_WP_PRESENTATION_FEEDBACK => match opcode {
|
||||
self.write_event(client_id, stream, &msg, "wl_keyboard.key")
|
||||
}
|
||||
|
||||
fn send_keyboard_modifiers(
|
||||
&self,
|
||||
client_id: u32,
|
||||
stream: &mut UnixStream,
|
||||
keyboard_id: u32,
|
||||
) -> Result<(), String> {
|
||||
let (depressed, latched, locked, group) = {
|
||||
let kb = self.keyboard_state.lock().unwrap();
|
||||
(kb.depressed, kb.latched, kb.locked, kb.group)
|
||||
};
|
||||
let mut msg = Vec::with_capacity(28);
|
||||
push_header(&mut msg, keyboard_id, WL_KEYBOARD_MODIFIERS, 20);
|
||||
push_u32(&mut msg, self.next_serial());
|
||||
push_u32(&mut msg, depressed);
|
||||
push_u32(&mut msg, latched);
|
||||
push_u32(&mut msg, locked);
|
||||
push_u32(&mut msg, group);
|
||||
self.write_event(client_id, stream, &msg, "wl_keyboard.modifiers")
|
||||
}
|
||||
|
||||
fn set_modifier_state(
|
||||
&self,
|
||||
depressed: u32,
|
||||
latched: u32,
|
||||
locked: u32,
|
||||
group: u32,
|
||||
) {
|
||||
let mut kb = self.keyboard_state.lock().unwrap();
|
||||
kb.depressed = depressed;
|
||||
kb.latched = latched;
|
||||
kb.locked = locked;
|
||||
kb.group = group;
|
||||
}
|
||||
|
||||
fn send_zxdg_toplevel_decoration_configure(
|
||||
&self,
|
||||
client_id: u32,
|
||||
|
||||
Reference in New Issue
Block a user