winit/platform_impl/linux/x11/
event_processor.rs

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
41/// The maximum amount of X modifiers to replay.
42pub const MAX_MOD_REPLAY_LEN: usize = 32;
43
44/// The X11 documentation states: "Keycodes lie in the inclusive range `[8, 255]`".
45const 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    // Number of touch events currently in progress
58    pub num_touch: u32,
59    // This is the last pressed key that is repeatable (if it hasn't been
60    // released).
61    //
62    // Used to detect key repeats.
63    pub held_key_press: Option<u32>,
64    pub first_touch: Option<u64>,
65    // Currently focused window belonging to this process
66    pub active_window: Option<xproto::Window>,
67    /// Latest modifiers we've sent for the user to trigger change in event.
68    pub modifiers: Cell<ModifiersState>,
69    // Track modifiers based on keycodes. NOTE: that serials generally don't work for tracking
70    // since they are not unique and could be duplicated in case of sequence of key events is
71    // delivered at near the same time.
72    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        // Handle IME requests.
87        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        // Drain IME events.
104        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                    // Issue empty preedit on `Done`.
118                    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    /// XFilterEvent tells us when an event has been discarded by the input method.
132    /// Specifically, this involves all of the KeyPress events in compose/pre-edit sequences,
133    /// along with an extra copy of the KeyRelease events. This also prevents backspace and
134    /// arrow keys from being detected twice.
135    #[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        // If we have IME disabled, don't try to `filter_event`, since only IME can consume them
153        // and forward back. This is not desired for e.g. games since some IMEs may delay the input
154        // and game can toggle IME back when e.g. typing into some field where latency won't really
155        // matter.
156        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                    // Don't grow the buffer past the `MAX_MOD_REPLAY_LEN`. This could happen
169                    // when the modifiers are consumed entirely.
170                    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        // Don't process event if it was filtered.
183        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            // Note that in compose/pre-edit sequences, we'll always receive KeyRelease events.
198            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        // This function is used to poll and remove a single event
331        // from the Xlib event queue in a non-blocking, atomic way.
332        // XCheckIfEvent is non-blocking and removes events from queue.
333        // XNextEvent can't be used because it blocks while holding the
334        // global Xlib mutex.
335        // XPeekEvent does not remove events from the queue.
336        unsafe extern "C" fn predicate(
337            _display: *mut XDisplay,
338            _event: *mut XEvent,
339            _arg: *mut c_char,
340        ) -> c_int {
341            // This predicate always returns "true" (1) to accept all events
342            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            // Garbage collection
387            window_target.windows.borrow_mut().remove(&window_id);
388        }
389
390        result
391    }
392
393    // NOTE: we avoid `self` to not borrow the entire `self` as not mut.
394    /// Get the platform window target.
395    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    /// Get the platform window target.
404    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            // This event occurs every time the mouse moves while a file's being dragged
475            // over our window. We emit HoveredFile in response; while the macOS backend
476            // does that upon a drag entering, XDND doesn't have access to the actual drop
477            // data until this event. For parity with other platforms, we only emit
478            // `HoveredFile` the first time, though if winit's API is later extended to
479            // supply position updates with `HoveredFile` or another event, implementing
480            // that here would be trivial.
481
482            let source_window = xev.data.get_long(0) as xproto::Window;
483
484            // Equivalent to `(x << shift) | y`
485            // where `shift = mem::size_of::<c_short>() * 8`
486            // Note that coordinates are in "desktop space", not "window space"
487            // (in X11 parlance, they're root window coordinates)
488            // let packed_coordinates = xev.data.get_long(2);
489            // let shift = mem::size_of::<libc::c_short>() * 8;
490            // let x = packed_coordinates >> shift;
491            // let y = packed_coordinates & !(x << shift);
492
493            // By our own state flow, `version` should never be `None` at this point.
494            let version = self.dnd.version.unwrap_or(5);
495
496            // Action is specified in versions 2 and up, though we don't need it anyway.
497            // let action = xev.data.get_long(4);
498
499            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                    // In version 0, time isn't specified
521                    x11rb::CURRENT_TIME
522                };
523
524                // Log this timestamp.
525                wt.xconn.set_timestamp(time);
526
527                // This results in the `SelectionNotify` event below
528                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                // `source_window` won't be part of our DND state if we already rejected the drop in
555                // our `XdndPosition` handler.
556                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        // Set the timestamp.
588        wt.xconn.set_timestamp(xev.time as xproto::Timestamp);
589
590        if xev.property != atoms[XdndSelection] as c_ulong {
591            return;
592        }
593
594        // This is where we receive data from drag and drop
595        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        // So apparently...
626        // `XSendEvent` (synthetic `ConfigureNotify`) -> position relative to root
627        // `XConfigureNotify` (real `ConfigureNotify`) -> position relative to parent
628        // https://tronche.com/gui/x/icccm/sec-4.html#s-4.1.5
629        // We don't want to send `Moved` when this is false, since then every `Resized`
630        // (whether the window moved or not) is accompanied by an extraneous `Moved` event
631        // that has a position relative to the parent window.
632        let is_synthetic = xev.send_event == xlib::True;
633
634        // These are both in physical space.
635        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                // Detect when frame extents change.
646                // Since this isn't synthetic, as per the notes above, this position is relative to
647                // the parent window.
648                let rel_parent = new_inner_position;
649                if util::maybe_change(&mut shared_state_lock.inner_position_rel_parent, rel_parent)
650                {
651                    // This ensures we process the next `Moved`.
652                    shared_state_lock.inner_position = None;
653                    // Extra insurance against stale frame extents.
654                    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            // We need to convert client area position to window position.
669            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            // Unlock shared state to prevent deadlock in callback below
680            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            // If we don't use the existing adjusted value when available, then the user can screw
694            // up the resizing by dragging across monitors *without* dropping the
695            // window.
696            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                    // Avoid updating monitor using a dummy monitor handle
709                    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                // Unlock shared state to prevent deadlock in callback below
728                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                    // if the DPI factor changed, force a resize event to ensure the logical
746                    // size is computed with the right DPI factor
747                    resized = true;
748                }
749            }
750        }
751
752        // NOTE: Ensure that the lock is dropped before handling the resized and
753        // sending the event back to user.
754        let hittest = {
755            let mut shared_state_lock = window.shared_state_lock();
756            let hittest = shared_state_lock.cursor_hittest;
757
758            // This is a hack to ensure that the DPI adjusted resize is actually
759            // applied on all WMs. KWin doesn't need this, but Xfwm does. The hack
760            // should not be run on other WMs, since tiling WMs constrain the window
761            // size, making the resize fail. This would cause an endless stream of
762            // XResizeWindow requests, making Xorg, the winit client, and the WM
763            // consume 100% of CPU.
764            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                    // When this finally happens, the event will not be synthetic.
767                    shared_state_lock.dpi_adjusted = None;
768                } else {
769                    // Unlock shared state to prevent deadlock in callback below
770                    drop(shared_state_lock);
771                    window.request_inner_size_physical(adjusted_size.0, adjusted_size.1);
772                }
773            }
774
775            hittest
776        };
777
778        // Reload hittest.
779        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    /// This is generally a reliable way to detect when the window manager's been
792    /// replaced, though this event is only fired by reparenting window managers
793    /// (which is almost all of them). Failing to correctly update WM info doesn't
794    /// really have much impact, since on the WMs affected (xmonad, dwm, etc.) the only
795    /// effect is that we waste some time trying to query unsupported properties.
796    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        // NOTE: Re-issue the focus state when mapping the window.
814        //
815        // The purpose of it is to deliver initial focused state of the newly created
816        // window, given that we can't rely on `CreateNotify`, due to it being not
817        // sent.
818        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        // In the event that the window's been destroyed without being dropped first, we
834        // cleanup again here.
835        wt.windows.borrow_mut().remove(&WindowId(window as _));
836
837        // Since all XIM stuff needs to happen from the same thread, we destroy the input
838        // context here instead of when dropping the window.
839        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        // Multiple Expose events may be received for subareas of a window.
885        // We issue `RedrawRequested` only for the last event of such a series.
886        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        // Set the timestamp.
907        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        // Update state to track key repeats and determine whether this key was a repeat.
920        //
921        // Note, when a key is held before focusing on this window the first
922        // (non-synthetic) event will not be flagged as a repeat (also note that the
923        // synthetic press event that is generated before this when the window gains focus
924        // will also not be flagged as a repeat).
925        //
926        // Only keys that can repeat should change the held_key_press state since a
927        // continuously held repeatable key may continue repeating after the press of a
928        // non-repeatable key.
929        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                // Check that the released key is the latest repeatable key that has been
939                // pressed, since repeats will continue for the latest key press if a
940                // different previously pressed key is released.
941                if is_latest_held {
942                    self.held_key_press = None;
943                }
944                false
945            }
946        } else {
947            false
948        };
949
950        // NOTE: When the modifier was captured by the XFilterEvents the modifiers for the modifier
951        // itself are out of sync due to XkbState being delivered before XKeyEvent, since it's
952        // being replayed by the XIM, thus we should replay ourselves.
953        let replay = if let Some(position) =
954            self.xfiltered_modifiers.iter().rev().position(|&s| s == xev.keycode as u8)
955        {
956            // We don't have to replay modifiers pressed before the current event if some events
957            // were not forwarded to us, since their state is irrelevant.
958            self.xfiltered_modifiers.resize(self.xfiltered_modifiers.len() - 1 - position, 0);
959            true
960        } else {
961            false
962        };
963
964        // Always update the modifiers when we're not replaying.
965        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            // Don't alter the modifiers state from replaying.
971            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            // Restore the client's modifiers state after replay.
985            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        // Use synthetic state since we're replaying the modifier. The user modifier state
1031        // will be restored later.
1032        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        // Set the timestamp.
1060        wt.xconn.set_timestamp(event.time as xproto::Timestamp);
1061
1062        // Deliver multi-touch events instead of emulated mouse events.
1063        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            // Suppress emulated scroll wheel clicks, since we handle the real motion events for
1080            // those. In practice, even clicky scroll wheels appear to be reported by
1081            // evdev (and XInput2 in turn) as axis motion, so we don't otherwise
1082            // special-case these button presses.
1083            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        // Set the timestamp.
1111        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        // More gymnastics, for self.devices
1136        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                // X11 vertical scroll coordinates are opposite to winit's
1160                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        // Set the timestamp.
1189        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                // The second expression is need for resetting to work correctly on i3, and
1199                // presumably some other WMs. On those, `XI_Enter` doesn't include the physical
1200                // device ID, so both `sourceid` and `deviceid` are the virtual device.
1201                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        // Set the timestamp.
1235        wt.xconn.set_timestamp(event.time as xproto::Timestamp);
1236
1237        // Leave, FocusIn, and FocusOut can be received by a window that's already
1238        // been destroyed, which the user presumably doesn't want to deal with.
1239        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        // Set the timestamp.
1258        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        // Issue key press events for all pressed keys
1283        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        // The deviceid for this event is for a keyboard instead of a pointer,
1294        // so we have to do a little extra work.
1295        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        // Set the timestamp.
1317        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            // Clear the modifiers when unfocusing the window.
1333            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            // Issue key release events for all pressed keys
1340            Self::handle_pressed_keys(
1341                &self.target,
1342                window_id,
1343                ElementState::Released,
1344                &mut self.xkb_context,
1345                &mut callback,
1346            );
1347
1348            // Clear this so detecting key repeats is consistently handled when the
1349            // window regains focus.
1350            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        // Set the timestamp.
1372        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            // Mouse cursor position changes when touch events are received.
1381            // Only the first concurrently active touch ID moves the mouse cursor.
1382            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, // TODO
1400                    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        // Set the timestamp.
1418        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        // Set the timestamp.
1436        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            // We assume that every XInput2 device with analog axes is a pointing device emitting
1452            // relative coordinates.
1453            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        // Set the timestamp.
1500        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        // Set the timestamp.
1522        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                // Set the timestamp.
1552                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                // Set the timestamp.
1596                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            // NOTE: we use active window since generally sub windows don't have keyboard input,
1641            // and winit assumes that unfocused window doesn't have modifiers.
1642            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        // NOTE: this is inspired by Qt impl.
1701        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        // Set modifiers in depressed if they don't appear in any of the final masks.
1705        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    // Bits 13 and 14 report the state keyboard group.
1721    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        // Build the XKB modifiers from the regular state.
1732        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    /// Send modifiers for the active window.
1762    ///
1763    /// The event won't be sent when the `modifiers` match the previously `sent` modifiers value,
1764    /// unless `force` is passed. The `force` should be passed when the active window changes.
1765    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        // NOTE: Always update the modifiers to account for case when they've changed
1773        // and forced was `true`.
1774        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        // Update modifiers state and emit key events based on which keys are currently pressed.
1795        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        // Send the keys using the synthetic state to not alter the main state.
1804        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        // In the future, it would be quite easy to emit monitor hotplug events.
1833        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            // Previous list may be empty, in case of disconnecting and
1844            // reconnecting the only one monitor. We still need to emit events in
1845            // this case.
1846            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}