0

我正在尝试创建一种在全屏和窗口之间切换的方法。我试图从继承自 NSOpenGLView 的类中执行此操作,基本上遵循此 blogpost。一次有效,从窗口到全屏;尝试返回以各种方式失败:窗口屏幕没有更新,或者我什至没有管理切换到窗口但全屏只是空白。无论如何尝试来回几次(将其映射到'f'键),程序经常锁定,在最坏的情况下,我必须重新启动计算机。我附上了以下方法的代码;出于调试目的,我将全帧矩形设置得更小,这样如果冻结,应用程序永远不会全屏显示。

Apple 开发人员示例中的全屏示例建议使用控制器,并且不会从继承的 NSOpenGLView 中全屏显示。

我的问题:

  • 我应该改用控制器,然后在窗口和全屏之间切换(每次创建一个单独的全屏视图)?或者这两种方法都应该有效吗?
  • 如果这两种方法都应该有效,那么首选哪一种?
  • 如果这两种方法都可以工作,那么我在当前的实现方式中做错了什么?
  • 或者,是否有第三种更好的方法?

请注意,对于这两个参考,我必须假设 10.8 的情况没有改变(这两个参考似乎都适用于 10.6)。

代码如下:

@implementation MyOpenGLView

[...]

- (void)toggleFullscreen
{
    mainWindow = [self window];

    if (isFullscreen) {
        [fullscreenWindow close];
        [mainWindow setAcceptsMouseMovedEvents:YES];
        [mainWindow setContentView: self];
        [mainWindow makeKeyAndOrderFront: self];
        [mainWindow makeFirstResponder: self];
        isFullscreen = false;
    } else {
        [mainWindow setAcceptsMouseMovedEvents:NO];
        //NSRect fullscreenFrame = [[NSScreen mainScreen] frame];
        NSRect fullscreenFrame = { {300, 300}, {300, 300} };
        fullscreenWindow = [[NSWindow alloc] initWithContentRect:fullscreenFrame
                                                       styleMask:NSBorderlessWindowMask
                                                         backing:NSBackingStoreBuffered
                                                           defer:NO];
        if (fullscreenWindow) {
            [fullscreenWindow setAcceptsMouseMovedEvents:YES];
            [fullscreenWindow setTitle:@"Full screen"];
            [fullscreenWindow setReleasedWhenClosed: YES];
            [fullscreenWindow setContentView: self];
            [fullscreenWindow makeKeyAndOrderFront: self];
            //[fullscreenWindow setOpaque:YES];
            //[fullscreenWindow setHidesOnDeactivate:YES];
            // Set the window level to be just above the menu bar
            //[fullScreenWindow setLevel:NSMainMenuWindowLevel+1];
            // Set the window level to be just below the screen saver
            [fullscreenWindow setLevel:NSScreenSaverWindowLevel-1];
            [fullscreenWindow makeFirstResponder:self];

            isFullscreen = true;
        } else {
            NSLog(@"Error: could not switch to full screen.");
        }
   }
}

[...]

@end
4

2 回答 2

1

我现在认为这是做不到的,也不应该做的。当窗口化时,渲染上下文是一个窗口,当渲染全屏时,它是一个不同于屏幕的野兽。因此,在切换时,每次切换时都必须重新设置。

可以简单地使用最新 OS X 变体中的本机全屏选项。这将(可能)将包含窗口放大到全屏大小,同时删除框架、边框和按钮。因此,尽管它看起来是全屏的,但您仍在渲染到一个窗口。

我不确定这个选项是否会使事情变慢:中间有一个窗口层,这可能比直接渲染到屏幕要慢。

对于好奇的人,实现原生全屏非常简单(至少在 10.8 和 10.9 中):在 XCode 中,选择.xib文件,选择编辑器侧边栏中的(主)窗口,然后选择右侧的属性选择器。您可以在 Unsupported、Primary Window 或 Auxiliary Window 之间找到“全屏”选项。这将自动将全屏切换添加到窗口。更简洁,现在选择主菜单 -> 侧边栏中的查看菜单,在底部的检查器中找到“全屏菜单项”(有一个搜索栏),将其拖到编辑器中的查看菜单中,然后瞧,它将有一个快捷方式并自动连接到窗口的全屏选项(选择新的查看菜单项并查看连接检查器是否已为您连接)。

测试所有这些的一个好方法是获取我在问题中链接的全屏示例,并按照上面的建议进行编辑。使用默认的控制命令 F 快捷方式在全屏之间来回切换将全屏显示 opengl 视图及其下方带有文本的框架。使用示例中编码的全屏选项将切换 openglview 以使用全屏,没有任何额外的 (Cocoa) 框架、按钮或文本。

于 2014-04-20T16:11:41.353 回答
0

我对此也很好奇-特别是您的前两个要点问题。

这并没有解决这些问题,但是您关于该错误的第三个问题,我认为您只需更改同一窗口的属性就可以逃脱(对我有用):

- (void)toggleFullscreen
{
    if (isFullscreen) {
        NSRect windowFrame = [[NSScreen mainScreen] visibleFrame];
        [mainWindow setStyleMask:NSTitledWindowMask | NSClosableWindowMask |
                             NSMiniaturizableWindowMask | NSResizableWindowMask ];
        [mainWindow setFrame:windowFrame display:true];
        [mainWindow setAcceptsMouseMovedEvents:YES];
        [mainWindow setLevel:NSNormalWindowLevel];
        [mainWindow setTitle:@"SimpleOculus"];
        [mainWindow makeKeyAndOrderFront:self];
        [mainWindow makeFirstResponder:self];
        isFullscreen = false;
    }
    else {
        NSRect fullscreenFrame = [[NSScreen mainScreen] frame];
        [mainWindow setStyleMask:NSBorderlessWindowMask];
        [mainWindow setFrame:fullscreenFrame display:true];
        [mainWindow setAcceptsMouseMovedEvents:YES];
        [mainWindow setLevel:NSScreenSaverWindowLevel-1];
        [mainWindow makeKeyAndOrderFront:self];
        [mainWindow makeFirstResponder:self];
        isFullscreen = true;
    }
}
于 2014-02-04T11:44:33.733 回答