summary history branches tags files
commit:1fd25ec65ce6647ffdd0a9e17b6844c53a2a82af
author:Trevor Bentley
committer:Trevor Bentley
date:Fri Jul 7 16:33:03 2017 +0200
parents:65add39963793ed5f9c226dab9445df202866127
Start wrapping Touchbar in a Rust struct
diff --git a/src/osx/mod.rs b/src/osx/mod.rs
line changes: +14/-21
index cfe6eb1..1d544e1
--- a/src/osx/mod.rs
+++ b/src/osx/mod.rs
@@ -1,12 +1,17 @@
-pub mod rustnsobject;
+mod rustnsobject;
 
 #[cfg(feature = "mac_touchbar")]
 mod touchbar;
-// TODO: Wrap the Objc class in a Rust struct
 #[cfg(feature = "mac_touchbar")]
-use self::touchbar::ObjcAppDelegate;
-#[cfg(feature = "mac_touchbar")]
-use self::objc_foundation::INSObject;
+use self::touchbar::{Touchbar, TouchbarTrait};
+#[cfg(not(feature = "mac_touchbar"))]
+struct Touchbar {}
+#[cfg(not(feature = "mac_touchbar"))]
+impl Touchbar {
+    fn alloc() -> Touchbar { Touchbar {} }
+    fn set_icon(&self, _: *mut Object) {}
+    fn enable(&self) {}
+}
 
 extern crate objc;
 extern crate objc_foundation;
