From 8aaec59452c9ea28f9769e4adf2eb996d5e95d3a Mon Sep 17 00:00:00 2001 From: Ottatop Date: Fri, 26 Apr 2024 18:43:18 -0500 Subject: [PATCH] Split off backend and rest of State Currently doesn't clean up anything, still need to change `impl State`s to `impl Pinnacle`s --- src/api.rs | 61 ++++++++------ src/api/layout.rs | 2 +- src/api/signal.rs | 14 ++-- src/api/window.rs | 47 +++++++---- src/backend/dummy.rs | 34 ++++---- src/backend/udev.rs | 109 ++++++++++++++----------- src/backend/winit.rs | 116 +++++++++++++-------------- src/backend/wlcs.rs | 23 +++--- src/config.rs | 72 +++++++++-------- src/focus.rs | 33 ++++---- src/focus/pointer.rs | 12 ++- src/grab/move_grab.rs | 18 ++++- src/grab/resize_grab.rs | 11 ++- src/handlers.rs | 112 +++++++++++++++----------- src/handlers/xdg_shell.rs | 36 ++++++--- src/handlers/xwayland.rs | 92 ++++++++++++++-------- src/input.rs | 121 ++++++++++++++++++++-------- src/input/libinput.rs | 9 ++- src/layout.rs | 45 +++++++---- src/main.rs | 11 ++- src/output.rs | 9 ++- src/render.rs | 2 +- src/state.rs | 140 ++++++++++++++++++--------------- src/tag.rs | 4 +- src/window.rs | 9 ++- src/window/rules.rs | 4 +- src/window/window_state.rs | 1 + tests/common/mod.rs | 10 ++- tests/lua_api.rs | 64 +++++++-------- tests/rust_api.rs | 24 +++--- wlcs_pinnacle/src/main_loop.rs | 39 ++++++--- 31 files changed, 770 insertions(+), 514 deletions(-) diff --git a/src/api.rs b/src/api.rs index a841f31..b11edcd 100644 --- a/src/api.rs +++ b/src/api.rs @@ -204,7 +204,9 @@ impl pinnacle_service_server::PinnacleService for PinnacleService { run_unary_no_response(&self.sender, |state| { info!("Reloading config"); state - .start_config(Some(state.config.dir(&state.xdg_base_dirs))) + .start_config(Some( + state.pinnacle.config.dir(&state.pinnacle.xdg_base_dirs), + )) .expect("failed to restart config"); }) .await @@ -220,7 +222,7 @@ impl pinnacle_service_server::PinnacleService for PinnacleService { _request: Request, ) -> Result, Status> { run_server_streaming(&self.sender, |state, sender| { - state.config.shutdown_sender.replace(sender); + state.pinnacle.config.shutdown_sender.replace(sender); }) } } @@ -291,6 +293,7 @@ impl input_service_server::InputService for InputService { run_server_streaming(&self.sender, move |state, sender| { state + .pinnacle .input_state .keybinds .insert((modifiers, keysym), sender); @@ -334,6 +337,7 @@ impl input_service_server::InputService for InputService { run_server_streaming(&self.sender, move |state, sender| { state + .pinnacle .input_state .mousebinds .insert((modifiers, button, edge), sender); @@ -354,7 +358,7 @@ impl input_service_server::InputService for InputService { layout: request.layout(), options: request.options.clone(), }; - if let Some(kb) = state.seat.get_keyboard() { + if let Some(kb) = state.pinnacle.seat.get_keyboard() { if let Err(err) = kb.set_xkb_config(state, new_config) { error!("Failed to set xkbconfig: {err}"); } @@ -377,7 +381,7 @@ impl input_service_server::InputService for InputService { .ok_or_else(|| Status::invalid_argument("no rate specified"))?; run_unary_no_response(&self.sender, move |state| { - if let Some(kb) = state.seat.get_keyboard() { + if let Some(kb) = state.pinnacle.seat.get_keyboard() { kb.change_repeat_info(rate, delay); } }) @@ -518,11 +522,12 @@ impl input_service_server::InputService for InputService { }; run_unary_no_response(&self.sender, move |state| { - for device in state.input_state.libinput_devices.iter_mut() { + for device in state.pinnacle.input_state.libinput_devices.iter_mut() { apply_setting(device); } state + .pinnacle .input_state .libinput_settings .insert(discriminant, apply_setting); @@ -562,18 +567,19 @@ impl process_service_server::ProcessService for ProcessService { run_server_streaming(&self.sender, move |state, sender| { if once { state + .pinnacle .system_processes .refresh_processes_specifics(ProcessRefreshKind::new()); let compositor_pid = std::process::id(); - let already_running = - state - .system_processes - .processes_by_exact_name(&arg0) - .any(|proc| { - proc.parent() - .is_some_and(|parent_pid| parent_pid.as_u32() == compositor_pid) - }); + let already_running = state + .pinnacle + .system_processes + .processes_by_exact_name(&arg0) + .any(|proc| { + proc.parent() + .is_some_and(|parent_pid| parent_pid.as_u32() == compositor_pid) + }); if already_running { return; @@ -743,7 +749,7 @@ impl tag_service_server::TagService for TagService { return; }; - state.fixup_xwayland_internal_z_indices(); + state.fixup_xwayland_window_layering(); state.request_layout(&output); state.update_focus(&output); @@ -772,7 +778,7 @@ impl tag_service_server::TagService for TagService { tag.set_active(true, state); }); - state.fixup_xwayland_internal_z_indices(); + state.fixup_xwayland_window_layering(); state.request_layout(&output); state.update_focus(&output); @@ -804,6 +810,7 @@ impl tag_service_server::TagService for TagService { .collect::>(); state + .pinnacle .config .connector_saved_states .entry(output_name.clone()) @@ -819,7 +826,7 @@ impl tag_service_server::TagService for TagService { } for tag in new_tags { - for window in state.windows.iter() { + for window in state.pinnacle.windows.iter() { window.with_state_mut(|state| { for win_tag in state.tags.iter_mut() { if win_tag.id() == tag.id() { @@ -844,7 +851,7 @@ impl tag_service_server::TagService for TagService { run_unary_no_response(&self.sender, move |state| { let tags_to_remove = tag_ids.flat_map(|id| id.tag(state)).collect::>(); - for output in state.space.outputs().cloned().collect::>() { + for output in state.pinnacle.space.outputs().cloned().collect::>() { // TODO: seriously, convert state.tags into a hashset output.with_state_mut(|state| { for tag_to_remove in tags_to_remove.iter() { @@ -856,7 +863,7 @@ impl tag_service_server::TagService for TagService { state.schedule_render(&output); } - for conn_saved_state in state.config.connector_saved_states.values_mut() { + for conn_saved_state in state.pinnacle.config.connector_saved_states.values_mut() { for tag_to_remove in tags_to_remove.iter() { conn_saved_state.tags.retain(|tag| tag != tag_to_remove); } @@ -871,6 +878,7 @@ impl tag_service_server::TagService for TagService { ) -> Result, Status> { run_unary(&self.sender, move |state| { let tag_ids = state + .pinnacle .space .outputs() .flat_map(|op| op.with_state(|state| state.tags.clone())) @@ -908,6 +916,7 @@ impl tag_service_server::TagService for TagService { .as_ref() .map(|tag| { state + .pinnacle .windows .iter() .filter_map(|win| { @@ -958,7 +967,12 @@ impl output_service_server::OutputService for OutputService { let y = request.y; run_unary_no_response(&self.sender, move |state| { - if let Some(saved_state) = state.config.connector_saved_states.get_mut(&output_name) { + if let Some(saved_state) = state + .pinnacle + .config + .connector_saved_states + .get_mut(&output_name) + { if let Some(x) = x { saved_state.loc.x = x; } @@ -966,7 +980,7 @@ impl output_service_server::OutputService for OutputService { saved_state.loc.y = y; } } else { - state.config.connector_saved_states.insert( + state.pinnacle.config.connector_saved_states.insert( output_name.clone(), ConnectorSavedState { loc: (x.unwrap_or_default(), y.unwrap_or_default()).into(), @@ -1100,6 +1114,7 @@ impl output_service_server::OutputService for OutputService { ) -> Result, Status> { run_unary(&self.sender, move |state| { let output_names = state + .pinnacle .space .outputs() .map(|output| output.name()) @@ -1135,7 +1150,7 @@ impl output_service_server::OutputService for OutputService { let logical_size = output .as_ref() - .and_then(|output| state.space.output_geometry(output)) + .and_then(|output| state.pinnacle.space.output_geometry(output)) .map(|geo| (geo.size.w, geo.size.h)); let current_mode = output @@ -1267,7 +1282,7 @@ impl render_service_server::RenderService for RenderService { run_unary_no_response(&self.sender, move |state| { state.backend.set_upscale_filter(filter); - for output in state.space.outputs().cloned().collect::>() { + for output in state.pinnacle.space.outputs().cloned().collect::>() { state.backend.reset_buffers(&output); state.schedule_render(&output); } @@ -1292,7 +1307,7 @@ impl render_service_server::RenderService for RenderService { run_unary_no_response(&self.sender, move |state| { state.backend.set_downscale_filter(filter); - for output in state.space.outputs().cloned().collect::>() { + for output in state.pinnacle.space.outputs().cloned().collect::>() { state.backend.reset_buffers(&output); state.schedule_render(&output); } diff --git a/src/api/layout.rs b/src/api/layout.rs index c9eb52f..e541f64 100644 --- a/src/api/layout.rs +++ b/src/api/layout.rs @@ -64,7 +64,7 @@ impl layout_service_server::LayoutService for LayoutService { } }, |state, sender, _join_handle| { - state.layout_state.layout_request_sender = Some(sender); + state.pinnacle.layout_state.layout_request_sender = Some(sender); }, ) } diff --git a/src/api/signal.rs b/src/api/signal.rs index 1fea7df..d498aa3 100644 --- a/src/api/signal.rs +++ b/src/api/signal.rs @@ -201,7 +201,7 @@ impl signal_service_server::SignalService for SignalService { let in_stream = request.into_inner(); start_signal_stream(self.sender.clone(), in_stream, |state| { - &mut state.signal_state.output_connect + &mut state.pinnacle.signal_state.output_connect }) } @@ -212,7 +212,7 @@ impl signal_service_server::SignalService for SignalService { let in_stream = request.into_inner(); start_signal_stream(self.sender.clone(), in_stream, |state| { - &mut state.signal_state.output_disconnect + &mut state.pinnacle.signal_state.output_disconnect }) } @@ -223,7 +223,7 @@ impl signal_service_server::SignalService for SignalService { let in_stream = request.into_inner(); start_signal_stream(self.sender.clone(), in_stream, |state| { - &mut state.signal_state.output_resize + &mut state.pinnacle.signal_state.output_resize }) } @@ -234,7 +234,7 @@ impl signal_service_server::SignalService for SignalService { let in_stream = request.into_inner(); start_signal_stream(self.sender.clone(), in_stream, |state| { - &mut state.signal_state.output_move + &mut state.pinnacle.signal_state.output_move }) } @@ -245,7 +245,7 @@ impl signal_service_server::SignalService for SignalService { let in_stream = request.into_inner(); start_signal_stream(self.sender.clone(), in_stream, |state| { - &mut state.signal_state.window_pointer_enter + &mut state.pinnacle.signal_state.window_pointer_enter }) } @@ -256,7 +256,7 @@ impl signal_service_server::SignalService for SignalService { let in_stream = request.into_inner(); start_signal_stream(self.sender.clone(), in_stream, |state| { - &mut state.signal_state.window_pointer_leave + &mut state.pinnacle.signal_state.window_pointer_leave }) } @@ -267,7 +267,7 @@ impl signal_service_server::SignalService for SignalService { let in_stream = request.into_inner(); start_signal_stream(self.sender.clone(), in_stream, |state| { - &mut state.signal_state.tag_active + &mut state.pinnacle.signal_state.tag_active }) } } diff --git a/src/api/window.rs b/src/api/window.rs index 69461ff..162a2e4 100644 --- a/src/api/window.rs +++ b/src/api/window.rs @@ -92,7 +92,11 @@ impl window_service_server::WindowService for WindowService { let Some(window) = window_id.window(state) else { return }; // TODO: with no x or y, defaults unmapped windows to 0, 0 - let mut window_loc = state.space.element_location(&window).unwrap_or_default(); + let mut window_loc = state + .pinnacle + .space + .element_location(&window) + .unwrap_or_default(); window_loc.x = x.unwrap_or(window_loc.x); window_loc.y = y.unwrap_or(window_loc.y); @@ -110,7 +114,7 @@ impl window_service_server::WindowService for WindowService { } }); - for output in state.space.outputs_for_element(&window) { + for output in state.pinnacle.space.outputs_for_element(&window) { state.request_layout(&output); state.schedule_render(&output); } @@ -293,7 +297,7 @@ impl window_service_server::WindowService for WindowService { return; }; - for win in state.space.elements() { + for win in state.pinnacle.space.elements() { win.set_activate(false); } @@ -301,8 +305,8 @@ impl window_service_server::WindowService for WindowService { SetOrToggle::Set => { window.set_activate(true); output.with_state_mut(|state| state.focus_stack.set_focus(window.clone())); - state.output_focus_stack.set_focus(output.clone()); - if let Some(keyboard) = state.seat.get_keyboard() { + state.pinnacle.output_focus_stack.set_focus(output.clone()); + if let Some(keyboard) = state.pinnacle.seat.get_keyboard() { keyboard.set_focus( state, Some(KeyboardFocusTarget::Window(window)), @@ -313,7 +317,7 @@ impl window_service_server::WindowService for WindowService { SetOrToggle::Unset => { if state.focused_window(&output) == Some(window) { output.with_state_mut(|state| state.focus_stack.unset_focus()); - if let Some(keyboard) = state.seat.get_keyboard() { + if let Some(keyboard) = state.pinnacle.seat.get_keyboard() { keyboard.set_focus(state, None, SERIAL_COUNTER.next_serial()); } } @@ -321,14 +325,14 @@ impl window_service_server::WindowService for WindowService { SetOrToggle::Toggle => { if state.focused_window(&output).as_ref() == Some(&window) { output.with_state_mut(|state| state.focus_stack.unset_focus()); - if let Some(keyboard) = state.seat.get_keyboard() { + if let Some(keyboard) = state.pinnacle.seat.get_keyboard() { keyboard.set_focus(state, None, SERIAL_COUNTER.next_serial()); } } else { window.set_activate(true); output.with_state_mut(|state| state.focus_stack.set_focus(window.clone())); - state.output_focus_stack.set_focus(output.clone()); - if let Some(keyboard) = state.seat.get_keyboard() { + state.pinnacle.output_focus_stack.set_focus(output.clone()); + if let Some(keyboard) = state.pinnacle.seat.get_keyboard() { keyboard.set_focus( state, Some(KeyboardFocusTarget::Window(window)), @@ -340,7 +344,7 @@ impl window_service_server::WindowService for WindowService { SetOrToggle::Unspecified => unreachable!(), } - for window in state.space.elements() { + for window in state.pinnacle.space.elements() { if let Some(toplevel) = window.toplevel() { toplevel.send_configure(); } @@ -461,7 +465,11 @@ impl window_service_server::WindowService for WindowService { .ok_or_else(|| Status::invalid_argument("no button specified"))?; run_unary_no_response(&self.sender, move |state| { - let Some(pointer_location) = state.seat.get_pointer().map(|ptr| ptr.current_location()) + let Some(pointer_location) = state + .pinnacle + .seat + .get_pointer() + .map(|ptr| ptr.current_location()) else { return; }; @@ -476,7 +484,7 @@ impl window_service_server::WindowService for WindowService { let Some(wl_surf) = window.wl_surface() else { return; }; - let seat = state.seat.clone(); + let seat = state.pinnacle.seat.clone(); crate::grab::move_grab::move_request_server( state, @@ -500,7 +508,11 @@ impl window_service_server::WindowService for WindowService { .ok_or_else(|| Status::invalid_argument("no button specified"))?; run_unary_no_response(&self.sender, move |state| { - let Some(pointer_loc) = state.seat.get_pointer().map(|ptr| ptr.current_location()) + let Some(pointer_loc) = state + .pinnacle + .seat + .get_pointer() + .map(|ptr| ptr.current_location()) else { return; }; @@ -557,7 +569,7 @@ impl window_service_server::WindowService for WindowService { crate::grab::resize_grab::resize_request_server( state, &wl_surf, - &state.seat.clone(), + &state.pinnacle.seat.clone(), SERIAL_COUNTER.next_serial(), edges.into(), button, @@ -572,6 +584,7 @@ impl window_service_server::WindowService for WindowService { ) -> Result, Status> { run_unary(&self.sender, move |state| { let window_ids = state + .pinnacle .windows .iter() .map(|win| win.with_state(|state| state.id.0)) @@ -603,12 +616,12 @@ impl window_service_server::WindowService for WindowService { let x = window .as_ref() - .and_then(|win| state.space.element_location(win)) + .and_then(|win| state.pinnacle.space.element_location(win)) .map(|loc| loc.x); let y = window .as_ref() - .and_then(|win| state.space.element_location(win)) + .and_then(|win| state.pinnacle.space.element_location(win)) .map(|loc| loc.y); let geometry = if width.is_none() && height.is_none() && x.is_none() && y.is_none() { @@ -691,7 +704,7 @@ impl window_service_server::WindowService for WindowService { .into(); run_unary_no_response(&self.sender, move |state| { - state.config.window_rules.push((cond, rule)); + state.pinnacle.config.window_rules.push((cond, rule)); }) .await } diff --git a/src/backend/dummy.rs b/src/backend/dummy.rs index 704bbcc..836ecaa 100644 --- a/src/backend/dummy.rs +++ b/src/backend/dummy.rs @@ -108,16 +108,19 @@ pub fn setup_dummy( config_dir, )?; - state.output_focus_stack.set_focus(output.clone()); + state.pinnacle.output_focus_stack.set_focus(output.clone()); let dummy = state.backend.dummy_mut(); - state.shm_state.update_formats(dummy.renderer.shm_formats()); + state + .pinnacle + .shm_state + .update_formats(dummy.renderer.shm_formats()); - state.space.map_output(&output, (0, 0)); + state.pinnacle.space.map_output(&output, (0, 0)); - if let Err(err) = state.xwayland.start( - state.loop_handle.clone(), + if let Err(err) = state.pinnacle.xwayland.start( + state.pinnacle.loop_handle.clone(), None, std::iter::empty::<(OsString, OsString)>(), true, @@ -149,11 +152,11 @@ impl State { output.set_preferred(mode); - output.create_global::(&self.display_handle); + output.create_global::(&self.pinnacle.display_handle); - self.space.map_output(&output, (0, 0)); + self.pinnacle.space.map_output(&output, (0, 0)); - self.signal_state.output_connect.signal(|buf| { + self.pinnacle.signal_state.output_connect.signal(|buf| { buf.push_back(OutputConnectResponse { output_name: Some(output.name()), }); @@ -161,12 +164,15 @@ impl State { } pub fn remove_output(&mut self, output: &Output) { - self.space.unmap_output(output); + self.pinnacle.space.unmap_output(output); - self.signal_state.output_disconnect.signal(|buffer| { - buffer.push_back(OutputDisconnectResponse { - output_name: Some(output.name()), - }) - }); + self.pinnacle + .signal_state + .output_disconnect + .signal(|buffer| { + buffer.push_back(OutputDisconnectResponse { + output_name: Some(output.name()), + }) + }); } } diff --git a/src/backend/udev.rs b/src/backend/udev.rs index 52f788d..689b9b6 100644 --- a/src/backend/udev.rs +++ b/src/backend/udev.rs @@ -432,7 +432,7 @@ pub fn setup_udev( udev.session.clone().into(), ); libinput_context - .udev_assign_seat(state.seat.name()) + .udev_assign_seat(state.pinnacle.seat.name()) .expect("failed to assign seat to libinput"); let libinput_backend = LibinputInputBackend::new(libinput_context.clone()); @@ -576,7 +576,7 @@ pub fn setup_udev( } } - for output in state.space.outputs().cloned().collect::>() { + for output in state.pinnacle.space.outputs().cloned().collect::>() { state.schedule_render(&output); } } @@ -584,7 +584,7 @@ pub fn setup_udev( }) .expect("failed to insert libinput notifier into event loop"); - state.shm_state.update_formats( + state.pinnacle.shm_state.update_formats( udev.gpu_manager .single_renderer(&primary_gpu)? .shm_formats(), @@ -676,8 +676,8 @@ pub fn setup_udev( }); }); - if let Err(err) = state.xwayland.start( - state.loop_handle.clone(), + if let Err(err) = state.pinnacle.xwayland.start( + state.pinnacle.loop_handle.clone(), None, std::iter::empty::<(OsString, OsString)>(), true, @@ -903,6 +903,7 @@ impl State { let gbm = GbmDevice::new(fd).map_err(DeviceAddError::GbmDevice)?; let registration_token = self + .pinnacle .loop_handle .insert_source(notifier, move |event, metadata, state| match event { DrmEvent::VBlank(crtc) => { @@ -1011,7 +1012,7 @@ impl State { let (phys_w, phys_h) = connector.size().unwrap_or((0, 0)); - if self.space.outputs().any(|op| { + if self.pinnacle.space.outputs().any(|op| { op.user_data() .get::() .is_some_and(|op_id| op_id.crtc == crtc) @@ -1034,10 +1035,10 @@ impl State { output.set_preferred(wl_mode); - self.output_focus_stack.set_focus(output.clone()); + self.pinnacle.output_focus_stack.set_focus(output.clone()); - let x = self.space.outputs().fold(0, |acc, o| { - let Some(geo) = self.space.output_geometry(o) else { + let x = self.pinnacle.space.outputs().fold(0, |acc, o| { + let Some(geo) = self.pinnacle.space.output_geometry(o) else { unreachable!() }; acc + geo.size.w @@ -1116,6 +1117,7 @@ impl State { // In this case, restore its tags and location. // TODO: instead of checking the connector, check the monitor's edid info instead if let Some(saved_state) = self + .pinnacle .config .connector_saved_states .get(&OutputName(output.name())) @@ -1124,7 +1126,7 @@ impl State { output.with_state_mut(|state| state.tags = tags.clone()); self.change_output_state(&output, None, None, *scale, Some(*loc)); } else { - self.signal_state.output_connect.signal(|buffer| { + self.pinnacle.signal_state.output_connect.signal(|buffer| { buffer.push_back(OutputConnectResponse { output_name: Some(output.name()), }) @@ -1152,6 +1154,7 @@ impl State { device.surfaces.remove(&crtc); let output = self + .pinnacle .space .outputs() .find(|o| { @@ -1164,7 +1167,7 @@ impl State { if let Some(output) = output { // Save this output's state. It will be restored if the monitor gets replugged. - self.config.connector_saved_states.insert( + self.pinnacle.config.connector_saved_states.insert( OutputName(output.name()), ConnectorSavedState { loc: output.current_location(), @@ -1172,14 +1175,19 @@ impl State { scale: Some(output.current_scale()), }, ); - self.space.unmap_output(&output); - self.gamma_control_manager_state.output_removed(&output); + self.pinnacle.space.unmap_output(&output); + self.pinnacle + .gamma_control_manager_state + .output_removed(&output); - self.signal_state.output_disconnect.signal(|buffer| { - buffer.push_back(OutputDisconnectResponse { - output_name: Some(output.name()), - }) - }); + self.pinnacle + .signal_state + .output_disconnect + .signal(|buffer| { + buffer.push_back(OutputDisconnectResponse { + output_name: Some(output.name()), + }) + }); } } @@ -1241,7 +1249,9 @@ impl State { .as_mut() .remove_node(&backend_data.render_node); - self.loop_handle.remove(backend_data.registration_token); + self.pinnacle + .loop_handle + .remove(backend_data.registration_token); tracing::debug!("Dropping device"); } @@ -1264,7 +1274,7 @@ impl State { return; }; - let output = if let Some(output) = self.space.outputs().find(|o| { + let output = if let Some(output) = self.pinnacle.space.outputs().find(|o| { let udev_op_data = o.user_data().get::(); udev_op_data .is_some_and(|data| data.device_id == surface.device_id && data.crtc == crtc) @@ -1299,7 +1309,10 @@ impl State { | wp_presentation_feedback::Kind::HwCompletion, ) } else { - (self.clock.now(), wp_presentation_feedback::Kind::Vsync) + ( + self.pinnacle.clock.now(), + wp_presentation_feedback::Kind::Vsync, + ) }; feedback.presented( @@ -1330,10 +1343,13 @@ impl State { if dirty { self.schedule_render(&output); } else { - for window in self.windows.iter() { - window.send_frame(&output, self.clock.now(), Some(Duration::ZERO), |_, _| { - Some(output.clone()) - }); + for window in self.pinnacle.windows.iter() { + window.send_frame( + &output, + self.pinnacle.clock.now(), + Some(Duration::ZERO), + |_, _| Some(output.clone()), + ); } } } @@ -1353,7 +1369,7 @@ impl State { let frame = udev.pointer_image.get_image( 1, // output.current_scale().integer_scale() as u32, - self.clock.now().into(), + self.pinnacle.clock.now().into(), ); let render_node = surface.render_node; @@ -1398,9 +1414,10 @@ impl State { texture }); - let windows = self.space.elements().cloned().collect::>(); + let windows = self.pinnacle.space.elements().cloned().collect::>(); let pointer_location = self + .pinnacle .seat .get_pointer() .map(|ptr| ptr.current_location()) @@ -1411,21 +1428,22 @@ impl State { // draw the cursor as relevant and // reset the cursor if the surface is no longer alive - if let CursorImageStatus::Surface(surface) = &self.cursor_status { + if let CursorImageStatus::Surface(surface) = &self.pinnacle.cursor_status { if !surface.alive() { - self.cursor_status = CursorImageStatus::default_named(); + self.pinnacle.cursor_status = CursorImageStatus::default_named(); } else { send_frames_surface_tree( surface, output, - self.clock.now(), + self.pinnacle.clock.now(), Some(Duration::ZERO), |_, _| None, ); } } - udev.pointer_element.set_status(self.cursor_status.clone()); + udev.pointer_element + .set_status(self.pinnacle.cursor_status.clone()); let pending_screencopy_with_cursor = output.with_state(|state| state.screencopy.as_ref().map(|sc| sc.overlay_cursor())); @@ -1449,10 +1467,10 @@ impl State { let pointer_render_elements = pointer_render_elements( output, &mut renderer, - &self.space, + &self.pinnacle.space, pointer_location, - &mut self.cursor_status, - self.dnd_icon.as_ref(), + &mut self.pinnacle.cursor_status, + self.pinnacle.dnd_icon.as_ref(), &udev.pointer_element, ); udev.pointer_element.set_element_kind(element::Kind::Cursor); @@ -1463,10 +1481,10 @@ impl State { let pointer_render_elements = pointer_render_elements( output, &mut renderer, - &self.space, + &self.pinnacle.space, pointer_location, - &mut self.cursor_status, - self.dnd_icon.as_ref(), + &mut self.pinnacle.cursor_status, + self.pinnacle.dnd_icon.as_ref(), &udev.pointer_element, ); output_render_elements.extend(pointer_render_elements); @@ -1476,7 +1494,7 @@ impl State { output_render_elements.extend(crate::render::output_render_elements( output, &mut renderer, - &self.space, + &self.pinnacle.space, &windows, )); @@ -1499,13 +1517,13 @@ impl State { output, surface, &render_frame_result, - &self.loop_handle, + &self.pinnacle.loop_handle, ); super::post_repaint( output, &render_frame_result.states, - &self.space, + &self.pinnacle.space, surface .dmabuf_feedback .as_ref() @@ -1513,15 +1531,18 @@ impl State { render_feedback: &feedback.render_feedback, scanout_feedback: &feedback.scanout_feedback, }), - Duration::from(self.clock.now()), - &self.cursor_status, + Duration::from(self.pinnacle.clock.now()), + &self.pinnacle.cursor_status, ); let rendered = !render_frame_result.is_empty; if rendered { - let output_presentation_feedback = - take_presentation_feedback(output, &self.space, &render_frame_result.states); + let output_presentation_feedback = take_presentation_feedback( + output, + &self.pinnacle.space, + &render_frame_result.states, + ); surface .compositor diff --git a/src/backend/winit.rs b/src/backend/winit.rs index 29b1d4d..2517157 100644 --- a/src/backend/winit.rs +++ b/src/backend/winit.rs @@ -190,18 +190,19 @@ pub fn setup_winit( // wl-mirror segfaults if it gets a wl-output global before the xdg output manager global output.create_global::(&display_handle); - state.output_focus_stack.set_focus(output.clone()); + state.pinnacle.output_focus_stack.set_focus(output.clone()); let winit = state.backend.winit_mut(); state + .pinnacle .shm_state .update_formats(winit.backend.renderer().shm_formats()); - state.space.map_output(&output, (0, 0)); + state.pinnacle.space.map_output(&output, (0, 0)); - if let Err(err) = state.xwayland.start( - state.loop_handle.clone(), + if let Err(err) = state.pinnacle.xwayland.start( + state.pinnacle.loop_handle.clone(), None, std::iter::empty::<(OsString, OsString)>(), true, @@ -210,49 +211,49 @@ pub fn setup_winit( error!("Failed to start XWayland: {err}"); } - let insert_ret = - state - .loop_handle - .insert_source(Timer::immediate(), move |_instant, _metadata, state| { - let status = winit_evt_loop.dispatch_new_events(|event| match event { - WinitEvent::Resized { size, scale_factor } => { - let mode = smithay::output::Mode { - size, - refresh: 144_000, - }; - state.change_output_state( - &output, - Some(mode), - None, - Some(Scale::Fractional(scale_factor)), - None, - ); - state.request_layout(&output); + let insert_ret = state.pinnacle.loop_handle.insert_source( + Timer::immediate(), + move |_instant, _metadata, state| { + let status = winit_evt_loop.dispatch_new_events(|event| match event { + WinitEvent::Resized { size, scale_factor } => { + let mode = smithay::output::Mode { + size, + refresh: 144_000, + }; + state.change_output_state( + &output, + Some(mode), + None, + Some(Scale::Fractional(scale_factor)), + None, + ); + state.request_layout(&output); + } + WinitEvent::Focus(focused) => { + if focused { + state.backend.winit_mut().reset_buffers(&output); } - WinitEvent::Focus(focused) => { - if focused { - state.backend.winit_mut().reset_buffers(&output); - } - } - WinitEvent::Input(input_evt) => { - state.process_input_event(input_evt); - } - WinitEvent::Redraw => { - state.render_winit_window(&output); - } - WinitEvent::CloseRequested => { - state.shutdown(); - } - }); - - if let PumpStatus::Exit(_) = status { + } + WinitEvent::Input(input_evt) => { + state.process_input_event(input_evt); + } + WinitEvent::Redraw => { + state.render_winit_window(&output); + } + WinitEvent::CloseRequested => { state.shutdown(); } - - state.render_winit_window(&output); - - TimeoutAction::ToDuration(Duration::from_micros(((1.0 / 144.0) * 1000000.0) as u64)) }); + + if let PumpStatus::Exit(_) = status { + state.shutdown(); + } + + state.render_winit_window(&output); + + TimeoutAction::ToDuration(Duration::from_micros(((1.0 / 144.0) * 1000000.0) as u64)) + }, + ); if let Err(err) = insert_ret { anyhow::bail!("Failed to insert winit events into event loop: {err}"); } @@ -267,21 +268,21 @@ impl State { let full_redraw = &mut winit.full_redraw; *full_redraw = full_redraw.saturating_sub(1); - if let CursorImageStatus::Surface(surface) = &self.cursor_status { + if let CursorImageStatus::Surface(surface) = &self.pinnacle.cursor_status { if !surface.alive() { - self.cursor_status = CursorImageStatus::default_named(); + self.pinnacle.cursor_status = CursorImageStatus::default_named(); } } - let cursor_visible = !matches!(self.cursor_status, CursorImageStatus::Surface(_)); + let cursor_visible = !matches!(self.pinnacle.cursor_status, CursorImageStatus::Surface(_)); let mut pointer_element = PointerElement::::new(); - pointer_element.set_status(self.cursor_status.clone()); + pointer_element.set_status(self.pinnacle.cursor_status.clone()); // The z-index of these is determined by `state.fixup_z_layering()`, which is called at the end // of every event loop cycle - let windows = self.space.elements().cloned().collect::>(); + let windows = self.pinnacle.space.elements().cloned().collect::>(); let mut output_render_elements = Vec::new(); @@ -299,6 +300,7 @@ impl State { // but it shouldn't meaningfully affect anything. if !pending_screencopy_without_cursor { let pointer_location = self + .pinnacle .seat .get_pointer() .map(|ptr| ptr.current_location()) @@ -307,10 +309,10 @@ impl State { let pointer_render_elements = pointer_render_elements( output, winit.backend.renderer(), - &self.space, + &self.pinnacle.space, pointer_location, - &mut self.cursor_status, - self.dnd_icon.as_ref(), + &mut self.pinnacle.cursor_status, + self.pinnacle.dnd_icon.as_ref(), &pointer_element, ); output_render_elements.extend(pointer_render_elements); @@ -319,7 +321,7 @@ impl State { output_render_elements.extend(crate::render::output_render_elements( output, winit.backend.renderer(), - &self.space, + &self.pinnacle.space, &windows, )); @@ -347,7 +349,7 @@ impl State { &mut winit.backend, output, &render_output_result, - &self.loop_handle, + &self.pinnacle.loop_handle, ); let has_rendered = render_output_result.damage.is_some(); @@ -359,21 +361,21 @@ impl State { winit.backend.window().set_cursor_visible(cursor_visible); - let time = self.clock.now(); + let time = self.pinnacle.clock.now(); super::post_repaint( output, &render_output_result.states, - &self.space, + &self.pinnacle.space, None, time.into(), - &self.cursor_status, + &self.pinnacle.cursor_status, ); if has_rendered { let mut output_presentation_feedback = take_presentation_feedback( output, - &self.space, + &self.pinnacle.space, &render_output_result.states, ); output_presentation_feedback.presented( diff --git a/src/backend/wlcs.rs b/src/backend/wlcs.rs index 6c7f560..6536028 100644 --- a/src/backend/wlcs.rs +++ b/src/backend/wlcs.rs @@ -80,11 +80,11 @@ pub fn setup_wlcs_dummy() -> anyhow::Result<(State, EventLoop<'static, State>)> None, )?; - state.output_focus_stack.set_focus(output.clone()); + state.pinnacle.output_focus_stack.set_focus(output.clone()); - state.shm_state.update_formats(shm_formats); + state.pinnacle.shm_state.update_formats(shm_formats); - state.space.map_output(&output, (0, 0)); + state.pinnacle.space.map_output(&output, (0, 0)); Ok((state, event_loop)) } @@ -96,7 +96,7 @@ impl State { { // Clear state debug!("Clearing tags"); - for output in self.space.outputs() { + for output in self.pinnacle.space.outputs() { output.with_state_mut(|state| state.tags.clear()); } @@ -104,22 +104,23 @@ impl State { debug!("Clearing input state"); - self.input_state.clear(); + self.pinnacle.input_state.clear(); - self.config.clear(&self.loop_handle); + self.pinnacle.config.clear(&self.pinnacle.loop_handle); - self.signal_state.clear(); + self.pinnacle.signal_state.clear(); - self.input_state.reload_keybind = None; - self.input_state.kill_keybind = None; + self.pinnacle.input_state.reload_keybind = None; + self.pinnacle.input_state.kill_keybind = None; - if self.grpc_server_join_handle.is_none() { + if self.pinnacle.grpc_server_join_handle.is_none() { self.start_grpc_server(socket_dir)?; } let (pinger, ping_source) = calloop::ping::make_ping()?; let token = self + .pinnacle .loop_handle .insert_source(ping_source, move |_, _, _state| {})?; @@ -128,7 +129,7 @@ impl State { pinger.ping(); }); - self.config.config_reload_on_crash_token = Some(token); + self.pinnacle.config.config_reload_on_crash_token = Some(token); Ok(()) } diff --git a/src/config.rs b/src/config.rs index 4c335e8..95be112 100644 --- a/src/config.rs +++ b/src/config.rs @@ -276,7 +276,7 @@ impl State { // Clear state debug!("Clearing tags"); - for output in self.space.outputs() { + for output in self.pinnacle.space.outputs() { output.with_state_mut(|state| state.tags.clear()); } @@ -284,11 +284,11 @@ impl State { debug!("Clearing input state"); - self.input_state.clear(); + self.pinnacle.input_state.clear(); - self.config.clear(&self.loop_handle); + self.pinnacle.config.clear(&self.pinnacle.loop_handle); - self.signal_state.clear(); + self.pinnacle.signal_state.clear(); let config_dir_clone = config_dir.as_ref().map(|dir| dir.as_ref().to_path_buf()); let load_default_config = |state: &mut State, reason: &str| { @@ -304,7 +304,7 @@ impl State { }; // If `--no-config` was set, still load the keybinds from the default metaconfig - if self.config.no_config { + if self.pinnacle.config.no_config { config_dir = None; } @@ -328,17 +328,17 @@ impl State { let reload_keybind = (reload_mask, Keysym::from(reload_keybind.key as u32)); let kill_keybind = (kill_mask, Keysym::from(kill_keybind.key as u32)); - self.input_state.reload_keybind = Some(reload_keybind); - self.input_state.kill_keybind = Some(kill_keybind); + self.pinnacle.input_state.reload_keybind = Some(reload_keybind); + self.pinnacle.input_state.kill_keybind = Some(kill_keybind); - if self.config.no_config { + if self.pinnacle.config.no_config { info!("`--no-config` was set, not spawning config"); return Ok(()); } // Because the grpc server is implemented to only start once, // any updates to `socket_dir` won't be applied until restart. - if self.grpc_server_join_handle.is_none() { + if self.pinnacle.grpc_server_join_handle.is_none() { // If a socket is provided in the metaconfig, use it. let socket_dir = if let Some(socket_dir) = &metaconfig.socket_dir { let Some(config_dir) = &config_dir else { @@ -356,7 +356,8 @@ impl State { socket_dir } else { // Otherwise, use $XDG_RUNTIME_DIR. If that doesn't exist, use /tmp. - self.xdg_base_dirs + self.pinnacle + .xdg_base_dirs .get_runtime_directory() .cloned() .unwrap_or(PathBuf::from(DEFAULT_SOCKET_DIR)) @@ -448,30 +449,32 @@ impl State { let (pinger, ping_source) = calloop::ping::make_ping()?; - let token = self - .loop_handle - .insert_source(ping_source, move |_, _, state| { - error!("Config crashed! Falling back to default config"); - state - .start_config(None::) - .expect("failed to start default config"); - })?; + let token = + self.pinnacle + .loop_handle + .insert_source(ping_source, move |_, _, state| { + error!("Config crashed! Falling back to default config"); + state + .start_config(None::) + .expect("failed to start default config"); + })?; - self.config.config_join_handle = Some(tokio::spawn(async move { + self.pinnacle.config.config_join_handle = Some(tokio::spawn(async move { let _ = child.wait().await; pinger.ping(); })); - self.config.config_reload_on_crash_token = Some(token); + self.pinnacle.config.config_reload_on_crash_token = Some(token); } None => { let (pinger, ping_source) = calloop::ping::make_ping()?; - let token = self - .loop_handle - .insert_source(ping_source, move |_, _, _state| { - panic!("builtin rust config crashed; this is a bug"); - })?; + let token = + self.pinnacle + .loop_handle + .insert_source(ping_source, move |_, _, _state| { + panic!("builtin rust config crashed; this is a bug"); + })?; std::thread::spawn(move || { info!("Starting builtin Rust config"); @@ -479,7 +482,7 @@ impl State { pinger.ping(); }); - self.config.config_reload_on_crash_token = Some(token); + self.pinnacle.config.config_reload_on_crash_token = Some(token); } } @@ -487,10 +490,12 @@ impl State { } pub fn start_grpc_server(&mut self, socket_dir: &Path) -> anyhow::Result<()> { - self.system_processes + self.pinnacle + .system_processes .refresh_processes_specifics(ProcessRefreshKind::new()); let multiple_instances = self + .pinnacle .system_processes .processes_by_exact_name("pinnacle") .filter(|proc| proc.thread_kind().is_none()) @@ -539,13 +544,14 @@ impl State { std::env::set_var( "PINNACLE_PROTO_DIR", - self.xdg_base_dirs.get_data_file("protobuf"), + self.pinnacle.xdg_base_dirs.get_data_file("protobuf"), ); let (grpc_sender, grpc_receiver) = calloop::channel::channel::>(); - self.loop_handle + self.pinnacle + .loop_handle .insert_source(grpc_receiver, |msg, _, state| match msg { Event::Msg(f) => f(state), Event::Closed => error!("grpc receiver was closed"), @@ -583,9 +589,9 @@ impl State { .add_service(LayoutServiceServer::new(layout_service)) .add_service(RenderServiceServer::new(render_service)); - match self.xdisplay.as_ref() { + match self.pinnacle.xdisplay.as_ref() { Some(_) => { - self.grpc_server_join_handle = Some(tokio::spawn(async move { + self.pinnacle.grpc_server_join_handle = Some(tokio::spawn(async move { if let Err(err) = grpc_server.serve_with_incoming(uds_stream).await { error!("gRPC server error: {err}"); } @@ -595,9 +601,9 @@ impl State { // | fast at startup then I think there's a chance that the gRPC server // | could get started twice. None => self.schedule( - |state| state.xdisplay.is_some(), + |state| state.pinnacle.xdisplay.is_some(), move |state| { - state.grpc_server_join_handle = Some(tokio::spawn(async move { + state.pinnacle.grpc_server_join_handle = Some(tokio::spawn(async move { if let Err(err) = grpc_server.serve_with_incoming(uds_stream).await { error!("gRPC server error: {err}"); } diff --git a/src/focus.rs b/src/focus.rs index 6f714ed..a7e6f1c 100644 --- a/src/focus.rs +++ b/src/focus.rs @@ -47,16 +47,20 @@ impl State { } } - self.seat.get_keyboard().expect("no keyboard").set_focus( - self, - current_focus.map(|win| win.into()), - SERIAL_COUNTER.next_serial(), - ); + self.pinnacle + .seat + .get_keyboard() + .expect("no keyboard") + .set_focus( + self, + current_focus.map(|win| win.into()), + SERIAL_COUNTER.next_serial(), + ); } pub fn fixup_z_layering(&mut self) { - for win in self.z_index_stack.iter() { - self.space.raise_element(win, false); + for win in self.pinnacle.z_index_stack.iter() { + self.pinnacle.space.raise_element(win, false); } } @@ -64,25 +68,26 @@ impl State { /// /// This does nothing if the window is unmapped. pub fn raise_window(&mut self, window: WindowElement, activate: bool) { - if self.space.elements().all(|win| win != &window) { + if self.pinnacle.space.elements().all(|win| win != &window) { warn!("Tried to raise an unmapped window"); return; } - self.space.raise_element(&window, activate); + self.pinnacle.space.raise_element(&window, activate); - self.z_index_stack.retain(|win| win != &window); - self.z_index_stack.push(window); + self.pinnacle.z_index_stack.retain(|win| win != &window); + self.pinnacle.z_index_stack.push(window); - self.fixup_xwayland_internal_z_indices(); + self.fixup_xwayland_window_layering(); } /// Get the currently focused output, or the first mapped output if there is none, or None. pub fn focused_output(&self) -> Option<&Output> { - self.output_focus_stack + self.pinnacle + .output_focus_stack .stack .last() - .or_else(|| self.space.outputs().next()) + .or_else(|| self.pinnacle.space.outputs().next()) } } diff --git a/src/focus/pointer.rs b/src/focus/pointer.rs index b507782..30a89fd 100644 --- a/src/focus/pointer.rs +++ b/src/focus/pointer.rs @@ -35,6 +35,7 @@ impl PointerFocusTarget { pub fn window_for(&self, state: &State) -> Option { match self { PointerFocusTarget::WlSurface(surf) => state + .pinnacle .windows .iter() .find(|win| { @@ -51,6 +52,7 @@ impl PointerFocusTarget { }) .cloned(), PointerFocusTarget::X11Surface(surf) => state + .pinnacle .windows .iter() .find(|win| win.x11_surface() == Some(surf)) @@ -61,7 +63,7 @@ impl PointerFocusTarget { pub fn layer_for(&self, state: &State) -> Option { match self { PointerFocusTarget::WlSurface(surf) => { - for output in state.space.outputs() { + for output in state.pinnacle.space.outputs() { let map = layer_map_for_output(output); for layer in map.layers() { let mut found = false; @@ -83,7 +85,7 @@ impl PointerFocusTarget { pub fn popup_for(&self, state: &State) -> Option { match self { - PointerFocusTarget::WlSurface(surf) => state.popup_manager.find_popup(surf), + PointerFocusTarget::WlSurface(surf) => state.pinnacle.popup_manager.find_popup(surf), PointerFocusTarget::X11Surface(_) => None, } } @@ -121,7 +123,8 @@ impl PointerTarget for PointerFocusTarget { if let Some(window) = self.window_for(data) { let window_id = Some(window.with_state(|state| state.id.0)); - data.signal_state + data.pinnacle + .signal_state .window_pointer_enter .signal(|buffer| buffer.push_back(WindowPointerEnterResponse { window_id })); } @@ -312,7 +315,8 @@ impl PointerTarget for PointerFocusTarget { if let Some(window) = self.window_for(data) { let window_id = Some(window.with_state(|state| state.id.0)); - data.signal_state + data.pinnacle + .signal_state .window_pointer_leave .signal(|buffer| buffer.push_back(WindowPointerLeaveResponse { window_id })); } diff --git a/src/grab/move_grab.rs b/src/grab/move_grab.rs index 6d34af1..828c6a7 100644 --- a/src/grab/move_grab.rs +++ b/src/grab/move_grab.rs @@ -56,6 +56,7 @@ impl PointerGrab for MoveSurfaceGrab { // INFO: can you raise OR windows or no idk if !surface.is_override_redirect() { state + .pinnacle .xwm .as_mut() .expect("no xwm") @@ -72,11 +73,12 @@ impl PointerGrab for MoveSurfaceGrab { // INFO: this is being used instead of space.element_under(event.location) because that // | uses the bounding box, which is different from the actual geometry let window_under = state + .pinnacle .space .elements() .rev() .find(|&win| { - if let Some(loc) = state.space.element_location(win) { + if let Some(loc) = state.pinnacle.space.element_location(win) { let size = win.geometry().size; let rect = Rectangle { size, loc }; rect.contains(event.location.to_i32_round()) @@ -87,7 +89,7 @@ impl PointerGrab for MoveSurfaceGrab { .cloned(); if let Some(window_under) = window_under { - if state.layout_state.pending_swap { + if state.pinnacle.layout_state.pending_swap { return; } @@ -96,10 +98,12 @@ impl PointerGrab for MoveSurfaceGrab { } if state + .pinnacle .space .element_geometry(&self.window) .is_some_and(|geo| { state + .pinnacle .space .element_geometry(&window_under) .is_some_and(|geo2| geo.overlaps(geo2)) @@ -120,9 +124,13 @@ impl PointerGrab for MoveSurfaceGrab { } else { let delta = event.location - self.start_data.location; let new_loc = (self.initial_window_loc.to_f64() + delta).to_i32_round(); - state.space.map_element(self.window.clone(), new_loc, true); + state + .pinnacle + .space + .map_element(self.window.clone(), new_loc, true); let size = state + .pinnacle .space .element_geometry(&self.window) .expect("window wasn't mapped") @@ -145,7 +153,7 @@ impl PointerGrab for MoveSurfaceGrab { } } - let outputs = state.space.outputs_for_element(&self.window); + let outputs = state.pinnacle.space.outputs_for_element(&self.window); for output in outputs { state.schedule_render(&output); } @@ -278,6 +286,7 @@ pub fn move_request_client( }; let initial_window_loc = state + .pinnacle .space .element_location(&window) .expect("move request was called on an unmapped window"); @@ -309,6 +318,7 @@ pub fn move_request_server( }; let initial_window_loc = state + .pinnacle .space .element_location(&window) .expect("move request was called on an unmapped window"); diff --git a/src/grab/resize_grab.rs b/src/grab/resize_grab.rs index fb4d0a1..718ee75 100644 --- a/src/grab/resize_grab.rs +++ b/src/grab/resize_grab.rs @@ -204,6 +204,7 @@ impl PointerGrab for ResizeSurfaceGrab { WindowSurface::X11(surface) => { if !surface.is_override_redirect() { let loc = data + .pinnacle .space .element_location(&self.window) .expect("failed to get x11 win loc"); @@ -366,7 +367,7 @@ pub fn move_surface_if_resized(state: &mut State, surface: &WlSurface) { return; }; - let Some(mut window_loc) = state.space.element_location(&window) else { + let Some(mut window_loc) = state.pinnacle.space.element_location(&window) else { return; }; let geometry = window.geometry(); @@ -413,6 +414,7 @@ pub fn move_surface_if_resized(state: &mut State, surface: &WlSurface) { } let size = state + .pinnacle .space .element_geometry(&window) .expect("called element_geometry on unmapped window") @@ -426,7 +428,10 @@ pub fn move_surface_if_resized(state: &mut State, surface: &WlSurface) { }); if new_loc.0.is_some() || new_loc.1.is_some() { - state.space.map_element(window.clone(), window_loc, false); + state + .pinnacle + .space + .map_element(window.clone(), window_loc, false); if let Some(surface) = window.x11_surface() { if !surface.is_override_redirect() { @@ -463,6 +468,7 @@ pub fn resize_request_client( } let initial_window_loc = state + .pinnacle .space .element_location(&window) .expect("resize request called on unmapped window"); @@ -513,6 +519,7 @@ pub fn resize_request_server( } let initial_window_loc = state + .pinnacle .space .element_location(&window) .expect("resize request called on unmapped window"); diff --git a/src/handlers.rs b/src/handlers.rs index bdc7648..385e80b 100644 --- a/src/handlers.rs +++ b/src/handlers.rs @@ -76,7 +76,7 @@ impl BufferHandler for State { impl CompositorHandler for State { fn compositor_state(&mut self) -> &mut CompositorState { - &mut self.compositor_state + &mut self.pinnacle.compositor_state } fn new_surface(&mut self, surface: &WlSurface) { @@ -97,12 +97,16 @@ impl CompositorHandler for State { let client = surface .client() .expect("Surface has no client/is no longer alive"); - let res = state.loop_handle.insert_source(source, move |_, _, state| { + let res = state - .client_compositor_state(&client) - .blocker_cleared(state, &state.display_handle.clone()); - Ok(()) - }); + .pinnacle + .loop_handle + .insert_source(source, move |_, _, state| { + state + .client_compositor_state(&client) + .blocker_cleared(state, &state.pinnacle.display_handle.clone()); + Ok(()) + }); if res.is_ok() { compositor::add_blocker(surface, blocker); } @@ -129,14 +133,15 @@ impl CompositorHandler for State { if let Some(window) = self.window_for_surface(&root) { window.on_commit(); if let Some(loc) = window.with_state_mut(|state| state.target_loc.take()) { - self.space.map_element(window.clone(), loc, false); + self.pinnacle.space.map_element(window.clone(), loc, false); } } }; - self.popup_manager.commit(surface); + self.pinnacle.popup_manager.commit(surface); if let Some(new_window) = self + .pinnacle .new_windows .iter() .find(|win| win.wl_surface().as_ref() == Some(surface)) @@ -149,8 +154,8 @@ impl CompositorHandler for State { }; if is_mapped { - self.new_windows.retain(|win| win != &new_window); - self.windows.push(new_window.clone()); + self.pinnacle.new_windows.retain(|win| win != &new_window); + self.pinnacle.windows.push(new_window.clone()); if let Some(output) = self.focused_output() { tracing::debug!("Placing toplevel"); @@ -161,7 +166,8 @@ impl CompositorHandler for State { // FIXME: I'm mapping way offscreen here then sending a frame to prevent a window from // | mapping with its default geometry then immediately resizing // | because I don't set a target geometry before the initial configure. - self.space + self.pinnacle + .space .map_element(new_window.clone(), (1000000, 0), true); self.raise_window(new_window.clone(), true); @@ -172,14 +178,15 @@ impl CompositorHandler for State { self.request_layout(&focused_output); new_window.send_frame( &focused_output, - self.clock.now(), + self.pinnacle.clock.now(), Some(Duration::ZERO), surface_primary_scanout_output, ); } - self.loop_handle.insert_idle(move |state| { + self.pinnacle.loop_handle.insert_idle(move |state| { state + .pinnacle .seat .get_keyboard() .expect("Seat had no keyboard") // FIXME: actually handle error @@ -202,7 +209,7 @@ impl CompositorHandler for State { crate::grab::resize_grab::move_surface_if_resized(self, surface); let outputs = if let Some(window) = self.window_for_surface(surface) { - let mut outputs = self.space.outputs_for_element(&window); + let mut outputs = self.pinnacle.space.outputs_for_element(&window); // When the window hasn't been mapped `outputs` is empty, // so also trigger a render using the window's tags' output @@ -211,24 +218,26 @@ impl CompositorHandler for State { } outputs // surface is a window } else if let Some(window) = self.window_for_surface(&root) { - let mut outputs = self.space.outputs_for_element(&window); + let mut outputs = self.pinnacle.space.outputs_for_element(&window); if let Some(output) = window.output(self) { outputs.push(output); } outputs // surface is a root window - } else if let Some(PopupKind::Xdg(surf)) = self.popup_manager.find_popup(surface) { + } else if let Some(PopupKind::Xdg(surf)) = self.pinnacle.popup_manager.find_popup(surface) { let geo = surf.with_pending_state(|state| state.geometry); let outputs = self + .pinnacle .space .outputs() .filter_map(|output| { - let op_geo = self.space.output_geometry(output); + let op_geo = self.pinnacle.space.output_geometry(output); op_geo.and_then(|op_geo| op_geo.overlaps_or_touches(geo).then_some(output)) }) .cloned() .collect::>(); outputs } else if let Some(output) = self + .pinnacle .space .outputs() .find(|op| { @@ -285,7 +294,7 @@ fn ensure_initial_configure(surface: &WlSurface, state: &mut State) { return; } - if let Some(popup) = state.popup_manager.find_popup(surface) { + if let Some(popup) = state.pinnacle.popup_manager.find_popup(surface) { let PopupKind::Xdg(popup) = &popup else { return }; let initial_configure_sent = compositor::with_states(surface, |states| { states @@ -304,7 +313,7 @@ fn ensure_initial_configure(surface: &WlSurface, state: &mut State) { return; } - if let Some(output) = state.space.outputs().find(|op| { + if let Some(output) = state.pinnacle.space.outputs().find(|op| { let map = layer_map_for_output(op); map.layer_for_surface(surface, WindowSurfaceType::TOPLEVEL) .is_some() @@ -338,11 +347,11 @@ impl ClientDndGrabHandler for State { icon: Option, _seat: Seat, ) { - self.dnd_icon = icon; + self.pinnacle.dnd_icon = icon; } fn dropped(&mut self, _seat: Seat) { - self.dnd_icon = None; + self.pinnacle.dnd_icon = None; } } @@ -357,7 +366,7 @@ impl SelectionHandler for State { source: Option, _seat: Seat, ) { - if let Some(xwm) = self.xwm.as_mut() { + if let Some(xwm) = self.pinnacle.xwm.as_mut() { if let Err(err) = xwm.new_selection(ty, source.map(|source| source.mime_types())) { tracing::warn!(?err, ?ty, "Failed to set Xwayland selection"); } @@ -372,8 +381,10 @@ impl SelectionHandler for State { _seat: Seat, _user_data: &(), ) { - if let Some(xwm) = self.xwm.as_mut() { - if let Err(err) = xwm.send_selection(ty, mime_type, fd, self.loop_handle.clone()) { + if let Some(xwm) = self.pinnacle.xwm.as_mut() { + if let Err(err) = + xwm.send_selection(ty, mime_type, fd, self.pinnacle.loop_handle.clone()) + { tracing::warn!(?err, "Failed to send primary (X11 -> Wayland)"); } } @@ -382,21 +393,21 @@ impl SelectionHandler for State { impl DataDeviceHandler for State { fn data_device_state(&self) -> &DataDeviceState { - &self.data_device_state + &self.pinnacle.data_device_state } } delegate_data_device!(State); impl PrimarySelectionHandler for State { fn primary_selection_state(&self) -> &PrimarySelectionState { - &self.primary_selection_state + &self.pinnacle.primary_selection_state } } delegate_primary_selection!(State); impl DataControlHandler for State { fn data_control_state(&self) -> &DataControlState { - &self.data_control_state + &self.pinnacle.data_control_state } } delegate_data_control!(State); @@ -407,28 +418,29 @@ impl SeatHandler for State { type TouchFocus = PointerFocusTarget; fn seat_state(&mut self) -> &mut SeatState { - &mut self.seat_state + &mut self.pinnacle.seat_state } fn cursor_image(&mut self, _seat: &Seat, image: CursorImageStatus) { - self.cursor_status = image; + self.pinnacle.cursor_status = image; } fn focus_changed(&mut self, seat: &Seat, focused: Option<&Self::KeyboardFocus>) { let focus_client = focused.and_then(|foc_target| { - self.display_handle + self.pinnacle + .display_handle .get_client(foc_target.wl_surface()?.id()) .ok() }); - set_data_device_focus(&self.display_handle, seat, focus_client.clone()); - set_primary_focus(&self.display_handle, seat, focus_client); + set_data_device_focus(&self.pinnacle.display_handle, seat, focus_client.clone()); + set_primary_focus(&self.pinnacle.display_handle, seat, focus_client); } } delegate_seat!(State); impl ShmHandler for State { fn shm_state(&self) -> &ShmState { - &self.shm_state + &self.pinnacle.shm_state } } delegate_shm!(State); @@ -466,17 +478,25 @@ impl FractionalScaleHandler for State { desktop::utils::surface_primary_scanout_output(&root, states) .or_else(|| { self.window_for_surface(&root).and_then(|window| { - self.space.outputs_for_element(&window).first().cloned() + self.pinnacle + .space + .outputs_for_element(&window) + .first() + .cloned() }) }) }) } else { self.window_for_surface(&root).and_then(|window| { - self.space.outputs_for_element(&window).first().cloned() + self.pinnacle + .space + .outputs_for_element(&window) + .first() + .cloned() }) } }) - .or_else(|| self.space.outputs().next().cloned()); + .or_else(|| self.pinnacle.space.outputs().next().cloned()); if let Some(output) = primary_scanout_output { fractional_scale::with_fractional_scale(states, |fractional_scale| { fractional_scale.set_preferred_scale(output.current_scale().fractional_scale()); @@ -494,7 +514,7 @@ delegate_presentation!(State); impl WlrLayerShellHandler for State { fn shell_state(&mut self) -> &mut WlrLayerShellState { - &mut self.layer_shell_state + &mut self.pinnacle.layer_shell_state } fn new_layer_surface( @@ -508,7 +528,7 @@ impl WlrLayerShellHandler for State { let output = output .as_ref() .and_then(Output::from_resource) - .or_else(|| self.space.outputs().next().cloned()); + .or_else(|| self.pinnacle.space.outputs().next().cloned()); let Some(output) = output else { error!("New layer surface, but there was no output to map it on"); @@ -521,14 +541,14 @@ impl WlrLayerShellHandler for State { error!("Failed to map layer surface: {err}"); } - self.loop_handle.insert_idle(move |state| { + self.pinnacle.loop_handle.insert_idle(move |state| { state.request_layout(&output); }); } fn layer_destroyed(&mut self, surface: wlr_layer::LayerSurface) { let mut output: Option = None; - if let Some((mut map, layer, op)) = self.space.outputs().find_map(|o| { + if let Some((mut map, layer, op)) = self.pinnacle.space.outputs().find_map(|o| { let map = layer_map_for_output(o); let layer = map .layers() @@ -541,7 +561,7 @@ impl WlrLayerShellHandler for State { } if let Some(output) = output { - self.loop_handle.insert_idle(move |state| { + self.pinnacle.loop_handle.insert_idle(move |state| { state.request_layout(&output); }); } @@ -567,7 +587,7 @@ delegate_screencopy!(State); impl GammaControlHandler for State { fn gamma_control_manager_state(&mut self) -> &mut GammaControlManagerState { - &mut self.gamma_control_manager_state + &mut self.pinnacle.gamma_control_manager_state } fn get_gamma_size(&mut self, output: &Output) -> Option { @@ -636,13 +656,13 @@ impl State { } let (root_global_loc, output) = if let Some(win) = self.window_for_surface(&root) { - let win_geo = self.space.element_geometry(&win)?; + let win_geo = self.pinnacle.space.element_geometry(&win)?; (win_geo.loc, self.focused_output()?.clone()) } else { - self.space.outputs().find_map(|op| { + self.pinnacle.space.outputs().find_map(|op| { let layer_map = layer_map_for_output(op); let layer = layer_map.layer_for_surface(&root, WindowSurfaceType::TOPLEVEL)?; - let output_loc = self.space.output_geometry(op)?.loc; + let output_loc = self.pinnacle.space.output_geometry(op)?.loc; Some(( layer_map.layer_geometry(layer)?.loc + output_loc, op.clone(), @@ -656,7 +676,7 @@ impl State { root_global_loc + get_popup_toplevel_coords(&PopupKind::Xdg(popup.clone())) }; - let mut output_geo = self.space.output_geometry(&output)?; + let mut output_geo = self.pinnacle.space.output_geometry(&output)?; // Make local to parent output_geo.loc -= parent_global_loc; diff --git a/src/handlers/xdg_shell.rs b/src/handlers/xdg_shell.rs index 6b5eaf1..f63c4bf 100644 --- a/src/handlers/xdg_shell.rs +++ b/src/handlers/xdg_shell.rs @@ -31,7 +31,7 @@ use crate::{ impl XdgShellHandler for State { fn xdg_shell_state(&mut self) -> &mut XdgShellState { - &mut self.xdg_shell_state + &mut self.pinnacle.xdg_shell_state } fn new_toplevel(&mut self, surface: ToplevelSurface) { @@ -43,24 +43,24 @@ impl XdgShellHandler for State { }); let window = WindowElement::new(Window::new_wayland_window(surface.clone())); - self.new_windows.push(window); + self.pinnacle.new_windows.push(window); } fn toplevel_destroyed(&mut self, surface: ToplevelSurface) { tracing::debug!("toplevel destroyed"); - self.windows.retain(|window| { + self.pinnacle.windows.retain(|window| { window .wl_surface() .is_some_and(|surf| &surf != surface.wl_surface()) }); - self.z_index_stack.retain(|window| { + self.pinnacle.z_index_stack.retain(|window| { window .wl_surface() .is_some_and(|surf| &surf != surface.wl_surface()) }); - for output in self.space.outputs() { + for output in self.pinnacle.space.outputs() { output.with_state_mut(|state| { state.focus_stack.stack.retain(|window| { window @@ -87,7 +87,8 @@ impl XdgShellHandler for State { toplevel.send_configure(); } } - self.seat + self.pinnacle + .seat .get_keyboard() .expect("Seat had no keyboard") .set_focus(self, focus, SERIAL_COUNTER.next_serial()); @@ -101,14 +102,18 @@ impl XdgShellHandler for State { self.position_popup(&surface); - if let Err(err) = self.popup_manager.track_popup(PopupKind::from(surface)) { + if let Err(err) = self + .pinnacle + .popup_manager + .track_popup(PopupKind::from(surface)) + { tracing::warn!("failed to track popup: {}", err); } } fn popup_destroyed(&mut self, _surface: PopupSurface) { // TODO: only schedule on the outputs the popup is on - for output in self.space.outputs().cloned().collect::>() { + for output in self.pinnacle.space.outputs().cloned().collect::>() { self.schedule_render(&output); } } @@ -164,7 +169,7 @@ impl XdgShellHandler for State { self.window_for_surface(&root) .map(KeyboardFocusTarget::Window) .or_else(|| { - self.space.outputs().find_map(|op| { + self.pinnacle.space.outputs().find_map(|op| { layer_map_for_output(op) .layer_for_surface(&root, WindowSurfaceType::TOPLEVEL) .cloned() @@ -173,6 +178,7 @@ impl XdgShellHandler for State { }) }) { if let Ok(mut grab) = self + .pinnacle .popup_manager .grab_popup(root, popup_kind, &seat, serial) { @@ -217,17 +223,23 @@ impl XdgShellHandler for State { .as_ref() .and_then(Output::from_resource) .or_else(|| { - self.window_for_surface(wl_surface) - .and_then(|window| self.space.outputs_for_element(&window).first().cloned()) + self.window_for_surface(wl_surface).and_then(|window| { + self.pinnacle + .space + .outputs_for_element(&window) + .first() + .cloned() + }) }); if let Some(output) = output { - let Some(geometry) = self.space.output_geometry(&output) else { + let Some(geometry) = self.pinnacle.space.output_geometry(&output) else { surface.send_configure(); return; }; let client = self + .pinnacle .display_handle .get_client(wl_surface.id()) .expect("wl_surface had no client"); diff --git a/src/handlers/xwayland.rs b/src/handlers/xwayland.rs index ecd9f97..fea379b 100644 --- a/src/handlers/xwayland.rs +++ b/src/handlers/xwayland.rs @@ -32,7 +32,7 @@ use crate::{ impl XwmHandler for State { fn xwm_state(&mut self, _xwm: XwmId) -> &mut X11Wm { - self.xwm.as_mut().expect("xwm not in state") + self.pinnacle.xwm.as_mut().expect("xwm not in state") } fn new_window(&mut self, _xwm: XwmId, _window: X11Surface) {} @@ -48,15 +48,18 @@ impl XwmHandler for State { } let window = WindowElement::new(Window::new_x11_window(surface)); - self.space.map_element(window.clone(), (0, 0), true); + self.pinnacle + .space + .map_element(window.clone(), (0, 0), true); let bbox = self + .pinnacle .space .element_bbox(&window) .expect("called element_bbox on an unmapped window"); let output_size = self .focused_output() - .and_then(|op| self.space.output_geometry(op)) + .and_then(|op| self.pinnacle.space.output_geometry(op)) .map(|geo| geo.size) .unwrap_or((2, 2).into()); @@ -78,7 +81,7 @@ impl XwmHandler for State { unreachable!() }; - self.space.map_element(window.clone(), loc, true); + self.pinnacle.space.map_element(window.clone(), loc, true); surface.set_mapped(true).expect("failed to map x11 window"); let bbox = Rectangle::from_loc_and_size(loc, bbox.size); @@ -100,7 +103,7 @@ impl XwmHandler for State { } // TODO: will an unmap -> map duplicate the window - self.windows.push(window.clone()); + self.pinnacle.windows.push(window.clone()); self.raise_window(window.clone(), true); self.apply_window_rules(&window); @@ -110,8 +113,9 @@ impl XwmHandler for State { self.request_layout(&output); } - self.loop_handle.insert_idle(move |state| { + self.pinnacle.loop_handle.insert_idle(move |state| { state + .pinnacle .seat .get_keyboard() .expect("Seat had no keyboard") // FIXME: actually handle error @@ -132,7 +136,7 @@ impl XwmHandler for State { let window = WindowElement::new(Window::new_x11_window(surface)); - self.windows.push(window.clone()); + self.pinnacle.windows.push(window.clone()); if let Some(output) = self.focused_output() { window.place_on_output(output); @@ -141,7 +145,7 @@ impl XwmHandler for State { output.with_state_mut(|state| state.focus_stack.set_focus(window.clone())); } - self.space.map_element(window.clone(), loc, true); + self.pinnacle.space.map_element(window.clone(), loc, true); self.raise_window(window.clone(), true); } @@ -159,7 +163,7 @@ impl XwmHandler for State { fn unmapped_window(&mut self, _xwm: XwmId, surface: X11Surface) { trace!("XwmHandler::unmapped_window"); - for output in self.space.outputs() { + for output in self.pinnacle.space.outputs() { output.with_state_mut(|state| { state.focus_stack.stack.retain(|win| { win.wl_surface() @@ -169,18 +173,21 @@ impl XwmHandler for State { } let win = self + .pinnacle .space .elements() .find(|elem| matches!(elem.x11_surface(), Some(surf) if surf == &surface)) .cloned(); if let Some(win) = win { - self.windows + self.pinnacle + .windows .retain(|elem| win.wl_surface() != elem.wl_surface()); - self.z_index_stack + self.pinnacle + .z_index_stack .retain(|elem| win.wl_surface() != elem.wl_surface()); - self.space.unmap_elem(&win); + self.pinnacle.space.unmap_elem(&win); if let Some(output) = win.output(self) { self.request_layout(&output); @@ -196,7 +203,8 @@ impl XwmHandler for State { } } - self.seat + self.pinnacle + .seat .get_keyboard() .expect("Seat had no keyboard") .set_focus(self, focus, SERIAL_COUNTER.next_serial()); @@ -213,7 +221,7 @@ impl XwmHandler for State { fn destroyed_window(&mut self, _xwm: XwmId, surface: X11Surface) { trace!("XwmHandler::destroyed_window"); - for output in self.space.outputs() { + for output in self.pinnacle.space.outputs() { output.with_state_mut(|state| { state.focus_stack.stack.retain(|win| { win.wl_surface() @@ -223,6 +231,7 @@ impl XwmHandler for State { } let win = self + .pinnacle .windows .iter() .find(|elem| { @@ -238,10 +247,12 @@ impl XwmHandler for State { // INFO: comparing the windows doesn't work so wlsurface it is // self.windows.retain(|elem| &win != elem); - self.windows + self.pinnacle + .windows .retain(|elem| win.wl_surface() != elem.wl_surface()); - self.z_index_stack + self.pinnacle + .z_index_stack .retain(|elem| win.wl_surface() != elem.wl_surface()); if let Some(output) = win.output(self) { @@ -258,7 +269,8 @@ impl XwmHandler for State { } } - self.seat + self.pinnacle + .seat .get_keyboard() .expect("Seat had no keyboard") .set_focus(self, focus, SERIAL_COUNTER.next_serial()); @@ -281,6 +293,7 @@ impl XwmHandler for State { ) { trace!("XwmHandler::configure_request"); let floating_or_override_redirect = self + .pinnacle .windows .iter() .find(|win| win.x11_surface() == Some(&window)) @@ -320,6 +333,7 @@ impl XwmHandler for State { _above: Option, ) { let Some(win) = self + .pinnacle .space .elements() .find(|elem| { @@ -331,7 +345,7 @@ impl XwmHandler for State { return; }; - self.space.map_element(win, geometry.loc, true); + self.pinnacle.space.map_element(win, geometry.loc, true); } fn maximize_request(&mut self, _xwm: XwmId, window: X11Surface) { @@ -416,7 +430,7 @@ impl XwmHandler for State { resize_edge: smithay::xwayland::xwm::ResizeEdge, ) { let Some(wl_surf) = window.wl_surface() else { return }; - let seat = self.seat.clone(); + let seat = self.pinnacle.seat.clone(); // We use the server one and not the client because windows like Steam don't provide // GrabStartData, so we need to create it ourselves. @@ -432,7 +446,7 @@ impl XwmHandler for State { fn move_request(&mut self, _xwm: XwmId, window: X11Surface, button: u32) { let Some(wl_surf) = window.wl_surface() else { return }; - let seat = self.seat.clone(); + let seat = self.pinnacle.seat.clone(); // We use the server one and not the client because windows like Steam don't provide // GrabStartData, so we need to create it ourselves. @@ -446,7 +460,8 @@ impl XwmHandler for State { } fn allow_selection_access(&mut self, xwm: XwmId, _selection: SelectionTarget) -> bool { - self.seat + self.pinnacle + .seat .get_keyboard() .and_then(|kb| kb.current_focus()) .is_some_and(|focus| { @@ -468,7 +483,9 @@ impl XwmHandler for State { ) { match selection { SelectionTarget::Clipboard => { - if let Err(err) = request_data_device_client_selection(&self.seat, mime_type, fd) { + if let Err(err) = + request_data_device_client_selection(&self.pinnacle.seat, mime_type, fd) + { error!( ?err, "Failed to request current wayland clipboard for XWayland" @@ -476,7 +493,9 @@ impl XwmHandler for State { } } SelectionTarget::Primary => { - if let Err(err) = request_primary_client_selection(&self.seat, mime_type, fd) { + if let Err(err) = + request_primary_client_selection(&self.pinnacle.seat, mime_type, fd) + { error!( ?err, "Failed to request current wayland primary selection for XWayland" @@ -489,10 +508,20 @@ impl XwmHandler for State { fn new_selection(&mut self, _xwm: XwmId, selection: SelectionTarget, mime_types: Vec) { match selection { SelectionTarget::Clipboard => { - set_data_device_selection(&self.display_handle, &self.seat, mime_types, ()); + set_data_device_selection( + &self.pinnacle.display_handle, + &self.pinnacle.seat, + mime_types, + (), + ); } SelectionTarget::Primary => { - set_primary_selection(&self.display_handle, &self.seat, mime_types, ()); + set_primary_selection( + &self.pinnacle.display_handle, + &self.pinnacle.seat, + mime_types, + (), + ); } } } @@ -500,13 +529,13 @@ impl XwmHandler for State { fn cleared_selection(&mut self, _xwm: XwmId, selection: SelectionTarget) { match selection { SelectionTarget::Clipboard => { - if current_data_device_selection_userdata(&self.seat).is_some() { - clear_data_device_selection(&self.display_handle, &self.seat); + if current_data_device_selection_userdata(&self.pinnacle.seat).is_some() { + clear_data_device_selection(&self.pinnacle.display_handle, &self.pinnacle.seat); } } SelectionTarget::Primary => { - if current_primary_selection_userdata(&self.seat).is_some() { - clear_primary_selection(&self.display_handle, &self.seat); + if current_primary_selection_userdata(&self.pinnacle.seat).is_some() { + clear_primary_selection(&self.pinnacle.display_handle, &self.pinnacle.seat); } } } @@ -514,12 +543,13 @@ impl XwmHandler for State { } impl State { - pub fn fixup_xwayland_internal_z_indices(&mut self) { - let Some(xwm) = self.xwm.as_mut() else { + pub fn fixup_xwayland_window_layering(&mut self) { + let Some(xwm) = self.pinnacle.xwm.as_mut() else { return; }; let x11_wins = self + .pinnacle .space .elements() .filter(|win| win.is_on_active_tag()) diff --git a/src/input.rs b/src/input.rs index 6916180..3f671e0 100644 --- a/src/input.rs +++ b/src/input.rs @@ -171,14 +171,16 @@ impl State { { let point: Point = point.into(); - let output = self.space.outputs().find(|op| { - self.space + let output = self.pinnacle.space.outputs().find(|op| { + self.pinnacle + .space .output_geometry(op) .expect("called output_geometry on unmapped output (this shouldn't happen here)") .contains(point.to_i32_round()) })?; let output_geo = self + .pinnacle .space .output_geometry(output) .expect("called output_geometry on unmapped output"); @@ -186,6 +188,7 @@ impl State { let mut fullscreen_and_up_split_at = 0; for (i, win) in self + .pinnacle .space .elements() .rev() @@ -223,6 +226,7 @@ impl State { |windows: &[&WindowElement]| -> Option<(PointerFocusTarget, Point)> { windows.iter().find_map(|win| { let loc = self + .pinnacle .space .element_location(win) .expect("called elem loc on unmapped win") @@ -246,6 +250,7 @@ impl State { .or_else(|| { window_under( &self + .pinnacle .space .elements() .rev() @@ -258,6 +263,7 @@ impl State { .or_else(|| { window_under( &self + .pinnacle .space .elements() .rev() @@ -271,7 +277,7 @@ impl State { /// Update the pointer focus if it's different from the previous one. pub fn update_pointer_focus(&mut self) { - let Some(pointer) = self.seat.get_pointer() else { + let Some(pointer) = self.pinnacle.seat.get_pointer() else { return; }; @@ -291,7 +297,7 @@ impl State { &MotionEvent { location, serial: SERIAL_COUNTER.next_serial(), - time: Duration::from(self.clock.now()).as_millis() as u32, + time: Duration::from(self.pinnacle.clock.now()).as_millis() as u32, }, ); pointer.frame(self); @@ -302,10 +308,14 @@ impl State { let time = event.time_msec(); let press_state = event.state(); - let reload_keybind = self.input_state.reload_keybind; - let kill_keybind = self.input_state.kill_keybind; + let reload_keybind = self.pinnacle.input_state.reload_keybind; + let kill_keybind = self.pinnacle.input_state.kill_keybind; - let keyboard = self.seat.get_keyboard().expect("Seat has no keyboard"); + let keyboard = self + .pinnacle + .seat + .get_keyboard() + .expect("Seat has no keyboard"); let modifiers = keyboard.modifier_state(); @@ -318,11 +328,11 @@ impl State { } // FIXME: Leds only update once another key is pressed. - for device in self.input_state.libinput_devices.iter_mut() { + for device in self.pinnacle.input_state.libinput_devices.iter_mut() { device.led_update(leds); } - for layer in self.layer_shell_state.layer_surfaces().rev() { + for layer in self.pinnacle.layer_shell_state.layer_surfaces().rev() { let data = compositor::with_states(layer.wl_surface(), |states| { *states.cached_state.current::() }); @@ -332,18 +342,19 @@ impl State { wlr_layer::Layer::Top | wlr_layer::Layer::Overlay ) { - let layer_surface = self.space.outputs().find_map(|op| { + let layer_surface = self.pinnacle.space.outputs().find_map(|op| { let map = layer_map_for_output(op); let cloned = map.layers().find(|l| l.layer_surface() == &layer).cloned(); cloned }); if let Some(layer_surface) = layer_surface { - match self.input_state.exclusive_layer_focus_stack.last() { + match self.pinnacle.input_state.exclusive_layer_focus_stack.last() { Some(focus) => { let layer_focus = KeyboardFocusTarget::LayerSurface(layer_surface); if &layer_focus != focus { - self.input_state + self.pinnacle + .input_state .exclusive_layer_focus_stack .push(layer_focus); } @@ -351,10 +362,12 @@ impl State { // Push the previous focus on as this is the first exclusive layer surface // on screen. This lets us restore it when that layer surface goes away. None => { - self.input_state + self.pinnacle + .input_state .exclusive_layer_focus_stack .extend(keyboard.current_focus()); - self.input_state + self.pinnacle + .input_state .exclusive_layer_focus_stack .push(KeyboardFocusTarget::LayerSurface(layer_surface)); } @@ -363,13 +376,19 @@ impl State { } } - while let Some(last) = self.input_state.exclusive_layer_focus_stack.pop() { + while let Some(last) = self.pinnacle.input_state.exclusive_layer_focus_stack.pop() { if last.alive() { // If it's not empty then there's another exclusive layer surface // underneath. Otherwise `last` is the previous keyboard focus // and we don't need the stack anymore. - if !self.input_state.exclusive_layer_focus_stack.is_empty() { - self.input_state + if !self + .pinnacle + .input_state + .exclusive_layer_focus_stack + .is_empty() + { + self.pinnacle + .input_state .exclusive_layer_focus_stack .push(last.clone()); } @@ -392,9 +411,17 @@ impl State { let mod_sym = keysym.modified_sym(); if let (Some(sender), _) | (None, Some(sender)) = ( - state.input_state.keybinds.get(&(mod_mask, mod_sym)), + state + .pinnacle + .input_state + .keybinds + .get(&(mod_mask, mod_sym)), raw_sym.and_then(|raw_sym| { - state.input_state.keybinds.get(&(mod_mask, *raw_sym)) + state + .pinnacle + .input_state + .keybinds + .get(&(mod_mask, *raw_sym)) }), ) { return FilterResult::Intercept(KeyAction::CallCallback(sender.clone())); @@ -429,7 +456,7 @@ impl State { } Some(KeyAction::ReloadConfig) => { info!("Reloading config"); - self.start_config(Some(self.config.dir(&self.xdg_base_dirs))) + self.start_config(Some(self.pinnacle.config.dir(&self.pinnacle.xdg_base_dirs))) .expect("failed to restart config"); } None => (), @@ -437,8 +464,16 @@ impl State { } fn pointer_button(&mut self, event: I::PointerButtonEvent) { - let pointer = self.seat.get_pointer().expect("Seat has no pointer"); // FIXME: handle err - let keyboard = self.seat.get_keyboard().expect("Seat has no keyboard"); // FIXME: handle err + let pointer = self + .pinnacle + .seat + .get_pointer() + .expect("Seat has no pointer"); // FIXME: handle err + let keyboard = self + .pinnacle + .seat + .get_keyboard() + .expect("Seat has no keyboard"); // FIXME: handle err let serial = SERIAL_COUNTER.next_serial(); @@ -456,6 +491,7 @@ impl State { }; if let Some(stream) = self + .pinnacle .input_state .mousebinds .get(&(mod_mask, button, mouse_edge)) @@ -489,7 +525,7 @@ impl State { keyboard.set_focus(self, focus.to_keyboard_focus_target(self), serial); } - for window in self.space.elements() { + for window in self.pinnacle.space.elements() { if let Some(toplevel) = window.toplevel() { toplevel.send_configure(); } @@ -556,7 +592,11 @@ impl State { frame = frame.stop(Axis::Vertical); } - let pointer = self.seat.get_pointer().expect("Seat has no pointer"); + let pointer = self + .pinnacle + .seat + .get_pointer() + .expect("Seat has no pointer"); pointer.axis(self, frame); pointer.frame(self); @@ -566,14 +606,15 @@ impl State { /// /// This returns the nearest point inside an output. fn clamp_coords(&self, pos: Point) -> Point { - if self.space.outputs().next().is_none() { + if self.pinnacle.space.outputs().next().is_none() { return pos; } let (pos_x, pos_y) = pos.into(); - let nearest_points = self.space.outputs().map(|op| { + let nearest_points = self.pinnacle.space.outputs().map(|op| { let size = self + .pinnacle .space .output_geometry(op) .expect("called output_geometry on unmapped output") @@ -599,24 +640,30 @@ impl State { /// This *should* only be generated on the winit backend. /// Unless there's a case where it's generated on udev that I'm unaware of. fn pointer_motion_absolute(&mut self, event: I::PointerMotionAbsoluteEvent) { - let Some(pointer) = self.seat.get_pointer() else { + let Some(pointer) = self.pinnacle.seat.get_pointer() else { tracing::error!("Pointer motion absolute received with no pointer on seat"); return; }; - let Some(output) = self.space.outputs().next() else { + let Some(output) = self.pinnacle.space.outputs().next() else { return; }; - let Some(output_geo) = self.space.output_geometry(output) else { + let Some(output_geo) = self.pinnacle.space.output_geometry(output) else { unreachable!("output should have a geometry as it was mapped"); }; let pointer_loc = event.position_transformed(output_geo.size) + output_geo.loc.to_f64(); let serial = SERIAL_COUNTER.next_serial(); - if let Some(output) = self.space.output_under(pointer_loc).next().cloned() { - self.output_focus_stack.set_focus(output); + if let Some(output) = self + .pinnacle + .space + .output_under(pointer_loc) + .next() + .cloned() + { + self.pinnacle.output_focus_stack.set_focus(output); } let pointer_focus = self.pointer_focus_target_under(pointer_loc); @@ -635,7 +682,7 @@ impl State { } fn pointer_motion(&mut self, event: I::PointerMotionEvent) { - let Some(pointer) = self.seat.get_pointer() else { + let Some(pointer) = self.pinnacle.seat.get_pointer() else { tracing::error!("Pointer motion received with no pointer on seat"); return; }; @@ -647,8 +694,14 @@ impl State { // this event is never generated by winit pointer_loc = self.clamp_coords(pointer_loc); - if let Some(output) = self.space.output_under(pointer_loc).next().cloned() { - self.output_focus_stack.set_focus(output); + if let Some(output) = self + .pinnacle + .space + .output_under(pointer_loc) + .next() + .cloned() + { + self.pinnacle.output_focus_stack.set_focus(output); } let surface_under = self.pointer_focus_target_under(pointer_loc); diff --git a/src/input/libinput.rs b/src/input/libinput.rs index f46b4fd..280a20c 100644 --- a/src/input/libinput.rs +++ b/src/input/libinput.rs @@ -8,7 +8,8 @@ impl State { let mut device = match event { InputEvent::DeviceAdded { device } => device.clone(), InputEvent::DeviceRemoved { device } => { - self.input_state + self.pinnacle + .input_state .libinput_devices .retain(|dev| dev != device); return; @@ -16,14 +17,14 @@ impl State { _ => return, }; - if self.input_state.libinput_devices.contains(&device) { + if self.pinnacle.input_state.libinput_devices.contains(&device) { return; } - for setting in self.input_state.libinput_settings.values() { + for setting in self.pinnacle.input_state.libinput_settings.values() { setting(&mut device); } - self.input_state.libinput_devices.push(device); + self.pinnacle.input_state.libinput_devices.push(device); } } diff --git a/src/layout.rs b/src/layout.rs index 1d79c3b..b195451 100644 --- a/src/layout.rs +++ b/src/layout.rs @@ -33,7 +33,8 @@ impl State { ) { let windows_on_foc_tags = output.with_state(|state| { let focused_tags = state.focused_tags().collect::>(); - self.windows + self.pinnacle + .windows .iter() .filter(|win| !win.is_x11_override_redirect()) .filter(|win| { @@ -52,7 +53,11 @@ impl State { }) .cloned(); - let output_geo = self.space.output_geometry(output).expect("no output geo"); + let output_geo = self + .pinnacle + .space + .output_geometry(output) + .expect("no output geo"); let non_exclusive_geo = { let map = layer_map_for_output(output); @@ -125,7 +130,7 @@ impl State { WindowSurface::X11(_) => { let loc = win.with_state_mut(|state| state.target_loc.take()); if let Some(loc) = loc { - self.space.map_element(win.clone(), loc, false); + self.pinnacle.space.map_element(win.clone(), loc, false); } } } @@ -133,17 +138,20 @@ impl State { } for (loc, window) in non_pending_wins { - self.space.map_element(window, loc, false); + self.pinnacle.space.map_element(window, loc, false); } - // HACK and FIXME: + // FIXME: // We are sending frames here to get offscreen windows to commit and map. // Obviously this is a bad way to do this but its a bandaid solution // until decent transactional layout applications are implemented. for (win, _serial) in pending_wins { - win.send_frame(output, self.clock.now(), Some(Duration::ZERO), |_, _| { - Some(output.clone()) - }); + win.send_frame( + output, + self.pinnacle.clock.now(), + Some(Duration::ZERO), + |_, _| Some(output.clone()), + ); } self.fixup_z_layering(); @@ -151,15 +159,15 @@ impl State { /// Swaps two windows in the main window vec and updates all windows. pub fn swap_window_positions(&mut self, win1: &WindowElement, win2: &WindowElement) { - let win1_index = self.windows.iter().position(|win| win == win1); - let win2_index = self.windows.iter().position(|win| win == win2); + let win1_index = self.pinnacle.windows.iter().position(|win| win == win1); + let win2_index = self.pinnacle.windows.iter().position(|win| win == win2); if let (Some(first), Some(second)) = (win1_index, win2_index) { - self.windows.swap(first, second); + self.pinnacle.windows.swap(first, second); if let Some(output) = win1.output(self) { self.request_layout(&output); } - self.layout_state.pending_swap = true; + self.pinnacle.layout_state.pending_swap = true; } } } @@ -179,14 +187,15 @@ pub struct LayoutState { impl State { pub fn request_layout(&mut self, output: &Output) { - let Some(sender) = self.layout_state.layout_request_sender.as_ref() else { + let Some(sender) = self.pinnacle.layout_state.layout_request_sender.as_ref() else { warn!("Layout requested but no client has connected to the layout service"); return; }; let windows_on_foc_tags = output.with_state(|state| { let focused_tags = state.focused_tags().collect::>(); - self.windows + self.pinnacle + .windows .iter() .filter(|win| !win.is_x11_override_redirect()) .filter(|win| { @@ -221,12 +230,14 @@ impl State { output.with_state(|state| state.focused_tags().map(|tag| tag.id().0).collect()); let id = self + .pinnacle .layout_state .id_maps .entry(output.clone()) .or_insert(LayoutRequestId(0)); - self.layout_state + self.pinnacle + .layout_state .pending_requests .entry(output.clone()) .or_default() @@ -261,6 +272,7 @@ impl State { }; let old_requests = self + .pinnacle .layout_state .old_requests .entry(output.clone()) @@ -271,6 +283,7 @@ impl State { } let pending = self + .pinnacle .layout_state .pending_requests .entry(output.clone()) @@ -312,7 +325,7 @@ impl State { self.schedule_render(&output); - self.layout_state.pending_swap = false; + self.pinnacle.layout_state.pending_swap = false; Ok(()) } diff --git a/src/main.rs b/src/main.rs index d1e20e8..5c8d4aa 100644 --- a/src/main.rs +++ b/src/main.rs @@ -132,18 +132,19 @@ async fn main() -> anyhow::Result<()> { event_loop.run(None, &mut state, |state| { state.update_pointer_focus(); state.fixup_z_layering(); - state.space.refresh(); - state.popup_manager.cleanup(); + state.pinnacle.space.refresh(); + state.pinnacle.popup_manager.cleanup(); state + .pinnacle .display_handle .flush_clients() .expect("failed to flush client buffers"); // TODO: couple these or something, this is really error-prone assert_eq!( - state.windows.len(), - state.z_index_stack.len(), + state.pinnacle.windows.len(), + state.pinnacle.z_index_stack.len(), "Length of `windows` and `z_index_stack` are different. \ If you see this, report it to the developer." ); @@ -157,6 +158,8 @@ async fn main() -> anyhow::Result<()> { fn set_log_panic_hook() { let hook = std::panic::take_hook(); std::panic::set_hook(Box::new(move |info| { + let _span = tracing::error_span!("panic"); + let _span = _span.enter(); error!("Panic occurred! Attempting to log backtrace"); let buffer = gag::BufferRedirect::stderr(); if let Ok(buffer) = buffer { diff --git a/src/output.rs b/src/output.rs index 08777fc..3f0c98a 100644 --- a/src/output.rs +++ b/src/output.rs @@ -28,6 +28,7 @@ impl OutputName { /// Get the output with this name. pub fn output(&self, state: &State) -> Option { state + .pinnacle .space .outputs() .find(|output| output.name() == self.0) @@ -90,8 +91,8 @@ impl State { output.change_current_state(mode, transform, scale, location); if let Some(location) = location { info!(?location); - self.space.map_output(output, location); - self.signal_state.output_move.signal(|buf| { + self.pinnacle.space.map_output(output, location); + self.pinnacle.signal_state.output_move.signal(|buf| { buf.push_back(OutputMoveResponse { output_name: Some(output.name()), x: Some(location.x), @@ -101,8 +102,8 @@ impl State { } if mode.is_some() || transform.is_some() || scale.is_some() { layer_map_for_output(output).arrange(); - self.signal_state.output_resize.signal(|buf| { - let geo = self.space.output_geometry(output); + self.pinnacle.signal_state.output_resize.signal(|buf| { + let geo = self.pinnacle.space.output_geometry(output); buf.push_back(OutputResizeResponse { output_name: Some(output.name()), logical_width: geo.map(|geo| geo.size.w as u32), diff --git a/src/render.rs b/src/render.rs index 2515636..77f89b5 100644 --- a/src/render.rs +++ b/src/render.rs @@ -349,7 +349,7 @@ impl State { /// Schedule a new render. This does nothing on the winit backend. pub fn schedule_render(&mut self, output: &Output) { if let Backend::Udev(udev) = &mut self.backend { - udev.schedule_render(&self.loop_handle, output); + udev.schedule_render(&self.pinnacle.loop_handle, output); } } } diff --git a/src/state.rs b/src/state.rs index ff06a67..23a837a 100644 --- a/src/state.rs +++ b/src/state.rs @@ -53,11 +53,14 @@ use crate::input::InputState; pub struct State { /// Which backend is currently running pub backend: Backend, + pub pinnacle: Pinnacle, +} +pub struct Pinnacle { /// A loop signal used to stop the compositor pub loop_signal: LoopSignal, /// A handle to the event loop - pub loop_handle: LoopHandle<'static, Self>, + pub loop_handle: LoopHandle<'static, State>, pub display_handle: DisplayHandle, pub clock: Clock, @@ -67,7 +70,7 @@ pub struct State { pub compositor_state: CompositorState, pub data_device_state: DataDeviceState, - pub seat_state: SeatState, + pub seat_state: SeatState, pub shm_state: ShmState, pub output_manager_state: OutputManagerState, pub xdg_shell_state: XdgShellState, @@ -150,8 +153,10 @@ impl State { info!("Fd raise success!"); } - loop_handle.insert_source(socket, |stream, _metadata, data| { - data.display_handle + loop_handle.insert_source(socket, |stream, _metadata, state| { + state + .pinnacle + .display_handle .insert_client(stream, Arc::new(ClientState::default())) .expect("Could not insert client into loop handle"); })?; @@ -191,7 +196,7 @@ impl State { display, } => { let mut wm = X11Wm::start_wm( - state.loop_handle.clone(), + state.pinnacle.loop_handle.clone(), dh_clone.clone(), connection, client, @@ -209,19 +214,19 @@ impl State { tracing::debug!("setting xwm and xdisplay"); - state.xwm = Some(wm); - state.xdisplay = Some(display); + state.pinnacle.xwm = Some(wm); + state.pinnacle.xdisplay = Some(display); std::env::set_var("DISPLAY", format!(":{display}")); - if let Err(err) = - state.start_config(Some(state.config.dir(&state.xdg_base_dirs))) - { + if let Err(err) = state.start_config(Some( + state.pinnacle.config.dir(&state.pinnacle.xdg_base_dirs), + )) { panic!("failed to start config: {err}"); } } XWaylandEvent::Exited => { - state.xwm.take(); + state.pinnacle.xwm.take(); } }); if let Err(err) = res { @@ -241,69 +246,74 @@ impl State { let state = Self { backend, - loop_signal, - loop_handle, - display_handle: display_handle.clone(), - clock: Clock::::new(), - compositor_state: CompositorState::new::(&display_handle), - data_device_state: DataDeviceState::new::(&display_handle), - seat_state, - shm_state: ShmState::new::(&display_handle, vec![]), - space: Space::::default(), - cursor_status: CursorImageStatus::default_named(), - output_manager_state: OutputManagerState::new_with_xdg_output::(&display_handle), - xdg_shell_state: XdgShellState::new::(&display_handle), - viewporter_state: ViewporterState::new::(&display_handle), - fractional_scale_manager_state: FractionalScaleManagerState::new::( - &display_handle, - ), - primary_selection_state, - layer_shell_state: WlrLayerShellState::new::(&display_handle), - data_control_state, - screencopy_manager_state: ScreencopyManagerState::new::( - &display_handle, - |_| true, - ), - gamma_control_manager_state: GammaControlManagerState::new::( - &display_handle, - |_| true, - ), - relative_pointer_manager_state: RelativePointerManagerState::new::( - &display_handle, - ), - input_state: InputState::new(), + pinnacle: Pinnacle { + loop_signal, + loop_handle, + display_handle: display_handle.clone(), + clock: Clock::::new(), + compositor_state: CompositorState::new::(&display_handle), + data_device_state: DataDeviceState::new::(&display_handle), + seat_state, + shm_state: ShmState::new::(&display_handle, vec![]), + space: Space::::default(), + cursor_status: CursorImageStatus::default_named(), + output_manager_state: OutputManagerState::new_with_xdg_output::( + &display_handle, + ), + xdg_shell_state: XdgShellState::new::(&display_handle), + viewporter_state: ViewporterState::new::(&display_handle), + fractional_scale_manager_state: FractionalScaleManagerState::new::( + &display_handle, + ), + primary_selection_state, + layer_shell_state: WlrLayerShellState::new::(&display_handle), + data_control_state, + screencopy_manager_state: ScreencopyManagerState::new::( + &display_handle, + |_| true, + ), + gamma_control_manager_state: GammaControlManagerState::new::( + &display_handle, + |_| true, + ), + relative_pointer_manager_state: RelativePointerManagerState::new::( + &display_handle, + ), - output_focus_stack: OutputFocusStack::default(), - z_index_stack: Vec::new(), + input_state: InputState::new(), - config: Config::new(no_config, config_dir), + output_focus_stack: OutputFocusStack::default(), + z_index_stack: Vec::new(), - seat, + config: Config::new(no_config, config_dir), - dnd_icon: None, + seat, - popup_manager: PopupManager::default(), + dnd_icon: None, - windows: Vec::new(), - new_windows: Vec::new(), + popup_manager: PopupManager::default(), - xwayland, - xwm: None, - xdisplay: None, + windows: Vec::new(), + new_windows: Vec::new(), - system_processes: sysinfo::System::new_with_specifics( - RefreshKind::new().with_processes(ProcessRefreshKind::new()), - ), + xwayland, + xwm: None, + xdisplay: None, - grpc_server_join_handle: None, + system_processes: sysinfo::System::new_with_specifics( + RefreshKind::new().with_processes(ProcessRefreshKind::new()), + ), - xdg_base_dirs: BaseDirectories::with_prefix("pinnacle") - .context("couldn't create xdg BaseDirectories")?, + grpc_server_join_handle: None, - signal_state: SignalState::default(), + xdg_base_dirs: BaseDirectories::with_prefix("pinnacle") + .context("couldn't create xdg BaseDirectories")?, - layout_state: LayoutState::default(), + signal_state: SignalState::default(), + + layout_state: LayoutState::default(), + }, }; Ok(state) @@ -317,7 +327,7 @@ impl State { F1: Fn(&mut Self) -> bool + 'static, F2: FnOnce(&mut Self) + 'static, { - self.loop_handle.insert_idle(|state| { + self.pinnacle.loop_handle.insert_idle(|state| { if !condition(state) { state.schedule(condition, run); } else { @@ -328,11 +338,11 @@ impl State { pub fn shutdown(&mut self) { info!("Shutting down Pinnacle"); - self.loop_signal.stop(); - if let Some(join_handle) = self.config.config_join_handle.take() { + self.pinnacle.loop_signal.stop(); + if let Some(join_handle) = self.pinnacle.config.config_join_handle.take() { join_handle.abort(); } - if let Some(shutdown_sender) = self.config.shutdown_sender.take() { + if let Some(shutdown_sender) = self.pinnacle.config.shutdown_sender.take() { if let Err(err) = shutdown_sender.send(Ok(ShutdownWatchResponse {})) { warn!("Failed to send shutdown signal to config: {err}"); } diff --git a/src/tag.rs b/src/tag.rs index f4cfda7..ab4624d 100644 --- a/src/tag.rs +++ b/src/tag.rs @@ -26,6 +26,7 @@ impl TagId { /// Get the tag associated with this id. pub fn tag(&self, state: &State) -> Option { state + .pinnacle .space .outputs() .flat_map(|op| op.with_state(|state| state.tags.clone())) @@ -83,7 +84,7 @@ impl Tag { pub fn set_active(&self, active: bool, state: &mut State) { self.0.borrow_mut().active = active; - state.signal_state.tag_active.signal(|buf| { + state.pinnacle.signal_state.tag_active.signal(|buf| { buf.push_back( pinnacle_api_defs::pinnacle::signal::v0alpha1::TagActiveResponse { tag_id: Some(self.id().0), @@ -108,6 +109,7 @@ impl Tag { /// RefCell Safety: This uses RefCells on every mapped output. pub fn output(&self, state: &State) -> Option { state + .pinnacle .space .outputs() .find(|output| output.with_state(|state| state.tags.iter().any(|tg| tg == self))) diff --git a/src/window.rs b/src/window.rs index bce6e4a..f65790d 100644 --- a/src/window.rs +++ b/src/window.rs @@ -212,11 +212,13 @@ impl WithState for WindowElement { impl State { /// Returns the [Window] associated with a given [WlSurface]. pub fn window_for_surface(&self, surface: &WlSurface) -> Option { - self.space + self.pinnacle + .space .elements() .find(|window| window.wl_surface().map(|s| s == *surface).unwrap_or(false)) .or_else(|| { - self.windows + self.pinnacle + .windows .iter() .find(|&win| win.wl_surface().is_some_and(|surf| &surf == surface)) }) @@ -227,7 +229,8 @@ impl State { /// /// Currently only used in `ensure_initial_configure` in [`handlers`][crate::handlers]. pub fn new_window_for_surface(&self, surface: &WlSurface) -> Option { - self.new_windows + self.pinnacle + .new_windows .iter() .find(|&win| win.wl_surface().is_some_and(|surf| &surf == surface)) .cloned() diff --git a/src/window/rules.rs b/src/window/rules.rs index 8e5004d..9e5e58e 100644 --- a/src/window/rules.rs +++ b/src/window/rules.rs @@ -170,7 +170,7 @@ pub enum FloatingOrTiled { impl State { pub fn apply_window_rules(&mut self, window: &WindowElement) { tracing::debug!("Applying window rules"); - for (cond, rule) in self.config.window_rules.iter() { + for (cond, rule) in self.pinnacle.config.window_rules.iter() { if cond.is_met(self, window) { let WindowRule { output, @@ -253,7 +253,7 @@ impl State { state.floating_or_tiled = window_state::FloatingOrTiled::Floating(rect) }); - self.space.map_element(window.clone(), *loc, false); + self.pinnacle.space.map_element(window.clone(), *loc, false); } window_state::FloatingOrTiled::Tiled(rect) => { // If the window is tiled, don't set the size. Instead, set diff --git a/src/window/window_state.rs b/src/window/window_state.rs index 9060843..9b1c9e1 100644 --- a/src/window/window_state.rs +++ b/src/window/window_state.rs @@ -30,6 +30,7 @@ impl WindowId { /// Get the window that has this WindowId. pub fn window(&self, state: &State) -> Option { state + .pinnacle .windows .iter() .find(|win| win.with_state(|state| &state.id == self)) diff --git a/tests/common/mod.rs b/tests/common/mod.rs index f7c8136..e0b4f68 100644 --- a/tests/common/mod.rs +++ b/tests/common/mod.rs @@ -55,18 +55,19 @@ where event_loop.run(None, &mut state, |state| { state.fixup_z_layering(); - state.space.refresh(); - state.popup_manager.cleanup(); + state.pinnacle.space.refresh(); + state.pinnacle.popup_manager.cleanup(); state + .pinnacle .display_handle .flush_clients() .expect("failed to flush client buffers"); // TODO: couple these or something, this is really error-prone assert_eq!( - state.windows.len(), - state.z_index_stack.len(), + state.pinnacle.windows.len(), + state.pinnacle.z_index_stack.len(), "Length of `windows` and `z_index_stack` are different. \ If you see this, report it to the developer." ); @@ -77,6 +78,7 @@ where pub fn output_for_name(state: &State, name: &str) -> Output { state + .pinnacle .space .outputs() .find(|op| op.name() == name) diff --git a/tests/lua_api.rs b/tests/lua_api.rs index 0a3afc3..f9bc91d 100644 --- a/tests/lua_api.rs +++ b/tests/lua_api.rs @@ -124,8 +124,8 @@ mod process { sleep_secs(1); with_state(&sender, |state| { - assert_eq!(state.windows.len(), 1); - assert_eq!(state.windows[0].class(), Some("foot".to_string())); + assert_eq!(state.pinnacle.windows.len(), 1); + assert_eq!(state.pinnacle.windows[0].class(), Some("foot".to_string())); }); Ok(()) @@ -217,9 +217,9 @@ mod window { sleep_secs(1); with_state(&sender, |state| { - assert_eq!(state.config.window_rules.len(), 1); + assert_eq!(state.pinnacle.config.window_rules.len(), 1); assert_eq!( - state.config.window_rules[0], + state.pinnacle.config.window_rules[0], ( WindowRuleCondition { class: Some(vec!["firefox".to_string()]), @@ -254,9 +254,9 @@ mod window { sleep_secs(1); with_state(&sender, |state| { - assert_eq!(state.config.window_rules.len(), 2); + assert_eq!(state.pinnacle.config.window_rules.len(), 2); assert_eq!( - state.config.window_rules[1], + state.pinnacle.config.window_rules[1], ( WindowRuleCondition { cond_all: Some(vec![WindowRuleCondition { @@ -297,7 +297,7 @@ mod window { sleep_secs(1); with_state(&sender, |state| { - assert_eq!(state.windows.len(), 1); + assert_eq!(state.pinnacle.windows.len(), 1); }); run_lua! { |Pinnacle| @@ -307,7 +307,7 @@ mod window { sleep_secs(1); with_state(&sender, |state| { - assert_eq!(state.windows.len(), 0); + assert_eq!(state.pinnacle.windows.len(), 0); }); Ok(()) @@ -329,7 +329,7 @@ mod window { with_state(&sender, |state| { assert_eq!( - state.windows[0].with_state(|st| st + state.pinnacle.windows[0].with_state(|st| st .tags .iter() .map(|tag| tag.name()) @@ -347,7 +347,7 @@ mod window { with_state(&sender, |state| { assert_eq!( - state.windows[0].with_state(|st| st + state.pinnacle.windows[0].with_state(|st| st .tags .iter() .map(|tag| tag.name()) @@ -365,7 +365,7 @@ mod window { with_state(&sender, |state| { assert_eq!( - state.windows[0].with_state(|st| st + state.pinnacle.windows[0].with_state(|st| st .tags .iter() .map(|tag| tag.name()) @@ -652,8 +652,8 @@ mod output { let original_op = output_for_name(state, DUMMY_OUTPUT_NAME); let first_op = output_for_name(state, "First"); - let original_geo = state.space.output_geometry(&original_op).unwrap(); - let first_geo = state.space.output_geometry(&first_op).unwrap(); + let original_geo = state.pinnacle.space.output_geometry(&original_op).unwrap(); + let first_geo = state.pinnacle.space.output_geometry(&first_op).unwrap(); assert_eq!( original_geo, @@ -674,9 +674,9 @@ mod output { let first_op = output_for_name(state, "First"); let second_op = output_for_name(state, "Second"); - let original_geo = state.space.output_geometry(&original_op).unwrap(); - let first_geo = state.space.output_geometry(&first_op).unwrap(); - let second_geo = state.space.output_geometry(&second_op).unwrap(); + let original_geo = state.pinnacle.space.output_geometry(&original_op).unwrap(); + let first_geo = state.pinnacle.space.output_geometry(&first_op).unwrap(); + let second_geo = state.pinnacle.space.output_geometry(&second_op).unwrap(); assert_eq!( original_geo, @@ -727,10 +727,10 @@ mod output { let second_op = output_for_name(state, "Second"); let third_op = output_for_name(state, "Third"); - let original_geo = state.space.output_geometry(&original_op).unwrap(); - let first_geo = state.space.output_geometry(&first_op).unwrap(); - let second_geo = state.space.output_geometry(&second_op).unwrap(); - let third_geo = state.space.output_geometry(&third_op).unwrap(); + let original_geo = state.pinnacle.space.output_geometry(&original_op).unwrap(); + let first_geo = state.pinnacle.space.output_geometry(&first_op).unwrap(); + let second_geo = state.pinnacle.space.output_geometry(&second_op).unwrap(); + let third_geo = state.pinnacle.space.output_geometry(&third_op).unwrap(); assert_eq!( original_geo, @@ -759,9 +759,9 @@ mod output { let first_op = output_for_name(state, "First"); let third_op = output_for_name(state, "Third"); - let original_geo = state.space.output_geometry(&original_op).unwrap(); - let first_geo = state.space.output_geometry(&first_op).unwrap(); - let third_geo = state.space.output_geometry(&third_op).unwrap(); + let original_geo = state.pinnacle.space.output_geometry(&original_op).unwrap(); + let first_geo = state.pinnacle.space.output_geometry(&first_op).unwrap(); + let third_geo = state.pinnacle.space.output_geometry(&third_op).unwrap(); assert_eq!( original_geo, @@ -793,7 +793,7 @@ async fn window_count_with_tag_is_correct() -> anyhow::Result<()> { sleep_secs(1); - with_state(&sender, |state| assert_eq!(state.windows.len(), 1)); + with_state(&sender, |state| assert_eq!(state.pinnacle.windows.len(), 1)); run_lua! { |Pinnacle| for i = 1, 20 do @@ -803,7 +803,9 @@ async fn window_count_with_tag_is_correct() -> anyhow::Result<()> { sleep_secs(1); - with_state(&sender, |state| assert_eq!(state.windows.len(), 21)); + with_state(&sender, |state| { + assert_eq!(state.pinnacle.windows.len(), 21) + }); Ok(()) }) @@ -819,7 +821,7 @@ async fn window_count_without_tag_is_correct() -> anyhow::Result<()> { sleep_secs(1); - with_state(&sender, |state| assert_eq!(state.windows.len(), 1)); + with_state(&sender, |state| assert_eq!(state.pinnacle.windows.len(), 1)); Ok(()) }) @@ -881,8 +883,8 @@ async fn spawned_window_has_correct_tags() -> anyhow::Result<()> { sleep_secs(1); with_state(&sender, |state| { - assert_eq!(state.windows.len(), 1); - assert_eq!(state.windows[0].with_state(|st| st.tags.len()), 1); + assert_eq!(state.pinnacle.windows.len(), 1); + assert_eq!(state.pinnacle.windows[0].with_state(|st| st.tags.len()), 1); }); run_lua! { |Pinnacle| @@ -894,10 +896,10 @@ async fn spawned_window_has_correct_tags() -> anyhow::Result<()> { sleep_secs(1); with_state(&sender, |state| { - assert_eq!(state.windows.len(), 2); - assert_eq!(state.windows[1].with_state(|st| st.tags.len()), 2); + assert_eq!(state.pinnacle.windows.len(), 2); + assert_eq!(state.pinnacle.windows[1].with_state(|st| st.tags.len()), 2); assert_eq!( - state.windows[1].with_state(|st| st + state.pinnacle.windows[1].with_state(|st| st .tags .iter() .map(|tag| tag.name()) diff --git a/tests/rust_api.rs b/tests/rust_api.rs index e959e11..6d64363 100644 --- a/tests/rust_api.rs +++ b/tests/rust_api.rs @@ -160,8 +160,8 @@ mod output { let original_op = output_for_name(state, DUMMY_OUTPUT_NAME); let first_op = output_for_name(state, "First"); - let original_geo = state.space.output_geometry(&original_op).unwrap(); - let first_geo = state.space.output_geometry(&first_op).unwrap(); + let original_geo = state.pinnacle.space.output_geometry(&original_op).unwrap(); + let first_geo = state.pinnacle.space.output_geometry(&first_op).unwrap(); assert_eq!( original_geo, @@ -182,9 +182,9 @@ mod output { let first_op = output_for_name(state, "First"); let second_op = output_for_name(state, "Second"); - let original_geo = state.space.output_geometry(&original_op).unwrap(); - let first_geo = state.space.output_geometry(&first_op).unwrap(); - let second_geo = state.space.output_geometry(&second_op).unwrap(); + let original_geo = state.pinnacle.space.output_geometry(&original_op).unwrap(); + let first_geo = state.pinnacle.space.output_geometry(&first_op).unwrap(); + let second_geo = state.pinnacle.space.output_geometry(&second_op).unwrap(); assert_eq!( original_geo, @@ -262,10 +262,10 @@ mod output { let second_op = output_for_name(state, "Second"); let third_op = output_for_name(state, "Third"); - let original_geo = state.space.output_geometry(&original_op).unwrap(); - let first_geo = state.space.output_geometry(&first_op).unwrap(); - let second_geo = state.space.output_geometry(&second_op).unwrap(); - let third_geo = state.space.output_geometry(&third_op).unwrap(); + let original_geo = state.pinnacle.space.output_geometry(&original_op).unwrap(); + let first_geo = state.pinnacle.space.output_geometry(&first_op).unwrap(); + let second_geo = state.pinnacle.space.output_geometry(&second_op).unwrap(); + let third_geo = state.pinnacle.space.output_geometry(&third_op).unwrap(); assert_eq!( original_geo, @@ -294,9 +294,9 @@ mod output { let first_op = output_for_name(state, "First"); let third_op = output_for_name(state, "Third"); - let original_geo = state.space.output_geometry(&original_op).unwrap(); - let first_geo = state.space.output_geometry(&first_op).unwrap(); - let third_geo = state.space.output_geometry(&third_op).unwrap(); + let original_geo = state.pinnacle.space.output_geometry(&original_op).unwrap(); + let first_geo = state.pinnacle.space.output_geometry(&first_op).unwrap(); + let third_geo = state.pinnacle.space.output_geometry(&third_op).unwrap(); assert_eq!( original_geo, diff --git a/wlcs_pinnacle/src/main_loop.rs b/wlcs_pinnacle/src/main_loop.rs index f789bbc..aca04b8 100644 --- a/wlcs_pinnacle/src/main_loop.rs +++ b/wlcs_pinnacle/src/main_loop.rs @@ -46,11 +46,11 @@ pub(crate) fn run(channel: Channel) { // when xdiplay is None when starting the config, the grpc server is not // started, until it is set; this bypasses this for now - state.xdisplay = Some(u32::MAX); + state.pinnacle.xdisplay = Some(u32::MAX); run_config(&mut state); // wait for the config to connect to the layout service - while state.layout_state.layout_request_sender.is_none() { + while state.pinnacle.layout_state.layout_request_sender.is_none() { event_loop .dispatch(Some(Duration::from_millis(10)), &mut state) .expect("event_loop error while waiting for config"); @@ -60,10 +60,11 @@ pub(crate) fn run(channel: Channel) { .run(None, &mut state, |state| { state.update_pointer_focus(); state.fixup_z_layering(); - state.space.refresh(); - state.popup_manager.cleanup(); + state.pinnacle.space.refresh(); + state.pinnacle.popup_manager.cleanup(); state + .pinnacle .display_handle .flush_clients() .expect("failed to flush client buffers"); @@ -77,6 +78,7 @@ fn handle_event(event: WlcsEvent, state: &mut State) { WlcsEvent::Stop => state.shutdown(), WlcsEvent::NewClient { stream, client_id } => { let client: Client = state + .pinnacle .display_handle .insert_client(stream, Arc::new(ClientState::default())) .expect("failed to insert new client"); @@ -89,11 +91,18 @@ fn handle_event(event: WlcsEvent, state: &mut State) { } => { let client = state.backend.wlcs_mut().clients.get(&client_id); let window = state + .pinnacle .space .elements() .find(|w| { if let Some(surface) = w.wl_surface() { - state.display_handle.get_client(surface.id()).ok().as_ref() == client + state + .pinnacle + .display_handle + .get_client(surface.id()) + .ok() + .as_ref() + == client && surface.id().protocol_id() == surface_id } else { false @@ -102,9 +111,13 @@ fn handle_event(event: WlcsEvent, state: &mut State) { .cloned(); if let Some(window) = window { - state.space.map_element(window.clone(), location, false); + state + .pinnacle + .space + .map_element(window.clone(), location, false); let size = state + .pinnacle .space .element_geometry(&window) .expect("window to be positioned was not mapped") @@ -119,7 +132,7 @@ fn handle_event(event: WlcsEvent, state: &mut State) { FloatingOrTiled::Floating(Rectangle::from_loc_and_size(location, size)); }); - for output in state.space.outputs_for_element(&window) { + for output in state.pinnacle.space.outputs_for_element(&window) { state.schedule_render(&output); } } @@ -139,7 +152,7 @@ fn handle_event(event: WlcsEvent, state: &mut State) { } => state.process_input_event( WlcsPointerMotionAbsoluteEvent { device_id, - time: Duration::from(state.clock.now()).as_millis() as u64, + time: Duration::from(state.pinnacle.clock.now()).as_millis() as u64, position, } .into(), @@ -147,7 +160,7 @@ fn handle_event(event: WlcsEvent, state: &mut State) { WlcsEvent::PointerMoveRelative { device_id, delta } => state.process_input_event( WlcsPointerMotionEvent { device_id, - time: Duration::from(state.clock.now()).as_millis() as u64, + time: Duration::from(state.pinnacle.clock.now()).as_millis() as u64, delta, } .into(), @@ -159,7 +172,7 @@ fn handle_event(event: WlcsEvent, state: &mut State) { } => state.process_input_event( WlcsPointerButtonEvent { device_id, - time: Duration::from(state.clock.now()).as_millis() as u64, + time: Duration::from(state.pinnacle.clock.now()).as_millis() as u64, button_code: button_id as u32, state: if pressed { ButtonState::Pressed @@ -183,7 +196,7 @@ fn handle_event(event: WlcsEvent, state: &mut State) { } => state.process_input_event( WlcsTouchDownEvent { device_id, - time: Duration::from(state.clock.now()).as_millis() as u64, + time: Duration::from(state.pinnacle.clock.now()).as_millis() as u64, position, } .into(), @@ -194,7 +207,7 @@ fn handle_event(event: WlcsEvent, state: &mut State) { } => state.process_input_event( WlcsTouchDownEvent { device_id, - time: Duration::from(state.clock.now()).as_millis() as u64, + time: Duration::from(state.pinnacle.clock.now()).as_millis() as u64, position, } .into(), @@ -202,7 +215,7 @@ fn handle_event(event: WlcsEvent, state: &mut State) { WlcsEvent::TouchUp { device_id } => state.process_input_event( WlcsTouchUpEvent { device_id, - time: Duration::from(state.clock.now()).as_millis() as u64, + time: Duration::from(state.pinnacle.clock.now()).as_millis() as u64, } .into(), ),