it: test xdg-activation
This commit is contained in:
parent
91022cd1c8
commit
6fe6b1b491
16 changed files with 239 additions and 23 deletions
|
|
@ -18,7 +18,7 @@ use {
|
|||
clonecell::CloneCell,
|
||||
errorfmt::ErrorFmt,
|
||||
},
|
||||
wire::{jay_compositor::*, JayCompositorId},
|
||||
wire::{jay_compositor::*, JayCompositorId, JayScreenshotId},
|
||||
},
|
||||
bstr::ByteSlice,
|
||||
log::Level,
|
||||
|
|
@ -125,14 +125,27 @@ impl JayCompositor {
|
|||
|
||||
fn take_screenshot(&self, parser: MsgParser<'_, '_>) -> Result<(), JayCompositorError> {
|
||||
let req: TakeScreenshot = self.client.parse(self, parser)?;
|
||||
self.take_screenshot_impl(req.id, false)
|
||||
}
|
||||
|
||||
fn take_screenshot2(&self, parser: MsgParser<'_, '_>) -> Result<(), JayCompositorError> {
|
||||
let req: TakeScreenshot2 = self.client.parse(self, parser)?;
|
||||
self.take_screenshot_impl(req.id, req.include_cursor != 0)
|
||||
}
|
||||
|
||||
fn take_screenshot_impl(
|
||||
&self,
|
||||
id: JayScreenshotId,
|
||||
include_cursor: bool,
|
||||
) -> Result<(), JayCompositorError> {
|
||||
let ss = Rc::new(JayScreenshot {
|
||||
id: req.id,
|
||||
id,
|
||||
client: self.client.clone(),
|
||||
tracker: Default::default(),
|
||||
});
|
||||
track!(self.client, ss);
|
||||
self.client.add_client_obj(&ss)?;
|
||||
match take_screenshot(&self.client.state) {
|
||||
match take_screenshot(&self.client.state, include_cursor) {
|
||||
Ok(s) => {
|
||||
let dmabuf = s.bo.dmabuf();
|
||||
let plane = &dmabuf.planes[0];
|
||||
|
|
@ -347,6 +360,7 @@ object_base! {
|
|||
CREATE_SCREENCAST => create_screencast,
|
||||
GET_RANDR => get_randr,
|
||||
GET_INPUT => get_input,
|
||||
TAKE_SCREENSHOT2 => take_screenshot2,
|
||||
}
|
||||
|
||||
impl Object for JayCompositor {}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ use {
|
|||
test_registry::TestRegistry, test_seat::TestSeat, test_shm::TestShm,
|
||||
test_single_pixel_buffer_manager::TestSinglePixelBufferManager,
|
||||
test_subcompositor::TestSubcompositor, test_viewporter::TestViewporter,
|
||||
test_xdg_base::TestXdgWmBase,
|
||||
test_xdg_activation::TestXdgActivation, test_xdg_base::TestXdgWmBase,
|
||||
},
|
||||
test_transport::TestTransport,
|
||||
test_utils::test_window::TestWindow,
|
||||
|
|
@ -34,6 +34,7 @@ pub struct TestClient {
|
|||
pub spbm: Rc<TestSinglePixelBufferManager>,
|
||||
pub viewporter: Rc<TestViewporter>,
|
||||
pub xdg: Rc<TestXdgWmBase>,
|
||||
pub activation: Rc<TestXdgActivation>,
|
||||
}
|
||||
|
||||
pub struct DefaultSeat {
|
||||
|
|
@ -86,22 +87,26 @@ impl TestClient {
|
|||
self.tran.sync().await;
|
||||
}
|
||||
|
||||
pub async fn take_screenshot(&self) -> Result<Vec<u8>, TestError> {
|
||||
let dmabuf = self.jc.take_screenshot().await?;
|
||||
pub async fn take_screenshot(&self, include_cursor: bool) -> Result<Vec<u8>, TestError> {
|
||||
let dmabuf = self.jc.take_screenshot(include_cursor).await?;
|
||||
let qoi = buf_to_qoi(&self.server.state.dma_buf_ids, &dmabuf);
|
||||
Ok(qoi)
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub async fn save_screenshot(&self, name: &str) -> Result<(), TestError> {
|
||||
let qoi = self.take_screenshot().await?;
|
||||
pub async fn save_screenshot(&self, name: &str, include_cursor: bool) -> Result<(), TestError> {
|
||||
let qoi = self.take_screenshot(include_cursor).await?;
|
||||
let path = format!("{}/screenshot_{}.qoi", self.run.out_dir, name);
|
||||
std::fs::write(path, qoi)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn compare_screenshot(&self, name: &str) -> Result<(), TestError> {
|
||||
let actual = self.take_screenshot().await?;
|
||||
pub async fn compare_screenshot(
|
||||
&self,
|
||||
name: &str,
|
||||
include_cursor: bool,
|
||||
) -> Result<(), TestError> {
|
||||
let actual = self.take_screenshot(include_cursor).await?;
|
||||
let expected_path = format!("{}/screenshot_{}.qoi", self.run.in_dir, name);
|
||||
let expected = std::fs::read(expected_path)?;
|
||||
if actual != expected {
|
||||
|
|
|
|||
|
|
@ -18,6 +18,8 @@ pub mod test_subsurface;
|
|||
pub mod test_surface;
|
||||
pub mod test_viewport;
|
||||
pub mod test_viewporter;
|
||||
pub mod test_xdg_activation;
|
||||
pub mod test_xdg_activation_token;
|
||||
pub mod test_xdg_base;
|
||||
pub mod test_xdg_surface;
|
||||
pub mod test_xdg_toplevel;
|
||||
|
|
|
|||
|
|
@ -33,14 +33,15 @@ impl TestJayCompositor {
|
|||
}
|
||||
}
|
||||
|
||||
pub async fn take_screenshot(&self) -> Result<Dmabuf, TestError> {
|
||||
pub async fn take_screenshot(&self, include_cursor: bool) -> Result<Dmabuf, TestError> {
|
||||
let js = Rc::new(TestJayScreenshot {
|
||||
id: self.tran.id(),
|
||||
result: Cell::new(None),
|
||||
});
|
||||
self.tran.send(TakeScreenshot {
|
||||
self.tran.send(TakeScreenshot2 {
|
||||
self_id: self.id,
|
||||
id: js.id,
|
||||
include_cursor: include_cursor as _,
|
||||
})?;
|
||||
self.tran.add_obj(js.clone())?;
|
||||
self.tran.sync().await;
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ use {
|
|||
test_compositor::TestCompositor, test_jay_compositor::TestJayCompositor,
|
||||
test_shm::TestShm, test_single_pixel_buffer_manager::TestSinglePixelBufferManager,
|
||||
test_subcompositor::TestSubcompositor, test_viewporter::TestViewporter,
|
||||
test_xdg_base::TestXdgWmBase,
|
||||
test_xdg_activation::TestXdgActivation, test_xdg_base::TestXdgWmBase,
|
||||
},
|
||||
test_object::TestObject,
|
||||
test_transport::TestTransport,
|
||||
|
|
@ -34,6 +34,7 @@ pub struct TestRegistrySingletons {
|
|||
pub xdg_wm_base: u32,
|
||||
pub wp_single_pixel_buffer_manager_v1: u32,
|
||||
pub wp_viewporter: u32,
|
||||
pub xdg_activation_v1: u32,
|
||||
}
|
||||
|
||||
pub struct TestRegistry {
|
||||
|
|
@ -48,6 +49,7 @@ pub struct TestRegistry {
|
|||
pub spbm: CloneCell<Option<Rc<TestSinglePixelBufferManager>>>,
|
||||
pub viewporter: CloneCell<Option<Rc<TestViewporter>>>,
|
||||
pub xdg: CloneCell<Option<Rc<TestXdgWmBase>>>,
|
||||
pub activation: CloneCell<Option<Rc<TestXdgActivation>>>,
|
||||
pub seats: CopyHashMap<GlobalName, Rc<WlSeatGlobal>>,
|
||||
}
|
||||
|
||||
|
|
@ -97,6 +99,7 @@ impl TestRegistry {
|
|||
xdg_wm_base,
|
||||
wp_single_pixel_buffer_manager_v1,
|
||||
wp_viewporter,
|
||||
xdg_activation_v1,
|
||||
};
|
||||
self.singletons.set(Some(singletons.clone()));
|
||||
Ok(singletons)
|
||||
|
|
@ -184,6 +187,20 @@ impl TestRegistry {
|
|||
Ok(jc)
|
||||
}
|
||||
|
||||
pub async fn get_activation(&self) -> Result<Rc<TestXdgActivation>, TestError> {
|
||||
singleton!(self.activation);
|
||||
let singletons = self.get_singletons().await?;
|
||||
singleton!(self.activation);
|
||||
let jc = Rc::new(TestXdgActivation {
|
||||
id: self.tran.id(),
|
||||
tran: self.tran.clone(),
|
||||
destroyed: Cell::new(false),
|
||||
});
|
||||
self.bind(&jc, singletons.xdg_activation_v1, 1)?;
|
||||
self.activation.set(Some(jc.clone()));
|
||||
Ok(jc)
|
||||
}
|
||||
|
||||
pub async fn get_xdg(&self) -> Result<Rc<TestXdgWmBase>, TestError> {
|
||||
singleton!(self.xdg);
|
||||
let singletons = self.get_singletons().await?;
|
||||
|
|
|
|||
66
src/it/test_ifs/test_xdg_activation.rs
Normal file
66
src/it/test_ifs/test_xdg_activation.rs
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
use {
|
||||
crate::{
|
||||
it::{
|
||||
test_error::{TestError, TestResult},
|
||||
test_ifs::{
|
||||
test_surface::TestSurface, test_xdg_activation_token::TestXdgActivationToken,
|
||||
},
|
||||
test_object::TestObject,
|
||||
test_transport::TestTransport,
|
||||
},
|
||||
wire::{xdg_activation_v1::*, XdgActivationV1Id},
|
||||
},
|
||||
std::{cell::Cell, rc::Rc},
|
||||
};
|
||||
|
||||
pub struct TestXdgActivation {
|
||||
pub id: XdgActivationV1Id,
|
||||
pub tran: Rc<TestTransport>,
|
||||
pub destroyed: Cell<bool>,
|
||||
}
|
||||
|
||||
impl TestXdgActivation {
|
||||
pub fn destroy(&self) -> Result<(), TestError> {
|
||||
if !self.destroyed.replace(true) {
|
||||
self.tran.send(Destroy { self_id: self.id })?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn get_token(&self) -> Result<String, TestError> {
|
||||
let token = Rc::new(TestXdgActivationToken {
|
||||
id: self.tran.id(),
|
||||
tran: self.tran.clone(),
|
||||
destroyed: Cell::new(false),
|
||||
token: Cell::new(None),
|
||||
});
|
||||
self.tran.add_obj(token.clone())?;
|
||||
self.tran.send(GetActivationToken {
|
||||
self_id: self.id,
|
||||
id: token.id,
|
||||
})?;
|
||||
let res = token.commit().await?;
|
||||
token.destroy()?;
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
pub fn activate(&self, tl: &TestSurface, token: &str) -> TestResult {
|
||||
self.tran.send(Activate {
|
||||
self_id: self.id,
|
||||
token,
|
||||
surface: tl.id,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
test_object! {
|
||||
TestXdgActivation, XdgActivationV1;
|
||||
}
|
||||
|
||||
impl TestObject for TestXdgActivation {}
|
||||
|
||||
impl Drop for TestXdgActivation {
|
||||
fn drop(&mut self) {
|
||||
let _ = self.destroy();
|
||||
}
|
||||
}
|
||||
56
src/it/test_ifs/test_xdg_activation_token.rs
Normal file
56
src/it/test_ifs/test_xdg_activation_token.rs
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
use {
|
||||
crate::{
|
||||
it::{
|
||||
test_error::TestError, test_object::TestObject, test_transport::TestTransport,
|
||||
testrun::ParseFull,
|
||||
},
|
||||
utils::buffd::MsgParser,
|
||||
wire::{xdg_activation_token_v1::*, XdgActivationTokenV1Id},
|
||||
},
|
||||
std::{cell::Cell, rc::Rc},
|
||||
};
|
||||
|
||||
pub struct TestXdgActivationToken {
|
||||
pub id: XdgActivationTokenV1Id,
|
||||
pub tran: Rc<TestTransport>,
|
||||
pub destroyed: Cell<bool>,
|
||||
pub token: Cell<Option<String>>,
|
||||
}
|
||||
|
||||
impl TestXdgActivationToken {
|
||||
pub fn destroy(&self) -> Result<(), TestError> {
|
||||
if !self.destroyed.replace(true) {
|
||||
self.tran.send(Destroy { self_id: self.id })?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn commit(&self) -> Result<String, TestError> {
|
||||
self.tran.send(Commit { self_id: self.id })?;
|
||||
self.tran.sync().await;
|
||||
match self.token.take() {
|
||||
Some(t) => Ok(t),
|
||||
_ => bail!("Server did not send a token"),
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_done(&self, parser: MsgParser<'_, '_>) -> Result<(), TestError> {
|
||||
let ev = Done::parse_full(parser)?;
|
||||
self.token.set(Some(ev.token.to_string()));
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
test_object! {
|
||||
TestXdgActivationToken, XdgActivationTokenV1;
|
||||
|
||||
DONE => handle_done,
|
||||
}
|
||||
|
||||
impl TestObject for TestXdgActivationToken {}
|
||||
|
||||
impl Drop for TestXdgActivationToken {
|
||||
fn drop(&mut self) {
|
||||
let _ = self.destroy();
|
||||
}
|
||||
}
|
||||
|
|
@ -59,6 +59,7 @@ impl TestTransport {
|
|||
spbm: Default::default(),
|
||||
viewporter: Default::default(),
|
||||
xdg: Default::default(),
|
||||
activation: Default::default(),
|
||||
seats: Default::default(),
|
||||
});
|
||||
self.send(wl_display::GetRegistry {
|
||||
|
|
@ -161,7 +162,12 @@ impl TestTransport {
|
|||
_ => bail!("Object with id {} has already been deleted", msg.id()),
|
||||
};
|
||||
if obj.interface().name() != msg.interface().name() {
|
||||
bail!("Object with id {} has an incompatible interface", msg.id());
|
||||
bail!(
|
||||
"Object with id {} has an incompatible interface: {} != {}",
|
||||
msg.id(),
|
||||
obj.interface().name(),
|
||||
msg.interface().name()
|
||||
);
|
||||
}
|
||||
let mut fds = vec![];
|
||||
let mut swapchain = self.swapchain.borrow_mut();
|
||||
|
|
|
|||
|
|
@ -87,6 +87,7 @@ impl TestRun {
|
|||
spbm: registry.get_spbm().await?,
|
||||
viewporter: registry.get_viewporter().await?,
|
||||
xdg: registry.get_xdg().await?,
|
||||
activation: registry.get_activation().await?,
|
||||
registry,
|
||||
}))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -53,6 +53,7 @@ mod t0019_natural_scrolling;
|
|||
mod t0020_surface_offset;
|
||||
mod t0021_preferred_buffer_scale;
|
||||
mod t0022_toplevel_suspended;
|
||||
mod t0023_xdg_activation;
|
||||
|
||||
pub trait TestCase: Sync {
|
||||
fn name(&self) -> &'static str;
|
||||
|
|
@ -94,5 +95,6 @@ pub fn tests() -> Vec<&'static dyn TestCase> {
|
|||
t0020_surface_offset,
|
||||
t0021_preferred_buffer_scale,
|
||||
t0022_toplevel_suspended,
|
||||
t0023_xdg_activation,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,19 +43,17 @@ async fn test(run: Rc<TestRun>) -> Result<(), TestError> {
|
|||
|
||||
parent.map().await?;
|
||||
|
||||
seat.set_app_cursor(None);
|
||||
|
||||
client.compare_screenshot("1").await?;
|
||||
client.compare_screenshot("1", false).await?;
|
||||
|
||||
sub.place_below(parent.surface.id)?;
|
||||
child.commit()?;
|
||||
parent.map().await?;
|
||||
client.compare_screenshot("2").await?;
|
||||
client.compare_screenshot("2", false).await?;
|
||||
|
||||
sub.place_above(parent.surface.id)?;
|
||||
child.commit()?;
|
||||
parent.map().await?;
|
||||
client.compare_screenshot("1").await?;
|
||||
client.compare_screenshot("1", false).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,12 +44,12 @@ async fn test(run: Rc<TestRun>) -> Result<(), TestError> {
|
|||
let enter = enter.next()?;
|
||||
seat.pointer.set_cursor(enter.serial, &surface, 0, 0)?;
|
||||
|
||||
client.compare_screenshot("1").await?;
|
||||
client.compare_screenshot("1", true).await?;
|
||||
|
||||
surface.offset(-100, -100)?;
|
||||
surface.commit()?;
|
||||
|
||||
client.compare_screenshot("2").await?;
|
||||
client.compare_screenshot("2", true).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
40
src/it/tests/t0023_xdg_activation.rs
Normal file
40
src/it/tests/t0023_xdg_activation.rs
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
use {
|
||||
crate::it::{
|
||||
test_error::TestResult,
|
||||
test_utils::{
|
||||
test_ouput_node_ext::TestOutputNodeExt, test_toplevel_node_ext::TestToplevelNodeExt,
|
||||
},
|
||||
testrun::TestRun,
|
||||
},
|
||||
std::rc::Rc,
|
||||
};
|
||||
|
||||
testcase!();
|
||||
|
||||
async fn test(run: Rc<TestRun>) -> TestResult {
|
||||
let ds = run.create_default_setup().await?;
|
||||
|
||||
let client = run.create_client().await?;
|
||||
|
||||
let win1 = client.create_window().await?;
|
||||
win1.set_color(255, 0, 0, 255);
|
||||
win1.map2().await?;
|
||||
|
||||
let win2 = client.create_window().await?;
|
||||
win2.set_color(0, 255, 0, 255);
|
||||
win2.map2().await?;
|
||||
|
||||
let (x, y) = ds.output.first_toplevel()?.center();
|
||||
ds.move_to(x, y);
|
||||
|
||||
client.sync().await;
|
||||
run.cfg.set_mono(ds.seat.id(), true)?;
|
||||
|
||||
let token = client.activation.get_token().await?;
|
||||
client.activation.activate(&win2.surface, &token)?;
|
||||
client.sync().await;
|
||||
|
||||
client.compare_screenshot("1", false).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
BIN
src/it/tests/t0023_xdg_activation/screenshot_1.qoi
Normal file
BIN
src/it/tests/t0023_xdg_activation/screenshot_1.qoi
Normal file
Binary file not shown.
|
|
@ -39,7 +39,10 @@ pub struct Screenshot {
|
|||
pub bo: GbmBo,
|
||||
}
|
||||
|
||||
pub fn take_screenshot(state: &State) -> Result<Screenshot, ScreenshooterError> {
|
||||
pub fn take_screenshot(
|
||||
state: &State,
|
||||
include_cursor: bool,
|
||||
) -> Result<Screenshot, ScreenshooterError> {
|
||||
let ctx = match state.render_ctx.get() {
|
||||
Some(ctx) => ctx,
|
||||
_ => return Err(ScreenshooterError::NoRenderContext),
|
||||
|
|
@ -72,7 +75,7 @@ pub fn take_screenshot(state: &State) -> Result<Screenshot, ScreenshooterError>
|
|||
fb.render_node(
|
||||
state.root.deref(),
|
||||
state,
|
||||
Some(state.root.extents.get()),
|
||||
include_cursor.then_some(state.root.extents.get()),
|
||||
None,
|
||||
Scale::from_int(1),
|
||||
true,
|
||||
|
|
|
|||
|
|
@ -73,6 +73,11 @@ msg get_input = 17 {
|
|||
id: id(jay_input),
|
||||
}
|
||||
|
||||
msg take_screenshot2 = 18 {
|
||||
id: id(jay_screenshot),
|
||||
include_cursor: u32,
|
||||
}
|
||||
|
||||
# events
|
||||
|
||||
msg client_id = 0 {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue