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