diff --git a/iced_examples/counter/src/main.rs b/iced_examples/counter/src/main.rs index 49c76f3..2366f5f 100644 --- a/iced_examples/counter/src/main.rs +++ b/iced_examples/counter/src/main.rs @@ -1,7 +1,7 @@ use iced::widget::{button, column, row, text, text_input}; use iced::{event, Alignment, Color, Element, Event, Length, Task as Command, Theme}; use iced_layershell::reexport::Anchor; -use iced_layershell::settings::{LayerShellSettings, Settings}; +use iced_layershell::settings::{LayerShellSettings, Settings, StartMode}; use iced_layershell::to_layer_message; use iced_layershell::Application; @@ -13,12 +13,17 @@ pub fn main() -> Result<(), iced_layershell::Error> { binded_output_name = Some(args[1].to_string()) } + let start_mode = match binded_output_name { + Some(output) => StartMode::TargetScreen(output), + None => StartMode::Active, + }; + Counter::run(Settings { layer_settings: LayerShellSettings { size: Some((0, 400)), exclusive_zone: 400, anchor: Anchor::Bottom | Anchor::Left | Anchor::Right, - binded_output_name, + start_mode, ..Default::default() }, ..Default::default() diff --git a/iced_examples/counter_muti/src/main.rs b/iced_examples/counter_muti/src/main.rs index a52f795..c8a7f76 100644 --- a/iced_examples/counter_muti/src/main.rs +++ b/iced_examples/counter_muti/src/main.rs @@ -8,15 +8,17 @@ use iced_runtime::window::Action as WindowAction; use iced_runtime::{task, Action}; use iced_layershell::reexport::{Anchor, KeyboardInteractivity, Layer, NewLayerShellSettings}; -use iced_layershell::settings::{LayerShellSettings, Settings}; +use iced_layershell::settings::{LayerShellSettings, Settings, StartMode}; use iced_layershell::to_layer_message; use iced_layershell::MultiApplication; + pub fn main() -> Result<(), iced_layershell::Error> { Counter::run(Settings { layer_settings: LayerShellSettings { size: Some((0, 400)), exclusive_zone: 400, anchor: Anchor::Bottom | Anchor::Left | Anchor::Right, + start_mode: StartMode::AllScreens, ..Default::default() }, ..Default::default() diff --git a/iced_examples/zbus_invoked_widget/src/main.rs b/iced_examples/zbus_invoked_widget/src/main.rs index c4bc32d..5d9827a 100644 --- a/iced_examples/zbus_invoked_widget/src/main.rs +++ b/iced_examples/zbus_invoked_widget/src/main.rs @@ -9,7 +9,7 @@ use iced_runtime::window::Action as WindowAction; use iced_runtime::Action; use iced_layershell::reexport::{Anchor, KeyboardInteractivity, Layer, NewLayerShellSettings}; -use iced_layershell::settings::Settings; +use iced_layershell::settings::{LayerShellSettings, Settings, StartMode}; use iced_layershell::MultiApplication; use zbus::{interface, ConnectionBuilder}; @@ -23,7 +23,13 @@ struct Counter { text: String, } pub fn main() -> Result<(), iced_layershell::Error> { - Counter::run(Settings::default()) + Counter::run(Settings { + layer_settings: LayerShellSettings { + start_mode: StartMode::Background, + ..Default::default() + }, + ..Default::default() + }) } #[derive(Debug, Clone)] @@ -64,8 +70,6 @@ impl MultiApplication for Counter { type Executor = iced::executor::Default; type WindowInfo = (); - const BACKGROUND_MODE: bool = true; - fn set_id_info(&mut self, _id: iced_runtime::core::window::Id, _info: Self::WindowInfo) { self.window_shown = true; } diff --git a/iced_layershell/src/application.rs b/iced_layershell/src/application.rs index adb121e..d4d3e48 100644 --- a/iced_layershell/src/application.rs +++ b/iced_layershell/src/application.rs @@ -23,7 +23,7 @@ use iced_futures::{Executor, Runtime, Subscription}; use layershellev::{ calloop::timer::{TimeoutAction, Timer}, reexport::zwp_virtual_keyboard_v1, - LayerEvent, ReturnData, WindowWrapper, + LayerEvent, ReturnData, StartMode, WindowWrapper, }; use futures::{channel::mpsc, StreamExt}; @@ -149,8 +149,12 @@ where runtime.enter(|| A::new(flags)) }; + assert!(!matches!( + settings.layer_settings.start_mode, + StartMode::AllScreens | StartMode::Background + )); + let ev = layershellev::WindowStateSimple::new(&application.namespace()) - .with_single(true) .with_use_display_handle(true) .with_option_size(settings.layer_settings.size) .with_layer(settings.layer_settings.layer) @@ -158,7 +162,7 @@ where .with_exclusize_zone(settings.layer_settings.exclusive_zone) .with_margin(settings.layer_settings.margin) .with_keyboard_interacivity(settings.layer_settings.keyboard_interactivity) - .with_xdg_output_name(settings.layer_settings.binded_output_name) + .with_start_mode(settings.layer_settings.start_mode) .build() .expect("Cannot create layershell"); diff --git a/iced_layershell/src/lib.rs b/iced_layershell/src/lib.rs index fd3fe70..81a9b40 100644 --- a/iced_layershell/src/lib.rs +++ b/iced_layershell/src/lib.rs @@ -260,8 +260,6 @@ pub trait MultiApplication: Sized { type Theme: Default + DefaultStyle; - const BACKGROUND_MODE: bool = false; - /// Initializes the [`Application`] with the flags provided to /// [`run`] as part of the [`Settings`]. /// @@ -409,8 +407,6 @@ where type WindowInfo = A::WindowInfo; - const BACKGROUND_MODE: bool = A::BACKGROUND_MODE; - fn new(flags: Self::Flags) -> (Self, Task) { let (app, command) = A::new(flags); diff --git a/iced_layershell/src/multi_window.rs b/iced_layershell/src/multi_window.rs index f837e34..22c25bb 100644 --- a/iced_layershell/src/multi_window.rs +++ b/iced_layershell/src/multi_window.rs @@ -63,8 +63,6 @@ where type WindowInfo; - const BACKGROUND_MODE: bool; - /// Initializes the [`Application`] with the flags provided to /// [`run`] as part of the [`Settings`]. /// @@ -187,9 +185,9 @@ where runtime.enter(|| application.subscription().map(Action::Output)), )); + let is_background_mode = settings.layer_settings.start_mode.is_background(); let ev: WindowState = layershellev::WindowState::new(&application.namespace()) - .with_single(false) - .with_background(A::BACKGROUND_MODE) + .with_start_mode(settings.layer_settings.start_mode) .with_use_display_handle(true) .with_option_size(settings.layer_settings.size) .with_layer(settings.layer_settings.layer) @@ -215,6 +213,7 @@ where event_receiver, control_sender, window, + is_background_mode, )); let mut context = task::Context::from_waker(task::noop_waker_ref()); @@ -461,6 +460,7 @@ async fn run_instance( >, mut control_sender: mpsc::UnboundedSender>, window: Arc, + is_background_mode: bool, ) where A: Application + 'static, E: Executor + 'static, @@ -746,7 +746,7 @@ async fn run_instance( // HACK: this logic is just from iced, but seems if there is no main window, // any window will not get Outdated state. // So here just check if there is window_events - if A::BACKGROUND_MODE && has_window_event { + if is_background_mode && has_window_event { custom_actions.push(LayerShellActions::RedrawAll); } @@ -765,7 +765,7 @@ async fn run_instance( window.state.synchronize(&application); } - if !A::BACKGROUND_MODE { + if !is_background_mode { custom_actions.push(LayerShellActions::RedrawAll); } diff --git a/iced_layershell/src/settings.rs b/iced_layershell/src/settings.rs index 5feeef3..5047bac 100644 --- a/iced_layershell/src/settings.rs +++ b/iced_layershell/src/settings.rs @@ -4,6 +4,8 @@ use iced::{Font, Pixels}; use crate::reexport::{Anchor, KeyboardInteractivity, Layer}; +pub use layershellev::StartMode; + use layershellev::reexport::wayland_client::wl_keyboard::KeymapFormat; #[derive(Debug)] @@ -80,7 +82,7 @@ pub struct LayerShellSettings { pub size: Option<(u32, u32)>, pub margin: (i32, i32, i32, i32), pub keyboard_interactivity: KeyboardInteractivity, - pub binded_output_name: Option, + pub start_mode: StartMode, } impl Default for LayerShellSettings { @@ -92,7 +94,7 @@ impl Default for LayerShellSettings { size: None, margin: (0, 0, 0, 0), keyboard_interactivity: KeyboardInteractivity::OnDemand, - binded_output_name: None, + start_mode: StartMode::default(), } } } @@ -125,7 +127,10 @@ mod tests { settings.layer_settings.keyboard_interactivity, KeyboardInteractivity::OnDemand ); - assert!(settings.layer_settings.binded_output_name.is_none()); + assert!(matches!( + settings.layer_settings.start_mode, + StartMode::Active + )); } #[test] @@ -153,7 +158,7 @@ mod tests { size: Some((1920, 1080)), margin: (10, 10, 10, 10), keyboard_interactivity: KeyboardInteractivity::None, - binded_output_name: Some("HDMI-1".to_string()), + start_mode: StartMode::TargetScreen("HDMI-1".to_string()), }; assert_eq!(layer_settings.anchor, Anchor::Top | Anchor::Left); @@ -166,8 +171,8 @@ mod tests { KeyboardInteractivity::None ); assert_eq!( - layer_settings.binded_output_name, - Some("HDMI-1".to_string()) + layer_settings.start_mode, + StartMode::TargetScreen("HDMI-1".to_string()) ); } } diff --git a/layershellev/examples/simplelayer.rs b/layershellev/examples/simplelayer.rs index 57fd788..c024733 100644 --- a/layershellev/examples/simplelayer.rs +++ b/layershellev/examples/simplelayer.rs @@ -7,7 +7,7 @@ use layershellev::*; fn main() { let ev: WindowState<()> = WindowState::new("Hello") - .with_single(false) + .with_allscreens() .with_size((0, 400)) .with_layer(Layer::Top) .with_margin((20, 20, 100, 20)) diff --git a/layershellev/src/lib.rs b/layershellev/src/lib.rs index caa424c..da07aad 100644 --- a/layershellev/src/lib.rs +++ b/layershellev/src/lib.rs @@ -12,7 +12,7 @@ //! //! fn main() { //! let mut ev: WindowState<()> = WindowState::new("Hello") -//! .with_single(false) +//! .with_allscreens() //! .with_size((0, 400)) //! .with_layer(Layer::Top) //! .with_margin((20, 20, 100, 20)) @@ -543,8 +543,6 @@ impl WindowStateUnit { pub struct WindowState { outputs: Vec<(u32, wl_output::WlOutput)>, current_surface: Option, - is_single: bool, - is_background: bool, units: Vec>, message: Vec<(Option, DispatchMessageInner)>, @@ -590,8 +588,10 @@ pub struct WindowState { last_touch_location: (f64, f64), last_touch_id: i32, - binded_output_name: Option, xdg_info_cache: Vec<(wl_output::WlOutput, ZxdgOutputInfo)>, + + start_mode: StartMode, + init_finished: bool, } impl WindowState { @@ -649,6 +649,30 @@ pub struct WindowWrapper { wl_surface: WlSurface, } +#[derive(Debug, Clone, Default, PartialEq, Eq)] +pub enum StartMode { + #[default] + Active, + Background, + AllScreens, + TargetScreen(String), +} + +impl StartMode { + pub fn is_active(&self) -> bool { + matches!(self, Self::Active) + } + pub fn is_background(&self) -> bool { + matches!(self, Self::Background) + } + pub fn is_allscreens(&self) -> bool { + matches!(self, Self::AllScreens) + } + pub fn is_with_target(&self) -> bool { + matches!(self, Self::TargetScreen(_)) + } +} + impl WindowWrapper { pub fn id(&self) -> id::Id { self.id @@ -681,7 +705,7 @@ impl WindowState { /// gen the wrapper to the main window /// used to get display and etc pub fn gen_main_wrapper(&self) -> WindowWrapper { - if self.is_background { + if self.is_background() { return WindowWrapper { id: id::Id::MAIN, display: self.display.as_ref().unwrap().clone(), @@ -690,6 +714,18 @@ impl WindowState { } self.main_window().gen_wrapper() } + pub fn is_active(&self) -> bool { + self.start_mode.is_active() + } + pub fn is_background(&self) -> bool { + self.start_mode.is_background() + } + pub fn is_allscreens(&self) -> bool { + self.start_mode.is_allscreens() + } + pub fn is_with_target(&self) -> bool { + self.start_mode.is_with_target() + } } impl WindowWrapper { @@ -746,20 +782,66 @@ impl WindowState { /// suggest to bind to specific output /// if there is no such output , it will bind the output which now is focused, /// same with when binded_output_name is None - pub fn with_xdg_output_name(mut self, binded_output_name: Option) -> Self { - self.binded_output_name = binded_output_name; + pub fn with_xdg_output_name(mut self, binded_output_name: String) -> Self { + self.start_mode = StartMode::TargetScreen(binded_output_name); + self + } + + pub fn with_start_mode(mut self, mode: StartMode) -> Self { + self.start_mode = mode; self } /// if the shell is a single one, only display on one screen, /// fi true, the layer will binding to current screen - pub fn with_single(mut self, single: bool) -> Self { - self.is_single = single; + pub fn with_active(mut self) -> Self { + self.start_mode = StartMode::Active; + self + } + + pub fn with_active_or_xdg_output_name(self, binded_output_name: Option) -> Self { + match binded_output_name { + Some(binded_output_name) => self.with_xdg_output_name(binded_output_name), + None => self.with_active(), + } + } + + pub fn with_allscreens_or_xdg_output_name(self, binded_output_name: Option) -> Self { + match binded_output_name { + Some(binded_output_name) => self.with_xdg_output_name(binded_output_name), + None => self.with_allscreens(), + } + } + pub fn with_xdg_output_name_or_not(self, binded_output_name: Option) -> Self { + let Some(binded_output_name) = binded_output_name else { + return self; + }; + self.with_xdg_output_name(binded_output_name) + } + + pub fn with_allscreens_or_active(mut self, allscreen: bool) -> Self { + if allscreen { + self.start_mode = StartMode::AllScreens; + } else { + self.start_mode = StartMode::Active; + } self } - pub fn with_background(mut self, background: bool) -> Self { - self.is_background = background; + pub fn with_allscreens(mut self) -> Self { + self.start_mode = StartMode::AllScreens; + self + } + + pub fn with_background_or_not(self, background_mode: bool) -> Self { + if !background_mode { + return self; + } + self.with_background() + } + + pub fn with_background(mut self) -> Self { + self.start_mode = StartMode::Background; self } @@ -823,8 +905,6 @@ impl Default for WindowState { Self { outputs: Vec::new(), current_surface: None, - is_single: true, - is_background: false, units: Vec::new(), message: Vec::new(), @@ -866,8 +946,10 @@ impl Default for WindowState { last_touch_id: 0, // NOTE: if is some, means it is to be binded, but not now it // is not binded - binded_output_name: None, xdg_info_cache: Vec::new(), + + start_mode: StartMode::Active, + init_finished: false, } } } @@ -1491,7 +1573,7 @@ impl Dispatch for WindowState { _conn: &Connection, _qhandle: &QueueHandle, ) { - if state.binded_output_name.is_some() { + if state.is_with_target() && !state.init_finished { let Some((_, xdg_info)) = state .xdg_info_cache .iter_mut() @@ -1657,12 +1739,12 @@ impl WindowState { // finally thing to remember is to commit the surface, make the shell to init. //let (init_w, init_h) = self.size; // this example is ok for both xdg_surface and layer_shell - if self.is_background { + if self.is_background() { self.background_surface = Some(wmcompositer.create_surface(&qh, ())); - } else if self.is_single { + } else if !self.is_allscreens() { let mut output = None; - if let Some(name) = self.binded_output_name.clone() { + if let StartMode::TargetScreen(name) = self.start_mode.clone() { for (_, output_display) in &self.outputs { let zxdgoutput = xdg_output_manager.get_xdg_output(output_display, &qh, ()); self.xdg_info_cache @@ -1678,7 +1760,6 @@ impl WindowState { output = Some(cache.clone()); } // clear binded_output_name, it is not used anymore - self.binded_output_name.take(); } self.xdg_info_cache.clear(); @@ -1793,6 +1874,7 @@ impl WindowState { } self.message.clear(); } + self.init_finished = true; self.event_queue = Some(event_queue); self.globals = Some(globals); self.wl_compositor = Some(wmcompositer); @@ -1932,7 +2014,7 @@ impl WindowState { ); } (_, DispatchMessageInner::NewDisplay(output_display)) => { - if self.is_single || self.is_background { + if !self.is_allscreens() { continue; } let wl_surface = wmcompositer.create_surface(&qh, ()); // and create a surface. if two or more, @@ -2195,9 +2277,6 @@ impl WindowState { }, info, )) => { - if self.is_single { - continue; - } let pos = self.surface_pos(); let mut output = pos.and_then(|p| self.units[p].wl_output.as_ref()); diff --git a/starcolorkeyboard/src/main.rs b/starcolorkeyboard/src/main.rs index 195dfe0..53afe13 100644 --- a/starcolorkeyboard/src/main.rs +++ b/starcolorkeyboard/src/main.rs @@ -82,7 +82,7 @@ pub fn get_keymap_as_file() -> (File, u32) { fn main() { let ev: WindowState = WindowState::new("precure") - .with_single(false) + .with_allscreens() .with_size((0, 300)) .with_layer(Layer::Top) .with_anchor(Anchor::Bottom | Anchor::Left | Anchor::Right)