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;
20use x11rb::x11_utils::Serialize;
21use xkbcommon_dl::xkb_mod_mask_t;
22
23use crate::dpi::{PhysicalPosition, PhysicalSize};
24use crate::event::{
25 DeviceEvent, ElementState, Event, Ime, MouseScrollDelta, RawKeyEvent, Touch, TouchPhase,
26 WindowEvent,
27};
28use crate::event::{InnerSizeWriter, MouseButton};
29use crate::event_loop::EventLoopWindowTarget as RootELW;
30use crate::keyboard::ModifiersState;
31use crate::platform_impl::common::xkb::{self, XkbState};
32use crate::platform_impl::platform::common::xkb::Context;
33use crate::platform_impl::platform::x11::ime::{ImeEvent, ImeEventReceiver, ImeRequest};
34use crate::platform_impl::platform::x11::EventLoopWindowTarget;
35use crate::platform_impl::platform::EventLoopWindowTarget as PlatformEventLoopWindowTarget;
36use crate::platform_impl::x11::util::cookie::GenericEventCookie;
37use crate::platform_impl::x11::{
38 atoms::*, mkdid, mkwid, util, CookieResultExt, Device, DeviceId, DeviceInfo, Dnd, DndState,
39 ImeReceiver, ScrollOrientation, UnownedWindow, WindowId,
40};
41
42/// The maximum amount of X modifiers to replay.
43pub const MAX_MOD_REPLAY_LEN: usize = 32;
44
45/// The X11 documentation states: "Keycodes lie in the inclusive range `[8, 255]`".
46const KEYCODE_OFFSET: u8 = 8;
47
48pub struct EventProcessor<T: 'static> {
49 pub dnd: Dnd,
50 pub ime_receiver: ImeReceiver,
51 pub ime_event_receiver: ImeEventReceiver,
52 pub randr_event_offset: u8,
53 pub devices: RefCell<HashMap<DeviceId, Device>>,
54 pub xi2ext: ExtensionInformation,
55 pub xkbext: ExtensionInformation,
56 pub target: RootELW<T>,
57 pub xkb_context: Context,
58 // Number of touch events currently in progress
59 pub num_touch: u32,
60 // This is the last pressed key that is repeatable (if it hasn't been
61 // released).
62 //
63 // Used to detect key repeats.
64 pub held_key_press: Option<u32>,
65 pub first_touch: Option<u64>,
66 // Currently focused window belonging to this process
67 pub active_window: Option<xproto::Window>,
68 /// Latest modifiers we've sent for the user to trigger change in event.
69 pub modifiers: Cell<ModifiersState>,
70 pub xfiltered_modifiers: VecDeque<c_ulong>,
71 pub xmodmap: util::ModifierKeymap,
72 pub is_composing: bool,
73}
74
75impl<T: 'static> EventProcessor<T> {
76 pub fn process_event<F>(&mut self, xev: &mut XEvent, mut callback: F)
77 where
78 F: FnMut(&RootELW<T>, Event<T>),
79 {
80 self.process_xevent(xev, &mut callback);
81
82 let window_target = Self::window_target_mut(&mut self.target);
83
84 // Handle IME requests.
85 while let Ok(request) = self.ime_receiver.try_recv() {
86 let ime = match window_target.ime.as_mut() {
87 Some(ime) => ime,
88 None => continue,
89 };
90 let ime = ime.get_mut();
91 match request {
92 ImeRequest::Position(window_id, x, y) => {
93 ime.send_xim_spot(window_id, x, y);
94 }
95 ImeRequest::Allow(window_id, allowed) => {
96 ime.set_ime_allowed(window_id, allowed);
97 }
98 }
99 }
100
101 // Drain IME events.
102 while let Ok((window, event)) = self.ime_event_receiver.try_recv() {
103 let window_id = mkwid(window as xproto::Window);
104 let event = match event {
105 ImeEvent::Enabled => WindowEvent::Ime(Ime::Enabled),
106 ImeEvent::Start => {
107 self.is_composing = true;
108 WindowEvent::Ime(Ime::Preedit("".to_owned(), None))
109 }
110 ImeEvent::Update(text, position) if self.is_composing => {
111 WindowEvent::Ime(Ime::Preedit(text, Some((position, position))))
112 }
113 ImeEvent::End => {
114 self.is_composing = false;
115 // Issue empty preedit on `Done`.
116 WindowEvent::Ime(Ime::Preedit(String::new(), None))
117 }
118 ImeEvent::Disabled => {
119 self.is_composing = false;
120 WindowEvent::Ime(Ime::Disabled)
121 }
122 _ => continue,
123 };
124
125 callback(&self.target, Event::WindowEvent { window_id, event });
126 }
127 }
128
129 /// XFilterEvent tells us when an event has been discarded by the input method.
130 /// Specifically, this involves all of the KeyPress events in compose/pre-edit sequences,
131 /// along with an extra copy of the KeyRelease events. This also prevents backspace and
132 /// arrow keys from being detected twice.
133 fn filter_event(&mut self, xev: &mut XEvent) -> bool {
134 let wt = Self::window_target(&self.target);
135 unsafe {
136 (wt.xconn.xlib.XFilterEvent)(xev, {
137 let xev: &XAnyEvent = xev.as_ref();
138 xev.window
139 }) == xlib::True
140 }
141 }
142
143 fn process_xevent<F>(&mut self, xev: &mut XEvent, mut callback: F)
144 where
145 F: FnMut(&RootELW<T>, Event<T>),
146 {
147 let event_type = xev.get_type();
148
149 if self.filter_event(xev) {
150 if event_type == xlib::KeyPress || event_type == xlib::KeyRelease {
151 let xev: &XKeyEvent = xev.as_ref();
152 if self.xmodmap.is_modifier(xev.keycode as u8) {
153 // Don't grow the buffer past the `MAX_MOD_REPLAY_LEN`. This could happen
154 // when the modifiers are consumed entirely or serials are altered.
155 //
156 // Both cases shouldn't happen in well behaving clients.
157 if self.xfiltered_modifiers.len() == MAX_MOD_REPLAY_LEN {
158 self.xfiltered_modifiers.pop_back();
159 }
160 self.xfiltered_modifiers.push_front(xev.serial);
161 }
162 }
163 return;
164 }
165
166 match event_type {
167 xlib::ClientMessage => self.client_message(xev.as_ref(), &mut callback),
168 xlib::SelectionNotify => self.selection_notify(xev.as_ref(), &mut callback),
169 xlib::ConfigureNotify => self.configure_notify(xev.as_ref(), &mut callback),
170 xlib::ReparentNotify => self.reparent_notify(xev.as_ref()),
171 xlib::MapNotify => self.map_notify(xev.as_ref(), &mut callback),
172 xlib::DestroyNotify => self.destroy_notify(xev.as_ref(), &mut callback),
173 xlib::PropertyNotify => self.property_notify(xev.as_ref(), &mut callback),
174 xlib::VisibilityNotify => self.visibility_notify(xev.as_ref(), &mut callback),
175 xlib::Expose => self.expose(xev.as_ref(), &mut callback),
176 // Note that in compose/pre-edit sequences, we'll always receive KeyRelease events.
177 ty @ xlib::KeyPress | ty @ xlib::KeyRelease => {
178 let state = if ty == xlib::KeyPress {
179 ElementState::Pressed
180 } else {
181 ElementState::Released
182 };
183
184 self.xinput_key_input(xev.as_mut(), state, &mut callback);
185 }
186 xlib::GenericEvent => {
187 let wt = Self::window_target(&self.target);
188 let xev: GenericEventCookie =
189 match GenericEventCookie::from_event(wt.xconn.clone(), *xev) {
190 Some(xev) if xev.extension() == self.xi2ext.major_opcode => xev,
191 _ => return,
192 };
193
194 let evtype = xev.evtype();
195
196 match evtype {
197 ty @ xinput2::XI_ButtonPress | ty @ xinput2::XI_ButtonRelease => {
198 let state = if ty == xinput2::XI_ButtonPress {
199 ElementState::Pressed
200 } else {
201 ElementState::Released
202 };
203
204 let xev: &XIDeviceEvent = unsafe { xev.as_event() };
205 self.update_mods_from_xinput2_event(
206 &xev.mods,
207 &xev.group,
208 false,
209 &mut callback,
210 );
211 self.xinput2_button_input(xev, state, &mut callback);
212 }
213 xinput2::XI_Motion => {
214 let xev: &XIDeviceEvent = unsafe { xev.as_event() };
215 self.update_mods_from_xinput2_event(
216 &xev.mods,
217 &xev.group,
218 false,
219 &mut callback,
220 );
221 self.xinput2_mouse_motion(xev, &mut callback);
222 }
223 xinput2::XI_Enter => {
224 let xev: &XIEnterEvent = unsafe { xev.as_event() };
225 self.xinput2_mouse_enter(xev, &mut callback);
226 }
227 xinput2::XI_Leave => {
228 let xev: &XILeaveEvent = unsafe { xev.as_event() };
229 self.update_mods_from_xinput2_event(
230 &xev.mods,
231 &xev.group,
232 false,
233 &mut callback,
234 );
235 self.xinput2_mouse_left(xev, &mut callback);
236 }
237 xinput2::XI_FocusIn => {
238 let xev: &XIFocusInEvent = unsafe { xev.as_event() };
239 self.xinput2_focused(xev, &mut callback);
240 }
241 xinput2::XI_FocusOut => {
242 let xev: &XIFocusOutEvent = unsafe { xev.as_event() };
243 self.xinput2_unfocused(xev, &mut callback);
244 }
245 xinput2::XI_TouchBegin | xinput2::XI_TouchUpdate | xinput2::XI_TouchEnd => {
246 let phase = match evtype {
247 xinput2::XI_TouchBegin => TouchPhase::Started,
248 xinput2::XI_TouchUpdate => TouchPhase::Moved,
249 xinput2::XI_TouchEnd => TouchPhase::Ended,
250 _ => unreachable!(),
251 };
252
253 let xev: &XIDeviceEvent = unsafe { xev.as_event() };
254 self.xinput2_touch(xev, phase, &mut callback);
255 }
256 xinput2::XI_RawButtonPress | xinput2::XI_RawButtonRelease => {
257 let state = match evtype {
258 xinput2::XI_RawButtonPress => ElementState::Pressed,
259 xinput2::XI_RawButtonRelease => ElementState::Released,
260 _ => unreachable!(),
261 };
262
263 let xev: &XIRawEvent = unsafe { xev.as_event() };
264 self.xinput2_raw_button_input(xev, state, &mut callback);
265 }
266 xinput2::XI_RawMotion => {
267 let xev: &XIRawEvent = unsafe { xev.as_event() };
268 self.xinput2_raw_mouse_motion(xev, &mut callback);
269 }
270 xinput2::XI_RawKeyPress | xinput2::XI_RawKeyRelease => {
271 let state = match evtype {
272 xinput2::XI_RawKeyPress => ElementState::Pressed,
273 xinput2::XI_RawKeyRelease => ElementState::Released,
274 _ => unreachable!(),
275 };
276
277 let xev: &xinput2::XIRawEvent = unsafe { xev.as_event() };
278 self.xinput2_raw_key_input(xev, state, &mut callback);
279 }
280
281 xinput2::XI_HierarchyChanged => {
282 let xev: &XIHierarchyEvent = unsafe { xev.as_event() };
283 self.xinput2_hierarchy_changed(xev, &mut callback);
284 }
285 _ => {}
286 }
287 }
288 _ => {
289 if event_type == self.xkbext.first_event as _ {
290 let xev: &XkbAnyEvent = unsafe { &*(xev as *const _ as *const XkbAnyEvent) };
291 self.xkb_event(xev, &mut callback);
292 }
293 if event_type == self.randr_event_offset as c_int {
294 self.process_dpi_change(&mut callback);
295 }
296 }
297 }
298 }
299
300 pub fn poll(&self) -> bool {
301 let window_target = Self::window_target(&self.target);
302 let result = unsafe { (window_target.xconn.xlib.XPending)(window_target.xconn.display) };
303
304 result != 0
305 }
306
307 pub unsafe fn poll_one_event(&mut self, event_ptr: *mut XEvent) -> bool {
308 let window_target = Self::window_target(&self.target);
309 // This function is used to poll and remove a single event
310 // from the Xlib event queue in a non-blocking, atomic way.
311 // XCheckIfEvent is non-blocking and removes events from queue.
312 // XNextEvent can't be used because it blocks while holding the
313 // global Xlib mutex.
314 // XPeekEvent does not remove events from the queue.
315 unsafe extern "C" fn predicate(
316 _display: *mut XDisplay,
317 _event: *mut XEvent,
318 _arg: *mut c_char,
319 ) -> c_int {
320 // This predicate always returns "true" (1) to accept all events
321 1
322 }
323
324 let result = unsafe {
325 (window_target.xconn.xlib.XCheckIfEvent)(
326 window_target.xconn.display,
327 event_ptr,
328 Some(predicate),
329 std::ptr::null_mut(),
330 )
331 };
332
333 result != 0
334 }
335
336 pub fn init_device(&self, device: xinput::DeviceId) {
337 let window_target = Self::window_target(&self.target);
338 let mut devices = self.devices.borrow_mut();
339 if let Some(info) = DeviceInfo::get(&window_target.xconn, device as _) {
340 for info in info.iter() {
341 devices.insert(DeviceId(info.deviceid as _), Device::new(info));
342 }
343 }
344 }
345
346 pub fn with_window<F, Ret>(&self, window_id: xproto::Window, callback: F) -> Option<Ret>
347 where
348 F: Fn(&Arc<UnownedWindow>) -> Ret,
349 {
350 let mut deleted = false;
351 let window_id = WindowId(window_id as _);
352 let window_target = Self::window_target(&self.target);
353 let result = window_target
354 .windows
355 .borrow()
356 .get(&window_id)
357 .and_then(|window| {
358 let arc = window.upgrade();
359 deleted = arc.is_none();
360 arc
361 })
362 .map(|window| callback(&window));
363
364 if deleted {
365 // Garbage collection
366 window_target.windows.borrow_mut().remove(&window_id);
367 }
368
369 result
370 }
371
372 // NOTE: we avoid `self` to not borrow the entire `self` as not mut.
373 /// Get the platform window target.
374 pub fn window_target(window_target: &RootELW<T>) -> &EventLoopWindowTarget<T> {
375 match &window_target.p {
376 PlatformEventLoopWindowTarget::X(target) => target,
377 #[cfg(wayland_platform)]
378 _ => unreachable!(),
379 }
380 }
381
382 /// Get the platform window target.
383 pub fn window_target_mut(window_target: &mut RootELW<T>) -> &mut EventLoopWindowTarget<T> {
384 match &mut window_target.p {
385 PlatformEventLoopWindowTarget::X(target) => target,
386 #[cfg(wayland_platform)]
387 _ => unreachable!(),
388 }
389 }
390
391 fn client_message<F>(&mut self, xev: &XClientMessageEvent, mut callback: F)
392 where
393 F: FnMut(&RootELW<T>, Event<T>),
394 {
395 let wt = Self::window_target(&self.target);
396 let atoms = wt.xconn.atoms();
397
398 let window = xev.window as xproto::Window;
399 let window_id = mkwid(window);
400
401 if xev.data.get_long(0) as xproto::Atom == wt.wm_delete_window {
402 let event = Event::WindowEvent {
403 window_id,
404 event: WindowEvent::CloseRequested,
405 };
406 callback(&self.target, event);
407 return;
408 }
409
410 if xev.data.get_long(0) as xproto::Atom == wt.net_wm_ping {
411 let client_msg = xproto::ClientMessageEvent {
412 response_type: xproto::CLIENT_MESSAGE_EVENT,
413 format: xev.format as _,
414 sequence: xev.serial as _,
415 window: wt.root,
416 type_: xev.message_type as _,
417 data: xproto::ClientMessageData::from({
418 let [a, b, c, d, e]: [c_long; 5] = xev.data.as_longs().try_into().unwrap();
419 [a as u32, b as u32, c as u32, d as u32, e as u32]
420 }),
421 };
422
423 wt.xconn
424 .xcb_connection()
425 .send_event(
426 false,
427 wt.root,
428 xproto::EventMask::SUBSTRUCTURE_NOTIFY
429 | xproto::EventMask::SUBSTRUCTURE_REDIRECT,
430 client_msg.serialize(),
431 )
432 .expect_then_ignore_error("Failed to send `ClientMessage` event.");
433 return;
434 }
435
436 if xev.message_type == atoms[XdndEnter] as c_ulong {
437 let source_window = xev.data.get_long(0) as xproto::Window;
438 let flags = xev.data.get_long(1);
439 let version = flags >> 24;
440 self.dnd.version = Some(version);
441 let has_more_types = flags - (flags & (c_long::max_value() - 1)) == 1;
442 if !has_more_types {
443 let type_list = vec![
444 xev.data.get_long(2) as xproto::Atom,
445 xev.data.get_long(3) as xproto::Atom,
446 xev.data.get_long(4) as xproto::Atom,
447 ];
448 self.dnd.type_list = Some(type_list);
449 } else if let Ok(more_types) = unsafe { self.dnd.get_type_list(source_window) } {
450 self.dnd.type_list = Some(more_types);
451 }
452 return;
453 }
454
455 if xev.message_type == atoms[XdndPosition] as c_ulong {
456 // This event occurs every time the mouse moves while a file's being dragged
457 // over our window. We emit HoveredFile in response; while the macOS backend
458 // does that upon a drag entering, XDND doesn't have access to the actual drop
459 // data until this event. For parity with other platforms, we only emit
460 // `HoveredFile` the first time, though if winit's API is later extended to
461 // supply position updates with `HoveredFile` or another event, implementing
462 // that here would be trivial.
463
464 let source_window = xev.data.get_long(0) as xproto::Window;
465
466 // Equivalent to `(x << shift) | y`
467 // where `shift = mem::size_of::<c_short>() * 8`
468 // Note that coordinates are in "desktop space", not "window space"
469 // (in X11 parlance, they're root window coordinates)
470 //let packed_coordinates = xev.data.get_long(2);
471 //let shift = mem::size_of::<libc::c_short>() * 8;
472 //let x = packed_coordinates >> shift;
473 //let y = packed_coordinates & !(x << shift);
474
475 // By our own state flow, `version` should never be `None` at this point.
476 let version = self.dnd.version.unwrap_or(5);
477
478 // Action is specified in versions 2 and up, though we don't need it anyway.
479 //let action = xev.data.get_long(4);
480
481 let accepted = if let Some(ref type_list) = self.dnd.type_list {
482 type_list.contains(&atoms[TextUriList])
483 } else {
484 false
485 };
486
487 if !accepted {
488 unsafe {
489 self.dnd
490 .send_status(window, source_window, DndState::Rejected)
491 .expect("Failed to send `XdndStatus` message.");
492 }
493 self.dnd.reset();
494 return;
495 }
496
497 self.dnd.source_window = Some(source_window);
498 if self.dnd.result.is_none() {
499 let time = if version >= 1 {
500 xev.data.get_long(3) as xproto::Timestamp
501 } else {
502 // In version 0, time isn't specified
503 x11rb::CURRENT_TIME
504 };
505
506 // Log this timestamp.
507 wt.xconn.set_timestamp(time);
508
509 // This results in the `SelectionNotify` event below
510 unsafe {
511 self.dnd.convert_selection(window, time);
512 }
513 }
514
515 unsafe {
516 self.dnd
517 .send_status(window, source_window, DndState::Accepted)
518 .expect("Failed to send `XdndStatus` message.");
519 }
520 return;
521 }
522
523 if xev.message_type == atoms[XdndDrop] as c_ulong {
524 let (source_window, state) = if let Some(source_window) = self.dnd.source_window {
525 if let Some(Ok(ref path_list)) = self.dnd.result {
526 for path in path_list {
527 let event = Event::WindowEvent {
528 window_id,
529 event: WindowEvent::DroppedFile(path.clone()),
530 };
531 callback(&self.target, event);
532 }
533 }
534 (source_window, DndState::Accepted)
535 } else {
536 // `source_window` won't be part of our DND state if we already rejected the drop in our
537 // `XdndPosition` handler.
538 let source_window = xev.data.get_long(0) as xproto::Window;
539 (source_window, DndState::Rejected)
540 };
541
542 unsafe {
543 self.dnd
544 .send_finished(window, source_window, state)
545 .expect("Failed to send `XdndFinished` message.");
546 }
547
548 self.dnd.reset();
549 return;
550 }
551
552 if xev.message_type == atoms[XdndLeave] as c_ulong {
553 self.dnd.reset();
554 let event = Event::WindowEvent {
555 window_id,
556 event: WindowEvent::HoveredFileCancelled,
557 };
558 callback(&self.target, event);
559 }
560 }
561
562 fn selection_notify<F>(&mut self, xev: &XSelectionEvent, mut callback: F)
563 where
564 F: FnMut(&RootELW<T>, Event<T>),
565 {
566 let wt = Self::window_target(&self.target);
567 let atoms = wt.xconn.atoms();
568
569 let window = xev.requestor as xproto::Window;
570 let window_id = mkwid(window);
571
572 // Set the timestamp.
573 wt.xconn.set_timestamp(xev.time as xproto::Timestamp);
574
575 if xev.property != atoms[XdndSelection] as c_ulong {
576 return;
577 }
578
579 // This is where we receive data from drag and drop
580 self.dnd.result = None;
581 if let Ok(mut data) = unsafe { self.dnd.read_data(window) } {
582 let parse_result = self.dnd.parse_data(&mut data);
583 if let Ok(ref path_list) = parse_result {
584 for path in path_list {
585 let event = Event::WindowEvent {
586 window_id,
587 event: WindowEvent::HoveredFile(path.clone()),
588 };
589 callback(&self.target, event);
590 }
591 }
592 self.dnd.result = Some(parse_result);
593 }
594 }
595
596 fn configure_notify<F>(&self, xev: &XConfigureEvent, mut callback: F)
597 where
598 F: FnMut(&RootELW<T>, Event<T>),
599 {
600 let wt = Self::window_target(&self.target);
601
602 let xwindow = xev.window as xproto::Window;
603 let window_id = mkwid(xwindow);
604
605 let window = match self.with_window(xwindow, Arc::clone) {
606 Some(window) => window,
607 None => return,
608 };
609
610 // So apparently...
611 // `XSendEvent` (synthetic `ConfigureNotify`) -> position relative to root
612 // `XConfigureNotify` (real `ConfigureNotify`) -> position relative to parent
613 // https://tronche.com/gui/x/icccm/sec-4.html#s-4.1.5
614 // We don't want to send `Moved` when this is false, since then every `Resized`
615 // (whether the window moved or not) is accompanied by an extraneous `Moved` event
616 // that has a position relative to the parent window.
617 let is_synthetic = xev.send_event == xlib::True;
618
619 // These are both in physical space.
620 let new_inner_size = (xev.width as u32, xev.height as u32);
621 let new_inner_position = (xev.x, xev.y);
622
623 let (mut resized, moved) = {
624 let mut shared_state_lock = window.shared_state_lock();
625
626 let resized = util::maybe_change(&mut shared_state_lock.size, new_inner_size);
627 let moved = if is_synthetic {
628 util::maybe_change(&mut shared_state_lock.inner_position, new_inner_position)
629 } else {
630 // Detect when frame extents change.
631 // Since this isn't synthetic, as per the notes above, this position is relative to the
632 // parent window.
633 let rel_parent = new_inner_position;
634 if util::maybe_change(&mut shared_state_lock.inner_position_rel_parent, rel_parent)
635 {
636 // This ensures we process the next `Moved`.
637 shared_state_lock.inner_position = None;
638 // Extra insurance against stale frame extents.
639 shared_state_lock.frame_extents = None;
640 }
641 false
642 };
643 (resized, moved)
644 };
645
646 let position = window.shared_state_lock().position;
647
648 let new_outer_position = if let (Some(position), false) = (position, moved) {
649 position
650 } else {
651 let mut shared_state_lock = window.shared_state_lock();
652
653 // We need to convert client area position to window position.
654 let frame_extents = shared_state_lock
655 .frame_extents
656 .as_ref()
657 .cloned()
658 .unwrap_or_else(|| {
659 let frame_extents = wt.xconn.get_frame_extents_heuristic(xwindow, wt.root);
660 shared_state_lock.frame_extents = Some(frame_extents.clone());
661 frame_extents
662 });
663 let outer =
664 frame_extents.inner_pos_to_outer(new_inner_position.0, new_inner_position.1);
665 shared_state_lock.position = Some(outer);
666
667 // Unlock shared state to prevent deadlock in callback below
668 drop(shared_state_lock);
669
670 if moved {
671 callback(
672 &self.target,
673 Event::WindowEvent {
674 window_id,
675 event: WindowEvent::Moved(outer.into()),
676 },
677 );
678 }
679 outer
680 };
681
682 if is_synthetic {
683 let mut shared_state_lock = window.shared_state_lock();
684 // If we don't use the existing adjusted value when available, then the user can screw up the
685 // resizing by dragging across monitors *without* dropping the window.
686 let (width, height) = shared_state_lock
687 .dpi_adjusted
688 .unwrap_or((xev.width as u32, xev.height as u32));
689
690 let last_scale_factor = shared_state_lock.last_monitor.scale_factor;
691 let new_scale_factor = {
692 let window_rect = util::AaRect::new(new_outer_position, new_inner_size);
693 let monitor = wt
694 .xconn
695 .get_monitor_for_window(Some(window_rect))
696 .expect("Failed to find monitor for window");
697
698 if monitor.is_dummy() {
699 // Avoid updating monitor using a dummy monitor handle
700 last_scale_factor
701 } else {
702 shared_state_lock.last_monitor = monitor.clone();
703 monitor.scale_factor
704 }
705 };
706 if last_scale_factor != new_scale_factor {
707 let (new_width, new_height) = window.adjust_for_dpi(
708 last_scale_factor,
709 new_scale_factor,
710 width,
711 height,
712 &shared_state_lock,
713 );
714
715 let old_inner_size = PhysicalSize::new(width, height);
716 let new_inner_size = PhysicalSize::new(new_width, new_height);
717
718 // Unlock shared state to prevent deadlock in callback below
719 drop(shared_state_lock);
720
721 let inner_size = Arc::new(Mutex::new(new_inner_size));
722 callback(
723 &self.target,
724 Event::WindowEvent {
725 window_id,
726 event: WindowEvent::ScaleFactorChanged {
727 scale_factor: new_scale_factor,
728 inner_size_writer: InnerSizeWriter::new(Arc::downgrade(&inner_size)),
729 },
730 },
731 );
732
733 let new_inner_size = *inner_size.lock().unwrap();
734 drop(inner_size);
735
736 if new_inner_size != old_inner_size {
737 window.request_inner_size_physical(new_inner_size.width, new_inner_size.height);
738 window.shared_state_lock().dpi_adjusted = Some(new_inner_size.into());
739 // if the DPI factor changed, force a resize event to ensure the logical
740 // size is computed with the right DPI factor
741 resized = true;
742 }
743 }
744 }
745
746 // NOTE: Ensure that the lock is dropped before handling the resized and
747 // sending the event back to user.
748 let hittest = {
749 let mut shared_state_lock = window.shared_state_lock();
750 let hittest = shared_state_lock.cursor_hittest;
751
752 // This is a hack to ensure that the DPI adjusted resize is actually
753 // applied on all WMs. KWin doesn't need this, but Xfwm does. The hack
754 // should not be run on other WMs, since tiling WMs constrain the window
755 // size, making the resize fail. This would cause an endless stream of
756 // XResizeWindow requests, making Xorg, the winit client, and the WM
757 // consume 100% of CPU.
758 if let Some(adjusted_size) = shared_state_lock.dpi_adjusted {
759 if new_inner_size == adjusted_size || !util::wm_name_is_one_of(&["Xfwm4"]) {
760 // When this finally happens, the event will not be synthetic.
761 shared_state_lock.dpi_adjusted = None;
762 } else {
763 // Unlock shared state to prevent deadlock in callback below
764 drop(shared_state_lock);
765 window.request_inner_size_physical(adjusted_size.0, adjusted_size.1);
766 }
767 }
768
769 hittest
770 };
771
772 // Reload hittest.
773 if hittest.unwrap_or(false) {
774 let _ = window.set_cursor_hittest(true);
775 }
776
777 if resized {
778 callback(
779 &self.target,
780 Event::WindowEvent {
781 window_id,
782 event: WindowEvent::Resized(new_inner_size.into()),
783 },
784 );
785 }
786 }
787
788 /// This is generally a reliable way to detect when the window manager's been
789 /// replaced, though this event is only fired by reparenting window managers
790 /// (which is almost all of them). Failing to correctly update WM info doesn't
791 /// really have much impact, since on the WMs affected (xmonad, dwm, etc.) the only
792 /// effect is that we waste some time trying to query unsupported properties.
793 fn reparent_notify(&self, xev: &XReparentEvent) {
794 let wt = Self::window_target(&self.target);
795
796 wt.xconn.update_cached_wm_info(wt.root);
797
798 self.with_window(xev.window as xproto::Window, |window| {
799 window.invalidate_cached_frame_extents();
800 });
801 }
802
803 fn map_notify<F>(&self, xev: &XMapEvent, mut callback: F)
804 where
805 F: FnMut(&RootELW<T>, Event<T>),
806 {
807 let window = xev.window as xproto::Window;
808 let window_id = mkwid(window);
809
810 // NOTE: Re-issue the focus state when mapping the window.
811 //
812 // The purpose of it is to deliver initial focused state of the newly created
813 // window, given that we can't rely on `CreateNotify`, due to it being not
814 // sent.
815 let focus = self
816 .with_window(window, |window| window.has_focus())
817 .unwrap_or_default();
818 let event = Event::WindowEvent {
819 window_id,
820 event: WindowEvent::Focused(focus),
821 };
822
823 callback(&self.target, event);
824 }
825
826 fn destroy_notify<F>(&self, xev: &XDestroyWindowEvent, mut callback: F)
827 where
828 F: FnMut(&RootELW<T>, Event<T>),
829 {
830 let wt = Self::window_target(&self.target);
831
832 let window = xev.window as xproto::Window;
833 let window_id = mkwid(window);
834
835 // In the event that the window's been destroyed without being dropped first, we
836 // cleanup again here.
837 wt.windows.borrow_mut().remove(&WindowId(window as _));
838
839 // Since all XIM stuff needs to happen from the same thread, we destroy the input
840 // context here instead of when dropping the window.
841 if let Some(ime) = wt.ime.as_ref() {
842 ime.borrow_mut()
843 .remove_context(window as XWindow)
844 .expect("Failed to destroy input context");
845 }
846
847 callback(
848 &self.target,
849 Event::WindowEvent {
850 window_id,
851 event: WindowEvent::Destroyed,
852 },
853 );
854 }
855
856 fn property_notify<F>(&mut self, xev: &XPropertyEvent, mut callback: F)
857 where
858 F: FnMut(&RootELW<T>, Event<T>),
859 {
860 let wt = Self::window_target(&self.target);
861 let atoms = wt.x_connection().atoms();
862 let atom = xev.atom as xproto::Atom;
863
864 if atom == xproto::Atom::from(xproto::AtomEnum::RESOURCE_MANAGER)
865 || atom == atoms[_XSETTINGS_SETTINGS]
866 {
867 self.process_dpi_change(&mut callback);
868 }
869 }
870
871 fn visibility_notify<F>(&self, xev: &XVisibilityEvent, mut callback: F)
872 where
873 F: FnMut(&RootELW<T>, Event<T>),
874 {
875 let xwindow = xev.window as xproto::Window;
876
877 let event = Event::WindowEvent {
878 window_id: mkwid(xwindow),
879 event: WindowEvent::Occluded(xev.state == xlib::VisibilityFullyObscured),
880 };
881 callback(&self.target, event);
882
883 self.with_window(xwindow, |window| {
884 window.visibility_notify();
885 });
886 }
887
888 fn expose<F>(&self, xev: &XExposeEvent, mut callback: F)
889 where
890 F: FnMut(&RootELW<T>, Event<T>),
891 {
892 // Multiple Expose events may be received for subareas of a window.
893 // We issue `RedrawRequested` only for the last event of such a series.
894 if xev.count == 0 {
895 let window = xev.window as xproto::Window;
896 let window_id = mkwid(window);
897
898 let event = Event::WindowEvent {
899 window_id,
900 event: WindowEvent::RedrawRequested,
901 };
902
903 callback(&self.target, event);
904 }
905 }
906
907 fn xinput_key_input<F>(&mut self, xev: &mut XKeyEvent, state: ElementState, mut callback: F)
908 where
909 F: FnMut(&RootELW<T>, Event<T>),
910 {
911 let wt = Self::window_target(&self.target);
912
913 // Set the timestamp.
914 wt.xconn.set_timestamp(xev.time as xproto::Timestamp);
915
916 let window = match self.active_window {
917 Some(window) => window,
918 None => return,
919 };
920
921 let window_id = mkwid(window);
922 let device_id = mkdid(util::VIRTUAL_CORE_KEYBOARD);
923
924 let keycode = xev.keycode as _;
925
926 // Update state to track key repeats and determine whether this key was a repeat.
927 //
928 // Note, when a key is held before focusing on this window the first
929 // (non-synthetic) event will not be flagged as a repeat (also note that the
930 // synthetic press event that is generated before this when the window gains focus
931 // will also not be flagged as a repeat).
932 //
933 // Only keys that can repeat should change the held_key_press state since a
934 // continuously held repeatable key may continue repeating after the press of a
935 // non-repeatable key.
936 let key_repeats = self
937 .xkb_context
938 .keymap_mut()
939 .map(|k| k.key_repeats(keycode))
940 .unwrap_or(false);
941 let repeat = if key_repeats {
942 let is_latest_held = self.held_key_press == Some(keycode);
943
944 if state == ElementState::Pressed {
945 self.held_key_press = Some(keycode);
946 is_latest_held
947 } else {
948 // Check that the released key is the latest repeatable key that has been
949 // pressed, since repeats will continue for the latest key press if a
950 // different previously pressed key is released.
951 if is_latest_held {
952 self.held_key_press = None;
953 }
954 false
955 }
956 } else {
957 false
958 };
959
960 // NOTE: When the modifier was captured by the XFilterEvents the modifiers for the modifier
961 // itself are out of sync due to XkbState being delivered before XKeyEvent, since it's
962 // being replayed by the XIM, thus we should replay ourselves.
963 let replay = if let Some(position) = self
964 .xfiltered_modifiers
965 .iter()
966 .rev()
967 .position(|&s| s == xev.serial)
968 {
969 // We don't have to replay modifiers pressed before the current event if some events
970 // were not forwarded to us, since their state is irrelevant.
971 self.xfiltered_modifiers
972 .resize(self.xfiltered_modifiers.len() - 1 - position, 0);
973 true
974 } else {
975 false
976 };
977
978 // Always update the modifiers when we're not replaying.
979 if !replay {
980 self.udpate_mods_from_core_event(window_id, xev.state as u16, &mut callback);
981 }
982
983 if keycode != 0 && !self.is_composing {
984 // Don't alter the modifiers state from replaying.
985 if replay {
986 self.send_synthic_modifier_from_core(window_id, xev.state as u16, &mut callback);
987 }
988
989 if let Some(mut key_processor) = self.xkb_context.key_context() {
990 let event = key_processor.process_key_event(keycode, state, repeat);
991 let event = Event::WindowEvent {
992 window_id,
993 event: WindowEvent::KeyboardInput {
994 device_id,
995 event,
996 is_synthetic: false,
997 },
998 };
999 callback(&self.target, event);
1000 }
1001
1002 // Restore the client's modifiers state after replay.
1003 if replay {
1004 self.send_modifiers(window_id, self.modifiers.get(), true, &mut callback);
1005 }
1006
1007 return;
1008 }
1009
1010 let wt = Self::window_target(&self.target);
1011
1012 if let Some(ic) = wt
1013 .ime
1014 .as_ref()
1015 .and_then(|ime| ime.borrow().get_context(window as XWindow))
1016 {
1017 let written = wt.xconn.lookup_utf8(ic, xev);
1018 if !written.is_empty() {
1019 let event = Event::WindowEvent {
1020 window_id,
1021 event: WindowEvent::Ime(Ime::Preedit(String::new(), None)),
1022 };
1023 callback(&self.target, event);
1024
1025 let event = Event::WindowEvent {
1026 window_id,
1027 event: WindowEvent::Ime(Ime::Commit(written)),
1028 };
1029
1030 self.is_composing = false;
1031 callback(&self.target, event);
1032 }
1033 }
1034 }
1035
1036 fn send_synthic_modifier_from_core<F>(
1037 &mut self,
1038 window_id: crate::window::WindowId,
1039 state: u16,
1040 mut callback: F,
1041 ) where
1042 F: FnMut(&RootELW<T>, Event<T>),
1043 {
1044 let keymap = match self.xkb_context.keymap_mut() {
1045 Some(keymap) => keymap,
1046 None => return,
1047 };
1048
1049 let wt = Self::window_target(&self.target);
1050 let xcb = wt.xconn.xcb_connection().get_raw_xcb_connection();
1051
1052 // Use synthetic state since we're replaying the modifier. The user modifier state
1053 // will be restored later.
1054 let mut xkb_state = match XkbState::new_x11(xcb, keymap) {
1055 Some(xkb_state) => xkb_state,
1056 None => return,
1057 };
1058
1059 let mask = self.xkb_mod_mask_from_core(state);
1060 xkb_state.update_modifiers(mask, 0, 0, 0, 0, Self::core_keyboard_group(state));
1061 let mods: ModifiersState = xkb_state.modifiers().into();
1062
1063 let event = Event::WindowEvent {
1064 window_id,
1065 event: WindowEvent::ModifiersChanged(mods.into()),
1066 };
1067
1068 callback(&self.target, event);
1069 }
1070
1071 fn xinput2_button_input<F>(&self, event: &XIDeviceEvent, state: ElementState, mut callback: F)
1072 where
1073 F: FnMut(&RootELW<T>, Event<T>),
1074 {
1075 let wt = Self::window_target(&self.target);
1076 let window_id = mkwid(event.event as xproto::Window);
1077 let device_id = mkdid(event.deviceid as xinput::DeviceId);
1078
1079 // Set the timestamp.
1080 wt.xconn.set_timestamp(event.time as xproto::Timestamp);
1081
1082 // Deliver multi-touch events instead of emulated mouse events.
1083 if (event.flags & xinput2::XIPointerEmulated) != 0 {
1084 return;
1085 }
1086
1087 let event = match event.detail as u32 {
1088 xlib::Button1 => WindowEvent::MouseInput {
1089 device_id,
1090 state,
1091 button: MouseButton::Left,
1092 },
1093 xlib::Button2 => WindowEvent::MouseInput {
1094 device_id,
1095 state,
1096 button: MouseButton::Middle,
1097 },
1098
1099 xlib::Button3 => WindowEvent::MouseInput {
1100 device_id,
1101 state,
1102 button: MouseButton::Right,
1103 },
1104
1105 // Suppress emulated scroll wheel clicks, since we handle the real motion events for those.
1106 // In practice, even clicky scroll wheels appear to be reported by evdev (and XInput2 in
1107 // turn) as axis motion, so we don't otherwise special-case these button presses.
1108 4..=7 => WindowEvent::MouseWheel {
1109 device_id,
1110 delta: match event.detail {
1111 4 => MouseScrollDelta::LineDelta(0.0, 1.0),
1112 5 => MouseScrollDelta::LineDelta(0.0, -1.0),
1113 6 => MouseScrollDelta::LineDelta(1.0, 0.0),
1114 7 => MouseScrollDelta::LineDelta(-1.0, 0.0),
1115 _ => unreachable!(),
1116 },
1117 phase: TouchPhase::Moved,
1118 },
1119 8 => WindowEvent::MouseInput {
1120 device_id,
1121 state,
1122 button: MouseButton::Back,
1123 },
1124
1125 9 => WindowEvent::MouseInput {
1126 device_id,
1127 state,
1128 button: MouseButton::Forward,
1129 },
1130 x => WindowEvent::MouseInput {
1131 device_id,
1132 state,
1133 button: MouseButton::Other(x as u16),
1134 },
1135 };
1136
1137 let event = Event::WindowEvent { window_id, event };
1138 callback(&self.target, event);
1139 }
1140
1141 fn xinput2_mouse_motion<F>(&self, event: &XIDeviceEvent, mut callback: F)
1142 where
1143 F: FnMut(&RootELW<T>, Event<T>),
1144 {
1145 let wt = Self::window_target(&self.target);
1146
1147 // Set the timestamp.
1148 wt.xconn.set_timestamp(event.time as xproto::Timestamp);
1149
1150 let device_id = mkdid(event.deviceid as xinput::DeviceId);
1151 let window = event.event as xproto::Window;
1152 let window_id = mkwid(window);
1153 let new_cursor_pos = (event.event_x, event.event_y);
1154
1155 let cursor_moved = self.with_window(window, |window| {
1156 let mut shared_state_lock = window.shared_state_lock();
1157 util::maybe_change(&mut shared_state_lock.cursor_pos, new_cursor_pos)
1158 });
1159
1160 if cursor_moved == Some(true) {
1161 let position = PhysicalPosition::new(event.event_x, event.event_y);
1162
1163 let event = Event::WindowEvent {
1164 window_id,
1165 event: WindowEvent::CursorMoved {
1166 device_id,
1167 position,
1168 },
1169 };
1170 callback(&self.target, event);
1171 } else if cursor_moved.is_none() {
1172 return;
1173 }
1174
1175 // More gymnastics, for self.devices
1176 let mask = unsafe {
1177 slice::from_raw_parts(event.valuators.mask, event.valuators.mask_len as usize)
1178 };
1179 let mut devices = self.devices.borrow_mut();
1180 let physical_device = match devices.get_mut(&DeviceId(event.sourceid as xinput::DeviceId)) {
1181 Some(device) => device,
1182 None => return,
1183 };
1184
1185 let mut events = Vec::new();
1186 let mut value = event.valuators.values;
1187 for i in 0..event.valuators.mask_len * 8 {
1188 if !xinput2::XIMaskIsSet(mask, i) {
1189 continue;
1190 }
1191
1192 let x = unsafe { *value };
1193
1194 let event = if let Some(&mut (_, ref mut info)) = physical_device
1195 .scroll_axes
1196 .iter_mut()
1197 .find(|&&mut (axis, _)| axis == i as _)
1198 {
1199 let delta = (x - info.position) / info.increment;
1200 info.position = x;
1201 // X11 vertical scroll coordinates are opposite to winit's
1202 let delta = match info.orientation {
1203 ScrollOrientation::Horizontal => {
1204 MouseScrollDelta::LineDelta(-delta as f32, 0.0)
1205 }
1206 ScrollOrientation::Vertical => MouseScrollDelta::LineDelta(0.0, -delta as f32),
1207 };
1208
1209 WindowEvent::MouseWheel {
1210 device_id,
1211 delta,
1212 phase: TouchPhase::Moved,
1213 }
1214 } else {
1215 WindowEvent::AxisMotion {
1216 device_id,
1217 axis: i as u32,
1218 value: unsafe { *value },
1219 }
1220 };
1221
1222 events.push(Event::WindowEvent { window_id, event });
1223
1224 value = unsafe { value.offset(1) };
1225 }
1226
1227 for event in events {
1228 callback(&self.target, event);
1229 }
1230 }
1231
1232 fn xinput2_mouse_enter<F>(&self, event: &XIEnterEvent, mut callback: F)
1233 where
1234 F: FnMut(&RootELW<T>, Event<T>),
1235 {
1236 let wt = Self::window_target(&self.target);
1237
1238 // Set the timestamp.
1239 wt.xconn.set_timestamp(event.time as xproto::Timestamp);
1240
1241 let window = event.event as xproto::Window;
1242 let window_id = mkwid(window);
1243 let device_id = mkdid(event.deviceid as xinput::DeviceId);
1244
1245 if let Some(all_info) = DeviceInfo::get(&wt.xconn, super::ALL_DEVICES.into()) {
1246 let mut devices = self.devices.borrow_mut();
1247 for device_info in all_info.iter() {
1248 if device_info.deviceid == event.sourceid
1249 // This is needed for resetting to work correctly on i3, and
1250 // presumably some other WMs. On those, `XI_Enter` doesn't include
1251 // the physical device ID, so both `sourceid` and `deviceid` are
1252 // the virtual device.
1253 || device_info.attachment == event.sourceid
1254 {
1255 let device_id = DeviceId(device_info.deviceid as _);
1256 if let Some(device) = devices.get_mut(&device_id) {
1257 device.reset_scroll_position(device_info);
1258 }
1259 }
1260 }
1261 }
1262
1263 if self.window_exists(window) {
1264 let position = PhysicalPosition::new(event.event_x, event.event_y);
1265
1266 let event = Event::WindowEvent {
1267 window_id,
1268 event: WindowEvent::CursorEntered { device_id },
1269 };
1270 callback(&self.target, event);
1271
1272 let event = Event::WindowEvent {
1273 window_id,
1274 event: WindowEvent::CursorMoved {
1275 device_id,
1276 position,
1277 },
1278 };
1279 callback(&self.target, event);
1280 }
1281 }
1282
1283 fn xinput2_mouse_left<F>(&self, event: &XILeaveEvent, mut callback: F)
1284 where
1285 F: FnMut(&RootELW<T>, Event<T>),
1286 {
1287 let wt = Self::window_target(&self.target);
1288 let window = event.event as xproto::Window;
1289
1290 // Set the timestamp.
1291 wt.xconn.set_timestamp(event.time as xproto::Timestamp);
1292
1293 // Leave, FocusIn, and FocusOut can be received by a window that's already
1294 // been destroyed, which the user presumably doesn't want to deal with.
1295 if self.window_exists(window) {
1296 let event = Event::WindowEvent {
1297 window_id: mkwid(window),
1298 event: WindowEvent::CursorLeft {
1299 device_id: mkdid(event.deviceid as xinput::DeviceId),
1300 },
1301 };
1302 callback(&self.target, event);
1303 }
1304 }
1305
1306 fn xinput2_focused<F>(&mut self, xev: &XIFocusInEvent, mut callback: F)
1307 where
1308 F: FnMut(&RootELW<T>, Event<T>),
1309 {
1310 let wt = Self::window_target(&self.target);
1311 let window = xev.event as xproto::Window;
1312
1313 // Set the timestamp.
1314 wt.xconn.set_timestamp(xev.time as xproto::Timestamp);
1315
1316 if let Some(ime) = wt.ime.as_ref() {
1317 ime.borrow_mut()
1318 .focus(xev.event)
1319 .expect("Failed to focus input context");
1320 }
1321
1322 if self.active_window == Some(window) {
1323 return;
1324 }
1325
1326 self.active_window = Some(window);
1327
1328 wt.update_listen_device_events(true);
1329
1330 let window_id = mkwid(window);
1331 let position = PhysicalPosition::new(xev.event_x, xev.event_y);
1332
1333 if let Some(window) = self.with_window(window, Arc::clone) {
1334 window.shared_state_lock().has_focus = true;
1335 }
1336
1337 let event = Event::WindowEvent {
1338 window_id,
1339 event: WindowEvent::Focused(true),
1340 };
1341 callback(&self.target, event);
1342
1343 // Issue key press events for all pressed keys
1344 Self::handle_pressed_keys(
1345 &self.target,
1346 window_id,
1347 ElementState::Pressed,
1348 &mut self.xkb_context,
1349 &mut callback,
1350 );
1351
1352 self.update_mods_from_query(window_id, &mut callback);
1353
1354 // The deviceid for this event is for a keyboard instead of a pointer,
1355 // so we have to do a little extra work.
1356 let pointer_id = self
1357 .devices
1358 .borrow()
1359 .get(&DeviceId(xev.deviceid as xinput::DeviceId))
1360 .map(|device| device.attachment)
1361 .unwrap_or(2);
1362
1363 let event = Event::WindowEvent {
1364 window_id,
1365 event: WindowEvent::CursorMoved {
1366 device_id: mkdid(pointer_id as _),
1367 position,
1368 },
1369 };
1370 callback(&self.target, event);
1371 }
1372
1373 fn xinput2_unfocused<F>(&mut self, xev: &XIFocusOutEvent, mut callback: F)
1374 where
1375 F: FnMut(&RootELW<T>, Event<T>),
1376 {
1377 let wt = Self::window_target(&self.target);
1378 let window = xev.event as xproto::Window;
1379
1380 // Set the timestamp.
1381 wt.xconn.set_timestamp(xev.time as xproto::Timestamp);
1382
1383 if !self.window_exists(window) {
1384 return;
1385 }
1386
1387 if let Some(ime) = wt.ime.as_ref() {
1388 ime.borrow_mut()
1389 .unfocus(xev.event)
1390 .expect("Failed to unfocus input context");
1391 }
1392
1393 if self.active_window.take() == Some(window) {
1394 let window_id = mkwid(window);
1395
1396 wt.update_listen_device_events(false);
1397
1398 // Clear the modifiers when unfocusing the window.
1399 if let Some(xkb_state) = self.xkb_context.state_mut() {
1400 xkb_state.update_modifiers(0, 0, 0, 0, 0, 0);
1401 let mods = xkb_state.modifiers();
1402 self.send_modifiers(window_id, mods.into(), true, &mut callback);
1403 }
1404
1405 // Issue key release events for all pressed keys
1406 Self::handle_pressed_keys(
1407 &self.target,
1408 window_id,
1409 ElementState::Released,
1410 &mut self.xkb_context,
1411 &mut callback,
1412 );
1413
1414 // Clear this so detecting key repeats is consistently handled when the
1415 // window regains focus.
1416 self.held_key_press = None;
1417
1418 if let Some(window) = self.with_window(window, Arc::clone) {
1419 window.shared_state_lock().has_focus = false;
1420 }
1421
1422 let event = Event::WindowEvent {
1423 window_id,
1424 event: WindowEvent::Focused(false),
1425 };
1426 callback(&self.target, event)
1427 }
1428 }
1429
1430 fn xinput2_touch<F>(&mut self, xev: &XIDeviceEvent, phase: TouchPhase, mut callback: F)
1431 where
1432 F: FnMut(&RootELW<T>, Event<T>),
1433 {
1434 let wt = Self::window_target(&self.target);
1435
1436 // Set the timestamp.
1437 wt.xconn.set_timestamp(xev.time as xproto::Timestamp);
1438
1439 let window = xev.event as xproto::Window;
1440 if self.window_exists(window) {
1441 let window_id = mkwid(window);
1442 let id = xev.detail as u64;
1443 let location = PhysicalPosition::new(xev.event_x, xev.event_y);
1444
1445 // Mouse cursor position changes when touch events are received.
1446 // Only the first concurrently active touch ID moves the mouse cursor.
1447 if is_first_touch(&mut self.first_touch, &mut self.num_touch, id, phase) {
1448 let event = Event::WindowEvent {
1449 window_id,
1450 event: WindowEvent::CursorMoved {
1451 device_id: mkdid(util::VIRTUAL_CORE_POINTER),
1452 position: location.cast(),
1453 },
1454 };
1455 callback(&self.target, event);
1456 }
1457
1458 let event = Event::WindowEvent {
1459 window_id,
1460 event: WindowEvent::Touch(Touch {
1461 device_id: mkdid(xev.deviceid as xinput::DeviceId),
1462 phase,
1463 location,
1464 force: None, // TODO
1465 id,
1466 }),
1467 };
1468 callback(&self.target, event)
1469 }
1470 }
1471
1472 fn xinput2_raw_button_input<F>(&self, xev: &XIRawEvent, state: ElementState, mut callback: F)
1473 where
1474 F: FnMut(&RootELW<T>, Event<T>),
1475 {
1476 let wt = Self::window_target(&self.target);
1477
1478 // Set the timestamp.
1479 wt.xconn.set_timestamp(xev.time as xproto::Timestamp);
1480
1481 if xev.flags & xinput2::XIPointerEmulated == 0 {
1482 let event = Event::DeviceEvent {
1483 device_id: mkdid(xev.deviceid as xinput::DeviceId),
1484 event: DeviceEvent::Button {
1485 state,
1486 button: xev.detail as u32,
1487 },
1488 };
1489 callback(&self.target, event);
1490 }
1491 }
1492
1493 fn xinput2_raw_mouse_motion<F>(&self, xev: &XIRawEvent, mut callback: F)
1494 where
1495 F: FnMut(&RootELW<T>, 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 did = mkdid(xev.deviceid as xinput::DeviceId);
1503
1504 let mask =
1505 unsafe { slice::from_raw_parts(xev.valuators.mask, xev.valuators.mask_len as usize) };
1506 let mut value = xev.raw_values;
1507 let mut mouse_delta = util::Delta::default();
1508 let mut scroll_delta = util::Delta::default();
1509 for i in 0..xev.valuators.mask_len * 8 {
1510 if !xinput2::XIMaskIsSet(mask, i) {
1511 continue;
1512 }
1513 let x = unsafe { *value };
1514
1515 // We assume that every XInput2 device with analog axes is a pointing device emitting
1516 // relative coordinates.
1517 match i {
1518 0 => mouse_delta.set_x(x),
1519 1 => mouse_delta.set_y(x),
1520 2 => scroll_delta.set_x(x as f32),
1521 3 => scroll_delta.set_y(x as f32),
1522 _ => {}
1523 }
1524
1525 let event = Event::DeviceEvent {
1526 device_id: did,
1527 event: DeviceEvent::Motion {
1528 axis: i as u32,
1529 value: x,
1530 },
1531 };
1532 callback(&self.target, event);
1533
1534 value = unsafe { value.offset(1) };
1535 }
1536
1537 if let Some(mouse_delta) = mouse_delta.consume() {
1538 let event = Event::DeviceEvent {
1539 device_id: did,
1540 event: DeviceEvent::MouseMotion { delta: mouse_delta },
1541 };
1542 callback(&self.target, event);
1543 }
1544
1545 if let Some(scroll_delta) = scroll_delta.consume() {
1546 let event = Event::DeviceEvent {
1547 device_id: did,
1548 event: DeviceEvent::MouseWheel {
1549 delta: MouseScrollDelta::LineDelta(scroll_delta.0, scroll_delta.1),
1550 },
1551 };
1552 callback(&self.target, event);
1553 }
1554 }
1555
1556 fn xinput2_raw_key_input<F>(&mut self, xev: &XIRawEvent, state: ElementState, mut callback: F)
1557 where
1558 F: FnMut(&RootELW<T>, Event<T>),
1559 {
1560 let wt = Self::window_target(&self.target);
1561
1562 // Set the timestamp.
1563 wt.xconn.set_timestamp(xev.time as xproto::Timestamp);
1564
1565 let device_id = mkdid(xev.sourceid as xinput::DeviceId);
1566 let keycode = xev.detail as u32;
1567 if keycode < KEYCODE_OFFSET as u32 {
1568 return;
1569 }
1570 let physical_key = xkb::raw_keycode_to_physicalkey(keycode);
1571
1572 callback(
1573 &self.target,
1574 Event::DeviceEvent {
1575 device_id,
1576 event: DeviceEvent::Key(RawKeyEvent {
1577 physical_key,
1578 state,
1579 }),
1580 },
1581 );
1582 }
1583
1584 fn xinput2_hierarchy_changed<F>(&mut self, xev: &XIHierarchyEvent, mut callback: F)
1585 where
1586 F: FnMut(&RootELW<T>, Event<T>),
1587 {
1588 let wt = Self::window_target(&self.target);
1589
1590 // Set the timestamp.
1591 wt.xconn.set_timestamp(xev.time as xproto::Timestamp);
1592 let infos = unsafe { slice::from_raw_parts(xev.info, xev.num_info as usize) };
1593 for info in infos {
1594 if 0 != info.flags & (xinput2::XISlaveAdded | xinput2::XIMasterAdded) {
1595 self.init_device(info.deviceid as xinput::DeviceId);
1596 callback(
1597 &self.target,
1598 Event::DeviceEvent {
1599 device_id: mkdid(info.deviceid as xinput::DeviceId),
1600 event: DeviceEvent::Added,
1601 },
1602 );
1603 } else if 0 != info.flags & (xinput2::XISlaveRemoved | xinput2::XIMasterRemoved) {
1604 callback(
1605 &self.target,
1606 Event::DeviceEvent {
1607 device_id: mkdid(info.deviceid as xinput::DeviceId),
1608 event: DeviceEvent::Removed,
1609 },
1610 );
1611 let mut devices = self.devices.borrow_mut();
1612 devices.remove(&DeviceId(info.deviceid as xinput::DeviceId));
1613 }
1614 }
1615 }
1616
1617 fn xkb_event<F>(&mut self, xev: &XkbAnyEvent, mut callback: F)
1618 where
1619 F: FnMut(&RootELW<T>, Event<T>),
1620 {
1621 let wt = Self::window_target(&self.target);
1622 match xev.xkb_type {
1623 xlib::XkbNewKeyboardNotify => {
1624 let xev = unsafe { &*(xev as *const _ as *const xlib::XkbNewKeyboardNotifyEvent) };
1625
1626 // Set the timestamp.
1627 wt.xconn.set_timestamp(xev.time as xproto::Timestamp);
1628
1629 let keycodes_changed_flag = 0x1;
1630 let geometry_changed_flag = 0x1 << 1;
1631
1632 let keycodes_changed = util::has_flag(xev.changed, keycodes_changed_flag);
1633 let geometry_changed = util::has_flag(xev.changed, geometry_changed_flag);
1634
1635 if xev.device == self.xkb_context.core_keyboard_id
1636 && (keycodes_changed || geometry_changed)
1637 {
1638 let xcb = wt.xconn.xcb_connection().get_raw_xcb_connection();
1639 self.xkb_context.set_keymap_from_x11(xcb);
1640 self.xmodmap.reload_from_x_connection(&wt.xconn);
1641
1642 let window_id = match self.active_window.map(super::mkwid) {
1643 Some(window_id) => window_id,
1644 None => return,
1645 };
1646
1647 if let Some(state) = self.xkb_context.state_mut() {
1648 let mods = state.modifiers().into();
1649 self.send_modifiers(window_id, mods, true, &mut callback);
1650 }
1651 }
1652 }
1653 xlib::XkbMapNotify => {
1654 let xcb = wt.xconn.xcb_connection().get_raw_xcb_connection();
1655 self.xkb_context.set_keymap_from_x11(xcb);
1656 self.xmodmap.reload_from_x_connection(&wt.xconn);
1657 let window_id = match self.active_window.map(super::mkwid) {
1658 Some(window_id) => window_id,
1659 None => return,
1660 };
1661
1662 if let Some(state) = self.xkb_context.state_mut() {
1663 let mods = state.modifiers().into();
1664 self.send_modifiers(window_id, mods, true, &mut callback);
1665 }
1666 }
1667 xlib::XkbStateNotify => {
1668 let xev = unsafe { &*(xev as *const _ as *const xlib::XkbStateNotifyEvent) };
1669
1670 // Set the timestamp.
1671 wt.xconn.set_timestamp(xev.time as xproto::Timestamp);
1672
1673 if let Some(state) = self.xkb_context.state_mut() {
1674 state.update_modifiers(
1675 xev.base_mods,
1676 xev.latched_mods,
1677 xev.locked_mods,
1678 xev.base_group as u32,
1679 xev.latched_group as u32,
1680 xev.locked_group as u32,
1681 );
1682
1683 let window_id = match self.active_window.map(super::mkwid) {
1684 Some(window_id) => window_id,
1685 None => return,
1686 };
1687
1688 let mods = state.modifiers().into();
1689 self.send_modifiers(window_id, mods, true, &mut callback);
1690 }
1691 }
1692 _ => {}
1693 }
1694 }
1695
1696 pub fn update_mods_from_xinput2_event<F>(
1697 &mut self,
1698 mods: &XIModifierState,
1699 group: &XIModifierState,
1700 force: bool,
1701 mut callback: F,
1702 ) where
1703 F: FnMut(&RootELW<T>, Event<T>),
1704 {
1705 if let Some(state) = self.xkb_context.state_mut() {
1706 state.update_modifiers(
1707 mods.base as u32,
1708 mods.latched as u32,
1709 mods.locked as u32,
1710 group.base as u32,
1711 group.latched as u32,
1712 group.locked as u32,
1713 );
1714
1715 // NOTE: we use active window since generally sub windows don't have keyboard input,
1716 // and winit assumes that unfocused window doesn't have modifiers.
1717 let window_id = match self.active_window.map(super::mkwid) {
1718 Some(window_id) => window_id,
1719 None => return,
1720 };
1721
1722 let mods = state.modifiers();
1723 self.send_modifiers(window_id, mods.into(), force, &mut callback);
1724 }
1725 }
1726
1727 fn update_mods_from_query<F>(&mut self, window_id: crate::window::WindowId, mut callback: F)
1728 where
1729 F: FnMut(&RootELW<T>, Event<T>),
1730 {
1731 let wt = Self::window_target(&self.target);
1732
1733 let xkb_state = match self.xkb_context.state_mut() {
1734 Some(xkb_state) => xkb_state,
1735 None => return,
1736 };
1737
1738 unsafe {
1739 let mut state: XkbStateRec = std::mem::zeroed();
1740 if (wt.xconn.xlib.XkbGetState)(wt.xconn.display, XkbId::USE_CORE_KBD.into(), &mut state)
1741 == xlib::True
1742 {
1743 xkb_state.update_modifiers(
1744 state.base_mods as u32,
1745 state.latched_mods as u32,
1746 state.locked_mods as u32,
1747 state.base_group as u32,
1748 state.latched_group as u32,
1749 state.locked_group as u32,
1750 );
1751 }
1752 }
1753
1754 let mods = xkb_state.modifiers();
1755 self.send_modifiers(window_id, mods.into(), true, &mut callback)
1756 }
1757
1758 pub fn udpate_mods_from_core_event<F>(
1759 &mut self,
1760 window_id: crate::window::WindowId,
1761 state: u16,
1762 mut callback: F,
1763 ) where
1764 F: FnMut(&RootELW<T>, Event<T>),
1765 {
1766 let xkb_mask = self.xkb_mod_mask_from_core(state);
1767 let xkb_state = match self.xkb_context.state_mut() {
1768 Some(xkb_state) => xkb_state,
1769 None => return,
1770 };
1771
1772 // NOTE: this is inspired by Qt impl.
1773 let mut depressed = xkb_state.depressed_modifiers() & xkb_mask;
1774 let latched = xkb_state.latched_modifiers() & xkb_mask;
1775 let locked = xkb_state.locked_modifiers() & xkb_mask;
1776 // Set modifiers in depressed if they don't appear in any of the final masks.
1777 depressed |= !(depressed | latched | locked) & xkb_mask;
1778
1779 xkb_state.update_modifiers(
1780 depressed,
1781 latched,
1782 locked,
1783 0,
1784 0,
1785 Self::core_keyboard_group(state),
1786 );
1787
1788 let mods = xkb_state.modifiers();
1789 self.send_modifiers(window_id, mods.into(), false, &mut callback);
1790 }
1791
1792 // Bits 13 and 14 report the state keyboard group.
1793 pub fn core_keyboard_group(state: u16) -> u32 {
1794 ((state >> 13) & 3) as u32
1795 }
1796
1797 pub fn xkb_mod_mask_from_core(&mut self, state: u16) -> xkb_mod_mask_t {
1798 let mods_indices = match self.xkb_context.keymap_mut() {
1799 Some(keymap) => keymap.mods_indices(),
1800 None => return 0,
1801 };
1802
1803 // Build the XKB modifiers from the regular state.
1804 let mut depressed = 0u32;
1805 if let Some(shift) = mods_indices
1806 .shift
1807 .filter(|_| ModMask::SHIFT.intersects(state))
1808 {
1809 depressed |= 1 << shift;
1810 }
1811 if let Some(caps) = mods_indices
1812 .caps
1813 .filter(|_| ModMask::LOCK.intersects(state))
1814 {
1815 depressed |= 1 << caps;
1816 }
1817 if let Some(ctrl) = mods_indices
1818 .ctrl
1819 .filter(|_| ModMask::CONTROL.intersects(state))
1820 {
1821 depressed |= 1 << ctrl;
1822 }
1823 if let Some(alt) = mods_indices.alt.filter(|_| ModMask::M1.intersects(state)) {
1824 depressed |= 1 << alt;
1825 }
1826 if let Some(num) = mods_indices.num.filter(|_| ModMask::M2.intersects(state)) {
1827 depressed |= 1 << num;
1828 }
1829 if let Some(mod3) = mods_indices.mod3.filter(|_| ModMask::M3.intersects(state)) {
1830 depressed |= 1 << mod3;
1831 }
1832 if let Some(logo) = mods_indices.logo.filter(|_| ModMask::M4.intersects(state)) {
1833 depressed |= 1 << logo;
1834 }
1835 if let Some(mod5) = mods_indices.mod5.filter(|_| ModMask::M5.intersects(state)) {
1836 depressed |= 1 << mod5;
1837 }
1838
1839 depressed
1840 }
1841
1842 /// Send modifiers for the active window.
1843 ///
1844 /// The event won't be sent when the `modifiers` match the previously `sent` modifiers value,
1845 /// unless `force` is passed. The `force` should be passed when the active window changes.
1846 fn send_modifiers<F: FnMut(&RootELW<T>, Event<T>)>(
1847 &self,
1848 window_id: crate::window::WindowId,
1849 modifiers: ModifiersState,
1850 force: bool,
1851 callback: &mut F,
1852 ) {
1853 // NOTE: Always update the modifiers to account for case when they've changed
1854 // and forced was `true`.
1855 if self.modifiers.replace(modifiers) != modifiers || force {
1856 let event = Event::WindowEvent {
1857 window_id,
1858 event: WindowEvent::ModifiersChanged(self.modifiers.get().into()),
1859 };
1860 callback(&self.target, event);
1861 }
1862 }
1863
1864 fn handle_pressed_keys<F>(
1865 target: &RootELW<T>,
1866 window_id: crate::window::WindowId,
1867 state: ElementState,
1868 xkb_context: &mut Context,
1869 callback: &mut F,
1870 ) where
1871 F: FnMut(&RootELW<T>, Event<T>),
1872 {
1873 let device_id = mkdid(util::VIRTUAL_CORE_KEYBOARD);
1874
1875 // Update modifiers state and emit key events based on which keys are currently pressed.
1876 let window_target = Self::window_target(target);
1877 let xcb = window_target
1878 .xconn
1879 .xcb_connection()
1880 .get_raw_xcb_connection();
1881
1882 let keymap = match xkb_context.keymap_mut() {
1883 Some(keymap) => keymap,
1884 None => return,
1885 };
1886
1887 // Send the keys using the sythetic state to not alter the main state.
1888 let mut xkb_state = match XkbState::new_x11(xcb, keymap) {
1889 Some(xkb_state) => xkb_state,
1890 None => return,
1891 };
1892 let mut key_processor = match xkb_context.key_context_with_state(&mut xkb_state) {
1893 Some(key_processor) => key_processor,
1894 None => return,
1895 };
1896
1897 for keycode in window_target
1898 .xconn
1899 .query_keymap()
1900 .into_iter()
1901 .filter(|k| *k >= KEYCODE_OFFSET)
1902 {
1903 let event = key_processor.process_key_event(keycode as u32, state, false);
1904 let event = Event::WindowEvent {
1905 window_id,
1906 event: WindowEvent::KeyboardInput {
1907 device_id,
1908 event,
1909 is_synthetic: true,
1910 },
1911 };
1912 callback(target, event);
1913 }
1914 }
1915
1916 fn process_dpi_change<F>(&self, callback: &mut F)
1917 where
1918 F: FnMut(&RootELW<T>, Event<T>),
1919 {
1920 let wt = Self::window_target(&self.target);
1921 wt.xconn
1922 .reload_database()
1923 .expect("failed to reload Xft database");
1924
1925 // In the future, it would be quite easy to emit monitor hotplug events.
1926 let prev_list = {
1927 let prev_list = wt.xconn.invalidate_cached_monitor_list();
1928 match prev_list {
1929 Some(prev_list) => prev_list,
1930 None => return,
1931 }
1932 };
1933
1934 let new_list = wt
1935 .xconn
1936 .available_monitors()
1937 .expect("Failed to get monitor list");
1938 for new_monitor in new_list {
1939 // Previous list may be empty, in case of disconnecting and
1940 // reconnecting the only one monitor. We still need to emit events in
1941 // this case.
1942 let maybe_prev_scale_factor = prev_list
1943 .iter()
1944 .find(|prev_monitor| prev_monitor.name == new_monitor.name)
1945 .map(|prev_monitor| prev_monitor.scale_factor);
1946 if Some(new_monitor.scale_factor) != maybe_prev_scale_factor {
1947 for window in wt.windows.borrow().iter().filter_map(|(_, w)| w.upgrade()) {
1948 window.refresh_dpi_for_monitor(&new_monitor, maybe_prev_scale_factor, |event| {
1949 callback(&self.target, event);
1950 })
1951 }
1952 }
1953 }
1954 }
1955
1956 fn window_exists(&self, window_id: xproto::Window) -> bool {
1957 self.with_window(window_id, |_| ()).is_some()
1958 }
1959}
1960
1961fn is_first_touch(first: &mut Option<u64>, num: &mut u32, id: u64, phase: TouchPhase) -> bool {
1962 match phase {
1963 TouchPhase::Started => {
1964 if *num == 0 {
1965 *first = Some(id);
1966 }
1967 *num += 1;
1968 }
1969 TouchPhase::Cancelled | TouchPhase::Ended => {
1970 if *first == Some(id) {
1971 *first = None;
1972 }
1973 *num = num.saturating_sub(1);
1974 }
1975 _ => (),
1976 }
1977
1978 *first == Some(id)
1979}
1980