I am working on a small Mac application which will typically run invisibly in the background. However, the app's primary functionality comes into play when the user renames a file on their desktop or elsewhere in Finder. When this occurs, I would like to present a dialog similar to that which appears when a user changes a file-extension through Finder. Since this would require my application getting frontmost focus (rather than Finder), I would like to return Finder as the frontmost application when the user hits "OK" in my dialog.
I am currently using Apple's Process Manager function SetFrontProcessWithOptions()
, but I run into trouble in the following scenario:
- A user opens a Finder window somewhere in their workspace
- The user then clicks on their desktop, unfocusing the window.
- The user renames a file on their desktop
- My application causes itself to focus using
SetFrontProcessWithOptions()
- The user hits
OK
in the dialog, my app focuses Finder usingSetFrontProcessWithOptions()
- When Finder refocuses, it focuses the window that the user had opened before, despite the fact that it was not focused when Finder was previously frontmost.
This gets really annoying if you have a Finder window open in another space before you rename a file on your desktop: in this scenario, hitting "OK" in the dialog causes Finder to automatically switch spaces and go back to the window.
This is only because of the nature of the SetFrontProcessWithOptions()
function, which can only focus a window of a given application. Since the desktop apparently does not count as a window, the function instead finds another window to focus, despite the fact that the user had not previously had that window focused.
It would be great if anyone has any better ideas of how to do a sort of dialog-based thing such as this, maybe even without the need for focusing and unfocusinng Finder at all.
EDIT: I found a somewhat ugly way to fix this behavior for the most part, but it involves the Scripting Bridge, and it does not re-focus the desktop in the event that an item from it was renamed. Here is my code for doing this:
FinderApplication * app = [SBApplication applicationWithBundleIdentifier:@"com.apple.finder"];
if (!app || ![app isRunning]) {
SetFrontProcessWithOptions(&processSerial, kSetFrontProcessFrontWindowOnly);
return;
}
SBElementArray * selArray = app.selection.get;
if ([selArray count] == 0) {
SetFrontProcessWithOptions(&processSerial, kSetFrontProcessFrontWindowOnly);
return;
} else {
FinderWindow * window = [[[selArray objectAtIndex:0] container].get containerWindow].get;
if ([window isKindOfClass:NSClassFromString(@"FinderFinderWindow")]) {
SetFrontProcessWithOptions(&processSerial, kSetFrontProcessFrontWindowOnly);
} else {
// TODO: this is where I'd insert code to select the item
// on the desktop...
}
}