Cocoa window position anomaly - objective-c

I have a weird problem with positioning a window on screen. I want to center the window on the screen, but i don't know how to do that. Here's what i've got. The window is created from nib by the main controller:
IdentFormController *ftf = [[IdentFormController alloc] initWithWindowNibName:#"IdentForm"];
[[ftf window] makeKeyAndOrderFront:self];
Now the IdentFormController has awakeFromNib() method in which it tries to position the window. For the sake of simplicity i've just tried to do setFrameOrigin(NSMakePoint(0, 0)). What happens is as follows:
The first time i create this window, everything works as expected. But if i create it again after releasing the previous, it starts appearing at random positions. Why does it do that?

So as I understand it you want to center the window on the screen?
Well assuming NSWindow *window is your window object then there are two methods...
[window center];
This is the best way to do it but it will ofset to take into account visual weight and the Dock's presence.
If you want dead center then this would work...
// Calculate the actual center
CGFloat x = (window.screen.frame.size.width - window.frame.size.width) / 2;
CGFloat y = (window.screen.frame.size.height - window.frame.size.height) / 2;
// Create a rect to send to the window
NSRect newFrame = NSMakeRect(x, y, window.frame.size.width, window.frame.size.height);
// Send message to the window to resize/relocate
[window setFrame:newFrame display:YES animate:NO];
This code is untested but it gives you a fair idea of what you need to do to get this thing working the way you want, personally I would advise you stick with Apple's code because it has been tested and is what the user would expect to see, also from a design perspective as a designer my self I don't always rely on the actual center to be where the optical center is.

You're probably running afoul of automatic window positioning. Have you tried calling
[myWindowController setShouldCascadeWindows: NO];
?

First of all, it sounds like you need to check "dealloc on close" or "release on close" in the NSWindow's property inspector. Then the window will clean up after itself and you can remove the (risky) call to [self release] in your own code.
awakeFromNib is called after all objects from the nib have been unarchived and outlets have been connected, but that may be too early to be setting the window coordinates. I believe Cocoa does some work to automatically position subsequent windows below and to the right of existing windows, so that new windows don't completely obscure old ones. It is likely doing this AFTER you set the position in awakeFromNib, stomping on your changes.
The best place to set your window position is probably in one of the NSWindow delegate methods (windowWillBecomeVisible: perhaps), or possibly right before you call makeKeyAndOrderFront:.

Check out if you can set the centre of your window with the centre of your screen. And set the window position on it. It might work out.

Related

Find the top-most NSView object located under NSPoint position

I know this question was already asked here in few forms but unfortunately non of the suggested solutions worked for me.I am implementing a multi-touch capability for my osx app.My problem:I need to resolve a location on the screen, described by NSPoint in screen coordinates, to the very top NSView object from my application that resides under this location (if any).This is a bit like HWND WindowFromPoint( Point) under Windows OS.
Few points to consider:
My application manage several NSWindows, where each window contains an hierarchy of several NSViews,
The NSView that I am interested in is not necessarily the application Key Window or Main Window, as it can be any of my other currently non-active NSView objects that happen to be under this screen location,
It is possible that under a particular NSPoint I will have more then one NSWindows and/or NSViews. In this case I wll be interested only in the very top-most NSView,
It is possible that NSView A is on top of NSView B, partialy hiding it, but the NSPoint location is present only on B, which is not the very top-most window of the application (but only the very top-most for this location). Here again I will be interested in B.
Things that I managed todo:
Enumerate NSApp for all its windows (NSApp.windows),
Enumerate NSWindow for its views (NSWindow.contentView.subviews),
Enumerate NSView for its sub-views (NSView.subviews)
Doing this I managed to enumerate all NSViews of my application, but I still need to filter out non-relevant NSViews, which are not visible.
Things that did not work for me:
NSView.hitTest returned nil for valid locations,
NSView.layer.zPosition alwyas is zero (0),
The order of the NSView.subviews list also does not reflacts the current GUI layout,
Testing if NSView is Visible also did not help as it returns true also if this window is hidden by other window.
My environment:Mac, OSX El-Capitan, XCode-7, Cocoa, Objective-C
Thanks for any help!PazO
Found it:
// 1. Get the Window-Number of the NSWindow object owning this point:
NSInteger wndNumber = [NSWindow windowNumberAtPoint:(point) belowWindowWithWindowNumber:(0)];
// 2. Get the NSWindow object associated with this particular Window-Number:
NSWindow* window = [NSApp windowWithWindowNumber:(wndNumber)];
// 3. Convert NSPoint values from System-coordinates to NSWindow-coordinates (Thanks #Willeke for his comment)
NSRect rctScreen;
rctScreen.origin = point;
rctScreen.size.height = rctScreen.size.width = 0;
NSRect rctWindow = [window convertRectFromScreen:rctScreen];
// 4. Now do the hitTest:
NSView* viewFound = [[window contentView] hitTest:rctWindow.origin];
Obviously each line should be tested for nil, but I leave this out for code brevity.

NSTextfield not accepting keyevents on NSWindow which has NSTitledWindowMask

I have started coding cocoa app. I have created a NSwindow with initWithContentRect.
I have created a NSTextField. I can not get any of the keyboard events. It is selectable. I also explicitly set editable to true.
I have realized there are similar questions but they are mostly about the responder, key window and Borderlesswindow style.
I have a NSWindows which has a titled window mask , is the key window and it is selected when I set it to be the first responder.
But why cant I type anything into the box.
int style = NSClosableWindowMask |NSTexturedBackgroundWindowMask | NSTitledWindowMask | NSMiniaturizableWindowMask;
window = [[NSWindow alloc] initWithContentRect:NSMakeRect(0, 0, 130, 150)
styleMask:style backing:NSBackingStoreBuffered defer:NO];
CGFloat height=20;
NSTextField * username=[[NSTextField alloc] initWithFrame:NSMakeRect(10, NSHeight(window.frame)-80, 100, height)];
[username setEditable:true];
[window.contentView addSubview:username ];
Is it because I need to create a subclass of NSwindow. I see this is suggested when the style is NSBorderlessWindowMask and by overriding
canBecomeKeyWindow it is suggested to solve the issue.
But I am not using NSBorderlessWindowMask.
What am I missing? Any help is appreciated.
From your comment, you say you don't have a Info.plist file. I'm guessing your app isn't even bundled. This is a crucial fact that you left out of your question, which only makes it hard for people to help you.
First, you should create apps the normal way. Make a bundled app with a main NIB. Follow the standard template, except delete the window from the main NIB and use separate window NIBs.
If you aren't equipped to understand what's going wrong with a "manually" constructed app and fix it, then you really shouldn't be going that route.
That said, an unbundled app will start life as a background-only process. What little interactivity you're seeing is, more or less, a bug. You can transform your app into a foreground app by setting the activationPolicy of the application object (instance of NSApplication or a subclass) to NSApplicationActivationPolicyRegular. Then, make it the active app by calling [NSApp activateWithOptions:NSApplicationActivateIgnoringOtherApps].

How do I change my cursor on the whole screen? (not only current view/window)

I'm currently learning objective c and I'm trying to write some simple apps to help me learn. Right now, I'm trying to make an app that lets me measure a certain area anywhere on the screen. (similar to this: https://addons.mozilla.org/de/firefox/addon/measureit/)
For that to work, I need to know how I can change my cursor anywhere on the screen, Not only within a certain window (I already got that to work).
Currently I have a class called "MyCustomView" that is assigned to my main window view. I implemented the resetCursorRects-method like this:
- (void) resetCursorRects {
[super resetCursorRects];
NSCursor *myCursor = [NSCursor crosshairCursor];
CGRect screenRect = [[NSScreen mainScreen] frame];
[self addCursorRect:screenRect cursor:myCursor];
}
It successfully changes my cursor to crosshair, but only within the current window. I want my cursor to change for all of the screen. How can I accomplish this?
Thank you for your help, guys!
You can create NSCursor instance and then invoke set method
[[[NSCursor alloc] initWithImage:[NSImage imageNamed:#"myCursor.png"] hotSpot:NSZeroPoint] set]
But other windows will change it, so i think you need a Window with 0.0 opacity overlaying all screen.
You can do it by setting window level. [window setLevel:NSScreenSaverWindowLevel]

Clicking through NSWindow/CALayer

So I'm working on an issue I have when trying to do some simple animation using CAKeyframeAnimation, and I believe my problem is more related to not fully understanding how NSWindow, NSView, and CALayer work together. 
I have two main objects in question. MyContainerWindow (NSWindow subclass) and MyMovableView (NSView subclass). My goal is to be able to animate MyMovableView back and forth across the screen, while maintaining the ability to click on anything through MyContainerWindow unless you are clicking on wherever MyMovableView is. I am able to accomplish the first part fine, by calling -addAnimation:forKeyPath: on myMovableView.layer, and everything is great except I can't click through MyContainerWindow. I could make the window smaller, but then the animation would clip by the bounds of the window.
Important points: 
1) MyContainerWindow is initWithFrame to [[NSScreen mainScreen] frame], NSBorderlessWindowMask, defer no, buffered
2) I setWantsLayer:TRUE to MyMovableView
3) MyContainerWindow is clear, and I want it to be as if there wasnt a window at all, but need it so I have a larger canvas to animate on.
Is there something obvious I'm missing to be able to click through an NSWindow?
Thanks in advance!
My solution in this scenario was actually to use:
[self ignoresMouseEvents:YES];
I originally was hoping to be able to retain the mouse events on the specific CALayer that I'm animating, but upon some further research I understand this comes with the cost of custom drawing everything from scratch, which is not ideal for this particular project.

what am I doing wrong in attempt to popup a web view and then allow user to go back

my app has tabBarController with 3 views and in one of them I want to popup a web browser with the ability to return back to the application. To do that I am using UINavigationController.
In myAppDelegate.h I have defined the property UINavigationController *nav and in myAppDelegate.m I have #synthesize nav.
In the class where the webPopup function resides upon pressing the button my code comes to this function.
- (IBAction)showWeb:(id)sender {
myAppDelegate *app=[[UINavigationController alloc] initWIthRootViewController:self];
// because I want to return back to the same view
webController *web = [[webController alloc] initWithStyle:UITableViewStypeGrouped];
[app.nav pushViewController:web animated:YES];
app.nav.view.frame = CGRect(,0,320,430);
[self.view.window addSUbview:app.nav.view];
}
The web popup occurs but it is moved vertically, when I press "back button" my former view appears as well and it is also shifted vertically from what it was before.
After going back and forth few times the thing hangs.
Questions:
1. what can cause the shift?
2. how to avoid when I go "back" to see the title(test from the "back"button, I think this might cause a shift when I go back.
3. how to find out why it hangs after few attempt?
Thanks.
Victor
The line:
myAppDelegate *app=[[UINavigationController alloc] initWIthRootViewController:self];
makes no sense to me. Surely your compiler is warning you about that? What is "myAppDelegate" defined as? Classes should have a capital letter at the front, by the way.
Also, the line
[self.view.window addSUbview:app.nav.view];
is highly suspect, because the UIWindow for your application should have only one child UIView. You shouldn't just add more views willy nilly and expect things to work. It is possible to change the child UIView by removing the old one and adding a new one, but you don't seem to be doing that. Having more than one child UIView of UIWindow gets you into trouble very quickly -- for example, device orientation changing can break.
I'm not exactly clear as to why the app delegate (or the window for that matter) needs to be messed with at all to do what you are trying to do. Sounds like you should just be using standard Nav View Controllers and Web Views.
Also, you are alloc init'ing w/o any memory management.