diff --git a/src/compositor.rs b/src/compositor.rs index 4427e8c1..8d6d2dff 100644 --- a/src/compositor.rs +++ b/src/compositor.rs @@ -26,8 +26,8 @@ use { state::{ConnectorData, IdleState, ScreenlockState, State, XWaylandState}, tasks::{self, idle}, tree::{ - container_layout, container_render_data, float_layout, float_titles, DisplayNode, - NodeIds, OutputNode, WorkspaceNode, + container_layout, container_render_data, float_layout, float_titles, + output_render_data, DisplayNode, NodeIds, OutputNode, WorkspaceNode, }, user_session::import_environment, utils::{ @@ -154,6 +154,7 @@ fn start_compositor2( theme: Default::default(), pending_container_layout: Default::default(), pending_container_render_data: Default::default(), + pending_output_render_data: Default::default(), pending_float_layout: Default::default(), pending_float_titles: Default::default(), dbus: Dbus::new(&engine, &ring, &run_toplevel), @@ -281,6 +282,7 @@ fn start_global_event_handlers( res.push(eng.spawn(tasks::handle_hardware_cursor_tick(state.clone()))); res.push(eng.spawn2(Phase::Layout, container_layout(state.clone()))); res.push(eng.spawn2(Phase::PostLayout, container_render_data(state.clone()))); + res.push(eng.spawn2(Phase::PostLayout, output_render_data(state.clone()))); res.push(eng.spawn2(Phase::Layout, float_layout(state.clone()))); res.push(eng.spawn2(Phase::PostLayout, float_titles(state.clone()))); res.push(eng.spawn2(Phase::PostLayout, idle(state.clone(), backend.clone()))); @@ -390,6 +392,7 @@ fn create_dummy_output(state: &Rc) { lock_surface: Default::default(), preferred_scale: Cell::new(Fixed::from_int(1)), hardware_cursor: Default::default(), + update_render_data_scheduled: Cell::new(false), screencasts: Default::default(), }); let dummy_workspace = Rc::new(WorkspaceNode { diff --git a/src/state.rs b/src/state.rs index 2b93123b..9b3d1b04 100644 --- a/src/state.rs +++ b/src/state.rs @@ -94,6 +94,7 @@ pub struct State { pub theme: Theme, pub pending_container_layout: AsyncQueue>, pub pending_container_render_data: AsyncQueue>, + pub pending_output_render_data: AsyncQueue>, pub pending_float_layout: AsyncQueue>, pub pending_float_titles: AsyncQueue>, pub dbus: Dbus, @@ -220,7 +221,7 @@ impl NodeVisitorBase for UpdateTextTexturesVisitor { node.node_visit_children(self); } fn visit_output(&mut self, node: &Rc) { - node.update_render_data(); + node.schedule_update_render_data(); node.node_visit_children(self); } fn visit_float(&mut self, node: &Rc) { @@ -468,7 +469,7 @@ impl State { } }; ws.flush_jay_workspaces(); - output.update_render_data(); + output.schedule_update_render_data(); self.tree_changed(); // let seats = self.globals.seats.lock(); // for seat in seats.values() { @@ -576,6 +577,7 @@ impl State { self.dbus.clear(); self.pending_container_layout.clear(); self.pending_container_render_data.clear(); + self.pending_output_render_data.clear(); self.pending_float_layout.clear(); self.pending_float_titles.clear(); self.render_ctx_watchers.clear(); diff --git a/src/tasks/connector.rs b/src/tasks/connector.rs index 122c13a7..e1576b31 100644 --- a/src/tasks/connector.rs +++ b/src/tasks/connector.rs @@ -126,6 +126,7 @@ impl ConnectorHandler { hardware_cursor: Default::default(), jay_outputs: Default::default(), screencasts: Default::default(), + update_render_data_scheduled: Cell::new(false), }); self.state.add_output_scale(on.preferred_scale.get()); let mode = info.initial_mode; @@ -180,7 +181,7 @@ impl ConnectorHandler { ws.flush_jay_workspaces(); } } - source.node.update_render_data(); + source.node.schedule_update_render_data(); } if on.workspace.get().is_none() { if let Some(ws) = on.workspaces.first() { @@ -189,7 +190,7 @@ impl ConnectorHandler { } } } - on.update_render_data(); + on.schedule_update_render_data(); self.state.root.outputs.set(self.id, on.clone()); self.state.root.update_extents(); self.state.add_global(&global); @@ -249,7 +250,7 @@ impl ConnectorHandler { } ws.flush_jay_workspaces(); } - target.update_render_data(); + target.schedule_update_render_data(); self.state.tree_changed(); self.state.damage(); } diff --git a/src/tree/output.rs b/src/tree/output.rs index d1d6cdf9..c0d6fe5f 100644 --- a/src/tree/output.rs +++ b/src/tree/output.rs @@ -59,9 +59,22 @@ pub struct OutputNode { pub lock_surface: CloneCell>>, pub preferred_scale: Cell, pub hardware_cursor: CloneCell>>, + pub update_render_data_scheduled: Cell, pub screencasts: CopyHashMap<(ClientId, JayScreencastId), Rc>, } +pub async fn output_render_data(state: Rc) { + loop { + let container = state.pending_output_render_data.pop().await; + if container.global.destroyed.get() { + continue; + } + if container.update_render_data_scheduled.get() { + container.update_render_data(); + } + } +} + impl OutputNode { pub fn perform_screencopies(&self, fb: &Framebuffer, tex: &Texture) { self.global.perform_screencopies(fb, tex); @@ -83,13 +96,13 @@ impl OutputNode { } pub fn on_spaces_changed(self: &Rc) { - self.update_render_data(); + self.schedule_update_render_data(); if let Some(c) = self.workspace.get() { c.change_extents(&self.workspace_rect()); } } - pub fn set_preferred_scale(&self, scale: Fixed) { + pub fn set_preferred_scale(self: &Rc, scale: Fixed) { let old_scale = self.preferred_scale.replace(scale); if scale == old_scale { return; @@ -109,10 +122,17 @@ impl OutputNode { stacked.deref().clone().node_visit(&mut visitor); } } - self.update_render_data(); + self.schedule_update_render_data(); } - pub fn update_render_data(&self) { + pub fn schedule_update_render_data(self: &Rc) { + if !self.update_render_data_scheduled.replace(true) { + self.state.pending_output_render_data.push(self.clone()); + } + } + + fn update_render_data(&self) { + self.update_render_data_scheduled.set(false); let mut rd = self.render_data.borrow_mut(); rd.titles.clear(); rd.inactive_workspaces.clear(); @@ -254,7 +274,7 @@ impl OutputNode { .output_link .set(Some(self.workspaces.add_last(workspace.clone()))); self.show_workspace(&workspace); - self.update_render_data(); + self.schedule_update_render_data(); workspace } @@ -320,7 +340,7 @@ impl OutputNode { for (client, e) in clients_to_kill.values() { client.error(e); } - self.update_render_data(); + self.schedule_update_render_data(); ws } @@ -336,7 +356,7 @@ impl OutputNode { .unwrap() } - pub fn set_position(&self, x: i32, y: i32) { + pub fn set_position(self: &Rc, x: i32, y: i32) { let pos = self.global.pos.get(); if (pos.x1(), pos.y1()) == (x, y) { return; @@ -345,7 +365,7 @@ impl OutputNode { self.change_extents_(&rect); } - pub fn update_mode(&self, mode: Mode) { + pub fn update_mode(self: &Rc, mode: Mode) { let old_mode = self.global.mode.get(); if old_mode == mode { return; @@ -387,10 +407,10 @@ impl OutputNode { pos.with_size(width, height).unwrap() } - fn change_extents_(&self, rect: &Rect) { + fn change_extents_(self: &Rc, rect: &Rect) { self.global.pos.set(*rect); self.state.root.update_extents(); - self.update_render_data(); + self.schedule_update_render_data(); if let Some(ls) = self.lock_surface.get() { ls.change_extents(*rect); } @@ -431,9 +451,9 @@ impl OutputNode { FindTreeResult::Other } - pub fn set_status(&self, status: &Rc) { + pub fn set_status(self: &Rc, status: &Rc) { self.status.set(status.clone()); - self.update_render_data(); + self.schedule_update_render_data(); } fn pointer_move(self: &Rc, seat: &Rc, x: i32, y: i32) { @@ -628,7 +648,7 @@ impl Node for OutputNode { }; self.show_workspace(&ws); ws.flush_jay_workspaces(); - self.update_render_data(); + self.schedule_update_render_data(); self.state.tree_changed(); } @@ -666,7 +686,7 @@ impl Node for OutputNode { ws.deref() .clone() .node_do_focus(seat, Direction::Unspecified); - self.update_render_data(); + self.schedule_update_render_data(); self.state.tree_changed(); }