diff --git a/src/shell/element/surface.rs b/src/shell/element/surface.rs index 9b6ea72a..dfcbbb3a 100644 --- a/src/shell/element/surface.rs +++ b/src/shell/element/surface.rs @@ -33,6 +33,7 @@ use smithay::{ shell::server::xdg_toplevel::State as ToplevelState, }, }, + wayland_protocols_misc::server_decoration::server::org_kde_kwin_server_decoration::Mode as KdeMode, wayland_server::protocol::wl_surface::WlSurface, }, utils::{ @@ -50,7 +51,7 @@ use tracing::trace; use crate::{ state::{State, SurfaceDmabufFeedback}, utils::prelude::*, - wayland::handlers::decoration::PreferredDecorationMode, + wayland::handlers::decoration::{KdeDecorationData, PreferredDecorationMode}, }; #[derive(Debug, Clone, PartialEq)] @@ -216,20 +217,29 @@ impl CosmicSurface { pub fn is_decorated(&self, pending: bool) -> bool { match self.0.underlying_surface() { WindowSurface::Wayland(toplevel) => { - if pending { + let xdg_state = if pending { toplevel.with_pending_state(|pending| { pending .decoration_mode .map(|mode| mode == DecorationMode::ClientSide) - .unwrap_or(true) }) } else { toplevel .current_state() .decoration_mode .map(|mode| mode == DecorationMode::ClientSide) - .unwrap_or(true) - } + }; + + xdg_state + .or_else(|| { + with_states(toplevel.wl_surface(), |states| { + states + .data_map + .get::() + .map(|data| data.lock().unwrap().mode != KdeMode::Server) + }) + }) + .unwrap_or(true) } WindowSurface::X11(surface) => surface.is_decorated(), } @@ -247,11 +257,25 @@ impl CosmicSurface { toplevel.with_pending_state(|pending| { pending.decoration_mode = Some(DecorationMode::ServerSide); }); + with_states(toplevel.wl_surface(), |data| { + if let Some(kde_data) = data.data_map.get::() { + for obj in kde_data.lock().unwrap().objs.iter() { + obj.mode(KdeMode::Server); + } + } + }) } else { let previous_mode = PreferredDecorationMode::mode(&self.0); toplevel.with_pending_state(|pending| { pending.decoration_mode = previous_mode; }); + with_states(toplevel.wl_surface(), |data| { + if let Some(kde_data) = data.data_map.get::() { + for obj in kde_data.lock().unwrap().objs.iter() { + obj.mode(KdeMode::Server); + } + } + }) } } WindowSurface::X11(_surface) => {} diff --git a/src/wayland/handlers/decoration.rs b/src/wayland/handlers/decoration.rs index 8589f7b9..1dff562f 100644 --- a/src/wayland/handlers/decoration.rs +++ b/src/wayland/handlers/decoration.rs @@ -1,4 +1,4 @@ -use std::cell::RefCell; +use std::{cell::RefCell, sync::Mutex}; use smithay::{ delegate_kde_decoration, delegate_xdg_decoration, @@ -11,6 +11,7 @@ use smithay::{ wayland_server::protocol::wl_surface::WlSurface, }, wayland::{ + compositor::with_states, seat::WaylandFocus, shell::{ kde::decoration::{KdeDecorationHandler, KdeDecorationState}, @@ -54,6 +55,22 @@ impl PreferredDecorationMode { } } +pub type KdeDecorationData = Mutex; +#[derive(Debug)] +pub struct KdeDecorationSurfaceState { + pub mode: KdeMode, + pub objs: Vec, +} + +impl Default for KdeDecorationSurfaceState { + fn default() -> Self { + KdeDecorationSurfaceState { + mode: KdeMode::Client, + objs: Vec::new(), + } + } +} + pub fn new_decoration(mapped: &CosmicMapped, surface: &WlSurface) -> KdeMode { if mapped.is_stack() { if let Some((window, _)) = mapped @@ -143,10 +160,22 @@ impl KdeDecorationHandler for State { } fn new_decoration(&mut self, surface: &WlSurface, decoration: &OrgKdeKwinServerDecoration) { + with_states(surface, |states| { + states + .data_map + .get_or_insert::(Default::default) + .lock() + .unwrap() + .objs + .push(decoration.clone()) + }); + let shell = self.common.shell.read(); if let Some(mapped) = shell.element_for_surface(surface) { let mode = new_decoration(mapped, surface); decoration.mode(mode); + } else { + decoration.mode(KdeMode::Client); } } @@ -157,8 +186,16 @@ impl KdeDecorationHandler for State { mode: WEnum, ) { if let WEnum::Value(mode) = mode { + with_states(surface, |states| { + states + .data_map + .get_or_insert::(Default::default) + .lock() + .unwrap() + .mode = mode + }); + let shell = self.common.shell.read(); - // TODO: We need to store this value until it gets mapped and apply it then, if it is not mapped yet. if let Some(mapped) = shell.element_for_surface(surface) { request_mode( mapped, @@ -168,12 +205,22 @@ impl KdeDecorationHandler for State { _ => XdgMode::ClientSide, }, ); - decoration.mode(mode); } + decoration.mode(mode); } } - fn release(&mut self, _decoration: &OrgKdeKwinServerDecoration, surface: &WlSurface) { + fn release(&mut self, decoration: &OrgKdeKwinServerDecoration, surface: &WlSurface) { + with_states(surface, |states| { + states + .data_map + .get_or_insert::(Default::default) + .lock() + .unwrap() + .objs + .retain(|obj| obj != decoration); + }); + let shell = self.common.shell.read(); if let Some(mapped) = shell.element_for_surface(surface) { unset_mode(mapped, surface)