use cef::ImplBrowserHost;
use tauri_runtime::dpi::{PhysicalPosition, PhysicalSize, Rect};
use tauri_utils::config::Color;
use windows::Win32::{
Foundation::{ERROR_SUCCESS, HWND, LPARAM, LRESULT, POINT, RECT, SetLastError, WPARAM},
Graphics::Gdi::MapWindowPoints,
UI::Shell::{DefSubclassProc, SetWindowSubclass},
UI::WindowsAndMessaging::{
DestroyWindow, GetParent, GetWindowRect, HWND_TOP, IsWindow, IsWindowVisible, SW_HIDE, SW_SHOW,
SWP_NOACTIVATE, SWP_NOMOVE, SWP_NOSIZE, SWP_NOZORDER, SetParent, SetWindowPos, ShowWindow,
WINDOWPOS, WM_WINDOWPOSCHANGING,
},
};
use crate::{webview::AppWebview, window::AppWindow};
impl AppWebview {
pub(crate) fn native_parent_matches(&self, parent: &AppWindow) -> Option<bool> {
let hwnd = self.hwnd();
unsafe {
if !IsWindow(Some(hwnd)).as_bool() {
return None;
}
SetLastError(ERROR_SUCCESS);
match GetParent(hwnd) {
Ok(native_parent) => Some(native_parent == parent.hwnd()),
Err(err) if err.code().is_ok() => Some(false),
Err(_) => None,
}
}
}
pub(crate) fn native_visible(&self) -> Option<bool> {
let hwnd = self.hwnd();
unsafe {
IsWindow(Some(hwnd))
.as_bool()
.then(|| IsWindowVisible(hwnd).as_bool())
}
}
pub(crate) fn hwnd(&self) -> HWND {
let hwnd = self.host.window_handle();
HWND(hwnd.0 as _)
}
pub(crate) fn set_background_color(&self, _color: Option<Color>) {
}
pub(crate) fn bounds(&self) -> Option<Rect> {
let hwnd = self.hwnd();
let mut rect = RECT::default();
unsafe {
let parent = GetParent(hwnd).ok()?;
if parent.0.is_null() {
return None;
}
GetWindowRect(hwnd, &mut rect).ok()?;
let mut points = [
POINT {
x: rect.left,
y: rect.top,
},
POINT {
x: rect.right,
y: rect.bottom,
},
];
if MapWindowPoints(None, Some(parent), &mut points) == 0 {
return None;
}
let x = points[0].x;
let y = points[0].y;
let width = (points[1].x - points[0].x).max(0) as u32;
let height = (points[1].y - points[0].y).max(0) as u32;
Some(Rect {
position: PhysicalPosition::new(x, y).into(),
size: PhysicalSize::new(width, height).into(),
})
}
}
pub(crate) fn reparent(&self, parent: &AppWindow) {
let parent = parent.hwnd();
let _ = unsafe { SetParent(self.hwnd(), Some(parent)) };
}
pub(crate) fn apply_visible(&self, visible: bool) {
let _ = unsafe { ShowWindow(self.hwnd(), if visible { SW_SHOW } else { SW_HIDE }) };
}
pub(crate) fn destroy_host_window(&self) {
let _ = unsafe { DestroyWindow(self.hwnd()) };
}
const PIN_Z_ORDER_SUBCLASS_ID: usize = 124;
const Z_ORDER_UNPINNED: usize = 0;
const Z_ORDER_PINNED: usize = 1;
unsafe extern "system" fn pin_z_order_subclass_proc(
hwnd: HWND,
msg: u32,
wparam: WPARAM,
lparam: LPARAM,
_subclass_id: usize,
pinned: usize,
) -> LRESULT {
unsafe {
if pinned == Self::Z_ORDER_PINNED && msg == WM_WINDOWPOSCHANGING && lparam.0 != 0 {
let window_pos = &mut *(lparam.0 as *mut WINDOWPOS);
window_pos.flags |= SWP_NOZORDER;
}
DefSubclassProc(hwnd, msg, wparam, lparam)
}
}
fn set_z_order_pinned(&self, pinned: bool) {
let _ = unsafe {
SetWindowSubclass(
self.hwnd(),
Some(Self::pin_z_order_subclass_proc),
Self::PIN_Z_ORDER_SUBCLASS_ID,
if pinned {
Self::Z_ORDER_PINNED
} else {
Self::Z_ORDER_UNPINNED
},
)
};
}
pub(crate) fn raise_to_top(&self) {
self.set_z_order_pinned(false);
let _ = unsafe {
SetWindowPos(
self.hwnd(),
Some(HWND_TOP),
0,
0,
0,
0,
SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE,
)
};
self.set_z_order_pinned(true);
}
pub(crate) fn apply_physical_bounds(&self, _scale: f64, x: i32, y: i32, width: i32, height: i32) {
unsafe {
let _ = SetWindowPos(
self.hwnd(),
None,
x,
y,
width,
height,
SWP_NOZORDER | SWP_NOACTIVATE,
);
}
}
}