Bring back dependency on core-graphics because, well, I'm apparently a moron. Further sketching out of WindowDelegate.

This commit is contained in:
Ryan McGrath 2020-03-26 17:31:42 -07:00
parent b0232ca225
commit d512b7bcf5
No known key found for this signature in database
GPG key ID: 811674B62B666830
14 changed files with 557 additions and 105 deletions

View file

@ -10,6 +10,7 @@ path = "lib.rs"
[dependencies] [dependencies]
block = "0.1.6" block = "0.1.6"
core-graphics = "0.19.0"
dispatch = "0.2.0" dispatch = "0.2.0"
libc = "0.2" libc = "0.2"
objc = "0.2.7" objc = "0.2.7"

View file

@ -56,3 +56,103 @@ impl From<AppDelegateResponse> for NSUInteger {
} }
} }
} }
/// Used (typically) when handling full-screening an application or window. Use these to instruct
/// how the full screen should work. Note that some may conflict!
///
/// From Apple's documentation, swapped to use the enum values here:
///
/// - _`AutoHideDock` and `HideDock` are mutually exclusive: You may specify one or the other, but
/// not both._
/// - _`AutoHideMenuBar` and `HideMenuBar` are mutually exclusive: You may specify one or the other, but not both._
/// - _If you specify `HideMenuBar`, it must be accompanied by `HideDock`._
/// - _If you specify `AutoHideMenuBar`, it must be accompanied by either `HideDock` or `AutoHideDock`._
/// - _If you specify any of `DisableProcessSwitching`, `DisableForceQuit`, `DisableSessionTermination`, or `DisableMenuBarTransparency`,
/// it must be accompanied by either `HideDock` or `AutoHideDock`._
/// - _`AutoHideToolbar` may be used only when both `FullScreen` and `AutoHideMenuBar` are also set.
#[derive(Copy, Clone, Debug)]
pub enum PresentationOption {
/// The default mode.
Default,
/// Auto hide the dock. Will reappear when moused near.
AutoHideDock,
/// Dock is entirely disabled.
HideDock,
/// Auto hide the menubar. Will reappear when moused near.
AutoHideMenuBar,
/// Menubar is entirely disabled.
HideMenuBar,
/// All Apple Menu items are disabled.
DisableAppleMenu,
/// The process switching user interface (Command + Tab to cycle through apps) is disabled.
DisableProcessSwitching,
/// The force quit panel (displayed by pressing Command + Option + Esc) is disabled
DisableForceQuit,
/// The panel that shows the Restart, Shut Down, and Log Out options that are displayed as a result of pushing the power key is disabled.
DisableSessionTermination,
/// The apps "Hide" menu item is disabled.
DisableHideApplication,
/// The menu bar transparency appearance is disabled.
DisableMenuBarTransparency,
/// The app is in fullscreen mode.
FullScreen,
/// When in fullscreen mode the window toolbar is detached from window and hides and shows with autoHidden menuBar.
AutoHideToolbar,
/// The behavior that allows the user to shake the mouse to locate the cursor is disabled.
DisableCursorLocationAssistance
}
impl From<PresentationOption> for NSUInteger {
fn from(option: PresentationOption) -> Self {
match option {
PresentationOption::Default => 0,
PresentationOption::AutoHideDock => (1 << 0),
PresentationOption::HideDock => (1 << 1),
PresentationOption::AutoHideMenuBar => (1 << 2),
PresentationOption::HideMenuBar => (1 << 3),
PresentationOption::DisableAppleMenu => (1 << 4),
PresentationOption::DisableProcessSwitching => (1 << 5),
PresentationOption::DisableForceQuit => (1 << 6),
PresentationOption::DisableSessionTermination => (1 << 7),
PresentationOption::DisableHideApplication => (1 << 8),
PresentationOption::DisableMenuBarTransparency => (1 << 9),
PresentationOption::FullScreen => (1 << 10),
PresentationOption::AutoHideToolbar => (1 << 11),
PresentationOption::DisableCursorLocationAssistance => (1 << 12)
}
}
}
impl From<&PresentationOption> for NSUInteger {
fn from(option: &PresentationOption) -> Self {
match option {
PresentationOption::Default => 0,
PresentationOption::AutoHideDock => (1 << 0),
PresentationOption::HideDock => (1 << 1),
PresentationOption::AutoHideMenuBar => (1 << 2),
PresentationOption::HideMenuBar => (1 << 3),
PresentationOption::DisableAppleMenu => (1 << 4),
PresentationOption::DisableProcessSwitching => (1 << 5),
PresentationOption::DisableForceQuit => (1 << 6),
PresentationOption::DisableSessionTermination => (1 << 7),
PresentationOption::DisableHideApplication => (1 << 8),
PresentationOption::DisableMenuBarTransparency => (1 << 9),
PresentationOption::FullScreen => (1 << 10),
PresentationOption::AutoHideToolbar => (1 << 11),
PresentationOption::DisableCursorLocationAssistance => (1 << 12)
}
}
}

