How to programmatically launch an OS X app in minimized mode? - objective-c

I need to launch my application on startup, but I want it to be "minimized", meaning, it will be opened in the dock but its window won't be displayed.
Same like TeamViewer, if you know this application.
I currently use launchctl with a plist I've added to ~Library\LaunchAgents, and indeed on startup the application is launched, and its window is shown.
How can I launch it in such a hidden / minimized state?

Uncheck visible at launch in your xib for main application window.
Implement - (BOOL)applicationShouldHandleReopen:(NSApplication *)theApplication hasVisibleWindows:(BOOL)flag in your app delegate class.
- (BOOL)applicationShouldHandleReopen:(NSApplication *)theApplication hasVisibleWindows:(BOOL)flag
{
if (!flag) {
[window makeKeyAndOrderFront:self];
return YES;
}
return NO;
}

The below line will help you to achieve
[[self window] miniaturize:self];

minimized .. I think you want to launch it as HIDDEN
see NSWorkspace's :
- (BOOL)launchAppWithBundleIdentifier:(NSString *)bundleIdentifier options:(NSWorkspaceLaunchOptions)options additionalEventParamDescriptor:(NSAppleEventDescriptor *)descriptor launchIdentifier:(NSNumber **)identifier
use that to launch an app from another app and pass option NSWorkspaceLaunchAndHide
if you wonder how you get the app to not show a dock icon:
define LSUIElement = YES in your plist

Related

Opening a "Welcome" window from main application window

I am working on a visual editor application for OSx
Currently, the application opens my MainMenu.xib.
I would like to present user when opening the application with a Welcome window, listing the previous opened projects, and a button to create a new project (actually linking to my App Delegate menuNewProject method)
What is the best approach to open this "Welcome" xib instead of MainMenu xib ?
Make my current app delegate open the Welcome xib like this ?
Welcome *welcome = [[Welcome alloc] initWithWindowNibName:#"Welcome"];
and then hide my MainMenu window ?
Or make the starting point of my application Welcome xib and not MainMenu, and open my visual editor from there ?
Thank you for your help.
As per my understanding you want to open "Welcome" Screen instead of "MainMenu"...
If you set launch screen in info.plist file, Welcome screen will be opened instead of MainMenu
Set this field in info.plist file :-
Launch screen interface file base name = Welcome
Hopefully it works for you.. Thanks
OK, I think I got it:
At the end of
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
I added:
[self.window orderOut:nil]; // hide application window
Welcome *welcome = [[Welcome alloc] initWithWindowNibName:#"Welcome"];
[welcome.window makeKeyAndOrderFront:self];
[[NSApplication sharedApplication] runModalForWindow:welcome.window]; // display splash screen
In my Welcome.m file, I added a close button on the splash window :
-(void)windowDidLoad
{
[super windowDidLoad];
NSButton* closeButton = [NSWindow standardWindowButton:NSWindowCloseButton forStyleMask:NSTitledWindowMask];
[closeButton setFrameOrigin:NSMakePoint(0, 410)];
NSView* contentView = self.window.contentView;
[contentView addSubview:closeButton];
[closeButton setTarget:[AppDelegate appDelegate]];
[closeButton setAction:#selector(closeModal:)];
}
And in AppDelegate.m, I added a closeModal method which is in charge of closing my welcome screen and display the application window:
-(void) closeModal:(id)sender
{
[[NSApplication sharedApplication] stopModal];
[self.window orderFront:nil];
}
Seems to work, maybe I should add something to discard my Welcome screen from memory too.

Cocoa How to remember the window position with multiple monitors?

To save window position for one(main) monitor i'm using this code:
[[win windowController] setShouldCascadeWindows:NO];
[win setFrameAutosaveName:#"My App"];
It's works fine.
But if I connect second monitor and drag my app window to second monitor, cocoa autosave does not work - after restart, window always placed on primary(main) monitor.
Any ideas?
Thank you!
Enable restore for your app:
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
[[NSUserDefaults standardUserDefaults] setObject:#YES forKey:#"NSQuitAlwaysKeepsWindows"];
}
Set your window to be restorable in Interface Builder
Also make sure that you don't call invalidate on close. It is just promise -> you might end app with deleted state
[self.window invalidateRestorableState];
To verify/debug check if the content of "~/Library/Saved Application State/yourbundleidentifier" persists after restart.

NSDocument-based app window position

My Xcode NSDocument-based app contains a floating panel. On each launch of the app the default doc window and panel appear in their previous locations on the screen. However, if I save a document and quit the app then double click the saved file, the document window is positioned at the same origin as the panel.
Turning off cascading gets around the problem but of course I lose cascading.
A minimum Xcode example showing the issue can be downloaded here.
Run the example project.
Do a File/Save.
Quit the app. << important
Double click the saved file.
Any help appreciated.
If you want to store the state of your window before the app terminates try this:
- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender
{
// If you want to save your window position
// you can use [window saveFrameUsingName:#"someWindowName"];
//
// then use [window setFrameAutosaveName:#"someWindowName"]; at the app launch.
return NSTerminateNow;
}
I knew it had something to do with document windows cascading from the panel. Adding this to the panel controller seems to have fixed it
- (void)windowDidLoad {
[super windowDidLoad];
[self setShouldCascadeWindows:NO];
}

Closing Mac application (clicking red cross on top) and reopening by clicking dock icon

When I close my Mac application (by clicking red cross button on window top bar) the app icon stays in the dock at the bottom. Now this is normal behaviour. When user click on it again it does not fire up the application unless the user quits the application altogether and relaunches it again.
A similar example on Mac OS X is "Activity Monitor". You can close the application by clicking the red cross button at the top the but dock icon stays there. User can re-open it by clicking dock icon.
How can I achieve this in my own application ?
If you are still concerned how to reopen the window that you have closed, use this method:
- (BOOL)applicationShouldHandleReopen:(NSApplication *)theApplication hasVisibleWindows:(BOOL)flag {
[window makeKeyAndOrderFront:self];
return YES;
}
You can use this to handle clicks on the applications icon in the dock.
For further information check out the NSApplicationDelegate Protocol Reference.
Here is the documentation:
http://developer.apple.com/library/mac/#documentation/cocoa/reference/NSApplicationDelegate_Protocol/Reference/Reference.html
Hope this helps!
Latest Update:
In latest Xcode 11.4 on MacOS 10.15 with Swift 5.2, this same problem exists in MacOS SwiftUI app. Adding following code inside AppDelegates.swift solves the issue.
func applicationShouldHandleReopen(_ sender: NSApplication, hasVisibleWindows flag: Bool) -> Bool {
if !flag{
window.makeKeyAndOrderFront(nil)
}
return true
}
Implement the method
- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender
{
return NO;
}
in your app delegate
Your app will hang around after the window is closed and then if you implement
- (void)applicationDidBecomeActive:(NSNotification *)aNotification
{
//dock icon has just been clicked , or cmd-tabbed into
}
in the app delegate
You can do things when the icon is clicked such as open a new or old window if you need to
See http://developer.apple.com/library/mac/#documentation/cocoa/reference/NSApplicationDelegate_Protocol/Reference/Reference.html for other relevant application events
I think that the answers above aren't fully correct, to achieve this you should override applicationShouldHandleReopen(_:hasVisibleWindows:) https://developer.apple.com/reference/appkit/nsapplicationdelegate/1428638-applicationshouldhandlereopen

How do I run modals windows from code with cocoa?

I`m trying to run a window as modal directly from the code.
My program starts and a main NSWindows is showed.A thread still running to see if the user has a valid distribution. if he doesn't I need to run a modal.I mean, I have no buttons clicked in the interface.I've designed a NSWindow on the interface builder for a password set, and I want to call it only when my validation is not successful.
I have tested and realized that these methods which are responsible for modal windows running only work in a IBAction environment.
//This doesn't work
-(void) showPasswordWindow
{
[NSApp runModalForWindow:[self window]];
}
//this works But its not useful for me =(
- (IBAction) passwordWindowButton:(id)sender
{
[NSApp runModalForWindow:[self window]];
}
Please, help this newbie =)
One thing to check: are you calling the method on the main thread?
to check, add this to showPasswordWindow
NSLog(#"Main thread? %d", [NSThread isMainThread]);