Skip to content
This repository has been archived by the owner on Mar 25, 2023. It is now read-only.

Mac ctypes - very nice work! #40

Closed
Noitidart opened this issue Dec 15, 2014 · 7 comments
Closed

Mac ctypes - very nice work! #40

Noitidart opened this issue Dec 15, 2014 · 7 comments

Comments

@Noitidart
Copy link

Your mac ctypes of objective c is so awesome. I've been struggling a lot with it. I couldn't find any open source examples of it but finally found your repo, its excellent and I can learn a TON from it!! :) Thanks for it!

Just trying my luck here: Would you have time to chat about objc ctypes? I'm trying to get setApplicationIcon: https://bugzilla.mozilla.org/show_bug.cgi?id=1108246#c2

@Noitidart Noitidart changed the title Mac ctypes so awesome Mac ctypes - very nice work! Dec 15, 2014
@mkiol
Copy link
Owner

mkiol commented Dec 15, 2014

I glad you find ctypes awesome :-) True that, they are quite useful and powerful tool.

Regarding objective c, the code is not mine. Everything was done by @kennydude. He is the author of all "OSX branch", so probably he will be the most appropriate person to ask about details.

@Noitidart
Copy link
Author

Thanks @mkiol for your fast reply!

I had a blast with ctypes I got it working in windows and linux's (Noitidart/Profilist#18 (comment)) but mac drives me nuts haha!

@Noitidart
Copy link
Author

@kennydude

Im working on the setApplicationIcon thing for my addon.

And im trying to help this user on stackoverflow: http://stackoverflow.com/questions/27377686/firefox-extension-addon-detect-workspace-locked

So I'm trying to convert this:

http://mxr.mozilla.org/chromium/source/src/chrome/browser/idle_mac.mm#28

28 - (id)init {
29   if ((self = [super init])) {
30     NSDistributedNotificationCenter* distCenter =
31           [NSDistributedNotificationCenter defaultCenter];
32     [distCenter addObserver:self
33                    selector:@selector(onScreenSaverStarted:)
34                        name:@"com.apple.screensaver.didstart"
35                      object:nil];
36     [distCenter addObserver:self
37                    selector:@selector(onScreenSaverStopped:)
38                        name:@"com.apple.screensaver.didstop"
39                      object:nil];
40     [distCenter addObserver:self
41                    selector:@selector(onScreenLocked:)
42                        name:@"com.apple.screenIsLocked"
43                      object:nil];
44     [distCenter addObserver:self
45                    selector:@selector(onScreenUnlocked:)
46                        name:@"com.apple.screenIsUnlocked"
47                      object:nil];
48   }
49   return self;
50 }

So far I got this:

Cu.import("resource://gre/modules/ctypes.jsm");

let objc = ctypes.open(ctypes.libraryName("objc"));

let id = ctypes.voidptr_t;
let SEL = ctypes.voidptr_t;

let objc_getClass = objc.declare("objc_getClass",
                                 ctypes.default_abi,
                                 id,
                                 ctypes.char.ptr);

let sel_registerName = objc.declare("sel_registerName",
                                    ctypes.default_abi,
                                    SEL,
                                    ctypes.char.ptr);

let objc_msgSend = objc.declare("objc_msgSend",
                                ctypes.default_abi,
                                id,
                                id,
                                SEL,
                                "...");

let NSDistributedNotificationCenter = objc_getClass("NSDistributedNotificationCenter");
let defaultCenter = sel_registerName("defaultCenter");
let nC = objc_msgSend(NSDistributedNotificationCenter, defaultCenter);

let addObserver = sel_registerName("addObserver:selector:name:object:");
let removeObserver = sel_registerName("removeObserver:name:object:");

lol please help me help this guy on stackvoerflow i think ill learn a lot in the process :D

https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSDistributedNotificationCenter_Class/index.html

@Noitidart
Copy link
Author

I got it! It works! Long live open source! Thanks for it @mkiol and @kennydude . But I'm not sure if the code is absolutely correct. @kennydude may you please review this code of mine here. It does addObserver of a callback to trigger when the screensaver turns on:

For instance I'm not sure if I'm not sure which is the right spot for me to execute objc_msgSend(pool, release); after I finish alloc and init of delegateInstance_onScreenSaverStarted. Is it ok to run right after the msgSend? Or maybe shutdown when I call removeObserver? Or after I do addObserver?

Thanks, can copy this code paste to scratchpad and run it will add the observer, then wait till screensaver triggers, then move mouse and u'll see the msg in browser console. To remove observer, blank the same scratchpad you ran the code from and type removeObsAndClose() then run.

Cu.import('resource://gre/modules/ctypes.jsm');
var objc = ctypes.open(ctypes.libraryName('objc'));

// types
var id = ctypes.voidptr_t;
var objc_selector = new ctypes.StructType('objc_selector');
var SEL = objc_selector.ptr;
var BOOL = ctypes.signed_char;
var IMP = ctypes.voidptr_t;

