From 3e3bc38920805c1cee76dea71737e221d4bd0d88 Mon Sep 17 00:00:00 2001 From: Julian Orth Date: Sat, 30 Jul 2022 11:09:21 +0200 Subject: [PATCH] wayland: add jay_output --- src/client/objects.rs | 10 +++-- src/compositor.rs | 1 + src/ifs.rs | 1 + src/ifs/jay_compositor.rs | 28 ++++++++++++-- src/ifs/jay_output.rs | 78 +++++++++++++++++++++++++++++++++++++++ src/tasks/connector.rs | 5 +++ src/tree/output.rs | 5 +++ wire/jay_compositor.txt | 5 +++ wire/jay_output.txt | 15 ++++++++ 9 files changed, 142 insertions(+), 6 deletions(-) create mode 100644 src/ifs/jay_output.rs create mode 100644 wire/jay_output.txt diff --git a/src/client/objects.rs b/src/client/objects.rs index bc7e604e..8477e992 100644 --- a/src/client/objects.rs +++ b/src/client/objects.rs @@ -6,6 +6,7 @@ use { wl_data_source::WlDataSource, zwp_primary_selection_source_v1::ZwpPrimarySelectionSourceV1, }, + jay_output::JayOutput, wl_buffer::WlBuffer, wl_display::WlDisplay, wl_output::WlOutput, @@ -25,9 +26,9 @@ use { copyhashmap::{CopyHashMap, Locked}, }, wire::{ - WlBufferId, WlDataSourceId, WlOutputId, WlPointerId, WlRegionId, WlRegistryId, - WlSeatId, WlSurfaceId, XdgPositionerId, XdgSurfaceId, XdgToplevelId, XdgWmBaseId, - ZwpPrimarySelectionSourceV1Id, + JayOutputId, WlBufferId, WlDataSourceId, WlOutputId, WlPointerId, WlRegionId, + WlRegistryId, WlSeatId, WlSurfaceId, XdgPositionerId, XdgSurfaceId, XdgToplevelId, + XdgWmBaseId, ZwpPrimarySelectionSourceV1Id, }, }, std::{cell::RefCell, mem, rc::Rc}, @@ -47,6 +48,7 @@ pub struct Objects { pub xdg_positioners: CopyHashMap>, pub regions: CopyHashMap>, pub buffers: CopyHashMap>, + pub jay_outputs: CopyHashMap>, pub pointers: CopyHashMap>, pub xdg_wm_bases: CopyHashMap>, pub seats: CopyHashMap>, @@ -71,6 +73,7 @@ impl Objects { xdg_positioners: Default::default(), regions: Default::default(), buffers: Default::default(), + jay_outputs: Default::default(), pointers: Default::default(), xdg_wm_bases: Default::default(), seats: Default::default(), @@ -99,6 +102,7 @@ impl Objects { self.xdg_positioners.clear(); self.regions.clear(); self.buffers.clear(); + self.jay_outputs.clear(); self.xdg_wm_bases.clear(); self.seats.clear(); self.pointers.clear(); diff --git a/src/compositor.rs b/src/compositor.rs index 0adc3f11..275e6d16 100644 --- a/src/compositor.rs +++ b/src/compositor.rs @@ -374,6 +374,7 @@ fn create_dummy_output(state: &Rc) { 0, 0, )), + jay_outputs: Default::default(), workspaces: Default::default(), workspace: Default::default(), seat_state: Default::default(), diff --git a/src/ifs.rs b/src/ifs.rs index 611347a9..171a10b8 100644 --- a/src/ifs.rs +++ b/src/ifs.rs @@ -4,6 +4,7 @@ pub mod ipc; pub mod jay_compositor; pub mod jay_idle; pub mod jay_log_file; +pub mod jay_output; pub mod jay_screenshot; pub mod jay_seat_events; pub mod org_kde_kwin_server_decoration; diff --git a/src/ifs/jay_compositor.rs b/src/ifs/jay_compositor.rs index 01dc6b59..8a3cf001 100644 --- a/src/ifs/jay_compositor.rs +++ b/src/ifs/jay_compositor.rs @@ -4,14 +4,15 @@ use { client::{Client, ClientError}, globals::{Global, GlobalName}, ifs::{ - jay_idle::JayIdle, jay_log_file::JayLogFile, jay_screenshot::JayScreenshot, - jay_seat_events::JaySeatEvents, + jay_idle::JayIdle, jay_log_file::JayLogFile, jay_output::JayOutput, + jay_screenshot::JayScreenshot, jay_seat_events::JaySeatEvents, }, leaks::Tracker, object::Object, screenshoter::take_screenshot, utils::{ buffd::{MsgParser, MsgParserError}, + clonecell::CloneCell, errorfmt::ErrorFmt, }, wire::{jay_compositor::*, JayCompositorId}, @@ -225,6 +226,26 @@ impl JayCompositor { .insert((self.client.id, req.id), se); Ok(()) } + + fn get_output(&self, parser: MsgParser<'_, '_>) -> Result<(), JayCompositorError> { + let req: GetOutput = self.client.parse(self, parser)?; + let output = self.client.lookup(req.output)?; + let jo = Rc::new(JayOutput { + id: req.id, + client: self.client.clone(), + output: CloneCell::new(output.global.node.get()), + tracker: Default::default(), + }); + track!(self.client, jo); + self.client.add_client_obj(&jo)?; + if let Some(node) = jo.output.get() { + node.jay_outputs.set((self.client.id, req.id), jo.clone()); + jo.send_linear_id(); + } else { + jo.send_destroyed(); + } + Ok(()) + } } object_base! { @@ -241,11 +262,12 @@ object_base! { UNLOCK => unlock, GET_SEATS => get_seats, SEAT_EVENTS => seat_events, + GET_OUTPUT => get_output, } impl Object for JayCompositor { fn num_requests(&self) -> u32 { - SEAT_EVENTS + 1 + GET_OUTPUT + 1 } } diff --git a/src/ifs/jay_output.rs b/src/ifs/jay_output.rs new file mode 100644 index 00000000..088d246e --- /dev/null +++ b/src/ifs/jay_output.rs @@ -0,0 +1,78 @@ +use { + crate::{ + client::{Client, ClientError}, + leaks::Tracker, + object::Object, + tree::OutputNode, + utils::{ + buffd::{MsgParser, MsgParserError}, + clonecell::CloneCell, + }, + wire::{jay_output::*, JayOutputId}, + }, + std::rc::Rc, + thiserror::Error, +}; + +pub struct JayOutput { + pub id: JayOutputId, + pub client: Rc, + pub output: CloneCell>>, + pub tracker: Tracker, +} + +impl JayOutput { + pub fn send_destroyed(&self) { + self.client.event(Destroyed { self_id: self.id }); + } + + pub fn send_linear_id(&self) { + if let Some(output) = self.output.get() { + self.client.event(LinearId { + self_id: self.id, + linear_id: output.id.raw(), + }); + } + } + + fn destroy(&self, parser: MsgParser<'_, '_>) -> Result<(), JayOutputError> { + let _req: Destroy = self.client.parse(self, parser)?; + self.remove_from_node(); + self.client.remove_obj(self)?; + Ok(()) + } + + fn remove_from_node(&self) { + if let Some(output) = self.output.get() { + output.jay_outputs.remove(&(self.client.id, self.id)); + } + } +} + +object_base! { + JayOutput; + + DESTROY => destroy, +} + +impl Object for JayOutput { + fn num_requests(&self) -> u32 { + 1 + } + + fn break_loops(&self) { + self.remove_from_node(); + } +} + +dedicated_add_obj!(JayOutput, JayOutputId, jay_outputs); + +#[derive(Debug, Error)] +pub enum JayOutputError { + #[error("Parsing failed")] + MsgParserError(Box), + #[error(transparent)] + ClientError(Box), +} +efrom!(JayOutputError, MsgParserError); +efrom!(JayOutputError, ClientError); diff --git a/src/tasks/connector.rs b/src/tasks/connector.rs index b1c32bc4..c2a235a6 100644 --- a/src/tasks/connector.rs +++ b/src/tasks/connector.rs @@ -124,6 +124,7 @@ impl ConnectorHandler { lock_surface: Default::default(), preferred_scale: Cell::new(Fixed::from_int(1)), hardware_cursor: Default::default(), + jay_outputs: Default::default(), }); self.state.add_output_scale(on.preferred_scale.get()); let mode = info.initial_mode; @@ -209,6 +210,10 @@ impl ConnectorHandler { config.connector_disconnected(self.id); } global.node.set(None); + for (_, jo) in on.jay_outputs.lock().drain() { + jo.send_destroyed(); + jo.output.take(); + } global.destroyed.set(true); self.state.root.outputs.remove(&self.id); self.data.connected.set(false); diff --git a/src/tree/output.rs b/src/tree/output.rs index 6bcbcd88..bb68f611 100644 --- a/src/tree/output.rs +++ b/src/tree/output.rs @@ -1,9 +1,11 @@ use { crate::{ backend::{HardwareCursor, KeyState, Mode}, + client::ClientId, cursor::KnownCursor, fixed::Fixed, ifs::{ + jay_output::JayOutput, wl_output::WlOutputGlobal, wl_seat::{ collect_kb_foci2, wl_pointer::PendingScroll, NodeSeatState, SeatId, WlSeatGlobal, @@ -26,6 +28,7 @@ use { clonecell::CloneCell, copyhashmap::CopyHashMap, errorfmt::ErrorFmt, linkedlist::LinkedList, scroller::Scroller, }, + wire::JayOutputId, }, smallvec::SmallVec, std::{ @@ -40,6 +43,7 @@ tree_id!(OutputNodeId); pub struct OutputNode { pub id: OutputNodeId, pub global: Rc, + pub jay_outputs: CopyHashMap<(ClientId, JayOutputId), Rc>, pub workspaces: LinkedList>, pub workspace: CloneCell>>, pub seat_state: NodeSeatState, @@ -65,6 +69,7 @@ impl OutputNode { } self.render_data.borrow_mut().titles.clear(); self.lock_surface.take(); + self.jay_outputs.clear(); } pub fn on_spaces_changed(self: &Rc) { diff --git a/wire/jay_compositor.txt b/wire/jay_compositor.txt index 36d913a5..16d7e600 100644 --- a/wire/jay_compositor.txt +++ b/wire/jay_compositor.txt @@ -43,6 +43,11 @@ msg seat_events = 10 { id: id(jay_seat_events), } +msg get_output = 11 { + id: id(jay_output), + output: id(wl_output), +} + # events msg client_id = 0 { diff --git a/wire/jay_output.txt b/wire/jay_output.txt new file mode 100644 index 00000000..2d098c8e --- /dev/null +++ b/wire/jay_output.txt @@ -0,0 +1,15 @@ +# requests + +msg destroy = 0 { + +} + +# events + +msg linear_id = 0 { + linear_id: u32, +} + +msg destroyed = 2 { + +}