server: verify window still exists when processing surface serial
Should fix #191
This commit is contained in:
parent
91d463851e
commit
0b2a139f98
3 changed files with 63 additions and 10 deletions
|
|
@ -1,5 +1,5 @@
|
||||||
use super::*;
|
use super::*;
|
||||||
use hecs::CommandBuffer;
|
use hecs::{CommandBuffer, DynamicBundle};
|
||||||
use log::{debug, error, trace, warn};
|
use log::{debug, error, trace, warn};
|
||||||
use macros::simple_event_shunt;
|
use macros::simple_event_shunt;
|
||||||
use std::sync::{Arc, OnceLock};
|
use std::sync::{Arc, OnceLock};
|
||||||
|
|
@ -1435,13 +1435,19 @@ impl<C: XConnection> Dispatch<XwaylandSurfaceV1, Entity> for ServerState<C> {
|
||||||
.map(|i| i.0);
|
.map(|i| i.0);
|
||||||
|
|
||||||
if let Some(win_entity) = win_entity {
|
if let Some(win_entity) = win_entity {
|
||||||
let win = *state.world.get::<&x::Window>(win_entity).unwrap();
|
let bundle = state.world.take(win_entity).unwrap();
|
||||||
debug!("associate {surface_id} with {win:?}");
|
if !bundle.has::<x::Window>() {
|
||||||
state.windows.insert(win, *entity);
|
warn!("Window with same serial ({serial:?}) as {surface_id} has been destroyed?");
|
||||||
|
return;
|
||||||
|
}
|
||||||
let mut builder = hecs::EntityBuilder::new();
|
let mut builder = hecs::EntityBuilder::new();
|
||||||
builder.add_bundle(state.world.take(win_entity).unwrap());
|
builder.add_bundle(bundle);
|
||||||
state.world.insert(*entity, builder.build()).unwrap();
|
state.world.insert(*entity, builder.build()).unwrap();
|
||||||
|
state.world.remove_one::<SurfaceSerial>(*entity).unwrap();
|
||||||
let data = state.world.entity(*entity).unwrap();
|
let data = state.world.entity(*entity).unwrap();
|
||||||
|
let win = data.get::<&x::Window>().as_deref().copied().unwrap();
|
||||||
|
state.windows.insert(win, *entity);
|
||||||
|
debug!("associate {surface_id} with {win:?} (serial {serial:?})");
|
||||||
if data.get::<&WindowData>().unwrap().mapped {
|
if data.get::<&WindowData>().unwrap().mapped {
|
||||||
state.create_role_window(win, *entity);
|
state.create_role_window(win, *entity);
|
||||||
}
|
}
|
||||||
|
|
@ -1449,9 +1455,7 @@ impl<C: XConnection> Dispatch<XwaylandSurfaceV1, Entity> for ServerState<C> {
|
||||||
state.world.insert(*entity, (serial,)).unwrap();
|
state.world.insert(*entity, (serial,)).unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Request::Destroy => {
|
Request::Destroy => {}
|
||||||
state.world.remove_one::<SurfaceSerial>(*entity).unwrap();
|
|
||||||
}
|
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -172,7 +172,7 @@ struct SurfaceAttach {
|
||||||
y: i32,
|
y: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Eq)]
|
#[derive(PartialEq, Eq, Debug)]
|
||||||
struct SurfaceSerial([u32; 2]);
|
struct SurfaceSerial([u32; 2]);
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
|
@ -749,7 +749,7 @@ impl<C: XConnection> ServerState<C> {
|
||||||
if dims == win.attrs.dims {
|
if dims == win.attrs.dims {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
debug!("Reconfiguring {win:?} {:?}", dims);
|
debug!("Reconfiguring {:?} {:?}", event.window(), dims);
|
||||||
if !win.mapped {
|
if !win.mapped {
|
||||||
win.attrs.dims = dims;
|
win.attrs.dims = dims;
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -2444,6 +2444,55 @@ fn quick_empty_data_offer() {
|
||||||
let selection = f.satellite.new_selection();
|
let selection = f.satellite.new_selection();
|
||||||
assert!(selection.is_none());
|
assert!(selection.is_none());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn quick_destroy_window_with_serial() {
|
||||||
|
let (mut f, comp) = TestFixture::new_with_compositor();
|
||||||
|
|
||||||
|
let window = unsafe { Window::new(1) };
|
||||||
|
let data = WindowData {
|
||||||
|
mapped: true,
|
||||||
|
dims: WindowDims {
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
width: 50,
|
||||||
|
height: 50,
|
||||||
|
},
|
||||||
|
fullscreen: false,
|
||||||
|
};
|
||||||
|
f.new_window(window, false, data);
|
||||||
|
f.satellite.map_window(window);
|
||||||
|
|
||||||
|
let (_, surface) = comp.create_surface();
|
||||||
|
let xwl = TestObject::<XwaylandSurfaceV1>::from_request(
|
||||||
|
&comp.shell.obj,
|
||||||
|
Req::<XwaylandShellV1>::GetXwaylandSurface {
|
||||||
|
surface: surface.clone(),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
let serial = f.surface_serial;
|
||||||
|
let serial_lo = (serial & 0xFF) as u32;
|
||||||
|
let serial_hi = ((serial >> 8) & 0xFF) as u32;
|
||||||
|
xwl.send_request(Req::<XwaylandSurfaceV1>::SetSerial {
|
||||||
|
serial_lo,
|
||||||
|
serial_hi,
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
f.satellite
|
||||||
|
.set_window_serial(window, [serial_lo, serial_hi]);
|
||||||
|
f.satellite.unmap_window(window);
|
||||||
|
f.satellite.destroy_window(window);
|
||||||
|
f.run();
|
||||||
|
|
||||||
|
let id = f.testwl.last_created_surface_id().unwrap();
|
||||||
|
let surface_data = f.testwl.get_surface_data(id).unwrap();
|
||||||
|
assert!(
|
||||||
|
surface_data.role.is_none(),
|
||||||
|
"Surface unexpectedly has role: {:?}",
|
||||||
|
surface_data.role
|
||||||
|
);
|
||||||
|
}
|
||||||
/// See Pointer::handle_event for an explanation.
|
/// See Pointer::handle_event for an explanation.
|
||||||
#[test]
|
#[test]
|
||||||
fn popup_pointer_motion_workaround() {}
|
fn popup_pointer_motion_workaround() {}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue