shell: Touch support for move grab
Touch support is still needed for other grabs. And SSDs (and libcosmic) need to start move/menu/etc. based on touch.
This commit is contained in:
parent
895ea6aec1
commit
b18a3a8bc7
5 changed files with 208 additions and 83 deletions
|
|
@ -1378,6 +1378,16 @@ impl State {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
InputEvent::TouchUp { event, .. } => {
|
InputEvent::TouchUp { event, .. } => {
|
||||||
|
if let OverviewMode::Started(Trigger::Touch(slot), _) =
|
||||||
|
self.common.shell.overview_mode().0
|
||||||
|
{
|
||||||
|
if slot == event.slot() {
|
||||||
|
self.common
|
||||||
|
.shell
|
||||||
|
.set_overview_mode(None, self.common.event_loop_handle.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(seat) = self.common.seat_with_device(&event.device()) {
|
if let Some(seat) = self.common.seat_with_device(&event.device()) {
|
||||||
let serial = SERIAL_COUNTER.next_serial();
|
let serial = SERIAL_COUNTER.next_serial();
|
||||||
let touch = seat.get_touch().unwrap();
|
let touch = seat.get_touch().unwrap();
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,13 @@
|
||||||
use smithay::{
|
use smithay::{
|
||||||
input::pointer::{
|
input::{
|
||||||
AxisFrame, ButtonEvent, GestureHoldBeginEvent, GestureHoldEndEvent, GesturePinchBeginEvent,
|
pointer::{
|
||||||
GesturePinchEndEvent, GesturePinchUpdateEvent, GestureSwipeBeginEvent,
|
AxisFrame, ButtonEvent, GestureHoldBeginEvent, GestureHoldEndEvent,
|
||||||
GestureSwipeEndEvent, GestureSwipeUpdateEvent, GrabStartData as PointerGrabStartData,
|
GesturePinchBeginEvent, GesturePinchEndEvent, GesturePinchUpdateEvent,
|
||||||
MotionEvent, PointerGrab, PointerInnerHandle, RelativeMotionEvent,
|
GestureSwipeBeginEvent, GestureSwipeEndEvent, GestureSwipeUpdateEvent,
|
||||||
|
GrabStartData as PointerGrabStartData, MotionEvent, PointerGrab, PointerInnerHandle,
|
||||||
|
RelativeMotionEvent,
|
||||||
|
},
|
||||||
|
touch::GrabStartData as TouchGrabStartData,
|
||||||
},
|
},
|
||||||
reexports::wayland_protocols::xdg::shell::server::xdg_toplevel,
|
reexports::wayland_protocols::xdg::shell::server::xdg_toplevel,
|
||||||
utils::{Logical, Point},
|
utils::{Logical, Point},
|
||||||
|
|
@ -17,6 +21,35 @@ use super::{
|
||||||
layout::{floating::ResizeSurfaceGrab, tiling::ResizeForkGrab},
|
layout::{floating::ResizeSurfaceGrab, tiling::ResizeForkGrab},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub enum GrabStartData {
|
||||||
|
Touch(TouchGrabStartData<State>),
|
||||||
|
Pointer(PointerGrabStartData<State>),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GrabStartData {
|
||||||
|
pub fn focus(&self) -> Option<&(PointerFocusTarget, Point<i32, Logical>)> {
|
||||||
|
match self {
|
||||||
|
Self::Touch(touch) => touch.focus.as_ref(),
|
||||||
|
Self::Pointer(pointer) => pointer.focus.as_ref(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_focus(&mut self, focus: Option<(PointerFocusTarget, Point<i32, Logical>)>) {
|
||||||
|
match self {
|
||||||
|
Self::Touch(touch) => touch.focus = focus,
|
||||||
|
Self::Pointer(pointer) => pointer.focus = focus,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn location(&self) -> Point<f64, Logical> {
|
||||||
|
match self {
|
||||||
|
Self::Touch(touch) => touch.location,
|
||||||
|
Self::Pointer(pointer) => pointer.location,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
pub enum ReleaseMode {
|
pub enum ReleaseMode {
|
||||||
Click,
|
Click,
|
||||||
|
|
|
||||||
|
|
@ -37,14 +37,15 @@ use smithay::{
|
||||||
GrabStartData as PointerGrabStartData, MotionEvent, PointerGrab, PointerInnerHandle,
|
GrabStartData as PointerGrabStartData, MotionEvent, PointerGrab, PointerInnerHandle,
|
||||||
RelativeMotionEvent,
|
RelativeMotionEvent,
|
||||||
},
|
},
|
||||||
|
touch::{self, GrabStartData as TouchGrabStartData, TouchGrab, TouchInnerHandle},
|
||||||
Seat,
|
Seat,
|
||||||
},
|
},
|
||||||
output::Output,
|
output::Output,
|
||||||
utils::{IsAlive, Logical, Point, Rectangle, Scale, SERIAL_COUNTER},
|
utils::{IsAlive, Logical, Point, Rectangle, Scale, Serial, SERIAL_COUNTER},
|
||||||
};
|
};
|
||||||
use std::{cell::RefCell, collections::HashSet, sync::atomic::Ordering, time::Instant};
|
use std::{cell::RefCell, collections::HashSet, sync::atomic::Ordering, time::Instant};
|
||||||
|
|
||||||
use super::ReleaseMode;
|
use super::{GrabStartData, ReleaseMode};
|
||||||
|
|
||||||
pub type SeatMoveGrabState = RefCell<Option<MoveGrabState>>;
|
pub type SeatMoveGrabState = RefCell<Option<MoveGrabState>>;
|
||||||
|
|
||||||
|
|
@ -58,6 +59,7 @@ pub struct MoveGrabState {
|
||||||
previous: ManagedLayer,
|
previous: ManagedLayer,
|
||||||
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>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MoveGrabState {
|
impl MoveGrabState {
|
||||||
|
|
@ -90,10 +92,8 @@ impl MoveGrabState {
|
||||||
0.4
|
0.4
|
||||||
};
|
};
|
||||||
|
|
||||||
let cursor_at = seat.get_pointer().unwrap().current_location();
|
|
||||||
|
|
||||||
let mut window_geo = self.window.geometry();
|
let mut window_geo = self.window.geometry();
|
||||||
window_geo.loc += cursor_at.to_i32_round() + self.window_offset;
|
window_geo.loc += self.location.to_i32_round() + self.window_offset;
|
||||||
if !output
|
if !output
|
||||||
.geometry()
|
.geometry()
|
||||||
.as_logical()
|
.as_logical()
|
||||||
|
|
@ -106,7 +106,7 @@ impl MoveGrabState {
|
||||||
let output_scale: Scale<f64> = output.current_scale().fractional_scale().into();
|
let output_scale: Scale<f64> = output.current_scale().fractional_scale().into();
|
||||||
let scaling_offset =
|
let scaling_offset =
|
||||||
self.window_offset - self.window_offset.to_f64().upscale(scale).to_i32_round();
|
self.window_offset - self.window_offset.to_f64().upscale(scale).to_i32_round();
|
||||||
let render_location = cursor_at.to_i32_round() - output.geometry().loc.as_logical()
|
let render_location = self.location.to_i32_round() - output.geometry().loc.as_logical()
|
||||||
+ self.window_offset
|
+ self.window_offset
|
||||||
- scaling_offset;
|
- scaling_offset;
|
||||||
|
|
||||||
|
|
@ -319,7 +319,7 @@ impl SnappingZone {
|
||||||
|
|
||||||
pub struct MoveGrab {
|
pub struct MoveGrab {
|
||||||
window: CosmicMapped,
|
window: CosmicMapped,
|
||||||
start_data: PointerGrabStartData<State>,
|
start_data: GrabStartData,
|
||||||
seat: Seat<State>,
|
seat: Seat<State>,
|
||||||
cursor_output: Output,
|
cursor_output: Output,
|
||||||
window_outputs: HashSet<Output>,
|
window_outputs: HashSet<Output>,
|
||||||
|
|
@ -329,28 +329,19 @@ pub struct MoveGrab {
|
||||||
evlh: NotSend<LoopHandle<'static, State>>,
|
evlh: NotSend<LoopHandle<'static, State>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PointerGrab<State> for MoveGrab {
|
impl MoveGrab {
|
||||||
fn motion(
|
fn update_location(&mut self, state: &mut State, location: Point<f64, Logical>) {
|
||||||
&mut self,
|
let Some(current_output) =
|
||||||
state: &mut State,
|
state
|
||||||
handle: &mut PointerInnerHandle<'_, State>,
|
.common
|
||||||
_focus: Option<(PointerFocusTarget, Point<i32, Logical>)>,
|
.shell
|
||||||
event: &MotionEvent,
|
.outputs()
|
||||||
) {
|
.find(|output| {
|
||||||
let Some(current_output) = state
|
output.geometry().as_logical().overlaps_or_touches(
|
||||||
.common
|
Rectangle::from_loc_and_size(location.to_i32_floor(), (0, 0)),
|
||||||
.shell
|
)
|
||||||
.outputs()
|
})
|
||||||
.find(|output| {
|
.cloned()
|
||||||
output
|
|
||||||
.geometry()
|
|
||||||
.as_logical()
|
|
||||||
.overlaps_or_touches(Rectangle::from_loc_and_size(
|
|
||||||
handle.current_location().to_i32_floor(),
|
|
||||||
(0, 0),
|
|
||||||
))
|
|
||||||
})
|
|
||||||
.cloned()
|
|
||||||
else {
|
else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
@ -371,8 +362,10 @@ impl PointerGrab<State> for MoveGrab {
|
||||||
.get::<SeatMoveGrabState>()
|
.get::<SeatMoveGrabState>()
|
||||||
.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;
|
||||||
|
|
||||||
let mut window_geo = self.window.geometry();
|
let mut window_geo = self.window.geometry();
|
||||||
window_geo.loc += event.location.to_i32_round() + grab_state.window_offset;
|
window_geo.loc += location.to_i32_round() + grab_state.window_offset;
|
||||||
for output in state.common.shell.outputs() {
|
for output in state.common.shell.outputs() {
|
||||||
if let Some(overlap) = output.geometry().as_logical().intersection(window_geo) {
|
if let Some(overlap) = output.geometry().as_logical().intersection(window_geo) {
|
||||||
if self.window_outputs.insert(output.clone()) {
|
if self.window_outputs.insert(output.clone()) {
|
||||||
|
|
@ -432,8 +425,7 @@ impl PointerGrab<State> for MoveGrab {
|
||||||
.iter()
|
.iter()
|
||||||
.find(|&x| {
|
.find(|&x| {
|
||||||
x.contains(
|
x.contains(
|
||||||
handle
|
location
|
||||||
.current_location()
|
|
||||||
.as_global()
|
.as_global()
|
||||||
.to_local(¤t_output)
|
.to_local(¤t_output)
|
||||||
.to_i32_floor(),
|
.to_i32_floor(),
|
||||||
|
|
@ -444,6 +436,18 @@ impl PointerGrab<State> for MoveGrab {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
drop(borrow);
|
drop(borrow);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PointerGrab<State> for MoveGrab {
|
||||||
|
fn motion(
|
||||||
|
&mut self,
|
||||||
|
state: &mut State,
|
||||||
|
handle: &mut PointerInnerHandle<'_, State>,
|
||||||
|
_focus: Option<(PointerFocusTarget, Point<i32, Logical>)>,
|
||||||
|
event: &MotionEvent,
|
||||||
|
) {
|
||||||
|
self.update_location(state, event.location);
|
||||||
|
|
||||||
// While the grab is active, no client has pointer focus
|
// While the grab is active, no client has pointer focus
|
||||||
handle.motion(state, None, event);
|
handle.motion(state, None, event);
|
||||||
|
|
@ -570,16 +574,75 @@ impl PointerGrab<State> for MoveGrab {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn start_data(&self) -> &PointerGrabStartData<State> {
|
fn start_data(&self) -> &PointerGrabStartData<State> {
|
||||||
&self.start_data
|
match &self.start_data {
|
||||||
|
GrabStartData::Pointer(start_data) => start_data,
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TouchGrab<State> for MoveGrab {
|
||||||
|
fn down(
|
||||||
|
&mut self,
|
||||||
|
data: &mut State,
|
||||||
|
handle: &mut TouchInnerHandle<'_, State>,
|
||||||
|
_focus: Option<(PointerFocusTarget, Point<i32, Logical>)>,
|
||||||
|
event: &touch::DownEvent,
|
||||||
|
seq: Serial,
|
||||||
|
) {
|
||||||
|
handle.down(data, None, event, seq)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn up(
|
||||||
|
&mut self,
|
||||||
|
data: &mut State,
|
||||||
|
handle: &mut TouchInnerHandle<'_, State>,
|
||||||
|
event: &touch::UpEvent,
|
||||||
|
seq: Serial,
|
||||||
|
) {
|
||||||
|
if event.slot == <Self as TouchGrab<State>>::start_data(self).slot {
|
||||||
|
handle.unset_grab(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
handle.up(data, event, seq);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn motion(
|
||||||
|
&mut self,
|
||||||
|
data: &mut State,
|
||||||
|
handle: &mut TouchInnerHandle<'_, State>,
|
||||||
|
_focus: Option<(PointerFocusTarget, Point<i32, Logical>)>,
|
||||||
|
event: &touch::MotionEvent,
|
||||||
|
seq: Serial,
|
||||||
|
) {
|
||||||
|
if event.slot == <Self as TouchGrab<State>>::start_data(self).slot {
|
||||||
|
self.update_location(data, event.location);
|
||||||
|
}
|
||||||
|
|
||||||
|
handle.motion(data, None, event, seq);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn frame(&mut self, data: &mut State, handle: &mut TouchInnerHandle<'_, State>, seq: Serial) {
|
||||||
|
handle.frame(data, seq)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn cancel(&mut self, data: &mut State, handle: &mut TouchInnerHandle<'_, State>, _seq: Serial) {
|
||||||
|
handle.unset_grab(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn start_data(&self) -> &TouchGrabStartData<State> {
|
||||||
|
match &self.start_data {
|
||||||
|
GrabStartData::Touch(start_data) => start_data,
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MoveGrab {
|
impl MoveGrab {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
start_data: PointerGrabStartData<State>,
|
start_data: GrabStartData,
|
||||||
window: CosmicMapped,
|
window: CosmicMapped,
|
||||||
seat: &Seat<State>,
|
seat: &Seat<State>,
|
||||||
initial_cursor_location: Point<f64, Global>,
|
|
||||||
initial_window_location: Point<i32, Global>,
|
initial_window_location: Point<i32, Global>,
|
||||||
indicator_thickness: u8,
|
indicator_thickness: u8,
|
||||||
previous_layer: ManagedLayer,
|
previous_layer: ManagedLayer,
|
||||||
|
|
@ -594,13 +657,15 @@ impl MoveGrab {
|
||||||
|
|
||||||
let grab_state = MoveGrabState {
|
let grab_state = MoveGrabState {
|
||||||
window: window.clone(),
|
window: window.clone(),
|
||||||
window_offset: (initial_window_location - initial_cursor_location.to_i32_round())
|
window_offset: (initial_window_location
|
||||||
.as_logical(),
|
- start_data.location().as_global().to_i32_round())
|
||||||
|
.as_logical(),
|
||||||
indicator_thickness,
|
indicator_thickness,
|
||||||
start: Instant::now(),
|
start: Instant::now(),
|
||||||
stacking_indicator: None,
|
stacking_indicator: None,
|
||||||
snapping_zone: None,
|
snapping_zone: None,
|
||||||
previous: previous_layer,
|
previous: previous_layer,
|
||||||
|
location: start_data.location(),
|
||||||
};
|
};
|
||||||
|
|
||||||
*seat
|
*seat
|
||||||
|
|
|
||||||
|
|
@ -3234,7 +3234,10 @@ impl TilingLayout {
|
||||||
}
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
} else if matches!(overview, OverviewMode::Started(Trigger::Pointer(_), _)) {
|
} else if matches!(
|
||||||
|
overview,
|
||||||
|
OverviewMode::Started(Trigger::Pointer(_) | Trigger::Touch(_), _)
|
||||||
|
) {
|
||||||
let non_exclusive_zone = layer_map_for_output(&self.output)
|
let non_exclusive_zone = layer_map_for_output(&self.output)
|
||||||
.non_exclusive_zone()
|
.non_exclusive_zone()
|
||||||
.as_local();
|
.as_local();
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ use cosmic_protocols::workspace::v1::server::zcosmic_workspace_handle_v1::{
|
||||||
};
|
};
|
||||||
use keyframe::{ease, functions::EaseInOutCubic};
|
use keyframe::{ease, functions::EaseInOutCubic};
|
||||||
use smithay::{
|
use smithay::{
|
||||||
|
backend::input::TouchSlot,
|
||||||
desktop::{
|
desktop::{
|
||||||
layer_map_for_output, space::SpaceElement, LayerSurface, PopupKind, PopupManager,
|
layer_map_for_output, space::SpaceElement, LayerSurface, PopupKind, PopupManager,
|
||||||
WindowSurface, WindowSurfaceType,
|
WindowSurface, WindowSurfaceType,
|
||||||
|
|
@ -85,7 +86,8 @@ use self::{
|
||||||
FocusDirection,
|
FocusDirection,
|
||||||
},
|
},
|
||||||
grabs::{
|
grabs::{
|
||||||
tab_items, window_items, Item, MenuGrab, MoveGrab, ReleaseMode, ResizeEdge, ResizeGrab,
|
tab_items, window_items, GrabStartData, Item, MenuGrab, MoveGrab, ReleaseMode, ResizeEdge,
|
||||||
|
ResizeGrab,
|
||||||
},
|
},
|
||||||
layout::{
|
layout::{
|
||||||
floating::{FloatingLayout, ResizeState},
|
floating::{FloatingLayout, ResizeState},
|
||||||
|
|
@ -103,6 +105,7 @@ pub enum Trigger {
|
||||||
KeyboardSwap(KeyPattern, NodeDesc),
|
KeyboardSwap(KeyPattern, NodeDesc),
|
||||||
KeyboardMove(KeyModifiers),
|
KeyboardMove(KeyModifiers),
|
||||||
Pointer(u32),
|
Pointer(u32),
|
||||||
|
Touch(TouchSlot),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
|
@ -1180,7 +1183,7 @@ impl Shell {
|
||||||
if let Some(set) = self.workspaces.sets.get_mut(output) {
|
if let Some(set) = self.workspaces.sets.get_mut(output) {
|
||||||
if matches!(
|
if matches!(
|
||||||
self.overview_mode,
|
self.overview_mode,
|
||||||
OverviewMode::Started(Trigger::Pointer(_), _)
|
OverviewMode::Started(Trigger::Pointer(_) | Trigger::Touch(_), _)
|
||||||
) {
|
) {
|
||||||
set.workspaces[set.active].tiling_layer.cleanup_drag();
|
set.workspaces[set.active].tiling_layer.cleanup_drag();
|
||||||
}
|
}
|
||||||
|
|
@ -1229,7 +1232,7 @@ impl Shell {
|
||||||
if let Some(set) = self.workspaces.sets.get_mut(output) {
|
if let Some(set) = self.workspaces.sets.get_mut(output) {
|
||||||
if matches!(
|
if matches!(
|
||||||
self.overview_mode,
|
self.overview_mode,
|
||||||
OverviewMode::Started(Trigger::Pointer(_), _)
|
OverviewMode::Started(Trigger::Pointer(_) | Trigger::Touch(_), _)
|
||||||
) {
|
) {
|
||||||
set.workspaces[set.active].tiling_layer.cleanup_drag();
|
set.workspaces[set.active].tiling_layer.cleanup_drag();
|
||||||
}
|
}
|
||||||
|
|
@ -2338,7 +2341,7 @@ impl Shell {
|
||||||
target_stack: bool,
|
target_stack: bool,
|
||||||
) {
|
) {
|
||||||
let serial = serial.into();
|
let serial = serial.into();
|
||||||
if let Some(start_data) =
|
if let Some(GrabStartData::Pointer(start_data)) =
|
||||||
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_surface(surface).cloned() {
|
if let Some(mapped) = state.common.shell.element_for_surface(surface).cloned() {
|
||||||
|
|
@ -2485,20 +2488,22 @@ impl Shell {
|
||||||
state.common.theme.clone(),
|
state.common.theme.clone(),
|
||||||
)
|
)
|
||||||
.into();
|
.into();
|
||||||
start_data.focus = new_mapped.focus_under((0., 0.).into());
|
start_data.set_focus(new_mapped.focus_under((0., 0.).into()));
|
||||||
new_mapped
|
new_mapped
|
||||||
} else {
|
} else {
|
||||||
old_mapped.clone()
|
old_mapped.clone()
|
||||||
};
|
};
|
||||||
|
|
||||||
let button = start_data.button;
|
let trigger = match &start_data {
|
||||||
|
GrabStartData::Pointer(start_data) => Trigger::Pointer(start_data.button),
|
||||||
|
GrabStartData::Touch(start_data) => Trigger::Touch(start_data.slot),
|
||||||
|
};
|
||||||
let active_hint = if state.common.config.cosmic_conf.active_hint {
|
let active_hint = if state.common.config.cosmic_conf.active_hint {
|
||||||
state.common.theme.cosmic().active_hint as u8
|
state.common.theme.cosmic().active_hint as u8
|
||||||
} else {
|
} else {
|
||||||
0
|
0
|
||||||
};
|
};
|
||||||
let pointer = seat.get_pointer().unwrap();
|
let pos = start_data.location().as_global();
|
||||||
let pos = pointer.current_location().as_global();
|
|
||||||
|
|
||||||
let (initial_window_location, layer, workspace_handle) =
|
let (initial_window_location, layer, workspace_handle) =
|
||||||
if let Some(workspace) = state.common.shell.space_for_mut(&old_mapped) {
|
if let Some(workspace) = state.common.shell.space_for_mut(&old_mapped) {
|
||||||
|
|
@ -2608,11 +2613,12 @@ impl Shell {
|
||||||
.refresh(&state.common.shell.xdg_activation_state);
|
.refresh(&state.common.shell.xdg_activation_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let is_touch_grab = matches!(start_data, GrabStartData::Touch(_));
|
||||||
|
|
||||||
let grab = MoveGrab::new(
|
let grab = MoveGrab::new(
|
||||||
start_data,
|
start_data,
|
||||||
mapped,
|
mapped,
|
||||||
seat,
|
seat,
|
||||||
pos,
|
|
||||||
initial_window_location,
|
initial_window_location,
|
||||||
active_hint as u8,
|
active_hint as u8,
|
||||||
layer,
|
layer,
|
||||||
|
|
@ -2621,18 +2627,26 @@ impl Shell {
|
||||||
);
|
);
|
||||||
|
|
||||||
if grab.is_tiling_grab() {
|
if grab.is_tiling_grab() {
|
||||||
state.common.shell.set_overview_mode(
|
state
|
||||||
Some(Trigger::Pointer(button)),
|
.common
|
||||||
state.common.event_loop_handle.clone(),
|
.shell
|
||||||
);
|
.set_overview_mode(Some(trigger), state.common.event_loop_handle.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
seat.get_pointer().unwrap().set_grab(
|
if is_touch_grab {
|
||||||
state,
|
seat.get_touch().unwrap().set_grab(
|
||||||
grab,
|
state,
|
||||||
serial.unwrap_or_else(|| SERIAL_COUNTER.next_serial()),
|
grab,
|
||||||
Focus::Clear,
|
serial.unwrap_or_else(|| SERIAL_COUNTER.next_serial()),
|
||||||
);
|
);
|
||||||
|
} else {
|
||||||
|
seat.get_pointer().unwrap().set_grab(
|
||||||
|
state,
|
||||||
|
grab,
|
||||||
|
serial.unwrap_or_else(|| SERIAL_COUNTER.next_serial()),
|
||||||
|
Focus::Clear,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -2828,7 +2842,7 @@ impl Shell {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(mut start_data) =
|
if let Some(GrabStartData::Pointer(mut start_data)) =
|
||||||
check_grab_preconditions(&seat, &surface, None, ReleaseMode::Click)
|
check_grab_preconditions(&seat, &surface, None, ReleaseMode::Click)
|
||||||
{
|
{
|
||||||
let (floating_layer, geometry) = if let Some(set) = state
|
let (floating_layer, geometry) = if let Some(set) = state
|
||||||
|
|
@ -3086,7 +3100,7 @@ impl Shell {
|
||||||
edges: ResizeEdge,
|
edges: ResizeEdge,
|
||||||
) {
|
) {
|
||||||
let serial = serial.into();
|
let serial = serial.into();
|
||||||
if let Some(start_data) =
|
if let Some(GrabStartData::Pointer(start_data)) =
|
||||||
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_surface(surface).cloned() {
|
if let Some(mapped) = state.common.shell.element_for_surface(surface).cloned() {
|
||||||
|
|
@ -3384,37 +3398,37 @@ pub fn check_grab_preconditions(
|
||||||
surface: &WlSurface,
|
surface: &WlSurface,
|
||||||
serial: Option<Serial>,
|
serial: Option<Serial>,
|
||||||
release: ReleaseMode,
|
release: ReleaseMode,
|
||||||
) -> Option<PointerGrabStartData<State>> {
|
) -> Option<GrabStartData> {
|
||||||
use smithay::reexports::wayland_server::Resource;
|
use smithay::reexports::wayland_server::Resource;
|
||||||
|
|
||||||
// TODO: touch resize.
|
|
||||||
let pointer = seat.get_pointer().unwrap();
|
let pointer = seat.get_pointer().unwrap();
|
||||||
|
let touch = seat.get_touch().unwrap();
|
||||||
|
|
||||||
let start_data = pointer
|
let start_data =
|
||||||
.grab_start_data()
|
if serial.map_or(false, |serial| touch.has_grab(serial)) {
|
||||||
.unwrap_or_else(|| PointerGrabStartData {
|
GrabStartData::Touch(touch.grab_start_data().unwrap())
|
||||||
focus: pointer.current_focus().map(|f| (f, Point::from((0, 0)))),
|
} else {
|
||||||
button: 0x110,
|
GrabStartData::Pointer(pointer.grab_start_data().unwrap_or_else(|| {
|
||||||
location: pointer.current_location(),
|
PointerGrabStartData {
|
||||||
});
|
focus: pointer.current_focus().map(|f| (f, Point::from((0, 0)))),
|
||||||
|
button: 0x110,
|
||||||
|
location: pointer.current_location(),
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
};
|
||||||
|
|
||||||
if release == ReleaseMode::NoMouseButtons {
|
if release == ReleaseMode::NoMouseButtons {
|
||||||
// Check that this surface has a click grab.
|
// Check that this surface has a click or touch down grab.
|
||||||
if !match serial {
|
if !match serial {
|
||||||
Some(serial) => pointer.has_grab(serial),
|
Some(serial) => pointer.has_grab(serial) || touch.has_grab(serial),
|
||||||
None => pointer.is_grabbed(),
|
None => pointer.is_grabbed() | touch.is_grabbed(),
|
||||||
} {
|
} {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the focus was for a different surface, ignore the request.
|
// If the focus was for a different surface, ignore the request.
|
||||||
if start_data.focus.is_none()
|
if start_data.focus().is_none()
|
||||||
|| !start_data
|
|| !start_data.focus().unwrap().0.same_client_as(&surface.id())
|
||||||
.focus
|
|
||||||
.as_ref()
|
|
||||||
.unwrap()
|
|
||||||
.0
|
|
||||||
.same_client_as(&surface.id())
|
|
||||||
{
|
{
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue