Move impls to Pinnacle

This commit is contained in:
Ottatop 2024-04-26 19:58:02 -05:00
parent 8aaec59452
commit b99cc8ffce
29 changed files with 665 additions and 647 deletions

View file

@ -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::<Vec<_>>();
let tags_to_remove = tag_ids
.flat_map(|id| id.tag(&state.pinnacle))
.collect::<Vec<_>>();
for output in state.pinnacle.space.outputs().cloned().collect::<Vec<_>>() {
// 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));

View file

@ -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);
}
}
}

View file

@ -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)
});

View file

@ -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<i32, Physical>) {
let mode = smithay::output::Mode {
size,
@ -152,11 +152,11 @@ impl State {
output.set_preferred(mode);
output.create_global::<State>(&self.pinnacle.display_handle);
output.create_global::<State>(&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()),
})
});
}
}

View file

@ -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 {

View file

@ -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);

View file

@ -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<F>(&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(())
}

View file

@ -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::<PathBuf>)
pinnacle.start_config(None::<PathBuf>)
};
// 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::<PathBuf>)
.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::<PathBuf>)
.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::<Box<dyn FnOnce(&mut Self) + Send>>();
calloop::channel::channel::<Box<dyn FnOnce(&mut State) + Send>>();
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}");
}

View file

@ -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) = &current_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) = &current_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())
}
}

View file

@ -50,7 +50,7 @@ impl PointerGrab<State> 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<State> 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<State> 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<State>,
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<State>, 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<State>,
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<State>,
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);
}

View file

@ -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<i32>, Option<i32>)> = surface.with_state_mut(|state| {
state
.resize_state
.on_commit()
.map(|(edges, initial_window_rect)| {
let mut new_x: Option<i32> = None;
let mut new_y: Option<i32> = 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<i32>, Option<i32>)> = surface.with_state_mut(|state| {
state
.resize_state
.on_commit()
.map(|(edges, initial_window_rect)| {
let mut new_x: Option<i32> = None;
let mut new_y: Option<i32> = 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<State>,
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<State>,
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<State>,
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<State>,
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);
}
}

View file

@ -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::<XdgToplevelSurfaceData>()
.expect("XdgToplevelSurfaceData wasn't in surface's data map")
.lock()
.expect("Failed to lock Mutex<XdgToplevelSurfaceData>")
.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::<XdgToplevelSurfaceData>()
.expect("XdgToplevelSurfaceData wasn't in surface's data map")
.get::<XdgPopupSurfaceData>()
.expect("XdgPopupSurfaceData wasn't in popup's data map")
.lock()
.expect("Failed to lock Mutex<XdgToplevelSurfaceData>")
.expect("Failed to lock Mutex<XdgPopupSurfaceData>")
.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::<LayerSurfaceData>()
.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::<XdgPopupSurfaceData>()
.expect("XdgPopupSurfaceData wasn't in popup's data map")
.lock()
.expect("Failed to lock Mutex<XdgPopupSurfaceData>")
.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::<LayerSurfaceData>()
.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;

View file

@ -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<Self> = 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) {

View file

@ -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())

View file

@ -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);
}
}

View file

@ -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<LibinputInputBackend>) {
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);
}
}

View file

@ -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::<Vec<_>>();
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<Output, HashSet<LayoutRequestId>>,
}
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::<Vec<_>>();
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);

View file

@ -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();

View file

@ -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<Output> {
state
.pinnacle
pub fn output(&self, pinnacle: &Pinnacle) -> Option<Output> {
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),

View file

@ -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<F1, F2>(&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}");
}

View file

@ -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<Tag> {
state
.pinnacle
pub fn tag(&self, pinnacle: &Pinnacle) -> Option<Tag> {
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<Output> {
state
.pinnacle
pub fn output(&self, pinnacle: &Pinnacle) -> Option<Output> {
pinnacle
.space
.outputs()
.find(|output| output.with_state(|state| state.tags.iter().any(|tg| tg == self)))

View file

@ -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<Output> {
self.with_state(|st| st.tags.first().and_then(|tag| tag.output(state)))
pub fn output(&self, pinnacle: &Pinnacle) -> Option<Output> {
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<WindowElement> {
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<WindowElement> {
self.pinnacle
.new_windows
self.new_windows
.iter()
.find(|&win| win.wl_surface().is_some_and(|surf| &surf == surface))
.cloned()

View file

@ -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

View file

@ -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<WindowElement> {
state
.pinnacle
pub fn window(&self, pinnacle: &Pinnacle) -> Option<WindowElement> {
pinnacle
.windows
.iter()
.find(|win| win.with_state(|state| &state.id == self))

View file

@ -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();

View file

@ -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(())

View file

@ -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);
});

View file

@ -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);

View file

@ -47,7 +47,7 @@ pub(crate) fn run(channel: Channel<WlcsEvent>) {
// 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<WlcsEvent>) {
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<WlcsEvent>) {
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