shell/wayland: Enable xdg/kde-decoration protocols
This commit is contained in:
parent
7992ad67f6
commit
78ffe3a93d
6 changed files with 195 additions and 39 deletions
|
|
@ -422,6 +422,20 @@ impl CosmicMapped {
|
||||||
window.close();
|
window.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_window(&self) -> bool {
|
||||||
|
match &self.element {
|
||||||
|
CosmicMappedInternal::Window(_) => true,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_stack(&self) -> bool {
|
||||||
|
match &self.element {
|
||||||
|
CosmicMappedInternal::Stack(_) => true,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(feature = "debug")]
|
#[cfg(feature = "debug")]
|
||||||
pub fn set_debug(&self, flag: bool) {
|
pub fn set_debug(&self, flag: bool) {
|
||||||
let mut debug = self.debug.lock().unwrap();
|
let mut debug = self.debug.lock().unwrap();
|
||||||
|
|
|
||||||
|
|
@ -58,7 +58,7 @@ impl fmt::Debug for CosmicWindow {
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct CosmicWindowInternal {
|
pub struct CosmicWindowInternal {
|
||||||
pub(super) window: CosmicSurface,
|
pub(super) window: CosmicSurface,
|
||||||
pointer_entered: Option<Arc<AtomicU8>>,
|
pointer_entered: Arc<AtomicU8>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
|
|
@ -71,27 +71,19 @@ pub enum Focus {
|
||||||
|
|
||||||
impl CosmicWindowInternal {
|
impl CosmicWindowInternal {
|
||||||
pub fn swap_focus(&self, focus: Focus) -> Focus {
|
pub fn swap_focus(&self, focus: Focus) -> Focus {
|
||||||
if let Some(pointer_entered) = self.pointer_entered.as_ref() {
|
unsafe {
|
||||||
unsafe {
|
std::mem::transmute::<u8, Focus>(
|
||||||
std::mem::transmute::<u8, Focus>(
|
self.pointer_entered.swap(focus as u8, Ordering::SeqCst),
|
||||||
pointer_entered.swap(focus as u8, Ordering::SeqCst),
|
)
|
||||||
)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Focus::Window
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn current_focus(&self) -> Focus {
|
pub fn current_focus(&self) -> Focus {
|
||||||
if let Some(pointer_entered) = self.pointer_entered.as_ref() {
|
unsafe { std::mem::transmute::<u8, Focus>(self.pointer_entered.load(Ordering::SeqCst)) }
|
||||||
unsafe { std::mem::transmute::<u8, Focus>(pointer_entered.load(Ordering::SeqCst)) }
|
|
||||||
} else {
|
|
||||||
Focus::Window
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn has_ssd(&self) -> bool {
|
pub fn has_ssd(&self) -> bool {
|
||||||
self.pointer_entered.is_some()
|
!self.window.is_decorated()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -101,16 +93,11 @@ impl CosmicWindow {
|
||||||
handle: LoopHandle<'static, crate::state::Data>,
|
handle: LoopHandle<'static, crate::state::Data>,
|
||||||
) -> CosmicWindow {
|
) -> CosmicWindow {
|
||||||
let window = window.into();
|
let window = window.into();
|
||||||
let needs_ssd = !window.is_decorated();
|
|
||||||
let width = window.geometry().size.w;
|
let width = window.geometry().size.w;
|
||||||
CosmicWindow(IcedElement::new(
|
CosmicWindow(IcedElement::new(
|
||||||
CosmicWindowInternal {
|
CosmicWindowInternal {
|
||||||
window,
|
window,
|
||||||
pointer_entered: if needs_ssd {
|
pointer_entered: Arc::new(AtomicU8::new(Focus::None as u8)),
|
||||||
Some(Arc::new(AtomicU8::new(Focus::None as u8)))
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
(width, SSD_HEIGHT),
|
(width, SSD_HEIGHT),
|
||||||
handle,
|
handle,
|
||||||
|
|
@ -382,6 +369,7 @@ impl PointerTarget<State> for CosmicWindow {
|
||||||
Some((previous, Focus::Window))
|
Some((previous, Focus::Window))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
p.swap_focus(Focus::Window);
|
||||||
PointerTarget::motion(&p.window, seat, data, event);
|
PointerTarget::motion(&p.window, seat, data, event);
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
@ -427,7 +415,6 @@ impl PointerTarget<State> for CosmicWindow {
|
||||||
|
|
||||||
p.swap_focus(Focus::None)
|
p.swap_focus(Focus::None)
|
||||||
});
|
});
|
||||||
assert!(previous != Focus::None);
|
|
||||||
match previous {
|
match previous {
|
||||||
Focus::Header => PointerTarget::leave(&self.0, seat, data, serial, time),
|
Focus::Header => PointerTarget::leave(&self.0, seat, data, serial, time),
|
||||||
Focus::Window => self
|
Focus::Window => self
|
||||||
|
|
@ -453,27 +440,27 @@ where
|
||||||
fn render_elements<C: From<Self::RenderElement>>(
|
fn render_elements<C: From<Self::RenderElement>>(
|
||||||
&self,
|
&self,
|
||||||
renderer: &mut R,
|
renderer: &mut R,
|
||||||
mut location: Point<i32, Physical>,
|
location: Point<i32, Physical>,
|
||||||
scale: Scale<f64>,
|
scale: Scale<f64>,
|
||||||
) -> Vec<C> {
|
) -> Vec<C> {
|
||||||
let has_ssd = self.0.with_program(|p| p.has_ssd());
|
let has_ssd = self.0.with_program(|p| p.has_ssd());
|
||||||
|
|
||||||
let mut elements = if has_ssd {
|
let window_loc = if has_ssd {
|
||||||
let elements = AsRenderElements::<R>::render_elements::<CosmicWindowRenderElement<R>>(
|
location + Point::from((0, (SSD_HEIGHT as f64 * scale.y) as i32))
|
||||||
&self.0, renderer, location, scale,
|
|
||||||
);
|
|
||||||
location.y += SSD_HEIGHT;
|
|
||||||
elements
|
|
||||||
} else {
|
} else {
|
||||||
Vec::new()
|
location
|
||||||
};
|
};
|
||||||
|
|
||||||
elements.extend(self.0.with_program(|p| {
|
let mut elements = self.0.with_program(|p| {
|
||||||
AsRenderElements::<R>::render_elements::<CosmicWindowRenderElement<R>>(
|
AsRenderElements::<R>::render_elements::<CosmicWindowRenderElement<R>>(
|
||||||
&p.window, renderer, location, scale,
|
&p.window, renderer, window_loc, scale,
|
||||||
)
|
)
|
||||||
.into_iter()
|
});
|
||||||
}));
|
if has_ssd {
|
||||||
|
elements.extend(AsRenderElements::<R>::render_elements::<
|
||||||
|
CosmicWindowRenderElement<R>,
|
||||||
|
>(&self.0, renderer, location, scale))
|
||||||
|
}
|
||||||
|
|
||||||
elements.into_iter().map(C::from).collect()
|
elements.into_iter().map(C::from).collect()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -37,10 +37,10 @@ pub mod focus;
|
||||||
pub mod grabs;
|
pub mod grabs;
|
||||||
pub mod layout;
|
pub mod layout;
|
||||||
mod workspace;
|
mod workspace;
|
||||||
pub use self::element::{CosmicMappedRenderElement, CosmicSurface};
|
pub use self::element::{CosmicMapped, CosmicMappedRenderElement, CosmicSurface};
|
||||||
pub use self::workspace::*;
|
pub use self::workspace::*;
|
||||||
use self::{
|
use self::{
|
||||||
element::{CosmicMapped, CosmicWindow},
|
element::CosmicWindow,
|
||||||
focus::target::KeyboardFocusTarget,
|
focus::target::KeyboardFocusTarget,
|
||||||
layout::{floating::FloatingLayout, tiling::TilingLayout},
|
layout::{floating::FloatingLayout, tiling::TilingLayout},
|
||||||
};
|
};
|
||||||
|
|
|
||||||
19
src/state.rs
19
src/state.rs
|
|
@ -29,6 +29,7 @@ use smithay::{
|
||||||
output::{Mode as OutputMode, Output, Scale},
|
output::{Mode as OutputMode, Output, Scale},
|
||||||
reexports::{
|
reexports::{
|
||||||
calloop::{LoopHandle, LoopSignal},
|
calloop::{LoopHandle, LoopSignal},
|
||||||
|
wayland_protocols_misc::server_decoration::server::org_kde_kwin_server_decoration_manager::Mode,
|
||||||
wayland_server::{
|
wayland_server::{
|
||||||
backend::{ClientData, ClientId, DisconnectReason},
|
backend::{ClientData, ClientId, DisconnectReason},
|
||||||
protocol::wl_shm,
|
protocol::wl_shm,
|
||||||
|
|
@ -37,9 +38,15 @@ use smithay::{
|
||||||
},
|
},
|
||||||
utils::{Clock, Monotonic},
|
utils::{Clock, Monotonic},
|
||||||
wayland::{
|
wayland::{
|
||||||
compositor::CompositorState, data_device::DataDeviceState, dmabuf::DmabufState,
|
compositor::CompositorState,
|
||||||
keyboard_shortcuts_inhibit::KeyboardShortcutsInhibitState, output::OutputManagerState,
|
data_device::DataDeviceState,
|
||||||
presentation::PresentationState, primary_selection::PrimarySelectionState, shm::ShmState,
|
dmabuf::DmabufState,
|
||||||
|
keyboard_shortcuts_inhibit::KeyboardShortcutsInhibitState,
|
||||||
|
output::OutputManagerState,
|
||||||
|
presentation::PresentationState,
|
||||||
|
primary_selection::PrimarySelectionState,
|
||||||
|
shell::{kde::decoration::KdeDecorationState, xdg::decoration::XdgDecorationState},
|
||||||
|
shm::ShmState,
|
||||||
viewporter::ViewporterState,
|
viewporter::ViewporterState,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
@ -101,6 +108,8 @@ pub struct Common {
|
||||||
pub shm_state: ShmState,
|
pub shm_state: ShmState,
|
||||||
pub wl_drm_state: WlDrmState,
|
pub wl_drm_state: WlDrmState,
|
||||||
pub viewporter_state: ViewporterState,
|
pub viewporter_state: ViewporterState,
|
||||||
|
pub kde_decoration_state: KdeDecorationState,
|
||||||
|
pub xdg_decoration_state: XdgDecorationState,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum BackendData {
|
pub enum BackendData {
|
||||||
|
|
@ -229,6 +238,8 @@ impl State {
|
||||||
let seat_state = SeatState::<Self>::new();
|
let seat_state = SeatState::<Self>::new();
|
||||||
let viewporter_state = ViewporterState::new::<Self, _>(dh, None);
|
let viewporter_state = ViewporterState::new::<Self, _>(dh, None);
|
||||||
let wl_drm_state = WlDrmState;
|
let wl_drm_state = WlDrmState;
|
||||||
|
let kde_decoration_state = KdeDecorationState::new::<Self, _>(&dh, Mode::Client, None);
|
||||||
|
let xdg_decoration_state = XdgDecorationState::new::<Self, _>(&dh, None);
|
||||||
|
|
||||||
let shell = Shell::new(&config, dh);
|
let shell = Shell::new(&config, dh);
|
||||||
|
|
||||||
|
|
@ -264,6 +275,8 @@ impl State {
|
||||||
primary_selection_state,
|
primary_selection_state,
|
||||||
viewporter_state,
|
viewporter_state,
|
||||||
wl_drm_state,
|
wl_drm_state,
|
||||||
|
kde_decoration_state,
|
||||||
|
xdg_decoration_state,
|
||||||
},
|
},
|
||||||
backend: BackendData::Unset,
|
backend: BackendData::Unset,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
141
src/wayland/handlers/decoration.rs
Normal file
141
src/wayland/handlers/decoration.rs
Normal file
|
|
@ -0,0 +1,141 @@
|
||||||
|
use smithay::{
|
||||||
|
delegate_kde_decoration, delegate_xdg_decoration,
|
||||||
|
reexports::{
|
||||||
|
wayland_protocols::xdg::decoration::zv1::server::zxdg_toplevel_decoration_v1::Mode as XdgMode,
|
||||||
|
wayland_protocols_misc::server_decoration::server::org_kde_kwin_server_decoration::{
|
||||||
|
Mode as KdeMode, OrgKdeKwinServerDecoration,
|
||||||
|
},
|
||||||
|
wayland_server::protocol::wl_surface::WlSurface,
|
||||||
|
},
|
||||||
|
wayland::{
|
||||||
|
seat::WaylandFocus,
|
||||||
|
shell::{
|
||||||
|
kde::decoration::{KdeDecorationHandler, KdeDecorationState},
|
||||||
|
xdg::{decoration::XdgDecorationHandler, ToplevelSurface},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
use wayland_backend::protocol::WEnum;
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
shell::{CosmicMapped, CosmicSurface},
|
||||||
|
state::State,
|
||||||
|
};
|
||||||
|
|
||||||
|
impl State {
|
||||||
|
pub fn new_decoration(mapped: &CosmicMapped, surface: &WlSurface) -> KdeMode {
|
||||||
|
if mapped.is_stack() {
|
||||||
|
if let Some((CosmicSurface::Wayland(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();
|
||||||
|
}
|
||||||
|
KdeMode::Server
|
||||||
|
} else {
|
||||||
|
if let Some((CosmicSurface::Wayland(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();
|
||||||
|
}
|
||||||
|
KdeMode::Client
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn request_mode(mapped: &CosmicMapped, surface: &WlSurface, mode: XdgMode) {
|
||||||
|
if let Some((CosmicSurface::Wayland(window), _)) = mapped
|
||||||
|
.windows()
|
||||||
|
.find(|(window, _)| window.wl_surface().as_ref() == Some(surface))
|
||||||
|
{
|
||||||
|
window.toplevel().with_pending_state(|state| {
|
||||||
|
state.decoration_mode = dbg!(Some(mode));
|
||||||
|
});
|
||||||
|
window.toplevel().send_configure();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn unset_mode(mapped: &CosmicMapped, surface: &WlSurface) {
|
||||||
|
if let Some((CosmicSurface::Wayland(window), _)) = mapped
|
||||||
|
.windows()
|
||||||
|
.find(|(window, _)| window.wl_surface().as_ref() == Some(surface))
|
||||||
|
{
|
||||||
|
window.toplevel().with_pending_state(|state| {
|
||||||
|
state.decoration_mode = None;
|
||||||
|
});
|
||||||
|
window.toplevel().send_configure();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl XdgDecorationHandler for State {
|
||||||
|
fn new_decoration(&mut self, toplevel: ToplevelSurface) {
|
||||||
|
if let Some(mapped) = self.common.shell.element_for_surface(toplevel.wl_surface()) {
|
||||||
|
State::new_decoration(mapped, toplevel.wl_surface());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn request_mode(&mut self, toplevel: ToplevelSurface, mode: XdgMode) {
|
||||||
|
if let Some(mapped) = self.common.shell.element_for_surface(toplevel.wl_surface()) {
|
||||||
|
State::request_mode(mapped, toplevel.wl_surface(), mode);
|
||||||
|
} else {
|
||||||
|
toplevel.with_pending_state(|state| state.decoration_mode = Some(mode));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn unset_mode(&mut self, toplevel: ToplevelSurface) {
|
||||||
|
if let Some(mapped) = self.common.shell.element_for_surface(toplevel.wl_surface()) {
|
||||||
|
State::unset_mode(mapped, toplevel.wl_surface())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl KdeDecorationHandler for State {
|
||||||
|
fn kde_decoration_state(&self) -> &KdeDecorationState {
|
||||||
|
&self.common.kde_decoration_state
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new_decoration(&mut self, surface: &WlSurface, decoration: &OrgKdeKwinServerDecoration) {
|
||||||
|
if let Some(mapped) = self.common.shell.element_for_surface(surface) {
|
||||||
|
let mode = State::new_decoration(mapped, surface);
|
||||||
|
decoration.mode(mode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn request_mode(
|
||||||
|
&mut self,
|
||||||
|
surface: &WlSurface,
|
||||||
|
decoration: &OrgKdeKwinServerDecoration,
|
||||||
|
mode: WEnum<KdeMode>,
|
||||||
|
) {
|
||||||
|
if let WEnum::Value(mode) = mode {
|
||||||
|
// 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) = self.common.shell.element_for_surface(surface) {
|
||||||
|
State::request_mode(
|
||||||
|
mapped,
|
||||||
|
surface,
|
||||||
|
match mode {
|
||||||
|
KdeMode::Server => XdgMode::ServerSide,
|
||||||
|
_ => XdgMode::ClientSide,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
decoration.mode(mode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn release(&mut self, _decoration: &OrgKdeKwinServerDecoration, surface: &WlSurface) {
|
||||||
|
if let Some(mapped) = self.common.shell.element_for_surface(surface) {
|
||||||
|
State::unset_mode(mapped, surface)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
delegate_xdg_decoration!(State);
|
||||||
|
delegate_kde_decoration!(State);
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
pub mod buffer;
|
pub mod buffer;
|
||||||
pub mod compositor;
|
pub mod compositor;
|
||||||
pub mod data_device;
|
pub mod data_device;
|
||||||
|
pub mod decoration;
|
||||||
pub mod dmabuf;
|
pub mod dmabuf;
|
||||||
pub mod keyboard_shortcuts_inhibit;
|
pub mod keyboard_shortcuts_inhibit;
|
||||||
pub mod layer_shell;
|
pub mod layer_shell;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue