Skip to content

Commit 4e807a5

Browse files
probablykasperamrbashirlucasfernog
authored
Support window parenting on macOS, closes #3751 (#3754)
Co-authored-by: Amr Bashir <amr.bashir2015@gmail.com> Co-authored-by: Lucas Nogueira <lucas@tauri.studio>
1 parent d36c8e0 commit 4e807a5

File tree

16 files changed

+239
-8
lines changed

16 files changed

+239
-8
lines changed

.changes/parent-window-hwnd.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"tauri": patch
3+
---
4+
5+
**Breaking change:** The `Window::hwnd` method now returns *HWND* from `windows-rs` crate instead of *c_void* on Windows.

.changes/parent-window-macos.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
"tauri-runtime-wry": minor
3+
"tauri-runtime": minor
4+
"tauri": minor
5+
---
6+
7+
Support window parenting on macOS

core/tauri-runtime-wry/src/lib.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -877,6 +877,14 @@ impl WindowBuilder for WindowBuilderWrapper {
877877
self
878878
}
879879

880+
#[cfg(target_os = "macos")]
881+
fn parent_window(mut self, parent: *mut std::ffi::c_void) -> Self {
882+
use wry::application::platform::macos::WindowBuilderExtMacOS;
883+
884+
self.inner = self.inner.with_parent_window(parent);
885+
self
886+
}
887+
880888
#[cfg(windows)]
881889
fn owner_window(mut self, owner: HWND) -> Self {
882890
self.inner = self.inner.with_owner_window(owner);

core/tauri-runtime/src/webview.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,15 @@ pub trait WindowBuilder: WindowBuilderBase {
165165
#[must_use]
166166
fn parent_window(self, parent: HWND) -> Self;
167167

168+
/// Sets a parent to the window to be created.
169+
///
170+
/// A child window has the WS_CHILD style and is confined to the client area of its parent window.
171+
///
172+
/// For more information, see <https://docs.microsoft.com/en-us/windows/win32/winmsg/window-features#child-windows>
173+
#[cfg(target_os = "macos")]
174+
#[must_use]
175+
fn parent_window(self, parent: *mut std::ffi::c_void) -> Self;
176+
168177
/// Set an owner to the window to be created.
169178
///
170179
/// From MSDN:

core/tauri/Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,10 @@ name = "multiwindow"
277277
path = "../../examples/multiwindow/src-tauri/src/main.rs"
278278
required-features = [ "window-create" ]
279279

280+
[[example]]
281+
name = "parent-window"
282+
path = "../../examples/parent-window/src-tauri/src/main.rs"
283+
280284
[[example]]
281285
name = "navigation"
282286
path = "../../examples/navigation/src-tauri/src/main.rs"

core/tauri/src/test/mock_runtime.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,11 @@ impl WindowBuilder for MockWindowBuilder {
238238
self
239239
}
240240

241+
#[cfg(target_os = "macos")]
242+
fn parent_window(self, parent: *mut std::ffi::c_void) -> Self {
243+
self
244+
}
245+
241246
#[cfg(windows)]
242247
fn owner_window(self, owner: HWND) -> Self {
243248
self

core/tauri/src/window.rs

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -387,6 +387,14 @@ impl<R: Runtime> WindowBuilder<R> {
387387
self
388388
}
389389

390+
/// Sets a parent to the window to be created.
391+
#[cfg(target_os = "macos")]
392+
#[must_use]
393+
pub fn parent_window(mut self, parent: *mut std::ffi::c_void) -> Self {
394+
self.window_builder = self.window_builder.parent_window(parent);
395+
self
396+
}
397+
390398
/// Set an owner to the window to be created.
391399
///
392400
/// From MSDN:
@@ -463,7 +471,7 @@ unsafe impl<R: Runtime> raw_window_handle::HasRawWindowHandle for Window<R> {
463471
#[cfg(windows)]
464472
fn raw_window_handle(&self) -> raw_window_handle::RawWindowHandle {
465473
let mut handle = raw_window_handle::Win32Handle::empty();
466-
handle.hwnd = self.hwnd().expect("failed to get window `hwnd`");
474+
handle.hwnd = self.hwnd().expect("failed to get window `hwnd`").0 as *mut _;
467475
raw_window_handle::RawWindowHandle::Win32(handle)
468476
}
469477

@@ -909,13 +917,8 @@ impl<R: Runtime> Window<R> {
909917
}
910918
/// Returns the native handle that is used by this window.
911919
#[cfg(windows)]
912-
pub fn hwnd(&self) -> crate::Result<*mut std::ffi::c_void> {
913-
self
914-
.window
915-
.dispatcher
916-
.hwnd()
917-
.map(|hwnd| hwnd.0 as *mut _)
918-
.map_err(Into::into)
920+
pub fn hwnd(&self) -> crate::Result<HWND> {
921+
self.window.dispatcher.hwnd().map_err(Into::into)
919922
}
920923

921924
/// Returns the `ApplicatonWindow` from gtk crate that is used by this window.

examples/parent-window/README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Parent Window Example
2+
3+
Run the following at the root directory of the repository to try it out: `cargo run --example parent-window`.

examples/parent-window/index.html

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
<!DOCTYPE html>
2+
<html>
3+
4+
<head>
5+
<style>
6+
#response {
7+
white-space: pre-wrap;
8+
}
9+
</style>
10+
</head>
11+
12+
<body>
13+
<div id="window-label"></div>
14+
<div id="container"></div>
15+
<div id="response"></div>
16+
17+
<script>
18+
var WebviewWindow = window.__TAURI__.window.WebviewWindow
19+
var thisTauriWindow = window.__TAURI__.window.getCurrent()
20+
var windowLabel = thisTauriWindow.label
21+
var windowLabelContainer = document.getElementById('window-label')
22+
windowLabelContainer.innerText = 'This is the ' + windowLabel + ' window.'
23+
24+
var container = document.getElementById('container')
25+
26+
var responseContainer = document.getElementById('response')
27+
function runCommand(commandName, args, optional) {
28+
window.__TAURI__
29+
.invoke(commandName, args)
30+
.then((response) => {
31+
responseContainer.innerText += `Ok(${response})\n\n`
32+
})
33+
.catch((error) => {
34+
responseContainer.innerText += `Err(${error})\n\n`
35+
})
36+
}
37+
window.__TAURI__.event.listen('tauri://window-created', function (event) {
38+
responseContainer.innerText += 'Got window-created event\n\n'
39+
})
40+
41+
var createWindowButton = document.createElement('button')
42+
var windowNumber = 1
43+
createWindowButton.innerHTML = 'Create child window '+windowNumber
44+
createWindowButton.addEventListener('click', function () {
45+
runCommand('create_child_window', { id: 'child-'+windowNumber })
46+
windowNumber += 1
47+
createWindowButton.innerHTML = 'Create child window '+windowNumber
48+
})
49+
container.appendChild(createWindowButton)
50+
</script>
51+
</body>
52+
53+
</html>
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# Generated by Cargo
2+
# will have compiled files and executables
3+
/target/
4+
WixTools

0 commit comments

Comments
 (0)