mirror of
https://github.com/italicsjenga/rust_minifb.git
synced 2024-12-23 19:31:30 +11:00
Memory-map the keymap FD on Wayland to fix EOF error (#278)
wlroots based compositors reuse the same FD for keymap, so after a first read is done, the file is seeked to the end and the next read fails, causing the following error: thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Error { kind: UnexpectedEof, message: "failed to fill whole buffer" }' The Wayland documentation says the FD "can be memory-mapped to provide a keyboard mapping description" and then "From version 7 onwards, the fd must be mapped with MAP_PRIVATE by the recipient, as MAP_SHARED may fail." Although it is not very clear, it probably means that the FD must be memory-mapped.
This commit is contained in:
parent
4962afd3f5
commit
344a1997c7
|
@ -30,9 +30,9 @@ use xkb::keymap::Keymap;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::ffi::c_void;
|
use std::ffi::c_void;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::{self, Read, Seek, SeekFrom, Write};
|
use std::io::{self, Seek, SeekFrom, Write};
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::os::unix::io::{AsRawFd, FromRawFd, RawFd};
|
use std::os::unix::io::{AsRawFd, RawFd};
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::slice;
|
use std::slice;
|
||||||
use std::sync::mpsc;
|
use std::sync::mpsc;
|
||||||
|
@ -1073,20 +1073,29 @@ impl Window {
|
||||||
match keymap {
|
match keymap {
|
||||||
KeymapFormat::XkbV1 => {
|
KeymapFormat::XkbV1 => {
|
||||||
unsafe {
|
unsafe {
|
||||||
// Read fd content into Vec
|
// The file descriptor must be memory-mapped (with MAP_PRIVATE).
|
||||||
let mut file = File::from_raw_fd(fd);
|
let addr = libc::mmap(
|
||||||
let mut v = Vec::with_capacity(len as usize);
|
std::ptr::null_mut(),
|
||||||
v.set_len(len as usize);
|
len as usize,
|
||||||
file.read_exact(&mut v)?;
|
libc::PROT_READ,
|
||||||
|
libc::MAP_PRIVATE,
|
||||||
|
fd,
|
||||||
|
0,
|
||||||
|
);
|
||||||
|
if addr == libc::MAP_FAILED {
|
||||||
|
return Err(std::io::Error::last_os_error());
|
||||||
|
}
|
||||||
|
|
||||||
let ctx = xkbcommon_sys::xkb_context_new(0);
|
let ctx = xkbcommon_sys::xkb_context_new(0);
|
||||||
let kb_map_ptr = xkbcommon_sys::xkb_keymap_new_from_string(
|
let kb_map_ptr = xkbcommon_sys::xkb_keymap_new_from_string(
|
||||||
ctx,
|
ctx,
|
||||||
v.as_ptr() as *const _ as *const std::os::raw::c_char,
|
addr as *const i8,
|
||||||
xkbcommon_sys::xkb_keymap_format::XKB_KEYMAP_FORMAT_TEXT_V1,
|
xkbcommon_sys::xkb_keymap_format::XKB_KEYMAP_FORMAT_TEXT_V1,
|
||||||
0,
|
0,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
libc::munmap(addr, len as usize);
|
||||||
|
|
||||||
// Wrap keymap
|
// Wrap keymap
|
||||||
Ok(Keymap::from_ptr(kb_map_ptr as *mut _ as *mut c_void))
|
Ok(Keymap::from_ptr(kb_map_ptr as *mut _ as *mut c_void))
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue