xwayland-satellite/src/clientside.rs
Shawn Wallace 2317ebb842 Set input focus on windows without WM_HINTS input flag
Also miscellaneous formatting things.
Part of #8
2024-05-20 01:26:06 -04:00

203 lines
5.7 KiB
Rust

use crate::server::{ObjectEvent, ObjectKey};
use std::os::fd::OwnedFd;
use std::os::unix::net::UnixStream;
use std::sync::mpsc;
use wayland_client::protocol::{
wl_buffer::WlBuffer, wl_callback::WlCallback, wl_compositor::WlCompositor,
wl_keyboard::WlKeyboard, wl_output::WlOutput, wl_pointer::WlPointer, wl_region::WlRegion,
wl_registry::WlRegistry, wl_seat::WlSeat, wl_shm::WlShm, wl_shm_pool::WlShmPool,
wl_surface::WlSurface, wl_touch::WlTouch,
};
use wayland_client::{delegate_noop, Connection, Dispatch, EventQueue, Proxy, QueueHandle};
use wayland_protocols::wp::relative_pointer::zv1::client::{
zwp_relative_pointer_manager_v1::ZwpRelativePointerManagerV1,
zwp_relative_pointer_v1::ZwpRelativePointerV1,
};
use wayland_protocols::{
wp::{
linux_dmabuf::zv1::client::{
self as dmabuf,
zwp_linux_dmabuf_feedback_v1::ZwpLinuxDmabufFeedbackV1 as DmabufFeedback,
zwp_linux_dmabuf_v1::ZwpLinuxDmabufV1,
},
viewporter::client::{wp_viewport::WpViewport, wp_viewporter::WpViewporter},
},
xdg::{
shell::client::{
xdg_popup::XdgPopup, xdg_positioner::XdgPositioner, xdg_surface::XdgSurface,
xdg_toplevel::XdgToplevel, xdg_wm_base::XdgWmBase,
},
xdg_output::zv1::client::{
zxdg_output_manager_v1::ZxdgOutputManagerV1, zxdg_output_v1::ZxdgOutputV1 as XdgOutput,
},
},
};
use wayland_server::protocol as server;
use wl_drm::client::wl_drm::WlDrm;
#[derive(Debug)]
pub struct GlobalData {
pub name: u32,
pub interface: String,
pub version: u32,
}
#[derive(Default)]
pub struct Globals {
pub(crate) events: Vec<(ObjectKey, ObjectEvent)>,
pub new_globals: Vec<GlobalData>,
}
pub type ClientQueueHandle = QueueHandle<Globals>;
pub struct ClientShmPool {
pub pool: WlShmPool,
pub fd: OwnedFd,
}
pub struct ClientState {
pub connection: Connection,
pub queue: EventQueue<Globals>,
pub qh: ClientQueueHandle,
pub globals: Globals,
pub registry: WlRegistry,
}
impl ClientState {
pub fn new(server_connection: Option<UnixStream>) -> Self {
let connection = if let Some(stream) = server_connection {
Connection::from_socket(stream)
} else {
Connection::connect_to_env()
}
.unwrap();
let mut queue = connection.new_event_queue::<Globals>();
let qh = queue.handle();
let mut globals = Globals::default();
let registry = connection.display().get_registry(&qh, ());
// Get initial globals
queue.roundtrip(&mut globals).unwrap();
Self {
connection,
queue,
qh,
globals,
registry,
}
}
}
pub type Event<T> = <T as Proxy>::Event;
delegate_noop!(Globals: WlCompositor);
delegate_noop!(Globals: WlRegion);
delegate_noop!(Globals: ignore WlShm);
delegate_noop!(Globals: ignore ZwpLinuxDmabufV1);
delegate_noop!(Globals: ZwpRelativePointerManagerV1);
delegate_noop!(Globals: ignore dmabuf::zwp_linux_buffer_params_v1::ZwpLinuxBufferParamsV1);
delegate_noop!(Globals: XdgPositioner);
delegate_noop!(Globals: WlShmPool);
delegate_noop!(Globals: WpViewporter);
delegate_noop!(Globals: WpViewport);
delegate_noop!(Globals: ZxdgOutputManagerV1);
impl Dispatch<WlRegistry, ()> for Globals {
fn event(
state: &mut Self,
_: &WlRegistry,
event: <WlRegistry as Proxy>::Event,
_: &(),
_: &wayland_client::Connection,
_: &wayland_client::QueueHandle<Self>,
) {
if let Event::<WlRegistry>::Global {
name,
interface,
version,
} = event
{
state.new_globals.push(GlobalData {
name,
interface,
version,
});
};
}
}
impl Dispatch<XdgWmBase, ()> for Globals {
fn event(
_: &mut Self,
base: &XdgWmBase,
event: <XdgWmBase as Proxy>::Event,
_: &(),
_: &wayland_client::Connection,
_: &wayland_client::QueueHandle<Self>,
) {
if let Event::<XdgWmBase>::Ping { serial } = event {
base.pong(serial);
}
}
}
impl Dispatch<WlCallback, server::wl_callback::WlCallback> for Globals {
fn event(
_: &mut Self,
_: &WlCallback,
event: <WlCallback as Proxy>::Event,
s_callback: &server::wl_callback::WlCallback,
_: &Connection,
_: &QueueHandle<Self>,
) {
if let Event::<WlCallback>::Done { callback_data } = event {
s_callback.done(callback_data);
}
}
}
impl Dispatch<WlOutput, mpsc::Sender<Event<WlOutput>>> for Globals {
fn event(
_: &mut Self,
_: &WlOutput,
event: <WlOutput as Proxy>::Event,
data: &mpsc::Sender<Event<WlOutput>>,
_: &Connection,
_: &QueueHandle<Self>,
) {
let _ = data.send(event);
}
}
macro_rules! push_events {
($type:ident) => {
impl Dispatch<$type, ObjectKey> for Globals {
fn event(
state: &mut Self,
_: &$type,
event: <$type as Proxy>::Event,
key: &ObjectKey,
_: &Connection,
_: &QueueHandle<Self>,
) {
state.events.push((*key, event.into()));
}
}
};
}
push_events!(WlSurface);
push_events!(WlBuffer);
push_events!(XdgSurface);
push_events!(XdgToplevel);
push_events!(XdgPopup);
push_events!(WlSeat);
push_events!(WlPointer);
push_events!(WlOutput);
push_events!(WlKeyboard);
push_events!(ZwpRelativePointerV1);
push_events!(WlDrm);
push_events!(DmabufFeedback);
push_events!(XdgOutput);
push_events!(WlTouch);