View file

@ -1,9 +1,11 @@
//! Implements `Color`. Heavily based on the `Color` module in Servo's CSS parser, but tweaked //! Implements `Color`. Heavily based on the `Color` module in Servo's CSS parser, but tweaked
//! for (what I believe) is a friendlier API. //! for (what I believe) is a friendlier API.
use core_graphics::base::CGFloat;
use objc::{class, msg_send, sel, sel_impl}; use objc::{class, msg_send, sel, sel_impl};
use crate::foundation::{id, CGFloat}; use crate::foundation::id;
/// A color with red, green, blue, and alpha components, in a byte each. /// A color with red, green, blue, and alpha components, in a byte each.
#[derive(Clone, Copy, PartialEq, Debug)] #[derive(Clone, Copy, PartialEq, Debug)]

View file

@ -1,81 +0,0 @@
//! Implements Core Graphics Geometry types. Most of this is lifted from `servo/core-foundation-rs`
//! - as such, we include a copy of the license below.
//!
//! Copyright (c) 2012-2013 Mozilla Foundation
//!
//! Permission is hereby granted, free of charge, to any
//! person obtaining a copy of this software and associated
//! documentation files (the "Software"), to deal in the
//! Software without restriction, including without
//! limitation the rights to use, copy, modify, merge,
//! publish, distribute, sublicense, and/or sell copies of
//! the Software, and to permit persons to whom the Software
//! is furnished to do so, subject to the following
//! conditions:
//!
//! The above copyright notice and this permission notice
//! shall be included in all copies or substantial portions
//! of the Software.
//!
//! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
//! ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
//! TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
//! PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
//! SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
//! CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
//! OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
//! IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
//! DEALINGS IN THE SOFTWARE.
use crate::foundation::CGFloat;
#[repr(C)]
#[derive(Clone, Copy, Debug, Default, PartialEq)]
pub struct CGSize {
pub width: CGFloat,
pub height: CGFloat,
}
impl CGSize {
#[inline]
pub fn new(width: CGFloat, height: CGFloat) -> CGSize {
CGSize {
width: width,
height: height,
}
}
}
#[repr(C)]
#[derive(Clone, Copy, Debug, Default, PartialEq)]
pub struct CGPoint {
pub x: CGFloat,
pub y: CGFloat,
}
impl CGPoint {
#[inline]
pub fn new(x: CGFloat, y: CGFloat) -> CGPoint {
CGPoint {
x: x,
y: y,
}
}
}
#[repr(C)]
#[derive(Clone, Copy, Debug, Default)]
pub struct CGRect {
pub origin: CGPoint,
pub size: CGSize
}
impl CGRect {
#[inline]
pub fn new(origin: &CGPoint, size: &CGSize) -> CGRect {
CGRect {
origin: *origin,
size: *size,
}
}
}

View file

@ -26,9 +26,6 @@ pub use string::NSString;
pub mod dictionary; pub mod dictionary;
pub use dictionary::NSDictionary; pub use dictionary::NSDictionary;
pub mod geometry;
pub use geometry::{CGSize, CGPoint, CGRect};
#[allow(non_camel_case_types)] #[allow(non_camel_case_types)]
pub type id = *mut runtime::Object; pub type id = *mut runtime::Object;
@ -44,8 +41,3 @@ pub type NSUInteger = libc::c_uint;
pub type NSInteger = libc::c_long; pub type NSInteger = libc::c_long;
#[cfg(target_pointer_width = "64")] #[cfg(target_pointer_width = "64")]
pub type NSUInteger = libc::c_ulong; pub type NSUInteger = libc::c_ulong;
#[cfg(target_pointer_width = "64")]
pub type CGFloat = libc::c_double;
#[cfg(not(target_pointer_width = "64"))]
pub type CGFloat = libc::c_float;

View file

