use cef::ImplBrowserHost;
use std::os::raw::c_ulong;
use tauri_runtime::dpi::{PhysicalPosition, PhysicalSize, Rect};
use tauri_utils::config::Color;
use x11_dl::xlib;
use crate::{webview::AppWebview, window::AppWindow};
use super::utils::{atom, with_cef_display};
impl AppWebview {
pub(crate) fn native_parent_matches(&self, parent: &AppWindow) -> Option<bool> {
let xid = self.host.window_handle();
if xid == 0 {
return None;
}
with_cef_display(None, |xlib, display| unsafe {
let mut root = 0;
let mut native_parent = 0;
let mut children = std::ptr::null_mut();
let mut count = 0;
let status = (xlib.XQueryTree)(
display,
xid as xlib::Window,
&mut root,
&mut native_parent,
&mut children,
&mut count,
);
if !children.is_null() {
(xlib.XFree)(children.cast());
}
(status != 0).then_some(native_parent == parent.cef_host_handle() as xlib::Window)
})
}
pub(crate) fn native_visible(&self) -> Option<bool> {
let xid = self.host.window_handle();
if xid == 0 {
return None;
}
with_cef_display(None, |xlib, display| unsafe {
let mut attributes = std::mem::MaybeUninit::<xlib::XWindowAttributes>::uninit();
if (xlib.XGetWindowAttributes)(display, xid as xlib::Window, attributes.as_mut_ptr()) == 0 {
return None;
}
Some(attributes.assume_init().map_state == xlib::IsViewable)
})
}
fn xid(&self) -> xlib::Window {
let xid = self.host.window_handle();
assert_ne!(xid, 0, "failed to get XID");
xid as xlib::Window
}
pub(crate) fn set_background_color(&self, color: Option<Color>) {
let _ = (self, color);
}
pub(crate) fn bounds(&self) -> Option<Rect> {
let xid = self.xid();
with_cef_display(None, |xlib, display| unsafe {
let mut root: xlib::Window = 0;
let mut x: i32 = 0;
let mut y: i32 = 0;
let mut width: u32 = 0;
let mut height: u32 = 0;
let mut border_width: u32 = 0;
let mut depth: u32 = 0;
if (xlib.XGetGeometry)(
display,
xid,
&mut root,
&mut x,
&mut y,
&mut width,
&mut height,
&mut border_width,
&mut depth,
) == 0
{
return None;
}
Some(Rect {
position: PhysicalPosition::new(x, y).into(),
size: PhysicalSize::new(width, height).into(),
})
})
}
pub(crate) fn reparent(&self, parent: &AppWindow) {
let xid = self.xid();
let parent_xid = parent.cef_host_handle();
with_cef_display((), |xlib, display| unsafe {
(xlib.XReparentWindow)(display, xid, parent_xid as xlib::Window, 0, 0);
(xlib.XMapRaised)(display, xid);
});
}
pub(crate) fn apply_visible(&self, visible: bool) {
let xid = self.xid();
with_cef_display((), |xlib, display| unsafe {
let net_wm_state = atom(xlib, display, "_NET_WM_STATE");
const PROP_MODE_REPLACE: i32 = 0;
if visible {
(xlib.XChangeProperty)(
display,
xid,
net_wm_state,
xlib::XA_ATOM,
32,
PROP_MODE_REPLACE,
std::ptr::null(),
0,
);
(xlib.XMapWindow)(display, xid);
} else {
let hidden: [c_ulong; 1] = [atom(xlib, display, "_NET_WM_STATE_HIDDEN")];
(xlib.XChangeProperty)(
display,
xid,
net_wm_state,
xlib::XA_ATOM,
32,
PROP_MODE_REPLACE,
hidden.as_ptr() as *const u8,
1,
);
(xlib.XUnmapWindow)(display, xid);
}
});
}
pub(crate) fn apply_physical_bounds(&self, _scale: f64, x: i32, y: i32, width: i32, height: i32) {
let xid = self.xid();
with_cef_display((), |xlib, display| unsafe {
(xlib.XMoveResizeWindow)(
display,
xid,
x,
y,
width.max(1) as u32,
height.max(1) as u32,
);
});
}
}