diff --git a/src/shell/mod.rs b/src/shell/mod.rs index e9022c67..2f10579c 100644 --- a/src/shell/mod.rs +++ b/src/shell/mod.rs @@ -10,7 +10,10 @@ use std::{ }; use wayland_backend::server::ClientId; -use crate::wayland::{handlers::data_device, protocols::workspace::WorkspaceCapabilities}; +use crate::wayland::{ + handlers::data_device::{self, get_dnd_icon}, + protocols::workspace::WorkspaceCapabilities, +}; use cosmic_comp_config::{ workspace::{WorkspaceLayout, WorkspaceMode}, TileBehavior, @@ -1579,13 +1582,59 @@ impl Shell { .refresh(xdg_activation_state) } - pub fn visible_output_for_surface(&self, surface: &WlSurface) -> Option<&Output> { + pub fn visible_output_for_surface(&self, surface: &WlSurface) -> Option { if let Some(session_lock) = &self.session_lock { return session_lock .surfaces .iter() .find(|(_, v)| v.wl_surface() == surface) - .map(|(k, _)| k); + .map(|(k, _)| k.clone()); + } + + if let Some(output) = self.seats.iter().find_map(|seat| { + let cursor_status = seat + .user_data() + .get::>() + .map(|lock| { + let mut cursor_status = lock.lock().unwrap(); + if let CursorImageStatus::Surface(ref surface) = *cursor_status { + if !surface.alive() { + *cursor_status = CursorImageStatus::default_named(); + } + } + cursor_status.clone() + }) + .unwrap_or(CursorImageStatus::default_named()); + + // cursor + if let CursorImageStatus::Surface(wl_surface) = cursor_status { + if &wl_surface == surface { + return Some(seat.active_output()); + } + } + + //dnd + if let Some(dnd_icon) = get_dnd_icon(seat) { + if &dnd_icon.surface == surface { + return Some(seat.active_output()); + } + } + + // grabs + if let Some(move_grab) = seat.user_data().get::() { + if let Some(grab_state) = move_grab.lock().unwrap().as_ref() { + if grab_state + .element() + .has_surface(surface, WindowSurfaceType::ALL) + { + return Some(seat.active_output()); + } + } + } + + None + }) { + return Some(output); } self.outputs() @@ -1639,6 +1688,7 @@ impl Shell { .any(|e| e.has_surface(surface, WindowSurfaceType::ALL)) }) }) + .cloned() } pub fn workspace_for_surface(&self, surface: &WlSurface) -> Option<(WorkspaceHandle, Output)> { diff --git a/src/state.rs b/src/state.rs index fc2ba06e..158b1d18 100644 --- a/src/state.rs +++ b/src/state.rs @@ -11,18 +11,20 @@ use crate::{ input::{gestures::GestureState, PointerFocusState}, shell::{grabs::SeatMoveGrabState, CosmicSurface, SeatExt, Shell}, utils::prelude::OutputExt, - wayland::handlers::screencopy::SessionHolder, - wayland::protocols::{ - atspi::AtspiState, - drm::WlDrmState, - image_source::ImageSourceState, - output_configuration::OutputConfigurationState, - output_power::OutputPowerState, - overlap_notify::OverlapNotifyState, - screencopy::ScreencopyState, - toplevel_info::ToplevelInfoState, - toplevel_management::{ManagementCapabilities, ToplevelManagementState}, - workspace::{WorkspaceClientState, WorkspaceState, WorkspaceUpdateGuard}, + wayland::{ + handlers::{data_device::get_dnd_icon, screencopy::SessionHolder}, + protocols::{ + atspi::AtspiState, + drm::WlDrmState, + image_source::ImageSourceState, + output_configuration::OutputConfigurationState, + output_power::OutputPowerState, + overlap_notify::OverlapNotifyState, + screencopy::ScreencopyState, + toplevel_info::ToplevelInfoState, + toplevel_management::{ManagementCapabilities, ToplevelManagementState}, + workspace::{WorkspaceClientState, WorkspaceState, WorkspaceUpdateGuard}, + }, }, xwayland::XWaylandState, }; @@ -722,6 +724,11 @@ impl Common { with_surfaces_surface_tree(&wl_surface, processor); } + //dnd + if let Some(dnd_icon) = get_dnd_icon(seat) { + with_surfaces_surface_tree(&dnd_icon.surface, processor); + } + // grabs if let Some(move_grab) = seat.user_data().get::() { if let Some(grab_state) = move_grab.lock().unwrap().as_ref() { @@ -807,6 +814,64 @@ impl Common { .iter() .filter(|seat| &seat.active_output() == output) { + let cursor_status = seat + .user_data() + .get::>() + .map(|lock| { + let mut cursor_status = lock.lock().unwrap(); + if let CursorImageStatus::Surface(ref surface) = *cursor_status { + if !surface.alive() { + *cursor_status = CursorImageStatus::default_named(); + } + } + cursor_status.clone() + }) + .unwrap_or(CursorImageStatus::default_named()); + + // cursor ... + if let CursorImageStatus::Surface(wl_surface) = cursor_status { + if let Some(feedback) = + advertised_node_for_surface(&wl_surface, &self.display_handle) + .and_then(|source| dmabuf_feedback(source)) + { + send_dmabuf_feedback_surface_tree( + &wl_surface, + output, + surface_primary_scanout_output, + |surface, _| { + select_dmabuf_feedback( + surface, + render_element_states, + &feedback.render_feedback, + &feedback.scanout_feedback, + ) + }, + ); + } + } + + //dnd + if let Some(dnd_icon) = get_dnd_icon(seat) { + if let Some(feedback) = + advertised_node_for_surface(&dnd_icon.surface, &self.display_handle) + .and_then(|source| dmabuf_feedback(source)) + { + send_dmabuf_feedback_surface_tree( + &dnd_icon.surface, + output, + surface_primary_scanout_output, + |surface, _| { + select_dmabuf_feedback( + surface, + render_element_states, + &feedback.render_feedback, + &feedback.scanout_feedback, + ) + }, + ) + } + } + if let Some(move_grab) = seat.user_data().get::() { if let Some(grab_state) = move_grab.lock().unwrap().as_ref() { for (window, _) in grab_state.element().windows() { @@ -1012,6 +1077,16 @@ impl Common { ) } + if let Some(dnd_icon) = get_dnd_icon(seat) { + send_frames_surface_tree( + &dnd_icon.surface, + output, + time, + Some(Duration::ZERO), + should_send, + ) + } + if let Some(move_grab) = seat.user_data().get::() { if let Some(grab_state) = move_grab.lock().unwrap().as_ref() { for (window, _) in grab_state.element().windows() { diff --git a/src/wayland/handlers/fractional_scale.rs b/src/wayland/handlers/fractional_scale.rs index b2cf0a08..7d71f731 100644 --- a/src/wayland/handlers/fractional_scale.rs +++ b/src/wayland/handlers/fractional_scale.rs @@ -44,7 +44,6 @@ impl FractionalScaleHandler for State { .read() .unwrap() .visible_output_for_surface(&surface) - .cloned() }) }) .unwrap_or_else(|| { diff --git a/src/wayland/handlers/xdg_shell/mod.rs b/src/wayland/handlers/xdg_shell/mod.rs index f3a4e5fe..3701dede 100644 --- a/src/wayland/handlers/xdg_shell/mod.rs +++ b/src/wayland/handlers/xdg_shell/mod.rs @@ -389,9 +389,7 @@ impl XdgShellHandler for State { &mut self.common.toplevel_info_state, ); - let output = shell - .visible_output_for_surface(surface.wl_surface()) - .cloned(); + let output = shell.visible_output_for_surface(surface.wl_surface()); if let Some(output) = output.as_ref() { shell.refresh_active_space(output, &self.common.xdg_activation_state); } diff --git a/src/xwayland.rs b/src/xwayland.rs index bec87771..d2556afd 100644 --- a/src/xwayland.rs +++ b/src/xwayland.rs @@ -420,7 +420,6 @@ impl XwmHandler for State { shell .visible_output_for_surface(&wl_surface) .into_iter() - .cloned() .collect::>() } else { shell.outputs().cloned().collect::>()