Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion crates/bevy_webview_wry/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
## v0.5.0(Unreleased)

### Features

- Support hot-reloading feature flag to enable hot-reloading of webviews.
### Bugfixes
- Fixed an issue where the embedded webview position would sometimes be incorrect when the window moved.

## v0.4.0

Expand Down
38 changes: 20 additions & 18 deletions crates/bevy_webview_wry/src/webview/load_webview.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,7 @@ use crate::webview::handlers::{HandlerQueries, WryEventParams};
use crate::webview::load_webview::ipc::IpcHandlerParams;
use crate::webview::load_webview::protocol::feed_uri;
use crate::webview::protocol::WryRequestSender;
use bevy::prelude::{
App, Commands, Entity, Name, NonSend, NonSendMut, Or, Plugin, PreUpdate, Query, Res, Window,
With, Without,
};
use bevy::prelude::*;
Copy link

Copilot AI Jul 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] Using wildcard imports (use bevy::prelude::*;) can make code less readable and may introduce naming conflicts. Consider importing only the specific items needed or using the previous explicit import style.

Suggested change
use bevy::prelude::*;
use bevy::prelude::{App, Plugin, PreUpdate, Update, WindowMoved, on_event};

Copilot uses AI. Check for mistakes.
use bevy::winit::WinitWindows;
use bevy_webview_core::bundle::embedding::{Bounds, EmbedWithin};
use bevy_webview_core::prelude::*;
Expand All @@ -33,9 +30,9 @@ impl Plugin for LoadWebviewPlugin {
{
use bevy::prelude::IntoScheduleConfigs;
app.add_systems(
PreUpdate,
(resize_webview_inner_window
.run_if(bevy::prelude::on_event::<bevy::window::WindowResized>),),
Update,
move_webview_inner_window
.run_if(on_event::<WindowMoved>.or(on_event::<bevy::window::WindowResized>)),
);
}
}
Expand Down Expand Up @@ -280,7 +277,6 @@ unsafe fn attach_inner_window(
// SAFETY: The `webview` is a valid pointer to an `NSView`.
unsafe {
use objc2_app_kit::NSAutoresizingMaskOptions;

webview.removeFromSuperview();
webview.setAutoresizingMask(
NSAutoresizingMaskOptions::ViewHeightSizable
Expand All @@ -303,10 +299,8 @@ unsafe fn attach_inner_window(

let content_rect = application_window.contentRectForFrameRect(application_window.frame());
inner_window.setFrame_display(content_rect, true);
inner_window.setHidesOnDeactivate(false);
inner_window.setTitlebarAppearsTransparent(true);
inner_window.setTitleVisibility(objc2_app_kit::NSWindowTitleVisibility::Hidden);

inner_window.setContentView(Some(webview));

inner_window.becomeKeyWindow();
Expand Down Expand Up @@ -334,18 +328,27 @@ unsafe fn attach_inner_window(
}

#[cfg(target_os = "macos")]
fn resize_webview_inner_window(
mut er: bevy::prelude::EventReader<bevy::window::WindowResized>,
fn move_webview_inner_window(
mut er_moved: EventReader<WindowMoved>,
mut er_resized: EventReader<bevy::window::WindowResized>,
winit_windows: NonSend<WinitWindows>,
wry_web_views: NonSend<WryWebViews>,
) {
let mut windows = bevy::platform::collections::HashSet::new();
#[allow(deprecated)]
use wry::raw_window_handle::{HasRawWindowHandle, RawWindowHandle};
for e in er.read() {
let Some(winit_window) = winit_windows.get_window(e.window) else {
for window in er_moved
.read()
.map(|e| e.window)
.chain(er_resized.read().map(|e| e.window))
{
if !windows.insert(window) {
continue; // Skip if we've already processed this window
}
let Some(winit_window) = winit_windows.get_window(window) else {
continue;
};
let Some(wry_webview) = wry_web_views.0.get(&e.window) else {
let Some(wry_webview) = wry_web_views.0.get(&window) else {
continue;
};
#[allow(deprecated)]
Expand All @@ -362,8 +365,7 @@ fn resize_webview_inner_window(
let Some(ns_window) = ns_view.window() else {
continue;
};
wry_webview
.ns_window()
.setFrame_display(ns_window.contentRectForFrameRect(ns_window.frame()), true);
let wry_ns_window = wry_webview.ns_window();
Copy link

Copilot AI Jul 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The change from true to false for the display parameter in setFrame_display should be documented. This parameter controls whether the window is immediately redrawn, and the change may have performance implications.

Suggested change
let wry_ns_window = wry_webview.ns_window();
let wry_ns_window = wry_webview.ns_window();
// The `display` parameter is set to `false` to avoid immediate redraw of the window.
// This is intentional to optimize performance, as the redraw is handled elsewhere.

Copilot uses AI. Check for mistakes.
wry_ns_window.setFrame_display(ns_window.contentRectForFrameRect(ns_window.frame()), false);
}
}
6 changes: 4 additions & 2 deletions crates/bevy_webview_wry/src/webview/protocol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ fn start_load(
csp: request.csp,
path: request.path.clone(),
};
commands.entity(request.webview).insert((
commands.entity(request.webview).try_insert((
args.clone(),
WryResponseHandle(asset_server.load(request.path.clone())),
));
Expand All @@ -81,7 +81,9 @@ fn response(
continue;
};
responder.respond(convert_to_response(response_body.0.clone(), args));
commands.entity(webview_entity).remove::<WryRequestArgs>();
commands
.entity(webview_entity)
.try_remove::<WryRequestArgs>();
}
}

Expand Down
Loading