Remove XDG Shell V6
This commit is contained in:
parent
a9f1188fea
commit
8114bac8fd
|
@ -335,7 +335,7 @@ pub fn init_shell<BackendData: 'static>(display: Rc<RefCell<Display>>, log: ::sl
|
||||||
);
|
);
|
||||||
|
|
||||||
// init the xdg_shell
|
// init the xdg_shell
|
||||||
let (xdg_shell_state, _, _) = xdg_shell_init(
|
let (xdg_shell_state, _) = xdg_shell_init(
|
||||||
&mut *display.borrow_mut(),
|
&mut *display.borrow_mut(),
|
||||||
move |shell_event, mut ddata| {
|
move |shell_event, mut ddata| {
|
||||||
let state = ddata.get::<AnvilState<BackendData>>().unwrap();
|
let state = ddata.get::<AnvilState<BackendData>>().unwrap();
|
||||||
|
|
|
@ -31,7 +31,7 @@
|
||||||
//! use smithay::wayland::shell::xdg::{xdg_shell_init, XdgRequest};
|
//! use smithay::wayland::shell::xdg::{xdg_shell_init, XdgRequest};
|
||||||
//!
|
//!
|
||||||
//! # let mut display = wayland_server::Display::new();
|
//! # let mut display = wayland_server::Display::new();
|
||||||
//! let (shell_state, _, _) = xdg_shell_init(
|
//! let (shell_state, _) = xdg_shell_init(
|
||||||
//! &mut display,
|
//! &mut display,
|
||||||
//! // your implementation
|
//! // your implementation
|
||||||
//! |event: XdgRequest, dispatch_data| { /* handle the shell requests here */ },
|
//! |event: XdgRequest, dispatch_data| { /* handle the shell requests here */ },
|
||||||
|
@ -74,12 +74,8 @@ use std::{
|
||||||
sync::{Arc, Mutex},
|
sync::{Arc, Mutex},
|
||||||
};
|
};
|
||||||
|
|
||||||
use wayland_protocols::unstable::xdg_shell::v6::server::zxdg_surface_v6;
|
|
||||||
use wayland_protocols::xdg_shell::server::xdg_surface;
|
use wayland_protocols::xdg_shell::server::xdg_surface;
|
||||||
use wayland_protocols::{
|
use wayland_protocols::xdg_shell::server::{xdg_popup, xdg_positioner, xdg_toplevel, xdg_wm_base};
|
||||||
unstable::xdg_shell::v6::server::{zxdg_popup_v6, zxdg_shell_v6, zxdg_toplevel_v6},
|
|
||||||
xdg_shell::server::{xdg_popup, xdg_positioner, xdg_toplevel, xdg_wm_base},
|
|
||||||
};
|
|
||||||
use wayland_server::DispatchData;
|
use wayland_server::DispatchData;
|
||||||
use wayland_server::{
|
use wayland_server::{
|
||||||
protocol::{wl_output, wl_seat, wl_surface},
|
protocol::{wl_output, wl_seat, wl_surface},
|
||||||
|
@ -90,8 +86,6 @@ use super::PingError;
|
||||||
|
|
||||||
// handlers for the xdg_shell protocol
|
// handlers for the xdg_shell protocol
|
||||||
pub(super) mod xdg_handlers;
|
pub(super) mod xdg_handlers;
|
||||||
// compatibility handlers for the zxdg_shell_v6 protocol, its earlier version
|
|
||||||
mod zxdgv6_handlers;
|
|
||||||
|
|
||||||
/// The role of an XDG toplevel surface.
|
/// The role of an XDG toplevel surface.
|
||||||
///
|
///
|
||||||
|
@ -327,7 +321,7 @@ xdg_role!(
|
||||||
pub current: PopupState,
|
pub current: PopupState,
|
||||||
/// Holds the pending state as set by the server.
|
/// Holds the pending state as set by the server.
|
||||||
pub server_pending: Option<PopupState>,
|
pub server_pending: Option<PopupState>,
|
||||||
popup_handle: Option<PopupKind>
|
popup_handle: Option<xdg_popup::XdgPopup>
|
||||||
},
|
},
|
||||||
|attributes,configure| {
|
|attributes,configure| {
|
||||||
attributes.last_acked = Some(configure.state);
|
attributes.last_acked = Some(configure.state);
|
||||||
|
@ -731,16 +725,12 @@ impl Clone for ShellData {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new `xdg_shell` globals
|
/// Create a new `xdg_shell` global
|
||||||
pub fn xdg_shell_init<L, Impl>(
|
pub fn xdg_shell_init<L, Impl>(
|
||||||
display: &mut Display,
|
display: &mut Display,
|
||||||
implementation: Impl,
|
implementation: Impl,
|
||||||
logger: L,
|
logger: L,
|
||||||
) -> (
|
) -> (Arc<Mutex<ShellState>>, Global<xdg_wm_base::XdgWmBase>)
|
||||||
Arc<Mutex<ShellState>>,
|
|
||||||
Global<xdg_wm_base::XdgWmBase>,
|
|
||||||
Global<zxdg_shell_v6::ZxdgShellV6>,
|
|
||||||
)
|
|
||||||
where
|
where
|
||||||
L: Into<Option<::slog::Logger>>,
|
L: Into<Option<::slog::Logger>>,
|
||||||
Impl: FnMut(XdgRequest, DispatchData<'_>) + 'static,
|
Impl: FnMut(XdgRequest, DispatchData<'_>) + 'static,
|
||||||
|
@ -757,8 +747,6 @@ where
|
||||||
shell_state: shell_state.clone(),
|
shell_state: shell_state.clone(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let shell_data_z = shell_data.clone();
|
|
||||||
|
|
||||||
let xdg_shell_global = display.create_global(
|
let xdg_shell_global = display.create_global(
|
||||||
3,
|
3,
|
||||||
Filter::new(move |(shell, _version), _, dispatch_data| {
|
Filter::new(move |(shell, _version), _, dispatch_data| {
|
||||||
|
@ -766,14 +754,7 @@ where
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
let zxdgv6_shell_global = display.create_global(
|
(shell_state, xdg_shell_global)
|
||||||
1,
|
|
||||||
Filter::new(move |(shell, _version), _, dispatch_data| {
|
|
||||||
self::zxdgv6_handlers::implement_shell(shell, &shell_data_z, dispatch_data);
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
|
|
||||||
(shell_state, xdg_shell_global, zxdgv6_shell_global)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Shell global state
|
/// Shell global state
|
||||||
|
@ -805,16 +786,6 @@ impl ShellState {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* User interaction
|
|
||||||
*/
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
enum ShellClientKind {
|
|
||||||
Xdg(xdg_wm_base::XdgWmBase),
|
|
||||||
ZxdgV6(zxdg_shell_v6::ZxdgShellV6),
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) struct ShellClientData {
|
pub(crate) struct ShellClientData {
|
||||||
pending_ping: Option<Serial>,
|
pending_ping: Option<Serial>,
|
||||||
data: UserDataMap,
|
data: UserDataMap,
|
||||||
|
@ -839,26 +810,19 @@ fn make_shell_client_data() -> ShellClientData {
|
||||||
/// client-specific data you wish to associate with it.
|
/// client-specific data you wish to associate with it.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct ShellClient {
|
pub struct ShellClient {
|
||||||
kind: ShellClientKind,
|
kind: xdg_wm_base::XdgWmBase,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::cmp::PartialEq for ShellClient {
|
impl std::cmp::PartialEq for ShellClient {
|
||||||
fn eq(&self, other: &Self) -> bool {
|
fn eq(&self, other: &Self) -> bool {
|
||||||
match (&self.kind, &other.kind) {
|
self.kind == other.kind
|
||||||
(&ShellClientKind::Xdg(ref s1), &ShellClientKind::Xdg(ref s2)) => s1 == s2,
|
|
||||||
(&ShellClientKind::ZxdgV6(ref s1), &ShellClientKind::ZxdgV6(ref s2)) => s1 == s2,
|
|
||||||
_ => false,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ShellClient {
|
impl ShellClient {
|
||||||
/// Is the shell client represented by this handle still connected?
|
/// Is the shell client represented by this handle still connected?
|
||||||
pub fn alive(&self) -> bool {
|
pub fn alive(&self) -> bool {
|
||||||
match self.kind {
|
self.kind.as_ref().is_alive()
|
||||||
ShellClientKind::Xdg(ref s) => s.as_ref().is_alive(),
|
|
||||||
ShellClientKind::ZxdgV6(ref s) => s.as_ref().is_alive(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Send a ping request to this shell client
|
/// Send a ping request to this shell client
|
||||||
|
@ -874,9 +838,8 @@ impl ShellClient {
|
||||||
if !self.alive() {
|
if !self.alive() {
|
||||||
return Err(PingError::DeadSurface);
|
return Err(PingError::DeadSurface);
|
||||||
}
|
}
|
||||||
match self.kind {
|
let user_data = self
|
||||||
ShellClientKind::Xdg(ref shell) => {
|
.kind
|
||||||
let user_data = shell
|
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.user_data()
|
.user_data()
|
||||||
.get::<self::xdg_handlers::ShellUserData>()
|
.get::<self::xdg_handlers::ShellUserData>()
|
||||||
|
@ -886,22 +849,8 @@ impl ShellClient {
|
||||||
return Err(PingError::PingAlreadyPending(pending_ping));
|
return Err(PingError::PingAlreadyPending(pending_ping));
|
||||||
}
|
}
|
||||||
guard.pending_ping = Some(serial);
|
guard.pending_ping = Some(serial);
|
||||||
shell.ping(serial.into());
|
self.kind.ping(serial.into());
|
||||||
}
|
|
||||||
ShellClientKind::ZxdgV6(ref shell) => {
|
|
||||||
let user_data = shell
|
|
||||||
.as_ref()
|
|
||||||
.user_data()
|
|
||||||
.get::<self::zxdgv6_handlers::ShellUserData>()
|
|
||||||
.unwrap();
|
|
||||||
let mut guard = user_data.client_data.lock().unwrap();
|
|
||||||
if let Some(pending_ping) = guard.pending_ping {
|
|
||||||
return Err(PingError::PingAlreadyPending(pending_ping));
|
|
||||||
}
|
|
||||||
guard.pending_ping = Some(serial);
|
|
||||||
shell.ping(serial.into());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -913,9 +862,8 @@ impl ShellClient {
|
||||||
if !self.alive() {
|
if !self.alive() {
|
||||||
return Err(crate::utils::DeadResource);
|
return Err(crate::utils::DeadResource);
|
||||||
}
|
}
|
||||||
match self.kind {
|
let data = self
|
||||||
ShellClientKind::Xdg(ref shell) => {
|
.kind
|
||||||
let data = shell
|
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.user_data()
|
.user_data()
|
||||||
.get::<self::xdg_handlers::ShellUserData>()
|
.get::<self::xdg_handlers::ShellUserData>()
|
||||||
|
@ -923,30 +871,13 @@ impl ShellClient {
|
||||||
let mut guard = data.client_data.lock().unwrap();
|
let mut guard = data.client_data.lock().unwrap();
|
||||||
Ok(f(&mut guard.data))
|
Ok(f(&mut guard.data))
|
||||||
}
|
}
|
||||||
ShellClientKind::ZxdgV6(ref shell) => {
|
|
||||||
let data = shell
|
|
||||||
.as_ref()
|
|
||||||
.user_data()
|
|
||||||
.get::<self::zxdgv6_handlers::ShellUserData>()
|
|
||||||
.unwrap();
|
|
||||||
let mut guard = data.client_data.lock().unwrap();
|
|
||||||
Ok(f(&mut guard.data))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub(crate) enum ToplevelKind {
|
|
||||||
Xdg(xdg_toplevel::XdgToplevel),
|
|
||||||
ZxdgV6(zxdg_toplevel_v6::ZxdgToplevelV6),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A handle to a toplevel surface
|
/// A handle to a toplevel surface
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct ToplevelSurface {
|
pub struct ToplevelSurface {
|
||||||
wl_surface: wl_surface::WlSurface,
|
wl_surface: wl_surface::WlSurface,
|
||||||
shell_surface: ToplevelKind,
|
shell_surface: xdg_toplevel::XdgToplevel,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::cmp::PartialEq for ToplevelSurface {
|
impl std::cmp::PartialEq for ToplevelSurface {
|
||||||
|
@ -958,11 +889,7 @@ impl std::cmp::PartialEq for ToplevelSurface {
|
||||||
impl ToplevelSurface {
|
impl ToplevelSurface {
|
||||||
/// Is the toplevel surface referred by this handle still alive?
|
/// Is the toplevel surface referred by this handle still alive?
|
||||||
pub fn alive(&self) -> bool {
|
pub fn alive(&self) -> bool {
|
||||||
let shell_alive = match self.shell_surface {
|
self.shell_surface.as_ref().is_alive() && self.wl_surface.as_ref().is_alive()
|
||||||
ToplevelKind::Xdg(ref s) => s.as_ref().is_alive(),
|
|
||||||
ToplevelKind::ZxdgV6(ref s) => s.as_ref().is_alive(),
|
|
||||||
};
|
|
||||||
shell_alive && self.wl_surface.as_ref().is_alive()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Retrieve the shell client owning this toplevel surface
|
/// Retrieve the shell client owning this toplevel surface
|
||||||
|
@ -973,23 +900,14 @@ impl ToplevelSurface {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
let shell = match self.shell_surface {
|
let shell = {
|
||||||
ToplevelKind::Xdg(ref s) => {
|
let data = self
|
||||||
let data = s
|
.shell_surface
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.user_data()
|
.user_data()
|
||||||
.get::<self::xdg_handlers::ShellSurfaceUserData>()
|
.get::<self::xdg_handlers::ShellSurfaceUserData>()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
ShellClientKind::Xdg(data.wm_base.clone())
|
data.wm_base.clone()
|
||||||
}
|
|
||||||
ToplevelKind::ZxdgV6(ref s) => {
|
|
||||||
let data = s
|
|
||||||
.as_ref()
|
|
||||||
.user_data()
|
|
||||||
.get::<self::zxdgv6_handlers::ShellSurfaceUserData>()
|
|
||||||
.unwrap();
|
|
||||||
ShellClientKind::ZxdgV6(data.shell.clone())
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Some(ShellClient { kind: shell })
|
Some(ShellClient { kind: shell })
|
||||||
|
@ -1062,12 +980,7 @@ impl ToplevelSurface {
|
||||||
})
|
})
|
||||||
.unwrap_or(None);
|
.unwrap_or(None);
|
||||||
if let Some(configure) = configure {
|
if let Some(configure) = configure {
|
||||||
match self.shell_surface {
|
self::xdg_handlers::send_toplevel_configure(&self.shell_surface, configure)
|
||||||
ToplevelKind::Xdg(ref s) => self::xdg_handlers::send_toplevel_configure(s, configure),
|
|
||||||
ToplevelKind::ZxdgV6(ref s) => {
|
|
||||||
self::zxdgv6_handlers::send_toplevel_configure(s, configure)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1114,9 +1027,8 @@ impl ToplevelSurface {
|
||||||
})
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
if !configured {
|
if !configured {
|
||||||
match self.shell_surface {
|
let data = self
|
||||||
ToplevelKind::Xdg(ref s) => {
|
.shell_surface
|
||||||
let data = s
|
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.user_data()
|
.user_data()
|
||||||
.get::<self::xdg_handlers::ShellSurfaceUserData>()
|
.get::<self::xdg_handlers::ShellSurfaceUserData>()
|
||||||
|
@ -1126,28 +1038,12 @@ impl ToplevelSurface {
|
||||||
"Surface has not been configured yet.".into(),
|
"Surface has not been configured yet.".into(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
ToplevelKind::ZxdgV6(ref s) => {
|
|
||||||
let data = s
|
|
||||||
.as_ref()
|
|
||||||
.user_data()
|
|
||||||
.get::<self::zxdgv6_handlers::ShellSurfaceUserData>()
|
|
||||||
.unwrap();
|
|
||||||
data.xdg_surface.as_ref().post_error(
|
|
||||||
zxdg_surface_v6::Error::NotConstructed as u32,
|
|
||||||
"Surface has not been configured yet.".into(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
configured
|
configured
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Send a "close" event to the client
|
/// Send a "close" event to the client
|
||||||
pub fn send_close(&self) {
|
pub fn send_close(&self) {
|
||||||
match self.shell_surface {
|
self.shell_surface.close()
|
||||||
ToplevelKind::Xdg(ref s) => s.close(),
|
|
||||||
ToplevelKind::ZxdgV6(ref s) => s.close(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Access the underlying `wl_surface` of this toplevel surface
|
/// Access the underlying `wl_surface` of this toplevel surface
|
||||||
|
@ -1219,10 +1115,7 @@ impl ToplevelSurface {
|
||||||
|
|
||||||
/// Returns the parent of this toplevel surface.
|
/// Returns the parent of this toplevel surface.
|
||||||
pub fn parent(&self) -> Option<wl_surface::WlSurface> {
|
pub fn parent(&self) -> Option<wl_surface::WlSurface> {
|
||||||
match &self.shell_surface {
|
xdg_handlers::get_parent(&self.shell_surface)
|
||||||
ToplevelKind::Xdg(toplevel) => xdg_handlers::get_parent(toplevel),
|
|
||||||
ToplevelKind::ZxdgV6(toplevel) => zxdgv6_handlers::get_parent(toplevel),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets the parent of this toplevel surface and returns whether the parent was successfully set.
|
/// Sets the parent of this toplevel surface and returns whether the parent was successfully set.
|
||||||
|
@ -1238,10 +1131,7 @@ impl ToplevelSurface {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unset the parent
|
// Unset the parent
|
||||||
match &self.shell_surface {
|
xdg_handlers::set_parent(&self.shell_surface, None);
|
||||||
ToplevelKind::Xdg(toplevel) => xdg_handlers::set_parent(toplevel, None),
|
|
||||||
ToplevelKind::ZxdgV6(toplevel) => zxdgv6_handlers::set_parent(toplevel, None),
|
|
||||||
}
|
|
||||||
|
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
@ -1262,12 +1152,6 @@ pub enum PopupConfigureError {
|
||||||
NotReactive,
|
NotReactive,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub(crate) enum PopupKind {
|
|
||||||
Xdg(xdg_popup::XdgPopup),
|
|
||||||
ZxdgV6(zxdg_popup_v6::ZxdgPopupV6),
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A handle to a popup surface
|
/// A handle to a popup surface
|
||||||
///
|
///
|
||||||
/// This is an unified abstraction over the popup surfaces
|
/// This is an unified abstraction over the popup surfaces
|
||||||
|
@ -1275,7 +1159,7 @@ pub(crate) enum PopupKind {
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct PopupSurface {
|
pub struct PopupSurface {
|
||||||
wl_surface: wl_surface::WlSurface,
|
wl_surface: wl_surface::WlSurface,
|
||||||
shell_surface: PopupKind,
|
shell_surface: xdg_popup::XdgPopup,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::cmp::PartialEq for PopupSurface {
|
impl std::cmp::PartialEq for PopupSurface {
|
||||||
|
@ -1287,11 +1171,7 @@ impl std::cmp::PartialEq for PopupSurface {
|
||||||
impl PopupSurface {
|
impl PopupSurface {
|
||||||
/// Is the popup surface referred by this handle still alive?
|
/// Is the popup surface referred by this handle still alive?
|
||||||
pub fn alive(&self) -> bool {
|
pub fn alive(&self) -> bool {
|
||||||
let shell_alive = match self.shell_surface {
|
self.shell_surface.as_ref().is_alive() && self.wl_surface.as_ref().is_alive()
|
||||||
PopupKind::Xdg(ref p) => p.as_ref().is_alive(),
|
|
||||||
PopupKind::ZxdgV6(ref p) => p.as_ref().is_alive(),
|
|
||||||
};
|
|
||||||
shell_alive && self.wl_surface.as_ref().is_alive()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets a reference of the parent WlSurface of
|
/// Gets a reference of the parent WlSurface of
|
||||||
|
@ -1322,23 +1202,14 @@ impl PopupSurface {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
let shell = match self.shell_surface {
|
let shell = {
|
||||||
PopupKind::Xdg(ref p) => {
|
let data = self
|
||||||
let data = p
|
.shell_surface
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.user_data()
|
.user_data()
|
||||||
.get::<self::xdg_handlers::ShellSurfaceUserData>()
|
.get::<self::xdg_handlers::ShellSurfaceUserData>()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
ShellClientKind::Xdg(data.wm_base.clone())
|
data.wm_base.clone()
|
||||||
}
|
|
||||||
PopupKind::ZxdgV6(ref p) => {
|
|
||||||
let data = p
|
|
||||||
.as_ref()
|
|
||||||
.user_data()
|
|
||||||
.get::<self::zxdgv6_handlers::ShellSurfaceUserData>()
|
|
||||||
.unwrap();
|
|
||||||
ShellClientKind::ZxdgV6(data.shell.clone())
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Some(ShellClient { kind: shell })
|
Some(ShellClient { kind: shell })
|
||||||
|
@ -1346,10 +1217,7 @@ impl PopupSurface {
|
||||||
|
|
||||||
/// Get the version of the popup resource
|
/// Get the version of the popup resource
|
||||||
fn version(&self) -> u32 {
|
fn version(&self) -> u32 {
|
||||||
match self.shell_surface {
|
self.shell_surface.as_ref().version()
|
||||||
PopupKind::Xdg(ref xdg) => xdg.as_ref().version(),
|
|
||||||
PopupKind::ZxdgV6(ref zxdg) => zxdg.as_ref().version(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Internal configure function to re-use the configure
|
/// Internal configure function to re-use the configure
|
||||||
|
@ -1386,14 +1254,7 @@ impl PopupSurface {
|
||||||
})
|
})
|
||||||
.unwrap_or(None);
|
.unwrap_or(None);
|
||||||
if let Some(configure) = next_configure {
|
if let Some(configure) = next_configure {
|
||||||
match self.shell_surface {
|
self::xdg_handlers::send_popup_configure(&self.shell_surface, configure);
|
||||||
PopupKind::Xdg(ref p) => {
|
|
||||||
self::xdg_handlers::send_popup_configure(p, configure);
|
|
||||||
}
|
|
||||||
PopupKind::ZxdgV6(ref p) => {
|
|
||||||
self::zxdgv6_handlers::send_popup_configure(p, configure);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1470,9 +1331,7 @@ impl PopupSurface {
|
||||||
})
|
})
|
||||||
.unwrap_or(None);
|
.unwrap_or(None);
|
||||||
if let Some(handle) = send_error_to {
|
if let Some(handle) = send_error_to {
|
||||||
match handle {
|
let data = handle
|
||||||
PopupKind::Xdg(ref s) => {
|
|
||||||
let data = s
|
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.user_data()
|
.user_data()
|
||||||
.get::<self::xdg_handlers::ShellSurfaceUserData>()
|
.get::<self::xdg_handlers::ShellSurfaceUserData>()
|
||||||
|
@ -1481,19 +1340,6 @@ impl PopupSurface {
|
||||||
xdg_surface::Error::NotConstructed as u32,
|
xdg_surface::Error::NotConstructed as u32,
|
||||||
"Surface has not been configured yet.".into(),
|
"Surface has not been configured yet.".into(),
|
||||||
);
|
);
|
||||||
}
|
|
||||||
PopupKind::ZxdgV6(ref s) => {
|
|
||||||
let data = s
|
|
||||||
.as_ref()
|
|
||||||
.user_data()
|
|
||||||
.get::<self::zxdgv6_handlers::ShellSurfaceUserData>()
|
|
||||||
.unwrap();
|
|
||||||
data.xdg_surface.as_ref().post_error(
|
|
||||||
zxdg_surface_v6::Error::NotConstructed as u32,
|
|
||||||
"Surface has not been configured yet.".into(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1539,9 +1385,8 @@ impl PopupSurface {
|
||||||
})
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
if !configured {
|
if !configured {
|
||||||
match self.shell_surface {
|
let data = self
|
||||||
PopupKind::Xdg(ref s) => {
|
.shell_surface
|
||||||
let data = s
|
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.user_data()
|
.user_data()
|
||||||
.get::<self::xdg_handlers::ShellSurfaceUserData>()
|
.get::<self::xdg_handlers::ShellSurfaceUserData>()
|
||||||
|
@ -1551,19 +1396,6 @@ impl PopupSurface {
|
||||||
"Surface has not been configured yet.".into(),
|
"Surface has not been configured yet.".into(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
PopupKind::ZxdgV6(ref s) => {
|
|
||||||
let data = s
|
|
||||||
.as_ref()
|
|
||||||
.user_data()
|
|
||||||
.get::<self::zxdgv6_handlers::ShellSurfaceUserData>()
|
|
||||||
.unwrap();
|
|
||||||
data.xdg_surface.as_ref().post_error(
|
|
||||||
zxdg_surface_v6::Error::NotConstructed as u32,
|
|
||||||
"Surface has not been configured yet.".into(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
configured
|
configured
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1576,10 +1408,7 @@ impl PopupSurface {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
match self.shell_surface {
|
self.shell_surface.popup_done();
|
||||||
PopupKind::Xdg(ref p) => p.popup_done(),
|
|
||||||
PopupKind::ZxdgV6(ref p) => p.popup_done(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Access the underlying `wl_surface` of this toplevel surface
|
/// Access the underlying `wl_surface` of this toplevel surface
|
||||||
|
|
|
@ -13,9 +13,9 @@ use wayland_server::{protocol::wl_surface, Filter, Main};
|
||||||
use crate::utils::Rectangle;
|
use crate::utils::Rectangle;
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
make_shell_client_data, PopupConfigure, PopupKind, PositionerState, ShellClient, ShellClientData,
|
make_shell_client_data, PopupConfigure, PositionerState, ShellClient, ShellClientData, ShellData,
|
||||||
ShellData, SurfaceCachedState, ToplevelConfigure, ToplevelKind, XdgPopupSurfaceRoleAttributes,
|
SurfaceCachedState, ToplevelConfigure, XdgPopupSurfaceRoleAttributes, XdgRequest,
|
||||||
XdgRequest, XdgToplevelSurfaceRoleAttributes,
|
XdgToplevelSurfaceRoleAttributes,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub(crate) fn implement_wm_base(
|
pub(crate) fn implement_wm_base(
|
||||||
|
@ -49,7 +49,7 @@ pub(crate) struct ShellUserData {
|
||||||
|
|
||||||
pub(crate) fn make_shell_client(resource: &xdg_wm_base::XdgWmBase) -> ShellClient {
|
pub(crate) fn make_shell_client(resource: &xdg_wm_base::XdgWmBase) -> ShellClient {
|
||||||
ShellClient {
|
ShellClient {
|
||||||
kind: super::ShellClientKind::Xdg(resource.clone()),
|
kind: resource.clone(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -547,7 +547,7 @@ fn make_toplevel_handle(resource: &xdg_toplevel::XdgToplevel) -> super::Toplevel
|
||||||
.unwrap();
|
.unwrap();
|
||||||
super::ToplevelSurface {
|
super::ToplevelSurface {
|
||||||
wl_surface: data.wl_surface.clone(),
|
wl_surface: data.wl_surface.clone(),
|
||||||
shell_surface: ToplevelKind::Xdg(resource.clone()),
|
shell_surface: resource.clone(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -735,7 +735,7 @@ fn make_popup_handle(resource: &xdg_popup::XdgPopup) -> super::PopupSurface {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
super::PopupSurface {
|
super::PopupSurface {
|
||||||
wl_surface: data.wl_surface.clone(),
|
wl_surface: data.wl_surface.clone(),
|
||||||
shell_surface: PopupKind::Xdg(resource.clone()),
|
shell_surface: resource.clone(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,846 +0,0 @@
|
||||||
use std::sync::atomic::{AtomicBool, Ordering};
|
|
||||||
use std::{cell::RefCell, ops::Deref as _, sync::Mutex};
|
|
||||||
|
|
||||||
use crate::wayland::compositor;
|
|
||||||
use crate::wayland::shell::xdg::{PopupState, ZXDG_POPUP_ROLE, ZXDG_TOPLEVEL_ROLE};
|
|
||||||
use crate::wayland::Serial;
|
|
||||||
use wayland_protocols::{
|
|
||||||
unstable::xdg_shell::v6::server::{
|
|
||||||
zxdg_popup_v6, zxdg_positioner_v6, zxdg_shell_v6, zxdg_surface_v6, zxdg_toplevel_v6,
|
|
||||||
},
|
|
||||||
xdg_shell::server::{xdg_positioner, xdg_toplevel},
|
|
||||||
};
|
|
||||||
use wayland_server::DispatchData;
|
|
||||||
use wayland_server::{protocol::wl_surface, Filter, Main};
|
|
||||||
|
|
||||||
use crate::utils::Rectangle;
|
|
||||||
|
|
||||||
use super::{
|
|
||||||
make_shell_client_data, PopupConfigure, PopupKind, PositionerState, ShellClient, ShellClientData,
|
|
||||||
ShellData, SurfaceCachedState, ToplevelConfigure, ToplevelKind, XdgPopupSurfaceRoleAttributes,
|
|
||||||
XdgRequest, XdgToplevelSurfaceRoleAttributes,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub(crate) fn implement_shell(
|
|
||||||
shell: Main<zxdg_shell_v6::ZxdgShellV6>,
|
|
||||||
shell_data: &ShellData,
|
|
||||||
dispatch_data: DispatchData<'_>,
|
|
||||||
) -> zxdg_shell_v6::ZxdgShellV6 {
|
|
||||||
shell.quick_assign(shell_implementation);
|
|
||||||
shell.as_ref().user_data().set(|| ShellUserData {
|
|
||||||
shell_data: shell_data.clone(),
|
|
||||||
client_data: Mutex::new(make_shell_client_data()),
|
|
||||||
});
|
|
||||||
let mut user_impl = shell_data.user_impl.borrow_mut();
|
|
||||||
(&mut *user_impl)(
|
|
||||||
XdgRequest::NewClient {
|
|
||||||
client: make_shell_client(&shell),
|
|
||||||
},
|
|
||||||
dispatch_data,
|
|
||||||
);
|
|
||||||
shell.deref().clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* xdg_shell
|
|
||||||
*/
|
|
||||||
|
|
||||||
pub(crate) struct ShellUserData {
|
|
||||||
shell_data: ShellData,
|
|
||||||
pub(crate) client_data: Mutex<ShellClientData>,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn make_shell_client(resource: &zxdg_shell_v6::ZxdgShellV6) -> ShellClient {
|
|
||||||
ShellClient {
|
|
||||||
kind: super::ShellClientKind::ZxdgV6(resource.clone()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn shell_implementation(
|
|
||||||
shell: Main<zxdg_shell_v6::ZxdgShellV6>,
|
|
||||||
request: zxdg_shell_v6::Request,
|
|
||||||
dispatch_data: DispatchData<'_>,
|
|
||||||
) {
|
|
||||||
let data = shell.as_ref().user_data().get::<ShellUserData>().unwrap();
|
|
||||||
match request {
|
|
||||||
zxdg_shell_v6::Request::Destroy => {
|
|
||||||
// all is handled by destructor
|
|
||||||
}
|
|
||||||
zxdg_shell_v6::Request::CreatePositioner { id } => {
|
|
||||||
implement_positioner(id);
|
|
||||||
}
|
|
||||||
zxdg_shell_v6::Request::GetXdgSurface { id, surface } => {
|
|
||||||
id.quick_assign(xdg_surface_implementation);
|
|
||||||
id.assign_destructor(Filter::new(|surface, _, _data| destroy_surface(surface)));
|
|
||||||
id.as_ref().user_data().set(|| XdgSurfaceUserData {
|
|
||||||
shell_data: data.shell_data.clone(),
|
|
||||||
wl_surface: surface,
|
|
||||||
shell: shell.deref().clone(),
|
|
||||||
has_active_role: AtomicBool::new(false),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
zxdg_shell_v6::Request::Pong { serial } => {
|
|
||||||
let serial = Serial::from(serial);
|
|
||||||
let valid = {
|
|
||||||
let mut guard = data.client_data.lock().unwrap();
|
|
||||||
if guard.pending_ping == Some(serial) {
|
|
||||||
guard.pending_ping = None;
|
|
||||||
true
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
};
|
|
||||||
if valid {
|
|
||||||
let mut user_impl = data.shell_data.user_impl.borrow_mut();
|
|
||||||
(&mut *user_impl)(
|
|
||||||
XdgRequest::ClientPong {
|
|
||||||
client: make_shell_client(&shell),
|
|
||||||
},
|
|
||||||
dispatch_data,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* xdg_positioner
|
|
||||||
*/
|
|
||||||
|
|
||||||
fn implement_positioner(
|
|
||||||
positioner: Main<zxdg_positioner_v6::ZxdgPositionerV6>,
|
|
||||||
) -> zxdg_positioner_v6::ZxdgPositionerV6 {
|
|
||||||
positioner.quick_assign(|positioner, request, _data| {
|
|
||||||
let mutex = positioner
|
|
||||||
.as_ref()
|
|
||||||
.user_data()
|
|
||||||
.get::<RefCell<PositionerState>>()
|
|
||||||
.unwrap();
|
|
||||||
let mut state = mutex.borrow_mut();
|
|
||||||
match request {
|
|
||||||
zxdg_positioner_v6::Request::Destroy => {
|
|
||||||
// handled by destructor
|
|
||||||
}
|
|
||||||
zxdg_positioner_v6::Request::SetSize { width, height } => {
|
|
||||||
if width < 1 || height < 1 {
|
|
||||||
positioner.as_ref().post_error(
|
|
||||||
zxdg_positioner_v6::Error::InvalidInput as u32,
|
|
||||||
"Invalid size for positioner.".into(),
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
state.rect_size = (width, height).into();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
zxdg_positioner_v6::Request::SetAnchorRect { x, y, width, height } => {
|
|
||||||
if width < 1 || height < 1 {
|
|
||||||
positioner.as_ref().post_error(
|
|
||||||
zxdg_positioner_v6::Error::InvalidInput as u32,
|
|
||||||
"Invalid size for positioner's anchor rectangle.".into(),
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
state.anchor_rect = Rectangle::from_loc_and_size((x, y), (width, height));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
zxdg_positioner_v6::Request::SetAnchor { anchor } => {
|
|
||||||
if let Some(anchor) = zxdg_anchor_to_xdg(anchor) {
|
|
||||||
state.anchor_edges = anchor;
|
|
||||||
} else {
|
|
||||||
positioner.as_ref().post_error(
|
|
||||||
zxdg_positioner_v6::Error::InvalidInput as u32,
|
|
||||||
"Invalid anchor for positioner.".into(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
zxdg_positioner_v6::Request::SetGravity { gravity } => {
|
|
||||||
if let Some(gravity) = zxdg_gravity_to_xdg(gravity) {
|
|
||||||
state.gravity = gravity;
|
|
||||||
} else {
|
|
||||||
positioner.as_ref().post_error(
|
|
||||||
zxdg_positioner_v6::Error::InvalidInput as u32,
|
|
||||||
"Invalid gravity for positioner.".into(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
zxdg_positioner_v6::Request::SetConstraintAdjustment {
|
|
||||||
constraint_adjustment,
|
|
||||||
} => {
|
|
||||||
let constraint_adjustment =
|
|
||||||
zxdg_positioner_v6::ConstraintAdjustment::from_bits_truncate(constraint_adjustment);
|
|
||||||
state.constraint_adjustment = zxdg_constraints_adg_to_xdg(constraint_adjustment);
|
|
||||||
}
|
|
||||||
zxdg_positioner_v6::Request::SetOffset { x, y } => {
|
|
||||||
state.offset = (x, y).into();
|
|
||||||
}
|
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
|
||||||
});
|
|
||||||
positioner
|
|
||||||
.as_ref()
|
|
||||||
.user_data()
|
|
||||||
.set(|| RefCell::new(PositionerState::default()));
|
|
||||||
|
|
||||||
positioner.deref().clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* xdg_surface
|
|
||||||
*/
|
|
||||||
|
|
||||||
struct XdgSurfaceUserData {
|
|
||||||
shell_data: ShellData,
|
|
||||||
wl_surface: wl_surface::WlSurface,
|
|
||||||
shell: zxdg_shell_v6::ZxdgShellV6,
|
|
||||||
has_active_role: AtomicBool,
|
|
||||||
}
|
|
||||||
|
|
||||||
fn destroy_surface(surface: zxdg_surface_v6::ZxdgSurfaceV6) {
|
|
||||||
let data = surface.as_ref().user_data().get::<XdgSurfaceUserData>().unwrap();
|
|
||||||
if !data.wl_surface.as_ref().is_alive() {
|
|
||||||
// the wl_surface is destroyed, this means the client is not
|
|
||||||
// trying to change the role but it's a cleanup (possibly a
|
|
||||||
// disconnecting client), ignore the protocol check.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if compositor::get_role(&data.wl_surface).is_none() {
|
|
||||||
// No role assigned to the surface, we can exit early.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if data.has_active_role.load(Ordering::Acquire) {
|
|
||||||
data.shell.as_ref().post_error(
|
|
||||||
zxdg_shell_v6::Error::Role as u32,
|
|
||||||
"xdg_surface was destroyed before its role object".into(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn xdg_surface_implementation(
|
|
||||||
xdg_surface: Main<zxdg_surface_v6::ZxdgSurfaceV6>,
|
|
||||||
request: zxdg_surface_v6::Request,
|
|
||||||
dispatch_data: DispatchData<'_>,
|
|
||||||
) {
|
|
||||||
let data = xdg_surface
|
|
||||||
.as_ref()
|
|
||||||
.user_data()
|
|
||||||
.get::<XdgSurfaceUserData>()
|
|
||||||
.unwrap();
|
|
||||||
match request {
|
|
||||||
zxdg_surface_v6::Request::Destroy => {
|
|
||||||
// all is handled by our destructor
|
|
||||||
}
|
|
||||||
zxdg_surface_v6::Request::GetToplevel { id } => {
|
|
||||||
// We now can assign a role to the surface
|
|
||||||
let surface = &data.wl_surface;
|
|
||||||
let shell = &data.shell;
|
|
||||||
|
|
||||||
if compositor::give_role(surface, ZXDG_TOPLEVEL_ROLE).is_err() {
|
|
||||||
shell.as_ref().post_error(
|
|
||||||
zxdg_shell_v6::Error::Role as u32,
|
|
||||||
"Surface already has a role.".into(),
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
data.has_active_role.store(true, Ordering::Release);
|
|
||||||
|
|
||||||
compositor::with_states(surface, |states| {
|
|
||||||
states
|
|
||||||
.data_map
|
|
||||||
.insert_if_missing_threadsafe(|| Mutex::new(XdgToplevelSurfaceRoleAttributes::default()))
|
|
||||||
})
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
compositor::add_commit_hook(surface, super::ToplevelSurface::commit_hook);
|
|
||||||
|
|
||||||
id.quick_assign(toplevel_implementation);
|
|
||||||
id.assign_destructor(Filter::new(|toplevel, _, _data| destroy_toplevel(toplevel)));
|
|
||||||
id.as_ref().user_data().set(|| ShellSurfaceUserData {
|
|
||||||
shell_data: data.shell_data.clone(),
|
|
||||||
wl_surface: data.wl_surface.clone(),
|
|
||||||
shell: data.shell.clone(),
|
|
||||||
xdg_surface: xdg_surface.deref().clone(),
|
|
||||||
});
|
|
||||||
|
|
||||||
data.shell_data
|
|
||||||
.shell_state
|
|
||||||
.lock()
|
|
||||||
.unwrap()
|
|
||||||
.known_toplevels
|
|
||||||
.push(make_toplevel_handle(&id));
|
|
||||||
|
|
||||||
let handle = make_toplevel_handle(&id);
|
|
||||||
let mut user_impl = data.shell_data.user_impl.borrow_mut();
|
|
||||||
(&mut *user_impl)(XdgRequest::NewToplevel { surface: handle }, dispatch_data);
|
|
||||||
}
|
|
||||||
zxdg_surface_v6::Request::GetPopup {
|
|
||||||
id,
|
|
||||||
parent,
|
|
||||||
positioner,
|
|
||||||
} => {
|
|
||||||
let positioner_data = *positioner
|
|
||||||
.as_ref()
|
|
||||||
.user_data()
|
|
||||||
.get::<RefCell<PositionerState>>()
|
|
||||||
.unwrap()
|
|
||||||
.borrow();
|
|
||||||
|
|
||||||
let parent_surface = {
|
|
||||||
let parent_data = parent.as_ref().user_data().get::<XdgSurfaceUserData>().unwrap();
|
|
||||||
parent_data.wl_surface.clone()
|
|
||||||
};
|
|
||||||
|
|
||||||
// We now can assign a role to the surface
|
|
||||||
let surface = &data.wl_surface;
|
|
||||||
let shell = &data.shell;
|
|
||||||
|
|
||||||
let attributes = XdgPopupSurfaceRoleAttributes {
|
|
||||||
parent: Some(parent_surface),
|
|
||||||
server_pending: Some(PopupState {
|
|
||||||
// Set the positioner data as the popup geometry
|
|
||||||
geometry: positioner_data.get_geometry(),
|
|
||||||
positioner: positioner_data,
|
|
||||||
}),
|
|
||||||
..Default::default()
|
|
||||||
};
|
|
||||||
if compositor::give_role(surface, ZXDG_POPUP_ROLE).is_err() {
|
|
||||||
shell.as_ref().post_error(
|
|
||||||
zxdg_shell_v6::Error::Role as u32,
|
|
||||||
"Surface already has a role.".into(),
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
data.has_active_role.store(true, Ordering::Release);
|
|
||||||
|
|
||||||
compositor::with_states(surface, |states| {
|
|
||||||
states
|
|
||||||
.data_map
|
|
||||||
.insert_if_missing_threadsafe(|| Mutex::new(XdgPopupSurfaceRoleAttributes::default()));
|
|
||||||
*states
|
|
||||||
.data_map
|
|
||||||
.get::<Mutex<XdgPopupSurfaceRoleAttributes>>()
|
|
||||||
.unwrap()
|
|
||||||
.lock()
|
|
||||||
.unwrap() = attributes;
|
|
||||||
})
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
compositor::add_commit_hook(surface, super::PopupSurface::commit_hook);
|
|
||||||
|
|
||||||
id.quick_assign(popup_implementation);
|
|
||||||
id.assign_destructor(Filter::new(|popup, _, _data| destroy_popup(popup)));
|
|
||||||
id.as_ref().user_data().set(|| ShellSurfaceUserData {
|
|
||||||
shell_data: data.shell_data.clone(),
|
|
||||||
wl_surface: data.wl_surface.clone(),
|
|
||||||
shell: data.shell.clone(),
|
|
||||||
xdg_surface: xdg_surface.deref().clone(),
|
|
||||||
});
|
|
||||||
|
|
||||||
data.shell_data
|
|
||||||
.shell_state
|
|
||||||
.lock()
|
|
||||||
.unwrap()
|
|
||||||
.known_popups
|
|
||||||
.push(make_popup_handle(&id));
|
|
||||||
|
|
||||||
let handle = make_popup_handle(&id);
|
|
||||||
let mut user_impl = data.shell_data.user_impl.borrow_mut();
|
|
||||||
(&mut *user_impl)(
|
|
||||||
XdgRequest::NewPopup {
|
|
||||||
surface: handle,
|
|
||||||
positioner: positioner_data,
|
|
||||||
},
|
|
||||||
dispatch_data,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
zxdg_surface_v6::Request::SetWindowGeometry { x, y, width, height } => {
|
|
||||||
// Check the role of the surface, this can be either xdg_toplevel
|
|
||||||
// or xdg_popup. If none of the role matches the xdg_surface has no role set
|
|
||||||
// which is a protocol error.
|
|
||||||
let surface = &data.wl_surface;
|
|
||||||
|
|
||||||
let role = compositor::get_role(surface);
|
|
||||||
|
|
||||||
if role.is_none() {
|
|
||||||
xdg_surface.as_ref().post_error(
|
|
||||||
zxdg_surface_v6::Error::NotConstructed as u32,
|
|
||||||
"xdg_surface must have a role.".into(),
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if role != Some(ZXDG_TOPLEVEL_ROLE) && role != Some(ZXDG_POPUP_ROLE) {
|
|
||||||
data.shell.as_ref().post_error(
|
|
||||||
zxdg_shell_v6::Error::Role as u32,
|
|
||||||
"xdg_surface must have a role of xdg_toplevel or xdg_popup.".into(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
compositor::with_states(surface, |states| {
|
|
||||||
states.cached_state.pending::<SurfaceCachedState>().geometry =
|
|
||||||
Some(Rectangle::from_loc_and_size((x, y), (width, height)));
|
|
||||||
})
|
|
||||||
.unwrap();
|
|
||||||
}
|
|
||||||
zxdg_surface_v6::Request::AckConfigure { serial } => {
|
|
||||||
let serial = Serial::from(serial);
|
|
||||||
let surface = &data.wl_surface;
|
|
||||||
|
|
||||||
// Check the role of the surface, this can be either xdg_toplevel
|
|
||||||
// or xdg_popup. If none of the role matches the xdg_surface has no role set
|
|
||||||
// which is a protocol error.
|
|
||||||
if compositor::get_role(surface).is_none() {
|
|
||||||
data.shell.as_ref().post_error(
|
|
||||||
zxdg_surface_v6::Error::NotConstructed as u32,
|
|
||||||
"xdg_surface must have a role.".into(),
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find the correct configure state for the provided serial
|
|
||||||
// discard all configure states that are older than the provided
|
|
||||||
// serial.
|
|
||||||
// If no matching serial can be found raise a protocol error
|
|
||||||
//
|
|
||||||
// Invoke the user impl with the found configuration
|
|
||||||
// This has to include the serial and the role specific data.
|
|
||||||
// - For xdg_popup there is no data.
|
|
||||||
// - For xdg_toplevel send the state data including
|
|
||||||
// width, height, min/max size, maximized, fullscreen, resizing, activated
|
|
||||||
//
|
|
||||||
// This can be used to integrate custom protocol extensions
|
|
||||||
//
|
|
||||||
let found_configure = compositor::with_states(surface, |states| {
|
|
||||||
if states.role == Some(ZXDG_TOPLEVEL_ROLE) {
|
|
||||||
Ok(states
|
|
||||||
.data_map
|
|
||||||
.get::<Mutex<XdgToplevelSurfaceRoleAttributes>>()
|
|
||||||
.unwrap()
|
|
||||||
.lock()
|
|
||||||
.unwrap()
|
|
||||||
.ack_configure(serial))
|
|
||||||
} else if states.role == Some(ZXDG_POPUP_ROLE) {
|
|
||||||
Ok(states
|
|
||||||
.data_map
|
|
||||||
.get::<Mutex<XdgPopupSurfaceRoleAttributes>>()
|
|
||||||
.unwrap()
|
|
||||||
.lock()
|
|
||||||
.unwrap()
|
|
||||||
.ack_configure(serial))
|
|
||||||
} else {
|
|
||||||
Err(())
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.unwrap();
|
|
||||||
let configure = match found_configure {
|
|
||||||
Ok(Some(configure)) => configure,
|
|
||||||
Ok(None) => {
|
|
||||||
data.shell.as_ref().post_error(
|
|
||||||
zxdg_shell_v6::Error::InvalidSurfaceState as u32,
|
|
||||||
format!("wrong configure serial: {}", <u32>::from(serial)),
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Err(_) => {
|
|
||||||
data.shell.as_ref().post_error(
|
|
||||||
zxdg_shell_v6::Error::Role as u32,
|
|
||||||
"xdg_surface must have a role of xdg_toplevel or xdg_popup.".into(),
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut user_impl = data.shell_data.user_impl.borrow_mut();
|
|
||||||
(&mut *user_impl)(
|
|
||||||
XdgRequest::AckConfigure {
|
|
||||||
surface: surface.clone(),
|
|
||||||
configure,
|
|
||||||
},
|
|
||||||
dispatch_data,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* xdg_toplevel
|
|
||||||
*/
|
|
||||||
|
|
||||||
pub struct ShellSurfaceUserData {
|
|
||||||
pub(crate) shell_data: ShellData,
|
|
||||||
pub(crate) wl_surface: wl_surface::WlSurface,
|
|
||||||
pub(crate) shell: zxdg_shell_v6::ZxdgShellV6,
|
|
||||||
pub(crate) xdg_surface: zxdg_surface_v6::ZxdgSurfaceV6,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Utility functions allowing to factor out a lot of the upcoming logic
|
|
||||||
fn with_surface_toplevel_role_data<F, T>(toplevel: &zxdg_toplevel_v6::ZxdgToplevelV6, f: F) -> T
|
|
||||||
where
|
|
||||||
F: FnOnce(&mut XdgToplevelSurfaceRoleAttributes) -> T,
|
|
||||||
{
|
|
||||||
let data = toplevel
|
|
||||||
.as_ref()
|
|
||||||
.user_data()
|
|
||||||
.get::<ShellSurfaceUserData>()
|
|
||||||
.unwrap();
|
|
||||||
compositor::with_states(&data.wl_surface, |states| {
|
|
||||||
f(&mut *states
|
|
||||||
.data_map
|
|
||||||
.get::<Mutex<XdgToplevelSurfaceRoleAttributes>>()
|
|
||||||
.unwrap()
|
|
||||||
.lock()
|
|
||||||
.unwrap())
|
|
||||||
})
|
|
||||||
.unwrap()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn with_toplevel_pending_state<F, T>(toplevel: &zxdg_toplevel_v6::ZxdgToplevelV6, f: F) -> T
|
|
||||||
where
|
|
||||||
F: FnOnce(&mut SurfaceCachedState) -> T,
|
|
||||||
{
|
|
||||||
let data = toplevel
|
|
||||||
.as_ref()
|
|
||||||
.user_data()
|
|
||||||
.get::<ShellSurfaceUserData>()
|
|
||||||
.unwrap();
|
|
||||||
compositor::with_states(&data.wl_surface, |states| {
|
|
||||||
f(&mut *states.cached_state.pending::<SurfaceCachedState>())
|
|
||||||
})
|
|
||||||
.unwrap()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn send_toplevel_configure(resource: &zxdg_toplevel_v6::ZxdgToplevelV6, configure: ToplevelConfigure) {
|
|
||||||
let data = resource
|
|
||||||
.as_ref()
|
|
||||||
.user_data()
|
|
||||||
.get::<ShellSurfaceUserData>()
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let (width, height) = configure.state.size.unwrap_or_default().into();
|
|
||||||
// convert the Vec<State> (which is really a Vec<u32>) into Vec<u8>
|
|
||||||
let states = {
|
|
||||||
let mut states: Vec<xdg_toplevel::State> = configure
|
|
||||||
.state
|
|
||||||
.states
|
|
||||||
.into_filtered_states(resource.as_ref().version());
|
|
||||||
let ptr = states.as_mut_ptr();
|
|
||||||
let len = states.len();
|
|
||||||
let cap = states.capacity();
|
|
||||||
::std::mem::forget(states);
|
|
||||||
unsafe { Vec::from_raw_parts(ptr as *mut u8, len * 4, cap * 4) }
|
|
||||||
};
|
|
||||||
let serial = configure.serial;
|
|
||||||
|
|
||||||
// Send the toplevel configure
|
|
||||||
resource.configure(width, height, states);
|
|
||||||
|
|
||||||
// Send the base xdg_surface configure event to mark
|
|
||||||
// The configure as finished
|
|
||||||
data.xdg_surface.configure(serial.into());
|
|
||||||
}
|
|
||||||
|
|
||||||
fn make_toplevel_handle(resource: &zxdg_toplevel_v6::ZxdgToplevelV6) -> super::ToplevelSurface {
|
|
||||||
let data = resource
|
|
||||||
.as_ref()
|
|
||||||
.user_data()
|
|
||||||
.get::<ShellSurfaceUserData>()
|
|
||||||
.unwrap();
|
|
||||||
super::ToplevelSurface {
|
|
||||||
wl_surface: data.wl_surface.clone(),
|
|
||||||
shell_surface: ToplevelKind::ZxdgV6(resource.clone()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn toplevel_implementation(
|
|
||||||
toplevel: Main<zxdg_toplevel_v6::ZxdgToplevelV6>,
|
|
||||||
request: zxdg_toplevel_v6::Request,
|
|
||||||
dispatch_data: DispatchData<'_>,
|
|
||||||
) {
|
|
||||||
let data = toplevel
|
|
||||||
.as_ref()
|
|
||||||
.user_data()
|
|
||||||
.get::<ShellSurfaceUserData>()
|
|
||||||
.unwrap();
|
|
||||||
match request {
|
|
||||||
zxdg_toplevel_v6::Request::Destroy => {
|
|
||||||
// all it done by the destructor
|
|
||||||
}
|
|
||||||
zxdg_toplevel_v6::Request::SetParent { parent } => {
|
|
||||||
let parent_surface = parent.map(|toplevel_surface_parent| {
|
|
||||||
toplevel_surface_parent
|
|
||||||
.as_ref()
|
|
||||||
.user_data()
|
|
||||||
.get::<ShellSurfaceUserData>()
|
|
||||||
.unwrap()
|
|
||||||
.wl_surface
|
|
||||||
.clone()
|
|
||||||
});
|
|
||||||
|
|
||||||
// Parent is not double buffered, we can set it directly
|
|
||||||
set_parent(&toplevel, parent_surface);
|
|
||||||
}
|
|
||||||
zxdg_toplevel_v6::Request::SetTitle { title } => {
|
|
||||||
// Title is not double buffered, we can set it directly
|
|
||||||
with_surface_toplevel_role_data(&toplevel, |data| {
|
|
||||||
data.title = Some(title);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
zxdg_toplevel_v6::Request::SetAppId { app_id } => {
|
|
||||||
// AppId is not double buffered, we can set it directly
|
|
||||||
with_surface_toplevel_role_data(&toplevel, |role| {
|
|
||||||
role.app_id = Some(app_id);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
zxdg_toplevel_v6::Request::ShowWindowMenu { seat, serial, x, y } => {
|
|
||||||
let handle = make_toplevel_handle(&toplevel);
|
|
||||||
let mut user_impl = data.shell_data.user_impl.borrow_mut();
|
|
||||||
let serial = Serial::from(serial);
|
|
||||||
(&mut *user_impl)(
|
|
||||||
XdgRequest::ShowWindowMenu {
|
|
||||||
surface: handle,
|
|
||||||
seat,
|
|
||||||
serial,
|
|
||||||
location: (x, y).into(),
|
|
||||||
},
|
|
||||||
dispatch_data,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
zxdg_toplevel_v6::Request::Move { seat, serial } => {
|
|
||||||
let handle = make_toplevel_handle(&toplevel);
|
|
||||||
let mut user_impl = data.shell_data.user_impl.borrow_mut();
|
|
||||||
let serial = Serial::from(serial);
|
|
||||||
(&mut *user_impl)(
|
|
||||||
XdgRequest::Move {
|
|
||||||
surface: handle,
|
|
||||||
seat,
|
|
||||||
serial,
|
|
||||||
},
|
|
||||||
dispatch_data,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
zxdg_toplevel_v6::Request::Resize { seat, serial, edges } => {
|
|
||||||
let edges =
|
|
||||||
zxdg_toplevel_v6::ResizeEdge::from_raw(edges).unwrap_or(zxdg_toplevel_v6::ResizeEdge::None);
|
|
||||||
let handle = make_toplevel_handle(&toplevel);
|
|
||||||
let mut user_impl = data.shell_data.user_impl.borrow_mut();
|
|
||||||
let serial = Serial::from(serial);
|
|
||||||
(&mut *user_impl)(
|
|
||||||
XdgRequest::Resize {
|
|
||||||
surface: handle,
|
|
||||||
seat,
|
|
||||||
serial,
|
|
||||||
edges: zxdg_edges_to_xdg(edges),
|
|
||||||
},
|
|
||||||
dispatch_data,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
zxdg_toplevel_v6::Request::SetMaxSize { width, height } => {
|
|
||||||
with_toplevel_pending_state(&toplevel, |toplevel_data| {
|
|
||||||
toplevel_data.max_size = (width, height).into();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
zxdg_toplevel_v6::Request::SetMinSize { width, height } => {
|
|
||||||
with_toplevel_pending_state(&toplevel, |toplevel_data| {
|
|
||||||
toplevel_data.min_size = (width, height).into();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
zxdg_toplevel_v6::Request::SetMaximized => {
|
|
||||||
let handle = make_toplevel_handle(&toplevel);
|
|
||||||
let mut user_impl = data.shell_data.user_impl.borrow_mut();
|
|
||||||
(&mut *user_impl)(XdgRequest::Maximize { surface: handle }, dispatch_data);
|
|
||||||
}
|
|
||||||
zxdg_toplevel_v6::Request::UnsetMaximized => {
|
|
||||||
let handle = make_toplevel_handle(&toplevel);
|
|
||||||
let mut user_impl = data.shell_data.user_impl.borrow_mut();
|
|
||||||
(&mut *user_impl)(XdgRequest::UnMaximize { surface: handle }, dispatch_data);
|
|
||||||
}
|
|
||||||
zxdg_toplevel_v6::Request::SetFullscreen { output } => {
|
|
||||||
let handle = make_toplevel_handle(&toplevel);
|
|
||||||
let mut user_impl = data.shell_data.user_impl.borrow_mut();
|
|
||||||
(&mut *user_impl)(
|
|
||||||
XdgRequest::Fullscreen {
|
|
||||||
surface: handle,
|
|
||||||
output,
|
|
||||||
},
|
|
||||||
dispatch_data,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
zxdg_toplevel_v6::Request::UnsetFullscreen => {
|
|
||||||
let handle = make_toplevel_handle(&toplevel);
|
|
||||||
let mut user_impl = data.shell_data.user_impl.borrow_mut();
|
|
||||||
(&mut *user_impl)(XdgRequest::UnFullscreen { surface: handle }, dispatch_data);
|
|
||||||
}
|
|
||||||
zxdg_toplevel_v6::Request::SetMinimized => {
|
|
||||||
// This has to be handled by the compositor, may not be
|
|
||||||
// supported and just ignored
|
|
||||||
let handle = make_toplevel_handle(&toplevel);
|
|
||||||
let mut user_impl = data.shell_data.user_impl.borrow_mut();
|
|
||||||
(&mut *user_impl)(XdgRequest::Minimize { surface: handle }, dispatch_data);
|
|
||||||
}
|
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn destroy_toplevel(toplevel: zxdg_toplevel_v6::ZxdgToplevelV6) {
|
|
||||||
let data = toplevel
|
|
||||||
.as_ref()
|
|
||||||
.user_data()
|
|
||||||
.get::<ShellSurfaceUserData>()
|
|
||||||
.unwrap();
|
|
||||||
if let Some(data) = data.xdg_surface.as_ref().user_data().get::<XdgSurfaceUserData>() {
|
|
||||||
data.has_active_role.store(false, Ordering::Release);
|
|
||||||
}
|
|
||||||
// remove this surface from the known ones (as well as any leftover dead surface)
|
|
||||||
data.shell_data
|
|
||||||
.shell_state
|
|
||||||
.lock()
|
|
||||||
.unwrap()
|
|
||||||
.known_toplevels
|
|
||||||
.retain(|other| other.alive());
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* xdg_popup
|
|
||||||
*/
|
|
||||||
|
|
||||||
pub(crate) fn send_popup_configure(resource: &zxdg_popup_v6::ZxdgPopupV6, configure: PopupConfigure) {
|
|
||||||
let data = resource
|
|
||||||
.as_ref()
|
|
||||||
.user_data()
|
|
||||||
.get::<ShellSurfaceUserData>()
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let serial = configure.serial;
|
|
||||||
let geometry = configure.state.geometry;
|
|
||||||
|
|
||||||
// Send the popup configure
|
|
||||||
resource.configure(geometry.loc.x, geometry.loc.y, geometry.size.w, geometry.size.h);
|
|
||||||
|
|
||||||
// Send the base xdg_surface configure event to mark
|
|
||||||
// the configure as finished
|
|
||||||
data.xdg_surface.configure(serial.into());
|
|
||||||
}
|
|
||||||
|
|
||||||
fn make_popup_handle(resource: &zxdg_popup_v6::ZxdgPopupV6) -> super::PopupSurface {
|
|
||||||
let data = resource
|
|
||||||
.as_ref()
|
|
||||||
.user_data()
|
|
||||||
.get::<ShellSurfaceUserData>()
|
|
||||||
.unwrap();
|
|
||||||
super::PopupSurface {
|
|
||||||
wl_surface: data.wl_surface.clone(),
|
|
||||||
shell_surface: PopupKind::ZxdgV6(resource.clone()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn popup_implementation(
|
|
||||||
popup: Main<zxdg_popup_v6::ZxdgPopupV6>,
|
|
||||||
request: zxdg_popup_v6::Request,
|
|
||||||
dispatch_data: DispatchData<'_>,
|
|
||||||
) {
|
|
||||||
let data = popup.as_ref().user_data().get::<ShellSurfaceUserData>().unwrap();
|
|
||||||
match request {
|
|
||||||
zxdg_popup_v6::Request::Destroy => {
|
|
||||||
// all is handled by our destructor
|
|
||||||
}
|
|
||||||
zxdg_popup_v6::Request::Grab { seat, serial } => {
|
|
||||||
let handle = make_popup_handle(&popup);
|
|
||||||
let mut user_impl = data.shell_data.user_impl.borrow_mut();
|
|
||||||
let serial = Serial::from(serial);
|
|
||||||
(&mut *user_impl)(
|
|
||||||
XdgRequest::Grab {
|
|
||||||
surface: handle,
|
|
||||||
seat,
|
|
||||||
serial,
|
|
||||||
},
|
|
||||||
dispatch_data,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn destroy_popup(popup: zxdg_popup_v6::ZxdgPopupV6) {
|
|
||||||
let data = popup.as_ref().user_data().get::<ShellSurfaceUserData>().unwrap();
|
|
||||||
if let Some(data) = data.xdg_surface.as_ref().user_data().get::<XdgSurfaceUserData>() {
|
|
||||||
data.has_active_role.store(false, Ordering::Release);
|
|
||||||
}
|
|
||||||
// remove this surface from the known ones (as well as any leftover dead surface)
|
|
||||||
data.shell_data
|
|
||||||
.shell_state
|
|
||||||
.lock()
|
|
||||||
.unwrap()
|
|
||||||
.known_popups
|
|
||||||
.retain(|other| other.alive());
|
|
||||||
}
|
|
||||||
|
|
||||||
fn zxdg_edges_to_xdg(e: zxdg_toplevel_v6::ResizeEdge) -> xdg_toplevel::ResizeEdge {
|
|
||||||
match e {
|
|
||||||
zxdg_toplevel_v6::ResizeEdge::None => xdg_toplevel::ResizeEdge::None,
|
|
||||||
zxdg_toplevel_v6::ResizeEdge::Top => xdg_toplevel::ResizeEdge::Top,
|
|
||||||
zxdg_toplevel_v6::ResizeEdge::Bottom => xdg_toplevel::ResizeEdge::Bottom,
|
|
||||||
zxdg_toplevel_v6::ResizeEdge::Left => xdg_toplevel::ResizeEdge::Left,
|
|
||||||
zxdg_toplevel_v6::ResizeEdge::Right => xdg_toplevel::ResizeEdge::Right,
|
|
||||||
zxdg_toplevel_v6::ResizeEdge::TopLeft => xdg_toplevel::ResizeEdge::TopLeft,
|
|
||||||
zxdg_toplevel_v6::ResizeEdge::TopRight => xdg_toplevel::ResizeEdge::TopRight,
|
|
||||||
zxdg_toplevel_v6::ResizeEdge::BottomLeft => xdg_toplevel::ResizeEdge::BottomLeft,
|
|
||||||
zxdg_toplevel_v6::ResizeEdge::BottomRight => xdg_toplevel::ResizeEdge::BottomRight,
|
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn zxdg_constraints_adg_to_xdg(
|
|
||||||
c: zxdg_positioner_v6::ConstraintAdjustment,
|
|
||||||
) -> xdg_positioner::ConstraintAdjustment {
|
|
||||||
xdg_positioner::ConstraintAdjustment::from_bits_truncate(c.bits())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn zxdg_gravity_to_xdg(c: zxdg_positioner_v6::Gravity) -> Option<xdg_positioner::Gravity> {
|
|
||||||
match c.bits() {
|
|
||||||
0b0000 => Some(xdg_positioner::Gravity::None),
|
|
||||||
0b0001 => Some(xdg_positioner::Gravity::Top),
|
|
||||||
0b0010 => Some(xdg_positioner::Gravity::Bottom),
|
|
||||||
0b0100 => Some(xdg_positioner::Gravity::Left),
|
|
||||||
0b0101 => Some(xdg_positioner::Gravity::TopLeft),
|
|
||||||
0b0110 => Some(xdg_positioner::Gravity::BottomLeft),
|
|
||||||
0b1000 => Some(xdg_positioner::Gravity::Right),
|
|
||||||
0b1001 => Some(xdg_positioner::Gravity::TopRight),
|
|
||||||
0b1010 => Some(xdg_positioner::Gravity::BottomRight),
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn zxdg_anchor_to_xdg(c: zxdg_positioner_v6::Anchor) -> Option<xdg_positioner::Anchor> {
|
|
||||||
match c.bits() {
|
|
||||||
0b0000 => Some(xdg_positioner::Anchor::None),
|
|
||||||
0b0001 => Some(xdg_positioner::Anchor::Top),
|
|
||||||
0b0010 => Some(xdg_positioner::Anchor::Bottom),
|
|
||||||
0b0100 => Some(xdg_positioner::Anchor::Left),
|
|
||||||
0b0101 => Some(xdg_positioner::Anchor::TopLeft),
|
|
||||||
0b0110 => Some(xdg_positioner::Anchor::BottomLeft),
|
|
||||||
0b1000 => Some(xdg_positioner::Anchor::Right),
|
|
||||||
0b1001 => Some(xdg_positioner::Anchor::TopRight),
|
|
||||||
0b1010 => Some(xdg_positioner::Anchor::BottomRight),
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn get_parent(toplevel: &zxdg_toplevel_v6::ZxdgToplevelV6) -> Option<wl_surface::WlSurface> {
|
|
||||||
with_surface_toplevel_role_data(toplevel, |data| data.parent.clone())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Sets the parent of the specified toplevel surface.
|
|
||||||
///
|
|
||||||
/// The parent must be a toplevel surface.
|
|
||||||
///
|
|
||||||
/// The parent of a surface is not double buffered and therefore may be set directly.
|
|
||||||
///
|
|
||||||
/// If the parent is `None`, the parent-child relationship is removed.
|
|
||||||
pub(crate) fn set_parent(toplevel: &zxdg_toplevel_v6::ZxdgToplevelV6, parent: Option<wl_surface::WlSurface>) {
|
|
||||||
with_surface_toplevel_role_data(toplevel, |data| {
|
|
||||||
data.parent = parent;
|
|
||||||
});
|
|
||||||
}
|
|
|
@ -20,7 +20,7 @@
|
||||||
//!
|
//!
|
||||||
//! # let mut display = wayland_server::Display::new();
|
//! # let mut display = wayland_server::Display::new();
|
||||||
//! // XDG Shell init
|
//! // XDG Shell init
|
||||||
//! let (shell_state, _, _) = xdg_shell_init(
|
//! let (shell_state, _) = xdg_shell_init(
|
||||||
//! &mut display,
|
//! &mut display,
|
||||||
//! |event: XdgRequest, dispatch_data| { /* handle the shell requests here */ },
|
//! |event: XdgRequest, dispatch_data| { /* handle the shell requests here */ },
|
||||||
//! None
|
//! None
|
||||||
|
|
Loading…
Reference in New Issue