Add a way to embed the X11 window into another
Signed-off-by: John Nunley <dev@notgull.net> Tested-by: Kirill Chibisov <contact@kchibisov.com>
This commit is contained in:
parent
2233edb9a0
commit
dc973883c9
6 changed files with 160 additions and 35 deletions
|
|
@ -96,15 +96,20 @@ pub struct PlatformSpecificWindowBuilderAttributes {
|
|||
pub name: Option<ApplicationName>,
|
||||
pub activation_token: Option<ActivationToken>,
|
||||
#[cfg(x11_platform)]
|
||||
pub x11: X11WindowBuilderAttributes,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
#[cfg(x11_platform)]
|
||||
pub struct X11WindowBuilderAttributes {
|
||||
pub visual_id: Option<x11rb::protocol::xproto::Visualid>,
|
||||
#[cfg(x11_platform)]
|
||||
pub screen_id: Option<i32>,
|
||||
#[cfg(x11_platform)]
|
||||
pub base_size: Option<Size>,
|
||||
#[cfg(x11_platform)]
|
||||
pub override_redirect: bool,
|
||||
#[cfg(x11_platform)]
|
||||
pub x11_window_types: Vec<XWindowType>,
|
||||
|
||||
/// The parent window to embed this window into.
|
||||
pub embed_window: Option<x11rb::protocol::xproto::Window>,
|
||||
}
|
||||
|
||||
impl Default for PlatformSpecificWindowBuilderAttributes {
|
||||
|
|
@ -113,15 +118,14 @@ impl Default for PlatformSpecificWindowBuilderAttributes {
|
|||
name: None,
|
||||
activation_token: None,
|
||||
#[cfg(x11_platform)]
|
||||
visual_id: None,
|
||||
#[cfg(x11_platform)]
|
||||
screen_id: None,
|
||||
#[cfg(x11_platform)]
|
||||
base_size: None,
|
||||
#[cfg(x11_platform)]
|
||||
override_redirect: false,
|
||||
#[cfg(x11_platform)]
|
||||
x11_window_types: vec![XWindowType::Normal],
|
||||
x11: X11WindowBuilderAttributes {
|
||||
visual_id: None,
|
||||
screen_id: None,
|
||||
base_size: None,
|
||||
override_redirect: false,
|
||||
x11_window_types: vec![XWindowType::Normal],
|
||||
embed_window: None,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -99,7 +99,8 @@ atom_manager! {
|
|||
_NET_CLIENT_LIST,
|
||||
_NET_FRAME_EXTENTS,
|
||||
_NET_SUPPORTED,
|
||||
_NET_SUPPORTING_WM_CHECK
|
||||
_NET_SUPPORTING_WM_CHECK,
|
||||
_XEMBED
|
||||
}
|
||||
|
||||
impl Index<AtomName> for Atoms {
|
||||
|
|
|
|||
|
|
@ -126,6 +126,15 @@ pub(crate) struct UnownedWindow {
|
|||
activation_sender: WakeSender<super::ActivationToken>,
|
||||
}
|
||||
|
||||
macro_rules! leap {
|
||||
($e:expr) => {
|
||||
match $e {
|
||||
Ok(x) => x,
|
||||
Err(err) => return Err(os_error!(OsError::XError(X11Error::from(err).into()))),
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
impl UnownedWindow {
|
||||
#[allow(clippy::unnecessary_cast)]
|
||||
pub(crate) fn new<T>(
|
||||
|
|
@ -133,15 +142,6 @@ impl UnownedWindow {
|
|||
window_attrs: WindowAttributes,
|
||||
pl_attribs: PlatformSpecificWindowBuilderAttributes,
|
||||
) -> Result<UnownedWindow, RootOsError> {
|
||||
macro_rules! leap {
|
||||
($e:expr) => {
|
||||
match $e {
|
||||
Ok(x) => x,
|
||||
Err(err) => return Err(os_error!(OsError::XError(X11Error::from(err).into()))),
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
let xconn = &event_loop.xconn;
|
||||
let atoms = xconn.atoms();
|
||||
let root = match window_attrs.parent_window {
|
||||
|
|
@ -210,7 +210,7 @@ impl UnownedWindow {
|
|||
dimensions
|
||||
};
|
||||
|
||||
let screen_id = match pl_attribs.screen_id {
|
||||
let screen_id = match pl_attribs.x11.screen_id {
|
||||
Some(id) => id,
|
||||
None => xconn.default_screen_index() as c_int,
|
||||
};
|
||||
|
|
@ -230,7 +230,7 @@ impl UnownedWindow {
|
|||
});
|
||||
|
||||
// creating
|
||||
let (visualtype, depth, require_colormap) = match pl_attribs.visual_id {
|
||||
let (visualtype, depth, require_colormap) = match pl_attribs.x11.visual_id {
|
||||
Some(vi) => {
|
||||
// Find this specific visual.
|
||||
let (visualtype, depth) = all_visuals
|
||||
|
|
@ -271,12 +271,12 @@ impl UnownedWindow {
|
|||
|
||||
aux = aux.event_mask(event_mask).border_pixel(0);
|
||||
|
||||
if pl_attribs.override_redirect {
|
||||
if pl_attribs.x11.override_redirect {
|
||||
aux = aux.override_redirect(true as u32);
|
||||
}
|
||||
|
||||
// Add a colormap if needed.
|
||||
let colormap_visual = match pl_attribs.visual_id {
|
||||
let colormap_visual = match pl_attribs.x11.visual_id {
|
||||
Some(vi) => Some(vi),
|
||||
None if require_colormap => Some(visual),
|
||||
_ => None,
|
||||
|
|
@ -298,6 +298,9 @@ impl UnownedWindow {
|
|||
aux
|
||||
};
|
||||
|
||||
// Figure out the window's parent.
|
||||
let parent = pl_attribs.x11.embed_window.unwrap_or(root);
|
||||
|
||||
// finally creating the window
|
||||
let xwindow = {
|
||||
let (x, y) = position.map_or((0, 0), Into::into);
|
||||
|
|
@ -305,7 +308,7 @@ impl UnownedWindow {
|
|||
let result = xconn.xcb_connection().create_window(
|
||||
depth,
|
||||
wid,
|
||||
root,
|
||||
parent,
|
||||
x,
|
||||
y,
|
||||
dimensions.0.try_into().unwrap(),
|
||||
|
|
@ -357,6 +360,11 @@ impl UnownedWindow {
|
|||
leap!(window.set_theme_inner(Some(theme))).ignore_error();
|
||||
}
|
||||
|
||||
// Embed the window if needed.
|
||||
if pl_attribs.x11.embed_window.is_some() {
|
||||
window.embed_window()?;
|
||||
}
|
||||
|
||||
{
|
||||
// Enable drag and drop (TODO: extend API to make this toggleable)
|
||||
{
|
||||
|
|
@ -407,7 +415,7 @@ impl UnownedWindow {
|
|||
flusher.ignore_error()
|
||||
}
|
||||
|
||||
leap!(window.set_window_types(pl_attribs.x11_window_types)).ignore_error();
|
||||
leap!(window.set_window_types(pl_attribs.x11.x11_window_types)).ignore_error();
|
||||
|
||||
// Set size hints.
|
||||
let mut min_inner_size = window_attrs
|
||||
|
|
@ -430,7 +438,7 @@ impl UnownedWindow {
|
|||
shared_state.min_inner_size = min_inner_size.map(Into::into);
|
||||
shared_state.max_inner_size = max_inner_size.map(Into::into);
|
||||
shared_state.resize_increments = window_attrs.resize_increments;
|
||||
shared_state.base_size = pl_attribs.base_size;
|
||||
shared_state.base_size = pl_attribs.x11.base_size;
|
||||
|
||||
let normal_hints = WmSizeHints {
|
||||
position: position.map(|PhysicalPosition { x, y }| {
|
||||
|
|
@ -447,6 +455,7 @@ impl UnownedWindow {
|
|||
.resize_increments
|
||||
.map(|size| cast_size_to_hint(size, scale_factor)),
|
||||
base_size: pl_attribs
|
||||
.x11
|
||||
.base_size
|
||||
.map(|size| cast_size_to_hint(size, scale_factor)),
|
||||
aspect: None,
|
||||
|
|
@ -559,6 +568,21 @@ impl UnownedWindow {
|
|||
Ok(window)
|
||||
}
|
||||
|
||||
/// Embed this window into a parent window.
|
||||
pub(super) fn embed_window(&self) -> Result<(), RootOsError> {
|
||||
let atoms = self.xconn.atoms();
|
||||
leap!(leap!(self.xconn.change_property(
|
||||
self.xwindow,
|
||||
atoms[_XEMBED],
|
||||
atoms[_XEMBED],
|
||||
xproto::PropMode::REPLACE,
|
||||
&[0u32, 1u32],
|
||||
))
|
||||
.check());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(super) fn shared_state_lock(&self) -> MutexGuard<'_, SharedState> {
|
||||
self.shared_state.lock().unwrap()
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue