Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: auto resize webview on Windows #628

Merged
merged 3 commits into from Jun 27, 2022
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 6 additions & 0 deletions .changes/auto-resize-on-windows.md
@@ -0,0 +1,6 @@
---
"wry": "minor"
---

* Automatically resize the webview on Windows to align with other platforms.
* **Breakin change**: Removed `WebView::resize`
3 changes: 0 additions & 3 deletions examples/custom_titlebar.rs
Expand Up @@ -145,9 +145,6 @@ fn main() -> wry::Result<()> {
*control_flow = ControlFlow::Exit
}
}
WindowEvent::Resized(_) => {
let _ = webviews[&window_id].resize();
}
_ => (),
},
Event::UserEvent(UserEvents::CloseWindow(id)) => {
Expand Down
6 changes: 2 additions & 4 deletions examples/dragndrop.rs
Expand Up @@ -20,7 +20,7 @@ fn main() -> wry::Result<()> {

let event_loop = EventLoop::new();
let window = WindowBuilder::new().build(&event_loop).unwrap();
let webview = WebViewBuilder::new(window)
let _webview = WebViewBuilder::new(window)
.unwrap()
.with_url(HTML)?
.with_file_drop_handler(|_, data| {
Expand All @@ -37,9 +37,7 @@ fn main() -> wry::Result<()> {
event: WindowEvent::CloseRequested,
..
} => *control_flow = ControlFlow::Exit,
_ => {
let _ = webview.resize();
}
_ => {}
}
});
}
6 changes: 2 additions & 4 deletions examples/fullscreen.rs
Expand Up @@ -18,7 +18,7 @@ fn main() -> wry::Result<()> {
.with_fullscreen(Some(Fullscreen::Borderless(None)))
.build(&event_loop)
.unwrap();
let webview = WebViewBuilder::new(window)
let _webview = WebViewBuilder::new(window)
.unwrap()
.with_url("https://browserbench.org/MotionMark1.2/")?
.build()?;
Expand All @@ -31,9 +31,7 @@ fn main() -> wry::Result<()> {
event: WindowEvent::CloseRequested,
..
} => *control_flow = ControlFlow::Exit,
_ => {
let _ = webview.resize();
}
_ => {}
}
});
}
Expand Down
3 changes: 0 additions & 3 deletions examples/multi_window.rs
Expand Up @@ -82,9 +82,6 @@ fn main() -> wry::Result<()> {
*control_flow = ControlFlow::Exit
}
}
WindowEvent::Resized(_) => {
let _ = webviews[&window_id].resize();
}
_ => (),
},
Event::UserEvent(UserEvents::NewWindow()) => {
Expand Down
5 changes: 1 addition & 4 deletions examples/stream_range.rs
Expand Up @@ -135,10 +135,7 @@ fn main() -> wry::Result<()> {
event: WindowEvent::CloseRequested,
..
} => *control_flow = ControlFlow::Exit,
_ => {
#[cfg(target_os = "windows")]
let _ = _webview.resize();
}
_ => {}
}
});
}
6 changes: 2 additions & 4 deletions examples/transparent.rs
Expand Up @@ -21,7 +21,7 @@ fn main() -> wry::Result<()> {
.build(&event_loop)
.unwrap();

let webview = WebViewBuilder::new(window)?
let _webview = WebViewBuilder::new(window)?
// The second is on webview...
.with_transparent(true)
// And the last is in html.
Expand All @@ -47,9 +47,7 @@ fn main() -> wry::Result<()> {
event: WindowEvent::CloseRequested,
..
} => *control_flow = ControlFlow::Exit,
_ => {
let _ = webview.resize();
}
_ => {}
}
});
}
8 changes: 0 additions & 8 deletions src/webview/mod.rs
Expand Up @@ -468,14 +468,6 @@ impl WebView {
Ok(())
}

/// Resize the WebView manually. This is only required on Windows because its WebView API doesn't
/// provide a way to resize automatically.
pub fn resize(&self) -> Result<()> {
#[cfg(target_os = "windows")]
self.webview.resize(HWND(self.window.hwnd() as _))?;
Ok(())
}

