2022-10-26 15:26:07 +02:00
|
|
|
// SPDX-License-Identifier: GPL-3.0-only
|
|
|
|
|
|
|
|
|
|
use crate::{
|
2023-07-18 12:21:16 +02:00
|
|
|
backend::render::{
|
|
|
|
|
cursor::{CursorShape, CursorState},
|
|
|
|
|
element::AsGlowRenderer,
|
2023-08-11 18:15:22 +02:00
|
|
|
IndicatorShader, Key, Usage,
|
2023-07-18 12:21:16 +02:00
|
|
|
},
|
2022-10-26 15:26:07 +02:00
|
|
|
shell::{
|
2023-07-24 19:31:31 +02:00
|
|
|
element::{
|
|
|
|
|
stack_hover::{stack_hover, StackHover},
|
|
|
|
|
CosmicMappedRenderElement,
|
|
|
|
|
},
|
2022-10-26 15:26:07 +02:00
|
|
|
focus::target::{KeyboardFocusTarget, PointerFocusTarget},
|
2023-06-08 21:50:16 +02:00
|
|
|
CosmicMapped, CosmicSurface,
|
2022-10-26 15:26:07 +02:00
|
|
|
},
|
|
|
|
|
utils::prelude::*,
|
|
|
|
|
};
|
|
|
|
|
|
2023-10-10 13:55:34 -04:00
|
|
|
use cosmic::theme::CosmicTheme;
|
2022-10-26 15:26:07 +02:00
|
|
|
use smithay::{
|
2023-07-18 12:21:31 +02:00
|
|
|
backend::renderer::{
|
2023-07-24 19:31:31 +02:00
|
|
|
element::{utils::RescaleRenderElement, AsRenderElements, RenderElement},
|
2023-07-18 12:21:31 +02:00
|
|
|
ImportAll, ImportMem, Renderer,
|
|
|
|
|
},
|
2022-10-26 15:26:07 +02:00
|
|
|
desktop::space::SpaceElement,
|
|
|
|
|
input::{
|
|
|
|
|
pointer::{
|
2023-09-05 10:55:23 -07:00
|
|
|
AxisFrame, ButtonEvent, GestureHoldBeginEvent, GestureHoldEndEvent,
|
|
|
|
|
GesturePinchBeginEvent, GesturePinchEndEvent, GesturePinchUpdateEvent,
|
|
|
|
|
GestureSwipeBeginEvent, GestureSwipeEndEvent, GestureSwipeUpdateEvent,
|
|
|
|
|
GrabStartData as PointerGrabStartData, MotionEvent, PointerGrab, PointerInnerHandle,
|
|
|
|
|
RelativeMotionEvent,
|
2022-10-26 15:26:07 +02:00
|
|
|
},
|
|
|
|
|
Seat,
|
|
|
|
|
},
|
|
|
|
|
output::Output,
|
2023-02-13 17:56:13 +01:00
|
|
|
reexports::wayland_server::protocol::wl_surface::WlSurface,
|
2023-08-31 18:17:37 +02:00
|
|
|
utils::{IsAlive, Logical, Point, Rectangle, Scale, Serial},
|
2023-02-13 17:56:13 +01:00
|
|
|
wayland::compositor::SurfaceData,
|
2022-10-26 15:26:07 +02:00
|
|
|
};
|
2023-07-18 12:21:31 +02:00
|
|
|
use std::{
|
|
|
|
|
cell::RefCell,
|
|
|
|
|
collections::HashSet,
|
|
|
|
|
time::{Duration, Instant},
|
|
|
|
|
};
|
2022-10-26 15:26:07 +02:00
|
|
|
|
|
|
|
|
pub type SeatMoveGrabState = RefCell<Option<MoveGrabState>>;
|
|
|
|
|
|
2023-07-18 12:21:31 +02:00
|
|
|
const RESCALE_ANIMATION_DURATION: f64 = 150.0;
|
|
|
|
|
|
2022-10-26 15:26:07 +02:00
|
|
|
pub struct MoveGrabState {
|
|
|
|
|
window: CosmicMapped,
|
2023-03-06 18:50:59 +01:00
|
|
|
window_offset: Point<i32, Logical>,
|
2023-03-09 18:27:11 +01:00
|
|
|
indicator_thickness: u8,
|
2023-07-18 12:21:31 +02:00
|
|
|
start: Instant,
|
2023-07-25 16:46:08 +02:00
|
|
|
tiling: bool,
|
2023-07-24 19:31:31 +02:00
|
|
|
stacking_indicator: Option<(StackHover, Point<i32, Logical>)>,
|
2022-10-26 15:26:07 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl MoveGrabState {
|
2023-10-10 13:55:34 -04:00
|
|
|
pub fn render<I, R>(
|
|
|
|
|
&self,
|
|
|
|
|
renderer: &mut R,
|
|
|
|
|
seat: &Seat<State>,
|
|
|
|
|
output: &Output,
|
|
|
|
|
theme: &CosmicTheme,
|
|
|
|
|
) -> Vec<I>
|
2022-10-26 15:26:07 +02:00
|
|
|
where
|
2023-01-16 15:12:25 +01:00
|
|
|
R: Renderer + ImportAll + ImportMem + AsGlowRenderer,
|
2022-10-26 15:26:07 +02:00
|
|
|
<R as Renderer>::TextureId: 'static,
|
2022-11-22 10:28:30 +01:00
|
|
|
CosmicMappedRenderElement<R>: RenderElement<R>,
|
2022-10-26 15:26:07 +02:00
|
|
|
I: From<CosmicMappedRenderElement<R>>,
|
|
|
|
|
{
|
2023-03-06 18:50:59 +01:00
|
|
|
#[cfg(feature = "debug")]
|
|
|
|
|
puffin::profile_function!();
|
|
|
|
|
|
2023-07-25 16:46:08 +02:00
|
|
|
let scale = if self.tiling {
|
|
|
|
|
0.6 + ((1.0
|
2023-07-18 12:21:31 +02:00
|
|
|
- (Instant::now().duration_since(self.start).as_millis() as f64
|
|
|
|
|
/ RESCALE_ANIMATION_DURATION)
|
|
|
|
|
.min(1.0))
|
2023-07-25 16:46:08 +02:00
|
|
|
* 0.4)
|
|
|
|
|
} else {
|
|
|
|
|
1.0
|
|
|
|
|
};
|
2023-10-11 19:16:51 +02:00
|
|
|
let alpha = if &seat.active_output() == output {
|
|
|
|
|
1.0
|
|
|
|
|
} else {
|
|
|
|
|
0.4
|
|
|
|
|
};
|
2023-07-18 12:21:31 +02:00
|
|
|
|
2022-10-26 15:26:07 +02:00
|
|
|
let cursor_at = seat.get_pointer().unwrap().current_location();
|
|
|
|
|
|
|
|
|
|
let mut window_geo = self.window.geometry();
|
2023-03-06 18:50:59 +01:00
|
|
|
window_geo.loc += cursor_at.to_i32_round() + self.window_offset;
|
2023-10-25 19:24:51 +02:00
|
|
|
if !output
|
|
|
|
|
.geometry()
|
|
|
|
|
.as_logical()
|
|
|
|
|
.intersection(window_geo)
|
|
|
|
|
.is_some()
|
|
|
|
|
{
|
2022-10-26 15:26:07 +02:00
|
|
|
return Vec::new();
|
|
|
|
|
}
|
|
|
|
|
|
2023-08-31 18:17:37 +02:00
|
|
|
let output_scale: Scale<f64> = output.current_scale().fractional_scale().into();
|
2023-07-18 12:21:31 +02:00
|
|
|
let scaling_offset =
|
|
|
|
|
self.window_offset - self.window_offset.to_f64().upscale(scale).to_i32_round();
|
2023-10-25 19:24:51 +02:00
|
|
|
let render_location = cursor_at.to_i32_round() - output.geometry().loc.as_logical()
|
|
|
|
|
+ self.window_offset
|
|
|
|
|
- scaling_offset;
|
2023-03-06 18:50:59 +01:00
|
|
|
|
2023-10-10 13:55:34 -04:00
|
|
|
let active_window_hint = crate::theme::active_window_hint(theme);
|
2023-07-13 17:19:29 +02:00
|
|
|
let focus_element = if self.indicator_thickness > 0 {
|
|
|
|
|
Some(
|
2023-05-30 13:20:46 +02:00
|
|
|
CosmicMappedRenderElement::from(IndicatorShader::focus_element(
|
2023-03-09 18:27:11 +01:00
|
|
|
renderer,
|
2023-08-11 18:15:22 +02:00
|
|
|
Key::Window(Usage::MoveGrabIndicator, self.window.clone()),
|
2023-07-18 12:21:31 +02:00
|
|
|
Rectangle::from_loc_and_size(
|
|
|
|
|
render_location,
|
|
|
|
|
self.window
|
|
|
|
|
.geometry()
|
|
|
|
|
.size
|
|
|
|
|
.to_f64()
|
|
|
|
|
.upscale(scale)
|
|
|
|
|
.to_i32_round(),
|
2023-10-25 19:24:51 +02:00
|
|
|
)
|
|
|
|
|
.as_local(),
|
2023-03-09 18:27:11 +01:00
|
|
|
self.indicator_thickness,
|
2023-08-31 18:17:37 +02:00
|
|
|
output_scale.x,
|
2023-10-11 19:16:51 +02:00
|
|
|
alpha,
|
2023-10-10 13:55:34 -04:00
|
|
|
[
|
|
|
|
|
active_window_hint.red,
|
|
|
|
|
active_window_hint.green,
|
|
|
|
|
active_window_hint.blue,
|
|
|
|
|
],
|
2023-03-09 18:27:11 +01:00
|
|
|
))
|
|
|
|
|
.into(),
|
2023-07-13 17:19:29 +02:00
|
|
|
)
|
|
|
|
|
} else {
|
|
|
|
|
None
|
|
|
|
|
};
|
|
|
|
|
|
2023-07-18 12:21:31 +02:00
|
|
|
let (window_elements, popup_elements) = self
|
|
|
|
|
.window
|
|
|
|
|
.split_render_elements::<R, CosmicMappedRenderElement<R>>(
|
|
|
|
|
renderer,
|
|
|
|
|
(render_location - self.window.geometry().loc)
|
|
|
|
|
.to_physical_precise_round(output_scale),
|
|
|
|
|
output_scale,
|
2023-10-11 19:16:51 +02:00
|
|
|
alpha,
|
2023-07-18 12:21:31 +02:00
|
|
|
);
|
2023-07-13 17:19:29 +02:00
|
|
|
|
2023-07-24 19:31:31 +02:00
|
|
|
self.stacking_indicator
|
|
|
|
|
.iter()
|
|
|
|
|
.flat_map(|(indicator, location)| {
|
|
|
|
|
indicator.render_elements(
|
|
|
|
|
renderer,
|
2023-07-26 16:13:48 +02:00
|
|
|
location.to_physical_precise_round(output_scale),
|
2023-07-24 19:31:31 +02:00
|
|
|
output_scale,
|
|
|
|
|
1.0,
|
|
|
|
|
)
|
|
|
|
|
})
|
|
|
|
|
.chain(popup_elements)
|
2023-07-13 17:19:29 +02:00
|
|
|
.chain(focus_element)
|
2023-07-18 12:21:31 +02:00
|
|
|
.chain(window_elements.into_iter().map(|elem| match elem {
|
|
|
|
|
CosmicMappedRenderElement::Stack(stack) => {
|
|
|
|
|
CosmicMappedRenderElement::GrabbedStack(
|
|
|
|
|
RescaleRenderElement::from_element(
|
|
|
|
|
stack,
|
|
|
|
|
render_location.to_physical_precise_round(
|
|
|
|
|
output.current_scale().fractional_scale(),
|
|
|
|
|
),
|
|
|
|
|
scale,
|
|
|
|
|
),
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
CosmicMappedRenderElement::Window(window) => {
|
|
|
|
|
CosmicMappedRenderElement::GrabbedWindow(
|
|
|
|
|
RescaleRenderElement::from_element(
|
|
|
|
|
window,
|
|
|
|
|
render_location.to_physical_precise_round(
|
|
|
|
|
output.current_scale().fractional_scale(),
|
|
|
|
|
),
|
|
|
|
|
scale,
|
|
|
|
|
),
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
x => x,
|
|
|
|
|
}))
|
|
|
|
|
.map(I::from)
|
2023-07-13 17:19:29 +02:00
|
|
|
.collect()
|
2022-10-26 15:26:07 +02:00
|
|
|
}
|
2023-02-13 17:56:13 +01:00
|
|
|
|
|
|
|
|
pub fn send_frames(
|
|
|
|
|
&self,
|
|
|
|
|
output: &Output,
|
|
|
|
|
time: impl Into<Duration>,
|
|
|
|
|
throttle: Option<Duration>,
|
|
|
|
|
primary_scan_out_output: impl FnMut(&WlSurface, &SurfaceData) -> Option<Output> + Copy,
|
|
|
|
|
) {
|
|
|
|
|
self.window
|
|
|
|
|
.active_window()
|
|
|
|
|
.send_frame(output, time, throttle, primary_scan_out_output)
|
|
|
|
|
}
|
2023-03-31 13:57:37 +02:00
|
|
|
|
|
|
|
|
pub fn window(&self) -> CosmicSurface {
|
|
|
|
|
self.window.active_window()
|
|
|
|
|
}
|
2022-10-26 15:26:07 +02:00
|
|
|
}
|
|
|
|
|
|
2023-07-17 21:11:23 +02:00
|
|
|
pub struct MoveGrab {
|
2022-10-26 15:26:07 +02:00
|
|
|
window: CosmicMapped,
|
|
|
|
|
start_data: PointerGrabStartData<State>,
|
|
|
|
|
seat: Seat<State>,
|
2023-07-31 17:25:09 +02:00
|
|
|
cursor_output: Output,
|
|
|
|
|
window_outputs: HashSet<Output>,
|
2023-07-17 21:11:23 +02:00
|
|
|
tiling: bool,
|
2022-10-26 15:26:07 +02:00
|
|
|
}
|
|
|
|
|
|
2023-07-17 21:11:23 +02:00
|
|
|
impl PointerGrab<State> for MoveGrab {
|
2022-10-26 15:26:07 +02:00
|
|
|
fn motion(
|
|
|
|
|
&mut self,
|
|
|
|
|
state: &mut State,
|
|
|
|
|
handle: &mut PointerInnerHandle<'_, State>,
|
|
|
|
|
_focus: Option<(PointerFocusTarget, Point<i32, Logical>)>,
|
|
|
|
|
event: &MotionEvent,
|
|
|
|
|
) {
|
2023-07-31 17:25:09 +02:00
|
|
|
let Some(current_output) = state
|
|
|
|
|
.common
|
|
|
|
|
.shell
|
|
|
|
|
.outputs()
|
|
|
|
|
.find(|output| {
|
|
|
|
|
output
|
|
|
|
|
.geometry()
|
2023-10-25 19:24:51 +02:00
|
|
|
.as_logical()
|
2023-07-31 17:25:09 +02:00
|
|
|
.contains(handle.current_location().to_i32_round())
|
|
|
|
|
})
|
|
|
|
|
.cloned()
|
|
|
|
|
else {
|
|
|
|
|
return;
|
|
|
|
|
};
|
|
|
|
|
if self.cursor_output != current_output {
|
|
|
|
|
state
|
|
|
|
|
.common
|
|
|
|
|
.shell
|
|
|
|
|
.workspaces
|
|
|
|
|
.active_mut(&self.cursor_output)
|
|
|
|
|
.tiling_layer
|
2023-10-25 19:40:26 +02:00
|
|
|
.cleanup_drag();
|
2023-07-31 17:25:09 +02:00
|
|
|
self.cursor_output = current_output.clone();
|
|
|
|
|
}
|
|
|
|
|
|
2023-07-24 19:31:31 +02:00
|
|
|
let mut borrow = self
|
2023-03-06 18:50:59 +01:00
|
|
|
.seat
|
|
|
|
|
.user_data()
|
|
|
|
|
.get::<SeatMoveGrabState>()
|
2023-07-24 19:31:31 +02:00
|
|
|
.map(|s| s.borrow_mut());
|
|
|
|
|
if let Some(grab_state) = borrow.as_mut().and_then(|s| s.as_mut()) {
|
2023-03-06 18:50:59 +01:00
|
|
|
let mut window_geo = self.window.geometry();
|
|
|
|
|
window_geo.loc += event.location.to_i32_round() + grab_state.window_offset;
|
2023-10-25 19:24:51 +02:00
|
|
|
for output in state.common.shell.outputs() {
|
|
|
|
|
if let Some(overlap) = output.geometry().as_logical().intersection(window_geo) {
|
2023-07-31 17:25:09 +02:00
|
|
|
if self.window_outputs.insert(output.clone()) {
|
2023-03-06 18:50:59 +01:00
|
|
|
self.window.output_enter(output, overlap);
|
2023-07-24 19:31:31 +02:00
|
|
|
if let Some(indicator) =
|
|
|
|
|
grab_state.stacking_indicator.as_ref().map(|x| &x.0)
|
|
|
|
|
{
|
|
|
|
|
indicator.output_enter(output, overlap);
|
|
|
|
|
}
|
2023-03-06 18:50:59 +01:00
|
|
|
}
|
2023-07-31 17:25:09 +02:00
|
|
|
} else if self.window_outputs.remove(&output) {
|
2023-03-06 18:50:59 +01:00
|
|
|
self.window.output_leave(output);
|
2023-07-24 19:31:31 +02:00
|
|
|
if let Some(indicator) = grab_state.stacking_indicator.as_ref().map(|x| &x.0) {
|
|
|
|
|
indicator.output_leave(output);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if self.tiling {
|
|
|
|
|
let indicator_location = state
|
|
|
|
|
.common
|
|
|
|
|
.shell
|
2023-07-31 17:25:09 +02:00
|
|
|
.active_space(¤t_output)
|
2023-07-24 19:31:31 +02:00
|
|
|
.tiling_layer
|
|
|
|
|
.stacking_indicator();
|
|
|
|
|
|
|
|
|
|
if indicator_location.is_some() != grab_state.stacking_indicator.is_some() {
|
|
|
|
|
grab_state.stacking_indicator = indicator_location.map(|geo| {
|
2023-10-25 19:24:51 +02:00
|
|
|
let element = stack_hover(
|
|
|
|
|
state.common.event_loop_handle.clone(),
|
|
|
|
|
geo.size.as_logical(),
|
2023-10-10 13:55:34 -04:00
|
|
|
state.common.theme.clone(),
|
2023-10-25 19:24:51 +02:00
|
|
|
);
|
2023-07-31 17:25:09 +02:00
|
|
|
for output in &self.window_outputs {
|
2023-10-25 19:24:51 +02:00
|
|
|
element.output_enter(
|
|
|
|
|
output,
|
|
|
|
|
Rectangle::from_loc_and_size(
|
|
|
|
|
(0, 0),
|
|
|
|
|
output.geometry().size.as_logical(),
|
|
|
|
|
),
|
|
|
|
|
);
|
2023-07-24 19:31:31 +02:00
|
|
|
}
|
2023-10-25 19:24:51 +02:00
|
|
|
(element, geo.loc.as_logical())
|
2023-07-24 19:31:31 +02:00
|
|
|
});
|
2023-03-06 18:50:59 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
drop(borrow);
|
|
|
|
|
|
2022-10-26 15:26:07 +02:00
|
|
|
// While the grab is active, no client has pointer focus
|
|
|
|
|
handle.motion(state, None, event);
|
|
|
|
|
if !self.window.alive() {
|
|
|
|
|
self.ungrab(state, handle, event.serial, event.time);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-30 23:19:36 +01:00
|
|
|
fn relative_motion(
|
|
|
|
|
&mut self,
|
|
|
|
|
state: &mut State,
|
|
|
|
|
handle: &mut PointerInnerHandle<'_, State>,
|
|
|
|
|
_focus: Option<(PointerFocusTarget, Point<i32, Logical>)>,
|
|
|
|
|
event: &RelativeMotionEvent,
|
|
|
|
|
) {
|
|
|
|
|
// While the grab is active, no client has pointer focus
|
|
|
|
|
handle.relative_motion(state, None, event);
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-26 15:26:07 +02:00
|
|
|
fn button(
|
|
|
|
|
&mut self,
|
|
|
|
|
state: &mut State,
|
|
|
|
|
handle: &mut PointerInnerHandle<'_, State>,
|
|
|
|
|
event: &ButtonEvent,
|
|
|
|
|
) {
|
|
|
|
|
handle.button(state, event);
|
|
|
|
|
if handle.current_pressed().is_empty() {
|
|
|
|
|
self.ungrab(state, handle, event.serial, event.time);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn axis(
|
|
|
|
|
&mut self,
|
|
|
|
|
state: &mut State,
|
|
|
|
|
handle: &mut PointerInnerHandle<'_, State>,
|
|
|
|
|
details: AxisFrame,
|
|
|
|
|
) {
|
|
|
|
|
handle.axis(state, details);
|
|
|
|
|
}
|
|
|
|
|
|
2023-09-13 20:52:10 -07:00
|
|
|
fn frame(&mut self, data: &mut State, handle: &mut PointerInnerHandle<'_, State>) {
|
|
|
|
|
handle.frame(data)
|
|
|
|
|
}
|
|
|
|
|
|
2023-09-05 10:55:23 -07:00
|
|
|
fn gesture_swipe_begin(
|
|
|
|
|
&mut self,
|
|
|
|
|
data: &mut State,
|
|
|
|
|
handle: &mut PointerInnerHandle<'_, State>,
|
|
|
|
|
event: &GestureSwipeBeginEvent,
|
|
|
|
|
) {
|
|
|
|
|
handle.gesture_swipe_begin(data, event)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn gesture_swipe_update(
|
|
|
|
|
&mut self,
|
|
|
|
|
data: &mut State,
|
|
|
|
|
handle: &mut PointerInnerHandle<'_, State>,
|
|
|
|
|
event: &GestureSwipeUpdateEvent,
|
|
|
|
|
) {
|
|
|
|
|
handle.gesture_swipe_update(data, event)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn gesture_swipe_end(
|
|
|
|
|
&mut self,
|
|
|
|
|
data: &mut State,
|
|
|
|
|
handle: &mut PointerInnerHandle<'_, State>,
|
|
|
|
|
event: &GestureSwipeEndEvent,
|
|
|
|
|
) {
|
|
|
|
|
handle.gesture_swipe_end(data, event)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn gesture_pinch_begin(
|
|
|
|
|
&mut self,
|
|
|
|
|
data: &mut State,
|
|
|
|
|
handle: &mut PointerInnerHandle<'_, State>,
|
|
|
|
|
event: &GesturePinchBeginEvent,
|
|
|
|
|
) {
|
|
|
|
|
handle.gesture_pinch_begin(data, event)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn gesture_pinch_update(
|
|
|
|
|
&mut self,
|
|
|
|
|
data: &mut State,
|
|
|
|
|
handle: &mut PointerInnerHandle<'_, State>,
|
|
|
|
|
event: &GesturePinchUpdateEvent,
|
|
|
|
|
) {
|
|
|
|
|
handle.gesture_pinch_update(data, event)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn gesture_pinch_end(
|
|
|
|
|
&mut self,
|
|
|
|
|
data: &mut State,
|
|
|
|
|
handle: &mut PointerInnerHandle<'_, State>,
|
|
|
|
|
event: &GesturePinchEndEvent,
|
|
|
|
|
) {
|
|
|
|
|
handle.gesture_pinch_end(data, event)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn gesture_hold_begin(
|
|
|
|
|
&mut self,
|
|
|
|
|
data: &mut State,
|
|
|
|
|
handle: &mut PointerInnerHandle<'_, State>,
|
|
|
|
|
event: &GestureHoldBeginEvent,
|
|
|
|
|
) {
|
|
|
|
|
handle.gesture_hold_begin(data, event)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn gesture_hold_end(
|
|
|
|
|
&mut self,
|
|
|
|
|
data: &mut State,
|
|
|
|
|
handle: &mut PointerInnerHandle<'_, State>,
|
|
|
|
|
event: &GestureHoldEndEvent,
|
|
|
|
|
) {
|
|
|
|
|
handle.gesture_hold_end(data, event)
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-26 15:26:07 +02:00
|
|
|
fn start_data(&self) -> &PointerGrabStartData<State> {
|
|
|
|
|
&self.start_data
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-07-17 21:11:23 +02:00
|
|
|
impl MoveGrab {
|
2022-10-26 15:26:07 +02:00
|
|
|
pub fn new(
|
|
|
|
|
start_data: PointerGrabStartData<State>,
|
|
|
|
|
window: CosmicMapped,
|
|
|
|
|
seat: &Seat<State>,
|
2023-10-25 19:24:51 +02:00
|
|
|
initial_cursor_location: Point<f64, Global>,
|
|
|
|
|
initial_window_location: Point<i32, Global>,
|
2023-03-09 18:27:11 +01:00
|
|
|
indicator_thickness: u8,
|
2023-07-17 21:11:23 +02:00
|
|
|
was_tiled: bool,
|
|
|
|
|
) -> MoveGrab {
|
2023-03-06 18:50:59 +01:00
|
|
|
let output = seat.active_output();
|
|
|
|
|
let mut outputs = HashSet::new();
|
|
|
|
|
outputs.insert(output.clone());
|
|
|
|
|
window.output_enter(&output, window.geometry()); // not accurate but...
|
|
|
|
|
|
2022-10-26 15:26:07 +02:00
|
|
|
let grab_state = MoveGrabState {
|
|
|
|
|
window: window.clone(),
|
2023-10-25 19:24:51 +02:00
|
|
|
window_offset: (initial_window_location - initial_cursor_location.to_i32_round())
|
|
|
|
|
.as_logical(),
|
2023-03-09 18:27:11 +01:00
|
|
|
indicator_thickness,
|
2023-07-18 12:21:31 +02:00
|
|
|
start: Instant::now(),
|
2023-07-24 19:31:31 +02:00
|
|
|
stacking_indicator: None,
|
2023-07-25 16:46:08 +02:00
|
|
|
tiling: was_tiled,
|
2022-10-26 15:26:07 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
*seat
|
|
|
|
|
.user_data()
|
|
|
|
|
.get::<SeatMoveGrabState>()
|
|
|
|
|
.unwrap()
|
|
|
|
|
.borrow_mut() = Some(grab_state);
|
|
|
|
|
|
2023-07-18 12:21:16 +02:00
|
|
|
{
|
|
|
|
|
let cursor_state = seat.user_data().get::<CursorState>().unwrap();
|
|
|
|
|
cursor_state.set_shape(CursorShape::Grab);
|
|
|
|
|
}
|
|
|
|
|
|
2023-07-17 21:11:23 +02:00
|
|
|
MoveGrab {
|
2022-10-26 15:26:07 +02:00
|
|
|
window,
|
|
|
|
|
start_data,
|
|
|
|
|
seat: seat.clone(),
|
2023-07-31 17:25:09 +02:00
|
|
|
window_outputs: outputs,
|
|
|
|
|
cursor_output: output,
|
2023-07-17 21:11:23 +02:00
|
|
|
tiling: was_tiled,
|
2022-10-26 15:26:07 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-07-17 21:11:23 +02:00
|
|
|
pub fn is_tiling_grab(&self) -> bool {
|
|
|
|
|
self.tiling
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-26 15:26:07 +02:00
|
|
|
fn ungrab(
|
|
|
|
|
&mut self,
|
|
|
|
|
state: &mut State,
|
|
|
|
|
handle: &mut PointerInnerHandle<'_, State>,
|
|
|
|
|
serial: Serial,
|
|
|
|
|
time: u32,
|
|
|
|
|
) {
|
|
|
|
|
// No more buttons are pressed, release the grab.
|
|
|
|
|
let output = self.seat.active_output();
|
|
|
|
|
|
2023-10-25 19:24:51 +02:00
|
|
|
let position: Option<(CosmicMapped, Point<i32, Global>)> = if let Some(grab_state) = self
|
2022-10-26 15:26:07 +02:00
|
|
|
.seat
|
|
|
|
|
.user_data()
|
|
|
|
|
.get::<SeatMoveGrabState>()
|
|
|
|
|
.and_then(|s| s.borrow_mut().take())
|
|
|
|
|
{
|
|
|
|
|
if grab_state.window.alive() {
|
2023-10-25 19:24:51 +02:00
|
|
|
let window_location = (handle.current_location().to_i32_round()
|
|
|
|
|
+ grab_state.window_offset)
|
|
|
|
|
.as_global();
|
2022-10-26 15:26:07 +02:00
|
|
|
|
|
|
|
|
let workspace_handle = state.common.shell.active_space(&output).handle;
|
2023-07-31 17:25:09 +02:00
|
|
|
for old_output in self.window_outputs.iter().filter(|o| *o != &output) {
|
2023-07-17 21:11:23 +02:00
|
|
|
grab_state.window.output_leave(old_output);
|
|
|
|
|
}
|
2022-10-26 15:26:07 +02:00
|
|
|
for (window, _) in grab_state.window.windows() {
|
|
|
|
|
state
|
|
|
|
|
.common
|
|
|
|
|
.shell
|
|
|
|
|
.toplevel_info_state
|
|
|
|
|
.toplevel_enter_workspace(&window, &workspace_handle);
|
|
|
|
|
state
|
|
|
|
|
.common
|
|
|
|
|
.shell
|
|
|
|
|
.toplevel_info_state
|
|
|
|
|
.toplevel_enter_output(&window, &output);
|
|
|
|
|
}
|
|
|
|
|
|
2023-07-17 21:11:23 +02:00
|
|
|
if self.tiling {
|
2023-10-25 19:24:51 +02:00
|
|
|
let (window, location) = state
|
2023-07-17 21:11:23 +02:00
|
|
|
.common
|
|
|
|
|
.shell
|
2023-10-25 19:24:51 +02:00
|
|
|
.active_space_mut(&output)
|
|
|
|
|
.tiling_layer
|
|
|
|
|
.drop_window(grab_state.window);
|
|
|
|
|
Some((window, location.to_global(&output)))
|
|
|
|
|
} else {
|
2023-07-17 21:11:23 +02:00
|
|
|
grab_state.window.set_geometry(Rectangle::from_loc_and_size(
|
2023-10-25 19:24:51 +02:00
|
|
|
window_location,
|
|
|
|
|
grab_state.window.geometry().size.as_global(),
|
2023-07-17 21:11:23 +02:00
|
|
|
));
|
2023-10-25 19:24:51 +02:00
|
|
|
let workspace = state.common.shell.active_space_mut(&output);
|
|
|
|
|
workspace.floating_layer.map_internal(
|
|
|
|
|
grab_state.window,
|
|
|
|
|
Some(window_location.to_local(&workspace.output)),
|
|
|
|
|
None,
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
Some((self.window.clone(), window_location))
|
2023-07-17 21:11:23 +02:00
|
|
|
}
|
2023-04-19 11:42:46 +02:00
|
|
|
} else {
|
|
|
|
|
None
|
2022-10-26 15:26:07 +02:00
|
|
|
}
|
2023-04-19 11:42:46 +02:00
|
|
|
} else {
|
|
|
|
|
None
|
|
|
|
|
};
|
2022-10-26 15:26:07 +02:00
|
|
|
|
2023-10-19 12:03:45 -07:00
|
|
|
handle.unset_grab(state, serial, time, true);
|
2023-07-18 12:21:16 +02:00
|
|
|
|
|
|
|
|
{
|
|
|
|
|
let cursor_state = self.seat.user_data().get::<CursorState>().unwrap();
|
|
|
|
|
cursor_state.set_shape(CursorShape::Default);
|
|
|
|
|
}
|
|
|
|
|
|
2023-07-24 21:14:34 +02:00
|
|
|
if let Some((mapped, position)) = position {
|
|
|
|
|
handle.motion(
|
|
|
|
|
state,
|
|
|
|
|
Some((
|
|
|
|
|
PointerFocusTarget::from(mapped.clone()),
|
2023-10-25 19:24:51 +02:00
|
|
|
position.as_logical() - self.window.geometry().loc,
|
2023-07-24 21:14:34 +02:00
|
|
|
)),
|
|
|
|
|
&MotionEvent {
|
|
|
|
|
location: handle.current_location(),
|
|
|
|
|
serial,
|
|
|
|
|
time,
|
|
|
|
|
},
|
|
|
|
|
);
|
2022-10-26 15:26:07 +02:00
|
|
|
Common::set_focus(
|
|
|
|
|
state,
|
2023-07-24 21:14:34 +02:00
|
|
|
Some(&KeyboardFocusTarget::from(mapped)),
|
2022-10-26 15:26:07 +02:00
|
|
|
&self.seat,
|
|
|
|
|
Some(serial),
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|