@@ -51,6 +56,7 @@ pub struct OSXStatusBar {
     app: *mut objc::runtime::Object,
     status_bar_item: *mut objc::runtime::Object,
     menu_bar: *mut objc::runtime::Object,
+    touchbar: Touchbar,
 
     // Run loop state
     // Keeping these in persistent state instead of recalculating saves quite a
@@ -61,24 +67,12 @@ pub struct OSXStatusBar {
     run_date: *mut objc::runtime::Object,
 }
 
-#[cfg(feature = "mac_touchbar")]
-fn create_touchbar_delegate(app: *mut Object) -> Id<ObjcAppDelegate, objc_id::Shared> {
-    unsafe {
-        info!("MacOS Touch Bar support enabled.  Initializing.");
-        let delegate = touchbar::ObjcAppDelegate::new().share();
-        msg_send![app, setDelegate:delegate.clone()];
-        delegate
-    }
-}
-
 impl TStatusBar for OSXStatusBar {
     type S = OSXStatusBar;
     fn new(tx: Sender<String>) -> OSXStatusBar {
         let mut bar;
         unsafe {
             let app = NSApp();
-            #[cfg(feature = "mac_touchbar")]
-            let delegate = create_touchbar_delegate(app);
             let status_bar = NSStatusBar::systemStatusBar(nil);
             let date_cls = Class::get("NSDate").unwrap();
             bar = OSXStatusBar {
@@ -86,6 +80,7 @@ impl TStatusBar for OSXStatusBar {
                 status_bar_item: status_bar.statusItemWithLength_(NSVariableStatusItemLength),
                 menu_bar: NSMenu::new(nil),
                 object: NSObj::alloc(tx).setup(),
+                touchbar: Touchbar::alloc(),
                 pool: Cell::new(nil),
                 run_count: Cell::new(0),
                 run_mode: NSString::alloc(nil).init_str("kCFRunLoopDefaultMode"),
@@ -119,8 +114,7 @@ impl TStatusBar for OSXStatusBar {
             #[cfg(feature = "mac_white_icon")]
             let _ = msg_send![icon, setTemplate: YES]; // enable to make icon white
             bar.status_bar_item.button().setImage_(icon);
-            #[cfg(feature = "mac_touchbar")]
-            msg_send![delegate, setIcon: icon]; // let touchbar use the same
+            bar.touchbar.set_icon(icon);
             let _ = msg_send![img, release];
             let _ = msg_send![icon, release];
 
@@ -142,8 +136,7 @@ impl TStatusBar for OSXStatusBar {
                 }
             ));
             let _: () = msg_send![app, finishLaunching];
-            #[cfg(feature = "mac_touchbar")]
-            let _: () = msg_send![delegate, applicationDidFinishLaunching: 0];
+            bar.touchbar.enable()
         }
         bar
     }

diff --git a/src/osx/rustnsobject.rs b/src/osx/rustnsobject.rs
line changes: +0/-2
index a574936..4f39bd3
--- a/src/osx/rustnsobject.rs
+++ b/src/osx/rustnsobject.rs
@@ -90,8 +90,6 @@ impl NSObjTrait for NSObj {
     }
 }
 
-pub type NSObjCallback<T> = Box<Fn(&mut T, u64)>;
-
 impl NSObjCallbackTrait for NSObj {
     fn set_value(&mut self, key: u64, val: NSCallback) {
         self.map.insert(key, val);

diff --git a/src/osx/touchbar.rs b/src/osx/touchbar.rs
line changes: +46/-9
index 17f4803..56b20ff
--- a/src/osx/touchbar.rs
+++ b/src/osx/touchbar.rs
@@ -17,9 +17,9 @@ use objc::runtime::{Class, Object, Sel};
 use self::objc_foundation::{INSObject, NSObject, INSArray, NSArray, INSString};
 use self::cocoa::base::{nil, YES};
 use self::cocoa::foundation::NSString;
-
-//use self::objc_id::Id;
-//use self::objc_id::Shared;
+use self::cocoa::appkit::NSApp;
+use self::objc_id::Id;
+use self::objc_id::Shared;
 
 #[link(name = "DFRFoundation", kind = "framework")]
 extern {
@@ -27,16 +27,46 @@ extern {
     pub fn DFRElementSetControlStripPresenceForIdentifier(n: *mut Object, x: i8);
 }
 
-//pub struct RustTouchbarDelegate {
-//    pub objc: Id<ObjcAppDelegate, Shared>,
-//}
-//
-//impl RustTouchbarDelegate {
+pub struct RustTouchbarDelegateWrapper {
+    objc: Id<ObjcAppDelegate, Shared>,
+}
+
+pub type Touchbar = Box<RustTouchbarDelegateWrapper>;
+
+pub trait TouchbarTrait {
+    fn alloc() -> Touchbar;
+    fn set_icon(&self, icon: *mut Object);
+    fn enable(&self);
+}
+
+impl TouchbarTrait for Touchbar {
+    fn alloc() -> Touchbar {
+        let objc = ObjcAppDelegate::new().share();
+        let rust = Box::new(RustTouchbarDelegateWrapper {
+            objc: objc.clone(),
+        });
+        unsafe {
+            let ptr: u64 = &*rust as *const RustTouchbarDelegateWrapper as u64;
+            let _ = msg_send![rust.objc, setRustWrapper: ptr];
+        }
+        return rust
+    }
+    fn set_icon(&self, icon: *mut Object) {
+        unsafe { let _:() = msg_send![self.objc, setIcon: icon]; }
+    }
+    fn enable(&self) {
+        unsafe {
+            let app = NSApp();
+            let _: () = msg_send![app, setDelegate: objc];
+            let _: () = msg_send![self.objc, applicationDidFinishLaunching: 0];
+        }
+    }
+
 //    pub fn add_button() {}
 //    pub fn add_quit_button() {}
 //    pub fn add_label() {}
 //    pub fn add_slider() {}
-//}
+}
 
 pub enum ObjcAppDelegate {}
 impl ObjcAppDelegate {}
@@ -50,10 +80,14 @@ impl INSObject for ObjcAppDelegate {
         OBJC_SUBCLASS_REGISTER_CLASS.call_once(|| {
             let superclass = NSObject::class();
             let mut decl = ClassDecl::new("ObjcAppDelegate", superclass).unwrap();
+            decl.add_ivar::<u64>("_rust_wrapper");
             decl.add_ivar::<u64>("_groupbar");
             decl.add_ivar::<u64>("_groupId");
             decl.add_ivar::<u64>("_icon");
 
+            extern fn objc_set_rust_wrapper(this: &mut Object, _cmd: Sel, ptr: u64) {
+                unsafe {this.set_ivar("_rust_wrapper", ptr);}
+            }
             extern fn objc_group_touch_bar(this: &mut Object, _cmd: Sel) -> u64 {
                 unsafe {*this.get_ivar("_groupbar")}
             }
@@ -204,6 +238,9 @@ impl INSObject for ObjcAppDelegate {
 
                 let f: extern fn(&mut Object, Sel, u64) = objc_set_icon;
                 decl.add_method(sel!(setIcon:), f);
+
+                let f: extern fn(&mut Object, Sel, u64) = objc_set_rust_wrapper;
+                decl.add_method(sel!(setRustWrapper:), f);
             }
 
             decl.register();