2024-04-16 14:04:34 +02:00
|
|
|
mod common;
|
|
|
|
|
|
|
|
use std::thread::JoinHandle;
|
|
|
|
|
|
|
|
use pinnacle_api::ApiModules;
|
|
|
|
use test_log::test;
|
|
|
|
|
2024-04-16 21:29:53 +02:00
|
|
|
use crate::common::output_for_name;
|
2024-04-16 14:04:34 +02:00
|
|
|
use crate::common::{sleep_secs, test_api, with_state};
|
|
|
|
|
|
|
|
#[tokio::main]
|
|
|
|
async fn setup_rust_inner(run: impl FnOnce(ApiModules) + Send + 'static) {
|
|
|
|
let (api, recv) = pinnacle_api::connect().await.unwrap();
|
|
|
|
|
2024-04-16 18:10:47 +02:00
|
|
|
run(api.clone());
|
2024-04-16 14:04:34 +02:00
|
|
|
|
2024-04-16 18:10:47 +02:00
|
|
|
pinnacle_api::listen(api, recv).await;
|
2024-04-16 14:04:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
fn setup_rust(run: impl FnOnce(ApiModules) + Send + 'static) -> JoinHandle<()> {
|
|
|
|
std::thread::spawn(|| {
|
|
|
|
setup_rust_inner(run);
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
mod output {
|
2024-04-16 21:29:53 +02:00
|
|
|
use pinnacle::state::WithState;
|
|
|
|
use pinnacle_api::output::{Alignment, OutputLoc, OutputSetup, UpdateLocsOn};
|
|
|
|
use smithay::{output::Output, utils::Rectangle};
|
2024-04-16 14:04:34 +02:00
|
|
|
|
|
|
|
use super::*;
|
|
|
|
|
|
|
|
#[tokio::main]
|
|
|
|
#[self::test]
|
|
|
|
async fn setup() -> anyhow::Result<()> {
|
|
|
|
test_api(|sender| {
|
|
|
|
setup_rust(|api| {
|
2024-04-16 21:29:53 +02:00
|
|
|
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("Second").with_scale(2.0).with_mode(
|
|
|
|
pinnacle_api::output::Mode {
|
|
|
|
pixel_width: 6900,
|
|
|
|
pixel_height: 420,
|
|
|
|
refresh_rate_millihertz: 69420,
|
|
|
|
},
|
|
|
|
),
|
|
|
|
]);
|
2024-04-16 14:04:34 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
sleep_secs(1);
|
|
|
|
|
|
|
|
with_state(&sender, |state| {
|
|
|
|
state.new_output("First", (300, 200).into());
|
2024-04-16 21:29:53 +02:00
|
|
|
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);
|
2024-04-16 14:04:34 +02:00
|
|
|
});
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
#[tokio::main]
|
|
|
|
#[self::test]
|
2024-04-17 02:25:59 +02:00
|
|
|
async fn setup_loc_with_cyclic_relative_locs_works() -> anyhow::Result<()> {
|
2024-04-16 14:04:34 +02:00
|
|
|
test_api(|sender| {
|
|
|
|
setup_rust(|api| {
|
2024-04-16 21:29:53 +02:00
|
|
|
api.output.setup_locs(
|
|
|
|
UpdateLocsOn::all(),
|
|
|
|
[
|
|
|
|
("Pinnacle Window", OutputLoc::Point(0, 0)),
|
|
|
|
(
|
|
|
|
"First",
|
2024-04-16 23:26:54 +02:00
|
|
|
OutputLoc::relative_to("Second", Alignment::LeftAlignTop),
|
2024-04-16 21:29:53 +02:00
|
|
|
),
|
|
|
|
(
|
|
|
|
"Second",
|
2024-04-16 23:26:54 +02:00
|
|
|
OutputLoc::relative_to("First", Alignment::RightAlignTop),
|
2024-04-16 21:29:53 +02:00
|
|
|
),
|
|
|
|
],
|
|
|
|
);
|
2024-04-16 14:04:34 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
sleep_secs(1);
|
|
|
|
|
|
|
|
with_state(&sender, |state| {
|
|
|
|
state.new_output("First", (300, 200).into());
|
|
|
|
});
|
|
|
|
|
|
|
|
sleep_secs(1);
|
|
|
|
|
|
|
|
with_state(&sender, |state| {
|
2024-04-16 21:29:53 +02:00
|
|
|
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();
|
2024-04-16 14:04:34 +02:00
|
|
|
|
|
|
|
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))
|
|
|
|
);
|
2024-04-16 18:10:47 +02:00
|
|
|
|
|
|
|
state.new_output("Second", (500, 500).into());
|
|
|
|
});
|
|
|
|
|
|
|
|
sleep_secs(1);
|
|
|
|
|
|
|
|
with_state(&sender, |state| {
|
2024-04-16 21:29:53 +02:00
|
|
|
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();
|
2024-04-16 18:10:47 +02:00
|
|
|
|
|
|
|
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]
|
2024-04-16 21:29:53 +02:00
|
|
|
async fn setup_loc_with_relative_locs_with_more_than_one_relative_works() -> anyhow::Result<()>
|
|
|
|
{
|
2024-04-16 18:10:47 +02:00
|
|
|
test_api(|sender| {
|
|
|
|
setup_rust(|api| {
|
2024-04-16 21:29:53 +02:00
|
|
|
api.output.setup_locs(
|
|
|
|
UpdateLocsOn::all(),
|
|
|
|
[
|
|
|
|
("Pinnacle Window", OutputLoc::Point(0, 0)),
|
|
|
|
(
|
|
|
|
"First",
|
|
|
|
OutputLoc::relative_to("Pinnacle Window", Alignment::BottomAlignLeft),
|
|
|
|
),
|
|
|
|
(
|
|
|
|
"Second",
|
|
|
|
OutputLoc::relative_to("First", Alignment::BottomAlignLeft),
|
|
|
|
),
|
|
|
|
(
|
|
|
|
"Third",
|
2024-04-16 23:26:54 +02:00
|
|
|
OutputLoc::relative_to_with_fallbacks(
|
|
|
|
"Second",
|
|
|
|
Alignment::BottomAlignLeft,
|
|
|
|
[("First", Alignment::BottomAlignLeft)],
|
|
|
|
),
|
2024-04-16 21:29:53 +02:00
|
|
|
),
|
|
|
|
],
|
|
|
|
);
|
2024-04-16 18:10:47 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
sleep_secs(1);
|
|
|
|
|
|
|
|
with_state(&sender, |state| {
|
|
|
|
state.new_output("First", (300, 200).into());
|
2024-04-16 21:29:53 +02:00
|
|
|
state.new_output("Second", (300, 700).into());
|
|
|
|
state.new_output("Third", (300, 400).into());
|
2024-04-16 18:10:47 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
sleep_secs(1);
|
|
|
|
|
|
|
|
with_state(&sender, |state| {
|
2024-04-16 21:29:53 +02:00
|
|
|
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))
|
|
|
|
);
|
2024-04-16 14:04:34 +02:00
|
|
|
});
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|