@ -1,6 +1,6 @@
//! Wrapper methods for various geometry types (rects, sizes, ec). //! Wrapper methods for various geometry types (rects, sizes, ec).
use crate::foundation::{CGRect, CGPoint, CGSize}; use core_graphics::geometry::{CGRect, CGPoint, CGSize};
/// A struct that represents a box - top, left, width and height. /// A struct that represents a box - top, left, width and height.
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug)]

View file

@ -2,11 +2,13 @@
//! escape hatch, if you need it (we use it for things like width and height, which aren't handled //! escape hatch, if you need it (we use it for things like width and height, which aren't handled
//! by an axis). //! by an axis).
use core_graphics::base::CGFloat;
use objc::{class, msg_send, sel, sel_impl}; use objc::{class, msg_send, sel, sel_impl};
use objc::runtime::Object; use objc::runtime::Object;
use objc_id::ShareId; use objc_id::ShareId;
use crate::foundation::{id, CGFloat}; use crate::foundation::id;
/// A wrapper for `NSLayoutConstraint`. This both acts as a central path through which to activate /// A wrapper for `NSLayoutConstraint`. This both acts as a central path through which to activate
/// constraints, as well as a wrapper for layout constraints that are not axis bound (e.g, width or /// constraints, as well as a wrapper for layout constraints that are not axis bound (e.g, width or

View file

@ -1,11 +1,13 @@
//! A wrapper for `NSLayoutAnchorDimension`, which is typically used to handle `width` and `height` //! A wrapper for `NSLayoutAnchorDimension`, which is typically used to handle `width` and `height`
//! values for how a given view should layout. //! values for how a given view should layout.
use core_graphics::base::CGFloat;
use objc::{msg_send, sel, sel_impl}; use objc::{msg_send, sel, sel_impl};
use objc::runtime::Object; use objc::runtime::Object;
use objc_id::ShareId; use objc_id::ShareId;
use crate::foundation::{id, CGFloat}; use crate::foundation::id;
use crate::layout::constraint::LayoutConstraint; use crate::layout::constraint::LayoutConstraint;
/// A wrapper for `NSLayoutAnchor`. You should never be creating this yourself - it's more of a /// A wrapper for `NSLayoutAnchor`. You should never be creating this yourself - it's more of a

View file

@ -3,11 +3,13 @@
//! //!
//! UNFORTUNATELY, this is a very old and janky API. So... yeah. //! UNFORTUNATELY, this is a very old and janky API. So... yeah.
use core_graphics::geometry::CGSize;
use objc_id::Id; use objc_id::Id;
use objc::runtime::Object; use objc::runtime::Object;
use objc::{class, msg_send, sel, sel_impl}; use objc::{class, msg_send, sel, sel_impl};
use crate::foundation::{id, CGSize, NSString}; use crate::foundation::{id, NSString};
use crate::button::Button; use crate::button::Button;
/// A wrapper for `NSWindow`. Holds (retains) pointers for the Objective-C runtime /// A wrapper for `NSWindow`. Holds (retains) pointers for the Objective-C runtime

View file

@ -5,6 +5,9 @@
use std::rc::Rc; use std::rc::Rc;
use std::cell::RefCell; use std::cell::RefCell;
use core_graphics::base::CGFloat;
use objc::{Encode, Encoding};
use objc::runtime::Object; use objc::runtime::Object;
use objc_id::ShareId; use objc_id::ShareId;
@ -24,3 +27,22 @@ pub fn load<T>(this: &Object, ptr: &str) -> Rc<RefCell<T>> {
Rc::from_raw(view_ptr) Rc::from_raw(view_ptr)
} }
} }
/// Upstream core graphics does not implement Encode for certain things, so we wrap them here -
/// these are only used in reading certain types passed to us from some delegate methods.
#[repr(C)]
#[derive(Clone, Copy, Debug, Default, PartialEq)]
pub struct CGSize {
pub width: CGFloat,
pub height: CGFloat,
}
unsafe impl Encode for CGSize {
fn encode() -> Encoding {
let encoding = format!("{{CGSize={}{}}}",
CGFloat::encode().as_str(),
CGFloat::encode().as_str()
);
unsafe { Encoding::from_str(&encoding) }
}
}

View file

