1
0
Fork 0
forked from wry/wry

it: test workspace restoration

This commit is contained in:
Julian Orth 2024-04-03 14:37:03 +02:00
parent 9efe9415c2
commit 15a1b600f3
8 changed files with 165 additions and 53 deletions

View file

@ -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>,

View file

@ -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 {

View file

@ -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) {

View file

@ -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,
}
}

View 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(())
}

View file

@ -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();

View file

@ -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
View 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"),
}
}
}