mirror of
https://github.com/pinnacle-comp/pinnacle.git
synced 2024-12-26 21:58:10 +01:00
Move impls to Pinnacle
This commit is contained in:
parent
8aaec59452
commit
b99cc8ffce
29 changed files with 665 additions and 647 deletions
60
src/api.rs
60
src/api.rs
|
@ -192,7 +192,7 @@ impl pinnacle_service_server::PinnacleService for PinnacleService {
|
||||||
trace!("PinnacleService.quit");
|
trace!("PinnacleService.quit");
|
||||||
|
|
||||||
run_unary_no_response(&self.sender, |state| {
|
run_unary_no_response(&self.sender, |state| {
|
||||||
state.shutdown();
|
state.pinnacle.shutdown();
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
@ -204,6 +204,7 @@ impl pinnacle_service_server::PinnacleService for PinnacleService {
|
||||||
run_unary_no_response(&self.sender, |state| {
|
run_unary_no_response(&self.sender, |state| {
|
||||||
info!("Reloading config");
|
info!("Reloading config");
|
||||||
state
|
state
|
||||||
|
.pinnacle
|
||||||
.start_config(Some(
|
.start_config(Some(
|
||||||
state.pinnacle.config.dir(&state.pinnacle.xdg_base_dirs),
|
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| {
|
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;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -745,13 +746,13 @@ impl tag_service_server::TagService for TagService {
|
||||||
SetOrToggle::Unspecified => unreachable!(),
|
SetOrToggle::Unspecified => unreachable!(),
|
||||||
}
|
}
|
||||||
|
|
||||||
let Some(output) = tag.output(state) else {
|
let Some(output) = tag.output(&state.pinnacle) else {
|
||||||
return;
|
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.update_focus(&output);
|
||||||
state.schedule_render(&output);
|
state.schedule_render(&output);
|
||||||
})
|
})
|
||||||
|
@ -768,8 +769,10 @@ impl tag_service_server::TagService for TagService {
|
||||||
);
|
);
|
||||||
|
|
||||||
run_unary_no_response(&self.sender, move |state| {
|
run_unary_no_response(&self.sender, move |state| {
|
||||||
let Some(tag) = tag_id.tag(state) else { return };
|
let Some(tag) = tag_id.tag(&state.pinnacle) else { return };
|
||||||
let Some(output) = tag.output(state) else { return };
|
let Some(output) = tag.output(&state.pinnacle) else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
output.with_state_mut(|op_state| {
|
output.with_state_mut(|op_state| {
|
||||||
for op_tag in op_state.tags.iter_mut() {
|
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);
|
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.update_focus(&output);
|
||||||
state.schedule_render(&output);
|
state.schedule_render(&output);
|
||||||
})
|
})
|
||||||
|
@ -818,7 +821,7 @@ impl tag_service_server::TagService for TagService {
|
||||||
.tags
|
.tags
|
||||||
.extend(new_tags.clone());
|
.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| {
|
output.with_state_mut(|state| {
|
||||||
state.tags.extend(new_tags.clone());
|
state.tags.extend(new_tags.clone());
|
||||||
debug!("tags added, are now {:?}", state.tags);
|
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);
|
let tag_ids = request.tag_ids.into_iter().map(TagId);
|
||||||
|
|
||||||
run_unary_no_response(&self.sender, move |state| {
|
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<_>>() {
|
for output in state.pinnacle.space.outputs().cloned().collect::<Vec<_>>() {
|
||||||
// TODO: seriously, convert state.tags into a hashset
|
// 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);
|
state.schedule_render(&output);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -904,11 +909,11 @@ impl tag_service_server::TagService for TagService {
|
||||||
);
|
);
|
||||||
|
|
||||||
run_unary(&self.sender, move |state| {
|
run_unary(&self.sender, move |state| {
|
||||||
let tag = tag_id.tag(state);
|
let tag = tag_id.tag(&state.pinnacle);
|
||||||
|
|
||||||
let output_name = tag
|
let output_name = tag
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.and_then(|tag| tag.output(state))
|
.and_then(|tag| tag.output(&state.pinnacle))
|
||||||
.map(|output| output.name());
|
.map(|output| output.name());
|
||||||
let active = tag.as_ref().map(|tag| tag.active());
|
let active = tag.as_ref().map(|tag| tag.active());
|
||||||
let name = tag.as_ref().map(|tag| tag.name());
|
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;
|
return;
|
||||||
};
|
};
|
||||||
let mut loc = output.current_location();
|
let mut loc = output.current_location();
|
||||||
|
@ -999,9 +1004,11 @@ impl output_service_server::OutputService for OutputService {
|
||||||
if let Some(y) = y {
|
if let Some(y) = y {
|
||||||
loc.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());
|
debug!("Mapping output {} to {loc:?}", output.name());
|
||||||
state.request_layout(&output);
|
state.pinnacle.request_layout(&output);
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
@ -1014,7 +1021,7 @@ impl output_service_server::OutputService for OutputService {
|
||||||
.output_name
|
.output_name
|
||||||
.clone()
|
.clone()
|
||||||
.map(OutputName)
|
.map(OutputName)
|
||||||
.and_then(|name| name.output(state))
|
.and_then(|name| name.output(&state.pinnacle))
|
||||||
else {
|
else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
@ -1046,7 +1053,7 @@ impl output_service_server::OutputService for OutputService {
|
||||||
};
|
};
|
||||||
|
|
||||||
run_unary_no_response(&self.sender, move |state| {
|
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;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1059,14 +1066,14 @@ impl output_service_server::OutputService for OutputService {
|
||||||
|
|
||||||
current_scale = f64::max(current_scale, 0.25);
|
current_scale = f64::max(current_scale, 0.25);
|
||||||
|
|
||||||
state.change_output_state(
|
state.pinnacle.change_output_state(
|
||||||
&output,
|
&output,
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
Some(Scale::Fractional(current_scale)),
|
Some(Scale::Fractional(current_scale)),
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
state.request_layout(&output);
|
state.pinnacle.request_layout(&output);
|
||||||
state.schedule_render(&output);
|
state.schedule_render(&output);
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
|
@ -1097,12 +1104,14 @@ impl output_service_server::OutputService for OutputService {
|
||||||
};
|
};
|
||||||
|
|
||||||
run_unary_no_response(&self.sender, move |state| {
|
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;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
state.change_output_state(&output, None, Some(smithay_transform), None, None);
|
state
|
||||||
state.request_layout(&output);
|
.pinnacle
|
||||||
|
.change_output_state(&output, None, Some(smithay_transform), None, None);
|
||||||
|
state.pinnacle.request_layout(&output);
|
||||||
state.schedule_render(&output);
|
state.schedule_render(&output);
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
|
@ -1146,7 +1155,7 @@ impl output_service_server::OutputService for OutputService {
|
||||||
};
|
};
|
||||||
|
|
||||||
run_unary(&self.sender, move |state| {
|
run_unary(&self.sender, move |state| {
|
||||||
let output = output_name.output(state);
|
let output = output_name.output(&state.pinnacle);
|
||||||
|
|
||||||
let logical_size = output
|
let logical_size = output
|
||||||
.as_ref()
|
.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 y = output.as_ref().map(|output| output.current_location().y);
|
||||||
|
|
||||||
let focused = state
|
let focused = state
|
||||||
|
.pinnacle
|
||||||
.focused_output()
|
.focused_output()
|
||||||
.and_then(|foc_op| output.as_ref().map(|op| op == foc_op));
|
.and_then(|foc_op| output.as_ref().map(|op| op == foc_op));
|
||||||
|
|
||||||
|
|
|
@ -44,10 +44,10 @@ impl layout_service_server::LayoutService for LayoutService {
|
||||||
layout_request::Body::Layout(ExplicitLayout { output_name }) => {
|
layout_request::Body::Layout(ExplicitLayout { output_name }) => {
|
||||||
if let Some(output) = output_name
|
if let Some(output) = output_name
|
||||||
.map(OutputName)
|
.map(OutputName)
|
||||||
.and_then(|name| name.output(state))
|
.and_then(|name| name.output(&state.pinnacle))
|
||||||
.or_else(|| state.focused_output().cloned())
|
.or_else(|| state.pinnacle.focused_output().cloned())
|
||||||
{
|
{
|
||||||
state.request_layout(&output);
|
state.pinnacle.request_layout(&output);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,7 +50,9 @@ impl window_service_server::WindowService for WindowService {
|
||||||
);
|
);
|
||||||
|
|
||||||
run_unary_no_response(&self.sender, move |state| {
|
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() {
|
match window.underlying_surface() {
|
||||||
WindowSurface::Wayland(toplevel) => toplevel.send_close(),
|
WindowSurface::Wayland(toplevel) => toplevel.send_close(),
|
||||||
|
@ -89,7 +91,9 @@ impl window_service_server::WindowService for WindowService {
|
||||||
let height = geometry.height;
|
let height = geometry.height;
|
||||||
|
|
||||||
run_unary_no_response(&self.sender, move |state| {
|
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
|
// TODO: with no x or y, defaults unmapped windows to 0, 0
|
||||||
let mut window_loc = state
|
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) {
|
for output in state.pinnacle.space.outputs_for_element(&window) {
|
||||||
state.request_layout(&output);
|
state.pinnacle.request_layout(&output);
|
||||||
state.schedule_render(&output);
|
state.schedule_render(&output);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -141,7 +145,8 @@ impl window_service_server::WindowService for WindowService {
|
||||||
}
|
}
|
||||||
|
|
||||||
run_unary_no_response(&self.sender, move |state| {
|
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;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -160,11 +165,11 @@ impl window_service_server::WindowService for WindowService {
|
||||||
SetOrToggle::Unspecified => unreachable!(),
|
SetOrToggle::Unspecified => unreachable!(),
|
||||||
}
|
}
|
||||||
|
|
||||||
let Some(output) = window.output(state) else {
|
let Some(output) = window.output(pinnacle) else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
state.request_layout(&output);
|
pinnacle.request_layout(&output);
|
||||||
state.schedule_render(&output);
|
state.schedule_render(&output);
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
|
@ -189,7 +194,8 @@ impl window_service_server::WindowService for WindowService {
|
||||||
}
|
}
|
||||||
|
|
||||||
run_unary_no_response(&self.sender, move |state| {
|
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;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -208,11 +214,11 @@ impl window_service_server::WindowService for WindowService {
|
||||||
SetOrToggle::Unspecified => unreachable!(),
|
SetOrToggle::Unspecified => unreachable!(),
|
||||||
}
|
}
|
||||||
|
|
||||||
let Some(output) = window.output(state) else {
|
let Some(output) = window.output(pinnacle) else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
state.request_layout(&output);
|
pinnacle.request_layout(&output);
|
||||||
state.schedule_render(&output);
|
state.schedule_render(&output);
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
|
@ -237,7 +243,8 @@ impl window_service_server::WindowService for WindowService {
|
||||||
}
|
}
|
||||||
|
|
||||||
run_unary_no_response(&self.sender, move |state| {
|
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;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -256,11 +263,11 @@ impl window_service_server::WindowService for WindowService {
|
||||||
SetOrToggle::Unspecified => unreachable!(),
|
SetOrToggle::Unspecified => unreachable!(),
|
||||||
}
|
}
|
||||||
|
|
||||||
let Some(output) = window.output(state) else {
|
let Some(output) = window.output(pinnacle) else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
state.request_layout(&output);
|
pinnacle.request_layout(&output);
|
||||||
state.schedule_render(&output);
|
state.schedule_render(&output);
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
|
@ -285,7 +292,7 @@ impl window_service_server::WindowService for WindowService {
|
||||||
}
|
}
|
||||||
|
|
||||||
run_unary_no_response(&self.sender, move |state| {
|
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;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -293,7 +300,7 @@ impl window_service_server::WindowService for WindowService {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let Some(output) = window.output(state) else {
|
let Some(output) = window.output(&state.pinnacle) else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -315,7 +322,7 @@ impl window_service_server::WindowService for WindowService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SetOrToggle::Unset => {
|
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());
|
output.with_state_mut(|state| state.focus_stack.unset_focus());
|
||||||
if let Some(keyboard) = state.pinnacle.seat.get_keyboard() {
|
if let Some(keyboard) = state.pinnacle.seat.get_keyboard() {
|
||||||
keyboard.set_focus(state, None, SERIAL_COUNTER.next_serial());
|
keyboard.set_focus(state, None, SERIAL_COUNTER.next_serial());
|
||||||
|
@ -323,7 +330,7 @@ impl window_service_server::WindowService for WindowService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SetOrToggle::Toggle => {
|
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());
|
output.with_state_mut(|state| state.focus_stack.unset_focus());
|
||||||
if let Some(keyboard) = state.pinnacle.seat.get_keyboard() {
|
if let Some(keyboard) = state.pinnacle.seat.get_keyboard() {
|
||||||
keyboard.set_focus(state, None, SERIAL_COUNTER.next_serial());
|
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| {
|
run_unary_no_response(&self.sender, move |state| {
|
||||||
let Some(window) = window_id.window(state) else { return };
|
let pinnacle = &mut state.pinnacle;
|
||||||
let Some(tag) = tag_id.tag(state) else { return };
|
let Some(window) = window_id.window(pinnacle) else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
let Some(tag) = tag_id.tag(pinnacle) else { return };
|
||||||
window.with_state_mut(|state| {
|
window.with_state_mut(|state| {
|
||||||
state.tags = vec![tag.clone()];
|
state.tags = vec![tag.clone()];
|
||||||
});
|
});
|
||||||
let Some(output) = tag.output(state) else { return };
|
let Some(output) = tag.output(pinnacle) else { return };
|
||||||
state.request_layout(&output);
|
pinnacle.request_layout(&output);
|
||||||
state.schedule_render(&output);
|
state.schedule_render(&output);
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
|
@ -408,8 +418,11 @@ impl window_service_server::WindowService for WindowService {
|
||||||
}
|
}
|
||||||
|
|
||||||
run_unary_no_response(&self.sender, move |state| {
|
run_unary_no_response(&self.sender, move |state| {
|
||||||
let Some(window) = window_id.window(state) else { return };
|
let pinnacle = &mut state.pinnacle;
|
||||||
let Some(tag) = tag_id.tag(state) else { return };
|
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
|
// TODO: turn state.tags into a hashset
|
||||||
match set_or_toggle {
|
match set_or_toggle {
|
||||||
|
@ -430,8 +443,8 @@ impl window_service_server::WindowService for WindowService {
|
||||||
SetOrToggle::Unspecified => unreachable!(),
|
SetOrToggle::Unspecified => unreachable!(),
|
||||||
}
|
}
|
||||||
|
|
||||||
let Some(output) = tag.output(state) else { return };
|
let Some(output) = tag.output(pinnacle) else { return };
|
||||||
state.request_layout(&output);
|
pinnacle.request_layout(&output);
|
||||||
state.schedule_render(&output);
|
state.schedule_render(&output);
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
|
@ -447,12 +460,13 @@ impl window_service_server::WindowService for WindowService {
|
||||||
);
|
);
|
||||||
|
|
||||||
run_unary_no_response(&self.sender, move |state| {
|
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");
|
warn!("`raise` was called on a nonexistent window");
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
state.raise_window(window, false);
|
pinnacle.raise_window(window, false);
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
@ -486,13 +500,7 @@ impl window_service_server::WindowService for WindowService {
|
||||||
};
|
};
|
||||||
let seat = state.pinnacle.seat.clone();
|
let seat = state.pinnacle.seat.clone();
|
||||||
|
|
||||||
crate::grab::move_grab::move_request_server(
|
state.move_request_server(&wl_surf, &seat, SERIAL_COUNTER.next_serial(), button);
|
||||||
state,
|
|
||||||
&wl_surf,
|
|
||||||
&seat,
|
|
||||||
SERIAL_COUNTER.next_serial(),
|
|
||||||
button,
|
|
||||||
);
|
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
@ -566,8 +574,7 @@ impl window_service_server::WindowService for WindowService {
|
||||||
_ => server::xdg_toplevel::ResizeEdge::None,
|
_ => server::xdg_toplevel::ResizeEdge::None,
|
||||||
};
|
};
|
||||||
|
|
||||||
crate::grab::resize_grab::resize_request_server(
|
state.resize_request_server(
|
||||||
state,
|
|
||||||
&wl_surf,
|
&wl_surf,
|
||||||
&state.pinnacle.seat.clone(),
|
&state.pinnacle.seat.clone(),
|
||||||
SERIAL_COUNTER.next_serial(),
|
SERIAL_COUNTER.next_serial(),
|
||||||
|
@ -608,7 +615,8 @@ impl window_service_server::WindowService for WindowService {
|
||||||
);
|
);
|
||||||
|
|
||||||
run_unary(&self.sender, move |state| {
|
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);
|
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 title = window.as_ref().and_then(|win| win.title());
|
||||||
|
|
||||||
let focused = window.as_ref().and_then(|win| {
|
let focused = window.as_ref().and_then(|win| {
|
||||||
state
|
pinnacle
|
||||||
.focused_output()
|
.focused_output()
|
||||||
.and_then(|output| state.focused_window(output))
|
.and_then(|output| pinnacle.focused_window(output))
|
||||||
.map(|foc_win| win == &foc_win)
|
.map(|foc_win| win == &foc_win)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@ use smithay::{
|
||||||
utils::Transform,
|
utils::Transform,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::state::State;
|
use crate::state::{Pinnacle, State};
|
||||||
|
|
||||||
#[cfg(feature = "wlcs")]
|
#[cfg(feature = "wlcs")]
|
||||||
use super::wlcs::Wlcs;
|
use super::wlcs::Wlcs;
|
||||||
|
@ -132,7 +132,7 @@ pub fn setup_dummy(
|
||||||
Ok((state, event_loop))
|
Ok((state, event_loop))
|
||||||
}
|
}
|
||||||
|
|
||||||
impl State {
|
impl Pinnacle {
|
||||||
pub fn new_output(&mut self, name: impl std::fmt::Display, size: Size<i32, Physical>) {
|
pub fn new_output(&mut self, name: impl std::fmt::Display, size: Size<i32, Physical>) {
|
||||||
let mode = smithay::output::Mode {
|
let mode = smithay::output::Mode {
|
||||||
size,
|
size,
|
||||||
|
@ -152,11 +152,11 @@ impl State {
|
||||||
|
|
||||||
output.set_preferred(mode);
|
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 {
|
buf.push_back(OutputConnectResponse {
|
||||||
output_name: Some(output.name()),
|
output_name: Some(output.name()),
|
||||||
});
|
});
|
||||||
|
@ -164,15 +164,12 @@ impl State {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn remove_output(&mut self, output: &Output) {
|
pub fn remove_output(&mut self, output: &Output) {
|
||||||
self.pinnacle.space.unmap_output(output);
|
self.space.unmap_output(output);
|
||||||
|
|
||||||
self.pinnacle
|
self.signal_state.output_disconnect.signal(|buffer| {
|
||||||
.signal_state
|
buffer.push_back(OutputDisconnectResponse {
|
||||||
.output_disconnect
|
output_name: Some(output.name()),
|
||||||
.signal(|buffer| {
|
})
|
||||||
buffer.push_back(OutputDisconnectResponse {
|
});
|
||||||
output_name: Some(output.name()),
|
|
||||||
})
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -271,18 +271,20 @@ impl State {
|
||||||
{
|
{
|
||||||
match render_surface.compositor.use_mode(drm_mode) {
|
match render_surface.compositor.use_mode(drm_mode) {
|
||||||
Ok(()) => {
|
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}"),
|
Err(err) => error!("Failed to resize output: {err}"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} 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.schedule_render(output);
|
||||||
self.request_layout(output);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -441,7 +443,7 @@ pub fn setup_udev(
|
||||||
let insert_ret = event_loop
|
let insert_ret = event_loop
|
||||||
.handle()
|
.handle()
|
||||||
.insert_source(libinput_backend, move |event, _, state| {
|
.insert_source(libinput_backend, move |event, _, state| {
|
||||||
state.apply_libinput_settings(&event);
|
state.pinnacle.apply_libinput_settings(&event);
|
||||||
state.process_input_event(event);
|
state.process_input_event(event);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1111,7 +1113,8 @@ impl State {
|
||||||
|
|
||||||
device.surfaces.insert(crtc, surface);
|
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.
|
// If there is saved connector state, the connector was previously plugged in.
|
||||||
// In this case, restore its tags and location.
|
// In this case, restore its tags and location.
|
||||||
|
@ -1124,7 +1127,8 @@ impl State {
|
||||||
{
|
{
|
||||||
let ConnectorSavedState { loc, tags, scale } = saved_state;
|
let ConnectorSavedState { loc, tags, scale } = saved_state;
|
||||||
output.with_state_mut(|state| state.tags = tags.clone());
|
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 {
|
} else {
|
||||||
self.pinnacle.signal_state.output_connect.signal(|buffer| {
|
self.pinnacle.signal_state.output_connect.signal(|buffer| {
|
||||||
buffer.push_back(OutputConnectResponse {
|
buffer.push_back(OutputConnectResponse {
|
||||||
|
|
|
@ -220,14 +220,14 @@ pub fn setup_winit(
|
||||||
size,
|
size,
|
||||||
refresh: 144_000,
|
refresh: 144_000,
|
||||||
};
|
};
|
||||||
state.change_output_state(
|
state.pinnacle.change_output_state(
|
||||||
&output,
|
&output,
|
||||||
Some(mode),
|
Some(mode),
|
||||||
None,
|
None,
|
||||||
Some(Scale::Fractional(scale_factor)),
|
Some(Scale::Fractional(scale_factor)),
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
state.request_layout(&output);
|
state.pinnacle.request_layout(&output);
|
||||||
}
|
}
|
||||||
WinitEvent::Focus(focused) => {
|
WinitEvent::Focus(focused) => {
|
||||||
if focused {
|
if focused {
|
||||||
|
@ -241,12 +241,12 @@ pub fn setup_winit(
|
||||||
state.render_winit_window(&output);
|
state.render_winit_window(&output);
|
||||||
}
|
}
|
||||||
WinitEvent::CloseRequested => {
|
WinitEvent::CloseRequested => {
|
||||||
state.shutdown();
|
state.pinnacle.shutdown();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if let PumpStatus::Exit(_) = status {
|
if let PumpStatus::Exit(_) = status {
|
||||||
state.shutdown();
|
state.pinnacle.shutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
state.render_winit_window(&output);
|
state.render_winit_window(&output);
|
||||||
|
|
|
@ -12,7 +12,7 @@ use smithay::{
|
||||||
use tracing::debug;
|
use tracing::debug;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
state::{State, WithState},
|
state::{Pinnacle, State, WithState},
|
||||||
tag::TagId,
|
tag::TagId,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -89,14 +89,14 @@ pub fn setup_wlcs_dummy() -> anyhow::Result<(State, EventLoop<'static, State>)>
|
||||||
Ok((state, event_loop))
|
Ok((state, event_loop))
|
||||||
}
|
}
|
||||||
|
|
||||||
impl State {
|
impl Pinnacle {
|
||||||
pub fn start_wlcs_config<F>(&mut self, socket_dir: &Path, run_config: F) -> anyhow::Result<()>
|
pub fn start_wlcs_config<F>(&mut self, socket_dir: &Path, run_config: F) -> anyhow::Result<()>
|
||||||
where
|
where
|
||||||
F: FnOnce() + Send + 'static,
|
F: FnOnce() + Send + 'static,
|
||||||
{
|
{
|
||||||
// Clear state
|
// Clear state
|
||||||
debug!("Clearing tags");
|
debug!("Clearing tags");
|
||||||
for output in self.pinnacle.space.outputs() {
|
for output in self.space.outputs() {
|
||||||
output.with_state_mut(|state| state.tags.clear());
|
output.with_state_mut(|state| state.tags.clear());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -104,23 +104,22 @@ impl State {
|
||||||
|
|
||||||
debug!("Clearing input 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.input_state.reload_keybind = None;
|
||||||
self.pinnacle.input_state.kill_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)?;
|
self.start_grpc_server(socket_dir)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let (pinger, ping_source) = calloop::ping::make_ping()?;
|
let (pinger, ping_source) = calloop::ping::make_ping()?;
|
||||||
|
|
||||||
let token = self
|
let token = self
|
||||||
.pinnacle
|
|
||||||
.loop_handle
|
.loop_handle
|
||||||
.insert_source(ping_source, move |_, _, _state| {})?;
|
.insert_source(ping_source, move |_, _, _state| {})?;
|
||||||
|
|
||||||
|
@ -129,7 +128,7 @@ impl State {
|
||||||
pinger.ping();
|
pinger.ping();
|
||||||
});
|
});
|
||||||
|
|
||||||
self.pinnacle.config.config_reload_on_crash_token = Some(token);
|
self.config.config_reload_on_crash_token = Some(token);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ use crate::{
|
||||||
},
|
},
|
||||||
input::ModifierMask,
|
input::ModifierMask,
|
||||||
output::OutputName,
|
output::OutputName,
|
||||||
|
state::Pinnacle,
|
||||||
tag::Tag,
|
tag::Tag,
|
||||||
window::rules::{WindowRule, WindowRuleCondition},
|
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())
|
config_dir.unwrap_or(xdg_base_dirs.get_config_home())
|
||||||
}
|
}
|
||||||
|
|
||||||
impl State {
|
impl Pinnacle {
|
||||||
/// Start the config in `config_dir`.
|
/// Start the config in `config_dir`.
|
||||||
///
|
///
|
||||||
/// If this method is called while a config is already running, it will be replaced.
|
/// If this method is called while a config is already running, it will be replaced.
|
||||||
|
@ -276,7 +277,7 @@ impl State {
|
||||||
// Clear state
|
// Clear state
|
||||||
|
|
||||||
debug!("Clearing tags");
|
debug!("Clearing tags");
|
||||||
for output in self.pinnacle.space.outputs() {
|
for output in self.space.outputs() {
|
||||||
output.with_state_mut(|state| state.tags.clear());
|
output.with_state_mut(|state| state.tags.clear());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -284,14 +285,14 @@ impl State {
|
||||||
|
|
||||||
debug!("Clearing input 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 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 {
|
match &config_dir_clone {
|
||||||
Some(dir) => warn!("Unable to load config at {}: {reason}", dir.display()),
|
Some(dir) => warn!("Unable to load config at {}: {reason}", dir.display()),
|
||||||
None => panic!(
|
None => panic!(
|
||||||
|
@ -300,11 +301,11 @@ impl State {
|
||||||
}
|
}
|
||||||
|
|
||||||
info!("Falling back to builtin Rust config");
|
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 `--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;
|
config_dir = None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -328,17 +329,17 @@ impl State {
|
||||||
let reload_keybind = (reload_mask, Keysym::from(reload_keybind.key as u32));
|
let reload_keybind = (reload_mask, Keysym::from(reload_keybind.key as u32));
|
||||||
let kill_keybind = (kill_mask, Keysym::from(kill_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.input_state.reload_keybind = Some(reload_keybind);
|
||||||
self.pinnacle.input_state.kill_keybind = Some(kill_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");
|
info!("`--no-config` was set, not spawning config");
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Because the grpc server is implemented to only start once,
|
// Because the grpc server is implemented to only start once,
|
||||||
// any updates to `socket_dir` won't be applied until restart.
|
// 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.
|
// If a socket is provided in the metaconfig, use it.
|
||||||
let socket_dir = if let Some(socket_dir) = &metaconfig.socket_dir {
|
let socket_dir = if let Some(socket_dir) = &metaconfig.socket_dir {
|
||||||
let Some(config_dir) = &config_dir else {
|
let Some(config_dir) = &config_dir else {
|
||||||
|
@ -356,8 +357,7 @@ impl State {
|
||||||
socket_dir
|
socket_dir
|
||||||
} else {
|
} else {
|
||||||
// Otherwise, use $XDG_RUNTIME_DIR. If that doesn't exist, use /tmp.
|
// Otherwise, use $XDG_RUNTIME_DIR. If that doesn't exist, use /tmp.
|
||||||
self.pinnacle
|
self.xdg_base_dirs
|
||||||
.xdg_base_dirs
|
|
||||||
.get_runtime_directory()
|
.get_runtime_directory()
|
||||||
.cloned()
|
.cloned()
|
||||||
.unwrap_or(PathBuf::from(DEFAULT_SOCKET_DIR))
|
.unwrap_or(PathBuf::from(DEFAULT_SOCKET_DIR))
|
||||||
|
@ -449,32 +449,31 @@ impl State {
|
||||||
|
|
||||||
let (pinger, ping_source) = calloop::ping::make_ping()?;
|
let (pinger, ping_source) = calloop::ping::make_ping()?;
|
||||||
|
|
||||||
let token =
|
let token = self
|
||||||
self.pinnacle
|
.loop_handle
|
||||||
.loop_handle
|
.insert_source(ping_source, move |_, _, state| {
|
||||||
.insert_source(ping_source, move |_, _, state| {
|
error!("Config crashed! Falling back to default config");
|
||||||
error!("Config crashed! Falling back to default config");
|
state
|
||||||
state
|
.pinnacle
|
||||||
.start_config(None::<PathBuf>)
|
.start_config(None::<PathBuf>)
|
||||||
.expect("failed to start default config");
|
.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;
|
let _ = child.wait().await;
|
||||||
pinger.ping();
|
pinger.ping();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
self.pinnacle.config.config_reload_on_crash_token = Some(token);
|
self.config.config_reload_on_crash_token = Some(token);
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
let (pinger, ping_source) = calloop::ping::make_ping()?;
|
let (pinger, ping_source) = calloop::ping::make_ping()?;
|
||||||
|
|
||||||
let token =
|
let token = self
|
||||||
self.pinnacle
|
.loop_handle
|
||||||
.loop_handle
|
.insert_source(ping_source, move |_, _, _state| {
|
||||||
.insert_source(ping_source, move |_, _, _state| {
|
panic!("builtin rust config crashed; this is a bug");
|
||||||
panic!("builtin rust config crashed; this is a bug");
|
})?;
|
||||||
})?;
|
|
||||||
|
|
||||||
std::thread::spawn(move || {
|
std::thread::spawn(move || {
|
||||||
info!("Starting builtin Rust config");
|
info!("Starting builtin Rust config");
|
||||||
|
@ -482,7 +481,7 @@ impl State {
|
||||||
pinger.ping();
|
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<()> {
|
pub fn start_grpc_server(&mut self, socket_dir: &Path) -> anyhow::Result<()> {
|
||||||
self.pinnacle
|
self.system_processes
|
||||||
.system_processes
|
|
||||||
.refresh_processes_specifics(ProcessRefreshKind::new());
|
.refresh_processes_specifics(ProcessRefreshKind::new());
|
||||||
|
|
||||||
let multiple_instances = self
|
let multiple_instances = self
|
||||||
.pinnacle
|
|
||||||
.system_processes
|
.system_processes
|
||||||
.processes_by_exact_name("pinnacle")
|
.processes_by_exact_name("pinnacle")
|
||||||
.filter(|proc| proc.thread_kind().is_none())
|
.filter(|proc| proc.thread_kind().is_none())
|
||||||
|
@ -544,14 +541,13 @@ impl State {
|
||||||
|
|
||||||
std::env::set_var(
|
std::env::set_var(
|
||||||
"PINNACLE_PROTO_DIR",
|
"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) =
|
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
|
self.loop_handle
|
||||||
.loop_handle
|
|
||||||
.insert_source(grpc_receiver, |msg, _, state| match msg {
|
.insert_source(grpc_receiver, |msg, _, state| match msg {
|
||||||
Event::Msg(f) => f(state),
|
Event::Msg(f) => f(state),
|
||||||
Event::Closed => error!("grpc receiver was closed"),
|
Event::Closed => error!("grpc receiver was closed"),
|
||||||
|
@ -589,9 +585,9 @@ impl State {
|
||||||
.add_service(LayoutServiceServer::new(layout_service))
|
.add_service(LayoutServiceServer::new(layout_service))
|
||||||
.add_service(RenderServiceServer::new(render_service));
|
.add_service(RenderServiceServer::new(render_service));
|
||||||
|
|
||||||
match self.pinnacle.xdisplay.as_ref() {
|
match self.xdisplay.as_ref() {
|
||||||
Some(_) => {
|
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 {
|
if let Err(err) = grpc_server.serve_with_incoming(uds_stream).await {
|
||||||
error!("gRPC server error: {err}");
|
error!("gRPC server error: {err}");
|
||||||
}
|
}
|
||||||
|
|
67
src/focus.rs
67
src/focus.rs
|
@ -4,7 +4,7 @@ use smithay::{output::Output, utils::SERIAL_COUNTER};
|
||||||
use tracing::warn;
|
use tracing::warn;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
state::{State, WithState},
|
state::{Pinnacle, State, WithState},
|
||||||
window::WindowElement,
|
window::WindowElement,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -12,6 +12,31 @@ pub mod keyboard;
|
||||||
pub mod pointer;
|
pub mod pointer;
|
||||||
|
|
||||||
impl State {
|
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`.
|
/// Get the currently focused window on `output`.
|
||||||
///
|
///
|
||||||
/// This returns the topmost window on the keyboard focus stack that is on an active tag.
|
/// This returns the topmost window on the keyboard focus stack that is on an active tag.
|
||||||
|
@ -35,32 +60,9 @@ impl State {
|
||||||
.flatten()
|
.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) {
|
pub fn fixup_z_layering(&mut self) {
|
||||||
for win in self.pinnacle.z_index_stack.iter() {
|
for win in self.z_index_stack.iter() {
|
||||||
self.pinnacle.space.raise_element(win, false);
|
self.space.raise_element(win, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,26 +70,25 @@ impl State {
|
||||||
///
|
///
|
||||||
/// This does nothing if the window is unmapped.
|
/// This does nothing if the window is unmapped.
|
||||||
pub fn raise_window(&mut self, window: WindowElement, activate: bool) {
|
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");
|
warn!("Tried to raise an unmapped window");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.pinnacle.space.raise_element(&window, activate);
|
self.space.raise_element(&window, activate);
|
||||||
|
|
||||||
self.pinnacle.z_index_stack.retain(|win| win != &window);
|
self.z_index_stack.retain(|win| win != &window);
|
||||||
self.pinnacle.z_index_stack.push(window);
|
self.z_index_stack.push(window);
|
||||||
|
|
||||||
self.fixup_xwayland_window_layering();
|
self.fixup_xwayland_window_layering();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the currently focused output, or the first mapped output if there is none, or None.
|
/// Get the currently focused output, or the first mapped output if there is none, or None.
|
||||||
pub fn focused_output(&self) -> Option<&Output> {
|
pub fn focused_output(&self) -> Option<&Output> {
|
||||||
self.pinnacle
|
self.output_focus_stack
|
||||||
.output_focus_stack
|
|
||||||
.stack
|
.stack
|
||||||
.last()
|
.last()
|
||||||
.or_else(|| self.pinnacle.space.outputs().next())
|
.or_else(|| self.space.outputs().next())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -50,7 +50,7 @@ impl PointerGrab<State> for MoveSurfaceGrab {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
state.raise_window(self.window.clone(), false);
|
state.pinnacle.raise_window(self.window.clone(), false);
|
||||||
|
|
||||||
if let Some(surface) = self.window.x11_surface() {
|
if let Some(surface) = self.window.x11_surface() {
|
||||||
// INFO: can you raise OR windows or no idk
|
// INFO: can you raise OR windows or no idk
|
||||||
|
@ -119,7 +119,9 @@ impl PointerGrab<State> for MoveSurfaceGrab {
|
||||||
}
|
}
|
||||||
|
|
||||||
debug!("Swapping window positions");
|
debug!("Swapping window positions");
|
||||||
state.swap_window_positions(&self.window, &window_under);
|
state
|
||||||
|
.pinnacle
|
||||||
|
.swap_window_positions(&self.window, &window_under);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let delta = event.location - self.start_data.location;
|
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.
|
impl State {
|
||||||
pub fn move_request_client(
|
/// The application initiated a move grab e.g. when you drag a titlebar.
|
||||||
state: &mut State,
|
pub fn move_request_client(&mut self, surface: &WlSurface, seat: &Seat<State>, serial: Serial) {
|
||||||
surface: &WlSurface,
|
let pointer = seat.get_pointer().expect("seat had no pointer");
|
||||||
seat: &Seat<State>,
|
if let Some(start_data) = crate::grab::pointer_grab_start_data(&pointer, surface, serial) {
|
||||||
serial: Serial,
|
let Some(window) = self.pinnacle.window_for_surface(surface) else {
|
||||||
) {
|
warn!("Surface had no window, cancelling move request");
|
||||||
let pointer = seat.get_pointer().expect("seat had no pointer");
|
return;
|
||||||
if let Some(start_data) = crate::grab::pointer_grab_start_data(&pointer, surface, serial) {
|
};
|
||||||
let Some(window) = state.window_for_surface(surface) else {
|
|
||||||
|
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");
|
warn!("Surface had no window, cancelling move request");
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
let initial_window_loc = state
|
let initial_window_loc = self
|
||||||
.pinnacle
|
.pinnacle
|
||||||
.space
|
.space
|
||||||
.element_location(&window)
|
.element_location(&window)
|
||||||
.expect("move request was called on an unmapped 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 {
|
let grab = MoveSurfaceGrab {
|
||||||
start_data,
|
start_data,
|
||||||
window,
|
window,
|
||||||
initial_window_loc,
|
initial_window_loc,
|
||||||
};
|
};
|
||||||
|
|
||||||
pointer.set_grab(state, grab, serial, Focus::Clear);
|
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(
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
|
@ -21,7 +21,7 @@ use smithay::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
state::{State, WithState},
|
state::{Pinnacle, State, WithState},
|
||||||
window::{window_state::FloatingOrTiled, WindowElement},
|
window::{window_state::FloatingOrTiled, WindowElement},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -362,119 +362,171 @@ impl ResizeSurfaceState {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn move_surface_if_resized(state: &mut State, surface: &WlSurface) {
|
impl Pinnacle {
|
||||||
let Some(window) = state.window_for_surface(surface) else {
|
pub fn move_surface_if_resized(&mut self, surface: &WlSurface) {
|
||||||
return;
|
let Some(window) = self.window_for_surface(surface) else {
|
||||||
};
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
let Some(mut window_loc) = state.pinnacle.space.element_location(&window) else {
|
let Some(mut window_loc) = self.space.element_location(&window) else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
let geometry = window.geometry();
|
let geometry = window.geometry();
|
||||||
|
|
||||||
let new_loc: Option<(Option<i32>, Option<i32>)> = surface.with_state_mut(|state| {
|
let new_loc: Option<(Option<i32>, Option<i32>)> = surface.with_state_mut(|state| {
|
||||||
state
|
state
|
||||||
.resize_state
|
.resize_state
|
||||||
.on_commit()
|
.on_commit()
|
||||||
.map(|(edges, initial_window_rect)| {
|
.map(|(edges, initial_window_rect)| {
|
||||||
let mut new_x: Option<i32> = None;
|
let mut new_x: Option<i32> = None;
|
||||||
let mut new_y: Option<i32> = None;
|
let mut new_y: Option<i32> = None;
|
||||||
if let xdg_toplevel::ResizeEdge::Left
|
if let xdg_toplevel::ResizeEdge::Left
|
||||||
| xdg_toplevel::ResizeEdge::TopLeft
|
| xdg_toplevel::ResizeEdge::TopLeft
|
||||||
| xdg_toplevel::ResizeEdge::BottomLeft = edges.0
|
| xdg_toplevel::ResizeEdge::BottomLeft = edges.0
|
||||||
{
|
{
|
||||||
new_x = Some(
|
new_x = Some(
|
||||||
initial_window_rect.loc.x + (initial_window_rect.size.w - geometry.size.w),
|
initial_window_rect.loc.x
|
||||||
);
|
+ (initial_window_rect.size.w - geometry.size.w),
|
||||||
}
|
);
|
||||||
if let xdg_toplevel::ResizeEdge::Top
|
}
|
||||||
| xdg_toplevel::ResizeEdge::TopLeft
|
if let xdg_toplevel::ResizeEdge::Top
|
||||||
| xdg_toplevel::ResizeEdge::TopRight = edges.0
|
| 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_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()) {
|
if window.with_state(|state| state.floating_or_tiled.is_tiled()) {
|
||||||
return;
|
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 new_loc.0.is_some() || new_loc.1.is_some() {
|
let Some(new_loc) = new_loc else { return };
|
||||||
state
|
|
||||||
.pinnacle
|
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
|
.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() {
|
window.with_state_mut(|state| {
|
||||||
if !surface.is_override_redirect() {
|
if state.floating_or_tiled.is_floating() {
|
||||||
let geo = surface.geometry();
|
state.floating_or_tiled =
|
||||||
let new_geo = Rectangle::from_loc_and_size(window_loc, geo.size);
|
FloatingOrTiled::Floating(Rectangle::from_loc_and_size(window_loc, size));
|
||||||
surface
|
}
|
||||||
.configure(new_geo)
|
});
|
||||||
.expect("failed to configure x11 win");
|
|
||||||
|
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.
|
impl State {
|
||||||
pub fn resize_request_client(
|
/// The application requests a resize e.g. when you drag the edges of a window.
|
||||||
state: &mut State,
|
pub fn resize_request_client(
|
||||||
surface: &WlSurface,
|
&mut self,
|
||||||
seat: &Seat<State>,
|
surface: &WlSurface,
|
||||||
serial: smithay::utils::Serial,
|
seat: &Seat<State>,
|
||||||
edges: self::ResizeEdge,
|
serial: smithay::utils::Serial,
|
||||||
button_used: u32,
|
edges: self::ResizeEdge,
|
||||||
) {
|
button_used: u32,
|
||||||
let pointer = seat.get_pointer().expect("seat had no pointer");
|
) {
|
||||||
|
let pointer = seat.get_pointer().expect("seat had no pointer");
|
||||||
|
|
||||||
if let Some(start_data) = crate::grab::pointer_grab_start_data(&pointer, surface, serial) {
|
if let Some(start_data) = crate::grab::pointer_grab_start_data(&pointer, surface, serial) {
|
||||||
let Some(window) = state.window_for_surface(surface) else {
|
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");
|
tracing::error!("Surface had no window, cancelling resize request");
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: check for fullscreen/maximized (probably shouldn't matter)
|
|
||||||
if window.with_state(|state| state.floating_or_tiled.is_tiled()) {
|
if window.with_state(|state| state.floating_or_tiled.is_tiled()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let initial_window_loc = state
|
let initial_window_loc = self
|
||||||
.pinnacle
|
.pinnacle
|
||||||
.space
|
.space
|
||||||
.element_location(&window)
|
.element_location(&window)
|
||||||
.expect("resize request called on unmapped window");
|
.expect("resize request called on unmapped window");
|
||||||
let initial_window_size = window.geometry().size;
|
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() {
|
if let Some(toplevel) = window.toplevel() {
|
||||||
toplevel.with_pending_state(|state| {
|
toplevel.with_pending_state(|state| {
|
||||||
state.states.set(xdg_toplevel::State::Resizing);
|
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(
|
let grab = ResizeSurfaceGrab::start(
|
||||||
start_data,
|
start_data,
|
||||||
window,
|
window,
|
||||||
|
@ -493,65 +553,7 @@ pub fn resize_request_client(
|
||||||
);
|
);
|
||||||
|
|
||||||
if let Some(grab) = grab {
|
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
164
src/handlers.rs
164
src/handlers.rs
|
@ -67,7 +67,7 @@ use crate::{
|
||||||
gamma_control::{GammaControlHandler, GammaControlManagerState},
|
gamma_control::{GammaControlHandler, GammaControlManagerState},
|
||||||
screencopy::{Screencopy, ScreencopyHandler},
|
screencopy::{Screencopy, ScreencopyHandler},
|
||||||
},
|
},
|
||||||
state::{ClientState, State, WithState},
|
state::{ClientState, Pinnacle, State, WithState},
|
||||||
};
|
};
|
||||||
|
|
||||||
impl BufferHandler for State {
|
impl BufferHandler for State {
|
||||||
|
@ -130,7 +130,7 @@ impl CompositorHandler for State {
|
||||||
}
|
}
|
||||||
|
|
||||||
if !compositor::is_sync_subsurface(surface) {
|
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();
|
window.on_commit();
|
||||||
if let Some(loc) = window.with_state_mut(|state| state.target_loc.take()) {
|
if let Some(loc) = window.with_state_mut(|state| state.target_loc.take()) {
|
||||||
self.pinnacle.space.map_element(window.clone(), loc, false);
|
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.new_windows.retain(|win| win != &new_window);
|
||||||
self.pinnacle.windows.push(new_window.clone());
|
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");
|
tracing::debug!("Placing toplevel");
|
||||||
new_window.place_on_output(output);
|
new_window.place_on_output(output);
|
||||||
output.with_state_mut(|state| state.focus_stack.set_focus(new_window.clone()));
|
output.with_state_mut(|state| state.focus_stack.set_focus(new_window.clone()));
|
||||||
|
@ -170,12 +170,12 @@ impl CompositorHandler for State {
|
||||||
.space
|
.space
|
||||||
.map_element(new_window.clone(), (1000000, 0), true);
|
.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() {
|
if let Some(focused_output) = self.pinnacle.focused_output().cloned() {
|
||||||
self.request_layout(&focused_output);
|
self.pinnacle.request_layout(&focused_output);
|
||||||
new_window.send_frame(
|
new_window.send_frame(
|
||||||
&focused_output,
|
&focused_output,
|
||||||
self.pinnacle.clock.now(),
|
self.pinnacle.clock.now(),
|
||||||
|
@ -198,28 +198,28 @@ impl CompositorHandler for State {
|
||||||
});
|
});
|
||||||
} else if new_window.toplevel().is_some() {
|
} else if new_window.toplevel().is_some() {
|
||||||
new_window.on_commit();
|
new_window.on_commit();
|
||||||
ensure_initial_configure(surface, self);
|
self.pinnacle.ensure_initial_configure(surface);
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
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);
|
let mut outputs = self.pinnacle.space.outputs_for_element(&window);
|
||||||
|
|
||||||
// When the window hasn't been mapped `outputs` is empty,
|
// When the window hasn't been mapped `outputs` is empty,
|
||||||
// so also trigger a render using the window's tags' output
|
// 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.push(output);
|
||||||
}
|
}
|
||||||
outputs // surface is a window
|
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);
|
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.push(output);
|
||||||
}
|
}
|
||||||
outputs // surface is a root window
|
outputs // surface is a root window
|
||||||
|
@ -270,73 +270,75 @@ impl CompositorHandler for State {
|
||||||
}
|
}
|
||||||
delegate_compositor!(State);
|
delegate_compositor!(State);
|
||||||
|
|
||||||
fn ensure_initial_configure(surface: &WlSurface, state: &mut State) {
|
impl Pinnacle {
|
||||||
if let (Some(window), _) | (None, Some(window)) = (
|
fn ensure_initial_configure(&mut self, surface: &WlSurface) {
|
||||||
state.window_for_surface(surface),
|
if let (Some(window), _) | (None, Some(window)) = (
|
||||||
state.new_window_for_surface(surface),
|
self.window_for_surface(surface),
|
||||||
) {
|
self.new_window_for_surface(surface),
|
||||||
if let Some(toplevel) = window.toplevel() {
|
) {
|
||||||
|
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| {
|
let initial_configure_sent = compositor::with_states(surface, |states| {
|
||||||
states
|
states
|
||||||
.data_map
|
.data_map
|
||||||
.get::<XdgToplevelSurfaceData>()
|
.get::<XdgPopupSurfaceData>()
|
||||||
.expect("XdgToplevelSurfaceData wasn't in surface's data map")
|
.expect("XdgPopupSurfaceData wasn't in popup's data map")
|
||||||
.lock()
|
.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
|
.initial_configure_sent
|
||||||
});
|
});
|
||||||
|
|
||||||
if !initial_configure_sent {
|
if !initial_configure_sent {
|
||||||
tracing::debug!("Initial configure");
|
layer_map_for_output(output)
|
||||||
toplevel.send_configure();
|
.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| {
|
compositor::with_states(&root, |states| {
|
||||||
desktop::utils::surface_primary_scanout_output(&root, states)
|
desktop::utils::surface_primary_scanout_output(&root, states)
|
||||||
.or_else(|| {
|
.or_else(|| {
|
||||||
self.window_for_surface(&root).and_then(|window| {
|
self.pinnacle.window_for_surface(&root).and_then(|window| {
|
||||||
self.pinnacle
|
self.pinnacle
|
||||||
.space
|
.space
|
||||||
.outputs_for_element(&window)
|
.outputs_for_element(&window)
|
||||||
|
@ -487,7 +489,7 @@ impl FractionalScaleHandler for State {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
self.window_for_surface(&root).and_then(|window| {
|
self.pinnacle.window_for_surface(&root).and_then(|window| {
|
||||||
self.pinnacle
|
self.pinnacle
|
||||||
.space
|
.space
|
||||||
.outputs_for_element(&window)
|
.outputs_for_element(&window)
|
||||||
|
@ -542,7 +544,7 @@ impl WlrLayerShellHandler for State {
|
||||||
}
|
}
|
||||||
|
|
||||||
self.pinnacle.loop_handle.insert_idle(move |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 {
|
if let Some(output) = output {
|
||||||
self.pinnacle.loop_handle.insert_idle(move |state| {
|
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) {
|
fn new_popup(&mut self, _parent: wlr_layer::LayerSurface, popup: PopupSurface) {
|
||||||
trace!("WlrLayerShellHandler::new_popup");
|
trace!("WlrLayerShellHandler::new_popup");
|
||||||
self.position_popup(&popup);
|
self.pinnacle.position_popup(&popup);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
delegate_layer_shell!(State);
|
delegate_layer_shell!(State);
|
||||||
|
@ -636,7 +638,7 @@ impl GammaControlHandler for State {
|
||||||
}
|
}
|
||||||
delegate_gamma_control!(State);
|
delegate_gamma_control!(State);
|
||||||
|
|
||||||
impl State {
|
impl Pinnacle {
|
||||||
fn position_popup(&self, popup: &PopupSurface) {
|
fn position_popup(&self, popup: &PopupSurface) {
|
||||||
trace!("State::position_popup");
|
trace!("State::position_popup");
|
||||||
let Ok(root) = find_popup_root_surface(&PopupKind::Xdg(popup.clone())) else {
|
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 (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())
|
(win_geo.loc, self.focused_output()?.clone())
|
||||||
} else {
|
} else {
|
||||||
self.pinnacle.space.outputs().find_map(|op| {
|
self.space.outputs().find_map(|op| {
|
||||||
let layer_map = layer_map_for_output(op);
|
let layer_map = layer_map_for_output(op);
|
||||||
let layer = layer_map.layer_for_surface(&root, WindowSurfaceType::TOPLEVEL)?;
|
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((
|
Some((
|
||||||
layer_map.layer_geometry(layer)?.loc + output_loc,
|
layer_map.layer_geometry(layer)?.loc + output_loc,
|
||||||
op.clone(),
|
op.clone(),
|
||||||
|
@ -676,7 +678,7 @@ impl State {
|
||||||
root_global_loc + get_popup_toplevel_coords(&PopupKind::Xdg(popup.clone()))
|
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
|
// Make local to parent
|
||||||
output_geo.loc -= parent_global_loc;
|
output_geo.loc -= parent_global_loc;
|
||||||
|
|
|
@ -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;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(output) = window.output(self) {
|
if let Some(output) = window.output(&self.pinnacle) {
|
||||||
self.request_layout(&output);
|
self.pinnacle.request_layout(&output);
|
||||||
let focus = self
|
let focus = self
|
||||||
|
.pinnacle
|
||||||
.focused_window(&output)
|
.focused_window(&output)
|
||||||
.map(KeyboardFocusTarget::Window);
|
.map(KeyboardFocusTarget::Window);
|
||||||
if let Some(KeyboardFocusTarget::Window(window)) = &focus {
|
if let Some(KeyboardFocusTarget::Window(window)) = &focus {
|
||||||
tracing::debug!("Focusing on prev win");
|
tracing::debug!("Focusing on prev win");
|
||||||
// TODO:
|
// TODO:
|
||||||
self.raise_window(window.clone(), true);
|
self.pinnacle.raise_window(window.clone(), true);
|
||||||
if let Some(toplevel) = window.toplevel() {
|
if let Some(toplevel) = window.toplevel() {
|
||||||
toplevel.send_configure();
|
toplevel.send_configure();
|
||||||
}
|
}
|
||||||
|
@ -100,7 +101,7 @@ impl XdgShellHandler for State {
|
||||||
fn new_popup(&mut self, surface: PopupSurface, _positioner: PositionerState) {
|
fn new_popup(&mut self, surface: PopupSurface, _positioner: PositionerState) {
|
||||||
trace!("XdgShellHandler::new_popup");
|
trace!("XdgShellHandler::new_popup");
|
||||||
|
|
||||||
self.position_popup(&surface);
|
self.pinnacle.position_popup(&surface);
|
||||||
|
|
||||||
if let Err(err) = self
|
if let Err(err) = self
|
||||||
.pinnacle
|
.pinnacle
|
||||||
|
@ -120,8 +121,7 @@ impl XdgShellHandler for State {
|
||||||
|
|
||||||
fn move_request(&mut self, surface: ToplevelSurface, seat: WlSeat, serial: Serial) {
|
fn move_request(&mut self, surface: ToplevelSurface, seat: WlSeat, serial: Serial) {
|
||||||
tracing::debug!("move_request_client");
|
tracing::debug!("move_request_client");
|
||||||
crate::grab::move_grab::move_request_client(
|
self.move_request_client(
|
||||||
self,
|
|
||||||
surface.wl_surface(),
|
surface.wl_surface(),
|
||||||
&Seat::from_resource(&seat).expect("couldn't get seat from WlSeat"),
|
&Seat::from_resource(&seat).expect("couldn't get seat from WlSeat"),
|
||||||
serial,
|
serial,
|
||||||
|
@ -136,8 +136,7 @@ impl XdgShellHandler for State {
|
||||||
edges: ResizeEdge,
|
edges: ResizeEdge,
|
||||||
) {
|
) {
|
||||||
const BUTTON_LEFT: u32 = 0x110;
|
const BUTTON_LEFT: u32 = 0x110;
|
||||||
crate::grab::resize_grab::resize_request_client(
|
self.resize_request_client(
|
||||||
self,
|
|
||||||
surface.wl_surface(),
|
surface.wl_surface(),
|
||||||
&Seat::from_resource(&seat).expect("couldn't get seat from WlSeat"),
|
&Seat::from_resource(&seat).expect("couldn't get seat from WlSeat"),
|
||||||
serial,
|
serial,
|
||||||
|
@ -158,7 +157,7 @@ impl XdgShellHandler for State {
|
||||||
state.geometry = positioner.get_geometry();
|
state.geometry = positioner.get_geometry();
|
||||||
state.positioner = positioner;
|
state.positioner = positioner;
|
||||||
});
|
});
|
||||||
self.position_popup(&surface);
|
self.pinnacle.position_popup(&surface);
|
||||||
surface.send_repositioned(token);
|
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 seat: Seat<Self> = Seat::from_resource(&seat).expect("couldn't get seat from WlSeat");
|
||||||
let popup_kind = PopupKind::Xdg(surface);
|
let popup_kind = PopupKind::Xdg(surface);
|
||||||
if let Some(root) = find_popup_root_surface(&popup_kind).ok().and_then(|root| {
|
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)
|
.map(KeyboardFocusTarget::Window)
|
||||||
.or_else(|| {
|
.or_else(|| {
|
||||||
self.pinnacle.space.outputs().find_map(|op| {
|
self.pinnacle.space.outputs().find_map(|op| {
|
||||||
|
@ -223,13 +223,15 @@ impl XdgShellHandler for State {
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.and_then(Output::from_resource)
|
.and_then(Output::from_resource)
|
||||||
.or_else(|| {
|
.or_else(|| {
|
||||||
self.window_for_surface(wl_surface).and_then(|window| {
|
self.pinnacle
|
||||||
self.pinnacle
|
.window_for_surface(wl_surface)
|
||||||
.space
|
.and_then(|window| {
|
||||||
.outputs_for_element(&window)
|
self.pinnacle
|
||||||
.first()
|
.space
|
||||||
.cloned()
|
.outputs_for_element(&window)
|
||||||
})
|
.first()
|
||||||
|
.cloned()
|
||||||
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
if let Some(output) = output {
|
if let Some(output) = output {
|
||||||
|
@ -253,14 +255,14 @@ impl XdgShellHandler for State {
|
||||||
state.fullscreen_output = wl_output;
|
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");
|
tracing::error!("wl_surface had no window");
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
if !window.with_state(|state| state.fullscreen_or_maximized.is_fullscreen()) {
|
if !window.with_state(|state| state.fullscreen_or_maximized.is_fullscreen()) {
|
||||||
window.toggle_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();
|
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");
|
tracing::error!("wl_surface had no window");
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
if window.with_state(|state| state.fullscreen_or_maximized.is_fullscreen()) {
|
if window.with_state(|state| state.fullscreen_or_maximized.is_fullscreen()) {
|
||||||
window.toggle_fullscreen();
|
window.toggle_fullscreen();
|
||||||
if let Some(output) = window.output(self) {
|
if let Some(output) = window.output(&self.pinnacle) {
|
||||||
self.request_layout(&output);
|
self.pinnacle.request_layout(&output);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn maximize_request(&mut self, surface: ToplevelSurface) {
|
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;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -306,12 +308,14 @@ impl XdgShellHandler for State {
|
||||||
window.toggle_maximized();
|
window.toggle_maximized();
|
||||||
}
|
}
|
||||||
|
|
||||||
let Some(output) = window.output(self) else { return };
|
let Some(output) = window.output(&self.pinnacle) else {
|
||||||
self.request_layout(&output);
|
return;
|
||||||
|
};
|
||||||
|
self.pinnacle.request_layout(&output);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn unmaximize_request(&mut self, surface: ToplevelSurface) {
|
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;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -319,8 +323,10 @@ impl XdgShellHandler for State {
|
||||||
window.toggle_maximized();
|
window.toggle_maximized();
|
||||||
}
|
}
|
||||||
|
|
||||||
let Some(output) = window.output(self) else { return };
|
let Some(output) = window.output(&self.pinnacle) else {
|
||||||
self.request_layout(&output);
|
return;
|
||||||
|
};
|
||||||
|
self.pinnacle.request_layout(&output);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn minimize_request(&mut self, _surface: ToplevelSurface) {
|
fn minimize_request(&mut self, _surface: ToplevelSurface) {
|
||||||
|
|
|
@ -26,7 +26,7 @@ use tracing::{debug, error, trace, warn};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
focus::keyboard::KeyboardFocusTarget,
|
focus::keyboard::KeyboardFocusTarget,
|
||||||
state::{State, WithState},
|
state::{Pinnacle, State, WithState},
|
||||||
window::{window_state::FloatingOrTiled, WindowElement},
|
window::{window_state::FloatingOrTiled, WindowElement},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -58,12 +58,14 @@ impl XwmHandler for State {
|
||||||
.expect("called element_bbox on an unmapped window");
|
.expect("called element_bbox on an unmapped window");
|
||||||
|
|
||||||
let output_size = self
|
let output_size = self
|
||||||
|
.pinnacle
|
||||||
.focused_output()
|
.focused_output()
|
||||||
.and_then(|op| self.pinnacle.space.output_geometry(op))
|
.and_then(|op| self.pinnacle.space.output_geometry(op))
|
||||||
.map(|geo| geo.size)
|
.map(|geo| geo.size)
|
||||||
.unwrap_or((2, 2).into());
|
.unwrap_or((2, 2).into());
|
||||||
|
|
||||||
let output_loc = self
|
let output_loc = self
|
||||||
|
.pinnacle
|
||||||
.focused_output()
|
.focused_output()
|
||||||
.map(|op| op.current_location())
|
.map(|op| op.current_location())
|
||||||
.unwrap_or((0, 0).into());
|
.unwrap_or((0, 0).into());
|
||||||
|
@ -92,7 +94,7 @@ impl XwmHandler for State {
|
||||||
.expect("failed to configure x11 window");
|
.expect("failed to configure x11 window");
|
||||||
// TODO: ssd
|
// TODO: ssd
|
||||||
|
|
||||||
if let Some(output) = self.focused_output() {
|
if let Some(output) = self.pinnacle.focused_output() {
|
||||||
window.place_on_output(output);
|
window.place_on_output(output);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -104,13 +106,13 @@ impl XwmHandler for State {
|
||||||
|
|
||||||
// TODO: will an unmap -> map duplicate the window
|
// TODO: will an unmap -> map duplicate the window
|
||||||
self.pinnacle.windows.push(window.clone());
|
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()));
|
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| {
|
self.pinnacle.loop_handle.insert_idle(move |state| {
|
||||||
|
@ -138,7 +140,7 @@ impl XwmHandler for State {
|
||||||
|
|
||||||
self.pinnacle.windows.push(window.clone());
|
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);
|
window.place_on_output(output);
|
||||||
// FIXME: setting focus here may possibly muck things up
|
// FIXME: setting focus here may possibly muck things up
|
||||||
// | or maybe they won't idk
|
// | or maybe they won't idk
|
||||||
|
@ -146,15 +148,15 @@ impl XwmHandler for State {
|
||||||
}
|
}
|
||||||
|
|
||||||
self.pinnacle.space.map_element(window.clone(), loc, true);
|
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) {
|
fn map_window_notify(&mut self, _xwm: XwmId, window: X11Surface) {
|
||||||
trace!("XwmHandler::map_window_notify");
|
trace!("XwmHandler::map_window_notify");
|
||||||
let Some(output) = window
|
let Some(output) = window
|
||||||
.wl_surface()
|
.wl_surface()
|
||||||
.and_then(|s| self.window_for_surface(&s))
|
.and_then(|s| self.pinnacle.window_for_surface(&s))
|
||||||
.and_then(|win| win.output(self))
|
.and_then(|win| win.output(&self.pinnacle))
|
||||||
else {
|
else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
@ -189,15 +191,16 @@ impl XwmHandler for State {
|
||||||
|
|
||||||
self.pinnacle.space.unmap_elem(&win);
|
self.pinnacle.space.unmap_elem(&win);
|
||||||
|
|
||||||
if let Some(output) = win.output(self) {
|
if let Some(output) = win.output(&self.pinnacle) {
|
||||||
self.request_layout(&output);
|
self.pinnacle.request_layout(&output);
|
||||||
|
|
||||||
let focus = self
|
let focus = self
|
||||||
|
.pinnacle
|
||||||
.focused_window(&output)
|
.focused_window(&output)
|
||||||
.map(KeyboardFocusTarget::Window);
|
.map(KeyboardFocusTarget::Window);
|
||||||
|
|
||||||
if let Some(KeyboardFocusTarget::Window(win)) = &focus {
|
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() {
|
if let Some(toplevel) = win.toplevel() {
|
||||||
toplevel.send_configure();
|
toplevel.send_configure();
|
||||||
}
|
}
|
||||||
|
@ -255,15 +258,16 @@ impl XwmHandler for State {
|
||||||
.z_index_stack
|
.z_index_stack
|
||||||
.retain(|elem| win.wl_surface() != elem.wl_surface());
|
.retain(|elem| win.wl_surface() != elem.wl_surface());
|
||||||
|
|
||||||
if let Some(output) = win.output(self) {
|
if let Some(output) = win.output(&self.pinnacle) {
|
||||||
self.request_layout(&output);
|
self.pinnacle.request_layout(&output);
|
||||||
|
|
||||||
let focus = self
|
let focus = self
|
||||||
|
.pinnacle
|
||||||
.focused_window(&output)
|
.focused_window(&output)
|
||||||
.map(KeyboardFocusTarget::Window);
|
.map(KeyboardFocusTarget::Window);
|
||||||
|
|
||||||
if let Some(KeyboardFocusTarget::Window(win)) = &focus {
|
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() {
|
if let Some(toplevel) = win.toplevel() {
|
||||||
toplevel.send_configure();
|
toplevel.send_configure();
|
||||||
}
|
}
|
||||||
|
@ -355,7 +359,7 @@ impl XwmHandler for State {
|
||||||
|
|
||||||
let Some(window) = window
|
let Some(window) = window
|
||||||
.wl_surface()
|
.wl_surface()
|
||||||
.and_then(|surf| self.window_for_surface(&surf))
|
.and_then(|surf| self.pinnacle.window_for_surface(&surf))
|
||||||
else {
|
else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
@ -372,7 +376,7 @@ impl XwmHandler for State {
|
||||||
|
|
||||||
let Some(window) = window
|
let Some(window) = window
|
||||||
.wl_surface()
|
.wl_surface()
|
||||||
.and_then(|surf| self.window_for_surface(&surf))
|
.and_then(|surf| self.pinnacle.window_for_surface(&surf))
|
||||||
else {
|
else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
@ -389,15 +393,15 @@ impl XwmHandler for State {
|
||||||
|
|
||||||
let Some(window) = window
|
let Some(window) = window
|
||||||
.wl_surface()
|
.wl_surface()
|
||||||
.and_then(|surf| self.window_for_surface(&surf))
|
.and_then(|surf| self.pinnacle.window_for_surface(&surf))
|
||||||
else {
|
else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
if !window.with_state(|state| state.fullscreen_or_maximized.is_fullscreen()) {
|
if !window.with_state(|state| state.fullscreen_or_maximized.is_fullscreen()) {
|
||||||
window.toggle_fullscreen();
|
window.toggle_fullscreen();
|
||||||
if let Some(output) = window.output(self) {
|
if let Some(output) = window.output(&self.pinnacle) {
|
||||||
self.request_layout(&output);
|
self.pinnacle.request_layout(&output);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -409,15 +413,15 @@ impl XwmHandler for State {
|
||||||
|
|
||||||
let Some(window) = window
|
let Some(window) = window
|
||||||
.wl_surface()
|
.wl_surface()
|
||||||
.and_then(|surf| self.window_for_surface(&surf))
|
.and_then(|surf| self.pinnacle.window_for_surface(&surf))
|
||||||
else {
|
else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
if window.with_state(|state| state.fullscreen_or_maximized.is_fullscreen()) {
|
if window.with_state(|state| state.fullscreen_or_maximized.is_fullscreen()) {
|
||||||
window.toggle_fullscreen();
|
window.toggle_fullscreen();
|
||||||
if let Some(output) = window.output(self) {
|
if let Some(output) = window.output(&self.pinnacle) {
|
||||||
self.request_layout(&output);
|
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
|
// We use the server one and not the client because windows like Steam don't provide
|
||||||
// GrabStartData, so we need to create it ourselves.
|
// GrabStartData, so we need to create it ourselves.
|
||||||
crate::grab::resize_grab::resize_request_server(
|
self.resize_request_server(
|
||||||
self,
|
|
||||||
&wl_surf,
|
&wl_surf,
|
||||||
&seat,
|
&seat,
|
||||||
SERIAL_COUNTER.next_serial(),
|
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
|
// We use the server one and not the client because windows like Steam don't provide
|
||||||
// GrabStartData, so we need to create it ourselves.
|
// GrabStartData, so we need to create it ourselves.
|
||||||
crate::grab::move_grab::move_request_server(
|
self.move_request_server(&wl_surf, &seat, SERIAL_COUNTER.next_serial(), button);
|
||||||
self,
|
|
||||||
&wl_surf,
|
|
||||||
&seat,
|
|
||||||
SERIAL_COUNTER.next_serial(),
|
|
||||||
button,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn allow_selection_access(&mut self, xwm: XwmId, _selection: SelectionTarget) -> bool {
|
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) {
|
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;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
let x11_wins = self
|
let x11_wins = self
|
||||||
.pinnacle
|
|
||||||
.space
|
.space
|
||||||
.elements()
|
.elements()
|
||||||
.filter(|win| win.is_on_active_tag())
|
.filter(|win| win.is_on_active_tag())
|
||||||
|
|
13
src/input.rs
13
src/input.rs
|
@ -452,11 +452,12 @@ impl State {
|
||||||
self.switch_vt(vt);
|
self.switch_vt(vt);
|
||||||
}
|
}
|
||||||
Some(KeyAction::Quit) => {
|
Some(KeyAction::Quit) => {
|
||||||
self.shutdown();
|
self.pinnacle.shutdown();
|
||||||
}
|
}
|
||||||
Some(KeyAction::ReloadConfig) => {
|
Some(KeyAction::ReloadConfig) => {
|
||||||
info!("Reloading config");
|
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");
|
.expect("failed to restart config");
|
||||||
}
|
}
|
||||||
None => (),
|
None => (),
|
||||||
|
@ -511,8 +512,8 @@ impl State {
|
||||||
// TODO: use update_keyboard_focus from anvil
|
// TODO: use update_keyboard_focus from anvil
|
||||||
|
|
||||||
if let Some(window) = focus.window_for(self) {
|
if let Some(window) = focus.window_for(self) {
|
||||||
self.raise_window(window.clone(), true);
|
self.pinnacle.raise_window(window.clone(), true);
|
||||||
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()));
|
output.with_state_mut(|state| state.focus_stack.set_focus(window.clone()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -531,7 +532,7 @@ impl State {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if let Some(focused_op) = self.focused_output() {
|
if let Some(focused_op) = self.pinnacle.focused_output() {
|
||||||
focused_op.with_state_mut(|state| {
|
focused_op.with_state_mut(|state| {
|
||||||
state.focus_stack.unset_focus();
|
state.focus_stack.unset_focus();
|
||||||
for window in state.focus_stack.stack.iter() {
|
for window in state.focus_stack.stack.iter() {
|
||||||
|
@ -728,7 +729,7 @@ impl State {
|
||||||
|
|
||||||
pointer.frame(self);
|
pointer.frame(self);
|
||||||
|
|
||||||
if let Some(output) = self.focused_output().cloned() {
|
if let Some(output) = self.pinnacle.focused_output().cloned() {
|
||||||
self.schedule_render(&output);
|
self.schedule_render(&output);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,15 +1,14 @@
|
||||||
use smithay::backend::{input::InputEvent, libinput::LibinputInputBackend};
|
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.
|
/// Apply current libinput settings to new devices.
|
||||||
pub fn apply_libinput_settings(&mut self, event: &InputEvent<LibinputInputBackend>) {
|
pub fn apply_libinput_settings(&mut self, event: &InputEvent<LibinputInputBackend>) {
|
||||||
let mut device = match event {
|
let mut device = match event {
|
||||||
InputEvent::DeviceAdded { device } => device.clone(),
|
InputEvent::DeviceAdded { device } => device.clone(),
|
||||||
InputEvent::DeviceRemoved { device } => {
|
InputEvent::DeviceRemoved { device } => {
|
||||||
self.pinnacle
|
self.input_state
|
||||||
.input_state
|
|
||||||
.libinput_devices
|
.libinput_devices
|
||||||
.retain(|dev| dev != device);
|
.retain(|dev| dev != device);
|
||||||
return;
|
return;
|
||||||
|
@ -17,14 +16,14 @@ impl State {
|
||||||
_ => return,
|
_ => return,
|
||||||
};
|
};
|
||||||
|
|
||||||
if self.pinnacle.input_state.libinput_devices.contains(&device) {
|
if self.input_state.libinput_devices.contains(&device) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for setting in self.pinnacle.input_state.libinput_settings.values() {
|
for setting in self.input_state.libinput_settings.values() {
|
||||||
setting(&mut device);
|
setting(&mut device);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.pinnacle.input_state.libinput_devices.push(device);
|
self.input_state.libinput_devices.push(device);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,14 +18,14 @@ use tracing::warn;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
output::OutputName,
|
output::OutputName,
|
||||||
state::{State, WithState},
|
state::{Pinnacle, State, WithState},
|
||||||
window::{
|
window::{
|
||||||
window_state::{FloatingOrTiled, FullscreenOrMaximized},
|
window_state::{FloatingOrTiled, FullscreenOrMaximized},
|
||||||
WindowElement,
|
WindowElement,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
impl State {
|
impl Pinnacle {
|
||||||
fn update_windows_with_geometries(
|
fn update_windows_with_geometries(
|
||||||
&mut self,
|
&mut self,
|
||||||
output: &Output,
|
output: &Output,
|
||||||
|
@ -33,8 +33,7 @@ impl State {
|
||||||
) {
|
) {
|
||||||
let windows_on_foc_tags = output.with_state(|state| {
|
let windows_on_foc_tags = output.with_state(|state| {
|
||||||
let focused_tags = state.focused_tags().collect::<Vec<_>>();
|
let focused_tags = state.focused_tags().collect::<Vec<_>>();
|
||||||
self.pinnacle
|
self.windows
|
||||||
.windows
|
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|win| !win.is_x11_override_redirect())
|
.filter(|win| !win.is_x11_override_redirect())
|
||||||
.filter(|win| {
|
.filter(|win| {
|
||||||
|
@ -53,11 +52,7 @@ impl State {
|
||||||
})
|
})
|
||||||
.cloned();
|
.cloned();
|
||||||
|
|
||||||
let output_geo = self
|
let output_geo = self.space.output_geometry(output).expect("no output geo");
|
||||||
.pinnacle
|
|
||||||
.space
|
|
||||||
.output_geometry(output)
|
|
||||||
.expect("no output geo");
|
|
||||||
|
|
||||||
let non_exclusive_geo = {
|
let non_exclusive_geo = {
|
||||||
let map = layer_map_for_output(output);
|
let map = layer_map_for_output(output);
|
||||||
|
@ -130,7 +125,7 @@ impl State {
|
||||||
WindowSurface::X11(_) => {
|
WindowSurface::X11(_) => {
|
||||||
let loc = win.with_state_mut(|state| state.target_loc.take());
|
let loc = win.with_state_mut(|state| state.target_loc.take());
|
||||||
if let Some(loc) = loc {
|
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 {
|
for (loc, window) in non_pending_wins {
|
||||||
self.pinnacle.space.map_element(window, loc, false);
|
self.space.map_element(window, loc, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME:
|
// FIXME:
|
||||||
|
@ -146,12 +141,9 @@ impl State {
|
||||||
// Obviously this is a bad way to do this but its a bandaid solution
|
// Obviously this is a bad way to do this but its a bandaid solution
|
||||||
// until decent transactional layout applications are implemented.
|
// until decent transactional layout applications are implemented.
|
||||||
for (win, _serial) in pending_wins {
|
for (win, _serial) in pending_wins {
|
||||||
win.send_frame(
|
win.send_frame(output, self.clock.now(), Some(Duration::ZERO), |_, _| {
|
||||||
output,
|
Some(output.clone())
|
||||||
self.pinnacle.clock.now(),
|
});
|
||||||
Some(Duration::ZERO),
|
|
||||||
|_, _| Some(output.clone()),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
self.fixup_z_layering();
|
self.fixup_z_layering();
|
||||||
|
@ -159,15 +151,15 @@ impl State {
|
||||||
|
|
||||||
/// Swaps two windows in the main window vec and updates all windows.
|
/// Swaps two windows in the main window vec and updates all windows.
|
||||||
pub fn swap_window_positions(&mut self, win1: &WindowElement, win2: &WindowElement) {
|
pub fn swap_window_positions(&mut self, win1: &WindowElement, win2: &WindowElement) {
|
||||||
let win1_index = self.pinnacle.windows.iter().position(|win| win == win1);
|
let win1_index = self.windows.iter().position(|win| win == win1);
|
||||||
let win2_index = self.pinnacle.windows.iter().position(|win| win == win2);
|
let win2_index = self.windows.iter().position(|win| win == win2);
|
||||||
|
|
||||||
if let (Some(first), Some(second)) = (win1_index, win2_index) {
|
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) {
|
if let Some(output) = win1.output(self) {
|
||||||
self.request_layout(&output);
|
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>>,
|
old_requests: HashMap<Output, HashSet<LayoutRequestId>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl State {
|
impl Pinnacle {
|
||||||
pub fn request_layout(&mut self, output: &Output) {
|
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");
|
warn!("Layout requested but no client has connected to the layout service");
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
let windows_on_foc_tags = output.with_state(|state| {
|
let windows_on_foc_tags = output.with_state(|state| {
|
||||||
let focused_tags = state.focused_tags().collect::<Vec<_>>();
|
let focused_tags = state.focused_tags().collect::<Vec<_>>();
|
||||||
self.pinnacle
|
self.windows
|
||||||
.windows
|
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|win| !win.is_x11_override_redirect())
|
.filter(|win| !win.is_x11_override_redirect())
|
||||||
.filter(|win| {
|
.filter(|win| {
|
||||||
|
@ -230,14 +221,12 @@ impl State {
|
||||||
output.with_state(|state| state.focused_tags().map(|tag| tag.id().0).collect());
|
output.with_state(|state| state.focused_tags().map(|tag| tag.id().0).collect());
|
||||||
|
|
||||||
let id = self
|
let id = self
|
||||||
.pinnacle
|
|
||||||
.layout_state
|
.layout_state
|
||||||
.id_maps
|
.id_maps
|
||||||
.entry(output.clone())
|
.entry(output.clone())
|
||||||
.or_insert(LayoutRequestId(0));
|
.or_insert(LayoutRequestId(0));
|
||||||
|
|
||||||
self.pinnacle
|
self.layout_state
|
||||||
.layout_state
|
|
||||||
.pending_requests
|
.pending_requests
|
||||||
.entry(output.clone())
|
.entry(output.clone())
|
||||||
.or_default()
|
.or_default()
|
||||||
|
@ -255,7 +244,9 @@ impl State {
|
||||||
|
|
||||||
*id = LayoutRequestId(id.0 + 1);
|
*id = LayoutRequestId(id.0 + 1);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl State {
|
||||||
pub fn apply_layout(&mut self, geometries: Geometries) -> anyhow::Result<()> {
|
pub fn apply_layout(&mut self, geometries: Geometries) -> anyhow::Result<()> {
|
||||||
let Geometries {
|
let Geometries {
|
||||||
request_id: Some(request_id),
|
request_id: Some(request_id),
|
||||||
|
@ -267,7 +258,7 @@ impl State {
|
||||||
};
|
};
|
||||||
|
|
||||||
let request_id = LayoutRequestId(request_id);
|
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");
|
anyhow::bail!("Output was invalid");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -321,7 +312,8 @@ impl State {
|
||||||
anyhow::bail!("Attempted to layout but one or more dimensions were null");
|
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);
|
self.schedule_render(&output);
|
||||||
|
|
||||||
|
|
|
@ -131,7 +131,7 @@ async fn main() -> anyhow::Result<()> {
|
||||||
|
|
||||||
event_loop.run(None, &mut state, |state| {
|
event_loop.run(None, &mut state, |state| {
|
||||||
state.update_pointer_focus();
|
state.update_pointer_focus();
|
||||||
state.fixup_z_layering();
|
state.pinnacle.fixup_z_layering();
|
||||||
state.pinnacle.space.refresh();
|
state.pinnacle.space.refresh();
|
||||||
state.pinnacle.popup_manager.cleanup();
|
state.pinnacle.popup_manager.cleanup();
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@ use tracing::info;
|
||||||
use crate::{
|
use crate::{
|
||||||
focus::WindowKeyboardFocusStack,
|
focus::WindowKeyboardFocusStack,
|
||||||
protocol::screencopy::Screencopy,
|
protocol::screencopy::Screencopy,
|
||||||
state::{State, WithState},
|
state::{Pinnacle, WithState},
|
||||||
tag::Tag,
|
tag::Tag,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -26,9 +26,8 @@ pub struct OutputName(pub String);
|
||||||
|
|
||||||
impl OutputName {
|
impl OutputName {
|
||||||
/// Get the output with this name.
|
/// Get the output with this name.
|
||||||
pub fn output(&self, state: &State) -> Option<Output> {
|
pub fn output(&self, pinnacle: &Pinnacle) -> Option<Output> {
|
||||||
state
|
pinnacle
|
||||||
.pinnacle
|
|
||||||
.space
|
.space
|
||||||
.outputs()
|
.outputs()
|
||||||
.find(|output| output.name() == self.0)
|
.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
|
/// A wrapper around [`Output::change_current_state`] that additionally sends an output
|
||||||
/// geometry signal.
|
/// geometry signal.
|
||||||
pub fn change_output_state(
|
pub fn change_output_state(
|
||||||
|
@ -91,8 +90,8 @@ impl State {
|
||||||
output.change_current_state(mode, transform, scale, location);
|
output.change_current_state(mode, transform, scale, location);
|
||||||
if let Some(location) = location {
|
if let Some(location) = location {
|
||||||
info!(?location);
|
info!(?location);
|
||||||
self.pinnacle.space.map_output(output, location);
|
self.space.map_output(output, location);
|
||||||
self.pinnacle.signal_state.output_move.signal(|buf| {
|
self.signal_state.output_move.signal(|buf| {
|
||||||
buf.push_back(OutputMoveResponse {
|
buf.push_back(OutputMoveResponse {
|
||||||
output_name: Some(output.name()),
|
output_name: Some(output.name()),
|
||||||
x: Some(location.x),
|
x: Some(location.x),
|
||||||
|
@ -102,8 +101,8 @@ impl State {
|
||||||
}
|
}
|
||||||
if mode.is_some() || transform.is_some() || scale.is_some() {
|
if mode.is_some() || transform.is_some() || scale.is_some() {
|
||||||
layer_map_for_output(output).arrange();
|
layer_map_for_output(output).arrange();
|
||||||
self.pinnacle.signal_state.output_resize.signal(|buf| {
|
self.signal_state.output_resize.signal(|buf| {
|
||||||
let geo = self.pinnacle.space.output_geometry(output);
|
let geo = self.space.output_geometry(output);
|
||||||
buf.push_back(OutputResizeResponse {
|
buf.push_back(OutputResizeResponse {
|
||||||
output_name: Some(output.name()),
|
output_name: Some(output.name()),
|
||||||
logical_width: geo.map(|geo| geo.size.w as u32),
|
logical_width: geo.map(|geo| geo.size.w as u32),
|
||||||
|
|
18
src/state.rs
18
src/state.rs
|
@ -219,7 +219,7 @@ impl State {
|
||||||
|
|
||||||
std::env::set_var("DISPLAY", format!(":{display}"));
|
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),
|
state.pinnacle.config.dir(&state.pinnacle.xdg_base_dirs),
|
||||||
)) {
|
)) {
|
||||||
panic!("failed to start config: {err}");
|
panic!("failed to start config: {err}");
|
||||||
|
@ -318,18 +318,20 @@ impl State {
|
||||||
|
|
||||||
Ok(state)
|
Ok(state)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Pinnacle {
|
||||||
/// Schedule `run` to run when `condition` returns true.
|
/// Schedule `run` to run when `condition` returns true.
|
||||||
///
|
///
|
||||||
/// This will continually reschedule `run` in the event loop if `condition` returns false.
|
/// This will continually reschedule `run` in the event loop if `condition` returns false.
|
||||||
pub fn schedule<F1, F2>(&self, condition: F1, run: F2)
|
pub fn schedule<F1, F2>(&self, condition: F1, run: F2)
|
||||||
where
|
where
|
||||||
F1: Fn(&mut Self) -> bool + 'static,
|
F1: Fn(&mut State) -> bool + 'static,
|
||||||
F2: FnOnce(&mut Self) + 'static,
|
F2: FnOnce(&mut State) + 'static,
|
||||||
{
|
{
|
||||||
self.pinnacle.loop_handle.insert_idle(|state| {
|
self.loop_handle.insert_idle(|state| {
|
||||||
if !condition(state) {
|
if !condition(state) {
|
||||||
state.schedule(condition, run);
|
state.pinnacle.schedule(condition, run);
|
||||||
} else {
|
} else {
|
||||||
run(state);
|
run(state);
|
||||||
}
|
}
|
||||||
|
@ -338,11 +340,11 @@ impl State {
|
||||||
|
|
||||||
pub fn shutdown(&mut self) {
|
pub fn shutdown(&mut self) {
|
||||||
info!("Shutting down Pinnacle");
|
info!("Shutting down Pinnacle");
|
||||||
self.pinnacle.loop_signal.stop();
|
self.loop_signal.stop();
|
||||||
if let Some(join_handle) = self.pinnacle.config.config_join_handle.take() {
|
if let Some(join_handle) = self.config.config_join_handle.take() {
|
||||||
join_handle.abort();
|
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 {})) {
|
if let Err(err) = shutdown_sender.send(Ok(ShutdownWatchResponse {})) {
|
||||||
warn!("Failed to send shutdown signal to config: {err}");
|
warn!("Failed to send shutdown signal to config: {err}");
|
||||||
}
|
}
|
||||||
|
|
12
src/tag.rs
12
src/tag.rs
|
@ -9,7 +9,7 @@ use std::{
|
||||||
|
|
||||||
use smithay::output::Output;
|
use smithay::output::Output;
|
||||||
|
|
||||||
use crate::state::{State, WithState};
|
use crate::state::{Pinnacle, State, WithState};
|
||||||
|
|
||||||
static TAG_ID_COUNTER: AtomicU32 = AtomicU32::new(0);
|
static TAG_ID_COUNTER: AtomicU32 = AtomicU32::new(0);
|
||||||
|
|
||||||
|
@ -24,9 +24,8 @@ impl TagId {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the tag associated with this id.
|
/// Get the tag associated with this id.
|
||||||
pub fn tag(&self, state: &State) -> Option<Tag> {
|
pub fn tag(&self, pinnacle: &Pinnacle) -> Option<Tag> {
|
||||||
state
|
pinnacle
|
||||||
.pinnacle
|
|
||||||
.space
|
.space
|
||||||
.outputs()
|
.outputs()
|
||||||
.flat_map(|op| op.with_state(|state| state.tags.clone()))
|
.flat_map(|op| op.with_state(|state| state.tags.clone()))
|
||||||
|
@ -107,9 +106,8 @@ impl Tag {
|
||||||
/// Get the output this tag is on.
|
/// Get the output this tag is on.
|
||||||
///
|
///
|
||||||
/// RefCell Safety: This uses RefCells on every mapped output.
|
/// RefCell Safety: This uses RefCells on every mapped output.
|
||||||
pub fn output(&self, state: &State) -> Option<Output> {
|
pub fn output(&self, pinnacle: &Pinnacle) -> Option<Output> {
|
||||||
state
|
pinnacle
|
||||||
.pinnacle
|
|
||||||
.space
|
.space
|
||||||
.outputs()
|
.outputs()
|
||||||
.find(|output| output.with_state(|state| state.tags.iter().any(|tg| tg == self)))
|
.find(|output| output.with_state(|state| state.tags.iter().any(|tg| tg == self)))
|
||||||
|
|
|
@ -12,7 +12,7 @@ use smithay::{
|
||||||
wayland::{compositor, seat::WaylandFocus, shell::xdg::XdgToplevelSurfaceData},
|
wayland::{compositor, seat::WaylandFocus, shell::xdg::XdgToplevelSurfaceData},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::state::{State, WithState};
|
use crate::state::{Pinnacle, WithState};
|
||||||
|
|
||||||
use self::window_state::WindowElementState;
|
use self::window_state::WindowElementState;
|
||||||
|
|
||||||
|
@ -103,8 +103,8 @@ impl WindowElement {
|
||||||
/// This method gets the first tag the window has and returns its output.
|
/// 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.
|
/// RefCell Safety: This method uses a [`RefCell`] on this window and every mapped output.
|
||||||
pub fn output(&self, state: &State) -> Option<Output> {
|
pub fn output(&self, pinnacle: &Pinnacle) -> Option<Output> {
|
||||||
self.with_state(|st| st.tags.first().and_then(|tag| tag.output(state)))
|
self.with_state(|st| st.tags.first().and_then(|tag| tag.output(pinnacle)))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns whether or not this window has an active tag.
|
/// 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].
|
/// Returns the [Window] associated with a given [WlSurface].
|
||||||
pub fn window_for_surface(&self, surface: &WlSurface) -> Option<WindowElement> {
|
pub fn window_for_surface(&self, surface: &WlSurface) -> Option<WindowElement> {
|
||||||
self.pinnacle
|
self.space
|
||||||
.space
|
|
||||||
.elements()
|
.elements()
|
||||||
.find(|window| window.wl_surface().map(|s| s == *surface).unwrap_or(false))
|
.find(|window| window.wl_surface().map(|s| s == *surface).unwrap_or(false))
|
||||||
.or_else(|| {
|
.or_else(|| {
|
||||||
self.pinnacle
|
self.windows
|
||||||
.windows
|
|
||||||
.iter()
|
.iter()
|
||||||
.find(|&win| win.wl_surface().is_some_and(|surf| &surf == surface))
|
.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].
|
/// Currently only used in `ensure_initial_configure` in [`handlers`][crate::handlers].
|
||||||
pub fn new_window_for_surface(&self, surface: &WlSurface) -> Option<WindowElement> {
|
pub fn new_window_for_surface(&self, surface: &WlSurface) -> Option<WindowElement> {
|
||||||
self.pinnacle
|
self.new_windows
|
||||||
.new_windows
|
|
||||||
.iter()
|
.iter()
|
||||||
.find(|&win| win.wl_surface().is_some_and(|surf| &surf == surface))
|
.find(|&win| win.wl_surface().is_some_and(|surf| &surf == surface))
|
||||||
.cloned()
|
.cloned()
|
||||||
|
|
|
@ -4,7 +4,7 @@ use smithay::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
state::{State, WithState},
|
state::{Pinnacle, WithState},
|
||||||
window::window_state,
|
window::window_state,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -41,11 +41,16 @@ enum AllOrAny {
|
||||||
|
|
||||||
impl WindowRuleCondition {
|
impl WindowRuleCondition {
|
||||||
/// RefCell Safety: This method uses RefCells on `window`.
|
/// RefCell Safety: This method uses RefCells on `window`.
|
||||||
pub fn is_met(&self, state: &State, window: &WindowElement) -> bool {
|
pub fn is_met(&self, pinnacle: &Pinnacle, window: &WindowElement) -> bool {
|
||||||
Self::is_met_inner(self, state, window, AllOrAny::All)
|
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:#?}");
|
tracing::debug!("{self:#?}");
|
||||||
|
|
||||||
let WindowRuleCondition {
|
let WindowRuleCondition {
|
||||||
|
@ -61,14 +66,14 @@ impl WindowRuleCondition {
|
||||||
let cond_any = if let Some(cond_any) = cond_any {
|
let cond_any = if let Some(cond_any) = cond_any {
|
||||||
cond_any
|
cond_any
|
||||||
.iter()
|
.iter()
|
||||||
.any(|cond| Self::is_met_inner(cond, state, window, AllOrAny::Any))
|
.any(|cond| Self::is_met_inner(cond, pinnacle, window, AllOrAny::Any))
|
||||||
} else {
|
} else {
|
||||||
true
|
true
|
||||||
};
|
};
|
||||||
let cond_all = if let Some(cond_all) = cond_all {
|
let cond_all = if let Some(cond_all) = cond_all {
|
||||||
cond_all
|
cond_all
|
||||||
.iter()
|
.iter()
|
||||||
.all(|cond| Self::is_met_inner(cond, state, window, AllOrAny::All))
|
.all(|cond| Self::is_met_inner(cond, pinnacle, window, AllOrAny::All))
|
||||||
} else {
|
} else {
|
||||||
true
|
true
|
||||||
};
|
};
|
||||||
|
@ -87,7 +92,7 @@ impl WindowRuleCondition {
|
||||||
true
|
true
|
||||||
};
|
};
|
||||||
let tags = if let Some(tag_ids) = tag {
|
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)))
|
tags.all(|tag| window.with_state(|state| state.tags.contains(&tag)))
|
||||||
} else {
|
} else {
|
||||||
true
|
true
|
||||||
|
@ -100,14 +105,14 @@ impl WindowRuleCondition {
|
||||||
let cond_any = if let Some(cond_any) = cond_any {
|
let cond_any = if let Some(cond_any) = cond_any {
|
||||||
cond_any
|
cond_any
|
||||||
.iter()
|
.iter()
|
||||||
.any(|cond| Self::is_met_inner(cond, state, window, AllOrAny::Any))
|
.any(|cond| Self::is_met_inner(cond, pinnacle, window, AllOrAny::Any))
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
};
|
};
|
||||||
let cond_all = if let Some(cond_all) = cond_all {
|
let cond_all = if let Some(cond_all) = cond_all {
|
||||||
cond_all
|
cond_all
|
||||||
.iter()
|
.iter()
|
||||||
.all(|cond| Self::is_met_inner(cond, state, window, AllOrAny::All))
|
.all(|cond| Self::is_met_inner(cond, pinnacle, window, AllOrAny::All))
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
};
|
};
|
||||||
|
@ -126,7 +131,7 @@ impl WindowRuleCondition {
|
||||||
false
|
false
|
||||||
};
|
};
|
||||||
let tags = if let Some(tag_ids) = tag {
|
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)))
|
tags.any(|tag| window.with_state(|state| state.tags.contains(&tag)))
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
|
@ -167,10 +172,10 @@ pub enum FloatingOrTiled {
|
||||||
Tiled,
|
Tiled,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl State {
|
impl Pinnacle {
|
||||||
pub fn apply_window_rules(&mut self, window: &WindowElement) {
|
pub fn apply_window_rules(&mut self, window: &WindowElement) {
|
||||||
tracing::debug!("Applying window rules");
|
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) {
|
if cond.is_met(self, window) {
|
||||||
let WindowRule {
|
let WindowRule {
|
||||||
output,
|
output,
|
||||||
|
@ -253,7 +258,7 @@ impl State {
|
||||||
state.floating_or_tiled =
|
state.floating_or_tiled =
|
||||||
window_state::FloatingOrTiled::Floating(rect)
|
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) => {
|
window_state::FloatingOrTiled::Tiled(rect) => {
|
||||||
// If the window is tiled, don't set the size. Instead, set
|
// If the window is tiled, don't set the size. Instead, set
|
||||||
|
|
|
@ -9,7 +9,7 @@ use smithay::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
state::{State, WithState},
|
state::{Pinnacle, WithState},
|
||||||
tag::Tag,
|
tag::Tag,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -28,9 +28,8 @@ impl WindowId {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the window that has this WindowId.
|
/// Get the window that has this WindowId.
|
||||||
pub fn window(&self, state: &State) -> Option<WindowElement> {
|
pub fn window(&self, pinnacle: &Pinnacle) -> Option<WindowElement> {
|
||||||
state
|
pinnacle
|
||||||
.pinnacle
|
|
||||||
.windows
|
.windows
|
||||||
.iter()
|
.iter()
|
||||||
.find(|win| win.with_state(|state| &state.id == self))
|
.find(|win| win.with_state(|state| &state.id == self))
|
||||||
|
|
|
@ -43,7 +43,7 @@ where
|
||||||
|
|
||||||
let tempdir = tempfile::tempdir()?;
|
let tempdir = tempfile::tempdir()?;
|
||||||
|
|
||||||
state.start_grpc_server(tempdir.path())?;
|
state.pinnacle.start_grpc_server(tempdir.path())?;
|
||||||
|
|
||||||
let loop_signal = event_loop.get_signal();
|
let loop_signal = event_loop.get_signal();
|
||||||
|
|
||||||
|
@ -54,7 +54,7 @@ where
|
||||||
});
|
});
|
||||||
|
|
||||||
event_loop.run(None, &mut state, |state| {
|
event_loop.run(None, &mut state, |state| {
|
||||||
state.fixup_z_layering();
|
state.pinnacle.fixup_z_layering();
|
||||||
state.pinnacle.space.refresh();
|
state.pinnacle.space.refresh();
|
||||||
state.pinnacle.popup_manager.cleanup();
|
state.pinnacle.popup_manager.cleanup();
|
||||||
|
|
||||||
|
|
|
@ -456,7 +456,7 @@ mod output {
|
||||||
sleep_secs(1);
|
sleep_secs(1);
|
||||||
|
|
||||||
with_state(&sender, |state| {
|
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);
|
assert_eq!(op.current_transform(), smithay::utils::Transform::Flipped90);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -467,7 +467,7 @@ mod output {
|
||||||
sleep_secs(1);
|
sleep_secs(1);
|
||||||
|
|
||||||
with_state(&sender, |state| {
|
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);
|
assert_eq!(op.current_transform(), smithay::utils::Transform::Normal);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -538,9 +538,9 @@ mod output {
|
||||||
sleep_secs(1);
|
sleep_secs(1);
|
||||||
|
|
||||||
with_state(&sender, |state| {
|
with_state(&sender, |state| {
|
||||||
state.new_output("First", (300, 200).into());
|
state.pinnacle.new_output("First", (300, 200).into());
|
||||||
state.new_output("Second", (300, 200).into());
|
state.pinnacle.new_output("Second", (300, 200).into());
|
||||||
state.new_output("Test Third", (300, 200).into());
|
state.pinnacle.new_output("Test Third", (300, 200).into());
|
||||||
});
|
});
|
||||||
|
|
||||||
sleep_secs(1);
|
sleep_secs(1);
|
||||||
|
@ -608,7 +608,7 @@ mod output {
|
||||||
sleep_secs(1);
|
sleep_secs(1);
|
||||||
|
|
||||||
with_state(&sender, |state| {
|
with_state(&sender, |state| {
|
||||||
state.new_output("First", (300, 200).into());
|
state.pinnacle.new_output("First", (300, 200).into());
|
||||||
});
|
});
|
||||||
|
|
||||||
sleep_secs(1);
|
sleep_secs(1);
|
||||||
|
@ -643,7 +643,7 @@ mod output {
|
||||||
sleep_secs(1);
|
sleep_secs(1);
|
||||||
|
|
||||||
with_state(&sender, |state| {
|
with_state(&sender, |state| {
|
||||||
state.new_output("First", (300, 200).into());
|
state.pinnacle.new_output("First", (300, 200).into());
|
||||||
});
|
});
|
||||||
|
|
||||||
sleep_secs(1);
|
sleep_secs(1);
|
||||||
|
@ -664,7 +664,7 @@ mod output {
|
||||||
Rectangle::from_loc_and_size((1920, 0), (300, 200))
|
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);
|
sleep_secs(1);
|
||||||
|
@ -714,9 +714,9 @@ mod output {
|
||||||
sleep_secs(1);
|
sleep_secs(1);
|
||||||
|
|
||||||
with_state(&sender, |state| {
|
with_state(&sender, |state| {
|
||||||
state.new_output("First", (300, 200).into());
|
state.pinnacle.new_output("First", (300, 200).into());
|
||||||
state.new_output("Second", (300, 700).into());
|
state.pinnacle.new_output("Second", (300, 700).into());
|
||||||
state.new_output("Third", (300, 400).into());
|
state.pinnacle.new_output("Third", (300, 400).into());
|
||||||
});
|
});
|
||||||
|
|
||||||
sleep_secs(1);
|
sleep_secs(1);
|
||||||
|
@ -749,7 +749,7 @@ mod output {
|
||||||
Rectangle::from_loc_and_size((0, 1080 + 200 + 700), (300, 400))
|
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);
|
sleep_secs(1);
|
||||||
|
@ -841,7 +841,8 @@ async fn spawned_window_on_active_tag_has_keyboard_focus() -> anyhow::Result<()>
|
||||||
with_state(&sender, |state| {
|
with_state(&sender, |state| {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
state
|
state
|
||||||
.focused_window(state.focused_output().unwrap())
|
.pinnacle
|
||||||
|
.focused_window(state.pinnacle.focused_output().unwrap())
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.class(),
|
.class(),
|
||||||
Some("foot".to_string())
|
Some("foot".to_string())
|
||||||
|
@ -864,7 +865,12 @@ async fn spawned_window_on_inactive_tag_does_not_have_keyboard_focus() -> anyhow
|
||||||
sleep_secs(1);
|
sleep_secs(1);
|
||||||
|
|
||||||
with_state(&sender, |state| {
|
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(())
|
Ok(())
|
||||||
|
|
|
@ -69,9 +69,9 @@ mod output {
|
||||||
sleep_secs(1);
|
sleep_secs(1);
|
||||||
|
|
||||||
with_state(&sender, |state| {
|
with_state(&sender, |state| {
|
||||||
state.new_output("First", (300, 200).into());
|
state.pinnacle.new_output("First", (300, 200).into());
|
||||||
state.new_output("Second", (300, 200).into());
|
state.pinnacle.new_output("Second", (300, 200).into());
|
||||||
state.new_output("Test Third", (300, 200).into());
|
state.pinnacle.new_output("Test Third", (300, 200).into());
|
||||||
});
|
});
|
||||||
|
|
||||||
sleep_secs(1);
|
sleep_secs(1);
|
||||||
|
@ -151,7 +151,7 @@ mod output {
|
||||||
sleep_secs(1);
|
sleep_secs(1);
|
||||||
|
|
||||||
with_state(&sender, |state| {
|
with_state(&sender, |state| {
|
||||||
state.new_output("First", (300, 200).into());
|
state.pinnacle.new_output("First", (300, 200).into());
|
||||||
});
|
});
|
||||||
|
|
||||||
sleep_secs(1);
|
sleep_secs(1);
|
||||||
|
@ -172,7 +172,7 @@ mod output {
|
||||||
Rectangle::from_loc_and_size((1920, 0), (300, 200))
|
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);
|
sleep_secs(1);
|
||||||
|
@ -249,9 +249,9 @@ mod output {
|
||||||
sleep_secs(1);
|
sleep_secs(1);
|
||||||
|
|
||||||
with_state(&sender, |state| {
|
with_state(&sender, |state| {
|
||||||
state.new_output("First", (300, 200).into());
|
state.pinnacle.new_output("First", (300, 200).into());
|
||||||
state.new_output("Second", (300, 700).into());
|
state.pinnacle.new_output("Second", (300, 700).into());
|
||||||
state.new_output("Third", (300, 400).into());
|
state.pinnacle.new_output("Third", (300, 400).into());
|
||||||
});
|
});
|
||||||
|
|
||||||
sleep_secs(1);
|
sleep_secs(1);
|
||||||
|
@ -284,7 +284,7 @@ mod output {
|
||||||
Rectangle::from_loc_and_size((0, 1080 + 200 + 700), (300, 400))
|
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);
|
sleep_secs(1);
|
||||||
|
@ -335,7 +335,7 @@ mod output {
|
||||||
sleep_secs(1);
|
sleep_secs(1);
|
||||||
|
|
||||||
with_state(&sender, |state| {
|
with_state(&sender, |state| {
|
||||||
let op = state.focused_output().unwrap();
|
let op = state.pinnacle.focused_output().unwrap();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
op.current_transform(),
|
op.current_transform(),
|
||||||
smithay::utils::Transform::Flipped270
|
smithay::utils::Transform::Flipped270
|
||||||
|
@ -352,7 +352,7 @@ mod output {
|
||||||
sleep_secs(1);
|
sleep_secs(1);
|
||||||
|
|
||||||
with_state(&sender, |state| {
|
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);
|
assert_eq!(op.current_transform(), smithay::utils::Transform::_180);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use pinnacle::state::State;
|
use pinnacle::state::Pinnacle;
|
||||||
mod inner {
|
mod inner {
|
||||||
use pinnacle_api::layout::{CyclingLayoutManager, MasterStackLayout};
|
use pinnacle_api::layout::{CyclingLayoutManager, MasterStackLayout};
|
||||||
use pinnacle_api::window::rules::{WindowRule, WindowRuleCondition};
|
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 temp_dir = tempfile::tempdir().expect("failed to setup temp dir for socket");
|
||||||
let socket_dir = temp_dir.path().to_owned();
|
let socket_dir = temp_dir.path().to_owned();
|
||||||
state
|
pinnacle
|
||||||
.start_wlcs_config(&socket_dir, move || {
|
.start_wlcs_config(&socket_dir, move || {
|
||||||
inner::start_config();
|
inner::start_config();
|
||||||
drop(temp_dir);
|
drop(temp_dir);
|
||||||
|
|
|
@ -47,7 +47,7 @@ pub(crate) fn run(channel: Channel<WlcsEvent>) {
|
||||||
// when xdiplay is None when starting the config, the grpc server is not
|
// when xdiplay is None when starting the config, the grpc server is not
|
||||||
// started, until it is set; this bypasses this for now
|
// started, until it is set; this bypasses this for now
|
||||||
state.pinnacle.xdisplay = Some(u32::MAX);
|
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
|
// wait for the config to connect to the layout service
|
||||||
while state.pinnacle.layout_state.layout_request_sender.is_none() {
|
while state.pinnacle.layout_state.layout_request_sender.is_none() {
|
||||||
|
@ -59,7 +59,7 @@ pub(crate) fn run(channel: Channel<WlcsEvent>) {
|
||||||
event_loop
|
event_loop
|
||||||
.run(None, &mut state, |state| {
|
.run(None, &mut state, |state| {
|
||||||
state.update_pointer_focus();
|
state.update_pointer_focus();
|
||||||
state.fixup_z_layering();
|
state.pinnacle.fixup_z_layering();
|
||||||
state.pinnacle.space.refresh();
|
state.pinnacle.space.refresh();
|
||||||
state.pinnacle.popup_manager.cleanup();
|
state.pinnacle.popup_manager.cleanup();
|
||||||
|
|
||||||
|
@ -75,7 +75,7 @@ pub(crate) fn run(channel: Channel<WlcsEvent>) {
|
||||||
fn handle_event(event: WlcsEvent, state: &mut State) {
|
fn handle_event(event: WlcsEvent, state: &mut State) {
|
||||||
tracing::debug!("handle_event {:?}", event);
|
tracing::debug!("handle_event {:?}", event);
|
||||||
match event {
|
match event {
|
||||||
WlcsEvent::Stop => state.shutdown(),
|
WlcsEvent::Stop => state.pinnacle.shutdown(),
|
||||||
WlcsEvent::NewClient { stream, client_id } => {
|
WlcsEvent::NewClient { stream, client_id } => {
|
||||||
let client: Client = state
|
let client: Client = state
|
||||||
.pinnacle
|
.pinnacle
|
||||||
|
|
Loading…
Reference in a new issue