shell: Allow active workspace to be None

This commit is contained in:
Victoria Brekenfeld 2025-01-06 19:23:06 +01:00 committed by Victoria Brekenfeld
parent 23570ea9f4
commit db13eea91c
13 changed files with 230 additions and 167 deletions

View file

@ -943,7 +943,11 @@ impl SurfaceThreadState {
let has_active_fullscreen = { let has_active_fullscreen = {
let shell = self.shell.read().unwrap(); let shell = self.shell.read().unwrap();
let output = self.mirroring.as_ref().unwrap_or(&self.output); let output = self.mirroring.as_ref().unwrap_or(&self.output);
shell.workspaces.active(output).1.get_fullscreen().is_some() if let Some((_, workspace)) = shell.workspaces.active(output) {
workspace.get_fullscreen().is_some()
} else {
false
}
}; };
if self.vrr_mode == AdaptiveSync::Enabled { if self.vrr_mode == AdaptiveSync::Enabled {
@ -1457,7 +1461,9 @@ fn render_node_for_output(
return *target_node; return *target_node;
} }
let workspace = shell.active_space(output); let Some(workspace) = shell.active_space(output) else {
return *target_node;
};
let nodes = workspace let nodes = workspace
.get_fullscreen() .get_fullscreen()
.map(|w| vec![w.clone()]) .map(|w| vec![w.clone()])

View file

@ -516,8 +516,42 @@ where
WorkspaceRenderElement<R>: RenderElement<R>, WorkspaceRenderElement<R>: RenderElement<R>,
{ {
let shell_guard = shell.read().unwrap(); let shell_guard = shell.read().unwrap();
#[cfg(feature = "debug")]
let mut debug_elements = {
let output_geo = output.geometry();
let seats = shell_guard.seats.iter().cloned().collect::<Vec<_>>();
let scale = output.current_scale().fractional_scale();
if let Some((state, timings)) = _fps {
let debug_active = shell_guard.debug_active;
vec![fps_ui(
_gpu,
debug_active,
&seats,
renderer.glow_renderer_mut(),
state,
timings,
Rectangle::from_loc_and_size(
(0, 0),
(output_geo.size.w.min(400), output_geo.size.h.min(800)),
),
scale,
)
.map_err(FromGlesError::from_gles_error)
.map_err(RenderError::Rendering)?
.into()]
} else {
Vec::new()
}
};
let Some((previous_workspace, workspace)) = shell_guard.workspaces.active(output) else {
#[cfg(not(feature = "debug"))]
return Ok(Vec::new());
#[cfg(feature = "debug")]
return Ok(debug_elements);
};
let (previous_workspace, workspace) = shell_guard.workspaces.active(output);
let (previous_idx, idx) = shell_guard.workspaces.active_num(&output); let (previous_idx, idx) = shell_guard.workspaces.active_num(&output);
let previous_workspace = previous_workspace let previous_workspace = previous_workspace
.zip(previous_idx) .zip(previous_idx)
@ -532,7 +566,8 @@ where
ElementFilter::All ElementFilter::All
}; };
workspace_elements( #[allow(unused_mut)]
let workspace_elements = workspace_elements(
_gpu, _gpu,
renderer, renderer,
shell, shell,
@ -542,8 +577,15 @@ where
workspace, workspace,
cursor_mode, cursor_mode,
element_filter, element_filter,
_fps, )?;
)
#[cfg(feature = "debug")]
{
debug_elements.extend(workspace_elements);
Ok(debug_elements)
}
#[cfg(not(feature = "debug"))]
Ok(workspace_elements)
} }
#[profiling::function] #[profiling::function]
@ -557,7 +599,6 @@ pub fn workspace_elements<R>(
current: (WorkspaceHandle, usize), current: (WorkspaceHandle, usize),
cursor_mode: CursorMode, cursor_mode: CursorMode,
element_filter: ElementFilter, element_filter: ElementFilter,
_fps: Option<(&EguiState, &Timings)>,
) -> Result<Vec<CosmicElement<R>>, RenderError<<R as Renderer>::Error>> ) -> Result<Vec<CosmicElement<R>>, RenderError<<R as Renderer>::Error>>
where where
R: Renderer + ImportAll + ImportMem + AsGlowRenderer, R: Renderer + ImportAll + ImportMem + AsGlowRenderer,
@ -588,31 +629,6 @@ where
element_filter == ElementFilter::ExcludeWorkspaceOverview, element_filter == ElementFilter::ExcludeWorkspaceOverview,
)); ));
#[cfg(feature = "debug")]
{
let output_geo = output.geometry();
if let Some((state, timings)) = _fps {
let debug_active = shell.read().unwrap().debug_active;
let fps_overlay = fps_ui(
_gpu,
debug_active,
&seats,
renderer.glow_renderer_mut(),
state,
timings,
Rectangle::from_loc_and_size(
(0, 0),
(output_geo.size.w.min(400), output_geo.size.h.min(800)),
),
scale,
)
.map_err(FromGlesError::from_gles_error)
.map_err(RenderError::Rendering)?;
elements.push(fps_overlay.into());
}
}
let shell = shell.read().unwrap(); let shell = shell.read().unwrap();
let overview = shell.overview_mode(); let overview = shell.overview_mode();
@ -933,7 +949,10 @@ where
Target: Clone, Target: Clone,
{ {
let shell_ref = shell.read().unwrap(); let shell_ref = shell.read().unwrap();
let (previous_workspace, workspace) = shell_ref.workspaces.active(output); let (previous_workspace, workspace) = shell_ref
.workspaces
.active(output)
.ok_or(RenderError::OutputNoMode(OutputNoMode))?;
let (previous_idx, idx) = shell_ref.workspaces.active_num(output); let (previous_idx, idx) = shell_ref.workspaces.active_num(output);
let previous_workspace = previous_workspace let previous_workspace = previous_workspace
.zip(previous_idx) .zip(previous_idx)
@ -1099,7 +1118,6 @@ where
current, current,
cursor_mode, cursor_mode,
element_filter, element_filter,
None,
)?; )?;
if let Some(additional_damage) = additional_damage { if let Some(additional_damage) = additional_damage {

View file

@ -408,6 +408,7 @@ impl State {
let new_target = shell let new_target = shell
.workspaces .workspaces
.active(&next_output) .active(&next_output)
.unwrap()
.1 .1
.focus_stack .focus_stack
.get(&seat) .get(&seat)
@ -495,6 +496,7 @@ impl State {
let new_target = shell let new_target = shell
.workspaces .workspaces
.active(&next_output) .active(&next_output)
.unwrap()
.1 .1
.focus_stack .focus_stack
.get(&seat) .get(&seat)
@ -554,6 +556,7 @@ impl State {
let new_target = shell let new_target = shell
.workspaces .workspaces
.active(&prev_output) .active(&prev_output)
.unwrap()
.1 .1
.focus_stack .focus_stack
.get(&seat) .get(&seat)
@ -765,7 +768,7 @@ impl State {
.next() .next()
.cloned(); .cloned();
(shell.active_space(&active_output).handle, output) (shell.active_space(&active_output).unwrap().handle, output)
}; };
if let Some(next_output) = next_output { if let Some(next_output) = next_output {
self.common self.common
@ -785,7 +788,7 @@ impl State {
.next() .next()
.cloned(); .cloned();
(shell.active_space(&active_output).handle, output) (shell.active_space(&active_output).unwrap().handle, output)
}; };
if let Some(prev_output) = prev_output { if let Some(prev_output) = prev_output {
self.common self.common
@ -799,7 +802,7 @@ impl State {
let shell = self.common.shell.read().unwrap(); let shell = self.common.shell.read().unwrap();
( (
shell.active_space(&active_output).handle, shell.active_space(&active_output).unwrap().handle,
shell.next_output(&active_output, direction).cloned(), shell.next_output(&active_output, direction).cloned(),
) )
}; };
@ -865,7 +868,7 @@ impl State {
_ => { _ => {
let current_output = seat.active_output(); let current_output = seat.active_output();
let mut shell = self.common.shell.write().unwrap(); let mut shell = self.common.shell.write().unwrap();
let workspace = shell.active_space(&current_output); let workspace = shell.active_space(&current_output).unwrap();
if let Some(focused_window) = workspace.focus_stack.get(seat).last() { if let Some(focused_window) = workspace.focus_stack.get(seat).last() {
if workspace.is_tiled(focused_window) { if workspace.is_tiled(focused_window) {
shell.set_overview_mode( shell.set_overview_mode(
@ -884,7 +887,7 @@ impl State {
}; };
let mut shell = self.common.shell.write().unwrap(); let mut shell = self.common.shell.write().unwrap();
let workspace = shell.active_space_mut(&focused_output); let workspace = shell.active_space_mut(&focused_output).unwrap();
if workspace.get_fullscreen().is_some() { if workspace.get_fullscreen().is_some() {
return; // TODO, is this what we want? Maybe disengage fullscreen instead? return; // TODO, is this what we want? Maybe disengage fullscreen instead?
} }
@ -909,7 +912,7 @@ impl State {
return; return;
}; };
let mut shell = self.common.shell.write().unwrap(); let mut shell = self.common.shell.write().unwrap();
let workspace = shell.active_space_mut(&focused_output); let workspace = shell.active_space_mut(&focused_output).unwrap();
let focus_stack = workspace.focus_stack.get(seat); let focus_stack = workspace.focus_stack.get(seat);
let focused_window = focus_stack.last().cloned(); let focused_window = focus_stack.last().cloned();
if let Some(window) = focused_window { if let Some(window) = focused_window {
@ -922,7 +925,7 @@ impl State {
return; return;
}; };
let mut shell = self.common.shell.write().unwrap(); let mut shell = self.common.shell.write().unwrap();
let workspace = shell.active_space(&focused_output); let workspace = shell.active_space(&focused_output).unwrap();
let focus_stack = workspace.focus_stack.get(seat); let focus_stack = workspace.focus_stack.get(seat);
let focused_window = focus_stack.last().cloned(); let focused_window = focus_stack.last().cloned();
if let Some(window) = focused_window { if let Some(window) = focused_window {
@ -940,14 +943,14 @@ impl State {
Action::ToggleOrientation => { Action::ToggleOrientation => {
let output = seat.active_output(); let output = seat.active_output();
let mut shell = self.common.shell.write().unwrap(); let mut shell = self.common.shell.write().unwrap();
let workspace = shell.active_space_mut(&output); let workspace = shell.active_space_mut(&output).unwrap();
workspace.tiling_layer.update_orientation(None, &seat); workspace.tiling_layer.update_orientation(None, &seat);
} }
Action::Orientation(orientation) => { Action::Orientation(orientation) => {
let output = seat.active_output(); let output = seat.active_output();
let mut shell = self.common.shell.write().unwrap(); let mut shell = self.common.shell.write().unwrap();
let workspace = shell.active_space_mut(&output); let workspace = shell.active_space_mut(&output).unwrap();
workspace workspace
.tiling_layer .tiling_layer
.update_orientation(Some(orientation), &seat); .update_orientation(Some(orientation), &seat);
@ -991,7 +994,7 @@ impl State {
} else { } else {
let output = seat.active_output(); let output = seat.active_output();
let mut shell = self.common.shell.write().unwrap(); let mut shell = self.common.shell.write().unwrap();
let workspace = shell.workspaces.active_mut(&output); let workspace = shell.workspaces.active_mut(&output).unwrap();
let mut guard = self.common.workspace_state.update(); let mut guard = self.common.workspace_state.update();
workspace.toggle_tiling(seat, &mut guard); workspace.toggle_tiling(seat, &mut guard);
} }
@ -1002,7 +1005,7 @@ impl State {
return; return;
}; };
let mut shell = self.common.shell.write().unwrap(); let mut shell = self.common.shell.write().unwrap();
let workspace = shell.active_space_mut(&output); let workspace = shell.active_space_mut(&output).unwrap();
workspace.toggle_floating_window_focused(seat); workspace.toggle_floating_window_focused(seat);
} }
@ -1035,7 +1038,7 @@ impl State {
let (token, data) = (token.clone(), data.clone()); let (token, data) = (token.clone(), data.clone());
let output = shell.seats.last_active().active_output(); let output = shell.seats.last_active().active_output();
let workspace = shell.active_space_mut(&output); let workspace = shell.active_space_mut(&output).unwrap();
workspace.pending_tokens.insert(token.clone()); workspace.pending_tokens.insert(token.clone());
let handle = workspace.handle; let handle = workspace.handle;
std::mem::drop(shell); std::mem::drop(shell);

View file

@ -1760,8 +1760,12 @@ impl State {
focused_output: &Output, focused_output: &Output,
) { ) {
if let Some(focus) = current_focus { if let Some(focus) = current_focus {
if let Some(new_descriptor) = if let Some(new_descriptor) = shell
shell.workspaces.active(&focused_output).1.node_desc(focus) .workspaces
.active(&focused_output)
.unwrap()
.1
.node_desc(focus)
{ {
let mut spaces = shell.workspaces.spaces_mut(); let mut spaces = shell.workspaces.spaces_mut();
if old_descriptor.handle != new_descriptor.handle { if old_descriptor.handle != new_descriptor.handle {
@ -1822,7 +1826,7 @@ impl State {
} }
} }
} else { } else {
let new_workspace = shell.workspaces.active(&focused_output).1.handle; let new_workspace = shell.workspaces.active(&focused_output).unwrap().1.handle;
if new_workspace != old_descriptor.handle { if new_workspace != old_descriptor.handle {
let spaces = shell.workspaces.spaces_mut(); let spaces = shell.workspaces.spaces_mut();
let (mut old_w, mut other_w) = let (mut old_w, mut other_w) =
@ -1867,7 +1871,7 @@ impl State {
output: &Output, output: &Output,
shell: &Shell, shell: &Shell,
) -> Option<KeyboardFocusTarget> { ) -> Option<KeyboardFocusTarget> {
let (previous_workspace, workspace) = shell.workspaces.active(output); let (previous_workspace, workspace) = shell.workspaces.active(output)?;
let (previous_idx, idx) = shell.workspaces.active_num(output); let (previous_idx, idx) = shell.workspaces.active_num(output);
let previous_workspace = previous_workspace let previous_workspace = previous_workspace
.zip(previous_idx) .zip(previous_idx)
@ -1990,7 +1994,7 @@ impl State {
output: &Output, output: &Output,
shell: &Shell, shell: &Shell,
) -> Option<(PointerFocusTarget, Point<f64, Global>)> { ) -> Option<(PointerFocusTarget, Point<f64, Global>)> {
let (previous_workspace, workspace) = shell.workspaces.active(output); let (previous_workspace, workspace) = shell.workspaces.active(output)?;
let (previous_idx, idx) = shell.workspaces.active_num(output); let (previous_idx, idx) = shell.workspaces.active_num(output);
let previous_workspace = previous_workspace let previous_workspace = previous_workspace
.zip(previous_idx) .zip(previous_idx)
@ -2122,22 +2126,26 @@ impl State {
} }
} }
fn cursor_sessions_for_output( fn cursor_sessions_for_output<'a>(
shell: &Shell, shell: &'a Shell,
output: &Output, output: &'a Output,
) -> impl Iterator<Item = CursorSession> { ) -> impl Iterator<Item = CursorSession> + 'a {
let workspace = shell.active_space(&output); shell
let maybe_fullscreen = workspace.get_fullscreen(); .active_space(&output)
workspace
.cursor_sessions()
.into_iter() .into_iter()
.chain( .flat_map(|workspace| {
maybe_fullscreen let maybe_fullscreen = workspace.get_fullscreen();
.map(|w| w.cursor_sessions()) workspace
.cursor_sessions()
.into_iter() .into_iter()
.flatten(), .chain(
) maybe_fullscreen
.chain(output.cursor_sessions().into_iter()) .map(|w| w.cursor_sessions())
.into_iter()
.flatten(),
)
.chain(output.cursor_sessions().into_iter())
})
} }
fn transform_output_mapped_position<'a, B, E>(output: &Output, event: &E) -> Point<f64, Global> fn transform_output_mapped_position<'a, B, E>(output: &Output, event: &E) -> Point<f64, Global>

View file

@ -146,6 +146,7 @@ impl Shell {
let workspace = if workspace.is_none() { let workspace = if workspace.is_none() {
//should this be the active output or the focused output? //should this be the active output or the focused output?
self.active_space_mut(&seat.focused_or_active_output()) self.active_space_mut(&seat.focused_or_active_output())
.unwrap()
} else { } else {
workspace.unwrap() workspace.unwrap()
}; };
@ -181,7 +182,7 @@ impl Shell {
} }
let output = seat.focused_or_active_output(); let output = seat.focused_or_active_output();
let space = self.active_space(&output); let space = self.active_space(&output).unwrap();
let stack = space.focus_stack.get(seat); let stack = space.focus_stack.get(seat);
stack.last().cloned() stack.last().cloned()
}) })
@ -404,7 +405,7 @@ impl Common {
trace!("Surface dead, focus fixup"); trace!("Surface dead, focus fixup");
} }
} else { } else {
let workspace = shell.active_space(&output); let workspace = shell.active_space(&output).unwrap();
let focus_stack = workspace.focus_stack.get(&seat); let focus_stack = workspace.focus_stack.get(&seat);
if focus_stack.last().is_none() { if focus_stack.last().is_none() {
@ -504,7 +505,7 @@ fn focus_target_is_valid(
.mapped() .mapped()
.any(|m| m == &mapped); .any(|m| m == &mapped);
let workspace = shell.active_space(&output); let workspace = shell.active_space(&output).unwrap();
let focus_stack = workspace.focus_stack.get(&seat); let focus_stack = workspace.focus_stack.get(&seat);
let is_in_focus_stack = focus_stack.last().map(|m| m == &mapped).unwrap_or(false); let is_in_focus_stack = focus_stack.last().map(|m| m == &mapped).unwrap_or(false);
let has_fullscreen = workspace.get_fullscreen().is_some(); let has_fullscreen = workspace.get_fullscreen().is_some();
@ -521,11 +522,12 @@ fn focus_target_is_valid(
KeyboardFocusTarget::Group(WindowGroup { node, .. }) => shell KeyboardFocusTarget::Group(WindowGroup { node, .. }) => shell
.workspaces .workspaces
.active(&output) .active(&output)
.unwrap()
.1 .1
.tiling_layer .tiling_layer
.has_node(&node), .has_node(&node),
KeyboardFocusTarget::Fullscreen(window) => { KeyboardFocusTarget::Fullscreen(window) => {
let workspace = shell.active_space(&output); let workspace = shell.active_space(&output).unwrap();
let focus_stack = workspace.focus_stack.get(&seat); let focus_stack = workspace.focus_stack.get(&seat);
focus_stack focus_stack
@ -560,15 +562,16 @@ fn update_focus_target(
}) })
.cloned() .cloned()
.map(KeyboardFocusTarget::from) .map(KeyboardFocusTarget::from)
} else if let Some(surface) = shell.active_space(&output).get_fullscreen() { } else if let Some(surface) = shell.active_space(&output).unwrap().get_fullscreen() {
Some(KeyboardFocusTarget::Fullscreen(surface.clone())) Some(KeyboardFocusTarget::Fullscreen(surface.clone()))
} else { } else {
shell shell
.active_space(&output) .active_space(&output)
.unwrap()
.focus_stack .focus_stack
.get(&seat) .get(&seat)
.last() .last()
.or_else(|| shell.active_space(&output).mapped().next()) .or_else(|| shell.active_space(&output).unwrap().mapped().next())
.cloned() .cloned()
.map(KeyboardFocusTarget::from) .map(KeyboardFocusTarget::from)
} }

View file

@ -117,7 +117,7 @@ pub fn tab_items(
let mut shell = state.common.shell.write().unwrap(); let mut shell = state.common.shell.write().unwrap();
let seat = shell.seats.last_active().clone(); let seat = shell.seats.last_active().clone();
let output = seat.active_output(); let output = seat.active_output();
let workspace = shell.workspaces.active_mut(&output); let workspace = shell.workspaces.active_mut(&output).unwrap();
if is_tiled { if is_tiled {
for mapped in workspace for mapped in workspace
.mapped() .mapped()

View file

@ -366,6 +366,7 @@ impl MoveGrab {
shell shell
.workspaces .workspaces
.active_mut(&self.cursor_output) .active_mut(&self.cursor_output)
.unwrap()
.tiling_layer .tiling_layer
.cleanup_drag(); .cleanup_drag();
self.cursor_output = current_output.clone(); self.cursor_output = current_output.clone();
@ -763,7 +764,7 @@ impl Drop for MoveGrab {
(grab_state.location.to_i32_round() + grab_state.window_offset).as_global(); (grab_state.location.to_i32_round() + grab_state.window_offset).as_global();
let mut shell = state.common.shell.write().unwrap(); let mut shell = state.common.shell.write().unwrap();
let workspace_handle = shell.active_space(&output).handle; let workspace_handle = shell.active_space(&output).unwrap().handle;
for old_output in window_outputs.iter().filter(|o| *o != &output) { for old_output in window_outputs.iter().filter(|o| *o != &output) {
grab_state.window.output_leave(old_output); grab_state.window.output_leave(old_output);
} }
@ -788,9 +789,12 @@ impl Drop for MoveGrab {
Some((window, location.to_global(&output))) Some((window, location.to_global(&output)))
} }
ManagedLayer::Tiling if shell.active_space(&output).tiling_enabled => { ManagedLayer::Tiling
if shell.active_space(&output).unwrap().tiling_enabled =>
{
let (window, location) = shell let (window, location) = shell
.active_space_mut(&output) .active_space_mut(&output)
.unwrap()
.tiling_layer .tiling_layer
.drop_window(grab_state.window); .drop_window(grab_state.window);
Some((window, location.to_global(&output))) Some((window, location.to_global(&output)))
@ -801,7 +805,7 @@ impl Drop for MoveGrab {
grab_state.window.geometry().size.as_global(), grab_state.window.geometry().size.as_global(),
)); ));
let theme = shell.theme.clone(); let theme = shell.theme.clone();
let workspace = shell.active_space_mut(&output); let workspace = shell.active_space_mut(&output).unwrap();
let (window, location) = workspace.floating_layer.drop_window( let (window, location) = workspace.floating_layer.drop_window(
grab_state.window, grab_state.window,
window_location.to_local(&workspace.output), window_location.to_local(&workspace.output),

View file

@ -222,7 +222,10 @@ impl ResizeForkGrab {
if let Some(output) = self.output.upgrade() { if let Some(output) = self.output.upgrade() {
let mut shell = data.common.shell.write().unwrap(); let mut shell = data.common.shell.write().unwrap();
let tiling_layer = &mut shell.active_space_mut(&output).tiling_layer; let Some(workspace) = shell.active_space_mut(&output) else {
return false;
};
let tiling_layer = &mut workspace.tiling_layer;
let gaps = tiling_layer.gaps(); let gaps = tiling_layer.gaps();
let tree = &mut tiling_layer.queue.trees.back_mut().unwrap().0; let tree = &mut tiling_layer.queue.trees.back_mut().unwrap().0;

View file

@ -973,22 +973,27 @@ impl Workspaces {
.and_then(|set| set.workspaces.get_mut(num)) .and_then(|set| set.workspaces.get_mut(num))
} }
pub fn active(&self, output: &Output) -> (Option<(&Workspace, WorkspaceDelta)>, &Workspace) { pub fn active(
let set = self.sets.get(output).or(self.backup_set.as_ref()).unwrap(); &self,
( output: &Output,
set.previously_active ) -> Option<(Option<(&Workspace, WorkspaceDelta)>, &Workspace)> {
.map(|(idx, start)| (&set.workspaces[idx], start)), self.sets
&set.workspaces[set.active], .get(output)
) .or(self.backup_set.as_ref())
.map(|set| {
(
set.previously_active
.map(|(idx, start)| (&set.workspaces[idx], start)),
&set.workspaces[set.active],
)
})
} }
pub fn active_mut(&mut self, output: &Output) -> &mut Workspace { pub fn active_mut(&mut self, output: &Output) -> Option<&mut Workspace> {
let set = self self.sets
.sets
.get_mut(output) .get_mut(output)
.or(self.backup_set.as_mut()) .or(self.backup_set.as_mut())
.unwrap(); .map(|set| &mut set.workspaces[set.active])
&mut set.workspaces[set.active]
} }
pub fn active_num(&self, output: &Output) -> (Option<usize>, usize) { pub fn active_num(&self, output: &Output) -> (Option<usize>, usize) {
@ -1434,11 +1439,11 @@ impl Shell {
} }
} }
pub fn active_space(&self, output: &Output) -> &Workspace { pub fn active_space(&self, output: &Output) -> Option<&Workspace> {
self.workspaces.active(output).1 self.workspaces.active(output).map(|(_, active)| active)
} }
pub fn active_space_mut(&mut self, output: &Output) -> &mut Workspace { pub fn active_space_mut(&mut self, output: &Output) -> Option<&mut Workspace> {
self.workspaces.active_mut(output) self.workspaces.active_mut(output)
} }
@ -1494,7 +1499,7 @@ impl Shell {
.mapped() .mapped()
.any(|m| m == &elem); .any(|m| m == &elem);
let workspace = self.active_space(output); let workspace = self.active_space(output).unwrap();
let is_mapped = workspace.mapped().any(|m| m == &elem); let is_mapped = workspace.mapped().any(|m| m == &elem);
is_sticky || is_mapped is_sticky || is_mapped
@ -1504,7 +1509,7 @@ impl Shell {
KeyboardFocusTarget::Fullscreen(elem) => self KeyboardFocusTarget::Fullscreen(elem) => self
.outputs() .outputs()
.find(|output| { .find(|output| {
let workspace = self.active_space(&output); let workspace = self.active_space(&output).unwrap();
workspace.get_fullscreen() == Some(&elem) workspace.get_fullscreen() == Some(&elem)
}) })
.cloned(), .cloned(),
@ -1513,6 +1518,7 @@ impl Shell {
.find(|output| { .find(|output| {
self.workspaces self.workspaces
.active(&output) .active(&output)
.unwrap()
.1 .1
.tiling_layer .tiling_layer
.has_node(&node) .has_node(&node)
@ -1574,9 +1580,9 @@ impl Shell {
output: &Output, output: &Output,
xdg_activation_state: &XdgActivationState, xdg_activation_state: &XdgActivationState,
) { ) {
self.workspaces if let Some(w) = self.workspaces.active_mut(output) {
.active_mut(output) w.refresh(xdg_activation_state)
.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<&Output> {
@ -1635,6 +1641,7 @@ impl Shell {
.or_else(|| { .or_else(|| {
self.outputs().find(|o| { self.outputs().find(|o| {
self.active_space(o) self.active_space(o)
.unwrap()
.mapped() .mapped()
.any(|e| e.has_surface(surface, WindowSurfaceType::ALL)) .any(|e| e.has_surface(surface, WindowSurfaceType::ALL))
}) })
@ -1904,10 +1911,10 @@ impl Shell {
.get(output) .get(output)
.and_then(|set| set.sticky_layer.stacking_indicator()), .and_then(|set| set.sticky_layer.stacking_indicator()),
ManagedLayer::Floating => self ManagedLayer::Floating => self
.active_space(output) .active_space(output)?
.floating_layer .floating_layer
.stacking_indicator(), .stacking_indicator(),
ManagedLayer::Tiling => self.active_space(output).tiling_layer.stacking_indicator(), ManagedLayer::Tiling => self.active_space(output)?.tiling_layer.stacking_indicator(),
} }
} }
@ -2092,7 +2099,7 @@ impl Shell {
.find(|space| space.handle == handle) .find(|space| space.handle == handle)
.unwrap() .unwrap()
} else { } else {
self.workspaces.active_mut(&output) self.workspaces.active_mut(&output).unwrap() // a seat's active output always has a workspace
}; };
if output != workspace.output { if output != workspace.output {
output = workspace.output.clone(); output = workspace.output.clone();
@ -2110,7 +2117,7 @@ impl Shell {
self.remap_unfullscreened_window(mapped, &old_handle, &new_workspace_handle, layer); self.remap_unfullscreened_window(mapped, &old_handle, &new_workspace_handle, layer);
}; };
let active_handle = self.active_space(&output).handle; let active_handle = self.active_space(&output).unwrap().handle;
let workspace = if let Some(handle) = workspace_handle.filter(|handle| { let workspace = if let Some(handle) = workspace_handle.filter(|handle| {
self.workspaces self.workspaces
.spaces() .spaces()
@ -2121,7 +2128,7 @@ impl Shell {
.find(|space| space.handle == handle) .find(|space| space.handle == handle)
.unwrap() .unwrap()
} else { } else {
self.workspaces.active_mut(&output) self.workspaces.active_mut(&output).unwrap()
}; };
toplevel_info.new_toplevel(&window, workspace_state); toplevel_info.new_toplevel(&window, workspace_state);
@ -2203,7 +2210,7 @@ impl Shell {
None None
}; };
let active_space = self.active_space(&output); let active_space = self.active_space(&output).unwrap();
for mapped in active_space.mapped() { for mapped in active_space.mapped() {
self.update_reactive_popups(mapped); self.update_reactive_popups(mapped);
} }
@ -2448,7 +2455,10 @@ impl Shell {
.map(|ws| ws.handle) .map(|ws| ws.handle)
.ok_or(InvalidWorkspaceIndex)?; .ok_or(InvalidWorkspaceIndex)?;
let from_workspace = self.workspaces.active_mut(from_output); let from_workspace = self
.workspaces
.active_mut(from_output)
.ok_or(InvalidWorkspaceIndex)?;
let last_focused_window = from_workspace.focus_stack.get(seat).last().cloned(); let last_focused_window = from_workspace.focus_stack.get(seat).last().cloned();
let from = from_workspace.handle; let from = from_workspace.handle;
@ -2816,7 +2826,7 @@ impl Shell {
( (
initial_window_location, initial_window_location,
ManagedLayer::Sticky, ManagedLayer::Sticky,
self.active_space(&cursor_output).handle, self.active_space(&cursor_output).unwrap().handle,
) )
} else { } else {
return None; return None;
@ -2896,7 +2906,7 @@ impl Shell {
return FocusResult::None; return FocusResult::None;
}; };
let output = seat.active_output(); let output = seat.active_output();
let workspace = self.active_space(&output); let workspace = self.active_space(&output).unwrap();
if workspace.fullscreen.is_some() { if workspace.fullscreen.is_some() {
return FocusResult::None; return FocusResult::None;
@ -3051,7 +3061,7 @@ impl Shell {
let Some(output) = seat.focused_output() else { let Some(output) = seat.focused_output() else {
return MoveResult::None; return MoveResult::None;
}; };
let workspace = self.active_space(&output); let workspace = self.active_space(&output).unwrap();
let focus_stack = workspace.focus_stack.get(seat); let focus_stack = workspace.focus_stack.get(seat);
let Some(last) = focus_stack.last().cloned() else { let Some(last) = focus_stack.last().cloned() else {
return MoveResult::None; return MoveResult::None;
@ -3084,7 +3094,7 @@ impl Shell {
) )
} else { } else {
let theme = self.theme.clone(); let theme = self.theme.clone();
let workspace = self.active_space_mut(&output); let workspace = self.active_space_mut(&output).unwrap();
workspace workspace
.floating_layer .floating_layer
.move_current_element(direction, seat, ManagedLayer::Floating, theme) .move_current_element(direction, seat, ManagedLayer::Floating, theme)
@ -3697,16 +3707,20 @@ impl Shell {
) -> OutputPresentationFeedback { ) -> OutputPresentationFeedback {
let mut output_presentation_feedback = OutputPresentationFeedback::new(output); let mut output_presentation_feedback = OutputPresentationFeedback::new(output);
let active = self.active_space(output); if let Some(active) = self.active_space(output) {
active.mapped().for_each(|mapped| { active.mapped().for_each(|mapped| {
mapped.active_window().take_presentation_feedback( mapped.active_window().take_presentation_feedback(
&mut output_presentation_feedback, &mut output_presentation_feedback,
surface_primary_scanout_output, surface_primary_scanout_output,
|surface, _| { |surface, _| {
surface_presentation_feedback_flags_from_states(surface, render_element_states) surface_presentation_feedback_flags_from_states(
}, surface,
); render_element_states,
}); )
},
);
});
}
self.override_redirect_windows.iter().for_each(|or| { self.override_redirect_windows.iter().for_each(|or| {
if let Some(wl_surface) = or.wl_surface() { if let Some(wl_surface) = or.wl_surface() {

View file

@ -862,25 +862,26 @@ impl Common {
} }
}); });
let active = shell.active_space(output); if let Some(active) = shell.active_space(output) {
active.mapped().for_each(|mapped| { active.mapped().for_each(|mapped| {
for (window, _) in mapped.windows() { for (window, _) in mapped.windows() {
if let Some(feedback) = window if let Some(feedback) = window
.wl_surface() .wl_surface()
.and_then(|wl_surface| { .and_then(|wl_surface| {
advertised_node_for_surface(&wl_surface, &self.display_handle) advertised_node_for_surface(&wl_surface, &self.display_handle)
}) })
.and_then(|source| dmabuf_feedback(source)) .and_then(|source| dmabuf_feedback(source))
{ {
window.send_dmabuf_feedback( window.send_dmabuf_feedback(
output, output,
&feedback, &feedback,
render_element_states, render_element_states,
surface_primary_scanout_output, surface_primary_scanout_output,
); );
}
} }
} });
}); }
shell.override_redirect_windows.iter().for_each(|or| { shell.override_redirect_windows.iter().for_each(|or| {
if let Some(wl_surface) = or.wl_surface() { if let Some(wl_surface) = or.wl_surface() {
@ -1041,35 +1042,37 @@ impl Common {
} }
}); });
let active = shell.active_space(output); if let Some(active) = shell.active_space(output) {
active.mapped().for_each(|mapped| { active.mapped().for_each(|mapped| {
for (window, _) in mapped.windows() {
window.send_frame(output, time, throttle(&window), should_send);
}
});
// other (throttled) windows
active.minimized_windows.iter().for_each(|m| {
for (window, _) in m.window.windows() {
window.send_frame(output, time, throttle(&window), |_, _| None);
}
});
for space in shell
.workspaces
.spaces_for_output(output)
.filter(|w| w.handle != active.handle)
{
space.mapped().for_each(|mapped| {
for (window, _) in mapped.windows() { for (window, _) in mapped.windows() {
let throttle = min(throttle(space), throttle(&window)); window.send_frame(output, time, throttle(&window), should_send);
window.send_frame(output, time, throttle, |_, _| None);
} }
}); });
space.minimized_windows.iter().for_each(|m| {
// other (throttled) windows
active.minimized_windows.iter().for_each(|m| {
for (window, _) in m.window.windows() { for (window, _) in m.window.windows() {
window.send_frame(output, time, throttle(&window), |_, _| None); window.send_frame(output, time, throttle(&window), |_, _| None);
} }
}) });
for space in shell
.workspaces
.spaces_for_output(output)
.filter(|w| w.handle != active.handle)
{
space.mapped().for_each(|mapped| {
for (window, _) in mapped.windows() {
let throttle = min(throttle(space), throttle(&window));
window.send_frame(output, time, throttle, |_, _| None);
}
});
space.minimized_windows.iter().for_each(|m| {
for (window, _) in m.window.windows() {
window.send_frame(output, time, throttle(&window), |_, _| None);
}
})
}
} }
shell.override_redirect_windows.iter().for_each(|or| { shell.override_redirect_windows.iter().for_each(|or| {

View file

@ -148,9 +148,10 @@ impl ToplevelManagementHandler for State {
let mut shell = self.common.shell.write().unwrap(); let mut shell = self.common.shell.write().unwrap();
let seat = shell.seats.last_active().clone(); let seat = shell.seats.last_active().clone();
if let Some(mapped) = shell.element_for_surface(window).cloned() { if let Some(mapped) = shell.element_for_surface(window).cloned() {
if let Some(output) = output { if let Some((output, workspace)) =
output.and_then(|output| shell.workspaces.active_mut(&output).map(|w| (output, w)))
{
let from = minimize_rectangle(&output, window); let from = minimize_rectangle(&output, window);
let workspace = shell.workspaces.active_mut(&output);
workspace.fullscreen_request(window, None, from, &seat); workspace.fullscreen_request(window, None, from, &seat);
} else if let Some((output, handle)) = shell } else if let Some((output, handle)) = shell
.space_for(&mapped) .space_for(&mapped)

View file

@ -42,7 +42,7 @@ impl XdgActivationHandler for State {
if let Some(seat) = data.serial.and_then(|(_, seat)| Seat::from_resource(&seat)) { if let Some(seat) = data.serial.and_then(|(_, seat)| Seat::from_resource(&seat)) {
let output = seat.active_output(); let output = seat.active_output();
let mut shell = self.common.shell.write().unwrap(); let mut shell = self.common.shell.write().unwrap();
let workspace = shell.active_space_mut(&output); let workspace = shell.active_space_mut(&output).unwrap();
workspace.pending_tokens.insert(token.clone()); workspace.pending_tokens.insert(token.clone());
let handle = workspace.handle; let handle = workspace.handle;
data.user_data data.user_data
@ -86,7 +86,7 @@ impl XdgActivationHandler for State {
if valid { if valid {
let output = seat.active_output(); let output = seat.active_output();
let mut shell = self.common.shell.write().unwrap(); let mut shell = self.common.shell.write().unwrap();
let workspace = shell.active_space_mut(&output); let workspace = shell.active_space_mut(&output).unwrap();
workspace.pending_tokens.insert(token.clone()); workspace.pending_tokens.insert(token.clone());
let handle = workspace.handle; let handle = workspace.handle;
data.user_data data.user_data
@ -125,7 +125,7 @@ impl XdgActivationHandler for State {
} }
let element_workspace = shell.space_for(&element).map(|w| w.handle.clone()); let element_workspace = shell.space_for(&element).map(|w| w.handle.clone());
let current_workspace = shell.active_space_mut(&current_output); let current_workspace = shell.active_space_mut(&current_output).unwrap();
let in_current_workspace = element_workspace let in_current_workspace = element_workspace
.as_ref() .as_ref()

View file

@ -270,13 +270,13 @@ impl XdgShellHandler for State {
mapped mapped
}; };
let workspace_handle = shell.active_space(&output).handle.clone(); let workspace_handle = shell.active_space(&output).unwrap().handle.clone();
for (window, _) in mapped.windows() { for (window, _) in mapped.windows() {
toplevel_enter_output(&window, &output); toplevel_enter_output(&window, &output);
toplevel_enter_workspace(&window, &workspace_handle); toplevel_enter_workspace(&window, &workspace_handle);
} }
let workspace = shell.active_space_mut(&output); let workspace = shell.active_space_mut(&output).unwrap();
workspace.floating_layer.map(mapped.clone(), None); workspace.floating_layer.map(mapped.clone(), None);
workspace.fullscreen_request( workspace.fullscreen_request(
@ -316,13 +316,13 @@ impl XdgShellHandler for State {
}; };
let handle = workspace.handle.clone(); let handle = workspace.handle.clone();
let workspace_handle = shell.active_space(&output).handle.clone(); let workspace_handle = shell.active_space(&output).unwrap().handle.clone();
for (window, _) in mapped.windows() { for (window, _) in mapped.windows() {
toplevel_enter_output(&window, &output); toplevel_enter_output(&window, &output);
toplevel_enter_workspace(&window, &workspace_handle); toplevel_enter_workspace(&window, &workspace_handle);
} }
let workspace = shell.active_space_mut(&output); let workspace = shell.active_space_mut(&output).unwrap();
workspace.floating_layer.map(mapped.clone(), None); workspace.floating_layer.map(mapped.clone(), None);
workspace.fullscreen_request( workspace.fullscreen_request(