winit/platform_impl/linux/x11/util/
input.rs
1use std::{slice, str};
2use x11rb::protocol::xinput::{self, ConnectionExt as _};
3use x11rb::protocol::xkb;
4
5use super::*;
6
7pub const VIRTUAL_CORE_POINTER: u16 = 2;
8pub const VIRTUAL_CORE_KEYBOARD: u16 = 3;
9
10const TEXT_BUFFER_SIZE: usize = 1024;
14
15impl XConnection {
16 pub fn select_xinput_events(
17 &self,
18 window: xproto::Window,
19 device_id: u16,
20 mask: xinput::XIEventMask,
21 ) -> Result<VoidCookie<'_>, X11Error> {
22 self.xcb_connection()
23 .xinput_xi_select_events(window, &[xinput::EventMask {
24 deviceid: device_id,
25 mask: vec![mask],
26 }])
27 .map_err(Into::into)
28 }
29
30 pub fn select_xkb_events(
31 &self,
32 device_id: xkb::DeviceSpec,
33 mask: xkb::EventType,
34 ) -> Result<bool, X11Error> {
35 let mask = u16::from(mask) as _;
36 let status =
37 unsafe { (self.xlib.XkbSelectEvents)(self.display, device_id as _, mask, mask) };
38
39 if status == ffi::True {
40 self.flush_requests()?;
41 Ok(true)
42 } else {
43 tracing::error!("Could not select XKB events: The XKB extension is not initialized!");
44 Ok(false)
45 }
46 }
47
48 pub fn query_pointer(
49 &self,
50 window: xproto::Window,
51 device_id: u16,
52 ) -> Result<xinput::XIQueryPointerReply, X11Error> {
53 self.xcb_connection()
54 .xinput_xi_query_pointer(window, device_id)?
55 .reply()
56 .map_err(Into::into)
57 }
58
59 fn lookup_utf8_inner(
60 &self,
61 ic: ffi::XIC,
62 key_event: &mut ffi::XKeyEvent,
63 buffer: *mut u8,
64 size: usize,
65 ) -> (ffi::KeySym, ffi::Status, c_int) {
66 let mut keysym: ffi::KeySym = 0;
67 let mut status: ffi::Status = 0;
68 let count = unsafe {
69 (self.xlib.Xutf8LookupString)(
70 ic,
71 key_event,
72 buffer as *mut c_char,
73 size as c_int,
74 &mut keysym,
75 &mut status,
76 )
77 };
78 (keysym, status, count)
79 }
80
81 pub fn lookup_utf8(&self, ic: ffi::XIC, key_event: &mut ffi::XKeyEvent) -> String {
82 let mut buffer: [MaybeUninit<u8>; TEXT_BUFFER_SIZE] =
85 unsafe { MaybeUninit::uninit().assume_init() };
86 let mut vec;
88
89 let (_, status, count) =
90 self.lookup_utf8_inner(ic, key_event, buffer.as_mut_ptr() as *mut u8, buffer.len());
91
92 let bytes = if status == ffi::XBufferOverflow {
93 vec = Vec::with_capacity(count as usize);
94 let (_, _, new_count) =
95 self.lookup_utf8_inner(ic, key_event, vec.as_mut_ptr(), vec.capacity());
96 debug_assert_eq!(count, new_count);
97
98 unsafe { vec.set_len(count as usize) };
99 &vec[..count as usize]
100 } else {
101 unsafe { slice::from_raw_parts(buffer.as_ptr() as *const u8, count as usize) }
102 };
103
104 str::from_utf8(bytes).unwrap_or("").to_string()
105 }
106}