diff --git a/iced_examples/counter_muti/src/main.rs b/iced_examples/counter_muti/src/main.rs index 211dec6..54b1c72 100644 --- a/iced_examples/counter_muti/src/main.rs +++ b/iced_examples/counter_muti/src/main.rs @@ -212,12 +212,13 @@ impl MultiApplication for Counter { Command::done(Message::NewLayerShell { settings: NewLayerShellSettings { size: Some((0, 20)), - exclusive_zone: None, + exclusive_zone: Some(20), anchor: Anchor::Top | Anchor::Right | Anchor::Left, layer: Layer::Top, margin: None, - keyboard_interactivity: KeyboardInteractivity::Exclusive, + keyboard_interactivity: KeyboardInteractivity::None, output_setting: LayerOutputSetting::ChosenOutput(output), + ..Default::default() }, info: WindowInfo::TopBar, }) @@ -234,7 +235,7 @@ impl MultiApplication for Counter { return button("close right").on_press(Message::Close(id)).into(); } if let Some(WindowInfo::TopBar) = self.id_info(id) { - return text("topbar").into(); + return text("hello here is topbar").into(); } if let Some(WindowInfo::PopUp) = self.id_info(id) { return container(button("close PopUp").on_press(Message::Close(id))) diff --git a/iced_wayland_subscriber/src/lib.rs b/iced_wayland_subscriber/src/lib.rs index c620773..0884774 100644 --- a/iced_wayland_subscriber/src/lib.rs +++ b/iced_wayland_subscriber/src/lib.rs @@ -1,6 +1,7 @@ use futures::SinkExt; use wayland_client::{ delegate_noop, + globals::{registry_queue_init, GlobalListContents}, protocol::{ wl_output::{self, WlOutput}, wl_registry, @@ -8,11 +9,30 @@ use wayland_client::{ Connection, Dispatch, Proxy, }; -use wayland_protocols::xdg::xdg_output::zv1::client::zxdg_output_manager_v1::ZxdgOutputManagerV1; +use wayland_protocols::xdg::xdg_output::zv1::client::{ + zxdg_output_manager_v1::ZxdgOutputManagerV1, zxdg_output_v1, +}; + +#[derive(Debug)] +struct BaseState; + +// so interesting, it is just need to invoke once, it just used to get the globals +impl Dispatch for BaseState { + fn event( + _state: &mut Self, + _proxy: &wl_registry::WlRegistry, + _event: ::Event, + _data: &GlobalListContents, + _conn: &Connection, + _qh: &wayland_client::QueueHandle, + ) { + } +} #[derive(Debug, Default)] struct SubscribeState { events: Vec, + padding_wloutputs: Vec, } impl Dispatch for SubscribeState { @@ -32,7 +52,7 @@ impl Dispatch for SubscribeState { } => { if interface == wl_output::WlOutput::interface().name { let output = proxy.bind::(name, version, qh, ()); - state.events.push(WaylandEvents::OutputInsert(output)); + state.padding_wloutputs.push(output); } } wl_registry::Event::GlobalRemove { .. } => {} @@ -40,27 +60,57 @@ impl Dispatch for SubscribeState { } } } +impl Dispatch for SubscribeState { + fn event( + state: &mut Self, + _proxy: &zxdg_output_v1::ZxdgOutputV1, + event: ::Event, + _data: &(), + _conn: &Connection, + _qhandle: &wayland_client::QueueHandle, + ) { + if let zxdg_output_v1::Event::Name { name } = event { + state.events.push(WaylandEvents::OutputInsert(name)); + } + } +} delegate_noop!(SubscribeState: ignore WlOutput); // output is need to place layer_shell, although here delegate_noop!(SubscribeState: ignore ZxdgOutputManagerV1); #[derive(Debug, Clone)] pub enum WaylandEvents { - OutputInsert(wl_output::WlOutput), + OutputInsert(String), } pub fn listen() -> iced::Subscription { iced::Subscription::run(|| { iced::stream::channel(100, |mut output| async move { let connection = Connection::connect_to_env().unwrap(); + let (globals, _) = registry_queue_init::(&connection).unwrap(); // We just need the + // global, the + // event_queue is + // not needed, we + // do not need + // BaseState after + let mut state = SubscribeState::default(); let mut event_queue = connection.new_event_queue::(); let qhandle = event_queue.handle(); let display = connection.display(); + let xdg_output_manager = globals + .bind::(&qhandle, 1..=3, ()) + .unwrap(); // b display.get_registry(&qhandle, ()); loop { event_queue.blocking_dispatch(&mut state).unwrap(); + let mut current_outputs = vec![]; + std::mem::swap(&mut current_outputs, &mut state.padding_wloutputs); + for output in current_outputs { + xdg_output_manager.get_xdg_output(&output, &qhandle, ()); + } + let mut current_events = vec![]; std::mem::swap(&mut current_events, &mut state.events); for event in current_events { diff --git a/layershellev/src/events.rs b/layershellev/src/events.rs index ea660db..9f0b35b 100644 --- a/layershellev/src/events.rs +++ b/layershellev/src/events.rs @@ -8,7 +8,7 @@ use wayland_client::{ protocol::{ wl_buffer::WlBuffer, wl_compositor::WlCompositor, - wl_output::{self, WlOutput}, + wl_output::WlOutput, wl_pointer::{self, ButtonState, WlPointer}, wl_shm::WlShm, }, @@ -71,7 +71,7 @@ pub enum LayerEvent<'a, T, Message> { /// This allow the new layershell can be selected on target output #[derive(Debug, Clone, PartialEq, Eq)] pub enum LayerOutputSetting { - ChosenOutput(wl_output::WlOutput), + ChosenOutput(String), FollowLastOutput, None, } diff --git a/layershellev/src/lib.rs b/layershellev/src/lib.rs index 624428f..88305cc 100644 --- a/layershellev/src/lib.rs +++ b/layershellev/src/lib.rs @@ -1663,31 +1663,6 @@ impl Dispatch for WindowState { _conn: &Connection, _qhandle: &QueueHandle, ) { - if state.is_with_target() && !state.init_finished { - let Some((_, xdg_info)) = state - .xdg_info_cache - .iter_mut() - .find(|(_, info)| info.zxdgoutput == *proxy) - else { - return; - }; - match event { - zxdg_output_v1::Event::LogicalSize { width, height } => { - xdg_info.logical_size = (width, height); - } - zxdg_output_v1::Event::LogicalPosition { x, y } => { - xdg_info.position = (x, y); - } - zxdg_output_v1::Event::Name { name } => { - xdg_info.name = name; - } - zxdg_output_v1::Event::Description { description } => { - xdg_info.description = description; - } - _ => {} - }; - return; - } let Some(index) = state.units.iter().position(|info| { info.zxdgoutput .as_ref() @@ -1695,23 +1670,34 @@ impl Dispatch for WindowState { }) else { return; }; + let Some((_, xdg_info_cached)) = state + .xdg_info_cache + .iter_mut() + .find(|(_, info)| info.zxdgoutput == *proxy) + else { + return; + }; let info = &mut state.units[index]; let xdg_info = info.zxdgoutput.as_mut().unwrap(); let change_type = match event { zxdg_output_v1::Event::LogicalSize { width, height } => { xdg_info.logical_size = (width, height); + xdg_info_cached.logical_size = (width, height); XdgInfoChangedType::Size } zxdg_output_v1::Event::LogicalPosition { x, y } => { xdg_info.position = (x, y); + xdg_info_cached.position = (x, y); XdgInfoChangedType::Position } zxdg_output_v1::Event::Name { name } => { - xdg_info.name = name; + xdg_info.name = name.clone(); + xdg_info_cached.name = name; XdgInfoChangedType::Name } zxdg_output_v1::Event::Description { description } => { - xdg_info.description = description; + xdg_info.description = description.clone(); + xdg_info_cached.description = description; XdgInfoChangedType::Description } _ => { @@ -1860,7 +1846,6 @@ impl WindowState { // clear binded_output_name, it is not used anymore } - self.xdg_info_cache.clear(); let binded_output = output.as_ref().map(|(output, _)| output); let binded_xdginfo = output.as_ref().map(|(_, xdginfo)| xdginfo); @@ -2451,7 +2436,11 @@ impl WindowState { events::LayerOutputSetting::FollowLastOutput => { self.last_wloutput.clone() } - events::LayerOutputSetting::ChosenOutput(output) => Some(output), + events::LayerOutputSetting::ChosenOutput(output) => self + .xdg_info_cache + .iter() + .find(|(_, xdg_output_info)| xdg_output_info.name == output) + .map(|(output, _)| output.clone()), }; let wl_surface = wmcompositer.create_surface(&qh, ()); // and create a surface. if two or more,