How to identify window under mouse with Objective-C? - objective-c

I have the following code:
id eventHandler = [NSEvent addGlobalMonitorForEventsMatchingMask:NSMouseMovedMask handler:^(NSEvent * event) {
CGWindowID windowID = (CGWindowID)[event windowNumber];
CFArrayRef a = CFArrayCreate(NULL, (void *)&windowID, 1, NULL);
NSArray *windowInfos = (__bridge NSArray *)CGWindowListCreateDescriptionFromArray(a);
CFRelease(a);
if ([windowInfos count] > 0) {
NSDictionary *windowInfo = [windowInfos objectAtIndex:0];
NSLog(#"Name: %#", [windowInfo objectForKey:(NSString *)kCGWindowName]);
NSLog(#"Owner: %#", [windowInfo objectForKey:(NSString *)kCGWindowOwnerName]);
//etc.
}
}];
Which does a pretty good job at identifying windows under the cursor. However, in order to identify them reliably you must click on the window. Some windows will trigger a change such as terminal and xcode, but hovering over say the desktop does not trigger that Finder is under the cursor. However if you click on the desktop then it is correctly identified. Any ideas what I might be missing?

Related

Remove an item from side bar using Applescript on Mac OS

Does anyone know how can I remove an item from favourites list on finder's sidebar using applescript, If it is not possible from applescript can we do something with shell script or terminal command on Mac OS?
Here is what I did to add it via applescript:
I opened the folder which I wanted to add to the sidebar and used a shortcut (Command+Control+t) to add it to favourites menu of finder's sidebar.
Please suggest if there is any other way to do this.
Thanks
This is how we can do it using objective-c:
LSSharedFileListRef sflRef = LSSharedFileListCreate(NULL, kLSSharedFileListFavoriteItems, NULL);
AuthorizationRef auth = NULL;
NSString *itemName = #"";
AuthorizationCreate(NULL, kAuthorizationEmptyEnvironment, kAuthorizationFlagDefaults, &auth);
LSSharedFileListSetAuthorization(sflRef, auth);
UInt32 seed;
if(sflRef){
NSArray *list = (__bridge NSArray *)LSSharedFileListCopySnapshot(sflRef, &seed);
LSSharedFileListItemRef sflItemRef = NULL;
for(NSObject *object in list) {
sflItemRef = (__bridge LSSharedFileListItemRef)object;
CFStringRef nameRef = LSSharedFileListItemCopyDisplayName(sflItemRef);
itemName = (__bridge NSString*)nameRef;
NSLog(#"%#", itemName);
if ([itemName isEqualToString:#"YourItem"]) {
LSSharedFileListItemRemove(sflRef, sflItemRef);
break;
}
}
}
CFRelease(sflRef);

Main while loop not getting current value of global variable

I have a Xcode 5/Cocoa program that clicks the left mouse button after specified interval a specified number of times. That part works fine. The problem occurs when I want to stop the while loop prematurely.
I'm using a listener to detect any key press during the running of the program, set a stopnow variable and check for that variable in the while loop. But, the while loop doesn't detect the change in the variable until the loop finishes.
Also, I change a counter in the title bar of the window to display the count of clicks done, and that doesn't get updated either until the loop finishes.
I do get the NSLog message when I press a key.
I'm very confused.
My code is here :
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
// Insert code here to initialize your application
[[self myWindow] setLevel:NSFloatingWindowLevel];
[NSEvent addGlobalMonitorForEventsMatchingMask:NSKeyDownMask handler:^(NSEvent *event) {
keychar = (unichar) event.characters;
[NSApp activateIgnoringOtherApps:YES];
stopnow = 1;
NSLog(#"Key Pressed = x%x (%x) (%x)",keychar,(keychar&0x7f00),((keychar&0xff00)>>8));
}];
}
- (IBAction)setClickPoint:(NSButton *)sender {
sleep(5);
CGEventRef ourEvent = CGEventCreate(NULL);
cgPoint = CGEventGetLocation(ourEvent);
myPoint = [NSString stringWithFormat:#" (%5.0f,%5.0f)", cgPoint.x, cgPoint.y];
myNewTitle = [mytitle stringByAppendingString:myPoint];
[[self myWindow] setTitle:myNewTitle];
}
(IBAction)strtButton:(NSButton *)sender {
NSLog(#"Entered strButtn");
numClicks = [_nClicks intValue];
numWait = [_nWait floatValue];
i = 0;
while (i < numClicks || numClicks == 0) {
i++;
myTotal = [NSString stringWithFormat:#" %i of %i", i, numClicks];
myNewTitle = [mytitle stringByAppendingString:myPoint];
myNewTitle = [myNewTitle stringByAppendingString:myTotal];
[[self myWindow] setTitle:myNewTitle];
CGWarpMouseCursorPosition(cgPoint);
CGEventRef down = CGEventCreateMouseEvent(0, kCGEventLeftMouseDown,cgPoint, 0);
CGEventPost(kCGSessionEventTap, down);
CFRelease(down);
CGEventRef up = CGEventCreateMouseEvent(0, kCGEventLeftMouseUp,cgPoint, 0);
CGEventPost(kCGSessionEventTap, up);
CGRealease(up);
NSLog(#"stopnow = %i", stopnow);
if (stopnow == 1) {
stopnow = 0;
break;
}
usleep((unsigned int)(numWait * 1000000.0));
}
}
A Cocoa/Cocoa Touch app is an event-based environment, so you cannot have long running "loops" in the main thread, as you stop the handling and delivery of the events.
When your loop finishes, the UI is able to update the bits you are seeing, as it can now deliver the events.
You will need to do this work in the background thread, or some such.
Ok, here is what works - use dispatch_async(global type) for the main loop, use dispatch_async(main queue) for the code that updates the title.

Get name of (external) display

I'm trying to get the name of the connected external display with Cocoa or CoreFoundation. With "name" I mean that string that appears in the title bar of the System Preferences window when editing Display preferences.
I couldn't find any API for that in NSScreen or in the Quartz Display Services.
But there has to be a way, because if I access the color space of the display like this:
CGColorSpaceRef colorSpace = CGDisplayCopyColorSpace(displayID);
and I log the color space's description I get:
<CGColorSpace 0x100113c20>
(kCGColorSpaceICCBased; kCGColorSpaceModelRGB; DELL 2408WFP)
I found a solution in an other thread (I wonder why I didn't find that before...).
I updated it to be ARC compatible:
- (NSString *)screenNameForDisplay:(CGDirectDisplayID)displayID {
NSString *screenName = #"";
NSDictionary *deviceInfo = (__bridge NSDictionary *)IODisplayCreateInfoDictionary(CGDisplayIOServicePort(displayID), kIODisplayOnlyPreferredName);
NSDictionary *localizedNames = [deviceInfo objectForKey:[NSString stringWithUTF8String:kDisplayProductName]];
if ([localizedNames count] > 0) {
screenName = [localizedNames objectForKey:[[localizedNames allKeys] objectAtIndex:0]];
}
return screenName;
}

List / Scan for available WiFis iPhone

I'm searching for a way to present available WiFis in an iPhone App.
So far my research resulted in the following:
Apps that implement(ed) such a functionality were removed from the AppStore (means you can't deploy the App via AppStore which is fine for me)
Apple hides the functionality that is necessary for a scan in a private framework and you can't find any explanations/comments/examples on "how to use"
http://code.google.com/p/iphone-wireless seems to be most promising. anyway, i can't figure out how to include the delivered sources in my code so that it runs on a device
Even the adaptions that are mentioned htt ://code.google.com/p/iphone-wireless/issues/detail?id=26 didn't get me the desired results. The most progress was ending up with a
dlopen error: dlopen(/System/Library/SystemConfiguration/Aeropuerto.bundle/Aeropuerto, 1): image not found
failed: __Apple80211Associate
message after launching the app on a device (iPhone 3GS; iOS 3.1.3).
Used source code that procudes the error is here:
NSMutableDictionary *networks;
bool scanning;
void *libHandle;
void *airportHandle;
int (*open)(void *);
int (*bind)(void *, NSString *);
int (*close)(void *);
int (*scan)(void *, NSArray **, void *);
networks = [[NSMutableDictionary alloc] init];
// libHandle = dlopen("/System/Library/Frameworks/Preferences.framework/Preferences", RTLD_LAZY);
// libHandle = dlopen("/System/Library/PrivateFrameworks/Apple80211.framework/Preferences", RTLD_LAZY);
libHandle = dlopen("/System/Library/SystemConfiguration/WiFiManager.bundle/WiFiManager", RTLD_LAZY);
open = dlsym(libHandle, "Apple80211Open");
bind = dlsym(libHandle, "Apple80211BindToInterface");
close = dlsym(libHandle, "Apple80211Close");
scan = dlsym(libHandle, "Apple80211Scan");
open(&airportHandle);
bind(airportHandle, #"en0");
NSLog(#"Scanning...");
scanning = true;
NSArray *scan_networks;
NSDictionary *parameters = [[NSDictionary alloc] init];
scan(airportHandle, &scan_networks, parameters);
bool changed;
for (int i = 0; i < [scan_networks count]; i++) {
if([networks objectForKey:[[scan_networks objectAtIndex: i] objectForKey:#"BSSID"]] != nil
&& ![[networks objectForKey:[[scan_networks objectAtIndex: i] objectForKey:#"BSSID"]] isEqualToDictionary:[scan_networks objectAtIndex: i]])
changed = true;
[networks setObject:[scan_networks objectAtIndex: i] forKey:[[scan_networks objectAtIndex: i] objectForKey:#"BSSID"]];
}
if(changed) {
NSLog(#"NetworksUpdated");
}
scanning = false;
NSLog(#"Scan Finished...");
NSLog(#"Found %i networks: %#", [networks count], networks);
Even if trying one of the other commented lines, it doesn't work:
program received EXC_BAD_ACCESS and several
warning: check_safe_call: could not restore current frame
warning: Unable to restore previously selected frame.
What i'm searching are hints how to include iphone-wireless in my project and how to modify the given code?
An alternative would be a tip on how to scan for WiFis in your environment.
Would be nice if someone could help.
path has changed in 3.X and beyond, from :
/System/Library/SystemConfiguration/Aeropuerto.bundle/Aeropuerto
to:
/System/Library/SystemConfiguration/IPConfiguration.bundle/IPConfifuration

How do I get the details of an application using Objective-C?

I have the following code to detect the current window. How can I get 1) application internal name, 2) location, 3) publisher and 4) description of the window/application?
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
//Get info about the currently active application.
NSWorkspace* workspace = [NSWorkspace sharedWorkspace];
NSDictionary* currentAppInfo = [workspace activeApplication];
//Get the PSN of the current application.
UInt32 lowLong = [[currentAppInfo objectForKey:#"NSApplicationProcessSerialNumberLow"] longValue];
UInt32 highLong = [[currentAppInfo objectForKey:#"NSApplicationProcessSerialNumberHigh"] longValue];
ProcessSerialNumber currentAppPSN = {highLong,lowLong};
//Grab window information from the window server.
CFArrayRef windowList = CGWindowListCopyWindowInfo(kCGWindowListOptionOnScreenOnly, kCGNullWindowID);
ProcessSerialNumber myPSN = {kNoProcess, kNoProcess};
//Loop through the windows, the window list is ordered from front to back.
for (NSMutableDictionary* entry in (NSArray*) windowList)
{
int pid = [[entry objectForKey:(id)kCGWindowOwnerPID] intValue];
GetProcessForPID(pid, &myPSN);
//If the process of the current window in the list matches our process, get the front window number.
if(myPSN.lowLongOfPSN == currentAppPSN.lowLongOfPSN && myPSN.highLongOfPSN == currentAppPSN.highLongOfPSN)
{
NSNumber *windowNumber = [entry objectForKey:(id)kCGWindowNumber];
windowNumber = [entry objectForKey:(id)kCGWindowNumber];
NSString* applicationName = [entry objectForKey:(id)kCGWindowOwnerName];
NSLog(#"Capture the window: %# with window ID: %#.",applicationName,windowNumber);
return applicationName;
//Break because we only want the front window.
break;
}
}
CFRelease(windowList);
[pool release];
You should use the ProcessInformationCopyDictionary function from the Process Manager API. Give it &myPSN and kProcessDictionaryIncludeAllInformationMask as arguments and you will get the information you are looking for.
I was looking for something related with this topic. I need a WindowRef of the window or window part at a certain location (mouse position) and it has to be over all the windows of all running applications...
I´ve tried it with Carbon (´Cos my App is entirely written in C++) but I´ve found that Some Carbon Functions Doesn´t work properly (MacFindWindow, FindWindow, HIWindowFindAtLocation, FindWindowOfClass, HIWindowGetCGWindowID...)
Maybe I´m doing it wrong, It´s difficult to believe that those Carbon functions won´t work any more in 64 bits architectures...
So, related with your question I found the same code and I tried this but it isn´t what I need, I hope it helps you in any way and I´ll keep searching and trying till I get it (If the O.S can do it everybody should).
//if the process of the current window in the list matches our process, get the front window number
if(myPSN.lowLongOfPSN == currentAppPSN.lowLongOfPSN && myPSN.highLongOfPSN == currentAppPSN.highLongOfPSN)
{
NSNumber* windowNumber = [entry objectForKey:(id)kCGWindowNumber];
NSString* applicationName = [entry objectForKey:(id)kCGWindowOwnerName];
NSLog(#"The current app is %# and the window number of its front window is %#.",applicationName,windowNumber);
CGRect bounds;
CGRectMakeWithDictionaryRepresentation((CFDictionaryRef)[entry objectForKey:(id)kCGWindowBounds], &bounds);
NSLog(#"WINDOW RECT BOUNDS; (x,y,width, height) = (%d,%d, %d, %d)", bounds.origin.x, bounds.origin.y, bounds.size.width, bounds.size.height);
break;
}
Also, follow this link, I´t will help you. I´m sure:
http://code.google.com/p/blazingstars/source/browse/trunk/PokerHK/HKLowLevel.m?r=70