state: Move shell behind RwLock

This commit is contained in:
Victoria Brekenfeld 2024-04-10 15:49:08 +02:00 committed by Victoria Brekenfeld
parent 647deb81f1
commit 5d5a510691
45 changed files with 2657 additions and 2097 deletions

View file

@ -11,8 +11,9 @@ use crate::{
utils::prelude::*,
wayland::{
handlers::screencopy::{submit_buffer, FrameHolder, SessionData},
protocols::screencopy::{
FailureReason, Frame as ScreencopyFrame, Session as ScreencopySession,
protocols::{
screencopy::{FailureReason, Frame as ScreencopyFrame, Session as ScreencopySession},
workspace::WorkspaceUpdateGuard,
},
},
};
@ -76,6 +77,7 @@ use smithay::{
relative_pointer::RelativePointerManagerState,
seat::WaylandFocus,
shm::{shm_format_to_fourcc, with_buffer_contents},
xdg_activation::XdgActivationState,
},
};
use tracing::{error, info, trace, warn};
@ -202,7 +204,7 @@ pub fn init_backend(
state.backend.kms().input_devices.remove(device.name());
}
state.process_input_event(event, true);
for output in state.common.shell.outputs() {
for output in state.common.shell.read().unwrap().outputs() {
if let Err(err) = state.backend.kms().schedule_render(
&state.common.event_loop_handle,
output,
@ -326,9 +328,13 @@ pub fn init_backend(
state.common.config.read_outputs(
&mut state.common.output_configuration_state,
&mut state.backend,
&mut state.common.shell,
&mut state.common.shell.write().unwrap(),
&state.common.event_loop_handle,
&mut state.common.workspace_state.update(),
&state.common.xdg_activation_state,
);
state.common.refresh();
for surface in state
.backend
.kms()
@ -339,7 +345,7 @@ pub fn init_backend(
surface.scheduled = false;
surface.pending = false;
}
for output in state.common.shell.outputs() {
for output in state.common.shell.read().unwrap().outputs() {
if let Err(err) = state.backend.kms().schedule_render(
&state.common.event_loop_handle,
output,
@ -601,7 +607,7 @@ impl State {
let outputs = device.enumerate_surfaces()?.added; // There are no removed outputs on newly added devices
let mut wl_outputs = Vec::new();
let mut w = self.common.shell.global_space().size.w;
let mut w = self.common.shell.read().unwrap().global_space().size.w;
{
let backend = self.backend.kms();
backend
@ -701,9 +707,12 @@ impl State {
self.common.config.read_outputs(
&mut self.common.output_configuration_state,
&mut self.backend,
&mut self.common.shell,
&mut *self.common.shell.write().unwrap(),
&self.common.event_loop_handle,
&mut self.common.workspace_state.update(),
&self.common.xdg_activation_state,
);
self.common.refresh();
Ok(())
}
@ -720,7 +729,7 @@ impl State {
let backend = self.backend.kms();
if let Some(device) = backend.devices.get_mut(&drm_node) {
let changes = device.enumerate_surfaces()?;
let mut w = self.common.shell.global_space().size.w;
let mut w = self.common.shell.read().unwrap().global_space().size.w;
for crtc in changes.removed {
if let Some(pos) = device
.non_desktop_connectors
@ -831,18 +840,23 @@ impl State {
self.common
.output_configuration_state
.add_heads(outputs_added.iter());
self.common.config.read_outputs(
&mut self.common.output_configuration_state,
&mut self.backend,
&mut self.common.shell,
&self.common.event_loop_handle,
);
// Don't remove the outputs, before potentially new ones have been initialized.
// reading a new config means outputs might become enabled, that were previously disabled.
// If we have 0 outputs at some point, we won't quit, but shell doesn't know where to move
// windows and workspaces to.
for output in outputs_removed {
self.common.shell.remove_output(&output);
{
self.common.config.read_outputs(
&mut self.common.output_configuration_state,
&mut self.backend,
&mut *self.common.shell.write().unwrap(),
&self.common.event_loop_handle,
&mut self.common.workspace_state.update(),
&self.common.xdg_activation_state,
);
self.common.refresh();
// Don't remove the outputs, before potentially new ones have been initialized.
// reading a new config means outputs might become enabled, that were previously disabled.
// If we have 0 outputs at some point, we won't quit, but shell doesn't know where to move
// windows and workspaces to.
for output in outputs_removed {
self.common.remove_output(&output);
}
}
{
@ -889,14 +903,17 @@ impl State {
if self.backend.kms().session.is_active() {
for output in outputs_removed {
self.common.shell.remove_output(&output);
self.common.remove_output(&output);
}
self.common.config.read_outputs(
&mut self.common.output_configuration_state,
&mut self.backend,
&mut self.common.shell,
&mut *self.common.shell.write().unwrap(),
&self.common.event_loop_handle,
&mut self.common.workspace_state.update(),
&self.common.xdg_activation_state,
);
self.common.refresh();
} else {
self.common.output_configuration_state.update();
}
@ -1178,30 +1195,33 @@ impl Surface {
);
}
let (previous_workspace, workspace) = state.shell.workspaces.active(&self.output);
let (previous_idx, idx) = state.shell.workspaces.active_num(&self.output);
let previous_workspace = previous_workspace
.zip(previous_idx)
.map(|((w, start), idx)| (w.handle, idx, start));
let workspace = (workspace.handle, idx);
let mut elements = {
let shell = state.shell.read().unwrap();
let (previous_workspace, workspace) = shell.workspaces.active(&self.output);
let (previous_idx, idx) = shell.workspaces.active_num(&self.output);
let previous_workspace = previous_workspace
.zip(previous_idx)
.map(|((w, start), idx)| (w.handle, idx, start));
let workspace = (workspace.handle, idx);
let mut elements = workspace_elements(
Some(&render_node),
&mut renderer,
&state.shell,
&state.config,
&state.theme,
state.clock.now(),
&self.output,
previous_workspace,
workspace,
CursorMode::All,
&mut Some(&mut self.fps),
false,
)
.map_err(|err| {
anyhow::format_err!("Failed to accumulate elements for rendering: {:?}", err)
})?;
workspace_elements(
Some(&render_node),
&mut renderer,
&*shell,
&state.config,
&state.theme,
state.clock.now(),
&self.output,
previous_workspace,
workspace,
CursorMode::All,
&mut Some(&mut self.fps),
false,
)
.map_err(|err| {
anyhow::format_err!("Failed to accumulate elements for rendering: {:?}", err)
})?
};
self.fps.elements();
let frames: Vec<(
@ -1490,6 +1510,8 @@ impl KmsState {
shell: &mut Shell,
test_only: bool,
loop_handle: &LoopHandle<'_, State>,
workspace_state: &mut WorkspaceUpdateGuard<'_, State>,
xdg_activation_state: &XdgActivationState,
) -> Result<(), anyhow::Error> {
let recreated = if let Some(device) = self
.devices
@ -1509,7 +1531,12 @@ impl KmsState {
if !output_config.enabled {
if !test_only {
shell.remove_output(output);
shell.workspaces.remove_output(
output,
shell.seats.iter(),
workspace_state,
xdg_activation_state,
);
if surface.surface.take().is_some() {
// just drop it
surface.pending = false;
@ -1608,7 +1635,9 @@ impl KmsState {
surface.surface = Some(target);
true
};
shell.add_output(output);
shell
.workspaces
.add_output(output, workspace_state, xdg_activation_state);
res
} else {
false
@ -1748,7 +1777,7 @@ impl KmsState {
&surface.output,
backend.primary_node,
target_node,
&common.shell,
&*common.shell.read().unwrap(),
);
let result = if render_node != target_node {

View file

@ -45,17 +45,26 @@ pub fn init_backend_auto(
let output = state
.common
.shell
.read()
.unwrap()
.outputs()
.next()
.with_context(|| "Backend initialized without output")?;
.with_context(|| "Backend initialized without output")
.cloned()?;
let initial_seat = crate::shell::create_seat(
dh,
&mut state.common.seat_state,
output,
&output,
&state.common.config,
"seat-0".into(),
);
state.common.shell.seats.add_seat(initial_seat);
state
.common
.shell
.write()
.unwrap()
.seats
.add_seat(initial_seat);
}
res
}

View file

@ -63,7 +63,7 @@ impl WinitState {
surface.clone(),
&mut self.damage_tracker,
age,
&state.shell,
&*state.shell.read().unwrap(),
&state.config,
&state.theme,
state.clock.now(),
@ -201,7 +201,7 @@ pub fn init_backend(
}
PumpStatus::Exit(_) => {
let output = state.backend.winit().output.clone();
state.common.shell.remove_output(&output);
state.common.remove_output(&output);
if let Some(token) = token.take() {
event_loop_handle.remove(token);
}
@ -226,13 +226,21 @@ pub fn init_backend(
.common
.output_configuration_state
.add_heads(std::iter::once(&output));
state.common.shell.add_output(&output);
state.common.config.read_outputs(
&mut state.common.output_configuration_state,
&mut state.backend,
&mut state.common.shell,
&state.common.event_loop_handle,
);
{
state.common.add_output(&output);
let mut shell = state.common.shell.write().unwrap();
state.common.config.read_outputs(
&mut state.common.output_configuration_state,
&mut state.backend,
&mut *shell,
&state.common.event_loop_handle,
&mut state.common.workspace_state.update(),
&state.common.xdg_activation_state,
);
std::mem::drop(shell);
state.common.refresh();
}
state.launch_xwayland(None);
Ok(())
@ -299,7 +307,7 @@ impl State {
// here we can handle special cases for winit inputs
match event {
WinitEvent::Focus(true) => {
for seat in self.common.shell.seats.iter() {
for seat in self.common.shell.read().unwrap().seats.iter() {
let devices = seat.user_data().get::<Devices>().unwrap();
if devices.has_device(&WinitVirtualDevice) {
seat.set_active_output(&self.backend.winit().output);

View file

@ -222,7 +222,7 @@ impl Surface {
buffer.clone(),
&mut self.damage_tracker,
age as usize,
&state.shell,
&*state.shell.read().unwrap(),
&state.config,
&state.theme,
state.clock.now(),
@ -364,13 +364,21 @@ pub fn init_backend(
.common
.output_configuration_state
.add_heads(std::iter::once(&output));
state.common.shell.add_output(&output);
state.common.config.read_outputs(
&mut state.common.output_configuration_state,
&mut state.backend,
&mut state.common.shell,
&state.common.event_loop_handle,
);
{
state.common.add_output(&output);
let mut shell = state.common.shell.write().unwrap();
state.common.config.read_outputs(
&mut state.common.output_configuration_state,
&mut state.backend,
&mut *shell,
&state.common.event_loop_handle,
&mut state.common.workspace_state.update(),
&state.common.xdg_activation_state,
);
std::mem::drop(shell);
state.common.refresh();
}
state.launch_xwayland(None);
event_loop
@ -395,7 +403,7 @@ pub fn init_backend(
.surfaces
.retain(|s| s.window.id() != window_id);
for output in outputs_removed.into_iter() {
state.common.shell.remove_output(&output);
state.common.remove_output(&output);
}
}
X11Event::Resized {
@ -504,7 +512,7 @@ impl State {
.unwrap();
let device = event.device();
for seat in self.common.shell.seats.iter() {
for seat in self.common.shell.read().unwrap().seats.iter() {
let devices = seat.user_data().get::<Devices>().unwrap();
if devices.has_device(&device) {
seat.set_active_output(&output);
@ -518,7 +526,7 @@ impl State {
self.process_input_event(event, false);
// TODO actually figure out the output
for output in self.common.shell.outputs() {
for output in self.common.shell.read().unwrap().outputs() {
self.backend.x11().schedule_render(output);
}
}