Merge tag 'epoch-1.8.0' into local/yoda-main

Epoch 1.8.0

# Conflicts:
#	Cargo.lock
This commit is contained in:
Lionel DARNIS 2026-09-10 17:57:28 +02:00
commit a69f659983
50 changed files with 3533 additions and 1713 deletions

View file

@ -12,7 +12,7 @@ use id_tree::NodeId;
use smithay::{
backend::{
drm::DrmNode,
input::KeyState,
input::{InputTime, KeyState},
renderer::{
element::{
Element, Kind, RenderElement, UnderlyingStorage,
@ -1012,7 +1012,7 @@ impl KeyboardTarget<State> for CosmicMapped {
key: KeysymHandle<'_>,
state: KeyState,
serial: Serial,
time: u32,
time: InputTime,
) {
match &self.element {
CosmicMappedInternal::Stack(s) => {

View file

@ -11,7 +11,7 @@ use crate::{
shell::{
element::{CosmicMappedKey, CosmicMappedKeyInner},
focus::target::PointerFocusTarget,
grabs::{ReleaseMode, ResizeEdge},
grabs::{GrabType, ReleaseMode, ResizeEdge},
layout::tiling::NodeDesc,
},
state::State,
@ -38,7 +38,7 @@ use shortcuts::action::{Direction, FocusDirection};
use smithay::{
backend::{
drm::DrmNode,
input::KeyState,
input::{InputTime, KeyState, TabletToolDescriptor},
renderer::{
ImportAll, ImportMem, Renderer,
element::{Element, Id as RendererId, Kind, RenderElement, UnderlyingStorage},
@ -52,14 +52,23 @@ use smithay::{
Seat,
keyboard::{KeyboardTarget, KeysymHandle, ModifiersState},
pointer::{
AxisFrame, ButtonEvent, CursorImageStatus, GestureHoldBeginEvent, GestureHoldEndEvent,
GesturePinchBeginEvent, GesturePinchEndEvent, GesturePinchUpdateEvent,
GestureSwipeBeginEvent, GestureSwipeEndEvent, GestureSwipeUpdateEvent, MotionEvent,
AxisFrame as PointerAxisFrame, ButtonEvent as PointerButtonEvent, CursorImageStatus,
GestureHoldBeginEvent, GestureHoldEndEvent, GesturePinchBeginEvent,
GesturePinchEndEvent, GesturePinchUpdateEvent, GestureSwipeBeginEvent,
GestureSwipeEndEvent, GestureSwipeUpdateEvent, MotionEvent as PointerMotionEvent,
PointerTarget, RelativeMotionEvent,
},
tablet::{
Tablet, TabletSeatTrait,
tool::{
AxisFrame as ToolAxisFrame, ButtonEvent as ToolButtonEvent,
DownEvent as ToolDownEvent, MotionEvent as ToolMotionEvent, TabletToolTarget,
UpEvent as ToolUpEvent,
},
},
touch::{
DownEvent, FrameMarker, MotionEvent as TouchMotionEvent, OrientationEvent, ShapeEvent,
TouchTarget, UpEvent,
DownEvent as TouchDownEvent, FrameMarker, MotionEvent as TouchMotionEvent,
OrientationEvent, ShapeEvent, TouchTarget, UpEvent as TouchUpEvent,
},
},
output::Output,
@ -112,6 +121,7 @@ pub struct CosmicStackInternal {
previous_keyboard: AtomicUsize,
pointer_entered: AtomicU8,
touch_serial: AtomicU32,
tablet_serial: AtomicU32,
reenter: AtomicBool,
potential_drag: Mutex<Option<usize>>,
override_alive: AtomicBool,
@ -171,6 +181,7 @@ impl CosmicStack {
previous_keyboard: AtomicUsize::new(0),
pointer_entered: AtomicU8::new(0),
touch_serial: AtomicU32::new(0),
tablet_serial: AtomicU32::new(0),
reenter: AtomicBool::new(false),
potential_drag: Mutex::new(None),
override_alive: AtomicBool::new(true),
@ -831,7 +842,7 @@ impl CosmicStack {
)));
};
let radii = radii.map(|[a, _, c, _]| [a, 0, c, 0]);
let radii = radii.map(|[_, _, c, d]| [0, 0, c, d]);
windows[active].push_render_elements(
renderer,
window_loc,
@ -909,12 +920,19 @@ impl CosmicStack {
false,
);
if let Some((grab, focus)) = res {
if grab.is_touch_grab() {
seat.get_touch().unwrap().set_grab(state, grab, serial);
} else {
seat.get_pointer()
match grab.grab_type() {
GrabType::Touch => {
seat.get_touch().unwrap().set_grab(state, grab, serial)
}
GrabType::Pointer => seat
.get_pointer()
.unwrap()
.set_grab(state, grab, serial, focus);
.set_grab(state, grab, serial, focus),
GrabType::TabletTool => seat
.tablet_seat()
.get_tool(grab.tool().unwrap())
.unwrap()
.set_grab(state, grab, InputTime::now(), serial, focus),
}
}
});
@ -997,17 +1015,17 @@ impl CosmicStack {
.corner_radius(geometry_size)
.unwrap_or([default_radius; 4]);
corners[0] = 0;
corners[1] = 0;
corners[3] = 0;
corners
} else {
let mut corners = active_window.corner_radius(geometry_size).unwrap_or(radii);
corners[0] = radii[0].max(corners[0]);
corners[0] = radii[0];
corners[1] = radii[1];
corners[2] = radii[2].max(corners[2]);
corners[3] = radii[3];
corners[3] = radii[3].max(corners[3]);
corners
}
@ -1089,12 +1107,19 @@ impl Program for CosmicStackInternal {
false,
);
if let Some((grab, focus)) = res {
if grab.is_touch_grab() {
seat.get_touch().unwrap().set_grab(state, grab, serial);
} else {
seat.get_pointer()
match grab.grab_type() {
GrabType::Touch => {
seat.get_touch().unwrap().set_grab(state, grab, serial)
}
GrabType::Pointer => seat
.get_pointer()
.unwrap()
.set_grab(state, grab, serial, focus);
.set_grab(state, grab, serial, focus),
GrabType::TabletTool => seat
.tablet_seat()
.get_tool(grab.tool().unwrap())
.unwrap()
.set_grab(state, grab, InputTime::now(), serial, focus),
}
}
});
@ -1547,7 +1572,7 @@ impl KeyboardTarget<State> for CosmicStack {
key: KeysymHandle<'_>,
state: KeyState,
serial: Serial,
time: u32,
time: InputTime,
) {
let active = self.keyboard_leave_if_previous(seat, data, serial);
self.0.with_program(|p| {
@ -1587,7 +1612,7 @@ impl KeyboardTarget<State> for CosmicStack {
}
impl PointerTarget<State> for CosmicStack {
fn enter(&self, seat: &Seat<State>, data: &mut State, event: &MotionEvent) {
fn enter(&self, seat: &Seat<State>, data: &mut State, event: &PointerMotionEvent) {
let mut event = event.clone();
self.0.with_program(|p| {
let active_window = &p.windows.lock().unwrap()[p.active.load(Ordering::SeqCst)];
@ -1615,7 +1640,7 @@ impl PointerTarget<State> for CosmicStack {
PointerTarget::enter(&self.0, seat, data, &event)
}
fn motion(&self, seat: &Seat<State>, data: &mut State, event: &MotionEvent) {
fn motion(&self, seat: &Seat<State>, data: &mut State, event: &PointerMotionEvent) {
let mut event = event.clone();
self.0.with_program(|p| {
let active = p.active.load(Ordering::SeqCst);
@ -1658,7 +1683,7 @@ impl PointerTarget<State> for CosmicStack {
) {
}
fn button(&self, seat: &Seat<State>, data: &mut State, event: &ButtonEvent) {
fn button(&self, seat: &Seat<State>, data: &mut State, event: &PointerButtonEvent) {
match self.0.with_program(|p| p.current_focus()) {
Some(Focus::Header) => PointerTarget::button(&self.0, seat, data, event),
Some(x) => {
@ -1689,14 +1714,12 @@ impl PointerTarget<State> for CosmicStack {
state.common.config.cosmic_conf.edge_snap_threshold,
false,
);
if let Some((grab, focus)) = res {
if grab.is_touch_grab() {
seat.get_touch().unwrap().set_grab(state, grab, serial);
} else {
seat.get_pointer()
.unwrap()
.set_grab(state, grab, serial, focus);
}
if let Some((grab, focus)) = res
&& let GrabType::Pointer = grab.grab_type()
{
seat.get_pointer()
.unwrap()
.set_grab(state, grab, serial, focus);
}
});
}
@ -1704,7 +1727,7 @@ impl PointerTarget<State> for CosmicStack {
}
}
fn axis(&self, seat: &Seat<State>, data: &mut State, frame: AxisFrame) {
fn axis(&self, seat: &Seat<State>, data: &mut State, frame: PointerAxisFrame) {
if let Some(Focus::Header) = self.0.with_program(|p| p.current_focus()) {
PointerTarget::axis(&self.0, seat, data, frame)
}
@ -1716,7 +1739,7 @@ impl PointerTarget<State> for CosmicStack {
}
}
fn leave(&self, seat: &Seat<State>, data: &mut State, serial: Serial, time: u32) {
fn leave(&self, seat: &Seat<State>, data: &mut State, serial: Serial, time: InputTime) {
self.0.with_program(|p| {
let mut cursor_state = seat
.user_data()
@ -1752,14 +1775,12 @@ impl PointerTarget<State> for CosmicStack {
&state.common.event_loop_handle,
false,
);
if let Some((grab, focus)) = res {
if grab.is_touch_grab() {
seat.get_touch().unwrap().set_grab(state, grab, serial);
} else {
seat.get_pointer()
.unwrap()
.set_grab(state, grab, serial, focus);
}
if let Some((grab, focus)) = res
&& let GrabType::Pointer = grab.grab_type()
{
seat.get_pointer()
.unwrap()
.set_grab(state, grab, serial, focus);
}
});
}
@ -1832,7 +1853,7 @@ impl PointerTarget<State> for CosmicStack {
}
impl TouchTarget<State> for CosmicStack {
fn down(&self, seat: &Seat<State>, data: &mut State, event: &DownEvent) {
fn down(&self, seat: &Seat<State>, data: &mut State, event: &TouchDownEvent) {
let mut event = event.clone();
let active_window_geo = self.0.with_program(|p| {
p.windows.lock().unwrap()[p.active.load(Ordering::SeqCst)].geometry()
@ -1843,7 +1864,7 @@ impl TouchTarget<State> for CosmicStack {
TouchTarget::down(&self.0, seat, data, &event)
}
fn up(&self, seat: &Seat<State>, data: &mut State, event: &UpEvent) {
fn up(&self, seat: &Seat<State>, data: &mut State, event: &TouchUpEvent) {
TouchTarget::up(&self.0, seat, data, event)
}
@ -1891,6 +1912,185 @@ impl TouchTarget<State> for CosmicStack {
}
}
impl TabletToolTarget<State> for CosmicStack {
fn proximity_in(
&self,
seat: &Seat<State>,
data: &mut State,
tool_descriptor: &TabletToolDescriptor,
tablet: &Tablet,
serial: Serial,
) {
TabletToolTarget::proximity_in(&self.0, seat, data, tool_descriptor, tablet, serial)
}
fn proximity_out(
&self,
seat: &Seat<State>,
data: &mut State,
tool_descriptor: &TabletToolDescriptor,
) {
self.0.with_program(|p| {
let mut cursor_state = seat
.user_data()
.get::<CursorState>()
.unwrap()
.lock()
.unwrap();
cursor_state.unset_shape();
let _previous = p.swap_focus(None);
});
TabletToolTarget::proximity_out(&self.0, seat, data, tool_descriptor);
}
fn down(
&self,
seat: &Seat<State>,
data: &mut State,
tool_descriptor: &TabletToolDescriptor,
event: &ToolDownEvent,
) {
self.0.with_program(|p| {
p.tablet_serial
.store(event.serial.into(), Ordering::Release)
});
match self.0.with_program(|p| p.current_focus()) {
Some(Focus::Header) => {
TabletToolTarget::down(&self.0, seat, data, tool_descriptor, event)
}
Some(x) => {
let serial = self
.0
.with_program(|p| p.tablet_serial.load(Ordering::Acquire))
.into();
let seat = seat.clone();
let Some(surface) = self.0.with_program(|p| {
let window = &p.windows.lock().unwrap()[p.active.load(Ordering::SeqCst)];
window.wl_surface().map(Cow::into_owned)
}) else {
return;
};
self.0.loop_handle().insert_idle(move |state| {
let res = state.common.shell.write().resize_request(
&surface,
&seat,
serial,
match x {
Focus::ResizeTop => ResizeEdge::TOP,
Focus::ResizeTopLeft => ResizeEdge::TOP_LEFT,
Focus::ResizeTopRight => ResizeEdge::TOP_RIGHT,
Focus::ResizeBottom => ResizeEdge::BOTTOM,
Focus::ResizeBottomLeft => ResizeEdge::BOTTOM_LEFT,
Focus::ResizeBottomRight => ResizeEdge::BOTTOM_RIGHT,
Focus::ResizeLeft => ResizeEdge::LEFT,
Focus::ResizeRight => ResizeEdge::RIGHT,
Focus::Header => unreachable!(),
},
state.common.config.cosmic_conf.edge_snap_threshold,
false,
);
if let Some((grab, focus)) = res
&& let GrabType::TabletTool = grab.grab_type()
{
seat.tablet_seat()
.get_tool(grab.tool().unwrap())
.unwrap()
.set_grab(state, grab, InputTime::now(), serial, focus);
}
});
}
None => {}
}
}
fn up(
&self,
seat: &Seat<State>,
data: &mut State,
tool_descriptor: &TabletToolDescriptor,
event: &ToolUpEvent,
) {
TabletToolTarget::up(&self.0, seat, data, tool_descriptor, event)
}
fn motion(
&self,
seat: &Seat<State>,
data: &mut State,
tool_descriptor: &TabletToolDescriptor,
event: &ToolMotionEvent,
) {
let mut event = event.clone();
self.0.with_program(|p| {
let active = p.active.load(Ordering::SeqCst);
let active_window = &p.windows.lock().unwrap()[active];
let Some(next) = Focus::under(active_window, TAB_HEIGHT, event.location) else {
return;
};
let _previous = p.swap_focus(Some(next));
let mut cursor_state = seat
.user_data()
.get::<CursorState>()
.unwrap()
.lock()
.unwrap();
cursor_state.set_shape(next.cursor_shape());
seat.set_cursor_image_status(CursorImageStatus::default_named());
});
let active_window_geo = self.0.with_program(|p| {
p.windows.lock().unwrap()[p.active.load(Ordering::SeqCst)].geometry()
});
event.location -= active_window_geo.loc.to_f64();
TabletToolTarget::motion(&self.0, seat, data, tool_descriptor, &event);
if event.location.y < 0.0
|| event.location.y > TAB_HEIGHT as f64
|| event.location.x < 64.0
|| event.location.x > (active_window_geo.size.w as f64 - 64.0)
{
self.start_drag(
data,
seat,
self.0
.with_program(|p| p.tablet_serial.load(Ordering::Acquire))
.into(),
);
}
}
fn axis(
&self,
seat: &Seat<State>,
data: &mut State,
tool_descriptor: &TabletToolDescriptor,
frame: ToolAxisFrame,
) {
TabletToolTarget::axis(&self.0, seat, data, tool_descriptor, frame)
}
fn button(
&self,
seat: &Seat<State>,
data: &mut State,
tool_descriptor: &TabletToolDescriptor,
event: &ToolButtonEvent,
) {
TabletToolTarget::button(&self.0, seat, data, tool_descriptor, event)
}
fn frame(
&self,
seat: &Seat<State>,
data: &mut State,
tool_descriptor: &TabletToolDescriptor,
time: InputTime,
) {
TabletToolTarget::frame(&self.0, seat, data, tool_descriptor, time)
}
}
pub enum CosmicStackRenderElement<R: Renderer + ImportAll + ImportMem> {
Header(IcedRenderElement<R>),
Shadow(PixelShaderElement),

View file

@ -8,6 +8,7 @@ use cosmic::{
layout::{Layout, Limits, Node},
mouse, overlay, renderer,
text::{Ellipsize, EllipsizeHeightLimit, Shaping, Wrapping},
touch,
widget::{Id, Widget, operation::Operation, tree::Tree},
},
widget::{self, container::draw_background, rule::FillMode, scrollable::AbsoluteOffset},
@ -370,6 +371,7 @@ where
if matches!(
event,
event::Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Left))
| event::Event::Touch(touch::Event::FingerPressed { .. })
) && let Some(message) = self.press_message.clone()
{
shell.publish(message);
@ -388,6 +390,7 @@ where
if matches!(
event,
event::Event::Mouse(mouse::Event::ButtonReleased(mouse::Button::Left))
| event::Event::Touch(touch::Event::FingerLifted { .. })
) {
shell.publish(Message::activate(self.idx));
shell.capture_event();

View file

@ -31,7 +31,7 @@ use keyframe::{
functions::{EaseInOutCubic, EaseOutCubic},
};
use std::{
collections::{HashMap, HashSet, VecDeque},
collections::{HashMap, VecDeque},
time::{Duration, Instant},
};
@ -757,12 +757,10 @@ where
state.last_state = Some(current_state.clone());
}
let last_state = state.last_state.as_mut().unwrap();
let unknown_keys = current_state
.keys()
.collect::<HashSet<_>>()
.symmetric_difference(&last_state.keys().collect::<HashSet<_>>())
.next()
.is_some();
let unknown_keys = current_state.len() != last_state.len()
|| current_state
.keys()
.any(|key| !last_state.contains_key(key));
enum Difference {
NewOrRemoved,

View file

@ -21,6 +21,7 @@ use std::{
use smithay::{
backend::{
drm::DrmNode,
input::InputTime,
renderer::{
ImportAll, Renderer, buffer_has_alpha,
element::{Kind, RenderElementStates, surface::KindEvaluation},
@ -1084,7 +1085,7 @@ impl KeyboardTarget<State> for CosmicSurface {
key: KeysymHandle<'_>,
state: smithay::backend::input::KeyState,
serial: smithay::utils::Serial,
time: u32,
time: InputTime,
) {
match self.0.underlying_surface() {
WindowSurface::Wayland(toplevel) => {

View file

@ -7,7 +7,7 @@ use crate::{
shell::{
element::{CosmicMappedKey, CosmicMappedKeyInner},
focus::target::PointerFocusTarget,
grabs::{ReleaseMode, ResizeEdge},
grabs::{GrabType, ReleaseMode, ResizeEdge},
},
state::State,
utils::{
@ -21,7 +21,7 @@ use cosmic_comp_config::AppearanceConfig;
use smithay::{
backend::{
drm::DrmNode,
input::KeyState,
input::{InputTime, KeyState, TabletToolDescriptor},
renderer::{
ImportAll, ImportMem, Renderer,
element::{Element, Id as RendererId, Kind, RenderElement, UnderlyingStorage},
@ -35,14 +35,23 @@ use smithay::{
Seat,
keyboard::{KeyboardTarget, KeysymHandle, ModifiersState},
pointer::{
AxisFrame, ButtonEvent, CursorIcon, CursorImageStatus, GestureHoldBeginEvent,
GestureHoldEndEvent, GesturePinchBeginEvent, GesturePinchEndEvent,
GesturePinchUpdateEvent, GestureSwipeBeginEvent, GestureSwipeEndEvent,
GestureSwipeUpdateEvent, MotionEvent, PointerTarget, RelativeMotionEvent,
AxisFrame as PointerAxisFrame, ButtonEvent as PointerButtonEvent, CursorIcon,
CursorImageStatus, GestureHoldBeginEvent, GestureHoldEndEvent, GesturePinchBeginEvent,
GesturePinchEndEvent, GesturePinchUpdateEvent, GestureSwipeBeginEvent,
GestureSwipeEndEvent, GestureSwipeUpdateEvent, MotionEvent as PointerMotionEvent,
PointerTarget, RelativeMotionEvent,
},
tablet::{
Tablet, TabletSeatTrait,
tool::{
AxisFrame as ToolAxisFrame, ButtonEvent as ToolButtonEvent,
DownEvent as ToolDownEvent, MotionEvent as ToolMotionEvent, TabletToolTarget,
UpEvent as ToolUpEvent,
},
},
touch::{
DownEvent, FrameMarker, MotionEvent as TouchMotionEvent, OrientationEvent, ShapeEvent,
TouchTarget, UpEvent,
DownEvent as TouchDownEvent, FrameMarker, MotionEvent as TouchMotionEvent,
OrientationEvent, ShapeEvent, TouchTarget, UpEvent as TouchUpEvent,
},
},
output::Output,
@ -429,12 +438,12 @@ impl CosmicWindow {
.map(|x| (x * scale as f32).round() as u8);
if has_ssd && !clip {
// bottom corners
radii[0] = 0;
radii[2] = 0;
radii[3] = 0;
if is_tiled {
// top corners
radii[0] = 0;
radii[1] = 0;
radii[3] = 0;
}
}
@ -501,12 +510,12 @@ impl CosmicWindow {
&& !is_maximized;
if has_ssd && !clip {
// bottom corners
radii[0] = 0;
radii[2] = 0;
radii[3] = 0;
if is_tiled {
// top corners
radii[0] = 0;
radii[1] = 0;
radii[3] = 0;
}
}
@ -551,8 +560,8 @@ impl CosmicWindow {
self.0.with_program(|p| {
let mut radii = radii;
if has_ssd {
radii[0] = 0;
radii[1] = 0;
radii[3] = 0;
}
let theme = p.theme.lock().unwrap();
let frosted = if theme.cosmic().frosted_windows {
@ -576,8 +585,8 @@ impl CosmicWindow {
});
if has_ssd {
radii[0] = 0;
radii[2] = 0;
radii[3] = 0;
let ssd_loc = location
+ self
.0
@ -682,26 +691,26 @@ impl CosmicWindow {
(has_ssd, true) => {
let mut corners = p.window.corner_radius(geometry_size).unwrap_or(radii);
corners[0] = radii[0].max(corners[0]);
corners[0] = if has_ssd {
radii[0]
} else {
radii[0].max(corners[0])
};
corners[1] = if has_ssd {
radii[1]
} else {
radii[1].max(corners[1])
};
corners[2] = radii[2].max(corners[2]);
corners[3] = if has_ssd {
radii[3]
} else {
radii[3].max(corners[3])
};
corners[3] = radii[3].max(corners[3]);
corners
}
(true, false) => p
.window
.corner_radius(geometry_size)
.map(|[a, _, c, _]| [a, radii[1], c, radii[3]])
.unwrap_or([default_radius, radii[1], default_radius, radii[3]]),
.map(|[_, _, c, d]| [radii[0], radii[1], c, d])
.unwrap_or([radii[0], radii[1], default_radius, default_radius]),
(false, false) => p
.window
.corner_radius(geometry_size)
@ -746,12 +755,19 @@ impl Program for CosmicWindowInternal {
false,
);
if let Some((grab, focus)) = res {
if grab.is_touch_grab() {
seat.get_touch().unwrap().set_grab(state, grab, serial);
} else {
seat.get_pointer()
match grab.grab_type() {
GrabType::Touch => {
seat.get_touch().unwrap().set_grab(state, grab, serial)
}
GrabType::Pointer => seat
.get_pointer()
.unwrap()
.set_grab(state, grab, serial, focus);
.set_grab(state, grab, serial, focus),
GrabType::TabletTool => seat
.tablet_seat()
.get_tool(grab.tool().unwrap())
.unwrap()
.set_grab(state, grab, InputTime::now(), serial, focus),
}
}
});
@ -981,7 +997,7 @@ impl KeyboardTarget<State> for CosmicWindow {
key: KeysymHandle<'_>,
state: KeyState,
serial: Serial,
time: u32,
time: InputTime,
) {
self.0
.with_program(|p| KeyboardTarget::key(&p.window, seat, data, key, state, serial, time))
@ -999,7 +1015,7 @@ impl KeyboardTarget<State> for CosmicWindow {
}
impl PointerTarget<State> for CosmicWindow {
fn enter(&self, seat: &Seat<State>, data: &mut State, event: &MotionEvent) {
fn enter(&self, seat: &Seat<State>, data: &mut State, event: &PointerMotionEvent) {
let mut event = event.clone();
self.0.with_program(|p| {
let has_ssd = p.has_ssd(false);
@ -1012,8 +1028,7 @@ impl PointerTarget<State> for CosmicWindow {
return;
};
let old_focus = p.swap_focus(Some(next));
assert_eq!(old_focus, None);
let _ = p.swap_focus(Some(next));
let cursor_state = seat.user_data().get::<CursorState>().unwrap();
cursor_state.lock().unwrap().set_shape(next.cursor_shape());
@ -1025,7 +1040,7 @@ impl PointerTarget<State> for CosmicWindow {
PointerTarget::enter(&self.0, seat, data, &event)
}
fn motion(&self, seat: &Seat<State>, data: &mut State, event: &MotionEvent) {
fn motion(&self, seat: &Seat<State>, data: &mut State, event: &PointerMotionEvent) {
let mut event = event.clone();
self.0.with_program(|p| {
let has_ssd = p.has_ssd(false);
@ -1057,7 +1072,7 @@ impl PointerTarget<State> for CosmicWindow {
) {
}
fn button(&self, seat: &Seat<State>, data: &mut State, event: &ButtonEvent) {
fn button(&self, seat: &Seat<State>, data: &mut State, event: &PointerButtonEvent) {
match self.0.with_program(|p| p.current_focus()) {
Some(Focus::Header) => PointerTarget::button(&self.0, seat, data, event),
Some(x) => {
@ -1093,14 +1108,12 @@ impl PointerTarget<State> for CosmicWindow {
false,
);
if let Some((grab, focus)) = res {
if grab.is_touch_grab() {
seat.get_touch().unwrap().set_grab(state, grab, serial);
} else {
seat.get_pointer()
.unwrap()
.set_grab(state, grab, serial, focus);
}
if let Some((grab, focus)) = res
&& let GrabType::Pointer = grab.grab_type()
{
seat.get_pointer()
.unwrap()
.set_grab(state, grab, serial, focus)
}
});
}
@ -1108,7 +1121,7 @@ impl PointerTarget<State> for CosmicWindow {
}
}
fn axis(&self, seat: &Seat<State>, data: &mut State, frame: AxisFrame) {
fn axis(&self, seat: &Seat<State>, data: &mut State, frame: PointerAxisFrame) {
if let Some(Focus::Header) = self.0.with_program(|p| p.current_focus()) {
PointerTarget::axis(&self.0, seat, data, frame)
}
@ -1120,7 +1133,7 @@ impl PointerTarget<State> for CosmicWindow {
}
}
fn leave(&self, seat: &Seat<State>, data: &mut State, serial: Serial, time: u32) {
fn leave(&self, seat: &Seat<State>, data: &mut State, serial: Serial, time: InputTime) {
self.0.with_program(|p| {
let cursor_state = seat.user_data().get::<CursorState>().unwrap();
cursor_state.lock().unwrap().unset_shape();
@ -1195,7 +1208,7 @@ impl PointerTarget<State> for CosmicWindow {
}
impl TouchTarget<State> for CosmicWindow {
fn down(&self, seat: &Seat<State>, data: &mut State, event: &DownEvent) {
fn down(&self, seat: &Seat<State>, data: &mut State, event: &TouchDownEvent) {
let mut event = event.clone();
self.0.with_program(|p| {
event.location -= p.window.geometry().loc.to_f64();
@ -1203,7 +1216,7 @@ impl TouchTarget<State> for CosmicWindow {
TouchTarget::down(&self.0, seat, data, &event)
}
fn up(&self, seat: &Seat<State>, data: &mut State, event: &UpEvent) {
fn up(&self, seat: &Seat<State>, data: &mut State, event: &TouchUpEvent) {
TouchTarget::up(&self.0, seat, data, event)
}
@ -1234,6 +1247,155 @@ impl TouchTarget<State> for CosmicWindow {
}
}
impl TabletToolTarget<State> for CosmicWindow {
fn proximity_in(
&self,
seat: &Seat<State>,
data: &mut State,
tool_descriptor: &TabletToolDescriptor,
tablet: &Tablet,
serial: Serial,
) {
TabletToolTarget::proximity_in(&self.0, seat, data, tool_descriptor, tablet, serial)
}
fn proximity_out(
&self,
seat: &Seat<State>,
data: &mut State,
tool_descriptor: &TabletToolDescriptor,
) {
self.0.with_program(|p| {
let cursor_state = seat.user_data().get::<CursorState>().unwrap();
cursor_state.lock().unwrap().unset_shape();
let _previous = p.swap_focus(None);
});
TabletToolTarget::proximity_out(&self.0, seat, data, tool_descriptor)
}
fn down(
&self,
seat: &Seat<State>,
data: &mut State,
tool_descriptor: &TabletToolDescriptor,
event: &ToolDownEvent,
) {
match self.0.with_program(|p| p.current_focus()) {
Some(Focus::Header) => {
TabletToolTarget::down(&self.0, seat, data, tool_descriptor, event)
}
Some(x) => {
let serial = event.serial;
let seat = seat.clone();
let Some(surface) = self.wl_surface().map(Cow::into_owned) else {
return;
};
self.0.loop_handle().insert_idle(move |state| {
let res = state.common.shell.write().resize_request(
&surface,
&seat,
serial,
match x {
Focus::ResizeTop => ResizeEdge::TOP,
Focus::ResizeTopLeft => ResizeEdge::TOP_LEFT,
Focus::ResizeTopRight => ResizeEdge::TOP_RIGHT,
Focus::ResizeBottom => ResizeEdge::BOTTOM,
Focus::ResizeBottomLeft => ResizeEdge::BOTTOM_LEFT,
Focus::ResizeBottomRight => ResizeEdge::BOTTOM_RIGHT,
Focus::ResizeLeft => ResizeEdge::LEFT,
Focus::ResizeRight => ResizeEdge::RIGHT,
Focus::Header => unreachable!(),
},
state.common.config.cosmic_conf.edge_snap_threshold,
false,
);
if let Some((grab, focus)) = res
&& let GrabType::TabletTool = grab.grab_type()
{
seat.tablet_seat()
.get_tool(grab.tool().unwrap())
.unwrap()
.set_grab(state, grab, InputTime::now(), serial, focus)
}
});
}
None => {}
}
}
fn up(
&self,
seat: &Seat<State>,
data: &mut State,
tool_descriptor: &TabletToolDescriptor,
event: &ToolUpEvent,
) {
TabletToolTarget::up(&self.0, seat, data, tool_descriptor, event)
}
fn motion(
&self,
seat: &Seat<State>,
data: &mut State,
tool_descriptor: &TabletToolDescriptor,
event: &ToolMotionEvent,
) {
let mut event = event.clone();
self.0.with_program(|p| {
let has_ssd = p.has_ssd(false);
if has_ssd || p.has_tiled_state() {
let Some(next) = Focus::under(
&p.window,
if has_ssd { SSD_HEIGHT } else { 0 },
event.location,
) else {
return;
};
let _previous = p.swap_focus(Some(next));
let cursor_state = seat.user_data().get::<CursorState>().unwrap();
cursor_state.lock().unwrap().set_shape(next.cursor_shape());
seat.set_cursor_image_status(CursorImageStatus::default_named());
}
});
event.location -= self.0.with_program(|p| p.window.geometry().loc.to_f64());
TabletToolTarget::motion(&self.0, seat, data, tool_descriptor, &event)
}
fn axis(
&self,
seat: &Seat<State>,
data: &mut State,
tool_descriptor: &TabletToolDescriptor,
frame: ToolAxisFrame,
) {
TabletToolTarget::axis(&self.0, seat, data, tool_descriptor, frame)
}
fn button(
&self,
seat: &Seat<State>,
data: &mut State,
tool_descriptor: &TabletToolDescriptor,
event: &ToolButtonEvent,
) {
TabletToolTarget::button(&self.0, seat, data, tool_descriptor, event)
}
fn frame(
&self,
seat: &Seat<State>,
data: &mut State,
tool_descriptor: &TabletToolDescriptor,
time: InputTime,
) {
TabletToolTarget::frame(&self.0, seat, data, tool_descriptor, time)
}
}
impl WaylandFocus for CosmicWindow {
fn wl_surface(&self) -> Option<Cow<'_, WlSurface>> {
self.0.with_program(|p| {