Is it possible to force control to an NSWindowController Subclass? - macos

I am creating a cocoa application and I am loading a preference window with a NSWindowController.
When the user selected the prefs button and the preference window opens
I want the application to force the user to finish what they are doing with the newly opened window controller before going back to the application in the background.
Is there anyway to block out whats happening in the background and force the user to complete there interactions with the foreground?
Thakns

Perhaps this works? Create a subclass of the HUD window and implement
- (BOOL)resignFirstResponder {
if (userMayLeave) return YES;
return NO;
}

You can use the following method to achieve this and display your window as a modal:
[[NSApplication sharedApplication] runModalForWindow:aWindow];
Then you need to use one of the following methods in your modal window in order to dismiss it:
[[NSApplication sharedApplication] stopModal];
[[NSApplication sharedApplication] abortModal];
[[NSApplication sharedApplication] stopModalWithCode:anInteger];

Related

How to prevent focus window when its view is clicked by mouse on OSX?

I am writing a Cocoa app and do not want it focus on mouse click it, but I found no way to implement yet. Any one can give me suggestions ?
I've finally found a solution!
Create a subclass of NSView, and reimplement the following methods:
-(BOOL) shouldDelayWindowOrderingForEvent:(NSEvent *)theEvent
{
return YES;
}
-(void) mouseDown:(NSEvent *)theEvent
{
[NSApp preventWindowOrdering];
}
and set the contentView property of the created NSWindow, and set the window style mask to NSBorderlessWindowMask , and it works.
There is method(s) you may override in your subclass with returning NO
-(BOOL)acceptsFirstResponder
-(BOOL)becomeFirstResponder
Select the Table View in Interface Builder. There is a "Focus Ring" Attribute, change it to "None".
I set all these attributes in Scroll View, Clip View, and Table View.
Hope it help.

How to change the NSScreen a NSWindow appears on

I have an application that will load a couple of windows depending on which button is pressed. All except one of these open on the mainScreen (the screen in which the main window is open in). One of them (the preference window) opens on the first screen (the screen with the menu bar). I cannot understand way it is doing this, is there a way to change the screen that a NSWindow opens on?
I could not get toohtik's answer to work. What I ended up doing was subclassing NSWindow and then overriding constrainFrameRect: toScreen:. This will automatically open the new window on the "main screen" of the application.
- (NSRect)constrainFrameRect:(NSRect)frameRect toScreen:(NSScreen *)screen
{
AppDelegate *delegate = [[NSApplication sharedApplication] delegate];
return [super constrainFrameRect:frameRect toScreen:delegate.window.screen];
}
I dont't know why you have that behaviour but you can change it through initWithFrame method that takes NSScreen argument.

How to give focus to NSWindow loaded from NIB?

I'm using NSWindowController to load a window from a NIB. However, when I call showWindow:, the window is visually topmost, but the focus remains where it was (instead of moving it to the new window).
It's easy to see this happening when the first window (with keyboard focus) is moved slightly, before creating the new window (via cmd+n). This is the result:
The bottom, focused window is the original window. The unfocused window on top is the newly created window.
This is the relevant code:
AppDelegate.h:
- (IBAction)newDocument:(id) sender;
AppDelegate.m:
- (IBAction)newDocument:(id) sender {
[[[FooController alloc] init] showWindow:self];
}
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
[self newDocument:self];
}
FooController.h:
#interface FooController : NSWindowController { }
#end
FooController.m:
- (id)init {
self = [super initWithWindowNibName:#"FooWindow"];
return self;
}
FooWindow.xib:
A freshly created Window xib, without modifications.
MainMenu.xib:
The default MainMenu.xib, with its window deleted.
Calling makeKeyAndOrderFront: on the window in the controller's windowDidLoad method does not appear to focus the new window. Setting the File's owner of FooWindow.xib to FooController also did not appear to help.
What is the correct way to load and show a window from a NIB so that it does receive keyboard focus?
Edit: It looks like NSWindowController's window method returns nil, which explains why calling methods on window doesn't do anything. But why is it nil?
Okay, I found the cause of this problem.
The xib's File's owner must be set to the controller, and (this is the part I didn't know about) you have to connect the controller's window outlet to the window itself.
Having done that, it just works. No makeKeyWindow, makeMainWindow or makeKeyAndOrderFront: needed.
Perhaps makeMainWindow: or makeKeyWindow: helps

NSEvent - NSLeftMouseDown

I'm trying to trigger basic functions using NSEvent and mouse clicks. For example close the window when pressing left mouse button. What else do I need in this method?
Thanks.
- (void)mouseDown:(NSEvent *)theEvent {
if ([theEvent type] == NSLeftMouseDown){
[window orderOut:nil];
}
}
Assuming this is in a custom view and the window outlet is connected (or you fill in that variable with [self window] when the view is added to a superview), that should be all you need. I would suggest handling mouseUp: instead of mouseDown:, though, to give the user the opportunity to back out by moving the mouse outside of your view.
You might also consider using an NSButton instead of (or inside of) a custom view. You could hook it up directly to the window's performClose: or orderOut: action.

Make OSX application respond to first mouse click when not focused

Normal OSX applications eat the first mouse click when not focused to first focus the application. Then future clicks are processed by the application. iTunes play/pause button and Finder behave differently, the first click is acted on even when not focused. I am looking for a way to force an existing application (Remote Desktop Connection.app) to act on the first click and not just focus.
Check NSView's acceptsFirstMouse, it may be what you're looking for.
acceptsFirstMouse:
Overridden by subclasses to return YES if the receiver should be sent a mouseDown: message for an initial mouse-down event, NO if not.
(BOOL)acceptsFirstMouse:(NSEvent *)theEvent
Parameters
theEvent
The initial mouse-down event, which must be over the receiver in its window.
Discussion
The receiver can either return a value unconditionally or use the location of theEvent to determine whether or not it wants the event. The default implementation ignores theEvent and returns NO.
Override this method in a subclass to allow instances to respond to click-through. This allows the user to click on a view in an inactive window, activating the view with one click, instead of clicking first to make the window active and then clicking the view. Most view objects refuse a click-through attempt, so the event simply activates the window. Many control objects, however, such as instances of NSButton and NSSlider, do accept them, so the user can immediately manipulate the control without having to release the mouse button.
Responding to the first mouse click when not focused is called 'click through'. And its worth is debated heatedly, for instance here and here.
// Assuming you have 1 view controller that's always hanging around. Over ride the loadview. N.B. this won't work pre-yosemite.
- (void)loadView {
NSLog(#"loadView");
self.view = [[NSView alloc] initWithFrame:
[[app.window contentView] frame]];
[self.view setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
int opts = (NSTrackingMouseEnteredAndExited | NSTrackingActiveAlways);
trackingArea0 = [[NSTrackingArea alloc] initWithRect:self.view.bounds
options:opts
owner:self
userInfo:nil];
[self.view addTrackingArea:trackingArea0];
}
- (void)mouseEntered:(NSEvent *)theEvent {
NSLog(#"entered");
if ([[NSApplication sharedApplication] respondsToSelector:#selector(activateIgnoringOtherApps:)]) {
[[NSApplication sharedApplication] activateIgnoringOtherApps:YES];
}
}

Resources