I’ve got an OpenGL MacOS game, my MacOS is 10.13.4 with all recent updates.
When the game switches windowed -> fullscreen, everything is fine.
When is switches fullscreen->windowed it renders the full screen white, while in focus, but it renders fine when it not in focus.
And the game runs initially fine both in fullscreen and windowed modes.
The code is quite old, this is not the first game uses this code, and I don’t remember I saw this issue on previous MacOS versions.
Here is my code:
- (void)toggleFullscreen:(const bool)value
{
if (value)
{
if (mFullScreenWindow)
return;
mFullScreenWindow = [[GameFullscreenWindow alloc] init];
NSRect viewRect = [mFullScreenWindow frame];
[mGameView stopDisplayLink:YES];
[mGameView setFrameSize: viewRect.size];
[mFullScreenWindow setContentView:mGameView];
[mFullScreenWindow makeKeyAndOrderFront:self];
RendererGLOSX::SaveDisplaySize(Vec2(viewRect.size.width, viewRect.size.height));
}
else
{
if (mFullScreenWindow == nil)
return;
NSRect viewRect = [mWindow contentRectForFrameRect:[mWindow frame]];
[mGameView stopDisplayLink:YES];
[mGameView setFrame:viewRect];
[mWindow setContentView:mGameView];
[mWindow makeKeyAndOrderFront:self];
[mFullScreenWindow release];
mFullScreenWindow = nil;
RendererGLOSX::SaveDisplaySize(Vec2(viewRect.size.width, viewRect.size.height));
}
[mGameView stopDisplayLink:NO];
}
That was mFullScreenWindow rendered.
The issue was fixed by adding [mFullScreenWindow orderOut: self] before [mFullScreenWindow release].
Related
I try to show/hide the title bar in a cocoa app. I use following code :
if ([window styleMask]==NSResizableWindowMask) {
[window setStyleMask:NSMiniaturizableWindowMask|NSClosableWindowMask|NSResizableWindowMask|NSTitledWindowMask];
}else{
[window setStyleMask:NSResizableWindowMask];
}
It works well before 10.10 but fails in 10.10. In 10.10, when the title bar is shown, the title, close/minimize/resize buttons are unshown. Only user resizes the window, those things will be shown.
I guess that something needs to be 'Flush' and hence I also try to add:
[window update];
[window display];
[[NSApplication sharedApplication] setWindowsNeedUpdate:YES];
[[NSApplication sharedApplication] updateWindows];
But all is failed.
Could anyone give any suggestion? Thanks!
This is an interesting issue. Can you file a bug report with Apple?
In the meantime, here is a hack that seems to fix the issue:
if ([window styleMask] == NSResizableWindowMask) {
NSDisableScreenUpdates();
[window setStyleMask:(NSMiniaturizableWindowMask|NSClosableWindowMask
|NSResizableWindowMask|NSTitledWindowMask)];
NSRect frame = [window frame];
frame.size.width += 1;
[window setFrame:frame display:NO];
frame.size.width -= 1;
[window setFrame:frame display:YES];
NSEnableScreenUpdates();
} else {
[window setStyleMask:NSResizableWindowMask];
}
(In addition, it seems that you will have to manually restore the title with setTitle:.)
Use
dispatch_async(dispatch_get_main_queue(), ^{
if ([window styleMask]==NSResizableWindowMask)
{
[window setStyleMask:NSMiniaturizableWindowMask|NSClosableWindowMask|NSResizableWindowMask|NSTitledWindowMask];
}
else
{
[window setStyleMask:NSResizableWindowMask];
}
});
it works in my case.
I am facing a weird issue when trying to make a full screen application. I am currently using a a NSWindow with a NSBorderlessWindowMask to make the screen show at top, and I subclassed NSWindow to accept keys:
- (BOOL) canBecomeKeyWindow
{
return YES;
}
This works fine, and I can use keys in my window, and quit out of the application with Command + Q. However, when I try to force quit the application on my Mac, the screen freezes, and I must restart my computer. I have a simple WebView inside my Window:
mainWindow = [[MyBorderWindow alloc] initWithContentRect:screenRect
styleMask:NSBorderlessWindowMask
backing:NSBackingStoreBuffered
defer:NO screen:[NSScreen mainScreen]];
[mainWindow setLevel:windowLevel];
[mainWindow setBackgroundColor:[NSColor blackColor]];
[mainWindow makeKeyAndOrderFront:nil];
NSView *contentView = [mainWindow contentView];
WebView *customView = [[WebView alloc] initWithFrame:[contentView bounds]];
[customView setTranslatesAutoresizingMaskIntoConstraints:NO];
[contentView addSubview:customView];
I have tried the application on another computer, and force quit does not freeze the screen. Both computers are running OS X Mavericks.
Please let me know if there is anything else I should add.
Thanks in advance,
Bucco
Edit:
I think that my applicationWillTerminate method in AppDelegate might be part of the issue, but am not sure. Why would this method work fine on another computer, but not mine?
- (void)applicationWillTerminate:(NSNotification *)notification
{
[mainWindow orderOut:self];
// Release the display(s)
if (CGDisplayRelease( kCGDirectMainDisplay ) != kCGErrorSuccess) {
NSLog( #"Couldn't release the display(s)!" );
}
}
I have an NSOpenGLView and OpenGL code that works with an NSTimer running in the main loop (calling setNeedsDisplay and drawRect). I would like to use a CVDisplayLink, so I can get a better frame-rate without overdriving the timer. I copied most of the code from apple's OSXGLEssentials example. The display link starts and the callback runs, but nothing is actually draw on screen. glGetError returns GL_INVALID_FRAMEBUFFER_OPERATION.
glCheckFramebufferStatus returns GL_FRAMEBUFFER_UNDEFINED for GL_FRAMEBUFFER, GL_DRAW_FRAMEBUFFER and GL_READ_FRAMEBUFFER.
Info from the documentation:
GL_FRAMEBUFFER_UNDEFINED is returned if target is the default
framebuffer, but the default framebuffer does not exist.
Here are the relevant bits of code:
- (void)awakeFromNib {
NSOpenGLPixelFormatAttribute attributes[] = {
NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core, // Core Profile !
NSOpenGLPFADoubleBuffer,
NSOpenGLPFAAccelerated,
NSOpenGLPFAColorSize, 24,
NSOpenGLPFAAlphaSize, 8,
NSOpenGLPFAAllowOfflineRenderers,
0
};
NSOpenGLPixelFormat *format = [[NSOpenGLPixelFormat alloc] initWithAttributes:attributes];
NSOpenGLContext *context = [[NSOpenGLContext alloc] initWithFormat:format shareContext: nil];
// [context setView: self];
[self setPixelFormat: format];
[self setOpenGLContext: context];
}
- (void)prepareOpenGL {
[super prepareOpenGL];
NSOpenGLContext* context = [self openGLContext];
[context makeCurrentContext];
// Synchronize buffer swaps with vertical refresh rate
GLint swapInt = 1;
[context setValues:&swapInt forParameter:NSOpenGLCPSwapInterval];
MyDisplay_setup();
MyDisplay_initScene(_bounds.size.width, _bounds.size.height);
CVDisplayLinkCreateWithActiveCGDisplays(&displayLink);
CVDisplayLinkSetOutputCallback(displayLink, &displayLinkCallback, (__bridge void *)self);
CGLPixelFormatObj cglPixelFormat = [[self pixelFormat] CGLPixelFormatObj];
CVDisplayLinkSetCurrentCGDisplayFromOpenGLContext(displayLink, [context CGLContextObj], cglPixelFormat);
CVDisplayLinkStart(displayLink);
}
static CVReturn displayLinkCallback(CVDisplayLinkRef displayLink, const CVTimeStamp* now, const CVTimeStamp* outputTime,
CVOptionFlags flagsIn, CVOptionFlags* flagsOut, void* displayLinkContext) {
#autoreleasepool {
[(__bridge MyView*)displayLinkContext redraw];
}
return kCVReturnSuccess;
}
- (void)redraw {
NSOpenGLContext* context = [self openGLContext];
[context makeCurrentContext];
CGLLockContext([context CGLContextObj]);
MyDisplay_drawScene();
CGLFlushDrawable([context CGLContextObj]);
CGLUnlockContext([context CGLContextObj]);
}
This is an old question, but this problem still persists, so here's my answer. For reference, i don't use Xcode at all, i write code in Vim and compile with Clang, so this is the default behaviour, and nothing to do with the IB. I use only the NSOpenGLView, NSOpenGLContext, and CGDisplayLink for rendering. I have a MacBook Pro (Retina, 15-inch, Mid 2014) running macOS Sierra.
While debugging i found that NSOpenGLContext's view property returned nil for the first few frames after starting the display link. This was enough to corrupt the context if you did any rendering (other than glClear) while the view wasn't attached, and caused the same GL_FRAMEBUFFER_UNDEFINED error.
The easiest way to solve this, i found, was to assign the NSOpenGLView to its NSOpenGLContext after creation like this:
NSOpenGLView *view = ...;
view.openglContext.view = view;
I'm baffled that, apparently, it's necessary to do this even though the NSOpenGLContext is created by the NSOpenGLView, but there it is.
The trick is to open the View Effects inspector and uncheck the parent View in the Core Animation Layer section.
I see a lot of questions about this subject but am unable to find a solution to the problem I am experiencing. I have created an iPad app that should be Landscape only - it works fine when ran on any os prior to iOS6 but on iOS6 the app opens in portrait view. This screenshot shows what I mean (sorry not a great explanation) http://s1342.beta.photobucket.com/user/designedbyria/media/ScreenShot2012-11-02at122113.png.html
I'm guessing the problem is somewhere in the below code, but I can't be sure. I have set the supported Interface Orientations to Landscape Left and Landscape Right only - but this has not worked. I have also taken a look at the questions here with no luck..
I am using xcode and cordova/phonegap
Interface orientation in iOS 6.0
Set orientation to landscape mode in xcode 4.5 GM IOS 6
iOS 6 apps - how to deal with iPhone 5 screen size?
Thanks in Advance!
/**
* This is main kick off after the app inits, the views and Settings are setup here. (preferred - iOS4 and up)
/
- (BOOL) application:(UIApplication)application didFinishLaunchingWithOptions: (NSDictionary*)launchOptions {
NSURL* url = [launchOptions objectForKey:UIApplicationLaunchOptionsURLKey];
NSString* invokeString = nil;
if (url && [url isKindOfClass:[NSURL class]]) {
invokeString = [url absoluteString]; NSLog(#"iwill launchOptions = %#", url);
}
CGRect screenBounds = [[UIScreen mainScreen] bounds];
self.window = [[[UIWindow alloc] initWithFrame:screenBounds] autorelease];
self.window.autoresizesSubviews = YES;
CGRect viewBounds = [[UIScreen mainScreen] applicationFrame];
self.viewController = [[[MainViewController alloc] init] autorelease];
self.viewController.useSplashScreen = YES;
self.viewController.wwwFolderName = #"www";
self.viewController.startPage = #"index.html";
self.viewController.invokeString = invokeString;
self.viewController.view.frame = viewBounds;
// check whether the current orientation is supported: if it is, keep it, rather than forcing a rotation
BOOL forceStartupRotation = YES;
UIDeviceOrientation curDevOrientation = [[UIDevice currentDevice] orientation];
if (UIDeviceOrientationUnknown == UIInterfaceOrientationLandscapeLeft) {
// UIDevice isn't firing orientation notifications yet… go look at the status bar
curDevOrientation = (UIDeviceOrientation)[[UIApplication sharedApplication] statusBarOrientation];
}
if (UIDeviceOrientationIsValidInterfaceOrientation(curDevOrientation)) {
for (NSNumber *orient in self.viewController.supportedOrientations) {
if ([orient intValue] == curDevOrientation) {
forceStartupRotation = YES;
break;
}
}
}
if (forceStartupRotation) {
NSLog(#"supportedOrientations: %#", self.viewController.supportedOrientations);
// The first item in the supportedOrientations array is the start orientation (guaranteed to be at least Portrait)
UIInterfaceOrientation newOrient = [[self.viewController.supportedOrientations objectAtIndex:0]
intValue];
NSLog(#"AppDelegate forcing status bar to: %d from: %d", newOrient, curDevOrientation);
[[UIApplication sharedApplication] setStatusBarOrientation:newOrient];
}
[self.window addSubview:self.viewController.view];
[self.window makeKeyAndVisible];
return YES; }
I had the same problem (but not using cordova/phonegap).
You have to set your view controller as a RootViewController in your appDelegate instead of just adding as a subview.
Replace in you appdelegate:
[self.window addSubview:self.viewController.view];
[self.window makeKeyAndVisible];
By
[self.window setRootViewController:self.viewController];
[self.window makeKeyAndVisible];
You can use the delegate
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
return UIInterfaceOrientationLandscapeLeft;
}
Using this delegate and the application will be present in Landscape mode or any desired orientation mode.
Try it.
I have a MPMoviePlayerController on my iPad app that works good when its frame is regular (not fullscreen).
When I tap the fullscreen button, the player goes fullscreen, but the movie stops. I perpetually see the title "Loading...", a black background, and the standard controls (back, play and next) disabled.
I declare an instance variable for the player:
MPMoviePlayerController *player;
In my implementation:
MPMoviePlayerController *player = [[MPMoviePlayerController alloc] initWithContentURL:videoUrl];
player.shouldAutoplay = NO;
player.movieSourceType = MPMovieSourceTypeFile;
player.controlStyle = MPMovieControlStyleEmbedded;
player.allowsAirPlay = YES;
player.view.frame = CGRectMake(xPos, yPos, width, height);
[self.view addSubview:player.view];
[player prepareToPlay];
Do you have any idea? I'm using iOS 6 SDK, and I'm testing the app on iPad 6.0 simulator and a real iPad2 with iOS 6 beta (latest).
OMG!!!
I wrote...
[player stop];
in viewWillDisappear!!! How could I be so stupid?! No cake tonight...