diff --git a/iced_examples/counter_muti/src/main.rs b/iced_examples/counter_muti/src/main.rs index 9cbaaaf..5e5f76d 100644 --- a/iced_examples/counter_muti/src/main.rs +++ b/iced_examples/counter_muti/src/main.rs @@ -1,7 +1,9 @@ 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::actions::{ + LayershellCustomActions, LayershellCustomActionsWithId, LayershellCustomActionsWithInfo, +}; use iced_layershell::reexport::Anchor; use iced_layershell::settings::{LayerShellSettings, Settings}; use iced_layershell::MultiApplication; @@ -85,7 +87,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, @@ -94,7 +96,7 @@ impl MultiApplication for Counter { .into(), ), Command::single( - LayershellCustomActionsWithId( + LayershellCustomActionsWithId::new( id, LayershellCustomActions::SizeChange((400, 0)), ) @@ -103,7 +105,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, @@ -112,7 +114,7 @@ impl MultiApplication for Counter { .into(), ), Command::single( - LayershellCustomActionsWithId( + LayershellCustomActionsWithId::new( id, LayershellCustomActions::SizeChange((400, 0)), ) @@ -121,7 +123,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, @@ -130,25 +132,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)), ) @@ -160,7 +162,6 @@ impl MultiApplication for Counter { } fn view(&self, id: iced::window::Id) -> Element { - //println!("{:?}, {}", _id, self.value); let center = column![ button("Increment").on_press(Message::IncrementPressed), text(self.value).size(50), diff --git a/iced_layershell/src/actions.rs b/iced_layershell/src/actions.rs index fb056ab..9bfc0a2 100644 --- a/iced_layershell/src/actions.rs +++ b/iced_layershell/src/actions.rs @@ -3,42 +3,64 @@ 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 }, + NewLayerShell((NewLayerShellSettings, INFO)), + 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, + pub Option, + pub LayershellCustomActionsWithInfo, +); -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..cd54a32 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, @@ -147,7 +147,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(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..e6ee4fb 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::WindowState<(), ()>) -> 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..563b560 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, @@ -78,23 +80,28 @@ pub enum IcedLayerEvent { #[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 { - fn from(value: &DispatchMessage) -> Self { +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 4496df6..2407157 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; @@ -243,6 +244,8 @@ pub trait MultiApplication: Sized { fn id_info(&self, _id: iced_core::window::Id) -> Option { None } + + fn set_id_info(&mut self, _id: iced_core::window::Id, _info: Self::WindowInfo) {} /// Handles a __message__ and updates the state of the [`Application`]. /// /// This is where you define your __update logic__. All the __messages__, @@ -313,6 +316,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 { @@ -392,4 +396,8 @@ where fn id_info(&self, id: iced_core::window::Id) -> Option { 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) + } } diff --git a/iced_layershell/src/multi_window.rs b/iced_layershell/src/multi_window.rs index e27dfe9..26b86a2 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, @@ -79,6 +79,7 @@ where } fn id_info(&self, _id: iced_core::window::Id) -> Option; + fn set_id_info(&mut self, _id: iced_core::window::Id, info: Self::WindowInfo); /// Returns the current [`Theme`] of the [`Application`]. fn theme(&self) -> Self::Theme; @@ -137,6 +138,7 @@ where E: Executor + 'static, C: Compositor + 'static, A::Theme: StyleSheet, + ::WindowInfo: Clone, { use futures::task; use futures::Future; @@ -160,17 +162,18 @@ where runtime.enter(|| A::new(flags)) }; - let ev: WindowState<()> = layershellev::WindowState::new(&application.namespace()) - .with_single(false) - .with_use_display_handle(true) - .with_option_size(settings.layer_settings.size) - .with_layer(settings.layer_settings.layer) - .with_anchor(settings.layer_settings.anchor) - .with_exclusize_zone(settings.layer_settings.exclusize_zone) - .with_margin(settings.layer_settings.margins) - .with_keyboard_interacivity(settings.layer_settings.keyboard_interactivity) - .build() - .unwrap(); + let ev: WindowState<(), A::WindowInfo> = + layershellev::WindowState::new(&application.namespace()) + .with_single(false) + .with_use_display_handle(true) + .with_option_size(settings.layer_settings.size) + .with_layer(settings.layer_settings.layer) + .with_anchor(settings.layer_settings.anchor) + .with_exclusize_zone(settings.layer_settings.exclusize_zone) + .with_margin(settings.layer_settings.margins) + .with_keyboard_interacivity(settings.layer_settings.keyboard_interactivity) + .build() + .unwrap(); let window = Arc::new(ev.gen_main_wrapper()); let mut compositor = C::new(compositor_settings, window.clone())?; @@ -185,8 +188,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, @@ -236,7 +240,12 @@ where } LayerEvent::RequestMessages(message) => 'outside: { match message { - DispatchMessage::RequestRefresh { width, height } => { + DispatchMessage::RequestRefresh { + width, + height, + is_created, + info, + } => { event_sender .start_send(MultiWindowIcedLayerEvent( id, @@ -244,6 +253,8 @@ where width: *width, height: *height, wrapper: ev.get_unit(index.unwrap()).gen_wrapper(), + is_created: *is_created, + info: info.clone(), }, )) .expect("Cannot send"); @@ -282,21 +293,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, } => { @@ -316,6 +329,18 @@ where ) .ok(); } + LayershellCustomActionsWithInfo::NewLayerShell(( + settings, + info, + )) => { + return ReturnData::NewLayerShell(( + settings, + Some(info), + )); + } + LayershellCustomActionsWithInfo::RemoveLayerShell(_) => { + return ReturnData::RemoveLayershell(option_id.unwrap()) + } } } } @@ -357,8 +382,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 @@ -366,6 +393,7 @@ async fn run_instance( E: Executor + 'static, C: Compositor + 'static, A::Theme: StyleSheet, + ::WindowInfo: Clone, { use iced::window; use iced_core::mouse; @@ -424,6 +452,8 @@ async fn run_instance( width, height, wrapper, + is_created, + info, }, ) => { let layerid = wrapper.id(); @@ -537,6 +567,21 @@ async fn run_instance( .ok(); debug.render_finished(); + + if is_created { + let mut 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 { @@ -705,13 +750,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, + ::WindowInfo: Clone + 'static, { for message in messages.drain(..) { debug.log_message(&message); @@ -745,7 +791,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, @@ -757,6 +803,7 @@ pub(crate) fn run_command( C: Compositor + 'static, A::Theme: StyleSheet, A::Message: 'static, + ::WindowInfo: Clone + 'static, { use iced_core::widget::operation; use iced_runtime::command; @@ -842,9 +889,21 @@ 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::>() + { + let option_id = if let LayershellCustomActionsWithInfo::RemoveLayerShell(id) = action.1 + { + window_manager.get_iced_id(id) + } else { + None + }; if let Some(id) = window_manager.get_iced_id(action.0) { - customactions.push(LayershellCustomActionsWithIdInner(id, action.1)); + customactions.push(LayershellCustomActionsWithIdInner( + id, + option_id, + action.1.clone(), + )); } } } diff --git a/layershellev/examples/simplelayer.rs b/layershellev/examples/simplelayer.rs index fe1ead3..a297ad1 100644 --- a/layershellev/examples/simplelayer.rs +++ b/layershellev/examples/simplelayer.rs @@ -6,7 +6,7 @@ use layershellev::reexport::*; use layershellev::*; fn main() { - let ev: WindowState<()> = WindowState::new("Hello") + let ev: WindowState<(), ()> = WindowState::new("Hello") .with_single(false) .with_size((0, 400)) .with_layer(Layer::Top) @@ -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..9e019a2 100644 --- a/layershellev/src/events.rs +++ b/layershellev/src/events.rs @@ -1,3 +1,7 @@ +use wayland_protocols_wlr::layer_shell::v1::client::{ + zwlr_layer_shell_v1::Layer, zwlr_layer_surface_v1::Anchor, +}; + use wayland_client::{ globals::GlobalList, protocol::{ @@ -9,7 +13,7 @@ use wayland_client::{ QueueHandle, WEnum, }; -use crate::xkb_keyboard::KeyEvent; +use crate::{id, xkb_keyboard::KeyEvent}; use crate::keyboard::ModifiersState; @@ -30,22 +34,31 @@ 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: Debug, Message, INFO: Clone> { InitRequest, XdgInfoChanged(XdgInfoChangedType), - BindProvide(&'a GlobalList, &'a QueueHandle>), + BindProvide(&'a GlobalList, &'a QueueHandle>), RequestBuffer( &'a mut File, &'a WlShm, - &'a QueueHandle>, + &'a QueueHandle>, u32, u32, ), - RequestMessages(&'a DispatchMessage), + RequestMessages(&'a DispatchMessage), NormalDispatch, UserEvent(Message), } +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub struct NewLayerShellSettings { + pub size: Option<(u32, u32)>, + pub layer: Layer, + pub anchor: Anchor, + pub exclude_zone: Option, + pub margin: Option<(i32, i32, i32, i32)>, +} + /// 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 +73,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, } @@ -97,7 +112,7 @@ pub struct AxisScroll { #[allow(unused)] #[derive(Debug, Clone)] -pub(crate) enum DispatchMessageInner { +pub(crate) enum DispatchMessageInner { NewDisplay(WlOutput), MouseButton { state: WEnum, @@ -164,6 +179,8 @@ pub(crate) enum DispatchMessageInner { RequestRefresh { width: u32, height: u32, + is_created: bool, + info: Option, }, PrefredScale(u32), XdgInfoChanged(XdgInfoChangedType), @@ -171,7 +188,7 @@ pub(crate) enum DispatchMessageInner { /// This tell the DispatchMessage by dispatch #[derive(Debug)] -pub enum DispatchMessage { +pub enum DispatchMessage { /// forward the event of wayland-mouse MouseButton { state: WEnum, @@ -241,13 +258,15 @@ pub enum DispatchMessage { RequestRefresh { width: u32, height: u32, + is_created: bool, + info: Option, }, /// fractal scale handle PrefredScale(u32), } -impl From for DispatchMessage { - fn from(val: DispatchMessageInner) -> Self { +impl From> for DispatchMessage { + fn from(val: DispatchMessageInner) -> Self { match val { DispatchMessageInner::NewDisplay(_) => unimplemented!(), DispatchMessageInner::MouseButton { @@ -301,9 +320,17 @@ 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, + info, + } => DispatchMessage::RequestRefresh { + width, + height, + is_created, + info, + }, DispatchMessageInner::Axis { time, horizontal, diff --git a/layershellev/src/lib.rs b/layershellev/src/lib.rs index a1648e2..b55a3f8 100644 --- a/layershellev/src/lib.rs +++ b/layershellev/src/lib.rs @@ -11,7 +11,7 @@ //! use layershellev::*; //! //! fn main() { -//! let mut ev: WindowState<()> = WindowState::new("Hello") +//! let mut ev: WindowState<(), ()> = WindowState::new("Hello") //! .with_single(false) //! .with_size((0, 400)) //! .with_layer(Layer::Top) @@ -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; @@ -284,7 +285,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, @@ -294,9 +295,11 @@ pub struct WindowStateUnit { zxdgoutput: Option, fractional_scale: Option, binding: Option, + becreated: bool, + info: Option, } -impl WindowStateUnit { +impl WindowStateUnit { pub fn id(&self) -> id::Id { self.id } @@ -308,7 +311,7 @@ impl WindowStateUnit { } } } -impl WindowStateUnit { +impl WindowStateUnit { #[inline] pub fn raw_window_handle_rwh_06(&self) -> Result { Ok(rwh_06::WaylandWindowHandle::new({ @@ -330,7 +333,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 +343,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 +354,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 +365,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 +374,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 @@ -440,15 +443,15 @@ 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, - units: Vec>, - message: Vec<(Option, DispatchMessageInner)>, + units: Vec>, + message: Vec<(Option, DispatchMessageInner)>, connection: Option, - event_queue: Option>>, + event_queue: Option>>, wl_compositor: Option, xdg_output_manager: Option, shm: Option, @@ -478,18 +481,18 @@ pub struct WindowState { loop_handler: Option>, } -impl WindowState { +impl WindowState { // return the first window // I will use it in iced - pub fn main_window(&self) -> &WindowStateUnit { + pub fn main_window(&self) -> &WindowStateUnit { &self.units[0] } - pub fn get_window_with_id(&self, id: id::Id) -> Option<&WindowStateUnit> { + pub fn get_window_with_id(&self, id: id::Id) -> Option<&WindowStateUnit> { self.units.iter().find(|w| w.id() == id) } // return all windows - pub fn windows(&self) -> &Vec> { + pub fn windows(&self) -> &Vec> { &self.units } } @@ -507,7 +510,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 +531,7 @@ impl WindowState { self.touch.as_ref() } } -impl WindowState { +impl WindowState { pub fn gen_main_wrapper(&self) -> WindowWrapper { self.main_window().gen_wrapper() } @@ -575,7 +578,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 +648,7 @@ impl WindowState { } } -impl Default for WindowState { +impl Default for WindowState { fn default() -> Self { Self { outputs: Vec::new(), @@ -683,7 +686,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); @@ -700,17 +703,17 @@ impl WindowState { } /// get the unit with the index returned by eventloop - pub fn get_unit(&mut self, index: usize) -> &mut WindowStateUnit { + pub fn get_unit(&mut self, index: usize) -> &mut WindowStateUnit { &mut self.units[index] } /// it return the iter of units. you can do loop with it - pub fn get_unit_iter(&self) -> impl Iterator> { + pub fn get_unit_iter(&self) -> impl Iterator> { self.units.iter() } /// it return the mut iter of units. you can do loop with it - pub fn get_unit_iter_mut(&mut self) -> impl Iterator> { + pub fn get_unit_iter_mut(&mut self) -> impl Iterator> { self.units.iter_mut() } @@ -727,7 +730,9 @@ impl WindowState { } } -impl Dispatch for WindowState { +impl Dispatch + for WindowState +{ fn event( state: &mut Self, proxy: &wl_registry::WlRegistry, @@ -760,7 +765,7 @@ impl Dispatch for WindowState Dispatch for WindowState { +impl Dispatch for WindowState { fn event( state: &mut Self, seat: &wl_seat::WlSeat, @@ -787,7 +792,7 @@ impl Dispatch for WindowState { } } -impl Dispatch for WindowState { +impl Dispatch for WindowState { fn event( state: &mut Self, _proxy: &wl_keyboard::WlKeyboard, @@ -863,7 +868,7 @@ impl Dispatch for WindowState { } } -impl Dispatch for WindowState { +impl Dispatch for WindowState { fn event( state: &mut Self, _proxy: &wl_touch::WlTouch, @@ -901,7 +906,7 @@ impl Dispatch for WindowState { } } -impl Dispatch for WindowState { +impl Dispatch for WindowState { fn event( state: &mut Self, pointer: &wl_pointer::WlPointer, @@ -1067,7 +1072,9 @@ 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 +1108,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 +1146,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 +1170,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 @@ -1193,7 +1200,7 @@ impl WindowState { // BaseState after // this anymore - let mut event_queue = connection.new_event_queue::>(); + let mut event_queue = connection.new_event_queue::>(); let qh = event_queue.handle(); let wmcompositer = globals.bind::(&qh, 1..=5, ())?; // so the first @@ -1278,6 +1285,8 @@ impl WindowState { zxdgoutput: None, fractional_scale, binding: None, + becreated: false, + info: None, }); } else { let displays = self.outputs.clone(); @@ -1331,6 +1340,8 @@ impl WindowState { zxdgoutput: Some(ZxdgOutputInfo::new(zxdgoutput)), fractional_scale, binding: None, + becreated: false, + info: None, }); } self.message.clear(); @@ -1363,7 +1374,11 @@ 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,11 @@ 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 +1411,11 @@ 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 +1481,8 @@ impl WindowState { LayerEvent::RequestMessages(&DispatchMessage::RequestRefresh { width: *width, height: *height, + is_created: self.units[index].becreated, + info: self.units[index].info.clone(), }), &mut self, Some(index), @@ -1530,11 +1555,13 @@ impl WindowState { zxdgoutput: Some(ZxdgOutputInfo::new(zxdgoutput)), fractional_scale, binding: None, + becreated: false, + info: None, }); } _ => { let (index_message, msg) = msg; - let msg: DispatchMessage = msg.clone().into(); + let msg: DispatchMessage = msg.clone().into(); match event_handler( LayerEvent::RequestMessages(&msg), &mut self, @@ -1548,6 +1575,8 @@ impl WindowState { &DispatchMessage::RequestRefresh { width: unit.size.0, height: unit.size.1, + is_created: unit.becreated, + info: unit.info.clone(), }, ), &mut self, @@ -1567,6 +1596,8 @@ impl WindowState { &DispatchMessage::RequestRefresh { width: unit.size.0, height: unit.size.1, + is_created: unit.becreated, + info: unit.info.clone(), }, ), &mut self, @@ -1660,6 +1691,8 @@ impl WindowState { LayerEvent::RequestMessages(&DispatchMessage::RequestRefresh { width: unit.size.0, height: unit.size.1, + is_created: unit.becreated, + info: unit.info.clone(), }), &mut self, Some(index), @@ -1677,6 +1710,8 @@ impl WindowState { LayerEvent::RequestMessages(&DispatchMessage::RequestRefresh { width: unit.size.0, height: unit.size.1, + is_created: unit.becreated, + info: unit.info.clone(), }), &mut self, Some(*index), @@ -1715,10 +1750,89 @@ impl WindowState { cursor_surface.commit(); } } + ReturnData::NewLayerShell(( + NewLayerShellSettings { + size, + layer, + anchor, + exclude_zone: exclusive_zone, + margin, + }, + info, + )) => { + if self.is_single { + continue; + } + 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, + None, + layer, + self.namespace.clone(), + &qh, + (), + ); + layer.set_anchor(anchor); + layer.set_keyboard_interactivity(self.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, + binding: None, + becreated: false, + info, + }); + } + ReturnData::RemoveLayershell(id) => { + let Some(index) = self + .units + .iter() + .position(|unit| unit.id == id && unit.becreated) + else { + continue; + }; + 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/starcolorkeyboard/src/main.rs b/starcolorkeyboard/src/main.rs index 003f6d8..27ffbc4 100644 --- a/starcolorkeyboard/src/main.rs +++ b/starcolorkeyboard/src/main.rs @@ -81,7 +81,7 @@ pub fn get_keymap_as_file() -> (File, u32) { } fn main() { - let ev: WindowState = WindowState::new("precure") + let ev: WindowState = WindowState::new("precure") .with_single(false) .with_size((0, 300)) .with_layer(Layer::Top) @@ -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();