use raw_window_handle::{RawDisplayHandle, RawWindowHandle};
use wayland_backend::client::ObjectId;
use wayland_backend::sys::client::Backend;
use wayland_client::globals::{GlobalListContents, registry_queue_init};
use wayland_client::protocol::wl_registry::WlRegistry;
use wayland_client::protocol::wl_surface::WlSurface;
use wayland_client::{Connection, Dispatch, Proxy, QueueHandle};
use wayland_protocols::xdg::activation::v1::client::xdg_activation_v1::XdgActivationV1;
use winit::raw_window_handle::{HasDisplayHandle, HasWindowHandle};
use winit::window::Window;
pub(super) fn activate_with_token(window: &Window, token: &str) {
if activate(window, token).is_none() {
super::request_attention(window);
}
}
struct ActivationState;
impl Dispatch<WlRegistry, GlobalListContents> for ActivationState {
fn event(
_: &mut Self,
_: &WlRegistry,
_: <WlRegistry as Proxy>::Event,
_: &GlobalListContents,
_: &Connection,
_: &QueueHandle<Self>,
) {
}
}
impl Dispatch<XdgActivationV1, ()> for ActivationState {
fn event(
_: &mut Self,
_: &XdgActivationV1,
_: <XdgActivationV1 as Proxy>::Event,
_: &(),
_: &Connection,
_: &QueueHandle<Self>,
) {
}
}
fn activate(window: &Window, token: &str) -> Option<()> {
let RawDisplayHandle::Wayland(display) = window.display_handle().ok()?.as_raw() else {
return None;
};
let RawWindowHandle::Wayland(surface_handle) = window.window_handle().ok()?.as_raw() else {
return None;
};
let backend = unsafe { Backend::from_foreign_display(display.display.as_ptr() as *mut _) };
let conn = Connection::from_backend(backend);
let (globals, queue) = registry_queue_init::<ActivationState>(&conn).ok()?;
let qh = queue.handle();
let activation = globals.bind::<XdgActivationV1, _, _>(&qh, 1..=1, ()).ok()?;
let surface_id = unsafe {
ObjectId::from_ptr(
WlSurface::interface(),
surface_handle.surface.as_ptr() as *mut _,
)
}
.ok()?;
let surface = WlSurface::from_id(&conn, surface_id).ok()?;
activation.activate(token.to_string(), &surface);
conn.flush().ok()?;
Some(())
}