mirror of
https://github.com/italicsjenga/winit-sonoma-fix.git
synced 2024-12-23 22:01:31 +11:00
Add keyboard modifiers to input event
Making applications track modifier keys results in unnecessary work for
consumers, it's error prone, and it turns out to have unavoidable bugs.
For example, alt-tabbing with x11 results in the alt modifier state
getting stuck.
To resolve these problems, this patch adds a Mods value to the keyboard
input event.
Based on this patch: d287fa96e3
This commit is contained in:
parent
449f7d9d90
commit
f3ccdb7aec
|
@ -13,7 +13,7 @@ fn main() {
|
||||||
|
|
||||||
events_loop.run_forever(|event| {
|
events_loop.run_forever(|event| {
|
||||||
match event {
|
match event {
|
||||||
Event::WindowEvent { event: WindowEvent::KeyboardInput(ElementState::Pressed, _, _), .. } => {
|
Event::WindowEvent { event: WindowEvent::KeyboardInput(ElementState::Pressed, _, _, _), .. } => {
|
||||||
println!("Setting cursor to \"{:?}\"", cursors[cursor_idx]);
|
println!("Setting cursor to \"{:?}\"", cursors[cursor_idx]);
|
||||||
window.set_cursor(cursors[cursor_idx]);
|
window.set_cursor(cursors[cursor_idx]);
|
||||||
if cursor_idx < cursors.len() - 1 {
|
if cursor_idx < cursors.len() - 1 {
|
||||||
|
|
|
@ -37,7 +37,7 @@ fn main() {
|
||||||
winit::Event::WindowEvent { event, .. } => {
|
winit::Event::WindowEvent { event, .. } => {
|
||||||
match event {
|
match event {
|
||||||
winit::WindowEvent::Closed => events_loop.interrupt(),
|
winit::WindowEvent::Closed => events_loop.interrupt(),
|
||||||
winit::WindowEvent::KeyboardInput(_, _, Some(winit::VirtualKeyCode::Escape)) => events_loop.interrupt(),
|
winit::WindowEvent::KeyboardInput(_, _, Some(winit::VirtualKeyCode::Escape), _) => events_loop.interrupt(),
|
||||||
_ => ()
|
_ => ()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -16,7 +16,7 @@ fn main() {
|
||||||
match event {
|
match event {
|
||||||
winit::Event::WindowEvent { event, .. } => {
|
winit::Event::WindowEvent { event, .. } => {
|
||||||
match event {
|
match event {
|
||||||
WindowEvent::KeyboardInput(ElementState::Pressed, _, _) => {
|
WindowEvent::KeyboardInput(ElementState::Pressed, _, _, _) => {
|
||||||
if grabbed {
|
if grabbed {
|
||||||
grabbed = false;
|
grabbed = false;
|
||||||
window.set_cursor_state(winit::CursorState::Normal)
|
window.set_cursor_state(winit::CursorState::Normal)
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
use {WindowEvent as Event, ElementState, MouseButton, MouseScrollDelta, TouchPhase};
|
use {WindowEvent as Event, ElementState, MouseButton, MouseScrollDelta, TouchPhase};
|
||||||
|
|
||||||
|
use events::ModifiersState;
|
||||||
|
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
|
@ -627,10 +629,12 @@ impl wl_keyboard::Handler for WaylandEnv {
|
||||||
wl_keyboard::KeyState::Released => ElementState::Released,
|
wl_keyboard::KeyState::Released => ElementState::Released,
|
||||||
};
|
};
|
||||||
let mut guard = eviter.lock().unwrap();
|
let mut guard = eviter.lock().unwrap();
|
||||||
|
// TODO implement ModifiersState
|
||||||
guard.push_back(Event::KeyboardInput(
|
guard.push_back(Event::KeyboardInput(
|
||||||
state,
|
state,
|
||||||
key as u8,
|
key as u8,
|
||||||
None
|
None,
|
||||||
|
ModifiersState::default()
|
||||||
));
|
));
|
||||||
},
|
},
|
||||||
KbdType::Plain(None) => ()
|
KbdType::Plain(None) => ()
|
||||||
|
|
|
@ -3,6 +3,8 @@ use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
use {VirtualKeyCode, ElementState, WindowEvent as Event};
|
use {VirtualKeyCode, ElementState, WindowEvent as Event};
|
||||||
|
|
||||||
|
use events::ModifiersState;
|
||||||
|
|
||||||
use super::wayland_kbd;
|
use super::wayland_kbd;
|
||||||
use wayland_client::EventQueueHandle;
|
use wayland_client::EventQueueHandle;
|
||||||
use wayland_client::protocol::wl_keyboard;
|
use wayland_client::protocol::wl_keyboard;
|
||||||
|
@ -35,7 +37,8 @@ impl wayland_kbd::Handler for KbdHandler {
|
||||||
};
|
};
|
||||||
let vkcode = key_to_vkey(rawkey, keysym);
|
let vkcode = key_to_vkey(rawkey, keysym);
|
||||||
let mut guard = eviter.lock().unwrap();
|
let mut guard = eviter.lock().unwrap();
|
||||||
guard.push_back(Event::KeyboardInput(state, rawkey as u8, vkcode));
|
// TODO implement ModifiersState
|
||||||
|
guard.push_back(Event::KeyboardInput(state, rawkey as u8, vkcode, ModifiersState::default()));
|
||||||
// send char event only on key press, not release
|
// send char event only on key press, not release
|
||||||
if let ElementState::Released = state { return }
|
if let ElementState::Released = state { return }
|
||||||
if let Some(txt) = utf8 {
|
if let Some(txt) = utf8 {
|
||||||
|
|
|
@ -8,6 +8,7 @@ use std::slice::from_raw_parts;
|
||||||
use WindowAttributes;
|
use WindowAttributes;
|
||||||
|
|
||||||
use events::WindowEvent as Event;
|
use events::WindowEvent as Event;
|
||||||
|
use events::ModifiersState;
|
||||||
|
|
||||||
use super::{events, ffi};
|
use super::{events, ffi};
|
||||||
use super::XConnection;
|
use super::XConnection;
|
||||||
|
@ -165,7 +166,7 @@ impl XInputEventHandler {
|
||||||
|
|
||||||
let vkey = events::keycode_to_element(keysym as libc::c_uint);
|
let vkey = events::keycode_to_element(keysym as libc::c_uint);
|
||||||
|
|
||||||
translated_events.push(KeyboardInput(state, event.keycode as u8, vkey));
|
translated_events.push(KeyboardInput(state, event.keycode as u8, vkey, ModifiersState::default()));
|
||||||
translated_events
|
translated_events
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,7 @@ pub enum WindowEvent {
|
||||||
Focused(bool),
|
Focused(bool),
|
||||||
|
|
||||||
/// An event from the keyboard has been received.
|
/// An event from the keyboard has been received.
|
||||||
KeyboardInput(ElementState, ScanCode, Option<VirtualKeyCode>),
|
KeyboardInput(ElementState, ScanCode, Option<VirtualKeyCode>, ModifiersState),
|
||||||
|
|
||||||
/// The cursor has moved on the window.
|
/// The cursor has moved on the window.
|
||||||
///
|
///
|
||||||
|
@ -320,3 +320,20 @@ pub enum VirtualKeyCode {
|
||||||
WebStop,
|
WebStop,
|
||||||
Yen,
|
Yen,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Represents the current state of the keyboard modifiers
|
||||||
|
///
|
||||||
|
/// Each field of this struct represents a modifier and is `true` if this modifier is active.
|
||||||
|
#[derive(Default, Debug, Clone, Copy)]
|
||||||
|
pub struct ModifiersState {
|
||||||
|
/// The "shift" key
|
||||||
|
pub shift: bool,
|
||||||
|
/// The "control" key
|
||||||
|
pub ctrl: bool,
|
||||||
|
/// The "alt" key
|
||||||
|
pub alt: bool,
|
||||||
|
/// The "logo" key
|
||||||
|
///
|
||||||
|
/// This is the "windows" key on PC and "command" key on Mac.
|
||||||
|
pub logo: bool
|
||||||
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use cocoa::{self, appkit, foundation};
|
use cocoa::{self, appkit, foundation};
|
||||||
use cocoa::appkit::{NSApplication, NSEvent, NSView, NSWindow};
|
use cocoa::appkit::{NSApplication, NSEvent, NSView, NSWindow};
|
||||||
use events::{self, ElementState, Event, MouseButton, TouchPhase, WindowEvent};
|
use events::{self, ElementState, Event, MouseButton, TouchPhase, WindowEvent, Modifiers};
|
||||||
use super::window::Window;
|
use super::window::Window;
|
||||||
use std;
|
use std;
|
||||||
|
|
||||||
|
@ -271,7 +271,7 @@ impl EventsLoop {
|
||||||
let vkey = to_virtual_key_code(NSEvent::keyCode(ns_event));
|
let vkey = to_virtual_key_code(NSEvent::keyCode(ns_event));
|
||||||
let state = ElementState::Pressed;
|
let state = ElementState::Pressed;
|
||||||
let code = NSEvent::keyCode(ns_event) as u8;
|
let code = NSEvent::keyCode(ns_event) as u8;
|
||||||
let window_event = WindowEvent::KeyboardInput(state, code, vkey);
|
let window_event = WindowEvent::KeyboardInput(state, code, vkey, ModifiersState::default());
|
||||||
events.push_back(into_event(window_event));
|
events.push_back(into_event(window_event));
|
||||||
let event = events.pop_front();
|
let event = events.pop_front();
|
||||||
self.pending_events.lock().unwrap().extend(events.into_iter());
|
self.pending_events.lock().unwrap().extend(events.into_iter());
|
||||||
|
@ -283,7 +283,7 @@ impl EventsLoop {
|
||||||
|
|
||||||
let state = ElementState::Released;
|
let state = ElementState::Released;
|
||||||
let code = NSEvent::keyCode(ns_event) as u8;
|
let code = NSEvent::keyCode(ns_event) as u8;
|
||||||
let window_event = WindowEvent::KeyboardInput(state, code, vkey);
|
let window_event = WindowEvent::KeyboardInput(state, code, vkey, ModifiersState::default());
|
||||||
Some(into_event(window_event))
|
Some(into_event(window_event))
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -298,13 +298,13 @@ impl EventsLoop {
|
||||||
if !key_pressed && NSEvent::modifierFlags(event).contains(keymask) {
|
if !key_pressed && NSEvent::modifierFlags(event).contains(keymask) {
|
||||||
let state = ElementState::Pressed;
|
let state = ElementState::Pressed;
|
||||||
let code = NSEvent::keyCode(event) as u8;
|
let code = NSEvent::keyCode(event) as u8;
|
||||||
let window_event = WindowEvent::KeyboardInput(state, code, Some(key));
|
let window_event = WindowEvent::KeyboardInput(state, code, Some(key), ModifiersState::default());
|
||||||
Some(window_event)
|
Some(window_event)
|
||||||
|
|
||||||
} else if key_pressed && !NSEvent::modifierFlags(event).contains(keymask) {
|
} else if key_pressed && !NSEvent::modifierFlags(event).contains(keymask) {
|
||||||
let state = ElementState::Released;
|
let state = ElementState::Released;
|
||||||
let code = NSEvent::keyCode(event) as u8;
|
let code = NSEvent::keyCode(event) as u8;
|
||||||
let window_event = WindowEvent::KeyboardInput(state, code, Some(key));
|
let window_event = WindowEvent::KeyboardInput(state, code, Some(key), ModifiersState::default());
|
||||||
Some(window_event)
|
Some(window_event)
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -8,6 +8,7 @@ use std::os::windows::ffi::OsStringExt;
|
||||||
|
|
||||||
use CursorState;
|
use CursorState;
|
||||||
use WindowEvent as Event;
|
use WindowEvent as Event;
|
||||||
|
use events::ModifersState;
|
||||||
use super::event;
|
use super::event;
|
||||||
use super::WindowState;
|
use super::WindowState;
|
||||||
|
|
||||||
|
@ -200,7 +201,7 @@ pub unsafe extern "system" fn callback(window: winapi::HWND, msg: winapi::UINT,
|
||||||
user32::DefWindowProcW(window, msg, wparam, lparam)
|
user32::DefWindowProcW(window, msg, wparam, lparam)
|
||||||
} else {
|
} else {
|
||||||
let (scancode, vkey) = event::vkeycode_to_element(wparam, lparam);
|
let (scancode, vkey) = event::vkeycode_to_element(wparam, lparam);
|
||||||
send_event(window, KeyboardInput(Pressed, scancode, vkey));
|
send_event(window, KeyboardInput(Pressed, scancode, vkey, ModifersState::default()));
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -209,7 +210,7 @@ pub unsafe extern "system" fn callback(window: winapi::HWND, msg: winapi::UINT,
|
||||||
use events::WindowEvent::KeyboardInput;
|
use events::WindowEvent::KeyboardInput;
|
||||||
use events::ElementState::Released;
|
use events::ElementState::Released;
|
||||||
let (scancode, vkey) = event::vkeycode_to_element(wparam, lparam);
|
let (scancode, vkey) = event::vkeycode_to_element(wparam, lparam);
|
||||||
send_event(window, KeyboardInput(Released, scancode, vkey));
|
send_event(window, KeyboardInput(Released, scancode, vkey, ModifersState::default()));
|
||||||
0
|
0
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue