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
2 ответа
Теперь я думаю, что это не может быть сделано, и не должно быть сделано. Когда окно отображается, контекст рендеринга - это окно, которое отличается от экрана при рендеринге в полноэкранном режиме. Таким образом, при переключении между вещами приходится переустанавливать каждый раз, когда вы переключаетесь.
Можно просто использовать встроенную полноэкранную опцию, которая есть в новейших вариантах OS X. Это (предположительно) увеличит окно контакта до полного размера экрана при удалении рамки, границ и кнопок. Таким образом, вы по-прежнему визуализируете окно, хотя оно выглядит полноэкранным.
Я не уверен, что эта опция делает вещи медленнее: между ними есть слой окна, который может сделать его медленнее, чем рендеринг непосредственно на экран.
Для любопытных реализовать родной полноэкранный режим смехотворно просто (по крайней мере, в 10.8 и 10.9): в XCode выберите .xib
файл, выберите (главное) окно на боковой панели редактора, затем выберите селектор атрибутов справа. Вы можете найти "Полноэкранный" выбор между Неподдерживаемым, Первичным окном или Вспомогательным окном. Это автоматически добавит полноэкранный переключатель к окну. Еще точнее, теперь выберите главное меню -> меню просмотра на боковой панели, найдите "Элемент полноэкранного меню" в инспекторе внизу (для него есть панель поиска), перетащите его в меню "Вид" в редакторе и Вуаля, он будет иметь ярлык и автоматически подключаться к полноэкранной опции для окна (выберите новый пункт меню "Просмотр" и посмотрите инспектор подключений, поскольку он уже подключен для вас).
Хороший способ проверить все это - взять полноэкранный пример, который я привел в своем вопросе, и отредактировать его, как предложено выше. При использовании стандартной комбинации клавиш управления F для переключения назад и вперед между полноэкранными режимами будет отображаться представление opengl и рамка с текстом под ним на полном экране. Использование полноэкранного параметра, как показано в примере, переключит openglview на использование полноэкранного режима без каких-либо дополнительных (какао) рамок, кнопок или текста.
Мне тоже интересно это, особенно ваши первые два вопроса.
Это не отвечает на эти вопросы, но ваш третий вопрос об ошибке, я думаю, вы можете обойтись, просто изменив свойства того же окна (работает для меня):
- (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;
}
}