diff --git a/src/backend/kms/surface/mod.rs b/src/backend/kms/surface/mod.rs index 1a51816e..33c08be6 100644 --- a/src/backend/kms/surface/mod.rs +++ b/src/backend/kms/surface/mod.rs @@ -3,11 +3,11 @@ use crate::{ backend::render::{ element::{CosmicElement, DamageElement}, - init_shaders, workspace_elements, CursorMode, GlMultiRenderer, CLEAR_COLOR, + init_shaders, workspace_elements, CursorMode, ElementFilter, GlMultiRenderer, CLEAR_COLOR, }, shell::Shell, state::SurfaceDmabufFeedback, - utils::prelude::*, + utils::{prelude::*, quirks::workspace_overview_is_open}, wayland::{ handlers::screencopy::{submit_buffer, FrameHolder, SessionData}, protocols::screencopy::{ @@ -869,6 +869,12 @@ impl SurfaceThreadState { std::mem::drop(shell); + let element_filter = if workspace_overview_is_open(output) { + ElementFilter::LayerShellOnly + } else { + ElementFilter::All + }; + workspace_elements( Some(&render_node), &mut renderer, @@ -878,7 +884,7 @@ impl SurfaceThreadState { previous_workspace, workspace, CursorMode::All, - false, + element_filter, #[cfg(not(feature = "debug"))] None, #[cfg(feature = "debug")] diff --git a/src/backend/render/mod.rs b/src/backend/render/mod.rs index 2674a938..7257bf07 100644 --- a/src/backend/render/mod.rs +++ b/src/backend/render/mod.rs @@ -20,11 +20,14 @@ use crate::{ CosmicMappedRenderElement, OverviewMode, SeatExt, SessionLock, Trigger, WorkspaceDelta, WorkspaceRenderElement, }, - utils::prelude::*, + utils::{ + prelude::*, + quirks::{workspace_overview_is_open, WORKSPACE_OVERVIEW_NAMESPACE}, + }, wayland::{ handlers::{ data_device::get_dnd_icon, - screencopy::{render_session, FrameHolder, SessionData, WORKSPACE_OVERVIEW_NAMESPACE}, + screencopy::{render_session, FrameHolder, SessionData}, }, protocols::workspace::WorkspaceHandle, }, @@ -58,7 +61,7 @@ use smithay::{ desktop::{layer_map_for_output, PopupManager}, input::Seat, output::{Output, OutputNoMode}, - utils::{IsAlive, Logical, Monotonic, Point, Rectangle, Scale, Time, Transform}, + utils::{IsAlive, Logical, Monotonic, Physical, Point, Rectangle, Scale, Time, Transform}, wayland::{ dmabuf::get_dmabuf, shell::wlr_layer::Layer, @@ -464,6 +467,67 @@ where #[cfg(not(feature = "debug"))] pub type EguiState = (); +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum ElementFilter { + All, + ExcludeWorkspaceOverview, + LayerShellOnly, +} + +#[derive(Clone, Debug)] +pub struct SplitRenderElements { + pub w_elements: Vec, + pub p_elements: Vec, +} + +impl Default for SplitRenderElements { + fn default() -> Self { + Self { + w_elements: Vec::new(), + p_elements: Vec::new(), + } + } +} + +impl SplitRenderElements { + pub fn extend(&mut self, other: Self) { + self.w_elements.extend(other.w_elements); + self.p_elements.extend(other.p_elements); + } + + pub fn extend_map E>(&mut self, other: SplitRenderElements, mut f: F) { + self.w_elements + .extend(other.w_elements.into_iter().map(&mut f)); + self.p_elements + .extend(other.p_elements.into_iter().map(&mut f)); + } + + pub fn join(mut self) -> Vec { + self.p_elements.extend(self.w_elements); + self.p_elements + } +} + +impl SplitRenderElements> +where + R: Renderer + ImportAll + ImportMem + AsGlowRenderer, + CosmicMappedRenderElement: RenderElement, +{ + fn extend_from_workspace_elements>>( + &mut self, + other: SplitRenderElements, + offset: Point, + ) { + self.extend_map(other, |element| { + CosmicElement::Workspace(RelocateRenderElement::from_element( + element.into(), + offset, + Relocate::Relative, + )) + }) + } +} + #[profiling::function] pub fn workspace_elements( _gpu: Option<&DrmNode>, @@ -474,7 +538,7 @@ pub fn workspace_elements( previous: Option<(WorkspaceHandle, usize, WorkspaceDelta)>, current: (WorkspaceHandle, usize), cursor_mode: CursorMode, - exclude_workspace_overview: bool, + element_filter: ElementFilter, _fps: Option<(&EguiState, &Timings)>, ) -> Result>, RenderError> where @@ -484,6 +548,8 @@ where CosmicMappedRenderElement: RenderElement, WorkspaceRenderElement: RenderElement, { + let mut elements = SplitRenderElements::default(); + let theme = shell.read().unwrap().theme().clone(); let seats = shell .read() @@ -493,15 +559,15 @@ where .cloned() .collect::>(); - let mut elements = cursor_elements( + elements.p_elements.extend(cursor_elements( renderer, seats.iter(), &theme, now, output, cursor_mode, - exclude_workspace_overview, - ); + element_filter == ElementFilter::ExcludeWorkspaceOverview, + )); #[cfg(feature = "debug")] { @@ -525,7 +591,7 @@ where ) .map_err(FromGlesError::from_gles_error) .map_err(RenderError::Rendering)?; - elements.push(fps_overlay.into()); + elements.p_elements.push(fps_overlay.into()); } } @@ -533,12 +599,12 @@ where // If session locked, only show session lock surfaces if let Some(session_lock) = &shell.session_lock { - elements.extend( + elements.p_elements.extend( session_lock_elements(renderer, output, session_lock) .into_iter() .map(|x| WorkspaceRenderElement::from(x).into()), ); - return Ok(elements); + return Ok(elements.join()); } let theme = theme.cosmic(); @@ -586,20 +652,21 @@ where .as_ref() .filter(|f| !f.is_animating()) .is_some(); - let (overlay_elements, overlay_popups) = - split_layer_elements(renderer, output, Layer::Overlay, exclude_workspace_overview); + let overlay_elements = split_layer_elements(renderer, output, Layer::Overlay, element_filter); // overlay is above everything - elements.extend(overlay_popups.into_iter().map(Into::into)); - elements.extend(overlay_elements.into_iter().map(Into::into)); - - let mut window_elements = if !has_fullscreen { - let (top_elements, top_popups) = - split_layer_elements(renderer, output, Layer::Top, exclude_workspace_overview); - elements.extend(top_popups.into_iter().map(Into::into)); - top_elements.into_iter().map(Into::into).collect() - } else { - Vec::new() + elements + .p_elements + .extend(overlay_elements.p_elements.into_iter().map(Into::into)); + elements + .p_elements + .extend(overlay_elements.w_elements.into_iter().map(Into::into)); + + if !has_fullscreen { + elements.extend_from_workspace_elements( + split_layer_elements(renderer, output, Layer::Top, element_filter), + (0, 0).into(), + ); }; let active_hint = if shell.active_hint { @@ -611,38 +678,34 @@ where // overlay redirect windows // they need to be over sticky windows, because they could be popups of sticky windows, // and we can't differenciate that. - elements.extend( - shell - .override_redirect_windows - .iter() - .filter(|or| { - (*or) - .geometry() - .as_global() - .intersection(workspace.output.geometry()) - .is_some() - }) - .flat_map(|or| { - AsRenderElements::::render_elements::>( - or, - renderer, - (or.geometry().loc - workspace.output.geometry().loc.as_logical()) - .to_physical_precise_round(output_scale), - Scale::from(output_scale), - 1.0, - ) - }) - .map(|p_element| { - CosmicElement::Workspace(RelocateRenderElement::from_element( - p_element, - (0, 0), - Relocate::Relative, - )) - }), - ); + if element_filter != ElementFilter::LayerShellOnly { + elements.p_elements.extend( + shell + .override_redirect_windows + .iter() + .filter(|or| { + (*or) + .geometry() + .as_global() + .intersection(workspace.output.geometry()) + .is_some() + }) + .flat_map(|or| { + AsRenderElements::::render_elements::>( + or, + renderer, + (or.geometry().loc - workspace.output.geometry().loc.as_logical()) + .to_physical_precise_round(output_scale), + Scale::from(output_scale), + 1.0, + ) + }) + .map(|p_element| p_element.into()), + ); + } // sticky windows - if !has_fullscreen { + if !has_fullscreen && element_filter != ElementFilter::LayerShellOnly { let alpha = match &overview.0 { OverviewMode::Started(_, started) => { (1.0 - (Instant::now().duration_since(*started).as_millis() @@ -664,29 +727,17 @@ where .then_some(last_active_seat) .map(|seat| workspace.focus_stack.get(seat)); - let (w_elements, p_elements) = set.sticky_layer.render( - renderer, - current_focus.as_ref().and_then(|stack| stack.last()), - resize_indicator.clone(), - active_hint, - alpha, - theme, + elements.extend_from_workspace_elements( + set.sticky_layer.render( + renderer, + current_focus.as_ref().and_then(|stack| stack.last()), + resize_indicator.clone(), + active_hint, + alpha, + theme, + ), + (0, 0).into(), ); - - elements.extend(p_elements.into_iter().map(|p_element| { - CosmicElement::Workspace(RelocateRenderElement::from_element( - WorkspaceRenderElement::Window(p_element), - (0, 0), - Relocate::Relative, - )) - })); - window_elements.extend(w_elements.into_iter().map(|w_element| { - CosmicElement::Workspace(RelocateRenderElement::from_element( - WorkspaceRenderElement::Window(w_element), - (0, 0), - Relocate::Relative, - )) - })); } let offset = match previous.as_ref() { @@ -728,48 +779,25 @@ where } }); - let (w_elements, p_elements) = workspace - .render::( - renderer, - (!move_active && is_active_space).then_some(last_active_seat), - overview.clone(), - resize_indicator.clone(), - active_hint, - theme, - ) - .map_err(|_| OutputNoMode)?; - elements.extend(p_elements.into_iter().map(|p_element| { - CosmicElement::Workspace(RelocateRenderElement::from_element( - p_element, - offset.to_physical_precise_round(output_scale), - Relocate::Relative, - )) - })); - window_elements.extend(w_elements.into_iter().map(|w_element| { - CosmicElement::Workspace(RelocateRenderElement::from_element( - w_element, - offset.to_physical_precise_round(output_scale), - Relocate::Relative, - )) - })); + elements.extend_from_workspace_elements( + workspace + .render::( + renderer, + (!move_active && is_active_space).then_some(last_active_seat), + overview.clone(), + resize_indicator.clone(), + active_hint, + theme, + ) + .map_err(|_| OutputNoMode)?, + offset.to_physical_precise_round(output_scale), + ); if !has_fullscreen { - let (w_elements, p_elements) = - background_layer_elements(renderer, output, exclude_workspace_overview); - elements.extend(p_elements.into_iter().map(|p_element| { - CosmicElement::Workspace(RelocateRenderElement::from_element( - p_element, - offset.to_physical_precise_round(output_scale), - Relocate::Relative, - )) - })); - window_elements.extend(w_elements.into_iter().map(|w_element| { - CosmicElement::Workspace(RelocateRenderElement::from_element( - w_element, - offset.to_physical_precise_round(output_scale), - Relocate::Relative, - )) - })); + elements.extend_from_workspace_elements( + background_layer_elements(renderer, output, element_filter), + offset.to_physical_precise_round(output_scale), + ); } Point::::from(match (layout, *previous_idx < current.1) { @@ -782,66 +810,38 @@ where None => (0, 0).into(), }; - let (w_elements, p_elements) = workspace - .render::( - renderer, - (!move_active && is_active_space).then_some(&last_active_seat), - overview, - resize_indicator, - active_hint, - theme, - ) - .map_err(|_| OutputNoMode)?; - elements.extend(p_elements.into_iter().map(|p_element| { - CosmicElement::Workspace(RelocateRenderElement::from_element( - p_element, - offset.to_physical_precise_round(output_scale), - Relocate::Relative, - )) - })); - window_elements.extend(w_elements.into_iter().map(|w_element| { - CosmicElement::Workspace(RelocateRenderElement::from_element( - w_element, + if element_filter != ElementFilter::LayerShellOnly { + elements.extend_from_workspace_elements( + workspace + .render::( + renderer, + (!move_active && is_active_space).then_some(&last_active_seat), + overview, + resize_indicator, + active_hint, + theme, + ) + .map_err(|_| OutputNoMode)?, offset.to_physical_precise_round(output_scale), - Relocate::Relative, - )) - })); + ); + } if !has_fullscreen { - let (w_elements, p_elements) = - background_layer_elements(renderer, output, exclude_workspace_overview); - - elements.extend(p_elements.into_iter().map(|p_element| { - CosmicElement::Workspace(RelocateRenderElement::from_element( - p_element, - offset.to_physical_precise_round(output_scale), - Relocate::Relative, - )) - })); - - window_elements.extend(w_elements.into_iter().map(|w_element| { - CosmicElement::Workspace(RelocateRenderElement::from_element( - w_element, - offset.to_physical_precise_round(output_scale), - Relocate::Relative, - )) - })); + elements.extend_from_workspace_elements( + background_layer_elements(renderer, output, element_filter), + offset.to_physical_precise_round(output_scale), + ); } - elements.extend(window_elements); - - Ok(elements) + Ok(elements.join()) } pub fn split_layer_elements( renderer: &mut R, output: &Output, layer: Layer, - exclude_workspace_overview: bool, -) -> ( - Vec>, - Vec>, -) + element_filter: ElementFilter, +) -> SplitRenderElements> where R: Renderer + ImportAll + ImportMem + AsGlowRenderer, ::TextureId: Clone + 'static, @@ -852,13 +852,15 @@ where let layer_map = layer_map_for_output(output); let output_scale = output.current_scale().fractional_scale(); - let mut popup_elements = Vec::new(); - let mut layer_elements = Vec::new(); + let mut elements = SplitRenderElements::default(); layer_map .layers_on(layer) .rev() - .filter(|s| !(exclude_workspace_overview && s.namespace() == WORKSPACE_OVERVIEW_NAMESPACE)) + .filter(|s| { + !(element_filter == ElementFilter::ExcludeWorkspaceOverview + && s.namespace() == WORKSPACE_OVERVIEW_NAMESPACE) + }) .filter_map(|surface| { layer_map .layer_geometry(surface) @@ -869,46 +871,47 @@ where let surface = surface.wl_surface(); let scale = Scale::from(output_scale); - popup_elements.extend(PopupManager::popups_for_surface(surface).flat_map( - |(popup, popup_offset)| { - let offset = (popup_offset - popup.geometry().loc) - .to_f64() - .to_physical(scale) - .to_i32_round(); - - render_elements_from_surface_tree( - renderer, - popup.wl_surface(), - location + offset, - scale, - 1.0, - Kind::Unspecified, - ) - }, - )); + elements + .p_elements + .extend(PopupManager::popups_for_surface(surface).flat_map( + |(popup, popup_offset)| { + let offset = (popup_offset - popup.geometry().loc) + .to_f64() + .to_physical(scale) + .to_i32_round(); + + render_elements_from_surface_tree( + renderer, + popup.wl_surface(), + location + offset, + scale, + 1.0, + Kind::Unspecified, + ) + }, + )); - layer_elements.extend(render_elements_from_surface_tree( - renderer, - surface, - location, - scale, - 1.0, - Kind::Unspecified, - )); + elements + .w_elements + .extend(render_elements_from_surface_tree( + renderer, + surface, + location, + scale, + 1.0, + Kind::Unspecified, + )); }); - (layer_elements, popup_elements) + elements } // bottom and background layer surfaces pub fn background_layer_elements( renderer: &mut R, output: &Output, - exclude_workspace_overview: bool, -) -> ( - Vec>, - Vec>, -) + element_filter: ElementFilter, +) -> SplitRenderElements> where R: Renderer + ImportAll + ImportMem + AsGlowRenderer, ::TextureId: Clone + 'static, @@ -916,17 +919,14 @@ where CosmicMappedRenderElement: RenderElement, WorkspaceRenderElement: RenderElement, { - let (mut layer_elements, mut popup_elements) = - split_layer_elements(renderer, output, Layer::Bottom, exclude_workspace_overview); - let more = split_layer_elements( + let mut elements = split_layer_elements(renderer, output, Layer::Bottom, element_filter); + elements.extend(split_layer_elements( renderer, output, Layer::Background, - exclude_workspace_overview, - ); - layer_elements.extend(more.0); - popup_elements.extend(more.1); - (layer_elements, popup_elements) + element_filter, + )); + elements } fn session_lock_elements( @@ -991,6 +991,12 @@ where let workspace = (workspace.handle, idx); std::mem::drop(shell_ref); + let element_filter = if workspace_overview_is_open(output) { + ElementFilter::LayerShellOnly + } else { + ElementFilter::All + }; + let result = render_workspace( gpu, renderer, @@ -1004,7 +1010,7 @@ where previous_workspace, workspace, cursor_mode, - false, + element_filter, ); match result { @@ -1116,7 +1122,7 @@ pub fn render_workspace<'d, R, Target, OffTarget>( previous: Option<(WorkspaceHandle, usize, WorkspaceDelta)>, current: (WorkspaceHandle, usize), cursor_mode: CursorMode, - exclude_workspace_overview: bool, + element_filter: ElementFilter, ) -> Result<(RenderOutputResult<'d>, Vec>), RenderError> where R: Renderer @@ -1142,7 +1148,7 @@ where previous, current, cursor_mode, - exclude_workspace_overview, + element_filter, None, )?; diff --git a/src/input/mod.rs b/src/input/mod.rs index c71bed8f..2f29f2c2 100644 --- a/src/input/mod.rs +++ b/src/input/mod.rs @@ -19,7 +19,7 @@ use crate::{ FocusResult, InvalidWorkspaceIndex, MoveResult, OverviewMode, ResizeMode, SeatExt, Trigger, WorkspaceDelta, }, - utils::prelude::*, + utils::{prelude::*, quirks::workspace_overview_is_open}, wayland::{ handlers::{screencopy::SessionHolder, xdg_activation::ActivationContext}, protocols::{ @@ -1000,7 +1000,7 @@ impl State { .cloned(); if let Some(seat) = maybe_seat { self.common.idle_notifier_state.notify_activity(&seat); - if event.fingers() >= 3 { + if event.fingers() >= 3 && !workspace_overview_is_open(&seat.active_output()) { self.common.gesture_state = Some(GestureState::new(event.fingers())); } else { let serial = SERIAL_COUNTER.next_serial(); diff --git a/src/shell/element/mod.rs b/src/shell/element/mod.rs index 231f633a..94cb702e 100644 --- a/src/shell/element/mod.rs +++ b/src/shell/element/mod.rs @@ -1,7 +1,7 @@ use crate::{ backend::render::{ element::{AsGlowFrame, AsGlowRenderer}, - GlMultiError, GlMultiFrame, GlMultiRenderer, + GlMultiError, GlMultiFrame, GlMultiRenderer, SplitRenderElements, }, state::State, utils::{iced::IcedElementInternal, prelude::*}, @@ -663,7 +663,7 @@ impl CosmicMapped { location: smithay::utils::Point, scale: smithay::utils::Scale, alpha: f32, - ) -> (Vec, Vec) + ) -> SplitRenderElements where R: Renderer + ImportAll + ImportMem + AsGlowRenderer, ::TextureId: Send + Clone + 'static, @@ -842,27 +842,28 @@ impl CosmicMapped { #[cfg(not(feature = "debug"))] let debug_elements = Vec::new(); - #[cfg_attr(not(feature = "debug"), allow(unused_mut))] - let (window_elements, popup_elements) = match &self.element { - CosmicMappedInternal::Stack(s) => s - .split_render_elements::>( - renderer, location, scale, alpha, - ), - CosmicMappedInternal::Window(w) => w - .split_render_elements::>( - renderer, location, scale, alpha, - ), - _ => unreachable!(), + let mut elements = SplitRenderElements { + w_elements: debug_elements, + p_elements: Vec::new(), }; - ( - debug_elements - .into_iter() - .map(C::from) - .chain(window_elements.into_iter().map(C::from)) - .collect(), - popup_elements.into_iter().map(C::from).collect(), - ) + #[cfg_attr(not(feature = "debug"), allow(unused_mut))] + elements.extend_map( + match &self.element { + CosmicMappedInternal::Stack(s) => s + .split_render_elements::>( + renderer, location, scale, alpha, + ), + CosmicMappedInternal::Window(w) => w + .split_render_elements::>( + renderer, location, scale, alpha, + ), + _ => unreachable!(), + }, + C::from, + ); + + elements } pub(crate) fn update_theme(&self, theme: cosmic::Theme) { diff --git a/src/shell/element/stack.rs b/src/shell/element/stack.rs index 107179a3..8489365b 100644 --- a/src/shell/element/stack.rs +++ b/src/shell/element/stack.rs @@ -1,6 +1,9 @@ use super::{surface::RESIZE_BORDER, window::Focus, CosmicSurface}; use crate::{ - backend::render::cursor::{CursorShape, CursorState}, + backend::render::{ + cursor::{CursorShape, CursorState}, + SplitRenderElements, + }, shell::{ focus::target::PointerFocusTarget, grabs::{ReleaseMode, ResizeEdge}, @@ -547,7 +550,7 @@ impl CosmicStack { location: Point, scale: Scale, alpha: f32, - ) -> (Vec, Vec) + ) -> SplitRenderElements where R: Renderer + ImportAll + ImportMem, ::TextureId: Send + Clone + 'static, @@ -564,30 +567,28 @@ impl CosmicStack { let stack_loc = location + offset; let window_loc = location + Point::from((0, (TAB_HEIGHT as f64 * scale.y) as i32)); - let elements = AsRenderElements::::render_elements::>( + let w_elements = AsRenderElements::::render_elements::>( &self.0, renderer, stack_loc, scale, alpha, ); - let (window_elements, popup_elements) = self.0.with_program(|p| { - let windows = p.windows.lock().unwrap(); - let active = p.active.load(Ordering::SeqCst); + let mut elements = SplitRenderElements { + w_elements: w_elements.into_iter().map(C::from).collect(), + p_elements: Vec::new(), + }; - let (window_elements, popup_elements) = windows[active] - .split_render_elements::>( - renderer, window_loc, scale, alpha, - ); + elements.extend_map( + self.0.with_program(|p| { + let windows = p.windows.lock().unwrap(); + let active = p.active.load(Ordering::SeqCst); - (window_elements, popup_elements) - }); + windows[active].split_render_elements::>( + renderer, window_loc, scale, alpha, + ) + }), + C::from, + ); - ( - elements - .into_iter() - .map(C::from) - .chain(window_elements.into_iter().map(C::from)) - .collect(), - popup_elements.into_iter().map(C::from).collect(), - ) + elements } pub(crate) fn set_theme(&self, theme: cosmic::Theme) { diff --git a/src/shell/element/surface.rs b/src/shell/element/surface.rs index 5c18870a..a870d8e4 100644 --- a/src/shell/element/surface.rs +++ b/src/shell/element/surface.rs @@ -42,6 +42,7 @@ use smithay::{ }; use crate::{ + backend::render::SplitRenderElements, state::{State, SurfaceDmabufFeedback}, utils::prelude::*, wayland::handlers::decoration::PreferredDecorationMode, @@ -563,7 +564,7 @@ impl CosmicSurface { location: smithay::utils::Point, scale: smithay::utils::Scale, alpha: f32, - ) -> (Vec, Vec) + ) -> SplitRenderElements where R: Renderer + ImportAll, ::TextureId: Clone + 'static, @@ -573,7 +574,7 @@ impl CosmicSurface { WindowSurface::Wayland(toplevel) => { let surface = toplevel.wl_surface(); - let popup_render_elements = PopupManager::popups_for_surface(surface) + let p_elements = PopupManager::popups_for_surface(surface) .flat_map(|(popup, popup_offset)| { let offset = (self.0.geometry().loc + popup_offset - popup.geometry().loc) .to_physical_precise_round(scale); @@ -589,7 +590,7 @@ impl CosmicSurface { }) .collect(); - let window_render_elements = render_elements_from_surface_tree( + let w_elements = render_elements_from_surface_tree( renderer, surface, location, @@ -598,12 +599,15 @@ impl CosmicSurface { element::Kind::Unspecified, ); - (window_render_elements, popup_render_elements) + SplitRenderElements { + w_elements, + p_elements, + } } - WindowSurface::X11(surface) => ( - surface.render_elements(renderer, location, scale, alpha), - Vec::new(), - ), + WindowSurface::X11(surface) => SplitRenderElements { + w_elements: surface.render_elements(renderer, location, scale, alpha), + p_elements: Vec::new(), + }, } } diff --git a/src/shell/element/window.rs b/src/shell/element/window.rs index 5917a78d..706784fd 100644 --- a/src/shell/element/window.rs +++ b/src/shell/element/window.rs @@ -1,5 +1,8 @@ use crate::{ - backend::render::cursor::{CursorShape, CursorState}, + backend::render::{ + cursor::{CursorShape, CursorState}, + SplitRenderElements, + }, shell::{ focus::target::PointerFocusTarget, grabs::{ReleaseMode, ResizeEdge}, @@ -317,7 +320,7 @@ impl CosmicWindow { location: smithay::utils::Point, scale: smithay::utils::Scale, alpha: f32, - ) -> (Vec, Vec) + ) -> SplitRenderElements where R: Renderer + ImportAll + ImportMem, ::TextureId: Send + Clone + 'static, @@ -331,12 +334,17 @@ impl CosmicWindow { location }; - let (mut window_elements, popup_elements) = self.0.with_program(|p| { - p.window - .split_render_elements::>( - renderer, window_loc, scale, alpha, - ) - }); + let mut elements = SplitRenderElements::default(); + + elements.extend_map( + self.0.with_program(|p| { + p.window + .split_render_elements::>( + renderer, window_loc, scale, alpha, + ) + }), + C::from, + ); if has_ssd { let ssd_loc = location @@ -344,15 +352,16 @@ impl CosmicWindow { .0 .with_program(|p| p.window.geometry().loc) .to_physical_precise_round(scale); - window_elements.extend(AsRenderElements::::render_elements::< - CosmicWindowRenderElement, - >(&self.0, renderer, ssd_loc, scale, alpha)) + elements.w_elements.extend( + AsRenderElements::::render_elements::>( + &self.0, renderer, ssd_loc, scale, alpha, + ) + .into_iter() + .map(C::from), + ) } - ( - window_elements.into_iter().map(C::from).collect(), - popup_elements.into_iter().map(C::from).collect(), - ) + elements } pub(crate) fn set_theme(&self, theme: cosmic::Theme) { diff --git a/src/shell/grabs/moving.rs b/src/shell/grabs/moving.rs index 0cbe400f..b4a0bac0 100644 --- a/src/shell/grabs/moving.rs +++ b/src/shell/grabs/moving.rs @@ -4,7 +4,7 @@ use crate::{ backend::render::{ cursor::{CursorShape, CursorState}, element::AsGlowRenderer, - BackdropShader, IndicatorShader, Key, Usage, + BackdropShader, IndicatorShader, Key, SplitRenderElements, Usage, }, shell::{ element::{ @@ -182,7 +182,10 @@ impl MoveGrabState { _ => vec![], }; - let (window_elements, popup_elements) = self + let SplitRenderElements { + w_elements, + p_elements, + } = self .window .split_render_elements::>( renderer, @@ -202,9 +205,9 @@ impl MoveGrabState { 1.0, ) }) - .chain(popup_elements) + .chain(p_elements) .chain(focus_element) - .chain(window_elements.into_iter().map(|elem| match elem { + .chain(w_elements.into_iter().map(|elem| match elem { CosmicMappedRenderElement::Stack(stack) => { CosmicMappedRenderElement::GrabbedStack( RescaleRenderElement::from_element( diff --git a/src/shell/layout/floating/mod.rs b/src/shell/layout/floating/mod.rs index 1c184a30..c0ff2ad2 100644 --- a/src/shell/layout/floating/mod.rs +++ b/src/shell/layout/floating/mod.rs @@ -24,7 +24,7 @@ use smithay::{ }; use crate::{ - backend::render::{element::AsGlowRenderer, IndicatorShader, Key, Usage}, + backend::render::{element::AsGlowRenderer, IndicatorShader, Key, SplitRenderElements, Usage}, shell::{ element::{ resize_indicator::ResizeIndicator, @@ -1270,10 +1270,7 @@ impl FloatingLayout { indicator_thickness: u8, alpha: f32, theme: &cosmic::theme::CosmicTheme, - ) -> ( - Vec>, - Vec>, - ) + ) -> SplitRenderElements> where R: Renderer + ImportAll + ImportMem + AsGlowRenderer, ::TextureId: Send + Clone + 'static, @@ -1288,8 +1285,7 @@ impl FloatingLayout { }; let output_scale = output.current_scale().fractional_scale(); - let mut window_elements = Vec::new(); - let mut popup_elements = Vec::new(); + let mut elements = SplitRenderElements::default(); for elem in self .animations @@ -1305,7 +1301,10 @@ impl FloatingLayout { .unwrap_or_else(|| (self.space.element_geometry(elem).unwrap().as_local(), alpha)); let render_location = geometry.loc - elem.geometry().loc.as_local(); - let (mut w_elements, p_elements) = elem.split_render_elements( + let SplitRenderElements { + mut w_elements, + p_elements, + } = elem.split_render_elements( renderer, render_location .as_logical() @@ -1388,7 +1387,7 @@ impl FloatingLayout { resize.resize(resize_geometry.size.as_logical()); resize.output_enter(output, Rectangle::default() /* unused */); - window_elements.extend( + elements.w_elements.extend( resize .render_elements::>( renderer, @@ -1420,15 +1419,15 @@ impl FloatingLayout { active_window_hint.blue, ], ); - window_elements.push(element.into()); + elements.w_elements.push(element.into()); } } - window_elements.extend(w_elements); - popup_elements.extend(p_elements); + elements.w_elements.extend(w_elements); + elements.p_elements.extend(p_elements); } - (window_elements, popup_elements) + elements } fn gaps(&self) -> (i32, i32) { diff --git a/src/shell/layout/tiling/mod.rs b/src/shell/layout/tiling/mod.rs index 83084b3f..3a16ef14 100644 --- a/src/shell/layout/tiling/mod.rs +++ b/src/shell/layout/tiling/mod.rs @@ -2,8 +2,8 @@ use crate::{ backend::render::{ - element::AsGlowRenderer, BackdropShader, IndicatorShader, Key, Usage, ACTIVE_GROUP_COLOR, - GROUP_COLOR, + element::AsGlowRenderer, BackdropShader, IndicatorShader, Key, SplitRenderElements, Usage, + ACTIVE_GROUP_COLOR, GROUP_COLOR, }, shell::{ element::{ @@ -3846,13 +3846,7 @@ impl TilingLayout { resize_indicator: Option<(ResizeMode, ResizeIndicator)>, indicator_thickness: u8, theme: &cosmic::theme::CosmicTheme, - ) -> Result< - ( - Vec>, - Vec>, - ), - OutputNotMapped, - > + ) -> Result>, OutputNotMapped> where R: Renderer + ImportAll + ImportMem + AsGlowRenderer, ::TextureId: Send + Clone + 'static, @@ -3885,8 +3879,7 @@ impl TilingLayout { }; let draw_groups = overview.0.alpha(); - let mut window_elements = Vec::new(); - let mut popup_elements = Vec::new(); + let mut elements = SplitRenderElements::default(); let is_overview = !matches!(overview.0, OverviewMode::None); let is_mouse_tiling = (matches!(overview.0, OverviewMode::Started(Trigger::Pointer(_), _))) @@ -3921,7 +3914,7 @@ impl TilingLayout { .unzip(); // all old windows we want to fade out - let (w_elements, p_elements) = render_old_tree( + elements.extend(render_old_tree( reference_tree, target_tree, renderer, @@ -3931,9 +3924,7 @@ impl TilingLayout { indicator_thickness, swap_desc.is_some(), theme, - ); - window_elements.extend(w_elements); - popup_elements.extend(p_elements); + )); geometries } else { @@ -3961,7 +3952,7 @@ impl TilingLayout { .unzip(); // all alive windows - let (w_elements, p_elements) = render_new_tree( + elements.extend(render_new_tree( target_tree, reference_tree, renderer, @@ -3989,16 +3980,14 @@ impl TilingLayout { &self.swapping_stack_surface_id, &self.placeholder_id, theme, - ); - window_elements.extend(w_elements); - popup_elements.extend(p_elements); + )); // tiling hints if let Some(group_elements) = group_elements { - window_elements.extend(group_elements); + elements.w_elements.extend(group_elements); } - Ok((window_elements, popup_elements)) + Ok(elements) } fn gaps(&self) -> (i32, i32) { @@ -4694,10 +4683,7 @@ fn render_old_tree( indicator_thickness: u8, is_swap_mode: bool, theme: &cosmic::theme::CosmicTheme, -) -> ( - Vec>, - Vec>, -) +) -> SplitRenderElements> where R: Renderer + ImportAll + ImportMem + AsGlowRenderer, ::TextureId: Send + Clone + 'static, @@ -4706,8 +4692,7 @@ where CosmicStackRenderElement: RenderElement, { let window_hint = crate::theme::active_window_hint(theme); - let mut window_elements = Vec::new(); - let mut popup_elements = Vec::new(); + let mut elements = SplitRenderElements::default(); if let Some(root) = reference_tree.root_node_id() { let geometries = geometries.unwrap_or_default(); @@ -4777,62 +4762,68 @@ where }; let elem_geometry = mapped.geometry().to_physical_precise_round(output_scale); - let (w_elements, p_elements) = mapped - .split_render_elements::>( - renderer, - geo.loc.as_logical().to_physical_precise_round(output_scale) - - elem_geometry.loc, - Scale::from(output_scale), - alpha, - ); + let SplitRenderElements { + w_elements, + p_elements, + } = mapped.split_render_elements::>( + renderer, + geo.loc.as_logical().to_physical_precise_round(output_scale) + - elem_geometry.loc, + Scale::from(output_scale), + alpha, + ); - window_elements.extend(w_elements.into_iter().flat_map(|element| { - match element { - CosmicMappedRenderElement::Stack(elem) => constrain_render_elements( - std::iter::once(elem), - geo.loc.as_logical().to_physical_precise_round(output_scale) - - elem_geometry.loc, - geo.as_logical().to_physical_precise_round(output_scale), - elem_geometry, - ConstrainScaleBehavior::Stretch, - ConstrainAlign::CENTER, - output_scale, - ) - .next() - .map(CosmicMappedRenderElement::TiledStack), - CosmicMappedRenderElement::Window(elem) => constrain_render_elements( - std::iter::once(elem), - geo.loc.as_logical().to_physical_precise_round(output_scale) - - elem_geometry.loc, - geo.as_logical().to_physical_precise_round(output_scale), - elem_geometry, - ConstrainScaleBehavior::Stretch, - ConstrainAlign::CENTER, - output_scale, - ) - .next() - .map(CosmicMappedRenderElement::TiledWindow), - x => Some(x), - } - })); + elements + .w_elements + .extend(w_elements.into_iter().flat_map(|element| { + match element { + CosmicMappedRenderElement::Stack(elem) => constrain_render_elements( + std::iter::once(elem), + geo.loc.as_logical().to_physical_precise_round(output_scale) + - elem_geometry.loc, + geo.as_logical().to_physical_precise_round(output_scale), + elem_geometry, + ConstrainScaleBehavior::Stretch, + ConstrainAlign::CENTER, + output_scale, + ) + .next() + .map(CosmicMappedRenderElement::TiledStack), + CosmicMappedRenderElement::Window(elem) => constrain_render_elements( + std::iter::once(elem), + geo.loc.as_logical().to_physical_precise_round(output_scale) + - elem_geometry.loc, + geo.as_logical().to_physical_precise_round(output_scale), + elem_geometry, + ConstrainScaleBehavior::Stretch, + ConstrainAlign::CENTER, + output_scale, + ) + .next() + .map(CosmicMappedRenderElement::TiledWindow), + x => Some(x), + } + })); if minimize_geo.is_some() && indicator_thickness > 0 { - window_elements.push(CosmicMappedRenderElement::FocusIndicator( - IndicatorShader::focus_element( - renderer, - Key::Window(Usage::FocusIndicator, mapped.clone().key()), - geo, - indicator_thickness, - output_scale, - alpha, - [window_hint.red, window_hint.green, window_hint.blue], - ), - )); + elements + .w_elements + .push(CosmicMappedRenderElement::FocusIndicator( + IndicatorShader::focus_element( + renderer, + Key::Window(Usage::FocusIndicator, mapped.clone().key()), + geo, + indicator_thickness, + output_scale, + alpha, + [window_hint.red, window_hint.green, window_hint.blue], + ), + )); } - popup_elements.extend(p_elements); + elements.p_elements.extend(p_elements); }); } - (window_elements, popup_elements) + elements } fn render_new_tree( @@ -4854,10 +4845,7 @@ fn render_new_tree( swapping_stack_surface_id: &Id, placeholder_id: &Id, theme: &cosmic::theme::CosmicTheme, -) -> ( - Vec>, - Vec>, -) +) -> SplitRenderElements> where R: Renderer + ImportAll + ImportMem + AsGlowRenderer, ::TextureId: Send + Clone + 'static, @@ -5246,15 +5234,17 @@ where if let Data::Mapped { mapped, .. } = data { let elem_geometry = mapped.geometry().to_physical_precise_round(output_scale); - let (mut w_elements, p_elements) = mapped - .split_render_elements::>( - renderer, - //original_location, - geo.loc.as_logical().to_physical_precise_round(output_scale) - - elem_geometry.loc, - Scale::from(output_scale), - alpha, - ); + let SplitRenderElements { + mut w_elements, + p_elements, + } = mapped.split_render_elements::>( + renderer, + //original_location, + geo.loc.as_logical().to_physical_precise_round(output_scale) + - elem_geometry.loc, + Scale::from(output_scale), + alpha, + ); if swap_desc .as_ref() .filter(|swap_desc| swap_desc.node == node_id) @@ -5373,7 +5363,10 @@ where .chain(group_backdrop.into_iter().map(Into::into)) .collect(); - (window_elements, popup_elements) + SplitRenderElements { + w_elements: window_elements, + p_elements: popup_elements, + } } fn scale_to_center( diff --git a/src/shell/mod.rs b/src/shell/mod.rs index 2e81c6a9..95052d92 100644 --- a/src/shell/mod.rs +++ b/src/shell/mod.rs @@ -52,7 +52,7 @@ use smithay::{ use crate::{ backend::render::animations::spring::{Spring, SpringParams}, config::Config, - utils::prelude::*, + utils::{prelude::*, quirks::WORKSPACE_OVERVIEW_NAMESPACE}, wayland::{ handlers::{ toplevel_management::minimize_rectangle, xdg_activation::ActivationContext, @@ -416,13 +416,23 @@ impl WorkspaceSet { return Err(InvalidWorkspaceIndex); } + // Animate if workspaces overview isn't open + let layer_map = layer_map_for_output(&self.output); + let animate = !layer_map + .layers() + .any(|l| l.namespace() == WORKSPACE_OVERVIEW_NAMESPACE); + if self.active != idx { let old_active = self.active; state.remove_workspace_state(&self.workspaces[old_active].handle, WState::Active); state.remove_workspace_state(&self.workspaces[old_active].handle, WState::Urgent); state.remove_workspace_state(&self.workspaces[idx].handle, WState::Urgent); state.add_workspace_state(&self.workspaces[idx].handle, WState::Active); - self.previously_active = Some((old_active, workspace_delta)); + self.previously_active = if animate { + Some((old_active, workspace_delta)) + } else { + None + }; self.active = idx; Ok(true) } else { diff --git a/src/shell/workspace.rs b/src/shell/workspace.rs index c161886d..94ba2d60 100644 --- a/src/shell/workspace.rs +++ b/src/shell/workspace.rs @@ -1,7 +1,7 @@ use crate::{ backend::render::{ element::{AsGlowFrame, AsGlowRenderer}, - BackdropShader, GlMultiError, GlMultiFrame, GlMultiRenderer, + BackdropShader, GlMultiError, GlMultiFrame, GlMultiRenderer, SplitRenderElements, }, shell::{ layout::{floating::FloatingLayout, tiling::TilingLayout}, @@ -1005,13 +1005,7 @@ impl Workspace { resize_indicator: Option<(ResizeMode, ResizeIndicator)>, indicator_thickness: u8, theme: &CosmicTheme, - ) -> Result< - ( - Vec>, - Vec>, - ), - OutputNotMapped, - > + ) -> Result>, OutputNotMapped> where R: Renderer + ImportAll + ImportMem + AsGlowRenderer, ::TextureId: Send + Clone + 'static, @@ -1020,8 +1014,7 @@ impl Workspace { CosmicStackRenderElement: RenderElement, WorkspaceRenderElement: RenderElement, { - let mut window_elements = Vec::new(); - let mut popup_elements = Vec::new(); + let mut elements = SplitRenderElements::default(); let output_scale = self.output.current_scale().fractional_scale(); let zone = { @@ -1104,7 +1097,10 @@ impl Workspace { y: target_geo.size.h as f64 / bbox.size.h as f64, }; - let (w_elements, p_elements) = fullscreen + let SplitRenderElements { + w_elements, + p_elements, + } = fullscreen .surface .split_render_elements::>( renderer, @@ -1112,13 +1108,15 @@ impl Workspace { output_scale.into(), alpha, ); - window_elements.extend( + elements.w_elements.extend( w_elements .into_iter() .map(|elem| RescaleRenderElement::from_element(elem, render_loc, scale)) .map(Into::into), ); - popup_elements.extend(p_elements.into_iter().map(Into::into)); + elements + .p_elements + .extend(p_elements.into_iter().map(Into::into)) } if self @@ -1149,16 +1147,17 @@ impl Workspace { OverviewMode::None => 1.0, }; - let (w_elements, p_elements) = self.floating_layer.render::( - renderer, - focused.as_ref(), - resize_indicator.clone(), - indicator_thickness, - alpha, - theme, + elements.extend_map( + self.floating_layer.render::( + renderer, + focused.as_ref(), + resize_indicator.clone(), + indicator_thickness, + alpha, + theme, + ), + WorkspaceRenderElement::from, ); - popup_elements.extend(p_elements.into_iter().map(WorkspaceRenderElement::from)); - window_elements.extend(w_elements.into_iter().map(WorkspaceRenderElement::from)); let alpha = match &overview.0 { OverviewMode::Started(_, start) => Some( @@ -1173,20 +1172,21 @@ impl Workspace { }; //tiling surfaces - let (w_elements, p_elements) = self.tiling_layer.render::( - renderer, - draw_focus_indicator, - zone, - overview, - resize_indicator, - indicator_thickness, - theme, - )?; - popup_elements.extend(p_elements.into_iter().map(WorkspaceRenderElement::from)); - window_elements.extend(w_elements.into_iter().map(WorkspaceRenderElement::from)); + elements.extend_map( + self.tiling_layer.render::( + renderer, + draw_focus_indicator, + zone, + overview, + resize_indicator, + indicator_thickness, + theme, + )?, + WorkspaceRenderElement::from, + ); if let Some(alpha) = alpha { - window_elements.push( + elements.w_elements.push( Into::>::into(BackdropShader::element( renderer, self.backdrop_id.clone(), @@ -1203,7 +1203,7 @@ impl Workspace { } } - Ok((window_elements, popup_elements)) + Ok(elements) } } diff --git a/src/utils/mod.rs b/src/utils/mod.rs index 75a928b3..4da680ef 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -5,6 +5,7 @@ pub(crate) use self::ids::id_gen; pub mod geometry; pub mod iced; pub mod prelude; +pub mod quirks; pub mod rlimit; pub mod screenshot; pub mod tween; diff --git a/src/utils/quirks.rs b/src/utils/quirks.rs new file mode 100644 index 00000000..2ecda9fd --- /dev/null +++ b/src/utils/quirks.rs @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: GPL-3.0-only + +use smithay::{desktop::layer_map_for_output, output::Output}; + +/// Layer shell namespace used by `cosmic-workspaces` +// TODO: Avoid special case, or add protocol to expose required behavior +pub const WORKSPACE_OVERVIEW_NAMESPACE: &str = "cosmic-workspace-overview"; + +/// Check if a workspace overview shell surface is open on the output +pub fn workspace_overview_is_open(output: &Output) -> bool { + layer_map_for_output(output) + .layers() + .any(|s| s.namespace() == WORKSPACE_OVERVIEW_NAMESPACE) +} diff --git a/src/wayland/handlers/screencopy/mod.rs b/src/wayland/handlers/screencopy/mod.rs index 9df67879..19b04bf3 100644 --- a/src/wayland/handlers/screencopy/mod.rs +++ b/src/wayland/handlers/screencopy/mod.rs @@ -39,8 +39,6 @@ pub use self::render::*; use self::user_data::*; pub use self::user_data::{FrameHolder, ScreencopySessions, SessionData, SessionHolder}; -pub const WORKSPACE_OVERVIEW_NAMESPACE: &str = "cosmic-workspace-overview"; - impl ScreencopyHandler for State { fn screencopy_state(&mut self) -> &mut ScreencopyState { &mut self.common.screencopy_state diff --git a/src/wayland/handlers/screencopy/render.rs b/src/wayland/handlers/screencopy/render.rs index 6ad8b027..ab1f95ea 100644 --- a/src/wayland/handlers/screencopy/render.rs +++ b/src/wayland/handlers/screencopy/render.rs @@ -36,7 +36,7 @@ use crate::{ backend::render::{ cursor, element::{AsGlowRenderer, CosmicElement, DamageElement, FromGlesError}, - render_workspace, CursorMode, CLEAR_COLOR, + render_workspace, CursorMode, ElementFilter, CLEAR_COLOR, }, shell::{CosmicMappedRenderElement, CosmicSurface, WorkspaceRenderElement}, state::{BackendData, Common, State}, @@ -287,7 +287,7 @@ pub fn render_workspace_to_buffer( None, handle, cursor_mode, - true, + ElementFilter::ExcludeWorkspaceOverview, ) .map(|res| res.0) } else { @@ -316,7 +316,7 @@ pub fn render_workspace_to_buffer( None, handle, cursor_mode, - true, + ElementFilter::ExcludeWorkspaceOverview, ) .map(|res| res.0) }