From fc4dd9d62e7206aee845f791f6410be8cbaac6d6 Mon Sep 17 00:00:00 2001 From: Ottatop Date: Tue, 18 Jun 2024 14:32:06 -0500 Subject: [PATCH] Take snapshot on foreign toplevel tag change --- src/handlers.rs | 116 +-------------------------- src/handlers/foreign_toplevel.rs | 130 +++++++++++++++++++++++++++++++ src/render/util/snapshot.rs | 4 +- 3 files changed, 136 insertions(+), 114 deletions(-) create mode 100644 src/handlers/foreign_toplevel.rs diff --git a/src/handlers.rs b/src/handlers.rs index 9477b9e..01059df 100644 --- a/src/handlers.rs +++ b/src/handlers.rs @@ -1,5 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-or-later +mod foreign_toplevel; pub mod idle; pub mod session_lock; pub mod window; @@ -73,13 +74,12 @@ use tracing::{debug, error, trace, warn}; use crate::{ backend::Backend, - delegate_foreign_toplevel, delegate_gamma_control, delegate_output_management, - delegate_output_power_management, delegate_screencopy, + delegate_gamma_control, delegate_output_management, delegate_output_power_management, + delegate_screencopy, focus::{keyboard::KeyboardFocusTarget, pointer::PointerFocusTarget}, handlers::xdg_shell::snapshot_pre_commit_hook, output::OutputMode, protocol::{ - foreign_toplevel::{self, ForeignToplevelHandler, ForeignToplevelManagerState}, gamma_control::{GammaControlHandler, GammaControlManagerState}, output_management::{ OutputConfiguration, OutputManagementHandler, OutputManagementManagerState, @@ -591,7 +591,7 @@ delegate_shm!(State); impl OutputHandler for State { fn output_bound(&mut self, output: Output, wl_output: WlOutput) { - foreign_toplevel::on_output_bound(self, &output, &wl_output); + crate::protocol::foreign_toplevel::on_output_bound(self, &output, &wl_output); } } delegate_output!(State); @@ -817,114 +817,6 @@ impl PointerConstraintsHandler for State { } delegate_pointer_constraints!(State); -impl ForeignToplevelHandler for State { - fn foreign_toplevel_manager_state(&mut self) -> &mut ForeignToplevelManagerState { - &mut self.pinnacle.foreign_toplevel_manager_state - } - - fn activate(&mut self, wl_surface: WlSurface) { - let Some(window) = self.pinnacle.window_for_surface(&wl_surface) else { - return; - }; - let Some(output) = window.output(&self.pinnacle) else { - return; - }; - - if !window.is_on_active_tag() { - let new_active_tag = - window.with_state(|state| state.tags.iter().min_by_key(|tag| tag.id().0).cloned()); - if let Some(tag) = new_active_tag { - output.with_state(|state| { - if state.tags.contains(&tag) { - for op_tag in state.tags.iter() { - op_tag.set_active(false, &mut self.pinnacle); - } - tag.set_active(true, &mut self.pinnacle); - } - }); - } - } - - output.with_state_mut(|state| state.focus_stack.set_focus(window.clone())); - self.pinnacle.raise_window(window, true); - self.update_keyboard_focus(&output); - - self.pinnacle.request_layout(&output); - self.schedule_render(&output); - } - - fn close(&mut self, wl_surface: WlSurface) { - let Some(window) = self.pinnacle.window_for_surface(&wl_surface) else { - return; - }; - - window.close(); - } - - fn set_fullscreen(&mut self, wl_surface: WlSurface, _wl_output: Option) { - let Some(window) = self.pinnacle.window_for_surface(&wl_surface) else { - return; - }; - - self.set_window_fullscreen(&window, true); - } - - fn unset_fullscreen(&mut self, wl_surface: WlSurface) { - let Some(window) = self.pinnacle.window_for_surface(&wl_surface) else { - return; - }; - - self.set_window_fullscreen(&window, false); - } - - fn set_maximized(&mut self, wl_surface: WlSurface) { - let Some(window) = self.pinnacle.window_for_surface(&wl_surface) else { - return; - }; - - self.set_window_maximized(&window, true); - } - - fn unset_maximized(&mut self, wl_surface: WlSurface) { - let Some(window) = self.pinnacle.window_for_surface(&wl_surface) else { - return; - }; - - self.set_window_maximized(&window, false); - } - - fn set_minimized(&mut self, wl_surface: WlSurface) { - let Some(window) = self.pinnacle.window_for_surface(&wl_surface) else { - return; - }; - - window.with_state_mut(|state| state.minimized = true); - - let Some(output) = window.output(&self.pinnacle) else { - return; - }; - - self.pinnacle.request_layout(&output); - self.schedule_render(&output); - } - - fn unset_minimized(&mut self, wl_surface: WlSurface) { - let Some(window) = self.pinnacle.window_for_surface(&wl_surface) else { - return; - }; - - window.with_state_mut(|state| state.minimized = false); - - let Some(output) = window.output(&self.pinnacle) else { - return; - }; - - self.pinnacle.request_layout(&output); - self.schedule_render(&output); - } -} -delegate_foreign_toplevel!(State); - impl XWaylandShellHandler for State { fn xwayland_shell_state(&mut self) -> &mut XWaylandShellState { &mut self.pinnacle.xwayland_shell_state diff --git a/src/handlers/foreign_toplevel.rs b/src/handlers/foreign_toplevel.rs new file mode 100644 index 0000000..234628e --- /dev/null +++ b/src/handlers/foreign_toplevel.rs @@ -0,0 +1,130 @@ +use smithay::reexports::wayland_server::protocol::{wl_output::WlOutput, wl_surface::WlSurface}; + +use crate::{ + delegate_foreign_toplevel, + protocol::foreign_toplevel::{ForeignToplevelHandler, ForeignToplevelManagerState}, + render::util::snapshot::capture_snapshots_on_output, + state::{State, WithState}, +}; + +impl ForeignToplevelHandler for State { + fn foreign_toplevel_manager_state(&mut self) -> &mut ForeignToplevelManagerState { + &mut self.pinnacle.foreign_toplevel_manager_state + } + + fn activate(&mut self, wl_surface: WlSurface) { + let Some(window) = self.pinnacle.window_for_surface(&wl_surface) else { + return; + }; + let Some(output) = window.output(&self.pinnacle) else { + return; + }; + + if !window.is_on_active_tag() { + let new_active_tag = + window.with_state(|state| state.tags.iter().min_by_key(|tag| tag.id().0).cloned()); + if let Some(tag) = new_active_tag { + let snapshots = self.backend.with_renderer(|renderer| { + capture_snapshots_on_output(&mut self.pinnacle, renderer, &output, []) + }); + + output.with_state(|state| { + if state.tags.contains(&tag) { + for op_tag in state.tags.iter() { + op_tag.set_active(false, &mut self.pinnacle); + } + tag.set_active(true, &mut self.pinnacle); + } + }); + + if let Some((above, below)) = snapshots { + output.with_state_mut(|state| { + state.new_wait_layout_transaction( + self.pinnacle.loop_handle.clone(), + above, + below, + ) + }); + } + } + } + + output.with_state_mut(|state| state.focus_stack.set_focus(window.clone())); + self.pinnacle.raise_window(window, true); + self.update_keyboard_focus(&output); + + self.pinnacle.request_layout(&output); + self.schedule_render(&output); + } + + fn close(&mut self, wl_surface: WlSurface) { + let Some(window) = self.pinnacle.window_for_surface(&wl_surface) else { + return; + }; + + window.close(); + } + + fn set_fullscreen(&mut self, wl_surface: WlSurface, _wl_output: Option) { + let Some(window) = self.pinnacle.window_for_surface(&wl_surface) else { + return; + }; + + self.set_window_fullscreen(&window, true); + } + + fn unset_fullscreen(&mut self, wl_surface: WlSurface) { + let Some(window) = self.pinnacle.window_for_surface(&wl_surface) else { + return; + }; + + self.set_window_fullscreen(&window, false); + } + + fn set_maximized(&mut self, wl_surface: WlSurface) { + let Some(window) = self.pinnacle.window_for_surface(&wl_surface) else { + return; + }; + + self.set_window_maximized(&window, true); + } + + fn unset_maximized(&mut self, wl_surface: WlSurface) { + let Some(window) = self.pinnacle.window_for_surface(&wl_surface) else { + return; + }; + + self.set_window_maximized(&window, false); + } + + fn set_minimized(&mut self, wl_surface: WlSurface) { + let Some(window) = self.pinnacle.window_for_surface(&wl_surface) else { + return; + }; + + window.with_state_mut(|state| state.minimized = true); + + let Some(output) = window.output(&self.pinnacle) else { + return; + }; + + self.pinnacle.request_layout(&output); + self.schedule_render(&output); + } + + fn unset_minimized(&mut self, wl_surface: WlSurface) { + let Some(window) = self.pinnacle.window_for_surface(&wl_surface) else { + return; + }; + + window.with_state_mut(|state| state.minimized = false); + + let Some(output) = window.output(&self.pinnacle) else { + return; + }; + + self.pinnacle.request_layout(&output); + self.schedule_render(&output); + } +} +delegate_foreign_toplevel!(State); diff --git a/src/render/util/snapshot.rs b/src/render/util/snapshot.rs index 67ced01..35df451 100644 --- a/src/render/util/snapshot.rs +++ b/src/render/util/snapshot.rs @@ -17,7 +17,7 @@ use smithay::{ }, utils::{Physical, Point, Scale, Transform}, }; -use tracing::error; +use tracing::debug; use crate::layout::transaction::{LayoutSnapshot, SnapshotRenderElement, SnapshotTarget}; use crate::render::texture::CommonTextureRenderElement; @@ -84,7 +84,7 @@ impl> RenderSnapshot { ) { Ok(tex) => tex, Err(err) => { - error!("Failed to render to encompassing texture: {err}"); + debug!("Failed to render to encompassing texture: {err}"); return None; } };