use rustc_hash::FxHashMap;
use crate::reactive::global::GlobalSignal;
use crate::reactive::{RwSignal, Signal};
use crate::surface::SurfaceId;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct OutputId(u32);
impl OutputId {
pub(crate) fn from_raw(raw: u32) -> Self {
Self(raw)
}
pub fn raw(&self) -> u32 {
self.0
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct OutputInfo {
pub id: OutputId,
pub name: Option<String>,
pub description: Option<String>,
pub make: String,
pub model: String,
pub scale_factor: i32,
pub logical_size: Option<(i32, i32)>,
pub logical_position: Option<(i32, i32)>,
}
#[cfg(any(test, feature = "testing"))]
impl OutputInfo {
pub(crate) fn named(id: OutputId, name: &str) -> Self {
Self {
id,
name: Some(name.to_string()),
description: None,
make: String::new(),
model: String::new(),
scale_factor: 1,
logical_size: None,
logical_position: None,
}
}
}
static OUTPUTS: GlobalSignal<Vec<OutputInfo>> = GlobalSignal::new(Vec::new);
static SURFACE_OUTPUTS: GlobalSignal<FxHashMap<SurfaceId, OutputId>> =
GlobalSignal::new(FxHashMap::default);
fn outputs_signal() -> RwSignal<Vec<OutputInfo>> {
OUTPUTS.get()
}
fn surface_outputs_signal() -> RwSignal<FxHashMap<SurfaceId, OutputId>> {
SURFACE_OUTPUTS.get()
}
pub fn outputs() -> Signal<Vec<OutputInfo>> {
outputs_signal().read_only()
}
pub fn surface_output(id: SurfaceId) -> Option<OutputId> {
surface_outputs_signal().with(|m| m.get(&id).copied())
}
pub(crate) fn current_outputs() -> Vec<OutputInfo> {
outputs_signal().with_untracked(|v| v.clone())
}
pub(crate) fn sync_outputs(list: Vec<OutputInfo>) {
outputs_signal().set(list);
}
pub(crate) fn surface_entered_output(surface: SurfaceId, output: OutputId) {
surface_outputs_signal().update(|m| {
m.insert(surface, output);
});
}
pub(crate) fn surface_left_output(surface: SurfaceId, output: OutputId) {
surface_outputs_signal().update(|m| {
if m.get(&surface) == Some(&output) {
m.remove(&surface);
}
});
}
pub(crate) fn surface_closed(surface: SurfaceId) {
surface_outputs_signal().update(|m| {
m.remove(&surface);
});
}
pub(crate) fn output_removed(output: OutputId) {
surface_outputs_signal().update(|m| {
m.retain(|_, o| *o != output);
});
}