// contstants
var nil = ctypes.voidptr_t(0);

// common functions
var objc_getClass = objc.declare('objc_getClass', ctypes.default_abi, id, ctypes.char.ptr);
var sel_registerName = objc.declare('sel_registerName', ctypes.default_abi, SEL, ctypes.char.ptr);
var objc_msgSend = objc.declare('objc_msgSend', ctypes.default_abi, id, id, SEL, '...');

// common selectors
var alloc = sel_registerName('alloc');
var init = sel_registerName('init');
var release = sel_registerName('release');

// notificationName_**** = [[NSString alloc] initWithUTF8String: 'com.apple.****'];
var NSString = objc_getClass('NSString');
var initWithUTF8String = sel_registerName('initWithUTF8String:');

// NSDistCent = [NSDistributedNotificationCenter defaultCenter];
var NSDistributedNotificationCenter = objc_getClass('NSDistributedNotificationCenter');
var defaultCenter = sel_registerName('defaultCenter');
var NSDistCent = objc_msgSend(NSDistributedNotificationCenter, defaultCenter);

//create notificationObserver's
var notificationSelector_onScreenSaverStarted = sel_registerName('onScreenSaverStarted:');
var notificationName_onScreenSaverStarted = objc_msgSend(objc_msgSend(NSString, alloc), initWithUTF8String, ctypes.char.array()('com.apple.screensaver.didstart'));

// NSAutoPool = [[NSAutoreleasePool alloc] init]
var NSAutoreleasePool = objc_getClass('NSAutoreleasePool');
var pool = objc_msgSend(objc_msgSend(NSAutoreleasePool, alloc), init);

var objc_allocateClassPair = objc.declare('objc_allocateClassPair', ctypes.default_abi, id, id, ctypes.char.ptr, ctypes.size_t);

var NSObject = objc_getClass('NSObject');
var delegate_onScreenSaverStarted = objc_allocateClassPair(NSObject, 'onScreenSaverStarted', 0);

var class_addMethod = objc.declare('class_addMethod', ctypes.default_abi, BOOL, id, SEL, IMP, ctypes.char.ptr);
//
var ftype_onScreenSaverStarted = ctypes.FunctionType(ctypes.default_abi, ctypes.void_t, [])

function jsCallback_onScreenSaverStarted(self, sel) {
    console.log('TRIGGERD: onScreenSaverStarted');
}

var callback_onScreenSaverStarted = ftype_onScreenSaverStarted.ptr(jsCallback_onScreenSaverStarted);
//
var rez_class_addMethod = class_addMethod(delegate_onScreenSaverStarted, notificationSelector_onScreenSaverStarted, callback_onScreenSaverStarted, 'onScreenSaverStarted:');
console.info('rez_class_addMethod:', rez_class_addMethod, rez_class_addMethod.toString(), uneval(rez_class_addMethod));

var objc_registerClassPair = objc.declare('objc_registerClassPair', ctypes.default_abi, id, id);
objc_registerClassPair(delegate_onScreenSaverStarted);

var delegateInstance_onScreenSaverStarted = objc_msgSend(objc_msgSend(delegate_onScreenSaverStarted, alloc), init);

objc_msgSend(pool, release); //maybe don't release pool yet?
//end - onScreenSaverStarted

// [NSDistCent addObserver:selector:name:object: ***, ***, notificationName_****, nil] // copied block: `// [NSApp setApplicationIconImage: icon]`
var addObserver = sel_registerName('addObserver:selector:name:object:')
var rez_addObserver = objc_msgSend(NSDistCent, addObserver, delegateInstance_onScreenSaverStarted, notificationSelector_onScreenSaverStarted, notificationName_onScreenSaverStarted, nil); // addObserver returns void so no need for `var rez_addObserver = `

function removeObsAndClose() {
  // [NSDistCent removeObserver:name:object: notificationName_****, nil] // copied block: `// [NSApp setApplicationIconImage: icon]`
  var removeObserver = sel_registerName('removeObserver:name:object:')
  var rez_removeObserver = objc_msgSend(NSDistCent, removeObserver, delegateInstance_onScreenSaverStarted, notificationName_onScreenSaverStarted, nil); // removeObserver returns void


  // [notificationName_**** release]
  objc_msgSend(notificationName_onScreenSaverStarted, release);

  objc.close();
}

@Noitidart
Copy link
Author

Thanks very much @mkiol for leaving this open. Closing stuff hurts feelings haha but I understand. Please close this whenever you wish. :)

@mkiol
Copy link
Owner

mkiol commented Feb 4, 2015

so, please, don't take this personal.. I'm closing this issue :-)

@mkiol mkiol closed this as completed Feb 4, 2015
@Noitidart
Copy link
Author

haha thanks man you're real nice guy :D thanks also for trying to get kenny's attention to my topic :)

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants