refactor: output handling and output registry

This commit is contained in:
drendog 2025-11-18 18:48:35 +01:00
parent 49432eecd2
commit fc4604c758
Signed by: dwenya
GPG key ID: 8DD77074645332D0
11 changed files with 263 additions and 131 deletions

View file

@ -169,16 +169,16 @@ impl Dispatch<WlPointer, ()> for AppState {
if let Some(window) = state.get_output_by_surface_mut(&surface_id) { if let Some(window) = state.get_output_by_surface_mut(&surface_id) {
window.handle_pointer_enter(serial, &surface, surface_x, surface_y); window.handle_pointer_enter(serial, &surface, surface_x, surface_y);
if let Some(key) = state.get_key_by_surface(&surface_id) { if let Some(handle) = state.get_handle_by_surface(&surface_id) {
state.set_active_output(Some(key)); state.set_active_output_handle(Some(handle));
} }
} else { } else {
let key = state.get_key_by_popup(&surface_id); let handle = state.get_handle_by_popup(&surface_id);
if let Some(window) = state.find_output_by_popup_mut(&surface_id) { if let Some(window) = state.find_output_by_popup_mut(&surface_id) {
window.handle_pointer_enter(serial, &surface, surface_x, surface_y); window.handle_pointer_enter(serial, &surface, surface_x, surface_y);
if let Some(key) = key { if let Some(handle) = handle {
state.set_active_output(Some(key)); state.set_active_output_handle(Some(handle));
} }
} }
} }
@ -189,20 +189,20 @@ impl Dispatch<WlPointer, ()> for AppState {
surface_y, surface_y,
.. ..
} => { } => {
if let Some(output_key) = state.active_output() { if let Some(output_handle) = state.active_output_handle() {
if let Some(window) = state.get_output_by_key_mut(&output_key) { if let Some(window) = state.get_output_by_handle_mut(output_handle) {
window.handle_pointer_motion(surface_x, surface_y); window.handle_pointer_motion(surface_x, surface_y);
} }
} }
} }
wl_pointer::Event::Leave { .. } => { wl_pointer::Event::Leave { .. } => {
if let Some(output_key) = state.active_output() { if let Some(output_handle) = state.active_output_handle() {
if let Some(window) = state.get_output_by_key_mut(&output_key) { if let Some(window) = state.get_output_by_handle_mut(output_handle) {
window.handle_pointer_leave(); window.handle_pointer_leave();
} }
} }
state.set_active_output(None); state.set_active_output_handle(None);
} }
wl_pointer::Event::Button { wl_pointer::Event::Button {
@ -210,8 +210,8 @@ impl Dispatch<WlPointer, ()> for AppState {
state: button_state, state: button_state,
.. ..
} => { } => {
if let Some(output_key) = state.active_output() { if let Some(output_handle) = state.active_output_handle() {
if let Some(window) = state.get_output_by_key_mut(&output_key) { if let Some(window) = state.get_output_by_handle_mut(output_handle) {
window.handle_pointer_button(serial, button_state); window.handle_pointer_button(serial, button_state);
} }
} }

View file

@ -1,42 +1,36 @@
use layer_shika_domain::value_objects::output_handle::OutputHandle; use layer_shika_domain::value_objects::output_handle::OutputHandle;
use std::collections::hash_map::DefaultHasher; use std::collections::HashMap;
use std::hash::{Hash, Hasher};
use wayland_client::backend::ObjectId; use wayland_client::backend::ObjectId;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct OutputMapping {
pub struct OutputKey { object_to_handle: HashMap<ObjectId, OutputHandle>,
handle: OutputHandle,
_object_id_hash: u64,
} }
impl OutputKey { impl OutputMapping {
pub fn new(object_id: &ObjectId) -> Self { pub fn new() -> Self {
let mut hasher = DefaultHasher::new();
object_id.hash(&mut hasher);
let object_id_hash = hasher.finish();
Self { Self {
handle: OutputHandle::new(), object_to_handle: HashMap::new(),
_object_id_hash: object_id_hash,
} }
} }
pub const fn handle(&self) -> OutputHandle { pub fn insert(&mut self, object_id: ObjectId) -> OutputHandle {
self.handle let handle = OutputHandle::new();
self.object_to_handle.insert(object_id, handle);
handle
}
pub fn get(&self, object_id: &ObjectId) -> Option<OutputHandle> {
self.object_to_handle.get(object_id).copied()
}
#[allow(dead_code)]
pub fn remove(&mut self, object_id: &ObjectId) -> Option<OutputHandle> {
self.object_to_handle.remove(object_id)
} }
} }
impl From<ObjectId> for OutputKey { impl Default for OutputMapping {
fn from(id: ObjectId) -> Self { fn default() -> Self {
Self::new(&id) Self::new()
}
}
impl From<OutputHandle> for OutputKey {
fn from(handle: OutputHandle) -> Self {
Self {
handle,
_object_id_hash: 0,
}
} }
} }

View file

@ -1,7 +1,8 @@
use super::event_context::SharedPointerSerial; use super::event_context::SharedPointerSerial;
use super::surface_state::WindowState; use super::surface_state::WindowState;
use crate::wayland::managed_proxies::ManagedWlPointer; use crate::wayland::managed_proxies::ManagedWlPointer;
use crate::wayland::outputs::OutputKey; use crate::wayland::outputs::OutputMapping;
use layer_shika_domain::entities::output_registry::OutputRegistry;
use layer_shika_domain::value_objects::output_handle::OutputHandle; use layer_shika_domain::value_objects::output_handle::OutputHandle;
use layer_shika_domain::value_objects::output_info::OutputInfo; use layer_shika_domain::value_objects::output_info::OutputInfo;
use std::collections::HashMap; use std::collections::HashMap;
@ -12,27 +13,23 @@ use wayland_client::backend::ObjectId;
pub type PerOutputWindow = WindowState; pub type PerOutputWindow = WindowState;
pub struct AppState { pub struct AppState {
outputs: HashMap<OutputHandle, PerOutputWindow>, output_registry: OutputRegistry,
output_info: HashMap<OutputHandle, OutputInfo>, output_mapping: OutputMapping,
windows: HashMap<OutputHandle, PerOutputWindow>,
surface_to_output: HashMap<ObjectId, OutputHandle>, surface_to_output: HashMap<ObjectId, OutputHandle>,
output_to_handle: HashMap<ObjectId, OutputHandle>,
_pointer: ManagedWlPointer, _pointer: ManagedWlPointer,
shared_pointer_serial: Rc<SharedPointerSerial>, shared_pointer_serial: Rc<SharedPointerSerial>,
active_output: Option<OutputHandle>,
primary_output: Option<OutputHandle>,
} }
impl AppState { impl AppState {
pub fn new(pointer: ManagedWlPointer, shared_serial: Rc<SharedPointerSerial>) -> Self { pub fn new(pointer: ManagedWlPointer, shared_serial: Rc<SharedPointerSerial>) -> Self {
Self { Self {
outputs: HashMap::new(), output_registry: OutputRegistry::new(),
output_info: HashMap::new(), output_mapping: OutputMapping::new(),
windows: HashMap::new(),
surface_to_output: HashMap::new(), surface_to_output: HashMap::new(),
output_to_handle: HashMap::new(),
_pointer: pointer, _pointer: pointer,
shared_pointer_serial: shared_serial, shared_pointer_serial: shared_serial,
active_output: None,
primary_output: None,
} }
} }
@ -42,61 +39,48 @@ impl AppState {
main_surface_id: ObjectId, main_surface_id: ObjectId,
window: PerOutputWindow, window: PerOutputWindow,
) { ) {
let key = OutputKey::new(&output_id); let handle = self.output_mapping.insert(output_id);
let handle = key.handle();
self.output_to_handle.insert(output_id, handle);
self.surface_to_output.insert(main_surface_id, handle); self.surface_to_output.insert(main_surface_id, handle);
let is_primary = self.primary_output.is_none(); let is_primary = self.output_registry.is_empty();
if is_primary {
self.primary_output = Some(handle);
}
let mut info = OutputInfo::new(handle); let mut info = OutputInfo::new(handle);
info.set_primary(is_primary); info.set_primary(is_primary);
self.output_info.insert(handle, info);
self.outputs.insert(handle, window); self.output_registry.add(info);
} self.windows.insert(handle, window);
pub fn get_output_by_key(&self, key: &OutputKey) -> Option<&PerOutputWindow> {
self.outputs.get(&key.handle())
}
pub fn get_output_by_key_mut(&mut self, key: &OutputKey) -> Option<&mut PerOutputWindow> {
self.outputs.get_mut(&key.handle())
} }
pub fn get_output_by_handle(&self, handle: OutputHandle) -> Option<&PerOutputWindow> { pub fn get_output_by_handle(&self, handle: OutputHandle) -> Option<&PerOutputWindow> {
self.outputs.get(&handle) self.windows.get(&handle)
} }
pub fn get_output_by_handle_mut( pub fn get_output_by_handle_mut(
&mut self, &mut self,
handle: OutputHandle, handle: OutputHandle,
) -> Option<&mut PerOutputWindow> { ) -> Option<&mut PerOutputWindow> {
self.outputs.get_mut(&handle) self.windows.get_mut(&handle)
} }
pub fn get_output_by_output_id(&self, output_id: &ObjectId) -> Option<&PerOutputWindow> { pub fn get_output_by_output_id(&self, output_id: &ObjectId) -> Option<&PerOutputWindow> {
self.output_to_handle self.output_mapping
.get(output_id) .get(output_id)
.and_then(|handle| self.outputs.get(handle)) .and_then(|handle| self.windows.get(&handle))
} }
pub fn get_output_by_output_id_mut( pub fn get_output_by_output_id_mut(
&mut self, &mut self,
output_id: &ObjectId, output_id: &ObjectId,
) -> Option<&mut PerOutputWindow> { ) -> Option<&mut PerOutputWindow> {
self.output_to_handle self.output_mapping
.get(output_id) .get(output_id)
.and_then(|handle| self.outputs.get_mut(handle)) .and_then(|handle| self.windows.get_mut(&handle))
} }
pub fn get_output_by_surface(&self, surface_id: &ObjectId) -> Option<&PerOutputWindow> { pub fn get_output_by_surface(&self, surface_id: &ObjectId) -> Option<&PerOutputWindow> {
self.surface_to_output self.surface_to_output
.get(surface_id) .get(surface_id)
.and_then(|handle| self.outputs.get(handle)) .and_then(|handle| self.windows.get(handle))
} }
pub fn get_output_by_surface_mut( pub fn get_output_by_surface_mut(
@ -105,78 +89,69 @@ impl AppState {
) -> Option<&mut PerOutputWindow> { ) -> Option<&mut PerOutputWindow> {
self.surface_to_output self.surface_to_output
.get(surface_id) .get(surface_id)
.and_then(|handle| self.outputs.get_mut(handle)) .and_then(|handle| self.windows.get_mut(handle))
} }
pub fn get_output_by_layer_surface_mut( pub fn get_output_by_layer_surface_mut(
&mut self, &mut self,
layer_surface_id: &ObjectId, layer_surface_id: &ObjectId,
) -> Option<&mut PerOutputWindow> { ) -> Option<&mut PerOutputWindow> {
self.outputs self.windows
.values_mut() .values_mut()
.find(|window| window.layer_surface().as_ref().id() == *layer_surface_id) .find(|window| window.layer_surface().as_ref().id() == *layer_surface_id)
} }
pub fn get_key_by_surface(&self, surface_id: &ObjectId) -> Option<OutputKey> {
self.surface_to_output
.get(surface_id)
.map(|&handle| OutputKey::from(handle))
}
pub fn get_key_by_output_id(&self, output_id: &ObjectId) -> Option<OutputKey> {
self.output_to_handle
.get(output_id)
.map(|&handle| OutputKey::from(handle))
}
pub fn get_handle_by_surface(&self, surface_id: &ObjectId) -> Option<OutputHandle> { pub fn get_handle_by_surface(&self, surface_id: &ObjectId) -> Option<OutputHandle> {
self.surface_to_output.get(surface_id).copied() self.surface_to_output.get(surface_id).copied()
} }
pub fn get_handle_by_output_id(&self, output_id: &ObjectId) -> Option<OutputHandle> { pub fn get_handle_by_output_id(&self, output_id: &ObjectId) -> Option<OutputHandle> {
self.output_to_handle.get(output_id).copied() self.output_mapping.get(output_id)
} }
pub fn register_popup_surface(&mut self, popup_surface_id: ObjectId, output_key: OutputKey) { pub fn register_popup_surface(
&mut self,
popup_surface_id: ObjectId,
output_handle: OutputHandle,
) {
self.surface_to_output self.surface_to_output
.insert(popup_surface_id, output_key.handle()); .insert(popup_surface_id, output_handle);
}
pub fn set_active_output(&mut self, key: Option<OutputKey>) {
self.active_output = key.map(|k| k.handle());
} }
pub fn set_active_output_handle(&mut self, handle: Option<OutputHandle>) { pub fn set_active_output_handle(&mut self, handle: Option<OutputHandle>) {
self.active_output = handle; self.output_registry.set_active(handle);
}
pub fn active_output(&self) -> Option<OutputKey> {
self.active_output.map(OutputKey::from)
} }
pub fn active_output_handle(&self) -> Option<OutputHandle> { pub fn active_output_handle(&self) -> Option<OutputHandle> {
self.active_output self.output_registry.active_handle()
} }
pub fn primary_output(&self) -> Option<&PerOutputWindow> { pub fn primary_output(&self) -> Option<&PerOutputWindow> {
self.primary_output self.output_registry
.and_then(|handle| self.outputs.get(&handle)) .primary_handle()
.and_then(|handle| self.windows.get(&handle))
} }
pub fn primary_output_handle(&self) -> Option<OutputHandle> { pub fn primary_output_handle(&self) -> Option<OutputHandle> {
self.primary_output self.output_registry.primary_handle()
}
pub fn active_output(&self) -> Option<&PerOutputWindow> {
self.output_registry
.active_handle()
.and_then(|handle| self.windows.get(&handle))
} }
pub fn all_outputs(&self) -> impl Iterator<Item = &PerOutputWindow> { pub fn all_outputs(&self) -> impl Iterator<Item = &PerOutputWindow> {
self.outputs.values() self.windows.values()
} }
pub fn all_outputs_mut(&mut self) -> impl Iterator<Item = &mut PerOutputWindow> { pub fn all_outputs_mut(&mut self) -> impl Iterator<Item = &mut PerOutputWindow> {
self.outputs.values_mut() self.windows.values_mut()
} }
pub fn outputs_with_handles(&self) -> impl Iterator<Item = (OutputHandle, &PerOutputWindow)> { pub fn outputs_with_handles(&self) -> impl Iterator<Item = (OutputHandle, &PerOutputWindow)> {
self.outputs self.windows
.iter() .iter()
.map(|(&handle, window)| (handle, window)) .map(|(&handle, window)| (handle, window))
} }
@ -186,7 +161,7 @@ impl AppState {
} }
pub fn find_output_by_popup(&self, popup_surface_id: &ObjectId) -> Option<&PerOutputWindow> { pub fn find_output_by_popup(&self, popup_surface_id: &ObjectId) -> Option<&PerOutputWindow> {
self.outputs.values().find(|window| { self.windows.values().find(|window| {
window window
.popup_manager() .popup_manager()
.as_ref() .as_ref()
@ -199,7 +174,7 @@ impl AppState {
&mut self, &mut self,
popup_surface_id: &ObjectId, popup_surface_id: &ObjectId,
) -> Option<&mut PerOutputWindow> { ) -> Option<&mut PerOutputWindow> {
self.outputs.values_mut().find(|window| { self.windows.values_mut().find(|window| {
window window
.popup_manager() .popup_manager()
.as_ref() .as_ref()
@ -208,18 +183,8 @@ impl AppState {
}) })
} }
pub fn get_key_by_popup(&self, popup_surface_id: &ObjectId) -> Option<OutputKey> {
self.outputs.iter().find_map(|(&handle, window)| {
window
.popup_manager()
.as_ref()
.and_then(|pm| pm.find_by_surface(popup_surface_id))
.map(|_| OutputKey::from(handle))
})
}
pub fn get_handle_by_popup(&self, popup_surface_id: &ObjectId) -> Option<OutputHandle> { pub fn get_handle_by_popup(&self, popup_surface_id: &ObjectId) -> Option<OutputHandle> {
self.outputs.iter().find_map(|(&handle, window)| { self.windows.iter().find_map(|(&handle, window)| {
window window
.popup_manager() .popup_manager()
.as_ref() .as_ref()
@ -229,20 +194,24 @@ impl AppState {
} }
pub fn get_output_info(&self, handle: OutputHandle) -> Option<&OutputInfo> { pub fn get_output_info(&self, handle: OutputHandle) -> Option<&OutputInfo> {
self.output_info.get(&handle) self.output_registry.get(handle)
} }
pub fn get_output_info_mut(&mut self, handle: OutputHandle) -> Option<&mut OutputInfo> { pub fn get_output_info_mut(&mut self, handle: OutputHandle) -> Option<&mut OutputInfo> {
self.output_info.get_mut(&handle) self.output_registry.get_mut(handle)
} }
pub fn all_output_info(&self) -> impl Iterator<Item = &OutputInfo> { pub fn all_output_info(&self) -> impl Iterator<Item = &OutputInfo> {
self.output_info.values() self.output_registry.all_info()
} }
pub fn outputs_with_info(&self) -> impl Iterator<Item = (&OutputInfo, &PerOutputWindow)> { pub fn outputs_with_info(&self) -> impl Iterator<Item = (&OutputInfo, &PerOutputWindow)> {
self.output_info self.output_registry
.iter() .all()
.filter_map(|(handle, info)| self.outputs.get(handle).map(|window| (info, window))) .filter_map(|(handle, info)| self.windows.get(&handle).map(|window| (info, window)))
}
pub const fn output_registry(&self) -> &OutputRegistry {
&self.output_registry
} }
} }

View file

@ -11,6 +11,7 @@ use std::result::Result as StdResult;
pub use builder::LayerShika; pub use builder::LayerShika;
pub use layer_shika_adapters::PopupWindow; pub use layer_shika_adapters::PopupWindow;
pub use layer_shika_adapters::platform::{slint, slint_interpreter}; pub use layer_shika_adapters::platform::{slint, slint_interpreter};
pub use layer_shika_domain::entities::output_registry::OutputRegistry;
pub use layer_shika_domain::value_objects::anchor::AnchorEdges; pub use layer_shika_domain::value_objects::anchor::AnchorEdges;
pub use layer_shika_domain::value_objects::keyboard_interactivity::KeyboardInteractivity; pub use layer_shika_domain::value_objects::keyboard_interactivity::KeyboardInteractivity;
pub use layer_shika_domain::value_objects::layer::Layer; pub use layer_shika_domain::value_objects::layer::Layer;

View file

@ -13,6 +13,7 @@ use layer_shika_adapters::{
AppState, PopupManager, WaylandWindowConfig, WindowState, WindowingSystemFacade, AppState, PopupManager, WaylandWindowConfig, WindowState, WindowingSystemFacade,
}; };
use layer_shika_domain::config::WindowConfig; use layer_shika_domain::config::WindowConfig;
use layer_shika_domain::entities::output_registry::OutputRegistry;
use layer_shika_domain::errors::DomainError; use layer_shika_domain::errors::DomainError;
use layer_shika_domain::value_objects::output_handle::OutputHandle; use layer_shika_domain::value_objects::output_handle::OutputHandle;
use layer_shika_domain::value_objects::output_info::OutputInfo; use layer_shika_domain::value_objects::output_info::OutputInfo;
@ -141,6 +142,10 @@ impl RuntimeState<'_> {
.map(WindowState::component_instance) .map(WindowState::component_instance)
} }
pub const fn output_registry(&self) -> &OutputRegistry {
self.app_state.output_registry()
}
#[must_use] #[must_use]
pub fn primary_output_handle(&self) -> Option<OutputHandle> { pub fn primary_output_handle(&self) -> Option<OutputHandle> {
self.app_state.primary_output_handle() self.app_state.primary_output_handle()
@ -180,7 +185,6 @@ impl RuntimeState<'_> {
fn active_or_primary_output(&self) -> Option<&WindowState> { fn active_or_primary_output(&self) -> Option<&WindowState> {
self.app_state self.app_state
.active_output() .active_output()
.and_then(|key| self.app_state.get_output_by_key(&key))
.or_else(|| self.app_state.primary_output()) .or_else(|| self.app_state.primary_output())
} }
@ -579,4 +583,10 @@ impl WindowingSystem {
let system = facade.inner_ref(); let system = facade.inner_ref();
system.app_state().all_output_info().cloned().collect() system.app_state().all_output_info().cloned().collect()
} }
pub fn output_registry(&self) -> OutputRegistry {
let facade = self.inner.borrow();
let system = facade.inner_ref();
system.app_state().output_registry().clone()
}
} }

View file

@ -1,3 +1,4 @@
pub mod component; pub mod component;
pub mod output_registry;
pub mod surface; pub mod surface;
pub mod window; pub mod window;

View file

@ -0,0 +1,156 @@
use crate::value_objects::output_handle::OutputHandle;
use crate::value_objects::output_info::OutputInfo;
use crate::value_objects::output_policy::OutputPolicy;
use std::collections::HashMap;
#[derive(Clone)]
pub struct OutputRegistry {
outputs: HashMap<OutputHandle, OutputInfo>,
primary_output: Option<OutputHandle>,
active_output: Option<OutputHandle>,
}
impl OutputRegistry {
pub fn new() -> Self {
Self {
outputs: HashMap::new(),
primary_output: None,
active_output: None,
}
}
pub fn add(&mut self, info: OutputInfo) -> OutputHandle {
let handle = info.handle();
let is_first = self.outputs.is_empty();
self.outputs.insert(handle, info);
if is_first {
self.primary_output = Some(handle);
}
handle
}
pub fn remove(&mut self, handle: OutputHandle) -> Option<OutputInfo> {
let info = self.outputs.remove(&handle);
if self.primary_output == Some(handle) {
self.primary_output = self.outputs.keys().next().copied();
}
if self.active_output == Some(handle) {
self.active_output = None;
}
info
}
pub fn get(&self, handle: OutputHandle) -> Option<&OutputInfo> {
self.outputs.get(&handle)
}
pub fn get_mut(&mut self, handle: OutputHandle) -> Option<&mut OutputInfo> {
self.outputs.get_mut(&handle)
}
pub fn find_by_name(&self, name: &str) -> Option<(OutputHandle, &OutputInfo)> {
self.outputs
.iter()
.find(|(_, info)| info.name() == Some(name))
.map(|(handle, info)| (*handle, info))
}
pub fn find_by_model(&self, model: &str) -> Option<(OutputHandle, &OutputInfo)> {
self.outputs
.iter()
.find(|(_, info)| info.geometry().and_then(|g| g.model.as_deref()) == Some(model))
.map(|(handle, info)| (*handle, info))
}
pub fn all(&self) -> impl Iterator<Item = (OutputHandle, &OutputInfo)> {
self.outputs.iter().map(|(handle, info)| (*handle, info))
}
pub fn all_info(&self) -> impl Iterator<Item = &OutputInfo> {
self.outputs.values()
}
pub fn primary(&self) -> Option<(OutputHandle, &OutputInfo)> {
self.primary_output
.and_then(|handle| self.outputs.get(&handle).map(|info| (handle, info)))
}
pub fn primary_handle(&self) -> Option<OutputHandle> {
self.primary_output
}
pub fn active(&self) -> Option<(OutputHandle, &OutputInfo)> {
self.active_output
.and_then(|handle| self.outputs.get(&handle).map(|info| (handle, info)))
}
pub fn active_handle(&self) -> Option<OutputHandle> {
self.active_output
}
pub fn active_or_primary(&self) -> Option<(OutputHandle, &OutputInfo)> {
self.active().or_else(|| self.primary())
}
pub fn active_or_primary_handle(&self) -> Option<OutputHandle> {
self.active_output.or(self.primary_output)
}
pub fn set_active(&mut self, handle: Option<OutputHandle>) {
if let Some(h) = handle {
if self.outputs.contains_key(&h) {
self.active_output = Some(h);
}
} else {
self.active_output = None;
}
}
pub fn set_primary(&mut self, handle: OutputHandle) -> bool {
if !self.outputs.contains_key(&handle) {
return false;
}
if let Some(old_primary) = self.primary_output {
if let Some(old_info) = self.outputs.get_mut(&old_primary) {
old_info.set_primary(false);
}
}
self.primary_output = Some(handle);
if let Some(new_info) = self.outputs.get_mut(&handle) {
new_info.set_primary(true);
}
true
}
pub fn select_by_policy(&self, policy: &OutputPolicy) -> Vec<(OutputHandle, &OutputInfo)> {
self.outputs
.iter()
.filter(|(_, info)| policy.should_render(info))
.map(|(handle, info)| (*handle, info))
.collect()
}
pub fn count(&self) -> usize {
self.outputs.len()
}
pub fn is_empty(&self) -> bool {
self.outputs.is_empty()
}
}
impl Default for OutputRegistry {
fn default() -> Self {
Self::new()
}
}

View file

@ -1,6 +1,6 @@
pub mod config; pub mod config;
pub mod dimensions; pub mod dimensions;
pub(crate) mod entities; pub mod entities;
pub mod errors; pub mod errors;
pub mod ports; pub mod ports;
pub mod prelude; pub mod prelude;

View file

@ -5,6 +5,7 @@ pub use crate::dimensions::{
LogicalPosition, LogicalSize, PhysicalPosition, PhysicalSize, ScaleFactor, LogicalPosition, LogicalSize, PhysicalPosition, PhysicalSize, ScaleFactor,
}; };
pub use crate::entities::component::UiComponentHandle; pub use crate::entities::component::UiComponentHandle;
pub use crate::entities::output_registry::OutputRegistry;
pub use crate::entities::surface::SurfaceHandle; pub use crate::entities::surface::SurfaceHandle;
pub use crate::entities::window::WindowHandle; pub use crate::entities::window::WindowHandle;
pub use crate::errors::{DomainError, Result}; pub use crate::errors::{DomainError, Result};

View file

@ -46,7 +46,7 @@ pub mod prelude;
pub use layer_shika_composition::{ pub use layer_shika_composition::{
AnchorEdges, Error, EventLoopHandle, KeyboardInteractivity, Layer, LayerShika, OutputGeometry, AnchorEdges, Error, EventLoopHandle, KeyboardInteractivity, Layer, LayerShika, OutputGeometry,
OutputHandle, OutputInfo, OutputPolicy, PopupAt, PopupHandle, PopupPositioningMode, OutputHandle, OutputInfo, OutputPolicy, OutputRegistry, PopupAt, PopupHandle, PopupPositioningMode,
PopupRequest, PopupSize, PopupWindow, Result, RuntimeState, SlintCallbackContract, PopupRequest, PopupSize, PopupWindow, Result, RuntimeState, SlintCallbackContract,
SlintCallbackNames, WindowingSystem, SlintCallbackNames, WindowingSystem,
}; };

View file

@ -17,7 +17,7 @@ pub use crate::{
// Domain value objects // Domain value objects
pub use crate::{ pub use crate::{
AnchorEdges, KeyboardInteractivity, Layer, OutputGeometry, OutputHandle, OutputInfo, AnchorEdges, KeyboardInteractivity, Layer, OutputGeometry, OutputHandle, OutputInfo,
OutputPolicy, PopupAt, PopupHandle, PopupPositioningMode, PopupRequest, PopupSize, OutputPolicy, OutputRegistry, PopupAt, PopupHandle, PopupPositioningMode, PopupRequest, PopupSize,
}; };
// Event loop types // Event loop types