2013-06-05 33 views
12

Tôi muốn theo dõi bảo vệ màn hình và các sự kiện trên màn hình khóa trên hộp OSX. Như một lần đầu tiên, tôi tốt với họ chỉ in đến bàn điều khiển.Giám sát Trình bảo vệ màn hình Sự kiện trong OSX

Sau the advice of another's question, tôi đã viết một số C Mục tiêu để nghe cho Cocoa Notifications cho com.apple.screensaver.didstart, com.apple.screensaver.didstop, com.apple.screenIsLocked, và com.apple.screenIsUnlocked sự kiện.

// ScreenSaverMonitor.h 
#import <Foundation/NSObject.h> 
#import <Foundation/NSNotification.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.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 
    ]; 
    printf("running loop... (^C to quit)"); 
    [[NSRunLoop currentRunLoop] run]; 
    printf("...ending loop"); 
    return self; 
} 
-(void) receive: (NSNotification*) notification { 
    printf("%s\n", [[notification name] UTF8String]); 
} 
@end 

// ScreenSaverMonitorMain.m 
#import "ScreenSaverMonitor.h" 

int main(int argc, char ** argv) { 
    [[ScreenSaverMonitor alloc] init]; 
    return 0; 
} 

Nó biên dịch tốt, nhưng khi tôi chạy nó, tôi dường như không quan sát bất kỳ sự kiện bảo vệ màn hình (mặc dù có bảo vệ màn hình đến trên nhiều lần):

% gcc -Wall ScreenSaverMonitor.m ScreenSaverMonitorMain.m -o ScreenSaverMonitor -lobjc -framework Cocoa 
% ./ScreenSaverMonitor 
running loop (^C to quit)... 
^C 
% 

C Mục tiêu của tôi và Cocoa kiến thức là rất gỉ, vì vậy tôi không chắc chắn nếu tôi đang sử dụng khuôn khổ sai, hoặc nếu tôi đã đăng ký cho các sự kiện sai (cũng không phải nơi để xem xét để tìm ra cho dù đó là những sự kiện đúng hay không).

Vì vậy, tôi đang làm gì sai?

Trả lời

9

Bạn đã nhận xét sự cố của mình rồi.

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

Ở trên gần như luôn luôn là một ý tưởng tồi.

NSDistributedNotificationCenter thực sự yêu cầu chủ đề chính đang chạy NSRunLoop hoạt động.

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

Tạo và quay một vòng lặp chạy từ main() của một ứng dụng dòng lệnh trên OS X là một điều khá đơn giản để làm. Có rất nhiều ví dụ có sẵn với tìm kiếm nhanh.

+0

Ý tưởng hay! Tôi thay thế 'while (1);' với '[[NSRunLoop currentRunLoop] chạy];', nhưng vẫn không có con xúc xắc. – rampion

+0

Tôi không chắc chắn những gì bạn đang chạy vào đây. Tôi đã lấy mã đã chỉnh sửa của bạn ở trên, đã sửa lỗi trình biên dịch và thực hiện thay đổi nhật ký nhỏ và có vẻ như nó hoạt động tốt cho tôi. Cụ thể, tôi đã thay đổi dòng #import thành #import và thay đổi các lệnh printf thành fprintf thành stderr. (Điều này hoạt động tốt hơn khi stderr được flushed ngay lập tức thay vì buffered như printf là. – GoannaGuy

+2

Thực ra, phiên bản tinh chỉnh của tôi, mà tôi hợp nhất thành một tệp nguồn duy nhất, có sẵn ở đây: http://pastie.org/8013106 Nó bao gồm một bản sửa đổi lệnh ở phía dưới mà xây dựng một chút nhanh hơn, kể từ khi nó liên kết với Foundation.framework thay vì Cocoa.framework lớn hơn (nhưng hoặc là nên làm việc tốt) – GoannaGuy

2

Dường như chiến lược bạn đang cố gắng sử dụng cho điều này sẽ không hoạt động vì thông báo com.apple.screensaver. * Không còn được hỗ trợ nữa.
Trong thư trả lời cho this equivalent question, có đề cập rằng: 'đối với Snow Leopard, màn hìnhĐược khóa và màn hìnhKhông có thông báo đã khóa không còn khả dụng'.
Bạn có thể đăng ký các chế độ ngủ màn hình, tất nhiên là không giống nhau nhưng có thể là lựa chọn phù hợp cho bạn, bằng cách nghe thông báo NSWorkspaceScreensDidSleepNotification hoặc máy tính chuyển sang ngủ bằng cách nghe NSWorkspaceWillSleepNotification. Mã mẫu có thể được tìm thấy on this forum.

Phụ chú: nếu bạn sử dụng con số không cho tên, bạn sẽ nhận được rất nhiều sự kiện:

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

Nếu bạn làm điều đó, bạn sẽ thấy rằng bạn đang làm tất cả mọi thứ về cơ bản đúng, bởi vì bạn sẽ nhận được tất cả loại sự kiện - nhưng không có trình bảo vệ màn hình.

+1

Kể từ 10.10, thông báo com.apple.screensaver. * Vẫn được gửi (như screenIsLocked/screenIsUnlocked). Ngoài ra, 'NSDistributedNotificationCenter' sẽ không cho phép bạn đăng ký tất cả các thông báo, ít nhất là trong một ứng dụng hộp cát. Bạn nhận được cảnh báo, "*** cố gắng đăng ký tất cả các thông báo được phân phối bị cản trở bởi hộp cát". – zpasternack

5

Edit: tiếp tục thử nghiệm cho thấy com.apple.screensaver.didlaunch cũng có sẵn, mã ở đây được thử nghiệm trên 10.6.8 và 10.8.4

Mã của bạn sẽ làm việc nếu bạn loại bỏ [[NSRunLoop currentRunLoop] run]; và khởi ScreenSaverMonitor từ phương pháp applicationDidFinishLaunching: một ứng dụng Cocoa của . (Chỉ cần tạo một dự án ứng dụng Cocoa mới trong XCode và thêm mã của bạn nếu thích hợp).

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); 
} 
Các vấn đề liên quan