summaryrefslogtreecommitdiff
path: root/alacritty_terminal/src
diff options
context:
space:
mode:
authormkosem <mattkosem@gmail.com>2019-09-24 13:43:54 -0400
committerChristian Duerr <contact@christianduerr.com>2019-09-24 19:43:54 +0200
commitc1f089970fd3d4b9137d07647f8cd028b2b5b3a9 (patch)
treeb8a8d9a62fa387f6b30e83b046f8beb4c521dbd7 /alacritty_terminal/src
parent856cddc8739c32d8bbfff72dd3692f49359142a9 (diff)
downloadalacritty-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.rs4
-rw-r--r--alacritty_terminal/src/window.rs57
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
///