Skip to content

Commit

Permalink
feat(macOS): Allow creation of child Window (#160)
Browse files Browse the repository at this point in the history
  • Loading branch information
lemarier authored Aug 4, 2021
1 parent f4d718a commit 73c7aac
Show file tree
Hide file tree
Showing 5 changed files with 92 additions and 3 deletions.
5 changes: 5 additions & 0 deletions .changes/parent-support.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"tao": patch
---

macOS: Add `with_parent_window()` on `WindowBuilder`.
62 changes: 62 additions & 0 deletions examples/parentwindow.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
// Copyright 2019-2021 Tauri Programme within The Commons Conservancy
// SPDX-License-Identifier: Apache-2.0

#[cfg(any(target_os = "windows", target_os = "macos"))]
fn main() {
use simple_logger::SimpleLogger;
use std::collections::HashMap;
#[cfg(target_os = "macos")]
use tao::platform::macos::{WindowBuilderExtMacOS, WindowExtMacOS};
#[cfg(target_os = "windows")]
use tao::platform::windows::{WindowBuilderExtWindows, WindowExtWindows};
use tao::{
dpi::LogicalSize,
event::{Event, StartCause, WindowEvent},
event_loop::{ControlFlow, EventLoop},
window::WindowBuilder,
};
#[cfg(target_os = "windows")]
use winapi::shared::windef::HWND;
SimpleLogger::new().init().unwrap();
let event_loop = EventLoop::new();
let mut windows = HashMap::new();
let main_window = WindowBuilder::new().build(&event_loop).unwrap();

#[cfg(target_os = "macos")]
let parent_window = main_window.ns_window();
#[cfg(target_os = "windows")]
let parent_window = main_window.hwnd() as HWND;

let child_window = WindowBuilder::new()
.with_parent_window(parent_window)
.with_inner_size(LogicalSize::new(200, 200))
.build(&event_loop)
.unwrap();

windows.insert(child_window.id(), child_window);
windows.insert(main_window.id(), main_window);

event_loop.run(move |event, _, control_flow| {
*control_flow = ControlFlow::Wait;

match event {
Event::NewEvents(StartCause::Init) => println!("TAO application started!"),
Event::WindowEvent {
event, window_id, ..
} if event == WindowEvent::CloseRequested => {
println!("Window {:?} has received the signal to close", window_id);
// This drop the window, causing it to close.
windows.remove(&window_id);
if windows.is_empty() {
*control_flow = ControlFlow::Exit;
}
}
_ => (),
};
})
}

#[cfg(not(any(target_os = "windows", target_os = "macos")))]
fn main() {
println!("This platform doesn't have the parent window support.");
}
10 changes: 9 additions & 1 deletion src/platform/macos.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use crate::{
event_loop::{EventLoop, EventLoopWindowTarget},
menu::CustomMenuItem,
monitor::MonitorHandle,
platform_impl::get_aux_state_mut,
platform_impl::{get_aux_state_mut, Parent},
window::{Window, WindowBuilder},
};

Expand Down Expand Up @@ -304,6 +304,8 @@ impl NativeImage {
/// - `with_titlebar_buttons_hidden`
/// - `with_fullsize_content_view`
pub trait WindowBuilderExtMacOS {
/// Sets a parent to the window to be created.
fn with_parent_window(self, parent: *mut c_void) -> WindowBuilder;
/// Enables click-and-drag behavior for the entire window, not just the titlebar.
fn with_movable_by_window_background(self, movable_by_window_background: bool) -> WindowBuilder;
/// Makes the titlebar transparent and allows the content to appear behind it.
Expand All @@ -323,6 +325,12 @@ pub trait WindowBuilderExtMacOS {
}

impl WindowBuilderExtMacOS for WindowBuilder {
#[inline]
fn with_parent_window(mut self, parent: *mut c_void) -> WindowBuilder {
self.platform_specific.parent = Parent::ChildOf(parent);
self
}

#[inline]
fn with_movable_by_window_background(
mut self,
Expand Down
2 changes: 1 addition & 1 deletion src/platform_impl/macos/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ pub use self::{
keycode::{keycode_from_scancode, keycode_to_scancode},
menu::{Menu, MenuItemAttributes},
monitor::{MonitorHandle, VideoMode},
window::{Id as WindowId, PlatformSpecificWindowBuilderAttributes, UnownedWindow},
window::{Id as WindowId, Parent, PlatformSpecificWindowBuilderAttributes, UnownedWindow},
};
use crate::{
error::OsError as RootOsError, event::DeviceId as RootDeviceId, window::WindowAttributes,
Expand Down
16 changes: 15 additions & 1 deletion src/platform_impl/macos/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ use crate::{
use cocoa::{
appkit::{
self, CGFloat, NSApp, NSApplication, NSApplicationPresentationOptions, NSColor,
NSRequestUserAttentionType, NSScreen, NSView, NSWindow, NSWindowButton, NSWindowStyleMask,
NSRequestUserAttentionType, NSScreen, NSView, NSWindow, NSWindowButton, NSWindowOrderingMode,
NSWindowStyleMask,
},
base::{id, nil},
foundation::{NSAutoreleasePool, NSDictionary, NSPoint, NSRect, NSSize},
Expand Down Expand Up @@ -62,8 +63,16 @@ pub fn get_window_id(window_cocoa_id: id) -> Id {
Id(window_cocoa_id as *const Object as _)
}

#[non_exhaustive]
#[derive(Clone)]
pub enum Parent {
None,
ChildOf(*mut c_void),
}

#[derive(Clone)]
pub struct PlatformSpecificWindowBuilderAttributes {
pub parent: Parent,
pub movable_by_window_background: bool,
pub titlebar_transparent: bool,
pub title_hidden: bool,
Expand All @@ -79,6 +88,7 @@ impl Default for PlatformSpecificWindowBuilderAttributes {
#[inline]
fn default() -> Self {
Self {
parent: Parent::None,
movable_by_window_background: false,
titlebar_transparent: false,
title_hidden: false,
Expand Down Expand Up @@ -229,6 +239,10 @@ fn create_window(
}
}

if let Parent::ChildOf(parent) = pl_attrs.parent {
let _: () = msg_send![parent as id, addChildWindow: *ns_window ordered: NSWindowOrderingMode::NSWindowAbove];
}

if !pl_attrs.has_shadow {
ns_window.setHasShadow_(NO);
}
Expand Down

0 comments on commit 73c7aac

Please sign in to comment.