Skip to content

Commit

Permalink
directly get window inner size from WKWebView's frame on macOS
Browse files Browse the repository at this point in the history
because `tao::Window::inner_size` does not work. It obtains
size of `contentView`'s frame. However `wry::WebView` replaces the
content view of the `NSWindow` with their own `NSView`. As the result
the replaced view is no longer updated on resizing the window but
`tao::Window` still refers the original view.
  • Loading branch information
rhysd committed Jun 17, 2024
1 parent 7226dd7 commit 948e7c6
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 19 deletions.
2 changes: 2 additions & 0 deletions v2/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions v2/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ tao = { version = "0.28.0", default-features = false, features = [ "rwh_06" ] }
[target.'cfg(target_os = "macos")'.dependencies]
wry = { version = "0.40.0", features = ["transparent"] }
window-vibrancy = "0.5.0"
objc = "0.2.7"
core-graphics = "0.23.2"

[target.'cfg(not(target_os = "macos"))'.dependencies]
wry = "0.40.0"
Expand Down
40 changes: 21 additions & 19 deletions v2/src/wry/webview.rs
Original file line number Diff line number Diff line change
Expand Up @@ -256,24 +256,19 @@ impl WebViewRenderer {
Ok(WebViewRenderer { webview, window, zoom_level, always_on_top, menu })
}

#[cfg(not(target_os = "macos"))]
fn window_rect(&self) -> Result<(LogicalSize<f64>, LogicalPosition<f64>)> {
let scale = self.window.scale_factor();
let size = self.window.inner_size().to_logical(scale);
let pos = self.window.outer_position()?.to_logical(scale);
Ok((size, pos))
}

// `self.window.inner_size()` does not work on macOS because `WebView` replaces `NSWindow`
// instance's `contentView` field of `self.window`.
#[cfg(target_os = "macos")]
fn window_rect(&self) -> Result<(LogicalSize<f64>, LogicalPosition<f64>)> {
let scale = self.window.scale_factor();
// `self.window.inner_size()` does not work because `WebView` replaces `NSWindow` instance's
// `contentView` field of `self.window`.
let size = self.webview.bounds()?.size.to_logical(scale);
// `self.webview.bounds()` does not report a correct position so it needs to be obtained
// separately.
let pos = self.window.outer_position()?.to_logical(scale);
Ok((size, pos))
fn wkwebview_frame_size(&self) -> (f64, f64) {
use core_graphics::geometry::CGRect;
use objc::*;
use wry::WebViewExtMacOS as _;
// Safety: `wry::WebView::webview` returns the valid reference to `WKWebView`. And `WKWebView`
// inherits `NSView`. So calling `frame` method returns its rect information.
// * https://developer.apple.com/documentation/webkit/wkwebview
// * https://developer.apple.com/documentation/appkit/nsview
let frame: CGRect = unsafe { msg_send![self.webview.webview(), frame] };
(frame.size.width, frame.size.height)
}
}

Expand Down Expand Up @@ -303,13 +298,20 @@ impl Renderer for WebViewRenderer {
fn set_title(&self, _title: &str) {} // On macOS, the title bar is hidden

fn window_state(&self) -> Option<WindowState> {
let (width, height, x, y) = match self.window_rect() {
Ok((size, pos)) => (size.width, size.height, pos.x, pos.y),
let scale = self.window.scale_factor();
let LogicalPosition { x, y } = match self.window.outer_position() {
Ok(pos) => pos.to_logical(scale),
Err(err) => {
log::debug!("Could not get window position for window state: {}", err);
return None;
}
};

#[cfg(not(target_os = "macos"))]
let LogicalSize { width, height } = self.window.inner_size().to_logical(scale);
#[cfg(target_os = "macos")]
let (width, height) = self.wkwebview_frame_size();

let fullscreen = self.window.fullscreen().is_some();
let zoom_level = self.zoom_level;
let always_on_top = self.always_on_top;
Expand Down

0 comments on commit 948e7c6

Please sign in to comment.