Repository: servo/servo
File: ports/servoshell/desktop/gamepad.rs (Rust)

Code before:
            gilrs::Button::South => 0,
            gilrs::Button::East => 1,
            gilrs::Button::West => 2,
            gilrs::Button::North => 3,
            gilrs::Button::LeftTrigger => 4,
            gilrs::Button::RightTrigger => 5,
            gilrs::Button::LeftTrigger2 => 6,
            gilrs::Button::RightTrigger2 => 7,
            gilrs::Button::Select => 8,
            gilrs::Button::Start => 9,
            gilrs::Button::LeftThumb => 10,
            gilrs::Button::RightThumb => 11,
            gilrs::Button::DPadUp => 12,
            gilrs::Button::DPadDown => 13,
            gilrs::Button::DPadLeft => 14,
            gilrs::Button::DPadRight => 15,
            gilrs::Button::Mode => 16,
            _ => 17, // Other buttons do not map to "standard" gamepad mapping and are ignored
        }
    }

    pub(crate) fn play_haptic_effect(
        &mut self,
        index: usize,
        effect_type: GamepadHapticEffectType,
        effect_complete_sender: Box<dyn Fn(bool)>,
    ) {
        let GamepadHapticEffectType::DualRumble(params) = effect_type;
        if let Some(connected_gamepad) = self
            .handle
            .gamepads()
            .find(|gamepad| usize::from(gamepad.0) == index)
        {
            let start_delay = Ticks::from_ms(params.start_delay as u32);
            let duration = Ticks::from_ms(params.duration as u32);
            let strong_magnitude = (params.strong_magnitude * u16::MAX as f64).round() as u16;
            let weak_magnitude = (params.weak_magnitude * u16::MAX as f64).round() as u16;

            let scheduling = Replay {
                after: start_delay,
                play_for: duration,
                with_delay: Ticks::from_ms(0),
            };
            let effect = EffectBuilder::new()
                .add_effect(BaseEffect {
                    kind: BaseEffectType::Strong { magnitude: strong_magnitude },
                    scheduling,
                    envelope: Default::default(),
                })
                .add_effect(BaseEffect {
                    kind: BaseEffectType::Weak { magnitude: weak_magnitude },

Review comment (suggestion):
```suggestion
        callback: Box<dyn Fn(bool)>,
```

Code after:
    fn map_gamepad_button(button: gilrs::Button) -> usize {
        match button {
            gilrs::Button::South => 0,
            gilrs::Button::East => 1,
            gilrs::Button::West => 2,
            gilrs::Button::North => 3,
            gilrs::Button::LeftTrigger => 4,
            gilrs::Button::RightTrigger => 5,
            gilrs::Button::LeftTrigger2 => 6,
            gilrs::Button::RightTrigger2 => 7,
            gilrs::Button::Select => 8,
            gilrs::Button::Start => 9,
            gilrs::Button::LeftThumb => 10,
            gilrs::Button::RightThumb => 11,
            gilrs::Button::DPadUp => 12,
            gilrs::Button::DPadDown => 13,
            gilrs::Button::DPadLeft => 14,
            gilrs::Button::DPadRight => 15,
            gilrs::Button::Mode => 16,
            _ => 17, // Other buttons do not map to "standard" gamepad mapping and are ignored
        }
    }

    pub(crate) fn play_haptic_effect(
        &mut self,
        index: usize,
        effect_type: GamepadHapticEffectType,
        callback: Box<dyn FnOnce(bool)>,
    ) {
        let GamepadHapticEffectType::DualRumble(params) = effect_type;
        if let Some(connected_gamepad) = self
            .handle
            .gamepads()
            .find(|gamepad| usize::from(gamepad.0) == index)
        {
            let start_delay = Ticks::from_ms(params.start_delay as u32);
            let duration = Ticks::from_ms(params.duration as u32);
            let strong_magnitude = (params.strong_magnitude * u16::MAX as f64).round() as u16;
            let weak_magnitude = (params.weak_magnitude * u16::MAX as f64).round() as u16;

            let scheduling = Replay {
                after: start_delay,
                play_for: duration,
                with_delay: Ticks::from_ms(0),
            };
            let effect = EffectBuilder::new()
                .add_effect(BaseEffect {
                    kind: BaseEffectType::Strong { magnitude: strong_magnitude },
                    scheduling,
                    envelope: Default::default(),
                })