shell: Lift/Refactor (interactive) resize to consider sticky windows
This commit is contained in:
parent
a333753c96
commit
97a13ea515
4 changed files with 101 additions and 73 deletions
|
|
@ -290,17 +290,34 @@ impl ResizeSurfaceGrab {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn apply_resize_to_location(window: CosmicMapped, space: &mut Workspace) {
|
pub fn apply_resize_to_location(window: CosmicMapped, shell: &mut Shell) {
|
||||||
if let Some(location) = space
|
let mut resize_state = window.resize_state.lock().unwrap();
|
||||||
.floating_layer
|
|
||||||
|
if resize_state.is_none() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let (output, floating_layer) = if let Some((output, set)) = shell
|
||||||
|
.workspaces
|
||||||
|
.sets
|
||||||
|
.iter_mut()
|
||||||
|
.find(|(_, set)| set.sticky_layer.mapped().any(|m| m == &window))
|
||||||
|
{
|
||||||
|
(output, &mut set.sticky_layer)
|
||||||
|
} else if let Some(workspace) = shell.space_for_mut(&window) {
|
||||||
|
(&workspace.output, &mut workspace.floating_layer)
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(location) = floating_layer
|
||||||
.space
|
.space
|
||||||
.element_location(&window)
|
.element_location(&window)
|
||||||
.map(PointExt::as_local)
|
.map(PointExt::as_local)
|
||||||
.map(|p| p.to_global(space.output()))
|
.map(|p| p.to_global(output))
|
||||||
{
|
{
|
||||||
let mut new_location = None;
|
let mut new_location = None;
|
||||||
|
|
||||||
let mut resize_state = window.resize_state.lock().unwrap();
|
|
||||||
// If the window is being resized by top or left, its location must be adjusted
|
// If the window is being resized by top or left, its location must be adjusted
|
||||||
// accordingly.
|
// accordingly.
|
||||||
match *resize_state {
|
match *resize_state {
|
||||||
|
|
@ -311,7 +328,7 @@ impl ResizeSurfaceGrab {
|
||||||
initial_window_location,
|
initial_window_location,
|
||||||
initial_window_size,
|
initial_window_size,
|
||||||
} = resize_data;
|
} = resize_data;
|
||||||
let initial_window_location = initial_window_location.to_global(space.output());
|
let initial_window_location = initial_window_location.to_global(output);
|
||||||
|
|
||||||
if edges.intersects(ResizeEdge::TOP_LEFT) {
|
if edges.intersects(ResizeEdge::TOP_LEFT) {
|
||||||
let size = window.geometry().size;
|
let size = window.geometry().size;
|
||||||
|
|
@ -344,7 +361,7 @@ impl ResizeSurfaceGrab {
|
||||||
update_reactive_popups(
|
update_reactive_popups(
|
||||||
&window,
|
&window,
|
||||||
new_location + offset.as_global(),
|
new_location + offset.as_global(),
|
||||||
space.floating_layer.space.outputs(),
|
floating_layer.space.outputs(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
CosmicSurface::X11(surface) => {
|
CosmicSurface::X11(surface) => {
|
||||||
|
|
@ -355,8 +372,7 @@ impl ResizeSurfaceGrab {
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
space
|
floating_layer
|
||||||
.floating_layer
|
|
||||||
.space
|
.space
|
||||||
.map_element(window, new_location.as_logical(), false);
|
.map_element(window, new_location.as_logical(), false);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2479,16 +2479,38 @@ impl Shell {
|
||||||
check_grab_preconditions(&seat, surface, serial, ReleaseMode::NoMouseButtons)
|
check_grab_preconditions(&seat, surface, serial, ReleaseMode::NoMouseButtons)
|
||||||
{
|
{
|
||||||
if let Some(mapped) = state.common.shell.element_for_wl_surface(surface).cloned() {
|
if let Some(mapped) = state.common.shell.element_for_wl_surface(surface).cloned() {
|
||||||
if let Some(workspace) = state.common.shell.space_for_mut(&mapped) {
|
if mapped.is_fullscreen(true) || mapped.is_maximized(true) {
|
||||||
if let Some(grab) = workspace.resize_request(&mapped, &seat, start_data, edges)
|
return;
|
||||||
{
|
}
|
||||||
|
|
||||||
|
let floating_layer = if let Some(set) = state
|
||||||
|
.common
|
||||||
|
.shell
|
||||||
|
.workspaces
|
||||||
|
.sets
|
||||||
|
.values_mut()
|
||||||
|
.find(|set| set.sticky_layer.mapped().any(|m| m == &mapped))
|
||||||
|
{
|
||||||
|
&mut set.sticky_layer
|
||||||
|
} else if let Some(workspace) = state.common.shell.space_for_mut(&mapped) {
|
||||||
|
&mut workspace.floating_layer
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(grab) = floating_layer.resize_request(
|
||||||
|
&mapped,
|
||||||
|
seat,
|
||||||
|
start_data.clone(),
|
||||||
|
edges,
|
||||||
|
ReleaseMode::NoMouseButtons,
|
||||||
|
) {
|
||||||
seat.get_pointer().unwrap().set_grab(
|
seat.get_pointer().unwrap().set_grab(
|
||||||
state,
|
state,
|
||||||
grab,
|
grab,
|
||||||
serial.unwrap_or_else(|| SERIAL_COUNTER.next_serial()),
|
serial.unwrap_or_else(|| SERIAL_COUNTER.next_serial()),
|
||||||
Focus::Clear,
|
Focus::Clear,
|
||||||
);
|
);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -2500,8 +2522,6 @@ impl Shell {
|
||||||
let Some(focused) = seat.get_keyboard().unwrap().current_focus() else {
|
let Some(focused) = seat.get_keyboard().unwrap().current_focus() else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(workspace) = self.workspaces.get_mut(idx, &output) {
|
|
||||||
let amount = (self
|
let amount = (self
|
||||||
.resize_state
|
.resize_state
|
||||||
.take()
|
.take()
|
||||||
|
|
@ -2509,6 +2529,17 @@ impl Shell {
|
||||||
.unwrap_or(10)
|
.unwrap_or(10)
|
||||||
+ 2)
|
+ 2)
|
||||||
.min(20);
|
.min(20);
|
||||||
|
|
||||||
|
if self
|
||||||
|
.workspaces
|
||||||
|
.sets
|
||||||
|
.get_mut(&output)
|
||||||
|
.unwrap()
|
||||||
|
.sticky_layer
|
||||||
|
.resize(&focused, direction, edge, amount)
|
||||||
|
{
|
||||||
|
self.resize_state = Some((focused, direction, edge, amount, idx, output));
|
||||||
|
} else if let Some(workspace) = self.workspaces.get_mut(idx, &output) {
|
||||||
if workspace.resize(&focused, direction, edge, amount) {
|
if workspace.resize(&focused, direction, edge, amount) {
|
||||||
self.resize_state = Some((focused, direction, edge, amount, idx, output));
|
self.resize_state = Some((focused, direction, edge, amount, idx, output));
|
||||||
}
|
}
|
||||||
|
|
@ -2519,18 +2550,25 @@ impl Shell {
|
||||||
if let Some((old_focused, old_direction, old_edge, _, idx, output)) =
|
if let Some((old_focused, old_direction, old_edge, _, idx, output)) =
|
||||||
self.resize_state.take()
|
self.resize_state.take()
|
||||||
{
|
{
|
||||||
let workspace = self.workspaces.get(idx, &output).unwrap();
|
|
||||||
if old_direction == direction && old_edge == edge {
|
if old_direction == direction && old_edge == edge {
|
||||||
let Some(toplevel) = old_focused.toplevel() else {
|
let Some(toplevel) = old_focused.toplevel() else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
let Some(mapped) = workspace
|
let Some(mapped) = self.workspaces.sets.values()
|
||||||
|
.find_map(|set| set.sticky_layer.mapped()
|
||||||
|
.find(|m| m.has_surface(&toplevel, WindowSurfaceType::TOPLEVEL))
|
||||||
|
).cloned()
|
||||||
|
.or_else(|| {
|
||||||
|
let workspace = self.workspaces.get(idx, &output).unwrap();
|
||||||
|
workspace
|
||||||
.mapped()
|
.mapped()
|
||||||
.find(|m| m.has_surface(&toplevel, WindowSurfaceType::TOPLEVEL))
|
.find(|m| m.has_surface(&toplevel, WindowSurfaceType::TOPLEVEL))
|
||||||
.cloned()
|
.cloned()
|
||||||
|
})
|
||||||
else {
|
else {
|
||||||
return;
|
return
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut resize_state = mapped.resize_state.lock().unwrap();
|
let mut resize_state = mapped.resize_state.lock().unwrap();
|
||||||
if let Some(ResizeState::Resizing(data)) = *resize_state {
|
if let Some(ResizeState::Resizing(data)) = *resize_state {
|
||||||
*resize_state = Some(ResizeState::WaitingForCommit(data));
|
*resize_state = Some(ResizeState::WaitingForCommit(data));
|
||||||
|
|
|
||||||
|
|
@ -69,7 +69,7 @@ use super::{
|
||||||
target::{KeyboardFocusTarget, PointerFocusTarget, WindowGroup},
|
target::{KeyboardFocusTarget, PointerFocusTarget, WindowGroup},
|
||||||
FocusDirection, FocusStack, FocusStackMut,
|
FocusDirection, FocusStack, FocusStackMut,
|
||||||
},
|
},
|
||||||
grabs::{ReleaseMode, ResizeEdge, ResizeGrab},
|
grabs::ResizeEdge,
|
||||||
layout::tiling::{Data, NodeDesc},
|
layout::tiling::{Data, NodeDesc},
|
||||||
CosmicMappedRenderElement, CosmicSurface, ResizeDirection, ResizeMode,
|
CosmicMappedRenderElement, CosmicSurface, ResizeDirection, ResizeMode,
|
||||||
};
|
};
|
||||||
|
|
@ -449,34 +449,34 @@ impl Workspace {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn unmaximize_request(&mut self, elem: &CosmicMapped) -> Option<Size<i32, Logical>> {
|
pub fn unmaximize_request(&mut self, elem: &CosmicMapped) -> Option<Size<i32, Logical>> {
|
||||||
let mut state = elem.maximized_state.lock().unwrap();
|
let mut state = elem.maximized_state.lock().unwrap();
|
||||||
if let Some(state) = state.take() {
|
if let Some(state) = state.take() {
|
||||||
match state.original_layer {
|
match state.original_layer {
|
||||||
ManagedLayer::Tiling => {
|
ManagedLayer::Tiling => {
|
||||||
// should still be mapped in tiling
|
// should still be mapped in tiling
|
||||||
self.floating_layer.unmap(&elem);
|
self.floating_layer.unmap(&elem);
|
||||||
elem.output_enter(&self.output, elem.bbox());
|
elem.output_enter(&self.output, elem.bbox());
|
||||||
elem.set_maximized(false);
|
elem.set_maximized(false);
|
||||||
elem.set_geometry(state.original_geometry.to_global(&self.output));
|
elem.set_geometry(state.original_geometry.to_global(&self.output));
|
||||||
elem.configure();
|
elem.configure();
|
||||||
self.tiling_layer.recalculate();
|
self.tiling_layer.recalculate();
|
||||||
self.tiling_layer
|
self.tiling_layer
|
||||||
.element_geometry(&elem)
|
.element_geometry(&elem)
|
||||||
.map(|geo| geo.size.as_logical())
|
.map(|geo| geo.size.as_logical())
|
||||||
}
|
|
||||||
ManagedLayer::Floating => {
|
|
||||||
elem.set_maximized(false);
|
|
||||||
self.floating_layer.map_internal(
|
|
||||||
elem.clone(),
|
|
||||||
Some(state.original_geometry.loc),
|
|
||||||
Some(state.original_geometry.size.as_logical()),
|
|
||||||
);
|
|
||||||
Some(state.original_geometry.size.as_logical())
|
|
||||||
}
|
|
||||||
ManagedLayer::Sticky => unreachable!(),
|
|
||||||
}
|
}
|
||||||
|
ManagedLayer::Floating => {
|
||||||
|
elem.set_maximized(false);
|
||||||
|
self.floating_layer.map_internal(
|
||||||
|
elem.clone(),
|
||||||
|
Some(state.original_geometry.loc),
|
||||||
|
Some(state.original_geometry.size.as_logical()),
|
||||||
|
);
|
||||||
|
Some(state.original_geometry.size.as_logical())
|
||||||
|
}
|
||||||
|
ManagedLayer::Sticky => unreachable!(),
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -595,32 +595,6 @@ impl Workspace {
|
||||||
.map(|f| &f.surface)
|
.map(|f| &f.surface)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn resize_request(
|
|
||||||
&mut self,
|
|
||||||
mapped: &CosmicMapped,
|
|
||||||
seat: &Seat<State>,
|
|
||||||
start_data: PointerGrabStartData<State>,
|
|
||||||
edges: ResizeEdge,
|
|
||||||
) -> Option<ResizeGrab> {
|
|
||||||
if mapped.is_fullscreen(true) || mapped.is_maximized(true) {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
if self.floating_layer.mapped().any(|m| m == mapped) {
|
|
||||||
self.floating_layer
|
|
||||||
.resize_request(
|
|
||||||
mapped,
|
|
||||||
seat,
|
|
||||||
start_data.clone(),
|
|
||||||
edges,
|
|
||||||
ReleaseMode::NoMouseButtons,
|
|
||||||
)
|
|
||||||
.map(Into::into)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn resize(
|
pub fn resize(
|
||||||
&mut self,
|
&mut self,
|
||||||
focused: &KeyboardFocusTarget,
|
focused: &KeyboardFocusTarget,
|
||||||
|
|
|
||||||
|
|
@ -219,11 +219,11 @@ impl CompositorHandler for State {
|
||||||
// We only want to resize once the client has acknoledged & commited the new size,
|
// We only want to resize once the client has acknoledged & commited the new size,
|
||||||
// so we need to carefully track the state through different handlers.
|
// so we need to carefully track the state through different handlers.
|
||||||
if let Some(element) = self.common.shell.element_for_wl_surface(surface).cloned() {
|
if let Some(element) = self.common.shell.element_for_wl_surface(surface).cloned() {
|
||||||
|
crate::shell::layout::floating::ResizeSurfaceGrab::apply_resize_to_location(
|
||||||
|
element.clone(),
|
||||||
|
&mut self.common.shell,
|
||||||
|
);
|
||||||
if let Some(workspace) = self.common.shell.space_for_mut(&element) {
|
if let Some(workspace) = self.common.shell.space_for_mut(&element) {
|
||||||
crate::shell::layout::floating::ResizeSurfaceGrab::apply_resize_to_location(
|
|
||||||
element.clone(),
|
|
||||||
workspace,
|
|
||||||
);
|
|
||||||
workspace.commit(surface);
|
workspace.commit(surface);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue