NSTextField and FirstResponder - objective-c

I am developing a cocoa application that has a main window and several panel windows.
I need to autosave some text on a NSTextField (which is on a panel window) when user leaves the textfield by clicking the main window etc. so far I have tried out by implementing resignFirstResponder on a NSTextField subclass,however if I click on another textfield on the same window "resignFirstResponder" gets triggered but if I just click on somewhere empty on my main window it does not get triggered. (NSTextField loses the blue focus though)
I need to capture this event the NSTextField loses the focus ring to save the uncommitted changes . Any pointers would be highly appreciated.
This text field is on NSTableCellView

use [[NSApp mainWindow] resignFirstResponder];

How about using the NStextfield's action sent on end editing
Then simply right-click-drag to an object (or FirstResponder) in your Xib file and connect it to a method. It should now run this method when you end the editing (deselect, Enter or Tab).

Related

Cocoa HUD panel shows again after calling orderOut:

I'm using a NSPanel with HUD style to display some information.
There's a button inside the HUD panel, when the user clicks the button, I'll open a new window by calling:
[anotherWindowController showWindow:self];
[anotherWindowController.window makeKeyAndOrderFront];
And I want the panel disappear when the window shows, so I set the delegate of the main window, and in the windowDidResignMain callback, I called [hudPanel orderOut:nil].
The HUD panel did disappear (I can see it), but right after it closed, it reopens.
I've checked all possible orderFront: code, and none of them get called. So my hands are really tied. Is this a system level behaviour? Can anyone guide me through this?
EDIT:
I forgot to mention that, the button resides in a NSPopover. So, basically, there's a NSButton in the HUD panel. When user clicks the button, a NSPopover will show up, inside which, there's the button to bring up the new window.
Big thanks!
I had the problem. The following solved it:
[NSApp endSheet:yourPanel];
[yourPanel orderOut:self];
Use
[hudPanel performClose:nil]
(in Swift I have to use self instead of nil). I had a problem using orderOut with a popover and it was solved by using the above method.
Please add [hudPanel close] after [hudPanel orderOut:nil]
swift: hudPanel.close()
from the apple docs:
If the window is the key or main window, the window object immediately behind it is made key or main in its place. Calling orderOut(_:) causes the window to be removed from the screen, but does not cause it to be released. See the close() method for information on when a window is released.
Sometimes the window reappears during window controller inner logic, I think. I have an issue when long pressing keyboard button kills window, but shot keyDown event only hides it on the split second. After using close all goes smoothly.

How to force an NSWindow to be always active/focused?

I have a transparent NSWindow that follows the user's screen everywhere he goes (the NSWindowstays in front of every app, no matter what, even fullscreen apps).
In that NSWindow i have a mouseDown event that shows a popup. Let's say i'm on safari in fullscreen mode and i have my Window in front of it, i click on safari and i click again on my Window: nothing happens, the mouseDown doesn't occur. I have to click again so the mouseDown event is triggered.
How can i force my NSWindow to be always active so i don't have to click it 2x to trigger the mouseDown when i click on a background app and click in my window again?
Thank you!
I'm not sure if this is exactly what you want (it's not quite a window wide setting), but, from the documentation:
By default, a mouse-down event in a window that isn’t the key window
simply brings the window forward and makes it key; the event isn’t
sent to the NSView object over which the mouse click occurs. The
NSView can claim an initial mouse-down event, however, by overriding
acceptsFirstMouse: to return YES.
The argument of this method is the
mouse-down event that occurred in the non-key window, which the view
object can examine to determine whether it wants to receive the mouse
event and potentially become first responder. You want the default
behavior of this method in, for example, a control that affects the
selected object in a window.
However, in certain cases it’s
appropriate to override this behavior, such as for controls that
should receive mouseDown: messages even when the window is inactive.
Examples of controls that support this click-through behavior are the
title-bar buttons of a window.
Or you could try fiddling with
- (void)sendEvent:(NSEvent *)theEvent
and see if you can handle events in a custom way.
If you add a borderless NSButton instance to your window's view and set your image as the button's image (and as its alternate image, to make it more beautiful), it will work out of the box: Just connect the button's action method to your app delegate (or the object where you want to process the click action). A click on the image (i.e. the button) will then trigger the button's action method, no matter which window is active.
This worked for me, hope that will be helpful, This will keep your window always on Top of all applications
[self.window makeKeyAndOrderFront:nil];
[self.window setLevel:NSStatusWindowLevel];
I think what you really should do is use an NSPanel (a floating palette -- a special kind of NSWindow) that will do exactly what you want in a way that's consistent with the OS rather than trying to fight intended behavior.
Here's the NSPanel documentation:
https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/ApplicationKit/Classes/nspanel_Class/Reference/Reference.html
And here's some helpful and pithy information:
http://cocoadev.com/wiki/NSPanel
By default, an NSPanel will disappear when the application is inactive, but you can turn this off.
I apologize for not laying it out more fully ... pressed for time.
Edit:
Note that you can probably get your window to behave as desired simply:
"The NSView can claim an initial mouse-down event, however, by overriding acceptsFirstMouse: to return YES."
https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/EventOverview/HandlingMouseEvents/HandlingMouseEvents.html
You'll need to do this with any NSView subclass to skip the "activation click".

How do I force keyboard focus for a Modal Window without Title Bar

I want to run a simple dialog similar to Finder Go To Folder.
I have used a NSPanel made this Document Modal and run with runModal.
This works, but displays a title.
If I turn off the Title Bar (in IB) the buttons work, but the NSTextField does not get keyboard focus.
I have tried lots of techniques to make it firstResponder or set as key, setBecomesKeyOnlyIfNeeded:NO but to no avail.
You need to subclass NSWindow, override - (BOOL)canBecomeKeyWindow and return YES.
By default, borderless windows cannot become the key window.

UISearchDisplayController not displaying keyboard when text area touched

I have a UITableView in a controller that is nested under a UITabBar.
The interaction is all wired up in Interface Builder so far, nothing done programmatically in terms of view switching.
I've added a UISearchDisplayController as the header of my UITableView. It displays fine, and when I tap on the text entry area, the cancel button appears and the black overlay flies in.
However, the keyboard never appears and when tapping the cancel button, the overlay flies out and the cancel button disappears, but the text entry area keeps focus and the caret stays flashing there, so I cannot tap there again to re-display the search results.
So essentially I have two problems:
Keyboard not appearing when starting to edit text on UISearchBar from UISearchDisplayController
UISearchBar not loosing focus when cancel button is tapped.
What am I doing wrong?
The .xib file that had my tab bar in it contained a UIWindow.
This lead to all sorts of craziness and in the end I gave up on trying to do this with interface builder, and resorted to constructing the UITabBar in code, thereby not creating a second UIWindow.
This resolved the problems and the UISearchDisplayController behaved correctly.
check this method in UISearchBarDelegate:
- (void)searchBarCancelButtonClicked:(UISearchBar *) searchBar;
Try to see if this is getting called and do keyboard-related removal in here. If not, try making another UISearchDisplayController. (I actually never use the default viewController's one). Also, make sure the delegate is correctly set.

NSTextField in status bar doesn't want to receive focus

For some reson sometimes a NSTextField I'm using in Status Bar menu doesn't always allow me to input text. I click it and nothing happens as if it was disabled. Upon restarting program it works again. I don't do anything with it, it's just created in the interface builder.
That's because no NSWindow contains the NSTextField. The NSWindow sets the first responder when the window gets the main window. The NSStatusBar is global. It's never focused so your textfield only will be focused in the very beginning.
I'm not sure if there's a way to solve this problem in a nice way. You might try to set the first responder manually. You could also add a global event monitor
Example:
[NSEvent addGlobalMonitorForEventsMatchingMask:NSKeyDownMask handler:^(NSEvent* incoming) {
[textfield setStringValue:[incoming characters]];
}];
Note: This is a very bad way to fix this problem. I'd first try to set the NSTextField manually as a first responder if this is possible.