@ -4,14 +4,34 @@
use std::rc::Rc; use std::rc::Rc;
use std::sync::Once; use std::sync::Once;
use core_graphics::base::CGFloat;
use objc::declare::ClassDecl; use objc::declare::ClassDecl;
use objc::runtime::{Class, Object, Sel}; use objc::runtime::{Class, Object, Sel};
use objc::{class, sel, sel_impl}; use objc::{class, sel, sel_impl};
use crate::foundation::id; use crate::foundation::{id, BOOL, YES, NO, NSUInteger};
use crate::utils::load; use crate::utils::{load, CGSize};
use crate::window::{WindowDelegate, WINDOW_DELEGATE_PTR}; use crate::window::{WindowDelegate, WINDOW_DELEGATE_PTR};
/// Called when an `NSWindowDelegate` receives a `windowWillClose:` event.
/// Good place to clean up memory and what not.
extern fn should_close<T: WindowDelegate>(this: &Object, _: Sel, _: id) -> BOOL {
let window = load::<T>(this, WINDOW_DELEGATE_PTR);
let result = {
let window = window.borrow();
(*window).should_close()
};
Rc::into_raw(window);
match result {
true => YES,
false => NO
}
}
/// Called when an `NSWindowDelegate` receives a `windowWillClose:` event. /// Called when an `NSWindowDelegate` receives a `windowWillClose:` event.
/// Good place to clean up memory and what not. /// Good place to clean up memory and what not.
extern fn will_close<T: WindowDelegate>(this: &Object, _: Sel, _: id) { extern fn will_close<T: WindowDelegate>(this: &Object, _: Sel, _: id) {
@ -73,6 +93,219 @@ extern fn did_change_screen_profile<T: WindowDelegate>(this: &Object, _: Sel, _:
Rc::into_raw(window); Rc::into_raw(window);
} }
/// Called when an `NSWindowDelegate` receives a `windowDidChangeScreen:` event.
extern fn will_resize<T: WindowDelegate>(this: &Object, _: Sel, _: id, size: CGSize) -> CGSize {
let window = load::<T>(this, WINDOW_DELEGATE_PTR);
let result = {
let window = window.borrow();
let s = (*window).will_resize(size.width as f64, size.height as f64);
CGSize {
width: s.0 as CGFloat,
height: s.1 as CGFloat
}
};
Rc::into_raw(window);
result
}
/// Called when an `NSWindowDelegate` receives a `windowDidChangeScreen:` event.
extern fn did_resize<T: WindowDelegate>(this: &Object, _: Sel, _: id) {
let window = load::<T>(this, WINDOW_DELEGATE_PTR);
{
let window = window.borrow();
(*window).did_resize();
}
Rc::into_raw(window);
}
/// Called when an `NSWindowDelegate` receives a `windowDidChangeScreen:` event.
extern fn will_start_live_resize<T: WindowDelegate>(this: &Object, _: Sel, _: id) {
let window = load::<T>(this, WINDOW_DELEGATE_PTR);
{
let window = window.borrow();
(*window).will_start_live_resize();
}
Rc::into_raw(window);
}
/// Called when an `NSWindowDelegate` receives a `windowDidChangeScreen:` event.
extern fn did_end_live_resize<T: WindowDelegate>(this: &Object, _: Sel, _: id) {
let window = load::<T>(this, WINDOW_DELEGATE_PTR);
{
let window = window.borrow();
(*window).did_end_live_resize();
}
Rc::into_raw(window);
}
/// Called when an `NSWindowDelegate` receives a `windowDidChangeScreen:` event.
extern fn will_miniaturize<T: WindowDelegate>(this: &Object, _: Sel, _: id) {
let window = load::<T>(this, WINDOW_DELEGATE_PTR);
{
let window = window.borrow();
(*window).will_miniaturize();
}
Rc::into_raw(window);
}
/// Called when an `NSWindowDelegate` receives a `windowDidChangeScreen:` event.
extern fn did_miniaturize<T: WindowDelegate>(this: &Object, _: Sel, _: id) {
let window = load::<T>(this, WINDOW_DELEGATE_PTR);
{
let window = window.borrow();
(*window).did_miniaturize();
}
Rc::into_raw(window);
}
/// Called when an `NSWindowDelegate` receives a `windowDidChangeScreen:` event.
extern fn did_deminiaturize<T: WindowDelegate>(this: &Object, _: Sel, _: id) {
let window = load::<T>(this, WINDOW_DELEGATE_PTR);
{
let window = window.borrow();
(*window).did_deminiaturize();
}
Rc::into_raw(window);
}
/// Called when an `NSWindowDelegate` receives a `windowDidChangeScreenProfile:` event.
extern fn will_enter_full_screen<T: WindowDelegate>(this: &Object, _: Sel, _: id) {
let window = load::<T>(this, WINDOW_DELEGATE_PTR);
{
let window = window.borrow();
(*window).will_enter_full_screen();
}
Rc::into_raw(window);
}
/// Called when an `NSWindowDelegate` receives a `windowDidChangeScreenProfile:` event.
extern fn did_enter_full_screen<T: WindowDelegate>(this: &Object, _: Sel, _: id) {
let window = load::<T>(this, WINDOW_DELEGATE_PTR);
{
let window = window.borrow();
(*window).did_enter_full_screen();
}
Rc::into_raw(window);
}
/// Called when an `NSWindowDelegate` receives a `windowDidChangeScreenProfile:` event.
extern fn content_size_for_full_screen<T: WindowDelegate>(this: &Object, _: Sel, _: id, size: CGSize) -> CGSize {
let window = load::<T>(this, WINDOW_DELEGATE_PTR);
let result = {
let window = window.borrow();
let (width, height) = (*window).content_size_for_full_screen(
size.width as f64,
size.height as f64
);
CGSize {
width: width as CGFloat,
height: height as CGFloat
}
};
Rc::into_raw(window);
result
}
/// Called when an `NSWindowDelegate` receives a `windowDidChangeScreenProfile:` event.
extern fn options_for_full_screen<T: WindowDelegate>(this: &Object, _: Sel, _: id, options: NSUInteger) -> NSUInteger {
let window = load::<T>(this, WINDOW_DELEGATE_PTR);
let result = {
let window = window.borrow();
let options = (*window).presentation_options_for_full_screen();
if options.is_none() {
None
} else {
let mut opts: NSUInteger = 0;
for opt in options.unwrap() {
opts = opts << NSUInteger::from(opt);
}
Some(opts)
}
};
Rc::into_raw(window);
match result {
Some(options) => options,
None => options
}
}
/// Called when an `NSWindowDelegate` receives a `windowDidChangeScreenProfile:` event.
extern fn will_exit_full_screen<T: WindowDelegate>(this: &Object, _: Sel, _: id) {
let window = load::<T>(this, WINDOW_DELEGATE_PTR);
{
let window = window.borrow();
(*window).will_exit_full_screen();
}
Rc::into_raw(window);
}
/// Called when an `NSWindowDelegate` receives a `windowDidChangeScreenProfile:` event.
extern fn did_exit_full_screen<T: WindowDelegate>(this: &Object, _: Sel, _: id) {
let window = load::<T>(this, WINDOW_DELEGATE_PTR);
{
let window = window.borrow();
(*window).did_exit_full_screen();
}
Rc::into_raw(window);
}
/// Called when an `NSWindowDelegate` receives a `windowDidChangeScreenProfile:` event.
extern fn did_fail_to_enter_full_screen<T: WindowDelegate>(this: &Object, _: Sel, _: id) {
let window = load::<T>(this, WINDOW_DELEGATE_PTR);
{
let window = window.borrow();
(*window).did_fail_to_enter_full_screen();
}
Rc::into_raw(window);
}
/// Called when an `NSWindowDelegate` receives a `windowDidChangeScreenProfile:` event.
extern fn did_fail_to_exit_full_screen<T: WindowDelegate>(this: &Object, _: Sel, _: id) {
let window = load::<T>(this, WINDOW_DELEGATE_PTR);
{
let window = window.borrow();
(*window).did_fail_to_exit_full_screen();
}
Rc::into_raw(window);
}
/// Called when an `NSWindowDelegate` receives a `windowDidChangeBackingProperties:` event. /// Called when an `NSWindowDelegate` receives a `windowDidChangeBackingProperties:` event.
extern fn did_change_backing_properties<T: WindowDelegate>(this: &Object, _: Sel, _: id) { extern fn did_change_backing_properties<T: WindowDelegate>(this: &Object, _: Sel, _: id) {
let window = load::<T>(this, WINDOW_DELEGATE_PTR); let window = load::<T>(this, WINDOW_DELEGATE_PTR);
@ -85,6 +318,91 @@ extern fn did_change_backing_properties<T: WindowDelegate>(this: &Object, _: Sel
Rc::into_raw(window); Rc::into_raw(window);
} }
/// Called when an `NSWindowDelegate` receives a `windowDidChangeBackingProperties:` event.
extern fn did_change_occlusion_state<T: WindowDelegate>(this: &Object, _: Sel, _: id) {
let window = load::<T>(this, WINDOW_DELEGATE_PTR);
{
let window = window.borrow();
(*window).did_change_occlusion_state();
}
Rc::into_raw(window);
}
/// Called when an `NSWindowDelegate` receives a `windowDidUpdate:` event.
extern fn did_update<T: WindowDelegate>(this: &Object, _: Sel, _: id) {
let window = load::<T>(this, WINDOW_DELEGATE_PTR);
{
let window = window.borrow();
(*window).did_update();
}
Rc::into_raw(window);
}
/// Called when an `NSWindowDelegate` receives a `windowDidExpose:` event.
extern fn did_become_main<T: WindowDelegate>(this: &Object, _: Sel, _: id) {
let window = load::<T>(this, WINDOW_DELEGATE_PTR);
{
let window = window.borrow();
(*window).did_become_main();
}
Rc::into_raw(window);
}
/// Called when an `NSWindowDelegate` receives a `windowDidExpose:` event.
extern fn did_resign_main<T: WindowDelegate>(this: &Object, _: Sel, _: id) {
let window = load::<T>(this, WINDOW_DELEGATE_PTR);
{
let window = window.borrow();
(*window).did_resign_main();
}
Rc::into_raw(window);
}
/// Called when an `NSWindowDelegate` receives a `windowDidExpose:` event.
extern fn did_become_key<T: WindowDelegate>(this: &Object, _: Sel, _: id) {
let window = load::<T>(this, WINDOW_DELEGATE_PTR);
{
let window = window.borrow();
(*window).did_become_key();
}
Rc::into_raw(window);
}
/// Called when an `NSWindowDelegate` receives a `windowDidExpose:` event.
extern fn did_resign_key<T: WindowDelegate>(this: &Object, _: Sel, _: id) {
let window = load::<T>(this, WINDOW_DELEGATE_PTR);
{
let window = window.borrow();
(*window).did_resign_key();
}
Rc::into_raw(window);
}
/// Called when an `NSWindowDelegate` receives a `windowDidExpose:` event.
extern fn did_expose<T: WindowDelegate>(this: &Object, _: Sel, _: id) {
let window = load::<T>(this, WINDOW_DELEGATE_PTR);
{
let window = window.borrow();
(*window).did_expose();
}
Rc::into_raw(window);
}
/// Injects an `NSWindow` subclass, with some callback and pointer ivars for what we /// Injects an `NSWindow` subclass, with some callback and pointer ivars for what we
/// need to do. /// need to do.
pub(crate) fn register_window_class() -> *const Class { pub(crate) fn register_window_class() -> *const Class {
@ -114,11 +432,39 @@ pub(crate) fn register_window_class_with_delegate<T: WindowDelegate>() -> *const
decl.add_ivar::<usize>(WINDOW_DELEGATE_PTR); decl.add_ivar::<usize>(WINDOW_DELEGATE_PTR);
// Subclassed methods
// NSWindowDelegate methods // NSWindowDelegate methods
decl.add_method(sel!(windowShouldClose:), should_close::<T> as extern fn(&Object, _, _) -> BOOL);
decl.add_method(sel!(windowWillClose:), will_close::<T> as extern fn(&Object, _, _)); decl.add_method(sel!(windowWillClose:), will_close::<T> as extern fn(&Object, _, _));
// Sizing
decl.add_method(sel!(windowWillResize:toSize:), will_resize::<T> as extern fn(&Object, _, _, CGSize) -> CGSize);
decl.add_method(sel!(windowDidResize:), did_resize::<T> as extern fn(&Object, _, _));
decl.add_method(sel!(windowWillStartLiveResize:), will_start_live_resize::<T> as extern fn(&Object, _, _));
decl.add_method(sel!(windowDidEndLiveResize:), did_end_live_resize::<T> as extern fn(&Object, _, _));
// Minimizing
decl.add_method(sel!(windowWillMiniaturize:), will_miniaturize::<T> as extern fn(&Object, _, _));
decl.add_method(sel!(windowDidMiniaturize:), did_miniaturize::<T> as extern fn(&Object, _, _));
decl.add_method(sel!(windowDidDeminiaturize:), did_deminiaturize::<T> as extern fn(&Object, _, _));
// Full Screen
decl.add_method(sel!(window:willUseFullScreenContentSize:), content_size_for_full_screen::<T> as extern fn(&Object, _, _, CGSize) -> CGSize);
decl.add_method(sel!(window:willUseFullScreenPresentationOptions:), options_for_full_screen::<T> as extern fn(&Object, _, _, NSUInteger) -> NSUInteger);
decl.add_method(sel!(windowWillEnterFullScreen:), will_enter_full_screen::<T> as extern fn(&Object, _, _));
decl.add_method(sel!(windowDidEnterFullScreen:), did_enter_full_screen::<T> as extern fn(&Object, _, _));
decl.add_method(sel!(windowWillExitFullScreen:), will_exit_full_screen::<T> as extern fn(&Object, _, _));
decl.add_method(sel!(windowDidExitFullScreen:), did_exit_full_screen::<T> as extern fn(&Object, _, _));
decl.add_method(sel!(windowDidFailToEnterFullScreen:), did_fail_to_enter_full_screen::<T> as extern fn(&Object, _, _));
decl.add_method(sel!(windowDidFailToExitFullScreen:), did_fail_to_exit_full_screen::<T> as extern fn(&Object, _, _));
// Key status
decl.add_method(sel!(windowDidBecomeKey:), did_become_key::<T> as extern fn(&Object, _, _));
decl.add_method(sel!(windowDidResignKey:), did_resign_key::<T> as extern fn(&Object, _, _));
// Main status
decl.add_method(sel!(windowDidBecomeMain:), did_become_main::<T> as extern fn(&Object, _, _));
decl.add_method(sel!(windowDidResignMain:), did_resign_main::<T> as extern fn(&Object, _, _));
// Moving Windows // Moving Windows
decl.add_method(sel!(windowWillMove:), will_move::<T> as extern fn(&Object, _, _)); decl.add_method(sel!(windowWillMove:), will_move::<T> as extern fn(&Object, _, _));
decl.add_method(sel!(windowDidMove:), did_move::<T> as extern fn(&Object, _, _)); decl.add_method(sel!(windowDidMove:), did_move::<T> as extern fn(&Object, _, _));
@ -126,6 +472,11 @@ pub(crate) fn register_window_class_with_delegate<T: WindowDelegate>() -> *const
decl.add_method(sel!(windowDidChangeScreenProfile:), did_change_screen_profile::<T> as extern fn(&Object, _, _)); decl.add_method(sel!(windowDidChangeScreenProfile:), did_change_screen_profile::<T> as extern fn(&Object, _, _));
decl.add_method(sel!(windowDidChangeBackingProperties:), did_change_backing_properties::<T> as extern fn(&Object, _, _)); decl.add_method(sel!(windowDidChangeBackingProperties:), did_change_backing_properties::<T> as extern fn(&Object, _, _));
// Random
decl.add_method(sel!(windowDidChangeOcclusionState:), did_change_occlusion_state::<T> as extern fn(&Object, _, _));
decl.add_method(sel!(windowDidExpose:), did_expose::<T> as extern fn(&Object, _, _));
decl.add_method(sel!(windowDidUpdate:), did_update::<T> as extern fn(&Object, _, _));
DELEGATE_CLASS = decl.register(); DELEGATE_CLASS = decl.register();
}); });

