Support setting _NET_WM_PID in X11 environments

Support is added for setting _NET_WM_PID automatically. This is to
support scripting of the window environment. For example, this makes it
possible to script opening a window with same CWD:

1. Retrieve the current window
2. (new) get PID of window
3. Check if it's Alacritty, find first child (presumably a shell), and
   get the child's cwd.
4. Spawn new instance of terminal with cwd.

Unaddressed in this commit is how this will coexist on a Wayland system.
This commit is contained in:
Joe Wilm 2017-04-26 10:26:46 -07:00 committed by Joe Wilm
parent 09031decc0
commit 574586045f
4 changed files with 57 additions and 2 deletions

1
Cargo.lock generated
View File

@ -24,6 +24,7 @@ dependencies = [
"serde_yaml 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
"vte 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"x11-dl 2.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
"xdg 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
]

View File

@ -35,6 +35,9 @@ unicode-width = "0.1.4"
clippy = { version = "0.0.104", optional = true }
[target.'cfg(any(target_os = "linux", target_os = "freebsd", target_os="dragonfly", target_os="openbsd"))'.dependencies]
x11-dl = "2.12.0"
[features]
default = ["err-println"]
# Enabling this feature makes shaders automatically reload when changed

View File

@ -27,6 +27,9 @@
#[macro_use] extern crate log;
#[macro_use] extern crate serde_derive;
#[cfg(any(target_os = "linux", target_os = "freebsd", target_os="dragonfly", target_os="openbsd"))]
extern crate x11_dl;
extern crate cgmath;
extern crate copypasta;
extern crate errno;

View File

@ -217,10 +217,14 @@ impl Window {
window.make_current()?;
}
Ok(Window {
let window = Window {
glutin_window: window,
cursor_visible: true,
})
};
window.run_os_extensions();
Ok(window)
}
/// Get some properties about the device
@ -301,6 +305,50 @@ impl Window {
}
}
pub trait OsExtensions {
fn run_os_extensions(&self) {}
}
#[cfg(not(any(target_os = "linux", target_os = "freebsd", target_os="dragonfly", target_os="openbsd")))]
impl OsExtensions for Window { }
#[cfg(any(target_os = "linux", target_os = "freebsd", target_os="dragonfly", target_os="openbsd"))]
impl OsExtensions for Window {
fn run_os_extensions(&self) {
use ::glutin::os::unix::WindowExt;
use ::x11_dl::xlib::{self, XA_CARDINAL, PropModeReplace};
use ::std::ffi::{CStr};
use ::std::ptr;
use ::libc::getpid;
let xlib_display = self.glutin_window.get_xlib_display();
let xlib_window = self.glutin_window.get_xlib_window();
if let (Some(xlib_window), Some(xlib_display)) = (xlib_window, xlib_display) {
let xlib = xlib::Xlib::open().expect("get xlib");
// Set _NET_WM_PID to process pid
unsafe {
let _net_wm_pid = CStr::from_ptr(b"_NET_WM_PID\0".as_ptr() as *const _);
let atom = (xlib.XInternAtom)(xlib_display as *mut _, _net_wm_pid.as_ptr(), 0);
let pid = getpid();
(xlib.XChangeProperty)(xlib_display as _, xlib_window as _, atom,
XA_CARDINAL, 32, PropModeReplace, &pid as *const i32 as *const u8, 1);
}
// Although this call doesn't actually pass any data, it does cause
// WM_CLIENT_MACHINE to be set. WM_CLIENT_MACHINE MUST be set if _NET_WM_PID is set
// (which we do above).
unsafe {
(xlib.XSetWMProperties)(xlib_display as _, xlib_window as _, ptr::null_mut(),
ptr::null_mut(), ptr::null_mut(), 0, ptr::null_mut(), ptr::null_mut(),
ptr::null_mut());
}
}
}
}
impl Proxy {
/// Wakes up the event loop of the window
///