it: test workspace restoration
This commit is contained in:
parent
9efe9415c2
commit
15a1b600f3
8 changed files with 165 additions and 53 deletions
|
|
@ -22,7 +22,7 @@ use {
|
|||
utils::{
|
||||
asyncevent::AsyncEvent, bitflags::BitflagsExt, clonecell::CloneCell,
|
||||
copyhashmap::CopyHashMap, debug_fn::debug_fn, errorfmt::ErrorFmt, numcell::NumCell,
|
||||
opaque_cell::OpaqueCell, oserror::OsError, syncqueue::SyncQueue,
|
||||
on_change::OnChange, opaque_cell::OpaqueCell, oserror::OsError,
|
||||
transform_ext::TransformExt,
|
||||
},
|
||||
video::{
|
||||
|
|
@ -320,38 +320,6 @@ impl Debug for ConnectorFutures {
|
|||
}
|
||||
}
|
||||
|
||||
pub struct OnChange<T> {
|
||||
pub on_change: CloneCell<Option<Rc<dyn Fn()>>>,
|
||||
pub events: SyncQueue<T>,
|
||||
}
|
||||
|
||||
impl<T> OnChange<T> {
|
||||
pub fn send_event(&self, event: T) {
|
||||
self.events.push(event);
|
||||
if let Some(cb) = self.on_change.get() {
|
||||
cb();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Default for OnChange<T> {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
on_change: Default::default(),
|
||||
events: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Debug for OnChange<T> {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
match self.on_change.get() {
|
||||
None => f.write_str("None"),
|
||||
Some(_) => f.write_str("Some"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct DirectScanoutCache {
|
||||
tex: Weak<dyn GfxTexture>,
|
||||
|
|
|
|||
|
|
@ -553,6 +553,11 @@ impl WlSurface {
|
|||
Ok(ext.into_xsurface().unwrap())
|
||||
}
|
||||
|
||||
#[cfg_attr(not(feature = "it"), allow(dead_code))]
|
||||
pub fn get_output(&self) -> Rc<OutputNode> {
|
||||
self.output.get()
|
||||
}
|
||||
|
||||
pub fn set_output(&self, output: &Rc<OutputNode>) {
|
||||
let old = self.output.set(output.clone());
|
||||
if old.id == output.id {
|
||||
|
|
|
|||
|
|
@ -14,7 +14,8 @@ use {
|
|||
state::State,
|
||||
time::now_usec,
|
||||
utils::{
|
||||
clonecell::CloneCell, copyhashmap::CopyHashMap, oserror::OsError, syncqueue::SyncQueue,
|
||||
clonecell::CloneCell, copyhashmap::CopyHashMap, on_change::OnChange, oserror::OsError,
|
||||
syncqueue::SyncQueue,
|
||||
},
|
||||
video::drm::{ConnectorType, Drm},
|
||||
},
|
||||
|
|
@ -39,6 +40,7 @@ pub enum TestBackendError {
|
|||
pub struct TestBackend {
|
||||
pub state: Rc<State>,
|
||||
pub test_future: TestFuture,
|
||||
pub default_monitor_info: MonitorInfo,
|
||||
pub default_connector: Rc<TestConnector>,
|
||||
pub default_mouse: Rc<TestBackendMouse>,
|
||||
pub default_kb: Rc<TestBackendKb>,
|
||||
|
|
@ -55,7 +57,6 @@ impl TestBackend {
|
|||
idx: 1,
|
||||
},
|
||||
events: Default::default(),
|
||||
on_change: Default::default(),
|
||||
});
|
||||
let default_mouse = Rc::new(TestBackendMouse {
|
||||
common: TestInputDeviceCommon {
|
||||
|
|
@ -89,9 +90,24 @@ impl TestBackend {
|
|||
name: Rc::new("default-keyboard".to_string()),
|
||||
},
|
||||
});
|
||||
let mode = Mode {
|
||||
width: 800,
|
||||
height: 600,
|
||||
refresh_rate_millihz: 60_000,
|
||||
};
|
||||
let default_monitor_info = MonitorInfo {
|
||||
modes: vec![mode],
|
||||
manufacturer: "jay".to_string(),
|
||||
product: "TestConnector".to_string(),
|
||||
serial_number: default_connector.id.to_string(),
|
||||
initial_mode: mode,
|
||||
width_mm: 80,
|
||||
height_mm: 60,
|
||||
};
|
||||
Self {
|
||||
state: state.clone(),
|
||||
test_future: future,
|
||||
default_monitor_info,
|
||||
default_connector,
|
||||
default_mouse,
|
||||
default_kb,
|
||||
|
|
@ -113,22 +129,9 @@ impl TestBackend {
|
|||
self.state
|
||||
.backend_events
|
||||
.push(BackendEvent::NewConnector(self.default_connector.clone()));
|
||||
let mode = Mode {
|
||||
width: 800,
|
||||
height: 600,
|
||||
refresh_rate_millihz: 60_000,
|
||||
};
|
||||
self.default_connector
|
||||
.events
|
||||
.push(ConnectorEvent::Connected(MonitorInfo {
|
||||
modes: vec![mode],
|
||||
manufacturer: "jay".to_string(),
|
||||
product: "TestConnector".to_string(),
|
||||
serial_number: self.default_connector.id.to_string(),
|
||||
initial_mode: mode,
|
||||
width_mm: 80,
|
||||
height_mm: 60,
|
||||
}));
|
||||
.send_event(ConnectorEvent::Connected(self.default_monitor_info.clone()));
|
||||
self.state
|
||||
.backend_events
|
||||
.push(BackendEvent::NewInputDevice(self.default_kb.clone()));
|
||||
|
|
@ -215,8 +218,7 @@ impl Backend for TestBackend {
|
|||
pub struct TestConnector {
|
||||
pub id: ConnectorId,
|
||||
pub kernel_id: ConnectorKernelId,
|
||||
pub events: SyncQueue<ConnectorEvent>,
|
||||
pub on_change: CloneCell<Option<Rc<dyn Fn()>>>,
|
||||
pub events: OnChange<ConnectorEvent>,
|
||||
}
|
||||
|
||||
impl Connector for TestConnector {
|
||||
|
|
@ -229,11 +231,11 @@ impl Connector for TestConnector {
|
|||
}
|
||||
|
||||
fn event(&self) -> Option<ConnectorEvent> {
|
||||
self.events.pop()
|
||||
self.events.events.pop()
|
||||
}
|
||||
|
||||
fn on_change(&self, cb: Rc<dyn Fn()>) {
|
||||
self.on_change.set(Some(cb));
|
||||
self.events.on_change.set(Some(cb));
|
||||
}
|
||||
|
||||
fn damage(&self) {
|
||||
|
|
|
|||
|
|
@ -65,6 +65,7 @@ mod t0031_syncobj;
|
|||
mod t0032_content_type;
|
||||
mod t0032_data_control;
|
||||
mod t0033_float_size_memoization;
|
||||
mod t0034_workspace_restoration;
|
||||
|
||||
pub trait TestCase: Sync {
|
||||
fn name(&self) -> &'static str;
|
||||
|
|
@ -117,5 +118,6 @@ pub fn tests() -> Vec<&'static dyn TestCase> {
|
|||
t0031_syncobj,
|
||||
t0032_data_control,
|
||||
t0033_float_size_memoization,
|
||||
t0034_workspace_restoration,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
94
src/it/tests/t0034_workspace_restoration.rs
Normal file
94
src/it/tests/t0034_workspace_restoration.rs
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
use {
|
||||
crate::{
|
||||
backend::{BackendEvent, ConnectorEvent, ConnectorKernelId, Mode, MonitorInfo},
|
||||
it::{test_backend::TestConnector, test_error::TestResult, testrun::TestRun},
|
||||
video::drm::ConnectorType,
|
||||
},
|
||||
std::rc::Rc,
|
||||
};
|
||||
|
||||
testcase!();
|
||||
|
||||
async fn test(run: Rc<TestRun>) -> TestResult {
|
||||
let ds = run.create_default_setup().await?;
|
||||
|
||||
let client1 = run.create_client().await?;
|
||||
let win1 = client1.create_window().await?;
|
||||
win1.map2().await?;
|
||||
let surface = &win1.surface.server;
|
||||
|
||||
let Some(dummy_output) = run.state.dummy_output.get() else {
|
||||
bail!("no dummy output");
|
||||
};
|
||||
|
||||
let new_connector = Rc::new(TestConnector {
|
||||
id: run.state.connector_ids.next(),
|
||||
kernel_id: ConnectorKernelId {
|
||||
ty: ConnectorType::VGA,
|
||||
idx: 2,
|
||||
},
|
||||
events: Default::default(),
|
||||
});
|
||||
let new_monitor_info = MonitorInfo {
|
||||
modes: vec![],
|
||||
manufacturer: "jay".to_string(),
|
||||
product: "jay second connector".to_string(),
|
||||
serial_number: "".to_string(),
|
||||
initial_mode: Mode {
|
||||
width: 400,
|
||||
height: 400,
|
||||
refresh_rate_millihz: 60000,
|
||||
},
|
||||
width_mm: 0,
|
||||
height_mm: 0,
|
||||
};
|
||||
run.backend
|
||||
.state
|
||||
.backend_events
|
||||
.push(BackendEvent::NewConnector(new_connector.clone()));
|
||||
|
||||
new_connector
|
||||
.events
|
||||
.send_event(ConnectorEvent::Connected(new_monitor_info.clone()));
|
||||
run.state.eng.yield_now().await;
|
||||
tassert_eq!(
|
||||
surface.get_output().global.connector.connector.id(),
|
||||
ds.connector.id
|
||||
);
|
||||
|
||||
ds.connector.events.send_event(ConnectorEvent::Disconnected);
|
||||
run.state.eng.yield_now().await;
|
||||
tassert_eq!(
|
||||
surface.get_output().global.connector.connector.id(),
|
||||
new_connector.id
|
||||
);
|
||||
|
||||
new_connector
|
||||
.events
|
||||
.send_event(ConnectorEvent::Disconnected);
|
||||
run.state.eng.yield_now().await;
|
||||
tassert_eq!(
|
||||
surface.get_output().global.connector.connector.id(),
|
||||
dummy_output.global.connector.connector.id()
|
||||
);
|
||||
|
||||
new_connector
|
||||
.events
|
||||
.send_event(ConnectorEvent::Connected(new_monitor_info.clone()));
|
||||
run.state.eng.yield_now().await;
|
||||
tassert_eq!(
|
||||
surface.get_output().global.connector.connector.id(),
|
||||
new_connector.id
|
||||
);
|
||||
|
||||
ds.connector.events.send_event(ConnectorEvent::Connected(
|
||||
run.backend.default_monitor_info.clone(),
|
||||
));
|
||||
run.state.eng.yield_now().await;
|
||||
tassert_eq!(
|
||||
surface.get_output().global.connector.connector.id(),
|
||||
ds.connector.id
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
@ -237,6 +237,7 @@ impl ConnectorHandler {
|
|||
}
|
||||
global.destroyed.set(true);
|
||||
self.state.root.outputs.remove(&self.id);
|
||||
self.state.root.update_extents();
|
||||
self.data.connected.set(false);
|
||||
self.state.outputs.remove(&self.id);
|
||||
on.lock_surface.take();
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ pub mod mmap;
|
|||
pub mod nonblock;
|
||||
pub mod num_cpus;
|
||||
pub mod numcell;
|
||||
pub mod on_change;
|
||||
pub mod once;
|
||||
pub mod opaque;
|
||||
pub mod opaque_cell;
|
||||
|
|
|
|||
39
src/utils/on_change.rs
Normal file
39
src/utils/on_change.rs
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
use {
|
||||
crate::utils::{clonecell::CloneCell, syncqueue::SyncQueue},
|
||||
std::{
|
||||
fmt::{Debug, Formatter},
|
||||
rc::Rc,
|
||||
},
|
||||
};
|
||||
|
||||
pub struct OnChange<T> {
|
||||
pub on_change: CloneCell<Option<Rc<dyn Fn()>>>,
|
||||
pub events: SyncQueue<T>,
|
||||
}
|
||||
|
||||
impl<T> OnChange<T> {
|
||||
pub fn send_event(&self, event: T) {
|
||||
self.events.push(event);
|
||||
if let Some(cb) = self.on_change.get() {
|
||||
cb();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Default for OnChange<T> {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
on_change: Default::default(),
|
||||
events: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Debug for OnChange<T> {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
match self.on_change.get() {
|
||||
None => f.write_str("None"),
|
||||
Some(_) => f.write_str("Some"),
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue