Skip to content

Commit

Permalink
feat: add WebView::bounds getter (#1091)
Browse files Browse the repository at this point in the history
* feat: add WebView::bounds getter

* macos impl

* windows impl

* dummy android

* fix build on ios

* fix initial size on macOS, adjust bounds impl

* fallback to controller.bounds on windows

* use webview.allocated_size on linux when not a child

* cleanup windows impl

* fix wgpu example

* cleanup linux impl

---------

Co-authored-by: amrbashir <amr.bashir2015@gmail.com>
  • Loading branch information
lucasfernog and amrbashir committed Nov 22, 2023
1 parent c241b48 commit 8fddbb6
Show file tree
Hide file tree
Showing 7 changed files with 124 additions and 21 deletions.
5 changes: 5 additions & 0 deletions .changes/webview-bounds.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"wry": patch
---

Add `WebView::bounds` getter.
8 changes: 4 additions & 4 deletions examples/wgpu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,10 +98,10 @@ fn fs_main() -> @location(0) vec4<f32> {

let _webview = WebViewBuilder::new_as_child(&window)
.with_bounds(Rect {
x: 0,
y: 0,
width: 1,
height: 1,
x: 100,
y: 100,
width: 200,
height: 200,
})
.with_transparent(true)
.with_html(
Expand Down
9 changes: 9 additions & 0 deletions src/android/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,15 @@ impl InnerWebView {
Ok(())
}

pub fn bounds(&self) -> crate::Rect {
crate::Rect {
x: 0,
y: 0,
width: 0,
height: 0,
}
}

pub fn set_bounds(&self, bounds: crate::Rect) {
// Unsupported
}
Expand Down
6 changes: 5 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ pub use url::Url;
pub use web_context::WebContext;

/// A rectangular region.
#[derive(Clone, Copy, Debug)]
#[derive(Clone, Copy, Debug, Default)]
pub struct Rect {
/// x coordinate of top left corner
pub x: i32,
Expand Down Expand Up @@ -1320,6 +1320,10 @@ impl WebView {
self.webview.clear_all_browsing_data()
}

pub fn bounds(&self) -> Rect {
self.webview.bounds()
}

/// Set the webview bounds.
///
/// This is only effective if the webview was created as a child.
Expand Down
37 changes: 37 additions & 0 deletions src/webkitgtk/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -600,6 +600,43 @@ impl InnerWebView {
Ok(())
}

pub fn bounds(&self) -> Rect {
let mut bounds = Rect::default();

if let (Some(xlib), Some(display), Some(window_handle)) =
(&self.xlib, self.x11_display, self.x11_window)
{
unsafe {
let mut attributes = std::mem::MaybeUninit::new(x11_dl::xlib::XWindowAttributes {
..std::mem::zeroed()
})
.assume_init();
let ok = (xlib.XGetWindowAttributes)(display as _, window_handle, &mut attributes);

if ok != 0 {
bounds.x = attributes.x;
bounds.y = attributes.y;
bounds.width = attributes.width as u32;
bounds.height = attributes.height as u32;
}
}
} else if let Some(window) = &self.gtk_window {
let position = window.position();
let size = window.size();

bounds.x = position.0;
bounds.y = position.1;
bounds.width = size.0 as u32;
bounds.height = size.1 as u32;
} else {
let (size, _) = self.webview.allocated_size();
bounds.width = size.width() as u32;
bounds.height = size.height() as u32;
}

bounds
}

pub fn set_bounds(&self, bounds: Rect) {
if self.is_child {
if let Some(window) = &self.gtk_window {
Expand Down
41 changes: 36 additions & 5 deletions src/webview2/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use windows::{
Win32::{
Foundation::*,
Globalization::{self, MAX_LOCALE_NAME},
Graphics::Gdi::{RedrawWindow, HBRUSH, HRGN, RDW_INTERNALPAINT},
Graphics::Gdi::{MapWindowPoints, RedrawWindow, HBRUSH, HRGN, RDW_INTERNALPAINT},
System::{
Com::{CoInitializeEx, IStream, COINIT_APARTMENTTHREADED},
LibraryLoader::GetModuleHandleW,
Expand All @@ -28,10 +28,11 @@ use windows::{
UI::{
Shell::{DefSubclassProc, SHCreateMemStream, SetWindowSubclass},
WindowsAndMessaging::{
self as win32wm, CreateWindowExW, DefWindowProcW, DestroyWindow, PostMessageW,
RegisterClassExW, RegisterWindowMessageA, SetWindowPos, ShowWindow, CS_HREDRAW, CS_VREDRAW,
CW_USEDEFAULT, HCURSOR, HICON, HMENU, SWP_ASYNCWINDOWPOS, SWP_NOACTIVATE, SWP_NOZORDER,
SW_HIDE, SW_SHOW, WINDOW_EX_STYLE, WNDCLASSEXW, WS_CHILD, WS_CLIPCHILDREN, WS_VISIBLE,
self as win32wm, CreateWindowExW, DefWindowProcW, DestroyWindow, GetClientRect, GetParent,
PostMessageW, RegisterClassExW, RegisterWindowMessageA, SetWindowPos, ShowWindow,
CS_HREDRAW, CS_VREDRAW, CW_USEDEFAULT, HCURSOR, HICON, HMENU, SWP_ASYNCWINDOWPOS,
SWP_NOACTIVATE, SWP_NOZORDER, SW_HIDE, SW_SHOW, WINDOW_EX_STYLE, WNDCLASSEXW, WS_CHILD,
WS_CLIPCHILDREN, WS_VISIBLE,
},
},
},
Expand Down Expand Up @@ -1009,6 +1010,36 @@ impl InnerWebView {
set_theme(&self.webview, theme);
}

pub fn bounds(&self) -> Rect {
let mut bounds = Rect::default();

if self.is_child {
let mut rect = RECT::default();
if unsafe { GetClientRect(self.hwnd, &mut rect) }.is_err() {
panic!("Unexpected GetClientRect failure")
}

let position_point = &mut [POINT {
x: rect.left,
y: rect.top,
}];
unsafe { MapWindowPoints(self.hwnd, GetParent(self.hwnd), position_point) };

bounds.x = position_point[0].x;
bounds.y = position_point[0].y;
bounds.width = (rect.right - rect.left) as u32;
bounds.height = (rect.bottom - rect.top) as u32;
} else {
let mut rect = RECT::default();
if unsafe { self.controller.Bounds(&mut rect) }.is_ok() {
bounds.width = (rect.right - rect.left) as u32;
bounds.height = (rect.bottom - rect.top) as u32;
}
}

bounds
}

pub fn set_bounds(&self, bounds: Rect) {
if self.is_child {
unsafe {
Expand Down
39 changes: 28 additions & 11 deletions src/wkwebview/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -397,17 +397,19 @@ impl InnerWebView {
#[cfg(target_os = "macos")]
{
let (x, y) = attributes.bounds.map(|b| (b.x, b.y)).unwrap_or((0, 0));
let (w, h) = attributes
.bounds
.map(|b| (b.width, b.height))
.unwrap_or_else(|| {
if is_child {
let frame = NSView::frame(ns_view);
(frame.size.width as u32, frame.size.height as u32)
} else {
(0, 0)
}
});
let (w, h) = if is_child {
attributes.bounds.map(|b| (b.width, b.height))
} else {
None
}
.unwrap_or_else(|| {
if is_child {
let frame = NSView::frame(ns_view);
(frame.size.width as u32, frame.size.height as u32)
} else {
(0, 0)
}
});

let frame = CGRect {
origin: window_position(if is_child { ns_view } else { webview }, x, y, h as f64),
Expand Down Expand Up @@ -1090,6 +1092,21 @@ r#"Object.defineProperty(window, 'ipc', {
Ok(())
}

pub fn bounds(&self) -> Rect {
unsafe {
let parent: id = msg_send![self.webview, superview];
let parent_frame: CGRect = msg_send![parent, frame];
let webview_frame: CGRect = msg_send![self.webview, frame];

Rect {
x: webview_frame.origin.x as i32,
y: (parent_frame.size.height - webview_frame.origin.y - webview_frame.size.height) as i32,
width: webview_frame.size.width as u32,
height: webview_frame.size.height as u32,
}
}
}

pub fn set_bounds(&self, bounds: Rect) {
if self.is_child {
unsafe {
Expand Down

0 comments on commit 8fddbb6

Please sign in to comment.