Linux/x11 input handling (#7811)

Implements the basics of keyboard and mouse handling.
Some keys will need special treatment, like Backspace/Delete. In this
PR, all keys are treated as append-only. Leaving this for a follow-up.

I used @gabydd 's branch as a reference (thank you!) as well as
https://github.com/xkbcommon/libxkbcommon/blob/master/doc/quick-guide.md
For future work, I'll also use
https://github.com/xkbcommon/libxkbcommon/blob/master/tools/interactive-x11.c

All commits are separately compileable and reviewable.

Release Notes:
- N/A

---------

Co-authored-by: Mikayla Maki <mikayla@zed.dev>
This commit is contained in:
Dzmitry Malyshau 2024-02-15 11:58:47 -08:00 committed by GitHub
parent aa319ccfd0
commit a41fb29e01
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
15 changed files with 253 additions and 53 deletions

View file

@ -49,8 +49,8 @@ pub(crate) struct LinuxPlatformInner {
}
pub(crate) struct LinuxPlatform {
client: Arc<dyn Client>,
inner: Arc<LinuxPlatformInner>,
client: Rc<dyn Client>,
inner: Rc<LinuxPlatformInner>,
}
pub(crate) struct LinuxPlatformState {
@ -93,7 +93,7 @@ impl LinuxPlatform {
let client_dispatcher: Arc<dyn ClientDispatcher + Send + Sync> =
Arc::new(WaylandClientDispatcher::new(&conn));
let dispatcher = Arc::new(LinuxDispatcher::new(main_sender, &client_dispatcher));
let inner = Arc::new(LinuxPlatformInner {
let inner = Rc::new(LinuxPlatformInner {
background_executor: BackgroundExecutor::new(dispatcher.clone()),
foreground_executor: ForegroundExecutor::new(dispatcher.clone()),
main_receiver,
@ -101,10 +101,10 @@ impl LinuxPlatform {
callbacks,
state,
});
let client = Arc::new(WaylandClient::new(Arc::clone(&inner), Arc::clone(&conn)));
let client = Rc::new(WaylandClient::new(Rc::clone(&inner), Arc::clone(&conn)));
Self {
client,
inner: Arc::clone(&inner),
inner: Rc::clone(&inner),
}
}
@ -115,15 +115,27 @@ impl LinuxPlatform {
callbacks: Mutex<Callbacks>,
state: Mutex<LinuxPlatformState>,
) -> Self {
let (xcb_connection, x_root_index) =
xcb::Connection::connect_with_extensions(None, &[xcb::Extension::Present], &[])
.unwrap();
let (xcb_connection, x_root_index) = xcb::Connection::connect_with_extensions(
None,
&[xcb::Extension::Present, xcb::Extension::Xkb],
&[],
)
.unwrap();
let xkb_ver = xcb_connection
.wait_for_reply(xcb_connection.send_request(&xcb::xkb::UseExtension {
wanted_major: xcb::xkb::MAJOR_VERSION as u16,
wanted_minor: xcb::xkb::MINOR_VERSION as u16,
}))
.unwrap();
assert!(xkb_ver.supported());
let atoms = XcbAtoms::intern_all(&xcb_connection).unwrap();
let xcb_connection = Arc::new(xcb_connection);
let client_dispatcher: Arc<dyn ClientDispatcher + Send + Sync> =
Arc::new(X11ClientDispatcher::new(&xcb_connection, x_root_index));
let dispatcher = Arc::new(LinuxDispatcher::new(main_sender, &client_dispatcher));
let inner = Arc::new(LinuxPlatformInner {
let inner = Rc::new(LinuxPlatformInner {
background_executor: BackgroundExecutor::new(dispatcher.clone()),
foreground_executor: ForegroundExecutor::new(dispatcher.clone()),
main_receiver,
@ -131,15 +143,15 @@ impl LinuxPlatform {
callbacks,
state,
});
let client = Arc::new(X11Client::new(
Arc::clone(&inner),
let client = Rc::new(X11Client::new(
Rc::clone(&inner),
xcb_connection,
x_root_index,
atoms,
));
Self {
client,
inner: Arc::clone(&inner),
inner: Rc::clone(&inner),
}
}
}