1use super::{
5 EventResult, FocusReasonArg, Item, ItemConsts, ItemRc, ItemRendererRef, KeyEventArg,
6 MouseCursor, PointerEvent, PointerEventArg, PointerEventButton, PointerEventKind,
7 PointerScrollEvent, PointerScrollEventArg, RenderingResult, VoidArg,
8};
9use crate::api::LogicalPosition;
10use crate::input::{
11 FocusEvent, FocusEventResult, FocusReason, InputEventFilterResult, InputEventResult, KeyEvent,
12 KeyEventResult, KeyEventType, MouseEvent,
13};
14use crate::item_rendering::CachedRenderingData;
15use crate::layout::{LayoutInfo, Orientation};
16use crate::lengths::{LogicalLength, LogicalPoint, LogicalRect, LogicalSize, PointLengths};
17#[cfg(feature = "rtti")]
18use crate::rtti::*;
19use crate::window::{WindowAdapter, WindowInner};
20use crate::{Callback, Coord, Property};
21use alloc::rc::Rc;
22use const_field_offset::FieldOffsets;
23use core::cell::Cell;
24use core::pin::Pin;
25use i_slint_core_macros::*;
26
27#[repr(C)]
29#[derive(FieldOffsets, SlintElement, Default)]
30#[pin]
31pub struct TouchArea {
32 pub enabled: Property<bool>,
33 pub pressed: Property<bool>,
35 pub has_hover: Property<bool>,
36 pub pressed_x: Property<LogicalLength>,
40 pub pressed_y: Property<LogicalLength>,
41 pub mouse_x: Property<LogicalLength>,
43 pub mouse_y: Property<LogicalLength>,
44 pub mouse_cursor: Property<MouseCursor>,
45 pub clicked: Callback<VoidArg>,
46 pub double_clicked: Callback<VoidArg>,
47 pub moved: Callback<VoidArg>,
48 pub pointer_event: Callback<PointerEventArg>,
49 pub scroll_event: Callback<PointerScrollEventArg, EventResult>,
50 pub cached_rendering_data: CachedRenderingData,
52 grabbed: Cell<bool>,
54}
55
56impl Item for TouchArea {
57 fn init(self: Pin<&Self>, _self_rc: &ItemRc) {}
58
59 fn layout_info(
60 self: Pin<&Self>,
61 _orientation: Orientation,
62 _window_adapter: &Rc<dyn WindowAdapter>,
63 _self_rc: &ItemRc,
64 ) -> LayoutInfo {
65 LayoutInfo { stretch: 1., ..LayoutInfo::default() }
66 }
67
68 fn input_event_filter_before_children(
69 self: Pin<&Self>,
70 event: &MouseEvent,
71 window_adapter: &Rc<dyn WindowAdapter>,
72 _self_rc: &ItemRc,
73 ) -> InputEventFilterResult {
74 if !self.enabled() {
75 self.has_hover.set(false);
76 if self.grabbed.replace(false) {
77 self.pressed.set(false);
78 Self::FIELD_OFFSETS.pointer_event.apply_pin(self).call(&(PointerEvent {
79 button: PointerEventButton::Other,
80 kind: PointerEventKind::Cancel,
81 modifiers: window_adapter.window().0.modifiers.get().into(),
82 },));
83 }
84 return InputEventFilterResult::ForwardAndIgnore;
85 }
86 if matches!(event, MouseEvent::DragMove(..) | MouseEvent::Drop(..)) {
87 return InputEventFilterResult::ForwardAndIgnore;
89 }
90 if let Some(pos) = event.position() {
91 Self::FIELD_OFFSETS.mouse_x.apply_pin(self).set(pos.x_length());
92 Self::FIELD_OFFSETS.mouse_y.apply_pin(self).set(pos.y_length());
93 }
94 let hovering = !matches!(event, MouseEvent::Exit);
95 Self::FIELD_OFFSETS.has_hover.apply_pin(self).set(hovering);
96 if hovering {
97 if let Some(x) = window_adapter.internal(crate::InternalToken) {
98 x.set_mouse_cursor(self.mouse_cursor());
99 }
100 }
101 InputEventFilterResult::ForwardAndInterceptGrab
102 }
103
104 fn input_event(
105 self: Pin<&Self>,
106 event: &MouseEvent,
107 window_adapter: &Rc<dyn WindowAdapter>,
108 self_rc: &ItemRc,
109 ) -> InputEventResult {
110 if matches!(event, MouseEvent::Exit) {
111 Self::FIELD_OFFSETS.has_hover.apply_pin(self).set(false);
112 if let Some(x) = window_adapter.internal(crate::InternalToken) {
113 x.set_mouse_cursor(MouseCursor::Default);
114 }
115 }
116 if !self.enabled() {
117 return InputEventResult::EventIgnored;
118 }
119
120 match event {
121 MouseEvent::Pressed { position, button, .. } => {
122 self.grabbed.set(true);
123 if *button == PointerEventButton::Left {
124 Self::FIELD_OFFSETS.pressed_x.apply_pin(self).set(position.x_length());
125 Self::FIELD_OFFSETS.pressed_y.apply_pin(self).set(position.y_length());
126 Self::FIELD_OFFSETS.pressed.apply_pin(self).set(true);
127 }
128 Self::FIELD_OFFSETS.pointer_event.apply_pin(self).call(&(PointerEvent {
129 button: *button,
130 kind: PointerEventKind::Down,
131 modifiers: window_adapter.window().0.modifiers.get().into(),
132 },));
133
134 InputEventResult::GrabMouse
135 }
136 MouseEvent::Exit => {
137 Self::FIELD_OFFSETS.pressed.apply_pin(self).set(false);
138 if self.grabbed.replace(false) {
139 Self::FIELD_OFFSETS.pointer_event.apply_pin(self).call(&(PointerEvent {
140 button: PointerEventButton::Other,
141 kind: PointerEventKind::Cancel,
142 modifiers: window_adapter.window().0.modifiers.get().into(),
143 },));
144 }
145
146 InputEventResult::EventAccepted
147 }
148
149 MouseEvent::Released { button, position, click_count } => {
150 let geometry = self_rc.geometry();
151 if *button == PointerEventButton::Left
152 && LogicalRect::new(LogicalPoint::default(), geometry.size).contains(*position)
153 && self.pressed()
154 {
155 Self::FIELD_OFFSETS.clicked.apply_pin(self).call(&());
156 if (click_count % 2) == 1 {
157 Self::FIELD_OFFSETS.double_clicked.apply_pin(self).call(&())
158 }
159 }
160
161 self.grabbed.set(false);
162 if *button == PointerEventButton::Left {
163 Self::FIELD_OFFSETS.pressed.apply_pin(self).set(false);
164 }
165 Self::FIELD_OFFSETS.pointer_event.apply_pin(self).call(&(PointerEvent {
166 button: *button,
167 kind: PointerEventKind::Up,
168 modifiers: window_adapter.window().0.modifiers.get().into(),
169 },));
170
171 InputEventResult::EventAccepted
172 }
173 MouseEvent::Moved { .. } => {
174 Self::FIELD_OFFSETS.pointer_event.apply_pin(self).call(&(PointerEvent {
175 button: PointerEventButton::Other,
176 kind: PointerEventKind::Move,
177 modifiers: window_adapter.window().0.modifiers.get().into(),
178 },));
179 if self.grabbed.get() {
180 Self::FIELD_OFFSETS.moved.apply_pin(self).call(&());
181 InputEventResult::GrabMouse
182 } else {
183 InputEventResult::EventAccepted
184 }
185 }
186 MouseEvent::Wheel { delta_x, delta_y, .. } => {
187 let modifiers = window_adapter.window().0.modifiers.get().into();
188 let r =
189 Self::FIELD_OFFSETS.scroll_event.apply_pin(self).call(&(PointerScrollEvent {
190 delta_x: *delta_x,
191 delta_y: *delta_y,
192 modifiers,
193 },));
194 if self.grabbed.get() {
195 InputEventResult::GrabMouse
196 } else {
197 match r {
198 EventResult::Reject => {
199 Self::FIELD_OFFSETS.has_hover.apply_pin(self).set(false);
203 InputEventResult::EventIgnored
204 }
205 EventResult::Accept => InputEventResult::EventAccepted,
206 }
207 }
208 }
209 MouseEvent::DragMove(..) | MouseEvent::Drop(..) => InputEventResult::EventIgnored,
210 }
211 }
212
213 fn capture_key_event(
214 self: Pin<&Self>,
215 _: &KeyEvent,
216 _window_adapter: &Rc<dyn WindowAdapter>,
217 _self_rc: &ItemRc,
218 ) -> KeyEventResult {
219 KeyEventResult::EventIgnored
220 }
221
222 fn key_event(
223 self: Pin<&Self>,
224 _: &KeyEvent,
225 _window_adapter: &Rc<dyn WindowAdapter>,
226 _self_rc: &ItemRc,
227 ) -> KeyEventResult {
228 KeyEventResult::EventIgnored
229 }
230
231 fn focus_event(
232 self: Pin<&Self>,
233 _: &FocusEvent,
234 _window_adapter: &Rc<dyn WindowAdapter>,
235 _self_rc: &ItemRc,
236 ) -> FocusEventResult {
237 FocusEventResult::FocusIgnored
238 }
239
240 fn render(
241 self: Pin<&Self>,
242 _backend: &mut ItemRendererRef,
243 _self_rc: &ItemRc,
244 _size: LogicalSize,
245 ) -> RenderingResult {
246 RenderingResult::ContinueRenderingChildren
247 }
248
249 fn bounding_rect(
250 self: core::pin::Pin<&Self>,
251 _window_adapter: &Rc<dyn WindowAdapter>,
252 _self_rc: &ItemRc,
253 mut geometry: LogicalRect,
254 ) -> LogicalRect {
255 geometry.size = LogicalSize::zero();
256 geometry
257 }
258
259 fn clips_children(self: core::pin::Pin<&Self>) -> bool {
260 false
261 }
262}
263
264impl ItemConsts for TouchArea {
265 const cached_rendering_data_offset: const_field_offset::FieldOffset<
266 TouchArea,
267 CachedRenderingData,
268 > = TouchArea::FIELD_OFFSETS.cached_rendering_data.as_unpinned_projection();
269}
270
271#[repr(C)]
273#[derive(FieldOffsets, Default, SlintElement)]
274#[pin]
275pub struct FocusScope {
276 pub enabled: Property<bool>,
277 pub has_focus: Property<bool>,
278 pub focus_on_click: Property<bool>,
279 pub focus_on_tab_navigation: Property<bool>,
280 pub key_pressed: Callback<KeyEventArg, EventResult>,
281 pub key_released: Callback<KeyEventArg, EventResult>,
282 pub capture_key_pressed: Callback<KeyEventArg, EventResult>,
283 pub capture_key_released: Callback<KeyEventArg, EventResult>,
284 pub focus_changed_event: Callback<FocusReasonArg>,
285 pub focus_gained: Callback<FocusReasonArg>,
286 pub focus_lost: Callback<FocusReasonArg>,
287 pub cached_rendering_data: CachedRenderingData,
289}
290
291impl Item for FocusScope {
292 fn init(self: Pin<&Self>, _self_rc: &ItemRc) {}
293
294 fn layout_info(
295 self: Pin<&Self>,
296 _orientation: Orientation,
297 _window_adapter: &Rc<dyn WindowAdapter>,
298 _self_rc: &ItemRc,
299 ) -> LayoutInfo {
300 LayoutInfo { stretch: 1., ..LayoutInfo::default() }
301 }
302
303 fn input_event_filter_before_children(
304 self: Pin<&Self>,
305 _: &MouseEvent,
306 _window_adapter: &Rc<dyn WindowAdapter>,
307 _self_rc: &ItemRc,
308 ) -> InputEventFilterResult {
309 InputEventFilterResult::ForwardEvent
310 }
311
312 fn input_event(
313 self: Pin<&Self>,
314 event: &MouseEvent,
315 window_adapter: &Rc<dyn WindowAdapter>,
316 self_rc: &ItemRc,
317 ) -> InputEventResult {
318 if self.enabled()
319 && self.focus_on_click()
320 && matches!(event, MouseEvent::Pressed { .. })
321 && !self.has_focus()
322 {
323 WindowInner::from_pub(window_adapter.window()).set_focus_item(
324 self_rc,
325 true,
326 FocusReason::PointerClick,
327 );
328 InputEventResult::EventAccepted
329 } else {
330 InputEventResult::EventIgnored
331 }
332 }
333
334 fn capture_key_event(
335 self: Pin<&Self>,
336 event: &KeyEvent,
337 _window_adapter: &Rc<dyn WindowAdapter>,
338 _self_rc: &ItemRc,
339 ) -> KeyEventResult {
340 let r = match event.event_type {
341 KeyEventType::KeyPressed => {
342 Self::FIELD_OFFSETS.capture_key_pressed.apply_pin(self).call(&(event.clone(),))
343 }
344 KeyEventType::KeyReleased => {
345 Self::FIELD_OFFSETS.capture_key_released.apply_pin(self).call(&(event.clone(),))
346 }
347 KeyEventType::UpdateComposition | KeyEventType::CommitComposition => {
348 EventResult::Reject
349 }
350 };
351 match r {
352 EventResult::Accept => KeyEventResult::EventAccepted,
353 EventResult::Reject => KeyEventResult::EventIgnored,
354 }
355 }
356
357 fn key_event(
358 self: Pin<&Self>,
359 event: &KeyEvent,
360 _window_adapter: &Rc<dyn WindowAdapter>,
361 _self_rc: &ItemRc,
362 ) -> KeyEventResult {
363 let r = match event.event_type {
364 KeyEventType::KeyPressed => {
365 Self::FIELD_OFFSETS.key_pressed.apply_pin(self).call(&(event.clone(),))
366 }
367 KeyEventType::KeyReleased => {
368 Self::FIELD_OFFSETS.key_released.apply_pin(self).call(&(event.clone(),))
369 }
370 KeyEventType::UpdateComposition | KeyEventType::CommitComposition => {
371 EventResult::Reject
372 }
373 };
374 match r {
375 EventResult::Accept => KeyEventResult::EventAccepted,
376 EventResult::Reject => KeyEventResult::EventIgnored,
377 }
378 }
379
380 fn focus_event(
381 self: Pin<&Self>,
382 event: &FocusEvent,
383 _window_adapter: &Rc<dyn WindowAdapter>,
384 _self_rc: &ItemRc,
385 ) -> FocusEventResult {
386 if !self.enabled() {
387 return FocusEventResult::FocusIgnored;
388 }
389
390 match event {
391 FocusEvent::FocusIn(reason) => {
392 match reason {
393 FocusReason::TabNavigation if !self.focus_on_tab_navigation() => {
394 return FocusEventResult::FocusIgnored
395 }
396 FocusReason::PointerClick if !self.focus_on_click() => {
397 return FocusEventResult::FocusIgnored
398 }
399 _ => (),
400 };
401
402 self.has_focus.set(true);
403 Self::FIELD_OFFSETS.focus_changed_event.apply_pin(self).call(&((*reason,)));
404 Self::FIELD_OFFSETS.focus_gained.apply_pin(self).call(&((*reason,)));
405 }
406 FocusEvent::FocusOut(reason) => {
407 self.has_focus.set(false);
408 Self::FIELD_OFFSETS.focus_changed_event.apply_pin(self).call(&((*reason,)));
409 Self::FIELD_OFFSETS.focus_lost.apply_pin(self).call(&((*reason,)));
410 }
411 }
412 FocusEventResult::FocusAccepted
413 }
414
415 fn render(
416 self: Pin<&Self>,
417 _backend: &mut ItemRendererRef,
418 _self_rc: &ItemRc,
419 _size: LogicalSize,
420 ) -> RenderingResult {
421 RenderingResult::ContinueRenderingChildren
422 }
423
424 fn bounding_rect(
425 self: core::pin::Pin<&Self>,
426 _window_adapter: &Rc<dyn WindowAdapter>,
427 _self_rc: &ItemRc,
428 mut geometry: LogicalRect,
429 ) -> LogicalRect {
430 geometry.size = LogicalSize::zero();
431 geometry
432 }
433
434 fn clips_children(self: core::pin::Pin<&Self>) -> bool {
435 false
436 }
437}
438
439impl ItemConsts for FocusScope {
440 const cached_rendering_data_offset: const_field_offset::FieldOffset<
441 FocusScope,
442 CachedRenderingData,
443 > = FocusScope::FIELD_OFFSETS.cached_rendering_data.as_unpinned_projection();
444}
445
446#[repr(C)]
447#[derive(FieldOffsets, Default, SlintElement)]
448#[pin]
449pub struct SwipeGestureHandler {
450 pub enabled: Property<bool>,
451 pub handle_swipe_left: Property<bool>,
452 pub handle_swipe_right: Property<bool>,
453 pub handle_swipe_up: Property<bool>,
454 pub handle_swipe_down: Property<bool>,
455
456 pub moved: Callback<VoidArg>,
457 pub swiped: Callback<VoidArg>,
458 pub cancelled: Callback<VoidArg>,
459
460 pub pressed_position: Property<LogicalPosition>,
461 pub current_position: Property<LogicalPosition>,
462 pub swiping: Property<bool>,
463
464 pressed: Cell<bool>,
466 pub cached_rendering_data: CachedRenderingData,
469}
470
471impl Item for SwipeGestureHandler {
472 fn init(self: Pin<&Self>, _self_rc: &ItemRc) {}
473
474 fn layout_info(
475 self: Pin<&Self>,
476 _orientation: Orientation,
477 _window_adapter: &Rc<dyn WindowAdapter>,
478 _self_rc: &ItemRc,
479 ) -> LayoutInfo {
480 LayoutInfo { stretch: 1., ..LayoutInfo::default() }
481 }
482
483 fn input_event_filter_before_children(
484 self: Pin<&Self>,
485 event: &MouseEvent,
486 _window_adapter: &Rc<dyn WindowAdapter>,
487 _self_rc: &ItemRc,
488 ) -> InputEventFilterResult {
489 if !self.enabled() {
490 if self.pressed.get() {
491 self.cancel_impl();
492 }
493 return InputEventFilterResult::ForwardAndIgnore;
494 }
495
496 match event {
497 MouseEvent::Pressed { position, button: PointerEventButton::Left, .. } => {
498 Self::FIELD_OFFSETS
499 .pressed_position
500 .apply_pin(self)
501 .set(crate::lengths::logical_position_to_api(*position));
502 self.pressed.set(true);
503 InputEventFilterResult::DelayForwarding(
504 super::flickable::FORWARD_DELAY.as_millis() as _
505 )
506 }
507 MouseEvent::Exit => {
508 self.cancel_impl();
509 InputEventFilterResult::ForwardAndIgnore
510 }
511 MouseEvent::Released { button: PointerEventButton::Left, .. } => {
512 if self.swiping() {
513 InputEventFilterResult::Intercept
514 } else {
515 self.pressed.set(false);
516 InputEventFilterResult::ForwardEvent
517 }
518 }
519 MouseEvent::Moved { position } => {
520 if self.swiping() {
521 InputEventFilterResult::Intercept
522 } else if !self.pressed.get() {
523 InputEventFilterResult::ForwardEvent
524 } else if self.is_over_threshold(position) {
525 InputEventFilterResult::Intercept
526 } else {
527 InputEventFilterResult::ForwardAndInterceptGrab
528 }
529 }
530 MouseEvent::Wheel { .. } => InputEventFilterResult::ForwardAndIgnore,
531 MouseEvent::Pressed { .. } | MouseEvent::Released { .. } => {
533 InputEventFilterResult::ForwardAndIgnore
534 }
535 MouseEvent::DragMove(..) | MouseEvent::Drop(..) => {
536 InputEventFilterResult::ForwardAndIgnore
537 }
538 }
539 }
540
541 fn input_event(
542 self: Pin<&Self>,
543 event: &MouseEvent,
544 _window_adapter: &Rc<dyn WindowAdapter>,
545 _self_rc: &ItemRc,
546 ) -> InputEventResult {
547 match event {
548 MouseEvent::Pressed { .. } => InputEventResult::GrabMouse,
549 MouseEvent::Exit => {
550 self.cancel_impl();
551 InputEventResult::EventIgnored
552 }
553 MouseEvent::Released { position, .. } => {
554 if !self.pressed.get() && !self.swiping() {
555 return InputEventResult::EventIgnored;
556 }
557 self.current_position.set(crate::lengths::logical_position_to_api(*position));
558 self.pressed.set(false);
559 if self.swiping() {
560 Self::FIELD_OFFSETS.swiping.apply_pin(self).set(false);
561 Self::FIELD_OFFSETS.swiped.apply_pin(self).call(&());
562 InputEventResult::EventAccepted
563 } else {
564 InputEventResult::EventIgnored
565 }
566 }
567 MouseEvent::Moved { position } => {
568 if !self.pressed.get() {
569 return InputEventResult::EventAccepted;
570 }
571 self.current_position.set(crate::lengths::logical_position_to_api(*position));
572 let mut swiping = self.swiping();
573 if !swiping && self.is_over_threshold(position) {
574 Self::FIELD_OFFSETS.swiping.apply_pin(self).set(true);
575 swiping = true;
576 }
577 Self::FIELD_OFFSETS.moved.apply_pin(self).call(&());
578 if swiping {
579 InputEventResult::GrabMouse
580 } else {
581 InputEventResult::EventAccepted
582 }
583 }
584 MouseEvent::Wheel { .. } => InputEventResult::EventIgnored,
585 MouseEvent::DragMove(..) | MouseEvent::Drop(..) => InputEventResult::EventIgnored,
586 }
587 }
588
589 fn capture_key_event(
590 self: Pin<&Self>,
591 _: &KeyEvent,
592 _window_adapter: &Rc<dyn WindowAdapter>,
593 _self_rc: &ItemRc,
594 ) -> KeyEventResult {
595 KeyEventResult::EventIgnored
596 }
597
598 fn key_event(
599 self: Pin<&Self>,
600 _event: &KeyEvent,
601 _window_adapter: &Rc<dyn WindowAdapter>,
602 _self_rc: &ItemRc,
603 ) -> KeyEventResult {
604 KeyEventResult::EventIgnored
605 }
606
607 fn focus_event(
608 self: Pin<&Self>,
609 _: &FocusEvent,
610 _window_adapter: &Rc<dyn WindowAdapter>,
611 _self_rc: &ItemRc,
612 ) -> FocusEventResult {
613 FocusEventResult::FocusIgnored
614 }
615
616 fn render(
617 self: Pin<&Self>,
618 _backend: &mut ItemRendererRef,
619 _self_rc: &ItemRc,
620 _size: LogicalSize,
621 ) -> RenderingResult {
622 RenderingResult::ContinueRenderingChildren
623 }
624
625 fn bounding_rect(
626 self: core::pin::Pin<&Self>,
627 _window_adapter: &Rc<dyn WindowAdapter>,
628 _self_rc: &ItemRc,
629 mut geometry: LogicalRect,
630 ) -> LogicalRect {
631 geometry.size = LogicalSize::zero();
632 geometry
633 }
634
635 fn clips_children(self: core::pin::Pin<&Self>) -> bool {
636 false
637 }
638}
639
640impl ItemConsts for SwipeGestureHandler {
641 const cached_rendering_data_offset: const_field_offset::FieldOffset<Self, CachedRenderingData> =
642 Self::FIELD_OFFSETS.cached_rendering_data.as_unpinned_projection();
643}
644
645impl SwipeGestureHandler {
646 pub fn cancel(self: Pin<&Self>, _: &Rc<dyn WindowAdapter>, _: &ItemRc) {
647 self.cancel_impl();
648 }
649
650 fn cancel_impl(self: Pin<&Self>) {
651 if !self.pressed.replace(false) {
652 debug_assert!(!self.swiping());
653 return;
654 }
655 if self.swiping() {
656 Self::FIELD_OFFSETS.swiping.apply_pin(self).set(false);
657 Self::FIELD_OFFSETS.cancelled.apply_pin(self).call(&());
658 }
659 }
660
661 fn is_over_threshold(self: Pin<&Self>, position: &LogicalPoint) -> bool {
662 let pressed_pos = self.pressed_position();
663 let dx = position.x - pressed_pos.x as Coord;
664 let dy = position.y - pressed_pos.y as Coord;
665 let threshold = super::flickable::DISTANCE_THRESHOLD.get();
666 (self.handle_swipe_down() && dy > threshold && dy > dx.abs() / 2 as Coord)
667 || (self.handle_swipe_up() && dy < -threshold && dy < -dx.abs() / 2 as Coord)
668 || (self.handle_swipe_left() && dx < -threshold && dx < -dy.abs() / 2 as Coord)
669 || (self.handle_swipe_right() && dx > threshold && dx > dy.abs() / 2 as Coord)
670 }
671}
672
673#[cfg(feature = "ffi")]
674#[unsafe(no_mangle)]
675pub unsafe extern "C" fn slint_swipegesturehandler_cancel(
676 s: Pin<&SwipeGestureHandler>,
677 window_adapter: *const crate::window::ffi::WindowAdapterRcOpaque,
678 self_component: &vtable::VRc<crate::item_tree::ItemTreeVTable>,
679 self_index: u32,
680) {
681 let window_adapter = &*(window_adapter as *const Rc<dyn WindowAdapter>);
682 let self_rc = ItemRc::new(self_component.clone(), self_index);
683 s.cancel(window_adapter, &self_rc);
684}