Set focus of NSWindow on top, even if changing of virtual desk - objective-c

I'm doing an application which consists of asking a question after a certain time, and the user can't do anything more, unless he answers the question, I've managed to mantain the window always on top by setting a 9999 level:
[_idleWindow setLevel:9999];
I would like to know if there is a way to avoid changing virtual desktop when the window is open, or to focus the window again when you change the virtual desktop.

Look at setCollectionBehavior:
[_idleWindow setCollectionBehavior:NSWindowCollectionBehaviorMoveToActiveSpace|NSWindowCollectionBehaviorTransient|NSWindowCollectionBehaviorFullScreenDisallowsTiling|NSWindowCollectionBehaviorFullScreenAuxiliary];
might do the trick.
Also, if you can use NSPanel instead of NSWindow, you can add the style mask: NSWindowStyleMaskNonactivatingPanel to give your window key status even when your app isn't active. (you'll need to implement canBecomeKeyWindow in the NSPanel subclass)

After a few researches on Google, I have found the solution on another Stackoverflow post.
Solution:
You need to add this code either in your xib / storyboard, either in your NSWindowController subclass -windowDidLoad method, either in your designated initialiser of your NSWindow subclass :
- (void) awakeFromNib {
[self setCollectionBehavior:NSWindowCollectionBehaviorCanJoinAllSpaces]; //this was the one that worked for me
}
OR
- (id)initWithContentRect:(NSRect)contentRect
styleMask:(NSUInteger)styleMask
backing:(NSBackingStoreType)bufferingType
defer:(BOOL)flag {
if (self = [super initWithContentRect:contentRect styleMask:styleMask backing:bufferingType defer:flag]) {
[self setCollectionBehavior:NSWindowCollectionBehaviorCanJoinAllSpaces];
}
return self;
}
OR if you have a NSWindowController
- (void)windowDidLoad {
[super windowDidLoad];
[[self window] setCollectionBehavior:NSWindowCollectionBehaviorCanJoinAllSpaces];
}
OR Edit the nib file and add this behaviour to your window in XCode.
Credits: Stefan Szekeres

Related

no methods on NSWindowController subclass are called

