View Full Version : Getting past the shielding window
Wowbagger
2006.09.03, 09:36 PM
It seems that, normally, there is no way to show dialogs and alerts when the display is captured and the shielding window is up. And it also seems that aglSetFullScreen() also effectively removes any possibility of using standard UI elements in full screen (according to what I've read here...).
However, I noticed one game that captures the screen (Otto Matic) is able to show dialogs in full screen. How is this achieved (or am I mistaken in assuming that Otto Matic captures the display)? Is there any possibility of applying this when using an AGL context? (Because it's fairly distracting to have to detach the context all the time just to show some alerts and dialogs.)
OneSadCookie
2006.09.03, 10:17 PM
Pretty sure Otto Matic doesn't capture the screen (naughty Brian Greenstone!)
You may or may not be able to use standard elements by manually raising their window levels above the shielding window.
The best solution is to use custom UI in these cases. You'll avoid breaking immersion a bit better that way, too.
KittyMac
2006.09.03, 10:39 PM
If all you are doing is capturing the display with CGDisplayCapture() and making a fullscreen window on top of it, you can get all of the other windows also on top of it by doing the following:
SetWindowGroupLevel(GetWindowGroupOfClass(kAlertWi ndowClass), CGShieldingWindowLevel());
SetWindowGroupLevel(GetWindowGroupOfClass(kMovable AlertWindowClass), CGShieldingWindowLevel());
SetWindowGroupLevel(GetWindowGroupOfClass(kModalWi ndowClass), CGShieldingWindowLevel());
SetWindowGroupLevel(GetWindowGroupOfClass(kMovable ModalWindowClass), CGShieldingWindowLevel());
SetWindowGroupLevel(GetWindowGroupOfClass(kFloatin gWindowClass), CGShieldingWindowLevel());
SetWindowGroupLevel(GetWindowGroupOfClass(kDocumen tWindowClass), CGShieldingWindowLevel());
SetWindowGroupLevel(GetWindowGroupOfClass(kUtility WindowClass), CGShieldingWindowLevel());
SetWindowGroupLevel(GetWindowGroupOfClass(kHelpWin dowClass), CGShieldingWindowLevel());
SetWindowGroupLevel(GetWindowGroupOfClass(kSheetWi ndowClass), CGShieldingWindowLevel());
SetWindowGroupLevel(GetWindowGroupOfClass(kToolbar WindowClass), CGShieldingWindowLevel());
SetWindowGroupLevel(GetWindowGroupOfClass(kPlainWi ndowClass), CGShieldingWindowLevel());
SetWindowGroupLevel(GetWindowGroupOfClass(kOverlay WindowClass), CGShieldingWindowLevel());
SetWindowGroupLevel(GetWindowGroupOfClass(kSheetAl ertWindowClass), CGShieldingWindowLevel());
SetWindowGroupLevel(GetWindowGroupOfClass(kAltPlai nWindowClass), CGShieldingWindowLevel());
SetWindowGroupLevel(GetWindowGroupOfClass(kDrawerW indowClass), CGShieldingWindowLevel());
However, if you are really going fullscreen with an OpenGL context (for instance, with CGLSetFullScreen()), then this does not work. When you go fullscreen OpenGL you shove the window manager aside and take over the video card, so you can't expect to use it after that.
Wowbagger
2006.09.03, 11:14 PM
I do capture the display with CGDisplayCapture(). I then manually switch the resolution using CGDisplaySwitchToMode() and call aglSetFullScreen(fullScreenContext, 0, 0, 0, 0) after switching the resolution. Would the above code still work using this method of resolution switching?
OneSadCookie
2006.09.03, 11:18 PM
aglSetFullScreen == CGLSetFullScreen, basically -- it gives you a true full-screen context, so you can't use normal windows or drawing whilst that's in place.
Wowbagger
2006.09.03, 11:27 PM
Ah, well. Thanks for the help anyway.
ThemsAllTook
2006.09.04, 12:54 PM
I've been able to display dialogs and alerts while in full screen mode with the display captured. Here's how I do it:
- Create a borderless NSWindow with a content rect the size of the display you'll be capturing.
- Set its window level to CGShieldingWindowLevel().
- Create an NSOpenGLView and an NSOpenGLContext, and add them to the full screen window.
- When toggling to full screen mode, determine which display contains the majority of the game window, perform a CGDisplayFade on it, CGDisplayCapture it, hide the game window, show the full screen window.
- Set the window level of any dialog you wish to show while in full screen mode to CGShieldingWindowLevel().
It works perfectly. I can post my code if you'd like, although if you're using AGL, you'll have to translate from NSOpenGL. Presumably you could use a similar approach, though.
ia3n_g
2006.09.04, 05:56 PM
I believe in Brian Greenstone's book he recommends capturing the display but temporarily switching to to window mode when you want to display system UI...
Supposing you go the custom UI route and never release the display, is there any way to get the force quit dialog box to be visible should your game crash? Debugging in full screen is no fun currently.
Frank C.
2006.09.04, 06:23 PM
I've used the SetWindowGroupLevel trick in the past but IIRC you can't get popup menus to draw over the shielding window from Carbon. I believe it's possible from Cocoa however.
OneSadCookie
2006.09.04, 08:02 PM
- Create an NSOpenGLView and an NSOpenGLContext, and add them to the full screen window.
You're not getting a true full-screen context if you do this, so you're not getting the performance benefits.
KittyMac
2006.09.04, 09:19 PM
Supposing you go the custom UI route and never release the display, is there any way to get the force quit dialog box to be visible should your game crash?
Unless I'm mistaken, in 10.4 they made it that pressing cmd+opt+esc (maybe twice) while an application is fullscreen will force quit that application automatically.
OneSadCookie
2006.09.04, 10:01 PM
The problem is, Xcode likes to automatically attach the debugger when you crash, which prevents your application from being force quit...
The solution it to turn off the annoying attach-on-crash behavior of Xcode. I forget how, but search the boards. I think it's a project or target setting.
You could also just use your windowed mode for debugging, of course :)
lightbringer
2006.09.04, 10:19 PM
The solution it to turn off the annoying attach-on-crash behavior of Xcode. I forget how, but search the boards. I think it's a project or target setting.
It's under the Executable setting, under the debugging tab it's labeled, "Auto-attach debugger on crash".
Frank C.
2006.09.05, 02:47 AM
Unless I'm mistaken, in 10.4 they made it that pressing cmd+opt+esc (maybe twice) while an application is fullscreen will force quit that application automatically.
That's been there for as long as I can remember - you just have to hold the keys down for a few seconds.
ThemsAllTook
2006.09.05, 02:43 PM
You're not getting a true full-screen context if you do this, so you're not getting the performance benefits.
That's what I thought at first. Performance on it was pretty bad until I captured the display, but then everything was silky-smooth. I suppose I could do a test to see if a "true" full-screen context is any faster, but the way I describe above already seemed faster than running in a window.
ThemsAllTook
2006.09.05, 03:46 PM
So, out of curiosity, I made a speed test application. It seems using setFullScreen is a bit faster in some cases.
http://www.sacredsoftware.net/temp/FullScreenSpeedTest.tgz (Includes source)
Command-1 toggles to and from full-screen-in-a-window, Command-2 toggles to and from full-screen with setFullScreen. Random geometry is drawn every frame. Frames per second are printfed. Be sure to toggle out of the current full-screen mode before toggling to the other one, or weird stuff happens. :)
So, unless I find a way to speed up method 1, it looks like this is a tradeoff between convenience and speed. In some cases, being able to display windows over a full-screen context may be more valuable than a few extra frames per second.
arekkusu
2006.09.05, 06:19 PM
Some hardware is able to re-tile the framebuffer in real fullscreen GL contexts for faster hardware write access. So in general, if you want the best performance, you should be capturing the display and using a fullscreen context, not a top-level window.
vBulletin® v3.6.8, Copyright ©2000-2008, Jelsoft Enterprises Ltd.