From bb07ab4155723d92dd4e247765ce0384d54762bb Mon Sep 17 00:00:00 2001 From: Victoria Brekenfeld Date: Mon, 24 Oct 2022 18:32:53 +0200 Subject: [PATCH] shell: Support maximize and fullscreen requests --- src/shell/element/mod.rs | 6 + src/shell/layout/floating/mod.rs | 46 ++++---- src/shell/layout/tiling/mod.rs | 2 +- src/shell/workspace.rs | 152 +++++++++++++++----------- src/wayland/handlers/xdg_shell/mod.rs | 63 ++++++++--- 5 files changed, 166 insertions(+), 103 deletions(-) diff --git a/src/shell/element/mod.rs b/src/shell/element/mod.rs index 20096d06..c0727b3b 100644 --- a/src/shell/element/mod.rs +++ b/src/shell/element/mod.rs @@ -107,6 +107,12 @@ impl CosmicMapped { } } + pub fn set_active(&self, window: &Window) { + if let CosmicMappedInternal::Stack(stack) = &self.element { + stack.set_active(window); + } + } + pub fn focus_window(&self, window: &Window) { match &self.element { CosmicMappedInternal::Stack(stack) => stack.set_active(window), diff --git a/src/shell/layout/floating/mod.rs b/src/shell/layout/floating/mod.rs index a64539c0..399f8cc9 100644 --- a/src/shell/layout/floating/mod.rs +++ b/src/shell/layout/floating/mod.rs @@ -155,30 +155,34 @@ impl FloatingLayout { self.space.element_geometry(elem) } - pub fn maximize_request(&mut self, window: &CosmicMapped, output: &Output) { - let layers = layer_map_for_output(&output); - let geometry = layers.non_exclusive_zone(); - - if let Some(location) = self.space.element_location(window) { - *window.last_geometry.lock().unwrap() = Some(Rectangle::from_loc_and_size( - location, - window.geometry().size, - )); + pub fn maximize_request(&mut self, window: &Window) { + if let Some(mapped) = self + .space + .elements() + .find(|m| m.windows().any(|(w, _)| &w == window)) + { + if let Some(location) = self.space.element_location(mapped) { + *mapped.last_geometry.lock().unwrap() = Some(Rectangle::from_loc_and_size( + location, + mapped.geometry().size, + )); + } } - - self.space.map_element(window.clone(), geometry.loc, true); - window.set_maximized(true); - window.set_size(geometry.size); - window.configure(); } - pub fn unmaximize_request(&mut self, window: &CosmicMapped) { - let last_geometry = window.last_geometry.lock().unwrap().clone(); - window.set_maximized(false); - window.set_size(last_geometry.map(|g| g.size).expect("No previous size?")); - window.configure(); - let last_location = last_geometry.map(|g| g.loc).expect("No previous location?"); - self.space.map_element(window.clone(), last_location, true); + pub fn unmaximize_request(&mut self, window: &Window) { + let maybe_mapped = self + .space + .elements() + .find(|m| m.windows().any(|(w, _)| &w == window)) + .cloned(); + + if let Some(mapped) = maybe_mapped { + let last_geometry = mapped.last_geometry.lock().unwrap().clone(); + mapped.set_size(last_geometry.map(|g| g.size).expect("No previous size?")); + let last_location = last_geometry.map(|g| g.loc).expect("No previous location?"); + self.space.map_element(mapped, last_location, true); + } } /* diff --git a/src/shell/layout/tiling/mod.rs b/src/shell/layout/tiling/mod.rs index 91a03aa9..87ee2fd1 100644 --- a/src/shell/layout/tiling/mod.rs +++ b/src/shell/layout/tiling/mod.rs @@ -795,7 +795,7 @@ impl TilingLayout { } }, Data::Mapped { mapped, .. } => { - if !mapped.is_fullscreen() { + if !(mapped.is_fullscreen() || mapped.is_maximized()) { mapped.set_tiled(true); mapped.set_size( (geo.size.w - inner * 2, geo.size.h - inner * 2).into(), diff --git a/src/shell/workspace.rs b/src/shell/workspace.rs index 1285a96a..2f8c4bcd 100644 --- a/src/shell/workspace.rs +++ b/src/shell/workspace.rs @@ -157,26 +157,103 @@ impl Workspace { }) } - /* - pub fn maximize_request(&mut self, window: &CosmicWindow, output: &Output) { - if self.fullscreen.values().any(|w| w == window) { + pub fn maximize_request(&mut self, window: &Window, output: &Output) { + if self.fullscreen.contains_key(output) { return; } - if self.floating_layer.windows.contains(window) { - self.floating_layer - .maximize_request(, window, output); + + self.floating_layer.maximize_request(window); + + #[allow(irrefutable_let_patterns)] + if let Kind::Xdg(xdg) = &window.toplevel() { + xdg.with_pending_state(|state| { + state.states.set(xdg_toplevel::State::Maximized); + state.states.unset(xdg_toplevel::State::Fullscreen); + }); } + + self.set_fullscreen(window, output) } - pub fn unmaximize_request(&mut self, window: &CosmicMapped) { + pub fn unmaximize_request(&mut self, window: &Window) { if self.fullscreen.values().any(|w| w == window) { + self.floating_layer.unmaximize_request(window); return self.unfullscreen_request(window); } - if self.floating_layer.windows.contains(window) { - self.floating_layer - .unmaximize_request(window); - } } + pub fn fullscreen_request(&mut self, window: &Window, output: &Output) { + if self.fullscreen.contains_key(output) { + return; + } + + #[allow(irrefutable_let_patterns)] + if let Kind::Xdg(xdg) = &window.toplevel() { + xdg.with_pending_state(|state| { + state.states.set(xdg_toplevel::State::Fullscreen); + state.states.unset(xdg_toplevel::State::Maximized); + }); + } + + self.set_fullscreen(window, output) + } + + fn set_fullscreen(&mut self, window: &Window, output: &Output) { + if let Some(mapped) = self + .mapped() + .find(|m| m.windows().any(|(w, _)| &w == window)) + { + mapped.set_active(window); + } + + #[allow(irrefutable_let_patterns)] + if let Kind::Xdg(xdg) = &window.toplevel() { + xdg.with_pending_state(|state| { + state.size = Some( + output + .current_mode() + .map(|m| m.size) + .unwrap_or((0, 0).into()) + .to_f64() + .to_logical(output.current_scale().fractional_scale()) + .to_i32_round(), + ); + }); + + xdg.send_configure(); + } + self.fullscreen.insert(output.clone(), window.clone()); + } + + pub fn unfullscreen_request(&mut self, window: &Window) { + if self.fullscreen.values().any(|w| w == window) { + #[allow(irrefutable_let_patterns)] + if let Kind::Xdg(xdg) = &window.toplevel() { + xdg.with_pending_state(|state| { + state.states.unset(xdg_toplevel::State::Fullscreen); + state.states.unset(xdg_toplevel::State::Maximized); + state.size = None; + }); + self.floating_layer.refresh(); + self.tiling_layer.refresh(); + xdg.send_configure(); + } + self.fullscreen.retain(|_, w| w != window); + } + } + + pub fn fullscreen_toggle(&mut self, window: &Window, output: &Output) { + if self.fullscreen.contains_key(output) { + self.unfullscreen_request(window) + } else { + self.fullscreen_request(window, output) + } + } + + pub fn get_fullscreen(&self, output: &Output) -> Option<&Window> { + self.fullscreen.get(output).filter(|w| w.alive()) + } + + /* pub fn resize_request( state: &mut State, surface: &WlSurface, @@ -203,59 +280,6 @@ impl Workspace { } */ - pub fn fullscreen_request(&mut self, window: &Window, output: &Output) { - if self.fullscreen.contains_key(output) { - return; - } - - #[allow(irrefutable_let_patterns)] - if let Kind::Xdg(xdg) = &window.toplevel() { - xdg.with_pending_state(|state| { - state.states.set(xdg_toplevel::State::Fullscreen); - state.size = Some( - output - .current_mode() - .map(|m| m.size) - .unwrap_or((0, 0).into()) - .to_f64() - .to_logical(output.current_scale().fractional_scale()) - .to_i32_round(), - ); - }); - - xdg.send_configure(); - self.fullscreen.insert(output.clone(), window.clone()); - } - } - - pub fn unfullscreen_request(&mut self, window: &Window) { - if self.fullscreen.values().any(|w| w == window) { - #[allow(irrefutable_let_patterns)] - if let Kind::Xdg(xdg) = &window.toplevel() { - xdg.with_pending_state(|state| { - state.states.unset(xdg_toplevel::State::Fullscreen); - state.size = None; - }); - self.floating_layer.refresh(); - self.tiling_layer.refresh(); - xdg.send_configure(); - } - self.fullscreen.retain(|_, w| w != window); - } - } - - pub fn fullscreen_toggle(&mut self, window: &Window, output: &Output) { - if self.fullscreen.contains_key(output) { - self.unfullscreen_request(window) - } else { - self.fullscreen_request(window, output) - } - } - - pub fn get_fullscreen(&self, output: &Output) -> Option<&Window> { - self.fullscreen.get(output).filter(|w| w.alive()) - } - pub fn toggle_tiling(&mut self, seat: &Seat) { if self.tiling_enabled { for window in self diff --git a/src/wayland/handlers/xdg_shell/mod.rs b/src/wayland/handlers/xdg_shell/mod.rs index e049710b..083ae411 100644 --- a/src/wayland/handlers/xdg_shell/mod.rs +++ b/src/wayland/handlers/xdg_shell/mod.rs @@ -176,23 +176,38 @@ impl XdgShellHandler for State { } fn maximize_request(&mut self, surface: ToplevelSurface) { - let surface = surface.wl_surface(); let seat = self.common.last_active_seat(); let output = seat.active_output(); - if let Some(mapped) = self.common.shell.element_for_surface(surface).cloned() { + if let Some(mapped) = self + .common + .shell + .element_for_surface(surface.wl_surface()) + .cloned() + { if let Some(workspace) = self.common.shell.space_for_mut(&mapped) { - //workspace.maximize_request(mapped, &output) + let (window, _) = mapped + .windows() + .find(|(w, _)| matches!(w.toplevel(), Kind::Xdg(s) if s == &surface)) + .unwrap(); + workspace.maximize_request(&window, &output) } } } fn unmaximize_request(&mut self, surface: ToplevelSurface) { - let surface = surface.wl_surface(); - - if let Some(mapped) = self.common.shell.element_for_surface(surface).cloned() { + if let Some(mapped) = self + .common + .shell + .element_for_surface(surface.wl_surface()) + .cloned() + { if let Some(workspace) = self.common.shell.space_for_mut(&mapped) { - //workspace.unmaximize_request(mapped, &output) + let (window, _) = mapped + .windows() + .find(|(w, _)| matches!(w.toplevel(), Kind::Xdg(s) if s == &surface)) + .unwrap(); + workspace.unmaximize_request(&window) } } } @@ -206,22 +221,36 @@ impl XdgShellHandler for State { seat.active_output() }); - let surface = surface.wl_surface(); - if let Some(mapped) = self.common.shell.element_for_surface(surface).cloned() { + if let Some(mapped) = self + .common + .shell + .element_for_surface(surface.wl_surface()) + .cloned() + { if let Some(workspace) = self.common.shell.space_for_mut(&mapped) { - workspace.fullscreen_request(&mapped.active_window(), &output) + let (window, _) = mapped + .windows() + .find(|(w, _)| matches!(w.toplevel(), Kind::Xdg(s) if s == &surface)) + .unwrap(); + workspace.fullscreen_request(&window, &output) } } } fn unfullscreen_request(&mut self, surface: ToplevelSurface) { - if let Some((workspace, window)) = self.common.shell.workspaces.spaces_mut().find_map(|w| { - let window = w - .windows() - .find(|w| w.toplevel().wl_surface() == surface.wl_surface()); - window.map(|win| (w, win)) - }) { - workspace.unfullscreen_request(&window) + if let Some(mapped) = self + .common + .shell + .element_for_surface(surface.wl_surface()) + .cloned() + { + if let Some(workspace) = self.common.shell.space_for_mut(&mapped) { + let (window, _) = mapped + .windows() + .find(|(w, _)| matches!(w.toplevel(), Kind::Xdg(s) if s == &surface)) + .unwrap(); + workspace.unfullscreen_request(&window) + } } } }