1#![allow(non_snake_case, clippy::missing_safety_doc)]
8
9mod backend;
10mod ffi_types;
11mod quirks;
12mod udev;
13
14use crate::ffi_types::{
15 BackendKind, EventPayload, LibinputContext, LibinputDevice, LibinputDeviceGroup, LibinputEvent,
16 LibinputEventType, LibinputInterface, LibinputSeat, LibinputTabletPadModeGroup,
17 LibinputTabletTool,
18};
19
20use std::ffi::CStr;
21use std::os::unix::io::RawFd;
22
23unsafe extern "C" {
24 fn input_emit_log(
25 handler: *mut libc::c_void,
26 context: *mut libc::c_void,
27 priority: u32,
28 format: *const libc::c_char,
29 ...
30 );
31}
32
33#[repr(C)]
34pub struct LibinputConfigAreaRectangle {
35 pub x1: f64,
36 pub y1: f64,
37 pub x2: f64,
38 pub y2: f64,
39}
40
41unsafe fn populate_events(ctx: *mut LibinputContext) {
46 if ctx.is_null() {
47 return;
48 }
49 let ctx_ref = &mut *ctx;
50 let mut tmp: std::collections::VecDeque<LibinputEvent> = std::collections::VecDeque::new();
51 if let Ok(mut backend) = ctx_ref.backend.lock() {
52 backend.drain_into_queue(ctx, &mut tmp);
53 }
54 ctx_ref.event_queue.extend(tmp);
55}
56
57pub(crate) unsafe fn emit_debug_log(ctx: *mut LibinputContext, message: &str) {
58 if ctx.is_null() || (*ctx).log_priority > 10 {
59 return;
60 }
61 let Some(handler) = (*ctx).log_handler else {
62 return;
63 };
64 let Ok(message) = std::ffi::CString::new(format!("{}\n", message.replace('%', "%%"))) else {
65 return;
66 };
67 input_emit_log(
68 handler as *mut libc::c_void,
69 ctx.cast(),
70 10,
71 message.as_ptr(),
72 );
73}
74
75pub(crate) unsafe fn emit_error_log(ctx: *mut LibinputContext, message: &str) {
76 if ctx.is_null() || (*ctx).log_priority > 30 {
77 return;
78 }
79 let Some(handler) = (*ctx).log_handler else {
80 return;
81 };
82 let Ok(message) = std::ffi::CString::new(format!("{}\n", message.replace('%', "%%"))) else {
83 return;
84 };
85 input_emit_log(
86 handler as *mut libc::c_void,
87 ctx.cast(),
88 30,
89 message.as_ptr(),
90 );
91}
92
93pub(crate) unsafe fn emit_info_log(ctx: *mut LibinputContext, message: &str) {
94 if ctx.is_null() || (*ctx).log_priority > 20 {
95 return;
96 }
97 let Some(handler) = (*ctx).log_handler else {
98 return;
99 };
100 let Ok(message) = std::ffi::CString::new(format!("{}\n", message.replace('%', "%%"))) else {
101 return;
102 };
103 input_emit_log(
104 handler as *mut libc::c_void,
105 ctx.cast(),
106 20,
107 message.as_ptr(),
108 );
109}
110
111#[no_mangle]
116pub unsafe extern "C" fn libinput_udev_create_context(
117 interface: *const LibinputInterface,
118 user_data: *mut libc::c_void,
119 udev: *mut libc::c_void,
120) -> *mut LibinputContext {
121 if interface.is_null() || udev.is_null() {
122 return std::ptr::null_mut();
123 }
124 let ctx = Box::into_raw(Box::new(LibinputContext::new(
125 interface,
126 user_data,
127 BackendKind::Udev,
128 )));
129 (*(*ctx).seat).context = ctx;
130 ctx
131}
132
133#[no_mangle]
134pub unsafe extern "C" fn libinput_path_create_context(
135 interface: *const LibinputInterface,
136 user_data: *mut libc::c_void,
137) -> *mut LibinputContext {
138 if interface.is_null() {
139 return std::ptr::null_mut();
140 }
141 let ctx = Box::into_raw(Box::new(LibinputContext::new(
142 interface,
143 user_data,
144 BackendKind::Path,
145 )));
146 (*(*ctx).seat).context = ctx;
147 ctx
148}
149
150#[no_mangle]
151pub unsafe extern "C" fn libinput_ref(ctx: *mut LibinputContext) -> *mut LibinputContext {
152 if ctx.is_null() {
153 return std::ptr::null_mut();
154 }
155 (*ctx).inc_ref();
156 ctx
157}
158
159#[no_mangle]
160pub unsafe extern "C" fn libinput_unref(ctx: *mut LibinputContext) -> *mut LibinputContext {
161 if ctx.is_null() {
162 return std::ptr::null_mut();
163 }
164 if (*ctx).dec_ref() == 0 {
165 drop(Box::from_raw(ctx));
166 return std::ptr::null_mut();
167 }
168 ctx
169}
170
171#[no_mangle]
172pub unsafe extern "C" fn libinput_udev_assign_seat(
173 ctx: *mut LibinputContext,
174 seat_name: *const libc::c_char,
175) -> libc::c_int {
176 if ctx.is_null()
177 || seat_name.is_null()
178 || (*ctx).backend_kind != BackendKind::Udev
179 || (*ctx).seat_assigned
180 {
181 return -1;
182 }
183 let seat_name = CStr::from_ptr(seat_name);
184 if seat_name.to_bytes().len() > 255 {
185 return -1;
186 }
187 let name = seat_name.to_string_lossy().into_owned();
188 if let Ok(cname) = std::ffi::CString::new(name) {
189 (*(*ctx).seat).physical_name = cname;
190 }
191 (*ctx).seat_assigned = true;
192 let mut tmp: Vec<LibinputEvent> = Vec::new();
193 if let Ok(mut backend) = (*ctx).backend.lock() {
194 backend.scan_and_open(ctx, &mut tmp);
195 }
196 for ev in tmp {
197 (*ctx).event_queue.push_back(ev);
198 }
199 0
200}
201
202#[no_mangle]
203pub unsafe extern "C" fn libinput_path_add_device(
204 ctx: *mut LibinputContext,
205 path: *const libc::c_char,
206) -> *mut LibinputDevice {
207 if ctx.is_null() || path.is_null() || (*ctx).backend_kind != BackendKind::Path {
208 return std::ptr::null_mut();
209 }
210 let path = CStr::from_ptr(path);
211 if path.to_bytes().len() > libc::PATH_MAX as usize {
212 emit_error_log(
213 ctx,
214 &format!(
215 "client bug: Unexpected path, limited to {} characters.",
216 libc::PATH_MAX
217 ),
218 );
219 return std::ptr::null_mut();
220 }
221 let devnode = path.to_string_lossy().into_owned();
222 let p = std::path::PathBuf::from(&devnode);
223 use std::os::unix::fs::FileTypeExt;
224 if !p
225 .metadata()
226 .is_ok_and(|metadata| metadata.file_type().is_char_device())
227 {
228 emit_error_log(ctx, "failed to add device");
229 return std::ptr::null_mut();
230 }
231 let mut tmp: Vec<LibinputEvent> = Vec::new();
232 let old_len = (*ctx).devices.len();
233 if let Ok(mut backend) = (*ctx).backend.lock() {
234 backend.try_open(ctx, &p, &mut tmp);
235 }
236 for ev in tmp {
237 (*ctx).event_queue.push_back(ev);
238 }
239 if (*ctx).devices.len() == old_len + 1 {
240 if let Ok(mut backend) = (*ctx).backend.lock() {
241 backend.remember_path(&p);
242 }
243 emit_info_log(ctx, "device added");
244 (&(*ctx).devices)[old_len]
245 } else {
246 emit_error_log(ctx, "failed to add device");
247 std::ptr::null_mut()
248 }
249}
250
251#[no_mangle]
252pub unsafe extern "C" fn libinput_path_remove_device(dev: *mut LibinputDevice) {
253 if dev.is_null() {
254 return;
255 }
256 let ctx = (*dev).context;
257 if ctx.is_null() || (*ctx).backend_kind != BackendKind::Path {
258 return;
259 }
260 let path = std::path::PathBuf::from((*dev).devnode.to_string_lossy().into_owned());
261 let mut events = std::collections::VecDeque::new();
262 let removed = if let Ok(mut backend) = (*ctx).backend.lock() {
263 backend.forget_path(&path);
264 backend.remove_device(ctx, dev, &mut events)
265 } else {
266 false
267 };
268 if removed {
269 (*ctx).devices.retain(|candidate| *candidate != dev);
270 (*ctx).event_queue.extend(events);
271 libinput_device_unref(dev);
272 }
273}
274
275#[no_mangle]
280pub unsafe extern "C" fn libinput_get_fd(ctx: *mut LibinputContext) -> RawFd {
281 if ctx.is_null() {
282 return -1;
283 }
284 (*ctx).epoll_fd
285}
286
287#[no_mangle]
288pub unsafe extern "C" fn libinput_dispatch(ctx: *mut LibinputContext) -> libc::c_int {
289 if ctx.is_null() {
290 return -1;
291 }
292 let mut events: [libc::epoll_event; 16] = std::mem::zeroed();
293 libc::epoll_wait((*ctx).epoll_fd, events.as_mut_ptr(), 16, 0);
294 (*ctx).drain_fd();
295 populate_events(ctx);
296 0
297}
298
299#[no_mangle]
304pub unsafe extern "C" fn libinput_get_event(ctx: *mut LibinputContext) -> *mut LibinputEvent {
305 if ctx.is_null() {
306 return std::ptr::null_mut();
307 }
308 match (*ctx).event_queue.pop_front() {
309 Some(ev) => Box::into_raw(Box::new(ev)),
310 None => std::ptr::null_mut(),
311 }
312}
313
314#[no_mangle]
315pub unsafe extern "C" fn libinput_next_event_type(ctx: *mut LibinputContext) -> LibinputEventType {
316 if ctx.is_null() {
317 return LibinputEventType::LIBINPUT_EVENT_NONE;
318 }
319 (*ctx)
320 .event_queue
321 .front()
322 .map(|e| e.event_type)
323 .unwrap_or(LibinputEventType::LIBINPUT_EVENT_NONE)
324}
325
326#[no_mangle]
327pub unsafe extern "C" fn libinput_event_destroy(event: *mut LibinputEvent) {
328 if !event.is_null() {
329 drop(Box::from_raw(event));
330 }
331}
332
333#[no_mangle]
334pub unsafe extern "C" fn libinput_event_get_type(event: *const LibinputEvent) -> LibinputEventType {
335 if event.is_null() {
336 return LibinputEventType::LIBINPUT_EVENT_NONE;
337 }
338 (*event).event_type
339}
340
341#[no_mangle]
342pub unsafe extern "C" fn libinput_event_get_context(
343 event: *const LibinputEvent,
344) -> *mut LibinputContext {
345 if event.is_null() {
346 return std::ptr::null_mut();
347 }
348 (*event).context
349}
350
351#[no_mangle]
352pub unsafe extern "C" fn libinput_event_get_device(
353 event: *const LibinputEvent,
354) -> *mut LibinputDevice {
355 if event.is_null() {
356 return std::ptr::null_mut();
357 }
358 (*event).device
359}
360
361#[no_mangle]
362pub unsafe extern "C" fn libinput_event_get_device_notify_event(
363 event: *mut LibinputEvent,
364) -> *mut LibinputEvent {
365 if event.is_null() {
366 return std::ptr::null_mut();
367 }
368 match (*event).event_type {
369 LibinputEventType::LIBINPUT_EVENT_DEVICE_ADDED
370 | LibinputEventType::LIBINPUT_EVENT_DEVICE_REMOVED => event,
371 _ => std::ptr::null_mut(),
372 }
373}
374
375#[no_mangle]
376pub unsafe extern "C" fn libinput_event_device_notify_get_base_event(
377 event: *mut LibinputEvent,
378) -> *mut LibinputEvent {
379 event
380}
381
382#[no_mangle]
387pub unsafe extern "C" fn libinput_event_get_pointer_event(
388 event: *mut LibinputEvent,
389) -> *mut LibinputEvent {
390 if event.is_null() {
391 return std::ptr::null_mut();
392 }
393 match (*event).event_type {
394 LibinputEventType::LIBINPUT_EVENT_POINTER_MOTION
395 | LibinputEventType::LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE
396 | LibinputEventType::LIBINPUT_EVENT_POINTER_BUTTON
397 | LibinputEventType::LIBINPUT_EVENT_POINTER_AXIS
398 | LibinputEventType::LIBINPUT_EVENT_POINTER_SCROLL_WHEEL
399 | LibinputEventType::LIBINPUT_EVENT_POINTER_SCROLL_FINGER
400 | LibinputEventType::LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS => event,
401 _ => std::ptr::null_mut(),
402 }
403}
404
405#[no_mangle]
406pub unsafe extern "C" fn libinput_event_pointer_get_base_event(
407 event: *mut LibinputEvent,
408) -> *mut LibinputEvent {
409 event
410}
411
412#[no_mangle]
413pub unsafe extern "C" fn libinput_event_pointer_get_time(event: *const LibinputEvent) -> u32 {
414 if event.is_null() {
415 return 0;
416 }
417 match &(*event).payload {
418 EventPayload::PointerMotion(e) => (e.time_usec / 1000) as u32,
419 EventPayload::PointerMotionAbsolute(e) => (e.time_usec / 1000) as u32,
420 EventPayload::PointerButton(e) => (e.time_usec / 1000) as u32,
421 EventPayload::PointerAxis(e) => (e.time_usec / 1000) as u32,
422 _ => 0,
423 }
424}
425
426#[no_mangle]
427pub unsafe extern "C" fn libinput_event_pointer_get_time_usec(event: *const LibinputEvent) -> u64 {
428 if event.is_null() {
429 return 0;
430 }
431 match &(*event).payload {
432 EventPayload::PointerMotion(e) => e.time_usec,
433 EventPayload::PointerMotionAbsolute(e) => e.time_usec,
434 EventPayload::PointerButton(e) => e.time_usec,
435 EventPayload::PointerAxis(e) => e.time_usec,
436 _ => 0,
437 }
438}
439
440#[no_mangle]
441pub unsafe extern "C" fn libinput_event_pointer_get_dx(event: *const LibinputEvent) -> f64 {
442 if event.is_null() {
443 return 0.0;
444 }
445 if let EventPayload::PointerMotion(e) = &(*event).payload {
446 e.dx
447 } else {
448 0.0
449 }
450}
451
452#[no_mangle]
453pub unsafe extern "C" fn libinput_event_pointer_get_dy(event: *const LibinputEvent) -> f64 {
454 if event.is_null() {
455 return 0.0;
456 }
457 if let EventPayload::PointerMotion(e) = &(*event).payload {
458 e.dy
459 } else {
460 0.0
461 }
462}
463
464#[no_mangle]
465pub unsafe extern "C" fn libinput_event_pointer_get_dx_unaccelerated(
466 event: *const LibinputEvent,
467) -> f64 {
468 if event.is_null() {
469 return 0.0;
470 }
471 if let EventPayload::PointerMotion(e) = &(*event).payload {
472 e.dx_unaccel
473 } else {
474 0.0
475 }
476}
477
478#[no_mangle]
479pub unsafe extern "C" fn libinput_event_pointer_get_dy_unaccelerated(
480 event: *const LibinputEvent,
481) -> f64 {
482 if event.is_null() {
483 return 0.0;
484 }
485 if let EventPayload::PointerMotion(e) = &(*event).payload {
486 e.dy_unaccel
487 } else {
488 0.0
489 }
490}
491
492#[no_mangle]
493pub unsafe extern "C" fn libinput_event_pointer_get_absolute_x(event: *const LibinputEvent) -> f64 {
494 if event.is_null() {
495 return 0.0;
496 }
497 if let EventPayload::PointerMotionAbsolute(e) = &(*event).payload {
498 e.abs_x
499 } else {
500 0.0
501 }
502}
503
504#[no_mangle]
505pub unsafe extern "C" fn libinput_event_pointer_get_absolute_y(event: *const LibinputEvent) -> f64 {
506 if event.is_null() {
507 return 0.0;
508 }
509 if let EventPayload::PointerMotionAbsolute(e) = &(*event).payload {
510 e.abs_y
511 } else {
512 0.0
513 }
514}
515
516#[no_mangle]
517pub unsafe extern "C" fn libinput_event_pointer_get_button(event: *const LibinputEvent) -> u32 {
518 if event.is_null() {
519 return 0;
520 }
521 if let EventPayload::PointerButton(e) = &(*event).payload {
522 e.button
523 } else {
524 0
525 }
526}
527
528#[no_mangle]
529pub unsafe extern "C" fn libinput_event_pointer_get_button_state(
530 event: *const LibinputEvent,
531) -> u32 {
532 if event.is_null() {
533 return 0;
534 }
535 if let EventPayload::PointerButton(e) = &(*event).payload {
536 e.state
537 } else {
538 0
539 }
540}
541
542#[no_mangle]
543pub unsafe extern "C" fn libinput_event_pointer_get_seat_button_count(
544 event: *const LibinputEvent,
545) -> u32 {
546 if event.is_null() {
547 return 0;
548 }
549 if let EventPayload::PointerButton(e) = &(*event).payload {
550 e.seat_button_count
551 } else {
552 0
553 }
554}
555
556#[no_mangle]
557pub unsafe extern "C" fn libinput_event_pointer_get_axis_value(
558 event: *const LibinputEvent,
559 axis: u32,
560) -> f64 {
561 if event.is_null() {
562 return 0.0;
563 }
564 if let EventPayload::PointerAxis(e) = &(*event).payload {
565 e.value(axis)
566 } else {
567 0.0
568 }
569}
570
571#[no_mangle]
572pub unsafe extern "C" fn libinput_event_pointer_get_axis_value_discrete(
573 event: *const LibinputEvent,
574 axis: u32,
575) -> f64 {
576 if event.is_null() {
577 return 0.0;
578 }
579 if let EventPayload::PointerAxis(e) = &(*event).payload {
580 e.value_discrete(axis) as f64
581 } else {
582 0.0
583 }
584}
585
586#[no_mangle]
587pub unsafe extern "C" fn libinput_event_pointer_get_axis_source(
588 event: *const LibinputEvent,
589) -> u32 {
590 if event.is_null() {
591 return 0;
592 }
593 if let EventPayload::PointerAxis(e) = &(*event).payload {
594 e.source
595 } else {
596 0
597 }
598}
599
600#[no_mangle]
601pub unsafe extern "C" fn libinput_event_pointer_has_axis(
602 event: *const LibinputEvent,
603 axis: u32,
604) -> libc::c_int {
605 if event.is_null() {
606 return 0;
607 }
608 matches!(&(*event).payload, EventPayload::PointerAxis(e) if e.has_axis(axis)) as libc::c_int
609}
610
611#[no_mangle]
616pub unsafe extern "C" fn libinput_event_get_keyboard_event(
617 event: *mut LibinputEvent,
618) -> *mut LibinputEvent {
619 if event.is_null() {
620 return std::ptr::null_mut();
621 }
622 if (*event).event_type == LibinputEventType::LIBINPUT_EVENT_KEYBOARD_KEY {
623 event
624 } else {
625 std::ptr::null_mut()
626 }
627}
628
629#[no_mangle]
630pub unsafe extern "C" fn libinput_event_keyboard_get_base_event(
631 event: *mut LibinputEvent,
632) -> *mut LibinputEvent {
633 event
634}
635
636#[no_mangle]
637pub unsafe extern "C" fn libinput_event_keyboard_get_time(event: *const LibinputEvent) -> u32 {
638 if event.is_null() {
639 return 0;
640 }
641 if let EventPayload::KeyboardKey(e) = &(*event).payload {
642 (e.time_usec / 1000) as u32
643 } else {
644 0
645 }
646}
647
648#[no_mangle]
649pub unsafe extern "C" fn libinput_event_keyboard_get_time_usec(event: *const LibinputEvent) -> u64 {
650 if event.is_null() {
651 return 0;
652 }
653 if let EventPayload::KeyboardKey(e) = &(*event).payload {
654 e.time_usec
655 } else {
656 0
657 }
658}
659
660#[no_mangle]
661pub unsafe extern "C" fn libinput_event_keyboard_get_key(event: *const LibinputEvent) -> u32 {
662 if event.is_null() {
663 return 0;
664 }
665 if let EventPayload::KeyboardKey(e) = &(*event).payload {
666 e.key
667 } else {
668 0
669 }
670}
671
672#[no_mangle]
673pub unsafe extern "C" fn libinput_event_keyboard_get_key_state(event: *const LibinputEvent) -> u32 {
674 if event.is_null() {
675 return 0;
676 }
677 if let EventPayload::KeyboardKey(e) = &(*event).payload {
678 e.state
679 } else {
680 0
681 }
682}
683
684#[no_mangle]
685pub unsafe extern "C" fn libinput_event_keyboard_get_seat_key_count(
686 event: *const LibinputEvent,
687) -> u32 {
688 if event.is_null() {
689 return 0;
690 }
691 if let EventPayload::KeyboardKey(e) = &(*event).payload {
692 if e.state >= 1 {
693 1
694 } else {
695 0
696 }
697 } else {
698 0
699 }
700}
701
702#[no_mangle]
707pub unsafe extern "C" fn libinput_event_get_touch_event(
708 event: *mut LibinputEvent,
709) -> *mut LibinputEvent {
710 if event.is_null() {
711 return std::ptr::null_mut();
712 }
713 match (*event).event_type {
714 LibinputEventType::LIBINPUT_EVENT_TOUCH_DOWN
715 | LibinputEventType::LIBINPUT_EVENT_TOUCH_UP
716 | LibinputEventType::LIBINPUT_EVENT_TOUCH_MOTION
717 | LibinputEventType::LIBINPUT_EVENT_TOUCH_CANCEL
718 | LibinputEventType::LIBINPUT_EVENT_TOUCH_FRAME => event,
719 _ => std::ptr::null_mut(),
720 }
721}
722
723#[no_mangle]
724pub unsafe extern "C" fn libinput_event_touch_get_base_event(
725 event: *mut LibinputEvent,
726) -> *mut LibinputEvent {
727 event
728}
729
730#[no_mangle]
731pub unsafe extern "C" fn libinput_event_touch_get_time(event: *const LibinputEvent) -> u32 {
732 if event.is_null() {
733 return 0;
734 }
735 match &(*event).payload {
736 EventPayload::TouchDown(e)
737 | EventPayload::TouchUp(e)
738 | EventPayload::TouchMotion(e)
739 | EventPayload::TouchCancel(e) => (e.time_usec / 1000) as u32,
740 EventPayload::TouchFrame { time_usec } => (*time_usec / 1000) as u32,
741 _ => 0,
742 }
743}
744
745#[no_mangle]
746pub unsafe extern "C" fn libinput_event_touch_get_time_usec(event: *const LibinputEvent) -> u64 {
747 if event.is_null() {
748 return 0;
749 }
750 match &(*event).payload {
751 EventPayload::TouchDown(e)
752 | EventPayload::TouchUp(e)
753 | EventPayload::TouchMotion(e)
754 | EventPayload::TouchCancel(e) => e.time_usec,
755 EventPayload::TouchFrame { time_usec } => *time_usec,
756 _ => 0,
757 }
758}
759
760#[no_mangle]
761pub unsafe extern "C" fn libinput_event_touch_get_slot(event: *const LibinputEvent) -> i32 {
762 if event.is_null() {
763 return -1;
764 }
765 match &(*event).payload {
766 EventPayload::TouchDown(e) | EventPayload::TouchMotion(e) | EventPayload::TouchUp(e) => {
767 e.slot
768 }
769 _ => -1,
770 }
771}
772
773#[no_mangle]
774pub unsafe extern "C" fn libinput_event_touch_get_seat_slot(event: *const LibinputEvent) -> i32 {
775 if event.is_null() {
776 return -1;
777 }
778 match &(*event).payload {
779 EventPayload::TouchDown(e) | EventPayload::TouchMotion(e) | EventPayload::TouchUp(e) => {
780 e.seat_slot
781 }
782 _ => -1,
783 }
784}
785
786#[no_mangle]
787pub unsafe extern "C" fn libinput_event_touch_get_x(event: *const LibinputEvent) -> f64 {
788 if event.is_null() {
789 return 0.0;
790 }
791 match &(*event).payload {
792 EventPayload::TouchDown(e) | EventPayload::TouchMotion(e) => {
793 let device = (*event).device;
794 if !device.is_null() {
795 if let (Some((minimum, _)), Some(resolution)) =
796 ((*device).abs_x_range, (*device).abs_x_resolution)
797 {
798 return (e.x - minimum as f64) / resolution as f64;
799 }
800 }
801 e.x
802 }
803 _ => 0.0,
804 }
805}
806
807#[no_mangle]
808pub unsafe extern "C" fn libinput_event_touch_get_y(event: *const LibinputEvent) -> f64 {
809 if event.is_null() {
810 return 0.0;
811 }
812 match &(*event).payload {
813 EventPayload::TouchDown(e) | EventPayload::TouchMotion(e) => {
814 let device = (*event).device;
815 if !device.is_null() {
816 if let (Some((minimum, _)), Some(resolution)) =
817 ((*device).abs_y_range, (*device).abs_y_resolution)
818 {
819 return (e.y - minimum as f64) / resolution as f64;
820 }
821 }
822 e.y
823 }
824 _ => 0.0,
825 }
826}
827
828unsafe fn transformed_touch_coordinates(event: *const LibinputEvent) -> Option<(f64, f64)> {
829 let touch = match &(*event).payload {
830 EventPayload::TouchDown(e) | EventPayload::TouchMotion(e) => e,
831 _ => return None,
832 };
833 let device = (*event).device;
834 if device.is_null() {
835 return None;
836 }
837 let ((xmin, xmax), (ymin, ymax)) = ((*device).abs_x_range?, (*device).abs_y_range?);
838 let x_span = (xmax as i64 - xmin as i64 + 1).max(1) as f64;
839 let y_span = (ymax as i64 - ymin as i64 + 1).max(1) as f64;
840 let x = (touch.x - xmin as f64) / x_span;
841 let y = (touch.y - ymin as f64) / y_span;
842 let matrix = (*device).calibration;
843 Some((
844 matrix[0] as f64 * x + matrix[1] as f64 * y + matrix[2] as f64,
845 matrix[3] as f64 * x + matrix[4] as f64 * y + matrix[5] as f64,
846 ))
847}
848
849#[no_mangle]
850pub unsafe extern "C" fn libinput_event_touch_get_x_transformed(
851 event: *const LibinputEvent,
852 width: u32,
853) -> f64 {
854 if event.is_null() {
855 return 0.0;
856 }
857 transformed_touch_coordinates(event)
858 .map(|(x, _)| x * width as f64)
859 .unwrap_or(0.0)
860}
861
862#[no_mangle]
863pub unsafe extern "C" fn libinput_event_touch_get_y_transformed(
864 event: *const LibinputEvent,
865 height: u32,
866) -> f64 {
867 if event.is_null() {
868 return 0.0;
869 }
870 transformed_touch_coordinates(event)
871 .map(|(_, y)| y * height as f64)
872 .unwrap_or(0.0)
873}
874
875#[no_mangle]
880pub unsafe extern "C" fn libinput_event_get_gesture_event(
881 event: *mut LibinputEvent,
882) -> *mut LibinputEvent {
883 if event.is_null() {
884 return std::ptr::null_mut();
885 }
886 match (*event).event_type {
887 LibinputEventType::LIBINPUT_EVENT_GESTURE_SWIPE_BEGIN
888 | LibinputEventType::LIBINPUT_EVENT_GESTURE_SWIPE_UPDATE
889 | LibinputEventType::LIBINPUT_EVENT_GESTURE_SWIPE_END
890 | LibinputEventType::LIBINPUT_EVENT_GESTURE_PINCH_BEGIN
891 | LibinputEventType::LIBINPUT_EVENT_GESTURE_PINCH_UPDATE
892 | LibinputEventType::LIBINPUT_EVENT_GESTURE_PINCH_END
893 | LibinputEventType::LIBINPUT_EVENT_GESTURE_HOLD_BEGIN
894 | LibinputEventType::LIBINPUT_EVENT_GESTURE_HOLD_END => event,
895 _ => std::ptr::null_mut(),
896 }
897}
898
899#[no_mangle]
900pub unsafe extern "C" fn libinput_event_gesture_get_base_event(
901 event: *mut LibinputEvent,
902) -> *mut LibinputEvent {
903 event
904}
905
906#[no_mangle]
907pub unsafe extern "C" fn libinput_event_gesture_get_time(event: *const LibinputEvent) -> u32 {
908 if event.is_null() {
909 return 0;
910 }
911 match &(*event).payload {
912 EventPayload::GestureSwipeBegin(e)
913 | EventPayload::GestureSwipeUpdate(e)
914 | EventPayload::GestureSwipeEnd(e)
915 | EventPayload::GesturePinchBegin(e)
916 | EventPayload::GesturePinchUpdate(e)
917 | EventPayload::GesturePinchEnd(e)
918 | EventPayload::GestureHoldBegin(e)
919 | EventPayload::GestureHoldEnd(e) => (e.time_usec / 1000) as u32,
920 _ => 0,
921 }
922}
923
924#[no_mangle]
925pub unsafe extern "C" fn libinput_event_gesture_get_time_usec(event: *const LibinputEvent) -> u64 {
926 if event.is_null() {
927 return 0;
928 }
929 match &(*event).payload {
930 EventPayload::GestureSwipeBegin(e)
931 | EventPayload::GestureSwipeUpdate(e)
932 | EventPayload::GestureSwipeEnd(e)
933 | EventPayload::GesturePinchBegin(e)
934 | EventPayload::GesturePinchUpdate(e)
935 | EventPayload::GesturePinchEnd(e)
936 | EventPayload::GestureHoldBegin(e)
937 | EventPayload::GestureHoldEnd(e) => e.time_usec,
938 _ => 0,
939 }
940}
941
942#[no_mangle]
943pub unsafe extern "C" fn libinput_event_gesture_get_finger_count(
944 event: *const LibinputEvent,
945) -> libc::c_int {
946 if event.is_null() {
947 return 0;
948 }
949 match &(*event).payload {
950 EventPayload::GestureSwipeBegin(e)
951 | EventPayload::GestureSwipeUpdate(e)
952 | EventPayload::GestureSwipeEnd(e)
953 | EventPayload::GesturePinchBegin(e)
954 | EventPayload::GesturePinchUpdate(e)
955 | EventPayload::GesturePinchEnd(e)
956 | EventPayload::GestureHoldBegin(e)
957 | EventPayload::GestureHoldEnd(e) => e.finger_count,
958 _ => 0,
959 }
960}
961
962#[no_mangle]
963pub unsafe extern "C" fn libinput_event_gesture_get_dx(event: *const LibinputEvent) -> f64 {
964 if event.is_null() {
965 return 0.0;
966 }
967 match &(*event).payload {
968 EventPayload::GestureSwipeUpdate(e) | EventPayload::GesturePinchUpdate(e) => e.dx,
969 _ => 0.0,
970 }
971}
972
973#[no_mangle]
974pub unsafe extern "C" fn libinput_event_gesture_get_dy(event: *const LibinputEvent) -> f64 {
975 if event.is_null() {
976 return 0.0;
977 }
978 match &(*event).payload {
979 EventPayload::GestureSwipeUpdate(e) | EventPayload::GesturePinchUpdate(e) => e.dy,
980 _ => 0.0,
981 }
982}
983
984#[no_mangle]
985pub unsafe extern "C" fn libinput_event_gesture_get_dx_unaccelerated(
986 event: *const LibinputEvent,
987) -> f64 {
988 if event.is_null() {
989 return 0.0;
990 }
991 match &(*event).payload {
992 EventPayload::GestureSwipeUpdate(e) | EventPayload::GesturePinchUpdate(e) => e.dx / 1.2,
993 _ => 0.0,
994 }
995}
996
997#[no_mangle]
998pub unsafe extern "C" fn libinput_event_gesture_get_dy_unaccelerated(
999 event: *const LibinputEvent,
1000) -> f64 {
1001 if event.is_null() {
1002 return 0.0;
1003 }
1004 match &(*event).payload {
1005 EventPayload::GestureSwipeUpdate(e) | EventPayload::GesturePinchUpdate(e) => e.dy / 1.2,
1006 _ => 0.0,
1007 }
1008}
1009
1010#[no_mangle]
1011pub unsafe extern "C" fn libinput_event_gesture_get_scale(event: *const LibinputEvent) -> f64 {
1012 if event.is_null() {
1013 return 1.0;
1014 }
1015 match &(*event).payload {
1016 EventPayload::GesturePinchUpdate(e) | EventPayload::GesturePinchEnd(e) => e.scale,
1017 _ => 1.0,
1018 }
1019}
1020
1021#[no_mangle]
1022pub unsafe extern "C" fn libinput_event_gesture_get_angle_delta(
1023 event: *const LibinputEvent,
1024) -> f64 {
1025 if event.is_null() {
1026 return 0.0;
1027 }
1028 match &(*event).payload {
1029 EventPayload::GesturePinchUpdate(e) => e.angle,
1030 _ => 0.0,
1031 }
1032}
1033
1034#[no_mangle]
1035pub unsafe extern "C" fn libinput_event_gesture_get_cancelled(
1036 event: *const LibinputEvent,
1037) -> libc::c_int {
1038 if event.is_null() {
1039 return 0;
1040 }
1041 match &(*event).payload {
1042 EventPayload::GestureSwipeEnd(e)
1043 | EventPayload::GesturePinchEnd(e)
1044 | EventPayload::GestureHoldEnd(e) => e.cancelled as libc::c_int,
1045 _ => 0,
1046 }
1047}
1048
1049#[no_mangle]
1054pub unsafe extern "C" fn libinput_event_get_switch_event(
1055 event: *mut LibinputEvent,
1056) -> *mut LibinputEvent {
1057 if event.is_null() {
1058 return std::ptr::null_mut();
1059 }
1060 if (*event).event_type == LibinputEventType::LIBINPUT_EVENT_SWITCH_TOGGLE {
1061 event
1062 } else {
1063 std::ptr::null_mut()
1064 }
1065}
1066
1067#[no_mangle]
1068pub unsafe extern "C" fn libinput_event_switch_get_base_event(
1069 event: *mut LibinputEvent,
1070) -> *mut LibinputEvent {
1071 event
1072}
1073
1074#[no_mangle]
1075pub unsafe extern "C" fn libinput_event_switch_get_switch(event: *const LibinputEvent) -> u32 {
1076 if event.is_null() {
1077 return 0;
1078 }
1079 if let EventPayload::SwitchToggle(e) = &(*event).payload {
1080 e.switch
1081 } else {
1082 0
1083 }
1084}
1085
1086#[no_mangle]
1087pub unsafe extern "C" fn libinput_event_switch_get_switch_state(
1088 event: *const LibinputEvent,
1089) -> u32 {
1090 if event.is_null() {
1091 return 0;
1092 }
1093 if let EventPayload::SwitchToggle(e) = &(*event).payload {
1094 e.state
1095 } else {
1096 0
1097 }
1098}
1099
1100#[no_mangle]
1105pub unsafe extern "C" fn libinput_device_ref(dev: *mut LibinputDevice) -> *mut LibinputDevice {
1106 if dev.is_null() {
1107 return std::ptr::null_mut();
1108 }
1109 let current = (*dev)
1110 .refcount
1111 .fetch_add(1, std::sync::atomic::Ordering::SeqCst);
1112 (*dev).abi.refcount = current + 1;
1113 dev
1114}
1115
1116#[no_mangle]
1117pub unsafe extern "C" fn libinput_device_unref(dev: *mut LibinputDevice) -> *mut LibinputDevice {
1118 if dev.is_null() {
1119 return std::ptr::null_mut();
1120 }
1121 let remaining = (*dev)
1122 .refcount
1123 .fetch_sub(1, std::sync::atomic::Ordering::SeqCst)
1124 - 1;
1125 (*dev).abi.refcount = remaining;
1126 if remaining <= 0 {
1127 drop(Box::from_raw(dev));
1128 std::ptr::null_mut()
1129 } else {
1130 dev
1131 }
1132}
1133
1134#[no_mangle]
1135pub unsafe extern "C" fn libinput_device_get_name(
1136 dev: *const LibinputDevice,
1137) -> *const libc::c_char {
1138 if dev.is_null() {
1139 return std::ptr::null();
1140 }
1141 (*dev).name.as_ptr()
1142}
1143
1144#[no_mangle]
1145pub unsafe extern "C" fn libinput_device_get_sysname(
1146 dev: *const LibinputDevice,
1147) -> *const libc::c_char {
1148 if dev.is_null() {
1149 return std::ptr::null();
1150 }
1151 (*dev).sysname.as_ptr()
1152}
1153
1154#[no_mangle]
1155pub unsafe extern "C" fn libinput_device_get_output_name(
1156 dev: *const LibinputDevice,
1157) -> *const libc::c_char {
1158 if dev.is_null() {
1159 return std::ptr::null();
1160 }
1161 (*dev)
1162 .output_name
1163 .as_ref()
1164 .map_or(std::ptr::null(), |name| name.as_ptr())
1165}
1166
1167#[no_mangle]
1168pub unsafe extern "C" fn libinput_device_get_id_vendor(dev: *const LibinputDevice) -> libc::c_uint {
1169 if dev.is_null() {
1170 return 0;
1171 }
1172 (*dev).vendor_id
1173}
1174
1175#[no_mangle]
1176pub unsafe extern "C" fn libinput_device_get_id_product(
1177 dev: *const LibinputDevice,
1178) -> libc::c_uint {
1179 if dev.is_null() {
1180 return 0;
1181 }
1182 (*dev).product_id
1183}
1184
1185#[no_mangle]
1186pub unsafe extern "C" fn libinput_device_get_context(
1187 dev: *const LibinputDevice,
1188) -> *mut LibinputContext {
1189 if dev.is_null() {
1190 return std::ptr::null_mut();
1191 }
1192 (*dev).context
1193}
1194
1195#[no_mangle]
1196pub unsafe extern "C" fn libinput_device_get_devnode(
1197 dev: *const LibinputDevice,
1198) -> *const libc::c_char {
1199 if dev.is_null() {
1200 return std::ptr::null();
1201 }
1202 (*dev).devnode.as_ptr()
1203}
1204
1205#[no_mangle]
1206pub unsafe extern "C" fn libinput_device_touch_get_touch_count(
1207 dev: *const LibinputDevice,
1208) -> libc::c_int {
1209 if dev.is_null() || !(*dev).has_touch {
1210 return -1;
1211 }
1212 (*dev).touch_count
1213}
1214
1215#[no_mangle]
1216pub unsafe extern "C" fn libinput_device_has_capability(
1217 dev: *const LibinputDevice,
1218 capability: u32,
1219) -> libc::c_int {
1220 if dev.is_null() {
1221 return 0;
1222 }
1223 let has = match capability {
1224 0 => (*dev).has_keyboard,
1225 1 => (*dev).has_pointer,
1226 2 => (*dev).has_touch,
1227 3 => (*dev).has_tablet,
1228 4 => (*dev).has_tablet_pad,
1229 5 => (*dev).has_gesture,
1230 6 => (*dev).has_switch,
1231 _ => false,
1232 };
1233 has as libc::c_int
1234}
1235
1236#[no_mangle]
1241pub unsafe extern "C" fn libinput_device_config_tap_get_finger_count(
1242 dev: *const LibinputDevice,
1243) -> libc::c_int {
1244 if dev.is_null() {
1245 return 0;
1246 }
1247 if (*dev).has_touch || (*dev).has_pointer {
1248 3
1249 } else {
1250 0
1251 }
1252}
1253
1254#[no_mangle]
1255pub unsafe extern "C" fn libinput_device_config_tap_set_enabled(
1256 dev: *mut LibinputDevice,
1257 enabled: u32,
1258) -> u32 {
1259 if dev.is_null() {
1260 return 1;
1261 }
1262 (*dev).tap_enabled = enabled != 0;
1263 0
1264}
1265
1266#[no_mangle]
1267pub unsafe extern "C" fn libinput_device_config_tap_get_enabled(dev: *const LibinputDevice) -> u32 {
1268 if dev.is_null() {
1269 return 0;
1270 }
1271 (*dev).tap_enabled as u32
1272}
1273
1274#[no_mangle]
1275pub unsafe extern "C" fn libinput_device_config_tap_get_default_enabled(
1276 _dev: *const LibinputDevice,
1277) -> u32 {
1278 0
1279}
1280
1281#[no_mangle]
1282pub unsafe extern "C" fn libinput_device_config_tap_set_drag_enabled(
1283 dev: *mut LibinputDevice,
1284 _e: u32,
1285) -> u32 {
1286 if dev.is_null() {
1287 1
1288 } else {
1289 0
1290 }
1291}
1292
1293#[no_mangle]
1294pub unsafe extern "C" fn libinput_device_config_tap_get_drag_enabled(
1295 _dev: *const LibinputDevice,
1296) -> u32 {
1297 1
1298}
1299
1300#[no_mangle]
1301pub unsafe extern "C" fn libinput_device_config_tap_get_default_drag_enabled(
1302 _dev: *const LibinputDevice,
1303) -> u32 {
1304 1
1305}
1306
1307#[no_mangle]
1308pub unsafe extern "C" fn libinput_device_config_tap_set_drag_lock_enabled(
1309 dev: *mut LibinputDevice,
1310 _e: u32,
1311) -> u32 {
1312 if dev.is_null() {
1313 1
1314 } else {
1315 0
1316 }
1317}
1318
1319#[no_mangle]
1320pub unsafe extern "C" fn libinput_device_config_tap_get_drag_lock_enabled(
1321 _dev: *const LibinputDevice,
1322) -> u32 {
1323 0
1324}
1325
1326#[no_mangle]
1328pub unsafe extern "C" fn libinput_device_config_tap_set_button_map(
1329 dev: *mut LibinputDevice,
1330 map: u32,
1331) -> u32 {
1332 if dev.is_null() {
1333 return 1;
1334 }
1335 (*dev).tap_button_map = map;
1336 0
1337}
1338
1339#[no_mangle]
1340pub unsafe extern "C" fn libinput_device_config_tap_get_button_map(
1341 dev: *const LibinputDevice,
1342) -> u32 {
1343 if dev.is_null() {
1344 return 0;
1345 }
1346 (*dev).tap_button_map
1347}
1348
1349#[no_mangle]
1350pub unsafe extern "C" fn libinput_device_config_tap_get_default_button_map(
1351 _dev: *const LibinputDevice,
1352) -> u32 {
1353 0
1354} #[no_mangle]
1357pub unsafe extern "C" fn libinput_device_config_3fg_drag_get_finger_count(
1358 dev: *const LibinputDevice,
1359) -> libc::c_int {
1360 if dev.is_null() || !(*dev).has_gesture {
1361 return 0;
1362 }
1363 (*dev).mt_slot_count
1364}
1365
1366#[no_mangle]
1367pub unsafe extern "C" fn libinput_device_config_3fg_drag_set_enabled(
1368 dev: *mut LibinputDevice,
1369 enable: u32,
1370) -> u32 {
1371 if dev.is_null() {
1372 return 1;
1373 }
1374 if !matches!(enable, 0..=2) {
1375 return 2;
1376 }
1377 if libinput_device_config_3fg_drag_get_finger_count(dev) < 3 {
1378 return 1;
1379 }
1380 (*dev).drag_3fg_enabled = enable;
1381 0
1382}
1383
1384#[no_mangle]
1385pub unsafe extern "C" fn libinput_device_config_3fg_drag_get_enabled(
1386 dev: *const LibinputDevice,
1387) -> u32 {
1388 if dev.is_null() {
1389 return 0;
1390 }
1391 (*dev).drag_3fg_enabled
1392}
1393
1394#[no_mangle]
1395pub unsafe extern "C" fn libinput_device_config_3fg_drag_get_default_enabled(
1396 _dev: *const LibinputDevice,
1397) -> u32 {
1398 0
1399}
1400
1401#[no_mangle]
1406pub unsafe extern "C" fn libinput_config_accel_create(profile: u32) -> *mut libc::c_void {
1407 if !matches!(profile, 1 | 2 | 4) {
1408 return std::ptr::null_mut();
1409 }
1410 Box::into_raw(Box::new(profile)) as *mut libc::c_void
1411}
1412
1413#[no_mangle]
1414pub unsafe extern "C" fn libinput_config_accel_destroy(accel_config: *mut libc::c_void) {
1415 if !accel_config.is_null() {
1416 drop(Box::from_raw(accel_config as *mut u32));
1417 }
1418}
1419
1420#[no_mangle]
1421pub unsafe extern "C" fn libinput_config_accel_set_points(
1422 accel_config: *mut libc::c_void,
1423 _accel_type: u32,
1424 step: f64,
1425 npoints: libc::size_t,
1426 points: *const f64,
1427) -> u32 {
1428 if accel_config.is_null()
1429 || points.is_null()
1430 || !step.is_finite()
1431 || step <= 0.0
1432 || step >= 1e10
1433 || npoints == 0
1434 {
1435 return 2;
1436 }
1437 let points = std::slice::from_raw_parts(points, npoints);
1438 if points
1439 .iter()
1440 .any(|point| !point.is_finite() || *point < 0.0 || *point >= 1e10)
1441 {
1442 return 2;
1443 }
1444 0
1445}
1446
1447#[no_mangle]
1448pub unsafe extern "C" fn libinput_device_config_accel_apply(
1449 dev: *mut LibinputDevice,
1450 accel_config: *mut libc::c_void,
1451) -> u32 {
1452 if dev.is_null() || accel_config.is_null() {
1453 return 2;
1454 }
1455 if !(*dev).accel_available {
1456 return 1;
1457 }
1458 let profile = *(accel_config as *const u32);
1459 if profile & libinput_device_config_accel_get_profiles(dev) == 0 {
1460 return 1;
1461 }
1462 (*dev).accel_profile = profile;
1463 (*dev).accel_speed = 0.0;
1464 0
1465}
1466
1467#[no_mangle]
1468pub unsafe extern "C" fn libinput_device_config_accel_is_available(
1469 dev: *const LibinputDevice,
1470) -> libc::c_int {
1471 if dev.is_null() {
1472 return 0;
1473 }
1474 (*dev).accel_available as libc::c_int
1475}
1476
1477#[no_mangle]
1478pub unsafe extern "C" fn libinput_device_config_accel_set_speed(
1479 dev: *mut LibinputDevice,
1480 speed: f64,
1481) -> u32 {
1482 if dev.is_null() {
1483 return 1;
1484 }
1485 if !speed.is_finite() || !(-1.0..=1.0).contains(&speed) {
1486 return 2;
1487 }
1488 if !(*dev).accel_available {
1489 return 1;
1490 }
1491 (*dev).accel_speed = speed;
1492 0
1493}
1494
1495#[no_mangle]
1496pub unsafe extern "C" fn libinput_device_config_accel_get_speed(dev: *const LibinputDevice) -> f64 {
1497 if dev.is_null() {
1498 return 0.0;
1499 }
1500 (*dev).accel_speed
1501}
1502
1503#[no_mangle]
1504pub unsafe extern "C" fn libinput_device_config_accel_get_default_speed(
1505 _dev: *const LibinputDevice,
1506) -> f64 {
1507 0.0
1508}
1509
1510#[no_mangle]
1511pub unsafe extern "C" fn libinput_device_config_accel_get_profiles(
1512 dev: *const LibinputDevice,
1513) -> u32 {
1514 if dev.is_null() {
1515 return 0;
1516 }
1517 if (*dev).accel_available
1518 && !((*dev).has_tablet && !(*dev).has_gesture && !(*dev).has_tablet_pad)
1519 {
1520 0b111
1521 } else {
1522 0
1523 }
1524}
1525
1526#[no_mangle]
1527pub unsafe extern "C" fn libinput_device_config_accel_set_profile(
1528 dev: *mut LibinputDevice,
1529 profile: u32,
1530) -> u32 {
1531 if dev.is_null() {
1532 return 1;
1533 }
1534 if profile == 0 || profile & !0b111 != 0 || profile.count_ones() != 1 {
1535 return 2;
1536 }
1537 if profile & libinput_device_config_accel_get_profiles(dev) == 0 {
1538 return 1;
1539 }
1540 (*dev).accel_profile = profile;
1541 0
1542}
1543
1544#[no_mangle]
1545pub unsafe extern "C" fn libinput_device_config_accel_get_profile(
1546 dev: *const LibinputDevice,
1547) -> u32 {
1548 if dev.is_null() {
1549 return 0;
1550 }
1551 if (*dev).accel_available
1552 && !((*dev).has_tablet && !(*dev).has_gesture && !(*dev).has_tablet_pad)
1553 {
1554 (*dev).accel_profile
1555 } else {
1556 0
1557 }
1558}
1559
1560#[no_mangle]
1561pub unsafe extern "C" fn libinput_device_config_accel_get_default_profile(
1562 dev: *const LibinputDevice,
1563) -> u32 {
1564 if dev.is_null()
1565 || !(*dev).accel_available
1566 || ((*dev).has_tablet && !(*dev).has_gesture && !(*dev).has_tablet_pad)
1567 {
1568 0
1569 } else {
1570 2
1571 }
1572}
1573
1574#[no_mangle]
1579pub unsafe extern "C" fn libinput_device_config_scroll_has_natural_scroll(
1580 dev: *const LibinputDevice,
1581) -> libc::c_int {
1582 if dev.is_null() {
1583 return 0;
1584 }
1585 (*dev).has_pointer as libc::c_int
1586}
1587
1588#[no_mangle]
1589pub unsafe extern "C" fn libinput_device_config_scroll_set_natural_scroll_enabled(
1590 dev: *mut LibinputDevice,
1591 enabled: libc::c_int,
1592) -> u32 {
1593 if dev.is_null() || !(*dev).has_pointer {
1594 return 1;
1595 }
1596 (*dev).natural_scroll = enabled != 0;
1597 0
1598}
1599
1600#[no_mangle]
1601pub unsafe extern "C" fn libinput_device_config_scroll_get_natural_scroll_enabled(
1602 dev: *const LibinputDevice,
1603) -> libc::c_int {
1604 if dev.is_null() {
1605 return 0;
1606 }
1607 (*dev).natural_scroll as libc::c_int
1608}
1609
1610#[no_mangle]
1611pub unsafe extern "C" fn libinput_device_config_scroll_get_default_natural_scroll_enabled(
1612 dev: *const LibinputDevice,
1613) -> libc::c_int {
1614 if dev.is_null() {
1615 return 0;
1616 }
1617 ((*dev).scroll_methods & 2 != 0 && (*dev).vendor_id == 0x05ac) as libc::c_int
1618}
1619
1620#[no_mangle]
1625pub unsafe extern "C" fn libinput_device_config_left_handed_is_available(
1626 dev: *const LibinputDevice,
1627) -> libc::c_int {
1628 if dev.is_null() {
1629 return 0;
1630 }
1631 (*dev).left_handed_available as libc::c_int
1632}
1633
1634#[no_mangle]
1635pub unsafe extern "C" fn libinput_device_config_left_handed_set(
1636 dev: *mut LibinputDevice,
1637 enabled: libc::c_int,
1638) -> u32 {
1639 if dev.is_null() || !(*dev).left_handed_available {
1640 return 1;
1641 }
1642 (*dev).left_handed = enabled != 0;
1643 0
1644}
1645
1646#[no_mangle]
1647pub unsafe extern "C" fn libinput_device_config_left_handed_get(
1648 dev: *const LibinputDevice,
1649) -> libc::c_int {
1650 if dev.is_null() {
1651 return 0;
1652 }
1653 (*dev).left_handed as libc::c_int
1654}
1655
1656#[no_mangle]
1657pub unsafe extern "C" fn libinput_device_config_left_handed_get_default(
1658 _dev: *const LibinputDevice,
1659) -> libc::c_int {
1660 0
1661}
1662
1663#[no_mangle]
1668pub unsafe extern "C" fn libinput_device_config_scroll_get_methods(
1669 dev: *const LibinputDevice,
1670) -> u32 {
1671 if dev.is_null() {
1672 return 0;
1673 }
1674 (*dev).scroll_methods
1675}
1676
1677#[no_mangle]
1678pub unsafe extern "C" fn libinput_device_config_scroll_set_method(
1679 dev: *mut LibinputDevice,
1680 method: u32,
1681) -> u32 {
1682 if dev.is_null() {
1683 return 1;
1684 }
1685 if !matches!(method, 0 | 1 | 2 | 4) {
1686 return 2;
1687 }
1688 if method != 0 && method & (*dev).scroll_methods == 0 {
1689 return 1;
1690 }
1691 if (*dev).scroll_method == method {
1692 return 0;
1693 }
1694 let ctx = (*dev).context;
1695 if !ctx.is_null() {
1696 let mut events = std::collections::VecDeque::new();
1697 if let Ok(mut backend) = (*ctx).backend.try_lock() {
1698 backend.stop_scroll_for_device(ctx, dev, &mut events);
1699 }
1700 (*ctx).event_queue.extend(events);
1701 }
1702 (*dev).scroll_method = method;
1703 0
1704}
1705
1706#[no_mangle]
1707pub unsafe extern "C" fn libinput_device_config_scroll_get_method(
1708 dev: *const LibinputDevice,
1709) -> u32 {
1710 if dev.is_null() {
1711 return 0;
1712 }
1713 (*dev).scroll_method
1714}
1715
1716#[no_mangle]
1717pub unsafe extern "C" fn libinput_device_config_scroll_get_default_method(
1718 dev: *const LibinputDevice,
1719) -> u32 {
1720 if dev.is_null() {
1721 0
1722 } else {
1723 (*dev).scroll_default_method
1724 }
1725}
1726
1727#[no_mangle]
1728pub unsafe extern "C" fn libinput_device_config_scroll_set_button(
1729 dev: *mut LibinputDevice,
1730 button: u32,
1731) -> u32 {
1732 if dev.is_null() || !(*dev).supports_button_scroll {
1733 return 1;
1734 }
1735 if button != 0
1736 && match u16::try_from(button) {
1737 Ok(button) => !(*dev).event_codes.contains(&button),
1738 Err(_) => true,
1739 }
1740 {
1741 return 2;
1742 }
1743 (*dev).scroll_button = button;
1744 0
1745}
1746
1747#[no_mangle]
1748pub unsafe extern "C" fn libinput_device_config_scroll_get_button(
1749 dev: *const LibinputDevice,
1750) -> u32 {
1751 if dev.is_null() || !(*dev).supports_button_scroll {
1752 0
1753 } else {
1754 (*dev).scroll_button
1755 }
1756}
1757
1758#[no_mangle]
1759pub unsafe extern "C" fn libinput_device_config_scroll_set_button_lock(
1760 dev: *mut LibinputDevice,
1761 state: u32,
1762) -> u32 {
1763 if dev.is_null() || !(*dev).supports_button_scroll {
1764 return 1;
1765 }
1766 if state > 1 {
1767 return 2;
1768 }
1769 (*dev).scroll_button_lock = state;
1770 0
1771}
1772
1773#[no_mangle]
1774pub unsafe extern "C" fn libinput_device_config_scroll_get_button_lock(
1775 dev: *const LibinputDevice,
1776) -> u32 {
1777 if dev.is_null() || !(*dev).supports_button_scroll {
1778 0
1779 } else {
1780 (*dev).scroll_button_lock
1781 }
1782}
1783
1784#[no_mangle]
1785pub unsafe extern "C" fn libinput_device_config_scroll_get_default_button_lock(
1786 _dev: *const LibinputDevice,
1787) -> u32 {
1788 0
1789}
1790
1791#[no_mangle]
1796pub unsafe extern "C" fn libinput_device_config_click_get_methods(
1797 dev: *const LibinputDevice,
1798) -> u32 {
1799 if dev.is_null() {
1800 return 0;
1801 }
1802 (*dev).click_methods
1803}
1804
1805#[no_mangle]
1806pub unsafe extern "C" fn libinput_device_config_click_set_method(
1807 dev: *mut LibinputDevice,
1808 method: u32,
1809) -> u32 {
1810 if dev.is_null() {
1811 return 1;
1812 }
1813 if !matches!(method, 0..=2) {
1814 return 2;
1815 }
1816 if method != 0 && method & (*dev).click_methods == 0 {
1817 return 1;
1818 }
1819 (*dev).click_method = method;
1820 0
1821}
1822
1823#[no_mangle]
1824pub unsafe extern "C" fn libinput_device_config_click_get_method(
1825 dev: *const LibinputDevice,
1826) -> u32 {
1827 if dev.is_null() {
1828 return 0;
1829 }
1830 (*dev).click_method
1831}
1832
1833#[no_mangle]
1834pub unsafe extern "C" fn libinput_device_config_click_get_default_method(
1835 dev: *const LibinputDevice,
1836) -> u32 {
1837 if dev.is_null() {
1838 0
1839 } else {
1840 (*dev).click_default_method
1841 }
1842}
1843
1844#[no_mangle]
1845pub unsafe extern "C" fn libinput_device_config_click_set_clickfinger_button_map(
1846 dev: *mut LibinputDevice,
1847 map: u32,
1848) -> u32 {
1849 if dev.is_null() {
1850 return 1;
1851 }
1852 if !matches!(map, 0 | 1) {
1853 return 2;
1854 }
1855 if (*dev).click_methods & 2 == 0 {
1856 return 1;
1857 }
1858 (*dev).clickfinger_button_map = map;
1859 0
1860}
1861
1862#[no_mangle]
1863pub unsafe extern "C" fn libinput_device_config_click_get_clickfinger_button_map(
1864 dev: *const LibinputDevice,
1865) -> u32 {
1866 if dev.is_null() || (*dev).click_methods & 2 == 0 {
1867 0
1868 } else {
1869 (*dev).clickfinger_button_map
1870 }
1871}
1872
1873#[no_mangle]
1874pub unsafe extern "C" fn libinput_device_config_click_get_default_clickfinger_button_map(
1875 dev: *const LibinputDevice,
1876) -> u32 {
1877 if dev.is_null() || (*dev).click_methods & 2 == 0 {
1878 0
1879 } else {
1880 (*dev).clickfinger_default_button_map
1881 }
1882}
1883
1884#[no_mangle]
1889pub unsafe extern "C" fn libinput_device_config_middle_emulation_is_available(
1890 dev: *const LibinputDevice,
1891) -> libc::c_int {
1892 if dev.is_null() {
1893 return 0;
1894 }
1895 (*dev).middle_emulation_available as libc::c_int
1896}
1897
1898#[no_mangle]
1899pub unsafe extern "C" fn libinput_device_config_middle_emulation_set_enabled(
1900 dev: *mut LibinputDevice,
1901 enabled: u32,
1902) -> u32 {
1903 if dev.is_null() {
1904 return 1;
1905 }
1906 if enabled > 1 {
1907 return 2;
1908 }
1909 if enabled == 1 && !(*dev).middle_emulation_available {
1910 return 1;
1911 }
1912 (*dev).middle_emulation = enabled != 0;
1913 0
1914}
1915
1916#[no_mangle]
1917pub unsafe extern "C" fn libinput_device_config_middle_emulation_get_enabled(
1918 dev: *const LibinputDevice,
1919) -> u32 {
1920 if dev.is_null() || !(*dev).middle_emulation_available {
1921 return 0;
1922 }
1923 (*dev).middle_emulation as u32
1924}
1925
1926#[no_mangle]
1927pub unsafe extern "C" fn libinput_device_config_middle_emulation_get_default_enabled(
1928 dev: *const LibinputDevice,
1929) -> u32 {
1930 if dev.is_null() || !(*dev).middle_emulation_available {
1931 return 0;
1932 }
1933 (*dev).middle_emulation_default as u32
1934}
1935
1936#[no_mangle]
1941pub unsafe extern "C" fn libinput_device_config_dwt_is_available(
1942 dev: *const LibinputDevice,
1943) -> libc::c_int {
1944 (!dev.is_null() && (*dev).dwt_available) as libc::c_int
1945}
1946
1947#[no_mangle]
1948pub unsafe extern "C" fn libinput_device_config_dwt_set_enabled(
1949 dev: *mut LibinputDevice,
1950 enabled: u32,
1951) -> u32 {
1952 if dev.is_null() {
1953 return 1;
1954 }
1955 if !matches!(enabled, 0 | 1) {
1956 return 2;
1957 }
1958 if !(*dev).dwt_available {
1959 return if enabled == 0 { 0 } else { 1 };
1960 }
1961 (*dev).dwt_enabled = enabled == 1;
1962 0
1963}
1964
1965#[no_mangle]
1966pub unsafe extern "C" fn libinput_device_config_dwt_get_enabled(dev: *const LibinputDevice) -> u32 {
1967 if dev.is_null() || !(*dev).dwt_available {
1968 return 0;
1969 }
1970 (*dev).dwt_enabled as u32
1971}
1972
1973#[no_mangle]
1974pub unsafe extern "C" fn libinput_device_config_dwt_get_default_enabled(
1975 dev: *const LibinputDevice,
1976) -> u32 {
1977 (!dev.is_null() && (*dev).dwt_available) as u32
1978}
1979
1980#[no_mangle]
1981pub unsafe extern "C" fn libinput_device_config_dwt_set_timeout(
1982 dev: *mut LibinputDevice,
1983 millis: u32,
1984) -> u32 {
1985 if dev.is_null() {
1986 return 1;
1987 }
1988 if millis == 0 {
1989 return 2;
1990 }
1991 if !(*dev).dwt_available {
1992 return 1;
1993 }
1994 if !(100..=5000).contains(&millis) {
1995 return 2;
1996 }
1997 (*dev).dwt_timeout = millis;
1998 0
1999}
2000
2001#[no_mangle]
2002pub unsafe extern "C" fn libinput_device_config_dwt_get_timeout(dev: *const LibinputDevice) -> u32 {
2003 if dev.is_null() || !(*dev).dwt_available {
2004 0
2005 } else {
2006 (*dev).dwt_timeout
2007 }
2008}
2009
2010#[no_mangle]
2011pub unsafe extern "C" fn libinput_device_config_dwt_get_default_timeout(
2012 dev: *const LibinputDevice,
2013) -> u32 {
2014 if !dev.is_null() && (*dev).dwt_available {
2015 500
2016 } else {
2017 0
2018 }
2019}
2020
2021#[no_mangle]
2022pub unsafe extern "C" fn libinput_device_config_dwtp_is_available(
2023 dev: *const LibinputDevice,
2024) -> libc::c_int {
2025 (!dev.is_null() && (*dev).dwtp_available) as libc::c_int
2026}
2027
2028#[no_mangle]
2029pub unsafe extern "C" fn libinput_device_config_dwtp_set_enabled(
2030 dev: *mut LibinputDevice,
2031 enabled: u32,
2032) -> u32 {
2033 if dev.is_null() {
2034 return 1;
2035 }
2036 if !matches!(enabled, 0 | 1) {
2037 return 2;
2038 }
2039 if !(*dev).dwtp_available {
2040 return if enabled == 0 { 0 } else { 1 };
2041 }
2042 (*dev).dwtp_enabled = enabled == 1;
2043 0
2044}
2045
2046#[no_mangle]
2047pub unsafe extern "C" fn libinput_device_config_dwtp_get_enabled(
2048 dev: *const LibinputDevice,
2049) -> u32 {
2050 if dev.is_null() || !(*dev).dwtp_available {
2051 0
2052 } else {
2053 (*dev).dwtp_enabled as u32
2054 }
2055}
2056
2057#[no_mangle]
2058pub unsafe extern "C" fn libinput_device_config_dwtp_get_default_enabled(
2059 dev: *const LibinputDevice,
2060) -> u32 {
2061 (!dev.is_null() && (*dev).dwtp_available) as u32
2062}
2063
2064#[no_mangle]
2065pub unsafe extern "C" fn libinput_device_config_dwtp_set_timeout(
2066 dev: *mut LibinputDevice,
2067 millis: u32,
2068) -> u32 {
2069 if dev.is_null() {
2070 return 1;
2071 }
2072 if millis == 0 {
2073 return 2;
2074 }
2075 if !(*dev).dwtp_available {
2076 return 1;
2077 }
2078 if !(100..=5000).contains(&millis) {
2079 return 2;
2080 }
2081 (*dev).dwtp_timeout = millis;
2082 0
2083}
2084
2085#[no_mangle]
2086pub unsafe extern "C" fn libinput_device_config_dwtp_get_timeout(
2087 dev: *const LibinputDevice,
2088) -> u32 {
2089 if dev.is_null() || !(*dev).dwtp_available {
2090 0
2091 } else {
2092 (*dev).dwtp_timeout
2093 }
2094}
2095
2096#[no_mangle]
2097pub unsafe extern "C" fn libinput_device_config_dwtp_get_default_timeout(
2098 dev: *const LibinputDevice,
2099) -> u32 {
2100 if !dev.is_null() && (*dev).dwtp_available {
2101 300
2102 } else {
2103 0
2104 }
2105}
2106
2107#[no_mangle]
2112pub unsafe extern "C" fn libinput_device_config_calibration_has_matrix(
2113 dev: *const LibinputDevice,
2114) -> libc::c_int {
2115 if dev.is_null() {
2116 return 0;
2117 }
2118 (*dev).calibration_available as libc::c_int
2119}
2120
2121#[no_mangle]
2122pub unsafe extern "C" fn libinput_device_config_calibration_set_matrix(
2123 dev: *mut LibinputDevice,
2124 matrix: *const f32,
2125) -> u32 {
2126 if dev.is_null() || matrix.is_null() || !(*dev).calibration_available {
2127 return 1;
2128 }
2129 (*dev)
2130 .calibration
2131 .copy_from_slice(std::slice::from_raw_parts(matrix, 6));
2132 0
2133}
2134
2135#[no_mangle]
2136pub unsafe extern "C" fn libinput_device_config_calibration_get_matrix(
2137 dev: *const LibinputDevice,
2138 matrix: *mut f32,
2139) -> libc::c_int {
2140 if dev.is_null() || matrix.is_null() || !(*dev).calibration_available {
2141 return 0;
2142 }
2143 std::slice::from_raw_parts_mut(matrix, 6).copy_from_slice(&(*dev).calibration);
2144 ((*dev).calibration != [1.0_f32, 0.0, 0.0, 0.0, 1.0, 0.0]) as libc::c_int
2145}
2146
2147#[no_mangle]
2148pub unsafe extern "C" fn libinput_device_config_calibration_get_default_matrix(
2149 dev: *const LibinputDevice,
2150 matrix: *mut f32,
2151) -> libc::c_int {
2152 if dev.is_null() || matrix.is_null() || !(*dev).calibration_available {
2153 return 0;
2154 }
2155 std::slice::from_raw_parts_mut(matrix, 6).copy_from_slice(&(*dev).default_calibration);
2156 ((*dev).default_calibration != [1.0_f32, 0.0, 0.0, 0.0, 1.0, 0.0]) as libc::c_int
2157}
2158
2159#[no_mangle]
2164pub unsafe extern "C" fn libinput_device_get_seat(dev: *const LibinputDevice) -> *mut libc::c_void {
2165 if dev.is_null() {
2166 return std::ptr::null_mut();
2167 }
2168 (*dev).seat as *mut libc::c_void
2169}
2170
2171#[no_mangle]
2172pub unsafe extern "C" fn libinput_device_set_seat_logical_name(
2173 dev: *mut LibinputDevice,
2174 name: *const libc::c_char,
2175) -> libc::c_int {
2176 if dev.is_null() || name.is_null() || (*dev).seat.is_null() {
2177 return -1;
2178 }
2179 let name = CStr::from_ptr(name);
2180 if name.to_bytes().is_empty() || name.to_bytes().len() > 255 {
2181 return -1;
2182 }
2183 if (*(*dev).seat).logical_name.as_c_str() == name {
2184 return 0;
2185 }
2186 let Ok(logical_name) = std::ffi::CString::new(name.to_bytes()) else {
2187 return -1;
2188 };
2189 let ctx = (*dev).context;
2190 if ctx.is_null() {
2191 return -1;
2192 }
2193 let physical_name = (*(*dev).seat).physical_name.clone();
2194 let new_seat = (*ctx)
2195 .seats
2196 .iter()
2197 .copied()
2198 .find(|seat| {
2199 !seat.is_null()
2200 && (**seat).physical_name == physical_name
2201 && (**seat).logical_name == logical_name
2202 })
2203 .unwrap_or_else(|| {
2204 let seat = Box::into_raw(Box::new(LibinputSeat {
2205 physical_name,
2206 logical_name,
2207 refcount: std::sync::atomic::AtomicI32::new(1),
2208 user_data: std::ptr::null_mut(),
2209 context: ctx,
2210 button_count: std::sync::atomic::AtomicU32::new(0),
2211 }));
2212 (*ctx).seats.push(seat);
2213 seat
2214 });
2215
2216 let path = std::path::PathBuf::from((*dev).devnode.to_string_lossy().into_owned());
2217 let mut removed = std::collections::VecDeque::new();
2218 let mut added = Vec::new();
2219 let replaced = if let Ok(mut backend) = (*ctx).backend.lock() {
2220 if backend.remove_device(ctx, dev, &mut removed) {
2221 backend.try_open(ctx, &path, &mut added);
2222 true
2223 } else {
2224 false
2225 }
2226 } else {
2227 false
2228 };
2229 let Some(replacement) = added.first().map(|event| event.device) else {
2230 return -1;
2231 };
2232 if !replaced || replacement.is_null() {
2233 return -1;
2234 }
2235 (*ctx).devices.retain(|candidate| *candidate != dev);
2236 libinput_device_unref(dev);
2237 (*replacement).seat = new_seat;
2238 (*ctx).event_queue.extend(removed);
2239 (*ctx).event_queue.extend(added);
2240 (*replacement).abi.seat = new_seat;
2241 (*ctx).signal_fd();
2242 0
2243}
2244
2245#[no_mangle]
2246pub unsafe extern "C" fn libinput_seat_get_physical_name(
2247 seat: *const libc::c_void,
2248) -> *const libc::c_char {
2249 if seat.is_null() {
2250 return std::ptr::null();
2251 }
2252 (*(seat as *const LibinputSeat)).physical_name.as_ptr()
2253}
2254
2255#[no_mangle]
2256pub unsafe extern "C" fn libinput_seat_get_logical_name(
2257 seat: *const libc::c_void,
2258) -> *const libc::c_char {
2259 if seat.is_null() {
2260 return std::ptr::null();
2261 }
2262 (*(seat as *const LibinputSeat)).logical_name.as_ptr()
2263}
2264
2265#[no_mangle]
2266pub unsafe extern "C" fn libinput_seat_get_context(
2267 seat: *const libc::c_void,
2268) -> *mut LibinputContext {
2269 if seat.is_null() {
2270 return std::ptr::null_mut();
2271 }
2272 (*(seat as *const LibinputSeat)).context
2273}
2274
2275#[no_mangle]
2276pub unsafe extern "C" fn libinput_seat_ref(seat: *mut libc::c_void) -> *mut libc::c_void {
2277 if !seat.is_null() {
2278 (*(seat as *mut LibinputSeat))
2279 .refcount
2280 .fetch_add(1, std::sync::atomic::Ordering::SeqCst);
2281 }
2282 seat
2283}
2284
2285#[no_mangle]
2286pub unsafe extern "C" fn libinput_seat_unref(seat: *mut libc::c_void) -> *mut libc::c_void {
2287 if !seat.is_null() {
2288 let seat = seat as *mut LibinputSeat;
2289 if (*seat)
2290 .refcount
2291 .fetch_sub(1, std::sync::atomic::Ordering::AcqRel)
2292 == 1
2293 {
2294 drop(Box::from_raw(seat));
2295 }
2296 }
2297 std::ptr::null_mut()
2298}
2299
2300#[no_mangle]
2301pub unsafe extern "C" fn libinput_seat_set_user_data(
2302 seat: *mut libc::c_void,
2303 data: *mut libc::c_void,
2304) {
2305 if !seat.is_null() {
2306 (*(seat as *mut LibinputSeat)).user_data = data;
2307 }
2308}
2309
2310#[no_mangle]
2311pub unsafe extern "C" fn libinput_seat_get_user_data(
2312 seat: *const libc::c_void,
2313) -> *mut libc::c_void {
2314 if seat.is_null() {
2315 return std::ptr::null_mut();
2316 }
2317 (*(seat as *const LibinputSeat)).user_data
2318}
2319
2320#[no_mangle]
2325pub unsafe extern "C" fn libinput_config_status_to_str(status: u32) -> *const libc::c_char {
2326 match status {
2327 0 => c"success".as_ptr(),
2328 1 => c"unsupported".as_ptr(),
2329 2 => c"invalid".as_ptr(),
2330 _ => std::ptr::null(),
2331 }
2332}
2333
2334#[no_mangle]
2339pub unsafe extern "C" fn libinput_log_set_priority(ctx: *mut LibinputContext, priority: u32) {
2340 if !ctx.is_null() {
2341 (*ctx).log_priority = priority;
2342 }
2343}
2344
2345#[no_mangle]
2346pub unsafe extern "C" fn libinput_log_get_priority(ctx: *const LibinputContext) -> u32 {
2347 if ctx.is_null() {
2348 return 30;
2349 }
2350 (*ctx).log_priority
2351}
2352
2353#[no_mangle]
2354pub unsafe extern "C" fn libinput_log_set_handler(
2355 ctx: *mut LibinputContext,
2356 handler: Option<
2357 unsafe extern "C" fn(
2358 ctx: *mut LibinputContext,
2359 priority: u32,
2360 format: *const libc::c_char,
2361 args: *mut libc::c_void,
2362 ),
2363 >,
2364) {
2365 if ctx.is_null() {
2366 return;
2367 }
2368 (*ctx).log_handler = handler;
2369}
2370
2371#[no_mangle]
2376pub unsafe extern "C" fn libinput_set_user_data(
2377 ctx: *mut LibinputContext,
2378 data: *mut libc::c_void,
2379) {
2380 if ctx.is_null() {
2381 return;
2382 }
2383 (*ctx).user_data = data;
2384}
2385
2386#[no_mangle]
2387pub unsafe extern "C" fn libinput_get_user_data(ctx: *const LibinputContext) -> *mut libc::c_void {
2388 if ctx.is_null() {
2389 return std::ptr::null_mut();
2390 }
2391 (*ctx).user_data
2392}
2393
2394#[no_mangle]
2395pub unsafe extern "C" fn libinput_device_set_user_data(
2396 dev: *mut LibinputDevice,
2397 data: *mut libc::c_void,
2398) {
2399 if dev.is_null() {
2400 return;
2401 }
2402 (*dev).user_data = data;
2403 (*dev).abi.user_data = data;
2404}
2405
2406#[no_mangle]
2407pub unsafe extern "C" fn libinput_device_get_user_data(
2408 dev: *const LibinputDevice,
2409) -> *mut libc::c_void {
2410 if dev.is_null() {
2411 return std::ptr::null_mut();
2412 }
2413 (*dev).user_data
2414}
2415
2416#[no_mangle]
2421pub unsafe extern "C" fn libinput_device_config_area_has_rectangle(
2422 dev: *const LibinputDevice,
2423) -> libc::c_int {
2424 if dev.is_null() {
2425 return 0;
2426 }
2427 (*dev).area_available as libc::c_int
2428}
2429
2430#[no_mangle]
2431pub unsafe extern "C" fn libinput_device_config_area_set_rectangle(
2432 dev: *mut LibinputDevice,
2433 rectangle: *const LibinputConfigAreaRectangle,
2434) -> u32 {
2435 if dev.is_null() || !(*dev).area_available {
2436 return 1;
2437 }
2438 if rectangle.is_null() {
2439 return 2;
2440 }
2441 let rectangle = &*rectangle;
2442 if rectangle.x1 >= rectangle.x2
2443 || rectangle.y1 >= rectangle.y2
2444 || rectangle.x1 < 0.0
2445 || rectangle.x2 > 1.0
2446 || rectangle.y1 < 0.0
2447 || rectangle.y2 > 1.0
2448 {
2449 return 2;
2450 }
2451 (*dev).wanted_area = [rectangle.x1, rectangle.y1, rectangle.x2, rectangle.y2];
2452 if !(*dev).tablet_in_proximity {
2453 (*dev).area = (*dev).wanted_area;
2454 }
2455 0
2456}
2457
2458#[no_mangle]
2459pub unsafe extern "C" fn libinput_device_config_area_get_rectangle(
2460 dev: *const LibinputDevice,
2461) -> LibinputConfigAreaRectangle {
2462 let area = if dev.is_null() || !(*dev).area_available {
2463 [0.0, 0.0, 1.0, 1.0]
2464 } else {
2465 (*dev).area
2466 };
2467 LibinputConfigAreaRectangle {
2468 x1: area[0],
2469 y1: area[1],
2470 x2: area[2],
2471 y2: area[3],
2472 }
2473}
2474
2475#[no_mangle]
2476pub unsafe extern "C" fn libinput_device_config_area_get_default_rectangle(
2477 _dev: *const LibinputDevice,
2478) -> LibinputConfigAreaRectangle {
2479 LibinputConfigAreaRectangle {
2480 x1: 0.0,
2481 y1: 0.0,
2482 x2: 1.0,
2483 y2: 1.0,
2484 }
2485}
2486
2487#[no_mangle]
2488pub unsafe extern "C" fn libinput_device_config_rotation_is_available(
2489 dev: *const LibinputDevice,
2490) -> libc::c_int {
2491 if dev.is_null() {
2492 return 0;
2493 }
2494 (*dev).has_touch as libc::c_int
2495}
2496
2497#[no_mangle]
2498pub unsafe extern "C" fn libinput_device_config_rotation_set_angle(
2499 dev: *mut LibinputDevice,
2500 _degrees_cw: u32,
2501) -> u32 {
2502 if dev.is_null() {
2503 return 1;
2504 }
2505 0
2506}
2507
2508#[no_mangle]
2509pub unsafe extern "C" fn libinput_device_config_rotation_get_angle(
2510 _dev: *const LibinputDevice,
2511) -> u32 {
2512 0
2513}
2514
2515#[no_mangle]
2516pub unsafe extern "C" fn libinput_device_config_rotation_get_default_angle(
2517 _dev: *const LibinputDevice,
2518) -> u32 {
2519 0
2520}
2521
2522#[no_mangle]
2523pub unsafe extern "C" fn libinput_device_config_scroll_get_default_button(
2524 dev: *const LibinputDevice,
2525) -> u32 {
2526 if dev.is_null() || !(*dev).supports_button_scroll {
2527 0
2528 } else {
2529 (*dev).scroll_default_button
2530 }
2531}
2532
2533#[no_mangle]
2534pub unsafe extern "C" fn libinput_device_config_send_events_get_modes(
2535 dev: *const LibinputDevice,
2536) -> u32 {
2537 if dev.is_null() {
2538 return 0;
2539 }
2540 (*dev).send_events_modes
2541}
2542
2543#[no_mangle]
2544pub unsafe extern "C" fn libinput_device_config_send_events_set_mode(
2545 dev: *mut LibinputDevice,
2546 mode: u32,
2547) -> u32 {
2548 if dev.is_null() {
2549 return 1;
2550 }
2551 let supported = (*dev).send_events_modes;
2552 if mode & !supported != 0 {
2553 return 1;
2554 }
2555 let previous = (*dev).send_events_mode;
2556 let next = if mode & 1 != 0 { 1 } else { mode };
2557 (*dev).send_events_mode = next;
2558 if previous != 1 && next == 1 {
2559 let ctx = (*dev).context;
2560 if !ctx.is_null() {
2561 let mut events = std::collections::VecDeque::new();
2562 if let Ok(mut backend) = (*ctx).backend.lock() {
2563 backend.release_active_inputs(ctx, dev, &mut events);
2564 }
2565 (*ctx).event_queue.extend(events);
2566 }
2567 }
2568 0
2569}
2570
2571#[no_mangle]
2572pub unsafe extern "C" fn libinput_device_config_send_events_get_mode(
2573 dev: *const LibinputDevice,
2574) -> u32 {
2575 if dev.is_null() {
2576 return 0;
2577 }
2578 (*dev).send_events_mode
2579}
2580
2581#[no_mangle]
2582pub unsafe extern "C" fn libinput_device_config_send_events_get_default_mode(
2583 _dev: *const LibinputDevice,
2584) -> u32 {
2585 0
2586}
2587
2588#[no_mangle]
2589pub unsafe extern "C" fn libinput_device_config_tap_get_default_drag_lock_enabled(
2590 _dev: *const LibinputDevice,
2591) -> u32 {
2592 0
2593}
2594
2595#[no_mangle]
2596pub unsafe extern "C" fn libinput_device_get_device_group(
2597 dev: *const LibinputDevice,
2598) -> *mut libc::c_void {
2599 if dev.is_null() {
2600 return std::ptr::null_mut();
2601 }
2602 (*dev).group.cast()
2603}
2604
2605#[no_mangle]
2606pub unsafe extern "C" fn libinput_device_group_ref(group: *mut libc::c_void) -> *mut libc::c_void {
2607 if group.is_null() {
2608 return std::ptr::null_mut();
2609 }
2610 let group = group.cast::<LibinputDeviceGroup>();
2611 (*group)
2612 .refcount
2613 .fetch_add(1, std::sync::atomic::Ordering::Relaxed);
2614 group.cast()
2615}
2616
2617#[no_mangle]
2618pub unsafe extern "C" fn libinput_device_group_unref(
2619 group: *mut libc::c_void,
2620) -> *mut libc::c_void {
2621 if group.is_null() {
2622 return std::ptr::null_mut();
2623 }
2624 let group = group.cast::<LibinputDeviceGroup>();
2625 if (*group)
2626 .refcount
2627 .fetch_sub(1, std::sync::atomic::Ordering::AcqRel)
2628 == 1
2629 {
2630 drop(Box::from_raw(group));
2631 std::ptr::null_mut()
2632 } else {
2633 group.cast()
2634 }
2635}
2636
2637#[no_mangle]
2638pub unsafe extern "C" fn libinput_device_group_set_user_data(
2639 group: *mut libc::c_void,
2640 data: *mut libc::c_void,
2641) {
2642 if !group.is_null() {
2643 (*group.cast::<LibinputDeviceGroup>()).user_data = data;
2644 }
2645}
2646
2647#[no_mangle]
2648pub unsafe extern "C" fn libinput_device_group_get_user_data(
2649 group: *const libc::c_void,
2650) -> *mut libc::c_void {
2651 if group.is_null() {
2652 return std::ptr::null_mut();
2653 }
2654 (*group.cast::<LibinputDeviceGroup>()).user_data
2655}
2656
2657#[no_mangle]
2658pub unsafe extern "C" fn libinput_device_get_id_bustype(dev: *const LibinputDevice) -> u32 {
2659 if dev.is_null() {
2660 return 0;
2661 }
2662 (*dev).bus_type
2663}
2664
2665#[no_mangle]
2666pub unsafe extern "C" fn libinput_device_get_size(
2667 dev: *const LibinputDevice,
2668 width: *mut f64,
2669 height: *mut f64,
2670) -> libc::c_int {
2671 if dev.is_null() || width.is_null() || height.is_null() {
2672 return 0;
2673 }
2674 match ((*dev).width_mm, (*dev).height_mm) {
2675 (Some(w), Some(h)) => {
2676 *width = w;
2677 *height = h;
2678 0
2679 }
2680 _ => -1,
2681 }
2682}
2683
2684#[no_mangle]
2685pub unsafe extern "C" fn libinput_device_get_udev_device(
2686 dev: *const LibinputDevice,
2687) -> *mut libc::c_void {
2688 if dev.is_null() || (*dev).udev_device.is_null() {
2689 return std::ptr::null_mut();
2690 }
2691 udev::udev_device_ref((*dev).udev_device)
2692}
2693
2694#[no_mangle]
2695pub unsafe extern "C" fn libinput_device_keyboard_has_key(
2696 dev: *const LibinputDevice,
2697 key: u32,
2698) -> libc::c_int {
2699 if dev.is_null() || !(*dev).has_keyboard || key > u16::MAX as u32 {
2700 return 0;
2701 }
2702 (*dev).event_codes.contains(&(key as u16)) as libc::c_int
2703}
2704
2705#[no_mangle]
2706pub unsafe extern "C" fn libinput_device_led_update(dev: *mut LibinputDevice, _leds: u32) -> u32 {
2707 if dev.is_null() {
2708 return 1;
2709 }
2710 0
2711}
2712
2713#[no_mangle]
2714pub unsafe extern "C" fn libinput_device_pointer_has_button(
2715 dev: *const LibinputDevice,
2716 button: u32,
2717) -> libc::c_int {
2718 if dev.is_null() || button > u16::MAX as u32 {
2719 return 0;
2720 }
2721 if !(*dev).has_pointer {
2722 return -1;
2723 }
2724 (*dev).event_codes.contains(&(button as u16)) as libc::c_int
2725}
2726
2727#[no_mangle]
2728pub unsafe extern "C" fn libinput_device_switch_has_switch(
2729 dev: *const LibinputDevice,
2730 _sw: u32,
2731) -> libc::c_int {
2732 if dev.is_null() {
2733 return 0;
2734 }
2735 (*dev).has_switch as libc::c_int
2736}
2737
2738#[no_mangle]
2739pub unsafe extern "C" fn libinput_device_tablet_pad_get_mode_group(
2740 dev: *const LibinputDevice,
2741 index: u32,
2742) -> *mut libc::c_void {
2743 if dev.is_null() || !(*dev).has_tablet_pad || index != 0 {
2744 return std::ptr::null_mut();
2745 }
2746 (*dev).tablet_pad_mode_group.cast()
2747}
2748
2749#[no_mangle]
2750pub unsafe extern "C" fn libinput_device_tablet_pad_get_num_buttons(
2751 dev: *const LibinputDevice,
2752) -> u32 {
2753 if dev.is_null() || !(*dev).has_tablet_pad {
2754 return u32::MAX;
2755 }
2756 (*dev).tablet_pad_button_codes.len() as u32
2757}
2758
2759#[no_mangle]
2760pub unsafe extern "C" fn libinput_device_tablet_pad_get_num_dials(
2761 dev: *const LibinputDevice,
2762) -> u32 {
2763 if dev.is_null() || !(*dev).has_tablet_pad {
2764 return u32::MAX;
2765 }
2766 (*dev).tablet_pad_num_dials
2767}
2768
2769#[no_mangle]
2770pub unsafe extern "C" fn libinput_device_tablet_pad_get_num_mode_groups(
2771 dev: *const LibinputDevice,
2772) -> u32 {
2773 u32::from(!dev.is_null() && (*dev).has_tablet_pad)
2774}
2775
2776#[no_mangle]
2777pub unsafe extern "C" fn libinput_device_tablet_pad_get_num_rings(
2778 dev: *const LibinputDevice,
2779) -> u32 {
2780 if dev.is_null() || !(*dev).has_tablet_pad {
2781 return u32::MAX;
2782 }
2783 (*dev).tablet_pad_num_rings
2784}
2785
2786#[no_mangle]
2787pub unsafe extern "C" fn libinput_device_tablet_pad_get_num_strips(
2788 dev: *const LibinputDevice,
2789) -> u32 {
2790 if dev.is_null() || !(*dev).has_tablet_pad {
2791 return u32::MAX;
2792 }
2793 (*dev).tablet_pad_num_strips
2794}
2795
2796#[no_mangle]
2797pub unsafe extern "C" fn libinput_device_tablet_pad_has_key(
2798 dev: *const LibinputDevice,
2799 code: u32,
2800) -> libc::c_int {
2801 if dev.is_null() || !(*dev).has_tablet_pad {
2802 return -1;
2803 }
2804 (code <= u16::MAX as u32 && (*dev).event_codes.contains(&(code as u16))) as libc::c_int
2805}
2806
2807#[no_mangle]
2808pub unsafe extern "C" fn libinput_event_get_tablet_pad_event(
2809 event: *mut LibinputEvent,
2810) -> *mut LibinputEvent {
2811 if event.is_null() {
2812 return std::ptr::null_mut();
2813 }
2814 match (*event).event_type {
2815 LibinputEventType::LIBINPUT_EVENT_TABLET_PAD_BUTTON
2816 | LibinputEventType::LIBINPUT_EVENT_TABLET_PAD_RING
2817 | LibinputEventType::LIBINPUT_EVENT_TABLET_PAD_STRIP
2818 | LibinputEventType::LIBINPUT_EVENT_TABLET_PAD_KEY
2819 | LibinputEventType::LIBINPUT_EVENT_TABLET_PAD_DIAL => event,
2820 _ => std::ptr::null_mut(),
2821 }
2822}
2823
2824#[no_mangle]
2825pub unsafe extern "C" fn libinput_event_tablet_pad_get_base_event(
2826 event: *mut LibinputEvent,
2827) -> *mut LibinputEvent {
2828 event
2829}
2830
2831#[no_mangle]
2832pub unsafe extern "C" fn libinput_event_get_tablet_tool_event(
2833 event: *mut LibinputEvent,
2834) -> *mut LibinputEvent {
2835 if event.is_null() {
2836 return std::ptr::null_mut();
2837 }
2838 match (*event).event_type {
2839 LibinputEventType::LIBINPUT_EVENT_TABLET_TOOL_AXIS
2840 | LibinputEventType::LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY
2841 | LibinputEventType::LIBINPUT_EVENT_TABLET_TOOL_TIP
2842 | LibinputEventType::LIBINPUT_EVENT_TABLET_TOOL_BUTTON => event,
2843 _ => std::ptr::null_mut(),
2844 }
2845}
2846
2847#[no_mangle]
2848pub unsafe extern "C" fn libinput_event_tablet_tool_get_base_event(
2849 event: *mut LibinputEvent,
2850) -> *mut LibinputEvent {
2851 event
2852}
2853
2854#[no_mangle]
2855pub unsafe extern "C" fn libinput_event_pointer_get_absolute_x_transformed(
2856 event: *const LibinputEvent,
2857 width: u32,
2858) -> f64 {
2859 if event.is_null() {
2860 return 0.0;
2861 }
2862 if let EventPayload::PointerMotionAbsolute(e) = &(*event).payload {
2863 let range = e.x_max - e.x_min;
2864 if range > 0.0 {
2865 (e.abs_x - e.x_min) * f64::from(width) / range
2866 } else {
2867 0.0
2868 }
2869 } else {
2870 0.0
2871 }
2872}
2873
2874#[no_mangle]
2875pub unsafe extern "C" fn libinput_event_pointer_get_absolute_y_transformed(
2876 event: *const LibinputEvent,
2877 height: u32,
2878) -> f64 {
2879 if event.is_null() {
2880 return 0.0;
2881 }
2882 if let EventPayload::PointerMotionAbsolute(e) = &(*event).payload {
2883 let range = e.y_max - e.y_min;
2884 if range > 0.0 {
2885 (e.abs_y - e.y_min) * f64::from(height) / range
2886 } else {
2887 0.0
2888 }
2889 } else {
2890 0.0
2891 }
2892}
2893
2894#[no_mangle]
2895pub unsafe extern "C" fn libinput_event_pointer_get_scroll_value(
2896 event: *const LibinputEvent,
2897 axis: u32,
2898) -> f64 {
2899 libinput_event_pointer_get_axis_value(event, axis)
2900}
2901
2902#[no_mangle]
2903pub unsafe extern "C" fn libinput_event_pointer_get_scroll_value_v120(
2904 event: *const LibinputEvent,
2905 axis: u32,
2906) -> f64 {
2907 if event.is_null() {
2908 return 0.0;
2909 }
2910 if let EventPayload::PointerAxis(e) = &(*event).payload {
2911 return e.value_v120(axis);
2912 }
2913 0.0
2914}
2915
2916#[no_mangle]
2917pub unsafe extern "C" fn libinput_event_switch_get_time_usec(event: *const LibinputEvent) -> u64 {
2918 if event.is_null() {
2919 return 0;
2920 }
2921 if let EventPayload::SwitchToggle(e) = &(*event).payload {
2922 e.time_usec
2923 } else {
2924 0
2925 }
2926}
2927
2928#[no_mangle]
2929pub unsafe extern "C" fn libinput_event_switch_get_time(event: *const LibinputEvent) -> u32 {
2930 (libinput_event_switch_get_time_usec(event) / 1000) as u32
2931}
2932
2933#[no_mangle]
2934pub unsafe extern "C" fn libinput_event_tablet_pad_get_button_number(
2935 event: *const LibinputEvent,
2936) -> u32 {
2937 if event.is_null() {
2938 return 0;
2939 }
2940 match &(*event).payload {
2941 EventPayload::TabletPad(pad) => pad.button,
2942 _ => 0,
2943 }
2944}
2945
2946#[no_mangle]
2947pub unsafe extern "C" fn libinput_event_tablet_pad_get_button_state(
2948 event: *const LibinputEvent,
2949) -> u32 {
2950 if event.is_null() {
2951 return 0;
2952 }
2953 match &(*event).payload {
2954 EventPayload::TabletPad(pad) => pad.button_state,
2955 _ => 0,
2956 }
2957}
2958
2959#[no_mangle]
2960pub unsafe extern "C" fn libinput_event_tablet_pad_get_key(event: *const LibinputEvent) -> u32 {
2961 if event.is_null() {
2962 return 0;
2963 }
2964 match &(*event).payload {
2965 EventPayload::TabletPad(pad) => pad.key,
2966 _ => 0,
2967 }
2968}
2969
2970#[no_mangle]
2971pub unsafe extern "C" fn libinput_event_tablet_pad_get_key_state(
2972 event: *const LibinputEvent,
2973) -> u32 {
2974 if event.is_null() {
2975 return 0;
2976 }
2977 match &(*event).payload {
2978 EventPayload::TabletPad(pad) => pad.key_state,
2979 _ => 0,
2980 }
2981}
2982
2983#[no_mangle]
2984pub unsafe extern "C" fn libinput_event_tablet_pad_get_dial_delta_v120(
2985 event: *const LibinputEvent,
2986) -> f64 {
2987 if event.is_null() {
2988 return 0.0;
2989 }
2990 match &(*event).payload {
2991 EventPayload::TabletPad(pad) => pad.dial_delta_v120,
2992 _ => 0.0,
2993 }
2994}
2995
2996#[no_mangle]
2997pub unsafe extern "C" fn libinput_event_tablet_pad_get_dial_number(
2998 event: *const LibinputEvent,
2999) -> u32 {
3000 if event.is_null() {
3001 return 0;
3002 }
3003 match &(*event).payload {
3004 EventPayload::TabletPad(pad) => pad.dial_number,
3005 _ => 0,
3006 }
3007}
3008
3009#[no_mangle]
3010pub unsafe extern "C" fn libinput_event_tablet_pad_get_mode(event: *const LibinputEvent) -> u32 {
3011 if event.is_null() {
3012 return 0;
3013 }
3014 match &(*event).payload {
3015 EventPayload::TabletPad(pad) => pad.mode,
3016 _ => 0,
3017 }
3018}
3019
3020#[no_mangle]
3021pub unsafe extern "C" fn libinput_event_tablet_pad_get_mode_group(
3022 event: *const LibinputEvent,
3023) -> *mut libc::c_void {
3024 if event.is_null() {
3025 return std::ptr::null_mut();
3026 }
3027 match &(*event).payload {
3028 EventPayload::TabletPad(pad) => pad.mode_group.cast(),
3029 _ => std::ptr::null_mut(),
3030 }
3031}
3032
3033#[no_mangle]
3034pub unsafe extern "C" fn libinput_event_tablet_pad_get_ring_number(
3035 event: *const LibinputEvent,
3036) -> u32 {
3037 if event.is_null() {
3038 return 0;
3039 }
3040 match &(*event).payload {
3041 EventPayload::TabletPad(pad) => pad.ring_number,
3042 _ => 0,
3043 }
3044}
3045
3046#[no_mangle]
3047pub unsafe extern "C" fn libinput_event_tablet_pad_get_ring_position(
3048 event: *const LibinputEvent,
3049) -> f64 {
3050 if event.is_null() {
3051 return 0.0;
3052 }
3053 match &(*event).payload {
3054 EventPayload::TabletPad(pad) => pad.ring_position,
3055 _ => 0.0,
3056 }
3057}
3058
3059#[no_mangle]
3060pub unsafe extern "C" fn libinput_event_tablet_pad_get_ring_source(
3061 event: *const LibinputEvent,
3062) -> u32 {
3063 if event.is_null() {
3064 return 0;
3065 }
3066 match &(*event).payload {
3067 EventPayload::TabletPad(pad) => pad.ring_source,
3068 _ => 0,
3069 }
3070}
3071
3072#[no_mangle]
3073pub unsafe extern "C" fn libinput_event_tablet_pad_get_strip_number(
3074 event: *const LibinputEvent,
3075) -> u32 {
3076 if event.is_null() {
3077 return 0;
3078 }
3079 match &(*event).payload {
3080 EventPayload::TabletPad(pad) => pad.strip_number,
3081 _ => 0,
3082 }
3083}
3084
3085#[no_mangle]
3086pub unsafe extern "C" fn libinput_event_tablet_pad_get_strip_position(
3087 event: *const LibinputEvent,
3088) -> f64 {
3089 if event.is_null() {
3090 return 0.0;
3091 }
3092 match &(*event).payload {
3093 EventPayload::TabletPad(pad) => pad.strip_position,
3094 _ => 0.0,
3095 }
3096}
3097
3098#[no_mangle]
3099pub unsafe extern "C" fn libinput_event_tablet_pad_get_strip_source(
3100 event: *const LibinputEvent,
3101) -> u32 {
3102 if event.is_null() {
3103 return 0;
3104 }
3105 match &(*event).payload {
3106 EventPayload::TabletPad(pad) => pad.strip_source,
3107 _ => 0,
3108 }
3109}
3110
3111#[no_mangle]
3112pub unsafe extern "C" fn libinput_event_tablet_pad_get_time_usec(
3113 event: *const LibinputEvent,
3114) -> u64 {
3115 if event.is_null() {
3116 return 0;
3117 }
3118 match &(*event).payload {
3119 EventPayload::TabletPad(pad) => pad.time_usec,
3120 _ => 0,
3121 }
3122}
3123
3124#[no_mangle]
3125pub unsafe extern "C" fn libinput_event_tablet_pad_get_time(event: *const LibinputEvent) -> u32 {
3126 (libinput_event_tablet_pad_get_time_usec(event) / 1000) as u32
3127}
3128
3129#[no_mangle]
3130pub unsafe extern "C" fn libinput_event_tablet_tool_get_button(event: *const LibinputEvent) -> u32 {
3131 if event.is_null() {
3132 return 0;
3133 }
3134 match &(*event).payload {
3135 EventPayload::TabletTool(tablet) => tablet.button,
3136 _ => 0,
3137 }
3138}
3139
3140#[no_mangle]
3141pub unsafe extern "C" fn libinput_event_tablet_tool_get_button_state(
3142 event: *const LibinputEvent,
3143) -> u32 {
3144 if event.is_null() {
3145 return 0;
3146 }
3147 match &(*event).payload {
3148 EventPayload::TabletTool(tablet) => tablet.button_state,
3149 _ => 0,
3150 }
3151}
3152
3153#[no_mangle]
3154pub unsafe extern "C" fn libinput_event_tablet_tool_get_seat_button_count(
3155 event: *const LibinputEvent,
3156) -> u32 {
3157 if event.is_null() {
3158 return 0;
3159 }
3160 match &(*event).payload {
3161 EventPayload::TabletTool(tablet) => tablet.seat_button_count,
3162 _ => 0,
3163 }
3164}
3165
3166#[no_mangle]
3167pub unsafe extern "C" fn libinput_event_tablet_tool_get_distance(
3168 event: *const LibinputEvent,
3169) -> f64 {
3170 if event.is_null() {
3171 return 0.0;
3172 }
3173 match &(*event).payload {
3174 EventPayload::TabletTool(tablet) => tablet.distance,
3175 _ => 0.0,
3176 }
3177}
3178
3179#[no_mangle]
3180pub unsafe extern "C" fn libinput_event_tablet_tool_get_dx(event: *const LibinputEvent) -> f64 {
3181 if event.is_null() || (*event).event_type != LibinputEventType::LIBINPUT_EVENT_TABLET_TOOL_AXIS
3182 {
3183 return 0.0;
3184 }
3185 match &(*event).payload {
3186 EventPayload::TabletTool(tablet) => tablet.dx,
3187 _ => 0.0,
3188 }
3189}
3190
3191#[no_mangle]
3192pub unsafe extern "C" fn libinput_event_tablet_tool_get_dy(event: *const LibinputEvent) -> f64 {
3193 if event.is_null() || (*event).event_type != LibinputEventType::LIBINPUT_EVENT_TABLET_TOOL_AXIS
3194 {
3195 return 0.0;
3196 }
3197 match &(*event).payload {
3198 EventPayload::TabletTool(tablet) => tablet.dy,
3199 _ => 0.0,
3200 }
3201}
3202
3203#[no_mangle]
3204pub unsafe extern "C" fn libinput_event_tablet_tool_get_pressure(
3205 event: *const LibinputEvent,
3206) -> f64 {
3207 if event.is_null() {
3208 return 0.0;
3209 }
3210 if let EventPayload::TabletTool(tablet) = &(*event).payload {
3211 let range = tablet.pressure_max - tablet.pressure_min;
3212 if range > 0.0 {
3213 ((tablet.pressure - tablet.pressure_min) / range).clamp(0.0, 1.0)
3214 } else {
3215 0.0
3216 }
3217 } else {
3218 0.0
3219 }
3220}
3221
3222#[no_mangle]
3223pub unsafe extern "C" fn libinput_event_tablet_tool_get_x(event: *const LibinputEvent) -> f64 {
3224 if event.is_null() {
3225 return 0.0;
3226 }
3227 if let EventPayload::TabletTool(tablet) = &(*event).payload {
3228 if tablet.x_resolution > 0.0 {
3229 (tablet.x - tablet.x_min) / tablet.x_resolution
3230 } else {
3231 tablet.x - tablet.x_min
3232 }
3233 } else {
3234 0.0
3235 }
3236}
3237
3238#[no_mangle]
3239pub unsafe extern "C" fn libinput_event_tablet_tool_get_y(event: *const LibinputEvent) -> f64 {
3240 if event.is_null() {
3241 return 0.0;
3242 }
3243 if let EventPayload::TabletTool(tablet) = &(*event).payload {
3244 if tablet.y_resolution > 0.0 {
3245 (tablet.y - tablet.y_min) / tablet.y_resolution
3246 } else {
3247 tablet.y - tablet.y_min
3248 }
3249 } else {
3250 0.0
3251 }
3252}
3253
3254#[no_mangle]
3255pub unsafe extern "C" fn libinput_event_tablet_tool_get_proximity_state(
3256 event: *const LibinputEvent,
3257) -> u32 {
3258 if event.is_null() {
3259 return 0;
3260 }
3261 if let EventPayload::TabletTool(tablet) = &(*event).payload {
3262 tablet.proximity_state
3263 } else {
3264 0
3265 }
3266}
3267
3268#[no_mangle]
3269pub unsafe extern "C" fn libinput_event_tablet_tool_get_rotation(
3270 event: *const LibinputEvent,
3271) -> f64 {
3272 if event.is_null() {
3273 return 0.0;
3274 }
3275 match &(*event).payload {
3276 EventPayload::TabletTool(tablet) => tablet.rotation,
3277 _ => 0.0,
3278 }
3279}
3280
3281#[no_mangle]
3282pub unsafe extern "C" fn libinput_event_tablet_tool_get_slider_position(
3283 event: *const LibinputEvent,
3284) -> f64 {
3285 if event.is_null() {
3286 return 0.0;
3287 }
3288 match &(*event).payload {
3289 EventPayload::TabletTool(tablet) => tablet.slider,
3290 _ => 0.0,
3291 }
3292}
3293
3294#[no_mangle]
3295pub unsafe extern "C" fn libinput_event_tablet_tool_get_wheel_delta(
3296 event: *const LibinputEvent,
3297) -> f64 {
3298 if event.is_null() {
3299 return 0.0;
3300 }
3301 match &(*event).payload {
3302 EventPayload::TabletTool(tablet) => tablet.wheel_delta,
3303 _ => 0.0,
3304 }
3305}
3306
3307#[no_mangle]
3308pub unsafe extern "C" fn libinput_event_tablet_tool_get_wheel_delta_discrete(
3309 event: *const LibinputEvent,
3310) -> i32 {
3311 if event.is_null() {
3312 return 0;
3313 }
3314 match &(*event).payload {
3315 EventPayload::TabletTool(tablet) => tablet.wheel_discrete,
3316 _ => 0,
3317 }
3318}
3319
3320#[no_mangle]
3321pub unsafe extern "C" fn libinput_event_tablet_tool_get_size_major(
3322 event: *const LibinputEvent,
3323) -> f64 {
3324 if event.is_null() {
3325 return 0.0;
3326 }
3327 match &(*event).payload {
3328 EventPayload::TabletTool(tablet) => tablet.size_major,
3329 _ => 0.0,
3330 }
3331}
3332
3333#[no_mangle]
3334pub unsafe extern "C" fn libinput_event_tablet_tool_get_size_minor(
3335 event: *const LibinputEvent,
3336) -> f64 {
3337 if event.is_null() {
3338 return 0.0;
3339 }
3340 match &(*event).payload {
3341 EventPayload::TabletTool(tablet) => tablet.size_minor,
3342 _ => 0.0,
3343 }
3344}
3345
3346#[no_mangle]
3347pub unsafe extern "C" fn libinput_event_tablet_tool_get_tilt_x(event: *const LibinputEvent) -> f64 {
3348 if event.is_null() {
3349 return 0.0;
3350 }
3351 match &(*event).payload {
3352 EventPayload::TabletTool(tablet) => tablet.tilt_x,
3353 _ => 0.0,
3354 }
3355}
3356
3357#[no_mangle]
3358pub unsafe extern "C" fn libinput_event_tablet_tool_get_tilt_y(event: *const LibinputEvent) -> f64 {
3359 if event.is_null() {
3360 return 0.0;
3361 }
3362 match &(*event).payload {
3363 EventPayload::TabletTool(tablet) => tablet.tilt_y,
3364 _ => 0.0,
3365 }
3366}
3367
3368#[no_mangle]
3369pub unsafe extern "C" fn libinput_event_tablet_tool_get_time_usec(
3370 event: *const LibinputEvent,
3371) -> u64 {
3372 if event.is_null() {
3373 return 0;
3374 }
3375 if let EventPayload::TabletTool(tablet) = &(*event).payload {
3376 tablet.time_usec
3377 } else {
3378 0
3379 }
3380}
3381
3382#[no_mangle]
3383pub unsafe extern "C" fn libinput_event_tablet_tool_get_time(event: *const LibinputEvent) -> u32 {
3384 (libinput_event_tablet_tool_get_time_usec(event) / 1000) as u32
3385}
3386
3387#[no_mangle]
3388pub unsafe extern "C" fn libinput_event_tablet_tool_get_tip_state(
3389 event: *const LibinputEvent,
3390) -> u32 {
3391 if event.is_null() {
3392 return 0;
3393 }
3394 match &(*event).payload {
3395 EventPayload::TabletTool(tablet) => tablet.tip_state,
3396 _ => 0,
3397 }
3398}
3399
3400#[no_mangle]
3401pub unsafe extern "C" fn libinput_event_tablet_tool_get_tool(
3402 event: *const LibinputEvent,
3403) -> *mut libc::c_void {
3404 if event.is_null() {
3405 return std::ptr::null_mut();
3406 }
3407 if let EventPayload::TabletTool(tablet) = &(*event).payload {
3408 tablet.tool.cast()
3409 } else {
3410 std::ptr::null_mut()
3411 }
3412}
3413
3414#[no_mangle]
3415pub unsafe extern "C" fn libinput_event_tablet_tool_get_x_transformed(
3416 event: *const LibinputEvent,
3417 width: u32,
3418) -> f64 {
3419 if event.is_null() {
3420 return 0.0;
3421 }
3422 if let EventPayload::TabletTool(tablet) = &(*event).payload {
3423 let range = tablet.x_max - tablet.x_min + 1.0;
3424 if range > 0.0 {
3425 (tablet.x - tablet.x_min) * f64::from(width) / range
3426 } else {
3427 0.0
3428 }
3429 } else {
3430 0.0
3431 }
3432}
3433
3434#[no_mangle]
3435pub unsafe extern "C" fn libinput_event_tablet_tool_get_y_transformed(
3436 event: *const LibinputEvent,
3437 height: u32,
3438) -> f64 {
3439 if event.is_null() {
3440 return 0.0;
3441 }
3442 if let EventPayload::TabletTool(tablet) = &(*event).payload {
3443 let range = tablet.y_max - tablet.y_min + 1.0;
3444 if range > 0.0 {
3445 (tablet.y - tablet.y_min) * f64::from(height) / range
3446 } else {
3447 0.0
3448 }
3449 } else {
3450 0.0
3451 }
3452}
3453
3454#[no_mangle]
3455pub unsafe extern "C" fn libinput_event_tablet_tool_x_has_changed(
3456 event: *const LibinputEvent,
3457) -> libc::c_int {
3458 if event.is_null() {
3459 return 0;
3460 }
3461 match &(*event).payload {
3462 EventPayload::TabletTool(tablet) => tablet.x_changed as libc::c_int,
3463 _ => 0,
3464 }
3465}
3466
3467#[no_mangle]
3468pub unsafe extern "C" fn libinput_event_tablet_tool_y_has_changed(
3469 event: *const LibinputEvent,
3470) -> libc::c_int {
3471 if event.is_null() {
3472 return 0;
3473 }
3474 match &(*event).payload {
3475 EventPayload::TabletTool(tablet) => tablet.y_changed as libc::c_int,
3476 _ => 0,
3477 }
3478}
3479
3480#[no_mangle]
3481pub unsafe extern "C" fn libinput_event_tablet_tool_pressure_has_changed(
3482 event: *const LibinputEvent,
3483) -> libc::c_int {
3484 if event.is_null() {
3485 return 0;
3486 }
3487 match &(*event).payload {
3488 EventPayload::TabletTool(tablet) => tablet.pressure_changed as libc::c_int,
3489 _ => 0,
3490 }
3491}
3492
3493#[no_mangle]
3494pub unsafe extern "C" fn libinput_event_tablet_tool_distance_has_changed(
3495 event: *const LibinputEvent,
3496) -> libc::c_int {
3497 if event.is_null() {
3498 return 0;
3499 }
3500 match &(*event).payload {
3501 EventPayload::TabletTool(tablet) => tablet.distance_changed as libc::c_int,
3502 _ => 0,
3503 }
3504}
3505
3506#[no_mangle]
3507pub unsafe extern "C" fn libinput_event_tablet_tool_tilt_x_has_changed(
3508 event: *const LibinputEvent,
3509) -> libc::c_int {
3510 if event.is_null() {
3511 return 0;
3512 }
3513 match &(*event).payload {
3514 EventPayload::TabletTool(tablet) => tablet.tilt_x_changed as libc::c_int,
3515 _ => 0,
3516 }
3517}
3518
3519#[no_mangle]
3520pub unsafe extern "C" fn libinput_event_tablet_tool_tilt_y_has_changed(
3521 event: *const LibinputEvent,
3522) -> libc::c_int {
3523 if event.is_null() {
3524 return 0;
3525 }
3526 match &(*event).payload {
3527 EventPayload::TabletTool(tablet) => tablet.tilt_y_changed as libc::c_int,
3528 _ => 0,
3529 }
3530}
3531
3532#[no_mangle]
3533pub unsafe extern "C" fn libinput_event_tablet_tool_rotation_has_changed(
3534 event: *const LibinputEvent,
3535) -> libc::c_int {
3536 if event.is_null() {
3537 return 0;
3538 }
3539 match &(*event).payload {
3540 EventPayload::TabletTool(tablet) => tablet.rotation_changed as libc::c_int,
3541 _ => 0,
3542 }
3543}
3544
3545#[no_mangle]
3546pub unsafe extern "C" fn libinput_event_tablet_tool_slider_has_changed(
3547 event: *const LibinputEvent,
3548) -> libc::c_int {
3549 if event.is_null() {
3550 return 0;
3551 }
3552 match &(*event).payload {
3553 EventPayload::TabletTool(tablet) => tablet.slider_changed as libc::c_int,
3554 _ => 0,
3555 }
3556}
3557
3558#[no_mangle]
3559pub unsafe extern "C" fn libinput_event_tablet_tool_wheel_has_changed(
3560 event: *const LibinputEvent,
3561) -> libc::c_int {
3562 if event.is_null() {
3563 return 0;
3564 }
3565 match &(*event).payload {
3566 EventPayload::TabletTool(tablet) => tablet.wheel_changed as libc::c_int,
3567 _ => 0,
3568 }
3569}
3570
3571#[no_mangle]
3572pub unsafe extern "C" fn libinput_event_tablet_tool_size_major_has_changed(
3573 event: *const LibinputEvent,
3574) -> libc::c_int {
3575 if event.is_null() {
3576 return 0;
3577 }
3578 match &(*event).payload {
3579 EventPayload::TabletTool(tablet) => tablet.size_major_changed as libc::c_int,
3580 _ => 0,
3581 }
3582}
3583
3584#[no_mangle]
3585pub unsafe extern "C" fn libinput_event_tablet_tool_size_minor_has_changed(
3586 event: *const LibinputEvent,
3587) -> libc::c_int {
3588 if event.is_null() {
3589 return 0;
3590 }
3591 match &(*event).payload {
3592 EventPayload::TabletTool(tablet) => tablet.size_minor_changed as libc::c_int,
3593 _ => 0,
3594 }
3595}
3596
3597#[no_mangle]
3598pub unsafe extern "C" fn libinput_plugin_system_append_default_paths(_ctx: *mut LibinputContext) {}
3599
3600#[no_mangle]
3601pub unsafe extern "C" fn libinput_plugin_system_append_path(
3602 _ctx: *mut LibinputContext,
3603 _path: *const libc::c_char,
3604) {
3605}
3606
3607#[no_mangle]
3608pub unsafe extern "C" fn libinput_plugin_system_load_plugins(
3609 _ctx: *mut LibinputContext,
3610 _flags: libc::c_uint,
3611) -> libc::c_int {
3612 -libc::ENOSYS
3613}
3614
3615#[no_mangle]
3616pub unsafe extern "C" fn libinput_tablet_pad_mode_group_button_is_toggle(
3617 _group: *const libc::c_void,
3618 _button: u32,
3619) -> libc::c_int {
3620 0
3621}
3622
3623#[no_mangle]
3624pub unsafe extern "C" fn libinput_tablet_pad_mode_group_get_index(
3625 group: *const libc::c_void,
3626) -> u32 {
3627 if group.is_null() {
3628 return 0;
3629 }
3630 (*group.cast::<LibinputTabletPadModeGroup>()).index
3631}
3632
3633#[no_mangle]
3634pub unsafe extern "C" fn libinput_tablet_pad_mode_group_get_mode(
3635 group: *const libc::c_void,
3636) -> u32 {
3637 if group.is_null() {
3638 return 0;
3639 }
3640 (*group.cast::<LibinputTabletPadModeGroup>()).current_mode
3641}
3642
3643#[no_mangle]
3644pub unsafe extern "C" fn libinput_tablet_pad_mode_group_get_num_modes(
3645 group: *const libc::c_void,
3646) -> u32 {
3647 if group.is_null() {
3648 return 0;
3649 }
3650 (*group.cast::<LibinputTabletPadModeGroup>()).num_modes
3651}
3652
3653#[no_mangle]
3654pub unsafe extern "C" fn libinput_tablet_pad_mode_group_has_button(
3655 group: *const libc::c_void,
3656 button: u32,
3657) -> libc::c_int {
3658 if group.is_null() {
3659 return 0;
3660 }
3661 (button < (*group.cast::<LibinputTabletPadModeGroup>()).num_buttons) as libc::c_int
3662}
3663
3664#[no_mangle]
3665pub unsafe extern "C" fn libinput_tablet_pad_mode_group_has_dial(
3666 group: *const libc::c_void,
3667 dial: u32,
3668) -> libc::c_int {
3669 if group.is_null() {
3670 return 0;
3671 }
3672 (dial < (*group.cast::<LibinputTabletPadModeGroup>()).num_dials) as libc::c_int
3673}
3674
3675#[no_mangle]
3676pub unsafe extern "C" fn libinput_tablet_pad_mode_group_has_ring(
3677 group: *const libc::c_void,
3678 ring: u32,
3679) -> libc::c_int {
3680 if group.is_null() {
3681 return 0;
3682 }
3683 (ring < (*group.cast::<LibinputTabletPadModeGroup>()).num_rings) as libc::c_int
3684}
3685
3686#[no_mangle]
3687pub unsafe extern "C" fn libinput_tablet_pad_mode_group_has_strip(
3688 group: *const libc::c_void,
3689 strip: u32,
3690) -> libc::c_int {
3691 if group.is_null() {
3692 return 0;
3693 }
3694 (strip < (*group.cast::<LibinputTabletPadModeGroup>()).num_strips) as libc::c_int
3695}
3696
3697#[no_mangle]
3698pub unsafe extern "C" fn libinput_tablet_pad_mode_group_ref(
3699 group: *mut libc::c_void,
3700) -> *mut libc::c_void {
3701 if !group.is_null() {
3702 (*group.cast::<LibinputTabletPadModeGroup>())
3703 .refcount
3704 .fetch_add(1, std::sync::atomic::Ordering::Relaxed);
3705 }
3706 group
3707}
3708
3709#[no_mangle]
3710pub unsafe extern "C" fn libinput_tablet_pad_mode_group_unref(
3711 group: *mut libc::c_void,
3712) -> *mut libc::c_void {
3713 if group.is_null() {
3714 return std::ptr::null_mut();
3715 }
3716 let group_ref = &*group.cast::<LibinputTabletPadModeGroup>();
3717 let current = group_ref
3718 .refcount
3719 .load(std::sync::atomic::Ordering::Relaxed);
3720 if current > 1 {
3721 group_ref
3722 .refcount
3723 .fetch_sub(1, std::sync::atomic::Ordering::AcqRel);
3724 }
3725 group
3726}
3727
3728#[no_mangle]
3729pub unsafe extern "C" fn libinput_tablet_pad_mode_group_set_user_data(
3730 group: *mut libc::c_void,
3731 data: *mut libc::c_void,
3732) {
3733 if !group.is_null() {
3734 (*group.cast::<LibinputTabletPadModeGroup>()).user_data = data;
3735 }
3736}
3737
3738#[no_mangle]
3739pub unsafe extern "C" fn libinput_tablet_pad_mode_group_get_user_data(
3740 group: *const libc::c_void,
3741) -> *mut libc::c_void {
3742 if group.is_null() {
3743 return std::ptr::null_mut();
3744 }
3745 (*group.cast::<LibinputTabletPadModeGroup>()).user_data
3746}
3747
3748#[no_mangle]
3749pub unsafe extern "C" fn libinput_tablet_tool_config_pressure_range_is_available(
3750 tool: *const LibinputTabletTool,
3751) -> libc::c_int {
3752 (!tool.is_null() && (*tool).has_pressure) as libc::c_int
3753}
3754
3755#[no_mangle]
3756pub unsafe extern "C" fn libinput_tablet_tool_config_pressure_range_set(
3757 tool: *mut LibinputTabletTool,
3758 minimum: f64,
3759 maximum: f64,
3760) -> u32 {
3761 if tool.is_null() || !(*tool).has_pressure {
3762 return 1;
3763 }
3764 if minimum < 0.0 || maximum > 1.0 || minimum >= maximum {
3765 return 2;
3766 }
3767 (*tool).wanted_pressure_range_minimum = minimum;
3768 (*tool).wanted_pressure_range_maximum = maximum;
3769 0
3770}
3771
3772#[no_mangle]
3773pub unsafe extern "C" fn libinput_tablet_tool_config_pressure_range_get_minimum(
3774 tool: *const LibinputTabletTool,
3775) -> f64 {
3776 if tool.is_null() {
3777 0.0
3778 } else {
3779 (*tool).wanted_pressure_range_minimum
3780 }
3781}
3782
3783#[no_mangle]
3784pub unsafe extern "C" fn libinput_tablet_tool_config_pressure_range_get_maximum(
3785 tool: *const LibinputTabletTool,
3786) -> f64 {
3787 if tool.is_null() {
3788 1.0
3789 } else {
3790 (*tool).wanted_pressure_range_maximum
3791 }
3792}
3793
3794#[no_mangle]
3795pub unsafe extern "C" fn libinput_tablet_tool_config_pressure_range_get_default_minimum(
3796 _tool: *const libc::c_void,
3797) -> f64 {
3798 0.0
3799}
3800
3801#[no_mangle]
3802pub unsafe extern "C" fn libinput_tablet_tool_config_pressure_range_get_default_maximum(
3803 _tool: *const libc::c_void,
3804) -> f64 {
3805 1.0
3806}
3807
3808#[no_mangle]
3809pub unsafe extern "C" fn libinput_tablet_tool_config_eraser_button_get_modes(
3810 tool: *const libc::c_void,
3811) -> u32 {
3812 let tool = tool.cast::<LibinputTabletTool>();
3813 if tool.is_null() {
3814 0
3815 } else {
3816 (*tool).eraser_button_modes
3817 }
3818}
3819
3820#[no_mangle]
3821pub unsafe extern "C" fn libinput_tablet_tool_config_eraser_button_set_mode(
3822 tool: *mut libc::c_void,
3823 mode: u32,
3824) -> u32 {
3825 let tool = tool.cast::<LibinputTabletTool>();
3826 if tool.is_null() || (mode != 0 && ((*tool).eraser_button_modes & mode) == 0) {
3827 return 1;
3828 }
3829 if !matches!(mode, 0 | 1) {
3830 return 2;
3831 }
3832 (*tool).wanted_eraser_button_mode = mode;
3833 if !(*tool).in_proximity {
3834 (*tool).eraser_button_mode = mode;
3835 }
3836 0
3837}
3838
3839#[no_mangle]
3840pub unsafe extern "C" fn libinput_tablet_tool_config_eraser_button_get_mode(
3841 tool: *const libc::c_void,
3842) -> u32 {
3843 let tool = tool.cast::<LibinputTabletTool>();
3844 if tool.is_null() || (*tool).eraser_button_modes == 0 {
3845 0
3846 } else {
3847 (*tool).wanted_eraser_button_mode
3848 }
3849}
3850
3851#[no_mangle]
3852pub unsafe extern "C" fn libinput_tablet_tool_config_eraser_button_get_default_mode(
3853 _tool: *const libc::c_void,
3854) -> u32 {
3855 0
3856}
3857
3858#[no_mangle]
3859pub unsafe extern "C" fn libinput_tablet_tool_config_eraser_button_set_button(
3860 tool: *mut libc::c_void,
3861 button: u32,
3862) -> u32 {
3863 let tool = tool.cast::<LibinputTabletTool>();
3864 if tool.is_null() || (*tool).eraser_button_modes == 0 {
3865 return 1;
3866 }
3867 let is_button = matches!(button, 0x149 | 0x14b | 0x14c)
3868 || (0x100..0x140).contains(&button)
3869 || (0x150..=0x151).contains(&button)
3870 || (0x220..=0x223).contains(&button)
3871 || (0x2c0..=0x2e7).contains(&button);
3872 if !is_button {
3873 return 2;
3874 }
3875 (*tool).wanted_eraser_button = button;
3876 if !(*tool).in_proximity {
3877 (*tool).eraser_button = button;
3878 }
3879 0
3880}
3881
3882#[no_mangle]
3883pub unsafe extern "C" fn libinput_tablet_tool_config_eraser_button_get_button(
3884 tool: *const libc::c_void,
3885) -> u32 {
3886 let tool = tool.cast::<LibinputTabletTool>();
3887 if tool.is_null() || (*tool).eraser_button_modes == 0 {
3888 0
3889 } else {
3890 (*tool).wanted_eraser_button
3891 }
3892}
3893
3894#[no_mangle]
3895pub unsafe extern "C" fn libinput_tablet_tool_config_eraser_button_get_default_button(
3896 tool: *const libc::c_void,
3897) -> u32 {
3898 let tool = tool.cast::<LibinputTabletTool>();
3899 if tool.is_null() || (*tool).eraser_button_modes == 0 {
3900 0
3901 } else {
3902 (*tool).default_eraser_button
3903 }
3904}
3905
3906#[no_mangle]
3907pub unsafe extern "C" fn libinput_tablet_tool_get_name(
3908 tool: *const libc::c_void,
3909) -> *const libc::c_char {
3910 let tool = tool.cast::<LibinputTabletTool>();
3911 if tool.is_null() {
3912 return std::ptr::null();
3913 }
3914 let tool = tool.cast::<LibinputTabletTool>();
3915 let tool = tool as *mut LibinputTabletTool;
3916 if let Some(name) = (*tool).name.as_ref() {
3917 return name.as_ptr();
3918 }
3919 if let Some(name) = crate::backend::tablet_tool_name_for_id((*tool).tool_id) {
3920 (*tool).name = Some(name);
3921 (*tool)
3922 .name
3923 .as_ref()
3924 .map_or(std::ptr::null(), |name| name.as_ptr())
3925 } else {
3926 std::ptr::null()
3927 }
3928}
3929
3930#[no_mangle]
3931pub unsafe extern "C" fn libinput_tablet_tool_get_serial(tool: *const libc::c_void) -> u64 {
3932 let tool = tool.cast::<LibinputTabletTool>();
3933 if tool.is_null() {
3934 0
3935 } else {
3936 (*tool).serial
3937 }
3938}
3939
3940#[no_mangle]
3941pub unsafe extern "C" fn libinput_tablet_tool_get_tool_id(tool: *const libc::c_void) -> u64 {
3942 let tool = tool.cast::<LibinputTabletTool>();
3943 if tool.is_null() {
3944 0
3945 } else {
3946 (*tool).tool_id
3947 }
3948}
3949
3950#[no_mangle]
3951pub unsafe extern "C" fn libinput_tablet_tool_get_type(tool: *const libc::c_void) -> u32 {
3952 let tool = tool.cast::<LibinputTabletTool>();
3953 if tool.is_null() {
3954 0
3955 } else {
3956 (*tool).tool_type
3957 }
3958}
3959
3960#[no_mangle]
3961pub unsafe extern "C" fn libinput_tablet_tool_has_distance(
3962 tool: *const libc::c_void,
3963) -> libc::c_int {
3964 let tool = tool.cast::<LibinputTabletTool>();
3965 (!tool.is_null() && (*tool).has_distance) as libc::c_int
3966}
3967
3968#[no_mangle]
3969pub unsafe extern "C" fn libinput_tablet_tool_has_button(
3970 tool: *const libc::c_void,
3971 button: u32,
3972) -> libc::c_int {
3973 let tool = tool.cast::<LibinputTabletTool>();
3974 (!tool.is_null() && (*tool).buttons.contains(&button)) as libc::c_int
3975}
3976
3977#[no_mangle]
3978pub unsafe extern "C" fn libinput_tablet_tool_has_size(tool: *const libc::c_void) -> libc::c_int {
3979 let tool = tool.cast::<LibinputTabletTool>();
3980 (!tool.is_null() && (*tool).has_size) as libc::c_int
3981}
3982
3983#[no_mangle]
3984pub unsafe extern "C" fn libinput_tablet_tool_is_unique(tool: *const libc::c_void) -> libc::c_int {
3985 let tool = tool.cast::<LibinputTabletTool>();
3986 (!tool.is_null() && (*tool).serial != 0) as libc::c_int
3987}
3988
3989#[no_mangle]
3990pub unsafe extern "C" fn libinput_tablet_tool_set_user_data(
3991 tool: *mut libc::c_void,
3992 data: *mut libc::c_void,
3993) {
3994 let tool = tool.cast::<LibinputTabletTool>();
3995 if !tool.is_null() {
3996 (*tool).user_data = data;
3997 }
3998}
3999
4000#[no_mangle]
4001pub unsafe extern "C" fn libinput_tablet_tool_get_user_data(
4002 tool: *const libc::c_void,
4003) -> *mut libc::c_void {
4004 let tool = tool.cast::<LibinputTabletTool>();
4005 if tool.is_null() {
4006 std::ptr::null_mut()
4007 } else {
4008 (*tool).user_data
4009 }
4010}
4011
4012#[no_mangle]
4013pub unsafe extern "C" fn libinput_tablet_tool_has_pressure(
4014 tool: *const libc::c_void,
4015) -> libc::c_int {
4016 let tool = tool.cast::<LibinputTabletTool>();
4017 (!tool.is_null() && (*tool).has_pressure) as libc::c_int
4018}
4019
4020#[no_mangle]
4021pub unsafe extern "C" fn libinput_tablet_tool_has_rotation(
4022 tool: *const libc::c_void,
4023) -> libc::c_int {
4024 let tool = tool.cast::<LibinputTabletTool>();
4025 (!tool.is_null() && (*tool).has_rotation) as libc::c_int
4026}
4027
4028#[no_mangle]
4029pub unsafe extern "C" fn libinput_tablet_tool_has_slider(tool: *const libc::c_void) -> libc::c_int {
4030 let tool = tool.cast::<LibinputTabletTool>();
4031 (!tool.is_null() && (*tool).has_slider) as libc::c_int
4032}
4033
4034#[no_mangle]
4035pub unsafe extern "C" fn libinput_tablet_tool_has_tilt(tool: *const libc::c_void) -> libc::c_int {
4036 let tool = tool.cast::<LibinputTabletTool>();
4037 (!tool.is_null() && (*tool).has_tilt) as libc::c_int
4038}
4039
4040#[no_mangle]
4041pub unsafe extern "C" fn libinput_tablet_tool_has_wheel(tool: *const libc::c_void) -> libc::c_int {
4042 let tool = tool.cast::<LibinputTabletTool>();
4043 (!tool.is_null() && (*tool).has_wheel) as libc::c_int
4044}
4045
4046#[no_mangle]
4047pub unsafe extern "C" fn libinput_tablet_tool_ref(tool: *mut libc::c_void) -> *mut libc::c_void {
4048 let tablet_tool = tool.cast::<LibinputTabletTool>();
4049 if !tablet_tool.is_null() {
4050 (*tablet_tool)
4051 .refcount
4052 .fetch_add(1, std::sync::atomic::Ordering::Relaxed);
4053 }
4054 tool
4055}
4056
4057#[no_mangle]
4058pub unsafe extern "C" fn libinput_tablet_tool_unref(tool: *mut libc::c_void) -> *mut libc::c_void {
4059 let tablet_tool = tool.cast::<LibinputTabletTool>();
4060 if tablet_tool.is_null() {
4061 return std::ptr::null_mut();
4062 }
4063 if (*tablet_tool)
4064 .refcount
4065 .fetch_sub(1, std::sync::atomic::Ordering::AcqRel)
4066 == 1
4067 {
4068 drop(Box::from_raw(tablet_tool));
4069 std::ptr::null_mut()
4070 } else {
4071 tool
4072 }
4073}
4074
4075#[no_mangle]
4080pub unsafe extern "C" fn libinput_suspend(ctx: *mut LibinputContext) {
4081 if ctx.is_null() {
4082 return;
4083 }
4084 let mut events = std::collections::VecDeque::new();
4085 if let Ok(mut backend) = (*ctx).backend.lock() {
4086 backend.suspend(ctx, &mut events);
4087 }
4088 (*ctx).event_queue.extend(events);
4089}
4090
4091#[no_mangle]
4092pub unsafe extern "C" fn libinput_resume(ctx: *mut LibinputContext) -> libc::c_int {
4093 if ctx.is_null() {
4094 return -1;
4095 }
4096 let mut events = std::collections::VecDeque::new();
4097 let status = if let Ok(mut backend) = (*ctx).backend.lock() {
4098 backend.resume(ctx, &mut events)
4099 } else {
4100 return -1;
4101 };
4102 (*ctx).event_queue.extend(events);
4103 if !(*ctx).event_queue.is_empty() {
4104 (*ctx).signal_fd();
4105 }
4106 status
4107}
4108
4109#[cfg(test)]
4110mod tests {
4111 use super::*;
4112
4113 unsafe extern "C" fn deny_open(
4114 _path: *const libc::c_char,
4115 _flags: libc::c_int,
4116 _user_data: *mut libc::c_void,
4117 ) -> libc::c_int {
4118 -libc::EACCES
4119 }
4120
4121 unsafe extern "C" fn close_fd(_fd: libc::c_int, _user_data: *mut libc::c_void) {}
4122
4123 static INTERFACE: LibinputInterface = LibinputInterface {
4124 open_restricted: Some(deny_open),
4125 close_restricted: Some(close_fd),
4126 };
4127
4128 #[test]
4129 fn udev_context_requires_interface_and_udev() {
4130 unsafe {
4131 let fake_udev = 1usize as *mut libc::c_void;
4132 assert!(libinput_udev_create_context(
4133 std::ptr::null(),
4134 std::ptr::null_mut(),
4135 fake_udev,
4136 )
4137 .is_null());
4138 assert!(libinput_udev_create_context(
4139 &INTERFACE,
4140 std::ptr::null_mut(),
4141 std::ptr::null_mut(),
4142 )
4143 .is_null());
4144 }
4145 }
4146
4147 #[test]
4148 fn seat_assignment_is_udev_only_and_happens_once() {
4149 unsafe {
4150 let fake_udev = 1usize as *mut libc::c_void;
4151 let seat = std::ffi::CString::new("seat0").unwrap();
4152 let udev_ctx =
4153 libinput_udev_create_context(&INTERFACE, std::ptr::null_mut(), fake_udev);
4154 assert!(!udev_ctx.is_null());
4155 assert_eq!(libinput_udev_assign_seat(udev_ctx, seat.as_ptr()), 0);
4156 assert_eq!(libinput_udev_assign_seat(udev_ctx, seat.as_ptr()), -1);
4157 libinput_unref(udev_ctx);
4158
4159 let path_ctx = libinput_path_create_context(&INTERFACE, std::ptr::null_mut());
4160 assert!(!path_ctx.is_null());
4161 assert_eq!(libinput_udev_assign_seat(path_ctx, seat.as_ptr()), -1);
4162 libinput_unref(path_ctx);
4163 }
4164 }
4165
4166 #[test]
4167 fn suspend_and_resume_are_null_safe() {
4168 unsafe {
4169 libinput_suspend(std::ptr::null_mut());
4170 assert_eq!(libinput_resume(std::ptr::null_mut()), -1);
4171 }
4172 }
4173}