use std::fmt;
use serde::{ser::Serializer, Serialize};
use zbus::zvariant::Type;
#[derive(Type)]
#[zvariant(signature = "s")]
#[doc(alias = "XdpParent")]
pub enum WindowIdentifier {
#[cfg(feature = "feature_gtk4")]
#[doc(hidden)]
Gtk4(Gtk4WindowIdentifier),
#[cfg(feature = "feature_gtk3")]
#[doc(hidden)]
Gtk3(Gtk3WindowIdentifier),
#[cfg(feature = "wayland")]
#[doc(hidden)]
Wayland(WaylandWindowIdentifier),
#[doc(hidden)]
X11(WindowIdentifierType),
#[doc(hidden)]
None,
}
unsafe impl Send for WindowIdentifier {}
unsafe impl Sync for WindowIdentifier {}
impl Serialize for WindowIdentifier {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_str(&self.to_string())
}
}
impl std::fmt::Display for WindowIdentifier {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
#[cfg(feature = "feature_gtk4")]
Self::Gtk4(identifier) => f.write_str(&format!("{}", identifier)),
#[cfg(feature = "feature_gtk3")]
Self::Gtk3(identifier) => f.write_str(&format!("{}", identifier)),
#[cfg(feature = "wayland")]
Self::Wayland(identifier) => f.write_str(&format!("{}", identifier)),
Self::X11(identifier) => f.write_str(&format!("{}", identifier)),
Self::None => f.write_str(""),
}
}
}
impl std::fmt::Debug for WindowIdentifier {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_tuple("WindowIdentifier")
.field(&format!("{}", self))
.finish()
}
}
impl Default for WindowIdentifier {
fn default() -> Self {
Self::None
}
}
impl WindowIdentifier {
#[cfg(feature = "feature_gtk4")]
#[doc(alias = "xdp_parent_new_gtk")]
pub async fn from_native(native: &impl ::gtk4::glib::IsA<::gtk4::Native>) -> Self {
match Gtk4WindowIdentifier::new(native).await {
Some(identifier) => Self::Gtk4(identifier),
None => Self::default(),
}
}
#[cfg(feature = "feature_gtk3")]
#[doc(alias = "xdp_parent_new_gtk")]
pub async fn from_window(win: &impl ::gtk3::glib::IsA<::gtk3::gdk::Window>) -> Self {
match Gtk3WindowIdentifier::new(win).await {
Some(identifier) => Self::Gtk3(identifier),
None => Self::default(),
}
}
#[cfg(feature = "raw_handle")]
pub fn from_raw_handle(handle: &raw_window_handle::RawWindowHandle) -> Self {
use raw_window_handle::RawWindowHandle::{Wayland, Xcb, Xlib};
match handle {
Wayland(wl_handle) => unsafe { Self::from_wayland_raw(wl_handle.surface) },
Xlib(x_handle) => Self::from_xid(x_handle.window),
Xcb(x_handle) => Self::from_xid(x_handle.window.into()),
_ => Self::default(), }
}
pub fn from_xid(xid: std::os::raw::c_ulong) -> Self {
Self::X11(WindowIdentifierType::X11(xid))
}
#[cfg(feature = "wayland")]
pub unsafe fn from_wayland_raw(surface_ptr: *mut std::ffi::c_void) -> Self {
match WaylandWindowIdentifier::from_raw(surface_ptr) {
Some(identifier) => Self::Wayland(identifier),
None => Self::default(),
}
}
#[cfg(feature = "wayland")]
pub fn from_wayland(surface: &wayland_client::protocol::wl_surface::WlSurface) -> Self {
match WaylandWindowIdentifier::new(surface) {
Some(identifier) => Self::Wayland(identifier),
None => Self::default(),
}
}
#[cfg(all(
feature = "raw_handle",
any(feature = "feature_gtk3", feature = "feature_gtk4")
))]
pub fn as_raw_handle(&self) -> raw_window_handle::RawWindowHandle {
match self {
#[cfg(feature = "feature_gtk4")]
Self::Gtk4(identifier) => identifier.as_raw_handle(),
#[cfg(feature = "feature_gtk3")]
Self::Gtk3(identifier) => identifier.as_raw_handle(),
_ => unreachable!(),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum WindowIdentifierType {
X11(std::os::raw::c_ulong),
#[allow(dead_code)]
Wayland(String),
}
impl fmt::Display for WindowIdentifierType {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::X11(xid) => f.write_str(&format!("x11:0x{:x}", xid)),
Self::Wayland(handle) => f.write_str(&format!("wayland:{}", handle)),
}
}
}
#[cfg(feature = "feature_gtk4")]
mod gtk4;
#[cfg(feature = "feature_gtk4")]
pub use self::gtk4::Gtk4WindowIdentifier;
#[cfg(feature = "feature_gtk3")]
mod gtk3;
#[cfg(feature = "feature_gtk3")]
pub use self::gtk3::Gtk3WindowIdentifier;
#[cfg(any(feature = "wayland"))]
mod wayland;
#[cfg(feature = "wayland")]
pub use self::wayland::WaylandWindowIdentifier;
#[cfg(test)]
mod tests {
use super::WindowIdentifier;
#[test]
fn test_serialize() {
let x11 = WindowIdentifier::from_xid(1024);
assert_eq!(x11.to_string(), "x11:0x400");
assert_eq!(WindowIdentifier::default().to_string(), "");
}
}