From 022d8d1db06a8a97c28e83f7bb80de2933ca99f9 Mon Sep 17 00:00:00 2001 From: Julian Orth Date: Sat, 30 Jul 2022 11:28:46 +0200 Subject: [PATCH] wayland: add jay_workspace_watcher --- src/compositor.rs | 1 + src/ifs.rs | 1 + src/ifs/jay_compositor.rs | 24 ++++++++- src/ifs/jay_workspace.rs | 1 - src/ifs/jay_workspace_watcher.rs | 91 ++++++++++++++++++++++++++++++++ src/state.rs | 5 +- src/tree/output.rs | 10 ++++ wire/jay_compositor.txt | 4 ++ wire/jay_workspace_watcher.txt | 12 +++++ 9 files changed, 145 insertions(+), 4 deletions(-) create mode 100644 src/ifs/jay_workspace_watcher.rs create mode 100644 wire/jay_workspace_watcher.txt diff --git a/src/compositor.rs b/src/compositor.rs index 7e9a1779..322feaeb 100644 --- a/src/compositor.rs +++ b/src/compositor.rs @@ -196,6 +196,7 @@ fn start_compositor2( hardware_tick_cursor: Default::default(), testers: Default::default(), render_ctx_watchers: Default::default(), + workspace_watchers: Default::default(), }); state.tracker.register(ClientId::from_raw(0)); create_dummy_output(&state); diff --git a/src/ifs.rs b/src/ifs.rs index ad69d68b..bdc541a3 100644 --- a/src/ifs.rs +++ b/src/ifs.rs @@ -10,6 +10,7 @@ pub mod jay_render_ctx; pub mod jay_screenshot; pub mod jay_seat_events; pub mod jay_workspace; +pub mod jay_workspace_watcher; pub mod org_kde_kwin_server_decoration; pub mod org_kde_kwin_server_decoration_manager; pub mod wl_buffer; diff --git a/src/ifs/jay_compositor.rs b/src/ifs/jay_compositor.rs index de61fc39..8f1094a5 100644 --- a/src/ifs/jay_compositor.rs +++ b/src/ifs/jay_compositor.rs @@ -6,7 +6,7 @@ use { ifs::{ jay_idle::JayIdle, jay_log_file::JayLogFile, jay_output::JayOutput, jay_pointer::JayPointer, jay_render_ctx::JayRenderCtx, jay_screenshot::JayScreenshot, - jay_seat_events::JaySeatEvents, + jay_seat_events::JaySeatEvents, jay_workspace_watcher::JayWorkspaceWatcher, }, leaks::Tracker, object::Object, @@ -279,6 +279,25 @@ impl JayCompositor { ctx.send_render_ctx(rctx.as_ref()); Ok(()) } + + fn watch_workspaces(&self, parser: MsgParser<'_, '_>) -> Result<(), JayCompositorError> { + let req: WatchWorkspaces = self.client.parse(self, parser)?; + let watcher = Rc::new(JayWorkspaceWatcher { + id: req.id, + client: self.client.clone(), + tracker: Default::default(), + }); + track!(self.client, watcher); + self.client.add_client_obj(&watcher)?; + self.client + .state + .workspace_watchers + .set((self.client.id, req.id), watcher.clone()); + for ws in self.client.state.workspaces.lock().values() { + watcher.send_workspace(ws)?; + } + Ok(()) + } } object_base! { @@ -298,11 +317,12 @@ object_base! { GET_OUTPUT => get_output, GET_POINTER => get_pointer, GET_RENDER_CTX => get_render_ctx, + WATCH_WORKSPACES => watch_workspaces, } impl Object for JayCompositor { fn num_requests(&self) -> u32 { - GET_RENDER_CTX + 1 + WATCH_WORKSPACES + 1 } } diff --git a/src/ifs/jay_workspace.rs b/src/ifs/jay_workspace.rs index 2a91fd60..96080b42 100644 --- a/src/ifs/jay_workspace.rs +++ b/src/ifs/jay_workspace.rs @@ -21,7 +21,6 @@ pub struct JayWorkspace { pub tracker: Tracker, } -#[allow(dead_code)] impl JayWorkspace { pub fn send_linear_id(&self, ws: &WorkspaceNode) { self.client.event(LinearId { diff --git a/src/ifs/jay_workspace_watcher.rs b/src/ifs/jay_workspace_watcher.rs new file mode 100644 index 00000000..0422adf0 --- /dev/null +++ b/src/ifs/jay_workspace_watcher.rs @@ -0,0 +1,91 @@ +use { + crate::{ + client::{Client, ClientError}, + ifs::jay_workspace::JayWorkspace, + leaks::Tracker, + object::Object, + tree::WorkspaceNode, + utils::{ + buffd::{MsgParser, MsgParserError}, + clonecell::CloneCell, + }, + wire::{jay_workspace_watcher::*, JayWorkspaceWatcherId}, + }, + std::rc::Rc, + thiserror::Error, +}; + +pub struct JayWorkspaceWatcher { + pub id: JayWorkspaceWatcherId, + pub client: Rc, + pub tracker: Tracker, +} + +impl JayWorkspaceWatcher { + pub fn send_workspace(&self, workspace: &Rc) -> Result<(), ClientError> { + let jw = Rc::new(JayWorkspace { + id: self.client.new_id()?, + client: self.client.clone(), + workspace: CloneCell::new(Some(workspace.clone())), + tracker: Default::default(), + }); + track!(self.client, jw); + self.client.add_server_obj(&jw); + workspace + .jay_workspaces + .set((self.client.id, jw.id), jw.clone()); + self.client.event(New { + self_id: self.id, + id: jw.id, + linear_id: workspace.id.raw(), + }); + jw.send_linear_id(workspace); + jw.send_name(workspace); + jw.send_output(&workspace.output.get()); + jw.send_visible(workspace.visible.get()); + jw.send_done(); + Ok(()) + } + + fn destroy(&self, parser: MsgParser<'_, '_>) -> Result<(), JayWorkspaceWatcherError> { + let _req: Destroy = self.client.parse(self, parser)?; + self.remove_from_state(); + self.client.remove_obj(self)?; + Ok(()) + } + + fn remove_from_state(&self) { + self.client + .state + .workspace_watchers + .remove(&(self.client.id, self.id)); + } +} + +object_base! { + JayWorkspaceWatcher; + + DESTROY => destroy, +} + +impl Object for JayWorkspaceWatcher { + fn num_requests(&self) -> u32 { + DESTROY + 1 + } + + fn break_loops(&self) { + self.remove_from_state(); + } +} + +simple_add_obj!(JayWorkspaceWatcher); + +#[derive(Debug, Error)] +pub enum JayWorkspaceWatcherError { + #[error("Parsing failed")] + MsgParserError(Box), + #[error(transparent)] + ClientError(Box), +} +efrom!(JayWorkspaceWatcherError, MsgParserError); +efrom!(JayWorkspaceWatcherError, ClientError); diff --git a/src/state.rs b/src/state.rs index b6c2fd28..32fb7283 100644 --- a/src/state.rs +++ b/src/state.rs @@ -19,6 +19,7 @@ use { ext_session_lock_v1::ExtSessionLockV1, jay_render_ctx::JayRenderCtx, jay_seat_events::JaySeatEvents, + jay_workspace_watcher::JayWorkspaceWatcher, wl_drm::WlDrmGlobal, wl_seat::{SeatIds, WlSeatGlobal}, wl_surface::{ @@ -43,7 +44,7 @@ use { queue::AsyncQueue, refcounted::RefCounted, run_toplevel::RunToplevel, }, wheel::Wheel, - wire::{JayRenderCtxId, JaySeatEventsId}, + wire::{JayRenderCtxId, JaySeatEventsId, JayWorkspaceWatcherId}, xkbcommon::{XkbContext, XkbKeymap}, xwayland::{self, XWaylandEvent}, }, @@ -119,6 +120,7 @@ pub struct State { pub hardware_tick_cursor: AsyncQueue>>, pub testers: RefCell>>, pub render_ctx_watchers: CopyHashMap<(ClientId, JayRenderCtxId), Rc>, + pub workspace_watchers: CopyHashMap<(ClientId, JayWorkspaceWatcherId), Rc>, } // impl Drop for State { @@ -567,6 +569,7 @@ impl State { self.pending_float_layout.clear(); self.pending_float_titles.clear(); self.render_ctx_watchers.clear(); + self.workspace_watchers.clear(); self.slow_clients.clear(); for (_, h) in self.input_device_handlers.borrow_mut().drain() { h.async_event.clear(); diff --git a/src/tree/output.rs b/src/tree/output.rs index 7fe90224..274a2e1d 100644 --- a/src/tree/output.rs +++ b/src/tree/output.rs @@ -30,6 +30,7 @@ use { }, wire::JayOutputId, }, + ahash::AHashMap, smallvec::SmallVec, std::{ cell::{Cell, RefCell}, @@ -301,6 +302,15 @@ impl OutputNode { if self.workspace.get().is_none() { self.show_workspace(&ws); } + let mut clients_to_kill = AHashMap::new(); + for watcher in self.state.workspace_watchers.lock().values() { + if let Err(e) = watcher.send_workspace(&ws) { + clients_to_kill.insert(watcher.client.id, (watcher.client.clone(), e)); + } + } + for (client, e) in clients_to_kill.values() { + client.error(e); + } self.update_render_data(); ws } diff --git a/wire/jay_compositor.txt b/wire/jay_compositor.txt index 97e8396f..1e4f318a 100644 --- a/wire/jay_compositor.txt +++ b/wire/jay_compositor.txt @@ -57,6 +57,10 @@ msg get_render_ctx = 13 { id: id(jay_render_ctx), } +msg watch_workspaces = 14 { + id: id(jay_workspace_watcher), +} + # events msg client_id = 0 { diff --git a/wire/jay_workspace_watcher.txt b/wire/jay_workspace_watcher.txt new file mode 100644 index 00000000..dcc9dc94 --- /dev/null +++ b/wire/jay_workspace_watcher.txt @@ -0,0 +1,12 @@ +# requests + +msg destroy = 0 { + +} + +# events + +msg new = 0 { + id: id(jay_workspace), + linear_id: u32, +}