Use wl_keyboard instead of toplevel state for focus

Rare TODO comment actually done.
Fixes #64
This commit is contained in:
Shawn Wallace 2024-10-23 02:27:14 -04:00
parent 8703e243eb
commit dc1f8a753d
4 changed files with 80 additions and 29 deletions

View file

@ -161,6 +161,11 @@ struct Output {
xdg: Option<ZxdgOutputV1>,
}
struct KeyboardState {
keyboard: WlKeyboard,
current_focus: Option<SurfaceId>,
}
struct State {
surfaces: HashMap<SurfaceId, SurfaceData>,
outputs: HashMap<WlOutput, Output>,
@ -171,7 +176,7 @@ struct State {
last_output: Option<WlOutput>,
callbacks: Vec<WlCallback>,
pointer: Option<WlPointer>,
keyboard: Option<WlKeyboard>,
keyboard: Option<KeyboardState>,
configure_serial: u32,
selection: Option<WlDataSource>,
data_device_man: Option<WlDataDeviceManager>,
@ -209,15 +214,6 @@ impl State {
states: Vec<xdg_toplevel::State>,
) {
let last_serial = self.configure_serial;
if states.contains(&xdg_toplevel::State::Activated) {
if let Some(kb) = &self.keyboard {
kb.enter(
last_serial,
&self.surfaces[&surface_id].surface,
Vec::default(),
);
}
}
let toplevel = self.get_toplevel(surface_id);
toplevel.states = states.clone();
let states: Vec<u8> = states
@ -229,6 +225,38 @@ impl State {
self.configure_serial += 1;
}
#[track_caller]
fn focus_toplevel(&mut self, surface_id: SurfaceId) {
let KeyboardState {
keyboard,
current_focus,
} = self.keyboard.as_mut().expect("Keyboard should be created");
if let Some(id) = current_focus {
keyboard.leave(self.configure_serial, &self.surfaces[id].surface);
}
keyboard.enter(
self.configure_serial,
&self.surfaces[&surface_id].surface,
Vec::default(),
);
*current_focus = Some(surface_id);
}
#[track_caller]
fn unfocus_toplevel(&mut self) {
let KeyboardState {
current_focus,
keyboard,
} = self.keyboard.as_mut().expect("Keyboard should be created");
if let Some(id) = current_focus.take() {
keyboard.leave(self.configure_serial, &self.surfaces[&id].surface);
}
}
#[track_caller]
pub fn configure_popup(&mut self, surface_id: SurfaceId) {
let surface = self.surfaces.get_mut(&surface_id).unwrap();
@ -433,6 +461,18 @@ impl Server {
self.display.flush_clients().unwrap();
}
#[track_caller]
pub fn focus_toplevel(&mut self, surface_id: SurfaceId) {
self.state.focus_toplevel(surface_id);
self.display.flush_clients().unwrap();
}
#[track_caller]
pub fn unfocus_toplevel(&mut self) {
self.state.unfocus_toplevel();
self.display.flush_clients().unwrap();
}
#[track_caller]
pub fn configure_popup(&mut self, surface_id: SurfaceId) {
self.state.configure_popup(surface_id);
@ -825,7 +865,10 @@ impl Dispatch<WlSeat, ()> for State {
state.pointer = Some(data_init.init(id, ()));
}
wl_seat::Request::GetKeyboard { id } => {
state.keyboard = Some(data_init.init(id, ()));
state.keyboard = Some(KeyboardState {
keyboard: data_init.init(id, ()),
current_focus: None,
});
}
wl_seat::Request::Release => {}
other => todo!("unhandled request {other:?}"),
@ -1317,9 +1360,16 @@ impl Dispatch<WlSurface, ()> for State {
}
Commit => {}
Destroy => {
state
.surfaces
.remove(&SurfaceId(resource.id().protocol_id()));
let id = SurfaceId(resource.id().protocol_id());
if let Some(kb) = state
.keyboard
.as_mut()
.filter(|kb| kb.current_focus == Some(id))
{
kb.keyboard.leave(state.configure_serial, resource);
kb.current_focus.take();
}
state.surfaces.remove(&id);
}
SetInputRegion { .. } => {}
SetBufferScale { .. } => {}