(&mut self, app: &mut S)
| 99 | |
| 100 | impl GamepadBackend { |
| 101 | pub(super) fn begin_frame<S: GamepadSink>(&mut self, app: &mut S) { |
| 102 | self.ensure_gilrs(); |
| 103 | self.consume_output_requests(app); |
| 104 | let Some(mut gilrs) = self.gilrs.take() else { |
| 105 | return; |
| 106 | }; |
| 107 | |
| 108 | // When no non-JoyCon gamepad is active, throttle gilrs polling. |
| 109 | // This keeps hot-loop overhead low for KBM-only projects while still |
| 110 | // discovering new controllers quickly. |
| 111 | if self.uuid_in_use.is_empty() { |
| 112 | self.idle_poll_frame_counter = self.idle_poll_frame_counter.wrapping_add(1); |
| 113 | if !self |
| 114 | .idle_poll_frame_counter |
| 115 | .is_multiple_of(IDLE_POLL_INTERVAL_FRAMES) |
| 116 | { |
| 117 | self.gilrs = Some(gilrs); |
| 118 | return; |
| 119 | } |
| 120 | } |
| 121 | |
| 122 | while let Some(event) = gilrs.next_event() { |
| 123 | self.handle_event(app, &gilrs, event); |
| 124 | } |
| 125 | |
| 126 | // Some controllers/drivers (notably on Windows) can miss or coalesce |
| 127 | // button events. Keep a periodic sync as a safety net, but avoid |
| 128 | // full per-frame scans when there are no active gamepads. |
| 129 | self.state_sync_frame_counter = self.state_sync_frame_counter.wrapping_add(1); |
| 130 | let should_sync = !self.uuid_in_use.is_empty() |
| 131 | && self |
| 132 | .state_sync_frame_counter |
| 133 | .is_multiple_of(STATE_SYNC_INTERVAL_FRAMES); |
| 134 | if should_sync { |
| 135 | self.sync_buttons(app, &gilrs); |
| 136 | self.sync_axes(app, &gilrs); |
| 137 | } |
| 138 | |
| 139 | self.gilrs = Some(gilrs); |
| 140 | } |
| 141 | |
| 142 | #[cfg(feature = "steamworks")] |
| 143 | pub(super) fn collect_connected_indices(&self, out: &mut Vec<usize>) { |
no test coverage detected