1
0
Fork 0
forked from wry/wry

Merge pull request #547 from mahkoh/jorth/pointer-absolute

metal: handle absolute motion events
This commit is contained in:
mahkoh 2025-07-27 16:15:26 +02:00 committed by GitHub
commit c61a04c3d3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 97 additions and 18 deletions

View file

@ -348,6 +348,11 @@ pub enum InputEvent {
dx_unaccelerated: Fixed, dx_unaccelerated: Fixed,
dy_unaccelerated: Fixed, dy_unaccelerated: Fixed,
}, },
MotionAbsolute {
time_usec: u64,
x_normed: f32,
y_normed: f32,
},
Button { Button {
time_usec: u64, time_usec: u64,
button: u32, button: u32,

View file

@ -95,6 +95,7 @@ impl MetalBackend {
c::LIBINPUT_EVENT_DEVICE_REMOVED => self.handle_li_device_removed(event), c::LIBINPUT_EVENT_DEVICE_REMOVED => self.handle_li_device_removed(event),
c::LIBINPUT_EVENT_KEYBOARD_KEY => self.handle_keyboard_key(event), c::LIBINPUT_EVENT_KEYBOARD_KEY => self.handle_keyboard_key(event),
c::LIBINPUT_EVENT_POINTER_MOTION => self.handle_pointer_motion(event), c::LIBINPUT_EVENT_POINTER_MOTION => self.handle_pointer_motion(event),
c::LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE => self.handle_pointer_motion_absolute(event),
c::LIBINPUT_EVENT_POINTER_BUTTON => self.handle_pointer_button(event), c::LIBINPUT_EVENT_POINTER_BUTTON => self.handle_pointer_button(event),
c::LIBINPUT_EVENT_POINTER_SCROLL_WHEEL => { c::LIBINPUT_EVENT_POINTER_SCROLL_WHEEL => {
self.handle_pointer_axis(event, AxisSource::Wheel) self.handle_pointer_axis(event, AxisSource::Wheel)
@ -248,6 +249,15 @@ impl MetalBackend {
}); });
} }
fn handle_pointer_motion_absolute(self: &Rc<Self>, event: LibInputEvent) {
let (event, dev) = unpack!(self, event, pointer_event);
dev.event(InputEvent::MotionAbsolute {
time_usec: event.time_usec(),
x_normed: event.x_transformed(1) as f32,
y_normed: event.y_transformed(1) as f32,
});
}
fn handle_gesture_swipe_begin(self: &Rc<Self>, event: LibInputEvent) { fn handle_gesture_swipe_begin(self: &Rc<Self>, event: LibInputEvent) {
let (event, dev) = unpack!(self, event, gesture_event); let (event, dev) = unpack!(self, event, gesture_event);
dev.event(InputEvent::SwipeBegin { dev.event(InputEvent::SwipeBegin {

View file

@ -359,6 +359,7 @@ fn start_compositor2(
enable_primary_selection: Cell::new(true), enable_primary_selection: Cell::new(true),
xdg_surface_configure_events: Default::default(), xdg_surface_configure_events: Default::default(),
workspace_display_order: Cell::new(WorkspaceDisplayOrder::Manual), workspace_display_order: Cell::new(WorkspaceDisplayOrder::Manual),
outputs_without_hc: Default::default(),
}); });
state.tracker.register(ClientId::from_raw(0)); state.tracker.register(ClientId::from_raw(0));
create_dummy_output(&state); create_dummy_output(&state);

View file

@ -85,7 +85,7 @@ impl CursorUserGroup {
let x_int = x.round_down(); let x_int = x.round_down();
let y_int = y.round_down(); let y_int = y.round_down();
let extents = cursor.extents_at_scale(Scale::default()); let extents = cursor.extents_at_scale(Scale::default());
self.state.damage2(true, extents.move_(x_int, y_int)); self.damage(extents.move_(x_int, y_int));
} }
} }
@ -248,6 +248,10 @@ impl CursorUserGroup {
}; };
active.present_hardware_cursor(output, hc); active.present_hardware_cursor(output, hc);
} }
fn damage(&self, rect: Rect) {
self.state.damage2(true, self.hardware_cursor.get(), rect);
}
} }
impl CursorUser { impl CursorUser {
@ -416,10 +420,8 @@ impl CursorUser {
let old_x_int = old_x.round_down(); let old_x_int = old_x.round_down();
let old_y_int = old_y.round_down(); let old_y_int = old_y.round_down();
let extents = cursor.extents_at_scale(Scale::default()); let extents = cursor.extents_at_scale(Scale::default());
self.group self.group.damage(extents.move_(old_x_int, old_y_int));
.state self.group.damage(extents.move_(x_int, y_int));
.damage2(true, extents.move_(old_x_int, old_y_int));
self.group.state.damage2(true, extents.move_(x_int, y_int));
} }
self.pos.set((x, y)); self.pos.set((x, y));
self.update_hardware_cursor_(false); self.update_hardware_cursor_(false);
@ -435,7 +437,8 @@ impl CursorUser {
} }
pub fn software_cursor(&self) -> bool { pub fn software_cursor(&self) -> bool {
self.is_active() && !self.group.hardware_cursor.get() self.is_active()
&& (!self.group.hardware_cursor.get() || self.group.state.outputs_without_hc.get() > 0)
} }
fn update_hardware_cursor_(&self, render: bool) { fn update_hardware_cursor_(&self, render: bool) {

View file

@ -310,6 +310,7 @@ impl WlSeatGlobal {
InputEvent::Key { time_usec, .. } InputEvent::Key { time_usec, .. }
| InputEvent::ConnectorPosition { time_usec, .. } | InputEvent::ConnectorPosition { time_usec, .. }
| InputEvent::Motion { time_usec, .. } | InputEvent::Motion { time_usec, .. }
| InputEvent::MotionAbsolute { time_usec, .. }
| InputEvent::Button { time_usec, .. } | InputEvent::Button { time_usec, .. }
| InputEvent::AxisFrame { time_usec, .. } | InputEvent::AxisFrame { time_usec, .. }
| InputEvent::SwipeBegin { time_usec, .. } | InputEvent::SwipeBegin { time_usec, .. }
@ -350,6 +351,7 @@ impl WlSeatGlobal {
match event { match event {
InputEvent::ConnectorPosition { .. } InputEvent::ConnectorPosition { .. }
| InputEvent::Motion { .. } | InputEvent::Motion { .. }
| InputEvent::MotionAbsolute { .. }
| InputEvent::Button { .. } | InputEvent::Button { .. }
| InputEvent::AxisFrame { .. } | InputEvent::AxisFrame { .. }
| InputEvent::SwipeBegin { .. } | InputEvent::SwipeBegin { .. }
@ -406,6 +408,13 @@ impl WlSeatGlobal {
dy_unaccelerated, dy_unaccelerated,
time_usec, time_usec,
} => self.motion_event(time_usec, dx, dy, dx_unaccelerated, dy_unaccelerated), } => self.motion_event(time_usec, dx, dy, dx_unaccelerated, dy_unaccelerated),
InputEvent::MotionAbsolute {
time_usec,
x_normed,
y_normed,
} => {
self.motion_absolute_event(time_usec, dev.get_rect(&self.state), x_normed, y_normed)
}
InputEvent::Button { InputEvent::Button {
time_usec, time_usec,
button, button,
@ -651,6 +660,18 @@ impl WlSeatGlobal {
self.cursor_moved(time_usec, false); self.cursor_moved(time_usec, false);
} }
fn motion_absolute_event(
self: &Rc<Self>,
time_usec: u64,
rect: Rect,
x_normed: f32,
y_normed: f32,
) {
let x = Fixed::from_f32(rect.x1() as f32 + x_normed * rect.width() as f32);
let y = Fixed::from_f32(rect.y1() as f32 + y_normed * rect.height() as f32);
self.motion_event_abs(time_usec, x, y, false);
}
pub fn button_event(self: &Rc<Self>, time_usec: u64, button: u32, state: KeyState) { pub fn button_event(self: &Rc<Self>, time_usec: u64, button: u32, state: KeyState) {
self.for_each_ei_seat(|ei_seat| { self.for_each_ei_seat(|ei_seat| {
ei_seat.handle_button(time_usec, button, state); ei_seat.handle_button(time_usec, button, state);

View file

@ -19,14 +19,16 @@ use {
libinput_event_get_touch_event, libinput_event_get_type, libinput_event_keyboard, libinput_event_get_touch_event, libinput_event_get_type, libinput_event_keyboard,
libinput_event_keyboard_get_key, libinput_event_keyboard_get_key_state, libinput_event_keyboard_get_key, libinput_event_keyboard_get_key_state,
libinput_event_keyboard_get_time_usec, libinput_event_pointer, libinput_event_keyboard_get_time_usec, libinput_event_pointer,
libinput_event_pointer_get_button, libinput_event_pointer_get_button_state, libinput_event_pointer_get_absolute_x_transformed,
libinput_event_pointer_get_dx, libinput_event_pointer_get_dx_unaccelerated, libinput_event_pointer_get_absolute_y_transformed, libinput_event_pointer_get_button,
libinput_event_pointer_get_dy, libinput_event_pointer_get_dy_unaccelerated, libinput_event_pointer_get_button_state, libinput_event_pointer_get_dx,
libinput_event_pointer_get_scroll_value, libinput_event_pointer_get_scroll_value_v120, libinput_event_pointer_get_dx_unaccelerated, libinput_event_pointer_get_dy,
libinput_event_pointer_get_time_usec, libinput_event_pointer_has_axis, libinput_event_pointer_get_dy_unaccelerated, libinput_event_pointer_get_scroll_value,
libinput_event_switch, libinput_event_switch_get_switch, libinput_event_pointer_get_scroll_value_v120, libinput_event_pointer_get_time_usec,
libinput_event_switch_get_switch_state, libinput_event_switch_get_time_usec, libinput_event_pointer_has_axis, libinput_event_switch,
libinput_event_tablet_pad, libinput_event_tablet_pad_get_button_number, libinput_event_switch_get_switch, libinput_event_switch_get_switch_state,
libinput_event_switch_get_time_usec, libinput_event_tablet_pad,
libinput_event_tablet_pad_get_button_number,
libinput_event_tablet_pad_get_button_state, libinput_event_tablet_pad_get_button_state,
libinput_event_tablet_pad_get_dial_delta_v120, libinput_event_tablet_pad_get_dial_delta_v120,
libinput_event_tablet_pad_get_dial_number, libinput_event_tablet_pad_get_mode, libinput_event_tablet_pad_get_dial_number, libinput_event_tablet_pad_get_mode,
@ -186,6 +188,14 @@ impl<'a> LibInputEventKeyboard<'a> {
} }
impl<'a> LibInputEventPointer<'a> { impl<'a> LibInputEventPointer<'a> {
pub fn x_transformed(&self, width: u32) -> f64 {
unsafe { libinput_event_pointer_get_absolute_x_transformed(self.event, width) }
}
pub fn y_transformed(&self, height: u32) -> f64 {
unsafe { libinput_event_pointer_get_absolute_y_transformed(self.event, height) }
}
pub fn dx(&self) -> f64 { pub fn dx(&self) -> f64 {
unsafe { libinput_event_pointer_get_dx(self.event) } unsafe { libinput_event_pointer_get_dx(self.event) }
} }

View file

@ -155,6 +155,14 @@ unsafe extern "C" {
pub fn libinput_event_pointer_get_dy(event: *mut libinput_event_pointer) -> f64; pub fn libinput_event_pointer_get_dy(event: *mut libinput_event_pointer) -> f64;
pub fn libinput_event_pointer_get_dx_unaccelerated(event: *mut libinput_event_pointer) -> f64; pub fn libinput_event_pointer_get_dx_unaccelerated(event: *mut libinput_event_pointer) -> f64;
pub fn libinput_event_pointer_get_dy_unaccelerated(event: *mut libinput_event_pointer) -> f64; pub fn libinput_event_pointer_get_dy_unaccelerated(event: *mut libinput_event_pointer) -> f64;
pub fn libinput_event_pointer_get_absolute_x_transformed(
event: *mut libinput_event_pointer,
width: u32,
) -> f64;
pub fn libinput_event_pointer_get_absolute_y_transformed(
event: *mut libinput_event_pointer,
height: u32,
) -> f64;
pub fn libinput_event_pointer_get_button(event: *mut libinput_event_pointer) -> u32; pub fn libinput_event_pointer_get_button(event: *mut libinput_event_pointer) -> u32;
pub fn libinput_event_pointer_get_button_state( pub fn libinput_event_pointer_get_button_state(
event: *mut libinput_event_pointer, event: *mut libinput_event_pointer,

View file

@ -277,6 +277,7 @@ pub struct State {
pub enable_primary_selection: Cell<bool>, pub enable_primary_selection: Cell<bool>,
pub xdg_surface_configure_events: AsyncQueue<XdgSurfaceConfigureEvent>, pub xdg_surface_configure_events: AsyncQueue<XdgSurfaceConfigureEvent>,
pub workspace_display_order: Cell<WorkspaceDisplayOrder>, pub workspace_display_order: Cell<WorkspaceDisplayOrder>,
pub outputs_without_hc: NumCell<usize>,
} }
// impl Drop for State { // impl Drop for State {
@ -648,7 +649,7 @@ impl State {
fn visit_output(&mut self, node: &Rc<OutputNode>) { fn visit_output(&mut self, node: &Rc<OutputNode>) {
node.render_data.borrow_mut().titles.clear(); node.render_data.borrow_mut().titles.clear();
node.render_data.borrow_mut().status.take(); node.render_data.borrow_mut().status.take();
node.hardware_cursor.set(None); node.set_hardware_cursor(None);
node.node_visit_children(self); node.node_visit_children(self);
} }
fn visit_float(&mut self, node: &Rc<FloatNode>) { fn visit_float(&mut self, node: &Rc<FloatNode>) {
@ -968,16 +969,19 @@ impl State {
} }
pub fn damage(&self, rect: Rect) { pub fn damage(&self, rect: Rect) {
self.damage2(false, rect); self.damage2(false, false, rect);
} }
pub fn damage2(&self, cursor: bool, rect: Rect) { pub fn damage2(&self, cursor: bool, skip_hc: bool, rect: Rect) {
if rect.is_empty() { if rect.is_empty() {
return; return;
} }
self.damage_visualizer.add(rect); self.damage_visualizer.add(rect);
for output in self.root.outputs.lock().values() { for output in self.root.outputs.lock().values() {
if output.global.pos.get().intersects(&rect) { if output.global.pos.get().intersects(&rect) {
if skip_hc && output.hardware_cursor.is_some() {
continue;
}
output.global.add_damage_area(&rect); output.global.add_damage_area(&rect);
if cursor && output.schedule.defer_cursor_updates() { if cursor && output.schedule.defer_cursor_updates() {
output.schedule.software_cursor_changed(); output.schedule.software_cursor_changed();

View file

@ -271,6 +271,7 @@ impl ConnectorHandler {
self.state.outputs.set(self.id, output_data.clone()); self.state.outputs.set(self.id, output_data.clone());
on.schedule_update_render_data(); on.schedule_update_render_data();
self.state.root.outputs.set(self.id, on.clone()); self.state.root.outputs.set(self.id, on.clone());
self.state.outputs_without_hc.fetch_add(1);
self.state.output_extents_changed(); self.state.output_extents_changed();
global.opt.node.set(Some(on.clone())); global.opt.node.set(Some(on.clone()));
global.opt.global.set(Some(global.clone())); global.opt.global.set(Some(global.clone()));
@ -330,7 +331,7 @@ impl ConnectorHandler {
ConnectorEvent::Disconnected => break 'outer, ConnectorEvent::Disconnected => break 'outer,
ConnectorEvent::HardwareCursor(hc) => { ConnectorEvent::HardwareCursor(hc) => {
on.schedule.set_hardware_cursor(&hc); on.schedule.set_hardware_cursor(&hc);
on.hardware_cursor.set(hc); on.set_hardware_cursor(hc);
self.state.refresh_hardware_cursors(); self.state.refresh_hardware_cursors();
} }
ConnectorEvent::FormatsChanged(formats) => { ConnectorEvent::FormatsChanged(formats) => {
@ -363,6 +364,9 @@ impl ConnectorHandler {
sc.stop(); sc.stop();
} }
global.destroyed.set(true); global.destroyed.set(true);
if on.hardware_cursor.is_none() {
self.state.outputs_without_hc.fetch_sub(1);
}
self.state.root.outputs.remove(&self.id); self.state.root.outputs.remove(&self.id);
self.state.output_extents_changed(); self.state.output_extents_changed();
self.state.outputs.remove(&self.id); self.state.outputs.remove(&self.id);

View file

@ -1433,6 +1433,19 @@ impl OutputNode {
.handle_tearing_mode_change(mode.to_config()); .handle_tearing_mode_change(mode.to_config());
} }
} }
pub fn set_hardware_cursor(&self, hc: Option<Rc<dyn HardwareCursor>>) {
let is_none = hc.is_none();
let old = self.hardware_cursor.set(hc);
let was_none = old.is_none();
if was_none != is_none {
if is_none {
self.state.outputs_without_hc.fetch_add(1);
} else {
self.state.outputs_without_hc.fetch_sub(1);
}
}
}
} }
pub struct OutputTitle { pub struct OutputTitle {