state: Move shell behind RwLock

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

View file

@ -1,4 +1,4 @@
use smithay::wayland::seat::WaylandFocus;
use smithay::{input::pointer::MotionEvent, utils::SERIAL_COUNTER, wayland::seat::WaylandFocus};
use crate::{
config::{Action, StaticConfig},
@ -6,7 +6,7 @@ use crate::{
shell::{
element::{CosmicMapped, CosmicWindow},
grabs::ReleaseMode,
CosmicSurface, Shell,
CosmicSurface, PointGlobalExt, Shell,
},
state::State,
utils::{prelude::SeatExt, screenshot::screenshot_window},
@ -15,61 +15,57 @@ use crate::{
use super::{Item, ResizeEdge};
fn toggle_stacking(state: &mut State, mapped: &CosmicMapped) {
let seat = state.common.shell.seats.last_active().clone();
if let Some(new_focus) = state.common.shell.toggle_stacking(mapped) {
let mut shell = state.common.shell.write().unwrap();
let seat = shell.seats.last_active().clone();
if let Some(new_focus) = shell.toggle_stacking(mapped) {
std::mem::drop(shell);
Shell::set_focus(state, Some(&new_focus), &seat, None);
}
}
fn move_prev_workspace(state: &mut State, mapped: &CosmicMapped) {
let seat = state.common.shell.seats.last_active().clone();
let mut shell = state.common.shell.write().unwrap();
let seat = shell.seats.last_active().clone();
let (current_handle, output) = {
let Some(ws) = state.common.shell.space_for(mapped) else {
let Some(ws) = shell.space_for(mapped) else {
return;
};
(ws.handle, ws.output.clone())
};
let maybe_handle = state
.common
.shell
let maybe_handle = shell
.workspaces
.spaces_for_output(&output)
.enumerate()
.find_map(|(i, space)| (space.handle == current_handle).then_some(i))
.and_then(|i| i.checked_sub(1))
.and_then(|i| {
state
.common
.shell
.workspaces
.get(i, &output)
.map(|s| s.handle)
});
.and_then(|i| shell.workspaces.get(i, &output).map(|s| s.handle));
if let Some(prev_handle) = maybe_handle {
if let Some((target, _)) = state.common.shell.move_window(
let res = shell.move_window(
Some(&seat),
mapped,
&current_handle,
&prev_handle,
true,
None,
) {
&mut state.common.workspace_state.update(),
);
if let Some((target, _)) = res {
std::mem::drop(shell);
Shell::set_focus(state, Some(&target), &seat, None);
}
}
}
fn move_next_workspace(state: &mut State, mapped: &CosmicMapped) {
let seat = state.common.shell.seats.last_active().clone();
let mut shell = state.common.shell.write().unwrap();
let seat = shell.seats.last_active().clone();
let (current_handle, output) = {
let Some(ws) = state.common.shell.space_for(mapped) else {
let Some(ws) = shell.space_for(mapped) else {
return;
};
(ws.handle, ws.output.clone())
};
let maybe_handle = state
.common
.shell
let maybe_handle = shell
.workspaces
.spaces_for_output(&output)
.skip_while(|space| space.handle != current_handle)
@ -77,14 +73,17 @@ fn move_next_workspace(state: &mut State, mapped: &CosmicMapped) {
.next()
.map(|space| space.handle);
if let Some(next_handle) = maybe_handle {
if let Some((target, _point)) = state.common.shell.move_window(
let res = shell.move_window(
Some(&seat),
mapped,
&current_handle,
&next_handle,
true,
None,
) {
&mut state.common.workspace_state.update(),
);
if let Some((target, _point)) = res {
std::mem::drop(shell);
Shell::set_focus(state, Some(&target), &seat, None)
}
}
@ -114,9 +113,10 @@ pub fn tab_items(
)
.into();
let seat = state.common.shell.seats.last_active();
let mut shell = state.common.shell.write().unwrap();
let seat = shell.seats.last_active().clone();
let output = seat.active_output();
let workspace = state.common.shell.workspaces.active_mut(&output);
let workspace = shell.workspaces.active_mut(&output);
if is_tiled {
for mapped in workspace
.mapped()
@ -127,7 +127,7 @@ pub fn tab_items(
{
workspace.unmaximize_request(&mapped);
}
let focus_stack = workspace.focus_stack.get(seat);
let focus_stack = workspace.focus_stack.get(&seat);
workspace
.tiling_layer
.map(mapped, Some(focus_stack.iter()), None);
@ -197,7 +197,12 @@ pub fn window_items(
Item::new(fl!("window-menu-minimize"), move |handle| {
let mapped = minimize_clone.clone();
let _ = handle.insert_idle(move |state| {
state.common.shell.minimize_request(&mapped);
state
.common
.shell
.write()
.unwrap()
.minimize_request(&mapped);
});
})
.shortcut(config.get_shortcut_for_action(&Action::Minimize)),
@ -206,8 +211,9 @@ pub fn window_items(
Item::new(fl!("window-menu-maximize"), move |handle| {
let mapped = maximize_clone.clone();
let _ = handle.insert_idle(move |state| {
let seat = state.common.shell.seats.last_active().clone();
state.common.shell.maximize_toggle(&mapped, &seat);
let mut shell = state.common.shell.write().unwrap();
let seat = shell.seats.last_active().clone();
shell.maximize_toggle(&mapped, &seat);
});
})
.shortcut(config.get_shortcut_for_action(&Action::Maximize))
@ -217,8 +223,9 @@ pub fn window_items(
Item::new(fl!("window-menu-tiled"), move |handle| {
let tile_clone = tile_clone.clone();
let _ = handle.insert_idle(move |state| {
let seat = state.common.shell.seats.last_active().clone();
if let Some(ws) = state.common.shell.space_for_mut(&tile_clone) {
let mut shell = state.common.shell.write().unwrap();
let seat = shell.seats.last_active().clone();
if let Some(ws) = shell.space_for_mut(&tile_clone) {
ws.toggle_floating_window(&seat, &tile_clone);
}
});
@ -238,8 +245,36 @@ pub fn window_items(
let move_clone = move_clone.clone();
let _ = handle.insert_idle(move |state| {
if let Some(surface) = move_clone.wl_surface() {
let seat = state.common.shell.seats.last_active().clone();
Shell::move_request(state, &surface, &seat, None, ReleaseMode::Click, false);
let mut shell = state.common.shell.write().unwrap();
let seat = shell.seats.last_active().clone();
let res = shell.move_request(
&surface,
&seat,
None,
ReleaseMode::Click,
false,
&state.common.config,
&state.common.event_loop_handle,
&state.common.xdg_activation_state,
);
std::mem::drop(shell);
if let Some((grab, focus)) = res {
if grab.is_touch_grab() {
seat.get_touch().unwrap().set_grab(
state,
grab,
SERIAL_COUNTER.next_serial(),
)
} else {
seat.get_pointer().unwrap().set_grab(
state,
grab,
SERIAL_COUNTER.next_serial(),
focus,
);
}
}
}
});
})),
@ -249,32 +284,122 @@ pub fn window_items(
Item::new(fl!("window-menu-resize-edge-top"), move |handle| {
let resize_clone = resize_top_clone.clone();
let _ = handle.insert_idle(move |state| {
let seat = state.common.shell.seats.last_active().clone();
Shell::menu_resize_request(state, &resize_clone, &seat, ResizeEdge::TOP);
let mut shell = state.common.shell.write().unwrap();
let seat = shell.seats.last_active().clone();
let res = shell.menu_resize_request(&resize_clone, &seat, ResizeEdge::TOP);
std::mem::drop(shell);
if let Some(((target, loc), (grab, focus))) = res {
let serial = SERIAL_COUNTER.next_serial();
if grab.is_touch_grab() {
seat.get_touch().unwrap().set_grab(state, grab, serial);
} else {
let pointer = seat.get_pointer().unwrap();
pointer.motion(
state,
target,
&MotionEvent {
location: loc.as_logical().to_f64(),
serial,
time: 0,
},
);
pointer.frame(state);
pointer.set_grab(state, grab, serial, focus);
}
}
});
})
.disabled(!possible_resizes.contains(ResizeEdge::TOP)),
Item::new(fl!("window-menu-resize-edge-left"), move |handle| {
let resize_clone = resize_left_clone.clone();
let _ = handle.insert_idle(move |state| {
let seat = state.common.shell.seats.last_active().clone();
Shell::menu_resize_request(state, &resize_clone, &seat, ResizeEdge::LEFT);
let mut shell = state.common.shell.write().unwrap();
let seat = shell.seats.last_active().clone();
let res = shell.menu_resize_request(&resize_clone, &seat, ResizeEdge::LEFT);
std::mem::drop(shell);
if let Some(((target, loc), (grab, focus))) = res {
let serial = SERIAL_COUNTER.next_serial();
if grab.is_touch_grab() {
seat.get_touch().unwrap().set_grab(state, grab, serial);
} else {
let pointer = seat.get_pointer().unwrap();
pointer.motion(
state,
target,
&MotionEvent {
location: loc.as_logical().to_f64(),
serial,
time: 0,
},
);
pointer.frame(state);
pointer.set_grab(state, grab, serial, focus);
}
}
});
})
.disabled(!possible_resizes.contains(ResizeEdge::LEFT)),
Item::new(fl!("window-menu-resize-edge-right"), move |handle| {
let resize_clone = resize_right_clone.clone();
let _ = handle.insert_idle(move |state| {
let seat = state.common.shell.seats.last_active().clone();
Shell::menu_resize_request(state, &resize_clone, &seat, ResizeEdge::RIGHT);
let mut shell = state.common.shell.write().unwrap();
let seat = shell.seats.last_active().clone();
let res =
shell.menu_resize_request(&resize_clone, &seat, ResizeEdge::RIGHT);
std::mem::drop(shell);
if let Some(((target, loc), (grab, focus))) = res {
let serial = SERIAL_COUNTER.next_serial();
if grab.is_touch_grab() {
seat.get_touch().unwrap().set_grab(state, grab, serial);
} else {
let pointer = seat.get_pointer().unwrap();
pointer.motion(
state,
target,
&MotionEvent {
location: loc.as_logical().to_f64(),
serial,
time: 0,
},
);
pointer.frame(state);
pointer.set_grab(state, grab, serial, focus);
}
}
});
})
.disabled(!possible_resizes.contains(ResizeEdge::RIGHT)),
Item::new(fl!("window-menu-resize-edge-bottom"), move |handle| {
let resize_clone = resize_bottom_clone.clone();
let _ = handle.insert_idle(move |state| {
let seat = state.common.shell.seats.last_active().clone();
Shell::menu_resize_request(state, &resize_clone, &seat, ResizeEdge::BOTTOM);
let mut shell = state.common.shell.write().unwrap();
let seat = shell.seats.last_active().clone();
let res =
shell.menu_resize_request(&resize_clone, &seat, ResizeEdge::BOTTOM);
std::mem::drop(shell);
if let Some(((target, loc), (grab, focus))) = res {
let serial = SERIAL_COUNTER.next_serial();
if grab.is_touch_grab() {
seat.get_touch().unwrap().set_grab(state, grab, serial);
} else {
let pointer = seat.get_pointer().unwrap();
pointer.motion(
state,
target,
&MotionEvent {
location: loc.as_logical().to_f64(),
serial,
time: 0,
},
);
pointer.frame(state);
pointer.set_grab(state, grab, serial, focus);
}
}
});
})
.disabled(!possible_resizes.contains(ResizeEdge::BOTTOM)),
@ -301,8 +426,9 @@ pub fn window_items(
Item::new(fl!("window-menu-sticky"), move |handle| {
let mapped = sticky_clone.clone();
let _ = handle.insert_idle(move |state| {
let seat = state.common.shell.seats.last_active().clone();
state.common.shell.toggle_sticky(&seat, &mapped);
let mut shell = state.common.shell.write().unwrap();
let seat = shell.seats.last_active().clone();
shell.toggle_sticky(&seat, &mapped);
});
})
.toggled(is_sticky),

View file

@ -216,7 +216,14 @@ impl Program for ContextMenu {
if let Some(Item::Submenu { items, .. }) = self.items.get_mut(idx) {
let items = items.clone();
let _ = loop_handle.insert_idle(move |state| {
let seat = state.common.shell.seats.last_active();
let seat = state
.common
.shell
.read()
.unwrap()
.seats
.last_active()
.clone();
let grab_state = seat
.user_data()
.get::<SeatMenuGrabState>()
@ -301,7 +308,14 @@ impl Program for ContextMenu {
Message::ItemLeft(idx, _) => {
if let Some(Item::Submenu { .. }) = self.items.get_mut(idx) {
let _ = loop_handle.insert_idle(|state| {
let seat = state.common.shell.seats.last_active();
let seat = state
.common
.shell
.read()
.unwrap()
.seats
.last_active()
.clone();
let grab_state = seat
.user_data()
.get::<SeatMenuGrabState>()

View file

@ -153,6 +153,15 @@ impl From<ResizeForkGrab> for ResizeGrab {
}
}
impl ResizeGrab {
pub fn is_touch_grab(&self) -> bool {
match self {
ResizeGrab::Floating(grab) => grab.is_touch_grab(),
ResizeGrab::Tiling(grab) => grab.is_touch_grab(),
}
}
}
impl PointerGrab<State> for ResizeGrab {
fn motion(
&mut self,

View file

@ -16,6 +16,7 @@ use crate::{
CosmicMapped, CosmicSurface, Direction, ManagedLayer,
},
utils::prelude::*,
wayland::protocols::toplevel_info::{toplevel_enter_output, toplevel_enter_workspace},
};
use calloop::LoopHandle;
@ -326,10 +327,10 @@ pub struct MoveGrab {
impl MoveGrab {
fn update_location(&mut self, state: &mut State, location: Point<f64, Logical>) {
let mut shell = state.common.shell.write().unwrap();
let Some(current_output) =
state
.common
.shell
shell
.outputs()
.find(|output| {
output.geometry().as_logical().overlaps_or_touches(
@ -341,9 +342,7 @@ impl MoveGrab {
return;
};
if self.cursor_output != current_output {
state
.common
.shell
shell
.workspaces
.active_mut(&self.cursor_output)
.tiling_layer
@ -362,7 +361,7 @@ impl MoveGrab {
let mut window_geo = self.window.geometry();
window_geo.loc += location.to_i32_round() + grab_state.window_offset;
for output in state.common.shell.outputs() {
for output in shell.outputs() {
if let Some(overlap) = output.geometry().as_logical().intersection(window_geo) {
if self.window_outputs.insert(output.clone()) {
self.window.output_enter(output, overlap);
@ -380,10 +379,7 @@ impl MoveGrab {
}
}
let indicator_location = state
.common
.shell
.stacking_indicator(&current_output, self.previous);
let indicator_location = shell.stacking_indicator(&current_output, self.previous);
if indicator_location.is_some() != grab_state.stacking_indicator.is_some() {
grab_state.stacking_indicator = indicator_location.map(|geo| {
let element = stack_hover(
@ -695,6 +691,13 @@ impl MoveGrab {
pub fn is_tiling_grab(&self) -> bool {
self.previous == ManagedLayer::Tiling
}
pub fn is_touch_grab(&self) -> bool {
match self.start_data {
GrabStartData::Touch(_) => true,
GrabStartData::Pointer(_) => false,
}
}
}
impl Drop for MoveGrab {
@ -716,23 +719,17 @@ impl Drop for MoveGrab {
if grab_state.window.alive() {
let window_location =
(grab_state.location.to_i32_round() + grab_state.window_offset).as_global();
let mut shell = state.common.shell.write().unwrap();
let workspace_handle = state.common.shell.active_space(&output).handle;
let workspace_handle = shell.active_space(&output).handle;
for old_output in window_outputs.iter().filter(|o| *o != &output) {
grab_state.window.output_leave(old_output);
}
for (window, _) in grab_state.window.windows() {
state
.common
.shell
.toplevel_info_state
.toplevel_enter_output(&window, &output);
toplevel_enter_output(&window, &output);
if previous != ManagedLayer::Sticky {
state
.common
.shell
.toplevel_info_state
.toplevel_enter_workspace(&window, &workspace_handle);
toplevel_enter_workspace(&window, &workspace_handle);
}
}
@ -742,19 +739,15 @@ impl Drop for MoveGrab {
window_location,
grab_state.window.geometry().size.as_global(),
));
let set = state.common.shell.workspaces.sets.get_mut(&output).unwrap();
let set = shell.workspaces.sets.get_mut(&output).unwrap();
let (window, location) = set
.sticky_layer
.drop_window(grab_state.window, window_location.to_local(&output));
Some((window, location.to_global(&output)))
}
ManagedLayer::Tiling
if state.common.shell.active_space(&output).tiling_enabled =>
{
let (window, location) = state
.common
.shell
ManagedLayer::Tiling if shell.active_space(&output).tiling_enabled => {
let (window, location) = shell
.active_space_mut(&output)
.tiling_layer
.drop_window(grab_state.window);
@ -765,8 +758,8 @@ impl Drop for MoveGrab {
window_location,
grab_state.window.geometry().size.as_global(),
));
let theme = state.common.shell.theme.clone();
let workspace = state.common.shell.active_space_mut(&output);
let theme = shell.theme.clone();
let workspace = shell.active_space_mut(&output);
let (window, location) = workspace.floating_layer.drop_window(
grab_state.window,
window_location.to_local(&workspace.output),
@ -775,7 +768,7 @@ impl Drop for MoveGrab {
if previous == ManagedLayer::Floating {
if let Some(sz) = grab_state.snapping_zone {
if sz == SnappingZone::Maximize {
state.common.shell.maximize_toggle(&window, &seat);
shell.maximize_toggle(&window, &seat);
} else {
let directions = match sz {
SnappingZone::Maximize => vec![],