Handle pointer-based scrolling for text inputs: scroll wheel and drag-to-scroll. Mobile-first: dragging scrolls the content rather than selecting text. `scroll_delta` contains (x, y) scroll wheel deltas. For single-line, both axes map to horizontal scroll. For multiline, y scrolls vertically.
(&mut self, scroll_delta: Vector2, touch_input_active: bool)
| 6368 | /// `scroll_delta` contains (x, y) scroll wheel deltas. For single-line, both axes |
| 6369 | /// map to horizontal scroll. For multiline, y scrolls vertically. |
| 6370 | pub fn update_text_input_pointer_scroll(&mut self, scroll_delta: Vector2, touch_input_active: bool) -> bool { |
| 6371 | for idle in self.text_input_scrollbar_idle_frames.values_mut() { |
| 6372 | *idle = idle.saturating_add(1); |
| 6373 | } |
| 6374 | |
| 6375 | let mut consumed_scroll = false; |
| 6376 | |
| 6377 | let focused = self.focused_element_id; |
| 6378 | |
| 6379 | // --- Scroll wheel: scroll any hovered text input (even if unfocused) --- |
| 6380 | let has_scroll = scroll_delta.x.abs() > 0.01 || scroll_delta.y.abs() > 0.01; |
| 6381 | if has_scroll { |
| 6382 | let p = self.pointer_info.position; |
| 6383 | // Find the text input under the pointer |
| 6384 | let hovered_ti = self.text_input_element_ids.iter().enumerate().find(|&(_, &id)| { |
| 6385 | self.layout_element_map.get(&id) |
| 6386 | .map(|item| { |
| 6387 | let bb = item.bounding_box; |
| 6388 | p.x >= bb.x && p.x <= bb.x + bb.width |
| 6389 | && p.y >= bb.y && p.y <= bb.y + bb.height |
| 6390 | }) |
| 6391 | .unwrap_or(false) |
| 6392 | }); |
| 6393 | if let Some((idx, &elem_id)) = hovered_ti { |
| 6394 | let is_multiline = self.text_input_configs.get(idx) |
| 6395 | .map(|cfg| cfg.is_multiline) |
| 6396 | .unwrap_or(false); |
| 6397 | if let Some(state) = self.text_edit_states.get_mut(&elem_id) { |
| 6398 | if is_multiline { |
| 6399 | if scroll_delta.y.abs() > 0.01 { |
| 6400 | state.scroll_offset_y -= scroll_delta.y; |
| 6401 | if state.scroll_offset_y < 0.0 { |
| 6402 | state.scroll_offset_y = 0.0; |
| 6403 | } |
| 6404 | } |
| 6405 | } else { |
| 6406 | let h_delta = if scroll_delta.x.abs() > scroll_delta.y.abs() { |
| 6407 | scroll_delta.x |
| 6408 | } else { |
| 6409 | scroll_delta.y |
| 6410 | }; |
| 6411 | if h_delta.abs() > 0.01 { |
| 6412 | state.scroll_offset -= h_delta; |
| 6413 | if state.scroll_offset < 0.0 { |
| 6414 | state.scroll_offset = 0.0; |
| 6415 | } |
| 6416 | } |
| 6417 | } |
| 6418 | consumed_scroll = true; |
| 6419 | self.text_input_scrollbar_idle_frames.insert(elem_id, 0); |
| 6420 | } |
| 6421 | } |
| 6422 | } |
| 6423 | |
| 6424 | // --- Drag scrolling (focused text input only) --- |
| 6425 | if focused == 0 { |
| 6426 | if self.text_input_drag_active { |
| 6427 | let pointer_state = self.pointer_info.state; |
no test coverage detected