Skip to content

Commit

Permalink
touch wip
Browse files Browse the repository at this point in the history
  • Loading branch information
cmeissl committed Feb 13, 2024
1 parent 91e61f1 commit 846b662
Show file tree
Hide file tree
Showing 38 changed files with 2,807 additions and 1,066 deletions.
402 changes: 316 additions & 86 deletions anvil/src/focus.rs

Large diffs are not rendered by default.

222 changes: 180 additions & 42 deletions anvil/src/input_handler.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::{convert::TryInto, process::Command, sync::atomic::Ordering};

use crate::{
focus::FocusTarget,
focus::PointerFocusTarget,
shell::{FullscreenSurface, WindowElement},
AnvilState,
};
Expand Down Expand Up @@ -52,14 +52,17 @@ use smithay::{
input::{
Device, DeviceCapability, GestureBeginEvent, GestureEndEvent, GesturePinchUpdateEvent as _,
GestureSwipeUpdateEvent as _, PointerMotionEvent, ProximityState, TabletToolButtonEvent,
TabletToolEvent, TabletToolProximityEvent, TabletToolTipEvent, TabletToolTipState,
TabletToolEvent, TabletToolProximityEvent, TabletToolTipEvent, TabletToolTipState, TouchEvent,
},
session::Session,
},
input::pointer::{
GestureHoldBeginEvent, GestureHoldEndEvent, GesturePinchBeginEvent, GesturePinchEndEvent,
GesturePinchUpdateEvent, GestureSwipeBeginEvent, GestureSwipeEndEvent, GestureSwipeUpdateEvent,
RelativeMotionEvent,
input::{
pointer::{
GestureHoldBeginEvent, GestureHoldEndEvent, GesturePinchBeginEvent, GesturePinchEndEvent,
GesturePinchUpdateEvent, GestureSwipeBeginEvent, GestureSwipeEndEvent, GestureSwipeUpdateEvent,
RelativeMotionEvent,
},
touch::{DownEvent, UpEvent},
},
wayland::{
pointer_constraints::{with_pointer_constraint, PointerConstraint},
Expand Down Expand Up @@ -240,7 +243,7 @@ impl<BackendData: Backend> AnvilState<BackendData> {
let state = wl_pointer::ButtonState::from(evt.state());

if wl_pointer::ButtonState::Pressed == state {
self.update_keyboard_focus(serial);
self.update_keyboard_focus(self.pointer.current_location(), serial);
};
let pointer = self.pointer.clone();
pointer.button(
Expand All @@ -255,8 +258,9 @@ impl<BackendData: Backend> AnvilState<BackendData> {
pointer.frame(self);
}

fn update_keyboard_focus(&mut self, serial: Serial) {
fn update_keyboard_focus(&mut self, location: Point<f64, Logical>, serial: Serial) {
let keyboard = self.seat.get_keyboard().unwrap();
let touch = self.seat.get_touch();
let input_method = self.seat.input_method();
// change the keyboard focus unless the pointer or keyboard is grabbed
// We test for any matching surface type here but always use the root
Expand All @@ -267,23 +271,21 @@ impl<BackendData: Backend> AnvilState<BackendData> {
// subsurface menus (for example firefox-wayland).
// see here for a discussion about that issue:
// https://gitlab.freedesktop.org/wayland/wayland/-/issues/294
if !self.pointer.is_grabbed() && (!keyboard.is_grabbed() || input_method.keyboard_grabbed()) {
let output = self
.space
.output_under(self.pointer.current_location())
.next()
.cloned();
if !self.pointer.is_grabbed()
&& (!keyboard.is_grabbed() || input_method.keyboard_grabbed())
&& !touch.map(|touch| touch.is_grabbed()).unwrap_or(false)
{
let output = self.space.output_under(location).next().cloned();
if let Some(output) = output.as_ref() {
let output_geo = self.space.output_geometry(output).unwrap();
if let Some(window) = output
.user_data()
.get::<FullscreenSurface>()
.and_then(|f| f.get())
{
if let Some((_, _)) = window.surface_under(
self.pointer.current_location() - output_geo.loc.to_f64(),
WindowSurfaceType::ALL,
) {
if let Some((_, _)) =
window.surface_under(location - output_geo.loc.to_f64(), WindowSurfaceType::ALL)
{
#[cfg(feature = "xwayland")]
if let WindowElement::X11(surf) = &window {
self.xwm.as_mut().unwrap().raise_window(surf).unwrap();
Expand All @@ -295,12 +297,12 @@ impl<BackendData: Backend> AnvilState<BackendData> {

let layers = layer_map_for_output(output);
if let Some(layer) = layers
.layer_under(WlrLayer::Overlay, self.pointer.current_location())
.or_else(|| layers.layer_under(WlrLayer::Top, self.pointer.current_location()))
.layer_under(WlrLayer::Overlay, location)
.or_else(|| layers.layer_under(WlrLayer::Top, location))
{
if layer.can_receive_keyboard_focus() {
if let Some((_, _)) = layer.surface_under(
self.pointer.current_location()
location
- output_geo.loc.to_f64()
- layers.layer_geometry(layer).unwrap().loc.to_f64(),
WindowSurfaceType::ALL,
Expand All @@ -312,30 +314,26 @@ impl<BackendData: Backend> AnvilState<BackendData> {
}
}

if let Some((window, _)) = self
.space
.element_under(self.pointer.current_location())
.map(|(w, p)| (w.clone(), p))
{
if let Some((window, _)) = self.space.element_under(location).map(|(w, p)| (w.clone(), p)) {
self.space.raise_element(&window, true);
keyboard.set_focus(self, Some(window.clone().into()), serial);
#[cfg(feature = "xwayland")]
if let WindowElement::X11(surf) = &window {
self.xwm.as_mut().unwrap().raise_window(surf).unwrap();
}
keyboard.set_focus(self, Some(window.into()), serial);
return;
}

if let Some(output) = output.as_ref() {
let output_geo = self.space.output_geometry(output).unwrap();
let layers = layer_map_for_output(output);
if let Some(layer) = layers
.layer_under(WlrLayer::Bottom, self.pointer.current_location())
.or_else(|| layers.layer_under(WlrLayer::Background, self.pointer.current_location()))
.layer_under(WlrLayer::Bottom, location)
.or_else(|| layers.layer_under(WlrLayer::Background, location))
{
if layer.can_receive_keyboard_focus() {
if let Some((_, _)) = layer.surface_under(
self.pointer.current_location()
location
- output_geo.loc.to_f64()
- layers.layer_geometry(layer).unwrap().loc.to_f64(),
WindowSurfaceType::ALL,
Expand All @@ -348,7 +346,10 @@ impl<BackendData: Backend> AnvilState<BackendData> {
}
}

pub fn surface_under(&self, pos: Point<f64, Logical>) -> Option<(FocusTarget, Point<i32, Logical>)> {
pub fn surface_under(
&self,
pos: Point<f64, Logical>,
) -> Option<(PointerFocusTarget, Point<i32, Logical>)> {
let output = self.space.outputs().find(|o| {
let geometry = self.space.output_geometry(o).unwrap();
geometry.contains(pos.to_i32_round())
Expand All @@ -357,26 +358,57 @@ impl<BackendData: Backend> AnvilState<BackendData> {
let layers = layer_map_for_output(output);

let mut under = None;
if let Some(window) = output
if let Some((surface, loc)) = output
.user_data()
.get::<FullscreenSurface>()
.and_then(|f| f.get())
.and_then(|w| w.surface_under(pos - output_geo.loc.to_f64(), WindowSurfaceType::ALL))
{
under = Some((window.into(), output_geo.loc));
} else if let Some(layer) = layers
under = Some((surface, loc + output_geo.loc));
} else if let Some(focus) = layers
.layer_under(WlrLayer::Overlay, pos)
.or_else(|| layers.layer_under(WlrLayer::Top, pos))
.and_then(|layer| {
let layer_loc = layers.layer_geometry(layer).unwrap().loc;
layer
.surface_under(
pos - output_geo.loc.to_f64() - layer_loc.to_f64(),
WindowSurfaceType::ALL,
)
.map(|(surface, loc)| {
(
PointerFocusTarget::from(surface),
loc + layer_loc + output_geo.loc,
)
})
})
{
let layer_loc = layers.layer_geometry(layer).unwrap().loc;
under = Some((layer.clone().into(), output_geo.loc + layer_loc))
} else if let Some((window, location)) = self.space.element_under(pos) {
under = Some((window.clone().into(), location));
} else if let Some(layer) = layers
under = Some(focus)
} else if let Some(focus) = self.space.element_under(pos).and_then(|(window, loc)| {
window
.surface_under(pos - loc.to_f64(), WindowSurfaceType::ALL)
.map(|(surface, surf_loc)| (surface, surf_loc + loc))
}) {
under = Some(focus);
} else if let Some(focus) = layers
.layer_under(WlrLayer::Bottom, pos)
.or_else(|| layers.layer_under(WlrLayer::Background, pos))
.and_then(|layer| {
let layer_loc = layers.layer_geometry(layer).unwrap().loc;
layer
.surface_under(
pos - output_geo.loc.to_f64() - layer_loc.to_f64(),
WindowSurfaceType::ALL,
)
.map(|(surface, loc)| {
(
PointerFocusTarget::from(surface),
loc + layer_loc + output_geo.loc,
)
})
})
{
let layer_loc = layers.layer_geometry(layer).unwrap().loc;
under = Some((layer.clone().into(), output_geo.loc + layer_loc));
under = Some(focus)
};
under
}
Expand Down Expand Up @@ -731,12 +763,22 @@ impl AnvilState<UdevData> {
InputEvent::GesturePinchEnd { event, .. } => self.on_gesture_pinch_end::<B>(event),
InputEvent::GestureHoldBegin { event, .. } => self.on_gesture_hold_begin::<B>(event),
InputEvent::GestureHoldEnd { event, .. } => self.on_gesture_hold_end::<B>(event),

InputEvent::TouchDown { event } => self.on_touch_down::<B>(event),
InputEvent::TouchUp { event } => self.on_touch_up::<B>(event),
InputEvent::TouchMotion { event } => self.on_touch_motion::<B>(event),
InputEvent::TouchFrame { event } => self.on_touch_frame::<B>(event),
InputEvent::TouchCancel { event } => self.on_touch_cancel::<B>(event),

InputEvent::DeviceAdded { device } => {
if device.has_capability(DeviceCapability::TabletTool) {
self.seat
.tablet_seat()
.add_tablet::<Self>(dh, &TabletDescriptor::from(&device));
}
if device.has_capability(DeviceCapability::Touch) && self.seat.get_touch().is_none() {
self.seat.add_touch();
}
}
InputEvent::DeviceRemoved { device } => {
if device.has_capability(DeviceCapability::TabletTool) {
Expand Down Expand Up @@ -1024,7 +1066,7 @@ impl AnvilState<UdevData> {
tool.tip_down(serial, evt.time_msec());

// change the keyboard focus
self.update_keyboard_focus(serial);
self.update_keyboard_focus(self.pointer.current_location(), serial);
}
TabletToolTipState::Up => {
tool.tip_up(evt.time_msec());
Expand Down Expand Up @@ -1148,6 +1190,102 @@ impl AnvilState<UdevData> {
);
}

fn touch_location_transformed<B: InputBackend, E: AbsolutePositionEvent<B>>(
&self,
evt: &E,
) -> Option<Point<f64, Logical>> {
let output = self
.space
.outputs()
.find(|output| output.name().starts_with("eDP"))
.or_else(|| self.space.outputs().next());

let Some(output) = output else {
return None;
};

let Some(output_geometry) = self.space.output_geometry(output) else {
return None;
};

let transform = output.current_transform();
let size = transform.invert().transform_size(output_geometry.size);
Some(
transform.transform_point_in(evt.position_transformed(size), &size.to_f64())
+ output_geometry.loc.to_f64(),
)
}

fn on_touch_down<B: InputBackend>(&mut self, evt: B::TouchDownEvent) {
let Some(handle) = self.seat.get_touch() else {
return;
};

let Some(touch_location) = self.touch_location_transformed(&evt) else {
return;
};

let serial = SCOUNTER.next_serial();
self.update_keyboard_focus(touch_location, serial);

let under = self.surface_under(touch_location);
handle.down(
self,
under,
&DownEvent {
slot: evt.slot(),
location: touch_location,
serial,
time: evt.time_msec(),
},
);
}
fn on_touch_up<B: InputBackend>(&mut self, evt: B::TouchUpEvent) {
let Some(handle) = self.seat.get_touch() else {
return;
};
let serial = SCOUNTER.next_serial();
handle.up(
self,
&UpEvent {
slot: evt.slot(),
serial,
time: evt.time_msec(),
},
)
}
fn on_touch_motion<B: InputBackend>(&mut self, evt: B::TouchMotionEvent) {
let Some(handle) = self.seat.get_touch() else {
return;
};
let Some(touch_location) = self.touch_location_transformed(&evt) else {
return;
};

let under = self.surface_under(touch_location);
handle.motion(
self,
under,
&smithay::input::touch::MotionEvent {
slot: evt.slot(),
location: touch_location,
time: evt.time_msec(),
},
);
}
fn on_touch_frame<B: InputBackend>(&mut self, _evt: B::TouchFrameEvent) {
let Some(handle) = self.seat.get_touch() else {
return;
};
handle.frame(self);
}
fn on_touch_cancel<B: InputBackend>(&mut self, _evt: B::TouchCancelEvent) {
let Some(handle) = self.seat.get_touch() else {
return;
};
handle.cancel(self);
}

fn clamp_coords(&self, pos: Point<f64, Logical>) -> Point<f64, Logical> {
if self.space.outputs().next().is_none() {
return pos;
Expand Down
Loading

0 comments on commit 846b662

Please sign in to comment.