Skip to content

Commit 19360ea

Browse files
authored
Port dioxus to objc2 (#5101)
Signed-off-by: Nico Burns <nico@nicoburns.com>
1 parent 2f40780 commit 19360ea

5 files changed

Lines changed: 58 additions & 102 deletions

File tree

Cargo.lock

Lines changed: 4 additions & 55 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,10 @@ infer = "0.19.0"
344344
dunce = "1.0.5"
345345
percent-encoding = "2.3.1"
346346
muda = "0.17.0"
347+
objc2 = { version = "0.6.3", features = ["exception"] }
348+
objc2-foundation = { version = "0.3.2", default-features = false }
349+
objc2-ui-kit = { version = "0.3.2", default-features = false }
350+
objc2-app-kit = { version = "0.3.2", default-features = false }
347351
tray-icon = "0.21.0"
348352
open = "5.3.2"
349353
webbrowser = "1.0"

packages/desktop/Cargo.toml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,9 @@ muda = { workspace = true }
7070
tray-icon = { workspace = true }
7171

7272
[target.'cfg(target_os = "ios")'.dependencies]
73-
objc = "0.2.7"
74-
objc_id = "0.1.1"
73+
objc2 = { workspace = true }
74+
objc2-foundation = { workspace = true, features = ["NSThread"] }
75+
objc2-ui-kit = { workspace = true, features = ["UIView", "UIViewController"] }
7576

7677
# use rustls on android
7778
[target.'cfg(target_os = "android")'.dependencies]
@@ -86,9 +87,8 @@ ndk-context = { version = "0.1.1" }
8687
tungstenite = { workspace = true, features = ["native-tls"] }
8788

8889
[target.'cfg(target_os = "macos")'.dependencies]
89-
cocoa = "0.26.1"
90-
core-foundation = "0.10.1"
91-
objc = "0.2.7"
90+
objc2 = { workspace = true }
91+
objc2-app-kit = { workspace = true, features = ["NSView"] }
9292

9393
[build-dependencies]
9494
lazy-js-bundle = { workspace = true }

packages/desktop/src/desktop_context.rs

Lines changed: 40 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@ use tao::{
2323
};
2424
use wry::{RequestAsyncResponder, WebView};
2525

26+
#[cfg(target_os = "ios")]
27+
use objc2::rc::Retained;
28+
#[cfg(target_os = "ios")]
29+
use objc2_ui_kit::UIView;
2630
#[cfg(target_os = "ios")]
2731
use tao::platform::ios::WindowExtIOS;
2832

@@ -71,7 +75,7 @@ pub struct DesktopService {
7175
pub(crate) close_behaviour: Rc<Cell<WindowCloseBehaviour>>,
7276

7377
#[cfg(target_os = "ios")]
74-
pub(crate) views: Rc<std::cell::RefCell<Vec<*mut objc::runtime::Object>>>,
78+
pub(crate) views: Rc<std::cell::RefCell<Vec<Retained<UIView>>>>,
7579
}
7680

7781
/// A smart pointer to the current window.
@@ -288,51 +292,54 @@ impl DesktopService {
288292
self.asset_handlers.remove_handler(name).map(|_| ())
289293
}
290294

295+
#[cfg(target_os = "ios")]
296+
/// Get a retained reference to the current UIView
297+
pub fn ui_view(&self) -> objc2::rc::Retained<objc2_ui_kit::UIView> {
298+
use objc2::rc::Retained;
299+
use objc2_ui_kit::UIView;
300+
let ui_view = self.window.ui_view().cast::<UIView>();
301+
unsafe { Retained::retain(ui_view) }.unwrap()
302+
}
303+
304+
#[cfg(target_os = "ios")]
305+
/// Get a retained reference to the current UIViewController
306+
pub fn ui_view_controller(&self) -> objc2::rc::Retained<objc2_ui_kit::UIViewController> {
307+
use objc2::rc::Retained;
308+
use objc2_ui_kit::UIViewController;
309+
let ui_view_controller = self.window.ui_view_controller().cast::<UIViewController>();
310+
unsafe { Retained::retain(ui_view_controller) }.unwrap()
311+
}
312+
291313
/// Push an objc view to the window
292314
#[cfg(target_os = "ios")]
293-
pub fn push_view(&self, view: objc_id::ShareId<objc::runtime::Object>) {
294-
let window = &self.window;
295-
296-
unsafe {
297-
use objc::runtime::Object;
298-
use objc::*;
299-
assert!(is_main_thread());
300-
let ui_view = window.ui_view() as *mut Object;
301-
let ui_view_frame: *mut Object = msg_send![ui_view, frame];
302-
let _: () = msg_send![view, setFrame: ui_view_frame];
303-
let _: () = msg_send![view, setAutoresizingMask: 31];
304-
305-
let ui_view_controller = window.ui_view_controller() as *mut Object;
306-
let _: () = msg_send![ui_view_controller, setView: view];
307-
self.views.borrow_mut().push(ui_view);
308-
}
315+
pub fn push_view(&self, new_view: Retained<UIView>) {
316+
use objc2_ui_kit::UIViewAutoresizing;
317+
318+
assert!(is_main_thread());
319+
let current_ui_view = self.ui_view();
320+
let current_ui_view_frame = current_ui_view.frame();
321+
322+
new_view.setFrame(current_ui_view_frame);
323+
new_view.setAutoresizingMask(UIViewAutoresizing::from_bits(31).unwrap());
324+
325+
let ui_view_controller = self.ui_view_controller();
326+
ui_view_controller.setView(Some(&new_view));
327+
self.views.borrow_mut().push(new_view);
309328
}
310329

311330
/// Pop an objc view from the window
312331
#[cfg(target_os = "ios")]
313332
pub fn pop_view(&self) {
314-
let window = &self.window;
315-
316-
unsafe {
317-
use objc::runtime::Object;
318-
use objc::*;
319-
assert!(is_main_thread());
320-
if let Some(view) = self.views.borrow_mut().pop() {
321-
let ui_view_controller = window.ui_view_controller() as *mut Object;
322-
let _: () = msg_send![ui_view_controller, setView: view];
323-
}
333+
assert!(is_main_thread());
334+
if let Some(view) = self.views.borrow_mut().pop() {
335+
self.ui_view_controller().setView(Some(&view));
324336
}
325337
}
326338
}
327339

328340
#[cfg(target_os = "ios")]
329341
fn is_main_thread() -> bool {
330-
use objc::runtime::{Class, BOOL, NO};
331-
use objc::*;
332-
333-
let cls = Class::get("NSThread").unwrap();
334-
let result: BOOL = unsafe { msg_send![cls, isMainThread] };
335-
result != NO
342+
objc2_foundation::NSThread::isMainThread_class()
336343
}
337344

338345
/// A [`DesktopContext`] that is pending creation.

packages/desktop/src/webview.rs

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -244,17 +244,13 @@ impl WebviewInstance {
244244

245245
// https://developer.apple.com/documentation/appkit/nswindowcollectionbehavior/nswindowcollectionbehaviormanaged
246246
#[cfg(target_os = "macos")]
247-
#[allow(deprecated)]
248247
{
249-
use cocoa::appkit::NSWindowCollectionBehavior;
250-
use cocoa::base::id;
251-
use objc::{msg_send, sel, sel_impl};
248+
use objc2::rc::Retained;
249+
use objc2_app_kit::{NSWindow, NSWindowCollectionBehavior};
252250
use tao::platform::macos::WindowExtMacOS;
253-
254-
unsafe {
255-
let window: id = window.ns_window() as id;
256-
let _: () = msg_send![window, setCollectionBehavior: NSWindowCollectionBehavior::NSWindowCollectionBehaviorManaged];
257-
}
251+
let ns_window: Retained<NSWindow> =
252+
unsafe { Retained::retain(window.ns_window().cast()) }.unwrap();
253+
ns_window.setCollectionBehavior(NSWindowCollectionBehavior::Managed)
258254
}
259255

260256
let mut web_context = WebContext::new(cfg.data_dir.clone().or_else(|| {

0 commit comments

Comments
 (0)