Capslock: Key::CapsLock-Event und heuristischer caps_lock()-Zustand

(cherry picked from commit 0df016d)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
irrlicht
2026-09-30 15:18:08 +02:00
co-authored by Claude Opus 5.5
parent 2d81471820
commit a120183f3b
2 changed files with 34 additions and 5 deletions
+1
View File
@@ -35,6 +35,7 @@ fn main() {
while let Some(ev) = p.poll_event() {
match ev {
Event::Key { key: Key::Escape, pressed: true, .. } => p.request_close(),
Event::Key { key: Key::CapsLock, pressed: true, .. } => eprintln!("CapsLock, Zustand: {:?}", p.caps_lock()),
Event::MouseMove { x, y } => mouse = (x, y),
Event::MouseBtn { button: MouseButton::Left, pressed } => paint = pressed,
_ => {}
+33 -5
View File
@@ -11,7 +11,7 @@ use winit::event::{
DeviceEvent, DeviceId, ElementState, KeyEvent, MouseButton as WinitMouseButton, WindowEvent,
};
use winit::event_loop::{ActiveEventLoop, EventLoop};
use winit::keyboard::{KeyCode, PhysicalKey};
use winit::keyboard::{KeyCode, ModifiersState, PhysicalKey};
use winit::platform::pump_events::EventLoopExtPumpEvents;
use winit::window::{CursorGrabMode, Window, WindowAttributes, WindowId};
@@ -55,7 +55,7 @@ pub enum Key {
Num0, Num1, Num2, Num3, Num4,
Num5, Num6, Num7, Num8, Num9,
Up, Down, Left, Right,
Space, Enter, Escape, Tab, Backspace,
Space, Enter, Escape, Tab, Backspace, CapsLock,
LShift, RShift, LCtrl, RCtrl, LAlt, RAlt,
F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12,
}
@@ -119,6 +119,8 @@ pub struct Platform {
// Mode-Wechsel/erstem Frame, damit ein Cursor-Sprung keinen Riesen-Delta erzeugt.
last_cursor_pos: Option<(f64, f64)>,
mouse_delta: (f32, f32),
modifiers: ModifiersState,
caps_lock: Option<bool>,
}
impl Platform {
@@ -247,6 +249,8 @@ impl Platform {
mouse_capture: cfg.mouse_capture,
last_cursor_pos: None,
mouse_delta: (0.0, 0.0),
modifiers: ModifiersState::empty(),
caps_lock: None,
};
platform.apply_cursor_mode();
platform
@@ -286,6 +290,13 @@ impl Platform {
std::mem::replace(&mut self.mouse_delta, (0.0, 0.0))
}
/// Capslock-Zustand, soweit bekannt. winit liefert ihn nicht direkt, daher
/// abgeleitet: `CapsLock`-Druck toggelt, getippte Buchstaben ohne Modifier
/// korrigieren (Groß → an, klein → aus). `None` bis zum ersten Buchstaben.
/// Auf macOS meldet winit 0.30 keine `CapsLock`-Key-Events — dort zählen
/// nur die Buchstaben.
pub fn caps_lock(&self) -> Option<bool> { self.caps_lock }
pub fn should_close(&self) -> bool { self.close_requested }
pub fn request_close(&mut self) { self.close_requested = true; }
@@ -293,13 +304,13 @@ impl Platform {
// Felder destructuren, um disjoint &mut-Borrows in den Handler zu reichen.
let Self {
event_loop, event_queue, close_requested, last_cursor_pos, mouse_delta,
surface, device, config, params, params_buf, queue, content_rect,
modifiers, caps_lock, surface, device, config, params, params_buf, queue, content_rect,
aspect_ratio, framebuffer_size, mouse_capture, ..
} = self;
let mut handler = Handler {
event_queue, close_requested, last_cursor_pos, mouse_delta,
surface, device, config, params, params_buf, queue, content_rect,
modifiers, caps_lock, surface, device, config, params, params_buf, queue, content_rect,
aspect_ratio: *aspect_ratio,
framebuffer_size: *framebuffer_size,
mouse_capture: *mouse_capture,
@@ -423,6 +434,8 @@ struct Handler<'a> {
close_requested: &'a mut bool,
last_cursor_pos: &'a mut Option<(f64, f64)>,
mouse_delta: &'a mut (f32, f32),
modifiers: &'a mut ModifiersState,
caps_lock: &'a mut Option<bool>,
surface: &'a wgpu::Surface<'static>,
device: &'a wgpu::Device,
config: &'a mut wgpu::SurfaceConfiguration,
@@ -458,10 +471,25 @@ impl<'a> ApplicationHandler for Handler<'a> {
*self.close_requested = true;
self.event_queue.push_back(Event::CloseRequested);
}
WindowEvent::ModifiersChanged(m) => *self.modifiers = m.state(),
WindowEvent::KeyboardInput { event: KeyEvent { physical_key, state, repeat, text, .. }, .. } => {
if let PhysicalKey::Code(code) = physical_key
&& let Some(key) = from_winit_keycode(code)
{
if key == Key::CapsLock && state == ElementState::Pressed && !repeat
&& let Some(on) = self.caps_lock
{
*on = !*on;
}
// Buchstabe ohne Modifier: Groß/klein verrät den Capslock-Zustand.
// Nur Tasten A–Z und Zeichen mit Groß/Kleinschreibung (Layout-unabhängig).
if state == ElementState::Pressed && self.modifiers.is_empty()
&& (Key::A as u8..=Key::Z as u8).contains(&(key as u8))
&& let Some(c) = text.as_ref().and_then(|t| t.chars().next())
&& (c.is_uppercase() || c.is_lowercase())
{
*self.caps_lock = Some(c.is_uppercase());
}
self.event_queue.push_back(Event::Key {
key,
pressed: state == ElementState::Pressed,
@@ -564,7 +592,7 @@ fn from_winit_keycode(k: KeyCode) -> Option<Key> {
K::ArrowUp => Key::Up, K::ArrowDown => Key::Down,
K::ArrowLeft => Key::Left, K::ArrowRight => Key::Right,
K::Space => Key::Space, K::Enter => Key::Enter, K::Escape => Key::Escape,
K::Tab => Key::Tab, K::Backspace => Key::Backspace,
K::Tab => Key::Tab, K::Backspace => Key::Backspace, K::CapsLock => Key::CapsLock,
K::ShiftLeft => Key::LShift, K::ShiftRight => Key::RShift,
K::ControlLeft => Key::LCtrl, K::ControlRight => Key::RCtrl,
K::AltLeft => Key::LAlt, K::AltRight => Key::RAlt,