Skip to content

M1 Input: факты о smithay 0.7 / winit 0.30 (verified)

M1 Input: факты о smithay 0.7 / winit 0.30 (verified)

Section titled “M1 Input: факты о smithay 0.7 / winit 0.30 (verified)”

Исследование для ввода M1 (look-mode, WASD, клик-фокус). Все пути проверены по исходникам smithay 0.7.0 (/tmp/smithay07) и winit 0.30.13.

  • InputEvent::PointerMotionAbsolute — единственный мышиный источник winit-бэкенда. Абсолютные координаты окна; относительного события нет (PointerMotionEvent = UnusedEvent), winit получает relative-motion но smithay его дропает (device_event не имплементирован).
  • На краях окна события просто прекращаются — дельта насыщается нулём (rubber-band). При sens 0.003 rad/px и окне 1280px: ~±110° от центра. Это ограничение M1; M2-фикс — патч smithay на пересылку DeviceEvent::MouseMotion + set_cursor_grab(Locked).
  • Скрытие курсора: Window::set_cursor_visible(false) — НЕ останавливает события. Вызывать из Redraw-arm (там есть backend.window()), только при смене флага.
  • set_cursor_position на Wayland требует CursorGrabMode::Locked → убивает поток событий. Не использовать.
  • CursorEntered/CursorLeft smithay дропает — первый ивент после возврата может дать спайк дельты; сбрасывать last при |delta| > пол-окна.
  • Сканкоды (evdev): W=17, A=30, S=31, D=32, F=33, Space=57, CtrlL=29, ShiftL=42, ShiftR=54. key_code() = scancode + 8 (xkb). Физическая раскладка = ZQSD работает как WASD (игровая конвенция).
  • Повторы клавиш не приходят: smithay фильтрует event.repeat и is_synthetic.
  • Focus loss не синтезирует release на Wayland: при alt-tab зажатая W остаётся «нажатой». Обязательно чистить свой pressed-set на WinitEvent::Focus(false) (сейчас игнорируется).
  • Перехват WASD от клиента: FilterResult::Intercept(()) + помнить перехваченные для перехвата release (паттерн anvil suppressed_keys).
  • HoverState { hit: Option<Hit> } уже обновляется каждый Update (nihil_core::raycast::update_hits из центрального луча камеры). Hit { entity, dist, local, px }.
  • Маппинг: Hit.entity → WindowEntity(id) → Nihil.window_entities[&id] → raise + keyboard.set_focus. В look-mode ЛКМ кликает по прицелу; в pointer-mode — фолбэк на 2D element_under.
  • Вход: удержание ПКМ (button_code 0x111; самосбрасывающийся). Выход: release ПКМ, Focus(false), Escape.
  • В look-mode НЕ слать pointer.motion/frame — фокус заморожен (клиент видит стационарный курсор).
  • Чувствительность: 2.5 / window_height_px rad/px (инвариант к DPI/resize). dy — инвертировать (экран y вниз, pitch вверх).
  • Накопление дельт между Redraw (несколько событий на кадр), запись в MoverInput перед app.update(), обнуление после.

Известные ограничения M1

Section titled “Известные ограничения M1”
  • Поворот насыщается у краёв окна (~±110°) — absolute-only на Wayland-хосте. M2: патч smithay (DeviceEvent::MouseMotion → InputEvent::PointerMotion) + cursor grab.
  • Повторы клавиш у клиентов не работают в nested-режиме (smithay limitation, не наш баг).