Skip to content

Commit

Permalink
Initial wl_touch support
Browse files Browse the repository at this point in the history
`builtin_output` is similar to `get_builtin_output_name` in Sway.

For full support, we need support for touch targets/grabs, touch support
for SSDs, and a way to configure what output is mapped to what input.

But this is usable for apps that support touch on a laptop with a
touchscreen.
  • Loading branch information
ids1024 committed Dec 21, 2023
1 parent aa9ec52 commit a52a602
Show file tree
Hide file tree
Showing 2 changed files with 104 additions and 5 deletions.
102 changes: 97 additions & 5 deletions src/input/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

use crate::{
backend::render::cursor::CursorState,
config::{xkb_config_to_wl, Action, Config, KeyPattern, KeyModifiers},
config::{xkb_config_to_wl, Action, Config, KeyModifiers, KeyPattern},
shell::{
focus::{target::PointerFocusTarget, FocusDirection},
grabs::{ResizeEdge, SeatMenuGrabState, SeatMoveGrabState},
Expand All @@ -25,9 +25,9 @@ use cosmic_comp_config::workspace::WorkspaceLayout;
use cosmic_protocols::screencopy::v1::server::zcosmic_screencopy_session_v1::InputType;
use smithay::{
backend::input::{
Axis, AxisSource, Device, DeviceCapability, GestureBeginEvent, GestureEndEvent,
GesturePinchUpdateEvent as _, GestureSwipeUpdateEvent as _, InputBackend, InputEvent,
KeyState, PointerAxisEvent,
AbsolutePositionEvent, Axis, AxisSource, Device, DeviceCapability, GestureBeginEvent,
GestureEndEvent, GesturePinchUpdateEvent as _, GestureSwipeUpdateEvent as _, InputBackend,
InputEvent, KeyState, PointerAxisEvent, TouchEvent,
},
desktop::{layer_map_for_output, space::SpaceElement, WindowSurfaceType},
input::{
Expand Down Expand Up @@ -205,6 +205,7 @@ pub fn add_seat(
.expect("Failed to load xkb configuration files");
}
seat.add_pointer();
seat.add_touch();

seat
}
Expand Down Expand Up @@ -1171,7 +1172,98 @@ impl State {
);
}
}
_ => { /* TODO e.g. tablet or touch events */ }
InputEvent::TouchDown { event, .. } => {
if let Some(seat) = self.common.seat_with_device(&event.device()).cloned() {
// TODO: Configuration option for mapping touch device to output
// Is it possible to determine mapping for external touchscreen?
let Some(output) = self.common.shell.builtin_output().cloned() else {
return;
};

let geometry = output.geometry();

let position = geometry.loc.to_f64()
+ event
.position_transformed(geometry.size.as_logical())
.as_global();

let overview = self.common.shell.overview_mode();
let workspace = self.common.shell.workspaces.active_mut(&output);
let under = State::surface_under(
position,
&output,
&self.common.shell.override_redirect_windows,
overview.0.clone(),
workspace,
self.common.shell.session_lock.as_ref(),
)
.map(|(target, pos)| (target, pos.as_logical()));

if let Some((target, pos)) = under {
if let Some(wl_surface) = target.wl_surface() {
let serial = SERIAL_COUNTER.next_serial();
let touch = seat.get_touch().unwrap();
touch.down(
serial,
event.time_msec(),
&wl_surface,
position.as_logical() - pos.to_f64(),
event.slot(),
);
}
}
}
}
InputEvent::TouchMotion { event, .. } => {
if let Some(seat) = self.common.seat_with_device(&event.device()).cloned() {
let Some(output) = self.common.shell.builtin_output().cloned() else {
return;
};

let geometry = output.geometry();

let position = geometry.loc.to_f64()
+ event
.position_transformed(geometry.size.as_logical())
.as_global();

let overview = self.common.shell.overview_mode();
let workspace = self.common.shell.workspaces.active_mut(&output);
let under = State::surface_under(
position,
&output,
&self.common.shell.override_redirect_windows,
overview.0.clone(),
workspace,
self.common.shell.session_lock.as_ref(),
)
.map(|(target, pos)| (target, pos.as_logical()));

if let Some((_target, pos)) = under {
let touch = seat.get_touch().unwrap();
touch.motion(
event.time_msec(),
event.slot(),
position.as_logical() - pos.to_f64(),
);
}
}
}
InputEvent::TouchUp { event, .. } => {
if let Some(seat) = self.common.seat_with_device(&event.device()) {
let serial = SERIAL_COUNTER.next_serial();
let touch = seat.get_touch().unwrap();
touch.up(serial, event.time_msec(), event.slot());
}
}
InputEvent::TouchCancel { event, .. } => {
if let Some(seat) = self.common.seat_with_device(&event.device()) {
let touch = seat.get_touch().unwrap();
touch.cancel();
}
}
InputEvent::TouchFrame { event: _, .. } => {}
_ => { /* TODO e.g. tablet events */ }
}
}

Expand Down
7 changes: 7 additions & 0 deletions src/shell/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1326,6 +1326,13 @@ impl Shell {
.map(|(o, _)| o)
}

pub fn builtin_output(&self) -> Option<&Output> {
self.outputs().find(|output| {
let name = output.name();
name.starts_with("eDP-") || name.starts_with("LVDS-") || name.starts_with("DSI-")
})
}

pub fn global_space(&self) -> Rectangle<i32, Global> {
self.outputs()
.fold(
Expand Down

0 comments on commit a52a602

Please sign in to comment.