CGEventTapCreate returns null in macOS Mojave - objective-c

I'm completely stuck with logic that's been working for many years now. I'm using this to listen to keyboard events (hotkeys) while the app is in background.
CFMachPortRef eventTap = CGEventTapCreate(kCGSessionEventTap,
kCGHeadInsertEventTap,
kCGEventTapOptionDefault,
CGEventMaskBit(kCGEventKeyDown) | CGEventMaskBit(kCGEventFlagsChanged),
myCGEventCallback,
nil);
if (!eventTap) {
printf("error: event tap register failed\n");
return false;
}
The code has not changed, and this has worked for a long time until the latest update to mojave. How can I go about troubleshooting the reason for this? Would anyone know how I can get this working again?

Got this working after some fighting. Add this to your info.plist:
<key>NSAppleEventsUsageDescription</key>
<string></string>
Then go to your system preferences -> security -> privacy -> accessibility, and ensure your app is there and checked.
If it's already there and this keeps happening, remove it and add it again. I have to do this every time I rebuild my app...

Related

addGlobalMonitorForEventsMatchingMask not working on some computers

I'm using this code to capture Global Keyboard Shortcuts in my app.
This works great on almost every computer I run it on. I tried it on a brand new Retina Macbook Pro this week and addGlobalMonitorForEventsMatchingMask doesn't work at all. It doesn't even log every key like I have it set up to do here for debugging.
Is there a more reliable way to do this? Right now I load this on applicationDidFinishLaunching.
I think it might make more sense to load it as its own method in the App Delegate but I'm not sure what the syntax of that would look like.
[NSEvent addGlobalMonitorForEventsMatchingMask:NSKeyDownMask handler:^(NSEvent *event){
NSLog(#"sequence = %li", (unsigned long)[event modifierFlags]);
// Activate app when pressing cmd-c
if([event modifierFlags] == 1048840 && [[event charactersIgnoringModifiers] compare:#"c"] == 0) {
In OSX 10.9 (Mavericks) the setting has moved to System Preferences > Security & Privacy > Privacy > Accessibility - make sure your app is checked.
check the "Enable access for assistive devies" in accessiblity in system prefrences and try again.

OSX: How to detect if Mission Control is running?

When Mission Control runs, it prevents applications from receiving keyboard and mouse events. It also leaves the last application running thinking that it still has focus. This is a problem for me because I don't receive keyUp or mouseUp events if I start Mission Control with a mouse button or a key held down and my application will behave as if that mouse button or key is held down.
I would like a way to either read both keyboard and mouse events even when Mission Control is active, or a way of detecting that Mission Control is active. Ideally, I would like to be able to do the latter since I effectively can't use my application when Mission Control is running.
I've tried a couple of things with no luck:
Use addGlobalMonitorForEventsMatchingMask to register a global monitor for keyboard and mouse events. This captures mouse events (but not keyboard events, although the documentation says keyDown events should be sent to the global monitor) when I switch to another application, but Mission Control doesn't seem to let events propagate to global monitors.
Check [[NSRunningApplication currentApplication] {isActive, ownsMenuBar}].
Apparently, my application is active even though it's not receiving events!
Check [NSApp keyWindow] != nil.
Apparently, one of my windows should be receiving key events. None of them are.
Check if Mission Control is one of the running applications returned by [NSWorkspace runningApplications]. Mission Control does not show up in this list when it's running.
Edit:
I've finally worked around this problem (albeit not in a very satisfactory way). For the mouse, it turns out that you can query the state of the pressed buttons with [NSEvent pressedMouseButtons]. I simply keep track of what I think the mouse state should be from NSLeftMouseDown and NSLeftMouseUp events and compare that to [NSEvent pressedMouseButtons] every so often to make sure that they're consistent. If they're not, then I know that something has hijacked my NSLeftMouseUp event and act accordingly.
For the keyboard, I could not find a way to query the keyboard state, so I couldn't do a similar workaround. I ended up disabling application switching using presentation options when keys are pressed.
At least in OS X 10.10, you can use this code to check if Mission Control is active or not:
func missionControlIsActive() -> Bool
{
var result: Bool = false
let windowInfosRef = CGWindowListCopyWindowInfo(CGWindowListOption(kCGWindowListOptionOnScreenOnly), CGWindowID(0)) // CGWindowID(0) is equal to kCGNullWindowID
let windowList: NSArray = windowInfosRef.takeRetainedValue() // We own the returned CFArrayRef
for entry in windowList
{
if (entry.objectForKey("kCGWindowOwnerName") as! String) == "Dock"
{
var bounds: NSDictionary = entry.objectForKey("kCGWindowBounds") as! NSDictionary
if (bounds.objectForKey("Y") as! NSNumber) == -1
{
result = true
}
}
}
return result
}
In a nutshell, the code checks if a specific window owned by the OS X Dock process is visible on the screen and if it is in a specific position. If both conditions are met, Mission Control will be active right now. Code will work in a sandboxed app and no privileges for assistive devices are required.
Did you try on bash level using NSTask? Something like ps -faxU <username> should list all running processes and then you could parse the output, or indeed you could use ps -faxU <username> | grep -i "mission control" (At the top of my head I am not sure how the process may be called, but sth like "mission control" seems legit). Not the most elegant solution maybe, but if nothing else works it may be worth it.
May be i'm missing something, but have you tried to use event taps instead of global monitoring?
It does appear that DTrace has some ability to see Mission Control being activated. Try running:
sudo fs_usage -filesys | grep Mission
from the command line and then launching the Mission Control app from the /Application folder.
You should see a lot of output related to Mission Control starting up. Unfortunately, this same output did not appear by using the keyboard short cut or swiping. Of course, using DTrace in production code is not something I would actually recommend.
C++ and Qt implementation works in latest OS X.
bool Window::missionControlIsActive() {
bool result = false;
CFArrayRef windows = CGWindowListCopyWindowInfo(kCGWindowListOptionOnScreenOnly+kCGWindowListExcludeDesktopElements, kCGNullWindowID);
for (int i = 0; i < CFArrayGetCount(windows) ; i++) {
auto cfMutableDictionaryRef_dict = (CFMutableDictionaryRef)CFArrayGetValueAtIndex( windows, i );
auto cfStringRef_name = (CFStringRef)CFDictionaryGetValue(cfMutableDictionaryRef_dict, kCGWindowName);
if (QString::fromCFString(cfStringRef_name) != u"") continue;
auto cfStringRef_ownerName = (CFStringRef)CFDictionaryGetValue(cfMutableDictionaryRef_dict, kCGWindowOwnerName);
if (QString::fromCFString(cfStringRef_ownerName) != u"Dock") continue;
auto cfDictRef_bounds = (CFDictionaryRef)CFDictionaryGetValue(cfMutableDictionaryRef_dict, kCGWindowBounds);
auto cfNumRef_bounds_Y = (CFNumberRef)CFDictionaryGetValue(cfDictRef_bounds, QString("Y").toCFString());
double num;
CFNumberGetValue(cfNumRef_bounds_Y, kCFNumberFloat64Type, &num);
if (num > 1.0 and num < 1000000) continue;
result = true;
break;
}
CFRelease(windows);
return result;
}

Testing internet connection on iPad app using ios5

I have been searching through the forum regarding how to check whether there is internet or not in my ipad app. I just created a simple webview project with other view controllers and I need to display a UIAlert message when the internet is not available. In my case it is displaying the message when I run the app. When I run the app with internet and then deactivate the internet, it does not show the UIAlert message, that is if I switch between the views, it does not any more show the no internet connection.
I have followed this way of implementation in my project: (sorry my mistake this is the link I followed) http://mozymac.com/forums/f54/how-check-if-there-internet-connection-iphone-os-devices-595/ [This is the new edited question]
Apart from that I went through some of the previous questions in Stackoverflow forum like for ex: How to check for an active Internet connection on iOS or OSX?
But everybody has their own version. If any one has a much more updated method for ios5, xcode 4.2.1 of how to accomplish this then would be helpful for me.
Thanks
Is there a reason why you want to check for internet connection before actually trying to load a request in the UIWebView?
Best practice is to just start loading, and use your UIWebViewDelegate/NURLConnectionDelegate to inspect the NSError to see what is wrong. In case of network failure you will receive an error with a domain equal to NSURLErrorDomain. The error code will indicate what the problem is, see the NSError codes enum.
And only after the first error start your reachability to see when the internet connection becomes available again. Or easier, just let the user retry.
Using the Reachability code will actually cause some overhead. It takes time to check if the internet is available, which you could just have used to set up the actual connection as well.
Example
Since you are using a UIWebView you should implement the following delegate method to be notified of errors.
- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error {
if (![[error domain] isEqualToString:NSURLErrorDomain]) {
// not a nsurl error, take other appropriate action
return;
}
NSInteger code = [error code];
// show appropriate error to user, based on code
}
In this delegate method you should do whatever is needed to achieve what you want. You could retry the request yourself, show a message to the user or start listening for reachability changes using the code from the Reachability example provided by Apple.
Apple has one, it's called Reachability. Here's the link to it.
http://developer.apple.com/library/ios/ipad/#samplecode/Reachability/Introduction/Intro.html
Best way to check internet connection is Reachibility application
link
Or else
+ (BOOL)isNetworkAvailable
{
CFNetDiagnosticRef diag;
diag = CFNetDiagnosticCreateWithURL (NULL, (CFURLRef)[NSURL URLWithString:#"www.apple.com"]);
CFNetDiagnosticStatus status;
status = CFNetDiagnosticCopyNetworkStatusPassively (diag, NULL);
CFRelease (diag);
if ( status == kCFNetDiagnosticConnectionUp )
{
//NSLog (#"Connection is up");
return YES;
} else {
NSLog (#"Connection is down");
return NO;
}
}

How to get the application terminated notification quickly cocoa

To get the application terminated notification I have something like the following
NSNotificationCenter* center = [[NSWorkspace sharedWorkspace] notificationCenter];
[center addObserver:self
selector:#selector(appTerminated:)
name:NSWorkspaceDidTerminateApplicationNotification
object:nil
];
- (void)appTerminated:(NSNotification *)note
{
NSLog(#"+ appTerminated");
}
actually my concern is when the firefox application quits/restarts,I need to update its database.When the firefox quits manually I can update with the help of appTerminated as firefox releasing its lock to the database.When it is running state,I am not able to update the database as firefox is locking it.when the firefox is restarted ,it is quitting and restarting too quickly so that I cannot update the database as it is in running stateI need to update database before it restarts.i.e.when the firefox is in quit state.
So,I need the notification just before firefox is going to quit.
Is any api availabe for this or please give some ideas.
Thanks in advance
I take it you have two applications, one that watches the other. Your concern seems to be that you don't want the watched app to start really doing anything until the watcher finishes its work.
You just need to communicate between the processes in this case. The watched application should wait until the watcher finishes its work. You can achieve this using a lock, or you could use NSDistributedNotification (or other IPC mechanism) to send messages from the watcher to the watched to let it know it may continue.
I prefer the locking mechanism since it behaves correctly if the watcher fails. The most correct place to put the lock would be on the database, since that's the resource you're trying to protect.
I would try something like that:
- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender
{
if (isMyDatabaseClosed) {
[self closeMyDatabaseAndQuit];
return NSTerminateLater;
} else {
return NSTerminateNow;
}
}
-(void)closeMyDatabaseAndQuit
{
/* close your database, etc...*/
[NSApp replyToApplicationShouldTerminate: YES];
}
The code is not tested, but you should get an idea.

Objective-c -> class method to main file query

Sorry to bug twice so quickly, but since people were so kind in their informative responces, I figured it couldnt hurt to ask another question.
The same program i tried to make it rather swanky and have a main screen which allows you to click on a button which leads to a limited options screen. This lets you switch the music on or off. Or at least it should do.
The music running code is in the main file (game.m), under the following:
//Music
[Settings setMusicEnabled:YES];
music = [SPSound soundWithContentsOfFile:#"music.caf"];
channel = [[music createChannel] retain];
channel.loop = YES;
channel.volume = 0.25;
if([Settings musicEnabled]){
[channel play];
}
I apologize for the strange format, but it is Sparrow framework. basically, the Settings file contains the class methods I am trying to use. If the methods cause YES, the music is on. If it is No, then the music is off.
settings.m
static BOOL isMusicEnabled;
#implementation Settings
+ (BOOL)musicEnabled
{
return isMusicEnabled;
}
+ (void)setMusicEnabled:(BOOL)value
{
isMusicEnabled = value;
NSLog(#"SME? %i", isMusicEnabled);
}
#end
Now, the options file is working and i tested that section. The program is reading that isMusicEnabled is getting a new value, thus musicEnabled is being altered as well, so there should be a change and the music should be switched off.
However, nothing happens. I have tried to use debugger, but I am not very good at it and I dont understand a lot of the information i am given. I do understand that the problem is sending the message from Settings file to the main/Game file.
I would appriciate anyone's help who could enlighten me as to how this could be solved.
I'm not familiar with Sparrow Framework, but let me make a guess anyway.
[channel play]; starts playing the music in background until the channel is asked to stop playing.
Changing the isMusicEnabled does not trigger any code to stop the currently playing music. When you change the value in Settings, you should inform the channel to stop (most probably by somehow accessing the channel and calling [channel stop].
There's another problem - isMusicEnabled is just a variable in memory, your program will not remember its state between restarts. And Settings are usually supposed to be remembered.
To summarize I see two problems: persisting settings between restarts first and informing about change of settings second. To remember settings I suggest you look into NSUserDefaults class. To inform the channel to stop playing you have couple of options - depending on you skills. Easiest is to simply access the channel variable from within the setMusicEnabled and call stop. Another option would be to use notifications, but for a beginner programmer that is more complicated (look for NSNotificationCenter if interested).