In my 3D application, I handle NSWindowWillCloseNotification to perform cleanup (stop display link, release resources, etc.). The app can run in two modes, OpenGL and Metal. There is a ViewBase class that implements common functionality and among other things handles the notification.
Everything works fine in OpenGL mode, however in Metal mode, the NSWindowWillCloseNotification is received when exiting fullscreen window causing the app to stop showing anything. The only meaningful difference between Metal and OpenGL is that Metal view uses backing layer, but I do not know why this may matter.
I am totally confused why this could be happening and would appreciate any help.
As it turned out, I was setting notification handler in awakeFromNib, where [self window] was nil. So notification handler was set of null window. I fixed the problem by referencing the main application window instead: auto* mainWindow = [[NSApplication sharedApplication] mainWindow];
Related
I have been making iOS apps for a while now and I decided that I wanted to start working on making some of them for the Mac too.
The question I have is this: is there any need for an NSWindow, now that developing for the Mac is so similar to iOS??
So I made a simple cocoa application using Xcode and its comes with a storyboard called "Main", just like on iOS.
In that storyboard file, there is a NSWindow which then links to a NSViewController.
Can I get rid of that NSWindow? As I tried setting the NSViewController as the "Initial Controller" and the app still works fine. So whats the point of the NSWindow?
Also, what class links to the NSWindow? I was trying to blur that background of the NSWindow, but I have no way of linking code to the NSWindow.
Sorry for my stupid questions, but I am completely new to development for OS X.
Thanks for your time, Dan.
Those are many questions in one question:
Can I get rid of NSwindow? No, you need a window to show you views.
What is the point of the NSWindow? NSWindow is needed as the window in which the views are displayed and your events are going up the responder chain.
What class is linked to NSWindow? Obviously the NSWindow class, but that is not what you want to know. I think you want to know the delegate that controls NSWindow. This is NSWindowController, although for the MainMenu.xib it is NSAppDelegate.
Hope this gives you the answers you need. An example for working with views in a window is given in this question.
Please, see for further details the windows programming guide, which states:
The NSWindow class defines objects that manage and coordinate the
windows an application displays on the screen. A single NSWindow
object corresponds to at most one onscreen window. The two principal
functions of an NSWindow object are to provide an area in which NSView
objects can be placed and to accept and distribute, to the appropriate
views, events the user instigates through actions with the mouse and
keyboard.
For the question: Can I get rid of NSwindow? I have further comments. In most cases, You need a NSWindow to show view on screen; but in special case you don't, for example, a popup view when you click a NSStatusItem.
So my answer is whenever you need to respond window event such as min/max, you need NSWindow as the view container.
At the moment I am experiencing a really weird behavior of my Mac App.
On my Mac (and on all other testing Macs) everything works fine. The app simply works, no leaks,...
BUT on all the review Macs (Yes, on all) it fails: First the launch failed and now, after submitting it more times and trying to workaround the bug, it does not get initialized: Icons that should get loaded dynamically are not shown.
WHY?! Perhaps anyone has made experiences with such a problem because I cannot test it. I try to find the issue but it's nearly impossible.
[EDIT]
App Information:
My app should list all the currently running applications and display them in some way. It reads no files, only the NSUserDefaults to setup itself.
Structure:
appDidFinishedLaunching setups basic stuff like global hotkeys, loads the NSUserDefaults and finally forwards the message to the subclassed main window (<- There is the problem).
There it should load its interface which does not work on review Macs.
I was able to "override" or "fix" this by a little, dirty code snippet but it does not fix the main problem:
//AppDelegate.m
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
[self performSelector:#selector(didLaunch) withObject:nil afterDelay:0.5f];//<- THIS does the trick, so that the app launches and shows the static content of the NIB, but NO dynamic content is displayed: exactly the same nib state
//Register hotkeys, load NSUserDefaults,
[mainview launched];//<- Here is the problem
finishedLaunching=1;//global var
}
-(void)didLaunch//Launching works
{
if (finishedLaunching==0) {//=0 because of the review results
//Does all the stuff that [mainview launched]; is supposed to do: Display window and setup position
//Calling methods included in main view does not work (OR the window is not refreshed
//so the first start finally works, but the interface is EMPTY, only static content visible
}
}
Does the setup not happen because it is done in its subclassed window?
Why does it work on my Mac (and another Mac mini)?
Do you know why this happens, a way how to correct it or how to reproduce the bugs?
I really need your help and appreciate every tip!
Since several days I am trying to resolve the folowing issue, reading all I found around the web about npapi on mac.
The goal is to have a npapi plugin which works for safari and firefox(mac).
My software (that I can not rewrite specialy for this purpose hase about 45000 lines of C code) is based on a NSView attached to a NSDocument....
I have a webkit version based plugin that I must trash (thanks to Apple!) based to the same NSView.
I have a npapi version plugin which works fine on firefox. In this npapi plugin, I take the carbon window ref, I make a NSWindow based on that:
NSWindow *browserWindow = [[[NSWindow alloc] initWithWindowRef:wind]autorelease];
and I put my NSView on this window and that works.
Now the pb is that I can not do the same thing on safari.
Look at attached picture, the window is not in the safari's window!
I tryed several ways... it dose not work.
Can a cocoa's gourou says where I am making something wrong? or is this a known issue?
NPError NPP_SetWindow(NPP instance, NPWindow* window){
NP_CGContext *ctx = window->window;
void *wind = ctx->window;
...
in the NSView init function:
NSWindow *browserWindow = [[NSWindow alloc] initWithWindowRef:wind];
self = [super initWithFrame:frame];
if( self )
{
[browserWindow makeFirstResponder: self];
[self setNextResponder: nil];
[browserWindow setContentView:self];
[self webPlugInInitialize];// my own initializing
}
return self;
In Safari 5.1, the web rendering is not done by Safari itself, but on a different process to enhance security. Open up the Activity Monitor, and you see that background process called "Safari Web Process" or something like that.
So, you can't and shouldn't create NSWindow based on the Carbon window ref which can be obtained within NPAPI plugin.
Read Apple's own documentation on this point. You should request the core graphics drawing method, and then the WindowRef field of NP_CGContext should have a NSWindow*, not the Carbon window ref.
If it works on Firefox, that's totally shocking and completely unsupported. Does it work in Firefox 4 and later?
If you absolutely have to use an NSView, the only way that I know to do it in a plugin is to render the NSView into your CGContext. Keep in mind that in newer NPAPI browsers with the Cocoa event system you get the CGContextRef as part of the draw event; to request a draw event you can call NPN_InvalidateWindow.
FireBreath has a completely experimental and not-fully-functional example of rendering an NSView (ans specifically a WebView) into a CGContextRef that you could look at as an example.
Other than using a CGContextRef your only other choice is to use a CALayer; if you can find a way to make a NSWindow or NSView in that you could be okay, but I don't know if there is one. Someone suggested that setting the CALayer as the rendering layer for the NSView might work. Either way you'll most likely have to forward all the events since you are basically hosting the NSView in an offscreen view.
Make no mistake; there is no supported way to get an NSView in the browser. There never has been -- methods that people have used were unsupported and depended on browser-specific implementations of the API. When you use things like that, you can reliably expect them to eventually break, such as in this case. For more information on the drawing models, you could read Stuart Morgan's blog post on the subject, check out the FireBreath mac drawing model docs, or read the Cocoa event model spec.
Given that you start with "take the carbon window ref", your approach is doomed, because it is based on the Carbon event model (and not just that, but assumptions about its internal implementation details). Anyone running Firefox on a 64-bit system will have to manually restart Firefox in 32-bit mode for your hack to work, and even then it will only work until Firefox completely removes Carbon support (which is planned for the foreseeable future).
As the other answers said, where you are going wrong is that your whole approach is completely unsupported, and the fact that it ever worked at all as an NPAPI plugin was luck. You simply cannot use an NSView directly in an NPAPI plugin.
Now I am porting some OpenGL tutorials from win/glut to cocoa/mac os x. In the windowed mode everything works, but when context switches to fullscreen, screen may be empty (only clear colour)! For example: in the first, second, third times cube is, but in the fourth time cube is not. Even if app launches in fullscreen without sharing context. I don`t understand.
Xcode 3.2.1, Mac OS X 10.6.2
source link
It looks like AFController's enterFullScreen method probably needs to set up the OpenGL context ([scene initGL]).
Also, awakeFromNib may be called before the application is ready to draw, so perhaps it's not the best place for [scene initGL]. I suggest implementing NSApplication's delegate method, applicationDidFinishLaunching:, and moving [scene initGL] there. Just to be safe, you might also try calling NSOpenGLContext's makeCurrentContext from there as well.
Can anyone provide a sample / link to a sample Cocoa app that changes the 'hardware' cursor in a fullscreen OpenGL Cocoa app? I have been able to create a full screen GL app and an app that changes the cursor by overriding NSView::resetCursorRects but I have not been able to get both to work simultaneously. I've also refitted some of the Apple GL samples (CocoaGL, Custom Cocoa OpenGL, etc) by overriding NSView::resetCursorRects and I haven't been able to get the cursor to change in fullscreen in them either. I have the book "OpenGL Programming on Mac OS X" which also avoids the problem.
#Christopher: I hadn't tried [NSCursor set]. Good call but I made a run at it and no luck. It still returns to the system cursor. I'd say that perhaps something is overriding it in my calls that switch to fullscreen but I've actually tried reseting the mouse cursor in my NSView's draw routine (which gets called repeatedly) and the cursor never switches from the system default.
Try using NSCursor directly, the NSView cursor rect methods depend on things such as a properly sized and visible NSWindow to work properly which aren't necessarily the case in full screen mode.