Update objc2 version (#2936)

* Upgrade to objc2 v0.4.0 and icrate v0.0.3

* Fix `touchBar` method

* Use ClassType::alloc

* Use #[method_id(...)] functionality in declare_class!
This commit is contained in:
Mads Marquart 2023-07-29 00:33:03 +02:00 committed by GitHub
parent ae7497e18f
commit e33d2bee6c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
53 changed files with 815 additions and 793 deletions

View file

@ -74,12 +74,38 @@ ndk-sys = "0.4.0"
[target.'cfg(any(target_os = "ios", target_os = "macos"))'.dependencies]
core-foundation = "0.9.3"
objc2 = ">=0.3.0-beta.3, <0.3.0-beta.4" # Allow `0.3.0-beta.3.patch-leaks`
objc2 = "0.4.0"
[target.'cfg(target_os = "macos")'.dependencies]
core-graphics = "0.22.3"
dispatch = "0.2.0"
[target.'cfg(target_os = "macos")'.dependencies.icrate]
version = "0.0.3"
features = [
"Foundation",
"Foundation_NSArray",
"Foundation_NSAttributedString",
"Foundation_NSMutableAttributedString",
"Foundation_NSData",
"Foundation_NSDictionary",
"Foundation_NSString",
"Foundation_NSProcessInfo",
"Foundation_NSThread",
"Foundation_NSNumber",
]
[target.'cfg(target_os = "ios")'.dependencies.icrate]
version = "0.0.3"
features = [
"Foundation",
"Foundation_NSArray",
"Foundation_NSString",
"Foundation_NSProcessInfo",
"Foundation_NSThread",
"Foundation_NSSet",
]
[target.'cfg(target_os = "windows")'.dependencies]
unicode-segmentation = "1.7.1"

View file

@ -15,8 +15,8 @@ use core_foundation::runloop::{
kCFRunLoopCommonModes, CFRunLoopAddTimer, CFRunLoopGetMain, CFRunLoopRef, CFRunLoopTimerCreate,
CFRunLoopTimerInvalidate, CFRunLoopTimerRef, CFRunLoopTimerSetNextFireDate,
};
use objc2::foundation::{CGRect, CGSize, NSInteger, NSProcessInfo};
use objc2::rc::{Id, Shared};
use icrate::Foundation::{CGRect, CGSize, NSInteger, NSProcessInfo};
use objc2::rc::Id;
use objc2::runtime::Object;
use objc2::{msg_send, sel};
use once_cell::sync::Lazy;
@ -68,25 +68,25 @@ impl Event<'static, Never> {
#[must_use = "dropping `AppStateImpl` without inspecting it is probably a bug"]
enum AppStateImpl {
NotLaunched {
queued_windows: Vec<Id<WinitUIWindow, Shared>>,
queued_windows: Vec<Id<WinitUIWindow>>,
queued_events: Vec<EventWrapper>,
queued_gpu_redraws: HashSet<Id<WinitUIWindow, Shared>>,
queued_gpu_redraws: HashSet<Id<WinitUIWindow>>,
},
Launching {
queued_windows: Vec<Id<WinitUIWindow, Shared>>,
queued_windows: Vec<Id<WinitUIWindow>>,
queued_events: Vec<EventWrapper>,
queued_event_handler: Box<dyn EventHandler>,
queued_gpu_redraws: HashSet<Id<WinitUIWindow, Shared>>,
queued_gpu_redraws: HashSet<Id<WinitUIWindow>>,
},
ProcessingEvents {
event_handler: Box<dyn EventHandler>,
queued_gpu_redraws: HashSet<Id<WinitUIWindow, Shared>>,
queued_gpu_redraws: HashSet<Id<WinitUIWindow>>,
active_control_flow: ControlFlow,
},
// special state to deal with reentrancy and prevent mutable aliasing.
InUserCallback {
queued_events: Vec<EventWrapper>,
queued_gpu_redraws: HashSet<Id<WinitUIWindow, Shared>>,
queued_gpu_redraws: HashSet<Id<WinitUIWindow>>,
},
ProcessingRedraws {
event_handler: Box<dyn EventHandler>,
@ -204,9 +204,7 @@ impl AppState {
});
}
fn did_finish_launching_transition(
&mut self,
) -> (Vec<Id<WinitUIWindow, Shared>>, Vec<EventWrapper>) {
fn did_finish_launching_transition(&mut self) -> (Vec<Id<WinitUIWindow>>, Vec<EventWrapper>) {
let (windows, events, event_handler, queued_gpu_redraws) = match self.take_state() {
AppStateImpl::Launching {
queued_windows,
@ -363,7 +361,7 @@ impl AppState {
}
}
fn main_events_cleared_transition(&mut self) -> HashSet<Id<WinitUIWindow, Shared>> {
fn main_events_cleared_transition(&mut self) -> HashSet<Id<WinitUIWindow>> {
let (event_handler, queued_gpu_redraws, active_control_flow) = match self.take_state() {
AppStateImpl::ProcessingEvents {
event_handler,
@ -451,7 +449,7 @@ impl AppState {
// requires main thread and window is a UIWindow
// retains window
pub(crate) unsafe fn set_key_window(window: &Id<WinitUIWindow, Shared>) {
pub(crate) unsafe fn set_key_window(window: &Id<WinitUIWindow>) {
let mut this = AppState::get_mut();
match this.state_mut() {
&mut AppStateImpl::NotLaunched {
@ -474,7 +472,7 @@ pub(crate) unsafe fn set_key_window(window: &Id<WinitUIWindow, Shared>) {
// requires main thread and window is a UIWindow
// retains window
pub(crate) unsafe fn queue_gl_or_metal_redraw(window: Id<WinitUIWindow, Shared>) {
pub(crate) unsafe fn queue_gl_or_metal_redraw(window: Id<WinitUIWindow>) {
let mut this = AppState::get_mut();
match this.state_mut() {
&mut AppStateImpl::NotLaunched {
@ -807,7 +805,7 @@ fn handle_hidpi_proxy(
mut control_flow: ControlFlow,
suggested_size: LogicalSize<f64>,
scale_factor: f64,
window: Id<WinitUIWindow, Shared>,
window: Id<WinitUIWindow>,
) {
let mut size = suggested_size.to_physical(scale_factor);
let new_inner_size = &mut size;
@ -827,7 +825,7 @@ fn handle_hidpi_proxy(
view.setFrame(new_frame);
}
fn get_view_and_screen_frame(window: &WinitUIWindow) -> (Id<UIView, Shared>, CGRect) {
fn get_view_and_screen_frame(window: &WinitUIWindow) -> (Id<UIView>, CGRect) {
let view_controller = window.rootViewController().unwrap();
let view = view_controller.view().unwrap();
let bounds = window.bounds();
@ -963,7 +961,7 @@ impl NSOperatingSystemVersion {
pub fn os_capabilities() -> OSCapabilities {
static OS_CAPABILITIES: Lazy<OSCapabilities> = Lazy::new(|| {
let version: NSOperatingSystemVersion = unsafe {
let process_info = NSProcessInfo::process_info();
let process_info = NSProcessInfo::processInfo();
let atleast_ios_8: bool = msg_send![
&process_info,
respondsToSelector: sel!(operatingSystemVersion)

View file

@ -14,8 +14,8 @@ use core_foundation::runloop::{
CFRunLoopObserverCreate, CFRunLoopObserverRef, CFRunLoopSourceContext, CFRunLoopSourceCreate,
CFRunLoopSourceInvalidate, CFRunLoopSourceRef, CFRunLoopSourceSignal, CFRunLoopWakeUp,
};
use objc2::foundation::{MainThreadMarker, NSString};
use objc2::rc::{Id, Shared};
use icrate::Foundation::{MainThreadMarker, NSString};
use objc2::rc::Id;
use objc2::ClassType;
use raw_window_handle::{RawDisplayHandle, UiKitDisplayHandle};
@ -40,7 +40,7 @@ pub(crate) enum EventWrapper {
#[derive(Debug, PartialEq)]
pub(crate) enum EventProxy {
DpiChangedProxy {
window: Id<WinitUIWindow, Shared>,
window: Id<WinitUIWindow>,
suggested_size: LogicalSize<f64>,
scale_factor: f64,
},

View file

@ -2,8 +2,8 @@
use std::convert::TryInto;
use icrate::Foundation::{NSInteger, NSUInteger};
use objc2::encode::{Encode, Encoding};
use objc2::foundation::{NSInteger, NSUInteger};
use crate::platform::ios::{Idiom, ScreenEdge};

View file

@ -63,7 +63,7 @@
// window size/position.
macro_rules! assert_main_thread {
($($t:tt)*) => {
if !::objc2::foundation::is_main_thread() {
if !::icrate::Foundation::is_main_thread() {
panic!($($t)*);
}
};

View file

@ -6,8 +6,8 @@ use std::{
ops::{Deref, DerefMut},
};
use objc2::foundation::{MainThreadMarker, NSInteger};
use objc2::rc::{Id, Shared};
use icrate::Foundation::{MainThreadMarker, NSInteger};
use objc2::rc::Id;
use super::uikit::{UIScreen, UIScreenMode};
use crate::{
@ -18,7 +18,7 @@ use crate::{
// TODO(madsmtm): Remove or refactor this
#[derive(Debug, PartialEq, Eq, Hash, Clone)]
pub(crate) struct ScreenModeSendSync(pub(crate) Id<UIScreenMode, Shared>);
pub(crate) struct ScreenModeSendSync(pub(crate) Id<UIScreenMode>);
unsafe impl Send for ScreenModeSendSync {}
unsafe impl Sync for ScreenModeSendSync {}
@ -33,7 +33,7 @@ pub struct VideoMode {
}
impl VideoMode {
fn new(uiscreen: Id<UIScreen, Shared>, screen_mode: Id<UIScreenMode, Shared>) -> VideoMode {
fn new(uiscreen: Id<UIScreen>, screen_mode: Id<UIScreenMode>) -> VideoMode {
assert_main_thread!("`VideoMode` can only be created on the main thread on iOS");
let refresh_rate_millihertz = refresh_rate_millihertz(&uiscreen);
let size = screen_mode.size();
@ -65,7 +65,7 @@ impl VideoMode {
#[derive(Clone, PartialEq, Eq, Hash)]
pub struct Inner {
uiscreen: Id<UIScreen, Shared>,
uiscreen: Id<UIScreen>,
}
#[derive(Clone, PartialEq, Eq, Hash)]
@ -135,7 +135,7 @@ impl fmt::Debug for MonitorHandle {
}
impl MonitorHandle {
pub(crate) fn new(uiscreen: Id<UIScreen, Shared>) -> Self {
pub(crate) fn new(uiscreen: Id<UIScreen>) -> Self {
assert_main_thread!("`MonitorHandle` can only be created on the main thread on iOS");
Self {
inner: Inner { uiscreen },
@ -182,13 +182,8 @@ impl Inner {
.uiscreen
.availableModes()
.into_iter()
.map(|mode| {
let mode: *const UIScreenMode = mode;
let mode = unsafe { Id::retain(mode as *mut UIScreenMode).unwrap() };
RootVideoMode {
video_mode: VideoMode::new(self.uiscreen.clone(), mode),
}
.map(|mode| RootVideoMode {
video_mode: VideoMode::new(self.uiscreen.clone(), mode),
})
.collect();
@ -222,7 +217,7 @@ fn refresh_rate_millihertz(uiscreen: &UIScreen) -> u32 {
// MonitorHandleExtIOS
impl Inner {
pub(crate) fn ui_screen(&self) -> &Id<UIScreen, Shared> {
pub(crate) fn ui_screen(&self) -> &Id<UIScreen> {
&self.uiscreen
}
@ -237,10 +232,6 @@ impl Inner {
pub fn uiscreens(mtm: MainThreadMarker) -> VecDeque<MonitorHandle> {
UIScreen::screens(mtm)
.into_iter()
.map(|screen| {
let screen: *const UIScreen = screen;
let screen = unsafe { Id::retain(screen as *mut UIScreen).unwrap() };
MonitorHandle::new(screen)
})
.map(MonitorHandle::new)
.collect()
}

View file

@ -1,6 +1,6 @@
use objc2::foundation::{CGRect, MainThreadMarker, NSArray, NSObject};
use objc2::rc::{Id, Shared};
use objc2::{extern_class, extern_methods, msg_send_id, ClassType};
use icrate::Foundation::{CGRect, MainThreadMarker, NSArray, NSObject};
use objc2::rc::Id;
use objc2::{extern_class, extern_methods, msg_send_id, mutability, ClassType};
use super::{UIResponder, UIWindow};
@ -11,20 +11,21 @@ extern_class!(
unsafe impl ClassType for UIApplication {
#[inherits(NSObject)]
type Super = UIResponder;
type Mutability = mutability::InteriorMutable;
}
);
extern_methods!(
unsafe impl UIApplication {
pub fn shared(_mtm: MainThreadMarker) -> Option<Id<Self, Shared>> {
pub fn shared(_mtm: MainThreadMarker) -> Option<Id<Self>> {
unsafe { msg_send_id![Self::class(), sharedApplication] }
}
pub fn windows(&self) -> Id<NSArray<UIWindow, Shared>, Shared> {
pub fn windows(&self) -> Id<NSArray<UIWindow>> {
unsafe { msg_send_id![self, windows] }
}
#[sel(statusBarFrame)]
#[method(statusBarFrame)]
pub fn statusBarFrame(&self) -> CGRect;
}
);

View file

@ -1,5 +1,5 @@
use objc2::foundation::NSObject;
use objc2::{extern_class, ClassType};
use icrate::Foundation::NSObject;
use objc2::{extern_class, mutability, ClassType};
extern_class!(
#[derive(Debug, PartialEq, Eq, Hash)]
@ -7,5 +7,6 @@ extern_class!(
unsafe impl ClassType for UICoordinateSpace {
type Super = NSObject;
type Mutability = mutability::InteriorMutable;
}
);

View file

@ -1,6 +1,6 @@
use objc2::foundation::{MainThreadMarker, NSObject};
use objc2::rc::{Id, Shared};
use objc2::{extern_class, extern_methods, msg_send_id, ClassType};
use icrate::Foundation::{MainThreadMarker, NSObject};
use objc2::rc::Id;
use objc2::{extern_class, extern_methods, msg_send_id, mutability, ClassType};
use super::super::ffi::UIUserInterfaceIdiom;
@ -10,16 +10,17 @@ extern_class!(
unsafe impl ClassType for UIDevice {
type Super = NSObject;
type Mutability = mutability::InteriorMutable;
}
);
extern_methods!(
unsafe impl UIDevice {
pub fn current(_mtm: MainThreadMarker) -> Id<Self, Shared> {
pub fn current(_mtm: MainThreadMarker) -> Id<Self> {
unsafe { msg_send_id![Self::class(), currentDevice] }
}
#[sel(userInterfaceIdiom)]
#[method(userInterfaceIdiom)]
pub fn userInterfaceIdiom(&self) -> UIUserInterfaceIdiom;
}
);

View file

@ -1,5 +1,5 @@
use objc2::foundation::NSObject;
use objc2::{extern_class, ClassType};
use icrate::Foundation::NSObject;
use objc2::{extern_class, mutability, ClassType};
extern_class!(
#[derive(Debug, PartialEq, Eq, Hash)]
@ -7,5 +7,6 @@ extern_class!(
unsafe impl ClassType for UIEvent {
type Super = NSObject;
type Mutability = mutability::InteriorMutable;
}
);

View file

@ -4,7 +4,7 @@
use std::os::raw::{c_char, c_int};
use objc2::foundation::NSString;
use icrate::Foundation::NSString;
mod application;
mod coordinate_space;

View file

@ -1,5 +1,5 @@
use objc2::foundation::NSObject;
use objc2::{extern_class, ClassType};
use icrate::Foundation::NSObject;
use objc2::{extern_class, mutability, ClassType};
extern_class!(
#[derive(Debug, PartialEq, Eq, Hash)]
@ -7,5 +7,6 @@ extern_class!(
unsafe impl ClassType for UIResponder {
type Super = NSObject;
type Mutability = mutability::InteriorMutable;
}
);

View file

@ -1,7 +1,7 @@
use icrate::Foundation::{CGFloat, CGRect, MainThreadMarker, NSArray, NSInteger, NSObject};
use objc2::encode::{Encode, Encoding};
use objc2::foundation::{CGFloat, CGRect, MainThreadMarker, NSArray, NSInteger, NSObject};
use objc2::rc::{Id, Shared};
use objc2::{extern_class, extern_methods, msg_send_id, ClassType};
use objc2::rc::Id;
use objc2::{extern_class, extern_methods, msg_send_id, mutability, ClassType};
use super::{UICoordinateSpace, UIScreenMode};
@ -11,53 +11,54 @@ extern_class!(
unsafe impl ClassType for UIScreen {
type Super = NSObject;
type Mutability = mutability::InteriorMutable;
}
);
extern_methods!(
unsafe impl UIScreen {
pub fn main(_mtm: MainThreadMarker) -> Id<Self, Shared> {
pub fn main(_mtm: MainThreadMarker) -> Id<Self> {
unsafe { msg_send_id![Self::class(), mainScreen] }
}
pub fn screens(_mtm: MainThreadMarker) -> Id<NSArray<Self, Shared>, Shared> {
pub fn screens(_mtm: MainThreadMarker) -> Id<NSArray<Self>> {
unsafe { msg_send_id![Self::class(), screens] }
}
#[sel(bounds)]
#[method(bounds)]
pub fn bounds(&self) -> CGRect;
#[sel(scale)]
#[method(scale)]
pub fn scale(&self) -> CGFloat;
#[sel(nativeBounds)]
#[method(nativeBounds)]
pub fn nativeBounds(&self) -> CGRect;
#[sel(nativeScale)]
#[method(nativeScale)]
pub fn nativeScale(&self) -> CGFloat;
#[sel(maximumFramesPerSecond)]
#[method(maximumFramesPerSecond)]
pub fn maximumFramesPerSecond(&self) -> NSInteger;
pub fn mirroredScreen(&self) -> Id<Self, Shared> {
pub fn mirroredScreen(&self) -> Id<Self> {
unsafe { msg_send_id![Self::class(), mirroredScreen] }
}
pub fn preferredMode(&self) -> Option<Id<UIScreenMode, Shared>> {
pub fn preferredMode(&self) -> Option<Id<UIScreenMode>> {
unsafe { msg_send_id![self, preferredMode] }
}
#[sel(setCurrentMode:)]
#[method(setCurrentMode:)]
pub fn setCurrentMode(&self, mode: Option<&UIScreenMode>);
pub fn availableModes(&self) -> Id<NSArray<UIScreenMode, Shared>, Shared> {
pub fn availableModes(&self) -> Id<NSArray<UIScreenMode>> {
unsafe { msg_send_id![self, availableModes] }
}
#[sel(setOverscanCompensation:)]
#[method(setOverscanCompensation:)]
pub fn setOverscanCompensation(&self, overscanCompensation: UIScreenOverscanCompensation);
pub fn coordinateSpace(&self) -> Id<UICoordinateSpace, Shared> {
pub fn coordinateSpace(&self) -> Id<UICoordinateSpace> {
unsafe { msg_send_id![self, coordinateSpace] }
}
}

View file

@ -1,5 +1,5 @@
use objc2::foundation::{CGSize, NSObject};
use objc2::{extern_class, extern_methods, ClassType};
use icrate::Foundation::{CGSize, NSObject};
use objc2::{extern_class, extern_methods, mutability, ClassType};
extern_class!(
#[derive(Debug, PartialEq, Eq, Hash)]
@ -7,12 +7,13 @@ extern_class!(
unsafe impl ClassType for UIScreenMode {
type Super = NSObject;
type Mutability = mutability::InteriorMutable;
}
);
extern_methods!(
unsafe impl UIScreenMode {
#[sel(size)]
#[method(size)]
pub fn size(&self) -> CGSize;
}
);

View file

@ -1,6 +1,6 @@
use icrate::Foundation::{CGFloat, CGPoint, NSInteger, NSObject};
use objc2::encode::{Encode, Encoding};
use objc2::foundation::{CGFloat, CGPoint, NSInteger, NSObject};
use objc2::{extern_class, extern_methods, ClassType};
use objc2::{extern_class, extern_methods, mutability, ClassType};
use super::UIView;
@ -10,27 +10,28 @@ extern_class!(
unsafe impl ClassType for UITouch {
type Super = NSObject;
type Mutability = mutability::InteriorMutable;
}
);
extern_methods!(
unsafe impl UITouch {
#[sel(locationInView:)]
#[method(locationInView:)]
pub fn locationInView(&self, view: Option<&UIView>) -> CGPoint;
#[sel(type)]
#[method(type)]
pub fn type_(&self) -> UITouchType;
#[sel(force)]
#[method(force)]
pub fn force(&self) -> CGFloat;
#[sel(maximumPossibleForce)]
#[method(maximumPossibleForce)]
pub fn maximumPossibleForce(&self) -> CGFloat;
#[sel(altitudeAngle)]
#[method(altitudeAngle)]
pub fn altitudeAngle(&self) -> CGFloat;
#[sel(phase)]
#[method(phase)]
pub fn phase(&self) -> UITouchPhase;
}
);

View file

@ -1,6 +1,6 @@
use icrate::Foundation::{NSInteger, NSObject};
use objc2::encode::{Encode, Encoding};
use objc2::foundation::{NSInteger, NSObject};
use objc2::{extern_class, extern_methods, ClassType};
use objc2::{extern_class, extern_methods, mutability, ClassType};
extern_class!(
#[derive(Debug, PartialEq, Eq, Hash)]
@ -8,12 +8,13 @@ extern_class!(
unsafe impl ClassType for UITraitCollection {
type Super = NSObject;
type Mutability = mutability::InteriorMutable;
}
);
extern_methods!(
unsafe impl UITraitCollection {
#[sel(forceTouchCapability)]
#[method(forceTouchCapability)]
pub fn forceTouchCapability(&self) -> UIForceTouchCapability;
}
);

View file

@ -1,7 +1,7 @@
use icrate::Foundation::{CGFloat, CGRect, NSObject};
use objc2::encode::{Encode, Encoding};
use objc2::foundation::{CGFloat, CGRect, NSObject};
use objc2::rc::{Id, Shared};
use objc2::{extern_class, extern_methods, msg_send_id, ClassType};
use objc2::rc::Id;
use objc2::{extern_class, extern_methods, msg_send_id, mutability, ClassType};
use super::{UICoordinateSpace, UIResponder, UIViewController};
@ -12,57 +12,58 @@ extern_class!(
unsafe impl ClassType for UIView {
#[inherits(NSObject)]
type Super = UIResponder;
type Mutability = mutability::InteriorMutable;
}
);
extern_methods!(
unsafe impl UIView {
#[sel(bounds)]
#[method(bounds)]
pub fn bounds(&self) -> CGRect;
#[sel(setBounds:)]
#[method(setBounds:)]
pub fn setBounds(&self, value: CGRect);
#[sel(frame)]
#[method(frame)]
pub fn frame(&self) -> CGRect;
#[sel(setFrame:)]
#[method(setFrame:)]
pub fn setFrame(&self, value: CGRect);
#[sel(contentScaleFactor)]
#[method(contentScaleFactor)]
pub fn contentScaleFactor(&self) -> CGFloat;
#[sel(setContentScaleFactor:)]
#[method(setContentScaleFactor:)]
pub fn setContentScaleFactor(&self, val: CGFloat);
#[sel(setMultipleTouchEnabled:)]
#[method(setMultipleTouchEnabled:)]
pub fn setMultipleTouchEnabled(&self, val: bool);
pub fn rootViewController(&self) -> Option<Id<UIViewController, Shared>> {
pub fn rootViewController(&self) -> Option<Id<UIViewController>> {
unsafe { msg_send_id![self, rootViewController] }
}
#[sel(setRootViewController:)]
#[method(setRootViewController:)]
pub fn setRootViewController(&self, rootViewController: Option<&UIViewController>);
#[sel(convertRect:toCoordinateSpace:)]
#[method(convertRect:toCoordinateSpace:)]
pub fn convertRect_toCoordinateSpace(
&self,
rect: CGRect,
coordinateSpace: &UICoordinateSpace,
) -> CGRect;
#[sel(convertRect:fromCoordinateSpace:)]
#[method(convertRect:fromCoordinateSpace:)]
pub fn convertRect_fromCoordinateSpace(
&self,
rect: CGRect,
coordinateSpace: &UICoordinateSpace,
) -> CGRect;
#[sel(safeAreaInsets)]
#[method(safeAreaInsets)]
pub fn safeAreaInsets(&self) -> UIEdgeInsets;
#[sel(setNeedsDisplay)]
#[method(setNeedsDisplay)]
pub fn setNeedsDisplay(&self);
}
);

View file

@ -1,7 +1,7 @@
use icrate::Foundation::{NSObject, NSUInteger};
use objc2::encode::{Encode, Encoding};
use objc2::foundation::{NSObject, NSUInteger};
use objc2::rc::{Id, Shared};
use objc2::{extern_class, extern_methods, msg_send_id, ClassType};
use objc2::rc::Id;
use objc2::{extern_class, extern_methods, msg_send_id, mutability, ClassType};
use super::{UIResponder, UIView};
@ -12,28 +12,29 @@ extern_class!(
unsafe impl ClassType for UIViewController {
#[inherits(NSObject)]
type Super = UIResponder;
type Mutability = mutability::InteriorMutable;
}
);
extern_methods!(
unsafe impl UIViewController {
#[sel(attemptRotationToDeviceOrientation)]
#[method(attemptRotationToDeviceOrientation)]
pub fn attemptRotationToDeviceOrientation();
#[sel(setNeedsStatusBarAppearanceUpdate)]
#[method(setNeedsStatusBarAppearanceUpdate)]
pub fn setNeedsStatusBarAppearanceUpdate(&self);
#[sel(setNeedsUpdateOfHomeIndicatorAutoHidden)]
#[method(setNeedsUpdateOfHomeIndicatorAutoHidden)]
pub fn setNeedsUpdateOfHomeIndicatorAutoHidden(&self);
#[sel(setNeedsUpdateOfScreenEdgesDeferringSystemGestures)]
#[method(setNeedsUpdateOfScreenEdgesDeferringSystemGestures)]
pub fn setNeedsUpdateOfScreenEdgesDeferringSystemGestures(&self);
pub fn view(&self) -> Option<Id<UIView, Shared>> {
pub fn view(&self) -> Option<Id<UIView>> {
unsafe { msg_send_id![self, view] }
}
#[sel(setView:)]
#[method(setView:)]
pub fn setView(&self, view: Option<&UIView>);
}
);

View file

@ -1,6 +1,6 @@
use objc2::foundation::NSObject;
use objc2::rc::{Id, Shared};
use objc2::{extern_class, extern_methods, msg_send_id, ClassType};
use icrate::Foundation::NSObject;
use objc2::rc::Id;
use objc2::{extern_class, extern_methods, msg_send_id, mutability, ClassType};
use super::{UIResponder, UIScreen, UIView};
@ -11,25 +11,26 @@ extern_class!(
unsafe impl ClassType for UIWindow {
#[inherits(UIResponder, NSObject)]
type Super = UIView;
type Mutability = mutability::InteriorMutable;
}
);
extern_methods!(
unsafe impl UIWindow {
pub fn screen(&self) -> Id<UIScreen, Shared> {
pub fn screen(&self) -> Id<UIScreen> {
unsafe { msg_send_id![self, screen] }
}
#[sel(setScreen:)]
#[method(setScreen:)]
pub fn setScreen(&self, screen: &UIScreen);
#[sel(setHidden:)]
#[method(setHidden:)]
pub fn setHidden(&self, flag: bool);
#[sel(makeKeyAndVisible)]
#[method(makeKeyAndVisible)]
pub fn makeKeyAndVisible(&self);
#[sel(isKeyWindow)]
#[method(isKeyWindow)]
pub fn isKeyWindow(&self) -> bool;
}
);

View file

@ -2,11 +2,11 @@
use std::cell::Cell;
use std::ptr::NonNull;
use icrate::Foundation::{CGFloat, CGRect, MainThreadMarker, NSObject, NSObjectProtocol, NSSet};
use objc2::declare::{Ivar, IvarDrop};
use objc2::foundation::{CGFloat, CGRect, MainThreadMarker, NSObject, NSSet};
use objc2::rc::{Id, Shared};
use objc2::rc::Id;
use objc2::runtime::Class;
use objc2::{declare_class, extern_methods, msg_send, msg_send_id, ClassType};
use objc2::{declare_class, extern_methods, msg_send, msg_send_id, mutability, ClassType};
use super::uikit::{
UIApplication, UIDevice, UIEvent, UIForceTouchCapability, UIInterfaceOrientationMask,
@ -29,16 +29,17 @@ use crate::{
};
declare_class!(
pub(crate) struct WinitView {}
pub(crate) struct WinitView;
unsafe impl ClassType for WinitView {
#[inherits(UIResponder, NSObject)]
type Super = UIView;
type Mutability = mutability::InteriorMutable;
const NAME: &'static str = "WinitUIView";
}
unsafe impl WinitView {
#[sel(drawRect:)]
#[method(drawRect:)]
fn draw_rect(&self, rect: CGRect) {
let window = self.window().unwrap();
unsafe {
@ -49,7 +50,7 @@ declare_class!(
let _: () = unsafe { msg_send![super(self), drawRect: rect] };
}
#[sel(layoutSubviews)]
#[method(layoutSubviews)]
fn layout_subviews(&self) {
let _: () = unsafe { msg_send![super(self), layoutSubviews] };
@ -81,7 +82,7 @@ declare_class!(
}
}
#[sel(setContentScaleFactor:)]
#[method(setContentScaleFactor:)]
fn set_content_scale_factor(&self, untrusted_scale_factor: CGFloat) {
let _: () =
unsafe { msg_send![super(self), setContentScaleFactor: untrusted_scale_factor] };
@ -131,22 +132,22 @@ declare_class!(
}
}
#[sel(touchesBegan:withEvent:)]
#[method(touchesBegan:withEvent:)]
fn touches_began(&self, touches: &NSSet<UITouch>, _event: Option<&UIEvent>) {
self.handle_touches(touches)
}
#[sel(touchesMoved:withEvent:)]
#[method(touchesMoved:withEvent:)]
fn touches_moved(&self, touches: &NSSet<UITouch>, _event: Option<&UIEvent>) {
self.handle_touches(touches)
}
#[sel(touchesEnded:withEvent:)]
#[method(touchesEnded:withEvent:)]
fn touches_ended(&self, touches: &NSSet<UITouch>, _event: Option<&UIEvent>) {
self.handle_touches(touches)
}
#[sel(touchesCancelled:withEvent:)]
#[method(touchesCancelled:withEvent:)]
fn touches_cancelled(&self, touches: &NSSet<UITouch>, _event: Option<&UIEvent>) {
self.handle_touches(touches)
}
@ -156,16 +157,16 @@ declare_class!(
extern_methods!(
#[allow(non_snake_case)]
unsafe impl WinitView {
fn window(&self) -> Option<Id<WinitUIWindow, Shared>> {
fn window(&self) -> Option<Id<WinitUIWindow>> {
unsafe { msg_send_id![self, window] }
}
unsafe fn traitCollection(&self) -> Id<UITraitCollection, Shared> {
unsafe fn traitCollection(&self) -> Id<UITraitCollection> {
msg_send_id![self, traitCollection]
}
// TODO: Allow the user to customize this
#[sel(layerClass)]
#[method(layerClass)]
pub(crate) fn layerClass() -> &'static Class;
}
);
@ -176,9 +177,8 @@ impl WinitView {
_window_attributes: &WindowAttributes,
platform_attributes: &PlatformSpecificWindowBuilderAttributes,
frame: CGRect,
) -> Id<Self, Shared> {
let this: Id<Self, Shared> =
unsafe { msg_send_id![msg_send_id![Self::class(), alloc], initWithFrame: frame] };
) -> Id<Self> {
let this: Id<Self> = unsafe { msg_send_id![Self::alloc(), initWithFrame: frame] };
this.setMultipleTouchEnabled(true);
@ -258,7 +258,7 @@ impl WinitView {
}
}
struct ViewControllerState {
pub struct ViewControllerState {
prefers_status_bar_hidden: Cell<bool>,
prefers_home_indicator_auto_hidden: Cell<bool>,
supported_orientations: Cell<UIInterfaceOrientationMask>,
@ -267,19 +267,22 @@ struct ViewControllerState {
declare_class!(
pub(crate) struct WinitViewController {
state: IvarDrop<Box<ViewControllerState>>,
state: IvarDrop<Box<ViewControllerState>, "_state">,
}
mod view_controller_ivars;
unsafe impl ClassType for WinitViewController {
#[inherits(UIResponder, NSObject)]
type Super = UIViewController;
type Mutability = mutability::InteriorMutable;
const NAME: &'static str = "WinitUIViewController";
}
unsafe impl WinitViewController {
#[sel(init)]
fn init(&mut self) -> Option<NonNull<Self>> {
let this: Option<&mut Self> = unsafe { msg_send![super(self), init] };
#[method(init)]
unsafe fn init(this: *mut Self) -> Option<NonNull<Self>> {
let this: Option<&mut Self> = msg_send![super(this), init];
this.map(|this| {
// These are set in WinitViewController::new, it's just to set them
// to _something_.
@ -300,27 +303,27 @@ declare_class!(
}
unsafe impl WinitViewController {
#[sel(shouldAutorotate)]
#[method(shouldAutorotate)]
fn should_autorotate(&self) -> bool {
true
}
#[sel(prefersStatusBarHidden)]
#[method(prefersStatusBarHidden)]
fn prefers_status_bar_hidden(&self) -> bool {
self.state.prefers_status_bar_hidden.get()
}
#[sel(prefersHomeIndicatorAutoHidden)]
#[method(prefersHomeIndicatorAutoHidden)]
fn prefers_home_indicator_auto_hidden(&self) -> bool {
self.state.prefers_home_indicator_auto_hidden.get()
}
#[sel(supportedInterfaceOrientations)]
#[method(supportedInterfaceOrientations)]
fn supported_orientations(&self) -> UIInterfaceOrientationMask {
self.state.supported_orientations.get()
}
#[sel(preferredScreenEdgesDeferringSystemGestures)]
#[method(preferredScreenEdgesDeferringSystemGestures)]
fn preferred_screen_edges_deferring_system_gestures(&self) -> UIRectEdge {
self.state
.preferred_screen_edges_deferring_system_gestures
@ -388,9 +391,8 @@ impl WinitViewController {
_window_attributes: &WindowAttributes,
platform_attributes: &PlatformSpecificWindowBuilderAttributes,
view: &UIView,
) -> Id<Self, Shared> {
let this: Id<Self, Shared> =
unsafe { msg_send_id![msg_send_id![Self::class(), alloc], init] };
) -> Id<Self> {
let this: Id<Self> = unsafe { msg_send_id![Self::alloc(), init] };
this.set_prefers_status_bar_hidden(platform_attributes.prefers_status_bar_hidden);
@ -414,15 +416,17 @@ impl WinitViewController {
declare_class!(
#[derive(Debug, PartialEq, Eq, Hash)]
pub(crate) struct WinitUIWindow {}
pub(crate) struct WinitUIWindow;
unsafe impl ClassType for WinitUIWindow {
#[inherits(UIResponder, NSObject)]
type Super = UIWindow;
type Mutability = mutability::InteriorMutable;
const NAME: &'static str = "WinitUIWindow";
}
unsafe impl WinitUIWindow {
#[sel(becomeKeyWindow)]
#[method(becomeKeyWindow)]
fn become_key_window(&self) {
unsafe {
app_state::handle_nonuser_event(EventWrapper::StaticEvent(Event::WindowEvent {
@ -433,7 +437,7 @@ declare_class!(
let _: () = unsafe { msg_send![super(self), becomeKeyWindow] };
}
#[sel(resignKeyWindow)]
#[method(resignKeyWindow)]
fn resign_key_window(&self) {
unsafe {
app_state::handle_nonuser_event(EventWrapper::StaticEvent(Event::WindowEvent {
@ -453,9 +457,8 @@ impl WinitUIWindow {
_platform_attributes: &PlatformSpecificWindowBuilderAttributes,
frame: CGRect,
view_controller: &UIViewController,
) -> Id<Self, Shared> {
let this: Id<Self, Shared> =
unsafe { msg_send_id![msg_send_id![Self::class(), alloc], initWithFrame: frame] };
) -> Id<Self> {
let this: Id<Self> = unsafe { msg_send_id![Self::alloc(), initWithFrame: frame] };
this.setRootViewController(Some(view_controller));
@ -482,15 +485,17 @@ impl WinitUIWindow {
}
declare_class!(
pub struct WinitApplicationDelegate {}
pub struct WinitApplicationDelegate;
unsafe impl ClassType for WinitApplicationDelegate {
type Super = NSObject;
type Mutability = mutability::InteriorMutable;
const NAME: &'static str = "WinitApplicationDelegate";
}
// UIApplicationDelegate protocol
unsafe impl WinitApplicationDelegate {
#[sel(application:didFinishLaunchingWithOptions:)]
#[method(application:didFinishLaunchingWithOptions:)]
fn did_finish_launching(&self, _application: &UIApplication, _: *mut NSObject) -> bool {
unsafe {
app_state::did_finish_launching();
@ -498,22 +503,23 @@ declare_class!(
true
}
#[sel(applicationDidBecomeActive:)]
#[method(applicationDidBecomeActive:)]
fn did_become_active(&self, _application: &UIApplication) {
unsafe { app_state::handle_nonuser_event(EventWrapper::StaticEvent(Event::Resumed)) }
}
#[sel(applicationWillResignActive:)]
#[method(applicationWillResignActive:)]
fn will_resign_active(&self, _application: &UIApplication) {
unsafe { app_state::handle_nonuser_event(EventWrapper::StaticEvent(Event::Suspended)) }
}
#[sel(applicationWillEnterForeground:)]
#[method(applicationWillEnterForeground:)]
fn will_enter_foreground(&self, _application: &UIApplication) {}
#[sel(applicationDidEnterBackground:)]
#[method(applicationDidEnterBackground:)]
fn did_enter_background(&self, _application: &UIApplication) {}
#[sel(applicationWillTerminate:)]
#[method(applicationWillTerminate:)]
fn will_terminate(&self, application: &UIApplication) {
let mut events = Vec::new();
for window in application.windows().iter() {

View file

@ -6,8 +6,8 @@ use std::{
ops::{Deref, DerefMut},
};
use objc2::foundation::{CGFloat, CGPoint, CGRect, CGSize, MainThreadMarker};
use objc2::rc::{Id, Shared};
use icrate::Foundation::{CGFloat, CGPoint, CGRect, CGSize, MainThreadMarker};
use objc2::rc::Id;
use objc2::runtime::Object;
use objc2::{class, msg_send};
use raw_window_handle::{RawDisplayHandle, RawWindowHandle, UiKitDisplayHandle, UiKitWindowHandle};
@ -32,9 +32,9 @@ use crate::{
};
pub struct Inner {
pub(crate) window: Id<WinitUIWindow, Shared>,
pub(crate) view_controller: Id<WinitViewController, Shared>,
pub(crate) view: Id<WinitView, Shared>,
pub(crate) window: Id<WinitUIWindow>,
pub(crate) view_controller: Id<WinitViewController>,
pub(crate) view: Id<WinitView>,
gl_or_metal_backed: bool,
}

View file

@ -1,7 +1,7 @@
#![allow(clippy::unnecessary_cast)]
use objc2::foundation::NSObject;
use objc2::{declare_class, msg_send, ClassType};
use icrate::Foundation::NSObject;
use objc2::{declare_class, msg_send, mutability, ClassType};
use super::appkit::{NSApplication, NSEvent, NSEventModifierFlags, NSEventType, NSResponder};
use super::{app_state::AppState, event::EventWrapper, DEVICE_ID};
@ -9,18 +9,20 @@ use crate::event::{DeviceEvent, ElementState, Event};
declare_class!(
#[derive(Debug, PartialEq, Eq, Hash)]
pub(super) struct WinitApplication {}
pub(super) struct WinitApplication;
unsafe impl ClassType for WinitApplication {
#[inherits(NSResponder, NSObject)]
type Super = NSApplication;
type Mutability = mutability::InteriorMutable;
const NAME: &'static str = "WinitApplication";
}
unsafe impl WinitApplication {
// Normally, holding Cmd + any key never sends us a `keyUp` event for that key.
// Overriding `sendEvent:` like this fixes that. (https://stackoverflow.com/a/15294196)
// Fun fact: Firefox still has this bug! (https://bugzilla.mozilla.org/show_bug.cgi?id=1299553)
#[sel(sendEvent:)]
#[method(sendEvent:)]
fn send_event(&self, event: &NSEvent) {
// For posterity, there are some undocumented event types
// (https://github.com/servo/cocoa-rs/issues/155)

View file

@ -1,9 +1,10 @@
use std::ptr::NonNull;
use objc2::foundation::NSObject;
use objc2::rc::{Id, Shared};
use icrate::Foundation::NSObject;
use objc2::declare::{IvarBool, IvarEncode};
use objc2::rc::Id;
use objc2::runtime::Object;
use objc2::{declare_class, msg_send, msg_send_id, ClassType};
use objc2::{declare_class, msg_send, msg_send_id, mutability, ClassType};
use super::app_state::AppState;
use super::appkit::NSApplicationActivationPolicy;
@ -11,25 +12,28 @@ use super::appkit::NSApplicationActivationPolicy;
declare_class!(
#[derive(Debug)]
pub(super) struct ApplicationDelegate {
activation_policy: NSApplicationActivationPolicy,
default_menu: bool,
activate_ignoring_other_apps: bool,
activation_policy: IvarEncode<NSApplicationActivationPolicy, "_activation_policy">,
default_menu: IvarBool<"_default_menu">,
activate_ignoring_other_apps: IvarBool<"_activate_ignoring_other_apps">,
}
mod ivars;
unsafe impl ClassType for ApplicationDelegate {
type Super = NSObject;
type Mutability = mutability::InteriorMutable;
const NAME: &'static str = "WinitApplicationDelegate";
}
unsafe impl ApplicationDelegate {
#[sel(initWithActivationPolicy:defaultMenu:activateIgnoringOtherApps:)]
#[method(initWithActivationPolicy:defaultMenu:activateIgnoringOtherApps:)]
unsafe fn init(
&mut self,
this: *mut Self,
activation_policy: NSApplicationActivationPolicy,
default_menu: bool,
activate_ignoring_other_apps: bool,
) -> Option<NonNull<Self>> {
let this: Option<&mut Self> = unsafe { msg_send![super(self), init] };
let this: Option<&mut Self> = unsafe { msg_send![super(this), init] };
this.map(|this| {
*this.activation_policy = activation_policy;
*this.default_menu = default_menu;
@ -38,8 +42,8 @@ declare_class!(
})
}
#[sel(applicationDidFinishLaunching:)]
fn did_finish_launching(&self, _sender: *const Object) {
#[method(applicationDidFinishLaunching:)]
fn did_finish_launching(&self, _sender: Option<&Object>) {
trace_scope!("applicationDidFinishLaunching:");
AppState::launched(
*self.activation_policy,
@ -48,8 +52,8 @@ declare_class!(
);
}
#[sel(applicationWillTerminate:)]
fn will_terminate(&self, _sender: *const Object) {
#[method(applicationWillTerminate:)]
fn will_terminate(&self, _sender: Option<&Object>) {
trace_scope!("applicationWillTerminate:");
// TODO: Notify every window that it will be destroyed, like done in iOS?
AppState::exit();
@ -62,10 +66,10 @@ impl ApplicationDelegate {
activation_policy: NSApplicationActivationPolicy,
default_menu: bool,
activate_ignoring_other_apps: bool,
) -> Id<Self, Shared> {
) -> Id<Self> {
unsafe {
msg_send_id![
msg_send_id![Self::class(), alloc],
Self::alloc(),
initWithActivationPolicy: activation_policy,
defaultMenu: default_menu,
activateIgnoringOtherApps: activate_ignoring_other_apps,

View file

@ -12,7 +12,7 @@ use std::{
};
use core_foundation::runloop::{CFRunLoopGetMain, CFRunLoopWakeUp};
use objc2::foundation::{is_main_thread, NSSize};
use icrate::Foundation::{is_main_thread, NSSize};
use objc2::rc::autoreleasepool;
use once_cell::sync::Lazy;

View file

@ -1,6 +1,6 @@
use objc2::foundation::{NSArray, NSObject, NSString};
use objc2::rc::{Id, Shared};
use objc2::{extern_class, extern_methods, msg_send_id, ClassType};
use icrate::Foundation::{NSArray, NSObject, NSString};
use objc2::rc::Id;
use objc2::{extern_class, extern_methods, mutability, ClassType};
extern_class!(
#[derive(Debug, PartialEq, Eq, Hash)]
@ -8,6 +8,7 @@ extern_class!(
unsafe impl ClassType for NSAppearance {
type Super = NSObject;
type Mutability = mutability::InteriorMutable;
}
);
@ -15,15 +16,13 @@ type NSAppearanceName = NSString;
extern_methods!(
unsafe impl NSAppearance {
pub fn appearanceNamed(name: &NSAppearanceName) -> Id<Self, Shared> {
unsafe { msg_send_id![Self::class(), appearanceNamed: name] }
}
#[method_id(appearanceNamed:)]
pub fn appearanceNamed(name: &NSAppearanceName) -> Id<Self>;
#[method_id(bestMatchFromAppearancesWithNames:)]
pub fn bestMatchFromAppearancesWithNames(
&self,
appearances: &NSArray<NSAppearanceName>,
) -> Id<NSAppearanceName, Shared> {
unsafe { msg_send_id![self, bestMatchFromAppearancesWithNames: appearances,] }
}
) -> Id<NSAppearanceName>;
}
);

View file

@ -1,7 +1,7 @@
use objc2::foundation::{MainThreadMarker, NSArray, NSInteger, NSObject, NSUInteger};
use objc2::rc::{Id, Shared};
use icrate::Foundation::{MainThreadMarker, NSArray, NSInteger, NSObject, NSUInteger};
use objc2::rc::Id;
use objc2::runtime::Object;
use objc2::{extern_class, extern_methods, msg_send_id, ClassType};
use objc2::{extern_class, extern_methods, msg_send_id, mutability, ClassType};
use objc2::{Encode, Encoding};
use super::{NSAppearance, NSEvent, NSMenu, NSResponder, NSWindow};
@ -13,10 +13,11 @@ extern_class!(
unsafe impl ClassType for NSApplication {
#[inherits(NSObject)]
type Super = NSResponder;
type Mutability = mutability::InteriorMutable;
}
);
pub(crate) fn NSApp() -> Id<NSApplication, Shared> {
pub(crate) fn NSApp() -> Id<NSApplication> {
// TODO: Only allow access from main thread
NSApplication::shared(unsafe { MainThreadMarker::new_unchecked() })
}
@ -26,70 +27,66 @@ extern_methods!(
/// This can only be called on the main thread since it may initialize
/// the application and since it's parameters may be changed by the main
/// thread at any time (hence it is only safe to access on the main thread).
pub fn shared(_mtm: MainThreadMarker) -> Id<Self, Shared> {
pub fn shared(_mtm: MainThreadMarker) -> Id<Self> {
let app: Option<_> = unsafe { msg_send_id![Self::class(), sharedApplication] };
// SAFETY: `sharedApplication` always initializes the app if it isn't already
unsafe { app.unwrap_unchecked() }
}
pub fn currentEvent(&self) -> Option<Id<NSEvent, Shared>> {
unsafe { msg_send_id![self, currentEvent] }
}
#[method_id(currentEvent)]
pub fn currentEvent(&self) -> Option<Id<NSEvent>>;
#[sel(postEvent:atStart:)]
#[method(postEvent:atStart:)]
pub fn postEvent_atStart(&self, event: &NSEvent, front_of_queue: bool);
#[sel(presentationOptions)]
#[method(presentationOptions)]
pub fn presentationOptions(&self) -> NSApplicationPresentationOptions;
pub fn windows(&self) -> Id<NSArray<NSWindow, Shared>, Shared> {
unsafe { msg_send_id![self, windows] }
}
#[method_id(windows)]
pub fn windows(&self) -> Id<NSArray<NSWindow>>;
pub fn keyWindow(&self) -> Option<Id<NSWindow, Shared>> {
unsafe { msg_send_id![self, keyWindow] }
}
#[method_id(keyWindow)]
pub fn keyWindow(&self) -> Option<Id<NSWindow>>;
// TODO: NSApplicationDelegate
#[sel(setDelegate:)]
#[method(setDelegate:)]
pub fn setDelegate(&self, delegate: &Object);
#[sel(setPresentationOptions:)]
#[method(setPresentationOptions:)]
pub fn setPresentationOptions(&self, options: NSApplicationPresentationOptions);
#[sel(hide:)]
#[method(hide:)]
pub fn hide(&self, sender: Option<&Object>);
#[sel(orderFrontCharacterPalette:)]
#[method(orderFrontCharacterPalette:)]
#[allow(dead_code)]
pub fn orderFrontCharacterPalette(&self, sender: Option<&Object>);
#[sel(hideOtherApplications:)]
#[method(hideOtherApplications:)]
pub fn hideOtherApplications(&self, sender: Option<&Object>);
#[sel(stop:)]
#[method(stop:)]
pub fn stop(&self, sender: Option<&Object>);
#[sel(activateIgnoringOtherApps:)]
#[method(activateIgnoringOtherApps:)]
pub fn activateIgnoringOtherApps(&self, ignore: bool);
#[sel(requestUserAttention:)]
#[method(requestUserAttention:)]
pub fn requestUserAttention(&self, type_: NSRequestUserAttentionType) -> NSInteger;
#[sel(setActivationPolicy:)]
#[method(setActivationPolicy:)]
pub fn setActivationPolicy(&self, policy: NSApplicationActivationPolicy) -> bool;
#[sel(setMainMenu:)]
#[method(setMainMenu:)]
pub fn setMainMenu(&self, menu: &NSMenu);
pub fn effectiveAppearance(&self) -> Id<NSAppearance, Shared> {
unsafe { msg_send_id![self, effectiveAppearance] }
}
#[method_id(effectiveAppearance)]
pub fn effectiveAppearance(&self) -> Id<NSAppearance>;
#[sel(setAppearance:)]
#[method(setAppearance:)]
pub fn setAppearance(&self, appearance: Option<&NSAppearance>);
#[sel(run)]
#[method(run)]
pub unsafe fn run(&self);
}
);

View file

@ -1,5 +1,5 @@
use objc2::foundation::NSObject;
use objc2::{extern_class, ClassType};
use icrate::Foundation::NSObject;
use objc2::{extern_class, mutability, ClassType};
use super::{NSControl, NSResponder, NSView};
@ -10,5 +10,6 @@ extern_class!(
unsafe impl ClassType for NSButton {
#[inherits(NSView, NSResponder, NSObject)]
type Super = NSControl;
type Mutability = mutability::InteriorMutable;
}
);

View file

@ -1,6 +1,6 @@
use objc2::foundation::NSObject;
use objc2::rc::{Id, Shared};
use objc2::{extern_class, extern_methods, msg_send_id, ClassType};
use icrate::Foundation::NSObject;
use objc2::rc::Id;
use objc2::{extern_class, extern_methods, mutability, ClassType};
extern_class!(
/// An object that stores color data and sometimes opacity (alpha value).
@ -11,6 +11,7 @@ extern_class!(
unsafe impl ClassType for NSColor {
type Super = NSObject;
type Mutability = mutability::InteriorMutable;
}
);
@ -21,8 +22,7 @@ unsafe impl Sync for NSColor {}
extern_methods!(
unsafe impl NSColor {
pub fn clear() -> Id<Self, Shared> {
unsafe { msg_send_id![Self::class(), clearColor] }
}
#[method_id(clearColor)]
pub fn clear() -> Id<Self>;
}
);

View file

@ -1,5 +1,5 @@
use objc2::foundation::NSObject;
use objc2::{extern_class, extern_methods, ClassType};
use icrate::Foundation::NSObject;
use objc2::{extern_class, extern_methods, mutability, ClassType};
use super::{NSResponder, NSView};
@ -10,15 +10,16 @@ extern_class!(
unsafe impl ClassType for NSControl {
#[inherits(NSResponder, NSObject)]
type Super = NSView;
type Mutability = mutability::InteriorMutable;
}
);
extern_methods!(
unsafe impl NSControl {
#[sel(setEnabled:)]
#[method(setEnabled:)]
pub fn setEnabled(&self, enabled: bool);
#[sel(isEnabled)]
#[method(isEnabled)]
pub fn isEnabled(&self) -> bool;
}
);

View file

@ -1,9 +1,12 @@
use once_cell::sync::Lazy;
use objc2::foundation::{NSData, NSDictionary, NSNumber, NSObject, NSPoint, NSString};
use objc2::rc::{DefaultId, Id, Shared};
use icrate::ns_string;
use icrate::Foundation::{
NSData, NSDictionary, NSNumber, NSObject, NSObjectProtocol, NSPoint, NSString,
};
use objc2::rc::{DefaultId, Id};
use objc2::runtime::Sel;
use objc2::{extern_class, extern_methods, msg_send_id, ns_string, sel, ClassType};
use objc2::{extern_class, extern_methods, msg_send_id, mutability, sel, ClassType};
use super::NSImage;
use crate::window::CursorIcon;
@ -15,6 +18,7 @@ extern_class!(
unsafe impl ClassType for NSCursor {
type Super = NSObject;
type Mutability = mutability::InteriorMutable;
}
);
@ -29,7 +33,7 @@ macro_rules! def_cursor {
pub fn $name:ident();
)*} => {$(
$(#[$($m)*])*
pub fn $name() -> Id<Self, Shared> {
pub fn $name() -> Id<Self> {
unsafe { msg_send_id![Self::class(), $name] }
}
)*};
@ -41,7 +45,7 @@ macro_rules! def_undocumented_cursor {
pub fn $name:ident();
)*} => {$(
$(#[$($m)*])*
pub fn $name() -> Id<Self, Shared> {
pub fn $name() -> Id<Self> {
unsafe { Self::from_selector(sel!($name)).unwrap_or_else(|| Default::default()) }
}
)*};
@ -71,12 +75,11 @@ extern_methods!(
);
// Creating cursors should be thread-safe, though using them for anything probably isn't.
pub fn new(image: &NSImage, hotSpot: NSPoint) -> Id<Self, Shared> {
let this = unsafe { msg_send_id![Self::class(), alloc] };
unsafe { msg_send_id![this, initWithImage: image, hotSpot: hotSpot] }
pub fn new(image: &NSImage, hotSpot: NSPoint) -> Id<Self> {
unsafe { msg_send_id![Self::alloc(), initWithImage: image, hotSpot: hotSpot] }
}
pub fn invisible() -> Id<Self, Shared> {
pub fn invisible() -> Id<Self> {
// 16x16 GIF data for invisible cursor
// You can reproduce this via ImageMagick.
// $ convert -size 16x16 xc:none cursor.gif
@ -87,7 +90,7 @@ extern_methods!(
0xCB, 0xED, 0x0F, 0xA3, 0x9C, 0xB4, 0xDA, 0x8B, 0xB3, 0x3E, 0x05, 0x00, 0x3B,
];
static CURSOR: Lazy<Id<NSCursor, Shared>> = Lazy::new(|| {
static CURSOR: Lazy<Id<NSCursor>> = Lazy::new(|| {
// TODO: Consider using `dataWithBytesNoCopy:`
let data = NSData::with_bytes(CURSOR_BYTES);
let image = NSImage::new_with_data(&data);
@ -100,14 +103,13 @@ extern_methods!(
/// Undocumented cursors
unsafe impl NSCursor {
#[sel(respondsToSelector:)]
#[method(respondsToSelector:)]
fn class_responds_to(sel: Sel) -> bool;
unsafe fn from_selector_unchecked(sel: Sel) -> Id<Self, Shared> {
unsafe { msg_send_id![Self::class(), performSelector: sel] }
}
#[method_id(performSelector:)]
unsafe fn from_selector_unchecked(sel: Sel) -> Id<Self>;
unsafe fn from_selector(sel: Sel) -> Option<Id<Self, Shared>> {
unsafe fn from_selector(sel: Sel) -> Option<Id<Self>> {
if Self::class_responds_to(sel) {
Some(unsafe { Self::from_selector_unchecked(sel) })
} else {
@ -143,20 +145,20 @@ extern_methods!(
unsafe impl NSCursor {
// Note that loading `busybutclickable` with this code won't animate
// the frames; instead you'll just get them all in a column.
unsafe fn load_webkit_cursor(name: &NSString) -> Id<Self, Shared> {
unsafe fn load_webkit_cursor(name: &NSString) -> Id<Self> {
// Snatch a cursor from WebKit; They fit the style of the native
// cursors, and will seem completely standard to macOS users.
//
// https://stackoverflow.com/a/21786835/5435443
let root = ns_string!("/System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/HIServices.framework/Versions/A/Resources/cursors");
let cursor_path = root.join_path(name);
let cursor_path = root.stringByAppendingPathComponent(name);
let pdf_path = cursor_path.join_path(ns_string!("cursor.pdf"));
let pdf_path = cursor_path.stringByAppendingPathComponent(ns_string!("cursor.pdf"));
let image = NSImage::new_by_referencing_file(&pdf_path);
// TODO: Handle PLists better
let info_path = cursor_path.join_path(ns_string!("info.plist"));
let info: Id<NSDictionary<NSObject, NSObject>, Shared> = unsafe {
let info_path = cursor_path.stringByAppendingPathComponent(ns_string!("info.plist"));
let info: Id<NSDictionary<NSObject, NSObject>> = unsafe {
msg_send_id![
<NSDictionary<NSObject, NSObject>>::class(),
dictionaryWithContentsOfFile: &*info_path,
@ -183,18 +185,18 @@ extern_methods!(
Self::new(&image, hotspot)
}
pub fn moveCursor() -> Id<Self, Shared> {
pub fn moveCursor() -> Id<Self> {
unsafe { Self::load_webkit_cursor(ns_string!("move")) }
}
pub fn cellCursor() -> Id<Self, Shared> {
pub fn cellCursor() -> Id<Self> {
unsafe { Self::load_webkit_cursor(ns_string!("cell")) }
}
}
);
impl NSCursor {
pub fn from_icon(icon: CursorIcon) -> Id<Self, Shared> {
pub fn from_icon(icon: CursorIcon) -> Id<Self> {
match icon {
CursorIcon::Default => Default::default(),
CursorIcon::Pointer => Self::pointingHandCursor(),
@ -233,9 +235,7 @@ impl NSCursor {
}
impl DefaultId for NSCursor {
type Ownership = Shared;
fn default_id() -> Id<Self, Shared> {
fn default_id() -> Id<Self> {
Self::arrowCursor()
}
}

View file

@ -1,11 +1,11 @@
use std::os::raw::c_ushort;
use objc2::encode::{Encode, Encoding};
use objc2::foundation::{
use icrate::Foundation::{
CGFloat, NSCopying, NSInteger, NSObject, NSPoint, NSString, NSTimeInterval, NSUInteger,
};
use objc2::rc::{Id, Shared};
use objc2::{extern_class, extern_methods, msg_send_id, ClassType};
use objc2::encode::{Encode, Encoding};
use objc2::rc::Id;
use objc2::{extern_class, extern_methods, mutability, ClassType};
extern_class!(
#[derive(Debug, PartialEq, Eq, Hash)]
@ -13,6 +13,7 @@ extern_class!(
unsafe impl ClassType for NSEvent {
type Super = NSObject;
type Mutability = mutability::InteriorMutable;
}
);
@ -24,6 +25,17 @@ extern_class!(
extern_methods!(
unsafe impl NSEvent {
#[method_id(
otherEventWithType:
location:
modifierFlags:
timestamp:
windowNumber:
context:
subtype:
data1:
data2:
)]
unsafe fn otherEventWithType(
type_: NSEventType,
location: NSPoint,
@ -34,24 +46,9 @@ extern_methods!(
subtype: NSEventSubtype,
data1: NSInteger,
data2: NSInteger,
) -> Id<Self, Shared> {
unsafe {
msg_send_id![
Self::class(),
otherEventWithType: type_,
location: location,
modifierFlags: flags,
timestamp: time,
windowNumber: window_num,
context: context,
subtype: subtype,
data1: data1,
data2: data2,
]
}
}
) -> Id<Self>;
pub fn dummy() -> Id<Self, Shared> {
pub fn dummy() -> Id<Self> {
unsafe {
Self::otherEventWithType(
NSEventType::NSApplicationDefined,
@ -67,6 +64,18 @@ extern_methods!(
}
}
#[method_id(
keyEventWithType:
location:
modifierFlags:
timestamp:
windowNumber:
context:
characters:
charactersIgnoringModifiers:
isARepeat:
keyCode:
)]
pub fn keyEventWithType(
type_: NSEventType,
location: NSPoint,
@ -78,92 +87,74 @@ extern_methods!(
characters_ignoring_modifiers: &NSString,
is_a_repeat: bool,
scancode: c_ushort,
) -> Id<Self, Shared> {
unsafe {
msg_send_id![
Self::class(),
keyEventWithType: type_,
location: location,
modifierFlags: modifier_flags,
timestamp: timestamp,
windowNumber: window_num,
context: context,
characters: characters,
charactersIgnoringModifiers: characters_ignoring_modifiers,
isARepeat: is_a_repeat,
keyCode: scancode,
]
}
}
) -> Id<Self>;
#[sel(locationInWindow)]
#[method(locationInWindow)]
pub fn locationInWindow(&self) -> NSPoint;
// TODO: MainThreadMarker
#[sel(pressedMouseButtons)]
#[method(pressedMouseButtons)]
pub fn pressedMouseButtons() -> NSUInteger;
#[sel(modifierFlags)]
#[method(modifierFlags)]
pub fn modifierFlags(&self) -> NSEventModifierFlags;
#[sel(type)]
#[method(type)]
pub fn type_(&self) -> NSEventType;
#[sel(keyCode)]
#[method(keyCode)]
pub fn key_code(&self) -> c_ushort;
#[sel(magnification)]
#[method(magnification)]
pub fn magnification(&self) -> CGFloat;
#[sel(phase)]
#[method(phase)]
pub fn phase(&self) -> NSEventPhase;
#[sel(momentumPhase)]
#[method(momentumPhase)]
pub fn momentumPhase(&self) -> NSEventPhase;
#[sel(deltaX)]
#[method(deltaX)]
pub fn deltaX(&self) -> CGFloat;
#[sel(deltaY)]
#[method(deltaY)]
pub fn deltaY(&self) -> CGFloat;
#[sel(buttonNumber)]
#[method(buttonNumber)]
pub fn buttonNumber(&self) -> NSInteger;
#[sel(scrollingDeltaX)]
#[method(scrollingDeltaX)]
pub fn scrollingDeltaX(&self) -> CGFloat;
#[sel(scrollingDeltaY)]
#[method(scrollingDeltaY)]
pub fn scrollingDeltaY(&self) -> CGFloat;
#[sel(hasPreciseScrollingDeltas)]
#[method(hasPreciseScrollingDeltas)]
pub fn hasPreciseScrollingDeltas(&self) -> bool;
#[sel(rotation)]
#[method(rotation)]
pub fn rotation(&self) -> f32;
#[sel(pressure)]
#[method(pressure)]
pub fn pressure(&self) -> f32;
#[sel(stage)]
#[method(stage)]
pub fn stage(&self) -> NSInteger;
#[sel(isARepeat)]
#[method(isARepeat)]
pub fn is_a_repeat(&self) -> bool;
#[sel(windowNumber)]
#[method(windowNumber)]
pub fn window_number(&self) -> NSInteger;
#[sel(timestamp)]
#[method(timestamp)]
pub fn timestamp(&self) -> NSTimeInterval;
pub fn characters(&self) -> Option<Id<NSString, Shared>> {
unsafe { msg_send_id![self, characters] }
}
#[method_id(characters)]
pub fn characters(&self) -> Option<Id<NSString>>;
pub fn charactersIgnoringModifiers(&self) -> Option<Id<NSString, Shared>> {
unsafe { msg_send_id![self, charactersIgnoringModifiers] }
}
#[method_id(charactersIgnoringModifiers)]
pub fn charactersIgnoringModifiers(&self) -> Option<Id<NSString>>;
pub fn lshift_pressed(&self) -> bool {
let raw_modifiers = self.modifierFlags().bits() as u32;
@ -207,10 +198,7 @@ extern_methods!(
}
);
unsafe impl NSCopying for NSEvent {
type Ownership = Shared;
type Output = NSEvent;
}
unsafe impl NSCopying for NSEvent {}
// The values are from the https://github.com/apple-oss-distributions/IOHIDFamily/blob/19666c840a6d896468416ff0007040a10b7b46b8/IOHIDSystem/IOKit/hidsystem/IOLLEvent.h#L258-L259
const NX_DEVICELCTLKEYMASK: u32 = 0x00000001;

View file

@ -1,6 +1,6 @@
use objc2::foundation::{NSData, NSObject, NSString};
use objc2::rc::{Id, Shared};
use objc2::{extern_class, extern_methods, msg_send_id, ClassType};
use icrate::Foundation::{NSData, NSObject, NSString};
use objc2::rc::Id;
use objc2::{extern_class, extern_methods, msg_send_id, mutability, ClassType};
extern_class!(
// TODO: Can this be mutable?
@ -9,6 +9,7 @@ extern_class!(
unsafe impl ClassType for NSImage {
type Super = NSObject;
type Mutability = mutability::InteriorMutable;
}
);
@ -24,14 +25,12 @@ unsafe impl Sync for NSImage {}
extern_methods!(
unsafe impl NSImage {
pub fn new_by_referencing_file(path: &NSString) -> Id<Self, Shared> {
let this = unsafe { msg_send_id![Self::class(), alloc] };
unsafe { msg_send_id![this, initByReferencingFile: path] }
pub fn new_by_referencing_file(path: &NSString) -> Id<Self> {
unsafe { msg_send_id![Self::alloc(), initByReferencingFile: path] }
}
pub fn new_with_data(data: &NSData) -> Id<Self, Shared> {
let this = unsafe { msg_send_id![Self::class(), alloc] };
unsafe { msg_send_id![this, initWithData: data] }
pub fn new_with_data(data: &NSData) -> Id<Self> {
unsafe { msg_send_id![Self::alloc(), initWithData: data] }
}
}
);

View file

@ -1,6 +1,6 @@
use objc2::foundation::NSObject;
use objc2::rc::{Id, Shared};
use objc2::{extern_class, extern_methods, msg_send_id, ClassType};
use icrate::Foundation::NSObject;
use objc2::rc::Id;
use objc2::{extern_class, extern_methods, mutability, ClassType};
use super::NSMenuItem;
@ -10,16 +10,16 @@ extern_class!(
unsafe impl ClassType for NSMenu {
type Super = NSObject;
type Mutability = mutability::InteriorMutable;
}
);
extern_methods!(
unsafe impl NSMenu {
pub fn new() -> Id<Self, Shared> {
unsafe { msg_send_id![Self::class(), new] }
}
#[method_id(new)]
pub fn new() -> Id<Self>;
#[sel(addItem:)]
#[method(addItem:)]
pub fn addItem(&self, item: &NSMenuItem);
}
);

View file

@ -1,7 +1,7 @@
use objc2::foundation::{NSObject, NSString};
use objc2::rc::{Id, Shared};
use icrate::Foundation::{NSObject, NSString};
use objc2::rc::Id;
use objc2::runtime::Sel;
use objc2::{extern_class, extern_methods, msg_send_id, ClassType};
use objc2::{extern_class, extern_methods, msg_send_id, mutability, ClassType};
use super::{NSEventModifierFlags, NSMenu};
@ -11,23 +11,19 @@ extern_class!(
unsafe impl ClassType for NSMenuItem {
type Super = NSObject;
type Mutability = mutability::InteriorMutable;
}
);
extern_methods!(
unsafe impl NSMenuItem {
pub fn new() -> Id<Self, Shared> {
unsafe { msg_send_id![Self::class(), new] }
}
#[method_id(new)]
pub fn new() -> Id<Self>;
pub fn newWithTitle(
title: &NSString,
action: Sel,
key_equivalent: &NSString,
) -> Id<Self, Shared> {
pub fn newWithTitle(title: &NSString, action: Sel, key_equivalent: &NSString) -> Id<Self> {
unsafe {
msg_send_id![
msg_send_id![Self::class(), alloc],
Self::alloc(),
initWithTitle: title,
action: action,
keyEquivalent: key_equivalent,
@ -35,14 +31,13 @@ extern_methods!(
}
}
pub fn separatorItem() -> Id<Self, Shared> {
unsafe { msg_send_id![Self::class(), separatorItem] }
}
#[method_id(separatorItem)]
pub fn separatorItem() -> Id<Self>;
#[sel(setKeyEquivalentModifierMask:)]
#[method(setKeyEquivalentModifierMask:)]
pub fn setKeyEquivalentModifierMask(&self, mask: NSEventModifierFlags);
#[sel(setSubmenu:)]
#[method(setSubmenu:)]
pub fn setSubmenu(&self, submenu: &NSMenu);
}
);

View file

@ -25,6 +25,7 @@ mod pasteboard;
mod responder;
mod screen;
mod tab_group;
mod text_input_client;
mod text_input_context;
mod version;
mod view;
@ -51,6 +52,7 @@ pub(crate) use self::responder::NSResponder;
#[allow(unused_imports)]
pub(crate) use self::screen::{NSDeviceDescriptionKey, NSScreen};
pub(crate) use self::tab_group::NSWindowTabGroup;
pub(crate) use self::text_input_client::NSTextInputClient;
pub(crate) use self::text_input_context::NSTextInputContext;
pub(crate) use self::version::NSAppKitVersion;
pub(crate) use self::view::{NSTrackingRectTag, NSView};

View file

@ -1,6 +1,6 @@
use objc2::foundation::{NSObject, NSString};
use objc2::rc::{Id, Shared};
use objc2::{extern_class, extern_methods, msg_send_id, ClassType};
use icrate::Foundation::{NSObject, NSString};
use objc2::rc::Id;
use objc2::{extern_class, extern_methods, mutability, ClassType};
extern_class!(
#[derive(Debug, PartialEq, Eq, Hash)]
@ -8,14 +8,14 @@ extern_class!(
unsafe impl ClassType for NSPasteboard {
type Super = NSObject;
type Mutability = mutability::InteriorMutable;
}
);
extern_methods!(
unsafe impl NSPasteboard {
pub fn propertyListForType(&self, type_: &NSPasteboardType) -> Id<NSObject, Shared> {
unsafe { msg_send_id![self, propertyListForType: type_] }
}
#[method_id(propertyListForType:)]
pub fn propertyListForType(&self, type_: &NSPasteboardType) -> Id<NSObject>;
}
);

View file

@ -1,15 +1,15 @@
use objc2::foundation::{NSArray, NSObject};
use objc2::rc::Shared;
use objc2::{extern_class, extern_methods, ClassType};
use icrate::Foundation::{NSArray, NSObject};
use objc2::{extern_class, extern_methods, mutability, ClassType};
use super::NSEvent;
extern_class!(
#[derive(Debug, PartialEq, Eq, Hash)]
pub(crate) struct NSResponder;
pub struct NSResponder;
unsafe impl ClassType for NSResponder {
type Super = NSObject;
type Mutability = mutability::InteriorMutable;
}
);
@ -17,7 +17,7 @@ extern_class!(
extern_methods!(
unsafe impl NSResponder {
#[sel(interpretKeyEvents:)]
pub unsafe fn interpretKeyEvents(&self, events: &NSArray<NSEvent, Shared>);
#[method(interpretKeyEvents:)]
pub(crate) unsafe fn interpretKeyEvents(&self, events: &NSArray<NSEvent>);
}
);

View file

@ -1,7 +1,8 @@
use objc2::foundation::{CGFloat, NSArray, NSDictionary, NSNumber, NSObject, NSRect, NSString};
use objc2::rc::{Id, Shared};
use icrate::ns_string;
use icrate::Foundation::{CGFloat, NSArray, NSDictionary, NSNumber, NSObject, NSRect, NSString};
use objc2::rc::Id;
use objc2::runtime::Object;
use objc2::{extern_class, extern_methods, msg_send_id, ns_string, ClassType};
use objc2::{extern_class, extern_methods, mutability, ClassType};
extern_class!(
#[derive(Debug, PartialEq, Eq, Hash)]
@ -9,6 +10,7 @@ extern_class!(
unsafe impl ClassType for NSScreen {
type Super = NSObject;
type Mutability = mutability::InteriorMutable;
}
);
@ -17,26 +19,21 @@ extern_class!(
extern_methods!(
unsafe impl NSScreen {
/// The application object must have been created.
pub fn main() -> Option<Id<Self, Shared>> {
unsafe { msg_send_id![Self::class(), mainScreen] }
}
#[method_id(mainScreen)]
pub fn main() -> Option<Id<Self>>;
/// The application object must have been created.
pub fn screens() -> Id<NSArray<Self, Shared>, Shared> {
unsafe { msg_send_id![Self::class(), screens] }
}
#[method_id(screens)]
pub fn screens() -> Id<NSArray<Self>>;
#[sel(frame)]
#[method(frame)]
pub fn frame(&self) -> NSRect;
#[sel(visibleFrame)]
#[method(visibleFrame)]
pub fn visibleFrame(&self) -> NSRect;
pub fn deviceDescription(
&self,
) -> Id<NSDictionary<NSDeviceDescriptionKey, Object>, Shared> {
unsafe { msg_send_id![self, deviceDescription] }
}
#[method_id(deviceDescription)]
pub fn deviceDescription(&self) -> Id<NSDictionary<NSDeviceDescriptionKey, Object>>;
pub fn display_id(&self) -> u32 {
let key = ns_string!("NSScreenNumber");
@ -60,7 +57,7 @@ extern_methods!(
})
}
#[sel(backingScaleFactor)]
#[method(backingScaleFactor)]
pub fn backingScaleFactor(&self) -> CGFloat;
}
);

View file

@ -1,6 +1,6 @@
use objc2::foundation::{NSArray, NSObject};
use objc2::rc::{Id, Shared};
use objc2::{extern_class, extern_methods, msg_send_id, ClassType};
use icrate::Foundation::{NSArray, NSObject};
use objc2::rc::Id;
use objc2::{extern_class, extern_methods, mutability, ClassType};
use super::NSWindow;
@ -10,19 +10,22 @@ extern_class!(
unsafe impl ClassType for NSWindowTabGroup {
type Super = NSObject;
type Mutability = mutability::InteriorMutable;
}
);
extern_methods!(
unsafe impl NSWindowTabGroup {
#[sel(selectNextTab)]
#[method(selectNextTab)]
pub fn selectNextTab(&self);
#[sel(selectPreviousTab)]
#[method(selectPreviousTab)]
pub fn selectPreviousTab(&self);
pub fn tabbedWindows(&self) -> Id<NSArray<NSWindow, Shared>, Shared> {
unsafe { msg_send_id![self, windows] }
}
#[sel(setSelectedWindow:)]
#[method_id(windows)]
pub fn tabbedWindows(&self) -> Id<NSArray<NSWindow>>;
#[method(setSelectedWindow:)]
pub fn setSelectedWindow(&self, window: &NSWindow);
}
);

View file

@ -0,0 +1,9 @@
use objc2::{extern_protocol, ProtocolType};
extern_protocol!(
pub(crate) unsafe trait NSTextInputClient {
// TODO: Methods
}
unsafe impl ProtocolType for dyn NSTextInputClient {}
);

View file

@ -1,6 +1,6 @@
use objc2::foundation::{NSObject, NSString};
use objc2::rc::{Id, Shared};
use objc2::{extern_class, extern_methods, msg_send_id, ClassType};
use icrate::Foundation::{NSObject, NSString};
use objc2::rc::Id;
use objc2::{extern_class, extern_methods, mutability, ClassType};
type NSTextInputSourceIdentifier = NSString;
@ -11,21 +11,19 @@ extern_class!(
unsafe impl ClassType for NSTextInputContext {
type Super = NSObject;
type Mutability = mutability::InteriorMutable;
}
);
extern_methods!(
unsafe impl NSTextInputContext {
#[sel(invalidateCharacterCoordinates)]
#[method(invalidateCharacterCoordinates)]
pub fn invalidateCharacterCoordinates(&self);
#[sel(discardMarkedText)]
#[method(discardMarkedText)]
pub fn discardMarkedText(&self);
pub fn selectedKeyboardInputSource(
&self,
) -> Option<Id<NSTextInputSourceIdentifier, Shared>> {
unsafe { msg_send_id![self, selectedKeyboardInputSource] }
}
#[method_id(selectedKeyboardInputSource)]
pub fn selectedKeyboardInputSource(&self) -> Option<Id<NSTextInputSourceIdentifier>>;
}
);

View file

@ -2,10 +2,10 @@ use std::ffi::c_void;
use std::num::NonZeroIsize;
use std::ptr;
use objc2::foundation::{NSObject, NSPoint, NSRect};
use objc2::rc::{Id, Shared};
use icrate::Foundation::{NSObject, NSPoint, NSRect};
use objc2::rc::Id;
use objc2::runtime::Object;
use objc2::{extern_class, extern_methods, msg_send_id, ClassType};
use objc2::{extern_class, extern_methods, mutability, ClassType};
use super::{NSCursor, NSResponder, NSTextInputContext, NSWindow};
@ -16,6 +16,7 @@ extern_class!(
unsafe impl ClassType for NSView {
#[inherits(NSObject)]
type Super = NSResponder;
type Mutability = mutability::InteriorMutable;
}
);
@ -31,47 +32,45 @@ extern_class!(
extern_methods!(
/// Getter methods
unsafe impl NSView {
#[sel(frame)]
#[method(frame)]
pub fn frame(&self) -> NSRect;
#[sel(bounds)]
#[method(bounds)]
pub fn bounds(&self) -> NSRect;
#[method_id(inputContext)]
pub fn inputContext(
&self,
// _mtm: MainThreadMarker,
) -> Option<Id<NSTextInputContext, Shared>> {
unsafe { msg_send_id![self, inputContext] }
}
) -> Option<Id<NSTextInputContext>>;
#[sel(visibleRect)]
#[method(visibleRect)]
pub fn visibleRect(&self) -> NSRect;
#[sel(hasMarkedText)]
#[method(hasMarkedText)]
pub fn hasMarkedText(&self) -> bool;
#[sel(convertPoint:fromView:)]
#[method(convertPoint:fromView:)]
pub fn convertPoint_fromView(&self, point: NSPoint, view: Option<&NSView>) -> NSPoint;
pub fn window(&self) -> Option<Id<NSWindow, Shared>> {
unsafe { msg_send_id![self, window] }
}
#[method_id(window)]
pub fn window(&self) -> Option<Id<NSWindow>>;
}
unsafe impl NSView {
#[sel(setWantsBestResolutionOpenGLSurface:)]
#[method(setWantsBestResolutionOpenGLSurface:)]
pub fn setWantsBestResolutionOpenGLSurface(&self, value: bool);
#[sel(setWantsLayer:)]
#[method(setWantsLayer:)]
pub fn setWantsLayer(&self, wants_layer: bool);
#[sel(setPostsFrameChangedNotifications:)]
#[method(setPostsFrameChangedNotifications:)]
pub fn setPostsFrameChangedNotifications(&self, value: bool);
#[sel(removeTrackingRect:)]
#[method(removeTrackingRect:)]
pub fn removeTrackingRect(&self, tag: NSTrackingRectTag);
#[sel(addTrackingRect:owner:userData:assumeInside:)]
#[method(addTrackingRect:owner:userData:assumeInside:)]
unsafe fn inner_addTrackingRect(
&self,
rect: NSRect,
@ -86,11 +85,11 @@ extern_methods!(
.expect("failed creating tracking rect")
}
#[sel(addCursorRect:cursor:)]
#[method(addCursorRect:cursor:)]
// NSCursor safe to take by shared reference since it is already immutable
pub fn addCursorRect(&self, rect: NSRect, cursor: &NSCursor);
#[sel(setHidden:)]
#[method(setHidden:)]
pub fn setHidden(&self, hidden: bool);
}
);

View file

@ -1,10 +1,10 @@
use objc2::encode::{Encode, Encoding};
use objc2::foundation::{
use icrate::Foundation::{
CGFloat, NSArray, NSInteger, NSObject, NSPoint, NSRect, NSSize, NSString, NSUInteger,
};
use objc2::rc::{Id, Shared};
use objc2::encode::{Encode, Encoding};
use objc2::rc::Id;
use objc2::runtime::Object;
use objc2::{extern_class, extern_methods, msg_send_id, ClassType};
use objc2::{extern_class, extern_methods, mutability, ClassType};
use super::{
NSButton, NSColor, NSEvent, NSPasteboardType, NSResponder, NSScreen, NSView, NSWindowTabGroup,
@ -13,11 +13,12 @@ use super::{
extern_class!(
/// Main-Thread-Only!
#[derive(Debug, PartialEq, Eq, Hash)]
pub(crate) struct NSWindow;
pub struct NSWindow;
unsafe impl ClassType for NSWindow {
#[inherits(NSObject)]
type Super = NSResponder;
type Mutability = mutability::InteriorMutable;
}
);
@ -32,221 +33,214 @@ extern_class!(
extern_methods!(
unsafe impl NSWindow {
#[sel(frame)]
pub fn frame(&self) -> NSRect;
#[method(frame)]
pub(crate) fn frame(&self) -> NSRect;
#[sel(backingScaleFactor)]
pub fn backingScaleFactor(&self) -> CGFloat;
#[method(backingScaleFactor)]
pub(crate) fn backingScaleFactor(&self) -> CGFloat;
pub fn contentView(&self) -> Id<NSView, Shared> {
unsafe { msg_send_id![self, contentView] }
}
#[method_id(contentView)]
pub(crate) fn contentView(&self) -> Id<NSView>;
#[sel(setContentView:)]
pub fn setContentView(&self, view: &NSView);
#[method(setContentView:)]
pub(crate) fn setContentView(&self, view: &NSView);
#[sel(setInitialFirstResponder:)]
pub fn setInitialFirstResponder(&self, view: &NSView);
#[method(setInitialFirstResponder:)]
pub(crate) fn setInitialFirstResponder(&self, view: &NSView);
#[sel(makeFirstResponder:)]
#[method(makeFirstResponder:)]
#[must_use]
pub fn makeFirstResponder(&self, responder: Option<&NSResponder>) -> bool;
pub(crate) fn makeFirstResponder(&self, responder: Option<&NSResponder>) -> bool;
#[sel(contentRectForFrameRect:)]
pub fn contentRectForFrameRect(&self, windowFrame: NSRect) -> NSRect;
#[method(contentRectForFrameRect:)]
pub(crate) fn contentRectForFrameRect(&self, windowFrame: NSRect) -> NSRect;
pub fn screen(&self) -> Option<Id<NSScreen, Shared>> {
unsafe { msg_send_id![self, screen] }
}
#[method_id(screen)]
pub(crate) fn screen(&self) -> Option<Id<NSScreen>>;
#[sel(setContentSize:)]
pub fn setContentSize(&self, contentSize: NSSize);
#[method(setContentSize:)]
pub(crate) fn setContentSize(&self, contentSize: NSSize);
#[sel(setFrameTopLeftPoint:)]
pub fn setFrameTopLeftPoint(&self, point: NSPoint);
#[method(setFrameTopLeftPoint:)]
pub(crate) fn setFrameTopLeftPoint(&self, point: NSPoint);
#[sel(setMinSize:)]
pub fn setMinSize(&self, minSize: NSSize);
#[method(setMinSize:)]
pub(crate) fn setMinSize(&self, minSize: NSSize);
#[sel(setMaxSize:)]
pub fn setMaxSize(&self, maxSize: NSSize);
#[method(setMaxSize:)]
pub(crate) fn setMaxSize(&self, maxSize: NSSize);
#[sel(setResizeIncrements:)]
pub fn setResizeIncrements(&self, increments: NSSize);
#[method(setResizeIncrements:)]
pub(crate) fn setResizeIncrements(&self, increments: NSSize);
#[sel(contentResizeIncrements)]
pub fn contentResizeIncrements(&self) -> NSSize;
#[method(contentResizeIncrements)]
pub(crate) fn contentResizeIncrements(&self) -> NSSize;
#[sel(setContentResizeIncrements:)]
pub fn setContentResizeIncrements(&self, increments: NSSize);
#[method(setContentResizeIncrements:)]
pub(crate) fn setContentResizeIncrements(&self, increments: NSSize);
#[sel(setFrame:display:)]
pub fn setFrame_display(&self, frameRect: NSRect, flag: bool);
#[method(setFrame:display:)]
pub(crate) fn setFrame_display(&self, frameRect: NSRect, flag: bool);
#[sel(setMovable:)]
pub fn setMovable(&self, movable: bool);
#[method(setMovable:)]
pub(crate) fn setMovable(&self, movable: bool);
#[sel(setSharingType:)]
pub fn setSharingType(&self, sharingType: NSWindowSharingType);
#[method(setSharingType:)]
pub(crate) fn setSharingType(&self, sharingType: NSWindowSharingType);
#[sel(setTabbingMode:)]
pub fn setTabbingMode(&self, tabbingMode: NSWindowTabbingMode);
#[method(setTabbingMode:)]
pub(crate) fn setTabbingMode(&self, tabbingMode: NSWindowTabbingMode);
#[sel(setOpaque:)]
pub fn setOpaque(&self, opaque: bool);
#[method(setOpaque:)]
pub(crate) fn setOpaque(&self, opaque: bool);
#[sel(hasShadow)]
pub fn hasShadow(&self) -> bool;
#[method(hasShadow)]
pub(crate) fn hasShadow(&self) -> bool;
#[sel(setHasShadow:)]
pub fn setHasShadow(&self, has_shadow: bool);
#[method(setHasShadow:)]
pub(crate) fn setHasShadow(&self, has_shadow: bool);
#[sel(setIgnoresMouseEvents:)]
pub fn setIgnoresMouseEvents(&self, ignores: bool);
#[method(setIgnoresMouseEvents:)]
pub(crate) fn setIgnoresMouseEvents(&self, ignores: bool);
#[sel(setBackgroundColor:)]
pub fn setBackgroundColor(&self, color: &NSColor);
#[method(setBackgroundColor:)]
pub(crate) fn setBackgroundColor(&self, color: &NSColor);
#[sel(styleMask)]
pub fn styleMask(&self) -> NSWindowStyleMask;
#[method(styleMask)]
pub(crate) fn styleMask(&self) -> NSWindowStyleMask;
#[sel(setStyleMask:)]
pub fn setStyleMask(&self, mask: NSWindowStyleMask);
#[method(setStyleMask:)]
pub(crate) fn setStyleMask(&self, mask: NSWindowStyleMask);
#[sel(registerForDraggedTypes:)]
pub fn registerForDraggedTypes(&self, types: &NSArray<NSPasteboardType>);
#[method(registerForDraggedTypes:)]
pub(crate) fn registerForDraggedTypes(&self, types: &NSArray<NSPasteboardType>);
#[sel(makeKeyAndOrderFront:)]
pub fn makeKeyAndOrderFront(&self, sender: Option<&Object>);
#[method(makeKeyAndOrderFront:)]
pub(crate) fn makeKeyAndOrderFront(&self, sender: Option<&Object>);
#[sel(orderFront:)]
pub fn orderFront(&self, sender: Option<&Object>);
#[method(orderFront:)]
pub(crate) fn orderFront(&self, sender: Option<&Object>);
#[sel(miniaturize:)]
pub fn miniaturize(&self, sender: Option<&Object>);
#[method(miniaturize:)]
pub(crate) fn miniaturize(&self, sender: Option<&Object>);
#[sel(sender:)]
pub fn deminiaturize(&self, sender: Option<&Object>);
#[method(sender:)]
pub(crate) fn deminiaturize(&self, sender: Option<&Object>);
#[sel(toggleFullScreen:)]
pub fn toggleFullScreen(&self, sender: Option<&Object>);
#[method(toggleFullScreen:)]
pub(crate) fn toggleFullScreen(&self, sender: Option<&Object>);
#[sel(orderOut:)]
pub fn orderOut(&self, sender: Option<&Object>);
#[method(orderOut:)]
pub(crate) fn orderOut(&self, sender: Option<&Object>);
#[sel(zoom:)]
pub fn zoom(&self, sender: Option<&Object>);
#[method(zoom:)]
pub(crate) fn zoom(&self, sender: Option<&Object>);
#[sel(selectNextKeyView:)]
pub fn selectNextKeyView(&self, sender: Option<&Object>);
#[method(selectNextKeyView:)]
pub(crate) fn selectNextKeyView(&self, sender: Option<&Object>);
#[sel(selectPreviousKeyView:)]
pub fn selectPreviousKeyView(&self, sender: Option<&Object>);
#[method(selectPreviousKeyView:)]
pub(crate) fn selectPreviousKeyView(&self, sender: Option<&Object>);
pub fn firstResponder(&self) -> Option<Id<NSResponder, Shared>> {
unsafe { msg_send_id![self, firstResponder] }
}
#[method_id(firstResponder)]
pub(crate) fn firstResponder(&self) -> Option<Id<NSResponder>>;
pub fn standardWindowButton(&self, kind: NSWindowButton) -> Option<Id<NSButton, Shared>> {
unsafe { msg_send_id![self, standardWindowButton: kind] }
}
#[method_id(standardWindowButton:)]
pub(crate) fn standardWindowButton(&self, kind: NSWindowButton) -> Option<Id<NSButton>>;
#[sel(setTitle:)]
pub fn setTitle(&self, title: &NSString);
#[method(setTitle:)]
pub(crate) fn setTitle(&self, title: &NSString);
pub fn title_(&self) -> Id<NSString, Shared> {
unsafe { msg_send_id![self, title] }
}
#[method_id(title)]
pub(crate) fn title_(&self) -> Id<NSString>;
#[sel(setReleasedWhenClosed:)]
pub fn setReleasedWhenClosed(&self, val: bool);
#[method(setReleasedWhenClosed:)]
pub(crate) fn setReleasedWhenClosed(&self, val: bool);
#[sel(setAcceptsMouseMovedEvents:)]
pub fn setAcceptsMouseMovedEvents(&self, val: bool);
#[method(setAcceptsMouseMovedEvents:)]
pub(crate) fn setAcceptsMouseMovedEvents(&self, val: bool);
#[sel(setTitlebarAppearsTransparent:)]
pub fn setTitlebarAppearsTransparent(&self, val: bool);
#[method(setTitlebarAppearsTransparent:)]
pub(crate) fn setTitlebarAppearsTransparent(&self, val: bool);
#[sel(setTitleVisibility:)]
pub fn setTitleVisibility(&self, visibility: NSWindowTitleVisibility);
#[method(setTitleVisibility:)]
pub(crate) fn setTitleVisibility(&self, visibility: NSWindowTitleVisibility);
#[sel(setMovableByWindowBackground:)]
pub fn setMovableByWindowBackground(&self, val: bool);
#[method(setMovableByWindowBackground:)]
pub(crate) fn setMovableByWindowBackground(&self, val: bool);
#[sel(setLevel:)]
pub fn setLevel(&self, level: NSWindowLevel);
#[method(setLevel:)]
pub(crate) fn setLevel(&self, level: NSWindowLevel);
#[sel(setAllowsAutomaticWindowTabbing:)]
pub fn setAllowsAutomaticWindowTabbing(val: bool);
#[method(setAllowsAutomaticWindowTabbing:)]
pub(crate) fn setAllowsAutomaticWindowTabbing(val: bool);
#[sel(setTabbingIdentifier:)]
pub fn setTabbingIdentifier(&self, identifier: &NSString);
#[method(setTabbingIdentifier:)]
pub(crate) fn setTabbingIdentifier(&self, identifier: &NSString);
#[sel(setDocumentEdited:)]
pub fn setDocumentEdited(&self, val: bool);
#[method(setDocumentEdited:)]
pub(crate) fn setDocumentEdited(&self, val: bool);
#[sel(occlusionState)]
pub fn occlusionState(&self) -> NSWindowOcclusionState;
#[method(occlusionState)]
pub(crate) fn occlusionState(&self) -> NSWindowOcclusionState;
#[sel(center)]
pub fn center(&self);
#[method(center)]
pub(crate) fn center(&self);
#[sel(isResizable)]
pub fn isResizable(&self) -> bool;
#[method(isResizable)]
pub(crate) fn isResizable(&self) -> bool;
#[sel(isMiniaturizable)]
pub fn isMiniaturizable(&self) -> bool;
#[method(isMiniaturizable)]
pub(crate) fn isMiniaturizable(&self) -> bool;
#[sel(hasCloseBox)]
pub fn hasCloseBox(&self) -> bool;
#[method(hasCloseBox)]
pub(crate) fn hasCloseBox(&self) -> bool;
#[sel(isMiniaturized)]
pub fn isMiniaturized(&self) -> bool;
#[method(isMiniaturized)]
pub(crate) fn isMiniaturized(&self) -> bool;
#[sel(isVisible)]
pub fn isVisible(&self) -> bool;
#[method(isVisible)]
pub(crate) fn isVisible(&self) -> bool;
#[sel(isKeyWindow)]
pub fn isKeyWindow(&self) -> bool;
#[method(isKeyWindow)]
pub(crate) fn isKeyWindow(&self) -> bool;
#[sel(isZoomed)]
pub fn isZoomed(&self) -> bool;
#[method(isZoomed)]
pub(crate) fn isZoomed(&self) -> bool;
#[sel(allowsAutomaticWindowTabbing)]
pub fn allowsAutomaticWindowTabbing() -> bool;
#[method(allowsAutomaticWindowTabbing)]
pub(crate) fn allowsAutomaticWindowTabbing() -> bool;
#[sel(selectNextTab)]
pub fn selectNextTab(&self);
#[method(selectNextTab)]
pub(crate) fn selectNextTab(&self);
pub fn tabbingIdentifier(&self) -> Id<NSString, Shared> {
unsafe { msg_send_id![self, tabbingIdentifier] }
}
#[method_id(tabbingIdentifier)]
pub(crate) fn tabbingIdentifier(&self) -> Id<NSString>;
pub fn tabGroup(&self) -> Id<NSWindowTabGroup, Shared> {
unsafe { msg_send_id![self, tabGroup] }
}
#[method_id(tabGroup)]
pub(crate) fn tabGroup(&self) -> Id<NSWindowTabGroup>;
#[sel(isDocumentEdited)]
pub fn isDocumentEdited(&self) -> bool;
#[method(isDocumentEdited)]
pub(crate) fn isDocumentEdited(&self) -> bool;
#[sel(close)]
pub fn close(&self);
#[method(close)]
pub(crate) fn close(&self);
#[sel(performWindowDragWithEvent:)]
#[method(performWindowDragWithEvent:)]
// TODO: Can this actually accept NULL?
pub fn performWindowDragWithEvent(&self, event: Option<&NSEvent>);
pub(crate) fn performWindowDragWithEvent(&self, event: Option<&NSEvent>);
#[sel(invalidateCursorRectsForView:)]
pub fn invalidateCursorRectsForView(&self, view: &NSView);
#[method(invalidateCursorRectsForView:)]
pub(crate) fn invalidateCursorRectsForView(&self, view: &NSView);
#[sel(setDelegate:)]
pub fn setDelegate(&self, delegate: Option<&NSObject>);
#[method(setDelegate:)]
pub(crate) fn setDelegate(&self, delegate: Option<&NSObject>);
#[sel(sendEvent:)]
pub unsafe fn sendEvent(&self, event: &NSEvent);
#[method(sendEvent:)]
pub(crate) unsafe fn sendEvent(&self, event: &NSEvent);
#[sel(addChildWindow:ordered:)]
pub unsafe fn addChildWindow(&self, child: &NSWindow, ordered: NSWindowOrderingMode);
#[method(addChildWindow:ordered:)]
pub(crate) unsafe fn addChildWindow(&self, child: &NSWindow, ordered: NSWindowOrderingMode);
}
);

View file

@ -4,7 +4,7 @@ use core_foundation::{
base::CFRelease,
data::{CFDataGetBytePtr, CFDataRef},
};
use objc2::rc::{Id, Shared};
use objc2::rc::Id;
use smol_str::SmolStr;
use super::appkit::{NSEvent, NSEventModifierFlags};
@ -31,7 +31,7 @@ pub(crate) enum EventWrapper {
#[derive(Debug)]
pub(crate) enum EventProxy {
DpiChangedProxy {
window: Id<WinitWindow, Shared>,
window: Id<WinitWindow>,
suggested_size: LogicalSize<f64>,
scale_factor: f64,
},

View file

@ -17,8 +17,8 @@ use core_foundation::runloop::{
kCFRunLoopCommonModes, CFRunLoopAddSource, CFRunLoopGetMain, CFRunLoopSourceContext,
CFRunLoopSourceCreate, CFRunLoopSourceRef, CFRunLoopSourceSignal, CFRunLoopWakeUp,
};
use objc2::foundation::is_main_thread;
use objc2::rc::{autoreleasepool, Id, Shared};
use icrate::Foundation::is_main_thread;
use objc2::rc::{autoreleasepool, Id};
use objc2::{msg_send_id, ClassType};
use raw_window_handle::{AppKitDisplayHandle, RawDisplayHandle};
@ -116,7 +116,7 @@ impl<T> EventLoopWindowTarget<T> {
pub struct EventLoop<T: 'static> {
/// The delegate is only weakly referenced by NSApplication, so we keep
/// it around here as well.
_delegate: Id<ApplicationDelegate, Shared>,
_delegate: Id<ApplicationDelegate>,
window_target: Rc<RootWindowTarget<T>>,
panic_info: Rc<PanicInfo>,
@ -157,7 +157,7 @@ impl<T> EventLoop<T> {
// `sharedApplication`) is called anywhere else, or we'll end up
// with the wrong `NSApplication` class and the wrong thread could
// be marked as main.
let app: Id<WinitApplication, Shared> =
let app: Id<WinitApplication> =
unsafe { msg_send_id![WinitApplication::class(), sharedApplication] };
use NSApplicationActivationPolicy::*;

View file

@ -1,7 +1,8 @@
use objc2::foundation::{NSProcessInfo, NSString};
use objc2::rc::{Id, Shared};
use icrate::ns_string;
use icrate::Foundation::{NSProcessInfo, NSString};
use objc2::rc::Id;
use objc2::runtime::Sel;
use objc2::{ns_string, sel};
use objc2::sel;
use super::appkit::{NSApp, NSEventModifierFlags, NSMenu, NSMenuItem};
@ -16,17 +17,17 @@ pub fn initialize() {
menubar.addItem(&app_menu_item);
let app_menu = NSMenu::new();
let process_name = NSProcessInfo::process_info().process_name();
let process_name = NSProcessInfo::processInfo().processName();
// About menu item
let about_item_title = ns_string!("About ").concat(&process_name);
let about_item_title = ns_string!("About ").stringByAppendingString(&process_name);
let about_item = menu_item(&about_item_title, sel!(orderFrontStandardAboutPanel:), None);
// Seperator menu item
let sep_first = NSMenuItem::separatorItem();
// Hide application menu item
let hide_item_title = ns_string!("Hide ").concat(&process_name);
let hide_item_title = ns_string!("Hide ").stringByAppendingString(&process_name);
let hide_item = menu_item(
&hide_item_title,
sel!(hide:),
@ -57,7 +58,7 @@ pub fn initialize() {
let sep = NSMenuItem::separatorItem();
// Quit application menu item
let quit_item_title = ns_string!("Quit ").concat(&process_name);
let quit_item_title = ns_string!("Quit ").stringByAppendingString(&process_name);
let quit_item = menu_item(
&quit_item_title,
sel!(terminate:),
@ -84,7 +85,7 @@ fn menu_item(
title: &NSString,
selector: Sel,
key_equivalent: Option<KeyEquivalent<'_>>,
) -> Id<NSMenuItem, Shared> {
) -> Id<NSMenuItem> {
let (key, masks) = match key_equivalent {
Some(ke) => (ke.key, ke.masks),
None => (ns_string!(""), None),

View file

@ -32,7 +32,7 @@ pub(crate) use self::{
use crate::{
error::OsError as RootOsError, event::DeviceId as RootDeviceId, window::WindowAttributes,
};
use objc2::rc::{autoreleasepool, Id, Shared};
use objc2::rc::{autoreleasepool, Id};
pub(crate) use crate::icon::NoIcon as PlatformIcon;
pub(crate) use crate::platform_impl::Fullscreen;
@ -50,9 +50,9 @@ impl DeviceId {
pub(crate) const DEVICE_ID: RootDeviceId = RootDeviceId(DeviceId);
pub(crate) struct Window {
pub(crate) window: Id<WinitWindow, Shared>,
pub(crate) window: Id<WinitWindow>,
// We keep this around so that it doesn't get dropped until the window does.
_delegate: Id<WinitWindowDelegate, Shared>,
_delegate: Id<WinitWindowDelegate>,
}
impl Drop for Window {

View file

@ -8,7 +8,7 @@ use core_foundation::{
string::CFString,
};
use core_graphics::display::{CGDirectDisplayID, CGDisplay, CGDisplayBounds};
use objc2::rc::{Id, Shared};
use objc2::rc::Id;
use super::appkit::NSScreen;
use super::ffi;
@ -295,19 +295,14 @@ impl MonitorHandle {
}
}
pub(crate) fn ns_screen(&self) -> Option<Id<NSScreen, Shared>> {
pub(crate) fn ns_screen(&self) -> Option<Id<NSScreen>> {
let uuid = unsafe { ffi::CGDisplayCreateUUIDFromDisplayID(self.0) };
NSScreen::screens()
.into_iter()
.find(|screen| {
let other_native_id = screen.display_id();
let other_uuid = unsafe {
ffi::CGDisplayCreateUUIDFromDisplayID(other_native_id as CGDirectDisplayID)
};
uuid == other_uuid
})
.map(|screen| unsafe {
Id::retain(screen as *const NSScreen as *mut NSScreen).unwrap()
})
NSScreen::screens().into_iter().find(|screen| {
let other_native_id = screen.display_id();
let other_uuid = unsafe {
ffi::CGDisplayCreateUUIDFromDisplayID(other_native_id as CGDirectDisplayID)
};
uuid == other_uuid
})
}
}

View file

@ -1,7 +1,7 @@
use std::ops::Deref;
use dispatch::Queue;
use objc2::foundation::{is_main_thread, CGFloat, NSPoint, NSSize, NSString};
use icrate::Foundation::{is_main_thread, CGFloat, NSPoint, NSSize, NSString};
use objc2::rc::autoreleasepool;
use crate::{

View file

@ -5,7 +5,7 @@ mod r#async;
pub(crate) use self::r#async::*;
use core_graphics::display::CGDisplay;
use objc2::foundation::{CGFloat, NSNotFound, NSPoint, NSRange, NSRect, NSUInteger};
use icrate::Foundation::{CGFloat, NSNotFound, NSPoint, NSRange, NSRect, NSUInteger};
use crate::dpi::LogicalPosition;

View file

@ -1,23 +1,23 @@
#![allow(clippy::unnecessary_cast)]
use std::boxed::Box;
use std::cell::{Cell, RefCell};
use std::collections::{HashMap, VecDeque};
use std::os::raw::*;
use std::ptr::{self, NonNull};
use std::str;
use std::ptr::NonNull;
use objc2::declare::{Ivar, IvarDrop};
use objc2::foundation::{
use icrate::Foundation::{
NSArray, NSAttributedString, NSAttributedStringKey, NSCopying, NSMutableAttributedString,
NSObject, NSPoint, NSRange, NSRect, NSSize, NSString, NSUInteger,
NSObject, NSObjectProtocol, NSPoint, NSRange, NSRect, NSSize, NSString, NSUInteger,
};
use objc2::rc::{Id, Owned, Shared, WeakId};
use objc2::declare::{Ivar, IvarDrop};
use objc2::rc::{Id, WeakId};
use objc2::runtime::{Object, Sel};
use objc2::{class, declare_class, msg_send, msg_send_id, sel, ClassType};
use objc2::{class, declare_class, msg_send, msg_send_id, mutability, sel, ClassType};
use super::{
appkit::{NSApp, NSCursor, NSEvent, NSEventPhase, NSResponder, NSTrackingRectTag, NSView},
appkit::{
NSApp, NSCursor, NSEvent, NSEventPhase, NSResponder, NSTextInputClient, NSTrackingRectTag,
NSView,
},
event::{code_to_key, code_to_location},
};
use crate::{
@ -42,7 +42,7 @@ use crate::{
#[derive(Debug)]
struct CursorState {
visible: bool,
cursor: Id<NSCursor, Shared>,
cursor: Id<NSCursor>,
}
impl Default for CursorState {
@ -119,7 +119,7 @@ fn get_left_modifier_code(key: &Key) -> KeyCode {
}
#[derive(Debug, Default)]
struct ViewState {
pub struct ViewState {
cursor_state: RefCell<CursorState>,
ime_position: Cell<LogicalPosition<f64>>,
ime_size: Cell<LogicalSize<f64>>,
@ -138,7 +138,7 @@ struct ViewState {
/// to the application, even during IME
forward_key_to_app: Cell<bool>,
marked_text: RefCell<Id<NSMutableAttributedString, Owned>>,
marked_text: RefCell<Id<NSMutableAttributedString>>,
accepts_first_mouse: bool,
}
@ -147,23 +147,27 @@ declare_class!(
#[allow(non_snake_case)]
pub(super) struct WinitView {
// Weak reference because the window keeps a strong reference to the view
_ns_window: IvarDrop<Box<WeakId<WinitWindow>>>,
state: IvarDrop<Box<ViewState>>,
_ns_window: IvarDrop<Box<WeakId<WinitWindow>>, "__ns_window">,
state: IvarDrop<Box<ViewState>, "_state">,
}
mod ivars;
unsafe impl ClassType for WinitView {
#[inherits(NSResponder, NSObject)]
type Super = NSView;
type Mutability = mutability::InteriorMutable;
const NAME: &'static str = "WinitView";
}
unsafe impl WinitView {
#[sel(initWithId:acceptsFirstMouse:)]
#[method(initWithId:acceptsFirstMouse:)]
unsafe fn init_with_id(
&mut self,
this: *mut Self,
window: &WinitWindow,
accepts_first_mouse: bool,
) -> Option<NonNull<Self>> {
let this: Option<&mut Self> = unsafe { msg_send![super(self), init] };
let this: Option<&mut Self> = unsafe { msg_send![super(this), init] };
this.map(|this| {
let state = ViewState {
accepts_first_mouse,
@ -201,7 +205,7 @@ declare_class!(
}
unsafe impl WinitView {
#[sel(viewDidMoveToWindow)]
#[method(viewDidMoveToWindow)]
fn view_did_move_to_window(&self) {
trace_scope!("viewDidMoveToWindow");
if let Some(tracking_rect) = self.state.tracking_rect.take() {
@ -213,7 +217,7 @@ declare_class!(
self.state.tracking_rect.set(Some(tracking_rect));
}
#[sel(frameDidChange:)]
#[method(frameDidChange:)]
fn frame_did_change(&self, _event: &NSEvent) {
trace_scope!("frameDidChange:");
if let Some(tracking_rect) = self.state.tracking_rect.take() {
@ -232,7 +236,7 @@ declare_class!(
self.queue_event(WindowEvent::Resized(size));
}
#[sel(drawRect:)]
#[method(drawRect:)]
fn draw_rect(&self, rect: NSRect) {
trace_scope!("drawRect:");
@ -247,7 +251,7 @@ declare_class!(
}
}
#[sel(acceptsFirstResponder)]
#[method(acceptsFirstResponder)]
fn accepts_first_responder(&self) -> bool {
trace_scope!("acceptsFirstResponder");
true
@ -256,13 +260,13 @@ declare_class!(
// This is necessary to prevent a beefy terminal error on MacBook Pros:
// IMKInputSession [0x7fc573576ff0 presentFunctionRowItemTextInputViewWithEndpoint:completionHandler:] : [self textInputContext]=0x7fc573558e10 *NO* NSRemoteViewController to client, NSError=Error Domain=NSCocoaErrorDomain Code=4099 "The connection from pid 0 was invalidated from this process." UserInfo={NSDebugDescription=The connection from pid 0 was invalidated from this process.}, com.apple.inputmethod.EmojiFunctionRowItem
// TODO: Add an API extension for using `NSTouchBar`
#[sel(touchBar)]
fn touch_bar(&self) -> bool {
#[method_id(touchBar)]
fn touch_bar(&self) -> Option<Id<NSObject>> {
trace_scope!("touchBar");
false
None
}
#[sel(resetCursorRects)]
#[method(resetCursorRects)]
fn reset_cursor_rects(&self) {
trace_scope!("resetCursorRects");
let bounds = self.bounds();
@ -276,17 +280,17 @@ declare_class!(
}
}
unsafe impl Protocol<NSTextInputClient> for WinitView {
#[sel(hasMarkedText)]
unsafe impl NSTextInputClient for WinitView {
#[method(hasMarkedText)]
fn has_marked_text(&self) -> bool {
trace_scope!("hasMarkedText");
self.state.marked_text.borrow().len_utf16() > 0
self.state.marked_text.borrow().length() > 0
}
#[sel(markedRange)]
#[method(markedRange)]
fn marked_range(&self) -> NSRange {
trace_scope!("markedRange");
let length = self.state.marked_text.borrow().len_utf16();
let length = self.state.marked_text.borrow().length();
if length > 0 {
NSRange::new(0, length)
} else {
@ -294,13 +298,13 @@ declare_class!(
}
}
#[sel(selectedRange)]
#[method(selectedRange)]
fn selected_range(&self) -> NSRange {
trace_scope!("selectedRange");
util::EMPTY_RANGE
}
#[sel(setMarkedText:selectedRange:replacementRange:)]
#[method(setMarkedText:selectedRange:replacementRange:)]
fn set_marked_text(
&self,
string: &NSObject,
@ -356,7 +360,7 @@ declare_class!(
self.queue_event(WindowEvent::Ime(Ime::Preedit(preedit_string, cursor_range)));
}
#[sel(unmarkText)]
#[method(unmarkText)]
fn unmark_text(&self) {
trace_scope!("unmarkText");
*self.state.marked_text.borrow_mut() = NSMutableAttributedString::new();
@ -373,33 +377,33 @@ declare_class!(
}
}
#[sel(validAttributesForMarkedText)]
fn valid_attributes_for_marked_text(&self) -> *const NSArray<NSAttributedStringKey> {
#[method_id(validAttributesForMarkedText)]
fn valid_attributes_for_marked_text(&self) -> Id<NSArray<NSAttributedStringKey>> {
trace_scope!("validAttributesForMarkedText");
Id::autorelease_return(NSArray::new())
NSArray::new()
}
#[sel(attributedSubstringForProposedRange:actualRange:)]
#[method_id(attributedSubstringForProposedRange:actualRange:)]
fn attributed_substring_for_proposed_range(
&self,
_range: NSRange,
_actual_range: *mut c_void, // *mut NSRange
) -> *const NSAttributedString {
_actual_range: *mut NSRange,
) -> Option<Id<NSAttributedString>> {
trace_scope!("attributedSubstringForProposedRange:actualRange:");
ptr::null()
None
}
#[sel(characterIndexForPoint:)]
#[method(characterIndexForPoint:)]
fn character_index_for_point(&self, _point: NSPoint) -> NSUInteger {
trace_scope!("characterIndexForPoint:");
0
}
#[sel(firstRectForCharacterRange:actualRange:)]
#[method(firstRectForCharacterRange:actualRange:)]
fn first_rect_for_character_range(
&self,
_range: NSRange,
_actual_range: *mut c_void, // *mut NSRange
_actual_range: *mut NSRange,
) -> NSRect {
trace_scope!("firstRectForCharacterRange:actualRange:");
let window = self.window();
@ -412,7 +416,7 @@ declare_class!(
NSRect::new(NSPoint::new(x as _, y as _), NSSize::new(width, height))
}
#[sel(insertText:replacementRange:)]
#[method(insertText:replacementRange:)]
fn insert_text(&self, string: &NSObject, _replacement_range: NSRange) {
trace_scope!("insertText:replacementRange:");
@ -439,7 +443,7 @@ declare_class!(
// Basically, we're sent this message whenever a keyboard event that doesn't generate a "human
// readable" character happens, i.e. newlines, tabs, and Ctrl+C.
#[sel(doCommandBySelector:)]
#[method(doCommandBySelector:)]
fn do_command_by_selector(&self, _command: Sel) {
trace_scope!("doCommandBySelector:");
// We shouldn't forward any character from just commited text, since we'll end up sending
@ -459,7 +463,7 @@ declare_class!(
}
unsafe impl WinitView {
#[sel(keyDown:)]
#[method(keyDown:)]
fn key_down(&self, event: &NSEvent) {
trace_scope!("keyDown:");
{
@ -485,7 +489,7 @@ declare_class!(
// `doCommandBySelector`. (doCommandBySelector means that the keyboard input
// is not handled by IME and should be handled by the application)
if self.state.ime_allowed.get() {
let events_for_nsview = NSArray::from_slice(&[event.copy()]);
let events_for_nsview = NSArray::from_slice(&[&*event]);
unsafe { self.interpretKeyEvents(&events_for_nsview) };
// If the text was commited we must treat the next keyboard event as IME related.
@ -518,7 +522,7 @@ declare_class!(
}
}
#[sel(keyUp:)]
#[method(keyUp:)]
fn key_up(&self, event: &NSEvent) {
trace_scope!("keyUp:");
@ -538,15 +542,15 @@ declare_class!(
}
}
#[sel(flagsChanged:)]
fn flags_changed(&self, ns_event: &NSEvent) {
#[method(flagsChanged:)]
fn flags_changed(&self, event: &NSEvent) {
trace_scope!("flagsChanged:");
self.update_modifiers(ns_event, true);
self.update_modifiers(event, true);
}
#[sel(insertTab:)]
fn insert_tab(&self, _sender: *const Object) {
#[method(insertTab:)]
fn insert_tab(&self, _sender: Option<&Object>) {
trace_scope!("insertTab:");
let window = self.window();
if let Some(first_responder) = window.firstResponder() {
@ -556,8 +560,8 @@ declare_class!(
}
}
#[sel(insertBackTab:)]
fn insert_back_tab(&self, _sender: *const Object) {
#[method(insertBackTab:)]
fn insert_back_tab(&self, _sender: Option<&Object>) {
trace_scope!("insertBackTab:");
let window = self.window();
if let Some(first_responder) = window.firstResponder() {
@ -569,8 +573,8 @@ declare_class!(
// Allows us to receive Cmd-. (the shortcut for closing a dialog)
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=300620#c6
#[sel(cancelOperation:)]
fn cancel_operation(&self, _sender: *const Object) {
#[method(cancelOperation:)]
fn cancel_operation(&self, _sender: Option<&Object>) {
trace_scope!("cancelOperation:");
let event = NSApp()
@ -587,42 +591,42 @@ declare_class!(
});
}
#[sel(mouseDown:)]
#[method(mouseDown:)]
fn mouse_down(&self, event: &NSEvent) {
trace_scope!("mouseDown:");
self.mouse_motion(event);
self.mouse_click(event, ElementState::Pressed);
}
#[sel(mouseUp:)]
#[method(mouseUp:)]
fn mouse_up(&self, event: &NSEvent) {
trace_scope!("mouseUp:");
self.mouse_motion(event);
self.mouse_click(event, ElementState::Released);
}
#[sel(rightMouseDown:)]
#[method(rightMouseDown:)]
fn right_mouse_down(&self, event: &NSEvent) {
trace_scope!("rightMouseDown:");
self.mouse_motion(event);
self.mouse_click(event, ElementState::Pressed);
}
#[sel(rightMouseUp:)]
#[method(rightMouseUp:)]
fn right_mouse_up(&self, event: &NSEvent) {
trace_scope!("rightMouseUp:");
self.mouse_motion(event);
self.mouse_click(event, ElementState::Released);
}
#[sel(otherMouseDown:)]
#[method(otherMouseDown:)]
fn other_mouse_down(&self, event: &NSEvent) {
trace_scope!("otherMouseDown:");
self.mouse_motion(event);
self.mouse_click(event, ElementState::Pressed);
}
#[sel(otherMouseUp:)]
#[method(otherMouseUp:)]
fn other_mouse_up(&self, event: &NSEvent) {
trace_scope!("otherMouseUp:");
self.mouse_motion(event);
@ -631,27 +635,27 @@ declare_class!(
// No tracing on these because that would be overly verbose
#[sel(mouseMoved:)]
#[method(mouseMoved:)]
fn mouse_moved(&self, event: &NSEvent) {
self.mouse_motion(event);
}
#[sel(mouseDragged:)]
#[method(mouseDragged:)]
fn mouse_dragged(&self, event: &NSEvent) {
self.mouse_motion(event);
}
#[sel(rightMouseDragged:)]
#[method(rightMouseDragged:)]
fn right_mouse_dragged(&self, event: &NSEvent) {
self.mouse_motion(event);
}
#[sel(otherMouseDragged:)]
#[method(otherMouseDragged:)]
fn other_mouse_dragged(&self, event: &NSEvent) {
self.mouse_motion(event);
}
#[sel(mouseEntered:)]
#[method(mouseEntered:)]
fn mouse_entered(&self, _event: &NSEvent) {
trace_scope!("mouseEntered:");
self.queue_event(WindowEvent::CursorEntered {
@ -659,7 +663,7 @@ declare_class!(
});
}
#[sel(mouseExited:)]
#[method(mouseExited:)]
fn mouse_exited(&self, _event: &NSEvent) {
trace_scope!("mouseExited:");
@ -668,7 +672,7 @@ declare_class!(
});
}
#[sel(scrollWheel:)]
#[method(scrollWheel:)]
fn scroll_wheel(&self, event: &NSEvent) {
trace_scope!("scrollWheel:");
@ -716,7 +720,7 @@ declare_class!(
});
}
#[sel(magnifyWithEvent:)]
#[method(magnifyWithEvent:)]
fn magnify_with_event(&self, event: &NSEvent) {
trace_scope!("magnifyWithEvent:");
@ -735,7 +739,7 @@ declare_class!(
});
}
#[sel(smartMagnifyWithEvent:)]
#[method(smartMagnifyWithEvent:)]
fn smart_magnify_with_event(&self, _event: &NSEvent) {
trace_scope!("smartMagnifyWithEvent:");
@ -744,7 +748,7 @@ declare_class!(
});
}
#[sel(rotateWithEvent:)]
#[method(rotateWithEvent:)]
fn rotate_with_event(&self, event: &NSEvent) {
trace_scope!("rotateWithEvent:");
@ -763,7 +767,7 @@ declare_class!(
});
}
#[sel(pressureChangeWithEvent:)]
#[method(pressureChangeWithEvent:)]
fn pressure_change_with_event(&self, event: &NSEvent) {
trace_scope!("pressureChangeWithEvent:");
@ -779,13 +783,13 @@ declare_class!(
// Allows us to receive Ctrl-Tab and Ctrl-Esc.
// Note that this *doesn't* help with any missing Cmd inputs.
// https://github.com/chromium/chromium/blob/a86a8a6bcfa438fa3ac2eba6f02b3ad1f8e0756f/ui/views/cocoa/bridged_content_view.mm#L816
#[sel(_wantsKeyDownForEvent:)]
#[method(_wantsKeyDownForEvent:)]
fn wants_key_down_for_event(&self, _event: &NSEvent) -> bool {
trace_scope!("_wantsKeyDownForEvent:");
true
}
#[sel(acceptsFirstMouse:)]
#[method(acceptsFirstMouse:)]
fn accepts_first_mouse(&self, _event: &NSEvent) -> bool {
trace_scope!("acceptsFirstMouse:");
self.state.accepts_first_mouse
@ -794,17 +798,17 @@ declare_class!(
);
impl WinitView {
pub(super) fn new(window: &WinitWindow, accepts_first_mouse: bool) -> Id<Self, Shared> {
pub(super) fn new(window: &WinitWindow, accepts_first_mouse: bool) -> Id<Self> {
unsafe {
msg_send_id![
msg_send_id![Self::class(), alloc],
Self::alloc(),
initWithId: window,
acceptsFirstMouse: accepts_first_mouse,
]
}
}
fn window(&self) -> Id<WinitWindow, Shared> {
fn window(&self) -> Id<WinitWindow> {
// TODO: Simply use `window` property on `NSView`.
// That only returns a window _after_ the view has been attached though!
// (which is incompatible with `frameDidChange:`)
@ -849,7 +853,7 @@ impl WinitView {
.unwrap_or_else(String::new)
}
pub(super) fn set_cursor_icon(&self, icon: Id<NSCursor, Shared>) {
pub(super) fn set_cursor_icon(&self, icon: Id<NSCursor>) {
let mut cursor_state = self.state.cursor_state.borrow_mut();
cursor_state.cursor = icon;
}
@ -1072,7 +1076,7 @@ fn mouse_button(event: &NSEvent) -> MouseButton {
// NOTE: to get option as alt working we need to rewrite events
// we're getting from the operating system, which makes it
// impossible to provide such events as extra in `KeyEvent`.
fn replace_event(event: &NSEvent, option_as_alt: OptionAsAlt) -> Id<NSEvent, Shared> {
fn replace_event(event: &NSEvent, option_as_alt: OptionAsAlt) -> Id<NSEvent> {
let ev_mods = event_mods(event).state;
let ignore_alt_characters = match option_as_alt {
OptionAsAlt::OnlyLeft if event.lalt_pressed() => true,

View file

@ -35,13 +35,13 @@ use crate::{
},
};
use core_graphics::display::{CGDisplay, CGPoint};
use objc2::declare::{Ivar, IvarDrop};
use objc2::foundation::{
use icrate::Foundation::{
is_main_thread, CGFloat, NSArray, NSCopying, NSInteger, NSObject, NSPoint, NSRect, NSSize,
NSString,
};
use objc2::rc::{autoreleasepool, Id, Shared};
use objc2::{declare_class, msg_send, msg_send_id, sel, ClassType};
use objc2::declare::{Ivar, IvarDrop};
use objc2::rc::{autoreleasepool, Id};
use objc2::{declare_class, msg_send, msg_send_id, mutability, sel, ClassType};
use super::appkit::{
NSApp, NSAppKitVersion, NSAppearance, NSApplicationPresentationOptions, NSBackingStoreType,
@ -107,27 +107,31 @@ impl Default for PlatformSpecificWindowBuilderAttributes {
declare_class!(
#[derive(Debug)]
pub(crate) struct WinitWindow {
pub struct WinitWindow {
// TODO: Fix unnecessary boxing here
shared_state: IvarDrop<Box<Mutex<SharedState>>>,
shared_state: IvarDrop<Box<Mutex<SharedState>>, "_shared_state">,
}
mod ivars;
unsafe impl ClassType for WinitWindow {
#[inherits(NSResponder, NSObject)]
type Super = NSWindow;
type Mutability = mutability::InteriorMutable;
const NAME: &'static str = "WinitWindow";
}
unsafe impl WinitWindow {
#[sel(initWithContentRect:styleMask:state:)]
#[method(initWithContentRect:styleMask:state:)]
unsafe fn init(
&mut self,
this: *mut Self,
frame: NSRect,
mask: NSWindowStyleMask,
state: *mut c_void,
) -> Option<NonNull<Self>> {
let this: Option<&mut Self> = unsafe {
msg_send![
super(self),
super(this),
initWithContentRect: frame,
styleMask: mask,
backing: NSBackingStoreType::NSBackingStoreBuffered,
@ -152,13 +156,13 @@ declare_class!(
}
unsafe impl WinitWindow {
#[sel(canBecomeMainWindow)]
#[method(canBecomeMainWindow)]
fn can_become_main_window(&self) -> bool {
trace_scope!("canBecomeMainWindow");
true
}
#[sel(canBecomeKeyWindow)]
#[method(canBecomeKeyWindow)]
fn can_become_key_window(&self) -> bool {
trace_scope!("canBecomeKeyWindow");
true
@ -249,7 +253,7 @@ impl WinitWindow {
pub(crate) fn new(
attrs: WindowAttributes,
pl_attrs: PlatformSpecificWindowBuilderAttributes,
) -> Result<(Id<Self, Shared>, Id<WinitWindowDelegate, Shared>), RootOsError> {
) -> Result<(Id<Self>, Id<WinitWindowDelegate>), RootOsError> {
trace_scope!("WinitWindow::new");
if !is_main_thread() {
@ -334,9 +338,9 @@ impl WinitWindow {
// Pass the state through FFI to the method declared on the class
let state_ptr: *mut c_void = Box::into_raw(Box::new(Mutex::new(state))).cast();
let this: Option<Id<Self, Shared>> = unsafe {
let this: Option<Id<Self>> = unsafe {
msg_send_id![
msg_send_id![WinitWindow::class(), alloc],
WinitWindow::alloc(),
initWithContentRect: frame,
styleMask: masks,
state: state_ptr,
@ -413,27 +417,26 @@ impl WinitWindow {
match attrs.parent_window {
Some(RawWindowHandle::AppKit(handle)) => {
// SAFETY: Caller ensures the pointer is valid or NULL
let parent: Id<NSWindow, Shared> =
match unsafe { Id::retain(handle.ns_window.cast()) } {
Some(window) => window,
None => {
// SAFETY: Caller ensures the pointer is valid or NULL
let parent_view: Id<NSView, Shared> =
match unsafe { Id::retain(handle.ns_view.cast()) } {
Some(view) => view,
None => {
return Err(os_error!(OsError::CreationError(
"raw window handle should be non-empty"
)))
}
};
parent_view.window().ok_or_else(|| {
os_error!(OsError::CreationError(
"parent view should be installed in a window"
))
})?
}
};
let parent: Id<NSWindow> = match unsafe { Id::retain(handle.ns_window.cast()) } {
Some(window) => window,
None => {
// SAFETY: Caller ensures the pointer is valid or NULL
let parent_view: Id<NSView> =
match unsafe { Id::retain(handle.ns_view.cast()) } {
Some(view) => view,
None => {
return Err(os_error!(OsError::CreationError(
"raw window handle should be non-empty"
)))
}
};
parent_view.window().ok_or_else(|| {
os_error!(OsError::CreationError(
"parent view should be installed in a window"
))
})?
}
};
// SAFETY: We know that there are no parent -> child -> parent cycles since the only place in `winit`
// where we allow making a window a child window is right here, just after it's been created.
unsafe { parent.addChildWindow(&this, NSWindowOrderingMode::NSWindowAbove) };
@ -477,7 +480,7 @@ impl WinitWindow {
this.set_window_level(attrs.window_level);
// register for drag and drop operations.
this.registerForDraggedTypes(&NSArray::from_slice(&[
this.registerForDraggedTypes(&NSArray::from_id_slice(&[
unsafe { NSFilenamesPboardType }.copy()
]));
@ -521,13 +524,7 @@ impl WinitWindow {
Ok((this, delegate))
}
pub(super) fn retain(&self) -> Id<WinitWindow, Shared> {
// SAFETY: The pointer is valid, and the window is always `Shared`
// TODO(madsmtm): Remove the need for unsafety here
unsafe { Id::retain(self as *const Self as *mut Self).unwrap() }
}
pub(super) fn view(&self) -> Id<WinitView, Shared> {
pub(super) fn view(&self) -> Id<WinitView> {
// SAFETY: The view inside WinitWindow is always `WinitView`
unsafe { Id::cast(self.contentView()) }
}
@ -1462,7 +1459,7 @@ pub(super) fn get_ns_theme() -> Theme {
return Theme::Light;
}
let appearance = app.effectiveAppearance();
let name = appearance.bestMatchFromAppearancesWithNames(&NSArray::from_slice(&[
let name = appearance.bestMatchFromAppearancesWithNames(&NSArray::from_id_slice(&[
NSString::from_str("NSAppearanceNameAqua"),
NSString::from_str("NSAppearanceNameDarkAqua"),
]));

View file

@ -2,11 +2,11 @@
use std::cell::Cell;
use std::ptr::{self, NonNull};
use icrate::Foundation::{NSArray, NSObject, NSSize, NSString};
use objc2::declare::{Ivar, IvarDrop};
use objc2::foundation::{NSArray, NSObject, NSSize, NSString};
use objc2::rc::{autoreleasepool, Id, Shared};
use objc2::rc::{autoreleasepool, Id};
use objc2::runtime::Object;
use objc2::{class, declare_class, msg_send, msg_send_id, sel, ClassType};
use objc2::{class, declare_class, msg_send, msg_send_id, mutability, sel, ClassType};
use super::appkit::{
NSApplicationPresentationOptions, NSFilenamesPboardType, NSPasteboard, NSWindowOcclusionState,
@ -25,7 +25,7 @@ use crate::{
};
#[derive(Debug)]
struct State {
pub struct State {
// This is set when WindowBuilder::with_fullscreen was set,
// see comments of `window_did_fail_to_enter_fullscreen`
initial_fullscreen: Cell<bool>,
@ -40,26 +40,30 @@ struct State {
declare_class!(
#[derive(Debug)]
pub(crate) struct WinitWindowDelegate {
window: IvarDrop<Id<WinitWindow, Shared>>,
window: IvarDrop<Id<WinitWindow>, "_window">,
// TODO: It may be possible for delegate methods to be called
// asynchronously, causing data races panics?
// TODO: Remove unnecessary boxing here
state: IvarDrop<Box<State>>,
state: IvarDrop<Box<State>, "_state">,
}
mod ivars;
unsafe impl ClassType for WinitWindowDelegate {
type Super = NSObject;
type Mutability = mutability::InteriorMutable;
const NAME: &'static str = "WinitWindowDelegate";
}
unsafe impl WinitWindowDelegate {
#[sel(initWithWindow:initialFullscreen:)]
#[method(initWithWindow:initialFullscreen:)]
unsafe fn init_with_winit(
&mut self,
this: *mut Self,
window: &WinitWindow,
initial_fullscreen: bool,
) -> Option<NonNull<Self>> {
let this: Option<&mut Self> = unsafe { msg_send![super(self), init] };
let this: Option<&mut Self> = unsafe { msg_send![super(this), init] };
this.map(|this| {
let scale_factor = window.scale_factor();
@ -79,7 +83,7 @@ declare_class!(
this.window.setDelegate(Some(this));
// Enable theme change event
let notification_center: Id<Object, Shared> =
let notification_center: Id<Object> =
unsafe { msg_send_id![class!(NSDistributedNotificationCenter), defaultCenter] };
let notification_name =
NSString::from_str("AppleInterfaceThemeChangedNotification");
@ -100,14 +104,14 @@ declare_class!(
// NSWindowDelegate + NSDraggingDestination protocols
unsafe impl WinitWindowDelegate {
#[sel(windowShouldClose:)]
#[method(windowShouldClose:)]
fn window_should_close(&self, _: Option<&Object>) -> bool {
trace_scope!("windowShouldClose:");
self.queue_event(WindowEvent::CloseRequested);
false
}
#[sel(windowWillClose:)]
#[method(windowWillClose:)]
fn window_will_close(&self, _: Option<&Object>) {
trace_scope!("windowWillClose:");
// `setDelegate:` retains the previous value and then autoreleases it
@ -119,14 +123,14 @@ declare_class!(
self.queue_event(WindowEvent::Destroyed);
}
#[sel(windowDidResize:)]
#[method(windowDidResize:)]
fn window_did_resize(&self, _: Option<&Object>) {
trace_scope!("windowDidResize:");
// NOTE: WindowEvent::Resized is reported in frameDidChange.
self.emit_move_event();
}
#[sel(windowWillStartLiveResize:)]
#[method(windowWillStartLiveResize:)]
fn window_will_start_live_resize(&self, _: Option<&Object>) {
trace_scope!("windowWillStartLiveResize:");
@ -137,26 +141,26 @@ declare_class!(
self.window.set_resize_increments_inner(increments);
}
#[sel(windowDidEndLiveResize:)]
#[method(windowDidEndLiveResize:)]
fn window_did_end_live_resize(&self, _: Option<&Object>) {
trace_scope!("windowDidEndLiveResize:");
self.window.set_resize_increments_inner(NSSize::new(1., 1.));
}
// This won't be triggered if the move was part of a resize.
#[sel(windowDidMove:)]
#[method(windowDidMove:)]
fn window_did_move(&self, _: Option<&Object>) {
trace_scope!("windowDidMove:");
self.emit_move_event();
}
#[sel(windowDidChangeBackingProperties:)]
#[method(windowDidChangeBackingProperties:)]
fn window_did_change_backing_properties(&self, _: Option<&Object>) {
trace_scope!("windowDidChangeBackingProperties:");
self.queue_static_scale_factor_changed_event();
}
#[sel(windowDidBecomeKey:)]
#[method(windowDidBecomeKey:)]
fn window_did_become_key(&self, _: Option<&Object>) {
trace_scope!("windowDidBecomeKey:");
// TODO: center the cursor if the window had mouse grab when it
@ -164,7 +168,7 @@ declare_class!(
self.queue_event(WindowEvent::Focused(true));
}
#[sel(windowDidResignKey:)]
#[method(windowDidResignKey:)]
fn window_did_resign_key(&self, _: Option<&Object>) {
trace_scope!("windowDidResignKey:");
// It happens rather often, e.g. when the user is Cmd+Tabbing, that the
@ -180,15 +184,15 @@ declare_class!(
}
/// Invoked when the dragged image enters destination bounds or frame
#[sel(draggingEntered:)]
fn dragging_entered(&self, sender: *mut Object) -> bool {
#[method(draggingEntered:)]
fn dragging_entered(&self, sender: &NSObject) -> bool {
trace_scope!("draggingEntered:");
use std::path::PathBuf;
let pb: Id<NSPasteboard, Shared> = unsafe { msg_send_id![sender, draggingPasteboard] };
let pb: Id<NSPasteboard> = unsafe { msg_send_id![sender, draggingPasteboard] };
let filenames = pb.propertyListForType(unsafe { NSFilenamesPboardType });
let filenames: Id<NSArray<NSString>, Shared> = unsafe { Id::cast(filenames) };
let filenames: Id<NSArray<NSString>> = unsafe { Id::cast(filenames) };
filenames.into_iter().for_each(|file| {
let path = PathBuf::from(file.to_string());
@ -199,22 +203,22 @@ declare_class!(
}
/// Invoked when the image is released
#[sel(prepareForDragOperation:)]
fn prepare_for_drag_operation(&self, _: Option<&Object>) -> bool {
#[method(prepareForDragOperation:)]
fn prepare_for_drag_operation(&self, _sender: &NSObject) -> bool {
trace_scope!("prepareForDragOperation:");
true
}
/// Invoked after the released image has been removed from the screen
#[sel(performDragOperation:)]
fn perform_drag_operation(&self, sender: *mut Object) -> bool {
#[method(performDragOperation:)]
fn perform_drag_operation(&self, sender: &NSObject) -> bool {
trace_scope!("performDragOperation:");
use std::path::PathBuf;
let pb: Id<NSPasteboard, Shared> = unsafe { msg_send_id![sender, draggingPasteboard] };
let pb: Id<NSPasteboard> = unsafe { msg_send_id![sender, draggingPasteboard] };
let filenames = pb.propertyListForType(unsafe { NSFilenamesPboardType });
let filenames: Id<NSArray<NSString>, Shared> = unsafe { Id::cast(filenames) };
let filenames: Id<NSArray<NSString>> = unsafe { Id::cast(filenames) };
filenames.into_iter().for_each(|file| {
let path = PathBuf::from(file.to_string());
@ -225,20 +229,20 @@ declare_class!(
}
/// Invoked when the dragging operation is complete
#[sel(concludeDragOperation:)]
fn conclude_drag_operation(&self, _: Option<&Object>) {
#[method(concludeDragOperation:)]
fn conclude_drag_operation(&self, _sender: Option<&NSObject>) {
trace_scope!("concludeDragOperation:");
}
/// Invoked when the dragging operation is cancelled
#[sel(draggingExited:)]
fn dragging_exited(&self, _: Option<&Object>) {
#[method(draggingExited:)]
fn dragging_exited(&self, _sender: Option<&NSObject>) {
trace_scope!("draggingExited:");
self.queue_event(WindowEvent::HoveredFileCancelled);
}
/// Invoked when before enter fullscreen
#[sel(windowWillEnterFullScreen:)]
#[method(windowWillEnterFullScreen:)]
fn window_will_enter_fullscreen(&self, _: Option<&Object>) {
trace_scope!("windowWillEnterFullScreen:");
@ -267,7 +271,7 @@ declare_class!(
}
/// Invoked when before exit fullscreen
#[sel(windowWillExitFullScreen:)]
#[method(windowWillExitFullScreen:)]
fn window_will_exit_fullscreen(&self, _: Option<&Object>) {
trace_scope!("windowWillExitFullScreen:");
@ -275,7 +279,7 @@ declare_class!(
shared_state.in_fullscreen_transition = true;
}
#[sel(window:willUseFullScreenPresentationOptions:)]
#[method(window:willUseFullScreenPresentationOptions:)]
fn window_will_use_fullscreen_presentation_options(
&self,
_: Option<&Object>,
@ -304,7 +308,7 @@ declare_class!(
}
/// Invoked when entered fullscreen
#[sel(windowDidEnterFullScreen:)]
#[method(windowDidEnterFullScreen:)]
fn window_did_enter_fullscreen(&self, _: Option<&Object>) {
trace_scope!("windowDidEnterFullScreen:");
self.state.initial_fullscreen.set(false);
@ -318,7 +322,7 @@ declare_class!(
}
/// Invoked when exited fullscreen
#[sel(windowDidExitFullScreen:)]
#[method(windowDidExitFullScreen:)]
fn window_did_exit_fullscreen(&self, _: Option<&Object>) {
trace_scope!("windowDidExitFullScreen:");
@ -348,7 +352,7 @@ declare_class!(
/// due to being in the midst of handling some other animation or user gesture.
/// This method indicates that there was an error, and you should clean up any
/// work you may have done to prepare to enter full-screen mode.
#[sel(windowDidFailToEnterFullScreen:)]
#[method(windowDidFailToEnterFullScreen:)]
fn window_did_fail_to_enter_fullscreen(&self, _: Option<&Object>) {
trace_scope!("windowDidFailToEnterFullScreen:");
let mut shared_state = self
@ -372,7 +376,7 @@ declare_class!(
}
// Invoked when the occlusion state of the window changes
#[sel(windowDidChangeOcclusionState:)]
#[method(windowDidChangeOcclusionState:)]
fn window_did_change_occlusion_state(&self, _: Option<&Object>) {
trace_scope!("windowDidChangeOcclusionState:");
self.queue_event(WindowEvent::Occluded(
@ -384,7 +388,7 @@ declare_class!(
}
// Observe theme change
#[sel(effectiveAppearanceDidChange:)]
#[method(effectiveAppearanceDidChange:)]
fn effective_appearance_did_change(&self, sender: Option<&Object>) {
trace_scope!("Triggered `effectiveAppearanceDidChange:`");
unsafe {
@ -397,7 +401,7 @@ declare_class!(
}
}
#[sel(effectiveAppearanceDidChangedOnMainThread:)]
#[method(effectiveAppearanceDidChangedOnMainThread:)]
fn effective_appearance_did_changed_on_main_thread(&self, _: Option<&Object>) {
let theme = get_ns_theme();
let mut shared_state = self
@ -411,7 +415,7 @@ declare_class!(
}
}
#[sel(windowDidChangeScreen:)]
#[method(windowDidChangeScreen:)]
fn window_did_change_screen(&self, _: Option<&Object>) {
trace_scope!("windowDidChangeScreen:");
let is_simple_fullscreen = self
@ -428,10 +432,10 @@ declare_class!(
);
impl WinitWindowDelegate {
pub fn new(window: &WinitWindow, initial_fullscreen: bool) -> Id<Self, Shared> {
pub fn new(window: &WinitWindow, initial_fullscreen: bool) -> Id<Self> {
unsafe {
msg_send_id![
msg_send_id![Self::class(), alloc],
Self::alloc(),
initWithWindow: window,
initialFullscreen: initial_fullscreen,
]