cosmic-comp/src/shell/layout/floating/grabs/moving.rs
Victoria Brekenfeld 7092c523f5 deps: Update smithay
- Use new GAT frame
- Bugfixes
- Finish window debug overlay
2022-11-28 17:50:41 +01:00

205 lines
6 KiB
Rust

// SPDX-License-Identifier: GPL-3.0-only
use crate::{
backend::render::element::AsGlowRenderer,
shell::{
element::{CosmicMapped, CosmicMappedRenderElement},
focus::target::{KeyboardFocusTarget, PointerFocusTarget},
},
utils::prelude::*,
};
use smithay::{
backend::renderer::{
element::{AsRenderElements, RenderElement},
ImportAll, Renderer,
},
desktop::space::SpaceElement,
input::{
pointer::{
AxisFrame, ButtonEvent, GrabStartData as PointerGrabStartData, MotionEvent,
PointerGrab, PointerInnerHandle,
},
Seat,
},
output::Output,
utils::{IsAlive, Logical, Point, Serial},
};
use std::cell::RefCell;
pub type SeatMoveGrabState = RefCell<Option<MoveGrabState>>;
pub struct MoveGrabState {
window: CosmicMapped,
initial_cursor_location: Point<f64, Logical>,
initial_window_location: Point<i32, Logical>,
}
impl MoveGrabState {
pub fn render<I, R>(&self, renderer: &mut R, seat: &Seat<State>, output: &Output) -> Vec<I>
where
R: Renderer + ImportAll + AsGlowRenderer,
<R as Renderer>::TextureId: 'static,
CosmicMappedRenderElement<R>: RenderElement<R>,
I: From<CosmicMappedRenderElement<R>>,
{
let cursor_at = seat.get_pointer().unwrap().current_location();
let delta = cursor_at - self.initial_cursor_location;
let location = self.initial_window_location.to_f64() + delta;
let mut window_geo = self.window.geometry();
window_geo.loc += location.to_i32_round();
if !output.geometry().intersection(window_geo).is_some() {
return Vec::new();
}
let scale = output.current_scale().fractional_scale().into();
AsRenderElements::<R>::render_elements::<I>(
&self.window,
renderer,
(location.to_i32_round() - output.geometry().loc - self.window.geometry().loc)
.to_physical_precise_round(scale),
scale,
)
}
}
pub struct MoveSurfaceGrab {
window: CosmicMapped,
start_data: PointerGrabStartData<State>,
seat: Seat<State>,
}
impl PointerGrab<State> for MoveSurfaceGrab {
fn motion(
&mut self,
state: &mut State,
handle: &mut PointerInnerHandle<'_, State>,
_focus: Option<(PointerFocusTarget, Point<i32, Logical>)>,
event: &MotionEvent,
) {
// 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);
}
}
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);
}
fn start_data(&self) -> &PointerGrabStartData<State> {
&self.start_data
}
}
impl MoveSurfaceGrab {
pub fn new(
start_data: PointerGrabStartData<State>,
window: CosmicMapped,
seat: &Seat<State>,
initial_cursor_location: Point<f64, Logical>,
initial_window_location: Point<i32, Logical>,
) -> MoveSurfaceGrab {
let grab_state = MoveGrabState {
window: window.clone(),
initial_cursor_location,
initial_window_location,
};
*seat
.user_data()
.get::<SeatMoveGrabState>()
.unwrap()
.borrow_mut() = Some(grab_state);
MoveSurfaceGrab {
window,
start_data,
seat: seat.clone(),
}
}
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();
if let Some(grab_state) = self
.seat
.user_data()
.get::<SeatMoveGrabState>()
.and_then(|s| s.borrow_mut().take())
{
if grab_state.window.alive() {
let delta = handle.current_location() - grab_state.initial_cursor_location;
let window_location = (grab_state.initial_window_location.to_f64() + delta)
.to_i32_round()
- output.geometry().loc;
let workspace_handle = state.common.shell.active_space(&output).handle;
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);
}
let offset = state
.common
.shell
.active_space(&output)
.floating_layer
.space
.output_geometry(&output)
.unwrap()
.loc;
state
.common
.shell
.active_space_mut(&output)
.floating_layer
.map_internal(grab_state.window, &output, Some(window_location + offset));
}
}
handle.unset_grab(state, serial, time);
if self.window.alive() {
Common::set_focus(
state,
Some(&KeyboardFocusTarget::from(self.window.clone())),
&self.seat,
Some(serial),
)
}
}
}