Skip to content

Commit

Permalink
Implements PlatformExt::set_modal for macOS (#1221)
Browse files Browse the repository at this point in the history
  • Loading branch information
ultimaweapon authored Jan 2, 2025
1 parent 96f4632 commit 809b149
Show file tree
Hide file tree
Showing 5 changed files with 51 additions and 14 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions gui/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ windows-sys = { version = "0.59.0", features = [

[target.'cfg(target_os = "macos")'.dependencies]
applevisor-sys = "0.1.3"
block = "0.1.6"
core-foundation = "0.10.0"
core-foundation-sys = "0.8.7"
core-graphics-types = "0.1.3"
Expand Down
14 changes: 14 additions & 0 deletions gui/src/ui/backend/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,20 @@ impl WindowAdapter for Window {
assert!(self.visible.get().is_none());

self.winit.set_visible(true);

// Render initial frame. Without this the modal on macOS will show a blank window until
// show animation is complete.
let scale_factor = self.winit.scale_factor() as f32;
let size = self.winit.inner_size();
let size = PhysicalSize::new(size.width, size.height);
let size = LogicalSize::from_physical(size, scale_factor);

self.slint
.dispatch_event(WindowEvent::ScaleFactorChanged { scale_factor });
self.slint.dispatch_event(WindowEvent::Resized { size });

self.renderer.render()?;

self.visible.set(Some(true));
} else if self.visible.get().is_some_and(|v| v) {
self.winit.set_visible(false);
Expand Down
34 changes: 20 additions & 14 deletions gui/src/ui/macos/mod.rs
Original file line number Diff line number Diff line change
@@ -1,24 +1,20 @@
use self::view::with_window;
use super::PlatformExt;
use crate::rt::RuntimeWindow;
use objc::runtime::Object;
use block::ConcreteBlock;
use objc::{msg_send, sel, sel_impl};
use raw_window_handle::{HasWindowHandle, RawWindowHandle};
use slint::ComponentHandle;
use std::ffi::c_long;
use std::ops::Deref;
use thiserror::Error;

mod view;

impl<T: ComponentHandle> PlatformExt for T {
fn set_center(&self) -> Result<(), PlatformError> {
// Get NSView.
let win = self.window().window_handle();
let win = win.window_handle().unwrap();
let win = match win.as_ref() {
RawWindowHandle::AppKit(v) => v.ns_view.as_ptr().cast::<Object>(),
_ => unreachable!(),
};

// Get NSWindow and call center() method.
let win: *mut Object = unsafe { msg_send![win, window] };
let _: () = unsafe { msg_send![win, center] };
with_window::<()>(&self.window().window_handle(), |win| unsafe {
msg_send![win, center]
});

Ok(())
}
Expand All @@ -27,7 +23,17 @@ impl<T: ComponentHandle> PlatformExt for T {
where
P: RuntimeWindow + ?Sized,
{
todo!()
// Setup completionHandler.
let cb = ConcreteBlock::new(move |_: c_long| {}).copy();

// Show the sheet.
let win = self.window().window_handle();
let win = with_window(&win, |w| w);
let _: () = with_window(parent, |w| unsafe {
msg_send![w, beginSheet:win completionHandler:cb.deref()]
});

Ok(())
}
}

Expand Down
15 changes: 15 additions & 0 deletions gui/src/ui/macos/view.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
use objc::runtime::Object;
use objc::{msg_send, sel, sel_impl};
use raw_window_handle::{HasWindowHandle, RawWindowHandle};

pub fn with_window<T>(win: impl HasWindowHandle, f: impl FnOnce(*mut Object) -> T) -> T {
// Get NSView.
let win = win.window_handle().unwrap();
let win = match win.as_ref() {
RawWindowHandle::AppKit(v) => v.ns_view.as_ptr().cast::<Object>(),
_ => unreachable!(),
};

// Get NSWindow.
f(unsafe { msg_send![win, window] })
}

0 comments on commit 809b149

Please sign in to comment.