Skip to content

Commit

Permalink
feat: auto resize webview on Windows (#628)
Browse files Browse the repository at this point in the history
* feat: auto resize webview on Windows

* Update auto-resize-on-windows.md

* cleanup raw pointer
  • Loading branch information
amrbashir committed Jun 27, 2022
1 parent fc3c978 commit d7c9097
Show file tree
Hide file tree
Showing 9 changed files with 56 additions and 48 deletions.
6 changes: 6 additions & 0 deletions .changes/auto-resize-on-windows.md
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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

0 comments on commit d7c9097

Please sign in to comment.