Bring back dependency on core-graphics because, well, I'm apparently a moron. Further sketching out of WindowDelegate.
This commit is contained in:
parent
b0232ca225
commit
d512b7bcf5
|
@ -10,6 +10,7 @@ path = "lib.rs"
|
|||
|
||||
[dependencies]
|
||||
block = "0.1.6"
|
||||
core-graphics = "0.19.0"
|
||||
dispatch = "0.2.0"
|
||||
libc = "0.2"
|
||||
objc = "0.2.7"
|
||||
|
|
|
@ -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 app’s "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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
//! Implements `Color`. Heavily based on the `Color` module in Servo's CSS parser, but tweaked
|
||||
//! for (what I believe) is a friendlier API.
|
||||
|
||||
use core_graphics::base::CGFloat;
|
||||
|
||||
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.
|
||||
#[derive(Clone, Copy, PartialEq, Debug)]
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
}
|
|
@ -26,9 +26,6 @@ pub use string::NSString;
|
|||
pub mod dictionary;
|
||||
pub use dictionary::NSDictionary;
|
||||
|
||||
pub mod geometry;
|
||||
pub use geometry::{CGSize, CGPoint, CGRect};
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
pub type id = *mut runtime::Object;
|
||||
|
||||
|
@ -44,8 +41,3 @@ pub type NSUInteger = libc::c_uint;
|
|||
pub type NSInteger = libc::c_long;
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
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;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
//! 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.
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
|
|
|
@ -2,11 +2,13 @@
|
|||
//! escape hatch, if you need it (we use it for things like width and height, which aren't handled
|
||||
//! by an axis).
|
||||
|
||||
use core_graphics::base::CGFloat;
|
||||
|
||||
use objc::{class, msg_send, sel, sel_impl};
|
||||
use objc::runtime::Object;
|
||||
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
|
||||
/// constraints, as well as a wrapper for layout constraints that are not axis bound (e.g, width or
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
//! A wrapper for `NSLayoutAnchorDimension`, which is typically used to handle `width` and `height`
|
||||
//! values for how a given view should layout.
|
||||
|
||||
use core_graphics::base::CGFloat;
|
||||
|
||||
use objc::{msg_send, sel, sel_impl};
|
||||
use objc::runtime::Object;
|
||||
use objc_id::ShareId;
|
||||
|
||||
use crate::foundation::{id, CGFloat};
|
||||
use crate::foundation::id;
|
||||
use crate::layout::constraint::LayoutConstraint;
|
||||
|
||||
/// A wrapper for `NSLayoutAnchor`. You should never be creating this yourself - it's more of a
|
||||
|
|
|
@ -3,11 +3,13 @@
|
|||
//!
|
||||
//! UNFORTUNATELY, this is a very old and janky API. So... yeah.
|
||||
|
||||
use core_graphics::geometry::CGSize;
|
||||
|
||||
use objc_id::Id;
|
||||
use objc::runtime::Object;
|
||||
use objc::{class, msg_send, sel, sel_impl};
|
||||
|
||||
use crate::foundation::{id, CGSize, NSString};
|
||||
use crate::foundation::{id, NSString};
|
||||
use crate::button::Button;
|
||||
|
||||
/// A wrapper for `NSWindow`. Holds (retains) pointers for the Objective-C runtime
|
||||
|
|
|
@ -5,6 +5,9 @@
|
|||
use std::rc::Rc;
|
||||
use std::cell::RefCell;
|
||||
|
||||
use core_graphics::base::CGFloat;
|
||||
|
||||
use objc::{Encode, Encoding};
|
||||
use objc::runtime::Object;
|
||||
use objc_id::ShareId;
|
||||
|
||||
|
@ -24,3 +27,22 @@ pub fn load<T>(this: &Object, ptr: &str) -> Rc<RefCell<T>> {
|
|||
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) }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,14 +4,34 @@
|
|||
use std::rc::Rc;
|
||||
use std::sync::Once;
|
||||
|
||||
use core_graphics::base::CGFloat;
|
||||
|
||||
use objc::declare::ClassDecl;
|
||||
use objc::runtime::{Class, Object, Sel};
|
||||
use objc::{class, sel, sel_impl};
|
||||
|
||||
use crate::foundation::id;
|
||||
use crate::utils::load;
|
||||
use crate::foundation::{id, BOOL, YES, NO, NSUInteger};
|
||||
use crate::utils::{load, CGSize};
|
||||
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.
|
||||
/// Good place to clean up memory and what not.
|
||||
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);
|
||||
}
|
||||
|
||||
/// 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.
|
||||
extern fn did_change_backing_properties<T: WindowDelegate>(this: &Object, _: Sel, _: id) {
|
||||
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);
|
||||
}
|
||||
|
||||
/// 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
|
||||
/// need to do.
|
||||
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);
|
||||
|
||||
// Subclassed 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, _, _));
|
||||
|
||||
// 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
|
||||
decl.add_method(sel!(windowWillMove:), will_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!(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();
|
||||
});
|
||||
|
||||
|
|
|
@ -4,11 +4,13 @@
|
|||
use std::rc::Rc;
|
||||
use std::cell::RefCell;
|
||||
|
||||
use core_graphics::geometry::{CGRect, CGSize};
|
||||
|
||||
use objc::{msg_send, sel, sel_impl};
|
||||
use objc::runtime::Object;
|
||||
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::toolbar::{Toolbar, ToolbarController};
|
||||
use crate::utils::Controller;
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
//! module. There's a few different ones, and it's just... cleaner, if
|
||||
//! it's organized here.
|
||||
|
||||
use crate::app::enums::PresentationOption;
|
||||
use crate::window::Window;
|
||||
|
||||
/// 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`.
|
||||
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 -
|
||||
/// perhaps you have a long running task, or something that should be removed.
|
||||
fn will_close(&self) {}
|
||||
|
@ -24,6 +29,23 @@ pub trait WindowDelegate {
|
|||
/// Fired after the window has moved.
|
||||
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,
|
||||
/// such as rendering in retina vs non-retina environments.
|
||||
fn did_change_screen(&self) {}
|
||||
|
@ -57,21 +79,43 @@ pub trait WindowDelegate {
|
|||
/// Fires when this window de-miniaturized (e.g, from the Dock).
|
||||
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.
|
||||
fn will_enter_fullscreen(&self) {}
|
||||
fn will_enter_full_screen(&self) {}
|
||||
|
||||
/// 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.
|
||||
fn will_exit_fullscreen(&self) {}
|
||||
fn will_exit_full_screen(&self) {}
|
||||
|
||||
/// 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.
|
||||
fn did_fail_to_enter_fullscreen(&self) {}
|
||||
fn did_fail_to_enter_full_screen(&self) {}
|
||||
|
||||
/// 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) {}
|
||||
}
|
||||
|
|
|
@ -26,6 +26,19 @@ impl WindowDelegate for MyWindow {
|
|||
fn will_close(&self) {
|
||||
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() {
|
||||
|
|
Loading…
Reference in a new issue