From 23354cf1a54002e28fec92a26b65cce47f89ba6e Mon Sep 17 00:00:00 2001 From: Ho-Yon Mak Date: Fri, 28 Jun 2019 01:40:27 +0100 Subject: [PATCH] Implement _NET_WM_PING for X11 (#977) --- CHANGELOG.md | 1 + src/platform_impl/linux/x11/event_processor.rs | 10 ++++++++++ src/platform_impl/linux/x11/mod.rs | 4 ++++ src/platform_impl/linux/x11/window.rs | 5 +++-- 4 files changed, 18 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a81c8ba4..19e81b1b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ - On Mac, implement `DeviceEvent::Button`. - Change `Event::Suspended(true / false)` to `Event::Suspended` and `Event::Resumed`. - On X11, fix sanity check which checks that a monitor's reported width and height (in millimeters) are non-zero when calculating the DPI factor. +- On X11, implement `_NET_WM_PING` to allow desktop environment to kill unresponsive programs. - On Windows, when a window is initially invisible, it won't take focus from the existing visible windows. # 0.20.0 Alpha 1 diff --git a/src/platform_impl/linux/x11/event_processor.rs b/src/platform_impl/linux/x11/event_processor.rs index edabc02a..572889b4 100644 --- a/src/platform_impl/linux/x11/event_processor.rs +++ b/src/platform_impl/linux/x11/event_processor.rs @@ -131,6 +131,16 @@ impl EventProcessor { window_id, event: WindowEvent::CloseRequested, }); + } else if client_msg.data.get_long(0) as ffi::Atom == wt.net_wm_ping { + let response_msg: &mut ffi::XClientMessageEvent = xev.as_mut(); + response_msg.window = wt.root; + wt.xconn + .send_event( + wt.root, + Some(ffi::SubstructureNotifyMask | ffi::SubstructureRedirectMask), + *response_msg, + ) + .queue(); } else if client_msg.message_type == self.dnd.atoms.enter { let source_window = client_msg.data.get_long(0) as c_ulong; let flags = client_msg.data.get_long(1); diff --git a/src/platform_impl/linux/x11/mod.rs b/src/platform_impl/linux/x11/mod.rs index 65f0737d..ba61e719 100644 --- a/src/platform_impl/linux/x11/mod.rs +++ b/src/platform_impl/linux/x11/mod.rs @@ -46,6 +46,7 @@ use crate::{ pub struct EventLoopWindowTarget { xconn: Arc, wm_delete_window: ffi::Atom, + net_wm_ping: ffi::Atom, ime_sender: ImeSender, root: ffi::Window, ime: RefCell, @@ -75,6 +76,8 @@ impl EventLoop { let wm_delete_window = unsafe { xconn.get_atom_unchecked(b"WM_DELETE_WINDOW\0") }; + let net_wm_ping = unsafe { xconn.get_atom_unchecked(b"_NET_WM_PING\0") }; + let dnd = Dnd::new(Arc::clone(&xconn)) .expect("Failed to call XInternAtoms when initializing drag and drop"); @@ -142,6 +145,7 @@ impl EventLoop { ime_sender, xconn, wm_delete_window, + net_wm_ping, pending_redraws: Default::default(), }), _marker: ::std::marker::PhantomData, diff --git a/src/platform_impl/linux/x11/window.rs b/src/platform_impl/linux/x11/window.rs index 5e973e93..fd85ec84 100644 --- a/src/platform_impl/linux/x11/window.rs +++ b/src/platform_impl/linux/x11/window.rs @@ -330,8 +330,9 @@ impl UnownedWindow { (xconn.xlib.XSetWMProtocols)( xconn.display, window.xwindow, - &event_loop.wm_delete_window as *const ffi::Atom as *mut ffi::Atom, - 1, + &[event_loop.wm_delete_window, event_loop.net_wm_ping] as *const ffi::Atom + as *mut ffi::Atom, + 2, ); } //.queue();