WayVR: Clean-up destroyed toplevel windows

This commit is contained in:
Aleksander
2025-03-09 22:04:46 +01:00
parent ed804820e9
commit 05b3baa5d9
4 changed files with 67 additions and 23 deletions

View File

@@ -157,6 +157,13 @@ impl XdgShellHandler for Application {
surface.send_configure(); surface.send_configure();
} }
fn toplevel_destroyed(&mut self, surface: ToplevelSurface) {
if let Some(client) = surface.wl_surface().client() {
self.wayvr_tasks
.send(WayVRTask::DropToplevel(client.id(), surface.clone()));
}
}
fn new_popup(&mut self, _surface: PopupSurface, _positioner: PositionerState) { fn new_popup(&mut self, _surface: PopupSurface, _positioner: PositionerState) {
// Handle popup creation here // Handle popup creation here
} }

View File

@@ -183,6 +183,11 @@ impl Display {
self.reposition_windows(); self.reposition_windows();
} }
pub fn remove_window(&mut self, window_handle: window::WindowHandle) {
self.displayed_windows
.retain(|disp| disp.window_handle != window_handle);
}
pub fn reposition_windows(&mut self) { pub fn reposition_windows(&mut self) {
let window_count = self.displayed_windows.len(); let window_count = self.displayed_windows.len();

View File

@@ -73,6 +73,7 @@ pub struct ExternalProcessRequest {
#[derive(Clone)] #[derive(Clone)]
pub enum WayVRTask { pub enum WayVRTask {
NewToplevel(ClientId, ToplevelSurface), NewToplevel(ClientId, ToplevelSurface),
DropToplevel(ClientId, ToplevelSurface),
NewExternalProcess(ExternalProcessRequest), NewExternalProcess(ExternalProcessRequest),
DropOverlay(super::overlay::OverlayID), DropOverlay(super::overlay::OverlayID),
ProcessTerminationRequest(process::ProcessHandle), ProcessTerminationRequest(process::ProcessHandle),
@@ -350,32 +351,59 @@ impl WayVR {
continue; continue;
} }
if let Some(process_handle) = let Some(process_handle) =
process::find_by_pid(&self.state.processes, client.pid) process::find_by_pid(&self.state.processes, client.pid)
{ else {
log::error!(
"WayVR window creation failed: Unexpected process ID {}. It wasn't registered before.",
client.pid
);
continue;
};
let window_handle = self let window_handle = self
.state .state
.wm .wm
.borrow_mut() .borrow_mut()
.create_window(client.display_handle, &toplevel); .create_window(client.display_handle, &toplevel);
if let Some(display) = let Some(display) = self.state.displays.get_mut(&client.display_handle)
self.state.displays.get_mut(&client.display_handle) else {
{ // This shouldn't happen, scream if it does
log::error!("Could not attach window handle into display");
continue;
};
display.add_window(window_handle, process_handle, &toplevel); display.add_window(window_handle, process_handle, &toplevel);
self.state.signals.send(WayVRSignal::BroadcastStateChanged( self.state.signals.send(WayVRSignal::BroadcastStateChanged(
packet_server::WvrStateChanged::WindowCreated, packet_server::WvrStateChanged::WindowCreated,
)); ));
} else {
// This shouldn't happen, scream if it does
log::error!("Could not attach window handle into display");
} }
} else {
log::error!(
"WayVR window creation failed: Unexpected process ID {}. It wasn't registered before.",
client.pid
);
} }
WayVRTask::DropToplevel(client_id, toplevel) => {
for client in &self.state.manager.clients {
if client.client.id() != client_id {
continue;
}
let mut wm = self.state.wm.borrow_mut();
let Some(window_handle) = wm.find_window_handle(&toplevel) else {
log::warn!("DropToplevel: Couldn't find matching window handle");
continue;
};
let Some(display) = self.state.displays.get_mut(&client.display_handle)
else {
log::warn!("DropToplevel: Couldn't find matching display");
continue;
};
display.remove_window(window_handle);
wm.remove_window(window_handle);
drop(wm);
display.reposition_windows();
} }
} }
WayVRTask::ProcessTerminationRequest(process_handle) => { WayVRTask::ProcessTerminationRequest(process_handle) => {

View File

@@ -77,6 +77,10 @@ impl WindowManager {
) -> WindowHandle { ) -> WindowHandle {
self.windows.add(Window::new(display_handle, toplevel)) self.windows.add(Window::new(display_handle, toplevel))
} }
pub fn remove_window(&mut self, window_handle: WindowHandle) {
self.windows.remove(&window_handle);
}
} }
gen_id!(WindowVec, Window, WindowCell, WindowHandle); gen_id!(WindowVec, Window, WindowCell, WindowHandle);