1

When the power button is pressed I am presented with the following dialogue box, and this notification if dispatched:

__CFNotification 0x10011f410 {name = com.apple.logoutInitiated; object = 501}

enter image description here

Question: How can I listen for and act upon this event from a C++ application?

fyi:

I have managed to hack together an Objective C snippet which does this:

#import "AppDelegate.h"

@implementation AppDelegate

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
    // Insert code here to initialize your application

    @autoreleasepool
    {
        [[NSDistributedNotificationCenter defaultCenter]
         addObserverForName: nil
         object: nil
         queue: [NSOperationQueue mainQueue]
         usingBlock: ^(NSNotification *notification) {

             //The event notification we are looking for:
             //__CFNotification 0x10011f410 {name = com.apple.logoutInitiated; object = 501}

             NSString *event = notification.name;
             BOOL res = [event isEqualToString:@"com.apple.logoutInitiated"];
             if (res)
             {
                 printf("POWER BUTTON PRESSED");
             }
             else
             {
                 printf("IGNORE");
             }
         }];

        [[NSRunLoop mainRunLoop] run];
    }

}
davivid
  • 5,910
  • 11
  • 42
  • 71
  • Correct me if I'm wrong but I believe the above code does not *intercept* but simply *listens* for the notification. (Nuance being that "interception" allows you to hide the notification to other processes which might also be listening for it.) –  Oct 30 '13 at 17:02
  • Yes sorry no interception needed, just to listen and act upon such event. – davivid Oct 30 '13 at 17:10
  • Is your C++ code in a mac app or a command line utility? – trojanfoe Oct 30 '13 at 17:17
  • 1
    @trojanfoe, I fail to see how that changes anything. –  Oct 30 '13 at 17:23
  • @QwertyBob It doesn't, but I'm just trying to understand the restrictions that might apply to a possible solution. – trojanfoe Oct 30 '13 at 17:25
  • In this case it's a mac app. – davivid Oct 30 '13 at 17:35
  • Have you considered implementing the app using Objective-C++, which is as simple as renaming all `.m` files to `.mm`. You can freely use C++ from these files. – trojanfoe Oct 30 '13 at 19:49

3 Answers3

2

a simple c++ SCCE would look like:

#include <iostream>
#include <CoreFoundation/CoreFoundation.h>

void
myCallBack(CFNotificationCenterRef center,
           void *observer,
           CFStringRef name,
           const void *object,
           CFDictionaryRef userInfo) {
    std::cout << "Power Button Pressed" << std::endl;
}

int
main(int argc, const char * argv[])
{
    CFNotificationCenterRef distCenter;
    CFStringRef evtName = CFSTR("com.apple.logoutInitiated");
    distCenter = CFNotificationCenterGetDistributedCenter();
    if (NULL == distCenter)
        return 1;
    CFNotificationCenterAddObserver(distCenter, NULL, &myCallBack, evtName, NULL, CFNotificationSuspensionBehaviorDeliverImmediately);
    CFRunLoopRun();
    return 0;
}

and would be compiled using clang++ -framework CoreFoundation testfile.cpp.

How you hook it into your own application is another matter entirely.

Anya Shenanigans
  • 91,618
  • 3
  • 107
  • 122
0

Essentially, you want to access the underlying functionality that NSDistributedNotificationCenter wraps around.

Perhaps you should look at CFNotificationCenterRef and more specifically CFNotificationCenterGetDistributedCenter().

These aren't C++ per se, they're C functions, but you can call them from C++.

0

The CoreFoundation has a nice API written in C, therefore you can use the CFNotificationCenterAddObserver function and link your C++ program to the necessary framework. Example:

clang++ <your options> -framework CoreFoundation

See the official documentation. A quick search here revealed an example of how to use it.

Community
  • 1
  • 1
jweyrich
  • 31,198
  • 5
  • 66
  • 97