/// Moves Focus to the Webview control.
///
/// It's usually safe to call `focus` method on `Window` which would also focus to `WebView` except Windows.
Expand Down
61 changes: 43 additions & 18 deletions src/webview/webview2/mod.rs
Expand Up @@ -18,15 +18,16 @@ use once_cell::unsync::OnceCell;
use windows::{
core::{Interface, PCWSTR, PWSTR},
Win32::{
Foundation::{BOOL, E_FAIL, E_POINTER, FARPROC, HWND, POINT, RECT},
Foundation::{BOOL, E_FAIL, E_POINTER, FARPROC, HWND, LPARAM, LRESULT, POINT, RECT, WPARAM},
System::{
Com::{IStream, StructuredStorage::CreateStreamOnHGlobal},
LibraryLoader::{GetProcAddress, LoadLibraryA},
SystemInformation::OSVERSIONINFOW,
WinRT::EventRegistrationToken,
},
UI::WindowsAndMessaging::{
self as win32wm, DestroyWindow, GetClientRect, GetCursorPos, WM_NCLBUTTONDOWN,
UI::{
Shell::{DefSubclassProc, SetWindowSubclass},
WindowsAndMessaging as win32wm,
},
},
};
Expand Down Expand Up @@ -193,7 +194,7 @@ impl InnerWebView {
unsafe {
let handler: ICoreWebView2WindowCloseRequestedEventHandler =
WindowCloseRequestedEventHandler::create(Box::new(move |_, _| {
if DestroyWindow(hwnd).as_bool() {
if win32wm::DestroyWindow(hwnd).as_bool() {
Ok(())
} else {
Err(E_FAIL.into())
Expand Down Expand Up @@ -228,7 +229,7 @@ impl InnerWebView {
let _ = settings5.SetIsPinchZoomEnabled(attributes.zoom_hotkeys_enabled);

let mut rect = RECT::default();
GetClientRect(hwnd, &mut rect);
win32wm::GetClientRect(hwnd, &mut rect);
controller
.SetBounds(rect)
.map_err(webview2_com::Error::WindowsError)?;
Expand Down Expand Up @@ -266,7 +267,7 @@ window.addEventListener('mousemove', (e) => window.chrome.webview.postMessage('_
use crate::application::{platform::windows::hit_test, window::CursorIcon};

let mut point = POINT::default();
GetCursorPos(&mut point);
win32wm::GetCursorPos(&mut point);
let result = hit_test(window.hwnd(), point.x, point.y);
let cursor = match result.0 as u32 {
win32wm::HTLEFT => CursorIcon::WResize,
Expand All @@ -288,7 +289,7 @@ window.addEventListener('mousemove', (e) => window.chrome.webview.postMessage('_
// we ignore `HTCLIENT` variant so the webview receives the click correctly if it is not on the edges
// and prevent conflict with `tao::window::drag_window`.
if result.0 as u32 != win32wm::HTCLIENT {
window.begin_resize_drag(result.0, WM_NCLBUTTONDOWN, point.x, point.y);
window.begin_resize_drag(result.0, win32wm::WM_NCLBUTTONDOWN, point.x, point.y);
}
}
}
Expand Down Expand Up @@ -574,6 +575,41 @@ window.addEventListener('mousemove', (e) => window.chrome.webview.postMessage('_
}
}

unsafe {
unsafe extern "system" fn subclass_proc(
hwnd: HWND,
msg: u32,
wparam: WPARAM,
lparam: LPARAM,
_uidsubclass: usize,
dwrefdata: usize,
) -> LRESULT {
if msg == win32wm::WM_SIZE {
let controller = dwrefdata as *mut ICoreWebView2Controller;
let mut client_rect = RECT::default();
win32wm::GetClientRect(hwnd, std::mem::transmute(&mut client_rect));
let _ = (*controller).SetBounds(RECT {
left: 0,
top: 0,
right: client_rect.right - client_rect.left,
bottom: client_rect.bottom - client_rect.top,
});
}

if msg == win32wm::WM_DESTROY {
Box::from_raw(dwrefdata as *mut ICoreWebView2Controller);
}

DefSubclassProc(hwnd, msg, wparam, lparam)
}
SetWindowSubclass(
hwnd,
Some(subclass_proc),
8080,
Box::into_raw(Box::new(controller.clone())) as _,
);
}

unsafe {
controller
.SetIsVisible(true)
Expand Down Expand Up @@ -619,17 +655,6 @@ window.addEventListener('mousemove', (e) => window.chrome.webview.postMessage('_
.map_err(|err| Error::WebView2Error(webview2_com::Error::WindowsError(err)))
}

pub fn resize(&self, hwnd: HWND) -> Result<()> {
// Safety: System calls are unsafe
// XXX: Resizing on Windows is usually sluggish. Many other applications share same behavior.
unsafe {
let mut rect = RECT::default();
GetClientRect(hwnd, &mut rect);
self.controller.SetBounds(rect)
}
.map_err(|error| Error::WebView2Error(webview2_com::Error::WindowsError(error)))
}

pub fn focus(&self) {
let _ = unsafe {
self
Expand Down