#![warn(missing_docs, missing_debug_implementations)]
#![allow(clippy::new_without_default)]
#[macro_use]
extern crate dlib;
pub mod reexports {
#[cfg(feature = "calloop")]
pub use calloop;
pub use wayland_client as client;
pub use wayland_protocols as protocols;
}
pub mod data_device;
pub mod environment;
mod lazy_global;
pub mod output;
pub mod primary_selection;
pub mod seat;
pub mod shell;
pub mod shm;
pub mod window;
#[cfg(feature = "calloop")]
mod event_loop;
mod surface;
#[cfg(feature = "calloop")]
pub use event_loop::WaylandSource;
pub use surface::{get_surface_outputs, get_surface_scale_factor};
#[macro_export]
macro_rules! default_environment {
($env_name:ident, desktop
$(,fields = [$($fname:ident : $fty:ty),* $(,)?])?
$(,singles = [$($sty:ty => $sname: ident),* $(,)?])?
$(,multis = [$($mty:ty => $mname:ident),* $(,)?])?
$(,)?
) => {
$crate::default_environment!($env_name,
fields=[
// shell
sctk_shell: $crate::shell::ShellHandler,
// decoration
sctk_decoration_mgr: $crate::environment::SimpleGlobal<$crate::reexports::protocols::unstable::xdg_decoration::v1::client::zxdg_decoration_manager_v1::ZxdgDecorationManagerV1>,
// others
$($($fname : $fty,)*)?
],
singles = [
$crate::reexports::client::protocol::wl_shell::WlShell => sctk_shell,
$crate::reexports::protocols::xdg_shell::client::xdg_wm_base::XdgWmBase => sctk_shell,
$crate::reexports::protocols::unstable::xdg_shell::v6::client::zxdg_shell_v6::ZxdgShellV6 => sctk_shell,
$crate::reexports::protocols::unstable::xdg_decoration::v1::client::zxdg_decoration_manager_v1::ZxdgDecorationManagerV1 => sctk_decoration_mgr,
$($($sty => $sname,)*)?
],
multis = [ $($($mty => $mname,)*)? ],
);
impl $crate::shell::ShellHandling for $env_name {
fn get_shell(&self) -> Option<$crate::shell::Shell> {
self.sctk_shell.get_shell()
}
}
};
($env_name:ident
$(,fields = [$($fname:ident : $fty:ty),* $(,)?])?
$(,singles = [$($sty:ty => $sname:ident),* $(,)?])?
$(,multis = [$($mty:ty => $mname:ident),* $(,)?])?
$(,)?
) => {
pub struct $env_name {
// SimpleGlobals
sctk_compositor: $crate::environment::SimpleGlobal<$crate::reexports::client::protocol::wl_compositor::WlCompositor>,
sctk_subcompositor: $crate::environment::SimpleGlobal<$crate::reexports::client::protocol::wl_subcompositor::WlSubcompositor>,
sctk_shm: $crate::shm::ShmHandler,
sctk_outputs: $crate::output::OutputHandler,
sctk_seats: $crate::seat::SeatHandler,
sctk_data_device_manager: $crate::data_device::DataDeviceHandler,
sctk_primary_selection_manager: $crate::primary_selection::PrimarySelectionHandler,
$($(
$fname : $fty,
)*)?
}
impl $crate::shm::ShmHandling for $env_name {
fn shm_formats(&self) -> Vec<$crate::reexports::client::protocol::wl_shm::Format> {
self.sctk_shm.shm_formats()
}
}
impl $crate::seat::SeatHandling for $env_name {
fn listen<F>(&mut self, f: F) -> $crate::seat::SeatListener
where F: FnMut(
$crate::reexports::client::Attached<$crate::reexports::client::protocol::wl_seat::WlSeat>,
&$crate::seat::SeatData,
$crate::reexports::client::DispatchData
) + 'static
{
self.sctk_seats.listen(f)
}
}
impl $crate::output::OutputHandling for $env_name {
fn listen<F>(&mut self, f: F) -> $crate::output::OutputStatusListener
where F: FnMut(
$crate::reexports::client::protocol::wl_output::WlOutput,
&$crate::output::OutputInfo,
$crate::reexports::client::DispatchData,
) + 'static
{
self.sctk_outputs.listen(f)
}
}
impl $crate::data_device::DataDeviceHandling for $env_name {
fn set_callback<F>(&mut self, callback: F) -> ::std::result::Result<(), $crate::MissingGlobal>
where F: FnMut(
$crate::reexports::client::protocol::wl_seat::WlSeat,
$crate::data_device::DndEvent,
$crate::reexports::client::DispatchData
) + 'static
{
self.sctk_data_device_manager.set_callback(callback)
}
fn with_device<F: FnOnce(&$crate::data_device::DataDevice)>(
&self,
seat: &$crate::reexports::client::protocol::wl_seat::WlSeat,
f: F
) -> ::std::result::Result<(), $crate::MissingGlobal> {
self.sctk_data_device_manager.with_device(seat, f)
}
}
impl $crate::primary_selection::PrimarySelectionHandling for $env_name {
fn with_primary_selection<F>(
&self,
seat: &$crate::reexports::client::protocol::wl_seat::WlSeat,
f: F,
) -> ::std::result::Result<(), $crate::MissingGlobal>
where F: FnOnce(&$crate::primary_selection::PrimarySelectionDevice)
{
self.sctk_primary_selection_manager.with_primary_selection(seat, f)
}
fn get_primary_selection_manager(&self) -> Option<$crate::primary_selection::PrimarySelectionDeviceManager> {
self.sctk_primary_selection_manager.get_primary_selection_manager()
}
}
$crate::environment!($env_name,
singles = [
$crate::reexports::client::protocol::wl_compositor::WlCompositor => sctk_compositor,
$crate::reexports::client::protocol::wl_subcompositor::WlSubcompositor => sctk_subcompositor,
$crate::reexports::client::protocol::wl_shm::WlShm => sctk_shm,
$crate::reexports::client::protocol::wl_data_device_manager::WlDataDeviceManager => sctk_data_device_manager,
$crate::reexports::protocols::unstable::primary_selection::v1::client::zwp_primary_selection_device_manager_v1::ZwpPrimarySelectionDeviceManagerV1 => sctk_primary_selection_manager,
$crate::reexports::protocols::misc::gtk_primary_selection::client::gtk_primary_selection_device_manager::GtkPrimarySelectionDeviceManager => sctk_primary_selection_manager,
$($($sty => $sname),*)?
],
multis = [
$crate::reexports::client::protocol::wl_output::WlOutput => sctk_outputs,
$crate::reexports::client::protocol::wl_seat::WlSeat => sctk_seats,
$($($mty => $mname),*)?
]
);
};
}
#[macro_export]
macro_rules! new_default_environment {
($env_name:ident, desktop
$(, with=($display:expr, $queue:expr))?
$(,fields = [$($fname:ident : $fval:expr),* $(,)?])?
$(,)?
) => {
$crate::new_default_environment!($env_name,
$(with=($display, $queue),)?
fields = [
sctk_shell: $crate::shell::ShellHandler::new(),
sctk_decoration_mgr: $crate::environment::SimpleGlobal::new(),
$($(
$fname: $fval,
)*)?
]
)
};
($env_name:ident, with=($display:expr, $queue:expr)
$(,fields = [$($fname:ident : $fval:expr),* $(,)?])?
$(,)?
) => {
{
let mut sctk_seats = $crate::seat::SeatHandler::new();
let sctk_data_device_manager = $crate::data_device::DataDeviceHandler::init(&mut sctk_seats);
let sctk_primary_selection_manager = $crate::primary_selection::PrimarySelectionHandler::init(&mut sctk_seats);
let display = $crate::reexports::client::Proxy::clone(&$display);
let env = $crate::environment::Environment::new(&display.attach($queue.token()), &mut $queue,$env_name {
sctk_compositor: $crate::environment::SimpleGlobal::new(),
sctk_subcompositor: $crate::environment::SimpleGlobal::new(),
sctk_shm: $crate::shm::ShmHandler::new(),
sctk_outputs: $crate::output::OutputHandler::new(),
sctk_seats,
sctk_data_device_manager,
sctk_primary_selection_manager,
$($(
$fname: $fval,
)*)?
});
if let Ok(env) = env.as_ref() {
let _psm = env.get_primary_selection_manager();
}
env
}
};
($env_name:ident
$(,fields = [$($fname:ident : $fval:expr),* $(,)?])?
$(,)?
) => {
$crate::reexports::client::Display::connect_to_env().and_then(|display| {
let mut queue = display.create_event_queue();
let ret = $crate::new_default_environment!(
$env_name,
with=(display, queue),
fields=[$($($fname: $fval),*)?],
);
match ret {
Ok(env) => Ok((env, display, queue)),
Err(e) => {
if let Some(perr) = display.protocol_error() {
panic!("[SCTK] A protocol error occured during initial setup: {}", perr);
} else {
Err($crate::reexports::client::ConnectError::NoCompositorListening)
}
}
}
})
};
}
#[derive(Debug, Copy, Clone)]
pub struct MissingGlobal;
impl std::error::Error for MissingGlobal {}
impl std::fmt::Display for MissingGlobal {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str("missing global")
}
}