From 891e21d3e9b02eb47752954c123ed9dc762c656c Mon Sep 17 00:00:00 2001 From: Ferdinand Schober Date: Thu, 21 Sep 2023 00:12:02 +0200 Subject: [PATCH] read all output globals --- README.md | 2 + config.toml | 2 + src/backend/producer/wayland.rs | 154 +++++++++++++++++++++++++++----- 3 files changed, 134 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index 3808dd5..ab163bf 100644 --- a/README.md +++ b/README.md @@ -44,6 +44,8 @@ ips = ["192.168.178.156"] host_name = "thorium" # ips for ethernet and wifi ips = ["192.168.178.189"] +# optional port +port = 4242 ``` Where `left` can be either `left`, `right`, `top` or `bottom`. diff --git a/config.toml b/config.toml index 82b19fd..c9b75a4 100644 --- a/config.toml +++ b/config.toml @@ -19,3 +19,5 @@ ips = ["192.168.178.156"] host_name = "thorium" # ips for ethernet and wifi ips = ["192.168.178.189", "192.168.178.172"] +# optional port +port = 4242 diff --git a/src/backend/producer/wayland.rs b/src/backend/producer/wayland.rs index 3768850..6a52e3f 100644 --- a/src/backend/producer/wayland.rs +++ b/src/backend/producer/wayland.rs @@ -12,7 +12,7 @@ use std::{ rc::Rc, }; -use wayland_protocols::wp::{ +use wayland_protocols::{wp::{ keyboard_shortcuts_inhibit::zv1::client::{ zwp_keyboard_shortcuts_inhibit_manager_v1::ZwpKeyboardShortcutsInhibitManagerV1, zwp_keyboard_shortcuts_inhibitor_v1::ZwpKeyboardShortcutsInhibitorV1, @@ -25,7 +25,7 @@ use wayland_protocols::wp::{ zwp_relative_pointer_manager_v1::ZwpRelativePointerManagerV1, zwp_relative_pointer_v1::{self, ZwpRelativePointerV1}, }, -}; +}, xdg::xdg_output::zv1::client::{zxdg_output_manager_v1::ZxdgOutputManagerV1, zxdg_output_v1::{self, ZxdgOutputV1}}}; use wayland_protocols_wlr::layer_shell::v1::client::{ zwlr_layer_shell_v1::{Layer, ZwlrLayerShellV1}, @@ -38,9 +38,9 @@ use wayland_client::{ globals::{registry_queue_init, GlobalListContents}, protocol::{ wl_buffer, wl_compositor, wl_keyboard, wl_pointer, wl_region, wl_registry, wl_seat, wl_shm, - wl_shm_pool, wl_surface, + wl_shm_pool, wl_surface, wl_output, }, - Connection, Dispatch, DispatchError, QueueHandle, WEnum, EventQueue, + Connection, Dispatch, DispatchError, QueueHandle, WEnum, EventQueue, delegate_dispatch, }; use tempfile; @@ -55,6 +55,8 @@ struct Globals { seat: wl_seat::WlSeat, shm: wl_shm::WlShm, layer_shell: ZwlrLayerShellV1, + outputs: Vec, + xdg_output_manager: ZxdgOutputManagerV1, } struct State { @@ -149,9 +151,16 @@ fn draw(f: &mut File, (width, height): (u32, u32)) { impl WaylandEventProducer { pub fn new() -> Result { - let conn = Connection::connect_to_env().expect("could not connect to wayland compositor"); - let (g, queue) = - registry_queue_init::(&conn).expect("failed to initialize wl_registry"); + let conn = match Connection::connect_to_env() { + Ok(c) => c, + Err(e) => return Err(anyhow!("could not connect to wayland compositor: {e:?}")), + }; + + let (g, mut queue) = match registry_queue_init::(&conn) { + Ok(q) => q, + Err(e) => return Err(anyhow!("failed to initialize wl_registry: {e:?}")), + }; + let qh = queue.handle(); let compositor: wl_compositor::WlCompositor = match g.bind(&qh, 4..=5, ()) { @@ -159,6 +168,11 @@ impl WaylandEventProducer { Err(_) => return Err(anyhow!("wl_compositor >= v4 not supported")), }; + let xdg_output_manager: ZxdgOutputManagerV1 = match g.bind(&qh, 1..=3, ()) { + Ok(xdg_output_manager) => xdg_output_manager, + Err(_) => return Err(anyhow!("xdg_output not supported!")), + }; + let shm: wl_shm::WlShm = match g.bind(&qh, 1..=1, ()) { Ok(wl_shm) => wl_shm, Err(_) => return Err(anyhow!("wl_shm v1 not supported")), @@ -189,6 +203,8 @@ impl WaylandEventProducer { Err(_) => return Err(anyhow!("zwp_keyboard_shortcuts_inhibit_manager_v1 not supported")), }; + let outputs = vec![]; + let g = Globals { compositor, shm, @@ -197,6 +213,8 @@ impl WaylandEventProducer { pointer_constraints, relative_pointer_manager, shortcut_inhibit_manager, + outputs, + xdg_output_manager, }; // flush outgoing events @@ -205,23 +223,43 @@ impl WaylandEventProducer { // prepare reading wayland events let read_guard = queue.prepare_read()?; let wayland_fd = read_guard.connection_fd().as_raw_fd(); - let read_guard = Some(read_guard); + std::mem::drop(read_guard); - Ok(WaylandEventProducer { - queue, - state: State { - g, - pointer_lock: None, - rel_pointer: None, - shortcut_inhibitor: None, - client_for_window: Vec::new(), - focused: None, - qh, - wayland_fd, - read_guard, - pending_events: vec![], - } - }) + let mut state = State { + g, + pointer_lock: None, + rel_pointer: None, + shortcut_inhibitor: None, + client_for_window: Vec::new(), + focused: None, + qh, + wayland_fd, + read_guard: None, + pending_events: vec![], + }; + + // dispatch registry to () again, in order to read all wl_outputs + conn.display().get_registry(&state.qh, ()); + log::debug!("==============> requested registry"); + + // roundtrip to read wl_output globals + queue.roundtrip(&mut state)?; + log::debug!("==============> roundtrip 1 done"); + + // read outputs + for output in state.g.outputs.iter() { + state.g.xdg_output_manager.get_xdg_output(output, &state.qh, ()); + } + + // roundtrip to read xdg_output events + queue.roundtrip(&mut state)?; + + log::debug!("==============> roundtrip 2 done"); + + let read_guard = queue.prepare_read()?; + state.read_guard = Some(read_guard); + + Ok(WaylandEventProducer { queue, state }) } } @@ -675,7 +713,6 @@ impl Dispatch for State { } // delegate wl_registry events to App itself -// delegate_dispatch!(App: [wl_registry::WlRegistry: GlobalListContents] => App); impl Dispatch for State { fn event( _state: &mut Self, @@ -688,6 +725,74 @@ impl Dispatch for State { } } +impl Dispatch for State { + fn event( + state: &mut Self, + registry: &wl_registry::WlRegistry, + event: ::Event, + _: &(), + _: &Connection, + qh: &QueueHandle, + ) { + match event { + wl_registry::Event::Global { name, interface, version: _ } => { + match interface.as_str() { + "wl_output" => { + log::debug!("wl_output global"); + state.g.outputs.push(registry.bind::(name, 4, qh, ())) + } + _ => {} + } + }, + wl_registry::Event::GlobalRemove { .. } => {}, + _ => {}, + } + } +} + +impl Dispatch for State { + fn event( + _state: &mut Self, + _wl_output: &wl_output::WlOutput, + event: ::Event, + _data: &(), + _conn: &Connection, + _qhandle: &QueueHandle, + ) { + log::debug!("wl_output - {event:?}"); + match event { + wl_output::Event::Geometry { .. } => {}, + wl_output::Event::Mode { .. } => {}, + wl_output::Event::Done => {}, + wl_output::Event::Scale { .. } => {}, + wl_output::Event::Name { .. } => {}, + wl_output::Event::Description { .. } => {}, + _ => {}, + } + } +} + +impl Dispatch for State { + fn event( + _state: &mut Self, + _proxy: &ZxdgOutputV1, + event: ::Event, + _data: &(), + _conn: &Connection, + _qhandle: &QueueHandle, + ) { + log::debug!("xdg-output - {event:?}"); + match event { + zxdg_output_v1::Event::LogicalPosition { .. } => {}, + zxdg_output_v1::Event::LogicalSize { .. } => {}, + zxdg_output_v1::Event::Done => {}, + zxdg_output_v1::Event::Name { .. } => {}, + zxdg_output_v1::Event::Description { .. } => {}, + _ => {}, + } + } +} + // don't emit any events delegate_noop!(State: wl_region::WlRegion); delegate_noop!(State: wl_shm_pool::WlShmPool); @@ -698,6 +803,7 @@ delegate_noop!(State: ZwpKeyboardShortcutsInhibitManagerV1); delegate_noop!(State: ZwpPointerConstraintsV1); // ignore events +delegate_noop!(State: ignore ZxdgOutputManagerV1); delegate_noop!(State: ignore wl_shm::WlShm); delegate_noop!(State: ignore wl_buffer::WlBuffer); delegate_noop!(State: ignore wl_surface::WlSurface);