diff --git a/src/client/objects.rs b/src/client/objects.rs index 28bb46a1..be1f5465 100644 --- a/src/client/objects.rs +++ b/src/client/objects.rs @@ -19,7 +19,6 @@ use { zwp_primary_selection_source_v1::ZwpPrimarySelectionSourceV1, }, jay_output::JayOutput, - jay_screencast::JayScreencast, jay_toplevel::JayToplevel, jay_workspace::JayWorkspace, wl_buffer::WlBuffer, @@ -49,9 +48,9 @@ use { wire::{ ExtDataControlSourceV1Id, ExtForeignToplevelHandleV1Id, ExtImageCaptureSourceV1Id, ExtImageCopyCaptureSessionV1Id, ExtWorkspaceGroupHandleV1Id, JayHeadErrorV1Id, - JayOutputId, JayScreencastId, JayToplevelId, JayWorkspaceId, WlBufferId, - WlDataSourceId, WlOutputId, WlPointerId, WlRegionId, WlRegistryId, WlSeatId, - WlSurfaceId, WpDrmLeaseConnectorV1Id, WpImageDescriptionReferenceV1Id, + JayOutputId, JayToplevelId, JayWorkspaceId, WlBufferId, WlDataSourceId, WlOutputId, + WlPointerId, WlRegionId, WlRegistryId, WlSeatId, WlSurfaceId, + WpDrmLeaseConnectorV1Id, WpImageDescriptionReferenceV1Id, WpImageDescriptionV1Id, WpLinuxDrmSyncobjTimelineV1Id, XdgPopupId, XdgPositionerId, XdgSurfaceId, XdgToplevelId, XdgWmBaseId, ZwlrDataControlSourceV1Id, ZwlrOutputHeadV1Id, ZwlrOutputModeV1Id, ZwpPrimarySelectionSourceV1Id, @@ -80,7 +79,6 @@ pub struct Objects { pub pointers: CopyHashMap>, pub xdg_wm_bases: CopyHashMap>, pub seats: CopyHashMap>, - pub screencasts: CopyHashMap>, pub timelines: CopyHashMap>, pub zwlr_data_sources: CopyHashMap>, pub zwlr_output_heads: CopyHashMap>, @@ -127,7 +125,6 @@ impl Objects { pointers: Default::default(), xdg_wm_bases: Default::default(), seats: Default::default(), - screencasts: Default::default(), timelines: Default::default(), zwlr_data_sources: Default::default(), zwlr_output_heads: Default::default(), @@ -176,7 +173,6 @@ impl Objects { self.xdg_wm_bases.clear(); self.seats.clear(); self.pointers.clear(); - self.screencasts.clear(); self.timelines.clear(); self.zwlr_data_sources.clear(); self.jay_toplevels.clear(); diff --git a/src/compositor.rs b/src/compositor.rs index 141a206f..ae030f6e 100644 --- a/src/compositor.rs +++ b/src/compositor.rs @@ -35,7 +35,6 @@ use { head_management::{ HeadManagers, HeadState, jay_head_manager_session_v1::handle_jay_head_manager_done, }, - jay_screencast::{perform_screencast_realloc, perform_toplevel_screencasts}, wl_output::{BlendSpace, OutputId, PersistentOutputState, WlOutputGlobal}, wl_seat::{handle_position_hint_requests, handle_warp_mouse_to_focus}, wl_surface::{ @@ -247,8 +246,6 @@ fn start_compositor2( pending_output_render_data: Default::default(), pending_float_layout: Default::default(), pending_input_popup_positioning: Default::default(), - pending_toplevel_screencasts: Default::default(), - pending_screencast_reallocs_or_reconfigures: Default::default(), pending_placeholder_render_textures: Default::default(), pending_container_tab_render_textures: Default::default(), dbus: Dbus::new(&engine, &ring, &run_toplevel), @@ -514,16 +511,6 @@ fn start_global_event_handlers(state: &Rc) -> Vec> { Phase::PostLayout, input_popup_positioning(state.clone()), ), - eng.spawn2( - "toplevel screencast present", - Phase::Present, - perform_toplevel_screencasts(state.clone()), - ), - eng.spawn2( - "screencast realloc", - Phase::PostLayout, - perform_screencast_realloc(state.clone()), - ), eng.spawn2( "visualize damage", Phase::PostLayout, @@ -759,7 +746,6 @@ fn create_dummy_output(state: &Rc) { lock_surface: Default::default(), hardware_cursor: Default::default(), update_render_data_scheduled: Cell::new(false), - screencasts: Default::default(), hardware_cursor_needs_render: Cell::new(false), screencopies: Default::default(), title_visible: Cell::new(false), diff --git a/src/ifs.rs b/src/ifs.rs index 85993cf3..e70a1555 100644 --- a/src/ifs.rs +++ b/src/ifs.rs @@ -28,7 +28,6 @@ pub mod jay_popup_ext_manager_v1; pub mod jay_randr; pub mod jay_reexec; pub mod jay_render_ctx; -pub mod jay_screencast; pub mod jay_screenshot; pub mod jay_seat_events; pub mod jay_select_toplevel; diff --git a/src/ifs/jay_compositor.rs b/src/ifs/jay_compositor.rs index 5084abed..cf86a67a 100644 --- a/src/ifs/jay_compositor.rs +++ b/src/ifs/jay_compositor.rs @@ -15,7 +15,6 @@ use { jay_randr::JayRandr, jay_reexec::JayReexec, jay_render_ctx::JayRenderCtx, - jay_screencast::JayScreencast, jay_screenshot::JayScreenshot, jay_seat_events::JaySeatEvents, jay_select_toplevel::{JaySelectToplevel, JayToplevelSelector}, @@ -95,7 +94,6 @@ pub struct Cap; impl Cap { pub const NONE: u16 = 0; - pub const WINDOW_CAPTURE: u16 = 1; pub const SELECT_WORKSPACE: u16 = 2; } @@ -103,7 +101,7 @@ impl JayCompositor { fn send_capabilities(&self) { self.client.event(Capabilities { self_id: self.id, - cap: &[Cap::NONE, Cap::WINDOW_CAPTURE, Cap::SELECT_WORKSPACE], + cap: &[Cap::NONE, Cap::SELECT_WORKSPACE], }); } @@ -332,13 +330,6 @@ impl JayCompositorRequestHandler for JayCompositor { Ok(()) } - fn create_screencast(&self, req: CreateScreencast, _slf: &Rc) -> Result<(), Self::Error> { - let sc = Rc::new_cyclic(|slf| JayScreencast::new(req.id, &self.client, slf, self.version)); - track!(self.client, sc); - self.client.add_client_obj(&sc)?; - Ok(()) - } - fn get_randr(&self, req: GetRandr, _slf: &Rc) -> Result<(), Self::Error> { let sc = Rc::new(JayRandr::new(req.id, &self.client, self.version)); track!(self.client, sc); diff --git a/src/ifs/jay_screencast.rs b/src/ifs/jay_screencast.rs deleted file mode 100644 index 9ec24eb1..00000000 --- a/src/ifs/jay_screencast.rs +++ /dev/null @@ -1,796 +0,0 @@ -use { - crate::{ - allocator::{AllocatorError, BO_USE_LINEAR, BO_USE_RENDERING, BufferObject}, - client::{Client, ClientError}, - cmm::cmm_description::ColorDescription, - format::XRGB8888, - gfx_api::{ - AcquireSync, BufferResv, GfxContext, GfxError, GfxFramebuffer, GfxTexture, ReleaseSync, - }, - ifs::{jay_output::JayOutput, jay_toplevel::JayToplevel, wl_buffer::WlBufferStorage}, - leaks::Tracker, - object::{Object, Version}, - scale::Scale, - state::State, - tree::{ - LatchListener, OutputNode, ToplevelNode, Transform, WorkspaceNode, WorkspaceNodeId, - }, - utils::{ - clonecell::{CloneCell, UnsafeCellCloneSafe}, - errorfmt::ErrorFmt, - event_listener::EventListener, - numcell::NumCell, - option_ext::OptionExt, - }, - video::{INVALID_MODIFIER, LINEAR_MODIFIER, dmabuf::DmaBuf}, - wire::{JayScreencastId, jay_screencast::*}, - }, - ahash::AHashSet, - std::{ - cell::{Cell, RefCell}, - ops::DerefMut, - rc::{Rc, Weak}, - }, - thiserror::Error, -}; - -pub async fn perform_toplevel_screencasts(state: Rc) { - loop { - let screencast = state.pending_toplevel_screencasts.pop().await; - screencast.perform_toplevel_screencast(); - } -} - -pub async fn perform_screencast_realloc(state: Rc) { - loop { - let screencast = state - .pending_screencast_reallocs_or_reconfigures - .pop() - .await; - screencast.realloc_or_reconfigure_scheduled.set(false); - match state.render_ctx.get() { - None => screencast.do_destroy(), - Some(ctx) => { - if let Err(e) = screencast.realloc(&ctx) { - screencast.client.error(e); - } - } - } - } -} - -pub const CLIENT_BUFFERS_SINCE: Version = Version(7); - -pub struct JayScreencast { - pub id: JayScreencastId, - pub version: Version, - pub client: Rc, - pub tracker: Tracker, - config_serial: NumCell, - config_acked: Cell, - buffers_serial: NumCell, - buffers_acked: Cell, - buffers: RefCell>, - missed_frame: Cell, - target: CloneCell>, - destroyed: Cell, - running: Cell, - show_all: Cell, - show_workspaces: RefCell>, - linear: Cell, - pending: Pending, - need_realloc_or_reconfigure: Cell, - realloc_or_reconfigure_scheduled: Cell, - latch_listener: EventListener, -} - -#[derive(Clone)] -enum Target { - Output(Rc), - Toplevel(Rc), -} - -impl LatchListener for JayScreencast { - fn after_latch(self: Rc, _on: &OutputNode, _tearing: bool) { - self.schedule_toplevel_screencast(); - } -} - -unsafe impl UnsafeCellCloneSafe for Target {} - -enum PendingTarget { - Output(Rc), - Toplevel(Rc), -} - -#[derive(Default)] -struct Pending { - linear: Cell>, - running: Cell>, - target: Cell>>, - show_all: Cell>, - show_workspaces: RefCell>>, - clear_buffers: Cell, - buffers: RefCell>>, -} - -struct ScreencastBuffer { - _bo: Option>, - dmabuf: Option, - fb: Rc, - free: bool, -} - -impl JayScreencast { - pub fn shows_ws(&self, ws: &WorkspaceNode) -> bool { - if self.show_all.get() { - return true; - } - for &id in &*self.show_workspaces.borrow() { - if id == ws.id { - return true; - } - } - false - } - - pub fn new( - id: JayScreencastId, - client: &Rc, - slf: &Weak, - version: Version, - ) -> Self { - Self { - id, - version, - client: client.clone(), - tracker: Default::default(), - config_serial: Default::default(), - config_acked: Cell::new(true), - buffers_serial: Default::default(), - buffers_acked: Cell::new(true), - buffers: Default::default(), - missed_frame: Cell::new(false), - target: Default::default(), - destroyed: Cell::new(false), - running: Cell::new(false), - show_all: Cell::new(false), - show_workspaces: Default::default(), - linear: Cell::new(false), - pending: Default::default(), - need_realloc_or_reconfigure: Cell::new(false), - realloc_or_reconfigure_scheduled: Cell::new(false), - latch_listener: EventListener::new(slf.clone()), - } - } - - fn schedule_toplevel_screencast(self: &Rc) { - if !self.running.get() { - return; - } - self.client - .state - .pending_toplevel_screencasts - .push(self.clone()); - } - - fn perform_toplevel_screencast(&self) { - if self.destroyed.get() || !self.running.get() { - return; - } - let Some(target) = self.target.get() else { - return; - }; - let Target::Toplevel(tl) = target else { - log::warn!("Tried to perform window screencast for output screencast"); - return; - }; - let scale = match tl.tl_data().workspace.get() { - None => Scale::default(), - Some(w) => w.output.get().global.persistent.scale.get(), - }; - let mut buffer = self.buffers.borrow_mut(); - for (idx, buffer) in buffer.deref_mut().iter_mut().enumerate() { - if buffer.free { - let res = buffer.fb.render_node( - AcquireSync::Implicit, - ReleaseSync::Implicit, - self.client.state.color_manager.srgb_gamma22(), - &*tl, - &self.client.state, - Some(tl.node_absolute_position()), - scale, - true, - true, - false, - false, - Transform::None, - None, - self.client.state.color_manager.srgb_linear(), - ); - match res { - Ok(_) => { - self.client.event(Ready { - self_id: self.id, - idx: idx as _, - }); - buffer.free = false; - return; - } - Err(e) => { - log::error!("Could not perform window copy: {}", ErrorFmt(e)); - break; - } - } - } - } - self.missed_frame.set(true); - self.client.event(MissedFrame { self_id: self.id }) - } - - fn send_buffers(&self) { - self.buffers_acked.set(false); - let serial = self.buffers_serial.fetch_add(1) + 1; - let buffers = self.buffers.borrow_mut(); - for buffer in buffers.iter() { - let Some(dmabuf) = &buffer.dmabuf else { - log::error!("Trying to send buffers but buffers are client allocated"); - self.do_destroy(); - return; - }; - for plane in &dmabuf.planes { - self.client.event(Plane { - self_id: self.id, - fd: plane.fd.clone(), - offset: plane.offset, - stride: plane.stride, - }); - } - self.client.event(Buffer { - self_id: self.id, - format: dmabuf.format.drm, - modifier: dmabuf.modifier, - width: dmabuf.width, - height: dmabuf.height, - }); - } - self.client.event(BuffersDone { - self_id: self.id, - serial, - }); - } - - fn send_config(&self) { - self.need_realloc_or_reconfigure.set(false); - self.config_acked.set(false); - let serial = self.config_serial.fetch_add(1) + 1; - if let Some(target) = self.target.get() { - let (width, height) = target_size(Some(&target)); - if self.version >= CLIENT_BUFFERS_SINCE { - self.client.event(ConfigSize { - self_id: self.id, - width, - height, - }); - } - if let Target::Output(output) = target { - self.client.event(ConfigOutput { - self_id: self.id, - linear_id: output.id.raw(), - }); - } - } - self.client.event(ConfigAllowAllWorkspaces { - self_id: self.id, - allow_all: self.show_all.get() as _, - }); - for &ws in self.show_workspaces.borrow_mut().iter() { - self.client.event(ConfigAllowWorkspace { - self_id: self.id, - linear_id: ws.raw(), - }); - } - self.client.event(ConfigUseLinearBuffers { - self_id: self.id, - use_linear: self.linear.get() as _, - }); - self.client.event(ConfigRunning { - self_id: self.id, - running: self.running.get() as _, - }); - self.client.event(ConfigDone { - self_id: self.id, - serial, - }); - } - - pub fn copy_texture( - &self, - on: &OutputNode, - texture: &Rc, - cd: &Rc, - resv: Option<&Rc>, - acquire_sync: &AcquireSync, - release_sync: ReleaseSync, - render_hardware_cursors: bool, - x_off: i32, - y_off: i32, - size: Option<(i32, i32)>, - ) { - if !self.running.get() { - return; - } - if !self.show_all.get() { - let ws = match on.workspace.get() { - Some(ws) => ws, - _ => return, - }; - if !self.show_workspaces.borrow_mut().contains(&ws.id) { - return; - } - } - let mut buffer = self.buffers.borrow_mut(); - for (idx, buffer) in buffer.deref_mut().iter_mut().enumerate() { - if buffer.free { - let res = self.client.state.perform_screencopy( - texture, - resv, - acquire_sync, - release_sync, - cd, - &buffer.fb, - AcquireSync::Implicit, - ReleaseSync::Implicit, - Transform::None, - self.client.state.color_manager.srgb_gamma22(), - on.global.pos.get(), - render_hardware_cursors, - x_off, - y_off, - size, - on.global.persistent.transform.get(), - on.global.persistent.scale.get(), - ); - match res { - Ok(_) => { - self.client.event(Ready { - self_id: self.id, - idx: idx as _, - }); - buffer.free = false; - return; - } - Err(e) => { - log::error!("Could not perform screencopy: {}", ErrorFmt(e)); - break; - } - } - } - } - self.missed_frame.set(true); - self.client.event(MissedFrame { self_id: self.id }) - } - - fn detach(&self) { - self.latch_listener.detach(); - if let Some(target) = self.target.take() { - match target { - Target::Output(output) => { - output.remove_screencast(self); - } - Target::Toplevel(tl) => { - let data = tl.tl_data(); - data.jay_screencasts.remove(&(self.client.id, self.id)); - } - } - } - } - - pub fn do_destroy(&self) { - self.detach(); - self.buffers.borrow_mut().clear(); - self.destroyed.set(true); - self.client.event(Destroyed { self_id: self.id }); - } - - pub fn schedule_realloc_or_reconfigure(self: &Rc) { - self.need_realloc_or_reconfigure.set(true); - if !self.realloc_or_reconfigure_scheduled.replace(true) { - self.client - .state - .pending_screencast_reallocs_or_reconfigures - .push(self.clone()); - } - } - - fn realloc(&self, ctx: &Rc) -> Result<(), JayScreencastError> { - if self.destroyed.get() { - return Ok(()); - } - if self.version < CLIENT_BUFFERS_SINCE { - if self.buffers_acked.get() { - return self.do_realloc(ctx); - } - } else { - if self.config_acked.get() { - self.send_config(); - } - } - Ok(()) - } - - fn do_realloc(&self, ctx: &Rc) -> Result<(), JayScreencastError> { - self.need_realloc_or_reconfigure.set(false); - let mut buffers = vec![]; - let formats = ctx.formats(); - let format = match formats.get(&XRGB8888.drm) { - Some(f) => f, - _ => return Err(JayScreencastError::XRGB8888), - }; - if let Some(target) = self.target.get() { - let (width, height) = target_size(Some(&target)); - let num = 3; - for _ in 0..num { - if width == 0 || height == 0 { - continue; - } - let mut usage = BO_USE_RENDERING; - let modifiers = match self.linear.get() { - true if format.write_modifiers.contains_key(&LINEAR_MODIFIER) => { - vec![LINEAR_MODIFIER] - } - true if format.write_modifiers.contains_key(&INVALID_MODIFIER) => { - usage |= BO_USE_LINEAR; - vec![INVALID_MODIFIER] - } - true => return Err(JayScreencastError::Modifier), - false if format.write_modifiers.is_empty() => { - return Err(JayScreencastError::XRGB8888Writing); - } - false => format.write_modifiers.keys().copied().collect(), - }; - let buffer = ctx.allocator().create_bo( - &self.client.state.dma_buf_ids, - width, - height, - format.format, - &modifiers, - usage, - )?; - let fb = ctx.clone().dmabuf_img(buffer.dmabuf())?.to_framebuffer()?; - buffers.push(ScreencastBuffer { - dmabuf: Some(buffer.dmabuf().clone()), - _bo: Some(buffer), - fb, - free: true, - }); - } - } - *self.buffers.borrow_mut() = buffers; - self.send_buffers(); - self.damage(); - Ok(()) - } - - fn damage(&self) { - if let Some(target) = self.target.get() { - let rect = match target { - Target::Output(o) => o.global.pos.get(), - Target::Toplevel(t) => { - if !t.node_visible() { - return; - } - t.node_absolute_position() - } - }; - self.client.state.damage(rect); - } - } - - pub fn update_latch_listener(&self) { - let Some(Target::Toplevel(tl)) = self.target.get() else { - return; - }; - let data = tl.tl_data(); - if data.visible.get() { - self.latch_listener.attach(&data.output().latch_event); - } else { - self.latch_listener.detach(); - } - } -} - -impl JayScreencastRequestHandler for JayScreencast { - type Error = JayScreencastError; - - fn destroy(&self, _req: Destroy, _slf: &Rc) -> Result<(), Self::Error> { - self.detach(); - self.client.remove_obj(self)?; - Ok(()) - } - - fn set_output(&self, req: SetOutput, _slf: &Rc) -> Result<(), Self::Error> { - let output = if req.output.is_some() { - Some(PendingTarget::Output(self.client.lookup(req.output)?)) - } else { - None - }; - if self.destroyed.get() { - return Ok(()); - } - self.pending.target.set(Some(output)); - Ok(()) - } - - fn set_allow_all_workspaces( - &self, - req: SetAllowAllWorkspaces, - _slf: &Rc, - ) -> Result<(), Self::Error> { - if self.destroyed.get() { - return Ok(()); - } - self.pending.show_all.set(Some(req.allow_all != 0)); - Ok(()) - } - - fn allow_workspace(&self, req: AllowWorkspace, _slf: &Rc) -> Result<(), Self::Error> { - let ws = self.client.lookup(req.workspace)?; - if self.destroyed.get() { - return Ok(()); - } - let mut sw = self.pending.show_workspaces.borrow_mut(); - let sw = sw.get_or_insert_default_ext(); - if let Some(ws) = ws.workspace.get() { - sw.insert(ws.id); - } - Ok(()) - } - - fn touch_allowed_workspaces( - &self, - _req: TouchAllowedWorkspaces, - _slf: &Rc, - ) -> Result<(), Self::Error> { - if self.destroyed.get() { - return Ok(()); - } - self.pending - .show_workspaces - .borrow_mut() - .get_or_insert_default_ext(); - Ok(()) - } - - fn set_use_linear_buffers( - &self, - req: SetUseLinearBuffers, - _slf: &Rc, - ) -> Result<(), Self::Error> { - if self.destroyed.get() { - return Ok(()); - } - self.pending.linear.set(Some(req.use_linear != 0)); - Ok(()) - } - - fn set_running(&self, req: SetRunning, _slf: &Rc) -> Result<(), Self::Error> { - if self.destroyed.get() { - return Ok(()); - } - self.pending.running.set(Some(req.running != 0)); - Ok(()) - } - - fn configure(&self, _req: Configure, slf: &Rc) -> Result<(), Self::Error> { - if self.destroyed.get() { - return Ok(()); - } - - let mut need_realloc_or_reconfigure = false; - - if let Some(target) = self.pending.target.take() { - self.detach(); - let mut new_target = None; - if let Some(new) = target { - match new { - PendingTarget::Output(o) => { - let Some(o) = o.output.node() else { - self.do_destroy(); - return Ok(()); - }; - o.add_screencast(slf); - new_target = Some(Target::Output(o)); - } - PendingTarget::Toplevel(t) => { - if t.destroyed.get() { - self.do_destroy(); - return Ok(()); - } - let t = t.toplevel.clone(); - let data = t.tl_data(); - data.jay_screencasts - .set((self.client.id, self.id), slf.clone()); - if data.visible.get() { - self.latch_listener.attach(&data.output().latch_event); - } - new_target = Some(Target::Toplevel(t)); - } - } - } - if target_size(new_target.as_ref()) != target_size(self.target.get().as_ref()) { - need_realloc_or_reconfigure = true; - } - self.target.set(new_target); - } - if let Some(linear) = self.pending.linear.take() { - if self.linear.replace(linear) != linear { - need_realloc_or_reconfigure = true; - } - } - if self.pending.clear_buffers.take() { - self.buffers.borrow_mut().clear(); - } - for buffer in self.pending.buffers.borrow_mut().drain(..) { - self.buffers.borrow_mut().push(ScreencastBuffer { - _bo: None, - dmabuf: None, - fb: buffer, - free: true, - }); - } - let mut capture_rules_changed = false; - if let Some(show_all) = self.pending.show_all.take() { - self.show_all.set(show_all); - capture_rules_changed = true; - } - if let Some(new_workspaces) = self.pending.show_workspaces.borrow_mut().take() { - *self.show_workspaces.borrow_mut() = new_workspaces; - capture_rules_changed = true; - } - if let Some(running) = self.pending.running.take() { - self.running.set(running); - } - - if need_realloc_or_reconfigure { - slf.schedule_realloc_or_reconfigure(); - } - - if capture_rules_changed && let Some(Target::Output(o)) = self.target.get() { - o.screencast_changed(); - } - - if self.running.get() { - self.damage(); - } - - Ok(()) - } - - fn ack_buffers(&self, req: AckBuffers, slf: &Rc) -> Result<(), Self::Error> { - if self.destroyed.get() { - return Ok(()); - } - if req.serial == self.buffers_serial.get() { - self.buffers_acked.set(true); - if self.need_realloc_or_reconfigure.get() { - slf.schedule_realloc_or_reconfigure(); - } - } - Ok(()) - } - - fn ack_config(&self, req: AckConfig, slf: &Rc) -> Result<(), Self::Error> { - if self.destroyed.get() { - return Ok(()); - } - if req.serial == self.config_serial.get() { - self.config_acked.set(true); - if self.need_realloc_or_reconfigure.get() { - slf.schedule_realloc_or_reconfigure(); - } - } - Ok(()) - } - - fn release_buffer(&self, req: ReleaseBuffer, _slf: &Rc) -> Result<(), Self::Error> { - if self.destroyed.get() || !self.buffers_acked.get() { - return Ok(()); - } - let idx = req.idx as usize; - if idx >= self.buffers.borrow_mut().len() { - return Err(JayScreencastError::OutOfBounds(req.idx)); - } - self.buffers.borrow_mut()[idx].free = true; - if self.missed_frame.replace(false) { - self.damage(); - } - Ok(()) - } - - fn set_toplevel(&self, req: SetToplevel, _slf: &Rc) -> Result<(), Self::Error> { - let toplevel = if req.id.is_some() { - Some(PendingTarget::Toplevel(self.client.lookup(req.id)?)) - } else { - None - }; - if self.destroyed.get() { - return Ok(()); - } - self.pending.target.set(Some(toplevel)); - Ok(()) - } - - fn clear_buffers(&self, _req: ClearBuffers, _slf: &Rc) -> Result<(), Self::Error> { - if self.destroyed.get() { - return Ok(()); - } - self.pending.clear_buffers.set(true); - Ok(()) - } - - fn add_buffer(&self, req: AddBuffer, _slf: &Rc) -> Result<(), Self::Error> { - if self.destroyed.get() { - return Ok(()); - } - let buffer = self.client.lookup(req.buffer)?; - if let Some(WlBufferStorage::Dmabuf { img, .. }) = &*buffer.storage.borrow() { - match img.clone().to_framebuffer() { - Ok(fb) => self.pending.buffers.borrow_mut().push(fb), - Err(e) => { - log::warn!( - "Could not turn GfxImage into GfxFramebuffer: {}", - ErrorFmt(e) - ); - self.do_destroy(); - } - } - return Ok(()); - } - Err(JayScreencastError::NotDmabuf) - } -} - -object_base! { - self = JayScreencast; - version = self.version; -} - -impl Object for JayScreencast { - fn break_loops(&self) { - self.detach(); - } -} - -dedicated_add_obj!(JayScreencast, JayScreencastId, screencasts); - -#[derive(Debug, Error)] -pub enum JayScreencastError { - #[error(transparent)] - ClientError(Box), - #[error("Buffer index {0} is out-of-bounds")] - OutOfBounds(u32), - #[error(transparent)] - AllocatorError(#[from] AllocatorError), - #[error(transparent)] - GfxError(#[from] GfxError), - #[error("Render context does not support XRGB8888 format")] - XRGB8888, - #[error("Render context does not support XRGB8888 format for rendering")] - XRGB8888Writing, - #[error("Render context supports neither linear or invalid modifier")] - Modifier, - #[error("Buffer is not a dmabuf")] - NotDmabuf, -} -efrom!(JayScreencastError, ClientError); - -fn target_size(target: Option<&Target>) -> (i32, i32) { - if let Some(target) = target { - return match target { - Target::Output(o) => o.global.pixel_size(), - Target::Toplevel(t) => t.tl_data().desired_pixel_size(), - }; - } - (0, 0) -} diff --git a/src/ifs/wl_surface.rs b/src/ifs/wl_surface.rs index 547b7e2a..2998aff6 100644 --- a/src/ifs/wl_surface.rs +++ b/src/ifs/wl_surface.rs @@ -164,9 +164,6 @@ pub struct SurfaceSendPreferredScaleVisitor; impl SurfaceSendPreferredScaleVisitor { fn schedule_realloc(&self, tl: &impl ToplevelNode) { let data = tl.tl_data(); - for sc in data.jay_screencasts.lock().values() { - sc.schedule_realloc_or_reconfigure(); - } for sc in data.ext_copy_sessions.lock().values() { sc.buffer_size_changed(); } diff --git a/src/state.rs b/src/state.rs index 047fdb9f..ee66a5ab 100644 --- a/src/state.rs +++ b/src/state.rs @@ -68,7 +68,6 @@ use { x_data_device::XTransferDeviceIds, }, jay_render_ctx::JayRenderCtx, - jay_screencast::JayScreencast, jay_seat_events::JaySeatEvents, jay_workspace_watcher::JayWorkspaceWatcher, wl_buffer::WlBuffer, @@ -294,8 +293,6 @@ pub struct State { pub pending_output_render_data: AsyncQueue>, pub pending_float_layout: AsyncQueue>, pub pending_input_popup_positioning: AsyncQueue>, - pub pending_toplevel_screencasts: AsyncQueue>, - pub pending_screencast_reallocs_or_reconfigures: AsyncQueue>, pub pending_placeholder_render_textures: AsyncQueue>, pub pending_container_tab_render_textures: AsyncQueue>, pub dbus: Dbus, @@ -854,18 +851,11 @@ impl State { watcher.send_render_ctx(ctx.clone()); } - let mut scs = vec![]; for client in self.clients.clients.borrow_mut().values() { - for sc in client.data.objects.screencasts.lock().values() { - scs.push(sc.clone()); - } for sc in client.data.objects.ext_copy_sessions.lock().values() { sc.stop(); } } - for sc in scs { - sc.do_destroy(); - } self.expose_new_singletons(); } @@ -1234,8 +1224,6 @@ impl State { self.pending_output_render_data.clear(); self.pending_float_layout.clear(); self.pending_input_popup_positioning.clear(); - self.pending_toplevel_screencasts.clear(); - self.pending_screencast_reallocs_or_reconfigures.clear(); self.pending_placeholder_render_textures.clear(); self.pending_container_tab_render_textures.clear(); self.animations.clear(); diff --git a/src/tasks/connector.rs b/src/tasks/connector.rs index 16362e44..9e84a394 100644 --- a/src/tasks/connector.rs +++ b/src/tasks/connector.rs @@ -218,7 +218,6 @@ impl ConnectorHandler { lock_surface: Default::default(), hardware_cursor: Default::default(), jay_outputs: Default::default(), - screencasts: Default::default(), update_render_data_scheduled: Cell::new(false), hardware_cursor_needs_render: Cell::new(false), screencopies: Default::default(), @@ -341,10 +340,6 @@ impl ConnectorHandler { for jo in on.jay_outputs.lock().drain_values() { jo.send_destroyed(); } - let screencasts: Vec<_> = on.screencasts.lock().values().cloned().collect(); - for sc in screencasts { - sc.do_destroy(); - } for sc in on.screencopies.lock().drain_values() { sc.send_failed(); } diff --git a/src/tree/output.rs b/src/tree/output.rs index d21b3e5e..7426c803 100644 --- a/src/tree/output.rs +++ b/src/tree/output.rs @@ -12,7 +12,6 @@ use { ifs::{ ext_image_copy::ext_image_copy_capture_session_v1::ExtImageCopyCaptureSessionV1, jay_output::JayOutput, - jay_screencast::JayScreencast, wl_buffer::WlBufferStorage, wl_output::{BlendSpace, WlOutputGlobal}, wl_seat::{ @@ -63,7 +62,7 @@ use { scroller::Scroller, }, wire::{ - ExtImageCopyCaptureSessionV1Id, JayOutputId, JayScreencastId, ZwlrScreencopyFrameV1Id, + ExtImageCopyCaptureSessionV1Id, JayOutputId, ZwlrScreencopyFrameV1Id, }, }, ahash::AHashMap, @@ -109,7 +108,6 @@ pub struct OutputNode { pub hardware_cursor: CloneCell>>, pub hardware_cursor_needs_render: Cell, pub update_render_data_scheduled: Cell, - pub screencasts: CopyHashMap<(ClientId, JayScreencastId), Rc>, pub screencopies: CopyHashMap<(ClientId, ZwlrScreencopyFrameV1Id), Rc>, pub title_visible: Cell, pub schedule: Rc, @@ -271,16 +269,6 @@ impl OutputNode { } } - pub fn add_screencast(&self, sc: &Rc) { - self.screencasts.set((sc.client.id, sc.id), sc.clone()); - self.screencast_changed(); - } - - pub fn remove_screencast(&self, sc: &JayScreencast) { - self.screencasts.remove(&(sc.client.id, sc.id)); - self.screencast_changed(); - } - pub fn screencast_changed(&self) { for ws in self.workspaces.iter() { ws.update_has_captures(); @@ -315,20 +303,6 @@ impl OutputNode { y_off, size, ); - for sc in self.screencasts.lock().values() { - sc.copy_texture( - self, - tex, - cd, - resv, - acquire_sync, - release_sync, - render_hardware_cursor, - x_off, - y_off, - size, - ); - } for sc in self.ext_copy_sessions.lock().values() { sc.copy_texture( self, @@ -460,7 +434,6 @@ impl OutputNode { } self.lock_surface.take(); self.jay_outputs.clear(); - self.screencasts.clear(); self.screencopies.clear(); self.ext_copy_sessions.clear(); self.ext_workspace_groups.clear(); @@ -885,9 +858,6 @@ impl OutputNode { self.change_extents_(&self.calculate_extents()); if (old_width, old_height) != (new_width, new_height) { - for sc in self.screencasts.lock().values() { - sc.schedule_realloc_or_reconfigure(); - } for sc in self.ext_copy_sessions.lock().values() { sc.buffer_size_changed(); } diff --git a/src/tree/toplevel.rs b/src/tree/toplevel.rs index a8a8d022..8dfa244f 100644 --- a/src/tree/toplevel.rs +++ b/src/tree/toplevel.rs @@ -20,7 +20,6 @@ use { ext_foreign_toplevel_handle_v1::ExtForeignToplevelHandleV1, ext_foreign_toplevel_list_v1::ExtForeignToplevelListV1, ext_image_copy::ext_image_copy_capture_session_v1::ExtImageCopyCaptureSessionV1, - jay_screencast::JayScreencast, jay_toplevel::JayToplevel, wl_seat::{NodeSeatState, SeatId, collect_kb_foci, collect_kb_foci2}, wl_surface::{ @@ -44,8 +43,8 @@ use { rc_eq::rc_eq, threshold_counter::ThresholdCounter, }, wire::{ - ExtForeignToplevelHandleV1Id, ExtImageCopyCaptureSessionV1Id, JayScreencastId, - JayToplevelId, XxForeignToplevelGeometryTrackerV1Id, ZwlrForeignToplevelHandleV1Id, + ExtForeignToplevelHandleV1Id, ExtImageCopyCaptureSessionV1Id, JayToplevelId, + XxForeignToplevelGeometryTrackerV1Id, ZwlrForeignToplevelHandleV1Id, }, }, jay_config::{window, window::WindowType}, @@ -174,9 +173,6 @@ impl ToplevelNode for T { fn tl_workspace_output_changed(&self, prev: &Rc, new: &Rc) { let data = self.tl_data(); - for sc in data.jay_screencasts.lock().values() { - sc.update_latch_listener(); - } for sc in data.ext_copy_sessions.lock().values() { sc.update_latch_listener(); } @@ -244,9 +240,6 @@ impl ToplevelNode for T { data.spawn_in_pending.set(false); } if prev.size() != rect.size() { - for sc in data.jay_screencasts.lock().values() { - sc.schedule_realloc_or_reconfigure(); - } for sc in data.ext_copy_sessions.lock().values() { sc.buffer_size_changed(); } @@ -543,7 +536,6 @@ pub struct ToplevelData { CopyHashMap<(ClientId, ZwlrForeignToplevelHandleV1Id), Rc>, pub render_highlight: NumCell, pub jay_toplevels: CopyHashMap<(ClientId, JayToplevelId), Rc>, - pub jay_screencasts: CopyHashMap<(ClientId, JayScreencastId), Rc>, pub ext_copy_sessions: CopyHashMap<(ClientId, ExtImageCopyCaptureSessionV1Id), Rc>, pub slf: Weak, @@ -603,7 +595,6 @@ impl ToplevelData { manager_handles: Default::default(), render_highlight: Default::default(), jay_toplevels: Default::default(), - jay_screencasts: Default::default(), ext_copy_sessions: Default::default(), slf: slf.clone(), destroyed: Default::default(), @@ -680,9 +671,6 @@ impl ToplevelData { for jay_tl in self.jay_toplevels.lock().drain_values() { jay_tl.destroy(); } - for screencast in self.jay_screencasts.lock().drain_values() { - screencast.do_destroy(); - } for screencast in self.ext_copy_sessions.lock().drain_values() { screencast.stop(); } @@ -1003,9 +991,6 @@ impl ToplevelData { self.property_changed(TL_CHANGED_VISIBLE); } self.seat_state.set_visible(node, visible); - for sc in self.jay_screencasts.lock().values() { - sc.update_latch_listener(); - } for sc in self.ext_copy_sessions.lock().values() { sc.update_latch_listener(); } diff --git a/src/tree/workspace.rs b/src/tree/workspace.rs index 5e31efe6..dfc72bc8 100644 --- a/src/tree/workspace.rs +++ b/src/tree/workspace.rs @@ -119,12 +119,6 @@ impl WorkspaceNode { if !self.may_capture.get() { break 'update; } - for sc in output.screencasts.lock().values() { - if sc.shows_ws(self) { - has_capture = true; - break 'update; - } - } if output.screencopies.is_not_empty() { has_capture = true; } diff --git a/src/wl_usr/usr_ifs.rs b/src/wl_usr/usr_ifs.rs index 82e1ab77..67ece7b9 100644 --- a/src/wl_usr/usr_ifs.rs +++ b/src/wl_usr/usr_ifs.rs @@ -4,7 +4,6 @@ pub mod usr_jay_ei_session_builder; pub mod usr_jay_output; pub mod usr_jay_pointer; pub mod usr_jay_render_ctx; -pub mod usr_jay_screencast; pub mod usr_jay_select_toplevel; pub mod usr_jay_select_workspace; pub mod usr_jay_sync_file_release; diff --git a/src/wl_usr/usr_ifs/usr_jay_compositor.rs b/src/wl_usr/usr_ifs/usr_jay_compositor.rs index d19d4658..848ac534 100644 --- a/src/wl_usr/usr_ifs/usr_jay_compositor.rs +++ b/src/wl_usr/usr_ifs/usr_jay_compositor.rs @@ -9,7 +9,6 @@ use { usr_ifs::{ usr_jay_ei_session_builder::UsrJayEiSessionBuilder, usr_jay_output::UsrJayOutput, usr_jay_pointer::UsrJayPointer, usr_jay_render_ctx::UsrJayRenderCtx, - usr_jay_screencast::UsrJayScreencast, usr_jay_select_toplevel::UsrJaySelectToplevel, usr_jay_select_workspace::UsrJaySelectWorkspace, usr_jay_workspace_watcher::UsrJayWorkspaceWatcher, usr_wl_output::UsrWlOutput, @@ -31,7 +30,6 @@ pub struct UsrJayCompositor { #[derive(Default)] pub struct UsrJayCompositorCaps { - pub window_capture: Cell, pub select_workspace: Cell, } @@ -62,24 +60,6 @@ impl UsrJayCompositor { rc } - pub fn create_screencast(&self) -> Rc { - let sc = Rc::new(UsrJayScreencast { - id: self.con.id(), - con: self.con.clone(), - owner: Default::default(), - version: self.version, - pending_buffers: Default::default(), - pending_planes: Default::default(), - pending_config: Default::default(), - }); - self.con.request(CreateScreencast { - self_id: self.id, - id: sc.id, - }); - self.con.add_object(sc.clone()); - sc - } - pub fn get_output(&self, output: &UsrWlOutput) -> Rc { let jo = Rc::new(UsrJayOutput { id: self.con.id(), @@ -210,7 +190,6 @@ impl JayCompositorEventHandler for UsrJayCompositor { for &cap in ev.cap { match cap { Cap::NONE => {} - Cap::WINDOW_CAPTURE => self.caps.window_capture.set(true), Cap::SELECT_WORKSPACE => self.caps.select_workspace.set(true), _ => {} } diff --git a/src/wl_usr/usr_ifs/usr_jay_screencast.rs b/src/wl_usr/usr_ifs/usr_jay_screencast.rs deleted file mode 100644 index 4091ea67..00000000 --- a/src/wl_usr/usr_ifs/usr_jay_screencast.rs +++ /dev/null @@ -1,272 +0,0 @@ -use { - crate::{ - format::formats, - object::Version, - utils::clonecell::CloneCell, - video::dmabuf::{DmaBuf, DmaBufPlane, PlaneVec}, - wire::{JayScreencastId, jay_screencast::*}, - wl_usr::{ - UsrCon, - usr_ifs::{ - usr_jay_output::UsrJayOutput, usr_jay_toplevel::UsrJayToplevel, - usr_jay_workspace::UsrJayWorkspace, usr_wl_buffer::UsrWlBuffer, - }, - usr_object::UsrObject, - }, - }, - std::{cell::RefCell, mem, ops::DerefMut, rc::Rc}, - thiserror::Error, -}; - -pub struct UsrJayScreencast { - pub id: JayScreencastId, - pub con: Rc, - pub owner: CloneCell>>, - pub version: Version, - - pub pending_buffers: RefCell>, - pub pending_planes: RefCell>, - - pub pending_config: RefCell, -} - -#[derive(Default)] -pub struct UsrJayScreencastServerConfig { - pub output: Option, - pub show_all: bool, - pub running: bool, - pub use_linear_buffers: bool, - pub allowed_workspaces: Vec, - pub width: i32, - pub height: i32, -} - -pub trait UsrJayScreencastOwner { - fn buffers(&self, buffers: Vec) { - let _ = buffers; - } - - fn ready(&self, ev: &Ready) { - let _ = ev; - } - - fn destroyed(&self) {} - - fn missed_frame(&self) {} - - fn config(&self, config: UsrJayScreencastServerConfig) { - let _ = config; - } -} - -impl UsrJayScreencast { - pub fn set_output(&self, output: &UsrJayOutput) { - self.con.request(SetOutput { - self_id: self.id, - output: output.id, - }); - } - - pub fn set_toplevel(&self, tl: &UsrJayToplevel) { - self.con.request(SetToplevel { - self_id: self.id, - id: tl.id, - }); - } - - pub fn set_allow_all_workspaces(&self, allow_all: bool) { - self.con.request(SetAllowAllWorkspaces { - self_id: self.id, - allow_all: allow_all as _, - }); - } - - pub fn allow_workspace(&self, ws: &UsrJayWorkspace) { - self.con.request(AllowWorkspace { - self_id: self.id, - workspace: ws.id, - }); - } - - #[expect(dead_code)] - pub fn touch_allowed_workspaces(&self) { - self.con - .request(TouchAllowedWorkspaces { self_id: self.id }); - } - - pub fn set_use_linear_buffers(&self, linear: bool) { - self.con.request(SetUseLinearBuffers { - self_id: self.id, - use_linear: linear as _, - }); - } - - pub fn set_running(&self, running: bool) { - self.con.request(SetRunning { - self_id: self.id, - running: running as _, - }); - } - - pub fn configure(&self) { - self.con.request(Configure { self_id: self.id }); - } - - pub fn release_buffer(&self, idx: usize) { - self.con.request(ReleaseBuffer { - self_id: self.id, - idx: idx as _, - }); - } - - pub fn clear_buffers(&self) { - self.con.request(ClearBuffers { self_id: self.id }); - } - - pub fn add_buffer(&self, buffer: &UsrWlBuffer) { - self.con.request(AddBuffer { - self_id: self.id, - buffer: buffer.id, - }); - } -} - -impl JayScreencastEventHandler for UsrJayScreencast { - type Error = UsrJayScreencastError; - - fn plane(&self, ev: Plane, _slf: &Rc) -> Result<(), Self::Error> { - self.pending_planes.borrow_mut().push(DmaBufPlane { - offset: ev.offset, - stride: ev.stride, - fd: ev.fd, - }); - Ok(()) - } - - fn buffer(&self, ev: Buffer, _slf: &Rc) -> Result<(), Self::Error> { - let format = match formats().get(&ev.format) { - Some(f) => f, - _ => return Err(UsrJayScreencastError::UnknownFormat(ev.format)), - }; - self.pending_buffers.borrow_mut().push(DmaBuf { - id: self.con.dma_buf_ids.next(), - width: ev.width, - height: ev.height, - format, - modifier: ev.modifier, - planes: mem::take(self.pending_planes.borrow_mut().deref_mut()), - is_disjoint: Default::default(), - }); - Ok(()) - } - - fn buffers_done(&self, ev: BuffersDone, _slf: &Rc) -> Result<(), Self::Error> { - if let Some(owner) = self.owner.get() { - owner.buffers(mem::take(self.pending_buffers.borrow_mut().deref_mut())); - } - self.con.request(AckBuffers { - self_id: self.id, - serial: ev.serial, - }); - Ok(()) - } - - fn ready(&self, ev: Ready, _slf: &Rc) -> Result<(), Self::Error> { - if let Some(owner) = self.owner.get() { - owner.ready(&ev); - } - Ok(()) - } - - fn destroyed(&self, _ev: Destroyed, _slf: &Rc) -> Result<(), Self::Error> { - if let Some(owner) = self.owner.get() { - owner.destroyed(); - } - Ok(()) - } - - fn missed_frame(&self, _ev: MissedFrame, _slf: &Rc) -> Result<(), Self::Error> { - if let Some(owner) = self.owner.get() { - owner.missed_frame(); - } - Ok(()) - } - - fn config_output(&self, ev: ConfigOutput, _slf: &Rc) -> Result<(), Self::Error> { - self.pending_config.borrow_mut().output = Some(ev.linear_id); - Ok(()) - } - - fn config_allow_all_workspaces( - &self, - ev: ConfigAllowAllWorkspaces, - _slf: &Rc, - ) -> Result<(), Self::Error> { - self.pending_config.borrow_mut().show_all = ev.allow_all != 0; - Ok(()) - } - - fn config_allow_workspace( - &self, - ev: ConfigAllowWorkspace, - _slf: &Rc, - ) -> Result<(), Self::Error> { - self.pending_config - .borrow_mut() - .allowed_workspaces - .push(ev.linear_id); - Ok(()) - } - - fn config_use_linear_buffers( - &self, - ev: ConfigUseLinearBuffers, - _slf: &Rc, - ) -> Result<(), Self::Error> { - self.pending_config.borrow_mut().use_linear_buffers = ev.use_linear != 0; - Ok(()) - } - - fn config_running(&self, ev: ConfigRunning, _slf: &Rc) -> Result<(), Self::Error> { - self.pending_config.borrow_mut().running = ev.running != 0; - Ok(()) - } - - fn config_done(&self, ev: ConfigDone, _slf: &Rc) -> Result<(), Self::Error> { - if let Some(owner) = self.owner.get() { - owner.config(mem::take(self.pending_config.borrow_mut().deref_mut())); - } - self.con.request(AckConfig { - self_id: self.id, - serial: ev.serial, - }); - Ok(()) - } - - fn config_size(&self, ev: ConfigSize, _slf: &Rc) -> Result<(), Self::Error> { - self.pending_config.borrow_mut().width = ev.width; - self.pending_config.borrow_mut().height = ev.height; - Ok(()) - } -} - -usr_object_base! { - self = UsrJayScreencast = JayScreencast; - version = self.version; -} - -impl UsrObject for UsrJayScreencast { - fn destroy(&self) { - self.con.request(Destroy { self_id: self.id }); - } - - fn break_loops(&self) { - self.owner.take(); - } -} - -#[derive(Debug, Error)] -pub enum UsrJayScreencastError { - #[error("The server sent an unknown format {0}")] - UnknownFormat(u32), -} diff --git a/wire/jay_compositor.txt b/wire/jay_compositor.txt index 25200404..9fe1ee8e 100644 --- a/wire/jay_compositor.txt +++ b/wire/jay_compositor.txt @@ -61,10 +61,6 @@ request watch_workspaces { id: id(jay_workspace_watcher), } -request create_screencast { - id: id(jay_screencast), -} - request get_randr { id: id(jay_randr), } diff --git a/wire/jay_screencast.txt b/wire/jay_screencast.txt deleted file mode 100644 index 0fd8bf6a..00000000 --- a/wire/jay_screencast.txt +++ /dev/null @@ -1,115 +0,0 @@ -# requests - -request destroy { - -} - -request set_output { - output: id(jay_output), -} - -request set_allow_all_workspaces { - allow_all: u32, -} - -request allow_workspace { - workspace: id(jay_workspace), -} - -request touch_allowed_workspaces { -} - -request set_use_linear_buffers { - use_linear: u32, -} - -request set_running { - running: u32, -} - -request configure { - -} - -request ack_buffers { - serial: u32, -} - -request ack_config { - serial: u32, -} - -request release_buffer { - idx: u32, -} - -request set_toplevel { - id: id(jay_toplevel), -} - -request clear_buffers (since = 7) { -} - -request add_buffer (since = 7) { - buffer: id(wl_buffer), -} - -# events - -event plane { - fd: fd, - offset: u32, - stride: u32, -} - -event buffer { - format: u32, - modifier: pod(u64), - width: i32, - height: i32, -} - -event buffers_done { - serial: u32, -} - -event ready { - idx: u32, -} - -event destroyed { - -} - -event missed_frame { - -} - -event config_output { - linear_id: u32, -} - -event config_allow_all_workspaces { - allow_all: u32, -} - -event config_allow_workspace { - linear_id: u32, -} - -event config_use_linear_buffers { - use_linear: u32, -} - -event config_running { - running: u32, -} - -event config_done { - serial: u32, -} - -event config_size (since = 7) { - width: i32, - height: i32, -}