diff --git a/v2/Cargo.lock b/v2/Cargo.lock index 503b251..b1ae679 100644 --- a/v2/Cargo.lock +++ b/v2/Cargo.lock @@ -3000,6 +3000,7 @@ dependencies = [ "aho-corasick", "ammonia", "anyhow", + "core-graphics", "dirs", "emojis", "env_logger", @@ -3009,6 +3010,7 @@ dependencies = [ "memchr", "muda", "notify", + "objc", "once_cell", "open", "phf 0.11.2", diff --git a/v2/Cargo.toml b/v2/Cargo.toml index b793d60..2a35029 100644 --- a/v2/Cargo.toml +++ b/v2/Cargo.toml @@ -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" diff --git a/v2/src/wry/webview.rs b/v2/src/wry/webview.rs index 917df17..5fa6801 100644 --- a/v2/src/wry/webview.rs +++ b/v2/src/wry/webview.rs @@ -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, LogicalPosition)> { - 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, LogicalPosition)> { - 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) } } @@ -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 { - 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;