diff --git a/iced_examples/counter_muti/src/main.rs b/iced_examples/counter_muti/src/main.rs index b3b83a2..730868e 100644 --- a/iced_examples/counter_muti/src/main.rs +++ b/iced_examples/counter_muti/src/main.rs @@ -1,8 +1,16 @@ +use std::collections::HashMap; + use iced::widget::{button, column, row, text, text_input}; use iced::window::Id; use iced::{event, Alignment, Command, Element, Event, Length, Theme}; -use iced_layershell::actions::{LayershellCustomActions, LayershellCustomActionsWithId}; -use iced_layershell::reexport::Anchor; +use iced_layershell::actions::{ + LayershellCustomActions, LayershellCustomActionsWithId, LayershellCustomActionsWithIdAndInfo, + LayershellCustomActionsWithInfo, +}; +use iced_runtime::command::Action; +use iced_runtime::window::Action as WindowAction; + +use iced_layershell::reexport::{Anchor, KeyboardInteractivity, Layer, NewLayerShellSettings}; use iced_layershell::settings::{LayerShellSettings, Settings}; use iced_layershell::MultiApplication; pub fn main() -> Result<(), iced_layershell::Error> { @@ -20,6 +28,13 @@ pub fn main() -> Result<(), iced_layershell::Error> { struct Counter { value: i32, text: String, + ids: HashMap, +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +enum WindowInfo { + Left, + Right, } #[derive(Debug, Clone, Copy)] @@ -34,27 +49,55 @@ enum WindowDirection { enum Message { IncrementPressed, DecrementPressed, + NewWindowLeft, + NewWindowRight, + Close(Id), TextInput(String), Direction(WindowDirection), IcedEvent(Event), } +impl Counter { + fn window_id(&self, info: &WindowInfo) -> Option<&iced::window::Id> { + for (k, v) in self.ids.iter() { + if info == v { + return Some(k); + } + } + None + } +} + impl MultiApplication for Counter { type Message = Message; type Flags = (); type Theme = Theme; type Executor = iced::executor::Default; + type WindowInfo = WindowInfo; fn new(_flags: ()) -> (Self, Command) { ( Self { value: 0, text: "eee".to_string(), + ids: HashMap::new(), }, Command::none(), ) } + fn id_info(&self, id: iced::window::Id) -> Option<&Self::WindowInfo> { + self.ids.get(&id) + } + + fn set_id_info(&mut self, id: iced::window::Id, info: Self::WindowInfo) { + self.ids.insert(id, info); + } + + fn remove_id(&mut self, id: iced::window::Id) { + self.ids.remove(&id); + } + fn namespace(&self) -> String { String::from("Counter - Iced") } @@ -64,9 +107,20 @@ impl MultiApplication for Counter { } fn update(&mut self, message: Message) -> Command { + use iced::keyboard; + use iced::keyboard::key::Named; + use iced::Event; match message { Message::IcedEvent(event) => { - println!("hello {event:?}"); + if let Event::Keyboard(keyboard::Event::KeyPressed { + key: keyboard::Key::Named(Named::Escape), + .. + }) = event + { + if let Some(id) = self.window_id(&WindowInfo::Left) { + return Command::single(Action::Window(WindowAction::Close(*id))); + } + } Command::none() } Message::IncrementPressed => { @@ -84,7 +138,7 @@ impl MultiApplication for Counter { Message::Direction(direction) => match direction { WindowDirection::Left(id) => Command::batch(vec![ Command::single( - LayershellCustomActionsWithId( + LayershellCustomActionsWithId::new( id, LayershellCustomActions::AnchorChange( Anchor::Left | Anchor::Top | Anchor::Bottom, @@ -93,7 +147,7 @@ impl MultiApplication for Counter { .into(), ), Command::single( - LayershellCustomActionsWithId( + LayershellCustomActionsWithId::new( id, LayershellCustomActions::SizeChange((400, 0)), ) @@ -102,7 +156,7 @@ impl MultiApplication for Counter { ]), WindowDirection::Right(id) => Command::batch(vec![ Command::single( - LayershellCustomActionsWithId( + LayershellCustomActionsWithId::new( id, LayershellCustomActions::AnchorChange( Anchor::Right | Anchor::Top | Anchor::Bottom, @@ -111,7 +165,7 @@ impl MultiApplication for Counter { .into(), ), Command::single( - LayershellCustomActionsWithId( + LayershellCustomActionsWithId::new( id, LayershellCustomActions::SizeChange((400, 0)), ) @@ -120,7 +174,7 @@ impl MultiApplication for Counter { ]), WindowDirection::Bottom(id) => Command::batch(vec![ Command::single( - LayershellCustomActionsWithId( + LayershellCustomActionsWithId::new( id, LayershellCustomActions::AnchorChange( Anchor::Bottom | Anchor::Left | Anchor::Right, @@ -129,25 +183,25 @@ impl MultiApplication for Counter { .into(), ), Command::single( - LayershellCustomActionsWithId( + LayershellCustomActionsWithId::new( id, - LayershellCustomActions::SizeChange((0, 400)), + LayershellCustomActionsWithInfo::SizeChange((0, 400)), ) .into(), ), ]), WindowDirection::Top(id) => Command::batch(vec![ Command::single( - LayershellCustomActionsWithId( + LayershellCustomActionsWithId::new( id, - LayershellCustomActions::AnchorChange( + LayershellCustomActionsWithInfo::AnchorChange( Anchor::Top | Anchor::Left | Anchor::Right, ), ) .into(), ), Command::single( - LayershellCustomActionsWithId( + LayershellCustomActionsWithId::new( id, LayershellCustomActions::SizeChange((0, 400)), ) @@ -155,15 +209,57 @@ impl MultiApplication for Counter { ), ]), }, + Message::NewWindowLeft => Command::single( + LayershellCustomActionsWithIdAndInfo::new( + iced::window::Id::MAIN, + LayershellCustomActionsWithInfo::NewLayerShell(( + NewLayerShellSettings { + size: Some((100, 100)), + exclusize_zone: None, + anchor: Anchor::Left | Anchor::Bottom, + layer: Layer::Top, + margins: None, + keyboard_interactivity: KeyboardInteractivity::Exclusive, + }, + WindowInfo::Left, + )), + ) + .into(), + ), + Message::NewWindowRight => Command::single( + LayershellCustomActionsWithIdAndInfo::new( + iced::window::Id::MAIN, + LayershellCustomActionsWithInfo::NewLayerShell(( + NewLayerShellSettings { + size: Some((100, 100)), + exclusize_zone: None, + anchor: Anchor::Right | Anchor::Bottom, + layer: Layer::Top, + margins: None, + keyboard_interactivity: KeyboardInteractivity::None, + }, + WindowInfo::Right, + )), + ) + .into(), + ), + Message::Close(id) => Command::single(Action::Window(WindowAction::Close(id))), } } fn view(&self, id: iced::window::Id) -> Element { - //println!("{:?}, {}", _id, self.value); + if let Some(WindowInfo::Left) = self.id_info(id) { + return button("close left").on_press(Message::Close(id)).into(); + } + if let Some(WindowInfo::Right) = self.id_info(id) { + return button("close right").on_press(Message::Close(id)).into(); + } let center = column![ button("Increment").on_press(Message::IncrementPressed), text(self.value).size(50), - button("Decrement").on_press(Message::DecrementPressed) + button("Decrement").on_press(Message::DecrementPressed), + button("newwindowLeft").on_press(Message::NewWindowLeft), + button("newwindowRight").on_press(Message::NewWindowRight) ] .padding(20) .align_items(Alignment::Center) diff --git a/iced_layershell/src/actions.rs b/iced_layershell/src/actions.rs index fb056ab..4ac8f89 100644 --- a/iced_layershell/src/actions.rs +++ b/iced_layershell/src/actions.rs @@ -3,42 +3,68 @@ use iced::window::Id as IcedId; use iced_core::mouse::Interaction; use iced_runtime::command::Action; use layershellev::id::Id as LayerId; +use layershellev::NewLayerShellSettings; #[allow(unused)] #[derive(Debug, Clone)] -pub(crate) enum LayerShellActions { +pub(crate) enum LayerShellActions { Mouse(Interaction), - CustomActions(Vec), - CustomActionsWithId(Vec), + CustomActions(Vec>), + CustomActionsWithId(Vec>), RedrawAll, RedrawWindow(LayerId), } #[derive(Debug, Clone, Copy)] -pub enum LayershellCustomActions { +pub enum LayershellCustomActionsWithInfo { AnchorChange(Anchor), LayerChange(Layer), SizeChange((u32, u32)), - VirtualKeyboardPressed { time: u32, key: u32 }, + VirtualKeyboardPressed { + time: u32, + key: u32, + }, + NewLayerShell((NewLayerShellSettings, INFO)), + /// is same with WindowAction::Close(id) + RemoveLayerShell(IcedId), } +pub type LayershellCustomActions = LayershellCustomActionsWithInfo<()>; + #[derive(Debug, Clone, Copy)] -pub struct LayershellCustomActionsWithId(pub IcedId, pub LayershellCustomActions); +pub struct LayershellCustomActionsWithIdAndInfo( + pub IcedId, + pub LayershellCustomActionsWithInfo, +); + +impl LayershellCustomActionsWithIdAndInfo { + pub fn new(id: IcedId, actions: LayershellCustomActionsWithInfo) -> Self { + Self(id, actions) + } +} + +pub type LayershellCustomActionsWithId = LayershellCustomActionsWithIdAndInfo<()>; + +// first one means #[derive(Debug, Clone, Copy)] -pub(crate) struct LayershellCustomActionsWithIdInner(pub LayerId, pub LayershellCustomActions); +pub(crate) struct LayershellCustomActionsWithIdInner( + pub LayerId, // come from + pub Option, // target if has one + pub LayershellCustomActionsWithInfo, // actions +); -impl From for Action { - fn from(value: LayershellCustomActionsWithId) -> Self { - Action::Custom(Box::new(value)) +impl From> for Action { + fn from(value: LayershellCustomActionsWithIdAndInfo) -> Self { + Action::Custom(Box::new(value.clone())) } } -impl From for Action { - fn from(value: LayershellCustomActions) -> Self { - Action::Custom(Box::new(value)) +impl From> for Action { + fn from(value: LayershellCustomActionsWithInfo) -> Self { + Action::Custom(Box::new(value.clone())) } } -impl LayershellCustomActions { +impl LayershellCustomActionsWithInfo { pub fn to_action(&self) -> Action { - (*self).into() + (*self).clone().into() } } diff --git a/iced_layershell/src/application.rs b/iced_layershell/src/application.rs index 437d222..93ff141 100644 --- a/iced_layershell/src/application.rs +++ b/iced_layershell/src/application.rs @@ -3,7 +3,7 @@ mod state; use std::{mem::ManuallyDrop, os::fd::AsFd, sync::Arc, time::Duration}; use crate::{ - actions::{LayerShellActions, LayershellCustomActions}, + actions::{LayerShellActions, LayershellCustomActionsWithInfo}, clipboard::LayerShellClipboard, conversion, error::Error, @@ -24,7 +24,7 @@ use iced_futures::{Executor, Runtime, Subscription}; use layershellev::{ calloop::timer::{TimeoutAction, Timer}, reexport::zwp_virtual_keyboard_v1, - LayerEvent, ReturnData, WindowState, WindowWrapper, + LayerEvent, ReturnData, WindowWrapper, }; use futures::{channel::mpsc, SinkExt, StreamExt}; @@ -147,7 +147,7 @@ where runtime.enter(|| A::new(flags)) }; - let ev: WindowState<()> = layershellev::WindowState::new(&application.namespace()) + let ev = layershellev::WindowStateSimple::new(&application.namespace()) .with_single(true) .with_use_display_handle(true) .with_option_size(settings.layer_settings.size) @@ -171,8 +171,8 @@ where let state = State::new(&application, &ev); - let (mut event_sender, event_receiver) = mpsc::unbounded::>(); - let (control_sender, mut control_receiver) = mpsc::unbounded::>(); + let (mut event_sender, event_receiver) = mpsc::unbounded::>(); + let (control_sender, mut control_receiver) = mpsc::unbounded::>>(); let mut instance = Box::pin(run_instance::( application, @@ -250,16 +250,16 @@ where LayerShellActions::CustomActions(actions) => { for action in actions { match action { - LayershellCustomActions::AnchorChange(anchor) => { + LayershellCustomActionsWithInfo::AnchorChange(anchor) => { ev.main_window().set_anchor(anchor); } - LayershellCustomActions::LayerChange(layer) => { + LayershellCustomActionsWithInfo::LayerChange(layer) => { ev.main_window().set_layer(layer); } - LayershellCustomActions::SizeChange((width, height)) => { + LayershellCustomActionsWithInfo::SizeChange((width, height)) => { ev.main_window().set_size((width, height)); } - LayershellCustomActions::VirtualKeyboardPressed { + LayershellCustomActionsWithInfo::VirtualKeyboardPressed { time, key, } => { @@ -279,6 +279,7 @@ where ) .ok(); } + _ => {} } } } @@ -319,8 +320,8 @@ async fn run_instance( mut runtime: Runtime, A::Message>, mut proxy: IcedProxy, mut debug: Debug, - mut event_receiver: mpsc::UnboundedReceiver>, - mut control_sender: mpsc::UnboundedSender>, + mut event_receiver: mpsc::UnboundedReceiver>, + mut control_sender: mpsc::UnboundedSender>>, mut state: State, init_command: Command, window: Arc, @@ -558,7 +559,7 @@ pub(crate) fn update( proxy: &mut IcedProxy, debug: &mut Debug, messages: &mut Vec, - custom_actions: &mut Vec, + custom_actions: &mut Vec>, ) where C: Compositor + 'static, A::Theme: StyleSheet, @@ -603,7 +604,7 @@ pub(crate) fn run_command( renderer: &mut A::Renderer, command: Command, runtime: &mut Runtime, A::Message>, - custom_actions: &mut Vec, + custom_actions: &mut Vec>, should_exit: &mut bool, proxy: &mut IcedProxy, debug: &mut Debug, @@ -685,7 +686,7 @@ pub(crate) fn run_command( proxy.send(tagger(Ok(()))); } command::Action::Custom(custom) => { - if let Some(action) = custom.downcast_ref::() { + if let Some(action) = custom.downcast_ref::>() { customactions.push(*action); } } diff --git a/iced_layershell/src/application/state.rs b/iced_layershell/src/application/state.rs index b69fdc0..a26e996 100644 --- a/iced_layershell/src/application/state.rs +++ b/iced_layershell/src/application/state.rs @@ -23,7 +23,7 @@ impl State where A::Theme: application::StyleSheet, { - pub fn new(application: &A, window: &layershellev::WindowState<()>) -> Self { + pub fn new(application: &A, window: &layershellev::WindowStateSimple) -> Self { let scale_factor = application.scale_factor(); let theme = application.theme(); let appearance = theme.appearance(&application.style()); diff --git a/iced_layershell/src/event.rs b/iced_layershell/src/event.rs index a87586a..40b9f6f 100644 --- a/iced_layershell/src/event.rs +++ b/iced_layershell/src/event.rs @@ -61,11 +61,13 @@ pub enum WindowEvent { } #[derive(Debug)] -pub enum IcedLayerEvent { +pub enum IcedLayerEvent { RequestRefreshWithWrapper { width: u32, height: u32, wrapper: WindowWrapper, + is_created: bool, + info: Option, }, RequestRefresh { width: u32, @@ -74,27 +76,33 @@ pub enum IcedLayerEvent { Window(WindowEvent), NormalUpdate, UserEvent(Message), + WindowRemoved(iced_core::window::Id), } #[allow(unused)] #[derive(Debug)] -pub struct MultiWindowIcedLayerEvent(pub Option, pub IcedLayerEvent); +pub struct MultiWindowIcedLayerEvent( + pub Option, + pub IcedLayerEvent, +); -impl From<(Option, IcedLayerEvent)> - for MultiWindowIcedLayerEvent +impl From<(Option, IcedLayerEvent)> + for MultiWindowIcedLayerEvent { - fn from((id, message): (Option, IcedLayerEvent)) -> Self { + fn from((id, message): (Option, IcedLayerEvent)) -> Self { MultiWindowIcedLayerEvent(id, message) } } -impl From<&DispatchMessage> for IcedLayerEvent { +impl From<&DispatchMessage> for IcedLayerEvent { fn from(value: &DispatchMessage) -> Self { match value { - DispatchMessage::RequestRefresh { width, height } => IcedLayerEvent::RequestRefresh { - width: *width, - height: *height, - }, + DispatchMessage::RequestRefresh { width, height, .. } => { + IcedLayerEvent::RequestRefresh { + width: *width, + height: *height, + } + } DispatchMessage::MouseEnter { surface_x: x, surface_y: y, diff --git a/iced_layershell/src/lib.rs b/iced_layershell/src/lib.rs index aed390a..3b12ac6 100644 --- a/iced_layershell/src/lib.rs +++ b/iced_layershell/src/lib.rs @@ -16,6 +16,7 @@ pub mod reexport { pub use layershellev::reexport::Anchor; pub use layershellev::reexport::KeyboardInteractivity; pub use layershellev::reexport::Layer; + pub use layershellev::NewLayerShellSettings; } use settings::Settings; @@ -218,6 +219,8 @@ pub trait MultiApplication: Sized { /// The data needed to initialize your [`Application`]. type Flags; + type WindowInfo; + type Theme: Default + StyleSheet; /// Initializes the [`Application`] with the flags provided to @@ -238,6 +241,12 @@ pub trait MultiApplication: Sized { /// title of your window when necessary. fn namespace(&self) -> String; + fn id_info(&self, _id: iced_core::window::Id) -> Option<&Self::WindowInfo> { + None + } + + fn set_id_info(&mut self, _id: iced_core::window::Id, _info: Self::WindowInfo) {} + fn remove_id(&mut self, _id: iced_core::window::Id) {} /// Handles a __message__ and updates the state of the [`Application`]. /// /// This is where you define your __update logic__. All the __messages__, @@ -308,6 +317,7 @@ pub trait MultiApplication: Sized { fn run(settings: Settings) -> Result<(), error::Error> where Self: 'static, + ::WindowInfo: Clone, { #[allow(clippy::needless_update)] let renderer_settings = iced_renderer::Settings { @@ -356,6 +366,8 @@ where { type Flags = A::Flags; + type WindowInfo = A::WindowInfo; + fn new(flags: Self::Flags) -> (Self, Command) { let (app, command) = A::new(flags); @@ -381,4 +393,15 @@ where fn scale_factor(&self, window: iced::window::Id) -> f64 { self.0.scale_factor(window) } + + fn id_info(&self, id: iced_core::window::Id) -> Option<&Self::WindowInfo> { + self.0.id_info(id) + } + + fn set_id_info(&mut self, id: iced_core::window::Id, info: Self::WindowInfo) { + self.0.set_id_info(id, info) + } + fn remove_id(&mut self, id: iced_core::window::Id) { + self.0.remove_id(id) + } } diff --git a/iced_layershell/src/multi_window.rs b/iced_layershell/src/multi_window.rs index 6115733..5e6e889 100644 --- a/iced_layershell/src/multi_window.rs +++ b/iced_layershell/src/multi_window.rs @@ -1,13 +1,13 @@ mod state; use crate::{ - actions::{LayershellCustomActionsWithId, LayershellCustomActionsWithIdInner}, + actions::{LayershellCustomActionsWithIdAndInfo, LayershellCustomActionsWithIdInner}, multi_window::window_manager::WindowManager, settings::VirtualKeyboardSettings, }; use std::{collections::HashMap, f64, mem::ManuallyDrop, os::fd::AsFd, sync::Arc, time::Duration}; use crate::{ - actions::{LayerShellActions, LayershellCustomActions}, + actions::{LayerShellActions, LayershellCustomActionsWithInfo}, clipboard::LayerShellClipboard, conversion, error::Error, @@ -57,6 +57,8 @@ where /// The data needed to initialize your [`Application`]. type Flags; + type WindowInfo; + /// Initializes the [`Application`] with the flags provided to /// [`run`] as part of the [`Settings`]. /// @@ -76,6 +78,11 @@ where self.namespace() } + fn id_info(&self, _id: iced_core::window::Id) -> Option<&Self::WindowInfo>; + + fn set_id_info(&mut self, _id: iced_core::window::Id, info: Self::WindowInfo); + fn remove_id(&mut self, _id: iced_core::window::Id); + /// Returns the current [`Theme`] of the [`Application`]. fn theme(&self) -> Self::Theme; @@ -133,6 +140,7 @@ where E: Executor + 'static, C: Compositor + 'static, A::Theme: StyleSheet, + ::WindowInfo: Clone, { use futures::task; use futures::Future; @@ -156,7 +164,7 @@ where runtime.enter(|| A::new(flags)) }; - let ev: WindowState<()> = layershellev::WindowState::new(&application.namespace()) + let ev: WindowState = layershellev::WindowState::new(&application.namespace()) .with_single(false) .with_use_display_handle(true) .with_option_size(settings.layer_settings.size) @@ -181,8 +189,9 @@ where ); let (mut event_sender, event_receiver) = - mpsc::unbounded::>(); - let (control_sender, mut control_receiver) = mpsc::unbounded::>(); + mpsc::unbounded::>(); + let (control_sender, mut control_receiver) = + mpsc::unbounded::>>(); let mut instance = Box::pin(run_instance::( application, @@ -232,14 +241,21 @@ where } LayerEvent::RequestMessages(message) => 'outside: { match message { - DispatchMessage::RequestRefresh { width, height } => { + DispatchMessage::RequestRefresh { + width, + height, + is_created, + } => { + let unit = ev.get_unit(index.unwrap()); event_sender .start_send(MultiWindowIcedLayerEvent( id, IcedLayerEvent::RequestRefreshWithWrapper { width: *width, height: *height, - wrapper: ev.get_unit(index.unwrap()).gen_wrapper(), + wrapper: unit.gen_wrapper(), + is_created: *is_created, + info: unit.get_binding().cloned(), }, )) .expect("Cannot send"); @@ -278,21 +294,23 @@ where for flow in flow { match flow { LayerShellActions::CustomActionsWithId(actions) => { - for LayershellCustomActionsWithIdInner(id, action) in actions { + for LayershellCustomActionsWithIdInner(id, option_id, action) in + actions + { let Some(window) = ev.get_window_with_id(id) else { continue; }; match action { - LayershellCustomActions::AnchorChange(anchor) => { + LayershellCustomActionsWithInfo::AnchorChange(anchor) => { window.set_anchor(anchor); } - LayershellCustomActions::LayerChange(layer) => { + LayershellCustomActionsWithInfo::LayerChange(layer) => { window.set_layer(layer); } - LayershellCustomActions::SizeChange((width, height)) => { + LayershellCustomActionsWithInfo::SizeChange((width, height)) => { window.set_size((width, height)); } - LayershellCustomActions::VirtualKeyboardPressed { + LayershellCustomActionsWithInfo::VirtualKeyboardPressed { time, key, } => { @@ -312,6 +330,19 @@ where ) .ok(); } + LayershellCustomActionsWithInfo::NewLayerShell(( + settings, + info, + )) => { + return ReturnData::NewLayerShell(( + settings, + Some(info), + )); + } + LayershellCustomActionsWithInfo::RemoveLayerShell(id) => { + event_sender.start_send(MultiWindowIcedLayerEvent(None, IcedLayerEvent::WindowRemoved(id))).ok(); + return ReturnData::RemoveLayershell(option_id.unwrap()) + } } } } @@ -345,7 +376,6 @@ where Ok(()) } -#[allow(unused)] #[allow(clippy::too_many_arguments)] async fn run_instance( mut application: A, @@ -353,8 +383,10 @@ async fn run_instance( mut runtime: Runtime, A::Message>, mut proxy: IcedProxy, mut debug: Debug, - mut event_receiver: mpsc::UnboundedReceiver>, - mut control_sender: mpsc::UnboundedSender>, + mut event_receiver: mpsc::UnboundedReceiver< + MultiWindowIcedLayerEvent, + >, + mut control_sender: mpsc::UnboundedSender>>, mut window_manager: WindowManager, init_command: Command, ) where @@ -362,9 +394,9 @@ async fn run_instance( E: Executor + 'static, C: Compositor + 'static, A::Theme: StyleSheet, + A::WindowInfo: Clone, { use iced::window; - use iced_core::mouse; use iced_core::Event; let main_window = window_manager .get_mut(window::Id::MAIN) @@ -420,9 +452,10 @@ async fn run_instance( width, height, wrapper, + is_created, + info, }, ) => { - let layerid = wrapper.id(); let (id, window) = if window_manager.get_mut_alias(wrapper.id()).is_none() { let id = window::Id::unique(); @@ -463,6 +496,7 @@ async fn run_instance( let (id, window) = window_manager.get_mut_alias(wrapper.id()).unwrap(); let ui = user_interfaces.remove(&id).expect("Get User interface"); window.state.update_view_port(width, height); + #[allow(unused)] let renderer = &window.renderer; let _ = user_interfaces.insert( id, @@ -533,6 +567,21 @@ async fn run_instance( .ok(); debug.render_finished(); + + if is_created { + let cached_interfaces: HashMap = + ManuallyDrop::into_inner(user_interfaces) + .drain() + .map(|(id, ui)| (id, ui.into_cache())) + .collect(); + application.set_id_info(id, info.unwrap().clone()); + user_interfaces = ManuallyDrop::new(build_user_interfaces( + &application, + &mut debug, + &mut window_manager, + cached_interfaces, + )); + } } MultiWindowIcedLayerEvent(Some(id), IcedLayerEvent::Window(event)) => { let Some((id, window)) = window_manager.get_mut_alias(id) else { @@ -613,7 +662,7 @@ async fn run_instance( &mut cached_interfaces, ); - for (id, window) in window_manager.iter_mut() { + for (_id, window) in window_manager.iter_mut() { window.state.synchronize(&application); } @@ -630,6 +679,20 @@ async fn run_instance( } } } + MultiWindowIcedLayerEvent(_, IcedLayerEvent::WindowRemoved(id)) => { + let cached_interfaces: HashMap = + ManuallyDrop::into_inner(user_interfaces) + .drain() + .map(|(id, ui)| (id, ui.into_cache())) + .collect(); + application.remove_id(id); + user_interfaces = ManuallyDrop::new(build_user_interfaces( + &application, + &mut debug, + &mut window_manager, + cached_interfaces, + )); + } _ => {} } control_sender.start_send(custom_actions.clone()).ok(); @@ -701,13 +764,14 @@ pub(crate) fn update( proxy: &mut IcedProxy, debug: &mut Debug, messages: &mut Vec, - custom_actions: &mut Vec, + custom_actions: &mut Vec>, window_manager: &mut WindowManager, ui_caches: &mut HashMap, ) where C: Compositor + 'static, A::Theme: StyleSheet, A::Message: 'static, + A::WindowInfo: Clone + 'static, { for message in messages.drain(..) { debug.log_message(&message); @@ -741,7 +805,7 @@ pub(crate) fn run_command( compositor: &mut C, command: Command, runtime: &mut Runtime, A::Message>, - custom_actions: &mut Vec, + custom_actions: &mut Vec>, should_exit: &mut bool, proxy: &mut IcedProxy, debug: &mut Debug, @@ -753,6 +817,7 @@ pub(crate) fn run_command( C: Compositor + 'static, A::Theme: StyleSheet, A::Message: 'static, + A::WindowInfo: Clone + 'static, { use iced_core::widget::operation; use iced_runtime::command; @@ -804,8 +869,18 @@ pub(crate) fn run_command( *ui_caches = uis.drain().map(|(id, ui)| (id, ui.into_cache())).collect(); } command::Action::Window(action) => match action { - WinowAction::Close(_) => { - *should_exit = true; + WinowAction::Close(id) => { + if id == iced::window::Id::MAIN { + *should_exit = true; + continue; + } + if let Some(layerid) = window_manager.get_layer_id(id) { + customactions.push(LayershellCustomActionsWithIdInner( + layerid, + Some(layerid), + LayershellCustomActionsWithInfo::RemoveLayerShell(id), + )) + } } WinowAction::Screenshot(id, tag) => { let Some(window) = window_manager.get_mut(id) else { @@ -838,9 +913,57 @@ pub(crate) fn run_command( proxy.send(tagger(Ok(()))); } command::Action::Custom(custom) => { - if let Some(action) = custom.downcast_ref::() { - if let Some(id) = window_manager.get_iced_id(action.0) { - customactions.push(LayershellCustomActionsWithIdInner(id, action.1)); + if let Some(action) = + custom.downcast_ref::>() + { + let option_id = + if let LayershellCustomActionsWithInfo::RemoveLayerShell(id) = action.1 { + window_manager.get_layer_id(id) + } else { + None + }; + if let Some(id) = window_manager.get_layer_id(action.0) { + customactions.push(LayershellCustomActionsWithIdInner( + id, + option_id, + action.1.clone(), + )); + } + } else if let Some(action) = + custom.downcast_ref::>() + { + // NOTE: try to unwrap again, if with type LayershellCustomActionsWithInfo<()>, + let option_id = + if let LayershellCustomActionsWithInfo::RemoveLayerShell(id) = action.1 { + window_manager.get_layer_id(id) + } else { + None + }; + let turnaction: LayershellCustomActionsWithInfo = match action.1 + { + LayershellCustomActionsWithInfo::AnchorChange(anchor) => { + LayershellCustomActionsWithInfo::AnchorChange(anchor) + } + LayershellCustomActionsWithInfo::LayerChange(layer) => { + LayershellCustomActionsWithInfo::LayerChange(layer) + } + LayershellCustomActionsWithInfo::SizeChange(size) => { + LayershellCustomActionsWithInfo::SizeChange(size) + } + LayershellCustomActionsWithInfo::VirtualKeyboardPressed { time, key } => { + LayershellCustomActionsWithInfo::VirtualKeyboardPressed { time, key } + } + LayershellCustomActionsWithInfo::RemoveLayerShell(id) => { + LayershellCustomActionsWithInfo::RemoveLayerShell(id) + } + _ => { + continue; + } + }; + if let Some(id) = window_manager.get_layer_id(action.0) { + customactions.push(LayershellCustomActionsWithIdInner( + id, option_id, turnaction, + )); } } } diff --git a/iced_layershell/src/multi_window/window_manager.rs b/iced_layershell/src/multi_window/window_manager.rs index fc32b62..18cca7a 100644 --- a/iced_layershell/src/multi_window/window_manager.rs +++ b/iced_layershell/src/multi_window/window_manager.rs @@ -102,7 +102,7 @@ where Some((id, self.get_mut(id)?)) } - pub fn get_iced_id(&self, id: IcedId) -> Option { + pub fn get_layer_id(&self, id: IcedId) -> Option { self.back_aliases.get(&id).copied() } diff --git a/layershellev/examples/simplelayer.rs b/layershellev/examples/simplelayer.rs index fe1ead3..dcb944e 100644 --- a/layershellev/examples/simplelayer.rs +++ b/layershellev/examples/simplelayer.rs @@ -55,7 +55,9 @@ fn main() { (), )) } - LayerEvent::RequestMessages(DispatchMessage::RequestRefresh { width, height }) => { + LayerEvent::RequestMessages(DispatchMessage::RequestRefresh { + width, height, .. + }) => { println!("{width}, {height}"); ReturnData::None } diff --git a/layershellev/src/events.rs b/layershellev/src/events.rs index dd34f57..3a6927d 100644 --- a/layershellev/src/events.rs +++ b/layershellev/src/events.rs @@ -1,3 +1,8 @@ +use wayland_protocols_wlr::layer_shell::v1::client::{ + zwlr_layer_shell_v1::Layer, + zwlr_layer_surface_v1::{Anchor, KeyboardInteractivity}, +}; + use wayland_client::{ globals::GlobalList, protocol::{ @@ -9,7 +14,7 @@ use wayland_client::{ QueueHandle, WEnum, }; -use crate::xkb_keyboard::KeyEvent; +use crate::{id, xkb_keyboard::KeyEvent}; use crate::keyboard::ModifiersState; @@ -30,7 +35,7 @@ use std::{fmt::Debug, fs::File}; /// /// RequestMessages store the DispatchMessage, you can know what happened during dispatch with this /// event. -pub enum LayerEvent<'a, T: Debug, Message> { +pub enum LayerEvent<'a, T, Message> { InitRequest, XdgInfoChanged(XdgInfoChangedType), BindProvide(&'a GlobalList, &'a QueueHandle>), @@ -46,6 +51,28 @@ pub enum LayerEvent<'a, T: Debug, Message> { UserEvent(Message), } +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub struct NewLayerShellSettings { + pub size: Option<(u32, u32)>, + pub layer: Layer, + pub anchor: Anchor, + pub exclusize_zone: Option, + pub margins: Option<(i32, i32, i32, i32)>, + pub keyboard_interactivity: KeyboardInteractivity, +} + +impl Default for NewLayerShellSettings { + fn default() -> Self { + NewLayerShellSettings { + anchor: Anchor::Bottom | Anchor::Left | Anchor::Right, + layer: Layer::Top, + exclusize_zone: None, + size: None, + margins: Some((0, 0, 0, 0)), + keyboard_interactivity: KeyboardInteractivity::OnDemand, + } + } +} /// the return data /// Note: when event is RequestBuffer, you must return WlBuffer /// Note: when receive InitRequest, you can request to bind extra wayland-protocols. this time you @@ -60,13 +87,15 @@ pub enum LayerEvent<'a, T: Debug, Message> { /// /// None means nothing will happened, no request, and no return data #[derive(Debug, PartialEq, Eq)] -pub enum ReturnData { +pub enum ReturnData { WlBuffer(WlBuffer), RequestBind, RequestExist, RedrawAllRequest, RedrawIndexRequest(Id), RequestSetCursorShape((String, WlPointer, u32)), + NewLayerShell((NewLayerShellSettings, Option)), + RemoveLayershell(id::Id), None, } @@ -164,6 +193,7 @@ pub(crate) enum DispatchMessageInner { RequestRefresh { width: u32, height: u32, + is_created: bool, }, PrefredScale(u32), XdgInfoChanged(XdgInfoChangedType), @@ -241,6 +271,7 @@ pub enum DispatchMessage { RequestRefresh { width: u32, height: u32, + is_created: bool, }, /// fractal scale handle PrefredScale(u32), @@ -301,9 +332,15 @@ impl From for DispatchMessage { DispatchMessageInner::TouchMotion { time, id, x, y } => { DispatchMessage::TouchMotion { time, id, x, y } } - DispatchMessageInner::RequestRefresh { width, height } => { - DispatchMessage::RequestRefresh { width, height } - } + DispatchMessageInner::RequestRefresh { + width, + height, + is_created, + } => DispatchMessage::RequestRefresh { + width, + height, + is_created, + }, DispatchMessageInner::Axis { time, horizontal, diff --git a/layershellev/src/lib.rs b/layershellev/src/lib.rs index a1648e2..b6fb191 100644 --- a/layershellev/src/lib.rs +++ b/layershellev/src/lib.rs @@ -60,7 +60,7 @@ //! (), //! )) //! } -//! LayerEvent::RequestMessages(DispatchMessage::RequestRefresh { width, height }) => { +//! LayerEvent::RequestMessages(DispatchMessage::RequestRefresh { width, height, .. }) => { //! println!("{width}, {height}"); //! ReturnData::None //! } @@ -111,6 +111,7 @@ //! } //! ``` //! +pub use events::NewLayerShellSettings; use sctk::reexports::calloop::LoopHandle; pub use waycrate_xkbkeycode::keyboard; pub use waycrate_xkbkeycode::xkb_keyboard; @@ -120,8 +121,6 @@ pub use sctk::reexports::calloop; mod events; mod strtoshape; -use std::fmt::Debug; - use events::DispatchMessageInner; pub mod id; @@ -284,7 +283,7 @@ impl ZxdgOutputInfo { /// and it can set a binding, you to store the related data. like /// a cario_context, which is binding to the buffer on the wl_surface. #[derive(Debug)] -pub struct WindowStateUnit { +pub struct WindowStateUnit { id: id::Id, display: WlDisplay, wl_surface: WlSurface, @@ -293,10 +292,12 @@ pub struct WindowStateUnit { layer_shell: ZwlrLayerSurfaceV1, zxdgoutput: Option, fractional_scale: Option, + wl_output: Option, binding: Option, + becreated: bool, } -impl WindowStateUnit { +impl WindowStateUnit { pub fn id(&self) -> id::Id { self.id } @@ -308,7 +309,7 @@ impl WindowStateUnit { } } } -impl WindowStateUnit { +impl WindowStateUnit { #[inline] pub fn raw_window_handle_rwh_06(&self) -> Result { Ok(rwh_06::WaylandWindowHandle::new({ @@ -330,7 +331,7 @@ impl WindowStateUnit { } } -impl rwh_06::HasWindowHandle for WindowStateUnit { +impl rwh_06::HasWindowHandle for WindowStateUnit { fn window_handle(&self) -> Result, rwh_06::HandleError> { let raw = self.raw_window_handle_rwh_06()?; @@ -340,7 +341,7 @@ impl rwh_06::HasWindowHandle for WindowStateUnit { } } -impl rwh_06::HasDisplayHandle for WindowStateUnit { +impl rwh_06::HasDisplayHandle for WindowStateUnit { fn display_handle(&self) -> Result, rwh_06::HandleError> { let raw = self.raw_display_handle_rwh_06()?; @@ -351,7 +352,7 @@ impl rwh_06::HasDisplayHandle for WindowStateUnit { } // if is only one window, use it will be easy -impl rwh_06::HasWindowHandle for WindowState { +impl rwh_06::HasWindowHandle for WindowState { fn window_handle(&self) -> Result, rwh_06::HandleError> { let raw = self.main_window().raw_window_handle_rwh_06()?; @@ -362,7 +363,7 @@ impl rwh_06::HasWindowHandle for WindowState { } // if is only one window, use it will be easy -impl rwh_06::HasDisplayHandle for WindowState { +impl rwh_06::HasDisplayHandle for WindowState { fn display_handle(&self) -> Result, rwh_06::HandleError> { let raw = self.main_window().raw_display_handle_rwh_06()?; @@ -371,7 +372,7 @@ impl rwh_06::HasDisplayHandle for WindowState { Ok(unsafe { rwh_06::DisplayHandle::borrow_raw(raw) }) } } -impl WindowStateUnit { +impl WindowStateUnit { /// get the wl surface from WindowState pub fn get_wlsurface(&self) -> &WlSurface { &self.wl_surface @@ -424,6 +425,10 @@ impl WindowStateUnit { self.binding.as_mut() } + pub fn get_binding(&self) -> Option<&T> { + self.binding.as_ref() + } + /// get the size of the surface pub fn get_size(&self) -> (u32, u32) { self.size @@ -440,7 +445,7 @@ impl WindowStateUnit { /// main state, store the main information #[derive(Debug)] -pub struct WindowState { +pub struct WindowState { outputs: Vec<(u32, wl_output::WlOutput)>, current_surface: Option, is_single: bool, @@ -478,7 +483,10 @@ pub struct WindowState { loop_handler: Option>, } -impl WindowState { +/// Simple WindowState, without any data binding or info +pub type WindowStateSimple = WindowState<()>; + +impl WindowState { // return the first window // I will use it in iced pub fn main_window(&self) -> &WindowStateUnit { @@ -507,7 +515,7 @@ impl WindowWrapper { } } -impl WindowState { +impl WindowState { /// get a seat from state pub fn get_seat(&self) -> &WlSeat { self.seat.as_ref().unwrap() @@ -528,7 +536,10 @@ impl WindowState { self.touch.as_ref() } } -impl WindowState { + +impl WindowState { + /// gen the wrapper to the main window + /// used to get display and etc pub fn gen_main_wrapper(&self) -> WindowWrapper { self.main_window().gen_wrapper() } @@ -575,7 +586,7 @@ impl rwh_06::HasDisplayHandle for WindowWrapper { } } -impl WindowState { +impl WindowState { /// create a WindowState, you need to pass a namespace in pub fn new(namespace: &str) -> Self { assert_ne!(namespace, ""); @@ -645,7 +656,7 @@ impl WindowState { } } -impl Default for WindowState { +impl Default for WindowState { fn default() -> Self { Self { outputs: Vec::new(), @@ -683,7 +694,7 @@ impl Default for WindowState { } } -impl WindowState { +impl WindowState { /// You can save the virtual_keyboard here pub fn set_virtual_keyboard(&mut self, keyboard: ZwpVirtualKeyboardV1) { self.virtual_keyboard = Some(keyboard); @@ -727,7 +738,7 @@ impl WindowState { } } -impl Dispatch for WindowState { +impl Dispatch for WindowState { fn event( state: &mut Self, proxy: &wl_registry::WlRegistry, @@ -760,7 +771,7 @@ impl Dispatch for WindowState Dispatch for WindowState { +impl Dispatch for WindowState { fn event( state: &mut Self, seat: &wl_seat::WlSeat, @@ -787,7 +798,7 @@ impl Dispatch for WindowState { } } -impl Dispatch for WindowState { +impl Dispatch for WindowState { fn event( state: &mut Self, _proxy: &wl_keyboard::WlKeyboard, @@ -863,7 +874,7 @@ impl Dispatch for WindowState { } } -impl Dispatch for WindowState { +impl Dispatch for WindowState { fn event( state: &mut Self, _proxy: &wl_touch::WlTouch, @@ -901,7 +912,7 @@ impl Dispatch for WindowState { } } -impl Dispatch for WindowState { +impl Dispatch for WindowState { fn event( state: &mut Self, pointer: &wl_pointer::WlPointer, @@ -1067,7 +1078,7 @@ impl Dispatch for WindowState { } } -impl Dispatch for WindowState { +impl Dispatch for WindowState { fn event( state: &mut Self, surface: &zwlr_layer_surface_v1::ZwlrLayerSurfaceV1, @@ -1101,7 +1112,7 @@ impl Dispatch for Windo } } -impl Dispatch for WindowState { +impl Dispatch for WindowState { fn event( state: &mut Self, proxy: &zxdg_output_v1::ZxdgOutputV1, @@ -1139,7 +1150,7 @@ impl Dispatch for WindowState { } } -impl Dispatch for WindowState { +impl Dispatch for WindowState { fn event( state: &mut Self, proxy: &wp_fractional_scale_v1::WpFractionalScaleV1, @@ -1163,26 +1174,26 @@ impl Dispatch for Win } } -delegate_noop!(@WindowState: ignore WlCompositor); // WlCompositor is need to create a surface -delegate_noop!(@WindowState: ignore WlSurface); // surface is the base needed to show buffer -delegate_noop!(@WindowState: ignore WlOutput); // output is need to place layer_shell, although here - // it is not used -delegate_noop!(@WindowState: ignore WlShm); // shm is used to create buffer pool -delegate_noop!(@WindowState: ignore WlShmPool); // so it is pool, created by wl_shm -delegate_noop!(@WindowState: ignore WlBuffer); // buffer show the picture -delegate_noop!(@WindowState: ignore ZwlrLayerShellV1); // it is similar with xdg_toplevel, also the - // ext-session-shell +delegate_noop!(@ WindowState: ignore WlCompositor); // WlCompositor is need to create a surface +delegate_noop!(@ WindowState: ignore WlSurface); // surface is the base needed to show buffer +delegate_noop!(@ WindowState: ignore WlOutput); // output is need to place layer_shell, although here + // it is not used +delegate_noop!(@ WindowState: ignore WlShm); // shm is used to create buffer pool +delegate_noop!(@ WindowState: ignore WlShmPool); // so it is pool, created by wl_shm +delegate_noop!(@ WindowState: ignore WlBuffer); // buffer show the picture +delegate_noop!(@ WindowState: ignore ZwlrLayerShellV1); // it is similar with xdg_toplevel, also the + // ext-session-shell -delegate_noop!(@WindowState: ignore WpCursorShapeManagerV1); -delegate_noop!(@WindowState: ignore WpCursorShapeDeviceV1); +delegate_noop!(@ WindowState: ignore WpCursorShapeManagerV1); +delegate_noop!(@ WindowState: ignore WpCursorShapeDeviceV1); -delegate_noop!(@WindowState: ignore ZwpVirtualKeyboardV1); -delegate_noop!(@WindowState: ignore ZwpVirtualKeyboardManagerV1); +delegate_noop!(@ WindowState: ignore ZwpVirtualKeyboardV1); +delegate_noop!(@ WindowState: ignore ZwpVirtualKeyboardManagerV1); -delegate_noop!(@WindowState: ignore ZxdgOutputManagerV1); -delegate_noop!(@WindowState: ignore WpFractionalScaleManagerV1); +delegate_noop!(@ WindowState: ignore ZxdgOutputManagerV1); +delegate_noop!(@ WindowState: ignore WpFractionalScaleManagerV1); -impl WindowState { +impl WindowState { pub fn build(mut self) -> Result { let connection = Connection::connect_to_env()?; let (globals, _) = registry_queue_init::(&connection)?; // We just need the @@ -1278,17 +1289,19 @@ impl WindowState { zxdgoutput: None, fractional_scale, binding: None, + becreated: false, + wl_output: None, }); } else { let displays = self.outputs.clone(); - for (_, display) in displays.iter() { + for (_, output_display) in displays.iter() { let wl_surface = wmcompositer.create_surface(&qh, ()); // and create a surface. if two or more, let layer_shell = globals .bind::(&qh, 3..=4, ()) .unwrap(); let layer = layer_shell.get_layer_surface( &wl_surface, - Some(display), + Some(output_display), self.layer, self.namespace.clone(), &qh, @@ -1310,7 +1323,7 @@ impl WindowState { wl_surface.commit(); - let zxdgoutput = xdg_output_manager.get_xdg_output(display, &qh, ()); + let zxdgoutput = xdg_output_manager.get_xdg_output(output_display, &qh, ()); let mut fractional_scale = None; if let Some(ref fractional_scale_manager) = fractional_scale_manager { fractional_scale = @@ -1331,6 +1344,8 @@ impl WindowState { zxdgoutput: Some(ZxdgOutputInfo::new(zxdgoutput)), fractional_scale, binding: None, + becreated: false, + wl_output: Some(output_display.clone()), }); } self.message.clear(); @@ -1363,7 +1378,7 @@ impl WindowState { event_handler: F, ) -> Result<(), LayerEventError> where - F: FnMut(LayerEvent, &mut WindowState, Option) -> ReturnData, + F: FnMut(LayerEvent, &mut WindowState, Option) -> ReturnData, { self.running_with_proxy_option(Some(message_receiver), event_handler) } @@ -1381,7 +1396,7 @@ impl WindowState { /// pub fn running(self, event_handler: F) -> Result<(), LayerEventError> where - F: FnMut(LayerEvent, &mut WindowState, Option) -> ReturnData, + F: FnMut(LayerEvent, &mut WindowState, Option) -> ReturnData, { self.running_with_proxy_option(None, event_handler) } @@ -1392,7 +1407,7 @@ impl WindowState { mut event_handler: F, ) -> Result<(), LayerEventError> where - F: FnMut(LayerEvent, &mut WindowState, Option) -> ReturnData, + F: FnMut(LayerEvent, &mut WindowState, Option) -> ReturnData, { let globals = self.globals.take().unwrap(); let event_queue = self.event_queue.take().unwrap(); @@ -1458,6 +1473,7 @@ impl WindowState { LayerEvent::RequestMessages(&DispatchMessage::RequestRefresh { width: *width, height: *height, + is_created: self.units[index].becreated, }), &mut self, Some(index), @@ -1474,7 +1490,7 @@ impl WindowState { *index_info, ); } - (_, DispatchMessageInner::NewDisplay(display)) => { + (_, DispatchMessageInner::NewDisplay(output_display)) => { if self.is_single { continue; } @@ -1484,7 +1500,7 @@ impl WindowState { .unwrap(); let layer = layer_shell.get_layer_surface( &wl_surface, - Some(display), + Some(output_display), self.layer, self.namespace.clone(), &qh, @@ -1506,7 +1522,7 @@ impl WindowState { wl_surface.commit(); - let zxdgoutput = xdg_output_manager.get_xdg_output(display, &qh, ()); + let zxdgoutput = xdg_output_manager.get_xdg_output(output_display, &qh, ()); let mut fractional_scale = None; if let Some(ref fractional_scale_manager) = fractional_scale_manager { fractional_scale = Some(fractional_scale_manager.get_fractional_scale( @@ -1530,6 +1546,8 @@ impl WindowState { zxdgoutput: Some(ZxdgOutputInfo::new(zxdgoutput)), fractional_scale, binding: None, + becreated: false, + wl_output: Some(output_display.clone()), }); } _ => { @@ -1548,10 +1566,11 @@ impl WindowState { &DispatchMessage::RequestRefresh { width: unit.size.0, height: unit.size.1, + is_created: unit.becreated, }, ), &mut self, - None, + Some(index), ); } } @@ -1567,6 +1586,7 @@ impl WindowState { &DispatchMessage::RequestRefresh { width: unit.size.0, height: unit.size.1, + is_created: unit.becreated, }, ), &mut self, @@ -1580,7 +1600,7 @@ impl WindowState { ReturnData::RequestSetCursorShape((shape_name, pointer, serial)) => { if let Some(ref cursor_manager) = cursor_manager { let Some(shape) = str_to_shape(&shape_name) else { - eprintln!("Not supported shape"); + log::error!("Not supported shape"); continue; }; let device = cursor_manager.get_pointer(&pointer, &qh, ()); @@ -1590,7 +1610,7 @@ impl WindowState { let Some(cursor_buffer) = get_cursor_buffer(&shape_name, &connection, &shm) else { - eprintln!("Cannot find cursor {shape_name}"); + log::error!("Cannot find cursor {shape_name}"); continue; }; let cursor_surface = wmcompositer.create_surface(&qh, ()); @@ -1619,7 +1639,7 @@ impl WindowState { ReturnData::RequestSetCursorShape((shape_name, pointer, serial)) => { if let Some(ref cursor_manager) = cursor_manager { let Some(shape) = str_to_shape(&shape_name) else { - eprintln!("Not supported shape"); + log::error!("Not supported shape"); continue; }; let device = cursor_manager.get_pointer(&pointer, &qh, ()); @@ -1629,7 +1649,7 @@ impl WindowState { let Some(cursor_buffer) = get_cursor_buffer(&shape_name, &connection, &shm) else { - eprintln!("Cannot find cursor {shape_name}"); + log::error!("Cannot find cursor {shape_name}"); continue; }; let cursor_surface = wmcompositer.create_surface(&qh, ()); @@ -1656,10 +1676,15 @@ impl WindowState { ReturnData::RedrawAllRequest => { for index in 0..self.units.len() { let unit = &self.units[index]; + // TODO: just fix it like this + if unit.size.0 == 0 || unit.size.1 == 0 { + continue; + } replace_data.push(event_handler( LayerEvent::RequestMessages(&DispatchMessage::RequestRefresh { width: unit.size.0, height: unit.size.1, + is_created: unit.becreated, }), &mut self, Some(index), @@ -1677,6 +1702,7 @@ impl WindowState { LayerEvent::RequestMessages(&DispatchMessage::RequestRefresh { width: unit.size.0, height: unit.size.1, + is_created: unit.becreated, }), &mut self, Some(*index), @@ -1689,7 +1715,7 @@ impl WindowState { ReturnData::RequestSetCursorShape((shape_name, pointer, serial)) => { if let Some(ref cursor_manager) = cursor_manager { let Some(shape) = str_to_shape(&shape_name) else { - eprintln!("Not supported shape"); + log::error!("Not supported shape"); continue; }; let device = cursor_manager.get_pointer(&pointer, &qh, ()); @@ -1699,7 +1725,7 @@ impl WindowState { let Some(cursor_buffer) = get_cursor_buffer(&shape_name, &connection, &shm) else { - eprintln!("Cannot find cursor {shape_name}"); + log::error!("Cannot find cursor {shape_name}"); continue; }; let cursor_surface = wmcompositer.create_surface(&qh, ()); @@ -1715,10 +1741,98 @@ impl WindowState { cursor_surface.commit(); } } + ReturnData::NewLayerShell(( + NewLayerShellSettings { + size, + layer, + anchor, + exclusize_zone: exclusive_zone, + margins: margin, + keyboard_interactivity, + }, + info, + )) => { + if self.is_single { + continue; + } + let pos = self.surface_pos(); + + let output = pos.and_then(|p| self.units[p].wl_output.as_ref()); + let wl_surface = wmcompositer.create_surface(&qh, ()); // and create a surface. if two or more, + let layer_shell = globals + .bind::(&qh, 3..=4, ()) + .unwrap(); + let layer = layer_shell.get_layer_surface( + &wl_surface, + output, + layer, + self.namespace.clone(), + &qh, + (), + ); + layer.set_anchor(anchor); + layer.set_keyboard_interactivity(keyboard_interactivity); + if let Some((init_w, init_h)) = size { + layer.set_size(init_w, init_h); + } + + if let Some(zone) = exclusive_zone { + layer.set_exclusive_zone(zone); + } + + if let Some((top, right, bottom, left)) = margin { + layer.set_margin(top, right, bottom, left); + } + + wl_surface.commit(); + + let mut fractional_scale = None; + if let Some(ref fractional_scale_manager) = fractional_scale_manager { + fractional_scale = + Some(fractional_scale_manager.get_fractional_scale( + &wl_surface, + &qh, + (), + )); + } + // so during the init Configure of the shell, a buffer, atleast a buffer is needed. + // and if you need to reconfigure it, you need to commit the wl_surface again + // so because this is just an example, so we just commit it once + // like if you want to reset anchor or KeyboardInteractivity or resize, commit is needed + + self.units.push(WindowStateUnit { + id: id::Id::unique(), + display: connection.display(), + wl_surface, + size: (0, 0), + buffer: None, + layer_shell: layer, + zxdgoutput: None, + fractional_scale, + becreated: true, + wl_output: output.cloned(), + binding: info, + }); + } + ReturnData::RemoveLayershell(id) => { + let Some(index) = self + .units + .iter() + .position(|unit| unit.id == id && unit.becreated) + else { + continue; + }; + self.units[index].layer_shell.destroy(); + self.units[index].wl_surface.destroy(); + if let Some(buffer) = self.units[index].buffer.as_ref() { + buffer.destroy() + } + self.units.remove(index); + } _ => {} } } - replace_data.retain(|x| *x != ReturnData::None); + replace_data.retain(|x| !matches!(x, ReturnData::None)); if replace_data.is_empty() { break; } diff --git a/sessionlockev/src/events.rs b/sessionlockev/src/events.rs index 702eb01..b83a97a 100644 --- a/sessionlockev/src/events.rs +++ b/sessionlockev/src/events.rs @@ -29,7 +29,7 @@ use std::{fmt::Debug, fs::File}; /// RequestMessages store the DispatchMessage, you can know what happened during dispatch with this /// event. #[derive(Debug)] -pub enum SessionLockEvent<'a, T: Debug, Message> { +pub enum SessionLockEvent<'a, T, Message> { InitRequest, BindProvide(&'a GlobalList, &'a QueueHandle>), RequestBuffer( diff --git a/sessionlockev/src/lib.rs b/sessionlockev/src/lib.rs index 38baa71..2cdebf3 100644 --- a/sessionlockev/src/lib.rs +++ b/sessionlockev/src/lib.rs @@ -110,8 +110,6 @@ pub mod id; use strtoshape::str_to_shape; -use std::fmt::Debug; - use events::{AxisScroll, DispatchMessageInner}; pub use events::{DispatchMessage, ReturnData, SessionLockEvent}; @@ -289,7 +287,7 @@ impl rwh_06::HasDisplayHandle for WindowWrapper { } #[derive(Debug)] -pub struct WindowStateUnit { +pub struct WindowStateUnit { id: id::Id, display: WlDisplay, wl_surface: WlSurface, @@ -300,7 +298,7 @@ pub struct WindowStateUnit { binding: Option, } -impl WindowStateUnit { +impl WindowStateUnit { pub fn id(&self) -> id::Id { self.id } @@ -313,7 +311,7 @@ impl WindowStateUnit { } } -impl WindowStateUnit { +impl WindowStateUnit { #[inline] pub fn raw_window_handle_rwh_06(&self) -> Result { Ok(rwh_06::WaylandWindowHandle::new({ @@ -342,7 +340,7 @@ impl WindowStateUnit { /// /// and it can set a binding, you to store the related data. like /// a cario_context, which is binding to the buffer on the wl_surface. -impl WindowStateUnit { +impl WindowStateUnit { /// get the wl surface from WindowState pub fn get_wlsurface(&self) -> &WlSurface { &self.wl_surface @@ -371,7 +369,7 @@ impl WindowStateUnit { } #[derive(Debug)] -pub struct WindowState { +pub struct WindowState { outputs: Vec<(u32, wl_output::WlOutput)>, current_surface: Option, units: Vec>, @@ -396,7 +394,7 @@ pub struct WindowState { use_display_handle: bool, } -impl WindowState { +impl WindowState { /// get a seat from state pub fn get_seat(&self) -> &WlSeat { self.seat.as_ref().unwrap() @@ -418,7 +416,7 @@ impl WindowState { } } -impl WindowState { +impl WindowState { pub fn gen_main_wrapper(&self) -> WindowWrapper { self.main_window().gen_wrapper() } @@ -437,14 +435,14 @@ impl WindowState { } } -impl WindowState { +impl WindowState { /// create a new WindowState pub fn new() -> Self { Self::default() } } -impl Default for WindowState { +impl Default for WindowState { fn default() -> Self { Self { outputs: Vec::new(), @@ -471,7 +469,7 @@ impl Default for WindowState { } } -impl WindowState { +impl WindowState { /// get the unit with the index returned by eventloop pub fn get_unit(&mut self, index: usize) -> &mut WindowStateUnit { &mut self.units[index] @@ -504,7 +502,7 @@ impl WindowState { } } -impl Dispatch for WindowState { +impl Dispatch for WindowState { fn event( state: &mut Self, proxy: &wl_registry::WlRegistry, @@ -537,7 +535,7 @@ impl Dispatch for WindowState Dispatch for WindowState { +impl Dispatch for WindowState { fn event( state: &mut Self, seat: &wl_seat::WlSeat, @@ -564,7 +562,7 @@ impl Dispatch for WindowState { } } -impl Dispatch for WindowState { +impl Dispatch for WindowState { fn event( state: &mut Self, _proxy: &wl_keyboard::WlKeyboard, @@ -640,7 +638,7 @@ impl Dispatch for WindowState { } } -impl Dispatch for WindowState { +impl Dispatch for WindowState { fn event( state: &mut Self, _proxy: &wl_touch::WlTouch, @@ -678,7 +676,7 @@ impl Dispatch for WindowState { } } -impl Dispatch for WindowState { +impl Dispatch for WindowState { fn event( state: &mut Self, pointer: &wl_pointer::WlPointer, @@ -839,9 +837,7 @@ impl Dispatch for WindowState { } } -impl Dispatch - for WindowState -{ +impl Dispatch for WindowState { fn event( state: &mut Self, surface: &ext_session_lock_surface_v1::ExtSessionLockSurfaceV1, @@ -875,7 +871,7 @@ impl Dispatch Dispatch for WindowState { +impl Dispatch for WindowState { fn event( state: &mut Self, proxy: &wp_fractional_scale_v1::WpFractionalScaleV1, @@ -899,28 +895,28 @@ impl Dispatch for Win } } -delegate_noop!(@WindowState: ignore WlCompositor); // WlCompositor is need to create a surface -delegate_noop!(@WindowState: ignore WlSurface); // surface is the base needed to show buffer -delegate_noop!(@WindowState: ignore WlOutput); // output is need to place layer_shell, although here - // it is not used -delegate_noop!(@WindowState: ignore WlShm); // shm is used to create buffer pool -delegate_noop!(@WindowState: ignore WlShmPool); // so it is pool, created by wl_shm -delegate_noop!(@WindowState: ignore WlBuffer); // buffer show the picture - // +delegate_noop!(@WindowState: ignore WlCompositor); // WlCompositor is need to create a surface +delegate_noop!(@WindowState: ignore WlSurface); // surface is the base needed to show buffer +delegate_noop!(@WindowState: ignore WlOutput); // output is need to place layer_shell, although here + // it is not used +delegate_noop!(@WindowState: ignore WlShm); // shm is used to create buffer pool +delegate_noop!(@WindowState: ignore WlShmPool); // so it is pool, created by wl_shm +delegate_noop!(@WindowState: ignore WlBuffer); // buffer show the picture + // -delegate_noop!(@WindowState: ignore ExtSessionLockV1); // buffer show the picture -delegate_noop!(@WindowState: ignore ExtSessionLockManagerV1); // buffer show the picture +delegate_noop!(@WindowState: ignore ExtSessionLockV1); // buffer show the picture +delegate_noop!(@WindowState: ignore ExtSessionLockManagerV1); // buffer show the picture -delegate_noop!(@WindowState: ignore WpCursorShapeManagerV1); -delegate_noop!(@WindowState: ignore WpCursorShapeDeviceV1); +delegate_noop!(@WindowState: ignore WpCursorShapeManagerV1); +delegate_noop!(@WindowState: ignore WpCursorShapeDeviceV1); -delegate_noop!(@WindowState: ignore ZwpVirtualKeyboardV1); -delegate_noop!(@WindowState: ignore ZwpVirtualKeyboardManagerV1); +delegate_noop!(@WindowState: ignore ZwpVirtualKeyboardV1); +delegate_noop!(@WindowState: ignore ZwpVirtualKeyboardManagerV1); // fractional_scale_manager -delegate_noop!(@WindowState: ignore WpFractionalScaleManagerV1); +delegate_noop!(@WindowState: ignore WpFractionalScaleManagerV1); -impl WindowState { +impl WindowState { pub fn build(mut self) -> Result { let connection = Connection::connect_to_env()?; let (globals, _) = registry_queue_init::(&connection)?; // We just need the @@ -1158,7 +1154,7 @@ impl WindowState { ReturnData::RequestSetCursorShape((shape_name, pointer, serial)) => { if let Some(ref cursor_manager) = cursor_manager { let Some(shape) = str_to_shape(&shape_name) else { - eprintln!("Not supported shape"); + log::error!("Not supported shape"); continue; }; let device = cursor_manager.get_pointer(&pointer, &qh, ()); @@ -1168,7 +1164,7 @@ impl WindowState { let Some(cursor_buffer) = get_cursor_buffer(&shape_name, &connection, &shm) else { - eprintln!("Cannot find cursor {shape_name}"); + log::error!("Cannot find cursor {shape_name}"); continue; }; let cursor_surface = wmcompositer.create_surface(&qh, ()); @@ -1199,7 +1195,7 @@ impl WindowState { ReturnData::RequestSetCursorShape((shape_name, pointer, serial)) => { if let Some(ref cursor_manager) = cursor_manager { let Some(shape) = str_to_shape(&shape_name) else { - eprintln!("Not supported shape"); + log::error!("Not supported shape"); continue; }; let device = cursor_manager.get_pointer(&pointer, &qh, ()); @@ -1209,7 +1205,7 @@ impl WindowState { let Some(cursor_buffer) = get_cursor_buffer(&shape_name, &connection, &shm) else { - eprintln!("Cannot find cursor {shape_name}"); + log::error!("Cannot find cursor {shape_name}"); continue; }; let cursor_surface = wmcompositer.create_surface(&qh, ()); diff --git a/starcolorkeyboard/src/main.rs b/starcolorkeyboard/src/main.rs index 003f6d8..1e3cf4d 100644 --- a/starcolorkeyboard/src/main.rs +++ b/starcolorkeyboard/src/main.rs @@ -139,7 +139,7 @@ fn main() { (), )) } - LayerEvent::RequestMessages(DispatchMessage::RequestRefresh { width, height }) => { + LayerEvent::RequestMessages(DispatchMessage::RequestRefresh { width, height, .. }) => { let index = index.unwrap(); let windowunit = ev.get_unit(index); let pangoui = windowunit.get_binding_mut().unwrap();