From 6cf1fe29fc056769621faa5f89cdcb0e9209631f Mon Sep 17 00:00:00 2001 From: Ashley Wulber Date: Fri, 22 Nov 2024 19:06:12 -0500 Subject: [PATCH] feat: implement handler for overlap notify --- Cargo.lock | 2 +- Cargo.toml | 60 ++++++++++++++++--------- src/state.rs | 5 +++ src/wayland/handlers/mod.rs | 1 + src/wayland/handlers/overlap_notify.rs | 42 +++++++++++++++++ src/wayland/protocols/overlap_notify.rs | 24 ++++++++-- 6 files changed, 107 insertions(+), 27 deletions(-) create mode 100644 src/wayland/handlers/overlap_notify.rs diff --git a/Cargo.lock b/Cargo.lock index aebb3e94..445de3d4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4667,7 +4667,7 @@ checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "smithay" version = "0.3.0" -source = "git+https://github.com/smithay//smithay?rev=05c49f7#05c49f7a193bc89fba12a6484dbac895d5c9f853" +source = "git+https://github.com/wash2/smithay?branch=shell-surface#f71169dd227883819362e5b550e9c2899b0169f8" dependencies = [ "appendlist", "ash 0.38.0+1.3.281", diff --git a/Cargo.toml b/Cargo.toml index 6aa22761..a0e38969 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,49 +6,65 @@ name = "cosmic-comp" version = "0.1.0" [workspace] -members = [ - "cosmic-comp-config", -] +members = ["cosmic-comp-config"] [dependencies] -anyhow = {version = "1.0.51", features = ["backtrace"]} +anyhow = { version = "1.0.51", features = ["backtrace"] } bitflags = "2.4" bytemuck = "1.12" -calloop = {version = "0.14.1", features = ["executor"]} -cosmic-comp-config = {path = "cosmic-comp-config"} -cosmic-config = {git = "https://github.com/pop-os/libcosmic/", features = ["calloop", "macro"]} -cosmic-protocols = {git = "https://github.com/pop-os/cosmic-protocols", branch = "main", default-features = false, features = ["server"]} +calloop = { version = "0.14.1", features = ["executor"] } +cosmic-comp-config = { path = "cosmic-comp-config" } +cosmic-config = { git = "https://github.com/pop-os/libcosmic/", features = [ + "calloop", + "macro", +] } +cosmic-protocols = { git = "https://github.com/pop-os/cosmic-protocols", branch = "main", default-features = false, features = [ + "server", +] } cosmic-settings-config = { git = "https://github.com/pop-os/cosmic-settings-daemon" } -edid-rs = {version = "0.1"} -egui = {version = "0.29.0", optional = true} -egui_plot = {version = "0.29.0", optional = true} +edid-rs = { version = "0.1" } +egui = { version = "0.29.0", optional = true } +egui_plot = { version = "0.29.0", optional = true } glow = "0.12.0" -i18n-embed = {version = "0.14", features = ["fluent-system", "desktop-requester"]} +i18n-embed = { version = "0.14", features = [ + "fluent-system", + "desktop-requester", +] } i18n-embed-fl = "0.8" -iced_tiny_skia = {git = "https://github.com/pop-os/libcosmic/"} +iced_tiny_skia = { git = "https://github.com/pop-os/libcosmic/" } indexmap = "2.0" keyframe = "1.1.1" lazy_static = "1.4.0" libc = "0.2.149" -libcosmic = {git = "https://github.com/pop-os/libcosmic/", default-features = false} -libsystemd = {version = "0.7", optional = true} -log-panics = {version = "2", features = ["with-backtrace"]} +libcosmic = { git = "https://github.com/pop-os/libcosmic/", default-features = false } +libsystemd = { version = "0.7", optional = true } +log-panics = { version = "2", features = ["with-backtrace"] } once_cell = "1.18.0" ordered-float = "4.0" png = "0.17.5" regex = "1" ron = "0.8" -rust-embed = {version = "8.0", features = ["debug-embed"]} +rust-embed = { version = "8.0", features = ["debug-embed"] } sanitize-filename = "0.5.0" sendfd = "0.4.1" -serde = {version = "1", features = ["derive"]} +serde = { version = "1", features = ["derive"] } serde_json = "1" thiserror = "1.0.26" -time = {version = "0.3.30", features = ["macros", "formatting", "local-offset"]} +time = { version = "0.3.30", features = [ + "macros", + "formatting", + "local-offset", +] } tiny-skia = "0.11" -tracing = { version = "0.1.37", features = ["max_level_debug", "release_max_level_info"] } +tracing = { version = "0.1.37", features = [ + "max_level_debug", + "release_max_level_info", +] } tracing-journald = "0.3.0" -tracing-subscriber = {version = "0.3.16", features = ["env-filter", "tracing-log"]} +tracing-subscriber = { version = "0.3.16", features = [ + "env-filter", + "tracing-log", +] } wayland-backend = "0.3.3" wayland-scanner = "0.31.1" xcursor = "0.3.3" @@ -119,4 +135,4 @@ inherits = "release" lto = "fat" [patch."https://github.com/Smithay/smithay.git"] -smithay = { git = "https://github.com/smithay//smithay", rev = "05c49f7" } +smithay = { git = "https://github.com/wash2/smithay", branch = "shell-surface" } diff --git a/src/state.rs b/src/state.rs index a5e68943..ce337297 100644 --- a/src/state.rs +++ b/src/state.rs @@ -17,6 +17,7 @@ use crate::{ image_source::ImageSourceState, output_configuration::OutputConfigurationState, output_power::OutputPowerState, + overlap_notify::OverlapNotifyState, screencopy::ScreencopyState, toplevel_info::ToplevelInfoState, toplevel_management::{ManagementCapabilities, ToplevelManagementState}, @@ -217,6 +218,7 @@ pub struct Common { pub viewporter_state: ViewporterState, pub kde_decoration_state: KdeDecorationState, pub xdg_decoration_state: XdgDecorationState, + pub overlap_notify_state: OverlapNotifyState, // shell-related wayland state pub xdg_shell_state: XdgShellState, @@ -497,6 +499,8 @@ impl State { let output_state = OutputManagerState::new_with_xdg_output::(dh); let output_configuration_state = OutputConfigurationState::new(dh, client_is_privileged); let output_power_state = OutputPowerState::new::(dh, client_is_privileged); + let overlap_notify_state = + OverlapNotifyState::new::(dh, client_has_no_security_context); let presentation_state = PresentationState::new::(dh, clock.id() as u32); let primary_selection_state = PrimarySelectionState::new::(dh); let image_source_state = ImageSourceState::new::(dh, client_is_privileged); @@ -607,6 +611,7 @@ impl State { output_state, output_configuration_state, output_power_state, + overlap_notify_state, presentation_state, primary_selection_state, data_control_state, diff --git a/src/wayland/handlers/mod.rs b/src/wayland/handlers/mod.rs index 52414103..870d74e2 100644 --- a/src/wayland/handlers/mod.rs +++ b/src/wayland/handlers/mod.rs @@ -21,6 +21,7 @@ pub mod layer_shell; pub mod output; pub mod output_configuration; pub mod output_power; +pub mod overlap_notify; pub mod pointer_constraints; pub mod pointer_gestures; pub mod presentation; diff --git a/src/wayland/handlers/overlap_notify.rs b/src/wayland/handlers/overlap_notify.rs new file mode 100644 index 00000000..7b948653 --- /dev/null +++ b/src/wayland/handlers/overlap_notify.rs @@ -0,0 +1,42 @@ +use smithay::{ + desktop::{layer_map_for_output, LayerSurface, WindowSurfaceType}, + output::Output, + reexports::wayland_protocols_wlr::layer_shell::v1::server::zwlr_layer_surface_v1::ZwlrLayerSurfaceV1, +}; + +use crate::{ + state::State, + wayland::protocols::overlap_notify::{ + delegate_overlap_notify, OverlapNotifyHandler, OverlapNotifyState, + }, +}; + +impl OverlapNotifyHandler for State { + fn overlap_notify_state(&mut self) -> &mut OverlapNotifyState { + &mut self.common.overlap_notify_state + } + + fn layer_surface_from_resource(&self, resource: ZwlrLayerSurfaceV1) -> Option { + self.common + .layer_shell_state + .layer_surfaces() + .find(|l| l.shell_surface() == &resource) + .and_then(|l| { + let shell = self.common.shell.read().unwrap(); + let outputs = shell.outputs(); + let ret = outputs.map(|o| layer_map_for_output(o)).find_map(|s| { + s.layer_for_surface(l.wl_surface(), WindowSurfaceType::ALL) + .cloned() + }); + drop(shell); + ret + }) + } + + fn outputs(&self) -> impl Iterator { + let shell = self.common.shell.read().unwrap(); + shell.outputs().cloned().collect::>().into_iter() + } +} + +delegate_overlap_notify!(State); diff --git a/src/wayland/protocols/overlap_notify.rs b/src/wayland/protocols/overlap_notify.rs index 2a79c268..2db73941 100644 --- a/src/wayland/protocols/overlap_notify.rs +++ b/src/wayland/protocols/overlap_notify.rs @@ -37,6 +37,7 @@ use super::toplevel_info::{ ToplevelHandleState, ToplevelInfoGlobalData, ToplevelInfoHandler, ToplevelState, Window, }; +#[derive(Debug)] pub struct OverlapNotifyState { instances: Vec, global: GlobalId, @@ -83,7 +84,7 @@ impl OverlapNotifyState { W: Window + 'static, { for output in state.outputs() { - let map = layer_map_for_output(output); + let map = layer_map_for_output(&output); for layer_surface in map.layers() { if let Some(data) = layer_surface .user_data() @@ -94,7 +95,7 @@ impl OverlapNotifyState { if inner.has_active_notifications() { let mut new_snapshot = OverlapSnapshot::default(); - let layer_geo = layer_surface.bbox().as_local().to_global(output); + let layer_geo = layer_surface.bbox().as_local().to_global(&output); for window in state.toplevel_info_state().registered_toplevels() { if let Some(window_geo) = window.global_geometry() { @@ -111,7 +112,7 @@ impl OverlapNotifyState { } for other_surface in map.layers().filter(|s| *s != layer_surface) { - let other_geo = other_surface.bbox().as_local().to_global(output); + let other_geo = other_surface.bbox().as_local().to_global(&output); if let Some(intersection) = layer_geo.intersection(other_geo) { // relative to window location let region = Rectangle::from_loc_and_size( @@ -134,7 +135,7 @@ impl OverlapNotifyState { pub trait OverlapNotifyHandler: ToplevelInfoHandler { fn overlap_notify_state(&mut self) -> &mut OverlapNotifyState; fn layer_surface_from_resource(&self, resource: ZwlrLayerSurfaceV1) -> Option; - fn outputs(&self) -> impl Iterator; + fn outputs(&self) -> impl Iterator; } pub struct OverlapNotifyGlobalData { @@ -392,3 +393,18 @@ where } } } + +macro_rules! delegate_overlap_notify { + ($(@<$( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? ),+>)? $ty: ty) => { + smithay::reexports::wayland_server::delegate_global_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: [ + cosmic_protocols::overlap_notify::v1::server::zcosmic_overlap_notify_v1::ZcosmicOverlapNotifyV1: $crate::wayland::protocols::overlap_notify::OverlapNotifyGlobalData + ] => $crate::wayland::protocols::overlap_notify::OverlapNotifyState); + smithay::reexports::wayland_server::delegate_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: [ + cosmic_protocols::overlap_notify::v1::server::zcosmic_overlap_notify_v1::ZcosmicOverlapNotifyV1: () + ] => $crate::wayland::protocols::overlap_notify::OverlapNotifyState); + smithay::reexports::wayland_server::delegate_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: [ + cosmic_protocols::overlap_notify::v1::server::zcosmic_overlap_notification_v1::ZcosmicOverlapNotificationV1: () + ] => $crate::wayland::protocols::overlap_notify::OverlapNotifyState); + }; +} +pub(crate) use delegate_overlap_notify;