View file

@ -4,11 +4,13 @@
use std::rc::Rc; use std::rc::Rc;
use std::cell::RefCell; use std::cell::RefCell;
use core_graphics::geometry::{CGRect, CGSize};
use objc::{msg_send, sel, sel_impl}; use objc::{msg_send, sel, sel_impl};
use objc::runtime::Object; use objc::runtime::Object;
use objc_id::ShareId; use objc_id::ShareId;
use crate::foundation::{id, nil, YES, NO, NSString, NSUInteger, CGRect, CGSize}; use crate::foundation::{id, nil, YES, NO, NSString, NSUInteger};
use crate::layout::traits::Layout; use crate::layout::traits::Layout;
use crate::toolbar::{Toolbar, ToolbarController}; use crate::toolbar::{Toolbar, ToolbarController};
use crate::utils::Controller; use crate::utils::Controller;

View file

@ -2,6 +2,7 @@
//! module. There's a few different ones, and it's just... cleaner, if //! module. There's a few different ones, and it's just... cleaner, if
//! it's organized here. //! it's organized here.
use crate::app::enums::PresentationOption;
use crate::window::Window; use crate::window::Window;
/// Lifecycle events for anything that `impl Window`'s. These map to the standard Cocoa /// Lifecycle events for anything that `impl Window`'s. These map to the standard Cocoa
@ -14,6 +15,10 @@ pub trait WindowDelegate {
/// If you're coming from the web, you can think of this as `DOMContentLoaded`. /// If you're coming from the web, you can think of this as `DOMContentLoaded`.
fn did_load(&mut self, _window: Window) {} fn did_load(&mut self, _window: Window) {}
/// Called when the user has attempted to close the window. NOT called when a user quits the
/// application. Return false here if you need to handle the edge case.
fn should_close(&self) -> bool { true }
/// Fires when a window is going to close. You might opt to, say, clean up things here - /// Fires when a window is going to close. You might opt to, say, clean up things here -
/// perhaps you have a long running task, or something that should be removed. /// perhaps you have a long running task, or something that should be removed.
fn will_close(&self) {} fn will_close(&self) {}
@ -24,6 +29,23 @@ pub trait WindowDelegate {
/// Fired after the window has moved. /// Fired after the window has moved.
fn did_move(&self) {} fn did_move(&self) {}
/// Fired before the window resizes, passing you the width and height.
/// To avoid resizing, return the current size. To resize to a different size, return the
/// desired size.
///
/// The default implementation of this method returns `None`, indicating the system should just
/// do its thing. If you implement it, you probably want that.
fn will_resize(&self, width: f64, height: f64) -> (f64, f64) { (width, height) }
/// Fired after the window has resized.
fn did_resize(&self) {}
/// Fired when the window is going to live resize.
fn will_start_live_resize(&self) {}
/// Fired when the window has ended live resizing.
fn did_end_live_resize(&self) {}
/// Fired when the window changes screens - you might find this useful for certain scenarios, /// Fired when the window changes screens - you might find this useful for certain scenarios,
/// such as rendering in retina vs non-retina environments. /// such as rendering in retina vs non-retina environments.
fn did_change_screen(&self) {} fn did_change_screen(&self) {}
@ -57,21 +79,43 @@ pub trait WindowDelegate {
/// Fires when this window de-miniaturized (e.g, from the Dock). /// Fires when this window de-miniaturized (e.g, from the Dock).
fn did_deminiaturize(&self) {} fn did_deminiaturize(&self) {}
/// Fires when the system is moving a window to full screen and wants to know what content size
/// to use. By default, this just returns the system-provided content size, but you can
/// override it if need be.
fn content_size_for_full_screen(&self, proposed_width: f64, proposed_height: f64) -> (f64, f64) {
(proposed_width, proposed_height)
}
/// Specify options for when this window goes full screen.
/// By default, this returns `None`, which tells the system to proceed as it normally would
/// without customization.
fn presentation_options_for_full_screen(&self) -> Option<&[PresentationOption]> { None }
/// Fires when this window is about to go full screen. /// Fires when this window is about to go full screen.
fn will_enter_fullscreen(&self) {} fn will_enter_full_screen(&self) {}
/// Fires when this window entered full screen. /// Fires when this window entered full screen.
fn did_enter_fullscreen(&self) {} fn did_enter_full_screen(&self) {}
/// Fires when this window is about to exit full screen. /// Fires when this window is about to exit full screen.
fn will_exit_fullscreen(&self) {} fn will_exit_full_screen(&self) {}
/// Fires when this window exited full screen. /// Fires when this window exited full screen.
fn did_exit_fullscreen(&self) {} fn did_exit_full_screen(&self) {}
/// Fires when this window failed to enter full screen. /// Fires when this window failed to enter full screen.
fn did_fail_to_enter_fullscreen(&self) {} fn did_fail_to_enter_full_screen(&self) {}
/// Fires when this window failed to exit full screen. /// Fires when this window failed to exit full screen.
fn did_fail_to_exit_fullscreen(&self) {} fn did_fail_to_exit_full_screen(&self) {}
/// Fired when the occlusion state for this window has changed. Similar in nature to the
/// app-level event, just for a Window.
fn did_change_occlusion_state(&self) {}
/// Fired when the Window receives a `didExpose` message from higher up in the chain.
fn did_expose(&self) {}
/// Fired when the Window receives an `update` message from higher up in the chain.
fn did_update(&self) {}
} }

View file

@ -26,6 +26,19 @@ impl WindowDelegate for MyWindow {
fn will_close(&self) { fn will_close(&self) {
println!("Closing now!"); println!("Closing now!");
} }
fn will_move(&self) {
println!("Will move...");
}
fn did_move(&self) {
println!("Did move...");
}
fn will_resize(&self, width: f64, height: f64) -> (f64, f64) {
println!("Resizing to: {} {}", width, height);
(width, height)
}
} }
fn main() { fn main() {