Getting past the shielding window

Member
Posts: 67
Joined: 2006.07
Post: #1
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.)
Quote this message in a reply
Luminary
Posts: 5,143
Joined: 2002.04
Post: #2
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.
Quote this message in a reply
Member
Posts: 204
Joined: 2002.09
Post: #3
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:

Code:
SetWindowGroupLevel(GetWindowGroupOfClass(kAlertWindowClass), CGShieldingWindowLevel());
SetWindowGroupLevel(GetWindowGroupOfClass(kMovableAlertWindowClass), CGShieldingWindowLevel());
SetWindowGroupLevel(GetWindowGroupOfClass(kModalWindowClass), CGShieldingWindowLevel());
SetWindowGroupLevel(GetWindowGroupOfClass(kMovableModalWindowClass), CGShieldingWindowLevel());
SetWindowGroupLevel(GetWindowGroupOfClass(kFloatingWindowClass), CGShieldingWindowLevel());
SetWindowGroupLevel(GetWindowGroupOfClass(kDocumentWindowClass), CGShieldingWindowLevel());
SetWindowGroupLevel(GetWindowGroupOfClass(kUtilityWindowClass), CGShieldingWindowLevel());
SetWindowGroupLevel(GetWindowGroupOfClass(kHelpWindowClass), CGShieldingWindowLevel());
SetWindowGroupLevel(GetWindowGroupOfClass(kSheetWindowClass), CGShieldingWindowLevel());
SetWindowGroupLevel(GetWindowGroupOfClass(kToolbarWindowClass), CGShieldingWindowLevel());
SetWindowGroupLevel(GetWindowGroupOfClass(kPlainWindowClass), CGShieldingWindowLevel());
SetWindowGroupLevel(GetWindowGroupOfClass(kOverlayWindowClass), CGShieldingWindowLevel());
SetWindowGroupLevel(GetWindowGroupOfClass(kSheetAlertWindowClass), CGShieldingWindowLevel());
SetWindowGroupLevel(GetWindowGroupOfClass(kAltPlainWindowClass), CGShieldingWindowLevel());
SetWindowGroupLevel(GetWindowGroupOfClass(kDrawerWindowClass), 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.
Quote this message in a reply
Member
Posts: 67
Joined: 2006.07
Post: #4
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?
Quote this message in a reply
Luminary
Posts: 5,143
Joined: 2002.04
Post: #5
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.
Quote this message in a reply
Member
Posts: 67
Joined: 2006.07
Post: #6
Ah, well. Thanks for the help anyway.
Quote this message in a reply
Moderator
Posts: 1,560
Joined: 2003.10
Post: #7
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.
Quote this message in a reply
Member
Posts: 49
Joined: 2006.07
Post: #8
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.
Quote this message in a reply
Member
Posts: 446
Joined: 2002.09
Post: #9
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.
Quote this message in a reply
Luminary
Posts: 5,143
Joined: 2002.04
Post: #10
ThemsAllTook Wrote:- 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.
Quote this message in a reply
Member
Posts: 204
Joined: 2002.09
Post: #11
ia3n_g Wrote: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.
Quote this message in a reply
Luminary
Posts: 5,143
Joined: 2002.04
Post: #12
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 Smile
Quote this message in a reply
Member
Posts: 144
Joined: 2004.07
Post: #13
OneSadCookie Wrote: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".
Quote this message in a reply
Member
Posts: 446
Joined: 2002.09
Post: #14
KittyMac Wrote: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.
Quote this message in a reply
Moderator
Posts: 1,560
Joined: 2003.10
Post: #15
OneSadCookie Wrote: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.
Quote this message in a reply
Post Reply