diff --git a/src/api.rs b/src/api.rs index b11edcd..a819a8b 100644 --- a/src/api.rs +++ b/src/api.rs @@ -192,7 +192,7 @@ impl pinnacle_service_server::PinnacleService for PinnacleService { trace!("PinnacleService.quit"); run_unary_no_response(&self.sender, |state| { - state.shutdown(); + state.pinnacle.shutdown(); }) .await } @@ -204,6 +204,7 @@ impl pinnacle_service_server::PinnacleService for PinnacleService { run_unary_no_response(&self.sender, |state| { info!("Reloading config"); state + .pinnacle .start_config(Some( state.pinnacle.config.dir(&state.pinnacle.xdg_base_dirs), )) @@ -734,7 +735,7 @@ impl tag_service_server::TagService for TagService { } run_unary_no_response(&self.sender, move |state| { - let Some(tag) = tag_id.tag(state) else { + let Some(tag) = tag_id.tag(&state.pinnacle) else { return; }; @@ -745,13 +746,13 @@ impl tag_service_server::TagService for TagService { SetOrToggle::Unspecified => unreachable!(), } - let Some(output) = tag.output(state) else { + let Some(output) = tag.output(&state.pinnacle) else { return; }; - state.fixup_xwayland_window_layering(); + state.pinnacle.fixup_xwayland_window_layering(); - state.request_layout(&output); + state.pinnacle.request_layout(&output); state.update_focus(&output); state.schedule_render(&output); }) @@ -768,8 +769,10 @@ impl tag_service_server::TagService for TagService { ); run_unary_no_response(&self.sender, move |state| { - let Some(tag) = tag_id.tag(state) else { return }; - let Some(output) = tag.output(state) else { return }; + let Some(tag) = tag_id.tag(&state.pinnacle) else { return }; + let Some(output) = tag.output(&state.pinnacle) else { + return; + }; output.with_state_mut(|op_state| { for op_tag in op_state.tags.iter_mut() { @@ -778,9 +781,9 @@ impl tag_service_server::TagService for TagService { tag.set_active(true, state); }); - state.fixup_xwayland_window_layering(); + state.pinnacle.fixup_xwayland_window_layering(); - state.request_layout(&output); + state.pinnacle.request_layout(&output); state.update_focus(&output); state.schedule_render(&output); }) @@ -818,7 +821,7 @@ impl tag_service_server::TagService for TagService { .tags .extend(new_tags.clone()); - if let Some(output) = output_name.output(state) { + if let Some(output) = output_name.output(&state.pinnacle) { output.with_state_mut(|state| { state.tags.extend(new_tags.clone()); debug!("tags added, are now {:?}", state.tags); @@ -849,7 +852,9 @@ impl tag_service_server::TagService for TagService { let tag_ids = request.tag_ids.into_iter().map(TagId); run_unary_no_response(&self.sender, move |state| { - let tags_to_remove = tag_ids.flat_map(|id| id.tag(state)).collect::>(); + let tags_to_remove = tag_ids + .flat_map(|id| id.tag(&state.pinnacle)) + .collect::>(); for output in state.pinnacle.space.outputs().cloned().collect::>() { // TODO: seriously, convert state.tags into a hashset @@ -859,7 +864,7 @@ impl tag_service_server::TagService for TagService { } }); - state.request_layout(&output); + state.pinnacle.request_layout(&output); state.schedule_render(&output); } @@ -904,11 +909,11 @@ impl tag_service_server::TagService for TagService { ); run_unary(&self.sender, move |state| { - let tag = tag_id.tag(state); + let tag = tag_id.tag(&state.pinnacle); let output_name = tag .as_ref() - .and_then(|tag| tag.output(state)) + .and_then(|tag| tag.output(&state.pinnacle)) .map(|output| output.name()); let active = tag.as_ref().map(|tag| tag.active()); let name = tag.as_ref().map(|tag| tag.name()); @@ -989,7 +994,7 @@ impl output_service_server::OutputService for OutputService { ); } - let Some(output) = output_name.output(state) else { + let Some(output) = output_name.output(&state.pinnacle) else { return; }; let mut loc = output.current_location(); @@ -999,9 +1004,11 @@ impl output_service_server::OutputService for OutputService { if let Some(y) = y { loc.y = y; } - state.change_output_state(&output, None, None, None, Some(loc)); + state + .pinnacle + .change_output_state(&output, None, None, None, Some(loc)); debug!("Mapping output {} to {loc:?}", output.name()); - state.request_layout(&output); + state.pinnacle.request_layout(&output); }) .await } @@ -1014,7 +1021,7 @@ impl output_service_server::OutputService for OutputService { .output_name .clone() .map(OutputName) - .and_then(|name| name.output(state)) + .and_then(|name| name.output(&state.pinnacle)) else { return; }; @@ -1046,7 +1053,7 @@ impl output_service_server::OutputService for OutputService { }; run_unary_no_response(&self.sender, move |state| { - let Some(output) = OutputName(output_name).output(state) else { + let Some(output) = OutputName(output_name).output(&state.pinnacle) else { return; }; @@ -1059,14 +1066,14 @@ impl output_service_server::OutputService for OutputService { current_scale = f64::max(current_scale, 0.25); - state.change_output_state( + state.pinnacle.change_output_state( &output, None, None, Some(Scale::Fractional(current_scale)), None, ); - state.request_layout(&output); + state.pinnacle.request_layout(&output); state.schedule_render(&output); }) .await @@ -1097,12 +1104,14 @@ impl output_service_server::OutputService for OutputService { }; run_unary_no_response(&self.sender, move |state| { - let Some(output) = OutputName(output_name).output(state) else { + let Some(output) = OutputName(output_name).output(&state.pinnacle) else { return; }; - state.change_output_state(&output, None, Some(smithay_transform), None, None); - state.request_layout(&output); + state + .pinnacle + .change_output_state(&output, None, Some(smithay_transform), None, None); + state.pinnacle.request_layout(&output); state.schedule_render(&output); }) .await @@ -1146,7 +1155,7 @@ impl output_service_server::OutputService for OutputService { }; run_unary(&self.sender, move |state| { - let output = output_name.output(state); + let output = output_name.output(&state.pinnacle); let logical_size = output .as_ref() @@ -1193,6 +1202,7 @@ impl output_service_server::OutputService for OutputService { let y = output.as_ref().map(|output| output.current_location().y); let focused = state + .pinnacle .focused_output() .and_then(|foc_op| output.as_ref().map(|op| op == foc_op)); diff --git a/src/api/layout.rs b/src/api/layout.rs index e541f64..b3826f1 100644 --- a/src/api/layout.rs +++ b/src/api/layout.rs @@ -44,10 +44,10 @@ impl layout_service_server::LayoutService for LayoutService { layout_request::Body::Layout(ExplicitLayout { output_name }) => { if let Some(output) = output_name .map(OutputName) - .and_then(|name| name.output(state)) - .or_else(|| state.focused_output().cloned()) + .and_then(|name| name.output(&state.pinnacle)) + .or_else(|| state.pinnacle.focused_output().cloned()) { - state.request_layout(&output); + state.pinnacle.request_layout(&output); } } } diff --git a/src/api/window.rs b/src/api/window.rs index 162a2e4..10eb952 100644 --- a/src/api/window.rs +++ b/src/api/window.rs @@ -50,7 +50,9 @@ impl window_service_server::WindowService for WindowService { ); run_unary_no_response(&self.sender, move |state| { - let Some(window) = window_id.window(state) else { return }; + let Some(window) = window_id.window(&state.pinnacle) else { + return; + }; match window.underlying_surface() { WindowSurface::Wayland(toplevel) => toplevel.send_close(), @@ -89,7 +91,9 @@ impl window_service_server::WindowService for WindowService { let height = geometry.height; run_unary_no_response(&self.sender, move |state| { - let Some(window) = window_id.window(state) else { return }; + let Some(window) = window_id.window(&state.pinnacle) else { + return; + }; // TODO: with no x or y, defaults unmapped windows to 0, 0 let mut window_loc = state @@ -115,7 +119,7 @@ impl window_service_server::WindowService for WindowService { }); for output in state.pinnacle.space.outputs_for_element(&window) { - state.request_layout(&output); + state.pinnacle.request_layout(&output); state.schedule_render(&output); } }) @@ -141,7 +145,8 @@ impl window_service_server::WindowService for WindowService { } run_unary_no_response(&self.sender, move |state| { - let Some(window) = window_id.window(state) else { + let pinnacle = &mut state.pinnacle; + let Some(window) = window_id.window(pinnacle) else { return; }; @@ -160,11 +165,11 @@ impl window_service_server::WindowService for WindowService { SetOrToggle::Unspecified => unreachable!(), } - let Some(output) = window.output(state) else { + let Some(output) = window.output(pinnacle) else { return; }; - state.request_layout(&output); + pinnacle.request_layout(&output); state.schedule_render(&output); }) .await @@ -189,7 +194,8 @@ impl window_service_server::WindowService for WindowService { } run_unary_no_response(&self.sender, move |state| { - let Some(window) = window_id.window(state) else { + let pinnacle = &mut state.pinnacle; + let Some(window) = window_id.window(pinnacle) else { return; }; @@ -208,11 +214,11 @@ impl window_service_server::WindowService for WindowService { SetOrToggle::Unspecified => unreachable!(), } - let Some(output) = window.output(state) else { + let Some(output) = window.output(pinnacle) else { return; }; - state.request_layout(&output); + pinnacle.request_layout(&output); state.schedule_render(&output); }) .await @@ -237,7 +243,8 @@ impl window_service_server::WindowService for WindowService { } run_unary_no_response(&self.sender, move |state| { - let Some(window) = window_id.window(state) else { + let pinnacle = &mut state.pinnacle; + let Some(window) = window_id.window(pinnacle) else { return; }; @@ -256,11 +263,11 @@ impl window_service_server::WindowService for WindowService { SetOrToggle::Unspecified => unreachable!(), } - let Some(output) = window.output(state) else { + let Some(output) = window.output(pinnacle) else { return; }; - state.request_layout(&output); + pinnacle.request_layout(&output); state.schedule_render(&output); }) .await @@ -285,7 +292,7 @@ impl window_service_server::WindowService for WindowService { } run_unary_no_response(&self.sender, move |state| { - let Some(window) = window_id.window(state) else { + let Some(window) = window_id.window(&state.pinnacle) else { return; }; @@ -293,7 +300,7 @@ impl window_service_server::WindowService for WindowService { return; } - let Some(output) = window.output(state) else { + let Some(output) = window.output(&state.pinnacle) else { return; }; @@ -315,7 +322,7 @@ impl window_service_server::WindowService for WindowService { } } SetOrToggle::Unset => { - if state.focused_window(&output) == Some(window) { + if state.pinnacle.focused_window(&output) == Some(window) { output.with_state_mut(|state| state.focus_stack.unset_focus()); if let Some(keyboard) = state.pinnacle.seat.get_keyboard() { keyboard.set_focus(state, None, SERIAL_COUNTER.next_serial()); @@ -323,7 +330,7 @@ impl window_service_server::WindowService for WindowService { } } SetOrToggle::Toggle => { - if state.focused_window(&output).as_ref() == Some(&window) { + if state.pinnacle.focused_window(&output).as_ref() == Some(&window) { output.with_state_mut(|state| state.focus_stack.unset_focus()); if let Some(keyboard) = state.pinnacle.seat.get_keyboard() { keyboard.set_focus(state, None, SERIAL_COUNTER.next_serial()); @@ -374,13 +381,16 @@ impl window_service_server::WindowService for WindowService { ); run_unary_no_response(&self.sender, move |state| { - let Some(window) = window_id.window(state) else { return }; - let Some(tag) = tag_id.tag(state) else { return }; + let pinnacle = &mut state.pinnacle; + let Some(window) = window_id.window(pinnacle) else { + return; + }; + let Some(tag) = tag_id.tag(pinnacle) else { return }; window.with_state_mut(|state| { state.tags = vec![tag.clone()]; }); - let Some(output) = tag.output(state) else { return }; - state.request_layout(&output); + let Some(output) = tag.output(pinnacle) else { return }; + pinnacle.request_layout(&output); state.schedule_render(&output); }) .await @@ -408,8 +418,11 @@ impl window_service_server::WindowService for WindowService { } run_unary_no_response(&self.sender, move |state| { - let Some(window) = window_id.window(state) else { return }; - let Some(tag) = tag_id.tag(state) else { return }; + let pinnacle = &mut state.pinnacle; + let Some(window) = window_id.window(pinnacle) else { + return; + }; + let Some(tag) = tag_id.tag(pinnacle) else { return }; // TODO: turn state.tags into a hashset match set_or_toggle { @@ -430,8 +443,8 @@ impl window_service_server::WindowService for WindowService { SetOrToggle::Unspecified => unreachable!(), } - let Some(output) = tag.output(state) else { return }; - state.request_layout(&output); + let Some(output) = tag.output(pinnacle) else { return }; + pinnacle.request_layout(&output); state.schedule_render(&output); }) .await @@ -447,12 +460,13 @@ impl window_service_server::WindowService for WindowService { ); run_unary_no_response(&self.sender, move |state| { - let Some(window) = window_id.window(state) else { + let pinnacle = &mut state.pinnacle; + let Some(window) = window_id.window(pinnacle) else { warn!("`raise` was called on a nonexistent window"); return; }; - state.raise_window(window, false); + pinnacle.raise_window(window, false); }) .await } @@ -486,13 +500,7 @@ impl window_service_server::WindowService for WindowService { }; let seat = state.pinnacle.seat.clone(); - crate::grab::move_grab::move_request_server( - state, - &wl_surf, - &seat, - SERIAL_COUNTER.next_serial(), - button, - ); + state.move_request_server(&wl_surf, &seat, SERIAL_COUNTER.next_serial(), button); }) .await } @@ -566,8 +574,7 @@ impl window_service_server::WindowService for WindowService { _ => server::xdg_toplevel::ResizeEdge::None, }; - crate::grab::resize_grab::resize_request_server( - state, + state.resize_request_server( &wl_surf, &state.pinnacle.seat.clone(), SERIAL_COUNTER.next_serial(), @@ -608,7 +615,8 @@ impl window_service_server::WindowService for WindowService { ); run_unary(&self.sender, move |state| { - let window = window_id.window(state); + let pinnacle = &state.pinnacle; + let window = window_id.window(pinnacle); let width = window.as_ref().map(|win| win.geometry().size.w); @@ -639,9 +647,9 @@ impl window_service_server::WindowService for WindowService { let title = window.as_ref().and_then(|win| win.title()); let focused = window.as_ref().and_then(|win| { - state + pinnacle .focused_output() - .and_then(|output| state.focused_window(output)) + .and_then(|output| pinnacle.focused_window(output)) .map(|foc_win| win == &foc_win) }); diff --git a/src/backend/dummy.rs b/src/backend/dummy.rs index 836ecaa..69e1f83 100644 --- a/src/backend/dummy.rs +++ b/src/backend/dummy.rs @@ -14,7 +14,7 @@ use smithay::{ utils::Transform, }; -use crate::state::State; +use crate::state::{Pinnacle, State}; #[cfg(feature = "wlcs")] use super::wlcs::Wlcs; @@ -132,7 +132,7 @@ pub fn setup_dummy( Ok((state, event_loop)) } -impl State { +impl Pinnacle { pub fn new_output(&mut self, name: impl std::fmt::Display, size: Size) { let mode = smithay::output::Mode { size, @@ -152,11 +152,11 @@ impl State { output.set_preferred(mode); - output.create_global::(&self.pinnacle.display_handle); + output.create_global::(&self.display_handle); - self.pinnacle.space.map_output(&output, (0, 0)); + self.space.map_output(&output, (0, 0)); - self.pinnacle.signal_state.output_connect.signal(|buf| { + self.signal_state.output_connect.signal(|buf| { buf.push_back(OutputConnectResponse { output_name: Some(output.name()), }); @@ -164,15 +164,12 @@ impl State { } pub fn remove_output(&mut self, output: &Output) { - self.pinnacle.space.unmap_output(output); + self.space.unmap_output(output); - self.pinnacle - .signal_state - .output_disconnect - .signal(|buffer| { - buffer.push_back(OutputDisconnectResponse { - output_name: Some(output.name()), - }) - }); + self.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 689b9b6..a97c9c5 100644 --- a/src/backend/udev.rs +++ b/src/backend/udev.rs @@ -271,18 +271,20 @@ impl State { { match render_surface.compositor.use_mode(drm_mode) { Ok(()) => { - self.change_output_state(output, Some(mode), None, None, None); + self.pinnacle + .change_output_state(output, Some(mode), None, None, None); } Err(err) => error!("Failed to resize output: {err}"), } } } } else { - self.change_output_state(output, Some(mode), None, None, None); + self.pinnacle + .change_output_state(output, Some(mode), None, None, None); } + self.pinnacle.request_layout(output); self.schedule_render(output); - self.request_layout(output); } } @@ -441,7 +443,7 @@ pub fn setup_udev( let insert_ret = event_loop .handle() .insert_source(libinput_backend, move |event, _, state| { - state.apply_libinput_settings(&event); + state.pinnacle.apply_libinput_settings(&event); state.process_input_event(event); }); @@ -1111,7 +1113,8 @@ impl State { device.surfaces.insert(crtc, surface); - self.change_output_state(&output, Some(wl_mode), None, None, Some(position)); + self.pinnacle + .change_output_state(&output, Some(wl_mode), None, None, Some(position)); // If there is saved connector state, the connector was previously plugged in. // In this case, restore its tags and location. @@ -1124,7 +1127,8 @@ impl State { { let ConnectorSavedState { loc, tags, scale } = saved_state; output.with_state_mut(|state| state.tags = tags.clone()); - self.change_output_state(&output, None, None, *scale, Some(*loc)); + self.pinnacle + .change_output_state(&output, None, None, *scale, Some(*loc)); } else { self.pinnacle.signal_state.output_connect.signal(|buffer| { buffer.push_back(OutputConnectResponse { diff --git a/src/backend/winit.rs b/src/backend/winit.rs index 2517157..59f8676 100644 --- a/src/backend/winit.rs +++ b/src/backend/winit.rs @@ -220,14 +220,14 @@ pub fn setup_winit( size, refresh: 144_000, }; - state.change_output_state( + state.pinnacle.change_output_state( &output, Some(mode), None, Some(Scale::Fractional(scale_factor)), None, ); - state.request_layout(&output); + state.pinnacle.request_layout(&output); } WinitEvent::Focus(focused) => { if focused { @@ -241,12 +241,12 @@ pub fn setup_winit( state.render_winit_window(&output); } WinitEvent::CloseRequested => { - state.shutdown(); + state.pinnacle.shutdown(); } }); if let PumpStatus::Exit(_) = status { - state.shutdown(); + state.pinnacle.shutdown(); } state.render_winit_window(&output); diff --git a/src/backend/wlcs.rs b/src/backend/wlcs.rs index 6536028..6d3fb71 100644 --- a/src/backend/wlcs.rs +++ b/src/backend/wlcs.rs @@ -12,7 +12,7 @@ use smithay::{ use tracing::debug; use crate::{ - state::{State, WithState}, + state::{Pinnacle, State, WithState}, tag::TagId, }; @@ -89,14 +89,14 @@ pub fn setup_wlcs_dummy() -> anyhow::Result<(State, EventLoop<'static, State>)> Ok((state, event_loop)) } -impl State { +impl Pinnacle { pub fn start_wlcs_config(&mut self, socket_dir: &Path, run_config: F) -> anyhow::Result<()> where F: FnOnce() + Send + 'static, { // Clear state debug!("Clearing tags"); - for output in self.pinnacle.space.outputs() { + for output in self.space.outputs() { output.with_state_mut(|state| state.tags.clear()); } @@ -104,23 +104,22 @@ impl State { debug!("Clearing input state"); - self.pinnacle.input_state.clear(); + self.input_state.clear(); - self.pinnacle.config.clear(&self.pinnacle.loop_handle); + self.config.clear(&self.loop_handle); - self.pinnacle.signal_state.clear(); + self.signal_state.clear(); - self.pinnacle.input_state.reload_keybind = None; - self.pinnacle.input_state.kill_keybind = None; + self.input_state.reload_keybind = None; + self.input_state.kill_keybind = None; - if self.pinnacle.grpc_server_join_handle.is_none() { + if self.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| {})?; @@ -129,7 +128,7 @@ impl State { pinger.ping(); }); - self.pinnacle.config.config_reload_on_crash_token = Some(token); + self.config.config_reload_on_crash_token = Some(token); Ok(()) } diff --git a/src/config.rs b/src/config.rs index 95be112..0adb5be 100644 --- a/src/config.rs +++ b/src/config.rs @@ -5,6 +5,7 @@ use crate::{ }, input::ModifierMask, output::OutputName, + state::Pinnacle, tag::Tag, window::rules::{WindowRule, WindowRuleCondition}, }; @@ -266,7 +267,7 @@ fn get_config_dir(xdg_base_dirs: &BaseDirectories) -> PathBuf { config_dir.unwrap_or(xdg_base_dirs.get_config_home()) } -impl State { +impl Pinnacle { /// Start the config in `config_dir`. /// /// If this method is called while a config is already running, it will be replaced. @@ -276,7 +277,7 @@ impl State { // Clear state debug!("Clearing tags"); - for output in self.pinnacle.space.outputs() { + for output in self.space.outputs() { output.with_state_mut(|state| state.tags.clear()); } @@ -284,14 +285,14 @@ impl State { debug!("Clearing input state"); - self.pinnacle.input_state.clear(); + self.input_state.clear(); - self.pinnacle.config.clear(&self.pinnacle.loop_handle); + self.config.clear(&self.loop_handle); - self.pinnacle.signal_state.clear(); + self.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| { + let load_default_config = |pinnacle: &mut Pinnacle, reason: &str| { match &config_dir_clone { Some(dir) => warn!("Unable to load config at {}: {reason}", dir.display()), None => panic!( @@ -300,11 +301,11 @@ impl State { } info!("Falling back to builtin Rust config"); - state.start_config(None::) + pinnacle.start_config(None::) }; // If `--no-config` was set, still load the keybinds from the default metaconfig - if self.pinnacle.config.no_config { + if self.config.no_config { config_dir = None; } @@ -328,17 +329,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.pinnacle.input_state.reload_keybind = Some(reload_keybind); - self.pinnacle.input_state.kill_keybind = Some(kill_keybind); + self.input_state.reload_keybind = Some(reload_keybind); + self.input_state.kill_keybind = Some(kill_keybind); - if self.pinnacle.config.no_config { + if self.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.pinnacle.grpc_server_join_handle.is_none() { + if self.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,8 +357,7 @@ impl State { socket_dir } else { // Otherwise, use $XDG_RUNTIME_DIR. If that doesn't exist, use /tmp. - self.pinnacle - .xdg_base_dirs + self.xdg_base_dirs .get_runtime_directory() .cloned() .unwrap_or(PathBuf::from(DEFAULT_SOCKET_DIR)) @@ -449,32 +449,31 @@ impl State { let (pinger, ping_source) = calloop::ping::make_ping()?; - 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"); - })?; + let token = self + .loop_handle + .insert_source(ping_source, move |_, _, state| { + error!("Config crashed! Falling back to default config"); + state + .pinnacle + .start_config(None::) + .expect("failed to start default config"); + })?; - self.pinnacle.config.config_join_handle = Some(tokio::spawn(async move { + self.config.config_join_handle = Some(tokio::spawn(async move { let _ = child.wait().await; pinger.ping(); })); - self.pinnacle.config.config_reload_on_crash_token = Some(token); + self.config.config_reload_on_crash_token = Some(token); } None => { let (pinger, ping_source) = calloop::ping::make_ping()?; - let token = - self.pinnacle - .loop_handle - .insert_source(ping_source, move |_, _, _state| { - panic!("builtin rust config crashed; this is a bug"); - })?; + let token = self + .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"); @@ -482,7 +481,7 @@ impl State { pinger.ping(); }); - self.pinnacle.config.config_reload_on_crash_token = Some(token); + self.config.config_reload_on_crash_token = Some(token); } } @@ -490,12 +489,10 @@ impl State { } pub fn start_grpc_server(&mut self, socket_dir: &Path) -> anyhow::Result<()> { - self.pinnacle - .system_processes + self.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()) @@ -544,14 +541,13 @@ impl State { std::env::set_var( "PINNACLE_PROTO_DIR", - self.pinnacle.xdg_base_dirs.get_data_file("protobuf"), + self.xdg_base_dirs.get_data_file("protobuf"), ); let (grpc_sender, grpc_receiver) = - calloop::channel::channel::>(); + calloop::channel::channel::>(); - self.pinnacle - .loop_handle + self.loop_handle .insert_source(grpc_receiver, |msg, _, state| match msg { Event::Msg(f) => f(state), Event::Closed => error!("grpc receiver was closed"), @@ -589,9 +585,9 @@ impl State { .add_service(LayoutServiceServer::new(layout_service)) .add_service(RenderServiceServer::new(render_service)); - match self.pinnacle.xdisplay.as_ref() { + match self.xdisplay.as_ref() { Some(_) => { - self.pinnacle.grpc_server_join_handle = Some(tokio::spawn(async move { + self.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 a7e6f1c..2ce0ec1 100644 --- a/src/focus.rs +++ b/src/focus.rs @@ -4,7 +4,7 @@ use smithay::{output::Output, utils::SERIAL_COUNTER}; use tracing::warn; use crate::{ - state::{State, WithState}, + state::{Pinnacle, State, WithState}, window::WindowElement, }; @@ -12,6 +12,31 @@ pub mod keyboard; pub mod pointer; impl State { + /// Update the keyboard focus. + pub fn update_focus(&mut self, output: &Output) { + let current_focus = self.pinnacle.focused_window(output); + + if let Some(win) = ¤t_focus { + assert!(!win.is_x11_override_redirect()); + + if let Some(toplevel) = win.toplevel() { + toplevel.send_configure(); + } + } + + self.pinnacle + .seat + .get_keyboard() + .expect("no keyboard") + .set_focus( + self, + current_focus.map(|win| win.into()), + SERIAL_COUNTER.next_serial(), + ); + } +} + +impl Pinnacle { /// Get the currently focused window on `output`. /// /// This returns the topmost window on the keyboard focus stack that is on an active tag. @@ -35,32 +60,9 @@ impl State { .flatten() } - /// Update the keyboard focus. - pub fn update_focus(&mut self, output: &Output) { - let current_focus = self.focused_window(output); - - if let Some(win) = ¤t_focus { - assert!(!win.is_x11_override_redirect()); - - if let Some(toplevel) = win.toplevel() { - toplevel.send_configure(); - } - } - - 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.pinnacle.z_index_stack.iter() { - self.pinnacle.space.raise_element(win, false); + for win in self.z_index_stack.iter() { + self.space.raise_element(win, false); } } @@ -68,26 +70,25 @@ impl State { /// /// This does nothing if the window is unmapped. pub fn raise_window(&mut self, window: WindowElement, activate: bool) { - if self.pinnacle.space.elements().all(|win| win != &window) { + if self.space.elements().all(|win| win != &window) { warn!("Tried to raise an unmapped window"); return; } - self.pinnacle.space.raise_element(&window, activate); + self.space.raise_element(&window, activate); - self.pinnacle.z_index_stack.retain(|win| win != &window); - self.pinnacle.z_index_stack.push(window); + self.z_index_stack.retain(|win| win != &window); + self.z_index_stack.push(window); 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.pinnacle - .output_focus_stack + self.output_focus_stack .stack .last() - .or_else(|| self.pinnacle.space.outputs().next()) + .or_else(|| self.space.outputs().next()) } } diff --git a/src/grab/move_grab.rs b/src/grab/move_grab.rs index 828c6a7..255d6bc 100644 --- a/src/grab/move_grab.rs +++ b/src/grab/move_grab.rs @@ -50,7 +50,7 @@ impl PointerGrab for MoveSurfaceGrab { return; } - state.raise_window(self.window.clone(), false); + state.pinnacle.raise_window(self.window.clone(), false); if let Some(surface) = self.window.x11_surface() { // INFO: can you raise OR windows or no idk @@ -119,7 +119,9 @@ impl PointerGrab for MoveSurfaceGrab { } debug!("Swapping window positions"); - state.swap_window_positions(&self.window, &window_under); + state + .pinnacle + .swap_window_positions(&self.window, &window_under); } } else { let delta = event.location - self.start_data.location; @@ -271,71 +273,68 @@ impl PointerGrab for MoveSurfaceGrab { } } -/// The application initiated a move grab e.g. when you drag a titlebar. -pub fn move_request_client( - state: &mut State, - surface: &WlSurface, - seat: &Seat, - serial: Serial, -) { - let pointer = seat.get_pointer().expect("seat had no pointer"); - if let Some(start_data) = crate::grab::pointer_grab_start_data(&pointer, surface, serial) { - let Some(window) = state.window_for_surface(surface) else { +impl State { + /// The application initiated a move grab e.g. when you drag a titlebar. + pub fn move_request_client(&mut self, surface: &WlSurface, seat: &Seat, serial: Serial) { + let pointer = seat.get_pointer().expect("seat had no pointer"); + if let Some(start_data) = crate::grab::pointer_grab_start_data(&pointer, surface, serial) { + let Some(window) = self.pinnacle.window_for_surface(surface) else { + warn!("Surface had no window, cancelling move request"); + return; + }; + + let initial_window_loc = self + .pinnacle + .space + .element_location(&window) + .expect("move request was called on an unmapped window"); + + let grab = MoveSurfaceGrab { + start_data, + window, + initial_window_loc, + }; + + pointer.set_grab(self, grab, serial, Focus::Clear); + } else { + debug!("No grab start data for grab, cancelling"); + } + } + + /// The compositor initiated a move grab e.g. you hold the mod key and drag. + pub fn move_request_server( + &mut self, + surface: &WlSurface, + seat: &Seat, + serial: Serial, + button_used: u32, + ) { + let pointer = seat.get_pointer().expect("seat had no pointer"); + let Some(window) = self.pinnacle.window_for_surface(surface) else { warn!("Surface had no window, cancelling move request"); return; }; - let initial_window_loc = state + let initial_window_loc = self .pinnacle .space .element_location(&window) .expect("move request was called on an unmapped window"); + let start_data = smithay::input::pointer::GrabStartData { + focus: pointer + .current_focus() + .map(|focus| (focus, initial_window_loc)), + button: button_used, + location: pointer.current_location(), + }; + let grab = MoveSurfaceGrab { start_data, window, initial_window_loc, }; - pointer.set_grab(state, grab, serial, Focus::Clear); - } else { - debug!("No grab start data for grab, cancelling"); + pointer.set_grab(self, grab, serial, Focus::Clear); } } - -/// The compositor initiated a move grab e.g. you hold the mod key and drag. -pub fn move_request_server( - state: &mut State, - surface: &WlSurface, - seat: &Seat, - serial: Serial, - button_used: u32, -) { - let pointer = seat.get_pointer().expect("seat had no pointer"); - let Some(window) = state.window_for_surface(surface) else { - warn!("Surface had no window, cancelling move request"); - return; - }; - - let initial_window_loc = state - .pinnacle - .space - .element_location(&window) - .expect("move request was called on an unmapped window"); - - let start_data = smithay::input::pointer::GrabStartData { - focus: pointer - .current_focus() - .map(|focus| (focus, initial_window_loc)), - button: button_used, - location: pointer.current_location(), - }; - - let grab = MoveSurfaceGrab { - start_data, - window, - initial_window_loc, - }; - - pointer.set_grab(state, grab, serial, Focus::Clear); -} diff --git a/src/grab/resize_grab.rs b/src/grab/resize_grab.rs index 718ee75..c8af5db 100644 --- a/src/grab/resize_grab.rs +++ b/src/grab/resize_grab.rs @@ -21,7 +21,7 @@ use smithay::{ }; use crate::{ - state::{State, WithState}, + state::{Pinnacle, State, WithState}, window::{window_state::FloatingOrTiled, WindowElement}, }; @@ -362,119 +362,171 @@ impl ResizeSurfaceState { } } -pub fn move_surface_if_resized(state: &mut State, surface: &WlSurface) { - let Some(window) = state.window_for_surface(surface) else { - return; - }; +impl Pinnacle { + pub fn move_surface_if_resized(&mut self, surface: &WlSurface) { + let Some(window) = self.window_for_surface(surface) else { + return; + }; - let Some(mut window_loc) = state.pinnacle.space.element_location(&window) else { - return; - }; - let geometry = window.geometry(); + let Some(mut window_loc) = self.space.element_location(&window) else { + return; + }; + let geometry = window.geometry(); - let new_loc: Option<(Option, Option)> = surface.with_state_mut(|state| { - state - .resize_state - .on_commit() - .map(|(edges, initial_window_rect)| { - let mut new_x: Option = None; - let mut new_y: Option = None; - if let xdg_toplevel::ResizeEdge::Left - | xdg_toplevel::ResizeEdge::TopLeft - | xdg_toplevel::ResizeEdge::BottomLeft = edges.0 - { - new_x = Some( - initial_window_rect.loc.x + (initial_window_rect.size.w - geometry.size.w), - ); - } - if let xdg_toplevel::ResizeEdge::Top - | xdg_toplevel::ResizeEdge::TopLeft - | xdg_toplevel::ResizeEdge::TopRight = edges.0 - { - new_y = Some( - initial_window_rect.loc.y + (initial_window_rect.size.h - geometry.size.h), - ); - } + let new_loc: Option<(Option, Option)> = surface.with_state_mut(|state| { + state + .resize_state + .on_commit() + .map(|(edges, initial_window_rect)| { + let mut new_x: Option = None; + let mut new_y: Option = None; + if let xdg_toplevel::ResizeEdge::Left + | xdg_toplevel::ResizeEdge::TopLeft + | xdg_toplevel::ResizeEdge::BottomLeft = edges.0 + { + new_x = Some( + initial_window_rect.loc.x + + (initial_window_rect.size.w - geometry.size.w), + ); + } + if let xdg_toplevel::ResizeEdge::Top + | xdg_toplevel::ResizeEdge::TopLeft + | xdg_toplevel::ResizeEdge::TopRight = edges.0 + { + new_y = Some( + initial_window_rect.loc.y + + (initial_window_rect.size.h - geometry.size.h), + ); + } - (new_x, new_y) - }) - }); + (new_x, new_y) + }) + }); - if window.with_state(|state| state.floating_or_tiled.is_tiled()) { - return; - } - - let Some(new_loc) = new_loc else { return }; - - if let Some(new_x) = new_loc.0 { - window_loc.x = new_x; - } - if let Some(new_y) = new_loc.1 { - window_loc.y = new_y; - } - - let size = state - .pinnacle - .space - .element_geometry(&window) - .expect("called element_geometry on unmapped window") - .size; - - window.with_state_mut(|state| { - if state.floating_or_tiled.is_floating() { - state.floating_or_tiled = - FloatingOrTiled::Floating(Rectangle::from_loc_and_size(window_loc, size)); + if window.with_state(|state| state.floating_or_tiled.is_tiled()) { + return; } - }); - if new_loc.0.is_some() || new_loc.1.is_some() { - state - .pinnacle + let Some(new_loc) = new_loc else { return }; + + if let Some(new_x) = new_loc.0 { + window_loc.x = new_x; + } + if let Some(new_y) = new_loc.1 { + window_loc.y = new_y; + } + + let size = self .space - .map_element(window.clone(), window_loc, false); + .element_geometry(&window) + .expect("called element_geometry on unmapped window") + .size; - if let Some(surface) = window.x11_surface() { - if !surface.is_override_redirect() { - let geo = surface.geometry(); - let new_geo = Rectangle::from_loc_and_size(window_loc, geo.size); - surface - .configure(new_geo) - .expect("failed to configure x11 win"); + window.with_state_mut(|state| { + if state.floating_or_tiled.is_floating() { + state.floating_or_tiled = + FloatingOrTiled::Floating(Rectangle::from_loc_and_size(window_loc, size)); + } + }); + + if new_loc.0.is_some() || new_loc.1.is_some() { + self.space.map_element(window.clone(), window_loc, false); + + if let Some(surface) = window.x11_surface() { + if !surface.is_override_redirect() { + let geo = surface.geometry(); + let new_geo = Rectangle::from_loc_and_size(window_loc, geo.size); + surface + .configure(new_geo) + .expect("failed to configure x11 win"); + } } } } } -/// The application requests a resize e.g. when you drag the edges of a window. -pub fn resize_request_client( - state: &mut State, - surface: &WlSurface, - seat: &Seat, - serial: smithay::utils::Serial, - edges: self::ResizeEdge, - button_used: u32, -) { - let pointer = seat.get_pointer().expect("seat had no pointer"); +impl State { + /// The application requests a resize e.g. when you drag the edges of a window. + pub fn resize_request_client( + &mut self, + surface: &WlSurface, + seat: &Seat, + serial: smithay::utils::Serial, + edges: self::ResizeEdge, + button_used: u32, + ) { + let pointer = seat.get_pointer().expect("seat had no pointer"); - if let Some(start_data) = crate::grab::pointer_grab_start_data(&pointer, surface, serial) { - let Some(window) = state.window_for_surface(surface) else { + if let Some(start_data) = crate::grab::pointer_grab_start_data(&pointer, surface, serial) { + let Some(window) = self.pinnacle.window_for_surface(surface) else { + tracing::error!("Surface had no window, cancelling resize request"); + return; + }; + + // TODO: check for fullscreen/maximized (probably shouldn't matter) + if window.with_state(|state| state.floating_or_tiled.is_tiled()) { + return; + } + + let initial_window_loc = self + .pinnacle + .space + .element_location(&window) + .expect("resize request called on unmapped window"); + let initial_window_size = window.geometry().size; + + if let Some(window) = self.pinnacle.window_for_surface(surface) { + if let Some(toplevel) = window.toplevel() { + toplevel.with_pending_state(|state| { + state.states.set(xdg_toplevel::State::Resizing); + }); + + toplevel.send_pending_configure(); + } + } + + let grab = ResizeSurfaceGrab::start( + start_data, + window, + edges, + Rectangle::from_loc_and_size(initial_window_loc, initial_window_size), + button_used, + ); + + if let Some(grab) = grab { + pointer.set_grab(self, grab, serial, Focus::Clear); + } + } + } + + /// The compositor requested a resize e.g. you hold the mod key and right-click drag. + pub fn resize_request_server( + &mut self, + surface: &WlSurface, + seat: &Seat, + serial: smithay::utils::Serial, + edges: self::ResizeEdge, + button_used: u32, + ) { + let pointer = seat.get_pointer().expect("seat had no pointer"); + + let Some(window) = self.pinnacle.window_for_surface(surface) else { tracing::error!("Surface had no window, cancelling resize request"); return; }; - // TODO: check for fullscreen/maximized (probably shouldn't matter) if window.with_state(|state| state.floating_or_tiled.is_tiled()) { return; } - let initial_window_loc = state + let initial_window_loc = self .pinnacle .space .element_location(&window) .expect("resize request called on unmapped window"); let initial_window_size = window.geometry().size; - if let Some(window) = state.window_for_surface(surface) { + if let Some(window) = self.pinnacle.window_for_surface(surface) { if let Some(toplevel) = window.toplevel() { toplevel.with_pending_state(|state| { state.states.set(xdg_toplevel::State::Resizing); @@ -484,6 +536,14 @@ pub fn resize_request_client( } } + let start_data = smithay::input::pointer::GrabStartData { + focus: pointer + .current_focus() + .map(|focus| (focus, initial_window_loc)), + button: button_used, + location: pointer.current_location(), + }; + let grab = ResizeSurfaceGrab::start( start_data, window, @@ -493,65 +553,7 @@ pub fn resize_request_client( ); if let Some(grab) = grab { - pointer.set_grab(state, grab, serial, Focus::Clear); + pointer.set_grab(self, grab, serial, Focus::Clear); } } } - -/// The compositor requested a resize e.g. you hold the mod key and right-click drag. -pub fn resize_request_server( - state: &mut State, - surface: &WlSurface, - seat: &Seat, - serial: smithay::utils::Serial, - edges: self::ResizeEdge, - button_used: u32, -) { - let pointer = seat.get_pointer().expect("seat had no pointer"); - - let Some(window) = state.window_for_surface(surface) else { - tracing::error!("Surface had no window, cancelling resize request"); - return; - }; - - if window.with_state(|state| state.floating_or_tiled.is_tiled()) { - return; - } - - let initial_window_loc = state - .pinnacle - .space - .element_location(&window) - .expect("resize request called on unmapped window"); - let initial_window_size = window.geometry().size; - - if let Some(window) = state.window_for_surface(surface) { - if let Some(toplevel) = window.toplevel() { - toplevel.with_pending_state(|state| { - state.states.set(xdg_toplevel::State::Resizing); - }); - - toplevel.send_pending_configure(); - } - } - - let start_data = smithay::input::pointer::GrabStartData { - focus: pointer - .current_focus() - .map(|focus| (focus, initial_window_loc)), - button: button_used, - location: pointer.current_location(), - }; - - let grab = ResizeSurfaceGrab::start( - start_data, - window, - edges, - Rectangle::from_loc_and_size(initial_window_loc, initial_window_size), - button_used, - ); - - if let Some(grab) = grab { - pointer.set_grab(state, grab, serial, Focus::Clear); - } -} diff --git a/src/handlers.rs b/src/handlers.rs index 385e80b..d4741a8 100644 --- a/src/handlers.rs +++ b/src/handlers.rs @@ -67,7 +67,7 @@ use crate::{ gamma_control::{GammaControlHandler, GammaControlManagerState}, screencopy::{Screencopy, ScreencopyHandler}, }, - state::{ClientState, State, WithState}, + state::{ClientState, Pinnacle, State, WithState}, }; impl BufferHandler for State { @@ -130,7 +130,7 @@ impl CompositorHandler for State { } if !compositor::is_sync_subsurface(surface) { - if let Some(window) = self.window_for_surface(&root) { + if let Some(window) = self.pinnacle.window_for_surface(&root) { window.on_commit(); if let Some(loc) = window.with_state_mut(|state| state.target_loc.take()) { self.pinnacle.space.map_element(window.clone(), loc, false); @@ -157,7 +157,7 @@ impl CompositorHandler for State { self.pinnacle.new_windows.retain(|win| win != &new_window); self.pinnacle.windows.push(new_window.clone()); - if let Some(output) = self.focused_output() { + if let Some(output) = self.pinnacle.focused_output() { tracing::debug!("Placing toplevel"); new_window.place_on_output(output); output.with_state_mut(|state| state.focus_stack.set_focus(new_window.clone())); @@ -170,12 +170,12 @@ impl CompositorHandler for State { .space .map_element(new_window.clone(), (1000000, 0), true); - self.raise_window(new_window.clone(), true); + self.pinnacle.raise_window(new_window.clone(), true); - self.apply_window_rules(&new_window); + self.pinnacle.apply_window_rules(&new_window); - if let Some(focused_output) = self.focused_output().cloned() { - self.request_layout(&focused_output); + if let Some(focused_output) = self.pinnacle.focused_output().cloned() { + self.pinnacle.request_layout(&focused_output); new_window.send_frame( &focused_output, self.pinnacle.clock.now(), @@ -198,28 +198,28 @@ impl CompositorHandler for State { }); } else if new_window.toplevel().is_some() { new_window.on_commit(); - ensure_initial_configure(surface, self); + self.pinnacle.ensure_initial_configure(surface); } return; } - ensure_initial_configure(surface, self); + self.pinnacle.ensure_initial_configure(surface); - crate::grab::resize_grab::move_surface_if_resized(self, surface); + self.pinnacle.move_surface_if_resized(surface); - let outputs = if let Some(window) = self.window_for_surface(surface) { + let outputs = if let Some(window) = self.pinnacle.window_for_surface(surface) { 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 - if let Some(output) = window.output(self) { + if let Some(output) = window.output(&self.pinnacle) { outputs.push(output); } outputs // surface is a window - } else if let Some(window) = self.window_for_surface(&root) { + } else if let Some(window) = self.pinnacle.window_for_surface(&root) { let mut outputs = self.pinnacle.space.outputs_for_element(&window); - if let Some(output) = window.output(self) { + if let Some(output) = window.output(&self.pinnacle) { outputs.push(output); } outputs // surface is a root window @@ -270,73 +270,75 @@ impl CompositorHandler for State { } delegate_compositor!(State); -fn ensure_initial_configure(surface: &WlSurface, state: &mut State) { - if let (Some(window), _) | (None, Some(window)) = ( - state.window_for_surface(surface), - state.new_window_for_surface(surface), - ) { - if let Some(toplevel) = window.toplevel() { +impl Pinnacle { + fn ensure_initial_configure(&mut self, surface: &WlSurface) { + if let (Some(window), _) | (None, Some(window)) = ( + self.window_for_surface(surface), + self.new_window_for_surface(surface), + ) { + if let Some(toplevel) = window.toplevel() { + let initial_configure_sent = compositor::with_states(surface, |states| { + states + .data_map + .get::() + .expect("XdgToplevelSurfaceData wasn't in surface's data map") + .lock() + .expect("Failed to lock Mutex") + .initial_configure_sent + }); + + if !initial_configure_sent { + tracing::debug!("Initial configure"); + toplevel.send_configure(); + } + } + return; + } + + if let Some(popup) = self.popup_manager.find_popup(surface) { + let PopupKind::Xdg(popup) = &popup else { return }; let initial_configure_sent = compositor::with_states(surface, |states| { states .data_map - .get::() - .expect("XdgToplevelSurfaceData wasn't in surface's data map") + .get::() + .expect("XdgPopupSurfaceData wasn't in popup's data map") .lock() - .expect("Failed to lock Mutex") + .expect("Failed to lock Mutex") + .initial_configure_sent + }); + if !initial_configure_sent { + popup + .send_configure() + .expect("popup initial configure failed"); + } + return; + } + + if let Some(output) = self.space.outputs().find(|op| { + let map = layer_map_for_output(op); + map.layer_for_surface(surface, WindowSurfaceType::TOPLEVEL) + .is_some() + }) { + layer_map_for_output(output).arrange(); + + let initial_configure_sent = compositor::with_states(surface, |states| { + states + .data_map + .get::() + .expect("no LayerSurfaceData") + .lock() + .expect("failed to lock data") .initial_configure_sent }); if !initial_configure_sent { - tracing::debug!("Initial configure"); - toplevel.send_configure(); + layer_map_for_output(output) + .layer_for_surface(surface, WindowSurfaceType::TOPLEVEL) + .expect("no layer for surface") + .layer_surface() + .send_configure(); } } - return; - } - - 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 - .data_map - .get::() - .expect("XdgPopupSurfaceData wasn't in popup's data map") - .lock() - .expect("Failed to lock Mutex") - .initial_configure_sent - }); - if !initial_configure_sent { - popup - .send_configure() - .expect("popup initial configure failed"); - } - return; - } - - 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() - }) { - layer_map_for_output(output).arrange(); - - let initial_configure_sent = compositor::with_states(surface, |states| { - states - .data_map - .get::() - .expect("no LayerSurfaceData") - .lock() - .expect("failed to lock data") - .initial_configure_sent - }); - - if !initial_configure_sent { - layer_map_for_output(output) - .layer_for_surface(surface, WindowSurfaceType::TOPLEVEL) - .expect("no layer for surface") - .layer_surface() - .send_configure(); - } } } @@ -477,7 +479,7 @@ impl FractionalScaleHandler for State { compositor::with_states(&root, |states| { desktop::utils::surface_primary_scanout_output(&root, states) .or_else(|| { - self.window_for_surface(&root).and_then(|window| { + self.pinnacle.window_for_surface(&root).and_then(|window| { self.pinnacle .space .outputs_for_element(&window) @@ -487,7 +489,7 @@ impl FractionalScaleHandler for State { }) }) } else { - self.window_for_surface(&root).and_then(|window| { + self.pinnacle.window_for_surface(&root).and_then(|window| { self.pinnacle .space .outputs_for_element(&window) @@ -542,7 +544,7 @@ impl WlrLayerShellHandler for State { } self.pinnacle.loop_handle.insert_idle(move |state| { - state.request_layout(&output); + state.pinnacle.request_layout(&output); }); } @@ -562,14 +564,14 @@ impl WlrLayerShellHandler for State { if let Some(output) = output { self.pinnacle.loop_handle.insert_idle(move |state| { - state.request_layout(&output); + state.pinnacle.request_layout(&output); }); } } fn new_popup(&mut self, _parent: wlr_layer::LayerSurface, popup: PopupSurface) { trace!("WlrLayerShellHandler::new_popup"); - self.position_popup(&popup); + self.pinnacle.position_popup(&popup); } } delegate_layer_shell!(State); @@ -636,7 +638,7 @@ impl GammaControlHandler for State { } delegate_gamma_control!(State); -impl State { +impl Pinnacle { fn position_popup(&self, popup: &PopupSurface) { trace!("State::position_popup"); let Ok(root) = find_popup_root_surface(&PopupKind::Xdg(popup.clone())) else { @@ -656,13 +658,13 @@ impl State { } let (root_global_loc, output) = if let Some(win) = self.window_for_surface(&root) { - let win_geo = self.pinnacle.space.element_geometry(&win)?; + let win_geo = self.space.element_geometry(&win)?; (win_geo.loc, self.focused_output()?.clone()) } else { - self.pinnacle.space.outputs().find_map(|op| { + self.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.pinnacle.space.output_geometry(op)?.loc; + let output_loc = self.space.output_geometry(op)?.loc; Some(( layer_map.layer_geometry(layer)?.loc + output_loc, op.clone(), @@ -676,7 +678,7 @@ impl State { root_global_loc + get_popup_toplevel_coords(&PopupKind::Xdg(popup.clone())) }; - let mut output_geo = self.pinnacle.space.output_geometry(&output)?; + let mut output_geo = self.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 f63c4bf..a7c0817 100644 --- a/src/handlers/xdg_shell.rs +++ b/src/handlers/xdg_shell.rs @@ -70,19 +70,20 @@ impl XdgShellHandler for State { }); } - let Some(window) = self.window_for_surface(surface.wl_surface()) else { + let Some(window) = self.pinnacle.window_for_surface(surface.wl_surface()) else { return; }; - if let Some(output) = window.output(self) { - self.request_layout(&output); + if let Some(output) = window.output(&self.pinnacle) { + self.pinnacle.request_layout(&output); let focus = self + .pinnacle .focused_window(&output) .map(KeyboardFocusTarget::Window); if let Some(KeyboardFocusTarget::Window(window)) = &focus { tracing::debug!("Focusing on prev win"); // TODO: - self.raise_window(window.clone(), true); + self.pinnacle.raise_window(window.clone(), true); if let Some(toplevel) = window.toplevel() { toplevel.send_configure(); } @@ -100,7 +101,7 @@ impl XdgShellHandler for State { fn new_popup(&mut self, surface: PopupSurface, _positioner: PositionerState) { trace!("XdgShellHandler::new_popup"); - self.position_popup(&surface); + self.pinnacle.position_popup(&surface); if let Err(err) = self .pinnacle @@ -120,8 +121,7 @@ impl XdgShellHandler for State { fn move_request(&mut self, surface: ToplevelSurface, seat: WlSeat, serial: Serial) { tracing::debug!("move_request_client"); - crate::grab::move_grab::move_request_client( - self, + self.move_request_client( surface.wl_surface(), &Seat::from_resource(&seat).expect("couldn't get seat from WlSeat"), serial, @@ -136,8 +136,7 @@ impl XdgShellHandler for State { edges: ResizeEdge, ) { const BUTTON_LEFT: u32 = 0x110; - crate::grab::resize_grab::resize_request_client( - self, + self.resize_request_client( surface.wl_surface(), &Seat::from_resource(&seat).expect("couldn't get seat from WlSeat"), serial, @@ -158,7 +157,7 @@ impl XdgShellHandler for State { state.geometry = positioner.get_geometry(); state.positioner = positioner; }); - self.position_popup(&surface); + self.pinnacle.position_popup(&surface); surface.send_repositioned(token); } @@ -166,7 +165,8 @@ impl XdgShellHandler for State { let seat: Seat = Seat::from_resource(&seat).expect("couldn't get seat from WlSeat"); let popup_kind = PopupKind::Xdg(surface); if let Some(root) = find_popup_root_surface(&popup_kind).ok().and_then(|root| { - self.window_for_surface(&root) + self.pinnacle + .window_for_surface(&root) .map(KeyboardFocusTarget::Window) .or_else(|| { self.pinnacle.space.outputs().find_map(|op| { @@ -223,13 +223,15 @@ impl XdgShellHandler for State { .as_ref() .and_then(Output::from_resource) .or_else(|| { - self.window_for_surface(wl_surface).and_then(|window| { - self.pinnacle - .space - .outputs_for_element(&window) - .first() - .cloned() - }) + self.pinnacle + .window_for_surface(wl_surface) + .and_then(|window| { + self.pinnacle + .space + .outputs_for_element(&window) + .first() + .cloned() + }) }); if let Some(output) = output { @@ -253,14 +255,14 @@ impl XdgShellHandler for State { state.fullscreen_output = wl_output; }); - let Some(window) = self.window_for_surface(wl_surface) else { + let Some(window) = self.pinnacle.window_for_surface(wl_surface) else { tracing::error!("wl_surface had no window"); return; }; if !window.with_state(|state| state.fullscreen_or_maximized.is_fullscreen()) { window.toggle_fullscreen(); - self.request_layout(&output); + self.pinnacle.request_layout(&output); } } @@ -284,21 +286,21 @@ impl XdgShellHandler for State { surface.send_pending_configure(); - let Some(window) = self.window_for_surface(surface.wl_surface()) else { + let Some(window) = self.pinnacle.window_for_surface(surface.wl_surface()) else { tracing::error!("wl_surface had no window"); return; }; if window.with_state(|state| state.fullscreen_or_maximized.is_fullscreen()) { window.toggle_fullscreen(); - if let Some(output) = window.output(self) { - self.request_layout(&output); + if let Some(output) = window.output(&self.pinnacle) { + self.pinnacle.request_layout(&output); } } } fn maximize_request(&mut self, surface: ToplevelSurface) { - let Some(window) = self.window_for_surface(surface.wl_surface()) else { + let Some(window) = self.pinnacle.window_for_surface(surface.wl_surface()) else { return; }; @@ -306,12 +308,14 @@ impl XdgShellHandler for State { window.toggle_maximized(); } - let Some(output) = window.output(self) else { return }; - self.request_layout(&output); + let Some(output) = window.output(&self.pinnacle) else { + return; + }; + self.pinnacle.request_layout(&output); } fn unmaximize_request(&mut self, surface: ToplevelSurface) { - let Some(window) = self.window_for_surface(surface.wl_surface()) else { + let Some(window) = self.pinnacle.window_for_surface(surface.wl_surface()) else { return; }; @@ -319,8 +323,10 @@ impl XdgShellHandler for State { window.toggle_maximized(); } - let Some(output) = window.output(self) else { return }; - self.request_layout(&output); + let Some(output) = window.output(&self.pinnacle) else { + return; + }; + self.pinnacle.request_layout(&output); } fn minimize_request(&mut self, _surface: ToplevelSurface) { diff --git a/src/handlers/xwayland.rs b/src/handlers/xwayland.rs index fea379b..60b5581 100644 --- a/src/handlers/xwayland.rs +++ b/src/handlers/xwayland.rs @@ -26,7 +26,7 @@ use tracing::{debug, error, trace, warn}; use crate::{ focus::keyboard::KeyboardFocusTarget, - state::{State, WithState}, + state::{Pinnacle, State, WithState}, window::{window_state::FloatingOrTiled, WindowElement}, }; @@ -58,12 +58,14 @@ impl XwmHandler for State { .expect("called element_bbox on an unmapped window"); let output_size = self + .pinnacle .focused_output() .and_then(|op| self.pinnacle.space.output_geometry(op)) .map(|geo| geo.size) .unwrap_or((2, 2).into()); let output_loc = self + .pinnacle .focused_output() .map(|op| op.current_location()) .unwrap_or((0, 0).into()); @@ -92,7 +94,7 @@ impl XwmHandler for State { .expect("failed to configure x11 window"); // TODO: ssd - if let Some(output) = self.focused_output() { + if let Some(output) = self.pinnacle.focused_output() { window.place_on_output(output); } @@ -104,13 +106,13 @@ impl XwmHandler for State { // TODO: will an unmap -> map duplicate the window self.pinnacle.windows.push(window.clone()); - self.raise_window(window.clone(), true); + self.pinnacle.raise_window(window.clone(), true); - self.apply_window_rules(&window); + self.pinnacle.apply_window_rules(&window); - if let Some(output) = window.output(self) { + if let Some(output) = window.output(&self.pinnacle) { output.with_state_mut(|state| state.focus_stack.set_focus(window.clone())); - self.request_layout(&output); + self.pinnacle.request_layout(&output); } self.pinnacle.loop_handle.insert_idle(move |state| { @@ -138,7 +140,7 @@ impl XwmHandler for State { self.pinnacle.windows.push(window.clone()); - if let Some(output) = self.focused_output() { + if let Some(output) = self.pinnacle.focused_output() { window.place_on_output(output); // FIXME: setting focus here may possibly muck things up // | or maybe they won't idk @@ -146,15 +148,15 @@ impl XwmHandler for State { } self.pinnacle.space.map_element(window.clone(), loc, true); - self.raise_window(window.clone(), true); + self.pinnacle.raise_window(window.clone(), true); } fn map_window_notify(&mut self, _xwm: XwmId, window: X11Surface) { trace!("XwmHandler::map_window_notify"); let Some(output) = window .wl_surface() - .and_then(|s| self.window_for_surface(&s)) - .and_then(|win| win.output(self)) + .and_then(|s| self.pinnacle.window_for_surface(&s)) + .and_then(|win| win.output(&self.pinnacle)) else { return; }; @@ -189,15 +191,16 @@ impl XwmHandler for State { self.pinnacle.space.unmap_elem(&win); - if let Some(output) = win.output(self) { - self.request_layout(&output); + if let Some(output) = win.output(&self.pinnacle) { + self.pinnacle.request_layout(&output); let focus = self + .pinnacle .focused_window(&output) .map(KeyboardFocusTarget::Window); if let Some(KeyboardFocusTarget::Window(win)) = &focus { - self.raise_window(win.clone(), true); + self.pinnacle.raise_window(win.clone(), true); if let Some(toplevel) = win.toplevel() { toplevel.send_configure(); } @@ -255,15 +258,16 @@ impl XwmHandler for State { .z_index_stack .retain(|elem| win.wl_surface() != elem.wl_surface()); - if let Some(output) = win.output(self) { - self.request_layout(&output); + if let Some(output) = win.output(&self.pinnacle) { + self.pinnacle.request_layout(&output); let focus = self + .pinnacle .focused_window(&output) .map(KeyboardFocusTarget::Window); if let Some(KeyboardFocusTarget::Window(win)) = &focus { - self.raise_window(win.clone(), true); + self.pinnacle.raise_window(win.clone(), true); if let Some(toplevel) = win.toplevel() { toplevel.send_configure(); } @@ -355,7 +359,7 @@ impl XwmHandler for State { let Some(window) = window .wl_surface() - .and_then(|surf| self.window_for_surface(&surf)) + .and_then(|surf| self.pinnacle.window_for_surface(&surf)) else { return; }; @@ -372,7 +376,7 @@ impl XwmHandler for State { let Some(window) = window .wl_surface() - .and_then(|surf| self.window_for_surface(&surf)) + .and_then(|surf| self.pinnacle.window_for_surface(&surf)) else { return; }; @@ -389,15 +393,15 @@ impl XwmHandler for State { let Some(window) = window .wl_surface() - .and_then(|surf| self.window_for_surface(&surf)) + .and_then(|surf| self.pinnacle.window_for_surface(&surf)) else { return; }; if !window.with_state(|state| state.fullscreen_or_maximized.is_fullscreen()) { window.toggle_fullscreen(); - if let Some(output) = window.output(self) { - self.request_layout(&output); + if let Some(output) = window.output(&self.pinnacle) { + self.pinnacle.request_layout(&output); } } } @@ -409,15 +413,15 @@ impl XwmHandler for State { let Some(window) = window .wl_surface() - .and_then(|surf| self.window_for_surface(&surf)) + .and_then(|surf| self.pinnacle.window_for_surface(&surf)) else { return; }; if window.with_state(|state| state.fullscreen_or_maximized.is_fullscreen()) { window.toggle_fullscreen(); - if let Some(output) = window.output(self) { - self.request_layout(&output); + if let Some(output) = window.output(&self.pinnacle) { + self.pinnacle.request_layout(&output); } } } @@ -434,8 +438,7 @@ impl XwmHandler for State { // We use the server one and not the client because windows like Steam don't provide // GrabStartData, so we need to create it ourselves. - crate::grab::resize_grab::resize_request_server( - self, + self.resize_request_server( &wl_surf, &seat, SERIAL_COUNTER.next_serial(), @@ -450,13 +453,7 @@ impl XwmHandler for State { // We use the server one and not the client because windows like Steam don't provide // GrabStartData, so we need to create it ourselves. - crate::grab::move_grab::move_request_server( - self, - &wl_surf, - &seat, - SERIAL_COUNTER.next_serial(), - button, - ); + self.move_request_server(&wl_surf, &seat, SERIAL_COUNTER.next_serial(), button); } fn allow_selection_access(&mut self, xwm: XwmId, _selection: SelectionTarget) -> bool { @@ -542,14 +539,13 @@ impl XwmHandler for State { } } -impl State { +impl Pinnacle { pub fn fixup_xwayland_window_layering(&mut self) { - let Some(xwm) = self.pinnacle.xwm.as_mut() else { + let Some(xwm) = self.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 3f671e0..41162b3 100644 --- a/src/input.rs +++ b/src/input.rs @@ -452,11 +452,12 @@ impl State { self.switch_vt(vt); } Some(KeyAction::Quit) => { - self.shutdown(); + self.pinnacle.shutdown(); } Some(KeyAction::ReloadConfig) => { info!("Reloading config"); - self.start_config(Some(self.pinnacle.config.dir(&self.pinnacle.xdg_base_dirs))) + self.pinnacle + .start_config(Some(self.pinnacle.config.dir(&self.pinnacle.xdg_base_dirs))) .expect("failed to restart config"); } None => (), @@ -511,8 +512,8 @@ impl State { // TODO: use update_keyboard_focus from anvil if let Some(window) = focus.window_for(self) { - self.raise_window(window.clone(), true); - if let Some(output) = window.output(self) { + self.pinnacle.raise_window(window.clone(), true); + if let Some(output) = window.output(&self.pinnacle) { output.with_state_mut(|state| state.focus_stack.set_focus(window.clone())); } } @@ -531,7 +532,7 @@ impl State { } } } else { - if let Some(focused_op) = self.focused_output() { + if let Some(focused_op) = self.pinnacle.focused_output() { focused_op.with_state_mut(|state| { state.focus_stack.unset_focus(); for window in state.focus_stack.stack.iter() { @@ -728,7 +729,7 @@ impl State { pointer.frame(self); - if let Some(output) = self.focused_output().cloned() { + if let Some(output) = self.pinnacle.focused_output().cloned() { self.schedule_render(&output); } } diff --git a/src/input/libinput.rs b/src/input/libinput.rs index 280a20c..7e1a485 100644 --- a/src/input/libinput.rs +++ b/src/input/libinput.rs @@ -1,15 +1,14 @@ use smithay::backend::{input::InputEvent, libinput::LibinputInputBackend}; -use crate::state::State; +use crate::state::Pinnacle; -impl State { +impl Pinnacle { /// Apply current libinput settings to new devices. pub fn apply_libinput_settings(&mut self, event: &InputEvent) { let mut device = match event { InputEvent::DeviceAdded { device } => device.clone(), InputEvent::DeviceRemoved { device } => { - self.pinnacle - .input_state + self.input_state .libinput_devices .retain(|dev| dev != device); return; @@ -17,14 +16,14 @@ impl State { _ => return, }; - if self.pinnacle.input_state.libinput_devices.contains(&device) { + if self.input_state.libinput_devices.contains(&device) { return; } - for setting in self.pinnacle.input_state.libinput_settings.values() { + for setting in self.input_state.libinput_settings.values() { setting(&mut device); } - self.pinnacle.input_state.libinput_devices.push(device); + self.input_state.libinput_devices.push(device); } } diff --git a/src/layout.rs b/src/layout.rs index b195451..be011ce 100644 --- a/src/layout.rs +++ b/src/layout.rs @@ -18,14 +18,14 @@ use tracing::warn; use crate::{ output::OutputName, - state::{State, WithState}, + state::{Pinnacle, State, WithState}, window::{ window_state::{FloatingOrTiled, FullscreenOrMaximized}, WindowElement, }, }; -impl State { +impl Pinnacle { fn update_windows_with_geometries( &mut self, output: &Output, @@ -33,8 +33,7 @@ impl State { ) { let windows_on_foc_tags = output.with_state(|state| { let focused_tags = state.focused_tags().collect::>(); - self.pinnacle - .windows + self.windows .iter() .filter(|win| !win.is_x11_override_redirect()) .filter(|win| { @@ -53,11 +52,7 @@ impl State { }) .cloned(); - let output_geo = self - .pinnacle - .space - .output_geometry(output) - .expect("no output geo"); + let output_geo = self.space.output_geometry(output).expect("no output geo"); let non_exclusive_geo = { let map = layer_map_for_output(output); @@ -130,7 +125,7 @@ impl State { WindowSurface::X11(_) => { let loc = win.with_state_mut(|state| state.target_loc.take()); if let Some(loc) = loc { - self.pinnacle.space.map_element(win.clone(), loc, false); + self.space.map_element(win.clone(), loc, false); } } } @@ -138,7 +133,7 @@ impl State { } for (loc, window) in non_pending_wins { - self.pinnacle.space.map_element(window, loc, false); + self.space.map_element(window, loc, false); } // FIXME: @@ -146,12 +141,9 @@ impl State { // 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.pinnacle.clock.now(), - Some(Duration::ZERO), - |_, _| Some(output.clone()), - ); + win.send_frame(output, self.clock.now(), Some(Duration::ZERO), |_, _| { + Some(output.clone()) + }); } self.fixup_z_layering(); @@ -159,15 +151,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.pinnacle.windows.iter().position(|win| win == win1); - let win2_index = self.pinnacle.windows.iter().position(|win| win == win2); + let win1_index = self.windows.iter().position(|win| win == win1); + let win2_index = self.windows.iter().position(|win| win == win2); if let (Some(first), Some(second)) = (win1_index, win2_index) { - self.pinnacle.windows.swap(first, second); + self.windows.swap(first, second); if let Some(output) = win1.output(self) { self.request_layout(&output); } - self.pinnacle.layout_state.pending_swap = true; + self.layout_state.pending_swap = true; } } } @@ -185,17 +177,16 @@ pub struct LayoutState { old_requests: HashMap>, } -impl State { +impl Pinnacle { pub fn request_layout(&mut self, output: &Output) { - let Some(sender) = self.pinnacle.layout_state.layout_request_sender.as_ref() else { + let Some(sender) = self.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.pinnacle - .windows + self.windows .iter() .filter(|win| !win.is_x11_override_redirect()) .filter(|win| { @@ -230,14 +221,12 @@ 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.pinnacle - .layout_state + self.layout_state .pending_requests .entry(output.clone()) .or_default() @@ -255,7 +244,9 @@ impl State { *id = LayoutRequestId(id.0 + 1); } +} +impl State { pub fn apply_layout(&mut self, geometries: Geometries) -> anyhow::Result<()> { let Geometries { request_id: Some(request_id), @@ -267,7 +258,7 @@ impl State { }; let request_id = LayoutRequestId(request_id); - let Some(output) = OutputName(output_name).output(self) else { + let Some(output) = OutputName(output_name).output(&self.pinnacle) else { anyhow::bail!("Output was invalid"); }; @@ -321,7 +312,8 @@ impl State { anyhow::bail!("Attempted to layout but one or more dimensions were null"); }; - self.update_windows_with_geometries(&output, geometries); + self.pinnacle + .update_windows_with_geometries(&output, geometries); self.schedule_render(&output); diff --git a/src/main.rs b/src/main.rs index 5c8d4aa..1d73f16 100644 --- a/src/main.rs +++ b/src/main.rs @@ -131,7 +131,7 @@ async fn main() -> anyhow::Result<()> { event_loop.run(None, &mut state, |state| { state.update_pointer_focus(); - state.fixup_z_layering(); + state.pinnacle.fixup_z_layering(); state.pinnacle.space.refresh(); state.pinnacle.popup_manager.cleanup(); diff --git a/src/output.rs b/src/output.rs index 3f0c98a..1820a93 100644 --- a/src/output.rs +++ b/src/output.rs @@ -13,7 +13,7 @@ use tracing::info; use crate::{ focus::WindowKeyboardFocusStack, protocol::screencopy::Screencopy, - state::{State, WithState}, + state::{Pinnacle, WithState}, tag::Tag, }; @@ -26,9 +26,8 @@ pub struct OutputName(pub String); impl OutputName { /// Get the output with this name. - pub fn output(&self, state: &State) -> Option { - state - .pinnacle + pub fn output(&self, pinnacle: &Pinnacle) -> Option { + pinnacle .space .outputs() .find(|output| output.name() == self.0) @@ -77,7 +76,7 @@ impl OutputState { } } -impl State { +impl Pinnacle { /// A wrapper around [`Output::change_current_state`] that additionally sends an output /// geometry signal. pub fn change_output_state( @@ -91,8 +90,8 @@ impl State { output.change_current_state(mode, transform, scale, location); if let Some(location) = location { info!(?location); - self.pinnacle.space.map_output(output, location); - self.pinnacle.signal_state.output_move.signal(|buf| { + self.space.map_output(output, location); + self.signal_state.output_move.signal(|buf| { buf.push_back(OutputMoveResponse { output_name: Some(output.name()), x: Some(location.x), @@ -102,8 +101,8 @@ impl State { } if mode.is_some() || transform.is_some() || scale.is_some() { layer_map_for_output(output).arrange(); - self.pinnacle.signal_state.output_resize.signal(|buf| { - let geo = self.pinnacle.space.output_geometry(output); + self.signal_state.output_resize.signal(|buf| { + let geo = self.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/state.rs b/src/state.rs index 23a837a..80899f4 100644 --- a/src/state.rs +++ b/src/state.rs @@ -219,7 +219,7 @@ impl State { std::env::set_var("DISPLAY", format!(":{display}")); - if let Err(err) = state.start_config(Some( + if let Err(err) = state.pinnacle.start_config(Some( state.pinnacle.config.dir(&state.pinnacle.xdg_base_dirs), )) { panic!("failed to start config: {err}"); @@ -318,18 +318,20 @@ impl State { Ok(state) } +} +impl Pinnacle { /// Schedule `run` to run when `condition` returns true. /// /// This will continually reschedule `run` in the event loop if `condition` returns false. pub fn schedule(&self, condition: F1, run: F2) where - F1: Fn(&mut Self) -> bool + 'static, - F2: FnOnce(&mut Self) + 'static, + F1: Fn(&mut State) -> bool + 'static, + F2: FnOnce(&mut State) + 'static, { - self.pinnacle.loop_handle.insert_idle(|state| { + self.loop_handle.insert_idle(|state| { if !condition(state) { - state.schedule(condition, run); + state.pinnacle.schedule(condition, run); } else { run(state); } @@ -338,11 +340,11 @@ impl State { pub fn shutdown(&mut self) { info!("Shutting down Pinnacle"); - self.pinnacle.loop_signal.stop(); - if let Some(join_handle) = self.pinnacle.config.config_join_handle.take() { + self.loop_signal.stop(); + if let Some(join_handle) = self.config.config_join_handle.take() { join_handle.abort(); } - if let Some(shutdown_sender) = self.pinnacle.config.shutdown_sender.take() { + if let Some(shutdown_sender) = self.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 ab4624d..ccabd98 100644 --- a/src/tag.rs +++ b/src/tag.rs @@ -9,7 +9,7 @@ use std::{ use smithay::output::Output; -use crate::state::{State, WithState}; +use crate::state::{Pinnacle, State, WithState}; static TAG_ID_COUNTER: AtomicU32 = AtomicU32::new(0); @@ -24,9 +24,8 @@ impl TagId { } /// Get the tag associated with this id. - pub fn tag(&self, state: &State) -> Option { - state - .pinnacle + pub fn tag(&self, pinnacle: &Pinnacle) -> Option { + pinnacle .space .outputs() .flat_map(|op| op.with_state(|state| state.tags.clone())) @@ -107,9 +106,8 @@ impl Tag { /// Get the output this tag is on. /// /// RefCell Safety: This uses RefCells on every mapped output. - pub fn output(&self, state: &State) -> Option { - state - .pinnacle + pub fn output(&self, pinnacle: &Pinnacle) -> Option { + 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 f65790d..94aea6f 100644 --- a/src/window.rs +++ b/src/window.rs @@ -12,7 +12,7 @@ use smithay::{ wayland::{compositor, seat::WaylandFocus, shell::xdg::XdgToplevelSurfaceData}, }; -use crate::state::{State, WithState}; +use crate::state::{Pinnacle, WithState}; use self::window_state::WindowElementState; @@ -103,8 +103,8 @@ impl WindowElement { /// This method gets the first tag the window has and returns its output. /// /// RefCell Safety: This method uses a [`RefCell`] on this window and every mapped output. - pub fn output(&self, state: &State) -> Option { - self.with_state(|st| st.tags.first().and_then(|tag| tag.output(state))) + pub fn output(&self, pinnacle: &Pinnacle) -> Option { + self.with_state(|st| st.tags.first().and_then(|tag| tag.output(pinnacle))) } /// Returns whether or not this window has an active tag. @@ -209,16 +209,14 @@ impl WithState for WindowElement { } } -impl State { +impl Pinnacle { /// Returns the [Window] associated with a given [WlSurface]. pub fn window_for_surface(&self, surface: &WlSurface) -> Option { - self.pinnacle - .space + self.space .elements() .find(|window| window.wl_surface().map(|s| s == *surface).unwrap_or(false)) .or_else(|| { - self.pinnacle - .windows + self.windows .iter() .find(|&win| win.wl_surface().is_some_and(|surf| &surf == surface)) }) @@ -229,8 +227,7 @@ impl State { /// /// Currently only used in `ensure_initial_configure` in [`handlers`][crate::handlers]. pub fn new_window_for_surface(&self, surface: &WlSurface) -> Option { - self.pinnacle - .new_windows + self.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 9e5e58e..02d4d10 100644 --- a/src/window/rules.rs +++ b/src/window/rules.rs @@ -4,7 +4,7 @@ use smithay::{ }; use crate::{ - state::{State, WithState}, + state::{Pinnacle, WithState}, window::window_state, }; @@ -41,11 +41,16 @@ enum AllOrAny { impl WindowRuleCondition { /// RefCell Safety: This method uses RefCells on `window`. - pub fn is_met(&self, state: &State, window: &WindowElement) -> bool { - Self::is_met_inner(self, state, window, AllOrAny::All) + pub fn is_met(&self, pinnacle: &Pinnacle, window: &WindowElement) -> bool { + Self::is_met_inner(self, pinnacle, window, AllOrAny::All) } - fn is_met_inner(&self, state: &State, window: &WindowElement, all_or_any: AllOrAny) -> bool { + fn is_met_inner( + &self, + pinnacle: &Pinnacle, + window: &WindowElement, + all_or_any: AllOrAny, + ) -> bool { tracing::debug!("{self:#?}"); let WindowRuleCondition { @@ -61,14 +66,14 @@ impl WindowRuleCondition { let cond_any = if let Some(cond_any) = cond_any { cond_any .iter() - .any(|cond| Self::is_met_inner(cond, state, window, AllOrAny::Any)) + .any(|cond| Self::is_met_inner(cond, pinnacle, window, AllOrAny::Any)) } else { true }; let cond_all = if let Some(cond_all) = cond_all { cond_all .iter() - .all(|cond| Self::is_met_inner(cond, state, window, AllOrAny::All)) + .all(|cond| Self::is_met_inner(cond, pinnacle, window, AllOrAny::All)) } else { true }; @@ -87,7 +92,7 @@ impl WindowRuleCondition { true }; let tags = if let Some(tag_ids) = tag { - let mut tags = tag_ids.iter().filter_map(|tag_id| tag_id.tag(state)); + let mut tags = tag_ids.iter().filter_map(|tag_id| tag_id.tag(pinnacle)); tags.all(|tag| window.with_state(|state| state.tags.contains(&tag))) } else { true @@ -100,14 +105,14 @@ impl WindowRuleCondition { let cond_any = if let Some(cond_any) = cond_any { cond_any .iter() - .any(|cond| Self::is_met_inner(cond, state, window, AllOrAny::Any)) + .any(|cond| Self::is_met_inner(cond, pinnacle, window, AllOrAny::Any)) } else { false }; let cond_all = if let Some(cond_all) = cond_all { cond_all .iter() - .all(|cond| Self::is_met_inner(cond, state, window, AllOrAny::All)) + .all(|cond| Self::is_met_inner(cond, pinnacle, window, AllOrAny::All)) } else { false }; @@ -126,7 +131,7 @@ impl WindowRuleCondition { false }; let tags = if let Some(tag_ids) = tag { - let mut tags = tag_ids.iter().filter_map(|tag_id| tag_id.tag(state)); + let mut tags = tag_ids.iter().filter_map(|tag_id| tag_id.tag(pinnacle)); tags.any(|tag| window.with_state(|state| state.tags.contains(&tag))) } else { false @@ -167,10 +172,10 @@ pub enum FloatingOrTiled { Tiled, } -impl State { +impl Pinnacle { pub fn apply_window_rules(&mut self, window: &WindowElement) { tracing::debug!("Applying window rules"); - for (cond, rule) in self.pinnacle.config.window_rules.iter() { + for (cond, rule) in self.config.window_rules.iter() { if cond.is_met(self, window) { let WindowRule { output, @@ -253,7 +258,7 @@ impl State { state.floating_or_tiled = window_state::FloatingOrTiled::Floating(rect) }); - self.pinnacle.space.map_element(window.clone(), *loc, false); + self.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 9b1c9e1..48f71a6 100644 --- a/src/window/window_state.rs +++ b/src/window/window_state.rs @@ -9,7 +9,7 @@ use smithay::{ }; use crate::{ - state::{State, WithState}, + state::{Pinnacle, WithState}, tag::Tag, }; @@ -28,9 +28,8 @@ impl WindowId { } /// Get the window that has this WindowId. - pub fn window(&self, state: &State) -> Option { - state - .pinnacle + pub fn window(&self, pinnacle: &Pinnacle) -> Option { + 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 e0b4f68..2ed2806 100644 --- a/tests/common/mod.rs +++ b/tests/common/mod.rs @@ -43,7 +43,7 @@ where let tempdir = tempfile::tempdir()?; - state.start_grpc_server(tempdir.path())?; + state.pinnacle.start_grpc_server(tempdir.path())?; let loop_signal = event_loop.get_signal(); @@ -54,7 +54,7 @@ where }); event_loop.run(None, &mut state, |state| { - state.fixup_z_layering(); + state.pinnacle.fixup_z_layering(); state.pinnacle.space.refresh(); state.pinnacle.popup_manager.cleanup(); diff --git a/tests/lua_api.rs b/tests/lua_api.rs index f9bc91d..1592ead 100644 --- a/tests/lua_api.rs +++ b/tests/lua_api.rs @@ -456,7 +456,7 @@ mod output { sleep_secs(1); with_state(&sender, |state| { - let op = state.focused_output().unwrap(); + let op = state.pinnacle.focused_output().unwrap(); assert_eq!(op.current_transform(), smithay::utils::Transform::Flipped90); }); @@ -467,7 +467,7 @@ mod output { sleep_secs(1); with_state(&sender, |state| { - let op = state.focused_output().unwrap(); + let op = state.pinnacle.focused_output().unwrap(); assert_eq!(op.current_transform(), smithay::utils::Transform::Normal); }); @@ -538,9 +538,9 @@ mod output { sleep_secs(1); with_state(&sender, |state| { - state.new_output("First", (300, 200).into()); - state.new_output("Second", (300, 200).into()); - state.new_output("Test Third", (300, 200).into()); + state.pinnacle.new_output("First", (300, 200).into()); + state.pinnacle.new_output("Second", (300, 200).into()); + state.pinnacle.new_output("Test Third", (300, 200).into()); }); sleep_secs(1); @@ -608,7 +608,7 @@ mod output { sleep_secs(1); with_state(&sender, |state| { - state.new_output("First", (300, 200).into()); + state.pinnacle.new_output("First", (300, 200).into()); }); sleep_secs(1); @@ -643,7 +643,7 @@ mod output { sleep_secs(1); with_state(&sender, |state| { - state.new_output("First", (300, 200).into()); + state.pinnacle.new_output("First", (300, 200).into()); }); sleep_secs(1); @@ -664,7 +664,7 @@ mod output { Rectangle::from_loc_and_size((1920, 0), (300, 200)) ); - state.new_output("Second", (500, 500).into()); + state.pinnacle.new_output("Second", (500, 500).into()); }); sleep_secs(1); @@ -714,9 +714,9 @@ mod output { sleep_secs(1); with_state(&sender, |state| { - state.new_output("First", (300, 200).into()); - state.new_output("Second", (300, 700).into()); - state.new_output("Third", (300, 400).into()); + state.pinnacle.new_output("First", (300, 200).into()); + state.pinnacle.new_output("Second", (300, 700).into()); + state.pinnacle.new_output("Third", (300, 400).into()); }); sleep_secs(1); @@ -749,7 +749,7 @@ mod output { Rectangle::from_loc_and_size((0, 1080 + 200 + 700), (300, 400)) ); - state.remove_output(&second_op); + state.pinnacle.remove_output(&second_op); }); sleep_secs(1); @@ -841,7 +841,8 @@ async fn spawned_window_on_active_tag_has_keyboard_focus() -> anyhow::Result<()> with_state(&sender, |state| { assert_eq!( state - .focused_window(state.focused_output().unwrap()) + .pinnacle + .focused_window(state.pinnacle.focused_output().unwrap()) .unwrap() .class(), Some("foot".to_string()) @@ -864,7 +865,12 @@ async fn spawned_window_on_inactive_tag_does_not_have_keyboard_focus() -> anyhow sleep_secs(1); with_state(&sender, |state| { - assert_eq!(state.focused_window(state.focused_output().unwrap()), None); + assert_eq!( + state + .pinnacle + .focused_window(state.pinnacle.focused_output().unwrap()), + None + ); }); Ok(()) diff --git a/tests/rust_api.rs b/tests/rust_api.rs index 6d64363..5a5299e 100644 --- a/tests/rust_api.rs +++ b/tests/rust_api.rs @@ -69,9 +69,9 @@ mod output { sleep_secs(1); with_state(&sender, |state| { - state.new_output("First", (300, 200).into()); - state.new_output("Second", (300, 200).into()); - state.new_output("Test Third", (300, 200).into()); + state.pinnacle.new_output("First", (300, 200).into()); + state.pinnacle.new_output("Second", (300, 200).into()); + state.pinnacle.new_output("Test Third", (300, 200).into()); }); sleep_secs(1); @@ -151,7 +151,7 @@ mod output { sleep_secs(1); with_state(&sender, |state| { - state.new_output("First", (300, 200).into()); + state.pinnacle.new_output("First", (300, 200).into()); }); sleep_secs(1); @@ -172,7 +172,7 @@ mod output { Rectangle::from_loc_and_size((1920, 0), (300, 200)) ); - state.new_output("Second", (500, 500).into()); + state.pinnacle.new_output("Second", (500, 500).into()); }); sleep_secs(1); @@ -249,9 +249,9 @@ mod output { sleep_secs(1); with_state(&sender, |state| { - state.new_output("First", (300, 200).into()); - state.new_output("Second", (300, 700).into()); - state.new_output("Third", (300, 400).into()); + state.pinnacle.new_output("First", (300, 200).into()); + state.pinnacle.new_output("Second", (300, 700).into()); + state.pinnacle.new_output("Third", (300, 400).into()); }); sleep_secs(1); @@ -284,7 +284,7 @@ mod output { Rectangle::from_loc_and_size((0, 1080 + 200 + 700), (300, 400)) ); - state.remove_output(&second_op); + state.pinnacle.remove_output(&second_op); }); sleep_secs(1); @@ -335,7 +335,7 @@ mod output { sleep_secs(1); with_state(&sender, |state| { - let op = state.focused_output().unwrap(); + let op = state.pinnacle.focused_output().unwrap(); assert_eq!( op.current_transform(), smithay::utils::Transform::Flipped270 @@ -352,7 +352,7 @@ mod output { sleep_secs(1); with_state(&sender, |state| { - let op = state.focused_output().unwrap(); + let op = state.pinnacle.focused_output().unwrap(); assert_eq!(op.current_transform(), smithay::utils::Transform::_180); }); diff --git a/wlcs_pinnacle/src/config.rs b/wlcs_pinnacle/src/config.rs index fa5334c..ef46ff0 100644 --- a/wlcs_pinnacle/src/config.rs +++ b/wlcs_pinnacle/src/config.rs @@ -1,4 +1,4 @@ -use pinnacle::state::State; +use pinnacle::state::Pinnacle; mod inner { use pinnacle_api::layout::{CyclingLayoutManager, MasterStackLayout}; use pinnacle_api::window::rules::{WindowRule, WindowRuleCondition}; @@ -24,10 +24,10 @@ mod inner { } } -pub fn run_config(state: &mut State) { +pub fn run_config(pinnacle: &mut Pinnacle) { let temp_dir = tempfile::tempdir().expect("failed to setup temp dir for socket"); let socket_dir = temp_dir.path().to_owned(); - state + pinnacle .start_wlcs_config(&socket_dir, move || { inner::start_config(); drop(temp_dir); diff --git a/wlcs_pinnacle/src/main_loop.rs b/wlcs_pinnacle/src/main_loop.rs index aca04b8..920dbec 100644 --- a/wlcs_pinnacle/src/main_loop.rs +++ b/wlcs_pinnacle/src/main_loop.rs @@ -47,7 +47,7 @@ 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.pinnacle.xdisplay = Some(u32::MAX); - run_config(&mut state); + run_config(&mut state.pinnacle); // wait for the config to connect to the layout service while state.pinnacle.layout_state.layout_request_sender.is_none() { @@ -59,7 +59,7 @@ pub(crate) fn run(channel: Channel) { event_loop .run(None, &mut state, |state| { state.update_pointer_focus(); - state.fixup_z_layering(); + state.pinnacle.fixup_z_layering(); state.pinnacle.space.refresh(); state.pinnacle.popup_manager.cleanup(); @@ -75,7 +75,7 @@ pub(crate) fn run(channel: Channel) { fn handle_event(event: WlcsEvent, state: &mut State) { tracing::debug!("handle_event {:?}", event); match event { - WlcsEvent::Stop => state.shutdown(), + WlcsEvent::Stop => state.pinnacle.shutdown(), WlcsEvent::NewClient { stream, client_id } => { let client: Client = state .pinnacle