Resizing an NSWindow setup as a childwindow - xcode

Let me rephrase the question:
How can I keep a child NSWindow (added to a main NSWindow using addChildWindow) the same size as the main window?
Old question:
I have two NSWindows: an uiWindow and an openglWindow. The uiWindow is borderless and initially the same size as the openglWindow. I add it as a child window. I would like to make the uiWindow follow any size changes that the openglWindow undergoes. To do that, I've subscribed to the delegate of openglWindow and I'm listening to the windowWillResize method. However, I'm confused now. I don't know which function to call on uiWindow to resize it. There are quite a few options:
setFrame: display:
`
contentRectForFrameRect
frameRectForContentRect
Below is the initialization code for the child window.
NSRect uiWindowRect = [self.openglWindow convertRectToScreen:((NSView*)self.openglWindow.contentView).bounds];
NSWindow* uiWindow = [[NSWindow alloc] initWithContentRect:uiWindowRect styleMask:NSBorderlessWindowMask backing:NSBackingStoreNonretained defer:NO];
[self.openglWindow addChildWindow:uiWindow ordered:NSWindowAbove];

I found a way that does exactly what I was looking for. Here's the code for reference:
-(void)windowDidResize:(NSNotification *)notification{
CGRect frame = CGRectMake(self.openglWindow.frame.origin.x,self.openglWindow.frame.origin.y, ((NSView*)self.openglWindow.contentView).frame.size.width, ((NSView*)self.openglWindow.contentView).frame.size.height);
[self.window setFrame:frame display:YES];
[self.window setFrameOrigin:NSMakePoint(self.openglWindow.frame.origin.x,self.openglWindow.frame.origin.y)];
[self.window viewsNeedDisplay];
}

Related

Why is this Cocoa layout ambiguous?

I want to use layout constraints and create my UI programmatically. Here is a simple program that I'm hoping you can help me understand. In Interface Builder, I simply took the defaults -- there is an NSWindow with its default contentView. Below is all the code, and a screenshot.
I create a single button, and place it in the content view. Then I try to use constraints to make it fill the window. As you can see, it claims the layout is ambiguous. But when I click that button to "Exercise Ambiguity", nothing changes. The docs say it should choose a different possible layout.
I also think the content view is tightly surrounding the button and not filling the window, but I don't know how to force that with constraints.
// In AppDelegate.h
#interface AppDelegate : NSObject <NSApplicationDelegate> {
NSButton *_button;
}
#property (assign) IBOutlet NSWindow *window;
#end
// In AppDelegate.m
#implementation AppDelegate
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
NSView *contentView = (NSView*)_window.contentView;
_button = [[NSButton alloc] init];
_button.title = #"Test";
_button.translatesAutoresizingMaskIntoConstraints = NO;
contentView.translatesAutoresizingMaskIntoConstraints = NO;
[contentView addSubview:_button];
NSDictionary *viewsDict = NSDictionaryOfVariableBindings(_button, contentView);
NSMutableArray *constraints = [[NSMutableArray alloc] init];
[constraints addObjectsFromArray: [NSLayoutConstraint constraintsWithVisualFormat:#"|[_button]|" options:0 metrics:0 views:viewsDict]];
[constraints addObjectsFromArray: [NSLayoutConstraint constraintsWithVisualFormat:#"V:|[_button]|" options:0 metrics:0 views:viewsDict]];
[contentView addConstraints:constraints];
[_window visualizeConstraints:constraints];
printf("Is layout ambiguous? %d\n", contentView.hasAmbiguousLayout);
}
#end
What if you visualize constraints on a subsequent iteration of the run loop, for example with a timer or by clicking a button, after the layout engine has had a pass at it? It may just be ambiguous because the layout engine hasn’t solved the system yet.
Edit: I ran your code, and am seeing the same issue. I’m also stumped now.

Open NSWindowController from NSMenu

I'm with a NSMenu in an agent application (without the icon in the dock). When a button from this menu is tapped, I want to show a generic NSWindowController.
My menu button action:
- (IBAction)menuButtonTapped:(id)sender {
MyWindowController *myWindow = [[MyWindowController alloc] initWithWindowNibName:#"MyWindowController"];
[myWindow showWindow:nil];
[[myWindow window] makeMainWindow];
}
But the window just "flashes" in the screen (it shows and disappears really fast).
Any solution?
The reason the window is showing up for a split second and then disappearing has to do with ARC and how you go about creating the instance of the window controller:
- (IBAction)menuButtonTapped:(id)sender {
MyWindowController *myWindow = [[MyWindowController alloc]
initWithWindowNibName:#"MyWindowController"];
[myWindow showWindow:nil];
[[myWindow window] makeMainWindow];
}
Under ARC, the myWindow instance will be valid for the scope where it is defined. In other words, after the last [[myWindow window] makeMainWindow]; line is reached and run, the window controller will be released and deallocated, and as a result, its window will be removed from the screen.
Generally speaking, for items or objects you create that you want to "stick around", you should define them as an instance variable with a strong property.
For example, your .h would look something like this:
#class MyWindowController;
#interface MDAppController : NSObject
#property (nonatomic, strong) MyWindowController *windowController;
#end
And the revised menuButtonTapped: method would look something like this:
- (IBAction)menuButtonTapped:(id)sender {
if (self.windowController == nil) {
self.windowController = [[MyWindowController alloc]
initWithWindowNibName:#"MyWindowController"];
}
[self.windowController showWindow:nil];
}
Use this:
[[myWindow window] makeKeyAndOrderFront:self];

How to add custom NSView to Window

I know how to do this in iOS but cannot figure it how to it in Cocoa.
I want to capture keyboard events and I think I need to override the acceptsFirstResponder method to accomplish that (keyDown method being triggered). So I created a class extending NSCustomView and tried to add it in the main Window but I just cannot understand how to do it. So far I added a Custom View to the main View then tried to add it programmatically like:
TestView *view = [[TestView alloc] init];
[[_window contentView] addSubview:view];
but this is not working. So how can I do this?
To see if the view has been added to a window, you can override the view's viewDidMoveToWindow method and log the value of [self window] to check (if it's nil then the view has been removed from a window):
- (void)viewDidMoveToWindow
{
NSLog(#"window=%p", [self window]);
[super viewDidMoveToWindow];
}
You should be subclassing NSView, not NSCustomView, and initWithFrame is the designated initializer for NSView, not init.
Try:
TestView *view = [[TestView alloc] initWithFrame:NSMakeRect(0, 0, 100, 200)];
[[_window contentView] addSubview:view];

Drag window with NSImage as handle?

I am writing a mac app and have used this code to hide the window handle,
[self.window setStyleMask:NSBorderlessWindowMask];
Well this is great, but i still need a handle to move around the window, so is there a way to move around the window from another object like an NSImage, acting like the window handle?
The code for my image is in the .h,
#interface WOWAppDelegate : NSObject <NSApplicationDelegate> {
NSWindow *window;
IBOutlet NSImageView* winView;
}
and in the .m file,
- (void)awakeFromNib {
NSString *inFilePathwin = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"win.png"];
NSImage *winImage = [[[NSImage alloc] initWithContentsOfFile:inFilePathwin] autorelease];
[winView setImage:winImage];
}
So the image is working and showing so how do i link that function?
Hook the mouseDragged event on a NSView subview.
-(void)mouseDragged:(NSEvent *)theEvent
{
CGFloat deltax = [theEvent deltaX];
CGFloat deltay = [theEvent deltaY];
NSRect frame = [[self window] frame];
frame.origin.x += deltax;
frame.origin.y -= deltay;
[[self window] setFrameOrigin:frame.origin];
}
So
subclass NSView as XView
place your handle image in an instance of this view container.
Place the container where you want in the windows main view.
Use this snippet in XView to drag the window around.
Adjust the behaviour with the mouseDown and MouseUp events.

makeKeyAndOrderFront only does the latter

I am trying to open one window from another using makeKeyAndOrderFront. The new window appears, but does not receive focus.
The code for the main window is:
#import "SecondWindowController.h"
#implementation FirstWindowController
-(IBAction)showSecondWindow:(id)sender
{
if (!secondWindowController)
secondWindowController = [[SecondWindowController alloc] init];
[[secondWindowController window] makeKeyAndOrderFront:self];
}
SecondWindowController is a NSWindowController, as follows:
#implementation SecondWindowController
-(id)init
{
if (![super initWithWindowNibName:#"SecondWindow"])
return nil;
return self;
}
I've also tried putting [secondWindowController showWindow:self] before the makeKeyAndOrderFront but it doesn't make a difference.
Did you make sure the window outlet for SecondWindowController is hooked up to the window in your NIB? The window could be displayed just by loading the NIB, even if the outlet is not hooked up.
Are you using a borderless window? If so you need to override canBecomeKeyWindow and return YES
Try this:
if (!secondWindowController)
secondWindowController = [[SecondWindowController alloc] init];
NSApplication *thisApp = [NSApplication sharedApplication];
[thisApp activateIgnoringOtherApps:YES];
[[secondWindowController window] makeKeyAndOrderFront:self];

Resources