diff options
author | mkosem <mattkosem@gmail.com> | 2019-09-24 13:43:54 -0400 |
---|---|---|
committer | Christian Duerr <contact@christianduerr.com> | 2019-09-24 19:43:54 +0200 |
commit | c1f089970fd3d4b9137d07647f8cd028b2b5b3a9 (patch) | |
tree | b8a8d9a62fa387f6b30e83b046f8beb4c521dbd7 /alacritty_terminal/src | |
parent | 856cddc8739c32d8bbfff72dd3692f49359142a9 (diff) | |
download | alacritty-c1f089970fd3d4b9137d07647f8cd028b2b5b3a9.tar.gz alacritty-c1f089970fd3d4b9137d07647f8cd028b2b5b3a9.zip |
Add Xembed support
Fixes #631.
Diffstat (limited to 'alacritty_terminal/src')
-rw-r--r-- | alacritty_terminal/src/config/window.rs | 4 | ||||
-rw-r--r-- | alacritty_terminal/src/window.rs | 57 |
2 files changed, 59 insertions, 2 deletions
diff --git a/alacritty_terminal/src/config/window.rs b/alacritty_terminal/src/config/window.rs index 60298383..7ca90a5b 100644 --- a/alacritty_terminal/src/config/window.rs +++ b/alacritty_terminal/src/config/window.rs @@ -39,6 +39,10 @@ pub struct WindowConfig { #[serde(deserialize_with = "from_string_or_deserialize")] pub class: Class, + /// XEmbed parent + #[serde(skip)] + pub embed: Option<u64>, + /// GTK theme variant #[serde(deserialize_with = "option_explicit_none")] pub gtk_theme_variant: Option<String>, diff --git a/alacritty_terminal/src/window.rs b/alacritty_terminal/src/window.rs index b5c56d3c..3e3f47f7 100644 --- a/alacritty_terminal/src/window.rs +++ b/alacritty_terminal/src/window.rs @@ -12,11 +12,10 @@ // See the License for the specific language governing permissions and // limitations under the License. use std::convert::From; -#[cfg(not(any(target_os = "macos", target_os = "windows")))] +#[cfg(not(any(target_os = "macos", windows)))] use std::ffi::c_void; use std::fmt::Display; -use crate::gl; use glutin::dpi::{LogicalPosition, LogicalSize, PhysicalSize}; #[cfg(target_os = "macos")] use glutin::os::macos::WindowExt; @@ -24,14 +23,19 @@ use glutin::os::macos::WindowExt; use glutin::os::unix::{EventsLoopExt, WindowExt}; #[cfg(not(target_os = "macos"))] use glutin::Icon; +#[cfg(not(any(target_os = "macos", windows)))] +use glutin::Window as GlutinWindow; use glutin::{ self, ContextBuilder, ControlFlow, Event, EventsLoop, MouseCursor, PossiblyCurrent, WindowBuilder, }; #[cfg(not(target_os = "macos"))] use image::ImageFormat; +#[cfg(not(any(target_os = "macos", windows)))] +use x11_dl::xlib::{Xlib, Display as XDisplay, PropModeReplace, XErrorEvent}; use crate::config::{Config, Decorations, StartupMode, WindowConfig}; +use crate::gl; // It's required to be in this directory due to the `windows.rc` file #[cfg(not(target_os = "macos"))] @@ -167,6 +171,16 @@ impl Window { // Set OpenGL symbol loader. This call MUST be after window.make_current on windows. gl::load_with(|symbol| windowed_context.get_proc_address(symbol) as *const _); + // On X11, embed the window inside another if the parent ID has been set + #[cfg(not(any(target_os = "macos", windows)))] + { + if event_loop.is_x11() { + if let Some(parent_window_id) = config.window.embed { + x_embed_window(window, parent_window_id); + } + } + } + let window = Window { event_loop, current_mouse_cursor: MouseCursor::Default, @@ -409,6 +423,45 @@ impl Window { } } +#[cfg(not(any(target_os = "macos", windows)))] +fn x_embed_window(window: &GlutinWindow, parent_id: u64) { + let (xlib_display, xlib_window) = match (window.get_xlib_display(), window.get_xlib_window()) { + (Some(display), Some(window)) => (display, window), + _ => return, + }; + + let xlib = Xlib::open().expect("get xlib"); + + unsafe { + let atom = (xlib.XInternAtom)(xlib_display as *mut _, "_XEMBED".as_ptr() as *const _, 0); + (xlib.XChangeProperty)( + xlib_display as _, + xlib_window as _, + atom, + atom, + 32, + PropModeReplace, + [0, 1].as_ptr(), + 2, + ); + + // Register new error handler + let old_handler = (xlib.XSetErrorHandler)(Some(xembed_error_handler)); + + // Check for the existence of the target before attempting reparenting + (xlib.XReparentWindow)(xlib_display as _, xlib_window as _, parent_id, 0, 0); + + // Drain errors and restore original error handler + (xlib.XSync)(xlib_display as _, 0); + (xlib.XSetErrorHandler)(old_handler); + } +} + +#[cfg(not(any(target_os = "macos", windows)))] +unsafe extern "C" fn xembed_error_handler(_: *mut XDisplay, _: *mut XErrorEvent) -> i32 { + die!("Could not embed into specified window."); +} + impl Proxy { /// Wakes up the event loop of the window /// |