From 3036448c19082feeb0aadd2d344390fb1531e97a Mon Sep 17 00:00:00 2001 From: Ian Douglas Scott Date: Wed, 21 Feb 2024 13:24:56 -0800 Subject: [PATCH] Update Smithay, with `Window` that supports X11 surfaces --- Cargo.lock | 2 +- Cargo.toml | 2 +- src/backend/kms/mod.rs | 4 +- src/backend/x11.rs | 4 +- src/input/mod.rs | 16 +- src/shell/element/mod.rs | 5 +- src/shell/element/surface.rs | 656 +++++++------------- src/shell/focus/mod.rs | 12 +- src/shell/grabs/menu/default.rs | 8 +- src/shell/grabs/moving.rs | 2 +- src/shell/layout/floating/grabs/resize.rs | 26 +- src/shell/layout/mod.rs | 10 +- src/shell/layout/tiling/grabs/swap.rs | 12 +- src/shell/layout/tiling/mod.rs | 84 ++- src/shell/mod.rs | 73 ++- src/shell/workspace.rs | 8 + src/wayland/handlers/compositor.rs | 26 +- src/wayland/handlers/decoration.rs | 57 +- src/wayland/handlers/dmabuf.rs | 2 +- src/wayland/handlers/toplevel_management.rs | 7 +- src/wayland/handlers/xdg_activation.rs | 10 +- src/wayland/handlers/xdg_shell/mod.rs | 4 +- src/wayland/handlers/xdg_shell/popup.rs | 10 +- src/xwayland.rs | 61 +- 24 files changed, 482 insertions(+), 619 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d05005a3..223c4c79 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4443,7 +4443,7 @@ checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7" [[package]] name = "smithay" version = "0.3.0" -source = "git+https://github.com/smithay//smithay?rev=094fa3f7c3#094fa3f7c3909a7815000174807d1d962d555718" +source = "git+https://github.com/smithay//smithay?rev=7f9e6d5#7f9e6d51e8a12fc992c305de03820a44811b8c18" dependencies = [ "appendlist", "ash", diff --git a/Cargo.toml b/Cargo.toml index 95ae920f..1079cca0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -108,4 +108,4 @@ inherits = "release" lto = "fat" [patch."https://github.com/Smithay/smithay.git"] -smithay = {git = "https://github.com/smithay//smithay", rev = "094fa3f7c3"} +smithay = {git = "https://github.com/smithay//smithay", rev = "7f9e6d5"} diff --git a/src/backend/kms/mod.rs b/src/backend/kms/mod.rs index f49caf0d..4deec1dc 100644 --- a/src/backend/kms/mod.rs +++ b/src/backend/kms/mod.rs @@ -642,7 +642,7 @@ impl State { if non_desktop { let Ok(output_name) = drm_helpers::interface_name(&device.drm, conn) else { - continue + continue; }; let drm_helpers::EdidInfo { model, @@ -779,7 +779,7 @@ impl State { if non_desktop { let Ok(output_name) = drm_helpers::interface_name(&device.drm, conn) else { - continue + continue; }; let drm_helpers::EdidInfo { model, diff --git a/src/backend/x11.rs b/src/backend/x11.rs index 4fb2f4e7..6e361a37 100644 --- a/src/backend/x11.rs +++ b/src/backend/x11.rs @@ -302,7 +302,9 @@ fn try_vulkan_allocator(node: &DrmNode) -> Option { let Some(device) = devices .filter(|phd| { - phd.has_device_extension(smithay::reexports::ash::extensions::ext::PhysicalDeviceDrm::name()) + phd.has_device_extension( + smithay::reexports::ash::extensions::ext::PhysicalDeviceDrm::name(), + ) }) .find(|phd| { phd.primary_node().unwrap() == Some(*node) || phd.render_node().unwrap() == Some(*node) diff --git a/src/input/mod.rs b/src/input/mod.rs index 021760e6..31a242de 100644 --- a/src/input/mod.rs +++ b/src/input/mod.rs @@ -1156,7 +1156,9 @@ impl State { } InputEvent::TouchDown { event, .. } => { if let Some(seat) = self.common.seat_with_device(&event.device()).cloned() { - let Some(output) = mapped_output_for_device(&self.common, &event.device()).cloned() else { + let Some(output) = + mapped_output_for_device(&self.common, &event.device()).cloned() + else { return; }; @@ -1187,7 +1189,9 @@ impl State { } InputEvent::TouchMotion { event, .. } => { if let Some(seat) = self.common.seat_with_device(&event.device()).cloned() { - let Some(output) = mapped_output_for_device(&self.common, &event.device()).cloned() else { + let Some(output) = + mapped_output_for_device(&self.common, &event.device()).cloned() + else { return; }; @@ -1227,7 +1231,9 @@ impl State { InputEvent::TouchFrame { event: _, .. } => {} InputEvent::TabletToolAxis { event, .. } => { if let Some(seat) = self.common.seat_with_device(&event.device()).cloned() { - let Some(output) = mapped_output_for_device(&self.common, &event.device()).cloned() else { + let Some(output) = + mapped_output_for_device(&self.common, &event.device()).cloned() + else { return; }; let geometry = output.geometry(); @@ -1288,7 +1294,9 @@ impl State { } InputEvent::TabletToolProximity { event, .. } => { if let Some(seat) = self.common.seat_with_device(&event.device()).cloned() { - let Some(output) = mapped_output_for_device(&self.common, &event.device()).cloned() else { + let Some(output) = + mapped_output_for_device(&self.common, &event.device()).cloned() + else { return; }; let geometry = output.geometry(); diff --git a/src/shell/element/mod.rs b/src/shell/element/mod.rs index c92bc179..88351ac3 100644 --- a/src/shell/element/mod.rs +++ b/src/shell/element/mod.rs @@ -843,10 +843,7 @@ impl SpaceElement for CosmicMapped { impl X11Relatable for CosmicMapped { fn is_window(&self, window: &X11Surface) -> bool { - match self.active_window() { - CosmicSurface::X11(surface) => &surface == window, - _ => false, - } + self.active_window().x11_surface() == Some(window) } } diff --git a/src/shell/element/surface.rs b/src/shell/element/surface.rs index fb31a41d..b6f20e33 100644 --- a/src/shell/element/surface.rs +++ b/src/shell/element/surface.rs @@ -11,12 +11,7 @@ use smithay::{ ImportAll, Renderer, }, desktop::{ - utils::{ - send_dmabuf_feedback_surface_tree, send_frames_surface_tree, - take_presentation_feedback_surface_tree, with_surfaces_surface_tree, - OutputPresentationFeedback, - }, - PopupManager, Window, + space::SpaceElement, utils::OutputPresentationFeedback, PopupManager, Window, WindowSurface, }, input::{ keyboard::{KeyboardTarget, KeysymHandle, ModifiersState}, @@ -39,8 +34,7 @@ use smithay::{ }, wayland_server::protocol::wl_surface::WlSurface, }, - space_elements, - utils::{user_data::UserDataMap, Logical, Rectangle, Serial, Size}, + utils::{user_data::UserDataMap, IsAlive, Logical, Rectangle, Serial, Size}, wayland::{ compositor::{with_states, SurfaceData}, seat::WaylandFocus, @@ -55,28 +49,24 @@ use crate::{ wayland::handlers::decoration::PreferredDecorationMode, }; -space_elements! { - #[derive(Debug, Clone, PartialEq)] - pub CosmicSurface; - Wayland=Window, - X11=X11Surface, -} +#[derive(Debug, Clone, PartialEq)] +pub struct CosmicSurface(pub Window); impl From for CosmicSurface { fn from(s: ToplevelSurface) -> Self { - CosmicSurface::Wayland(Window::new(s)) + CosmicSurface(Window::new_wayland_window(s)) } } impl From for CosmicSurface { fn from(w: Window) -> Self { - CosmicSurface::Wayland(w) + CosmicSurface(w) } } impl From for CosmicSurface { fn from(s: X11Surface) -> Self { - CosmicSurface::X11(s) + CosmicSurface(Window::new_x11_window(s)) } } @@ -84,217 +74,200 @@ pub const SSD_HEIGHT: i32 = 48; impl CosmicSurface { pub fn title(&self) -> String { - match self { - CosmicSurface::Wayland(window) => { - with_states(window.toplevel().wl_surface(), |states| { - states - .data_map - .get::() - .unwrap() - .lock() - .unwrap() - .title - .clone() - .unwrap_or_default() - }) - } - CosmicSurface::X11(surface) => surface.title(), - _ => unreachable!(), + match self.0.underlying_surface() { + WindowSurface::Wayland(toplevel) => with_states(toplevel.wl_surface(), |states| { + states + .data_map + .get::() + .unwrap() + .lock() + .unwrap() + .title + .clone() + .unwrap_or_default() + }), + WindowSurface::X11(surface) => surface.title(), } } pub fn app_id(&self) -> String { - match self { - CosmicSurface::Wayland(window) => { - with_states(window.toplevel().wl_surface(), |states| { - states - .data_map - .get::() - .unwrap() - .lock() - .unwrap() - .app_id - .clone() - .unwrap_or_default() - }) - } - CosmicSurface::X11(surface) => surface.class(), - _ => unreachable!(), + match self.0.underlying_surface() { + WindowSurface::Wayland(toplevel) => with_states(toplevel.wl_surface(), |states| { + states + .data_map + .get::() + .unwrap() + .lock() + .unwrap() + .app_id + .clone() + .unwrap_or_default() + }), + WindowSurface::X11(surface) => surface.class(), } } pub fn pending_size(&self) -> Option> { - match self { - CosmicSurface::Wayland(window) => { - window.toplevel().with_pending_state(|state| state.size) - } - CosmicSurface::X11(surface) => Some(surface.geometry().size), - _ => unreachable!(), + match self.0.underlying_surface() { + WindowSurface::Wayland(toplevel) => toplevel.with_pending_state(|state| state.size), + WindowSurface::X11(surface) => Some(surface.geometry().size), } } pub fn set_geometry(&self, geo: Rectangle) { - match self { - CosmicSurface::Wayland(window) => window - .toplevel() - .with_pending_state(|state| state.size = Some(geo.size.as_logical())), - CosmicSurface::X11(surface) => { + match self.0.underlying_surface() { + WindowSurface::Wayland(toplevel) => { + toplevel.with_pending_state(|state| state.size = Some(geo.size.as_logical())) + } + WindowSurface::X11(surface) => { let _ = surface.configure(geo.as_logical()); } - _ => {} } } pub fn set_bounds(&self, size: impl Into>>) { - match self { - CosmicSurface::Wayland(window) => window.toplevel().with_pending_state(|state| { - state.bounds = size.into(); - }), - _ => {} + match self.0.underlying_surface() { + WindowSurface::Wayland(toplevel) => { + toplevel.with_pending_state(|state| state.bounds = size.into()) + } + WindowSurface::X11(_surface) => {} } } pub fn is_activated(&self, pending: bool) -> bool { - match self { - CosmicSurface::Wayland(window) => { + match self.0.underlying_surface() { + WindowSurface::Wayland(toplevel) => { if pending { - window.toplevel().with_pending_state(|pending| { + toplevel.with_pending_state(|pending| { pending.states.contains(ToplevelState::Activated) }) } else { - window - .toplevel() + toplevel .current_state() .states .contains(ToplevelState::Activated) } } - CosmicSurface::X11(surface) => surface.is_activated(), - _ => unreachable!(), + WindowSurface::X11(surface) => surface.is_activated(), } } pub fn set_activated(&self, activated: bool) { - match self { - CosmicSurface::Wayland(window) => window.toplevel().with_pending_state(|state| { + match self.0.underlying_surface() { + WindowSurface::Wayland(toplevel) => toplevel.with_pending_state(|state| { if activated { state.states.set(ToplevelState::Activated); } else { state.states.unset(ToplevelState::Activated); } }), - CosmicSurface::X11(surface) => { + WindowSurface::X11(surface) => { let _ = surface.set_activated(activated); } - _ => unreachable!(), } } pub fn is_decorated(&self, pending: bool) -> bool { - match self { - CosmicSurface::Wayland(window) => { + match self.0.underlying_surface() { + WindowSurface::Wayland(toplevel) => { if pending { - window.toplevel().with_pending_state(|pending| { + toplevel.with_pending_state(|pending| { pending .decoration_mode .map(|mode| mode == DecorationMode::ClientSide) .unwrap_or(true) }) } else { - window - .toplevel() + toplevel .current_state() .decoration_mode .map(|mode| mode == DecorationMode::ClientSide) .unwrap_or(true) } } - CosmicSurface::X11(surface) => surface.is_decorated(), - _ => unreachable!(), + WindowSurface::X11(surface) => surface.is_decorated(), } } pub fn try_force_undecorated(&self, enable: bool) { - match self { - CosmicSurface::Wayland(window) => { + match self.0.underlying_surface() { + WindowSurface::Wayland(toplevel) => { if enable { let previous_decoration_state = - window.toplevel().current_state().decoration_mode.clone(); - if PreferredDecorationMode::is_unset(window) { - PreferredDecorationMode::update(window, previous_decoration_state); + toplevel.current_state().decoration_mode.clone(); + if PreferredDecorationMode::is_unset(&self.0) { + PreferredDecorationMode::update(&self.0, previous_decoration_state); } - window.toplevel().with_pending_state(|pending| { + toplevel.with_pending_state(|pending| { pending.decoration_mode = Some(DecorationMode::ServerSide); }); } else { - let previous_mode = PreferredDecorationMode::mode(window); - window.toplevel().with_pending_state(|pending| { + let previous_mode = PreferredDecorationMode::mode(&self.0); + toplevel.with_pending_state(|pending| { pending.decoration_mode = previous_mode; }); } } - _ => {} + WindowSurface::X11(_surface) => {} } } pub fn is_resizing(&self, pending: bool) -> Option { - match self { - CosmicSurface::Wayland(window) => { + match self.0.underlying_surface() { + WindowSurface::Wayland(toplevel) => { if pending { - Some(window.toplevel().with_pending_state(|pending| { + Some(toplevel.with_pending_state(|pending| { pending.states.contains(ToplevelState::Resizing) })) } else { Some( - window - .toplevel() + toplevel .current_state() .states .contains(ToplevelState::Resizing), ) } } - _ => None, + WindowSurface::X11(_surface) => None, } } pub fn set_resizing(&self, resizing: bool) { - match self { - CosmicSurface::Wayland(window) => window.toplevel().with_pending_state(|state| { + match self.0.underlying_surface() { + WindowSurface::Wayland(toplevel) => toplevel.with_pending_state(|state| { if resizing { state.states.set(ToplevelState::Resizing); } else { state.states.unset(ToplevelState::Resizing); } }), - _ => {} + WindowSurface::X11(_surface) => {} } } pub fn is_tiled(&self, pending: bool) -> Option { - match self { - CosmicSurface::Wayland(window) => { + match self.0.underlying_surface() { + WindowSurface::Wayland(toplevel) => { if pending { - Some(window.toplevel().with_pending_state(|pending| { + Some(toplevel.with_pending_state(|pending| { pending.states.contains(ToplevelState::TiledLeft) })) } else { Some( - window - .toplevel() + toplevel .current_state() .states .contains(ToplevelState::TiledLeft), ) } } - _ => None, + WindowSurface::X11(_surface) => None, } } pub fn set_tiled(&self, tiled: bool) { - match self { - CosmicSurface::Wayland(window) => window.toplevel().with_pending_state(|state| { + match self.0.underlying_surface() { + WindowSurface::Wayland(toplevel) => toplevel.with_pending_state(|state| { if tiled { state.states.set(ToplevelState::TiledLeft); state.states.set(ToplevelState::TiledRight); @@ -307,92 +280,85 @@ impl CosmicSurface { state.states.unset(ToplevelState::TiledBottom); } }), - _ => {} + WindowSurface::X11(_surface) => {} } } pub fn is_fullscreen(&self, pending: bool) -> bool { - match self { - CosmicSurface::Wayland(window) => { + match self.0.underlying_surface() { + WindowSurface::Wayland(toplevel) => { if pending { - window.toplevel().with_pending_state(|pending| { + toplevel.with_pending_state(|pending| { pending.states.contains(ToplevelState::Fullscreen) }) } else { - window - .toplevel() + toplevel .current_state() .states .contains(ToplevelState::Fullscreen) } } - CosmicSurface::X11(surface) => surface.is_fullscreen(), - _ => unreachable!(), + WindowSurface::X11(surface) => surface.is_fullscreen(), } } pub fn set_fullscreen(&self, fullscreen: bool) { - match self { - CosmicSurface::Wayland(window) => window.toplevel().with_pending_state(|state| { + match self.0.underlying_surface() { + WindowSurface::Wayland(toplevel) => toplevel.with_pending_state(|state| { if fullscreen { state.states.set(ToplevelState::Fullscreen); } else { state.states.unset(ToplevelState::Fullscreen); } }), - CosmicSurface::X11(surface) => { + WindowSurface::X11(surface) => { let _ = surface.set_fullscreen(fullscreen); } - _ => unreachable!(), } } pub fn is_maximized(&self, pending: bool) -> bool { - match self { - CosmicSurface::Wayland(window) => { + match self.0.underlying_surface() { + WindowSurface::Wayland(toplevel) => { if pending { - window.toplevel().with_pending_state(|pending| { + toplevel.with_pending_state(|pending| { pending.states.contains(ToplevelState::Maximized) }) } else { - window - .toplevel() + toplevel .current_state() .states .contains(ToplevelState::Maximized) } } - CosmicSurface::X11(surface) => surface.is_maximized(), - _ => unreachable!(), + WindowSurface::X11(surface) => surface.is_maximized(), } } pub fn set_maximized(&self, maximized: bool) { - match self { - CosmicSurface::Wayland(window) => window.toplevel().with_pending_state(|state| { + match self.0.underlying_surface() { + WindowSurface::Wayland(toplevel) => toplevel.with_pending_state(|state| { if maximized { state.states.set(ToplevelState::Maximized); } else { state.states.unset(ToplevelState::Maximized); } }), - CosmicSurface::X11(surface) => { + WindowSurface::X11(surface) => { let _ = surface.set_maximized(maximized); } - _ => unreachable!(), } } pub fn min_size(&self) -> Option> { - match self { - CosmicSurface::Wayland(window) => { - Some(with_states(window.toplevel().wl_surface(), |states| { + match self.0.underlying_surface() { + WindowSurface::Wayland(toplevel) => { + Some(with_states(toplevel.wl_surface(), |states| { states.cached_state.current::().min_size })) .filter(|size| !(size.w == 0 && size.h == 0)) } - CosmicSurface::X11(surface) => surface.min_size(), - _ => unreachable!(), + WindowSurface::X11(surface) => surface.min_size(), } .map(|size| { if self.is_decorated(false) { @@ -404,15 +370,14 @@ impl CosmicSurface { } pub fn max_size(&self) -> Option> { - match self { - CosmicSurface::Wayland(window) => { - Some(with_states(window.toplevel().wl_surface(), |states| { + match self.0.underlying_surface() { + WindowSurface::Wayland(toplevel) => { + Some(with_states(toplevel.wl_surface(), |states| { states.cached_state.current::().max_size })) .filter(|size| !(size.w == 0 && size.h == 0)) } - CosmicSurface::X11(surface) => surface.max_size(), - _ => unreachable!(), + WindowSurface::X11(surface) => surface.max_size(), } .map(|size| { if self.is_decorated(false) { @@ -424,60 +389,52 @@ impl CosmicSurface { } pub fn serial_acked(&self, serial: &Serial) -> bool { - match self { - CosmicSurface::Wayland(window) => { - with_states(window.toplevel().wl_surface(), |states| { - let attrs = states - .data_map - .get::() - .unwrap() - .lock() - .unwrap(); - attrs - .configure_serial - .as_ref() - .map(|s| s >= serial) - .unwrap_or(false) - }) - } - _ => true, + match self.0.underlying_surface() { + WindowSurface::Wayland(toplevel) => with_states(toplevel.wl_surface(), |states| { + let attrs = states + .data_map + .get::() + .unwrap() + .lock() + .unwrap(); + attrs + .configure_serial + .as_ref() + .map(|s| s >= serial) + .unwrap_or(false) + }), + WindowSurface::X11(_surface) => true, } } pub fn force_configure(&self) -> Option { - match self { - CosmicSurface::Wayland(window) => Some(window.toplevel().send_configure()), - CosmicSurface::X11(surface) => { + match self.0.underlying_surface() { + WindowSurface::Wayland(toplevel) => Some(toplevel.send_configure()), + WindowSurface::X11(surface) => { let _ = surface.configure(None); None } - _ => unreachable!(), } } pub fn send_configure(&self) -> Option { - match self { - CosmicSurface::Wayland(window) => window.toplevel().send_pending_configure(), - CosmicSurface::X11(_) => None, - _ => unreachable!(), + match self.0.underlying_surface() { + WindowSurface::Wayland(toplevel) => toplevel.send_pending_configure(), + WindowSurface::X11(_) => None, } } pub fn close(&self) { - match self { - CosmicSurface::Wayland(window) => window.toplevel().send_close(), - CosmicSurface::X11(surface) => { + match self.0.underlying_surface() { + WindowSurface::Wayland(toplevel) => toplevel.send_close(), + WindowSurface::X11(surface) => { let _ = surface.close(); } - _ => unreachable!(), } } pub fn on_commit(&self) { - match self { - CosmicSurface::Wayland(window) => window.on_commit(), - _ => {} - } + self.0.on_commit(); } pub fn send_frame( @@ -490,23 +447,8 @@ impl CosmicSurface { T: Into, F: FnMut(&WlSurface, &SurfaceData) -> Option + Copy, { - match self { - CosmicSurface::Wayland(window) => { - window.send_frame(output, time, throttle, primary_scan_out_output); - } - CosmicSurface::X11(surface) => { - if let Some(wl_surface) = surface.wl_surface() { - send_frames_surface_tree( - &wl_surface, - output, - time, - throttle, - primary_scan_out_output, - ) - } - } - _ => unreachable!(), - } + self.0 + .send_frame(output, time, throttle, primary_scan_out_output); } pub fn send_dmabuf_feedback( @@ -518,36 +460,15 @@ impl CosmicSurface { ) where F1: FnMut(&WlSurface, &SurfaceData) -> Option + Copy, { - match self { - CosmicSurface::Wayland(window) => { - window.send_dmabuf_feedback(output, primary_scan_out_output, |surface, _| { - select_dmabuf_feedback( - surface, - render_element_states, - &feedback.render_feedback, - &feedback.scanout_feedback, - ) - }) - } - CosmicSurface::X11(surface) => { - if let Some(wl_surface) = surface.wl_surface() { - send_dmabuf_feedback_surface_tree( - &wl_surface, - output, - primary_scan_out_output, - |surface, _| { - select_dmabuf_feedback( - surface, - render_element_states, - &feedback.render_feedback, - &feedback.scanout_feedback, - ) - }, - ) - } - } - _ => unreachable!(), - } + self.0 + .send_dmabuf_feedback(output, primary_scan_out_output, |surface, _| { + select_dmabuf_feedback( + surface, + render_element_states, + &feedback.render_feedback, + &feedback.scanout_feedback, + ) + }) } pub fn take_presentation_feedback( @@ -559,47 +480,22 @@ impl CosmicSurface { F1: FnMut(&WlSurface, &SurfaceData) -> Option + Copy, F2: FnMut(&WlSurface, &SurfaceData) -> Kind + Copy, { - match self { - CosmicSurface::Wayland(window) => window.take_presentation_feedback( - output_feedback, - primary_scan_out_output, - presentation_feedback_flags, - ), - CosmicSurface::X11(surface) => { - if let Some(wl_surface) = surface.wl_surface() { - take_presentation_feedback_surface_tree( - &wl_surface, - output_feedback, - primary_scan_out_output, - presentation_feedback_flags, - ) - } - } - _ => unreachable!(), - } + self.0.take_presentation_feedback( + output_feedback, + primary_scan_out_output, + presentation_feedback_flags, + ) } pub fn with_surfaces(&self, processor: F) where F: FnMut(&WlSurface, &SurfaceData), { - match self { - CosmicSurface::Wayland(window) => window.with_surfaces(processor), - CosmicSurface::X11(surface) => { - if let Some(wl_surface) = surface.wl_surface() { - with_surfaces_surface_tree(&wl_surface, processor) - } - } - _ => unreachable!(), - } + self.0.with_surfaces(processor) } pub fn user_data(&self) -> &UserDataMap { - match self { - CosmicSurface::Wayland(window) => window.user_data(), - CosmicSurface::X11(surface) => surface.user_data(), - _ => unreachable!(), - } + self.0.user_data() } pub fn split_render_elements( @@ -614,13 +510,13 @@ impl CosmicSurface { ::TextureId: 'static, C: From>, { - match self { - CosmicSurface::Wayland(window) => { - let surface = window.toplevel().wl_surface(); + match self.0.underlying_surface() { + WindowSurface::Wayland(toplevel) => { + let surface = toplevel.wl_surface(); let popup_render_elements = PopupManager::popups_for_surface(surface) .flat_map(|(popup, popup_offset)| { - let offset = (window.geometry().loc + popup_offset - popup.geometry().loc) + let offset = (self.0.geometry().loc + popup_offset - popup.geometry().loc) .to_physical_precise_round(scale); render_elements_from_surface_tree( @@ -645,13 +541,63 @@ impl CosmicSurface { (window_render_elements, popup_render_elements) } - CosmicSurface::X11(surface) => ( + WindowSurface::X11(surface) => ( surface.render_elements(renderer, location, scale, alpha), Vec::new(), ), - _ => unreachable!(), } } + + pub fn x11_surface(&self) -> Option<&X11Surface> { + self.0.x11_surface() + } +} + +impl IsAlive for CosmicSurface { + fn alive(&self) -> bool { + self.0.alive() + } +} + +impl SpaceElement for CosmicSurface { + fn geometry(&self) -> Rectangle { + SpaceElement::geometry(&self.0) + } + + fn bbox(&self) -> Rectangle { + SpaceElement::bbox(&self.0) + } + + fn is_in_input_region( + &self, + point: &smithay::utils::Point, + ) -> bool { + SpaceElement::is_in_input_region(&self.0, point) + } + + fn z_index(&self) -> u8 { + SpaceElement::z_index(&self.0) + } + + fn set_activate(&self, activated: bool) { + SpaceElement::set_activate(&self.0, activated) + } + + fn output_enter( + &self, + output: &Output, + overlap: smithay::utils::Rectangle, + ) { + SpaceElement::output_enter(&self.0, output, overlap) + } + + fn output_leave(&self, output: &Output) { + SpaceElement::output_leave(&self.0, output) + } + + fn refresh(&self) { + SpaceElement::refresh(&self.0) + } } impl KeyboardTarget for CosmicSurface { @@ -659,26 +605,17 @@ impl KeyboardTarget for CosmicSurface { &self, seat: &Seat, data: &mut State, - keys: Vec>, + mut keys: Vec>, serial: smithay::utils::Serial, ) { - match self { - CosmicSurface::Wayland(window) => { - KeyboardTarget::enter(window, seat, data, keys, serial) - } - CosmicSurface::X11(surface) => { - KeyboardTarget::enter(surface, seat, data, vec![], serial) - } - _ => unreachable!(), + if self.0.is_x11() { + keys = vec![]; } + KeyboardTarget::enter(&self.0, seat, data, keys, serial) } fn leave(&self, seat: &Seat, data: &mut State, serial: smithay::utils::Serial) { - match self { - CosmicSurface::Wayland(window) => KeyboardTarget::leave(window, seat, data, serial), - CosmicSurface::X11(surface) => KeyboardTarget::leave(surface, seat, data, serial), - _ => unreachable!(), - } + KeyboardTarget::leave(&self.0, seat, data, serial) } fn key( @@ -690,15 +627,7 @@ impl KeyboardTarget for CosmicSurface { serial: smithay::utils::Serial, time: u32, ) { - match self { - CosmicSurface::Wayland(window) => { - KeyboardTarget::key(window, seat, data, key, state, serial, time) - } - CosmicSurface::X11(surface) => { - KeyboardTarget::key(surface, seat, data, key, state, serial, time) - } - _ => unreachable!(), - } + KeyboardTarget::key(&self.0, seat, data, key, state, serial, time) } fn modifiers( @@ -708,69 +637,33 @@ impl KeyboardTarget for CosmicSurface { modifiers: ModifiersState, serial: smithay::utils::Serial, ) { - match self { - CosmicSurface::Wayland(window) => { - KeyboardTarget::modifiers(window, seat, data, modifiers, serial) - } - CosmicSurface::X11(surface) => { - KeyboardTarget::modifiers(surface, seat, data, modifiers, serial) - } - _ => unreachable!(), - } + KeyboardTarget::modifiers(&self.0, seat, data, modifiers, serial) } } impl PointerTarget for CosmicSurface { fn enter(&self, seat: &Seat, data: &mut State, event: &MotionEvent) { - match self { - CosmicSurface::Wayland(window) => PointerTarget::enter(window, seat, data, event), - CosmicSurface::X11(surface) => PointerTarget::enter(surface, seat, data, event), - _ => unreachable!(), - } + PointerTarget::enter(&self.0, seat, data, event) } fn motion(&self, seat: &Seat, data: &mut State, event: &MotionEvent) { - match self { - CosmicSurface::Wayland(window) => PointerTarget::motion(window, seat, data, event), - CosmicSurface::X11(surface) => PointerTarget::motion(surface, seat, data, event), - _ => unreachable!(), - } + PointerTarget::motion(&self.0, seat, data, event) } fn relative_motion(&self, seat: &Seat, data: &mut State, event: &RelativeMotionEvent) { - match self { - CosmicSurface::Wayland(window) => { - PointerTarget::relative_motion(window, seat, data, event) - } - CosmicSurface::X11(surface) => { - PointerTarget::relative_motion(surface, seat, data, event) - } - _ => unreachable!(), - } + PointerTarget::relative_motion(&self.0, seat, data, event) } fn button(&self, seat: &Seat, data: &mut State, event: &ButtonEvent) { - match self { - CosmicSurface::Wayland(window) => PointerTarget::button(window, seat, data, event), - CosmicSurface::X11(surface) => PointerTarget::button(surface, seat, data, event), - _ => unreachable!(), - } + PointerTarget::button(&self.0, seat, data, event) } fn axis(&self, seat: &Seat, data: &mut State, frame: AxisFrame) { - match self { - CosmicSurface::Wayland(window) => PointerTarget::axis(window, seat, data, frame), - CosmicSurface::X11(surface) => PointerTarget::axis(surface, seat, data, frame), - _ => unreachable!(), - } + PointerTarget::axis(&self.0, seat, data, frame) } fn frame(&self, seat: &Seat, data: &mut State) { - match self { - CosmicSurface::Wayland(window) => PointerTarget::frame(window, seat, data), - CosmicSurface::X11(surface) => PointerTarget::frame(surface, seat, data), - _ => unreachable!(), - } + PointerTarget::frame(&self.0, seat, data) } fn leave( @@ -780,13 +673,7 @@ impl PointerTarget for CosmicSurface { serial: smithay::utils::Serial, time: u32, ) { - match self { - CosmicSurface::Wayland(window) => { - PointerTarget::leave(window, seat, data, serial, time) - } - CosmicSurface::X11(surface) => PointerTarget::leave(surface, seat, data, serial, time), - _ => unreachable!(), - } + PointerTarget::leave(&self.0, seat, data, serial, time) } fn gesture_swipe_begin( @@ -795,15 +682,7 @@ impl PointerTarget for CosmicSurface { data: &mut State, event: &GestureSwipeBeginEvent, ) { - match self { - CosmicSurface::Wayland(window) => { - PointerTarget::gesture_swipe_begin(window, seat, data, event) - } - CosmicSurface::X11(surface) => { - PointerTarget::gesture_swipe_begin(surface, seat, data, event) - } - _ => unreachable!(), - } + PointerTarget::gesture_swipe_begin(&self.0, seat, data, event) } fn gesture_swipe_update( @@ -812,15 +691,7 @@ impl PointerTarget for CosmicSurface { data: &mut State, event: &GestureSwipeUpdateEvent, ) { - match self { - CosmicSurface::Wayland(window) => { - PointerTarget::gesture_swipe_update(window, seat, data, event) - } - CosmicSurface::X11(surface) => { - PointerTarget::gesture_swipe_update(surface, seat, data, event) - } - _ => unreachable!(), - } + PointerTarget::gesture_swipe_update(&self.0, seat, data, event) } fn gesture_swipe_end( @@ -829,15 +700,7 @@ impl PointerTarget for CosmicSurface { data: &mut State, event: &GestureSwipeEndEvent, ) { - match self { - CosmicSurface::Wayland(window) => { - PointerTarget::gesture_swipe_end(window, seat, data, event) - } - CosmicSurface::X11(surface) => { - PointerTarget::gesture_swipe_end(surface, seat, data, event) - } - _ => unreachable!(), - } + PointerTarget::gesture_swipe_end(&self.0, seat, data, event) } fn gesture_pinch_begin( @@ -846,15 +709,7 @@ impl PointerTarget for CosmicSurface { data: &mut State, event: &GesturePinchBeginEvent, ) { - match self { - CosmicSurface::Wayland(window) => { - PointerTarget::gesture_pinch_begin(window, seat, data, event) - } - CosmicSurface::X11(surface) => { - PointerTarget::gesture_pinch_begin(surface, seat, data, event) - } - _ => unreachable!(), - } + PointerTarget::gesture_pinch_begin(&self.0, seat, data, event) } fn gesture_pinch_update( @@ -863,15 +718,7 @@ impl PointerTarget for CosmicSurface { data: &mut State, event: &GesturePinchUpdateEvent, ) { - match self { - CosmicSurface::Wayland(window) => { - PointerTarget::gesture_pinch_update(window, seat, data, event) - } - CosmicSurface::X11(surface) => { - PointerTarget::gesture_pinch_update(surface, seat, data, event) - } - _ => unreachable!(), - } + PointerTarget::gesture_pinch_update(&self.0, seat, data, event) } fn gesture_pinch_end( @@ -880,15 +727,7 @@ impl PointerTarget for CosmicSurface { data: &mut State, event: &GesturePinchEndEvent, ) { - match self { - CosmicSurface::Wayland(window) => { - PointerTarget::gesture_pinch_end(window, seat, data, event) - } - CosmicSurface::X11(surface) => { - PointerTarget::gesture_pinch_end(surface, seat, data, event) - } - _ => unreachable!(), - } + PointerTarget::gesture_pinch_end(&self.0, seat, data, event) } fn gesture_hold_begin( @@ -897,46 +736,23 @@ impl PointerTarget for CosmicSurface { data: &mut State, event: &GestureHoldBeginEvent, ) { - match self { - CosmicSurface::Wayland(window) => { - PointerTarget::gesture_hold_begin(window, seat, data, event) - } - CosmicSurface::X11(surface) => { - PointerTarget::gesture_hold_begin(surface, seat, data, event) - } - _ => unreachable!(), - } + PointerTarget::gesture_hold_begin(&self.0, seat, data, event) } fn gesture_hold_end(&self, seat: &Seat, data: &mut State, event: &GestureHoldEndEvent) { - match self { - CosmicSurface::Wayland(window) => { - PointerTarget::gesture_hold_end(window, seat, data, event) - } - CosmicSurface::X11(surface) => { - PointerTarget::gesture_hold_end(surface, seat, data, event) - } - _ => unreachable!(), - } + PointerTarget::gesture_hold_end(&self.0, seat, data, event) } } impl WaylandFocus for CosmicSurface { fn wl_surface(&self) -> Option { - match self { - CosmicSurface::Wayland(window) => window.wl_surface(), - CosmicSurface::X11(surface) => surface.wl_surface(), - _ => unreachable!(), - } + self.0.wl_surface() } } impl X11Relatable for CosmicSurface { fn is_window(&self, window: &X11Surface) -> bool { - match self { - CosmicSurface::X11(surface) => surface == window, - _ => false, - } + self.x11_surface() == Some(window) } } @@ -954,14 +770,6 @@ where scale: smithay::utils::Scale, alpha: f32, ) -> Vec { - match self { - CosmicSurface::Wayland(window) => { - window.render_elements(renderer, location, scale, alpha) - } - CosmicSurface::X11(surface) => { - surface.render_elements(renderer, location, scale, alpha) - } - _ => unreachable!(), - } + self.0.render_elements(renderer, location, scale, alpha) } } diff --git a/src/shell/focus/mod.rs b/src/shell/focus/mod.rs index 237bbaa6..39d92e0a 100644 --- a/src/shell/focus/mod.rs +++ b/src/shell/focus/mod.rs @@ -20,7 +20,7 @@ use tracing::{debug, trace}; use self::target::{KeyboardFocusTarget, WindowGroup}; -use super::{layout::floating::FloatingLayout, CosmicSurface}; +use super::layout::floating::FloatingLayout; pub mod target; @@ -207,11 +207,11 @@ fn raise_with_children(floating_layer: &mut FloatingLayout, focused: &CosmicMapp .space .elements() .filter(|elem| { - let parent = match elem.active_window() { - CosmicSurface::Wayland(w) => w.toplevel().parent(), - _ => None, - }; - + let parent = elem + .active_window() + .0 + .toplevel() + .and_then(|toplevel| toplevel.parent()); parent == focused.active_window().wl_surface() }) .cloned() diff --git a/src/shell/grabs/menu/default.rs b/src/shell/grabs/menu/default.rs index 9d4ad67d..7f352984 100644 --- a/src/shell/grabs/menu/default.rs +++ b/src/shell/grabs/menu/default.rs @@ -24,7 +24,9 @@ fn toggle_stacking(state: &mut State, mapped: &CosmicMapped) { fn move_prev_workspace(state: &mut State, mapped: &CosmicMapped) { let seat = state.common.last_active_seat().clone(); let (current_handle, output) = { - let Some(ws) = state.common.shell.space_for(mapped) else { return }; + let Some(ws) = state.common.shell.space_for(mapped) else { + return; + }; (ws.handle, ws.output.clone()) }; let maybe_handle = state @@ -59,7 +61,9 @@ fn move_prev_workspace(state: &mut State, mapped: &CosmicMapped) { fn move_next_workspace(state: &mut State, mapped: &CosmicMapped) { let seat = state.common.last_active_seat().clone(); let (current_handle, output) = { - let Some(ws) = state.common.shell.space_for(mapped) else { return }; + let Some(ws) = state.common.shell.space_for(mapped) else { + return; + }; (ws.handle, ws.output.clone()) }; let maybe_handle = state diff --git a/src/shell/grabs/moving.rs b/src/shell/grabs/moving.rs index 35742f6a..ff695db5 100644 --- a/src/shell/grabs/moving.rs +++ b/src/shell/grabs/moving.rs @@ -230,7 +230,7 @@ impl PointerGrab for MoveGrab { .as_logical() .overlaps_or_touches(Rectangle::from_loc_and_size( handle.current_location().to_i32_floor(), - (0,0), + (0, 0), )) }) .cloned() diff --git a/src/shell/layout/floating/grabs/resize.rs b/src/shell/layout/floating/grabs/resize.rs index f61a5490..27153d11 100644 --- a/src/shell/layout/floating/grabs/resize.rs +++ b/src/shell/layout/floating/grabs/resize.rs @@ -7,13 +7,12 @@ use crate::{ element::CosmicMapped, focus::target::PointerFocusTarget, grabs::{ReleaseMode, ResizeEdge}, - CosmicSurface, }, utils::prelude::*, }; use smithay::{ backend::input::ButtonState, - desktop::space::SpaceElement, + desktop::{space::SpaceElement, WindowSurface}, input::{ pointer::{ AxisFrame, ButtonEvent, GestureHoldBeginEvent, GestureHoldEndEvent, @@ -118,9 +117,10 @@ impl PointerGrab for ResizeSurfaceGrab { self.window.set_resizing(true); self.window.set_geometry(Rectangle::from_loc_and_size( - match self.window.active_window() { - CosmicSurface::X11(s) => s.geometry().loc.as_global(), - _ => (0, 0).into(), + if let Some(s) = self.window.active_window().x11_surface() { + s.geometry().loc.as_global() + } else { + (0, 0).into() }, self.last_window_size.as_global(), )); @@ -356,20 +356,19 @@ impl ResizeSurfaceGrab { if let Some(new_location) = new_location { for (window, offset) in window.windows() { - match window { - CosmicSurface::Wayland(window) => { + match window.0.underlying_surface() { + WindowSurface::Wayland(toplevel) => { update_reactive_popups( - &window, + toplevel, new_location + offset.as_global(), floating_layer.space.outputs(), ); } - CosmicSurface::X11(surface) => { + WindowSurface::X11(surface) => { let mut geometry = surface.geometry(); geometry.loc += (location - new_location).as_logical(); let _ = surface.configure(geometry); } - _ => unreachable!(), } } floating_layer @@ -402,9 +401,10 @@ impl ResizeSurfaceGrab { self.window.set_resizing(false); self.window.set_geometry(Rectangle::from_loc_and_size( - match self.window.active_window() { - CosmicSurface::X11(s) => s.geometry().loc.as_global(), - _ => (0, 0).into(), + if let Some(x11_surface) = self.window.active_window().x11_surface() { + x11_surface.geometry().loc.as_global() + } else { + (0, 0).into() }, self.last_window_size.as_global(), )); diff --git a/src/shell/layout/mod.rs b/src/shell/layout/mod.rs index bdae6ed3..8adfbdac 100644 --- a/src/shell/layout/mod.rs +++ b/src/shell/layout/mod.rs @@ -2,6 +2,7 @@ use regex::RegexSet; use smithay::{ + desktop::WindowSurface, wayland::{compositor::with_states, shell::xdg::XdgToplevelSurfaceData}, xwayland::xwm::WmWindowType, }; @@ -100,9 +101,9 @@ lazy_static::lazy_static! { pub fn is_dialog(window: &CosmicSurface) -> bool { // Check "window type" - match window { - CosmicSurface::Wayland(window) => { - if with_states(window.toplevel().wl_surface(), |states| { + match window.0.underlying_surface() { + WindowSurface::Wayland(toplevel) => { + if with_states(toplevel.wl_surface(), |states| { let attrs = states .data_map .get::() @@ -114,7 +115,7 @@ pub fn is_dialog(window: &CosmicSurface) -> bool { return true; } } - CosmicSurface::X11(surface) => { + WindowSurface::X11(surface) => { if surface.is_override_redirect() || surface.is_popup() || !matches!( @@ -125,7 +126,6 @@ pub fn is_dialog(window: &CosmicSurface) -> bool { return true; } } - _ => {} }; // Check if sizing suggest dialog diff --git a/src/shell/layout/tiling/grabs/swap.rs b/src/shell/layout/tiling/grabs/swap.rs index 9a84fca0..95f131f0 100644 --- a/src/shell/layout/tiling/grabs/swap.rs +++ b/src/shell/layout/tiling/grabs/swap.rs @@ -58,11 +58,19 @@ impl KeyboardGrab for SwapWindowGrab { .iter() .filter(|(_, action)| matches!(action, Action::Focus(_))) .map(|(pattern, action)| { - let Action::Focus(direction) = action else { unreachable!() }; + let Action::Focus(direction) = action else { + unreachable!() + }; (pattern.key, *direction) }) .collect::>(); - let Some(direction) = syms.iter().find_map(|sym| focus_bindings.iter().find_map(|(key, direction)| (key.is_some() && sym == key.as_ref().unwrap()).then_some(*direction))) else { return }; + let Some(direction) = syms.iter().find_map(|sym| { + focus_bindings.iter().find_map(|(key, direction)| { + (key.is_some() && sym == key.as_ref().unwrap()).then_some(*direction) + }) + }) else { + return; + }; data.handle_action( Action::Focus(direction), diff --git a/src/shell/layout/tiling/mod.rs b/src/shell/layout/tiling/mod.rs index b9f70300..0f346174 100644 --- a/src/shell/layout/tiling/mod.rs +++ b/src/shell/layout/tiling/mod.rs @@ -462,7 +462,9 @@ impl TilingLayout { pub fn replace_window(&mut self, old: &CosmicMapped, new: &CosmicMapped) { let gaps = self.gaps(); - let Some(old_id) = old.tiling_node_id.lock().unwrap().clone() else { return }; + let Some(old_id) = old.tiling_node_id.lock().unwrap().clone() else { + return; + }; let mut tree = self.queue.trees.back().unwrap().0.copy_clone(); if let Ok(node) = tree.get_mut(&old_id) { @@ -501,7 +503,13 @@ impl TilingLayout { match desc.stack_window { Some(stack_surface) => { let node = this_tree.get(&desc.node).ok()?; - let Data::Mapped { mapped: this_mapped, .. } = node.data() else { return None }; + let Data::Mapped { + mapped: this_mapped, + .. + } = node.data() + else { + return None; + }; let this_stack = this_mapped.stack_ref()?; this_stack.remove_window(&stack_surface); if !this_stack.alive() { @@ -698,7 +706,9 @@ impl TilingLayout { } } (None, None) => { - let Some(other_tree) = other_tree.as_mut() else { unreachable!() }; + let Some(other_tree) = other_tree.as_mut() else { + unreachable!() + }; let this_node = this_tree.get_mut(&this_desc.node).ok()?; let other_node = other_tree.get_mut(&other_desc.node).ok()?; @@ -842,7 +852,13 @@ impl TilingLayout { return None; } let this_node = this_tree.get_mut(&this_desc.node).ok()?; - let Data::Mapped { mapped: this_mapped, .. } = this_node.data() else { return None }; + let Data::Mapped { + mapped: this_mapped, + .. + } = this_node.data() + else { + return None; + }; let this_mapped = this_mapped.clone(); let geometry = *this_node.data().geometry(); assert!(this_mapped.is_stack()); @@ -927,7 +943,13 @@ impl TilingLayout { let other_tree = other_tree.as_mut().unwrap_or(&mut this_tree); let other_node = other_tree.get_mut(&other_desc.node).ok()?; - let Data::Mapped { mapped: other_mapped, .. } = other_node.data() else { return None }; + let Data::Mapped { + mapped: other_mapped, + .. + } = other_node.data() + else { + return None; + }; let other_mapped = other_mapped.clone(); let geometry = *other_node.data().geometry(); assert!(other_mapped.is_stack()); @@ -1259,9 +1281,7 @@ impl TilingLayout { let Some(target) = seat.get_keyboard().unwrap().current_focus() else { return MoveResult::None; }; - let Some((node_id, data)) = - TilingLayout::currently_focused_node(&mut tree, target) - else { + let Some((node_id, data)) = TilingLayout::currently_focused_node(&mut tree, target) else { return MoveResult::None; }; @@ -1587,14 +1607,10 @@ impl TilingLayout { let Some(target) = seat.get_keyboard().unwrap().current_focus() else { return FocusResult::None; }; - let Some(focused) = - TilingLayout::currently_focused_node(tree, target).or_else( - || { - TilingLayout::last_active_window(tree, focus_stack) - .map(|(id, mapped)| (id, FocusedNodeData::Window(mapped))) - }, - ) - else { + let Some(focused) = TilingLayout::currently_focused_node(tree, target).or_else(|| { + TilingLayout::last_active_window(tree, focus_stack) + .map(|(id, mapped)| (id, FocusedNodeData::Window(mapped))) + }) else { return FocusResult::None; }; @@ -2252,21 +2268,23 @@ impl TilingLayout { let gaps = self.gaps(); let mut tree = self.queue.trees.back().unwrap().0.copy_clone(); - let Some(root_id) = tree.root_node_id() else { return false }; - let Some(mut node_id) = - (match TilingLayout::currently_focused_node(&tree, focused.clone()) { - Some((_id, FocusedNodeData::Window(mapped))) => - // we need to make sure the id belongs to this tree.. - { - tree.traverse_pre_order_ids(root_id) - .unwrap() - .find(|id| tree.get(id).unwrap().data().is_mapped(Some(&mapped))) - } - Some((id, FocusedNodeData::Group(_, _))) => Some(id), // in this case the workspace handle was already matched, so the id is to be trusted - _ => None, - }) else { - return false - }; + let Some(root_id) = tree.root_node_id() else { + return false; + }; + let Some(mut node_id) = (match TilingLayout::currently_focused_node(&tree, focused.clone()) + { + Some((_id, FocusedNodeData::Window(mapped))) => + // we need to make sure the id belongs to this tree.. + { + tree.traverse_pre_order_ids(root_id) + .unwrap() + .find(|id| tree.get(id).unwrap().data().is_mapped(Some(&mapped))) + } + Some((id, FocusedNodeData::Group(_, _))) => Some(id), // in this case the workspace handle was already matched, so the id is to be trusted + _ => None, + }) else { + return false; + }; while let Some(group_id) = tree.get(&node_id).unwrap().parent().cloned() { let orientation = tree.get(&group_id).unwrap().data().orientation(); @@ -3138,8 +3156,8 @@ impl TilingLayout { .unwrap() .position(|node| { let Some(geo) = geometries.get(node) else { - return false; - }; + return false; + }; match orientation { Orientation::Vertical => location.x < geo.loc.x, Orientation::Horizontal => location.y < geo.loc.y, diff --git a/src/shell/mod.rs b/src/shell/mod.rs index 19f57956..aafb88ed 100644 --- a/src/shell/mod.rs +++ b/src/shell/mod.rs @@ -15,7 +15,7 @@ use keyframe::{ease, functions::EaseInOutCubic}; use smithay::{ desktop::{ layer_map_for_output, space::SpaceElement, LayerSurface, PopupKind, PopupManager, - WindowSurfaceType, + WindowSurface, WindowSurfaceType, }, input::{ pointer::{Focus, GrabStartData as PointerGrabStartData, MotionEvent}, @@ -170,10 +170,11 @@ pub enum ActivationKey { impl From<&CosmicSurface> for ActivationKey { fn from(value: &CosmicSurface) -> Self { - match value { - CosmicSurface::Wayland(w) => ActivationKey::Wayland(w.toplevel().wl_surface().clone()), - CosmicSurface::X11(s) => ActivationKey::X11(s.window_id()), - _ => unreachable!(), + match value.0.underlying_surface() { + WindowSurface::Wayland(toplevel) => { + ActivationKey::Wayland(toplevel.wl_surface().clone()) + } + WindowSurface::X11(s) => ActivationKey::X11(s.window_id()), } } } @@ -1091,19 +1092,19 @@ impl Shell { .map(|(_, w, _)| w) .chain(set.workspaces[set.active].floating_layer.space.elements()) { - if let CosmicSurface::X11(surf) = window.active_window() { - let _ = xwm.raise_window(&surf); + if let Some(surf) = window.active_window().x11_surface() { + let _ = xwm.raise_window(surf); } } for window in set.sticky_layer.space.elements() { - if let CosmicSurface::X11(surf) = window.active_window() { - let _ = xwm.raise_window(&surf); + if let Some(surf) = window.active_window().x11_surface() { + let _ = xwm.raise_window(surf); } } - if let Some(CosmicSurface::X11(ref surf)) = set.workspaces[set.active] + if let Some(surf) = set.workspaces[set.active] .fullscreen .as_ref() - .map(|f| &f.surface) + .and_then(|f| f.surface.x11_surface()) { let _ = xwm.raise_window(surf); } @@ -1258,6 +1259,19 @@ impl Shell { }) } + pub fn element_for_x11_surface(&self, surface: &X11Surface) -> Option<&CosmicMapped> { + self.workspaces.sets.values().find_map(|set| { + set.sticky_layer + .mapped() + .find(|w| w.windows().any(|(s, _)| s.x11_surface() == Some(surface))) + .or_else(|| { + set.workspaces + .iter() + .find_map(|w| w.element_for_x11_surface(surface)) + }) + }) + } + pub fn space_for(&self, mapped: &CosmicMapped) -> Option<&Workspace> { self.workspaces .spaces() @@ -1554,25 +1568,24 @@ impl Shell { .unwrap(); let (window, seat, output) = state.common.shell.pending_windows.remove(pos); - let parent_is_sticky = match window.clone() { - CosmicSurface::Wayland(toplevel) => { - if let Some(parent) = toplevel.toplevel().parent() { - if let Some(elem) = state.common.shell.element_for_wl_surface(&parent) { - state - .common - .shell - .workspaces - .sets - .values() - .any(|set| set.sticky_layer.mapped().any(|m| m == elem)) - } else { - false - } + let parent_is_sticky = if let Some(toplevel) = window.0.toplevel() { + if let Some(parent) = toplevel.parent() { + if let Some(elem) = state.common.shell.element_for_wl_surface(&parent) { + state + .common + .shell + .workspaces + .sets + .values() + .any(|set| set.sticky_layer.mapped().any(|m| m == elem)) } else { false } + } else { + false } - _ => false, + } else { + false }; let pending_activation = state @@ -2013,11 +2026,11 @@ impl Shell { .unwrap() .loc .to_global(&workspace.output); - for (toplevel, offset) in mapped.windows() { - if let CosmicSurface::Wayland(toplevel) = toplevel { - let window_geo_offset = toplevel.geometry().loc.as_global(); + for (window, offset) in mapped.windows() { + if let Some(toplevel) = window.0.toplevel() { + let window_geo_offset = window.geometry().loc.as_global(); update_reactive_popups( - &toplevel, + toplevel, element_loc + offset.as_global() + window_geo_offset, self.outputs(), ); diff --git a/src/shell/workspace.rs b/src/shell/workspace.rs index 19341e81..b83761a3 100644 --- a/src/shell/workspace.rs +++ b/src/shell/workspace.rs @@ -44,6 +44,7 @@ use smithay::{ seat::WaylandFocus, xdg_activation::{XdgActivationState, XdgActivationToken}, }, + xwayland::X11Surface, }; use std::{ collections::{HashMap, HashSet, VecDeque}, @@ -418,6 +419,13 @@ impl Workspace { }) } + pub fn element_for_x11_surface(&self, surface: &X11Surface) -> Option<&CosmicMapped> { + self.floating_layer + .mapped() + .chain(self.tiling_layer.mapped().map(|(_, w, _)| w)) + .find(|e| e.windows().any(|(w, _)| w.x11_surface() == Some(surface))) + } + pub fn element_under( &mut self, location: Point, diff --git a/src/wayland/handlers/compositor.rs b/src/wayland/handlers/compositor.rs index 367f6525..68669a08 100644 --- a/src/wayland/handlers/compositor.rs +++ b/src/wayland/handlers/compositor.rs @@ -1,9 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only -use crate::{ - shell::CosmicSurface, state::ClientState, utils::prelude::*, - wayland::protocols::screencopy::SessionType, -}; +use crate::{state::ClientState, utils::prelude::*, wayland::protocols::screencopy::SessionType}; use calloop::Interest; use smithay::{ backend::renderer::utils::{on_commit_buffer_handler, with_renderer_surface_state}, @@ -157,21 +154,14 @@ impl CompositorHandler for State { .find(|(window, _, _)| window.wl_surface().as_ref() == Some(surface)) .cloned() { - match window { - CosmicSurface::Wayland(ref wl_window) => { - let toplevel = wl_window.toplevel(); - if self.toplevel_ensure_initial_configure(&toplevel) - && with_renderer_surface_state(&surface, |state| state.buffer().is_some()) - .unwrap_or(false) - { - window.on_commit(); - Shell::map_window(self, &window); - } else { - return; - } + if let Some(toplevel) = window.0.toplevel() { + if self.toplevel_ensure_initial_configure(&toplevel) + && with_renderer_surface_state(&surface, |state| state.buffer().is_some()) + .unwrap_or(false) + { + window.on_commit(); + Shell::map_window(self, &window); } - CosmicSurface::X11(_) => {} - _ => unreachable!(), } } diff --git a/src/wayland/handlers/decoration.rs b/src/wayland/handlers/decoration.rs index 151e0890..6a085e9e 100644 --- a/src/wayland/handlers/decoration.rs +++ b/src/wayland/handlers/decoration.rs @@ -20,10 +20,7 @@ use smithay::{ }; use wayland_backend::protocol::WEnum; -use crate::{ - shell::{CosmicMapped, CosmicSurface}, - state::State, -}; +use crate::{shell::CosmicMapped, state::State}; pub struct PreferredDecorationMode(RefCell>); @@ -60,53 +57,61 @@ impl PreferredDecorationMode { impl State { pub fn new_decoration(mapped: &CosmicMapped, surface: &WlSurface) -> KdeMode { if mapped.is_stack() { - if let Some((CosmicSurface::Wayland(window), _)) = mapped + if let Some((window, _)) = mapped .windows() .find(|(window, _)| window.wl_surface().as_ref() == Some(surface)) { - window - .toplevel() - .with_pending_state(|state| state.decoration_mode = Some(XdgMode::ServerSide)); - window.toplevel().send_configure(); + if let Some(toplevel) = window.0.toplevel() { + toplevel.with_pending_state(|state| { + state.decoration_mode = Some(XdgMode::ServerSide) + }); + toplevel.send_configure(); + } } KdeMode::Server } else { - if let Some((CosmicSurface::Wayland(window), _)) = mapped + if let Some((window, _)) = mapped .windows() .find(|(window, _)| window.wl_surface().as_ref() == Some(surface)) { - window - .toplevel() - .with_pending_state(|state| state.decoration_mode = Some(XdgMode::ClientSide)); - window.toplevel().send_configure(); + if let Some(toplevel) = window.0.toplevel() { + toplevel.with_pending_state(|state| { + state.decoration_mode = Some(XdgMode::ClientSide) + }); + toplevel.send_configure(); + } } KdeMode::Client } } pub fn request_mode(mapped: &CosmicMapped, surface: &WlSurface, mode: XdgMode) { - if let Some((CosmicSurface::Wayland(window), _)) = mapped + if let Some((window, _)) = mapped .windows() .find(|(window, _)| window.wl_surface().as_ref() == Some(surface)) { - PreferredDecorationMode::update(&window, Some(mode)); - window.toplevel().with_pending_state(|state| { - state.decoration_mode = Some(mode); - }); - window.toplevel().send_configure(); + if let Some(toplevel) = window.0.toplevel() { + PreferredDecorationMode::update(&window.0, Some(mode)); + toplevel.with_pending_state(|state| { + state.decoration_mode = Some(mode); + }); + toplevel.send_configure(); + } } } pub fn unset_mode(mapped: &CosmicMapped, surface: &WlSurface) { - if let Some((CosmicSurface::Wayland(window), _)) = mapped + if let Some((window, _)) = mapped .windows() .find(|(window, _)| window.wl_surface().as_ref() == Some(surface)) { - PreferredDecorationMode::update(&window, None); - window.toplevel().with_pending_state(|state| { - state.decoration_mode = None; - }); - window.toplevel().send_configure(); + if let Some(toplevel) = window.0.toplevel() { + PreferredDecorationMode::update(&window.0, None); + toplevel.with_pending_state(|state| { + state.decoration_mode = None; + }); + toplevel.send_configure(); + } } } } diff --git a/src/wayland/handlers/dmabuf.rs b/src/wayland/handlers/dmabuf.rs index fd48d355..5be49b9b 100644 --- a/src/wayland/handlers/dmabuf.rs +++ b/src/wayland/handlers/dmabuf.rs @@ -30,7 +30,7 @@ impl DmabufHandler for State { Ok(Some(node)) => { // kms backend let Ok(buffer) = import_notifier.successful::() else { - return + return; }; if let BackendData::Kms(kms_state) = &mut self.backend { diff --git a/src/wayland/handlers/toplevel_management.rs b/src/wayland/handlers/toplevel_management.rs index 4fbaab6b..75ca3707 100644 --- a/src/wayland/handlers/toplevel_management.rs +++ b/src/wayland/handlers/toplevel_management.rs @@ -68,7 +68,12 @@ impl ToplevelManagementHandler for State { workspace: ZcosmicWorkspaceHandleV1, _output: Output, ) { - let Some(to_handle) = self.common.shell.workspace_state.get_workspace_handle(&workspace) else { + let Some(to_handle) = self + .common + .shell + .workspace_state + .get_workspace_handle(&workspace) + else { return; }; diff --git a/src/wayland/handlers/xdg_activation.rs b/src/wayland/handlers/xdg_activation.rs index c0f895e0..c21c2d64 100644 --- a/src/wayland/handlers/xdg_activation.rs +++ b/src/wayland/handlers/xdg_activation.rs @@ -61,14 +61,16 @@ impl XdgActivationHandler for State { // Tokens without validation aren't allowed to steal focus let Some((serial, seat)) = data.serial else { - data.user_data.insert_if_missing(|| ActivationContext::UrgentOnly); + data.user_data + .insert_if_missing(|| ActivationContext::UrgentOnly); debug!(?token, "created urgent-only token for missing seat/serial"); - return true + return true; }; let Some(seat) = Seat::from_resource(&seat) else { - data.user_data.insert_if_missing(|| ActivationContext::UrgentOnly); + data.user_data + .insert_if_missing(|| ActivationContext::UrgentOnly); debug!(?token, "created urgent-only token for unknown seat"); - return true + return true; }; // At this point we don't bother with urgent-only tokens. diff --git a/src/wayland/handlers/xdg_shell/mod.rs b/src/wayland/handlers/xdg_shell/mod.rs index f2385b8d..915c0c63 100644 --- a/src/wayland/handlers/xdg_shell/mod.rs +++ b/src/wayland/handlers/xdg_shell/mod.rs @@ -9,7 +9,7 @@ use smithay::{ delegate_xdg_shell, desktop::{ find_popup_root_surface, PopupGrab, PopupKeyboardGrab, PopupKind, PopupPointerGrab, - PopupUngrabStrategy, Window, + PopupUngrabStrategy, }, input::{pointer::Focus, Seat}, output::Output, @@ -43,7 +43,7 @@ impl XdgShellHandler for State { fn new_toplevel(&mut self, surface: ToplevelSurface) { let seat = self.common.last_active_seat().clone(); - let window = CosmicSurface::Wayland(Window::new(surface)); + let window = CosmicSurface::from(surface); self.common.shell.pending_windows.push((window, seat, None)); // We will position the window after the first commit, when we know its size hints } diff --git a/src/wayland/handlers/xdg_shell/popup.rs b/src/wayland/handlers/xdg_shell/popup.rs index 271a21ba..b69aee92 100644 --- a/src/wayland/handlers/xdg_shell/popup.rs +++ b/src/wayland/handlers/xdg_shell/popup.rs @@ -3,7 +3,7 @@ use crate::{shell::Shell, utils::prelude::*}; use smithay::{ desktop::{ - layer_map_for_output, space::SpaceElement, LayerSurface, PopupKind, PopupManager, Window, + layer_map_for_output, space::SpaceElement, LayerSurface, PopupKind, PopupManager, WindowSurfaceType, }, output::Output, @@ -18,8 +18,8 @@ use smithay::{ compositor::{get_role, with_states}, seat::WaylandFocus, shell::xdg::{ - PopupSurface, PositionerState, SurfaceCachedState, XdgPopupSurfaceRoleAttributes, - XDG_POPUP_ROLE, + PopupSurface, PositionerState, SurfaceCachedState, ToplevelSurface, + XdgPopupSurfaceRoleAttributes, XDG_POPUP_ROLE, }, }, }; @@ -85,12 +85,12 @@ impl Shell { } pub fn update_reactive_popups<'a>( - window: &Window, + toplevel: &ToplevelSurface, loc: Point, outputs: impl Iterator, ) { let output_geo = outputs.map(|o| o.geometry()).collect::>(); - for (popup, _) in PopupManager::popups_for_surface(window.toplevel().wl_surface()) { + for (popup, _) in PopupManager::popups_for_surface(toplevel.wl_surface()) { match popup { PopupKind::Xdg(surface) => { let positioner = with_states(&surface.wl_surface(), |states| { diff --git a/src/xwayland.rs b/src/xwayland.rs index a0f11f87..8b925bf2 100644 --- a/src/xwayland.rs +++ b/src/xwayland.rs @@ -153,8 +153,7 @@ impl XwmHandler for State { } let startup_id = window.startup_id(); - let surface = CosmicSurface::X11(window.clone()); - if self.common.shell.element_for_surface(&surface).is_some() { + if self.common.shell.element_for_x11_surface(&window).is_some() { return; } @@ -175,6 +174,7 @@ impl XwmHandler for State { ); } + let surface = CosmicSurface::from(window); self.common .shell .pending_windows @@ -187,13 +187,7 @@ impl XwmHandler for State { .shell .pending_windows .iter() - .find(|(window, _, _)| { - if let CosmicSurface::X11(window) = window { - window == &surface - } else { - false - } - }) + .find(|(window, _, _)| window.x11_surface() == Some(&surface)) .cloned() { if !self @@ -202,10 +196,7 @@ impl XwmHandler for State { .pending_activations .contains_key(&crate::shell::ActivationKey::X11(surface.window_id())) { - if let Some(startup_id) = match &window { - CosmicSurface::X11(x11) => x11.startup_id(), - _ => None, - } { + if let Some(startup_id) = window.x11_surface().and_then(|x| x.startup_id()) { if let Some(context) = self .common .shell @@ -238,7 +229,6 @@ impl XwmHandler for State { } fn unmapped_window(&mut self, _xwm: XwmId, window: X11Surface) { - let surface = CosmicSurface::X11(window.clone()); if window.is_override_redirect() { self.common .shell @@ -247,7 +237,7 @@ impl XwmHandler for State { } else if let Some((element, space)) = self .common .shell - .element_for_surface(&surface) + .element_for_x11_surface(&window) .cloned() .and_then(|element| { self.common @@ -257,7 +247,12 @@ impl XwmHandler for State { }) { if element.is_stack() && element.stack_ref().unwrap().len() >= 2 { - element.stack_ref().unwrap().remove_window(&surface); + if let Some((surface, _)) = element + .windows() + .find(|(w, _)| w.x11_surface() == Some(&window)) + { + element.stack_ref().unwrap().remove_window(&surface); + } } else { space.unmap(&element); } @@ -322,11 +317,7 @@ impl XwmHandler for State { ) { // We only allow floating X11 windows to resize themselves. Nothing else let mut current_geo = window.geometry(); - if let Some(mapped) = self - .common - .shell - .element_for_surface(&CosmicSurface::X11(window.clone())) - { + if let Some(mapped) = self.common.shell.element_for_x11_surface(&window) { let space = self.common.shell.space_for(mapped).unwrap(); if space.is_floating(mapped) { mapped.set_geometry( @@ -424,24 +415,26 @@ impl XwmHandler for State { } fn maximize_request(&mut self, _xwm: XwmId, window: X11Surface) { - let surface = CosmicSurface::X11(window); - if let Some(mapped) = self.common.shell.element_for_surface(&surface).cloned() { + if let Some(mapped) = self.common.shell.element_for_x11_surface(&window).cloned() { self.common.shell.maximize_request(&mapped); } } fn unmaximize_request(&mut self, _xwm: XwmId, window: X11Surface) { - let surface = CosmicSurface::X11(window); - if let Some(mapped) = self.common.shell.element_for_surface(&surface).cloned() { + if let Some(mapped) = self.common.shell.element_for_x11_surface(&window).cloned() { self.common.shell.unmaximize_request(&mapped); } } fn fullscreen_request(&mut self, _xwm: XwmId, window: X11Surface) { - let surface = CosmicSurface::X11(window); - if let Some(mapped) = self.common.shell.element_for_surface(&surface).cloned() { + if let Some(mapped) = self.common.shell.element_for_x11_surface(&window).cloned() { if let Some(workspace) = self.common.shell.space_for_mut(&mapped) { - workspace.fullscreen_request(&surface, None) + if let Some((surface, _)) = mapped + .windows() + .find(|(w, _)| w.x11_surface() == Some(&window)) + { + workspace.fullscreen_request(&surface, None) + } } } else { let output = self.common.last_active_seat().active_output(); @@ -450,7 +443,7 @@ impl XwmHandler for State { .shell .pending_windows .iter_mut() - .find(|(s, _, _)| s == &surface) + .find(|(s, _, _)| s.x11_surface() == Some(&window)) .map(|(_, _, o)| o) { *o = Some(output); @@ -459,10 +452,12 @@ impl XwmHandler for State { } fn unfullscreen_request(&mut self, _xwm: XwmId, window: X11Surface) { - let surface = CosmicSurface::X11(window); - if let Some(mapped) = self.common.shell.element_for_surface(&surface).cloned() { + if let Some(mapped) = self.common.shell.element_for_x11_surface(&window).cloned() { if let Some(workspace) = self.common.shell.space_for_mut(&mapped) { - let (window, _) = mapped.windows().find(|(w, _)| w == &surface).unwrap(); + let (window, _) = mapped + .windows() + .find(|(w, _)| w.x11_surface() == Some(&window)) + .unwrap(); let previous = workspace.unfullscreen_request(&window); assert!(previous.is_none()); } @@ -539,7 +534,7 @@ impl Common { fn is_x_focused(&self, xwm: XwmId) -> bool { if let Some(keyboard) = self.last_active_seat().get_keyboard() { if let Some(KeyboardFocusTarget::Element(mapped)) = keyboard.current_focus() { - if let CosmicSurface::X11(surface) = mapped.active_window() { + if let Some(surface) = mapped.active_window().x11_surface() { return surface.xwm_id().unwrap() == xwm; } }