mirror of
https://github.com/italicsjenga/winit-sonoma-fix.git
synced 2024-12-24 06:11:30 +11:00
Add key repetition for the wayland backend (#628)
* Add key repetition for the wayland backend * Upgrade smithay-client-toolkit to 0.3.0
This commit is contained in:
parent
1c795c3f1c
commit
e4e53fe315
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
- On macOS, fix `<C-Tab>` so applications receive the event.
|
- On macOS, fix `<C-Tab>` so applications receive the event.
|
||||||
- On macOS, fix `<Cmd-{key}>` so applications receive the event.
|
- On macOS, fix `<Cmd-{key}>` so applications receive the event.
|
||||||
|
- On Wayland, key press events will now be repeated.
|
||||||
|
|
||||||
# Version 0.17.1 (2018-08-05)
|
# Version 0.17.1 (2018-08-05)
|
||||||
|
|
||||||
|
|
|
@ -55,7 +55,7 @@ features = [
|
||||||
|
|
||||||
[target.'cfg(any(target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "openbsd", target_os = "netbsd"))'.dependencies]
|
[target.'cfg(any(target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "openbsd", target_os = "netbsd"))'.dependencies]
|
||||||
wayland-client = { version = "0.20.10", features = [ "dlopen", "egl", "cursor"] }
|
wayland-client = { version = "0.20.10", features = [ "dlopen", "egl", "cursor"] }
|
||||||
smithay-client-toolkit = "0.2.6"
|
smithay-client-toolkit = "0.3.0"
|
||||||
x11-dl = "2.18.3"
|
x11-dl = "2.18.3"
|
||||||
parking_lot = "0.6"
|
parking_lot = "0.6"
|
||||||
percent-encoding = "1.0"
|
percent-encoding = "1.0"
|
||||||
|
|
|
@ -1,20 +1,21 @@
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::sync::{Arc, Mutex, Weak};
|
|
||||||
use std::sync::atomic::{AtomicBool, Ordering};
|
use std::sync::atomic::{AtomicBool, Ordering};
|
||||||
|
use std::sync::{Arc, Mutex, Weak};
|
||||||
|
|
||||||
use {ControlFlow, EventsLoopClosed, PhysicalPosition, PhysicalSize};
|
use {ControlFlow, EventsLoopClosed, PhysicalPosition, PhysicalSize};
|
||||||
|
|
||||||
use super::WindowId;
|
|
||||||
use super::window::WindowStore;
|
use super::window::WindowStore;
|
||||||
|
use super::WindowId;
|
||||||
|
|
||||||
use sctk::Environment;
|
|
||||||
use sctk::output::OutputMgr;
|
use sctk::output::OutputMgr;
|
||||||
use sctk::reexports::client::{Display, EventQueue, GlobalEvent, Proxy, ConnectError};
|
|
||||||
use sctk::reexports::client::commons::Implementation;
|
use sctk::reexports::client::commons::Implementation;
|
||||||
use sctk::reexports::client::protocol::{wl_keyboard, wl_output, wl_pointer, wl_registry, wl_seat,
|
use sctk::reexports::client::protocol::{
|
||||||
wl_touch};
|
wl_keyboard, wl_output, wl_pointer, wl_registry, wl_seat, wl_touch,
|
||||||
|
};
|
||||||
|
use sctk::reexports::client::{ConnectError, Display, EventQueue, GlobalEvent, Proxy};
|
||||||
|
use sctk::Environment;
|
||||||
|
|
||||||
use sctk::reexports::client::protocol::wl_display::RequestsTrait as DisplayRequests;
|
use sctk::reexports::client::protocol::wl_display::RequestsTrait as DisplayRequests;
|
||||||
|
|
||||||
|
@ -104,6 +105,8 @@ impl EventsLoop {
|
||||||
pub fn new() -> Result<EventsLoop, ConnectError> {
|
pub fn new() -> Result<EventsLoop, ConnectError> {
|
||||||
let (display, mut event_queue) = Display::connect_to_env()?;
|
let (display, mut event_queue) = Display::connect_to_env()?;
|
||||||
|
|
||||||
|
let display = Arc::new(display);
|
||||||
|
let pending_wakeup = Arc::new(AtomicBool::new(false));
|
||||||
let sink = Arc::new(Mutex::new(EventsLoopSink::new()));
|
let sink = Arc::new(Mutex::new(EventsLoopSink::new()));
|
||||||
let store = Arc::new(Mutex::new(WindowStore::new()));
|
let store = Arc::new(Mutex::new(WindowStore::new()));
|
||||||
let seats = Arc::new(Mutex::new(Vec::new()));
|
let seats = Arc::new(Mutex::new(Vec::new()));
|
||||||
|
@ -115,18 +118,22 @@ impl EventsLoop {
|
||||||
sink: sink.clone(),
|
sink: sink.clone(),
|
||||||
store: store.clone(),
|
store: store.clone(),
|
||||||
seats: seats.clone(),
|
seats: seats.clone(),
|
||||||
|
events_loop_proxy: EventsLoopProxy {
|
||||||
|
display: Arc::downgrade(&display),
|
||||||
|
pending_wakeup: Arc::downgrade(&pending_wakeup),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
).unwrap();
|
).unwrap();
|
||||||
|
|
||||||
Ok(EventsLoop {
|
Ok(EventsLoop {
|
||||||
display: Arc::new(display),
|
display,
|
||||||
evq: RefCell::new(event_queue),
|
evq: RefCell::new(event_queue),
|
||||||
sink: sink,
|
sink,
|
||||||
pending_wakeup: Arc::new(AtomicBool::new(false)),
|
pending_wakeup,
|
||||||
store: store,
|
store,
|
||||||
env: env,
|
env,
|
||||||
cleanup_needed: Arc::new(Mutex::new(false)),
|
cleanup_needed: Arc::new(Mutex::new(false)),
|
||||||
seats: seats,
|
seats,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -266,6 +273,7 @@ struct SeatManager {
|
||||||
sink: Arc<Mutex<EventsLoopSink>>,
|
sink: Arc<Mutex<EventsLoopSink>>,
|
||||||
store: Arc<Mutex<WindowStore>>,
|
store: Arc<Mutex<WindowStore>>,
|
||||||
seats: Arc<Mutex<Vec<(u32, Proxy<wl_seat::WlSeat>)>>>,
|
seats: Arc<Mutex<Vec<(u32, Proxy<wl_seat::WlSeat>)>>>,
|
||||||
|
events_loop_proxy: EventsLoopProxy,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Implementation<Proxy<wl_registry::WlRegistry>, GlobalEvent> for SeatManager {
|
impl Implementation<Proxy<wl_registry::WlRegistry>, GlobalEvent> for SeatManager {
|
||||||
|
@ -289,6 +297,7 @@ impl Implementation<Proxy<wl_registry::WlRegistry>, GlobalEvent> for SeatManager
|
||||||
pointer: None,
|
pointer: None,
|
||||||
keyboard: None,
|
keyboard: None,
|
||||||
touch: None,
|
touch: None,
|
||||||
|
events_loop_proxy: self.events_loop_proxy.clone(),
|
||||||
});
|
});
|
||||||
self.store.lock().unwrap().new_seat(&seat);
|
self.store.lock().unwrap().new_seat(&seat);
|
||||||
self.seats.lock().unwrap().push((id, seat));
|
self.seats.lock().unwrap().push((id, seat));
|
||||||
|
@ -313,6 +322,7 @@ struct SeatData {
|
||||||
pointer: Option<Proxy<wl_pointer::WlPointer>>,
|
pointer: Option<Proxy<wl_pointer::WlPointer>>,
|
||||||
keyboard: Option<Proxy<wl_keyboard::WlKeyboard>>,
|
keyboard: Option<Proxy<wl_keyboard::WlKeyboard>>,
|
||||||
touch: Option<Proxy<wl_touch::WlTouch>>,
|
touch: Option<Proxy<wl_touch::WlTouch>>,
|
||||||
|
events_loop_proxy: EventsLoopProxy,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Implementation<Proxy<wl_seat::WlSeat>, wl_seat::Event> for SeatData {
|
impl Implementation<Proxy<wl_seat::WlSeat>, wl_seat::Event> for SeatData {
|
||||||
|
@ -343,6 +353,7 @@ impl Implementation<Proxy<wl_seat::WlSeat>, wl_seat::Event> for SeatData {
|
||||||
self.keyboard = Some(super::keyboard::init_keyboard(
|
self.keyboard = Some(super::keyboard::init_keyboard(
|
||||||
seat.get_keyboard().unwrap(),
|
seat.get_keyboard().unwrap(),
|
||||||
self.sink.clone(),
|
self.sink.clone(),
|
||||||
|
self.events_loop_proxy.clone(),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
// destroy keyboard if applicable
|
// destroy keyboard if applicable
|
||||||
|
|
|
@ -1,77 +1,110 @@
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
use {ElementState, KeyboardInput, ModifiersState, VirtualKeyCode, WindowEvent};
|
use super::{make_wid, DeviceId, EventsLoopProxy, EventsLoopSink};
|
||||||
|
use sctk::keyboard::{
|
||||||
use super::{make_wid, DeviceId, EventsLoopSink};
|
self, map_keyboard_auto_with_repeat, Event as KbEvent, KeyRepeatEvent, KeyRepeatKind,
|
||||||
use sctk::keyboard::{self, map_keyboard_auto, Event as KbEvent};
|
};
|
||||||
use sctk::reexports::client::{NewProxy, Proxy};
|
|
||||||
use sctk::reexports::client::protocol::wl_keyboard;
|
use sctk::reexports::client::protocol::wl_keyboard;
|
||||||
|
use sctk::reexports::client::{NewProxy, Proxy};
|
||||||
|
use {ElementState, KeyboardInput, ModifiersState, VirtualKeyCode, WindowEvent};
|
||||||
|
|
||||||
pub fn init_keyboard(
|
pub fn init_keyboard(
|
||||||
keyboard: NewProxy<wl_keyboard::WlKeyboard>,
|
keyboard: NewProxy<wl_keyboard::WlKeyboard>,
|
||||||
sink: Arc<Mutex<EventsLoopSink>>,
|
sink: Arc<Mutex<EventsLoopSink>>,
|
||||||
|
events_loop_proxy: EventsLoopProxy,
|
||||||
) -> Proxy<wl_keyboard::WlKeyboard> {
|
) -> Proxy<wl_keyboard::WlKeyboard> {
|
||||||
// { variables to be captured by the closure
|
// { variables to be captured by the closures
|
||||||
let mut target = None;
|
let target = Arc::new(Mutex::new(None));
|
||||||
let my_sink = sink.clone();
|
let my_sink = sink.clone();
|
||||||
|
let repeat_sink = sink.clone();
|
||||||
|
let repeat_target = target.clone();
|
||||||
// }
|
// }
|
||||||
let ret = map_keyboard_auto(keyboard, move |evt: KbEvent, _| match evt {
|
let ret = map_keyboard_auto_with_repeat(
|
||||||
KbEvent::Enter { surface, .. } => {
|
keyboard,
|
||||||
let wid = make_wid(&surface);
|
KeyRepeatKind::System,
|
||||||
my_sink
|
move |evt: KbEvent, _| match evt {
|
||||||
.lock()
|
KbEvent::Enter { surface, .. } => {
|
||||||
.unwrap()
|
let wid = make_wid(&surface);
|
||||||
.send_event(WindowEvent::Focused(true), wid);
|
my_sink
|
||||||
target = Some(wid);
|
.lock()
|
||||||
}
|
.unwrap()
|
||||||
KbEvent::Leave { surface, .. } => {
|
.send_event(WindowEvent::Focused(true), wid);
|
||||||
let wid = make_wid(&surface);
|
*target.lock().unwrap() = Some(wid);
|
||||||
my_sink
|
}
|
||||||
.lock()
|
KbEvent::Leave { surface, .. } => {
|
||||||
.unwrap()
|
let wid = make_wid(&surface);
|
||||||
.send_event(WindowEvent::Focused(false), wid);
|
my_sink
|
||||||
target = None;
|
.lock()
|
||||||
}
|
.unwrap()
|
||||||
KbEvent::Key {
|
.send_event(WindowEvent::Focused(false), wid);
|
||||||
modifiers,
|
*target.lock().unwrap() = None;
|
||||||
rawkey,
|
}
|
||||||
keysym,
|
KbEvent::Key {
|
||||||
state,
|
modifiers,
|
||||||
utf8,
|
rawkey,
|
||||||
..
|
keysym,
|
||||||
} => {
|
state,
|
||||||
if let Some(wid) = target {
|
utf8,
|
||||||
let state = match state {
|
..
|
||||||
wl_keyboard::KeyState::Pressed => ElementState::Pressed,
|
} => {
|
||||||
wl_keyboard::KeyState::Released => ElementState::Released,
|
if let Some(wid) = *target.lock().unwrap() {
|
||||||
};
|
let state = match state {
|
||||||
let vkcode = key_to_vkey(rawkey, keysym);
|
wl_keyboard::KeyState::Pressed => ElementState::Pressed,
|
||||||
let mut guard = my_sink.lock().unwrap();
|
wl_keyboard::KeyState::Released => ElementState::Released,
|
||||||
|
};
|
||||||
|
let vkcode = key_to_vkey(rawkey, keysym);
|
||||||
|
let mut guard = my_sink.lock().unwrap();
|
||||||
|
guard.send_event(
|
||||||
|
WindowEvent::KeyboardInput {
|
||||||
|
device_id: ::DeviceId(::platform::DeviceId::Wayland(DeviceId)),
|
||||||
|
input: KeyboardInput {
|
||||||
|
state: state,
|
||||||
|
scancode: rawkey,
|
||||||
|
virtual_keycode: vkcode,
|
||||||
|
modifiers: modifiers.into(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
wid,
|
||||||
|
);
|
||||||
|
// send char event only on key press, not release
|
||||||
|
if let ElementState::Released = state {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if let Some(txt) = utf8 {
|
||||||
|
for chr in txt.chars() {
|
||||||
|
guard.send_event(WindowEvent::ReceivedCharacter(chr), wid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
KbEvent::RepeatInfo { .. } => { /* Handled by smithay client toolkit */ }
|
||||||
|
},
|
||||||
|
move |repeat_event: KeyRepeatEvent, _| {
|
||||||
|
if let Some(wid) = *repeat_target.lock().unwrap() {
|
||||||
|
let state = ElementState::Pressed;
|
||||||
|
let vkcode = key_to_vkey(repeat_event.rawkey, repeat_event.keysym);
|
||||||
|
let mut guard = repeat_sink.lock().unwrap();
|
||||||
guard.send_event(
|
guard.send_event(
|
||||||
WindowEvent::KeyboardInput {
|
WindowEvent::KeyboardInput {
|
||||||
device_id: ::DeviceId(::platform::DeviceId::Wayland(DeviceId)),
|
device_id: ::DeviceId(::platform::DeviceId::Wayland(DeviceId)),
|
||||||
input: KeyboardInput {
|
input: KeyboardInput {
|
||||||
state: state,
|
state: state,
|
||||||
scancode: rawkey,
|
scancode: repeat_event.rawkey,
|
||||||
virtual_keycode: vkcode,
|
virtual_keycode: vkcode,
|
||||||
modifiers: modifiers.into(),
|
modifiers: repeat_event.modifiers.into(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
wid,
|
wid,
|
||||||
);
|
);
|
||||||
// send char event only on key press, not release
|
if let Some(txt) = repeat_event.utf8 {
|
||||||
if let ElementState::Released = state {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if let Some(txt) = utf8 {
|
|
||||||
for chr in txt.chars() {
|
for chr in txt.chars() {
|
||||||
guard.send_event(WindowEvent::ReceivedCharacter(chr), wid);
|
guard.send_event(WindowEvent::ReceivedCharacter(chr), wid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
events_loop_proxy.wakeup().unwrap();
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
KbEvent::RepeatInfo { .. } => { /* TODO: handle repeat info */ }
|
);
|
||||||
});
|
|
||||||
|
|
||||||
match ret {
|
match ret {
|
||||||
Ok(keyboard) => keyboard,
|
Ok(keyboard) => keyboard,
|
||||||
|
|
Loading…
Reference in a new issue