From 1342c000ab2ace13de83a4c0bf0c0715219a031d Mon Sep 17 00:00:00 2001 From: Ian Douglas Scott Date: Wed, 28 Aug 2024 15:04:00 -0700 Subject: [PATCH] Add `ext-foreign-toplevel-list-v1` protocol --- Cargo.lock | 2 +- Cargo.toml | 2 +- src/shell/mod.rs | 12 +++- src/state.rs | 5 ++ src/wayland/handlers/compositor.rs | 1 + src/wayland/handlers/foreign_toplevel_list.rs | 68 +++++++++++++++++++ src/wayland/handlers/mod.rs | 1 + src/wayland/handlers/xdg_shell/mod.rs | 1 + src/xwayland.rs | 8 ++- 9 files changed, 96 insertions(+), 4 deletions(-) create mode 100644 src/wayland/handlers/foreign_toplevel_list.rs diff --git a/Cargo.lock b/Cargo.lock index 5e9b2e2e..06a31055 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4703,7 +4703,7 @@ checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "smithay" version = "0.3.0" -source = "git+https://github.com/smithay//smithay?rev=5dc0153#5dc015361c641cd76d4abbd60dd8896dd8cb8adc" +source = "git+https://github.com/smithay//smithay?rev=298bef3#298bef358d4bbffd3a1159dc2ec418b9f81417cc" dependencies = [ "appendlist", "ash 0.38.0+1.3.281", diff --git a/Cargo.toml b/Cargo.toml index c221e8e2..f24d4403 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -116,4 +116,4 @@ inherits = "release" lto = "fat" [patch."https://github.com/Smithay/smithay.git"] -smithay = { git = "https://github.com/smithay//smithay", rev = "5dc0153" } +smithay = { git = "https://github.com/smithay//smithay", rev = "298bef3" } diff --git a/src/shell/mod.rs b/src/shell/mod.rs index 890e3e6d..96df55dc 100644 --- a/src/shell/mod.rs +++ b/src/shell/mod.rs @@ -41,6 +41,7 @@ use smithay::{ utils::{IsAlive, Logical, Point, Rectangle, Serial, Size}, wayland::{ compositor::with_states, + foreign_toplevel_list::ForeignToplevelListState, seat::WaylandFocus, session_lock::LockSurface, shell::wlr_layer::{KeyboardInteractivity, Layer, LayerSurfaceCachedState}, @@ -55,7 +56,11 @@ use crate::{ utils::{prelude::*, quirks::WORKSPACE_OVERVIEW_NAMESPACE}, wayland::{ handlers::{ - toplevel_management::minimize_rectangle, xdg_activation::ActivationContext, + foreign_toplevel_list::{ + new_foreign_toplevel, refresh_foreign_toplevels, remove_foreign_toplevel, + }, + toplevel_management::minimize_rectangle, + xdg_activation::ActivationContext, xdg_shell::popup::get_popup_toplevel, }, protocols::{ @@ -1184,6 +1189,7 @@ impl Common { ); self.popups.cleanup(); self.toplevel_info_state.refresh(&self.workspace_state); + refresh_foreign_toplevels(&self.shell.read().unwrap()); self.refresh_idle_inhibit(); } @@ -1851,6 +1857,7 @@ impl Shell { &mut self, window: &CosmicSurface, toplevel_info: &mut ToplevelInfoState, + foreign_toplevel_list: &mut ForeignToplevelListState, workspace_state: &mut WorkspaceState, evlh: &LoopHandle<'static, State>, ) -> Option { @@ -1933,6 +1940,7 @@ impl Shell { toplevel_info.new_toplevel(&window, workspace_state); toplevel_enter_output(&window, &output); toplevel_enter_workspace(&window, &workspace.handle); + new_foreign_toplevel(&window, foreign_toplevel_list); let mut workspace_state = workspace_state.update(); @@ -2064,6 +2072,7 @@ impl Shell { surface: &S, seat: &Seat, toplevel_info: &mut ToplevelInfoState, + foreign_toplevel_list: &mut ForeignToplevelListState, ) where CosmicSurface: PartialEq, { @@ -2113,6 +2122,7 @@ impl Shell { if let Some(surface) = surface { toplevel_info.remove_toplevel(&surface); + remove_foreign_toplevel(&surface, foreign_toplevel_list); self.pending_windows.push((surface, seat.clone(), None)); return; } diff --git a/src/state.rs b/src/state.rs index 0776d71e..186f2971 100644 --- a/src/state.rs +++ b/src/state.rs @@ -67,6 +67,7 @@ use smithay::{ alpha_modifier::AlphaModifierState, compositor::{CompositorClientState, CompositorState, SurfaceData}, dmabuf::{DmabufFeedback, DmabufGlobal, DmabufState}, + foreign_toplevel_list::ForeignToplevelListState, fractional_scale::{with_fractional_scale, FractionalScaleManagerState}, idle_inhibit::IdleInhibitManagerState, idle_notify::IdleNotifierState, @@ -192,6 +193,7 @@ pub struct Common { pub compositor_state: CompositorState, pub data_device_state: DataDeviceState, pub dmabuf_state: DmabufState, + pub foreign_toplevel_list: ForeignToplevelListState, pub fractional_scale_state: FractionalScaleManagerState, pub keyboard_shortcuts_inhibit_state: KeyboardShortcutsInhibitState, pub output_state: OutputManagerState, @@ -486,6 +488,8 @@ impl State { let compositor_state = CompositorState::new::(dh); let data_device_state = DataDeviceState::new::(dh); let dmabuf_state = DmabufState::new(); + let foreign_toplevel_list = + ForeignToplevelListState::new_with_filter::(dh, client_is_privileged); let fractional_scale_state = FractionalScaleManagerState::new::(dh); let keyboard_shortcuts_inhibit_state = KeyboardShortcutsInhibitState::new::(dh); let output_state = OutputManagerState::new_with_xdg_output::(dh); @@ -581,6 +585,7 @@ impl State { compositor_state, data_device_state, dmabuf_state, + foreign_toplevel_list, fractional_scale_state, idle_notifier_state, idle_inhibit_manager_state, diff --git a/src/wayland/handlers/compositor.rs b/src/wayland/handlers/compositor.rs index b596b194..395aa229 100644 --- a/src/wayland/handlers/compositor.rs +++ b/src/wayland/handlers/compositor.rs @@ -265,6 +265,7 @@ impl State { let res = shell.map_window( &window, &mut self.common.toplevel_info_state, + &mut self.common.foreign_toplevel_list, &mut self.common.workspace_state, &self.common.event_loop_handle, ); diff --git a/src/wayland/handlers/foreign_toplevel_list.rs b/src/wayland/handlers/foreign_toplevel_list.rs new file mode 100644 index 00000000..ad0676ae --- /dev/null +++ b/src/wayland/handlers/foreign_toplevel_list.rs @@ -0,0 +1,68 @@ +// SPDX-License-Identifier: GPL-3.0-only + +use crate::{ + shell::{CosmicSurface, Shell}, + state::State, +}; +use smithay::wayland::foreign_toplevel_list::{ + ForeignToplevelHandle, ForeignToplevelListHandler, ForeignToplevelListState, +}; +use std::sync::Mutex; + +impl ForeignToplevelListHandler for State { + fn foreign_toplevel_list_state(&mut self) -> &mut ForeignToplevelListState { + &mut self.common.foreign_toplevel_list + } +} + +pub fn new_foreign_toplevel( + window: &CosmicSurface, + foreign_toplevel_list: &mut ForeignToplevelListState, +) { + let toplevel_handle = + foreign_toplevel_list.new_toplevel::(window.title(), window.app_id()); + *window + .user_data() + .get_or_insert::>, _>(Default::default) + .lock() + .unwrap() = Some(toplevel_handle); +} + +pub fn remove_foreign_toplevel( + window: &CosmicSurface, + foreign_toplevel_list: &mut ForeignToplevelListState, +) { + if let Some(handle) = window + .user_data() + .get::>>() + { + if let Some(handle) = handle.lock().unwrap().take() { + foreign_toplevel_list.remove_toplevel(&handle); + } + } +} + +pub fn refresh_foreign_toplevels(shell: &Shell) { + for (window, _) in shell + .workspaces + .spaces() + .flat_map(|workspace| workspace.mapped()) + .flat_map(|mapped| mapped.windows()) + { + let foreign_toplevel_handle = window + .user_data() + .get::>>() + .and_then(|handle| handle.lock().unwrap().clone()); + if let Some(handle) = foreign_toplevel_handle { + let app_id = window.app_id(); + let title = window.title(); + if handle.app_id() != app_id || handle.title() != title { + handle.send_app_id(&app_id); + handle.send_title(&title); + handle.send_done(); + } + } + } +} + +smithay::delegate_foreign_toplevel_list!(State); diff --git a/src/wayland/handlers/mod.rs b/src/wayland/handlers/mod.rs index b25ec2bb..3fc4f9e6 100644 --- a/src/wayland/handlers/mod.rs +++ b/src/wayland/handlers/mod.rs @@ -9,6 +9,7 @@ pub mod decoration; pub mod dmabuf; pub mod drm; pub mod drm_lease; +pub mod foreign_toplevel_list; pub mod fractional_scale; pub mod idle_inhibit; pub mod idle_notify; diff --git a/src/wayland/handlers/xdg_shell/mod.rs b/src/wayland/handlers/xdg_shell/mod.rs index 9b833851..e97ac671 100644 --- a/src/wayland/handlers/xdg_shell/mod.rs +++ b/src/wayland/handlers/xdg_shell/mod.rs @@ -379,6 +379,7 @@ impl XdgShellHandler for State { surface.wl_surface(), &seat, &mut self.common.toplevel_info_state, + &mut self.common.foreign_toplevel_list, ); let output = shell diff --git a/src/xwayland.rs b/src/xwayland.rs index 3621b1a9..ab10fe8c 100644 --- a/src/xwayland.rs +++ b/src/xwayland.rs @@ -313,6 +313,7 @@ impl XwmHandler for State { let res = shell.map_window( &window, &mut self.common.toplevel_info_state, + &mut self.common.foreign_toplevel_list, &mut self.common.workspace_state, &self.common.event_loop_handle, ); @@ -342,7 +343,12 @@ impl XwmHandler for State { shell.override_redirect_windows.retain(|or| or != &window); } else { let seat = shell.seats.last_active().clone(); - shell.unmap_surface(&window, &seat, &mut self.common.toplevel_info_state); + shell.unmap_surface( + &window, + &seat, + &mut self.common.toplevel_info_state, + &mut self.common.foreign_toplevel_list, + ); } let outputs = if let Some(wl_surface) = window.wl_surface() {