I have a window that I am creating based off of clicking a row in a Tableview, instantiated like such:
HKLUserProfileController *userProfileController = [[HKLUserProfileController alloc] initWithNibName:#"HKLUserProfileController" bundle:nil];
_wc =[[NSWindowController alloc] initWithWindowNibName:#"HKLProfileWindowController"];
[_wc.window.contentView addSubview:userProfileController.view];
// other extraneous stuff here
[_wc showWindow:self];
if([_wc.window canBecomeKeyWindow]) {
[_wc.window makeMainWindow];
[NSApp activateIgnoringOtherApps:YES];
[self makeKeyAndOrderFront:self];
}
This works, but I cannot seem to get the window to become the main/key/front window. I've tried:
... from this place where I am creating the WindowController, and also from inside viewDidLoad/loadView of the NSViewController whose View was added to the Window. No dice. (this is my ultimate goal here, so if you see something obvious i'm missing, please point it out).
So I realized that I should be trying to do this in the subclass of the WindowController itself... so I thought to put it in windowDidLoad, but no result. I set some breakpoints, and tried the other logical init methods, and to my surprise, NONE of them fire at all.
#implementation HKLProfileWindowController
- (void)windowDidLoad {
[super windowDidLoad];
// breakpoint here
}
-(void)awakeFromNib {
// breakpoint here
}
- (id)init {
// breakpoint here
self = [super init];
if (self) {
// breakpoint here
}
return self;
}
#end
My xib is connected as an Outlet / Delegate to my File's Owner properly, as far as I can tell. This is leading me to believe this is the root of the problem, but for the life of me, I can't figure out what is the issue...
Thanks...
EDIT
I realize what is happening with the keyWindow - because it's coming from shouldSelectRow in the TableView, it IS becoming key on mouseDown events, but the first window - which holds the TableView - is becoming key again on mouseUp events... which is maddening!
Will search for solutions to that, but open to comments here!
(still can't figure out why the init methods are not firing though...
You use NSWindowController in your alloc/init line and you expect it to become an HKLProfileWindowController instance? Why?
You also need the File's Owner custom class set to HKLProfileWindowController but there's no reason to expect that's sufficient to get an HKLProfileWindowController instance when you ask for an NSWindowController. What you get is an NSWindowController and none of the subclass code is used.
I'll delete this answer if your code is from before you implemented the HKLProfileWindowController class, but given what you have pasted here, that's why your breakpoints don't get hit.

NSPanel - Why can I not set my Panel title and data values before showing the window?

Simple structure:
exampleController.h :
#import <Foundation/Foundation.h>
#interface exampleController : NSWindowController {
#public
IBOutlet NSPanel *entryPanel;
#property (nonatomic, strong) IBOutlet NSPanel *entryPanel;
#end
exampleController.m :
#import "exampleController.h"
#implementation exampleController
#synthesize entryPanel;
- (id)init {
self = [super initWithWindowNibName:#"ExamplePanel"];
if (self) {
// Initialization code here.
NSLog(#"entryPanel: %#", entryPanel);
[self.entryPanel setTitle:#"TESTING!"];
}
return self;
}
randomController.m :
...
- (id) init {
self = [super init];
if (self) {
// loading our example controller if it isn't loaded yet.
if (!ourExampleController) {
ourExampleController = [exampleController alloc] init];
}
}
return self;
}
...and then later in the random controller within a method I show the NSPanel via:
[ourExampleController showWindow:self];
[ourExampleController window] makeKeyAndOrderFront:self];
My problem is that no matter what, the first time the NSPanel displays and shows itself the title is always still set to the title that it has in Interface Builder! Even though I explicitly set the title in the exampleController init method.
I've also tried throwing an NSLog(#"entryPanel: %#", entryPanel) in the init method for exampleController and at launch it is always NULL. I do not have to ALLOC all my IBOutlets in the init because I am already synthesizing them?
I've double checked everything in interface builder. The File Owner for the ExamplePanel.xib is set to the exampleController class. The window AND entryPanel outlets are both referencing the NSPanel in our xib file. What am I missing ??
Thanks in advance!
EDIT: Just to add. If I open the window (..and see the default IB title) and then close it and reopen it with a method that changes the title - it seems to work! This problem seems to only reside with the window first opening. It seems like my properties are not being alloc'd until the window first opens?
EUREKA!
As per discussion here:
IBOutlet instances are (null) after loading from NIB
I learnt that the window itself is not loaded when my controller is initialized. Found that surprising since I figured using initWithWindowNibName:#"myNibFile" would also alloc and initialize all outlet properties but since I'm new to OSX Obj-C that appears to not be the case. All the outlet properties are only alloc'd once the window itself is loaded too.
It's easy to just show the window (which also loads the window if it's not loaded yet) and then quickly set all the outlets to my desired values BUT this was an issue for me since I wanted to avoid that ever so slight "screen flicker" (for lack of a better description) that occurs as the values adjust to their new settings.
The solution was to find a way to load the controller and load the window without actually showing it first! Then I discovered this:
Can you force a NSWindow to load, i.e. before it is presented onscreen?
Steps to make that happen:
Add the following to my NSWindowController subclass init method:
// this loads the window as per link/description above
[self window]
The key seems to be though to ensure that in your NIB/XIB file that the Visible At Launch is unchecked. If it is checked (default behavior) then the [self window] call above will still show your window when your app launches. Unchecking the above option ensures the above call does not show your window until you explicitly show it yourself!
E.g. You can define an action button which loads your window:
[exampleController showWindow:self];
[[exampleController window] makeKeyAndOrderFront:self];
Hope this helps someone else out. Was a head scratcher for a couple hours!
You should set the title, etc. in -awakeFromNib or -windowDidLoad instead of an -init… method. That way the values will be set before the window is shown and you won't get the flicker.

NSTextView not properly resizing with auto layout

I have a simple layout, which consists of NSView and its subview NSTextView. NSTextView is programmatically filled with some text that spawns multiple lines. I tie everything together using auto-layout (all done programmatically). However, when everything is displayed NSTextView is cut off, only one line is showing.
After searching the web, the best answer I could find was:
Using Autolayout with expanding NSTextViews
However, this only works if I manually change the text in NSTextView after everything is displayed (which is not really my use case). The views are readjusted and the whole NSTextView is displayed.
I am trying to figure out when NSViewController is done with laying out subviews so that I could call invalidateIntrinsicContentSize on the NSTextView. The equivalent of viewDidLayoutSubviews in UIViewController.
Nothing I tried worked so far. I attempted calling invalidateIntrinsicContentSize for NSTextView:
At the end of loadView
After I filled NSTextView with my text
Is there a better way to achieve this?
After further research, found the answer:
Create custom NSView subclass that contains NSTextView
In NSView subclass override layout method that calls invalidateIntrinsicContentSize
Also check out this link that explains subtleties of auto layout and intrinsic content size (among many other things):
http://www.objc.io/issue-3/advanced-auto-layout-toolbox.html
Sample code:
#interface MyView : NSView
#property MyTextView *textView;
#end
#implementation MyView
// init & create content & set constraints
-(void) layout {
[super layout];
[self.textView invalidateIntrinsicContentSize];
}
#end
Implementation of MyTextView:
#implementation MyTextView
- (NSSize) intrinsicContentSize {
NSTextContainer* textContainer = [self textContainer];
NSLayoutManager* layoutManager = [self layoutManager];
[layoutManager ensureLayoutForTextContainer: textContainer];
return [layoutManager usedRectForTextContainer: textContainer].size;
}
- (void) didChangeText {
[super didChangeText];
[self invalidateIntrinsicContentSize];
}
#end

Keyboard not show onload

I want the keyboad show automatically onload, but it did not work as i expect
here is the code i use:
- (void)viewDidLoad {
[super viewDidLoad];
[seachBar2 setDelegate:self];
}
- (BOOL)Searchbar2ShouldReturn:(UISearchBar *)searchBar2 {
[searchBar2 becomeFirstResponder];
return YES;
}
Coud somebody will point me how to fix this
thank you somuch
- (void)viewDidLoad {
[super viewDidLoad];
[seachBar2 setDelegate:self];
[seachBar2 becomeFirstResponder];
}
Just came across this, and it helped but the answers are vague.
All you need to do now in iOS 5 is make an outlet connection to your object (for example a UITextField) and then in viewDidLoad method type;
[myTextField becomeFirstResponder];
or for your search bar
[searchBar2 becomeFirstResponder];
Make sure searchBar2 in your code points (IBOutlet) to the searchBar in the Interaface Builder.
in your code:
IBOutlet UISearchBar *searchBar2;
In IB:
goto the search bar's Connections Inspector (apple-2) and drag the Referencing Outlet to File Owner and select searchBar2
Hope this helps.
You do need to override viewDidAppear:, and verify it's actually being called (put a breakpoint or an NSLog() statement in there). You should also determine the language you're coding in (it's Objective C).
Your -Searchbar2ShouldReturn: method will never be called by the system. I think you may need to go back and work through a few of Apple's tutorials here; your grasp of the frameworks seems tenuous, at best.

How to custom draw window title bar in Objective-C?

I'd like to customize the way I draw the window title bar on OS X. Specifically, I'd like to do something like the Twitterrific app where there is a custom close button, no min/max buttons, and the window title text is right-justified. Unlike Twitterrific, I'm not looking to custom draw the entire window (though I'm not completely opposed to that either).
I've already seen the RoundWindow sample on Cocoa With Love as well as the RoundTransparentWindow example Apple provides, but neither seems appropriate.
If you don't want to use a borderless window class then you can do a couple of things.
First, you can customize the close/min/max buttons buy using -[NSWindow standardWindowButton:]. Once you get the button you can position it/remove it/etc...
You can customize the title by setting the title to #"". Then you can add a NSTextField to draw your own title by doing the following [[[NSWindow contentView] superview] addSubview:textField].
This is probably the easiest way to do things.
Another way to do this is to customize the view that draws all the window title bar, etc...
NSWindow's content view's is inside a "theme view". You can subclass the theme view and do your own drawing. The only problem is that the theme view is a private class so you'll have to be careful.
cocoadev provides some more detail on how best to implement your own NSWindow subclass, complete with a description of most of the common pitfalls.
The gist of it is to create a subclass of NSWindow, and set its styleMask to NSBorderlessWindowMask in the init method:
- (id) initWithContentRect: (NSRect) contentRect
styleMask: (unsigned int) aStyle
backing: (NSBackingStoreType) bufferingType
defer: (BOOL) flag
{
if ((self = [super initWithContentRect: contentRect
styleMask: NSBorderlessWindowMask
backing: bufferingType
defer: flag]) == nil) { return nil; }
[super setMovableByWindowBackground:YES];
[super setLevel:NSNormalWindowLevel];
[super setHasShadow:YES];
// etc.
return self;
}
Note that you should probably return YES for canbecomeKeyWindow in order to make your window behave like a normal window.
- (BOOL) canBecomeKeyWindow
{
return YES;
}
You can then create a custom NSView subclass, fill the entire window with an instance of said class, and then perform all of the appropriate window drawing from within that custom view.
The whole thing can get a bit painful. You will have to re-implement most of the normal window behaviours such as resizing by dragging the bottom right corner.
There's an example of a custom window implementation in the CoreData Stickies sample project.