mirror of
https://codeberg.org/waydeer/layer-shika.git
synced 2025-12-23 11:25:54 +00:00
feat: add output abstractions and its policy
This commit is contained in:
parent
e194682785
commit
49432eecd2
14 changed files with 317 additions and 10 deletions
|
|
@ -3,6 +3,7 @@ use layer_shika_domain::value_objects::anchor::AnchorEdges;
|
||||||
use layer_shika_domain::value_objects::keyboard_interactivity::KeyboardInteractivity as DomainKeyboardInteractivity;
|
use layer_shika_domain::value_objects::keyboard_interactivity::KeyboardInteractivity as DomainKeyboardInteractivity;
|
||||||
use layer_shika_domain::value_objects::layer::Layer;
|
use layer_shika_domain::value_objects::layer::Layer;
|
||||||
use layer_shika_domain::value_objects::margins::Margins;
|
use layer_shika_domain::value_objects::margins::Margins;
|
||||||
|
use layer_shika_domain::value_objects::output_policy::OutputPolicy;
|
||||||
use slint_interpreter::{CompilationResult, ComponentDefinition};
|
use slint_interpreter::{CompilationResult, ComponentDefinition};
|
||||||
use smithay_client_toolkit::reexports::protocols_wlr::layer_shell::v1::client::{
|
use smithay_client_toolkit::reexports::protocols_wlr::layer_shell::v1::client::{
|
||||||
zwlr_layer_shell_v1::{self},
|
zwlr_layer_shell_v1::{self},
|
||||||
|
|
@ -31,6 +32,7 @@ pub struct WaylandWindowConfig {
|
||||||
pub namespace: String,
|
pub namespace: String,
|
||||||
pub component_definition: ComponentDefinition,
|
pub component_definition: ComponentDefinition,
|
||||||
pub compilation_result: Option<Rc<CompilationResult>>,
|
pub compilation_result: Option<Rc<CompilationResult>>,
|
||||||
|
pub output_policy: OutputPolicy,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WaylandWindowConfig {
|
impl WaylandWindowConfig {
|
||||||
|
|
@ -53,6 +55,7 @@ impl WaylandWindowConfig {
|
||||||
namespace: domain_config.namespace,
|
namespace: domain_config.namespace,
|
||||||
component_definition,
|
component_definition,
|
||||||
compilation_result,
|
compilation_result,
|
||||||
|
output_policy: domain_config.output_policy,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
use crate::wayland::surfaces::app_state::AppState;
|
use crate::wayland::surfaces::app_state::AppState;
|
||||||
use crate::wayland::surfaces::display_metrics::DisplayMetrics;
|
use crate::wayland::surfaces::display_metrics::DisplayMetrics;
|
||||||
|
use layer_shika_domain::value_objects::output_info::OutputGeometry;
|
||||||
use log::info;
|
use log::info;
|
||||||
use smithay_client_toolkit::reexports::protocols_wlr::layer_shell::v1::client::{
|
use smithay_client_toolkit::reexports::protocols_wlr::layer_shell::v1::client::{
|
||||||
zwlr_layer_shell_v1::ZwlrLayerShellV1,
|
zwlr_layer_shell_v1::ZwlrLayerShellV1,
|
||||||
|
|
@ -77,21 +78,38 @@ impl Dispatch<WlOutput, ()> for AppState {
|
||||||
_conn: &Connection,
|
_conn: &Connection,
|
||||||
_qhandle: &QueueHandle<Self>,
|
_qhandle: &QueueHandle<Self>,
|
||||||
) {
|
) {
|
||||||
|
let output_id = proxy.id();
|
||||||
|
let handle = state.get_handle_by_output_id(&output_id);
|
||||||
|
|
||||||
match event {
|
match event {
|
||||||
wl_output::Event::Mode { width, height, .. } => {
|
wl_output::Event::Mode { width, height, .. } => {
|
||||||
let output_id = proxy.id();
|
|
||||||
if let Some(window) = state.get_output_by_output_id_mut(&output_id) {
|
if let Some(window) = state.get_output_by_output_id_mut(&output_id) {
|
||||||
window.handle_output_mode(width, height);
|
window.handle_output_mode(width, height);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
wl_output::Event::Description { ref description } => {
|
wl_output::Event::Description { ref description } => {
|
||||||
info!("WlOutput description: {description:?}");
|
info!("WlOutput description: {description:?}");
|
||||||
|
if let Some(handle) = handle {
|
||||||
|
if let Some(info) = state.get_output_info_mut(handle) {
|
||||||
|
info.set_description(description.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
wl_output::Event::Scale { ref factor } => {
|
wl_output::Event::Scale { ref factor } => {
|
||||||
info!("WlOutput factor scale: {factor:?}");
|
info!("WlOutput factor scale: {factor:?}");
|
||||||
|
if let Some(handle) = handle {
|
||||||
|
if let Some(info) = state.get_output_info_mut(handle) {
|
||||||
|
info.set_scale(*factor);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
wl_output::Event::Name { ref name } => {
|
wl_output::Event::Name { ref name } => {
|
||||||
info!("WlOutput name: {name:?}");
|
info!("WlOutput name: {name:?}");
|
||||||
|
if let Some(handle) = handle {
|
||||||
|
if let Some(info) = state.get_output_info_mut(handle) {
|
||||||
|
info.set_name(name.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
wl_output::Event::Geometry {
|
wl_output::Event::Geometry {
|
||||||
x,
|
x,
|
||||||
|
|
@ -106,6 +124,19 @@ impl Dispatch<WlOutput, ()> for AppState {
|
||||||
info!(
|
info!(
|
||||||
"WlOutput geometry: x={x}, y={y}, physical_width={physical_width}, physical_height={physical_height}, subpixel={subpixel:?}, make={make:?}, model={model:?}, transform={transform:?}"
|
"WlOutput geometry: x={x}, y={y}, physical_width={physical_width}, physical_height={physical_height}, subpixel={subpixel:?}, make={make:?}, model={model:?}, transform={transform:?}"
|
||||||
);
|
);
|
||||||
|
if let Some(handle) = handle {
|
||||||
|
if let Some(info) = state.get_output_info_mut(handle) {
|
||||||
|
let mut geometry =
|
||||||
|
OutputGeometry::new(x, y, physical_width, physical_height);
|
||||||
|
if !make.is_empty() {
|
||||||
|
geometry = geometry.with_make(make);
|
||||||
|
}
|
||||||
|
if !model.is_empty() {
|
||||||
|
geometry = geometry.with_model(model);
|
||||||
|
}
|
||||||
|
info.set_geometry(geometry);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
wl_output::Event::Done => {
|
wl_output::Event::Done => {
|
||||||
info!("WlOutput done");
|
info!("WlOutput done");
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,8 @@ use crate::{
|
||||||
use core::result::Result as CoreResult;
|
use core::result::Result as CoreResult;
|
||||||
use layer_shika_domain::errors::DomainError;
|
use layer_shika_domain::errors::DomainError;
|
||||||
use layer_shika_domain::ports::windowing::WindowingSystemPort;
|
use layer_shika_domain::ports::windowing::WindowingSystemPort;
|
||||||
|
use layer_shika_domain::value_objects::output_handle::OutputHandle;
|
||||||
|
use layer_shika_domain::value_objects::output_info::OutputInfo;
|
||||||
use log::{error, info};
|
use log::{error, info};
|
||||||
use slint::{
|
use slint::{
|
||||||
LogicalPosition, PhysicalSize, PlatformError, WindowPosition,
|
LogicalPosition, PhysicalSize, PlatformError, WindowPosition,
|
||||||
|
|
@ -98,7 +100,17 @@ impl WaylandWindowingSystem {
|
||||||
) -> Result<Vec<OutputSetup>> {
|
) -> Result<Vec<OutputSetup>> {
|
||||||
let mut setups = Vec::new();
|
let mut setups = Vec::new();
|
||||||
|
|
||||||
for output in &global_ctx.outputs {
|
for (index, output) in global_ctx.outputs.iter().enumerate() {
|
||||||
|
let is_primary = index == 0;
|
||||||
|
|
||||||
|
let mut temp_info = OutputInfo::new(OutputHandle::new());
|
||||||
|
temp_info.set_primary(is_primary);
|
||||||
|
|
||||||
|
if !config.output_policy.should_render(&temp_info) {
|
||||||
|
info!("Skipping output {} due to output policy", index);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
let output_id = output.id();
|
let output_id = output.id();
|
||||||
|
|
||||||
let setup_params = SurfaceSetupParams {
|
let setup_params = SurfaceSetupParams {
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ 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::OutputKey;
|
||||||
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 std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use wayland_client::Proxy;
|
use wayland_client::Proxy;
|
||||||
|
|
@ -12,6 +13,7 @@ pub type PerOutputWindow = WindowState;
|
||||||
|
|
||||||
pub struct AppState {
|
pub struct AppState {
|
||||||
outputs: HashMap<OutputHandle, PerOutputWindow>,
|
outputs: HashMap<OutputHandle, PerOutputWindow>,
|
||||||
|
output_info: HashMap<OutputHandle, OutputInfo>,
|
||||||
surface_to_output: HashMap<ObjectId, OutputHandle>,
|
surface_to_output: HashMap<ObjectId, OutputHandle>,
|
||||||
output_to_handle: HashMap<ObjectId, OutputHandle>,
|
output_to_handle: HashMap<ObjectId, OutputHandle>,
|
||||||
_pointer: ManagedWlPointer,
|
_pointer: ManagedWlPointer,
|
||||||
|
|
@ -24,6 +26,7 @@ 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(),
|
outputs: HashMap::new(),
|
||||||
|
output_info: HashMap::new(),
|
||||||
surface_to_output: HashMap::new(),
|
surface_to_output: HashMap::new(),
|
||||||
output_to_handle: HashMap::new(),
|
output_to_handle: HashMap::new(),
|
||||||
_pointer: pointer,
|
_pointer: pointer,
|
||||||
|
|
@ -44,10 +47,15 @@ impl AppState {
|
||||||
self.output_to_handle.insert(output_id, 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);
|
||||||
|
|
||||||
if self.primary_output.is_none() {
|
let is_primary = self.primary_output.is_none();
|
||||||
|
if is_primary {
|
||||||
self.primary_output = Some(handle);
|
self.primary_output = Some(handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mut info = OutputInfo::new(handle);
|
||||||
|
info.set_primary(is_primary);
|
||||||
|
self.output_info.insert(handle, info);
|
||||||
|
|
||||||
self.outputs.insert(handle, window);
|
self.outputs.insert(handle, window);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -219,4 +227,22 @@ impl AppState {
|
||||||
.map(|_| handle)
|
.map(|_| handle)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_output_info(&self, handle: OutputHandle) -> Option<&OutputInfo> {
|
||||||
|
self.output_info.get(&handle)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_output_info_mut(&mut self, handle: OutputHandle) -> Option<&mut OutputInfo> {
|
||||||
|
self.output_info.get_mut(&handle)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn all_output_info(&self) -> impl Iterator<Item = &OutputInfo> {
|
||||||
|
self.output_info.values()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn outputs_with_info(&self) -> impl Iterator<Item = (&OutputInfo, &PerOutputWindow)> {
|
||||||
|
self.output_info
|
||||||
|
.iter()
|
||||||
|
.filter_map(|(handle, info)| self.outputs.get(handle).map(|window| (info, window)))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,8 @@ use crate::system::WindowingSystem;
|
||||||
use layer_shika_adapters::platform::slint_interpreter::{CompilationResult, Compiler};
|
use layer_shika_adapters::platform::slint_interpreter::{CompilationResult, Compiler};
|
||||||
use layer_shika_domain::errors::DomainError;
|
use layer_shika_domain::errors::DomainError;
|
||||||
use layer_shika_domain::prelude::{
|
use layer_shika_domain::prelude::{
|
||||||
AnchorEdges, KeyboardInteractivity, Layer, Margins, ScaleFactor, WindowConfig, WindowHeight,
|
AnchorEdges, KeyboardInteractivity, Layer, Margins, OutputPolicy, ScaleFactor, WindowConfig,
|
||||||
|
WindowHeight,
|
||||||
};
|
};
|
||||||
use spin_on::spin_on;
|
use spin_on::spin_on;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
|
@ -187,6 +188,12 @@ impl LayerShika<HasComponent> {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub fn with_output_policy(mut self, policy: OutputPolicy) -> Self {
|
||||||
|
self.config.output_policy = policy;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
pub fn build(self) -> Result<WindowingSystem> {
|
pub fn build(self) -> Result<WindowingSystem> {
|
||||||
let component_definition = self
|
let component_definition = self
|
||||||
.state
|
.state
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,8 @@ 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;
|
||||||
pub use layer_shika_domain::value_objects::output_handle::OutputHandle;
|
pub use layer_shika_domain::value_objects::output_handle::OutputHandle;
|
||||||
|
pub use layer_shika_domain::value_objects::output_info::{OutputGeometry, OutputInfo};
|
||||||
|
pub use layer_shika_domain::value_objects::output_policy::OutputPolicy;
|
||||||
pub use layer_shika_domain::value_objects::popup_positioning_mode::PopupPositioningMode;
|
pub use layer_shika_domain::value_objects::popup_positioning_mode::PopupPositioningMode;
|
||||||
pub use layer_shika_domain::value_objects::popup_request::{
|
pub use layer_shika_domain::value_objects::popup_request::{
|
||||||
PopupAt, PopupHandle, PopupRequest, PopupSize,
|
PopupAt, PopupHandle, PopupRequest, PopupSize,
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ use layer_shika_adapters::{
|
||||||
use layer_shika_domain::config::WindowConfig;
|
use layer_shika_domain::config::WindowConfig;
|
||||||
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::popup_positioning_mode::PopupPositioningMode;
|
use layer_shika_domain::value_objects::popup_positioning_mode::PopupPositioningMode;
|
||||||
use layer_shika_domain::value_objects::popup_request::{PopupHandle, PopupRequest, PopupSize};
|
use layer_shika_domain::value_objects::popup_request::{PopupHandle, PopupRequest, PopupSize};
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
|
|
@ -162,6 +163,20 @@ impl RuntimeState<'_> {
|
||||||
.map(WindowState::component_instance)
|
.map(WindowState::component_instance)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_output_info(&self, handle: OutputHandle) -> Option<&OutputInfo> {
|
||||||
|
self.app_state.get_output_info(handle)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn all_output_info(&self) -> impl Iterator<Item = &OutputInfo> {
|
||||||
|
self.app_state.all_output_info()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn outputs_with_info(&self) -> impl Iterator<Item = (&OutputInfo, &ComponentInstance)> {
|
||||||
|
self.app_state
|
||||||
|
.outputs_with_info()
|
||||||
|
.map(|(info, window)| (info, window.component_instance()))
|
||||||
|
}
|
||||||
|
|
||||||
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()
|
||||||
|
|
@ -524,4 +539,44 @@ impl WindowingSystem {
|
||||||
f(window.component_instance());
|
f(window.component_instance());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn with_output<F, R>(&self, handle: OutputHandle, f: F) -> Result<R>
|
||||||
|
where
|
||||||
|
F: FnOnce(&ComponentInstance) -> R,
|
||||||
|
{
|
||||||
|
let facade = self.inner.borrow();
|
||||||
|
let system = facade.inner_ref();
|
||||||
|
let window = system
|
||||||
|
.app_state()
|
||||||
|
.get_output_by_handle(handle)
|
||||||
|
.ok_or_else(|| {
|
||||||
|
Error::Domain(DomainError::Configuration {
|
||||||
|
message: format!("Output with handle {:?} not found", handle),
|
||||||
|
})
|
||||||
|
})?;
|
||||||
|
Ok(f(window.component_instance()))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_all_outputs<F>(&self, mut f: F)
|
||||||
|
where
|
||||||
|
F: FnMut(OutputHandle, &ComponentInstance),
|
||||||
|
{
|
||||||
|
let facade = self.inner.borrow();
|
||||||
|
let system = facade.inner_ref();
|
||||||
|
for (handle, window) in system.app_state().outputs_with_handles() {
|
||||||
|
f(handle, window.component_instance());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_output_info(&self, handle: OutputHandle) -> Option<OutputInfo> {
|
||||||
|
let facade = self.inner.borrow();
|
||||||
|
let system = facade.inner_ref();
|
||||||
|
system.app_state().get_output_info(handle).cloned()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn all_output_info(&self) -> Vec<OutputInfo> {
|
||||||
|
let facade = self.inner.borrow();
|
||||||
|
let system = facade.inner_ref();
|
||||||
|
system.app_state().all_output_info().cloned().collect()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ use crate::value_objects::dimensions::WindowHeight;
|
||||||
use crate::value_objects::keyboard_interactivity::KeyboardInteractivity;
|
use crate::value_objects::keyboard_interactivity::KeyboardInteractivity;
|
||||||
use crate::value_objects::layer::Layer;
|
use crate::value_objects::layer::Layer;
|
||||||
use crate::value_objects::margins::Margins;
|
use crate::value_objects::margins::Margins;
|
||||||
|
use crate::value_objects::output_policy::OutputPolicy;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct WindowConfig {
|
pub struct WindowConfig {
|
||||||
|
|
@ -15,6 +16,7 @@ pub struct WindowConfig {
|
||||||
pub layer: Layer,
|
pub layer: Layer,
|
||||||
pub anchor: AnchorEdges,
|
pub anchor: AnchorEdges,
|
||||||
pub keyboard_interactivity: KeyboardInteractivity,
|
pub keyboard_interactivity: KeyboardInteractivity,
|
||||||
|
pub output_policy: OutputPolicy,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WindowConfig {
|
impl WindowConfig {
|
||||||
|
|
@ -29,6 +31,7 @@ impl WindowConfig {
|
||||||
layer: Layer::default(),
|
layer: Layer::default(),
|
||||||
anchor: AnchorEdges::default(),
|
anchor: AnchorEdges::default(),
|
||||||
keyboard_interactivity: KeyboardInteractivity::default(),
|
keyboard_interactivity: KeyboardInteractivity::default(),
|
||||||
|
output_policy: OutputPolicy::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,3 +14,6 @@ pub use crate::value_objects::dimensions::WindowHeight;
|
||||||
pub use crate::value_objects::keyboard_interactivity::KeyboardInteractivity;
|
pub use crate::value_objects::keyboard_interactivity::KeyboardInteractivity;
|
||||||
pub use crate::value_objects::layer::Layer;
|
pub use crate::value_objects::layer::Layer;
|
||||||
pub use crate::value_objects::margins::Margins;
|
pub use crate::value_objects::margins::Margins;
|
||||||
|
pub use crate::value_objects::output_handle::OutputHandle;
|
||||||
|
pub use crate::value_objects::output_info::{OutputGeometry, OutputInfo};
|
||||||
|
pub use crate::value_objects::output_policy::OutputPolicy;
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,8 @@ pub mod keyboard_interactivity;
|
||||||
pub mod layer;
|
pub mod layer;
|
||||||
pub mod margins;
|
pub mod margins;
|
||||||
pub mod output_handle;
|
pub mod output_handle;
|
||||||
|
pub mod output_info;
|
||||||
|
pub mod output_policy;
|
||||||
pub mod popup_config;
|
pub mod popup_config;
|
||||||
pub mod popup_positioning_mode;
|
pub mod popup_positioning_mode;
|
||||||
pub mod popup_request;
|
pub mod popup_request;
|
||||||
|
|
|
||||||
103
crates/domain/src/value_objects/output_info.rs
Normal file
103
crates/domain/src/value_objects/output_info.rs
Normal file
|
|
@ -0,0 +1,103 @@
|
||||||
|
use crate::value_objects::output_handle::OutputHandle;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
|
pub struct OutputInfo {
|
||||||
|
handle: OutputHandle,
|
||||||
|
name: Option<String>,
|
||||||
|
description: Option<String>,
|
||||||
|
geometry: Option<OutputGeometry>,
|
||||||
|
scale: Option<i32>,
|
||||||
|
is_primary: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
|
pub struct OutputGeometry {
|
||||||
|
pub x: i32,
|
||||||
|
pub y: i32,
|
||||||
|
pub physical_width: i32,
|
||||||
|
pub physical_height: i32,
|
||||||
|
pub make: Option<String>,
|
||||||
|
pub model: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl OutputInfo {
|
||||||
|
pub fn new(handle: OutputHandle) -> Self {
|
||||||
|
Self {
|
||||||
|
handle,
|
||||||
|
name: None,
|
||||||
|
description: None,
|
||||||
|
geometry: None,
|
||||||
|
scale: None,
|
||||||
|
is_primary: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const fn handle(&self) -> OutputHandle {
|
||||||
|
self.handle
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn name(&self) -> Option<&str> {
|
||||||
|
self.name.as_deref()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn description(&self) -> Option<&str> {
|
||||||
|
self.description.as_deref()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const fn geometry(&self) -> Option<&OutputGeometry> {
|
||||||
|
self.geometry.as_ref()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const fn scale(&self) -> Option<i32> {
|
||||||
|
self.scale
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const fn is_primary(&self) -> bool {
|
||||||
|
self.is_primary
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_name(&mut self, name: String) {
|
||||||
|
self.name = Some(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_description(&mut self, description: String) {
|
||||||
|
self.description = Some(description);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_geometry(&mut self, geometry: OutputGeometry) {
|
||||||
|
self.geometry = Some(geometry);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_scale(&mut self, scale: i32) {
|
||||||
|
self.scale = Some(scale);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_primary(&mut self, is_primary: bool) {
|
||||||
|
self.is_primary = is_primary;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl OutputGeometry {
|
||||||
|
pub const fn new(x: i32, y: i32, physical_width: i32, physical_height: i32) -> Self {
|
||||||
|
Self {
|
||||||
|
x,
|
||||||
|
y,
|
||||||
|
physical_width,
|
||||||
|
physical_height,
|
||||||
|
make: None,
|
||||||
|
model: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub fn with_make(mut self, make: String) -> Self {
|
||||||
|
self.make = Some(make);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub fn with_model(mut self, model: String) -> Self {
|
||||||
|
self.model = Some(model);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
58
crates/domain/src/value_objects/output_policy.rs
Normal file
58
crates/domain/src/value_objects/output_policy.rs
Normal file
|
|
@ -0,0 +1,58 @@
|
||||||
|
use crate::value_objects::output_info::OutputInfo;
|
||||||
|
use std::fmt;
|
||||||
|
|
||||||
|
pub enum OutputPolicy {
|
||||||
|
AllOutputs,
|
||||||
|
PrimaryOnly,
|
||||||
|
Custom(Box<dyn Fn(&OutputInfo) -> bool>),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl OutputPolicy {
|
||||||
|
pub fn should_render(&self, info: &OutputInfo) -> bool {
|
||||||
|
match self {
|
||||||
|
OutputPolicy::AllOutputs => true,
|
||||||
|
OutputPolicy::PrimaryOnly => info.is_primary(),
|
||||||
|
OutputPolicy::Custom(filter) => filter(info),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn primary_only() -> Self {
|
||||||
|
Self::PrimaryOnly
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn all_outputs() -> Self {
|
||||||
|
Self::AllOutputs
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn custom<F>(filter: F) -> Self
|
||||||
|
where
|
||||||
|
F: Fn(&OutputInfo) -> bool + 'static,
|
||||||
|
{
|
||||||
|
Self::Custom(Box::new(filter))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for OutputPolicy {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::AllOutputs
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Clone for OutputPolicy {
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
match self {
|
||||||
|
OutputPolicy::AllOutputs | OutputPolicy::Custom(_) => OutputPolicy::AllOutputs,
|
||||||
|
OutputPolicy::PrimaryOnly => OutputPolicy::PrimaryOnly,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Debug for OutputPolicy {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
match self {
|
||||||
|
OutputPolicy::AllOutputs => write!(f, "OutputPolicy::AllOutputs"),
|
||||||
|
OutputPolicy::PrimaryOnly => write!(f, "OutputPolicy::PrimaryOnly"),
|
||||||
|
OutputPolicy::Custom(_) => write!(f, "OutputPolicy::Custom(<function>)"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
10
src/lib.rs
10
src/lib.rs
|
|
@ -22,12 +22,13 @@
|
||||||
//! ```rust,no_run
|
//! ```rust,no_run
|
||||||
//! use layer_shika::prelude::*;
|
//! use layer_shika::prelude::*;
|
||||||
//!
|
//!
|
||||||
//! let (window, system) = LayerShika::from_file("ui/main.slint", "AppWindow")?
|
//! let system = LayerShika::from_file("ui/main.slint", Some("AppWindow"))?
|
||||||
//! .with_height(42)
|
//! .with_height(42)
|
||||||
//! .with_anchor(AnchorEdges::top_bar())
|
//! .with_anchor(AnchorEdges::top_bar())
|
||||||
//! .with_exclusive_zone(42)
|
//! .with_exclusive_zone(42)
|
||||||
//! .build()?;
|
//! .build()?;
|
||||||
//!
|
//!
|
||||||
|
//! let mut system = system;
|
||||||
//! system.run()?;
|
//! system.run()?;
|
||||||
//! # Ok::<(), layer_shika::Error>(())
|
//! # Ok::<(), layer_shika::Error>(())
|
||||||
//! ```
|
//! ```
|
||||||
|
|
@ -44,9 +45,10 @@
|
||||||
pub mod prelude;
|
pub mod prelude;
|
||||||
|
|
||||||
pub use layer_shika_composition::{
|
pub use layer_shika_composition::{
|
||||||
AnchorEdges, Error, EventLoopHandle, KeyboardInteractivity, Layer, LayerShika, OutputHandle,
|
AnchorEdges, Error, EventLoopHandle, KeyboardInteractivity, Layer, LayerShika, OutputGeometry,
|
||||||
PopupAt, PopupHandle, PopupPositioningMode, PopupRequest, PopupSize, PopupWindow, Result,
|
OutputHandle, OutputInfo, OutputPolicy, PopupAt, PopupHandle, PopupPositioningMode,
|
||||||
RuntimeState, SlintCallbackContract, SlintCallbackNames, WindowingSystem,
|
PopupRequest, PopupSize, PopupWindow, Result, RuntimeState, SlintCallbackContract,
|
||||||
|
SlintCallbackNames, WindowingSystem,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub use layer_shika_composition::{slint, slint_interpreter};
|
pub use layer_shika_composition::{slint, slint_interpreter};
|
||||||
|
|
|
||||||
|
|
@ -16,8 +16,8 @@ pub use crate::{
|
||||||
|
|
||||||
// Domain value objects
|
// Domain value objects
|
||||||
pub use crate::{
|
pub use crate::{
|
||||||
AnchorEdges, KeyboardInteractivity, Layer, OutputHandle, PopupAt, PopupHandle,
|
AnchorEdges, KeyboardInteractivity, Layer, OutputGeometry, OutputHandle, OutputInfo,
|
||||||
PopupPositioningMode, PopupRequest, PopupSize,
|
OutputPolicy, PopupAt, PopupHandle, PopupPositioningMode, PopupRequest, PopupSize,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Event loop types
|
// Event loop types
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue