Monitoring Screensaver Events in OSX

后端 未结 3 1534
佛祖请我去吃肉
佛祖请我去吃肉 2021-02-02 16:45

I want to monitor screensaver and lockscreen events on an OSX box. As a first pass, I\'m fine with them just printing to the console.

Following the advice of another\'s

相关标签:
3条回答
  • 2021-02-02 17:15

    You've commented your problem already.

    while(1); // busy wait's bad, I know, but easy to implement
    

    The above is almost ALWAYS a bad idea.

    NSDistributedNotificationCenter actually requires a running main thread NSRunLoop to operate.

    http://developer.apple.com/library/ios/#documentation/cocoa/Conceptual/Notifications/Articles/NotificationCenters.html#//apple_ref/doc/uid/20000216-BAJGDAFC

    Creating and spinning a run loop from the main() of a command line application on OS X is a fairly simple thing to do. There are plenty of examples available with a quick search.

    0 讨论(0)
  • 2021-02-02 17:15

    It appears the strategy you're trying to use for this won't work, because the com.apple.screensaver.* notifications are no longer supported.
    In the replies to this equivalent question, it is mentioned that: 'for Snow Leopard the screenIsLocked and screenIsUnlocked notifications aren't available anymore.'
    You can register for screen sleeps, which of course is not the same but may be an acceptable alternative for you, by listening to the NSWorkspaceScreensDidSleepNotification notification, or to the computer going to sleep by listening to the NSWorkspaceWillSleepNotification. Sample code can be found on this forum.

    Sidenote: if you use nil for the name, you will receive lots of events:

    [center addObserver:self
               selector:@selector(receive:)
                   name:nil
                 object:nil
    ];
    

    If you do that, you will see that you're doing everything basically right, because you will receive all kind of events - but no screensaver ones.

    0 讨论(0)
  • 2021-02-02 17:32

    Edit: further testing showed that com.apple.screensaver.didlaunch is also available, the code here is tested on 10.6.8 and 10.8.4

    Your code will work if you remove [[NSRunLoop currentRunLoop] run]; and initialize ScreenSaverMonitor from a Cocoa application's applicationDidFinishLaunching: method. ( Just create a new Cocoa application project in XCode and add your code where appropriate ).

    ScreenSaverMonitor.h

    #import <Foundation/Foundation.h>
    
    @interface ScreenSaverMonitor : NSObject
    -(id) init;
    -(void) receive: (NSNotification*) notification;
    
    @end
    

    ScreenSaverMonitor.m

    #import "ScreenSaverMonitor.h"
    #import <Foundation/NSString.h>
    #import <Foundation/NSDistributedNotificationCenter.h>
    #import <Foundation/NSRunLoop.h>
    #import <stdio.h>
    
    @implementation ScreenSaverMonitor
    -(id) init {
        NSDistributedNotificationCenter * center
        = [NSDistributedNotificationCenter defaultCenter];
    
        [center addObserver: self
                   selector:    @selector(receive:)
                       name:        @"com.apple.screensaver.didlaunch"
                     object:      nil
         ];
    
        [center addObserver: self
                   selector:    @selector(receive:)
                       name:        @"com.apple.screensaver.didstart"
                     object:      nil
         ];
        [center addObserver: self
                   selector:    @selector(receive:)
                       name:        @"com.apple.screensaver.didstop"
                     object:      nil
         ];
        [center addObserver: self
                   selector:    @selector(receive:)
                       name:        @"com.apple.screenIsLocked"
                     object:      nil
         ];
        [center addObserver: self
                   selector:    @selector(receive:)
                       name:        @"com.apple.screenIsUnlocked"
                     object:      nil
         ];
        return self;
    }
    -(void) receive: (NSNotification*) notification {
        printf("%s\n", [[notification name] UTF8String] );
    }
    
    @end
    

    AppDelegate.h

    #import <Cocoa/Cocoa.h>
    #import "ScreenSaverMonitor.h"
    
    @interface AppDelegate : NSObject <NSApplicationDelegate>
    
    @property (assign) IBOutlet NSWindow *window;
    @property (retain) ScreenSaverMonitor *monitor;
    @end
    

    AppDelegate.m

    #import "AppDelegate.h"
    #import "ScreenSaverMonitor.h"
    
    @implementation AppDelegate
    @synthesize monitor;
    - (void)applicationDidFinishLaunching:(NSNotification *)aNotification
    {
        // Insert code here to initialize your application
        self.monitor = [[ScreenSaverMonitor alloc] init];
    
    }
    
    @end
    

    main.m

    #import <Cocoa/Cocoa.h>
    
    int main(int argc, char *argv[])
    {
        return NSApplicationMain(argc, (const char **)argv);
    }
    
    0 讨论(0)
提交回复
热议问题