NSOpenGLView переключается в полноэкранный режим из представления

Я пытаюсь создать метод, который будет переключаться между полноэкранным режимом и окном. Я пытаюсь сделать это из класса, унаследованного от NSOpenGLView, по существу следуя это сообщение в блоге. Это работает один раз при переходе из оконного режима в полноэкранный; попытка вернуться назад терпит неудачу по-разному: экран окна не обновляется, или мне даже не удается переключиться в окно, но полноэкранный режим просто гаснет. В любом случае, пытаясь несколько раз перейти туда и обратно (сопоставил это с клавишей «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

person Community    schedule 13.05.2013    source источник


Ответы (2)


Теперь я думаю, что этого нельзя делать и не следует делать. В оконном режиме контекстом рендеринга является окно, которое отличается от экрана при рендеринге в полноэкранном режиме. Таким образом, при переключении между ними все приходится перенастраивать каждый раз, когда вы переключаетесь.

Можно просто использовать собственный полноэкранный режим, который есть в новейших вариантах OS X. Это (предположительно) увеличит содержащее окно до полного размера экрана, удалив при этом рамку, границы и кнопки. Таким образом, вы по-прежнему выполняете рендеринг в окно, хотя оно выглядит полноэкранным.

Я не уверен, что эта опция делает вещи медленнее: между ними есть слой окна, который может сделать его медленнее, чем рендеринг непосредственно на экран.

Для любопытных, реализация собственного полноэкранного режима до смешного проста (по крайней мере, в 10.8 и 10.9): в XCode выберите файл .xib, выберите (главное) окно на боковой панели редактора, затем выберите селектор атрибутов справа. Вы можете найти вариант «Полный экран» между «Неподдерживаемый», «Основное окно» или «Вспомогательное окно». Это автоматически добавит полноэкранный переключатель в окно. Еще лучше, теперь выберите главное меню -> меню просмотра на боковой панели, найдите «Элемент полноэкранного меню» в инспекторе внизу (для него есть строка поиска), перетащите его в меню «Вид» в редакторе и вуаля, он будет иметь ярлык и автоматически подключаться к полноэкранному режиму для окна (выберите новый пункт меню «Вид» и посмотрите в инспекторе подключений, он уже подключен для вас).

Хороший способ проверить все это — взять полноэкранный пример Я связал свой вопрос и отредактировал его, как было предложено выше. Использование сочетания клавиш F по умолчанию для переключения между полноэкранным режимом и обратно отобразит представление opengl и фрейм с текстом под ним в полноэкранном режиме. Использование полноэкранного режима, как закодировано в примере, переключит openglview на использование полноэкранного режима без каких-либо дополнительных (какао) фреймов, кнопок или текста.

person Community    schedule 20.04.2014
comment
Я думаю, что для вашего первого примера это просто полноэкранная поверхность CGL. Более подробную информацию см. в книге Роберта П. Кюне. - person ; 19.02.2016

Мне это тоже интересно, особенно ваши первые два вопроса.

Это не отвечает на эти вопросы, но ваш третий вопрос об ошибке, я думаю, вам может сойти с рук простое изменение свойств того же окна (у меня работает):

- (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;
    }
}
person Robby    schedule 04.02.2014