1use std::cell::{Cell, RefCell};
2use std::collections::{HashMap, VecDeque};
3use std::os::raw::{c_char, c_int, c_long, c_ulong};
4use std::slice;
5use std::sync::{Arc, Mutex};
6
7use x11_dl::xinput2::{
8 self, XIDeviceEvent, XIEnterEvent, XIFocusInEvent, XIFocusOutEvent, XIHierarchyEvent,
9 XILeaveEvent, XIModifierState, XIRawEvent,
10};
11use x11_dl::xlib::{
12 self, Display as XDisplay, Window as XWindow, XAnyEvent, XClientMessageEvent, XConfigureEvent,
13 XDestroyWindowEvent, XEvent, XExposeEvent, XKeyEvent, XMapEvent, XPropertyEvent,
14 XReparentEvent, XSelectionEvent, XVisibilityEvent, XkbAnyEvent, XkbStateRec,
15};
16use x11rb::protocol::sync::{ConnectionExt, Int64};
17use x11rb::protocol::xinput;
18use x11rb::protocol::xkb::ID as XkbId;
19use x11rb::protocol::xproto::{self, ConnectionExt as _, ModMask};
20use x11rb::x11_utils::{ExtensionInformation, Serialize};
21use xkbcommon_dl::xkb_mod_mask_t;
22
23use crate::dpi::{PhysicalPosition, PhysicalSize};
24use crate::event::{
25 DeviceEvent, ElementState, Event, Ime, MouseButton, MouseScrollDelta, RawKeyEvent,
26 SurfaceSizeWriter, Touch, TouchPhase, WindowEvent,
27};
28use crate::keyboard::ModifiersState;
29use crate::platform_impl::common::xkb::{self, XkbState};
30use crate::platform_impl::platform::common::xkb::Context;
31use crate::platform_impl::platform::x11::ime::{ImeEvent, ImeEventReceiver, ImeRequest};
32use crate::platform_impl::platform::x11::ActiveEventLoop;
33use crate::platform_impl::x11::atoms::*;
34use crate::platform_impl::x11::util::cookie::GenericEventCookie;
35use crate::platform_impl::x11::{
36 mkdid, mkfid, mkwid, util, CookieResultExt, Device, DeviceId, DeviceInfo, Dnd, DndState,
37 ImeReceiver, ScrollOrientation, UnownedWindow, WindowId,
38};
39
40pub const MAX_MOD_REPLAY_LEN: usize = 32;
42
43const KEYCODE_OFFSET: u8 = 8;
45
46pub struct EventProcessor {
47 pub dnd: Dnd,
48 pub ime_receiver: ImeReceiver,
49 pub ime_event_receiver: ImeEventReceiver,
50 pub randr_event_offset: u8,
51 pub devices: RefCell<HashMap<DeviceId, Device>>,
52 pub xi2ext: ExtensionInformation,
53 pub xkbext: ExtensionInformation,
54 pub target: ActiveEventLoop,
55 pub xkb_context: Context,
56 pub num_touch: u32,
58 pub held_key_press: Option<u32>,
63 pub first_touch: Option<u32>,
64 pub active_window: Option<xproto::Window>,
66 pub modifiers: Cell<ModifiersState>,
68 pub xfiltered_modifiers: VecDeque<c_ulong>,
69 pub xmodmap: util::ModifierKeymap,
70 pub is_composing: bool,
71}
72
73impl EventProcessor {
74 pub(crate) fn process_event<F>(&mut self, xev: &mut XEvent, mut callback: F)
75 where
76 F: FnMut(&ActiveEventLoop, Event),
77 {
78 self.process_xevent(xev, &mut callback);
79
80 while let Ok(request) = self.ime_receiver.try_recv() {
82 let ime = match self.target.ime.as_mut() {
83 Some(ime) => ime,
84 None => continue,
85 };
86
87 let ime = ime.get_mut();
88 match request {
89 ImeRequest::Position(window_id, x, y) => {
90 ime.send_xim_spot(window_id, x, y);
91 },
92 ImeRequest::Allow(window_id, allowed) => {
93 ime.set_ime_allowed(window_id, allowed);
94 },
95 }
96 }
97
98 while let Ok((window, event)) = self.ime_event_receiver.try_recv() {
100 let window_id = mkwid(window as xproto::Window);
101 let event = match event {
102 ImeEvent::Enabled => WindowEvent::Ime(Ime::Enabled),
103 ImeEvent::Start => {
104 self.is_composing = true;
105 WindowEvent::Ime(Ime::Preedit("".to_owned(), None))
106 },
107 ImeEvent::Update(text, position) if self.is_composing => {
108 WindowEvent::Ime(Ime::Preedit(text, Some((position, position))))
109 },
110 ImeEvent::End => {
111 self.is_composing = false;
112 WindowEvent::Ime(Ime::Preedit(String::new(), None))
114 },
115 ImeEvent::Disabled => {
116 self.is_composing = false;
117 WindowEvent::Ime(Ime::Disabled)
118 },
119 _ => continue,
120 };
121
122 callback(&self.target, Event::WindowEvent { window_id, event });
123 }
124 }
125
126 fn filter_event(&mut self, xev: &mut XEvent) -> bool {
131 unsafe {
132 (self.target.xconn.xlib.XFilterEvent)(xev, {
133 let xev: &XAnyEvent = xev.as_ref();
134 xev.window
135 }) == xlib::True
136 }
137 }
138
139 fn process_xevent<F>(&mut self, xev: &mut XEvent, mut callback: F)
140 where
141 F: FnMut(&ActiveEventLoop, Event),
142 {
143 let event_type = xev.get_type();
144
145 if self.filter_event(xev) {
146 if event_type == xlib::KeyPress || event_type == xlib::KeyRelease {
147 let xev: &XKeyEvent = xev.as_ref();
148 if self.xmodmap.is_modifier(xev.keycode as u8) {
149 if self.xfiltered_modifiers.len() == MAX_MOD_REPLAY_LEN {
154 self.xfiltered_modifiers.pop_back();
155 }
156 self.xfiltered_modifiers.push_front(xev.serial);
157 }
158 }
159 return;
160 }
161
162 match event_type {
163 xlib::ClientMessage => self.client_message(xev.as_ref(), &mut callback),
164 xlib::SelectionNotify => self.selection_notify(xev.as_ref(), &mut callback),
165 xlib::ConfigureNotify => self.configure_notify(xev.as_ref(), &mut callback),
166 xlib::ReparentNotify => self.reparent_notify(xev.as_ref()),
167 xlib::MapNotify => self.map_notify(xev.as_ref(), &mut callback),
168 xlib::DestroyNotify => self.destroy_notify(xev.as_ref(), &mut callback),
169 xlib::PropertyNotify => self.property_notify(xev.as_ref(), &mut callback),
170 xlib::VisibilityNotify => self.visibility_notify(xev.as_ref(), &mut callback),
171 xlib::Expose => self.expose(xev.as_ref(), &mut callback),
172 ty @ xlib::KeyPress | ty @ xlib::KeyRelease => {
174 let state = if ty == xlib::KeyPress {
175 ElementState::Pressed
176 } else {
177 ElementState::Released
178 };
179
180 self.xinput_key_input(xev.as_mut(), state, &mut callback);
181 },
182 xlib::GenericEvent => {
183 let xev: GenericEventCookie =
184 match GenericEventCookie::from_event(self.target.xconn.clone(), *xev) {
185 Some(xev) if xev.extension() == self.xi2ext.major_opcode => xev,
186 _ => return,
187 };
188
189 let evtype = xev.evtype();
190
191 match evtype {
192 ty @ xinput2::XI_ButtonPress | ty @ xinput2::XI_ButtonRelease => {
193 let state = if ty == xinput2::XI_ButtonPress {
194 ElementState::Pressed
195 } else {
196 ElementState::Released
197 };
198
199 let xev: &XIDeviceEvent = unsafe { xev.as_event() };
200 self.update_mods_from_xinput2_event(
201 &xev.mods,
202 &xev.group,
203 false,
204 &mut callback,
205 );
206 self.xinput2_button_input(xev, state, &mut callback);
207 },
208 xinput2::XI_Motion => {
209 let xev: &XIDeviceEvent = unsafe { xev.as_event() };
210 self.update_mods_from_xinput2_event(
211 &xev.mods,
212 &xev.group,
213 false,
214 &mut callback,
215 );
216 self.xinput2_mouse_motion(xev, &mut callback);
217 },
218 xinput2::XI_Enter => {
219 let xev: &XIEnterEvent = unsafe { xev.as_event() };
220 self.xinput2_mouse_enter(xev, &mut callback);
221 },
222 xinput2::XI_Leave => {
223 let xev: &XILeaveEvent = unsafe { xev.as_event() };
224 self.update_mods_from_xinput2_event(
225 &xev.mods,
226 &xev.group,
227 false,
228 &mut callback,
229 );
230 self.xinput2_mouse_left(xev, &mut callback);
231 },
232 xinput2::XI_FocusIn => {
233 let xev: &XIFocusInEvent = unsafe { xev.as_event() };
234 self.xinput2_focused(xev, &mut callback);
235 },
236 xinput2::XI_FocusOut => {
237 let xev: &XIFocusOutEvent = unsafe { xev.as_event() };
238 self.xinput2_unfocused(xev, &mut callback);
239 },
240 xinput2::XI_TouchBegin | xinput2::XI_TouchUpdate | xinput2::XI_TouchEnd => {
241 let phase = match evtype {
242 xinput2::XI_TouchBegin => TouchPhase::Started,
243 xinput2::XI_TouchUpdate => TouchPhase::Moved,
244 xinput2::XI_TouchEnd => TouchPhase::Ended,
245 _ => unreachable!(),
246 };
247
248 let xev: &XIDeviceEvent = unsafe { xev.as_event() };
249 self.xinput2_touch(xev, phase, &mut callback);
250 },
251 xinput2::XI_RawButtonPress | xinput2::XI_RawButtonRelease => {
252 let state = match evtype {
253 xinput2::XI_RawButtonPress => ElementState::Pressed,
254 xinput2::XI_RawButtonRelease => ElementState::Released,
255 _ => unreachable!(),
256 };
257
258 let xev: &XIRawEvent = unsafe { xev.as_event() };
259 self.xinput2_raw_button_input(xev, state, &mut callback);
260 },
261 xinput2::XI_RawMotion => {
262 let xev: &XIRawEvent = unsafe { xev.as_event() };
263 self.xinput2_raw_mouse_motion(xev, &mut callback);
264 },
265 xinput2::XI_RawKeyPress | xinput2::XI_RawKeyRelease => {
266 let state = match evtype {
267 xinput2::XI_RawKeyPress => ElementState::Pressed,
268 xinput2::XI_RawKeyRelease => ElementState::Released,
269 _ => unreachable!(),
270 };
271
272 let xev: &xinput2::XIRawEvent = unsafe { xev.as_event() };
273 self.xinput2_raw_key_input(xev, state, &mut callback);
274 },
275
276 xinput2::XI_HierarchyChanged => {
277 let xev: &XIHierarchyEvent = unsafe { xev.as_event() };
278 self.xinput2_hierarchy_changed(xev);
279 },
280 _ => {},
281 }
282 },
283 _ => {
284 if event_type == self.xkbext.first_event as _ {
285 let xev: &XkbAnyEvent = unsafe { &*(xev as *const _ as *const XkbAnyEvent) };
286 self.xkb_event(xev, &mut callback);
287 }
288 if event_type == self.randr_event_offset as c_int {
289 self.process_dpi_change(&mut callback);
290 }
291 },
292 }
293 }
294
295 pub fn poll(&self) -> bool {
296 unsafe { (self.target.xconn.xlib.XPending)(self.target.xconn.display) != 0 }
297 }
298
299 pub unsafe fn poll_one_event(&mut self, event_ptr: *mut XEvent) -> bool {
300 unsafe extern "C" fn predicate(
307 _display: *mut XDisplay,
308 _event: *mut XEvent,
309 _arg: *mut c_char,
310 ) -> c_int {
311 1
313 }
314
315 unsafe {
316 (self.target.xconn.xlib.XCheckIfEvent)(
317 self.target.xconn.display,
318 event_ptr,
319 Some(predicate),
320 std::ptr::null_mut(),
321 ) != 0
322 }
323 }
324
325 pub fn init_device(&self, device: xinput::DeviceId) {
326 let mut devices = self.devices.borrow_mut();
327 if let Some(info) = DeviceInfo::get(&self.target.xconn, device as _) {
328 for info in info.iter() {
329 devices.insert(DeviceId(info.deviceid as _), Device::new(info));
330 }
331 }
332 }
333
334 pub fn with_window<F, Ret>(&self, window_id: xproto::Window, callback: F) -> Option<Ret>
335 where
336 F: Fn(&Arc<UnownedWindow>) -> Ret,
337 {
338 let mut deleted = false;
339 let window_id = WindowId(window_id as _);
340 let result = self
341 .target
342 .windows
343 .borrow()
344 .get(&window_id)
345 .and_then(|window| {
346 let arc = window.upgrade();
347 deleted = arc.is_none();
348 arc
349 })
350 .map(|window| callback(&window));
351
352 if deleted {
353 self.target.windows.borrow_mut().remove(&window_id);
355 }
356
357 result
358 }
359
360 fn client_message<F>(&mut self, xev: &XClientMessageEvent, mut callback: F)
361 where
362 F: FnMut(&ActiveEventLoop, Event),
363 {
364 let atoms = self.target.xconn.atoms();
365
366 let window = xev.window as xproto::Window;
367 let window_id = mkwid(window);
368
369 if xev.data.get_long(0) as xproto::Atom == self.target.wm_delete_window {
370 let event = Event::WindowEvent { window_id, event: WindowEvent::CloseRequested };
371 callback(&self.target, event);
372 return;
373 }
374
375 if xev.data.get_long(0) as xproto::Atom == self.target.net_wm_ping {
376 let client_msg = xproto::ClientMessageEvent {
377 response_type: xproto::CLIENT_MESSAGE_EVENT,
378 format: xev.format as _,
379 sequence: xev.serial as _,
380 window: self.target.root,
381 type_: xev.message_type as _,
382 data: xproto::ClientMessageData::from({
383 let [a, b, c, d, e]: [c_long; 5] = xev.data.as_longs().try_into().unwrap();
384 [a as u32, b as u32, c as u32, d as u32, e as u32]
385 }),
386 };
387
388 self.target
389 .xconn
390 .xcb_connection()
391 .send_event(
392 false,
393 self.target.root,
394 xproto::EventMask::SUBSTRUCTURE_NOTIFY
395 | xproto::EventMask::SUBSTRUCTURE_REDIRECT,
396 client_msg.serialize(),
397 )
398 .expect_then_ignore_error("Failed to send `ClientMessage` event.");
399 return;
400 }
401
402 if xev.data.get_long(0) as xproto::Atom == self.target.net_wm_sync_request {
403 let sync_counter_id = match self
404 .with_window(xev.window as xproto::Window, |window| window.sync_counter_id())
405 {
406 Some(Some(sync_counter_id)) => sync_counter_id.get(),
407 _ => return,
408 };
409
410 #[cfg(target_pointer_width = "32")]
411 let (lo, hi) =
412 (bytemuck::cast::<c_long, u32>(xev.data.get_long(2)), xev.data.get_long(3));
413
414 #[cfg(not(target_pointer_width = "32"))]
415 let (lo, hi) = (
416 (xev.data.get_long(2) & 0xffffffff) as u32,
417 bytemuck::cast::<u32, i32>((xev.data.get_long(3) & 0xffffffff) as u32),
418 );
419
420 self.target
421 .xconn
422 .xcb_connection()
423 .sync_set_counter(sync_counter_id, Int64 { lo, hi })
424 .expect_then_ignore_error("Failed to set XSync counter.");
425
426 return;
427 }
428
429 if xev.message_type == atoms[XdndEnter] as c_ulong {
430 let source_window = xev.data.get_long(0) as xproto::Window;
431 let flags = xev.data.get_long(1);
432 let version = flags >> 24;
433 self.dnd.version = Some(version);
434 let has_more_types = flags - (flags & (c_long::MAX - 1)) == 1;
435 if !has_more_types {
436 let type_list = vec![
437 xev.data.get_long(2) as xproto::Atom,
438 xev.data.get_long(3) as xproto::Atom,
439 xev.data.get_long(4) as xproto::Atom,
440 ];
441 self.dnd.type_list = Some(type_list);
442 } else if let Ok(more_types) = unsafe { self.dnd.get_type_list(source_window) } {
443 self.dnd.type_list = Some(more_types);
444 }
445 return;
446 }
447
448 if xev.message_type == atoms[XdndPosition] as c_ulong {
449 let source_window = xev.data.get_long(0) as xproto::Window;
458
459 let version = self.dnd.version.unwrap_or(5);
470
471 let accepted = if let Some(ref type_list) = self.dnd.type_list {
475 type_list.contains(&atoms[TextUriList])
476 } else {
477 false
478 };
479
480 if !accepted {
481 unsafe {
482 self.dnd
483 .send_status(window, source_window, DndState::Rejected)
484 .expect("Failed to send `XdndStatus` message.");
485 }
486 self.dnd.reset();
487 return;
488 }
489
490 self.dnd.source_window = Some(source_window);
491 if self.dnd.result.is_none() {
492 let time = if version >= 1 {
493 xev.data.get_long(3) as xproto::Timestamp
494 } else {
495 x11rb::CURRENT_TIME
497 };
498
499 self.target.xconn.set_timestamp(time);
501
502 unsafe {
504 self.dnd.convert_selection(window, time);
505 }
506 }
507
508 unsafe {
509 self.dnd
510 .send_status(window, source_window, DndState::Accepted)
511 .expect("Failed to send `XdndStatus` message.");
512 }
513 return;
514 }
515
516 if xev.message_type == atoms[XdndDrop] as c_ulong {
517 let (source_window, state) = if let Some(source_window) = self.dnd.source_window {
518 if let Some(Ok(ref path_list)) = self.dnd.result {
519 for path in path_list {
520 let event = Event::WindowEvent {
521 window_id,
522 event: WindowEvent::DroppedFile(path.clone()),
523 };
524 callback(&self.target, event);
525 }
526 }
527 (source_window, DndState::Accepted)
528 } else {
529 let source_window = xev.data.get_long(0) as xproto::Window;
532 (source_window, DndState::Rejected)
533 };
534
535 unsafe {
536 self.dnd
537 .send_finished(window, source_window, state)
538 .expect("Failed to send `XdndFinished` message.");
539 }
540
541 self.dnd.reset();
542 return;
543 }
544
545 if xev.message_type == atoms[XdndLeave] as c_ulong {
546 self.dnd.reset();
547 let event = Event::WindowEvent { window_id, event: WindowEvent::HoveredFileCancelled };
548 callback(&self.target, event);
549 }
550 }
551
552 fn selection_notify<F>(&mut self, xev: &XSelectionEvent, mut callback: F)
553 where
554 F: FnMut(&ActiveEventLoop, Event),
555 {
556 let atoms = self.target.xconn.atoms();
557
558 let window = xev.requestor as xproto::Window;
559 let window_id = mkwid(window);
560
561 self.target.xconn.set_timestamp(xev.time as xproto::Timestamp);
563
564 if xev.property != atoms[XdndSelection] as c_ulong {
565 return;
566 }
567
568 self.dnd.result = None;
570 if let Ok(mut data) = unsafe { self.dnd.read_data(window) } {
571 let parse_result = self.dnd.parse_data(&mut data);
572 if let Ok(ref path_list) = parse_result {
573 for path in path_list {
574 let event = Event::WindowEvent {
575 window_id,
576 event: WindowEvent::HoveredFile(path.clone()),
577 };
578 callback(&self.target, event);
579 }
580 }
581 self.dnd.result = Some(parse_result);
582 }
583 }
584
585 fn configure_notify<F>(&self, xev: &XConfigureEvent, mut callback: F)
586 where
587 F: FnMut(&ActiveEventLoop, Event),
588 {
589 let xwindow = xev.window as xproto::Window;
590 let window_id = mkwid(xwindow);
591
592 let window = match self.with_window(xwindow, Arc::clone) {
593 Some(window) => window,
594 None => return,
595 };
596
597 let is_synthetic = xev.send_event == xlib::True;
605
606 let new_surface_size = (xev.width as u32, xev.height as u32);
608 let new_inner_position = (xev.x, xev.y);
609
610 let (mut resized, moved) = {
611 let mut shared_state_lock = window.shared_state_lock();
612
613 let resized = util::maybe_change(&mut shared_state_lock.size, new_surface_size);
614 let moved = if is_synthetic {
615 util::maybe_change(&mut shared_state_lock.inner_position, new_inner_position)
616 } else {
617 let rel_parent = new_inner_position;
621 if util::maybe_change(&mut shared_state_lock.inner_position_rel_parent, rel_parent)
622 {
623 shared_state_lock.inner_position = None;
625 shared_state_lock.frame_extents = None;
627 }
628 false
629 };
630 (resized, moved)
631 };
632
633 let position = window.shared_state_lock().position;
634
635 let new_outer_position = if let (Some(position), false) = (position, moved) {
636 position
637 } else {
638 let mut shared_state_lock = window.shared_state_lock();
639
640 let frame_extents =
642 shared_state_lock.frame_extents.as_ref().cloned().unwrap_or_else(|| {
643 let frame_extents =
644 self.target.xconn.get_frame_extents_heuristic(xwindow, self.target.root);
645 shared_state_lock.frame_extents = Some(frame_extents.clone());
646 frame_extents
647 });
648 let outer =
649 frame_extents.inner_pos_to_outer(new_inner_position.0, new_inner_position.1);
650 shared_state_lock.position = Some(outer);
651
652 drop(shared_state_lock);
654
655 if moved {
656 callback(&self.target, Event::WindowEvent {
657 window_id,
658 event: WindowEvent::Moved(outer.into()),
659 });
660 }
661 outer
662 };
663
664 if is_synthetic {
665 let mut shared_state_lock = window.shared_state_lock();
666 let (width, height) =
670 shared_state_lock.dpi_adjusted.unwrap_or((xev.width as u32, xev.height as u32));
671
672 let last_scale_factor = shared_state_lock.last_monitor.scale_factor;
673 let new_scale_factor = {
674 let window_rect = util::AaRect::new(new_outer_position, new_surface_size);
675 let monitor = self
676 .target
677 .xconn
678 .get_monitor_for_window(Some(window_rect))
679 .expect("Failed to find monitor for window");
680
681 if monitor.is_dummy() {
682 last_scale_factor
684 } else {
685 shared_state_lock.last_monitor = monitor.clone();
686 monitor.scale_factor
687 }
688 };
689 if last_scale_factor != new_scale_factor {
690 let (new_width, new_height) = window.adjust_for_dpi(
691 last_scale_factor,
692 new_scale_factor,
693 width,
694 height,
695 &shared_state_lock,
696 );
697
698 let old_surface_size = PhysicalSize::new(width, height);
699 let new_surface_size = PhysicalSize::new(new_width, new_height);
700
701 drop(shared_state_lock);
703
704 let surface_size = Arc::new(Mutex::new(new_surface_size));
705 callback(&self.target, Event::WindowEvent {
706 window_id,
707 event: WindowEvent::ScaleFactorChanged {
708 scale_factor: new_scale_factor,
709 surface_size_writer: SurfaceSizeWriter::new(Arc::downgrade(&surface_size)),
710 },
711 });
712
713 let new_surface_size = *surface_size.lock().unwrap();
714 drop(surface_size);
715
716 if new_surface_size != old_surface_size {
717 window.request_surface_size_physical(
718 new_surface_size.width,
719 new_surface_size.height,
720 );
721 window.shared_state_lock().dpi_adjusted = Some(new_surface_size.into());
722 resized = true;
725 }
726 }
727 }
728
729 let hittest = {
732 let mut shared_state_lock = window.shared_state_lock();
733 let hittest = shared_state_lock.cursor_hittest;
734
735 if let Some(adjusted_size) = shared_state_lock.dpi_adjusted {
742 if new_surface_size == adjusted_size || !util::wm_name_is_one_of(&["Xfwm4"]) {
743 shared_state_lock.dpi_adjusted = None;
745 } else {
746 drop(shared_state_lock);
748 window.request_surface_size_physical(adjusted_size.0, adjusted_size.1);
749 }
750 }
751
752 hittest
753 };
754
755 if hittest.unwrap_or(false) {
757 let _ = window.set_cursor_hittest(true);
758 }
759
760 if resized {
761 callback(&self.target, Event::WindowEvent {
762 window_id,
763 event: WindowEvent::SurfaceResized(new_surface_size.into()),
764 });
765 }
766 }
767
768 fn reparent_notify(&self, xev: &XReparentEvent) {
774 self.target.xconn.update_cached_wm_info(self.target.root);
775
776 self.with_window(xev.window as xproto::Window, |window| {
777 window.invalidate_cached_frame_extents();
778 });
779 }
780
781 fn map_notify<F>(&self, xev: &XMapEvent, mut callback: F)
782 where
783 F: FnMut(&ActiveEventLoop, Event),
784 {
785 let window = xev.window as xproto::Window;
786 let window_id = mkwid(window);
787
788 let focus = self.with_window(window, |window| window.has_focus()).unwrap_or_default();
794 let event = Event::WindowEvent { window_id, event: WindowEvent::Focused(focus) };
795
796 callback(&self.target, event);
797 }
798
799 fn destroy_notify<F>(&self, xev: &XDestroyWindowEvent, mut callback: F)
800 where
801 F: FnMut(&ActiveEventLoop, Event),
802 {
803 let window = xev.window as xproto::Window;
804 let window_id = mkwid(window);
805
806 self.target.windows.borrow_mut().remove(&WindowId(window as _));
809
810 if let Some(ime) = self.target.ime.as_ref() {
813 ime.borrow_mut()
814 .remove_context(window as XWindow)
815 .expect("Failed to destroy input context");
816 }
817
818 callback(&self.target, Event::WindowEvent { window_id, event: WindowEvent::Destroyed });
819 }
820
821 fn property_notify<F>(&mut self, xev: &XPropertyEvent, mut callback: F)
822 where
823 F: FnMut(&ActiveEventLoop, Event),
824 {
825 let atoms = self.target.x_connection().atoms();
826 let atom = xev.atom as xproto::Atom;
827
828 if atom == xproto::Atom::from(xproto::AtomEnum::RESOURCE_MANAGER)
829 || atom == atoms[_XSETTINGS_SETTINGS]
830 {
831 self.process_dpi_change(&mut callback);
832 }
833 }
834
835 fn visibility_notify<F>(&self, xev: &XVisibilityEvent, mut callback: F)
836 where
837 F: FnMut(&ActiveEventLoop, Event),
838 {
839 let xwindow = xev.window as xproto::Window;
840
841 let event = Event::WindowEvent {
842 window_id: mkwid(xwindow),
843 event: WindowEvent::Occluded(xev.state == xlib::VisibilityFullyObscured),
844 };
845 callback(&self.target, event);
846
847 self.with_window(xwindow, |window| {
848 window.visibility_notify();
849 });
850 }
851
852 fn expose<F>(&self, xev: &XExposeEvent, mut callback: F)
853 where
854 F: FnMut(&ActiveEventLoop, Event),
855 {
856 if xev.count == 0 {
859 let window = xev.window as xproto::Window;
860 let window_id = mkwid(window);
861
862 let event = Event::WindowEvent { window_id, event: WindowEvent::RedrawRequested };
863
864 callback(&self.target, event);
865 }
866 }
867
868 fn xinput_key_input<F>(&mut self, xev: &mut XKeyEvent, state: ElementState, mut callback: F)
869 where
870 F: FnMut(&ActiveEventLoop, Event),
871 {
872 self.target.xconn.set_timestamp(xev.time as xproto::Timestamp);
874
875 let window = match self.active_window {
876 Some(window) => window,
877 None => return,
878 };
879
880 let window_id = mkwid(window);
881 let device_id = mkdid(util::VIRTUAL_CORE_KEYBOARD);
882
883 let keycode = xev.keycode as _;
884
885 let key_repeats =
896 self.xkb_context.keymap_mut().map(|k| k.key_repeats(keycode)).unwrap_or(false);
897 let repeat = if key_repeats {
898 let is_latest_held = self.held_key_press == Some(keycode);
899
900 if state == ElementState::Pressed {
901 self.held_key_press = Some(keycode);
902 is_latest_held
903 } else {
904 if is_latest_held {
908 self.held_key_press = None;
909 }
910 false
911 }
912 } else {
913 false
914 };
915
916 let replay = if let Some(position) =
920 self.xfiltered_modifiers.iter().rev().position(|&s| s == xev.serial)
921 {
922 self.xfiltered_modifiers.resize(self.xfiltered_modifiers.len() - 1 - position, 0);
925 true
926 } else {
927 false
928 };
929
930 if !replay {
932 self.update_mods_from_core_event(window_id, xev.state as u16, &mut callback);
933 }
934
935 if keycode != 0 && !self.is_composing {
936 if replay {
938 self.send_synthic_modifier_from_core(window_id, xev.state as u16, &mut callback);
939 }
940
941 if let Some(mut key_processor) = self.xkb_context.key_context() {
942 let event = key_processor.process_key_event(keycode, state, repeat);
943 let event = Event::WindowEvent {
944 window_id,
945 event: WindowEvent::KeyboardInput { device_id, event, is_synthetic: false },
946 };
947 callback(&self.target, event);
948 }
949
950 if replay {
952 self.send_modifiers(window_id, self.modifiers.get(), true, &mut callback);
953 }
954
955 return;
956 }
957
958 if let Some(ic) =
959 self.target.ime.as_ref().and_then(|ime| ime.borrow().get_context(window as XWindow))
960 {
961 let written = self.target.xconn.lookup_utf8(ic, xev);
962 if !written.is_empty() {
963 let event = Event::WindowEvent {
964 window_id,
965 event: WindowEvent::Ime(Ime::Preedit(String::new(), None)),
966 };
967 callback(&self.target, event);
968
969 let event =
970 Event::WindowEvent { window_id, event: WindowEvent::Ime(Ime::Commit(written)) };
971
972 self.is_composing = false;
973 callback(&self.target, event);
974 }
975 }
976 }
977
978 fn send_synthic_modifier_from_core<F>(
979 &mut self,
980 window_id: crate::window::WindowId,
981 state: u16,
982 mut callback: F,
983 ) where
984 F: FnMut(&ActiveEventLoop, Event),
985 {
986 let keymap = match self.xkb_context.keymap_mut() {
987 Some(keymap) => keymap,
988 None => return,
989 };
990
991 let xcb = self.target.xconn.xcb_connection().get_raw_xcb_connection();
992
993 let mut xkb_state = match XkbState::new_x11(xcb, keymap) {
996 Some(xkb_state) => xkb_state,
997 None => return,
998 };
999
1000 let mask = self.xkb_mod_mask_from_core(state);
1001 xkb_state.update_modifiers(mask, 0, 0, 0, 0, Self::core_keyboard_group(state));
1002 let mods: ModifiersState = xkb_state.modifiers().into();
1003
1004 let event =
1005 Event::WindowEvent { window_id, event: WindowEvent::ModifiersChanged(mods.into()) };
1006
1007 callback(&self.target, event);
1008 }
1009
1010 fn xinput2_button_input<F>(&self, event: &XIDeviceEvent, state: ElementState, mut callback: F)
1011 where
1012 F: FnMut(&ActiveEventLoop, Event),
1013 {
1014 let window_id = mkwid(event.event as xproto::Window);
1015 let device_id = mkdid(event.deviceid as xinput::DeviceId);
1016
1017 self.target.xconn.set_timestamp(event.time as xproto::Timestamp);
1019
1020 if (event.flags & xinput2::XIPointerEmulated) != 0 {
1022 return;
1023 }
1024
1025 let event = match event.detail as u32 {
1026 xlib::Button1 => {
1027 WindowEvent::MouseInput { device_id, state, button: MouseButton::Left }
1028 },
1029 xlib::Button2 => {
1030 WindowEvent::MouseInput { device_id, state, button: MouseButton::Middle }
1031 },
1032
1033 xlib::Button3 => {
1034 WindowEvent::MouseInput { device_id, state, button: MouseButton::Right }
1035 },
1036
1037 4..=7 => WindowEvent::MouseWheel {
1042 device_id,
1043 delta: match event.detail {
1044 4 => MouseScrollDelta::LineDelta(0.0, 1.0),
1045 5 => MouseScrollDelta::LineDelta(0.0, -1.0),
1046 6 => MouseScrollDelta::LineDelta(1.0, 0.0),
1047 7 => MouseScrollDelta::LineDelta(-1.0, 0.0),
1048 _ => unreachable!(),
1049 },
1050 phase: TouchPhase::Moved,
1051 },
1052 8 => WindowEvent::MouseInput { device_id, state, button: MouseButton::Back },
1053
1054 9 => WindowEvent::MouseInput { device_id, state, button: MouseButton::Forward },
1055 x => WindowEvent::MouseInput { device_id, state, button: MouseButton::Other(x as u16) },
1056 };
1057
1058 let event = Event::WindowEvent { window_id, event };
1059 callback(&self.target, event);
1060 }
1061
1062 fn xinput2_mouse_motion<F>(&self, event: &XIDeviceEvent, mut callback: F)
1063 where
1064 F: FnMut(&ActiveEventLoop, Event),
1065 {
1066 self.target.xconn.set_timestamp(event.time as xproto::Timestamp);
1068
1069 let device_id = mkdid(event.deviceid as xinput::DeviceId);
1070 let window = event.event as xproto::Window;
1071 let window_id = mkwid(window);
1072 let new_cursor_pos = (event.event_x, event.event_y);
1073
1074 let cursor_moved = self.with_window(window, |window| {
1075 let mut shared_state_lock = window.shared_state_lock();
1076 util::maybe_change(&mut shared_state_lock.cursor_pos, new_cursor_pos)
1077 });
1078
1079 if cursor_moved == Some(true) {
1080 let position = PhysicalPosition::new(event.event_x, event.event_y);
1081
1082 let event = Event::WindowEvent {
1083 window_id,
1084 event: WindowEvent::CursorMoved { device_id, position },
1085 };
1086 callback(&self.target, event);
1087 } else if cursor_moved.is_none() {
1088 return;
1089 }
1090
1091 let mask = unsafe {
1093 slice::from_raw_parts(event.valuators.mask, event.valuators.mask_len as usize)
1094 };
1095 let mut devices = self.devices.borrow_mut();
1096 let physical_device = match devices.get_mut(&DeviceId(event.sourceid as xinput::DeviceId)) {
1097 Some(device) => device,
1098 None => return,
1099 };
1100
1101 let mut events = Vec::new();
1102 let mut value = event.valuators.values;
1103 for i in 0..event.valuators.mask_len * 8 {
1104 if !xinput2::XIMaskIsSet(mask, i) {
1105 continue;
1106 }
1107
1108 let x = unsafe { *value };
1109
1110 if let Some(&mut (_, ref mut info)) =
1111 physical_device.scroll_axes.iter_mut().find(|&&mut (axis, _)| axis == i as _)
1112 {
1113 let delta = (x - info.position) / info.increment;
1114 info.position = x;
1115 let delta = match info.orientation {
1117 ScrollOrientation::Horizontal => {
1118 MouseScrollDelta::LineDelta(-delta as f32, 0.0)
1119 },
1120 ScrollOrientation::Vertical => MouseScrollDelta::LineDelta(0.0, -delta as f32),
1121 };
1122
1123 let event = WindowEvent::MouseWheel { device_id, delta, phase: TouchPhase::Moved };
1124 events.push(Event::WindowEvent { window_id, event });
1125 }
1126
1127 value = unsafe { value.offset(1) };
1128 }
1129
1130 for event in events {
1131 callback(&self.target, event);
1132 }
1133 }
1134
1135 fn xinput2_mouse_enter<F>(&self, event: &XIEnterEvent, mut callback: F)
1136 where
1137 F: FnMut(&ActiveEventLoop, Event),
1138 {
1139 self.target.xconn.set_timestamp(event.time as xproto::Timestamp);
1141
1142 let window = event.event as xproto::Window;
1143 let window_id = mkwid(window);
1144 let device_id = mkdid(event.deviceid as xinput::DeviceId);
1145
1146 if let Some(all_info) = DeviceInfo::get(&self.target.xconn, super::ALL_DEVICES.into()) {
1147 let mut devices = self.devices.borrow_mut();
1148 for device_info in all_info.iter() {
1149 if device_info.deviceid == event.sourceid
1153 || device_info.attachment == event.sourceid
1154 {
1155 let device_id = DeviceId(device_info.deviceid as _);
1156 if let Some(device) = devices.get_mut(&device_id) {
1157 device.reset_scroll_position(device_info);
1158 }
1159 }
1160 }
1161 }
1162
1163 if self.window_exists(window) {
1164 let position = PhysicalPosition::new(event.event_x, event.event_y);
1165
1166 let event =
1167 Event::WindowEvent { window_id, event: WindowEvent::CursorEntered { device_id } };
1168 callback(&self.target, event);
1169
1170 let event = Event::WindowEvent {
1171 window_id,
1172 event: WindowEvent::CursorMoved { device_id, position },
1173 };
1174 callback(&self.target, event);
1175 }
1176 }
1177
1178 fn xinput2_mouse_left<F>(&self, event: &XILeaveEvent, mut callback: F)
1179 where
1180 F: FnMut(&ActiveEventLoop, Event),
1181 {
1182 let window = event.event as xproto::Window;
1183
1184 self.target.xconn.set_timestamp(event.time as xproto::Timestamp);
1186
1187 if self.window_exists(window) {
1190 let event = Event::WindowEvent {
1191 window_id: mkwid(window),
1192 event: WindowEvent::CursorLeft {
1193 device_id: mkdid(event.deviceid as xinput::DeviceId),
1194 },
1195 };
1196 callback(&self.target, event);
1197 }
1198 }
1199
1200 fn xinput2_focused<F>(&mut self, xev: &XIFocusInEvent, mut callback: F)
1201 where
1202 F: FnMut(&ActiveEventLoop, Event),
1203 {
1204 let window = xev.event as xproto::Window;
1205
1206 self.target.xconn.set_timestamp(xev.time as xproto::Timestamp);
1208
1209 if let Some(ime) = self.target.ime.as_ref() {
1210 ime.borrow_mut().focus(xev.event).expect("Failed to focus input context");
1211 }
1212
1213 if self.active_window == Some(window) {
1214 return;
1215 }
1216
1217 self.active_window = Some(window);
1218
1219 self.target.update_listen_device_events(true);
1220
1221 let window_id = mkwid(window);
1222 let position = PhysicalPosition::new(xev.event_x, xev.event_y);
1223
1224 if let Some(window) = self.with_window(window, Arc::clone) {
1225 window.shared_state_lock().has_focus = true;
1226 }
1227
1228 let event = Event::WindowEvent { window_id, event: WindowEvent::Focused(true) };
1229 callback(&self.target, event);
1230
1231 Self::handle_pressed_keys(
1233 &self.target,
1234 window_id,
1235 ElementState::Pressed,
1236 &mut self.xkb_context,
1237 &mut callback,
1238 );
1239
1240 self.update_mods_from_query(window_id, &mut callback);
1241
1242 let pointer_id = self
1245 .devices
1246 .borrow()
1247 .get(&DeviceId(xev.deviceid as xinput::DeviceId))
1248 .map(|device| device.attachment)
1249 .unwrap_or(2);
1250
1251 let event = Event::WindowEvent {
1252 window_id,
1253 event: WindowEvent::CursorMoved { device_id: mkdid(pointer_id as _), position },
1254 };
1255 callback(&self.target, event);
1256 }
1257
1258 fn xinput2_unfocused<F>(&mut self, xev: &XIFocusOutEvent, mut callback: F)
1259 where
1260 F: FnMut(&ActiveEventLoop, Event),
1261 {
1262 let window = xev.event as xproto::Window;
1263
1264 self.target.xconn.set_timestamp(xev.time as xproto::Timestamp);
1266
1267 if !self.window_exists(window) {
1268 return;
1269 }
1270
1271 if let Some(ime) = self.target.ime.as_ref() {
1272 ime.borrow_mut().unfocus(xev.event).expect("Failed to unfocus input context");
1273 }
1274
1275 if self.active_window.take() == Some(window) {
1276 let window_id = mkwid(window);
1277
1278 self.target.update_listen_device_events(false);
1279
1280 if let Some(xkb_state) = self.xkb_context.state_mut() {
1282 xkb_state.update_modifiers(0, 0, 0, 0, 0, 0);
1283 let mods = xkb_state.modifiers();
1284 self.send_modifiers(window_id, mods.into(), true, &mut callback);
1285 }
1286
1287 Self::handle_pressed_keys(
1289 &self.target,
1290 window_id,
1291 ElementState::Released,
1292 &mut self.xkb_context,
1293 &mut callback,
1294 );
1295
1296 self.held_key_press = None;
1299
1300 if let Some(window) = self.with_window(window, Arc::clone) {
1301 window.shared_state_lock().has_focus = false;
1302 }
1303
1304 let event = Event::WindowEvent { window_id, event: WindowEvent::Focused(false) };
1305 callback(&self.target, event)
1306 }
1307 }
1308
1309 fn xinput2_touch<F>(&mut self, xev: &XIDeviceEvent, phase: TouchPhase, mut callback: F)
1310 where
1311 F: FnMut(&ActiveEventLoop, Event),
1312 {
1313 self.target.xconn.set_timestamp(xev.time as xproto::Timestamp);
1315
1316 let window = xev.event as xproto::Window;
1317 if self.window_exists(window) {
1318 let window_id = mkwid(window);
1319 let id = xev.detail as u32;
1320 let location = PhysicalPosition::new(xev.event_x, xev.event_y);
1321
1322 if is_first_touch(&mut self.first_touch, &mut self.num_touch, id, phase) {
1325 let event = Event::WindowEvent {
1326 window_id,
1327 event: WindowEvent::CursorMoved {
1328 device_id: mkdid(util::VIRTUAL_CORE_POINTER),
1329 position: location.cast(),
1330 },
1331 };
1332 callback(&self.target, event);
1333 }
1334
1335 let event = Event::WindowEvent {
1336 window_id,
1337 event: WindowEvent::Touch(Touch {
1338 device_id: mkdid(xev.deviceid as xinput::DeviceId),
1339 phase,
1340 location,
1341 force: None, finger_id: mkfid(id),
1343 }),
1344 };
1345 callback(&self.target, event)
1346 }
1347 }
1348
1349 fn xinput2_raw_button_input<F>(&self, xev: &XIRawEvent, state: ElementState, mut callback: F)
1350 where
1351 F: FnMut(&ActiveEventLoop, Event),
1352 {
1353 self.target.xconn.set_timestamp(xev.time as xproto::Timestamp);
1355
1356 if xev.flags & xinput2::XIPointerEmulated == 0 {
1357 let event = Event::DeviceEvent {
1358 device_id: mkdid(xev.deviceid as xinput::DeviceId),
1359 event: DeviceEvent::Button { state, button: xev.detail as u32 },
1360 };
1361 callback(&self.target, event);
1362 }
1363 }
1364
1365 fn xinput2_raw_mouse_motion<F>(&self, xev: &XIRawEvent, mut callback: F)
1366 where
1367 F: FnMut(&ActiveEventLoop, Event),
1368 {
1369 self.target.xconn.set_timestamp(xev.time as xproto::Timestamp);
1371
1372 let did = mkdid(xev.deviceid as xinput::DeviceId);
1373
1374 let mask =
1375 unsafe { slice::from_raw_parts(xev.valuators.mask, xev.valuators.mask_len as usize) };
1376 let mut value = xev.raw_values;
1377 let mut mouse_delta = util::Delta::default();
1378 let mut scroll_delta = util::Delta::default();
1379 for i in 0..xev.valuators.mask_len * 8 {
1380 if !xinput2::XIMaskIsSet(mask, i) {
1381 continue;
1382 }
1383 let x = unsafe { value.read_unaligned() };
1384
1385 match i {
1388 0 => mouse_delta.set_x(x),
1389 1 => mouse_delta.set_y(x),
1390 2 => scroll_delta.set_x(x as f32),
1391 3 => scroll_delta.set_y(x as f32),
1392 _ => {},
1393 }
1394
1395 value = unsafe { value.offset(1) };
1396 }
1397
1398 if let Some(mouse_delta) = mouse_delta.consume() {
1399 let event = Event::DeviceEvent {
1400 device_id: did,
1401 event: DeviceEvent::MouseMotion { delta: mouse_delta },
1402 };
1403 callback(&self.target, event);
1404 }
1405
1406 if let Some(scroll_delta) = scroll_delta.consume() {
1407 let event = Event::DeviceEvent {
1408 device_id: did,
1409 event: DeviceEvent::MouseWheel {
1410 delta: MouseScrollDelta::LineDelta(scroll_delta.0, scroll_delta.1),
1411 },
1412 };
1413 callback(&self.target, event);
1414 }
1415 }
1416
1417 fn xinput2_raw_key_input<F>(&mut self, xev: &XIRawEvent, state: ElementState, mut callback: F)
1418 where
1419 F: FnMut(&ActiveEventLoop, Event),
1420 {
1421 self.target.xconn.set_timestamp(xev.time as xproto::Timestamp);
1423
1424 let device_id = mkdid(xev.sourceid as xinput::DeviceId);
1425 let keycode = xev.detail as u32;
1426 if keycode < KEYCODE_OFFSET as u32 {
1427 return;
1428 }
1429 let physical_key = xkb::raw_keycode_to_physicalkey(keycode);
1430
1431 callback(&self.target, Event::DeviceEvent {
1432 device_id,
1433 event: DeviceEvent::Key(RawKeyEvent { physical_key, state }),
1434 });
1435 }
1436
1437 fn xinput2_hierarchy_changed(&mut self, xev: &XIHierarchyEvent) {
1438 self.target.xconn.set_timestamp(xev.time as xproto::Timestamp);
1440 let infos = unsafe { slice::from_raw_parts(xev.info, xev.num_info as usize) };
1441 for info in infos {
1442 if 0 != info.flags & (xinput2::XISlaveAdded | xinput2::XIMasterAdded) {
1443 self.init_device(info.deviceid as xinput::DeviceId);
1444 } else if 0 != info.flags & (xinput2::XISlaveRemoved | xinput2::XIMasterRemoved) {
1445 let mut devices = self.devices.borrow_mut();
1446 devices.remove(&DeviceId(info.deviceid as xinput::DeviceId));
1447 }
1448 }
1449 }
1450
1451 fn xkb_event<F>(&mut self, xev: &XkbAnyEvent, mut callback: F)
1452 where
1453 F: FnMut(&ActiveEventLoop, Event),
1454 {
1455 match xev.xkb_type {
1456 xlib::XkbNewKeyboardNotify => {
1457 let xev = unsafe { &*(xev as *const _ as *const xlib::XkbNewKeyboardNotifyEvent) };
1458
1459 self.target.xconn.set_timestamp(xev.time as xproto::Timestamp);
1461
1462 let keycodes_changed_flag = 0x1;
1463 let geometry_changed_flag = 0x1 << 1;
1464
1465 let keycodes_changed = util::has_flag(xev.changed, keycodes_changed_flag);
1466 let geometry_changed = util::has_flag(xev.changed, geometry_changed_flag);
1467
1468 if xev.device == self.xkb_context.core_keyboard_id
1469 && (keycodes_changed || geometry_changed)
1470 {
1471 let xcb = self.target.xconn.xcb_connection().get_raw_xcb_connection();
1472 self.xkb_context.set_keymap_from_x11(xcb);
1473 self.xmodmap.reload_from_x_connection(&self.target.xconn);
1474
1475 let window_id = match self.active_window.map(super::mkwid) {
1476 Some(window_id) => window_id,
1477 None => return,
1478 };
1479
1480 if let Some(state) = self.xkb_context.state_mut() {
1481 let mods = state.modifiers().into();
1482 self.send_modifiers(window_id, mods, true, &mut callback);
1483 }
1484 }
1485 },
1486 xlib::XkbMapNotify => {
1487 let xcb = self.target.xconn.xcb_connection().get_raw_xcb_connection();
1488 self.xkb_context.set_keymap_from_x11(xcb);
1489 self.xmodmap.reload_from_x_connection(&self.target.xconn);
1490 let window_id = match self.active_window.map(super::mkwid) {
1491 Some(window_id) => window_id,
1492 None => return,
1493 };
1494
1495 if let Some(state) = self.xkb_context.state_mut() {
1496 let mods = state.modifiers().into();
1497 self.send_modifiers(window_id, mods, true, &mut callback);
1498 }
1499 },
1500 xlib::XkbStateNotify => {
1501 let xev = unsafe { &*(xev as *const _ as *const xlib::XkbStateNotifyEvent) };
1502
1503 self.target.xconn.set_timestamp(xev.time as xproto::Timestamp);
1505
1506 if let Some(state) = self.xkb_context.state_mut() {
1507 state.update_modifiers(
1508 xev.base_mods,
1509 xev.latched_mods,
1510 xev.locked_mods,
1511 xev.base_group as u32,
1512 xev.latched_group as u32,
1513 xev.locked_group as u32,
1514 );
1515
1516 let window_id = match self.active_window.map(super::mkwid) {
1517 Some(window_id) => window_id,
1518 None => return,
1519 };
1520
1521 let mods = state.modifiers().into();
1522 self.send_modifiers(window_id, mods, true, &mut callback);
1523 }
1524 },
1525 _ => {},
1526 }
1527 }
1528
1529 pub(crate) fn update_mods_from_xinput2_event<F>(
1530 &mut self,
1531 mods: &XIModifierState,
1532 group: &XIModifierState,
1533 force: bool,
1534 mut callback: F,
1535 ) where
1536 F: FnMut(&ActiveEventLoop, Event),
1537 {
1538 if let Some(state) = self.xkb_context.state_mut() {
1539 state.update_modifiers(
1540 mods.base as u32,
1541 mods.latched as u32,
1542 mods.locked as u32,
1543 group.base as u32,
1544 group.latched as u32,
1545 group.locked as u32,
1546 );
1547
1548 let window_id = match self.active_window.map(super::mkwid) {
1551 Some(window_id) => window_id,
1552 None => return,
1553 };
1554
1555 let mods = state.modifiers();
1556 self.send_modifiers(window_id, mods.into(), force, &mut callback);
1557 }
1558 }
1559
1560 fn update_mods_from_query<F>(&mut self, window_id: crate::window::WindowId, mut callback: F)
1561 where
1562 F: FnMut(&ActiveEventLoop, Event),
1563 {
1564 let xkb_state = match self.xkb_context.state_mut() {
1565 Some(xkb_state) => xkb_state,
1566 None => return,
1567 };
1568
1569 unsafe {
1570 let mut state: XkbStateRec = std::mem::zeroed();
1571 if (self.target.xconn.xlib.XkbGetState)(
1572 self.target.xconn.display,
1573 XkbId::USE_CORE_KBD.into(),
1574 &mut state,
1575 ) == xlib::True
1576 {
1577 xkb_state.update_modifiers(
1578 state.base_mods as u32,
1579 state.latched_mods as u32,
1580 state.locked_mods as u32,
1581 state.base_group as u32,
1582 state.latched_group as u32,
1583 state.locked_group as u32,
1584 );
1585 }
1586 }
1587
1588 let mods = xkb_state.modifiers();
1589 self.send_modifiers(window_id, mods.into(), true, &mut callback)
1590 }
1591
1592 pub(crate) fn update_mods_from_core_event<F>(
1593 &mut self,
1594 window_id: crate::window::WindowId,
1595 state: u16,
1596 mut callback: F,
1597 ) where
1598 F: FnMut(&ActiveEventLoop, Event),
1599 {
1600 let xkb_mask = self.xkb_mod_mask_from_core(state);
1601 let xkb_state = match self.xkb_context.state_mut() {
1602 Some(xkb_state) => xkb_state,
1603 None => return,
1604 };
1605
1606 let mut depressed = xkb_state.depressed_modifiers() & xkb_mask;
1608 let latched = xkb_state.latched_modifiers() & xkb_mask;
1609 let locked = xkb_state.locked_modifiers() & xkb_mask;
1610 depressed |= !(depressed | latched | locked) & xkb_mask;
1612
1613 xkb_state.update_modifiers(
1614 depressed,
1615 latched,
1616 locked,
1617 0,
1618 0,
1619 Self::core_keyboard_group(state),
1620 );
1621
1622 let mods = xkb_state.modifiers();
1623 self.send_modifiers(window_id, mods.into(), false, &mut callback);
1624 }
1625
1626 pub fn core_keyboard_group(state: u16) -> u32 {
1628 ((state >> 13) & 3) as u32
1629 }
1630
1631 pub fn xkb_mod_mask_from_core(&mut self, state: u16) -> xkb_mod_mask_t {
1632 let mods_indices = match self.xkb_context.keymap_mut() {
1633 Some(keymap) => keymap.mods_indices(),
1634 None => return 0,
1635 };
1636
1637 let mut depressed = 0u32;
1639 if let Some(shift) = mods_indices.shift.filter(|_| ModMask::SHIFT.intersects(state)) {
1640 depressed |= 1 << shift;
1641 }
1642 if let Some(caps) = mods_indices.caps.filter(|_| ModMask::LOCK.intersects(state)) {
1643 depressed |= 1 << caps;
1644 }
1645 if let Some(ctrl) = mods_indices.ctrl.filter(|_| ModMask::CONTROL.intersects(state)) {
1646 depressed |= 1 << ctrl;
1647 }
1648 if let Some(alt) = mods_indices.alt.filter(|_| ModMask::M1.intersects(state)) {
1649 depressed |= 1 << alt;
1650 }
1651 if let Some(num) = mods_indices.num.filter(|_| ModMask::M2.intersects(state)) {
1652 depressed |= 1 << num;
1653 }
1654 if let Some(mod3) = mods_indices.mod3.filter(|_| ModMask::M3.intersects(state)) {
1655 depressed |= 1 << mod3;
1656 }
1657 if let Some(logo) = mods_indices.logo.filter(|_| ModMask::M4.intersects(state)) {
1658 depressed |= 1 << logo;
1659 }
1660 if let Some(mod5) = mods_indices.mod5.filter(|_| ModMask::M5.intersects(state)) {
1661 depressed |= 1 << mod5;
1662 }
1663
1664 depressed
1665 }
1666
1667 fn send_modifiers<F: FnMut(&ActiveEventLoop, Event)>(
1672 &self,
1673 window_id: crate::window::WindowId,
1674 modifiers: ModifiersState,
1675 force: bool,
1676 callback: &mut F,
1677 ) {
1678 if self.modifiers.replace(modifiers) != modifiers || force {
1681 let event = Event::WindowEvent {
1682 window_id,
1683 event: WindowEvent::ModifiersChanged(self.modifiers.get().into()),
1684 };
1685 callback(&self.target, event);
1686 }
1687 }
1688
1689 fn handle_pressed_keys<F>(
1690 target: &ActiveEventLoop,
1691 window_id: crate::window::WindowId,
1692 state: ElementState,
1693 xkb_context: &mut Context,
1694 callback: &mut F,
1695 ) where
1696 F: FnMut(&ActiveEventLoop, Event),
1697 {
1698 let device_id = mkdid(util::VIRTUAL_CORE_KEYBOARD);
1699
1700 let xcb = target.xconn.xcb_connection().get_raw_xcb_connection();
1702
1703 let keymap = match xkb_context.keymap_mut() {
1704 Some(keymap) => keymap,
1705 None => return,
1706 };
1707
1708 let mut xkb_state = match XkbState::new_x11(xcb, keymap) {
1710 Some(xkb_state) => xkb_state,
1711 None => return,
1712 };
1713 let mut key_processor = match xkb_context.key_context_with_state(&mut xkb_state) {
1714 Some(key_processor) => key_processor,
1715 None => return,
1716 };
1717
1718 for keycode in target.xconn.query_keymap().into_iter().filter(|k| *k >= KEYCODE_OFFSET) {
1719 let event = key_processor.process_key_event(keycode as u32, state, false);
1720 let event = Event::WindowEvent {
1721 window_id,
1722 event: WindowEvent::KeyboardInput { device_id, event, is_synthetic: true },
1723 };
1724 callback(target, event);
1725 }
1726 }
1727
1728 fn process_dpi_change<F>(&self, callback: &mut F)
1729 where
1730 F: FnMut(&ActiveEventLoop, Event),
1731 {
1732 self.target.xconn.reload_database().expect("failed to reload Xft database");
1733
1734 let prev_list = {
1736 let prev_list = self.target.xconn.invalidate_cached_monitor_list();
1737 match prev_list {
1738 Some(prev_list) => prev_list,
1739 None => return,
1740 }
1741 };
1742
1743 let new_list = self.target.xconn.available_monitors().expect("Failed to get monitor list");
1744 for new_monitor in new_list {
1745 let maybe_prev_scale_factor = prev_list
1749 .iter()
1750 .find(|prev_monitor| prev_monitor.name == new_monitor.name)
1751 .map(|prev_monitor| prev_monitor.scale_factor);
1752 if Some(new_monitor.scale_factor) != maybe_prev_scale_factor {
1753 for window in self.target.windows.borrow().iter().filter_map(|(_, w)| w.upgrade()) {
1754 window.refresh_dpi_for_monitor(&new_monitor, maybe_prev_scale_factor, |event| {
1755 callback(&self.target, event);
1756 })
1757 }
1758 }
1759 }
1760 }
1761
1762 fn window_exists(&self, window_id: xproto::Window) -> bool {
1763 self.with_window(window_id, |_| ()).is_some()
1764 }
1765}
1766
1767fn is_first_touch(first: &mut Option<u32>, num: &mut u32, id: u32, phase: TouchPhase) -> bool {
1768 match phase {
1769 TouchPhase::Started => {
1770 if *num == 0 {
1771 *first = Some(id);
1772 }
1773 *num += 1;
1774 },
1775 TouchPhase::Cancelled | TouchPhase::Ended => {
1776 if *first == Some(id) {
1777 *first = None;
1778 }
1779 *num = num.saturating_sub(1);
1780 },
1781 _ => (),
1782 }
1783
1784 *first == Some(id)
1785}