shell: Fix MoveGrab with touch not on output pointer is on
This commit is contained in:
parent
2c5c32ad4e
commit
f2efc5d56f
3 changed files with 118 additions and 99 deletions
|
|
@ -445,7 +445,7 @@ where
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.borrow()
|
.borrow()
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|state| state.render::<CosmicElement<R>, R>(renderer, seat, output, theme))
|
.map(|state| state.render::<CosmicElement<R>, R>(renderer, output, theme))
|
||||||
{
|
{
|
||||||
elements.extend(grab_elements);
|
elements.extend(grab_elements);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -60,17 +60,12 @@ pub struct MoveGrabState {
|
||||||
snapping_zone: Option<SnappingZone>,
|
snapping_zone: Option<SnappingZone>,
|
||||||
stacking_indicator: Option<(StackHover, Point<i32, Logical>)>,
|
stacking_indicator: Option<(StackHover, Point<i32, Logical>)>,
|
||||||
location: Point<f64, Logical>,
|
location: Point<f64, Logical>,
|
||||||
|
cursor_output: Output,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MoveGrabState {
|
impl MoveGrabState {
|
||||||
#[profiling::function]
|
#[profiling::function]
|
||||||
pub fn render<I, R>(
|
pub fn render<I, R>(&self, renderer: &mut R, output: &Output, theme: &CosmicTheme) -> Vec<I>
|
||||||
&self,
|
|
||||||
renderer: &mut R,
|
|
||||||
seat: &Seat<State>,
|
|
||||||
output: &Output,
|
|
||||||
theme: &CosmicTheme,
|
|
||||||
) -> Vec<I>
|
|
||||||
where
|
where
|
||||||
R: Renderer + ImportAll + ImportMem + AsGlowRenderer,
|
R: Renderer + ImportAll + ImportMem + AsGlowRenderer,
|
||||||
<R as Renderer>::TextureId: 'static,
|
<R as Renderer>::TextureId: 'static,
|
||||||
|
|
@ -86,7 +81,7 @@ impl MoveGrabState {
|
||||||
} else {
|
} else {
|
||||||
1.0
|
1.0
|
||||||
};
|
};
|
||||||
let alpha = if &seat.active_output() == output {
|
let alpha = if &self.cursor_output == output {
|
||||||
1.0
|
1.0
|
||||||
} else {
|
} else {
|
||||||
0.4
|
0.4
|
||||||
|
|
@ -147,7 +142,7 @@ impl MoveGrabState {
|
||||||
};
|
};
|
||||||
|
|
||||||
let snapping_indicator = match &self.snapping_zone {
|
let snapping_indicator = match &self.snapping_zone {
|
||||||
Some(t) if &seat.active_output() == output => {
|
Some(t) if &self.cursor_output == output => {
|
||||||
let base_color = theme.palette.neutral_9;
|
let base_color = theme.palette.neutral_9;
|
||||||
let overlay_geometry = t.overlay_geometry(non_exclusive_geometry);
|
let overlay_geometry = t.overlay_geometry(non_exclusive_geometry);
|
||||||
vec![
|
vec![
|
||||||
|
|
@ -363,6 +358,7 @@ impl MoveGrab {
|
||||||
.map(|s| s.borrow_mut());
|
.map(|s| s.borrow_mut());
|
||||||
if let Some(grab_state) = borrow.as_mut().and_then(|s| s.as_mut()) {
|
if let Some(grab_state) = borrow.as_mut().and_then(|s| s.as_mut()) {
|
||||||
grab_state.location = location;
|
grab_state.location = location;
|
||||||
|
grab_state.cursor_output = self.cursor_output.clone();
|
||||||
|
|
||||||
let mut window_geo = self.window.geometry();
|
let mut window_geo = self.window.geometry();
|
||||||
window_geo.loc += location.to_i32_round() + grab_state.window_offset;
|
window_geo.loc += location.to_i32_round() + grab_state.window_offset;
|
||||||
|
|
@ -644,15 +640,15 @@ impl MoveGrab {
|
||||||
window: CosmicMapped,
|
window: CosmicMapped,
|
||||||
seat: &Seat<State>,
|
seat: &Seat<State>,
|
||||||
initial_window_location: Point<i32, Global>,
|
initial_window_location: Point<i32, Global>,
|
||||||
|
cursor_output: Output,
|
||||||
indicator_thickness: u8,
|
indicator_thickness: u8,
|
||||||
previous_layer: ManagedLayer,
|
previous_layer: ManagedLayer,
|
||||||
release: ReleaseMode,
|
release: ReleaseMode,
|
||||||
evlh: LoopHandle<'static, State>,
|
evlh: LoopHandle<'static, State>,
|
||||||
) -> MoveGrab {
|
) -> MoveGrab {
|
||||||
let output = seat.active_output();
|
|
||||||
let mut outputs = HashSet::new();
|
let mut outputs = HashSet::new();
|
||||||
outputs.insert(output.clone());
|
outputs.insert(cursor_output.clone());
|
||||||
window.output_enter(&output, window.geometry()); // not accurate but...
|
window.output_enter(&cursor_output, window.geometry()); // not accurate but...
|
||||||
window.moved_since_mapped.store(true, Ordering::SeqCst);
|
window.moved_since_mapped.store(true, Ordering::SeqCst);
|
||||||
|
|
||||||
let grab_state = MoveGrabState {
|
let grab_state = MoveGrabState {
|
||||||
|
|
@ -666,6 +662,7 @@ impl MoveGrab {
|
||||||
snapping_zone: None,
|
snapping_zone: None,
|
||||||
previous: previous_layer,
|
previous: previous_layer,
|
||||||
location: start_data.location(),
|
location: start_data.location(),
|
||||||
|
cursor_output: cursor_output.clone(),
|
||||||
};
|
};
|
||||||
|
|
||||||
*seat
|
*seat
|
||||||
|
|
@ -684,7 +681,7 @@ impl MoveGrab {
|
||||||
start_data,
|
start_data,
|
||||||
seat: seat.clone(),
|
seat: seat.clone(),
|
||||||
window_outputs: outputs,
|
window_outputs: outputs,
|
||||||
cursor_output: output,
|
cursor_output,
|
||||||
previous: previous_layer,
|
previous: previous_layer,
|
||||||
release,
|
release,
|
||||||
evlh: NotSend(evlh),
|
evlh: NotSend(evlh),
|
||||||
|
|
@ -699,7 +696,7 @@ impl MoveGrab {
|
||||||
impl Drop for MoveGrab {
|
impl Drop for MoveGrab {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
// No more buttons are pressed, release the grab.
|
// No more buttons are pressed, release the grab.
|
||||||
let output = self.seat.active_output();
|
let output = self.cursor_output.clone();
|
||||||
let seat = self.seat.clone();
|
let seat = self.seat.clone();
|
||||||
let window_outputs = self.window_outputs.drain().collect::<HashSet<_>>();
|
let window_outputs = self.window_outputs.drain().collect::<HashSet<_>>();
|
||||||
let previous = self.previous;
|
let previous = self.previous;
|
||||||
|
|
|
||||||
190
src/shell/mod.rs
190
src/shell/mod.rs
|
|
@ -2460,7 +2460,6 @@ impl Shell {
|
||||||
move_out_of_stack: bool,
|
move_out_of_stack: bool,
|
||||||
) {
|
) {
|
||||||
let serial = serial.into();
|
let serial = serial.into();
|
||||||
let output = seat.active_output();
|
|
||||||
|
|
||||||
if let Some(mut start_data) = check_grab_preconditions(&seat, surface, serial, release) {
|
if let Some(mut start_data) = check_grab_preconditions(&seat, surface, serial, release) {
|
||||||
if let Some(mut old_mapped) = state.common.shell.element_for_surface(surface).cloned() {
|
if let Some(mut old_mapped) = state.common.shell.element_for_surface(surface).cloned() {
|
||||||
|
|
@ -2505,91 +2504,113 @@ impl Shell {
|
||||||
};
|
};
|
||||||
let pos = start_data.location().as_global();
|
let pos = start_data.location().as_global();
|
||||||
|
|
||||||
let (initial_window_location, layer, workspace_handle) =
|
let cursor_output = if let Some(output) = state
|
||||||
if let Some(workspace) = state.common.shell.space_for_mut(&old_mapped) {
|
.common
|
||||||
if workspace
|
.shell
|
||||||
.fullscreen
|
.outputs()
|
||||||
.as_ref()
|
.find(|output| {
|
||||||
.is_some_and(|f| f.surface == window)
|
output.geometry().as_logical().overlaps_or_touches(
|
||||||
{
|
Rectangle::from_loc_and_size(
|
||||||
let _ = workspace.remove_fullscreen(); // We are moving this window, we don't need to send it back to it's original workspace
|
start_data.location().to_i32_floor(),
|
||||||
}
|
(0, 0),
|
||||||
|
),
|
||||||
let Some(elem_geo) = workspace.element_geometry(&old_mapped) else {
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
let mut initial_window_location = elem_geo.loc.to_global(&output);
|
|
||||||
|
|
||||||
if mapped.maximized_state.lock().unwrap().is_some() {
|
|
||||||
// If surface is maximized then unmaximize it
|
|
||||||
let new_size = workspace.unmaximize_request(&mapped);
|
|
||||||
let ratio = pos.to_local(&output).x / output.geometry().size.w as f64;
|
|
||||||
|
|
||||||
initial_window_location = new_size
|
|
||||||
.map(|size| (pos.x - (size.w as f64 * ratio), pos.y).into())
|
|
||||||
.unwrap_or_else(|| pos)
|
|
||||||
.to_i32_round();
|
|
||||||
}
|
|
||||||
|
|
||||||
let layer = if mapped == old_mapped {
|
|
||||||
let was_floating = workspace.floating_layer.unmap(&mapped);
|
|
||||||
let was_tiled = workspace.tiling_layer.unmap_as_placeholder(&mapped);
|
|
||||||
assert!(was_floating != was_tiled.is_some());
|
|
||||||
was_tiled.is_some()
|
|
||||||
} else {
|
|
||||||
workspace
|
|
||||||
.tiling_layer
|
|
||||||
.mapped()
|
|
||||||
.any(|(m, _)| m == &old_mapped)
|
|
||||||
}
|
|
||||||
.then_some(ManagedLayer::Tiling)
|
|
||||||
.unwrap_or(ManagedLayer::Floating);
|
|
||||||
|
|
||||||
(initial_window_location, layer, workspace.handle)
|
|
||||||
} else if let Some(sticky_layer) = state
|
|
||||||
.common
|
|
||||||
.shell
|
|
||||||
.workspaces
|
|
||||||
.sets
|
|
||||||
.get_mut(&output)
|
|
||||||
.filter(|set| set.sticky_layer.mapped().any(|m| m == &old_mapped))
|
|
||||||
.map(|set| &mut set.sticky_layer)
|
|
||||||
{
|
|
||||||
let mut initial_window_location = sticky_layer
|
|
||||||
.element_geometry(&old_mapped)
|
|
||||||
.unwrap()
|
|
||||||
.loc
|
|
||||||
.to_global(&output);
|
|
||||||
|
|
||||||
if let Some(state) = mapped.maximized_state.lock().unwrap().take() {
|
|
||||||
// If surface is maximized then unmaximize it
|
|
||||||
mapped.set_maximized(false);
|
|
||||||
let new_size = state.original_geometry.size.as_logical();
|
|
||||||
sticky_layer.map_internal(
|
|
||||||
mapped.clone(),
|
|
||||||
Some(state.original_geometry.loc),
|
|
||||||
Some(new_size),
|
|
||||||
None,
|
|
||||||
);
|
|
||||||
|
|
||||||
let ratio = pos.to_local(&output).x / output.geometry().size.w as f64;
|
|
||||||
initial_window_location =
|
|
||||||
Point::<f64, _>::from((pos.x - (new_size.w as f64 * ratio), pos.y))
|
|
||||||
.to_i32_round();
|
|
||||||
}
|
|
||||||
|
|
||||||
if mapped == old_mapped {
|
|
||||||
sticky_layer.unmap(&mapped);
|
|
||||||
}
|
|
||||||
|
|
||||||
(
|
|
||||||
initial_window_location,
|
|
||||||
ManagedLayer::Sticky,
|
|
||||||
state.common.shell.active_space(&output).handle,
|
|
||||||
)
|
)
|
||||||
} else {
|
})
|
||||||
|
.cloned()
|
||||||
|
{
|
||||||
|
output
|
||||||
|
} else {
|
||||||
|
seat.active_output()
|
||||||
|
};
|
||||||
|
|
||||||
|
let (initial_window_location, layer, workspace_handle) = if let Some(workspace) =
|
||||||
|
state.common.shell.space_for_mut(&old_mapped)
|
||||||
|
{
|
||||||
|
if workspace
|
||||||
|
.fullscreen
|
||||||
|
.as_ref()
|
||||||
|
.is_some_and(|f| f.surface == window)
|
||||||
|
{
|
||||||
|
let _ = workspace.remove_fullscreen(); // We are moving this window, we don't need to send it back to it's original workspace
|
||||||
|
}
|
||||||
|
|
||||||
|
let Some(elem_geo) = workspace.element_geometry(&old_mapped) else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
let mut initial_window_location = elem_geo.loc.to_global(&workspace.output());
|
||||||
|
|
||||||
|
if mapped.maximized_state.lock().unwrap().is_some() {
|
||||||
|
// If surface is maximized then unmaximize it
|
||||||
|
let new_size = workspace.unmaximize_request(&mapped);
|
||||||
|
let output = workspace.output();
|
||||||
|
let ratio = pos.to_local(output).x / output.geometry().size.w as f64;
|
||||||
|
|
||||||
|
initial_window_location = new_size
|
||||||
|
.map(|size| (pos.x - (size.w as f64 * ratio), pos.y).into())
|
||||||
|
.unwrap_or_else(|| pos)
|
||||||
|
.to_i32_round();
|
||||||
|
}
|
||||||
|
|
||||||
|
let layer = if mapped == old_mapped {
|
||||||
|
let was_floating = workspace.floating_layer.unmap(&mapped);
|
||||||
|
let was_tiled = workspace.tiling_layer.unmap_as_placeholder(&mapped);
|
||||||
|
assert!(was_floating != was_tiled.is_some());
|
||||||
|
was_tiled.is_some()
|
||||||
|
} else {
|
||||||
|
workspace
|
||||||
|
.tiling_layer
|
||||||
|
.mapped()
|
||||||
|
.any(|(m, _)| m == &old_mapped)
|
||||||
|
}
|
||||||
|
.then_some(ManagedLayer::Tiling)
|
||||||
|
.unwrap_or(ManagedLayer::Floating);
|
||||||
|
|
||||||
|
(initial_window_location, layer, workspace.handle)
|
||||||
|
} else if let Some(sticky_layer) = state
|
||||||
|
.common
|
||||||
|
.shell
|
||||||
|
.workspaces
|
||||||
|
.sets
|
||||||
|
.get_mut(&cursor_output)
|
||||||
|
.filter(|set| set.sticky_layer.mapped().any(|m| m == &old_mapped))
|
||||||
|
.map(|set| &mut set.sticky_layer)
|
||||||
|
{
|
||||||
|
let mut initial_window_location = sticky_layer
|
||||||
|
.element_geometry(&old_mapped)
|
||||||
|
.unwrap()
|
||||||
|
.loc
|
||||||
|
.to_global(&cursor_output);
|
||||||
|
|
||||||
|
if let Some(state) = mapped.maximized_state.lock().unwrap().take() {
|
||||||
|
// If surface is maximized then unmaximize it
|
||||||
|
mapped.set_maximized(false);
|
||||||
|
let new_size = state.original_geometry.size.as_logical();
|
||||||
|
sticky_layer.map_internal(
|
||||||
|
mapped.clone(),
|
||||||
|
Some(state.original_geometry.loc),
|
||||||
|
Some(new_size),
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
|
||||||
|
let ratio =
|
||||||
|
pos.to_local(&cursor_output).x / cursor_output.geometry().size.w as f64;
|
||||||
|
initial_window_location =
|
||||||
|
Point::<f64, _>::from((pos.x - (new_size.w as f64 * ratio), pos.y))
|
||||||
|
.to_i32_round();
|
||||||
|
}
|
||||||
|
|
||||||
|
if mapped == old_mapped {
|
||||||
|
sticky_layer.unmap(&mapped);
|
||||||
|
}
|
||||||
|
|
||||||
|
(
|
||||||
|
initial_window_location,
|
||||||
|
ManagedLayer::Sticky,
|
||||||
|
state.common.shell.active_space(&cursor_output).handle,
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
state
|
state
|
||||||
.common
|
.common
|
||||||
|
|
@ -2600,7 +2621,7 @@ impl Shell {
|
||||||
.common
|
.common
|
||||||
.shell
|
.shell
|
||||||
.toplevel_info_state
|
.toplevel_info_state
|
||||||
.toplevel_leave_output(&window, &output);
|
.toplevel_leave_output(&window, &cursor_output);
|
||||||
|
|
||||||
if move_out_of_stack {
|
if move_out_of_stack {
|
||||||
old_mapped.stack_ref_mut().unwrap().remove_window(&window);
|
old_mapped.stack_ref_mut().unwrap().remove_window(&window);
|
||||||
|
|
@ -2620,6 +2641,7 @@ impl Shell {
|
||||||
mapped,
|
mapped,
|
||||||
seat,
|
seat,
|
||||||
initial_window_location,
|
initial_window_location,
|
||||||
|
cursor_output,
|
||||||
active_hint as u8,
|
active_hint as u8,
|
||||||
layer,
|
layer,
|
||||||
release,
|
release,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue