Moving tab focus to another NSWindow's view then back again - cocoa

Have a borderless window over NSTextField with a NSButton in that window. canBecomeKeyView returns YES for this NSButton. I want to be able to emulate setNextKeyView for this NSButton to be the next focus holder after NSTextField. The borderless window is the child window of the main window. The NSTextField resides on main window. What is the proper way of doing this thing?

I experienced the same problem.
In interface builder I had a window with an NSTextField and an NSButton. I want to be able to tab between them. I did what I thought was correct:
Set the intialFirstResponser for the NSWindow to be my NSTextField
Set the NSTextField nextKeyView to be the NSButton
Set the NSButton nextKeyView to be my NSTextField
But this was not working as expected.
It Turns out that in the Apple > System Preferences > Keyboard there is a setting that allows you to press Tab to move keyboard focus between:
Text boxes and lists only
All controls
The first option is set by default. Once changed to All controls everything worked as expected.

Related

Extra Control inserted into Key View Loop in NSScrollView - Text View in Catalina

The default behavior for an NSScrollView - Text View in Catalina has changed. If the Text View has enough text to show a scroll bar, there is an extra control inserted into the Key View Loop after the NSScrollView has become firstResponder. Mojave does not show this extra control in the Key View Loop.
The 2nd control is a NSScroller contained in the Scroll View. NSScroller as firstResponder doesn't appear to have any functionality (e.g. arrow keys do not have any effect).
Can this behavior be turned off? Is there a way to make the ScrollView have a single responder in Catalina?
One thing I tried is setting "Refuses First Responder" of the NSScroller to false, but this had no effect.
Note: Full Keyboard Access (the Catalina equivalent) must be turned on to reproduce this.
I think the reason NSScroller accepts first responder is so that if all the subviews of your scroll view refuse first responder you still have a way to scroll the scroll view. While the NSScroller is first responder, if I hit page up/page down on my keyboard it scrolls the scroll view. If you want to disable this behavior you can:
scrollView.verticalScroller.refusesFirstResponder = YES;
scrollView.horizontalScroller.refusesFirstResponder = YES;

How to disable default cursor on transparent titlebar of NSWindow?

I create a NSWindow with transparent title using:
setTitleVisibility:NSWindowTitleHidden
setTitlebarAppearsTransparent:YES
setMovable:NO
and the style includes NSWindowStyleMaskFullSizeContentView. The window becomes title-less, zoom and fullscreen modes work well. Everything is ok, except the mouse cursor. It becomes the default one when I move it to the area where titlebar would be located if it was visible.
Is it possible to override this behavior so that the mouse cursor shape will be defined by the window content (which uses addCursorRect)?
There's a difference between a transparent titlebar and no titlebar at all. It sounds like you have a window with a transparent titlebar, but you want a window with no titlebar.
If you want no titlebar at all, you need to make sure the window's styleMask does not have NSWindowStyleMaskTitled.
If you create the window in a xib or storyboard, you can turn off the “Title Bar” checkbox in the window's Attributes inspector.
If you create the window in code, you can set the styleMask using the initWithContentRect:styleMask:backing:defer: initializer, or you can set the styleMask after creation.
For example, this line will remove the NSWindowStyleMaskTitled bit from an existing window's styleMask:
self.window.styleMask &= ~NSWindowSytleMaskTitled;

Close borderless floating NSWindow on click outside

I want to create a borderless window floating above the main window. The main window should be the key window (I want it to handle the keyboard and mouse events). Also, the floating window should close as the user clicks outside of it. Basically, I'm creating a very custom context menu, just like NSMenu. It should behave likewise.
So I created my window this way:
NSWindow *menuWindow = [NSWindow windowWithContentViewController:menuViewController];
menuWindow.styleMask = NSBorderlessWindowMask;
menuWindow.level = NSFloatingWindowLevel;
[menuWindow makeKeyAndOrderFront:self];
That works perfectly, but how do I handle clicks outside to close it? The window doesn't invoke delegate's windowDidResignKey, because it's not a key window. If it does overload canBecomeKeyWindow (so that it returns YES), then the floating window grabs the user input, which is not what I want.
So, is there any way to automatically close a borderless window? Can NSPanel help? I tried using it, but with no success (the becomesKeyOnlyIfNeeded selector doesn't do what I need).
To detect clicks outside the window but within your app, you could install an event monitor using +[NSEvent addLocalMonitorForEventsMatchingMask:handler:]. If you also want to close the window when the user clicks in a different app, you could observe the NSApplicationDidResignActiveNotification notification.
NSWindow has a property hidesOnDeactivate that should do this for you.
From the Apple Docs:
The value of this property is true if the window is removed from the
screen when its application is deactivated; false if it remains
onscreen. The default value for NSWindow is false; the default value
for NSPanel is true.

NSWindow resize indicator not visible

How do I show resize indicators for an NSWindow without Titlebar?
I created a new Xcode project(for Mac app) with storyboard. I just disabled the checkbox Title Bar in Appearance(It hides the Title bar of NSwindow).
The strange thing was, after disabling the TitleBar, NSWindow was not showing resize indicators while mouse was above the window edges. Although if I drag at edges it was resizing.
I guess this is a bug, because if the window can be resized by dragging the mouse over edges, it must show the resize indicators.
As it can be seen in the image, the resize indicators are seen after user drags the window, but many users would think that since there is no resize indicator, the window is not resizable.
I've fixed this issue by subclassing NSWindow and overriding canBecomeKeyWindow to return YES:
#import "MyWindow.h"
#implementation MyWindow
- (BOOL)canBecomeKeyWindow {
return YES;
}
#end
Not updating resize cursors in this case looks like Apple bug. Documentation states "The value of canBecomeKeyWindow property is YES if the window has a title bar or a resize bar, or NO otherwise.", so I expect that canBecomeKeyWindow will return YES for resizable window. But it doesn't.
UPD: Checked on 10.10.5. Hopefully, you will have same behaviour on 10.11.
I have not checked this, but you could set the resize indicators manually. I think I would add four NSTrackingAreas to the windows contentView subclass (one for each side of the window, only few pixels in height/width).
In the mouseEntered() method, create a new NSCursor object for the appropriate mouse position. Remember that the position could change, so use the mouseMoved() method as well.
On mouseExited() reset the cursor.
Again, I have not tried this, but it should work.
PS: Don't forget to file a radar on this ;)

Programmatically selecting NSToolBarItem

How can I programmatically select an NSToolbar item?
[toolbar setSelectedItemIdentifier:[theToolbarItem itemIdentifier]]
This code only selects it. I want to send it's action too, so that it changes panes.
You could set the target and action of the NSButton in the nib file itself, or if you need to do it programmatically, then create an IBOutlet to the NSButton and do it in code.
When you use an NSButton in a toolbar item, it effectively acts like an NSButton would anywhere else in your interface, rather than as an NSToolbarItem per se. For example, you won't be able to easily disable or enable the button through the use of the standard -validateToolbarItem: or -validateUserInterfaceItem:; rather, you'll need to have an IBOutlet to the button in question, or otherwise use bindings to enable or disable the button.

Resources