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,
dy_unaccelerated: Fixed,
},
MotionAbsolute {
time_usec: u64,
x_normed: f32,
y_normed: f32,
},
Button {
time_usec: u64,
button: u32,

View file

@ -95,6 +95,7 @@ impl MetalBackend {
c::LIBINPUT_EVENT_DEVICE_REMOVED => self.handle_li_device_removed(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_ABSOLUTE => self.handle_pointer_motion_absolute(event),
c::LIBINPUT_EVENT_POINTER_BUTTON => self.handle_pointer_button(event),
c::LIBINPUT_EVENT_POINTER_SCROLL_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) {
let (event, dev) = unpack!(self, event, gesture_event);
dev.event(InputEvent::SwipeBegin {

View file

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

View file

@ -85,7 +85,7 @@ impl CursorUserGroup {
let x_int = x.round_down();
let y_int = y.round_down();
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);
}
fn damage(&self, rect: Rect) {
self.state.damage2(true, self.hardware_cursor.get(), rect);
}
}
impl CursorUser {
@ -416,10 +420,8 @@ impl CursorUser {
let old_x_int = old_x.round_down();
let old_y_int = old_y.round_down();
let extents = cursor.extents_at_scale(Scale::default());
self.group
.state
.damage2(true, extents.move_(old_x_int, old_y_int));
self.group.state.damage2(true, extents.move_(x_int, y_int));
self.group.damage(extents.move_(old_x_int, old_y_int));
self.group.damage(extents.move_(x_int, y_int));
}
self.pos.set((x, y));
self.update_hardware_cursor_(false);
@ -435,7 +437,8 @@ impl CursorUser {
}
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) {

View file

@ -310,6 +310,7 @@ impl WlSeatGlobal {
InputEvent::Key { time_usec, .. }
| InputEvent::ConnectorPosition { time_usec, .. }
| InputEvent::Motion { time_usec, .. }
| InputEvent::MotionAbsolute { time_usec, .. }
| InputEvent::Button { time_usec, .. }
| InputEvent::AxisFrame { time_usec, .. }
| InputEvent::SwipeBegin { time_usec, .. }
@ -350,6 +351,7 @@ impl WlSeatGlobal {
match event {
InputEvent::ConnectorPosition { .. }
| InputEvent::Motion { .. }
| InputEvent::MotionAbsolute { .. }
| InputEvent::Button { .. }
| InputEvent::AxisFrame { .. }
| InputEvent::SwipeBegin { .. }
@ -406,6 +408,13 @@ impl WlSeatGlobal {
dy_unaccelerated,
time_usec,
} => 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 {
time_usec,
button,
@ -651,6 +660,18 @@ impl WlSeatGlobal {
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) {
self.for_each_ei_seat(|ei_seat| {
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_keyboard_get_key, libinput_event_keyboard_get_key_state,
libinput_event_keyboard_get_time_usec, libinput_event_pointer,
libinput_event_pointer_get_button, libinput_event_pointer_get_button_state,
libinput_event_pointer_get_dx, libinput_event_pointer_get_dx_unaccelerated,
libinput_event_pointer_get_dy, libinput_event_pointer_get_dy_unaccelerated,
libinput_event_pointer_get_scroll_value, libinput_event_pointer_get_scroll_value_v120,
libinput_event_pointer_get_time_usec, libinput_event_pointer_has_axis,
libinput_event_switch, 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_pointer_get_absolute_x_transformed,
libinput_event_pointer_get_absolute_y_transformed, libinput_event_pointer_get_button,
libinput_event_pointer_get_button_state, libinput_event_pointer_get_dx,
libinput_event_pointer_get_dx_unaccelerated, libinput_event_pointer_get_dy,
libinput_event_pointer_get_dy_unaccelerated, libinput_event_pointer_get_scroll_value,
libinput_event_pointer_get_scroll_value_v120, libinput_event_pointer_get_time_usec,
libinput_event_pointer_has_axis, libinput_event_switch,
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_dial_delta_v120,
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> {
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 {
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_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_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_state(
event: *mut libinput_event_pointer,

View file

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

View file

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

View file

@ -1433,6 +1433,19 @@ impl OutputNode {
.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 {