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