pinnacle/tests/rust_api.rs
2024-04-17 21:31:39 -05:00

354 lines
12 KiB
Rust

mod common;
use std::thread::JoinHandle;
use pinnacle_api::ApiModules;
use test_log::test;
use crate::common::output_for_name;
use crate::common::{sleep_secs, test_api, with_state};
#[tokio::main]
async fn run_rust_inner(run: impl FnOnce(ApiModules) + Send + 'static) {
let (api, _recv) = pinnacle_api::connect().await.unwrap();
run(api.clone());
}
fn run_rust(run: impl FnOnce(ApiModules) + Send + 'static) {
std::thread::spawn(|| {
run_rust_inner(run);
})
.join()
.unwrap();
}
#[tokio::main]
async fn setup_rust_inner(run: impl FnOnce(ApiModules) + Send + 'static) {
let (api, recv) = pinnacle_api::connect().await.unwrap();
run(api.clone());
pinnacle_api::listen(api, recv).await;
}
fn setup_rust(run: impl FnOnce(ApiModules) + Send + 'static) -> JoinHandle<()> {
std::thread::spawn(|| {
setup_rust_inner(run);
})
}
mod output {
use pinnacle::state::WithState;
use pinnacle_api::output::{Alignment, OutputId, OutputLoc, OutputSetup, UpdateLocsOn};
use smithay::{output::Output, utils::Rectangle};
use super::*;
#[tokio::main]
#[self::test]
async fn setup() -> anyhow::Result<()> {
test_api(|sender| {
setup_rust(|api| {
api.output.setup([
OutputSetup::new_with_matcher(|_| true).with_tags(["1", "2", "3"]),
OutputSetup::new_with_matcher(|op| op.name().contains("Test"))
.with_tags(["Test 4", "Test 5"]),
OutputSetup::new(OutputId::name("Second"))
.with_scale(2.0)
.with_mode(pinnacle_api::output::Mode {
pixel_width: 6900,
pixel_height: 420,
refresh_rate_millihertz: 69420,
})
.with_transform(pinnacle_api::output::Transform::_90),
]);
});
sleep_secs(1);
with_state(&sender, |state| {
state.new_output("First", (300, 200).into());
state.new_output("Second", (300, 200).into());
state.new_output("Test Third", (300, 200).into());
});
sleep_secs(1);
with_state(&sender, |state| {
let original_op = output_for_name(state, "Pinnacle Window");
let first_op = output_for_name(state, "First");
let second_op = output_for_name(state, "Second");
let test_third_op = output_for_name(state, "Test Third");
let tags_for = |output: &Output| {
output
.with_state(|state| state.tags.iter().map(|t| t.name()).collect::<Vec<_>>())
};
let focused_tags_for = |output: &Output| {
output.with_state(|state| {
state.focused_tags().map(|t| t.name()).collect::<Vec<_>>()
})
};
assert_eq!(tags_for(&original_op), vec!["1", "2", "3"]);
assert_eq!(tags_for(&first_op), vec!["1", "2", "3"]);
assert_eq!(tags_for(&second_op), vec!["1", "2", "3"]);
assert_eq!(
tags_for(&test_third_op),
vec!["1", "2", "3", "Test 4", "Test 5"]
);
assert_eq!(focused_tags_for(&original_op), vec!["1"]);
assert_eq!(focused_tags_for(&test_third_op), vec!["1"]);
assert_eq!(second_op.current_scale().fractional_scale(), 2.0);
let second_mode = second_op.current_mode().unwrap();
assert_eq!(second_mode.size.w, 6900);
assert_eq!(second_mode.size.h, 420);
assert_eq!(second_mode.refresh, 69420);
assert_eq!(
second_op.current_transform(),
smithay::utils::Transform::_90
);
});
})
}
#[tokio::main]
#[self::test]
async fn setup_loc_with_cyclic_relative_locs_works() -> anyhow::Result<()> {
test_api(|sender| {
setup_rust(|api| {
api.output.setup_locs(
UpdateLocsOn::all(),
[
(OutputId::name("Pinnacle Window"), OutputLoc::Point(0, 0)),
(
OutputId::name("First"),
OutputLoc::RelativeTo(
OutputId::name("Second"),
Alignment::LeftAlignTop,
),
),
(
OutputId::name("Second"),
OutputLoc::RelativeTo(
OutputId::name("First"),
Alignment::RightAlignTop,
),
),
],
);
});
sleep_secs(1);
with_state(&sender, |state| {
state.new_output("First", (300, 200).into());
});
sleep_secs(1);
with_state(&sender, |state| {
let original_op = output_for_name(state, "Pinnacle Window");
let first_op = output_for_name(state, "First");
let original_geo = state.space.output_geometry(&original_op).unwrap();
let first_geo = state.space.output_geometry(&first_op).unwrap();
assert_eq!(
original_geo,
Rectangle::from_loc_and_size((0, 0), (1920, 1080))
);
assert_eq!(
first_geo,
Rectangle::from_loc_and_size((1920, 0), (300, 200))
);
state.new_output("Second", (500, 500).into());
});
sleep_secs(1);
with_state(&sender, |state| {
let original_op = output_for_name(state, "Pinnacle Window");
let first_op = output_for_name(state, "First");
let second_op = output_for_name(state, "Second");
let original_geo = state.space.output_geometry(&original_op).unwrap();
let first_geo = state.space.output_geometry(&first_op).unwrap();
let second_geo = state.space.output_geometry(&second_op).unwrap();
assert_eq!(
original_geo,
Rectangle::from_loc_and_size((0, 0), (1920, 1080))
);
assert_eq!(
first_geo,
Rectangle::from_loc_and_size((1920, 0), (300, 200))
);
assert_eq!(
second_geo,
Rectangle::from_loc_and_size((1920 + 300, 0), (500, 500))
);
});
})
}
#[tokio::main]
#[self::test]
async fn setup_loc_with_relative_locs_with_more_than_one_relative_works() -> anyhow::Result<()>
{
test_api(|sender| {
setup_rust(|api| {
api.output.setup_locs(
UpdateLocsOn::all(),
[
(OutputId::name("Pinnacle Window"), OutputLoc::Point(0, 0)),
(
OutputId::name("First"),
OutputLoc::RelativeTo(
OutputId::name("Pinnacle Window"),
Alignment::BottomAlignLeft,
),
),
(
OutputId::name("Second"),
OutputLoc::RelativeTo(
OutputId::name("First"),
Alignment::BottomAlignLeft,
),
),
(
OutputId::name("Third"),
OutputLoc::RelativeTo(
OutputId::name("Second"),
Alignment::BottomAlignLeft,
),
),
(
OutputId::name("Third"),
OutputLoc::RelativeTo(
OutputId::name("First"),
Alignment::BottomAlignLeft,
),
),
],
);
});
sleep_secs(1);
with_state(&sender, |state| {
state.new_output("First", (300, 200).into());
state.new_output("Second", (300, 700).into());
state.new_output("Third", (300, 400).into());
});
sleep_secs(1);
with_state(&sender, |state| {
let original_op = output_for_name(state, "Pinnacle Window");
let first_op = output_for_name(state, "First");
let second_op = output_for_name(state, "Second");
let third_op = output_for_name(state, "Third");
let original_geo = state.space.output_geometry(&original_op).unwrap();
let first_geo = state.space.output_geometry(&first_op).unwrap();
let second_geo = state.space.output_geometry(&second_op).unwrap();
let third_geo = state.space.output_geometry(&third_op).unwrap();
assert_eq!(
original_geo,
Rectangle::from_loc_and_size((0, 0), (1920, 1080))
);
assert_eq!(
first_geo,
Rectangle::from_loc_and_size((0, 1080), (300, 200))
);
assert_eq!(
second_geo,
Rectangle::from_loc_and_size((0, 1080 + 200), (300, 700))
);
assert_eq!(
third_geo,
Rectangle::from_loc_and_size((0, 1080 + 200 + 700), (300, 400))
);
state.remove_output(&second_op);
});
sleep_secs(1);
with_state(&sender, |state| {
let original_op = output_for_name(state, "Pinnacle Window");
let first_op = output_for_name(state, "First");
let third_op = output_for_name(state, "Third");
let original_geo = state.space.output_geometry(&original_op).unwrap();
let first_geo = state.space.output_geometry(&first_op).unwrap();
let third_geo = state.space.output_geometry(&third_op).unwrap();
assert_eq!(
original_geo,
Rectangle::from_loc_and_size((0, 0), (1920, 1080))
);
assert_eq!(
first_geo,
Rectangle::from_loc_and_size((0, 1080), (300, 200))
);
assert_eq!(
third_geo,
Rectangle::from_loc_and_size((0, 1080 + 200), (300, 400))
);
});
})
}
mod handle {
use pinnacle_api::output::Transform;
use super::*;
#[tokio::main]
#[self::test]
async fn set_transform() -> anyhow::Result<()> {
test_api(|sender| {
run_rust(|api| {
api.output
.get_focused()
.unwrap()
.set_transform(Transform::Flipped270);
});
sleep_secs(1);
with_state(&sender, |state| {
let op = state.focused_output().unwrap();
assert_eq!(
op.current_transform(),
smithay::utils::Transform::Flipped270
);
});
run_rust(|api| {
api.output
.get_focused()
.unwrap()
.set_transform(Transform::_180);
});
sleep_secs(1);
with_state(&sender, |state| {
let op = state.focused_output().unwrap();
assert_eq!(op.current_transform(), smithay::utils::Transform::_180);
});
})
}
}
}